171 lines
6.3 KiB
Python
171 lines
6.3 KiB
Python
# The COPYRIGHT file at the top level of this repository contains the full
|
|
# copyright notices and license terms.
|
|
from trytond.model import ModelSQL, fields
|
|
from trytond.pool import Pool, PoolMeta
|
|
from trytond.pyson import Eval, Id
|
|
from trytond.modules.company.model import CompanyValueMixin
|
|
from trytond.i18n import gettext
|
|
from trytond.exceptions import UserError
|
|
|
|
__all__ = ['Configuration', 'ConfigurationCompany', 'Production', 'StockMove']
|
|
|
|
_OUTPUT_LOT_CREATION = [
|
|
('running', 'Production in Running'),
|
|
('done', 'Production is Done'),
|
|
]
|
|
|
|
|
|
class Configuration(metaclass=PoolMeta):
|
|
__name__ = 'production.configuration'
|
|
|
|
output_lot_creation = fields.MultiValue(fields.Selection(
|
|
_OUTPUT_LOT_CREATION, 'When Output Lot is created?', required=True,
|
|
help='The Production\'s state in which the Output Lot will be '
|
|
'created automatically, if the Output Product is configured to '
|
|
'require lot in production.'))
|
|
output_lot_sequence = fields.MultiValue(fields.Many2One('ir.sequence',
|
|
'Output Lot Sequence', required=True, domain=[
|
|
('company', 'in',
|
|
[Eval('context', {}).get('company', -1), None]),
|
|
('sequence_type', '=', Id('stock_lot',
|
|
'sequence_type_stock_lot')),
|
|
]))
|
|
|
|
@classmethod
|
|
def multivalue_model(cls, field):
|
|
pool = Pool()
|
|
if field in {'output_lot_creation', 'output_lot_sequence'}:
|
|
return pool.get('production.configuration.company')
|
|
return super(Configuration, cls).multivalue_model(field)
|
|
|
|
@classmethod
|
|
def default_output_lot_creation(cls, **pattern):
|
|
return cls.multivalue_model(
|
|
'output_lot_creation').default_output_lot_creation()
|
|
|
|
|
|
class ConfigurationCompany(ModelSQL, CompanyValueMixin):
|
|
'Production Configuration by Company'
|
|
__name__ = 'production.configuration.company'
|
|
|
|
output_lot_creation = fields.Selection(_OUTPUT_LOT_CREATION,
|
|
'When Output Lot is created?')
|
|
output_lot_sequence = fields.Many2One('ir.sequence',
|
|
'Output Lot Sequence', domain=[
|
|
('company', 'in', [Eval('company', -1), None]),
|
|
('sequence_type', '=', Id('stock_lot',
|
|
'sequence_type_stock_lot')),
|
|
], depends=['company'])
|
|
|
|
@classmethod
|
|
def default_output_lot_creation(cls):
|
|
return 'running'
|
|
|
|
|
|
class Production(metaclass=PoolMeta):
|
|
__name__ = 'production'
|
|
|
|
@classmethod
|
|
def run(cls, productions):
|
|
pool = Pool()
|
|
Config = pool.get('production.configuration')
|
|
config = Config(1)
|
|
if not config.output_lot_creation:
|
|
raise UserError(gettext(
|
|
'production_output_lot.missing_output_lot_creation_config'))
|
|
|
|
super(Production, cls).run(productions)
|
|
if config.output_lot_creation == 'running':
|
|
for production in productions:
|
|
production.create_output_lots()
|
|
|
|
@classmethod
|
|
def done(cls, productions):
|
|
pool = Pool()
|
|
Config = pool.get('production.configuration')
|
|
config = Config(1)
|
|
if not config.output_lot_creation:
|
|
raise UserError(gettext(
|
|
'production_output_lot.missing_output_lot_creation_config'))
|
|
|
|
if config.output_lot_creation == 'done':
|
|
for production in productions:
|
|
production.create_output_lots()
|
|
super(Production, cls).done(productions)
|
|
|
|
def create_output_lots(self):
|
|
Config = Pool().get('production.configuration')
|
|
config = Config(1)
|
|
|
|
if not config.output_lot_creation or not config.output_lot_sequence:
|
|
raise UserError(gettext(
|
|
'production_output_lot.missing_output_lot_creation_config'))
|
|
|
|
created_lots = []
|
|
drag_lot = None
|
|
|
|
if self.bom:
|
|
products = [x for x in self.bom.inputs if x.use_lot == True]
|
|
if products:
|
|
product = products[0]
|
|
inputs = [x for x in self.inputs if x.lot
|
|
and x.product == product.product]
|
|
if len(inputs) != 1:
|
|
raise UserError(gettext(
|
|
'production_output_lot.more_than_one_input_lots'))
|
|
drag_lot = inputs[0].lot
|
|
|
|
for output in self.outputs:
|
|
if output.lot:
|
|
continue
|
|
if output.product.lot_is_required(output.from_location, output.to_location):
|
|
lot = output.get_production_output_lot()
|
|
if lot:
|
|
if drag_lot:
|
|
lot.number = drag_lot.number
|
|
lot.expiration_date = (drag_lot.expiration_date if
|
|
drag_lot.expiration_date else None)
|
|
lot.shelf_life_expiration_date = (
|
|
drag_lot.shelf_life_expiration_date if
|
|
drag_lot.shelf_life_expiration_date else None)
|
|
lot.save()
|
|
output.lot = lot
|
|
output.save()
|
|
created_lots.append(lot)
|
|
return created_lots
|
|
|
|
|
|
class StockMove(metaclass=PoolMeta):
|
|
__name__ = 'stock.move'
|
|
|
|
def get_production_output_lot(self):
|
|
pool = Pool()
|
|
Lot = pool.get('stock.lot')
|
|
|
|
if not self.production_output:
|
|
return
|
|
|
|
number = self._get_output_lot_sequence().get()
|
|
lot = Lot(product=self.product, number=number)
|
|
|
|
if hasattr(Lot, 'expiration_date'):
|
|
if self.product.expiration_time:
|
|
input_expiry_dates = [i.lot.expiration_date
|
|
for i in self.production_output.inputs
|
|
if i.lot and i.lot.expiration_date]
|
|
if input_expiry_dates:
|
|
lot.expiration_date = min(input_expiry_dates)
|
|
else:
|
|
lot.on_change_product()
|
|
return lot
|
|
|
|
def _get_output_lot_sequence(self):
|
|
pool = Pool()
|
|
Config = pool.get('production.configuration')
|
|
config = Config(1)
|
|
if hasattr(self.product, 'lot_sequence') and self.product.lot_sequence:
|
|
return self.product.lot_sequence
|
|
elif not config.output_lot_sequence:
|
|
raise UserError(gettext('production_output_lot.no_sequence'))
|
|
return config.output_lot_sequence
|