Files
2026-03-14 09:42:12 +00:00

88 lines
3.6 KiB
Python

# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from trytond.i18n import gettext
from trytond.model import ModelStorage, fields
from trytond.modules.sale.exceptions import SaleValidationError
from trytond.pool import Pool, PoolMeta
def product_quantity_mixin(states):
class ProductQuantityMixin(ModelStorage):
@fields.depends('product', 'quantity', 'unit')
def on_change_product(self):
pool = Pool()
Uom = pool.get('product.uom')
super().on_change_product()
if self.product and self.quantity is None:
if self.unit:
unit = self.unit
else:
unit = self.product.sale_uom
if self.product.sale_quantity_minimal:
self.quantity = Uom.compute_qty(
self.product.sale_uom,
self.product.sale_quantity_minimal,
unit)
@classmethod
def validate(cls, lines):
super().validate(lines)
for line in lines:
line.check_quantity()
def check_quantity(self):
pool = Pool()
Lang = pool.get('ir.lang')
Uom = pool.get('product.uom')
if (not self.product
or self.sale.state not in states
or self.quantity < 0):
return
lang = Lang.get()
quantity = Uom.compute_qty(
self.unit, self.quantity, self.product.sale_uom, round=False)
if self.product.sale_quantity_minimal:
if quantity < self.product.sale_quantity_minimal:
minimum = Uom.compute_qty(
self.product.sale_uom,
self.product.sale_quantity_minimal,
self.unit)
raise SaleValidationError(gettext(
'sale_product_quantity'
'.msg_sale_line_quantity_minimal',
line=self.rec_name,
quantity=lang.format_number_symbol(
self.quantity, self.unit),
minimum=lang.format_number_symbol(
minimum, self.unit)))
if self.product.sale_quantity_rounding:
remainder = round(
quantity % self.product.sale_quantity_rounding,
self.product.sale_quantity_digits)
if (remainder
and remainder != self.product.sale_quantity_rounding):
rounding = Uom.compute_qty(
self.product.sale_uom,
self.product.sale_quantity_rounding,
self.unit, round=False)
raise SaleValidationError(gettext(
'sale_product_quantity'
'.msg_sale_line_quantity_rounding',
line=self.rec_name,
quantity=lang.format_number_symbol(
self.quantity, self.unit),
rounding=lang.format_number_symbol(
rounding, self.unit)))
return ProductQuantityMixin
class Line(product_quantity_mixin(['draft']), metaclass=PoolMeta):
__name__ = 'sale.line'
class POSLine(product_quantity_mixin(['open']), metaclass=PoolMeta):
__name__ = 'sale.point.sale.line'