[FIX] mrp: check SN uniqueness on WO
When marking a WO as done, if the serial number defined is related to an
unbuilt product, an error will be raised and the user will not be able
to mark the WO as done
To reproduce the issue:
1. Create a BoM for product P with one operation
- P is tracked by SN
2. Produce one P with serial S
3. Unbuild it
4. Create and confirm a second MO with 1 x P
5. Start the WO
6. On tablet view, set the finished lot to S
7. Mark the WO as done
Error: a UserError is raised because "This serial number [...] has
already been produced". However, this serial number has been unbuilt so
the worker should be able to use it again
When marking the WO as done, we check the uniqueness of the defined
serial number. But:
- The check is not accurate enough, hence the above error
- The lot of the WO is a computed/inverse field based on lot of the MO
- Once the WO closed, we can still change the lot of the MO
- When marking the MO as done, a better method checks the SN uniqueness
(does not fail in the above case)
Therefore, the checking on WO side is useless. We should let the MO side
handle this.
Moreover, let's say that there is already one P in stock with serial S2.
On tablet view, if the worker set the lot to S2, there should be a
warning so he can be aware of the situation. This is already the case on
MO side:
https://github.com/odoo/odoo/blob/45e37b2ad7bdcfd9f9f7e1dabbd0a99c9a0b5cdc/addons/mrp/models/mrp_production.py#L694-L705
(This commit is linked to a similar commit OE side, same opw)
OPW-3002424
closes odoo/odoo#106152
X-original-commit: 60a4c37c781ceb20123cb99603ddd2890b1c806c
Related: odoo/enterprise#34183
Signed-off-by: Tiffany Chang <tic@odoo.com>
Signed-off-by: Adrien Widart <awt@odoo.com>
This commit is contained in:
@@ -736,12 +736,18 @@ class MrpProduction(models.Model):
|
||||
|
||||
@api.onchange('lot_producing_id')
|
||||
def _onchange_lot_producing(self):
|
||||
if self.product_id.tracking == 'serial' and self.lot_producing_id:
|
||||
message, dummy = self.env['stock.quant'].sudo()._check_serial_number(self.product_id,
|
||||
self.lot_producing_id,
|
||||
self.company_id)
|
||||
res = self._can_produce_serial_number()
|
||||
if res is not True:
|
||||
return res
|
||||
|
||||
def _can_produce_serial_number(self, sn=None):
|
||||
self.ensure_one()
|
||||
sn = sn or self.lot_producing_id
|
||||
if self.product_id.tracking == 'serial' and sn:
|
||||
message, dummy = self.env['stock.quant'].sudo()._check_serial_number(self.product_id, sn, self.company_id)
|
||||
if message:
|
||||
return {'warning': {'title': _('Warning'), 'message': message}}
|
||||
return True
|
||||
|
||||
@api.onchange('product_id', 'move_raw_ids')
|
||||
def _onchange_product_id(self):
|
||||
|
||||
@@ -437,6 +437,12 @@ class MrpWorkorder(models.Model):
|
||||
)
|
||||
return interval['hours'] * 60
|
||||
|
||||
@api.onchange('finished_lot_id')
|
||||
def _onchange_finished_lot_id(self):
|
||||
res = self.production_id._can_produce_serial_number(sn=self.finished_lot_id)
|
||||
if res is not True:
|
||||
return res
|
||||
|
||||
def write(self, values):
|
||||
if 'production_id' in values and any(values['production_id'] != w.production_id.id for w in self):
|
||||
raise UserError(_('You cannot link this work order to another manufacturing order.'))
|
||||
@@ -843,18 +849,6 @@ class MrpWorkorder(models.Model):
|
||||
float_round(self.qty_producing, precision_rounding=rounding)
|
||||
)
|
||||
|
||||
def _check_sn_uniqueness(self):
|
||||
""" Alert the user if the serial number as already been produced """
|
||||
if self.product_tracking == 'serial' and self.finished_lot_id:
|
||||
sml = self.env['stock.move.line'].search_count([
|
||||
('lot_id', '=', self.finished_lot_id.id),
|
||||
('location_id.usage', '=', 'production'),
|
||||
('qty_done', '=', 1),
|
||||
('state', '=', 'done')
|
||||
])
|
||||
if sml:
|
||||
raise UserError(_('This serial number for product %s has already been produced', self.product_id.name))
|
||||
|
||||
def _should_start_timer(self):
|
||||
return True
|
||||
|
||||
|
||||
Reference in New Issue
Block a user