From 443a21a0cc000341a17192007880948a4bb915b4 Mon Sep 17 00:00:00 2001 From: liaodanlong Date: Fri, 25 Apr 2025 11:46:05 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=B7=A5=E5=BA=8F=E5=A4=96=E5=8D=8F?= =?UTF-8?q?=E9=9C=80=E6=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...rchase_request_line_make_purchase_order.py | 3 + sf_manufacturing/models/mrp_production.py | 3 +- sf_manufacturing/models/mrp_workorder.py | 11 +- sf_manufacturing/models/purchase_order.py | 112 +++++++++++++----- sf_sale/models/sale_order.py | 1 + 5 files changed, 90 insertions(+), 40 deletions(-) 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 83bf1f39..16248b7b 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 @@ -32,6 +32,7 @@ class PurchaseRequestLineMakePurchaseOrder(models.TransientModel): line.company_id, line.request_id.origin, ) + # po_data.update({'related_product':line.related_product.id}) purchase = purchase_obj.create(po_data) # Look for any other PO line in the selected PO with same @@ -63,6 +64,8 @@ class PurchaseRequestLineMakePurchaseOrder(models.TransientModel): po_line_data = self._prepare_purchase_order_line(purchase, item) if item.keep_description: po_line_data["name"] = item.name + if line.related_product: + po_line_data.update({'related_product': line.related_product.id}) po_line = po_line_obj.create(po_line_data) po_line_product_uom_qty = po_line.product_uom._compute_quantity( po_line.product_uom_qty, alloc_uom diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py index e82b1b40..c051126c 100644 --- a/sf_manufacturing/models/mrp_production.py +++ b/sf_manufacturing/models/mrp_production.py @@ -934,6 +934,7 @@ class MrpProduction(models.Model): cur_request_line.pop('group_id', None) cur_request_line.pop('production_name', None) self.env["purchase.request.line"].create(cur_request_line) + pr.button_approved() # 外协出入库单处理 def get_subcontract_pick_purchase(self): @@ -961,7 +962,7 @@ class MrpProduction(models.Model): if not sorted_workorders: return for workorders in reversed(sorted_workorders): - self.env['stock.picking'].create_outcontract_picking(workorders, production, sorted_workorders) + # self.env['stock.picking'].create_outcontract_picking(workorders, production, sorted_workorders) # self.env['purchase.order'].get_purchase_order(workorders, production, product_id_to_production_names) purchase_request_line = purchase_request_line + self.env['purchase.order'].get_purchase_request( workorders, production) diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index a36e4b9d..036cfdae 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -1243,7 +1243,8 @@ class ResMrpWorkOrder(models.Model): return workorders_values_str def _process_compute_state(self): - for workorder in self: + sorted_workorders = sorted(self, key=lambda x: x.sequence) + for workorder in sorted_workorders: # 如果工单的工序没有进行排序则跳出循环 if workorder.production_id.workorder_ids.filtered(lambda wk: wk.sequence == 0): continue @@ -1302,13 +1303,6 @@ class ResMrpWorkOrder(models.Model): workorder.state = 'ready' elif workorder.state != 'waiting': workorder.state = 'waiting' - # =========== 特殊工艺工单处理 =================== - # if workorder.routing_type == '表面工艺' and workorder.is_subcontrac: - # purchase_order = self.env['purchase.order'].search( - # [('origin', 'ilike', workorder.production_id.name)]) - # if purchase_order.picking_ids.filtered(lambda p: p.state in ['waiting', 'confirmed', 'assigned']): - # workorder.state = 'waiting' - # continue if workorder.technology_design_id.routing_tag == 'special': if workorder.is_subcontract is False: workorder.state = 'ready' @@ -1330,6 +1324,7 @@ class ResMrpWorkOrder(models.Model): else: workorder.state = 'waiting' + @api.depends('production_availability', 'blocked_by_workorder_ids', 'blocked_by_workorder_ids.state', 'production_id.tool_state', 'production_id.schedule_state', 'sequence', 'production_id.programming_state') diff --git a/sf_manufacturing/models/purchase_order.py b/sf_manufacturing/models/purchase_order.py index a919b3be..833f9fb8 100644 --- a/sf_manufacturing/models/purchase_order.py +++ b/sf_manufacturing/models/purchase_order.py @@ -59,6 +59,86 @@ class PurchaseOrder(models.Model): production_id = self.env['mrp.production'].search([('origin', 'in', origins)]) purchase.production_count = len(production_id) + def process_replenish(self,production,total_qty): + record = self + bom_line_id = production.bom_id.bom_line_ids + replenish = self.env['stock.warehouse.orderpoint'].search([ + ('product_id', '=', bom_line_id.product_id.id), + ( + 'location_id', '=', self.env.ref('sf_stock.stock_location_outsourcing_material_receiving_area').id), + # ('state', 'in', ['draft', 'confirmed']) + ], limit=1) + if not replenish: + replenish_model = self.env['stock.warehouse.orderpoint'] + replenish = replenish_model.create({ + 'product_id': bom_line_id.product_id.id, + 'location_id': self.env.ref( + 'sf_stock.stock_location_outsourcing_material_receiving_area').id, + 'route_id': self.env.ref('sf_stock.stock_route_process_outsourcing').id, + 'group_id': record.group_id.id, + 'qty_to_order': total_qty, + 'origin': record.name, + }) + else: + replenish.write({ + 'product_id': bom_line_id.product_id.id, + 'location_id': self.env.ref( + 'sf_stock.stock_location_outsourcing_material_receiving_area').id, + 'route_id': self.env.ref('sf_stock.stock_route_process_outsourcing').id, + 'group_id': record.group_id.id, + 'qty_to_order': total_qty + replenish.qty_to_order, + 'origin': record.name + ',' + replenish.origin, + }) + replenish.action_replenish() + + def outsourcing_service_replenishment(self): + record = self + if record.purchase_type != 'consignment': + return + grouped_lines = {} + for line in record.order_line: + if line.related_product.id not in grouped_lines: + grouped_lines[line.related_product.id] = [] + grouped_lines[line.related_product.id].append(line) + for product_id,lines in grouped_lines.items(): + production = self.env['mrp.production'].search([('product_id', '=', product_id)], limit=1) + if not production: + continue + total_qty = sum(line.product_qty for line in lines) + record.process_replenish(production,total_qty) + for product_id,lines in grouped_lines.items(): + productions = self.env['mrp.production'].search([('product_id', '=', product_id)], limit=1) + if not productions: + continue + # production.bom_id.bom_line_ids.product_id + location_id = self.env['stock.location'].search([('name', '=', '制造前')]) + quants = self.env['stock.quant'].search([ + ('product_id', '=', product_id), + ('location_id', '=', location_id.id) + ]) + total_qty = sum(quants.mapped('quantity')) # 计算该位置的总库存量 + is_available = total_qty > 0 + if not is_available: + continue + for production_id in productions: + work_ids = production_id.workorder_ids.filtered( + lambda wk: wk.state not in ['done', 'rework', 'cancel']) + if not work_ids: + continue + min_sequence_wk = min(work_ids, key=lambda wk: wk.sequence) + if min_sequence_wk.is_subcontract: + picking_id = production_id.picking_ids.filtered( + lambda wk: wk.location_id.name == '制造前' and wk.location_dest_id.name == '外协加工区') + move_out = picking_id.move_id + for mo in move_out: + if mo.state != 'done': + mo.write({'state': 'assigned', 'production_id': False}) + if not mo.move_line_ids: + self.env['stock.move.line'].create( + mo.get_move_line(production_id, min_sequence_wk)) + # product = self.env['mrp.production'].search([('product_id', '=', product_id)], limit=1) + # match = re.search(r'(S\d{5}-\d)',product.name) + # pass def button_confirm(self): for record in self: for line in record.order_line: @@ -66,37 +146,7 @@ class PurchaseOrder(models.Model): raise UserError('请对【产品】中的【数量】进行输入') if line.price_unit <= 0: raise UserError('请对【产品】中的【单价】进行输入') - if record.purchase_type == 'consignment': - bom_line_id = record.order_line[0].purchase_request_lines.request_id.bom_id.bom_line_ids - replenish = self.env['stock.warehouse.orderpoint'].search([ - ('product_id', '=', bom_line_id.product_id.id), - ( - 'location_id', '=', self.env.ref('sf_stock.stock_location_outsourcing_material_receiving_area').id), - # ('state', 'in', ['draft', 'confirmed']) - ], limit=1) - if not replenish: - replenish_model = self.env['stock.warehouse.orderpoint'] - replenish = replenish_model.create({ - 'product_id': bom_line_id.product_id.id, - 'location_id': self.env.ref( - 'sf_stock.stock_location_outsourcing_material_receiving_area').id, - 'route_id': self.env.ref('sf_stock.stock_route_process_outsourcing').id, - 'group_id': record.group_id.id, - 'qty_to_order': 1, - 'origin': record.name, - }) - else: - replenish.write({ - 'product_id': bom_line_id.product_id.id, - 'location_id': self.env.ref( - 'sf_stock.stock_location_outsourcing_material_receiving_area').id, - 'route_id': self.env.ref('sf_stock.stock_route_process_outsourcing').id, - 'group_id': record.group_id.id, - 'qty_to_order': 1 + replenish.qty_to_order, - 'origin': record.name + ',' + replenish.origin, - }) - replenish.action_replenish() - + record.outsourcing_service_replenishment() return super(PurchaseOrder, self).button_confirm() diff --git a/sf_sale/models/sale_order.py b/sf_sale/models/sale_order.py index 279ac895..ccb25258 100644 --- a/sf_sale/models/sale_order.py +++ b/sf_sale/models/sale_order.py @@ -390,6 +390,7 @@ class RePurchaseOrder(models.Model): # route_ids result.append({ "product_id": server_template.product_variant_id.id, + 'related_product':production.product_id.id, "name": production.procurement_group_id.name, "date_required": fields.Datetime.now(), "product_uom_id":server_template.uom_id.id, From 10a1d43a17a380635b0087f13bbc2fe67705ca17 Mon Sep 17 00:00:00 2001 From: liaodanlong Date: Fri, 25 Apr 2025 14:39:58 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E6=8E=92=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_plan/models/custom_plan.py | 4 ++-- sf_plan/wizard/action_plan_some.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sf_plan/models/custom_plan.py b/sf_plan/models/custom_plan.py index 20ae4967..af5b387f 100644 --- a/sf_plan/models/custom_plan.py +++ b/sf_plan/models/custom_plan.py @@ -224,11 +224,11 @@ class sf_production_plan(models.Model): return num - def do_production_schedule(self,date_planned_start): + def do_production_schedule(self): """ 排程方法 """ - self.deal_processing_schedule(date_planned_start) + self.deal_processing_schedule(self.date_planned_start) for record in self: if not record.production_line_id: raise ValidationError("未选择生产线") diff --git a/sf_plan/wizard/action_plan_some.py b/sf_plan/wizard/action_plan_some.py index 1145af9f..78726c4d 100644 --- a/sf_plan/wizard/action_plan_some.py +++ b/sf_plan/wizard/action_plan_some.py @@ -40,5 +40,5 @@ class Action_Plan_All_Wizard(models.TransientModel): self.plan_ids.date_planned_start = self.date_planned_start # 在这里添加您的逻辑来处理这些ID # 判断能否排成 - self.plan_ids.do_production_schedule(self.date_planned_start) + self.plan_ids.do_production_schedule() _logger.info('处理计划: %s 完成', self.plan_ids.ids)