From 4bea16932725a05fef06c796fcc99dd32275f464 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Thu, 26 Jun 2025 10:26:39 +0800 Subject: [PATCH] =?UTF-8?q?=E6=92=A4=E5=9B=9E=5Frun=5Fmanufacturing?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_production.py | 152 +++++---- sf_manufacturing/models/stock.py | 380 +++++++++++----------- sf_mrs_connect/models/__init__.py | 1 - sf_mrs_connect/models/mrp_production.py | 138 -------- sf_plan/models/__init__.py | 1 - sf_plan/models/mrp_production.py | 41 --- 6 files changed, 271 insertions(+), 442 deletions(-) delete mode 100644 sf_mrs_connect/models/mrp_production.py delete 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 65b51fee..cf196ad6 100644 --- a/sf_manufacturing/models/mrp_production.py +++ b/sf_manufacturing/models/mrp_production.py @@ -740,6 +740,86 @@ class MrpProduction(models.Model): logging.info('change_programming_state error:%s' % e) raise UserError("修改编程单状态失败,请联系管理员") + # cnc程序获取 + def fetchCNC(self, production_names): + cnc = self.env['mrp.production'].search([('id', '=', self.id)]) + quick_order = False + if cnc.product_id.default_code: + quick_order = self.env['quick.easy.order'].search( + [('name', '=', cnc.product_id.default_code.rsplit('-', 1)[0])]) + programme_way = False + if cnc.manual_quotation is True: + programme_way = 'manual operation' + else: + programme_way = 'auto' + if cnc.production_type == '人工线下加工': + programme_way = 'manual operation' + if quick_order: + programme_way = 'manual operation' + try: + res = { + 'production_no': production_names, + 'machine_tool_code': '', + 'product_name': cnc.product_id.name, + 'remanufacture_type': '', + 'model_code': cnc.product_id.model_code, + 'material_code': self.env['sf.production.materials'].search( + [('id', '=', cnc.product_id.materials_id.id)]).materials_no, + 'material_type_code': self.env['sf.materials.model'].search( + [('id', '=', cnc.product_id.materials_type_id.id)]).materials_no, + 'machining_processing_panel': cnc.product_id.model_processing_panel, + 'machining_precision': '', + 'embryo_long': cnc.product_id.bom_ids[0].bom_line_ids.product_id.length, + 'embryo_height': cnc.product_id.bom_ids[0].bom_line_ids.product_id.height, + 'embryo_width': cnc.product_id.bom_ids[0].bom_line_ids.product_id.width, + 'order_no': cnc.origin, + 'model_order_no': cnc.product_id.default_code, + 'user': cnc.env.user.name, + 'programme_way': programme_way, + # 'model_file': '' if not cnc.product_id.model_file else base64.b64encode( + # cnc.product_id.model_file).decode('utf-8'), + # 'glb_url': cnc.product_id.glb_url, + 'part_name': cnc.product_id.part_name, + 'part_number': cnc.product_id.part_number, + 'machining_drawings': base64.b64encode(cnc.product_id.machining_drawings).decode( + 'utf-8') if cnc.product_id.machining_drawings else '', + 'machining_drawings_name': cnc.product_id.machining_drawings_name, + 'machining_drawings_mimetype': cnc.product_id.machining_drawings_mimetype, + # 'model_id': cnc.product_id.model_id, + } + # 打印出除了 model_file 之外的所有键值对 + for key, value in res.items(): + if key != 'model_file': + logging.info('%s: %s' % (key, value)) + configsettings = self.env['res.config.settings'].get_values() + config_header = Common.get_headers(self, configsettings['token'], configsettings['sf_secret_key']) + url = '/api/intelligent_programming/create' + config_url = configsettings['sf_url'] + url + res['token'] = configsettings['token'] + # res_str = json.dumps(res) + ret = requests.post(config_url, json={}, data=res, headers=config_header) + ret = ret.json() + logging.info('fetchCNC-ret:%s' % ret) + if ret['status'] == 1: + self.write( + {'programming_no': ret['programming_no'], 'programming_state': '编程中', 'work_state': '编程中'}) + # 生成编程记录 + self.programming_record_ids.create({ + 'number': len(self.programming_record_ids) + 1, + 'production_id': self.id, + 'reason': '首次下发', + 'programming_method': False, + 'current_programming_count': False, + 'target_production_id': False, + 'apply_time': fields.Datetime.now(), + 'send_time': False, + }) + else: + raise UserError(ret['message']) + except Exception as e: + logging.info('fetchCNC error:%s' % e) + raise UserError("cnc程序获取编程单失败,请联系管理员") + # 维修模块按钮 def button_maintenance_req(self): self.ensure_one() @@ -1630,77 +1710,7 @@ class MrpProduction(models.Model): else: vals['procurement_group_id'] = is_custemer_group_id[key] - 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 == '自动化产线加工': - if production.product_id.model_processing_panel: - 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 + return super(MrpProduction, self).create(vals_list) @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 4e8dc438..f6787b10 100644 --- a/sf_manufacturing/models/stock.py +++ b/sf_manufacturing/models/stock.py @@ -163,203 +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) + 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) - # ''' - # 创建工单 - # ''' - # # 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 6450f26f..01498b21 100644 --- a/sf_mrs_connect/models/__init__.py +++ b/sf_mrs_connect/models/__init__.py @@ -2,4 +2,3 @@ from . import ftp_operate from . import res_config_setting from . import sync_common 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 deleted file mode 100644 index 50f9d2a0..00000000 --- a/sf_mrs_connect/models/mrp_production.py +++ /dev/null @@ -1,138 +0,0 @@ -import base64 -import requests -import logging - -from itertools import groupby -from odoo import models, api, fields -from odoo.exceptions import UserError -from odoo.addons.sf_base.commons.common import Common - - -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 = {} - - if productions and productions[0].origin: - # 查出所有的制造订单,为了适配通过补货生成的制造订单 - 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 production.subcontractor_id: - continue - # 没有模型ID的制造订单不请求编程 - if not production.model_id: - continue - 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 - - # cnc程序获取 - def fetchCNC(self, production_names): - cnc = self.env['mrp.production'].search([('id', '=', self.id)]) - quick_order = False - if cnc.product_id.default_code: - quick_order = self.env['quick.easy.order'].search( - [('name', '=', cnc.product_id.default_code.rsplit('-', 1)[0])]) - programme_way = False - if cnc.manual_quotation is True: - programme_way = 'manual operation' - else: - programme_way = 'auto' - if cnc.production_type == '人工线下加工': - programme_way = 'manual operation' - if quick_order: - programme_way = 'manual operation' - try: - res = { - 'production_no': production_names, - 'machine_tool_code': '', - 'product_name': cnc.product_id.name, - 'remanufacture_type': '', - 'model_code': cnc.product_id.model_code, - 'material_code': self.env['sf.production.materials'].search( - [('id', '=', cnc.product_id.materials_id.id)]).materials_no, - 'material_type_code': self.env['sf.materials.model'].search( - [('id', '=', cnc.product_id.materials_type_id.id)]).materials_no, - 'machining_processing_panel': cnc.product_id.model_processing_panel, - 'machining_precision': '', - 'embryo_long': cnc.product_id.bom_ids[0].bom_line_ids.product_id.length, - 'embryo_height': cnc.product_id.bom_ids[0].bom_line_ids.product_id.height, - 'embryo_width': cnc.product_id.bom_ids[0].bom_line_ids.product_id.width, - 'order_no': cnc.origin, - 'model_order_no': cnc.product_id.default_code, - 'user': cnc.env.user.name, - 'programme_way': programme_way, - # 'model_file': '' if not cnc.product_id.model_file else base64.b64encode( - # cnc.product_id.model_file).decode('utf-8'), - # 'glb_url': cnc.product_id.glb_url, - 'part_name': cnc.product_id.part_name, - 'part_number': cnc.product_id.part_number, - 'machining_drawings': base64.b64encode(cnc.product_id.machining_drawings).decode( - 'utf-8') if cnc.product_id.machining_drawings else '', - 'machining_drawings_name': cnc.product_id.machining_drawings_name, - 'machining_drawings_mimetype': cnc.product_id.machining_drawings_mimetype, - # 'model_id': cnc.product_id.model_id, - } - # 打印出除了 model_file 之外的所有键值对 - for key, value in res.items(): - if key != 'model_file': - logging.info('%s: %s' % (key, value)) - configsettings = self.env['res.config.settings'].get_values() - config_header = Common.get_headers(self, configsettings['token'], configsettings['sf_secret_key']) - url = '/api/intelligent_programming/create' - config_url = configsettings['sf_url'] + url - res['token'] = configsettings['token'] - # res_str = json.dumps(res) - ret = requests.post(config_url, json={}, data=res, headers=config_header) - ret = ret.json() - logging.info('fetchCNC-ret:%s' % ret) - if ret['status'] == 1: - self.write( - {'programming_no': ret['programming_no'], 'programming_state': '编程中', 'work_state': '编程中'}) - # 生成编程记录 - self.programming_record_ids.create({ - 'number': len(self.programming_record_ids) + 1, - 'production_id': self.id, - 'reason': '首次下发', - 'programming_method': False, - 'current_programming_count': False, - 'target_production_id': False, - 'apply_time': fields.Datetime.now(), - 'send_time': False, - }) - else: - raise UserError(ret['message']) - except Exception as e: - logging.info('fetchCNC error:%s' % e) - raise UserError("cnc程序获取编程单失败,请联系管理员") \ No newline at end of file diff --git a/sf_plan/models/__init__.py b/sf_plan/models/__init__.py index 0eba6ec9..57dea5da 100644 --- a/sf_plan/models/__init__.py +++ b/sf_plan/models/__init__.py @@ -3,4 +3,3 @@ 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 deleted file mode 100644 index 961d5f35..00000000 --- a/sf_plan/models/mrp_production.py +++ /dev/null @@ -1,41 +0,0 @@ -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