parameters: (self)
docstring: Alert the user if the serial number as already been consumed/produced
docstring_summary: Alert the user if the serial number as already been consumed/produced
docstring_tokens: Alert the user if the serial number as already been consumed / produced
function: def _check_sn_uniqueness(self):
          """ Alert the user if the serial number as already been consumed/produced """
          if self.product_tracking == 'serial' and self.lot_producing_id:
              sml = self.env['stock.move.line'].search_count([
                  ('lot_id', '=', self.lot_producing_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))
  
          for move in self.move_finished_ids:
              if move.has_tracking != 'serial' or move.product_id == self.product_id:
                  continue
              for move_line in move.move_line_ids:
                  domain = [
                      ('lot_id', '=', move_line.lot_id.id),
                      ('qty_done', '=', 1),
                      ('state', '=', 'done')
                  ]
                  message = _('The serial number %(number)s used for byproduct %(product_name)s has already been produced',
                      number=move_line.lot_id.name,
                      product_name=move_line.product_id.name)
                  co_prod_move_lines = self.move_finished_ids.move_line_ids.filtered(lambda ml: ml.product_id != self.product_id)
                  domain_unbuild = domain + [
                      ('production_id', '=', False),
                      ('location_dest_id.usage', '=', 'production')
                  ]
  
                  # Check presence of same sn in previous productions
                  duplicates = self.env['stock.move.line'].search_count(domain + [
                      ('location_id.usage', '=', 'production')
                  ])
                  if duplicates:
                      # Maybe some move lines have been compensated by unbuild
                      duplicates_unbuild = self.env['stock.move.line'].search_count(domain_unbuild + [
                          ('move_id.unbuild_id', '!=', False)
                      ])
                      removed = self.env['stock.move.line'].search_count([
                          ('lot_id', '=', move_line.lot_id.id),
                          ('state', '=', 'done'),
                          ('location_dest_id.scrap_location', '=', True)
                      ])
                      # Either removed or unbuild
                      if not ((duplicates_unbuild or removed) and duplicates - duplicates_unbuild - removed == 0):
                          raise UserError(message)
                  # Check presence of same sn in current production
                  duplicates = co_prod_move_lines.filtered(lambda ml: ml.qty_done and ml.lot_id == move_line.lot_id) - move_line
                  if duplicates:
                      raise UserError(message)
  
          for move in self.move_raw_ids:
              if move.has_tracking != 'serial':
                  continue
              for move_line in move.move_line_ids:
                  if float_is_zero(move_line.qty_done, precision_rounding=move_line.product_uom_id.rounding):
                      continue
                  message = _('The serial number %(number)s used for component %(component)s has already been consumed',
                      number=move_line.lot_id.name,
                      component=move_line.product_id.name)
                  co_prod_move_lines = self.move_raw_ids.move_line_ids
  
                  # Check presence of same sn in previous productions
                  duplicates = self.env['stock.move.line'].search_count([
                      ('lot_id', '=', move_line.lot_id.id),
                      ('qty_done', '=', 1),
                      ('state', '=', 'done'),
                      ('location_dest_id.usage', '=', 'production'),
                  ])
                  if duplicates:
                      # Maybe some move lines have been compensated by unbuild
                      duplicates_returned = move.product_id._count_returned_sn_products(move_line.lot_id)
                      removed = self.env['stock.move.line'].search_count([
                          ('lot_id', '=', move_line.lot_id.id),
                          ('state', '=', 'done'),
                          ('location_dest_id.scrap_location', '=', True)
                      ])
                      # Either removed or unbuild
                      if not ((duplicates_returned or removed) and duplicates - duplicates_returned - removed == 0):
                          raise UserError(message)
                  # Check presence of same sn in current production
                  duplicates = co_prod_move_lines.filtered(lambda ml: ml.qty_done and ml.lot_id == move_line.lot_id) - move_line
                  if duplicates:
                      raise UserError(message)
function_tokens: def _check_sn_uniqueness ( self ) : if self . product_tracking == 'serial' and self . lot_producing_id : sml = self . env [ 'stock.move.line' ] . search_count ( [ ( 'lot_id' , '=' , self . lot_producing_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 ) ) for move in self . move_finished_ids : if move . has_tracking != 'serial' or move . product_id == self . product_id : continue for move_line in move . move_line_ids : domain = [ ( 'lot_id' , '=' , move_line . lot_id . id ) , ( 'qty_done' , '=' , 1 ) , ( 'state' , '=' , 'done' ) ] message = _ ( 'The serial number %(number)s used for byproduct %(product_name)s has already been produced' , number = move_line . lot_id . name , product_name = move_line . product_id . name ) co_prod_move_lines = self . move_finished_ids . move_line_ids . filtered ( lambda ml : ml . product_id != self . product_id ) domain_unbuild = domain + [ ( 'production_id' , '=' , False ) , ( 'location_dest_id.usage' , '=' , 'production' ) ] # Check presence of same sn in previous productions duplicates = self . env [ 'stock.move.line' ] . search_count ( domain + [ ( 'location_id.usage' , '=' , 'production' ) ] ) if duplicates : # Maybe some move lines have been compensated by unbuild duplicates_unbuild = self . env [ 'stock.move.line' ] . search_count ( domain_unbuild + [ ( 'move_id.unbuild_id' , '!=' , False ) ] ) removed = self . env [ 'stock.move.line' ] . search_count ( [ ( 'lot_id' , '=' , move_line . lot_id . id ) , ( 'state' , '=' , 'done' ) , ( 'location_dest_id.scrap_location' , '=' , True ) ] ) # Either removed or unbuild if not ( ( duplicates_unbuild or removed ) and duplicates - duplicates_unbuild - removed == 0 ) : raise UserError ( message ) # Check presence of same sn in current production duplicates = co_prod_move_lines . filtered ( lambda ml : ml . qty_done and ml . lot_id == move_line . lot_id ) - move_line if duplicates : raise UserError ( message ) for move in self . move_raw_ids : if move . has_tracking != 'serial' : continue for move_line in move . move_line_ids : if float_is_zero ( move_line . qty_done , precision_rounding = move_line . product_uom_id . rounding ) : continue message = _ ( 'The serial number %(number)s used for component %(component)s has already been consumed' , number = move_line . lot_id . name , component = move_line . product_id . name ) co_prod_move_lines = self . move_raw_ids . move_line_ids # Check presence of same sn in previous productions duplicates = self . env [ 'stock.move.line' ] . search_count ( [ ( 'lot_id' , '=' , move_line . lot_id . id ) , ( 'qty_done' , '=' , 1 ) , ( 'state' , '=' , 'done' ) , ( 'location_dest_id.usage' , '=' , 'production' ) , ] ) if duplicates : # Maybe some move lines have been compensated by unbuild duplicates_returned = move . product_id . _count_returned_sn_products ( move_line . lot_id ) removed = self . env [ 'stock.move.line' ] . search_count ( [ ( 'lot_id' , '=' , move_line . lot_id . id ) , ( 'state' , '=' , 'done' ) , ( 'location_dest_id.scrap_location' , '=' , True ) ] ) # Either removed or unbuild if not ( ( duplicates_returned or removed ) and duplicates - duplicates_returned - removed == 0 ) : raise UserError ( message ) # Check presence of same sn in current production duplicates = co_prod_move_lines . filtered ( lambda ml : ml . qty_done and ml . lot_id == move_line . lot_id ) - move_line if duplicates : raise UserError ( message )