product_lot_sequence_per_pr.../models/product_template.py

95 lines
4.1 KiB
Python

from odoo import api, fields, models
class ProductTemplate(models.Model):
_inherit = 'product.template'
lot_sequence_id = fields.Many2one(
'ir.sequence',
string='Serial/Lot Numbers Sequence',
domain=[('code', '=', 'stock.lot.serial')],
help='Technical Field: The Ir.Sequence record that is used to generate serial/lot numbers for this product'
)
serial_prefix_format = fields.Char(
'Custom Lot/Serial',
compute='_compute_serial_prefix_format',
inverse='_inverse_serial_prefix_format',
help='Set a prefix to generate serial/lot numbers automatically when receiving or producing this product. '
'Use % codes like %(y)s for year, %(month)s for month, etc.'
)
next_serial = fields.Char(
'Next Number',
compute='_compute_next_serial',
help='The next serial/lot number to be generated for this product'
)
@api.depends('lot_sequence_id', 'lot_sequence_id.prefix')
def _compute_serial_prefix_format(self):
for template in self:
template.serial_prefix_format = template.lot_sequence_id.prefix or ""
def _inverse_serial_prefix_format(self):
valid_sequences = self.env['ir.sequence'].search([('prefix', 'in', self.mapped('serial_prefix_format'))])
sequences_by_prefix = {seq.prefix: seq for seq in valid_sequences}
for template in self:
if template.serial_prefix_format:
if template.serial_prefix_format in sequences_by_prefix:
template.lot_sequence_id = sequences_by_prefix[template.serial_prefix_format]
else:
# Create a new sequence with the given prefix
new_sequence = self.env['ir.sequence'].create({
'name': f'{template.name} Serial Sequence',
'code': 'stock.lot.serial',
'prefix': template.serial_prefix_format,
'padding': 7,
'company_id': False, # Global sequence to avoid cross-company conflicts
})
template.lot_sequence_id = new_sequence
sequences_by_prefix[template.serial_prefix_format] = new_sequence
else:
# Reset to default if no prefix
template.lot_sequence_id = self.env.ref('stock.sequence_production_lots', raise_if_not_found=False)
@api.depends('serial_prefix_format', 'lot_sequence_id')
def _compute_next_serial(self):
from datetime import datetime
for template in self:
if template.lot_sequence_id:
seq = template.lot_sequence_id
# Build the interpolation dictionary for date formatting
now = datetime.now()
interpolation_dict = {
'year': now.strftime('%Y'),
'y': now.strftime('%y'),
'month': now.strftime('%m'),
'day': now.strftime('%d'),
'doy': now.strftime('%j'),
'woy': now.strftime('%W'),
'weekday': now.strftime('%w'),
'h24': now.strftime('%H'),
'h12': now.strftime('%I'),
'min': now.strftime('%M'),
'sec': now.strftime('%S'),
}
# Format prefix and suffix with date codes
try:
prefix = (seq.prefix or '') % interpolation_dict if seq.prefix else ''
except (KeyError, ValueError):
prefix = seq.prefix or ''
try:
suffix = (seq.suffix or '') % interpolation_dict if seq.suffix else ''
except (KeyError, ValueError):
suffix = seq.suffix or ''
template.next_serial = '{}{:0{}d}{}'.format(
prefix,
seq.number_next_actual,
seq.padding,
suffix
)
else:
template.next_serial = '00001'