From 7b4499184d27ed25d3cf306713c9f8081463d91e Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Wed, 9 Jul 2025 16:58:20 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=A6=81=E6=AD=A2=E8=B4=9F?= =?UTF-8?q?=E5=BA=93=E5=AD=98=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_warehouse/__manifest__.py | 1 + sf_warehouse/models/__init__.py | 1 + sf_warehouse/models/model.py | 22 +++++++++++++--------- sf_warehouse/models/product.py | 29 +++++++++++++++++++++++++++++ sf_warehouse/views/product.xml | 17 +++++++++++++++++ 5 files changed, 61 insertions(+), 9 deletions(-) create mode 100644 sf_warehouse/models/product.py create mode 100644 sf_warehouse/views/product.xml diff --git a/sf_warehouse/__manifest__.py b/sf_warehouse/__manifest__.py index 456d3b96..28f6434e 100644 --- a/sf_warehouse/__manifest__.py +++ b/sf_warehouse/__manifest__.py @@ -16,6 +16,7 @@ # 'security/sf_stock_security.xml', 'security/ir.model.access.csv', 'wizard/wizard_view.xml', + 'views/product.xml', 'views/view.xml', 'views/shelf_location.xml', 'views/change_stock_move_views.xml', diff --git a/sf_warehouse/models/__init__.py b/sf_warehouse/models/__init__.py index 72b9b610..9035056a 100644 --- a/sf_warehouse/models/__init__.py +++ b/sf_warehouse/models/__init__.py @@ -1,2 +1,3 @@ from . import model from . import sync_common +from . import product diff --git a/sf_warehouse/models/model.py b/sf_warehouse/models/model.py index 2cb35264..74daafb4 100644 --- a/sf_warehouse/models/model.py +++ b/sf_warehouse/models/model.py @@ -471,7 +471,7 @@ class ShelfLocation(models.Model): record.display_rfid = record.product_sn_id.rfid if record.product_sn_id else '' except Exception as e: record.display_rfid = '' - + @api.depends('product_id') def _compute_tool(self): """计算工具 RFID""" @@ -594,7 +594,7 @@ class ShelfLocation(models.Model): _layer_capacity = _cc_code % record.shelf_id.layer_capacity if _layer_capacity == 0: _layer_capacity = record.shelf_id.layer_capacity - else: + else: _layer_capacity = _layer_capacity _layer = _layer+1 _layer_capacity = f"{_layer_capacity:02d}" @@ -634,7 +634,7 @@ class SfShelfLocationLot(models.Model): for item in self: if item.qty_num > item.qty: raise ValidationError('变更数量不能比库存数量大!!!') - + class SfStockMoveLine(models.Model): @@ -899,7 +899,7 @@ class SfStockMoveLine(models.Model): def _compute_current_location_id(self): # 批量获取所有相关记录的picking pickings = self.mapped('picking_id') - + # 构建源picking的移库行与目标位置的映射 origin_location_map = {} for picking in pickings: @@ -907,11 +907,11 @@ class SfStockMoveLine(models.Model): origin_move = picking.move_ids[:1].move_orig_ids[:1] if not origin_move: continue - + origin_picking = origin_move.picking_id if not origin_picking: continue - + # 为每个picking构建lot_id到location的映射 origin_location_map[picking.id] = { move_line.lot_id.id: move_line.destination_location_id @@ -919,17 +919,17 @@ class SfStockMoveLine(models.Model): lambda ml: ml.destination_location_id and ml.lot_id ) } - + # 批量更新current_location_id for record in self: current_picking = record.picking_id if not current_picking: record.current_location_id = False continue - + # 获取当前picking对应的lot_location映射 lot_dest_map = origin_location_map.get(current_picking.id, {}) - + # 查找匹配的lot_id for move_line in current_picking.move_line_ids: if move_line.lot_id and move_line.lot_id.id in lot_dest_map: @@ -1082,6 +1082,10 @@ class SfStockPicking(models.Model): 重写验证方法,当验证时意味着调拨单已经完成,已经移动到了目标货位,所以需要将当前货位的状态改为空闲 """ res = super(SfStockPicking, self).button_validate() + if any(ml.state == 'done' for ml in self.move_line_ids): + # 验证产品库存为负库存问题 + self.move_ids.product_id.verify_product_repertory(self.location_id) + for line in self.move_line_ids: if line: if line.destination_location_id: diff --git a/sf_warehouse/models/product.py b/sf_warehouse/models/product.py new file mode 100644 index 00000000..a0839512 --- /dev/null +++ b/sf_warehouse/models/product.py @@ -0,0 +1,29 @@ +from odoo import models, fields +from odoo.exceptions import ValidationError + + +class SfProductCategory(models.Model): + _inherit = 'product.category' + + negative_inventory_allowed = fields.Boolean('可负库存', default=True) + + +class SfProductTemplate(models.Model): + _inherit = 'product.product' + + def verify_product_repertory(self, location_id): + """ + 验证产品 负库存 + """ + if not location_id: + raise ValidationError('当前位置为空!!') + elif len(location_id) != 1: + raise ValidationError(f'存在多个当前位置{[item.name for item in location_id]}') + elif location_id.usage == 'supplier': + return True + for pp in self: + if not pp.categ_id.negative_inventory_allowed: + sq = pp.stock_quant_ids.filtered(lambda sq: sq.quantity < 0 and sq.location_id == location_id) + if sq: + raise ValidationError( + f'产品{pp.name}的产品类型设置为不可负库存,当前操作会导致产品{pp.name}在库存{location_id.name}上的库存数量为负!!!') diff --git a/sf_warehouse/views/product.xml b/sf_warehouse/views/product.xml new file mode 100644 index 00000000..3844b94c --- /dev/null +++ b/sf_warehouse/views/product.xml @@ -0,0 +1,17 @@ + + + + product.category.property.form.warehouse + product.category + + + + + + + + + + + + \ No newline at end of file