Create lot for output product when needed

When the output product has a sequence and a lot is required, we create a new
lot to set on the output move.

Closes #11923
This commit is contained in:
Cédric Krier
2023-01-24 10:53:23 +01:00
parent 8ee974fb19
commit ee5cb27962
7 changed files with 118 additions and 2 deletions
+1
View File
@@ -1,3 +1,4 @@
* Create lot for output product when needed
* Assign all possible productions when trying
Version 6.6.0 - 2022-10-31
+1
View File
@@ -28,6 +28,7 @@ def register():
module='production', type_='model')
Pool.register(
stock.LotTrace,
production.Production_Lot,
module='production', type_='model', depends=['stock_lot'])
Pool.register(
bom.OpenBOMTree,
+25 -1
View File
@@ -15,7 +15,7 @@ from trytond.model import (
from trytond.modules.company.model import employee_field, set_employee
from trytond.modules.product import price_digits, round_price
from trytond.modules.stock.shipment import ShipmentAssignMixin
from trytond.pool import Pool
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Bool, Eval, If
from trytond.transaction import Transaction
@@ -830,3 +830,27 @@ class Production(ShipmentAssignMixin, Workflow, ModelSQL, ModelView):
if self.warehouse:
return (self.warehouse.production_output_location
or self.warehouse.storage_location)
class Production_Lot(metaclass=PoolMeta):
__name__ = 'production'
@classmethod
@ModelView.button
@Workflow.transition('done')
def done(cls, productions):
pool = Pool()
Lot = pool.get('stock.lot')
Move = pool.get('stock.move')
lots, moves = [], []
for production in productions:
for move in production.outputs:
if not move.lot and move.product.lot_is_required(
move.from_location, move.to_location):
move.add_lot()
if move.lot:
lots.append(move.lot)
moves.append(move)
Lot.save(lots)
Move.save(moves)
super().done(productions)
+4 -1
View File
@@ -47,7 +47,10 @@ for dep in info.get('depends', []):
requires.append(get_require_version('trytond_%s' % dep))
requires.append(get_require_version('trytond'))
tests_require = [get_require_version('proteus')]
tests_require = [
get_require_version('proteus'),
get_require_version('trytond_stock_lot'),
]
setup(name=name,
version=version,
@@ -0,0 +1,70 @@
====================================
Stock Lot Number Production Scenario
====================================
Imports::
>>> from decimal import Decimal
>>> from proteus import Model
>>> from trytond.tests.tools import activate_modules
>>> from trytond.modules.company.tests.tools import (
... create_company, get_company)
Activate modules::
>>> config = activate_modules(['stock_lot', 'production'])
>>> ProductTemplate = Model.get('product.template')
>>> Production = Model.get('production')
>>> Production = Model.get('production')
>>> Sequence = Model.get('ir.sequence')
>>> SequenceType = Model.get('ir.sequence.type')
>>> UoM = Model.get('product.uom')
Create company::
>>> _ = create_company()
>>> company = get_company()
Create lot sequence::
>>> sequence_type, = SequenceType.find(
... [('name', '=', "Stock Lot")], limit=1)
>>> sequence = Sequence(name="Lot", sequence_type=sequence_type)
>>> sequence.save()
Create product::
>>> unit, = UoM.find([('name', '=', 'Unit')])
>>> template = ProductTemplate()
>>> template.name = "Product"
>>> template.default_uom = unit
>>> template.type = 'goods'
>>> template.list_price = Decimal('10.0000')
>>> template.lot_required = ['storage']
>>> template.lot_sequence = sequence
>>> template.save()
>>> product, = template.products
Make a production::
>>> production = Production()
>>> output = production.outputs.new()
>>> output.from_location = production.location
>>> output.to_location = production.warehouse.storage_location
>>> output.product = product
>>> output.quantity = 1
>>> output.unit_price = Decimal(0)
>>> output.currency = production.company.currency
>>> production.click('wait')
>>> production.click('assign_force')
>>> production.click('run')
>>> production.click('done')
>>> production.state
'done'
>>> output, = production.outputs
>>> bool(output.lot)
True
+11
View File
@@ -112,3 +112,14 @@ class Product(metaclass=PoolMeta):
def lot_is_required(self, from_, to):
'Is product lot required for move with "from_" and "to" location ?'
return any(l.type in (self.lot_required or []) for l in [from_, to])
def create_lot(self):
pool = Pool()
Lot = pool.get('stock.lot')
if self.lot_sequence:
lot = Lot(product=self)
try:
lot.on_change_product()
except AttributeError:
pass
return lot
+6
View File
@@ -433,6 +433,12 @@ class Move(metaclass=PoolMeta):
def add_lots_wizard(cls, moves):
pass
def add_lot(self):
if not self.lot and self.product:
lot = self.product.create_lot()
if lot:
self.lot = lot
def check_lot(self):
"Check if lot is required"
if (self.state == 'done'