diff --git a/product_sale_price_from_pricelist/README.md b/product_sale_price_from_pricelist/README.md index 4fbebb0..6b5e482 100644 --- a/product_sale_price_from_pricelist/README.md +++ b/product_sale_price_from_pricelist/README.md @@ -12,6 +12,7 @@ Automatically calculate and update product sale prices based on the last purchas - Triple discount - Manual update - **Tax-Aware Pricing**: Automatically includes tax calculations in pricing +- **Configurable Price Rounding**: Round the final theoretical price (after taxes) to a configurable step, with choice of rounding direction - **UoM Conversion**: Handles different purchase and sale units of measure - **Batch Updates**: Update theoretical prices for multiple products - **Product Flags**: Mark products for price updates and track status @@ -23,7 +24,17 @@ Automatically calculate and update product sale prices based on the last purchas - **Last purchase price**: Cost at which the product was last purchased - **Last purchase price calculation type**: Choose how to apply discounts - Mark **Last purchase price updated** when prices need to be reviewed +## Price Rounding +Pricelist can be configured to round the final theoretical price (after taxes) to a fixed step: + +- **Sale Price Rounding Step**: Interval to round to (e.g. `0.05` rounds to the nearest 5 cents). Set to `0.00` to disable. +- **Sale Price Rounding Method**: Direction applied when rounding: + - **Always up (ceil)**: rounds to the next multiple of the step *(default)* + - **Always down (floor)**: rounds to the previous multiple of the step + - **Nearest (round)**: rounds to the closest multiple of the step + +These settings are found on pricelist form under the **Sale Price Rounding** group. ## Price Calculation Types - **Without Discounts**: Uses base purchase price without discounts diff --git a/product_sale_price_from_pricelist/__manifest__.py b/product_sale_price_from_pricelist/__manifest__.py index 66ed993..f65a0da 100644 --- a/product_sale_price_from_pricelist/__manifest__.py +++ b/product_sale_price_from_pricelist/__manifest__.py @@ -1,6 +1,6 @@ { "name": "Product Sale Price from Pricelist", - "version": "16.0.1.0.0", + "version": "16.0.1.1.0", "category": "product", "summary": "Set sale price from pricelist based on last purchase price", "description": """ diff --git a/product_sale_price_from_pricelist/i18n/es.po b/product_sale_price_from_pricelist/i18n/es.po index 002dd2c..b721349 100644 --- a/product_sale_price_from_pricelist/i18n/es.po +++ b/product_sale_price_from_pricelist/i18n/es.po @@ -27,6 +27,31 @@ msgstr "Redondeo del precio de venta" msgid "Round the theoretical sale price (after taxes) to the nearest multiple of this value. Set to 0.00 to disable rounding (e.g. 0.05 rounds to the nearest 5 cents)." msgstr "Redondea el precio de venta teórico (con impuestos) al múltiplo más cercano de este valor. Pon 0,00 para desactivar el redondeo (p. ej. 0,05 redondea al céntimo más cercano de 5)." +#. module: product_sale_price_from_pricelist +#: model:ir.model.fields,field_description:product_sale_price_from_pricelist.field_product_pricelist__price_rounding_method +msgid "Sale Price Rounding Method" +msgstr "Dirección del redondeo" + +#. module: product_sale_price_from_pricelist +#: model:ir.model.fields,help:product_sale_price_from_pricelist.field_product_pricelist__price_rounding_method +msgid "Direction to apply when rounding the theoretical sale price to the configured step.\n* Always up: rounds to the next multiple (ceil).\n* Always down: rounds to the previous multiple (floor).\n* Nearest: rounds to the closest multiple (standard round)." +msgstr "Dirección a aplicar al redondear el precio de venta teórico al escalón configurado.\n* Siempre arriba: redondea al siguiente múltiplo (techo).\n* Siempre abajo: redondea al múltiplo anterior (suelo).\n* Más cercano: redondea al múltiplo más próximo (redondeo estándar)." + +#. module: product_sale_price_from_pricelist +#: model:ir.model.fields.selection,name:product_sale_price_from_pricelist.selection__product_pricelist__price_rounding_method__up +msgid "Always up (ceil)" +msgstr "Siempre arriba (techo)" + +#. module: product_sale_price_from_pricelist +#: model:ir.model.fields.selection,name:product_sale_price_from_pricelist.selection__product_pricelist__price_rounding_method__down +msgid "Always down (floor)" +msgstr "Siempre abajo (suelo)" + +#. module: product_sale_price_from_pricelist +#: model:ir.model.fields.selection,name:product_sale_price_from_pricelist.selection__product_pricelist__price_rounding_method__round +msgid "Nearest (round)" +msgstr "Más cercano (redondeo)" + #. module: product_sale_price_from_pricelist #: model:ir.model.fields,field_description:product_sale_price_from_pricelist.field_product_product__configured_sale_margin #: model:ir.model.fields,field_description:product_sale_price_from_pricelist.field_product_template__configured_sale_margin diff --git a/product_sale_price_from_pricelist/i18n/product_sale_price_from_pricelist.pot b/product_sale_price_from_pricelist/i18n/product_sale_price_from_pricelist.pot index b5019fc..95b1bcb 100644 --- a/product_sale_price_from_pricelist/i18n/product_sale_price_from_pricelist.pot +++ b/product_sale_price_from_pricelist/i18n/product_sale_price_from_pricelist.pot @@ -25,6 +25,31 @@ msgstr "" msgid "Round the theoretical sale price (after taxes) to the nearest multiple of this value. Set to 0.00 to disable rounding (e.g. 0.05 rounds to the nearest 5 cents)." msgstr "" +#. module: product_sale_price_from_pricelist +#: model:ir.model.fields,field_description:product_sale_price_from_pricelist.field_product_pricelist__price_rounding_method +msgid "Sale Price Rounding Method" +msgstr "" + +#. module: product_sale_price_from_pricelist +#: model:ir.model.fields,help:product_sale_price_from_pricelist.field_product_pricelist__price_rounding_method +msgid "Direction to apply when rounding the theoretical sale price to the configured step.\n* Always up: rounds to the next multiple (ceil).\n* Always down: rounds to the previous multiple (floor).\n* Nearest: rounds to the closest multiple (standard round)." +msgstr "" + +#. module: product_sale_price_from_pricelist +#: model:ir.model.fields.selection,name:product_sale_price_from_pricelist.selection__product_pricelist__price_rounding_method__up +msgid "Always up (ceil)" +msgstr "" + +#. module: product_sale_price_from_pricelist +#: model:ir.model.fields.selection,name:product_sale_price_from_pricelist.selection__product_pricelist__price_rounding_method__down +msgid "Always down (floor)" +msgstr "" + +#. module: product_sale_price_from_pricelist +#: model:ir.model.fields.selection,name:product_sale_price_from_pricelist.selection__product_pricelist__price_rounding_method__round +msgid "Nearest (round)" +msgstr "" + #. module: product_sale_price_from_pricelist #: model:ir.model.fields,field_description:product_sale_price_from_pricelist.field_product_product__configured_sale_margin #: model:ir.model.fields,field_description:product_sale_price_from_pricelist.field_product_template__configured_sale_margin diff --git a/product_sale_price_from_pricelist/models/product_pricelist.py b/product_sale_price_from_pricelist/models/product_pricelist.py index 1442d6b..2c71e20 100644 --- a/product_sale_price_from_pricelist/models/product_pricelist.py +++ b/product_sale_price_from_pricelist/models/product_pricelist.py @@ -19,6 +19,20 @@ class ProductPricelist(models.Model): help="Round the theoretical sale price (after taxes) to the nearest multiple of this value. " "Set to 0.00 to disable rounding (e.g. 0.05 rounds to the nearest 5 cents).", ) + price_rounding_method = fields.Selection( + [ + ("up", "Always up (ceil)"), + ("down", "Always down (floor)"), + ("round", "Nearest (round)"), + ], + string="Sale Price Rounding Method", + default="round", + required=True, + help="Direction to apply when rounding the theoretical sale price to the configured step.\n" + "* Always up: rounds to the next multiple (ceil).\n" + "* Always down: rounds to the previous multiple (floor).\n" + "* Nearest: rounds to the closest multiple (standard round).", + ) def _compute_price_rule(self, products, qty, uom=None, date=False, **kwargs): ProductPricelistItem = self.env["product.pricelist.item"] diff --git a/product_sale_price_from_pricelist/models/product_template.py b/product_sale_price_from_pricelist/models/product_template.py index 49c10a7..449baf6 100644 --- a/product_sale_price_from_pricelist/models/product_template.py +++ b/product_sale_price_from_pricelist/models/product_template.py @@ -130,7 +130,15 @@ class ProductTemplate(models.Model): # Round to configurable step (defined on the pricelist) step = pricelist.price_rounding_step if step: - price_with_taxes = math.ceil(price_with_taxes / step) * step + method = pricelist.price_rounding_method + if method == "down": + price_with_taxes = ( + math.floor(price_with_taxes / step) * step + ) + elif method == "round": + price_with_taxes = round(price_with_taxes / step) * step + else: # "up" (default) + price_with_taxes = math.ceil(price_with_taxes / step) * step template.write( { diff --git a/product_sale_price_from_pricelist/views/product_view.xml b/product_sale_price_from_pricelist/views/product_view.xml index 9a59924..492db34 100644 --- a/product_sale_price_from_pricelist/views/product_view.xml +++ b/product_sale_price_from_pricelist/views/product_view.xml @@ -49,6 +49,7 @@ +