diff --git a/__init__.py b/__init__.py
index 242d0429c7..6237703102 100644
--- a/__init__.py
+++ b/__init__.py
@@ -5,7 +5,9 @@ from trytond.pool import Pool
from . import product
from . import stock
-__all__ = ['register']
+from .stock import LotUnitMixin
+
+__all__ = ['LotUnitMixin', 'register']
def register():
@@ -13,6 +15,7 @@ def register():
product.Template,
product.Product,
stock.Lot,
+ stock.MoveAddLotsStartLot,
stock.Move,
stock.Inventory,
stock.ShipmentIn,
diff --git a/stock.py b/stock.py
index 6504eca5b7..7cbbe8526a 100644
--- a/stock.py
+++ b/stock.py
@@ -10,8 +10,7 @@ from trytond.pyson import Eval, Bool
from .exceptions import LotUnitQuantityError
-class Lot(metaclass=PoolMeta):
- __name__ = 'stock.lot'
+class LotUnitMixin:
unit = fields.Many2One(
'product.uom', "Unit",
@@ -21,7 +20,7 @@ class Lot(metaclass=PoolMeta):
depends=['product_default_uom_category'],
help="The biggest unit for the lot.")
unit_quantity = fields.Float(
- "Quantity", digits=(16, Eval('unit_digits', 2)),
+ "Unit Quantity", digits=(16, Eval('unit_digits', 2)),
states={
'required': Bool(Eval('unit')),
'invisible': ~Eval('unit'),
@@ -36,19 +35,10 @@ class Lot(metaclass=PoolMeta):
unit_digits = fields.Function(
fields.Integer("Unit Digits"), 'on_change_with_unit_digits')
- @classmethod
- def __setup__(cls):
- super(Lot, cls).__setup__()
- cls._modify_no_move += [
- ('unit', 'done', 'stock_lot_unit.msg_change_unit'),
- ('unit_quantity', 'done',
- 'stock_lot_unit.msg_change_unit_quantity'),
- ]
-
@fields.depends('product', methods=['on_change_unit'])
def on_change_product(self):
try:
- super(Lot, self).on_change_product()
+ super().on_change_product()
except AttributeError:
pass
if self.product and self.product.lot_unit:
@@ -72,6 +62,43 @@ class Lot(metaclass=PoolMeta):
return self.unit.digits
+class Lot(LotUnitMixin, metaclass=PoolMeta):
+ __name__ = 'stock.lot'
+
+ @classmethod
+ def __setup__(cls):
+ super(Lot, cls).__setup__()
+ cls._modify_no_move += [
+ ('unit', 'done', 'stock_lot_unit.msg_change_unit'),
+ ('unit_quantity', 'done',
+ 'stock_lot_unit.msg_change_unit_quantity'),
+ ]
+
+
+class MoveAddLotsStartLot(LotUnitMixin, metaclass=PoolMeta):
+ __name__ = 'stock.move.add.lots.start.lot'
+
+ @fields.depends(
+ 'unit', 'unit_quantity', 'quantity', 'parent', '_parent_parent.unit')
+ def _set_lot_values(self, lot):
+ pool = Pool()
+ Uom = pool.get('product.uom')
+ super()._set_lot_values(lot)
+ self.unit = lot.unit
+ self.unit_quantity = lot.unit_quantity
+ if self.parent.unit:
+ maximum_quantity = Uom.compute_qty(
+ lot.unit, lot.unit_quantity, self.parent.unit, round=False)
+ if self.quantity > maximum_quantity:
+ self.quantity = self.parent.unit.round(maximum_quantity)
+
+ def _get_lot_values(self, move):
+ values = super()._get_lot_values(move)
+ values['unit'] = self.unit
+ values['unit_quantity'] = self.unit_quantity
+ return values
+
+
class Move(metaclass=PoolMeta):
__name__ = 'stock.move'
diff --git a/stock.xml b/stock.xml
index d4115e9d43..59e5a2d692 100644
--- a/stock.xml
+++ b/stock.xml
@@ -14,5 +14,11 @@ this repository contains the full copyright notices and license terms. -->
lot_list
+
+
+ stock.move.add.lots.start.lot
+
+ lot_list
+
diff --git a/tests/scenario_stock_lot_unit_move_add.rst b/tests/scenario_stock_lot_unit_move_add.rst
new file mode 100644
index 0000000000..854464f69f
--- /dev/null
+++ b/tests/scenario_stock_lot_unit_move_add.rst
@@ -0,0 +1,72 @@
+================================
+Stock Lot Unit Move Add Scenario
+================================
+
+Imports::
+
+ >>> from decimal import Decimal
+ >>> from proteus import Model, Wizard
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import create_company
+
+Activate modules::
+
+ >>> config = activate_modules('stock_lot_unit')
+
+Create company::
+
+ >>> _ = create_company()
+
+Create product::
+
+ >>> ProductUom = Model.get('product.uom')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'Product'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.list_price = Decimal('20')
+ >>> template.save()
+ >>> product, = template.products
+
+Get stock locations::
+
+ >>> Location = Model.get('stock.location')
+ >>> storage_loc, = Location.find([('code', '=', 'STO')])
+ >>> customer_loc, = Location.find([('code', '=', 'CUS')])
+
+Create a move::
+
+ >>> Move = Model.get('stock.move')
+ >>> move = Move()
+ >>> move.from_location = storage_loc
+ >>> move.to_location = customer_loc
+ >>> move.product = product
+ >>> move.quantity = 5
+ >>> move.unit_price = Decimal('20')
+ >>> move.save()
+
+Create a lot::
+
+ >>> Lot = Model.get('stock.lot')
+ >>> lot = Lot(number='01', product=product)
+ >>> lot.unit = unit
+ >>> lot.unit_quantity = 1
+ >>> lot.save()
+
+Add a lot::
+
+ >>> add_lots = Wizard('stock.move.add.lots', [move])
+ >>> lot = add_lots.form.lots.new()
+ >>> lot.quantity
+ 5.0
+ >>> lot.product = product # proteus does not set reverse domain
+ >>> lot.number = '01'
+ >>> lot.unit == unit
+ True
+ >>> lot.unit_quantity
+ 1.0
+ >>> lot.quantity
+ 1.0
diff --git a/tests/test_stock_lot_unit.py b/tests/test_stock_lot_unit.py
index 780017ddfb..eb654bd53c 100644
--- a/tests/test_stock_lot_unit.py
+++ b/tests/test_stock_lot_unit.py
@@ -22,4 +22,8 @@ def suite():
tearDown=doctest_teardown, encoding='utf-8',
checker=doctest_checker,
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ suite.addTests(doctest.DocFileSuite('scenario_stock_lot_unit_move_add.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
return suite