feat: Add picking type to stock moves and enhance picking type and allowed source location inheritance for move lines, including production contexts.

This commit is contained in:
Suherdy Yacob 2026-03-10 11:50:06 +07:00
parent f246f885a8
commit 9692283620
2 changed files with 51 additions and 12 deletions

View File

@ -7,9 +7,25 @@ class StockMove(models.Model):
allowed_source_location_ids = fields.Many2many(
'stock.location', string='Allowed Source Locations',
compute='_compute_allowed_source_location_ids',
store=True, precompute=True, compute_sudo=True
store=True, compute_sudo=True
)
picking_type_id = fields.Many2one(
'stock.picking.type', 'Operation Type',
compute='_compute_picking_type_id', store=True, readonly=False)
@api.depends('picking_id.picking_type_id', 'raw_material_production_id.picking_type_id', 'production_id.picking_type_id')
def _compute_picking_type_id(self):
for move in self:
if move.picking_id:
move.picking_type_id = move.picking_id.picking_type_id
elif move.raw_material_production_id:
move.picking_type_id = move.raw_material_production_id.picking_type_id
elif move.production_id:
move.picking_type_id = move.production_id.picking_type_id
elif not move.picking_type_id:
move.picking_type_id = False
@api.depends('picking_type_id', 'picking_type_id.default_location_src_ids', 'picking_id.allowed_source_location_ids', 'raw_material_production_id.allowed_source_location_ids', 'production_id.allowed_source_location_ids')
def _compute_allowed_source_location_ids(self):
for move in self:

View File

@ -8,39 +8,62 @@ class StockMoveLine(models.Model):
picking_type_id = fields.Many2one(
'stock.picking.type', 'Operation type', compute='_compute_picking_type_id',
store=True, precompute=True, compute_sudo=True)
store=True, compute_sudo=True)
allowed_source_location_ids = fields.Many2many(
'stock.location', string='Allowed Source Locations',
compute='_compute_allowed_source_location_ids',
store=True, precompute=True
compute='_compute_allowed_source_location_ids'
)
@api.depends('picking_id', 'move_id.picking_type_id')
@api.model
def default_get(self, fields_list):
res = super().default_get(fields_list)
if 'allowed_source_location_ids' in fields_list and not res.get('allowed_source_location_ids'):
move_id = res.get('move_id') or self.env.context.get('default_move_id')
if move_id:
move = self.env['stock.move'].browse(move_id)
if move.exists() and move.allowed_source_location_ids:
res['allowed_source_location_ids'] = [fields.Command.set(move.allowed_source_location_ids.ids)]
return res
@api.depends('picking_id', 'move_id.picking_type_id', 'move_id.raw_material_production_id.picking_type_id', 'move_id.production_id.picking_type_id')
def _compute_picking_type_id(self):
for line in self:
if line.picking_id:
line.picking_type_id = line.picking_id.picking_type_id
_logger.info(f"LOCATION_RESTRICT: Line {line.id} picking_type_id from picking: {line.picking_type_id.name if line.picking_type_id else 'None'}")
elif line.move_id:
line.picking_type_id = line.move_id.picking_type_id
_logger.info(f"LOCATION_RESTRICT: Line {line.id} picking_type_id from move: {line.picking_type_id.name if line.picking_type_id else 'None'}")
line.picking_type_id = line.move_id.picking_type_id or \
(line.move_id.raw_material_production_id.picking_type_id if line.move_id.raw_material_production_id else False) or \
(line.move_id.production_id.picking_type_id if line.move_id.production_id else False)
_logger.info(f"LOCATION_RESTRICT: Line {line.id} picking_type_id from move/production: {line.picking_type_id.name if line.picking_type_id else 'None'}")
else:
line.picking_type_id = False
_logger.info(f"LOCATION_RESTRICT: Line {line.id} NO picking_type_id")
@api.depends('picking_type_id', 'picking_type_id.default_location_src_ids')
@api.depends('picking_type_id', 'picking_type_id.default_location_src_ids', 'move_id.allowed_source_location_ids')
def _compute_allowed_source_location_ids(self):
for line in self:
line.allowed_source_location_ids = line.picking_type_id.default_location_src_ids
move = line.move_id
if not move and self.env.context.get('default_move_id'):
move = self.env['stock.move'].browse(self.env.context.get('default_move_id'))
if move and move.exists() and move.allowed_source_location_ids:
line.allowed_source_location_ids = move.allowed_source_location_ids
else:
line.allowed_source_location_ids = line.picking_type_id.default_location_src_ids
_logger.info(f"LOCATION_RESTRICT: Line {line.id} allowed locations: {[loc.complete_name for loc in line.allowed_source_location_ids]}")
@api.onchange('move_id')
def _onchange_move_id_restrict(self):
"""Populate allowed locations from move for virtual records"""
if self.move_id and self.move_id.picking_type_id:
self.allowed_source_location_ids = self.move_id.picking_type_id.default_location_src_ids
_logger.info(f"LOCATION_RESTRICT ONCHANGE: Setting allowed from move {self.move_id.id}: {[loc.complete_name for loc in self.allowed_source_location_ids]}")
if self.move_id:
if self.move_id.allowed_source_location_ids:
self.allowed_source_location_ids = self.move_id.allowed_source_location_ids
_logger.info(f"LOCATION_RESTRICT ONCHANGE: Setting allowed from move {self.move_id.id} (specific ids): {[loc.complete_name for loc in self.allowed_source_location_ids]}")
elif self.move_id.picking_type_id:
self.allowed_source_location_ids = self.move_id.picking_type_id.default_location_src_ids
_logger.info(f"LOCATION_RESTRICT ONCHANGE: Setting allowed from move {self.move_id.id} (picking type defaults): {[loc.complete_name for loc in self.allowed_source_location_ids]}")
@api.onchange('picking_id')
def _onchange_picking_id_restrict(self):