diff --git a/sf_demand_plan/models/sf_demand_plan.py b/sf_demand_plan/models/sf_demand_plan.py index b5a2eda0..99b85447 100644 --- a/sf_demand_plan/models/sf_demand_plan.py +++ b/sf_demand_plan/models/sf_demand_plan.py @@ -85,6 +85,8 @@ class SfDemandPlan(models.Model): default=False ) + procurement_group_id = fields.Many2one('procurement.group', '补货组', copy=False) + @api.depends('product_id.part_number', 'product_id.model_name') def _compute_part_number(self): for line in self: diff --git a/sf_demand_plan/models/sf_production_demand_plan.py b/sf_demand_plan/models/sf_production_demand_plan.py index 97e8b99a..c53bf552 100644 --- a/sf_demand_plan/models/sf_production_demand_plan.py +++ b/sf_demand_plan/models/sf_production_demand_plan.py @@ -13,6 +13,10 @@ class SfProductionDemandPlan(models.Model): _name = 'sf.production.demand.plan' _description = 'sf_production_demand_plan' + def get_location_id(self): + stock_location = self.env['stock.location'].sudo().search([('name', '=', '客户')], limit=1) + return stock_location.id + def _get_machining_precision(self): machinings = self.env['sf.machining.accuracy'].sudo().search([]) list = [(m.sync_id, m.name) for m in machinings] @@ -31,7 +35,7 @@ class SfProductionDemandPlan(models.Model): ('50', '待下达生产'), ('60', '已下达'), ('100', '取消'), - ], string='状态', default='30') + ], string='状态', default='30', readonly=True) demand_plan_id = fields.Many2one(comodel_name="sf.demand.plan", string="物料需求", readonly=True) sale_order_id = fields.Many2one(comodel_name="sale.order", @@ -59,7 +63,7 @@ class SfProductionDemandPlan(models.Model): ('manual', "人工线下加工"), ('purchase', "外购"), ('outsourcing', "委外加工"), - ], string='供货方式') + ], string='供货方式', default='manual') product_uom_qty = fields.Float( string="需求数量", related='sale_order_line_id.product_uom_qty', store=True) @@ -145,7 +149,8 @@ class SfProductionDemandPlan(models.Model): blank_arrival_date = fields.Date('采购计划到货(坯料)') finished_product_arrival_date = fields.Date('采购计划到货(成品)') - bom_id = fields.Many2one('mrp.bom', readonly=True, string="BOM") + bom_id = fields.Many2one('mrp.bom', string="BOM", readonly=True) + location_id = fields.Many2one('stock.location', string='需求位置', default=get_location_id, readonly=True) @api.depends('supply_method') def _compute_route_ids(self): @@ -552,6 +557,11 @@ class SfProductionDemandPlan(models.Model): 'default_release_message': f"您正在下达计划量 {self.plan_uom_qty},需求数量为 {self.product_uom_qty},已超过需求数量,是否继续?", }} self.mrp_bom_create() + self._action_launch_stock_rule() + if self.supply_method in ('automation', 'manual'): + self.write({'status': '50'}) + else: + self.write({'status': '60'}) def mrp_bom_create(self): self.ensure_one() @@ -689,3 +699,66 @@ class SfProductionDemandPlan(models.Model): product_bom_purchase.with_user(self.env.ref("base.user_admin")).bom_create_line_has( purchase_embryo) self.bom_id = product_bom_purchase.id + + def _action_launch_stock_rule(self): + procurements = [] + group_id = self.demand_plan_id.procurement_group_id + if not group_id: + group_id = self.env['procurement.group'].create(self._prepare_procurement_group_vals()) + self.demand_plan_id.procurement_group_id = group_id + else: + updated_vals = {} + if group_id.partner_id != self.sale_order_id.partner_shipping_id: + updated_vals.update({'partner_id': self.sale_order_id.partner_shipping_id.id}) + if group_id.move_type != self.sale_order_id.picking_policy: + updated_vals.update({'move_type': self.sale_order_id.picking_policy}) + if updated_vals: + group_id.write(updated_vals) + values = self._prepare_procurement_values(group_id=group_id) + line_uom = self.sale_order_line_id.product_uom + quant_uom = self.product_id.uom_id + plan_uom_qty, procurement_uom = line_uom._adjust_uom_quantities(self.plan_uom_qty, quant_uom) + procurements.append(self.env['procurement.group'].Procurement( + self.product_id, plan_uom_qty, procurement_uom, + self.sale_order_id.partner_shipping_id.property_stock_customer, + self.product_id.display_name, self.sale_order_id.name, self.sale_order_id.company_id, values)) + if procurements: + procurement_group = self.env['procurement.group'] + if self.env.context.get('import_file'): + procurement_group = procurement_group.with_context(import_file=False) + procurement_group.run(procurements) + orders = self.mapped('sale_order_id') + for order in orders: + pickings_to_confirm = order.picking_ids.filtered(lambda p: p.state not in ['cancel', 'done']) + if pickings_to_confirm: + pickings_to_confirm.action_confirm() + return True + + def _prepare_procurement_group_vals(self): + return { + 'name': self.sale_order_id.name, + 'move_type': self.sale_order_id.picking_policy, + 'sale_id': self.sale_order_id.id, + 'partner_id': self.sale_order_id.partner_shipping_id.id, + } + + def _prepare_procurement_values(self, group_id=False): + self.ensure_one() + date_deadline = self.sale_order_id.commitment_date or ( + self.sale_order_id.date_order + timedelta(days=self.sale_order_line_id.customer_lead or 0.0)) + date_planned = date_deadline - timedelta(days=self.sale_order_id.company_id.security_lead) + values = { + 'group_id': group_id, + 'sale_line_id': self.sale_order_line_id.id, + 'date_planned': date_planned, + 'date_deadline': date_deadline, + 'route_ids': self.route_ids, + 'warehouse_id': self.sale_order_id.warehouse_id or False, + 'partner_id': self.sale_order_id.partner_shipping_id.id, + 'product_description_variants': self.sale_order_line_id.with_context( + lang=self.sale_order_id.partner_id.lang)._get_sale_order_line_multiline_description_variants(), + 'company_id': self.sale_order_id.company_id, + 'product_packaging_id': self.sale_order_line_id.product_packaging_id, + 'sequence': self.sale_order_line_id.sequence, + } + return values diff --git a/sf_demand_plan/views/demand_plan.xml b/sf_demand_plan/views/demand_plan.xml index 5f623267..062fe9ea 100644 --- a/sf_demand_plan/views/demand_plan.xml +++ b/sf_demand_plan/views/demand_plan.xml @@ -71,7 +71,7 @@