From 92f591c3e7a44f004bca4642b388beefab8ec95d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Wed, 18 Jun 2025 09:25:44 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=86sf=5Fmanufacturing=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E4=B8=ADstock.py=E7=9A=84=5Frun=5Fmanufacture=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E8=BF=9B=E8=A1=8C=E6=8B=86=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_production.py | 72 +++- sf_manufacturing/models/stock.py | 429 +++++++++++----------- sf_mrs_connect/models/__init__.py | 3 +- sf_mrs_connect/models/mrp_production.py | 44 +++ sf_plan/models/__init__.py | 1 + sf_plan/models/mrp_production.py | 41 +++ 6 files changed, 368 insertions(+), 222 deletions(-) create mode 100644 sf_mrs_connect/models/mrp_production.py create mode 100644 sf_plan/models/mrp_production.py diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py index 46c0ae39..2d0545af 100644 --- a/sf_manufacturing/models/mrp_production.py +++ b/sf_manufacturing/models/mrp_production.py @@ -1709,7 +1709,77 @@ class MrpProduction(models.Model): vals['procurement_group_id'] = product_group_id[product_id.id] else: vals['procurement_group_id'] = is_custemer_group_id[key] - return super(MrpProduction, self).create(vals_list) + + productions = super(MrpProduction, self).create(vals_list) + + # 查询成品工序排序(自动化产线加工),供后续使用 + product_model_type_routing_sorts = self.env['sf.product.model.type.routing.sort'].search([], order='sequence asc') + # 查询成品工序排序(人工线下加工),供后续使用 + manual_product_model_type_routing_sorts = self.env['sf.manual.product.model.type.routing.sort'].search([], order='sequence asc') + # 查询坯料工序排序,供后续使用 + embryo_model_type_routing_sorts = self.env['sf.embryo.model.type.routing.sort'].search([], order='sequence asc') + + for production in productions: + # 生成序列号 + production.action_generate_serial() + # 创建工序模板 + technology_design_values = [] + i = 0 + if production.product_id.categ_id.type == '成品': + # 根据加工面板的面数及成品工序模板生成工序设计 + if production.production_type == '自动化产线加工': + product_routing_workcenter = product_model_type_routing_sorts.filtered( + lambda s: s.product_model_type_id.id == production.product_id.product_model_type_id.id + ) + else: + product_routing_workcenter = manual_product_model_type_routing_sorts.filtered( + lambda s: s.manual_product_model_type_id.id == production.product_id.product_model_type_id.id + ) + if production.production_type == '自动化产线加工': + for k in (production.product_id.model_processing_panel.split(',')): + for route in product_routing_workcenter: + i += 1 + technology_design_values.append( + self.env['sf.technology.design'].json_technology_design_str(k, route, i, False) + ) + elif production.production_type == '人工线下加工': + for route in product_routing_workcenter: + i += 1 + technology_design_values.append( + self.env['sf.technology.design'].json_technology_design_str('ZM', route, i, False) + ) + else: + for route in product_routing_workcenter: + i += 1 + technology_design_values.append( + self.env['sf.technology.design'].json_technology_design_str(False, route, i, False) + ) + elif production.product_id.categ_id.type == '坯料': + embryo_routing_workcenter = embryo_model_type_routing_sorts.filtered( + lambda s: s.embryo_model_type_id.id == production.product_id.embryo_model_type_id.id + ) + for route_embryo in embryo_routing_workcenter: + i += 1 + technology_design_values.append( + self.env['sf.technology.design'].json_technology_design_str(False, route_embryo, i, False) + ) + # 处理表面工艺 + for item in production.product_id.product_model_type_id.surface_technics_routing_tmpl_ids: + if item.route_workcenter_id.surface_technics_id.id: + for process_param in production.product_id.model_process_parameters_ids: + if item.route_workcenter_id.surface_technics_id == process_param.process_id: + technology_design_values.append( + self.env['sf.technology.design'].json_technology_design_str( + False, + item.route_workcenter_id, + i, + process_param + ) + ) + production.technology_design_ids = technology_design_values + # 设置制造订单状态为待工艺确认 + productions.write({'state': 'technology_to_confirmed'}) + return productions @api.depends('procurement_group_id.stock_move_ids.created_purchase_line_id.order_id', 'procurement_group_id.stock_move_ids.move_orig_ids.purchase_line_id.order_id') diff --git a/sf_manufacturing/models/stock.py b/sf_manufacturing/models/stock.py index 4134de94..7dbe1706 100644 --- a/sf_manufacturing/models/stock.py +++ b/sf_manufacturing/models/stock.py @@ -95,35 +95,36 @@ class StockRule(models.Model): precision_rounding=proc[ 0].product_uom.rounding) > 0) list2 = [] - for item in procurements: - num = int(item[0].product_qty) + for procurement, rule in procurements: + num = int(procurement.product_qty) - product = self.env['product.product'].search( - [("id", '=', item[0].product_id.id)]) - product_tmpl = self.env['product.template'].search( - ["&", ("id", '=', product.product_tmpl_id.id), ('single_manufacturing', "!=", False)]) - if product_tmpl: + warehouse_id = rule.warehouse_id + if not warehouse_id: + warehouse_id = rule.location_dest_id.warehouse_id + manu_rule = rule.route_id.rule_ids.filtered(lambda r: r.action == 'manufacture' and r.warehouse_id == warehouse_id) + + if procurement.product_id.product_tmpl_id.single_manufacturing and manu_rule: if num > 1: for no in range(1, num + 1): Procurement = namedtuple('Procurement', ['product_id', 'product_qty', 'product_uom', 'location_id', 'name', 'origin', 'company_id', 'values']) - s = Procurement(product_id=item[0].product_id, product_qty=1.0, product_uom=item[0].product_uom, - location_id=item[0].location_id, - name=item[0].name, - origin=item[0].origin, - company_id=item[0].company_id, - values=item[0].values, + s = Procurement(product_id=procurement.product_id, product_qty=1.0, product_uom=procurement.product_uom, + location_id=procurement.location_id, + name=procurement.name, + origin=procurement.origin, + company_id=procurement.company_id, + values=procurement.values, ) - item1 = list(item) - item1[0] = s + # item1 = list(item) + # item1[0] = s - list2.append(tuple(item1)) + list2.append((s, rule)) else: - list2.append(item) + list2.append((procurement, rule)) else: - list2.append(item) + list2.append((procurement, rule)) for procurement, rule in list2: procure_method = rule.procure_method @@ -162,215 +163,203 @@ class StockRule(models.Model): [('res_id', '=', res_id), ('res_field', '=', res_field)], limit=1) attachment_info.write({'name': name}) - @api.model - def _run_manufacture(self, procurements): - productions_values_by_company = defaultdict(list) - errors = [] - for procurement, rule in procurements: - if float_compare(procurement.product_qty, 0, precision_rounding=procurement.product_uom.rounding) <= 0: - # If procurement contains negative quantity, don't create a MO that would be for a negative value. - continue - bom = rule._get_matching_bom(procurement.product_id, procurement.company_id, procurement.values) + # @api.model + # def _run_manufacture(self, procurements): + # productions_values_by_company = defaultdict(list) + # errors = [] + # for procurement, rule in procurements: + # if float_compare(procurement.product_qty, 0, precision_rounding=procurement.product_uom.rounding) <= 0: + # # If procurement contains negative quantity, don't create a MO that would be for a negative value. + # continue + # bom = rule._get_matching_bom(procurement.product_id, procurement.company_id, procurement.values) - productions_values_by_company[procurement.company_id.id].append(rule._prepare_mo_vals(*procurement, bom)) + # productions_values_by_company[procurement.company_id.id].append(rule._prepare_mo_vals(*procurement, bom)) - if errors: - raise ProcurementException(errors) + # if errors: + # raise ProcurementException(errors) - for company_id, productions_values in productions_values_by_company.items(): - # create the MO as SUPERUSER because the current user may not have the rights to do it - # (mto product launched by a sale for example) - '''创建制造订单''' - productions = self.env['mrp.production'].with_user(SUPERUSER_ID).sudo().with_company(company_id).create( - productions_values) - # 将这一批制造订单的采购组根据成品设置为不同的采购组 - # product_group_id = {} - # for index, production in enumerate(productions): - # if production.product_id.id not in product_group_id.keys(): - # product_group_id[production.product_id.id] = production.procurement_group_id.id - # else: - # productions_values[index].update({'name': production.name}) - # procurement_group_vals = production._prepare_procurement_group_vals(productions_values[index]) - # production.procurement_group_id = self.env["procurement.group"].create(procurement_group_vals).id + # for company_id, productions_values in productions_values_by_company.items(): + # # create the MO as SUPERUSER because the current user may not have the rights to do it + # # (mto product launched by a sale for example) + # '''创建制造订单''' + # productions = self.env['mrp.production'].with_user(SUPERUSER_ID).sudo().with_company(company_id).create( + # productions_values) - # self.env['stock.move'].sudo().create(productions._get_moves_raw_values()) - # self.env['stock.move'].sudo().create(productions._get_moves_finished_values()) + # ''' + # 创建工单 + # ''' + # # productions._create_workorder() + # # + # # self.env['stock.move'].sudo().create(productions._get_moves_finished_values()) + # productions.filtered(lambda p: (not p.orderpoint_id and p.move_raw_ids) or \ + # ( + # p.move_dest_ids.procure_method != 'make_to_order' and not + # p.move_raw_ids and not p.workorder_ids)).action_confirm() + # # 处理 根据制造订单生成的采购单坯料入库时到原材料库,手动将原材料位置该为坯料存货区 + # for production in productions: + # if production.picking_ids: + # product_type_id = production.picking_ids[0].move_ids[0].product_id.categ_id + # if product_type_id.name == '坯料': + # location_id = self.env['stock.location'].search([('name', '=', '坯料存货区')]) + # if not location_id: + # logging.info(f'没有搜索到【坯料存货区】: {location_id}') + # break + # for picking_id in production.picking_ids: + # if picking_id.picking_type_id.name == '内部调拨': + # if picking_id.location_dest_id.product_type != product_type_id: + # picking_id.location_dest_id = location_id.id + # elif picking_id.picking_type_id.name == '生产发料': + # if picking_id.location_id.product_type != product_type_id: + # picking_id.location_id = location_id.id - ''' - 创建工单 - ''' - # productions._create_workorder() - # - # self.env['stock.move'].sudo().create(productions._get_moves_finished_values()) - productions.filtered(lambda p: (not p.orderpoint_id and p.move_raw_ids) or \ - ( - p.move_dest_ids.procure_method != 'make_to_order' and not - p.move_raw_ids and not p.workorder_ids)).action_confirm() - # 处理 根据制造订单生成的采购单坯料入库时到原材料库,手动将原材料位置该为坯料存货区 - for production in productions: - if production.picking_ids: - product_type_id = production.picking_ids[0].move_ids[0].product_id.categ_id - if product_type_id.name == '坯料': - location_id = self.env['stock.location'].search([('name', '=', '坯料存货区')]) - if not location_id: - logging.info(f'没有搜索到【坯料存货区】: {location_id}') - break - for picking_id in production.picking_ids: - if picking_id.picking_type_id.name == '内部调拨': - if picking_id.location_dest_id.product_type != product_type_id: - picking_id.location_dest_id = location_id.id - elif picking_id.picking_type_id.name == '生产发料': - if picking_id.location_id.product_type != product_type_id: - picking_id.location_id = location_id.id + # for production in productions: + # ''' + # 创建制造订单时生成序列号 + # ''' + # # production.action_generate_serial() + # origin_production = production.move_dest_ids and production.move_dest_ids[ + # 0].raw_material_production_id or False + # orderpoint = production.orderpoint_id + # if orderpoint and orderpoint.create_uid.id == SUPERUSER_ID and orderpoint.trigger == 'manual': + # production.message_post( + # body=_('This production order has been created from Replenishment Report.'), + # message_type='comment', + # subtype_xmlid='mail.mt_note') + # elif orderpoint: + # production.message_post_with_view( + # 'mail.message_origin_link', + # values={'self': production, 'origin': orderpoint}, + # subtype_id=self.env.ref('mail.mt_note').id) + # elif origin_production: + # production.message_post_with_view( + # 'mail.message_origin_link', + # values={'self': production, 'origin': origin_production}, + # subtype_id=self.env.ref('mail.mt_note').id) - for production in productions: - ''' - 创建制造订单时生成序列号 - ''' - production.action_generate_serial() - origin_production = production.move_dest_ids and production.move_dest_ids[ - 0].raw_material_production_id or False - orderpoint = production.orderpoint_id - if orderpoint and orderpoint.create_uid.id == SUPERUSER_ID and orderpoint.trigger == 'manual': - production.message_post( - body=_('This production order has been created from Replenishment Report.'), - message_type='comment', - subtype_xmlid='mail.mt_note') - elif orderpoint: - production.message_post_with_view( - 'mail.message_origin_link', - values={'self': production, 'origin': orderpoint}, - subtype_id=self.env.ref('mail.mt_note').id) - elif origin_production: - production.message_post_with_view( - 'mail.message_origin_link', - values={'self': production, 'origin': origin_production}, - subtype_id=self.env.ref('mail.mt_note').id) + # ''' + # 创建生产计划 + # ''' + # # 工单耗时 + # # workorder_duration = 0 + # # for workorder in production.workorder_ids: + # # workorder_duration += workorder.duration_expected - ''' - 创建生产计划 - ''' - # 工单耗时 - workorder_duration = 0 - for workorder in production.workorder_ids: - workorder_duration += workorder.duration_expected - - sale_order = self.env['sale.order'].sudo().search([('name', '=', production.origin)]) - # 如果订单为空,则获取来源制造订单的销售单 - if not sale_order: - mrp_production = self.env['mrp.production'].sudo().search([('name', '=', production.origin)], - limit=1) - if mrp_production: - sale_order = self.env['sale.order'].sudo().search([('name', '=', mrp_production.origin)]) - else: - mrp_production = production - # if sale_order: - # sale_order.write({'schedule_status': 'to schedule'}) - self.env['sf.production.plan'].sudo().with_company(company_id).create({ - 'name': production.name, - 'order_deadline': sale_order.deadline_of_delivery, - 'production_id': production.id, - 'date_planned_start': production.date_planned_start, - 'origin': mrp_production.origin, - 'product_qty': production.product_qty, - 'product_id': production.product_id.id, - 'state': 'draft', - }) - all_production = productions - grouped_product_ids = {k: list(g) for k, g in groupby(all_production, key=lambda x: x.product_id.id)} - # 初始化一个字典来存储每个product_id对应的生产订单名称列表 - product_id_to_production_names = {} - # 对于每个product_id,获取其所有生产订单的名称 - for product_id, all_production in grouped_product_ids.items(): - # 为同一个product_id创建一个生产订单名称列表 - product_id_to_production_names[product_id] = [production.name for production in all_production] - for production_item in productions: - technology_design_values = [] - production_programming = self.env['mrp.production'].search( - [('product_id.id', '=', production_item.product_id.id), - ('origin', '=', production_item.origin)], - limit=1, order='id asc') - if production_item.product_id.id in product_id_to_production_names: - # 同一个产品多个制造订单对应一个编程单和模型库 - # 只调用一次fetchCNC,并将所有生产订单的名称作为字符串传递 - if not production_item.programming_no and production_item.production_type in ['自动化产线加工', - '人工线下加工']: - if not production_programming.programming_no: - production_item.fetchCNC( - ', '.join(product_id_to_production_names[production_item.product_id.id])) - else: - production_item.write({'programming_no': production_programming.programming_no, - 'programming_state': '编程中'}) - i = 0 - if production_item.product_id.categ_id.type == '成品': - # 根据加工面板的面数及成品工序模板生成工序设计 - if production_item.production_type == '自动化产线加工': - model = 'sf.product.model.type.routing.sort' - domain = [ - ('product_model_type_id', '=', production_item.product_id.product_model_type_id.id)] - else: - model = 'sf.manual.product.model.type.routing.sort' - domain = [('manual_product_model_type_id', '=', - production_item.product_id.product_model_type_id.id)] - product_routing_workcenter = self.env[model].search(domain, order='sequence asc') - if production_item.production_type == '自动化产线加工': - for k in (production_item.product_id.model_processing_panel.split(',')): - for route in product_routing_workcenter: - i += 1 - technology_design_values.append( - self.env['sf.technology.design'].json_technology_design_str(k, route, i, False)) - elif production_item.production_type == '人工线下加工': - for route in product_routing_workcenter: - i += 1 - technology_design_values.append( - self.env['sf.technology.design'].json_technology_design_str('ZM', route, i, False)) - else: - for route in product_routing_workcenter: - i += 1 - technology_design_values.append( - self.env['sf.technology.design'].json_technology_design_str(False, route, i, False)) - elif production_item.product_id.categ_id.type == '坯料': - embryo_routing_workcenter = self.env['sf.embryo.model.type.routing.sort'].search( - [('embryo_model_type_id', '=', production_item.product_id.embryo_model_type_id.id)], - order='sequence asc' - ) - for route_embryo in embryo_routing_workcenter: - i += 1 - technology_design_values.append( - self.env['sf.technology.design'].json_technology_design_str(False, route_embryo, i, - False)) - surface_technics_arr = [] - route_workcenter_arr = [] - for item in production_item.product_id.product_model_type_id.surface_technics_routing_tmpl_ids: - if item.route_workcenter_id.surface_technics_id.id: - for process_param in production_item.product_id.model_process_parameters_ids: - if item.route_workcenter_id.surface_technics_id == process_param.process_id: - surface_technics_arr.append( - item.route_workcenter_id.surface_technics_id.id) - route_workcenter_arr.append(item.route_workcenter_id.id) - if surface_technics_arr: - production_process = self.env['sf.production.process'].search( - [('id', 'in', surface_technics_arr)], - order='sequence asc' - ) - for p in production_process: - logging.info('production_process:%s' % p.name) - process_parameters = production_item.product_id.model_process_parameters_ids.filtered( - lambda pm: pm.process_id.id == p.id) - for process_parameter in process_parameters: - i += 1 - route_production_process = self.env[ - 'mrp.routing.workcenter'].search( - [('surface_technics_id', '=', p.id), - ('id', 'in', route_workcenter_arr)]) - technology_design_values.append( - self.env['sf.technology.design'].json_technology_design_str(False, - route_production_process, - i, - process_parameter)) - production_item.technology_design_ids = technology_design_values - productions.write({'state': 'technology_to_confirmed'}) - return True + # # sale_order = self.env['sale.order'].sudo().search([('name', '=', production.origin)]) + # # # 如果订单为空,则获取来源制造订单的销售单 + # # if not sale_order: + # # mrp_production = self.env['mrp.production'].sudo().search([('name', '=', production.origin)], + # # limit=1) + # # if mrp_production: + # # sale_order = self.env['sale.order'].sudo().search([('name', '=', mrp_production.origin)]) + # # else: + # # mrp_production = production + # # # if sale_order: + # # # sale_order.write({'schedule_status': 'to schedule'}) + # # self.env['sf.production.plan'].sudo().with_company(company_id).create({ + # # 'name': production.name, + # # 'order_deadline': sale_order.deadline_of_delivery, + # # 'production_id': production.id, + # # 'date_planned_start': production.date_planned_start, + # # 'origin': mrp_production.origin, + # # 'product_qty': production.product_qty, + # # 'product_id': production.product_id.id, + # # 'state': 'draft', + # # }) + # all_production = productions + # grouped_product_ids = {k: list(g) for k, g in groupby(all_production, key=lambda x: x.product_id.id)} + # # 初始化一个字典来存储每个product_id对应的生产订单名称列表 + # product_id_to_production_names = {} + # # 对于每个product_id,获取其所有生产订单的名称 + # for product_id, all_production in grouped_product_ids.items(): + # # 为同一个product_id创建一个生产订单名称列表 + # product_id_to_production_names[product_id] = [production.name for production in all_production] + # for production_item in productions: + # technology_design_values = [] + # # production_programming = self.env['mrp.production'].search( + # # [('product_id.id', '=', production_item.product_id.id), + # # ('origin', '=', production_item.origin)], + # # limit=1, order='id asc') + # # if production_item.product_id.id in product_id_to_production_names: + # # # 同一个产品多个制造订单对应一个编程单和模型库 + # # # 只调用一次fetchCNC,并将所有生产订单的名称作为字符串传递 + # # if not production_item.programming_no and production_item.production_type in ['自动化产线加工', + # # '人工线下加工']: + # # if not production_programming.programming_no: + # # production_item.fetchCNC( + # # ', '.join(product_id_to_production_names[production_item.product_id.id])) + # # else: + # # production_item.write({'programming_no': production_programming.programming_no, + # # 'programming_state': '编程中'}) + # i = 0 + # if production_item.product_id.categ_id.type == '成品': + # # 根据加工面板的面数及成品工序模板生成工序设计 + # if production_item.production_type == '自动化产线加工': + # model = 'sf.product.model.type.routing.sort' + # domain = [ + # ('product_model_type_id', '=', production_item.product_id.product_model_type_id.id)] + # else: + # model = 'sf.manual.product.model.type.routing.sort' + # domain = [('manual_product_model_type_id', '=', + # production_item.product_id.product_model_type_id.id)] + # product_routing_workcenter = self.env[model].search(domain, order='sequence asc') + # if production_item.production_type == '自动化产线加工': + # for k in (production_item.product_id.model_processing_panel.split(',')): + # for route in product_routing_workcenter: + # i += 1 + # technology_design_values.append( + # self.env['sf.technology.design'].json_technology_design_str(k, route, i, False)) + # elif production_item.production_type == '人工线下加工': + # for route in product_routing_workcenter: + # i += 1 + # technology_design_values.append( + # self.env['sf.technology.design'].json_technology_design_str('ZM', route, i, False)) + # else: + # for route in product_routing_workcenter: + # i += 1 + # technology_design_values.append( + # self.env['sf.technology.design'].json_technology_design_str(False, route, i, False)) + # elif production_item.product_id.categ_id.type == '坯料': + # embryo_routing_workcenter = self.env['sf.embryo.model.type.routing.sort'].search( + # [('embryo_model_type_id', '=', production_item.product_id.embryo_model_type_id.id)], + # order='sequence asc' + # ) + # for route_embryo in embryo_routing_workcenter: + # i += 1 + # technology_design_values.append( + # self.env['sf.technology.design'].json_technology_design_str(False, route_embryo, i, + # False)) + # surface_technics_arr = [] + # route_workcenter_arr = [] + # for item in production_item.product_id.product_model_type_id.surface_technics_routing_tmpl_ids: + # if item.route_workcenter_id.surface_technics_id.id: + # for process_param in production_item.product_id.model_process_parameters_ids: + # if item.route_workcenter_id.surface_technics_id == process_param.process_id: + # surface_technics_arr.append( + # item.route_workcenter_id.surface_technics_id.id) + # route_workcenter_arr.append(item.route_workcenter_id.id) + # if surface_technics_arr: + # production_process = self.env['sf.production.process'].search( + # [('id', 'in', surface_technics_arr)], + # order='sequence asc' + # ) + # for p in production_process: + # logging.info('production_process:%s' % p.name) + # process_parameters = production_item.product_id.model_process_parameters_ids.filtered( + # lambda pm: pm.process_id.id == p.id) + # for process_parameter in process_parameters: + # i += 1 + # route_production_process = self.env[ + # 'mrp.routing.workcenter'].search( + # [('surface_technics_id', '=', p.id), + # ('id', 'in', route_workcenter_arr)]) + # technology_design_values.append( + # self.env['sf.technology.design'].json_technology_design_str(False, + # route_production_process, + # i, + # process_parameter)) + # production_item.technology_design_ids = technology_design_values + # productions.write({'state': 'technology_to_confirmed'}) + # return True class ProductionLot(models.Model): diff --git a/sf_mrs_connect/models/__init__.py b/sf_mrs_connect/models/__init__.py index f01fb4fe..6450f26f 100644 --- a/sf_mrs_connect/models/__init__.py +++ b/sf_mrs_connect/models/__init__.py @@ -1,4 +1,5 @@ from . import ftp_operate from . import res_config_setting from . import sync_common -from . import order_price \ No newline at end of file +from . import order_price +from . import mrp_production diff --git a/sf_mrs_connect/models/mrp_production.py b/sf_mrs_connect/models/mrp_production.py new file mode 100644 index 00000000..ac3f6640 --- /dev/null +++ b/sf_mrs_connect/models/mrp_production.py @@ -0,0 +1,44 @@ +from itertools import groupby +from odoo import models, api +from odoo.tools.misc import OrderedSet + + +class MrpProduction(models.Model): + _inherit = 'mrp.production' + + + @api.model_create_multi + def create(self, vals_list): + """ + 生成编程单 + """ + productions = super().create(vals_list) + # 定义变量存储编程单 + grouped_product_programming_no = {} + # 定义产品拼接成的制造订单名称 + grouped_product_production_name = {} + # 查出所有的制造订单,为了适配通过补货生成的制造订单 + all_productions = self.env['mrp.production'].search([('origin', '=', productions[0].origin)]) + # 将不同产品的制造订单进行分组 + grouped_product_productions = {k: list(g) for k, g in groupby(all_productions, key=lambda x: x.product_id.id)} + + for product_id, grouped_productions in grouped_product_productions.items(): + # 产品对应的编程单号 + if product_id not in grouped_product_programming_no: + # 使用列表推导式获取非空的programming_no + programming_nos = [p.programming_no for p in grouped_productions if p.programming_no if p.programming_no is not False] + if programming_nos: + grouped_product_programming_no[product_id] = programming_nos[0] + grouped_product_production_name[product_id] = ','.join(list(map(lambda p:p.name, grouped_productions))) + # 同一个产品的制造订单只请求一次CNC编程 + for production in productions: + if not production.programming_no and production.production_type in ['自动化产线加工','人工线下加工']: + if production.product_id.id not in grouped_product_programming_no: + production.fetchCNC(grouped_product_production_name[production.product_id.id]) + grouped_product_programming_no[production.product_id.id] = production.programming_no + else: + production.write({ + 'programming_no': grouped_product_programming_no[production.product_id.id], + 'programming_state': '编程中' + }) + return productions \ No newline at end of file diff --git a/sf_plan/models/__init__.py b/sf_plan/models/__init__.py index 57dea5da..0eba6ec9 100644 --- a/sf_plan/models/__init__.py +++ b/sf_plan/models/__init__.py @@ -3,3 +3,4 @@ from . import custom_plan from . import change_manufactuing +from . import mrp_production diff --git a/sf_plan/models/mrp_production.py b/sf_plan/models/mrp_production.py new file mode 100644 index 00000000..961d5f35 --- /dev/null +++ b/sf_plan/models/mrp_production.py @@ -0,0 +1,41 @@ +from odoo import models, api + + +class MrpProduction(models.Model): + _inherit = 'mrp.production' + + @api.model_create_multi + def create(self, vals_list): + """ + 创建生产计划 + """ + productions = super().create(vals_list) + + for production in productions: + # 工单耗时 + workorder_duration = 0 + for workorder in production.workorder_ids: + workorder_duration += workorder.duration_expected + + sale_order = self.env['sale.order'].sudo().search([('name', '=', production.origin)]) + # 如果订单为空,则获取来源制造订单的销售单 + if not sale_order: + mrp_production = self.env['mrp.production'].sudo().search([('name', '=', production.origin)], + limit=1) + if mrp_production: + sale_order = self.env['sale.order'].sudo().search([('name', '=', mrp_production.origin)]) + else: + mrp_production = production + # if sale_order: + # sale_order.write({'schedule_status': 'to schedule'}) + self.env['sf.production.plan'].sudo().with_company(production.company_id).create({ + 'name': production.name, + 'order_deadline': sale_order.deadline_of_delivery, + 'production_id': production.id, + 'date_planned_start': production.date_planned_start, + 'origin': mrp_production.origin, + 'product_qty': production.product_qty, + 'product_id': production.product_id.id, + 'state': 'draft', + }) + return productions \ No newline at end of file