diff options
Diffstat (limited to 'indoteknik_custom/models/stock_move.py')
| -rw-r--r-- | indoteknik_custom/models/stock_move.py | 71 |
1 files changed, 69 insertions, 2 deletions
diff --git a/indoteknik_custom/models/stock_move.py b/indoteknik_custom/models/stock_move.py index cac88287..320c175f 100644 --- a/indoteknik_custom/models/stock_move.py +++ b/indoteknik_custom/models/stock_move.py @@ -2,6 +2,8 @@ from odoo import fields, models, api from odoo.tools.misc import format_date, OrderedSet from odoo.exceptions import UserError import logging +from odoo.tools.float_utils import float_compare, float_is_zero, float_round + _logger = logging.getLogger(__name__) @@ -20,7 +22,6 @@ class StockMove(models.Model): hold_outgoingg = fields.Boolean('Hold Outgoing', default=False) product_image = fields.Binary(related="product_id.image_128", string="Product Image", readonly=True) partial = fields.Boolean('Partial?', default=False) - # Ambil product uom dari SO line @api.model def create(self, vals): @@ -28,7 +29,66 @@ class StockMove(models.Model): sale_line = self.env['sale.order.line'].browse(vals['sale_line_id']) vals['product_uom'] = sale_line.product_uom.id return super().create(vals) + + def _update_reserved_quantity( + self, need, available_quantity, location_id, + lot_id=None, package_id=None, owner_id=None, strict=True + ): + self.ensure_one() + picking = self.picking_id + if picking and 'BU/PICK' in (picking.name or ''): + _logger.info(f"[LocatorLogic] Running custom locator logic for {picking.name}") + + # Ambil semua lokasi anak dari source location (ex: BU/Stock) + locations = self.env['stock.location'].search([ + ('id', 'child_of', self.location_id.id), + ('usage', '=', 'internal'), + ('is_locked', '=', False), + # ('id', '!=', 57), + ], order='rack_level asc') + + total_reserved = 0.0 + remaining_need = need + + for loc in locations: + if remaining_need <= 0: + break + + quants = self.env['stock.quant']._gather(self.product_id, loc) + for quant in quants: + if quant.available_quantity <= 0: + continue + + qty_to_take = min(quant.available_quantity, remaining_need) + _logger.info( + f"[LocatorLogic] Reserving {qty_to_take}/{remaining_need} " + f"from {loc.display_name} (avail={quant.available_quantity})" + ) + + reserved_now = super(StockMove, self)._update_reserved_quantity( + qty_to_take, quant.available_quantity, quant.location_id, + lot_id, package_id, owner_id, strict + ) + + total_reserved += reserved_now + remaining_need -= reserved_now + + if remaining_need <= 0: + break + + if total_reserved > 0: + _logger.info(f"[LocatorLogic] Total reserved: {total_reserved} / {need}") + return total_reserved + else: + _logger.info("[LocatorLogic] No available stock found in unlocked locations by level order.") + return 0 + + return super(StockMove, self)._update_reserved_quantity( + need, available_quantity, location_id, lot_id, package_id, owner_id, strict + ) + + # @api.model_create_multi # def create(self, vals_list): # moves = super(StockMove, self).create(vals_list) @@ -288,4 +348,11 @@ class StockMoveLine(models.Model): move = self.env['stock.move'].browse(vals['move_id']) if move.product_uom: vals['product_uom_id'] = move.product_uom.id - return super().create(vals)
\ No newline at end of file + return super().create(vals) + def _action_done(self): + for line in self: + if line.location_dest_id and line.location_dest_id.is_locked: + raise UserError(f"Lokasi '{line.location_dest_id.display_name}' sedang dikunci dan tidak bisa menerima barang.") + if line.location_id and line.location_id.is_locked: + raise UserError(f"Lokasi '{line.location_id.display_name}' sedang dikunci dan tidak bisa reserve barang.") + return super(StockMoveLine, self)._action_done() |
