# Weight-Based Product Sales

Weight-based sales is a feature used to sell products measured by weight in a more flexible and customer-friendly way. This sales model plays a critical role, especially in the trade of products measured by weight, such as food, construction materials, and chemical products. In weight-based sales, customers can purchase as much as they need in specified weight units, rather than buying a fixed quantity of a product.

For a product to be sold based on weight, specific attributes need to be defined. These attributes manage the sales process based on the product's weight and ensure that transactions are processed correctly according to the weight when added to the basket.

Additionally, attribute keys can be changed by setting environment variables in project's commerce instance.

| Flag                              | Default Key            |
| --------------------------------- | ---------------------- |
| BASKET\_UNIT\_VALUE\_ATTRIBUTE    | basket\_unit\_value    |
| UNIT\_STEP\_VALUE\_ATTRIBUTE      | unit\_step\_value      |
| UNIT\_REFERENCE\_VALUE\_ATTRIBUTE | unit\_reference\_value |
| UNIT\_PRODUCT\_FLAG\_ATTRIBUTE    | is\_unit\_product      |
| UNIT\_MINIMUM\_VALUE\_ATTRIBUTE   | unit\_minimum\_value   |

Below are the default values and explanations for these keys:

<table><thead><tr><th width="198.53515625">Default Key</th><th>Description</th></tr></thead><tbody><tr><td><strong>is_unit_product</strong></td><td>This attribute indicates that the product is sold by weight. When creating this attribute in Omnitron, the <strong>Product Attribute Input Type</strong> should be set to <code>Boolean</code>. It takes <code>True/False</code> values. For the product to be sold by weight, this attribute must be set to <code>True</code>.</td></tr><tr><td><strong>unit_minimum_value</strong></td><td>This defines the minimum weight value that can be added to the basket. This value shows the minimum weight of the product that can be purchased in basket transactions. When creating this attribute in Omnitron, the <strong>Product Attribute Input Type</strong> should be set to <code>Text</code> and it takes an <code>Integer</code> value in grams. The default value is 0. For example, if the <code>unit_minimum_value</code> is set to 500, at least 500 grams of this product can be added to the basket.</td></tr><tr><td><strong>unit_step_value</strong></td><td>This attribute defines the weight increment frequency of the product. When creating this attribute in Omnitron, the <strong>Product Attribute Input Type</strong> should be set to <code>Text</code>, and it takes an <code>Integer</code> value in grams. For example, if the <code>product.unit_step_value</code> is set to 300: If the <code>unit_minimum_value</code> is not entered, requests can be made for values that are multiples of 300, such as 300, 600, 900, 1200. Requests for values like 200, 500, 700, 850, and 1000 will result in an error. If the <code>unit_minimum_value</code> is set to 500, requests can be made for values like 500, 800, 1100, 1400, which are obtained by adding multiples of 300 to 500. Requests for values like 200, 600, 750, 900, and 1000 will result in an error.</td></tr><tr><td><strong>unit_reference_value</strong></td><td>This defines the weight for which the set price is valid. When creating this attribute in Omnitron, the <strong>Product Attribute Input Type</strong> should be set to <code>Text</code>, and it takes an <code>Integer</code> value in grams. For example, if the <code>unit_reference_value</code> is set to 500 and the product price is set to 100 TL, then 500 grams of the product will be priced at 100 TL, and 1000 grams will be priced at 200 TL.</td></tr><tr><td><strong>basket_unit_value</strong></td><td>This attribute indicates the total weight of the product added to the basket in the basket item. It is sent in the request body.</td></tr></tbody></table>

### Example Request

```bash
curl --location 'https://{commerce_url}/baskets/basket/' \
--header 'accept: application/json, text/plain, */*' \

--data '{
    "product": "product_id",
    "quantity": 1,
    "attributes": {
        "basket_unit_value": "basket_unit_value"
    }
}'
```

### Configuration Considerations

**1.** When adding a weight-based product to the basket, the quantity value is always set to 1.

```json
{
    "product": "product_id",
    "quantity": 1,
    "attributes": {
        "basket_unit_value": 1500
    }
}
```

If the quantity is set to more than 1 for weight-based products, the system will throw a serializer error and display the following error message:

```
ValidationError("This product can not be added more than 1.")
```

**2.** When the product is deducted from stock, the weight is converted into kilograms and rounded up to the nearest whole number. This rounded value is then deducted from the stock. For example:

```
1200 g → 1.2 kg → 2 (Stock will decrease by 2)
4000 g → 4 kg → 4 (Stock will decrease by 4)
900 g → 0.9 kg → 1 (Stock will decrease by 1)
4001 g → 4.001 kg → 5 (Stock will decrease by 5)
```

**3.** The product price is calculated as follows:

```
price = (basket_unit_value * product.price / unit_reference_value)
```

**4.** The appropriate stock information is calculated based on the weight intended to be added to the basket. This calculation uses the `unit_minimum_value` and `unit_step_value` values.

For example:

* `product.unit_minimum_value: 1000`
* `product.unit_step_value: 300`

If 1500 grams is desired, it will round down to 1300 grams; if 1200 grams is desired, it will round down to 1000 grams.

The `omnishop.baskets.utils.find_appropriate_unit_amount` function is used for this calculation.

**5.** To sell the product based on weight, during stock definition, the `unit_type` field should be set to `kg` instead of `qty`.
