# Attribute Based Shipping Options

Attribute Based Shipping Options provide a cutting-edge solution to this challenge by allowing businesses to customize shipping methods based on specific product attributes. This approach ensures that shipping is not only efficient but also tailored to the unique characteristics of each order.

These shipping options are especially useful in scenarios where certain product attributes necessitate different handling or delivery strategies. For example, consider an online marketplace that sells a variety of products, including perishable goods, fragile items, and heavy equipment. By utilizing attribute-based shipping, the marketplace can allocate specialized cold-chain services for perishable goods, enhanced protective packaging for fragile items, and specialized freight services for heavy equipment. This nuanced approach not only optimizes shipping efficiency but also enhances customer satisfaction by ensuring that each item is delivered in its ideal condition.

Moreover, businesses with diverse product lines can utilize these options to offer customers a more personalized shopping experience. Imagine a retailer that offers clothing, electronics, and furniture. By implementing attribute-based shipping, they can ensure that clothing is dispatched quickly at a lower cost, while electronics are shipped with insurance and furniture with white-glove delivery services.

Ultimately, Attribute Based Shipping Options empower businesses to leverage detailed product information to improve logistics, reduce costs, and provide enhanced service, cementing stronger relationships with their customers.

### Key Dynamic Settings​ <a href="#key-dynamic-settings" id="key-dynamic-settings"></a>

* `ATTRIBUTE_KEYS_FOR_ATTRIBUTE_BASED_SHIPPING_OPTION`: This dynamic setting allows you to specify the rule for attribute keys that will be used for grouping shipping options.
* `CHECKOUT_SHIPPING_OPTION_SELECTION_PAGE`: This dynamic setting should be set to `AttributeBasedShippingOptionSelectionPage` to enable the specific selection page for attribute-based shipping options.

This setting can take following values as described:

| Value                                     | Description                                                                 |
| ----------------------------------------- | --------------------------------------------------------------------------- |
| AttributeBasedShippingOptionSelectionPage | Groups shipping options based on attribute values of products.              |
| DataSourceShippingOptionSelectionPage     | Groups shipping options based on seller information of products.            |
| ShippingOptionSelectionPage               | Allows selection of a single shipping company for all products in a basket. |

These shipping option pages cannot be used simultaneously as they serve as alternatives.

{% hint style="warning" %}
Attribute Based Shipping Options are not compatible with cash on delivery (COD) payment methods. If a COD option is available, a shipping option page rule must be added to accommodate this. \[[Shipping Option Page Rule\]](#shipping-option-page-rule)
{% endhint %}

### Configuration Steps​ <a href="#configuration-steps" id="configuration-steps"></a>

#### Example Scenario 1​ <a href="#example-scenario-1" id="example-scenario-1"></a>

In these configuration steps, we will proceed with an example where different shipping options are defined for products sold in stores located in different districts. Here, "**store**" will be defined as a product attribute, and the attribute values will be the districts “**Pendik**” and “**Kadıköy**”.

The products sold and their corresponding stores are as follows.

| Product Name | Attribute Values for “store” Attribute |
| ------------ | -------------------------------------- |
| Hat          | Pendik                                 |
| Dress        | Pendik                                 |
| Bag          | Kadıköy                                |

{% hint style="warning" %}
It is essential to assign this "store" attribute and its respective values to each product.
{% endhint %}

Under the default shipping method, all products are processed by a single shipping company. With the attribute-based development, you can separate shipping methods:

* **Hat & Dress:** Use Shipping Company A.
* **Bag:** Use Shipping Company B.

Please follow the below steps to configure attribute based shipping options:

**Step 1: Define Product Attributes​**

As a first step, it is necessary to create a product attribute on the *Product and Catalogs > Product Attributes* page in Omnitron and to add attribute values for this attribute. After the attribute is defined, an attribute set should be created for this attribute, and then this attribute set should be assigned to the products.

In the following example, the attribute has been defined with the Attribute Code “**store**”, and two attribute values have been added: “**pendik**” and “**kadikoy**”.

<figure><img src="https://2911598027-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FlQinVPnOffBiOp126ldR%2Fuploads%2Fgit-blob-f5c44ff862574b32bbd834a5e02748d7096776ef%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

<figure><img src="https://2911598027-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FlQinVPnOffBiOp126ldR%2Fuploads%2Fgit-blob-4d0a6b32aef488134f9da3e9ad30d8d70963df05%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

**Important settings**:

* Ensure that **Is Localizable?** is set to `No` for both attributes, meaning they will not vary based on language or locale.
* Use these Attribute Code (`store`) for future steps in the configuration.

**Step 2: Define Shipping Options​**

Once the attribute and its values are set up, you need to define the shipping options for these attribute values. For detailed information on defining shipping options, please refer to the [Shipping Options](https://app.gitbook.com/s/IbwGN7KwvYi0iLbjtnXz/omnitron/sales-channels/sales-channel-settings/how-to-manage-shipping-options-in-omnitron) documentation.

In this example, you could have shipping options such as:

* For products in **Pendik**: Create **Shipping Company A**.\\

  <figure><img src="https://2911598027-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FlQinVPnOffBiOp126ldR%2Fuploads%2Fgit-blob-e936ff454e2a22dfcaf3d1a8778e46da2a5a4ae1%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>
* For products in **Kadıköy**: Create **Shipping Company B**.\\

  <figure><img src="https://2911598027-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FlQinVPnOffBiOp126ldR%2Fuploads%2Fgit-blob-2b47ffc585a612ef506b19e52532be6179798c3a%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

When defining shipping options, the values entered in the **Calculator** and **Rule** fields are not crucial at this stage. Calculators and Rules that will be defined in the subsequent steps will be used for the attribute-based shipping options configuration.

**Step 3: Configure Dynamic Settings for Attribute-Based Shipping​**

In this step, you need to configure the dynamic setting for the `ATTRIBUTE_KEYS_FOR_ATTRIBUTE_BASED_SHIPPING_OPTION` . This step is crucial as it defines the attribute key that will be used for grouping shipping options based on product attributes.

Complete the fields as follows:

<figure><img src="https://2911598027-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FlQinVPnOffBiOp126ldR%2Fuploads%2Fgit-blob-e661d5e92c5179b09d81bb402b43c61b8c409d94%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

**1. Group attribute key:** Enter the “Group attribute key” (as known as the “Attribute Code” in Omnitron) that you have previously defined in step 1. In this example, you will enter: “**store**”. This key will be used to group products by store locations.

{% hint style="warning" %}
For products that lack the specified attribute key (for instance, those not tagged with "store"), they will be grouped under a string value of `None`.
{% endhint %}

**2. Rule:** In the Rule field, the rules detailed in the [Rules](#rules) section should be configured for this field. Since this example involves configuring different store locations, the **Any Rule** is used.

Example configuration:

```json
{
    "name": "Any Rule",
    "slug": "any-rule"
}
```

**3. Sort Order:** This determines the priority order of the rule, sorted in ascending order. The first group attribute key that meets the rule is used for grouping.

In this example, since only one rule is being defined for the `store` attribute code, you can set the sort order to 1.

**Step 4: Add Attribute-Based Shipping Options​**

In this step, it is necessary to add attribute-based shipping options. To do this, navigate to *Sales Channels > Sales Channel Settings > Attribute Based Shipping Options* and click on the "+ New Attribute Based Shipping Option" button to open the form.

In this form, the calculator and rule fields should be filled out as needed. If you want to specify the order, you can provide a value for the order. Make sure to set the status to active.

The most crucial step is to enter the previously defined attribute values and select the corresponding shipping option that will be applicable for each value. After completing these steps, save the form. Then, repeat this configuration for all desired attribute values.

In this example, the shipping options defined in Step 2 have been matched with the relevant attribute values:

**Attribute Value:** pendik **→ Shipping Option:** Shipping Company A

In this example, products in **Pendik** are assigned to **Shipping Company A**.

<figure><img src="https://2911598027-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FlQinVPnOffBiOp126ldR%2Fuploads%2Fgit-blob-8816d116ef3333620af94627a343c1496cdcacad%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

The sample rule is as follows:

```json
{
  "attribute_value": "pendik",
  "attribute_field": "store",
  "name": "Product Attribute Rule",
  "func": "all",
  "slug": "product-attribute-rule"
}
```

**Attribute Value:** kadikoy **→ Shipping Option:** Shipping Company B

In this example, products in **Kadıköy** are assigned to **Shipping Company B**.

<figure><img src="https://2911598027-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FlQinVPnOffBiOp126ldR%2Fuploads%2Fgit-blob-ce584702c5ce08936d882395befd168eb8867ddf%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

The sample rule is as follows:

```json
{
  "attribute_value": "kadikoy",
  "attribute_field": "store",
  "name": "Product Attribute Rule",
  "func": "all",
  "slug": "product-attribute-rule"
}
```

**Step 5: Enable the Checkout Shipping Option Selection Page​**

Finally, to enable the configuration, set the `CHECKOUT_SHIPPING_OPTION_SELECTION_PAGE` dynamic setting to `AttributeBasedShippingOptionSelectionPage`.

<figure><img src="https://2911598027-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FlQinVPnOffBiOp126ldR%2Fuploads%2Fgit-blob-40cbeacaa41b536b720ce1333a78b9f3d46a2723%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

#### Example Scenario 2​ <a href="#example-scenario-2" id="example-scenario-2"></a>

In this configuration scenario, a home appliance company operates with different delivery strategies for products delivered to two major cities:

* The company offers separate shipping options for products delivered to **İstanbul** based on their **brand** (Beko, Arçelik, Siemens).
* Where all brands are available under a single store, shipping options for products delivered to **İzmir** are determined by the **type** of appliance (small or large home appliance).

Please follow the below steps to configure attribute based shipping options:

**Step 1: Define Product Attributes​**

As a first step, it is necessary to create a product attribute on the *Product and Catalogs > Product Attributes* page in Omnitron and to add attribute values for this attribute. After the attribute is defined, an attribute set should be created for this attribute, and then this attribute set should be assigned to the products.

In this example, the following product attributes have been defined:

**Attribute Code**: `brand`

* **Values**: `beko`, `arcelik`, `siemens` (these are the brands)

  <figure><img src="https://2911598027-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FlQinVPnOffBiOp126ldR%2Fuploads%2Fgit-blob-8b3a58783451dbd9a9f0d0564abfb6d6c7c51285%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

  <figure><img src="https://2911598027-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FlQinVPnOffBiOp126ldR%2Fuploads%2Fgit-blob-efa61184fe973d08a3f4caddaa1a38202d7938cf%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

**Attribute Code**: `type`

* **Values**: `small`, `large` (these are the product types)

  <figure><img src="https://2911598027-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FlQinVPnOffBiOp126ldR%2Fuploads%2Fgit-blob-c26ab4e8c2d4cae819cf23d907e8b572eb39587f%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

  <figure><img src="https://2911598027-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FlQinVPnOffBiOp126ldR%2Fuploads%2Fgit-blob-e0fd34dd7392c5f42330ba221fd4bf9772f6ad25%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

**Important settings**:

* Ensure that **Is Localizable?** is set to `No` for both attributes, meaning they will not vary based on language or locale.
* Use these Attribute Codes (`brand` and `type`) for future steps in the configuration.

**Step 2: Define Shipping Options​**

Once the attribute and its values are set up, you need to define the shipping options for these attribute values. For detailed information on defining shipping options, please refer to the [Shipping Options](https://app.gitbook.com/s/IbwGN7KwvYi0iLbjtnXz/omnitron/sales-channels/sales-channel-settings/how-to-manage-shipping-options-in-omnitron) documentation.

In this example, you could have shipping options such as:

* For **beko** products delivered to **İstanbul**: Create **Shipping Company A**.
* For **arcelik** products delivered to **İstanbul**: Create **Shipping Company B**.
* For **siemens** products delivered to **İstanbul**: Create **Shipping Company C**.
* For **small** products delivered to **İzmir**: Create **Shipping Company D**.
* For **large** products delivered to **İzmir**: Create **Shipping Company E**.\
  ![](https://2911598027-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FlQinVPnOffBiOp126ldR%2Fuploads%2Fgit-blob-061771cd4744236c8e5770f93487f28870f3c01c%2Fimage.png?alt=media)

When defining shipping options, the values entered in the **Calculator** and **Rule** fields are not crucial at this stage. Calculators and Rules that will be defined in the subsequent steps will be used for the attribute-based shipping options configuration.

**Step 3: Configure Dynamic Settings for Attribute-Based Shipping​**

In this step, you need to configure the dynamic setting for the `ATTRIBUTE_KEYS_FOR_ATTRIBUTE_BASED_SHIPPING_OPTION`. This step is crucial as it defines the attribute key that will be used for grouping shipping options based on product attributes.

Complete the fields as follows:

<figure><img src="https://2911598027-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FlQinVPnOffBiOp126ldR%2Fuploads%2Fgit-blob-672f221d20224230f5d7bc2e1855b72af72f05b1%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

**1. Group attribute key:** Enter the “Group attribute key” (also known as the “Attribute Code” in Omnitron) that you have previously defined in step 1. In this example, you will enter: “**brand**” for the **1. Field** and “**type**” for the **2. Field**. These keys will be used to group products by brand and type.

{% hint style="warning" %}
For products that lack the specified attribute key (for instance, those not tagged with "store"), they will be grouped under a string value of `None`.
{% endhint %}

**2. Rule:** In the Rule field, the rules detailed in the [Rules](#rules) section should be configured for this field. Since this example involves grouping products by brand and type across different cities, the **City Rule** is applied.

***Example Rule for the "brand" group attribute key for Istanbul:***

```json
{
    "exclude": false,
    "cities": [34], // Istanbul City ID
    "name": "City Rule",
    "slug": "city-rule"
}
```

***Example Rule for the "type" group attribute key for Izmir:***

```json
{
    "exclude": false,
    "cities": [35], // Izmir City ID
    "name": "City Rule",
    "slug": "city-rule"
}
```

**3. Sort Order:** This setting determines the priority order for applying the rule, sorted in ascending order. The first matching group attribute key is used for grouping.

In this example, the sort order for products delivered to Istanbul is set to 1, while for products delivered to Izmir, it is set to 2.

**Step 4: Add Attribute-Based Shipping Options​**

In this step, it is necessary to add attribute-based shipping options. To do this, navigate to *Sales Channels > Sales Channel Settings > Attribute Based Shipping Options* and click on the "+ New Attribute Based Shipping Option" button to open the form.

In this form, the calculator and rule fields should be filled out as needed. If you want to specify the order, you can provide a value for the order. Make sure to set the status to active.

The most crucial step is to enter the previously defined attribute values and select the corresponding shipping option that will be applicable for each value. After completing these steps, save the form. Then, repeat this configuration for all desired attribute values.

In this example, the shipping options defined in Step 2 have been matched with the relevant attribute values defined in Step 1:

**For İstanbul (based on brand)**: Products will be assigned to the shipping company by brand, and different shipping companies will handle the deliveries:

**Attribute Value:** beko **→ Shipping Option:** Shipping Company A

In this example, products of the **Beko** brand delivered to **Istanbul** are assigned to **Shipping Company A** using the **And Rule**.

<figure><img src="https://2911598027-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FlQinVPnOffBiOp126ldR%2Fuploads%2Fgit-blob-be501168b7eaed9bace8b336f7223f745c913eee%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

The sample rule is as follows:

```json
{
    "name": "And Rule",
    "slug": "and-rule",
    "children": [
        {
            "attribute_value": "beko",
            "attribute_field": "brand",
            "name": "Product Attribute Rule",
            "func": "all",
            "slug": "product-attribute-rule"
        },
        {
            "exclude": false,
            "cities": [34], // Istanbul City ID
            "name": "City Rule",
            "slug": "city-rule"
        }
    ]
}
```

**Attribute Value:** arcelik **→ Shipping Option:** Shipping Company B

In this example, products of the **Arçelik** brand delivered to **Istanbul** are assigned to **Shipping Company B** using the **And Rule**.

<figure><img src="https://2911598027-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FlQinVPnOffBiOp126ldR%2Fuploads%2Fgit-blob-37153f9fef730e1577bdc14bf23dbf9ec850ec24%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

The sample rule is as follows:

```json
{
    "name": "And Rule",
    "slug": "and-rule",
    "children": [
        {
            "attribute_value": "arcelik",
            "attribute_field": "brand",
            "name": "Product Attribute Rule",
            "func": "all",
            "slug": "product-attribute-rule"
        },
        {
            "exclude": false,
            "cities": [34], // Istanbul City ID
            "name": "City Rule",
            "slug": "city-rule"
        }
    ]
}
```

**Attribute Value:** siemens **→ Shipping Option:** Shipping Company C

In this example, products of the **Siemens** brand delivered to **Istanbul** are assigned to **Shipping Company C** using the **And Rule**.

<figure><img src="https://github.com/akinon/docs/blob/main/technicalguides/commerce/broken-reference" alt=""><figcaption></figcaption></figure>

The sample rule is as follows:

```json
{
    "name": "And Rule",
    "slug": "and-rule",
    "children": [
        {
            "attribute_value": "siemens",
            "attribute_field": "brand",
            "name": "Product Attribute Rule",
            "func": "all",
            "slug": "product-attribute-rule"
        },
        {
            "exclude": false,
            "cities": [34], // Istanbul City ID
            "name": "City Rule",
            "slug": "city-rule"
        }
    ]
}
```

**For İzmir (based on type):** Products will be assigned to the shipping company by type, and different shipping companies will handle the deliveries:

**Attribute Value:** small **→ Shipping Option:** Shipping Company D

In this example, products of the **Small home appliance** type delivered to **İzmir** are assigned to **Shipping Company D** using the **And Rule**.

<figure><img src="https://github.com/akinon/docs/blob/main/technicalguides/commerce/broken-reference" alt=""><figcaption></figcaption></figure>

The sample rule is as follows:

```json
{
    "name": "And Rule",
    "slug": "and-rule",
    "children": [
        {
            "attribute_value": "small",
            "attribute_field": "type",
            "name": "Product Attribute Rule",
            "func": "all",
            "slug": "product-attribute-rule"
        },
        {
            "exclude": false,
            "cities": [35], // Izmir City ID
            "name": "City Rule",
            "slug": "city-rule"
        }
    ]
}
```

**Attribute Value:** large **→ Shipping Option:** Shipping Company E

In this example, products of the **Large home appliance** type delivered to **İzmir** are assigned to **Shipping Company E** using the **And Rule**.

<figure><img src="https://github.com/akinon/docs/blob/main/technicalguides/commerce/broken-reference" alt=""><figcaption></figcaption></figure>

The sample rule is as follows:

```json
{
    "name": "And Rule",
    "slug": "and-rule",
    "children": [
        {
            "attribute_value": "large",
            "attribute_field": "type",
            "name": "Product Attribute Rule",
            "func": "all",
            "slug": "product-attribute-rule"
        },
        {
            "exclude": false,
            "cities": [35], // Izmir City ID
            "name": "City Rule",
            "slug": "city-rule"
        }
    ]
}
```

**Step 5: Enable the Checkout Shipping Option Selection Page​**

Finally, to enable the configuration, set the `CHECKOUT_SHIPPING_OPTION_SELECTION_PAGE` dynamic setting to `AttributeBasedShippingOptionSelectionPage`.

<figure><img src="https://2911598027-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FlQinVPnOffBiOp126ldR%2Fuploads%2Fgit-blob-40cbeacaa41b536b720ce1333a78b9f3d46a2723%2Fimage%20(57).png?alt=media" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
If the address selected by the user during the checkout process does not meet the defined `ATTRIBUTE_KEYS_FOR_ATTRIBUTE_BASED_SHIPPING_OPTION` setting, the following error message will be displayed:

```
"code": "attribute_based_shipping_option_100",
"en": _("No attribute based shipping option available.")
```

To prevent this error, an additional field for the rule must be defined in the `ATTRIBUTE_KEYS_FOR_ATTRIBUTE_BASED_SHIPPING_OPTION` setting in Step 3 of the configuration. In the following example, an Any Rule has been added to group fragile products that are not delivered to Istanbul or Izmir. Based on this grouping, a shipping option can be offered according to the attribute-based shipping option defined in Step 4.

<img src="https://github.com/akinon/docs/blob/main/technicalguides/commerce/broken-reference" alt="" data-size="original">
{% endhint %}

### Rules​ <a href="#rules" id="rules"></a>

The Rules section defines configurable rule types for implementing Attribute-Based Shipping Options. This section provides an overview of each rule type, its parameters, and examples for setting up complex structures.

Here is an outline of the rule types and their applications:

<table><thead><tr><th width="142.76171875">Slug</th><th width="119.70703125">Name</th><th width="143.7578125">Serializer</th><th>Description</th></tr></thead><tbody><tr><td><code>any-rule</code></td><td>Any Rule</td><td>-</td><td>Applies when any conditions are met.</td></tr><tr><td><code>not-rule</code></td><td>Not Rule</td><td>child dict</td><td>Used to exclude specific conditions; works by negating attribute conditions.</td></tr><tr><td><code>and-rule</code></td><td>And Rule</td><td>children list[{dict}]</td><td>Combines multiple conditions that all must be met; ideal for complex shipping configurations based on multiple attributes.</td></tr><tr><td><code>or-rule</code></td><td>Or Rule</td><td>children list[{dict}]</td><td>Applies if any one of several conditions is met.</td></tr><tr><td><code>city-rule</code></td><td>City Rule</td><td>cities list, exclude boolean</td><td>Enables shipping rules based on specific cities, including/excluding certain city IDs.</td></tr><tr><td><code>country-rule</code></td><td>Country Rule</td><td>countries list, exclude boolean</td><td>Enables shipping rules based on specific countries, including/excluding certain country IDs.</td></tr><tr><td><code>township-rule</code></td><td>Township Rule</td><td>townships list, exclude boolean</td><td>Enables shipping rules based on specific townships, including/excluding certain township IDs.</td></tr><tr><td><code>district-rule</code></td><td>District Rule</td><td>districts list, exclude boolean</td><td>Enables shipping rules based on specific districts, including/excluding certain district IDs.</td></tr><tr><td><code>postal-code-rule</code></td><td>Postal Code Rule</td><td>postal_codes list, exclude boolean</td><td>Enables shipping rules based on specific postal codes, including/excluding certain postal code IDs.</td></tr></tbody></table>

#### Location-Based Rules for Shipping Address​ <a href="#location-based-rules-for-shipping-address" id="location-based-rules-for-shipping-address"></a>

The `city-rule`, `country-rule`, `township-rule`, `district-rule`, and `postal-code-rule` apply shipping options based on selected shipping address during the checkout process.

Here are examples for setting up a `city-rule`: *(For other location-based rules, refer to the slug and name in the table above.)*

**1. Including Specific Cities** (e.g., city IDs 1234, 1235):

```json
{
    "exclude": false,
    "cities": [1234, 1235],
    "name": "City Rule",
    "slug": "city-rule"
}
```

**2. Excluding Specific Cities** (e.g., all cities except city IDs 1234, 1235):

```json
{
    "exclude": true,
    "cities": [1234, 1235],
    "name": "City Rule",
    "slug": "city-rule"
}
```

#### Any-Rule​ <a href="#any-rule" id="any-rule"></a>

This rule applies when no specific conditions are needed. Useful for cases where a flexible rule setup is required.

```json
{
    "name": "Any Rule",
    "slug": "any-rule"
}
```

#### Complex Rule Structure Example​ <a href="#complex-rule-structure-example" id="complex-rule-structure-example"></a>

This example demonstrates how to set up a **complex rule structure** by combining multiple rule types.

```json
{
    "children": [
        {
            ...(rule1)
        },
        {
            "children": [
                {
                    "child": {
                        ...(rule2)
                    },
                    "name": "Not Rule",
                    "slug": "not-rule"
                },
                {
                    "child": {
                        ...(rule3)
                    },
                    "name": "Not Rule",
                    "slug": "not-rule"
                }
            ],
            "name": "And Rule",
            "slug": "and-rule"
        }
    ],
    "name": "Or Rule",
    "slug": "or-rule"
}
```

This rule structure demonstrates a logical configuration that applies the following conditions:

1. The **Or Rule** at the top level will result in a positive outcome if **either rule1 is satisfied** or if the **And Rule** is satisfied.
2. Within the **And Rule**, two **Not Rules** are applied to rule2 and rule3, meaning that **both rule2 and rule3 must not be satisfied** for the **And Rule** to be true.

In simpler terms, this configuration will trigger the `ATTRIBUTE_KEYS_FOR_ATTRIBUTE_BASED_SHIPPING_OPTION` dynamic setting if:

* **rule1 is satisfied**, or
* **both rule2 and rule3 are not satisfied simultaneously**.

The structure above can be logically represented as:

```
(rule1 or ((not rule2) and (not rule3)))
```

### Managing Shipping Options for Products with Undefined or None Attributes​ <a href="#managing-shipping-options-for-products-with-undefined-or-none-attributes" id="managing-shipping-options-for-products-with-undefined-or-none-attributes"></a>

Products that either lack the attribute key set by dynamic settings or have the attribute key but do not have an attribute value will be grouped under the string value `None`. If you want to display specific shipping options for these products without attribute key, it is necessary to create an attribute-based shipping option in the configuration steps, as in the Step 4. This created shipping option may also be visible for other products. If you wish to restrict the visibility for this option, a specific rule can be implemented.

**Example for Scenario 1:**

If the shipping option should only apply to locations other than Kadıköy and Pendik, you can use the following rule configuration:

```json
{
    "name": "Not Rule",
    "slug": "not-rule",
    "child": {
        "name": "Or Rule",
        "slug": "or-rule",
        "children": [
            {
                "attribute_value": "kadikoy",
                "attribute_field": "store",
                "name": "Product Attribute Rule",
                "func": "all",
                "slug": "product-attribute-rule"
            },
            {
                "attribute_value": "pendik",
                "attribute_field": "store",
                "name": "Product Attribute Rule",
                "func": "all",
                "slug": "product-attribute-rule"
            }
        ]
    }
}
```

* **Not Rule**: This rule is designed to exclude the conditions specified in the child rules.
* **Or Rule**: Contains two child rules that target the attributes for Kadıköy and Pendik:
  * The first child rule specifies that the `attribute_value` for the store must not be `kadikoy`.
  * The second child rule specifies that the `attribute_value` for the store must not be `pendik`.

By implementing this configuration, the shipping options will be visible for all locations except for Kadıköy and Pendik.

### Shipping Option Page Rule​ <a href="#shipping-option-page-rule" id="shipping-option-page-rule"></a>

Important Note on Cash on Delivery: The cash on delivery payment method cannot be managed with `AttributeBasedShippingOptionSelectionPage` and `DataSourceShippingOptionSelectionPage`. Therefore, COD should not be enabled for these shipping options.

To resolve this, the omnishop.payments.rules.ShippingOptionPageRule is to be utilized, which allows configuring the `page` parameter with the following setup:

#### Example Configuration​ <a href="#example-configuration" id="example-configuration"></a>

The COD payment method is only applicable with the `ShippingOptionSelectionPage` shipping option. Therefore, the rule specified in the JSON format below needs to be added as a `conf` for the cash on delivery payment method.

```json
{
   "rule": {
       "params": {
           "page": "ShippingOptionSelectionPage"
       },
       "klass": "omnishop.payments.rules.ShippingOptionPageRule"
   }
}
```

### API Methods​ <a href="#api-methods" id="api-methods"></a>

#### `GET` List Attribute Shipping Options​ <a href="#get-list-attribute-shipping-options" id="get-list-attribute-shipping-options"></a>

This method is used to get the available attribute shipping options for the current checkout.

**Path:** `/orders/checkout/?page=AttributeBasedShippingOptionSelectionPage`

**Query Parameters​**

The following query parameters can be used to get a list of attribute based shipping options.

| Parameter | Data Type | In    | Description                            |
| --------- | --------- | ----- | -------------------------------------- |
| `page`    | `string`  | query | The checkout page for the transaction. |

**Example Request​**

To retrieve available attribute based shipping options, a GET request should be sent to the `/orders/checkout/?page=AttributeBasedShippingOptionSelectionPage` endpoint.

```
curl --location --request POST 'https://{storefront_url}/orders/checkout/?page=AttributeBasedShippingOptionSelectionPage' \
```

**Example Response (200 OK)​**

In a successful response with a status code of 200 OK, the API returns the requested attribute-based shipping options in a checkout context. The response includes the complete checkout page information of the user.

<table><thead><tr><th width="230.859375">Key</th><th width="88.35546875">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>attribute_based_shipping_options</code></td><td><code>dict</code></td><td>A dictionary structure that contains shipping options grouped by various attributes based on the basket.</td></tr><tr><td><code>key &#x3C;attribute value></code></td><td><code>str</code></td><td>Represents the attribute value that groups the shipping options (e.g., "kadikoy"). This key encompasses the list of attribute shipping options.</td></tr><tr><td><code>attribute_based_shipping_options[].pk</code></td><td><code>int</code></td><td>The primary key (PK) of the attribute shipping option.</td></tr><tr><td><code>attribute_based_shipping_options[].shipping_amount</code></td><td><code>str</code></td><td>A string indicating the cost of the attribute shipping option (e.g., "39.90").</td></tr><tr><td><code>attribute_based_shipping_options[].shipping_option_name</code></td><td><code>str</code></td><td>Represents the name of the shipping option (e.g., "Shipping Company A").</td></tr><tr><td><code>attribute_based_shipping_options[].shipping_option_logo</code></td><td><code>url or null</code></td><td>Contains the URL of the shipping option's logo. Returns null if no logo is available.</td></tr><tr><td><code>attribute_key</code></td><td><code>list of str</code></td><td>A list of keys that represents how the shipping options are grouped (e.g., "store"). This shows the attributes used for organizing the shipping options.</td></tr><tr><td><code>product_ids</code></td><td><code>list of int</code></td><td>A list containing the IDs of products.</td></tr></tbody></table>

Example Response Structure:

```json
{
    "page_context": {
        "attribute_based_shipping_options": {
            "pendik": {
                "attribute_based_shipping_options": [
                    {
                        "pk": 1,
                        "shipping_amount": "39.90",
                        "shipping_option_name": "Shipping Company A",
                        "shipping_option_logo": null
                    }
                ],
                "product_ids": [
                    535
                ],
                "attribute_key": [
                    "store"
                ]
            },
            "kadikoy": {
                "attribute_based_shipping_options": [
                    {
                        "pk": 3,
                        "shipping_amount": "59.90",
                        "shipping_option_name": "Shipping Company B",
                        "shipping_option_logo": null
                    }
                ],
                "product_ids": [
                    536
                ],
                "attribute_key": [
                    "store"
                ]
            }
        }
    },
    "page_name": "AttributeBasedShippingOptionSelectionPage",
    "page_slug": "attributebasedshippingoptionselectionpage"
}
```

#### `POST` Select Attribute Based Shipping Options​ <a href="#post-select-attribute-based-shipping-options" id="post-select-attribute-based-shipping-options"></a>

This method is used to select attribute based shipping options for the checkout data sources.

**Path:** `/orders/checkout/?page=AttributeBasedShippingOptionSelectionPage`

**Body Parameters​**

The following request body parameters can be used to select attribute based shipping options.

<table><thead><tr><th width="174.34375">Parameter</th><th width="93.8984375">Data Type</th><th width="69.8046875">In</th><th width="84.00390625">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>attribute_based_shipping_options</code></td><td><code>dict</code></td><td>body</td><td>Yes</td><td>Dictionary containing PKs of selected shipping options categorized by attribute names.</td></tr></tbody></table>

**Example Request​**

```python
curl --location '<https://{storefront_url}/orders/checkout/?page=AttributeBasedShippingOptionSelectionPage>' \\
--data 'attribute_based_shipping_options={"pendik": 1, "kadikoy": 2}'
```

**Example Response (200 OK)​**

In a successful response with a status code of 200 OK, the API indicates that a change has occurred in the checkout. The `error` field must be checked; if it is null, the `page_context` will include the next page information, and the selected shipping options will be returned.

```json
{
    ...
    "attribute_based_shipping_options": [
        {
            "pk": 135,
            "shipping_option_name": "Shipping Company A",
            "shipping_option_logo": null,
            "shipping_amount": "39.90",
            "product_ids": [
                535
            ],
            "attribute_value": "pendik",
            "attribute_key": [
                "store"
            ]
        },
        {
            "pk": 134,
            "shipping_option_name": "Shipping Company B",
            "shipping_option_logo": null,
            "shipping_amount": "59.90",
            "product_ids": [
                536
            ],
            "attribute_value": "kadikoy",
            "attribute_key": [
                "store"
            ]
        }
    ]
}
```

**Example Bad Request Response (200 OK)​**

In an unsuccessful response with a status code of 200 but containing a non-null error field, the errors might resemble the following:

```json
{
"errors": {
        "attribute_based_shipping_options": [
            "Invalid pk \"5\" - object does not exist."
        ]
}
}
```

```json
"errors":{
    "attribute_based_shipping_options":"This field is required"
  }

```
