diff --git a/jikimo_purchase_request/__manifest__.py b/jikimo_purchase_request/__manifest__.py index dad34ddc..3221a54e 100644 --- a/jikimo_purchase_request/__manifest__.py +++ b/jikimo_purchase_request/__manifest__.py @@ -12,12 +12,13 @@ 'views/mrp_production.xml', 'views/purchase_request_view.xml', 'wizard/purchase_request_line_make_purchase_order_view.xml', + 'views/purchase_request_line_view.xml', ], - # 'assets': { - # 'web.assets_backend': [ - # 'jikimo_purchase_request/static/src/**/*' - # ], - # }, + 'assets': { + 'web.assets_backend': [ + 'jikimo_purchase_request/static/src/**/*' + ], + }, 'application': True, 'installable': True, 'auto_install': False, diff --git a/jikimo_purchase_request/models/purchase_request.py b/jikimo_purchase_request/models/purchase_request.py index 9e610612..3ecd2161 100644 --- a/jikimo_purchase_request/models/purchase_request.py +++ b/jikimo_purchase_request/models/purchase_request.py @@ -47,6 +47,19 @@ class PurchaseRequestLine(models.Model): ('outsourcing', "委外加工"), ], string='供货方式', compute='_compute_supply_method', store=True) + purchase_request_count = fields.Integer(string='采购申请数量', compute='_compute_purchase_request_count', readonly=True) + purchase_count = fields.Integer(string="采购订单数量", compute="_compute_purchase_count", readonly=True) + + @api.depends("purchase_lines") + def _compute_purchase_count(self): + for rec in self: + rec.purchase_count = len(rec.mapped("purchase_lines.order_id")) + + @api.depends('request_id') + def _compute_purchase_request_count(self): + for order in self: + order.purchase_request_count = len(order.request_id) + @api.depends('origin') def _compute_supply_method(self): for prl in self: @@ -98,3 +111,33 @@ class PurchaseRequestLine(models.Model): else: record.part_number = record.product_id.part_number record.part_name = record.product_id.part_name + + def _compute_qty_to_buy(self): + for pr in self: + qty_to_buy = sum(pr.mapped("product_qty")) - sum(pr.mapped("qty_done")) - sum(pr.mapped("qty_in_progress")) + pr.qty_to_buy = qty_to_buy > 0.0 + pr.pending_qty_to_receive = qty_to_buy + + def action_view_purchase_request(self): + action = self.env["ir.actions.actions"]._for_xml_id("purchase_request.purchase_request_form_action") + action.update({ + 'res_id': self.request_id.id, + 'views': [[False, 'form']], + }) + return action + + def action_view_purchase_order(self): + action = self.env["ir.actions.actions"]._for_xml_id("purchase.purchase_rfq") + lines = self.mapped("purchase_lines.order_id") + if len(lines) > 1: + action["domain"] = [("id", "in", lines.ids)] + elif lines: + action["views"] = [ + (self.env.ref("purchase.purchase_order_form").id, "form") + ] + action["res_id"] = lines.id + origin_context = ast.literal_eval(action['context']) + if 'search_default_draft' in origin_context: + origin_context.pop('search_default_draft') + action['context'] = origin_context + return action diff --git a/jikimo_purchase_request/static/src/change.scss b/jikimo_purchase_request/static/src/change.scss new file mode 100644 index 00000000..be14ac07 --- /dev/null +++ b/jikimo_purchase_request/static/src/change.scss @@ -0,0 +1,3 @@ +th[data-name=keep_description] { + min-width: 220px; +} \ No newline at end of file diff --git a/jikimo_purchase_request/views/purchase_request_line_view.xml b/jikimo_purchase_request/views/purchase_request_line_view.xml new file mode 100644 index 00000000..51b9e09e --- /dev/null +++ b/jikimo_purchase_request/views/purchase_request_line_view.xml @@ -0,0 +1,22 @@ + + + purchase.request.line.sf.form + purchase.request.line + + + +
+ + +
+
+ +
+
+
diff --git a/jikimo_purchase_request/wizard/purchase_request_line_make_purchase_order.py b/jikimo_purchase_request/wizard/purchase_request_line_make_purchase_order.py index 16248b7b..81722ec5 100644 --- a/jikimo_purchase_request/wizard/purchase_request_line_make_purchase_order.py +++ b/jikimo_purchase_request/wizard/purchase_request_line_make_purchase_order.py @@ -104,7 +104,16 @@ class PurchaseRequestLineMakePurchaseOrder(models.TransientModel): # 去掉合并必须同一采购组的限制 pass - + def get_items(self, request_line_ids): + request_line_obj = self.env["purchase.request.line"] + items = [] + request_lines = request_line_obj.browse(request_line_ids).filtered(lambda line: line.pending_qty_to_receive > 0) + self._check_valid_request_line(request_line_ids) + self.check_group(request_lines) + for line in request_lines: + items.append([0, 0, self._prepare_item(line)]) + return items + class PurchaseRequestLineMakePurchaseOrderItem(models.TransientModel): _inherit = "purchase.request.line.make.purchase.order.item" diff --git a/sf_manufacturing/models/product_template.py b/sf_manufacturing/models/product_template.py index 41637123..775df50e 100644 --- a/sf_manufacturing/models/product_template.py +++ b/sf_manufacturing/models/product_template.py @@ -1030,6 +1030,7 @@ class ResProductMo(models.Model): 'single_manufacturing': product_id.single_manufacturing, 'is_bfm': True, 'active': True, + 'tracking': finish_product.tracking, # 坯料的跟踪方式跟随成品 } # 外协和采购生成的坯料需要根据材料型号绑定供应商 if route_type == 'subcontract' or route_type == 'purchase': diff --git a/sf_manufacturing/models/sale_order.py b/sf_manufacturing/models/sale_order.py index c8cc129d..4ce8750c 100644 --- a/sf_manufacturing/models/sale_order.py +++ b/sf_manufacturing/models/sale_order.py @@ -59,6 +59,7 @@ class SaleOrder(models.Model): line.product_id.product_tmpl_id.copy_template(product_template_id) # 将模板上的single_manufacturing属性复制到成品上 line.product_id.single_manufacturing = product_template_id.single_manufacturing + line.product_id.tracking = product_template_id.tracking order_id = self product = line.product_id diff --git a/sf_warehouse/models/model.py b/sf_warehouse/models/model.py index 65cca601..f47421ef 100644 --- a/sf_warehouse/models/model.py +++ b/sf_warehouse/models/model.py @@ -812,40 +812,49 @@ class SfStockMoveLine(models.Model): # # 从目标stock.move对象获取目标stock.picking对象 # dest_picking = dest_move.picking_id if dest_move else False # # 现在,dest_picking就是current_picking的下一步 + # 添加所有需要的依赖字段 @api.depends('location_id') def _compute_current_location_id(self): + # 批量获取所有相关记录的picking + pickings = self.mapped('picking_id') + + # 构建源picking的移库行与目标位置的映射 + origin_location_map = {} + for picking in pickings: + # 获取源picking + 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 + for move_line in origin_picking.move_line_ids.filtered( + lambda ml: ml.destination_location_id and ml.lot_id + ) + } + + # 批量更新current_location_id for record in self: - # 使用record代替self来引用当前遍历到的记录 - logging.info('record.picking_id.name: %s' % record.picking_id.name) - logging.info('record.env: %s' % record.env['stock.picking'].search([('name', '=', record.picking_id.name)])) - - # 获取当前的stock.picking对象 - current_picking = record.env['stock.picking'].search([('name', '=', record.picking_id.name)], limit=1) - - # 获取当前picking的第一个stock.move对象 - current_move = current_picking.move_ids[0] if current_picking.move_ids else False - - # 如果存在相关的stock.move对象 - if current_move: - # 获取源stock.move对象 - origin_move = current_move.move_orig_ids[0] if current_move.move_orig_ids else False - - # 从源stock.move对象获取源stock.picking对象 - origin_picking = origin_move.picking_id if origin_move else False - - # 如果前一个调拨单有目标货位 - if origin_picking: - for i in current_picking.move_line_ids: - for j in origin_picking.move_line_ids: - if j.destination_location_id and i.lot_id == j.lot_id: - # 更新当前记录的current_location_id字段 - record.current_location_id = j.destination_location_id - # # 获取目标stock.move对象 - # dest_move = current_move.move_dest_ids[0] if current_move.move_dest_ids else False - # - # # 从目标stock.move对象获取目标stock.picking对象 - # dest_picking = dest_move.picking_id if dest_move else False - # # 现在,dest_picking就是current_picking的下一步 + 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: + record.current_location_id = lot_dest_map[move_line.lot_id.id] + break + else: + record.current_location_id = False # 是一张单据一张单据往下走的,所以这里的目标货位是上一张单据的当前货位,且这样去计算是可以的。 @api.depends('location_dest_id')