diff --git a/sf_manufacturing/__manifest__.py b/sf_manufacturing/__manifest__.py index 991b26ab..612577c2 100644 --- a/sf_manufacturing/__manifest__.py +++ b/sf_manufacturing/__manifest__.py @@ -24,6 +24,7 @@ 'wizard/production_wizard_views.xml', 'wizard/production_technology_wizard_views.xml', 'wizard/production_technology_re_adjust_wizard_views.xml', + 'wizard/mrp_workorder_batch_replan_wizard_views.xml', 'views/mrp_views_menus.xml', 'views/agv_scheduling_views.xml', 'views/stock_lot_views.xml', @@ -38,6 +39,7 @@ 'views/sf_maintenance_equipment.xml', 'views/res_config_settings_views.xml', 'views/sale_order_views.xml', + 'views/mrp_workorder_batch_replan.xml', ], 'assets': { diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py index f11a32ac..7bfc0abb 100644 --- a/sf_manufacturing/models/mrp_production.py +++ b/sf_manufacturing/models/mrp_production.py @@ -8,6 +8,7 @@ import re import requests from itertools import groupby from collections import defaultdict, namedtuple + from odoo import api, fields, models, SUPERUSER_ID, _ from odoo.exceptions import UserError, ValidationError from odoo.addons.sf_base.commons.common import Common @@ -18,6 +19,7 @@ class MrpProduction(models.Model): _inherit = 'mrp.production' _description = "制造订单" _order = 'create_date desc' + sale_order_id = fields.Many2one('sale.order', string='销售订单', compute='_compute_sale_order_id', store=True) deadline_of_delivery = fields.Date('订单交期', tracking=True, compute='_compute_deadline_of_delivery') # tray_ids = fields.One2many('sf.tray', 'production_id', string="托盘") maintenance_count = fields.Integer(compute='_compute_maintenance_count', string="Number of maintenance requests") @@ -34,6 +36,29 @@ class MrpProduction(models.Model): tool_state_remark = fields.Text(string='功能刀具状态备注(缺刀)', compute='_compute_tool_state_remark', store=True) tool_state_remark2 = fields.Text(string='功能刀具状态备注(无效刀)', readonly=True) + @api.depends('procurement_group_id.mrp_production_ids.move_dest_ids.group_id.sale_id') + def _compute_sale_order_id(self): + for production in self: + # 初始化 sale_order_id 为 False + sale_order_id = False + # 使用正则表达式查找产品名称中的 'S' 开头的字母数字字符串 + match = re.search(r'S\d+', production.product_id.with_context(lang='zh_CN').name) # 从字符串开始匹配 + + if match: + result = match.group(0) + try: + # 查找与匹配的字符串相符的销售订单 + sale_order = self.env['sale.order'].search( + [('name', '=', result)], limit=1, order='id asc' + ) + if sale_order: + production.sale_order_id = sale_order.id + else: + logging.warning("No sale order found for production {} with product {} (name match: {})".format( + production.id, production.product_id.name, result)) + except Exception as e: + logging.error("Error while fetching sale order for production {}: {}".format(production.id, str(e))) + @api.depends('procurement_group_id.mrp_production_ids.move_dest_ids.group_id.sale_id') def _compute_deadline_of_delivery(self): for production in self: @@ -378,16 +403,37 @@ class MrpProduction(models.Model): if process_parameters: raise UserError(_("【工艺设计】-【参数】为%s的在【产品】中不存在,请先创建", ", ".join(process_parameters))) if production_confirmed: - return { - 'name': _('退回调整'), - 'type': 'ir.actions.act_window', - 'view_mode': 'form', - 'res_model': 'sf.production.technology.re_adjust.wizard', - 'target': 'new', - 'context': { - 'default_production_id': self.id, - 'default_origin': self.origin, - }} + production_count = self.env['mrp.production'].search_count([ + ('origin', '=', self.origin), + ('product_id', '=', self.product_id.id), + ('state', '=', 'confirmed') + ]) + if production_count > 1: + return { + 'name': _('退回调整'), + 'type': 'ir.actions.act_window', + 'views': [(self.env.ref( + 'sf_manufacturing.sf_production_technology_re_adjust_wizard_form_view').id, + 'form')], + 'res_model': 'sf.production.technology.re_adjust.wizard', + 'target': 'new', + 'context': { + 'default_production_id': self.id, + 'default_origin': self.origin, + }} + else: + return { + 'name': _('退回调整'), + 'type': 'ir.actions.act_window', + 'views': [(self.env.ref( + 'sf_manufacturing.sf_production_technology_re_adjust_wizard_confirm_form_view').id, + 'form')], + 'res_model': 'sf.production.technology.re_adjust.wizard', + 'target': 'new', + 'context': { + 'default_production_id': self.id, + 'default_origin': self.origin, + }} # 工艺确认 def technology_confirm(self): @@ -441,16 +487,37 @@ class MrpProduction(models.Model): error_panel.append(design.panel) else: if not error_panel and not process_parameters: - return { - 'name': _('工艺确认'), - 'type': 'ir.actions.act_window', - 'view_mode': 'form', - 'res_model': 'sf.production.technology.wizard', - 'target': 'new', - 'context': { - 'default_production_id': self.id, - 'default_origin': self.origin, - }} + production_count = self.env['mrp.production'].search_count([ + ('origin', '=', self.origin), + ('product_id', '=', self.product_id.id), + ('state', '=', 'technology_to_confirmed') + ]) + if production_count > 1: + return { + 'name': _('工艺确认'), + 'type': 'ir.actions.act_window', + 'views': [(self.env.ref( + 'sf_manufacturing.sf_production_technology_wizard_form_view').id, + 'form')], + 'res_model': 'sf.production.technology.wizard', + 'target': 'new', + 'context': { + 'default_production_id': self.id, + 'default_origin': self.origin, + }} + else: + return { + 'name': _('工艺确认'), + 'type': 'ir.actions.act_window', + 'views': [(self.env.ref( + 'sf_manufacturing.sf_production_technology_wizard_confirm_form_view').id, + 'form')], + 'res_model': 'sf.production.technology.wizard', + 'target': 'new', + 'context': { + 'default_production_id': self.id, + 'default_origin': self.origin, + }} if error_panel: raise UserError(_("【加工面】为%s的标准工序顺序有误,请调整后重试", ", ".join(error_panel))) return True @@ -762,7 +829,7 @@ class MrpProduction(models.Model): # 立即创建外协出入库单和采购订单 # self.env['stock.picking'].create_outcontract_picking(workorder, production) # self.env['purchase.order'].get_purchase_order(workorder, production, - # product_id_to_production_names) + # product_id_to_production_names) consecutive_workorders = [] # 处理最后一个组,即使它可能只有一个工作订单 @@ -774,6 +841,7 @@ class MrpProduction(models.Model): for workorders in reversed(proc_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) + # 工单排序 def _reset_work_order_sequence1(self, k): for rec in self: @@ -888,7 +956,7 @@ class MrpProduction(models.Model): # 对工单进行逐个插入 for work_id in work_ids: for order_id in rec.workorder_ids.filtered(lambda item: item.sequence > 0): - if work_id.name == order_id.name: + if work_id.name == order_id.name and work_id.processing_panel == order_id.processing_panel: work_id.sequence = order_id.sequence + 1 break # 对该工单之后的工单工序进行加一 @@ -1170,7 +1238,9 @@ class MrpProduction(models.Model): lambda wk: (wk.name == result_id.routing_type and wk.processing_panel == result_id.processing_panel and wk.state == 'done')).id for result_id in result_ids] - + workorder_ids = self.workorder_ids.filtered( + lambda wk: wk.technology_design_id.routing_tag == 'standard' and wk.state not in ['rework', 'cancel']) + logging.info('标准工艺工单【%s】' % workorder_ids) return { 'name': _('返工'), 'type': 'ir.actions.act_window', @@ -1179,7 +1249,7 @@ class MrpProduction(models.Model): 'target': 'new', 'context': { 'default_production_id': self.id, - 'default_workorder_ids': self.workorder_ids.ids, + 'default_workorder_ids': workorder_ids.ids if workorder_ids.ids != [] else self.workorder_ids.ids, 'default_hidden_workorder_ids': ','.join(map(str, work_id_list)) if work_id_list != [] else '', 'default_reprogramming_num': cloud_programming['reprogramming_num'], 'default_programming_state': cloud_programming['programming_state'], @@ -1435,6 +1505,26 @@ class MrpProduction(models.Model): for production in self: production.production_type = '自动化产线加工' if not production.product_id.is_manual_processing else '人工线下加工' + @api.depends('procurement_group_id.mrp_production_ids.move_dest_ids.group_id.sale_id') + def _compute_sale_order_count(self): + for production in self: + if production.sale_order_id: + production.sale_order_count = 1 + else: + production.sale_order_count = 0 + + def action_view_sale_orders(self): + if self.sale_order_id: + action = { + 'res_model': 'sale.order', + 'type': 'ir.actions.act_window', + } + action.update({ + 'view_mode': 'form', + 'res_id': self.sale_order_id.id, + }) + return action + @api.model_create_multi def create(self, vals_list): """ @@ -1495,7 +1585,9 @@ class MrpProduction(models.Model): def action_view_purchase_orders(self): self.ensure_one() - if self.product_id.product_tmpl_id.single_manufacturing == True: + if self.is_remanufacture: + production = self + elif self.product_id.product_tmpl_id.single_manufacturing == True: production = self.env['mrp.production'].search( [('origin', '=', self.origin), ('product_id', '=', self.product_id.id)], limit=1, order='id asc') else: diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index bc012ab9..bab7e282 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -129,7 +129,7 @@ class ResMrpWorkOrder(models.Model): Y10_axis = fields.Float(default=0) Z10_axis = fields.Float(default=0) X_deviation_angle = fields.Integer(string="X轴偏差度", default=0) - test_results = fields.Selection([("合格", "合格")], default='合格', + test_results = fields.Selection([("合格", "合格"), ("返工", "返工"), ("报废", "报废")], default='合格', string="检测结果", tracking=True) cnc_ids = fields.One2many("sf.cnc.processing", 'workorder_id', string="CNC加工程序") cmm_ids = fields.One2many("sf.cmm.program", 'workorder_id', string="CMM程序") diff --git a/sf_manufacturing/models/stock.py b/sf_manufacturing/models/stock.py index 01c7bd93..fbe3be8c 100644 --- a/sf_manufacturing/models/stock.py +++ b/sf_manufacturing/models/stock.py @@ -656,8 +656,8 @@ class StockPicking(models.Model): def create_outcontract_picking(self, workorders, item, sorted_workorders): for workorder in workorders: if workorder.move_subcontract_workorder_ids: - workorder.move_subcontract_workorder_ids.write({'state': 'draft'}) - workorder.move_subcontract_workorder_ids.picking_id.write({'state': 'draft'}) + workorder.move_subcontract_workorder_ids.write({'state': 'waiting'}) + workorder.move_subcontract_workorder_ids.picking_id.write({'state': 'waiting'}) else: # 创建一个新的补货组 procurement_group_id = self.env['procurement.group'].create({ @@ -993,7 +993,8 @@ class ReStockMove(models.Model): production = self.env['mrp.production'].search([('name', '=', self[0].origin)], limit=1, order='id asc') productions = self.env['mrp.production'].search( [('origin', '=', production.origin), ('product_id', '=', production.product_id.id)]) - res['origin'] = ','.join(productions.mapped('name')) + if productions.mapped('name'): + res['origin'] = ','.join(productions.mapped('name')) res['retrospect_ref'] = production.product_id.name return res diff --git a/sf_manufacturing/security/ir.model.access.csv b/sf_manufacturing/security/ir.model.access.csv index 2880e662..f096b449 100644 --- a/sf_manufacturing/security/ir.model.access.csv +++ b/sf_manufacturing/security/ir.model.access.csv @@ -182,3 +182,5 @@ access_sf_manual_product_model_type_routing_sort_group_sf_mrp_user,sf_manual_pro access_sf_manual_product_model_type_routing_sort_manager,sf_manual_product_model_type_routing_sort,model_sf_manual_product_model_type_routing_sort,sf_base.group_sf_mrp_manager,1,1,1,1 access_sf_manual_product_model_type_routing_sort_group_plan_dispatch,sf_manual_product_model_type_routing_sort_group_plan_dispatch,model_sf_manual_product_model_type_routing_sort,sf_base.group_plan_dispatch,1,0,0,0 access_sf_detection_result_manager,sf_detection_result_manager,model_sf_detection_result,,1,1,1,1 + +access_mrp_workorder_batch_replan_wizard_group_plan_dispatch,mrp_workorder_batch_replan_wizard_group_plan_dispatch,model_mrp_workorder_batch_replan_wizard,sf_base.group_plan_dispatch,1,1,1,0 \ No newline at end of file diff --git a/sf_manufacturing/views/mrp_production_addional_change.xml b/sf_manufacturing/views/mrp_production_addional_change.xml index fd0a5ead..043990ef 100644 --- a/sf_manufacturing/views/mrp_production_addional_change.xml +++ b/sf_manufacturing/views/mrp_production_addional_change.xml @@ -43,6 +43,7 @@ + @@ -123,6 +124,7 @@ + @@ -584,6 +586,7 @@ + diff --git a/sf_manufacturing/views/mrp_workorder_batch_replan.xml b/sf_manufacturing/views/mrp_workorder_batch_replan.xml new file mode 100644 index 00000000..972d77c7 --- /dev/null +++ b/sf_manufacturing/views/mrp_workorder_batch_replan.xml @@ -0,0 +1,18 @@ + + + + >mrp.workorder.tree.editable.inherit + mrp.workorder + + + + + + + + + + + \ No newline at end of file diff --git a/sf_manufacturing/views/mrp_workorder_view.xml b/sf_manufacturing/views/mrp_workorder_view.xml index be1a6523..3828f00e 100644 --- a/sf_manufacturing/views/mrp_workorder_view.xml +++ b/sf_manufacturing/views/mrp_workorder_view.xml @@ -104,8 +104,7 @@ current [('state', '!=', 'cancel'),('schedule_state', '=', '已排')] - {'search_default_product': 1, 'search_default_workcenter_id': - active_id,'search_default_filter_order_warning':1,'search_default_filter_order_overdue':1,'search_default_filter_order_normal':1} + {'search_default_product': 1, 'search_default_workcenter_id': active_id} @@ -200,7 +199,7 @@ - 1: + raise models.ValidationError("批量重新安排工单类型必须一致。") + show_json_popover = self.workorder_id.mapped('show_json_popover') + if any(not value for value in show_json_popover): + raise models.ValidationError("所选工单必须都为逾期状态") + failed_workorders = {} + for workorder_info in self.workorder_id: + try: + workorder_info.action_replan() + except Exception as e: + reason = str(e) + if reason in failed_workorders: + failed_workorders[reason].append( + workorder_info.production_id.name) + else: + failed_workorders[reason] = [workorder_info.production_id.name] + if failed_workorders: + error_messages = "\n".join( + [f"制造订单: {', '.join(workorder_names)}, 原因: {reason}" for reason, workorder_names in + failed_workorders.items()]) + return { + 'type': 'ir.actions.client', + 'tag': 'display_notification', + 'params': { + 'message': f"以下工单重新安排失败:\n{error_messages}", + 'sticky': False, + 'color': 'red', + 'next': { + 'type': 'ir.actions.act_window_close' + } + }, + } diff --git a/sf_manufacturing/wizard/mrp_workorder_batch_replan_wizard_views.xml b/sf_manufacturing/wizard/mrp_workorder_batch_replan_wizard_views.xml new file mode 100644 index 00000000..37d26ac7 --- /dev/null +++ b/sf_manufacturing/wizard/mrp_workorder_batch_replan_wizard_views.xml @@ -0,0 +1,31 @@ + + + + mrp.workorder.batch.replan.wizard.form.view + mrp.workorder.batch.replan.wizard + + + + + + + + + + + + + + 重新安排工单 + ir.actions.act_window + mrp.workorder.batch.replan.wizard + form + + new + {'default_workorder_id': active_ids} + + + \ No newline at end of file diff --git a/sf_manufacturing/wizard/production_technology_re_adjust_wizard_views.xml b/sf_manufacturing/wizard/production_technology_re_adjust_wizard_views.xml index 48346cb2..4ab7fc86 100644 --- a/sf_manufacturing/wizard/production_technology_re_adjust_wizard_views.xml +++ b/sf_manufacturing/wizard/production_technology_re_adjust_wizard_views.xml @@ -21,6 +21,26 @@ + + sf.production.technology.re_adjust.wizard.form.view + sf.production.technology.re_adjust.wizard + + + + + + + 是否确认退回调整 + + + + + + + 工艺退回调整 sf.production.technology.re_adjust.wizard diff --git a/sf_manufacturing/wizard/production_technology_wizard.py b/sf_manufacturing/wizard/production_technology_wizard.py index f49480aa..e5976aaa 100644 --- a/sf_manufacturing/wizard/production_technology_wizard.py +++ b/sf_manufacturing/wizard/production_technology_wizard.py @@ -14,7 +14,7 @@ class ProductionTechnologyWizard(models.TransientModel): is_technology_confirm = fields.Boolean(default=False) def confirm(self): - if self.is_technology_confirm is True and self.production_id.product_id.categ_id.type == '成品': + if self.is_technology_confirm is True and self.production_id.product_id.categ_id.type in ['成品', '坯料']: domain = [('origin', '=', self.origin), ('state', '=', 'technology_to_confirmed'), ('product_id', '=', self.production_id.product_id.id)] else: diff --git a/sf_manufacturing/wizard/production_technology_wizard_views.xml b/sf_manufacturing/wizard/production_technology_wizard_views.xml index 134fb8a9..8706ef83 100644 --- a/sf_manufacturing/wizard/production_technology_wizard_views.xml +++ b/sf_manufacturing/wizard/production_technology_wizard_views.xml @@ -1,6 +1,6 @@ - + sf.production.technology.wizard.form.view sf.production.technology.wizard @@ -13,7 +13,28 @@ 对当前制造订单,同一销售订单相同产品所生成的制造订单统一进行工艺调整与确认 + + + + + + + sf.production.technology.wizard.form.view + sf.production.technology.wizard + + + + + + + 是否确认工艺调整 + + diff --git a/sf_manufacturing/wizard/rework_wizard.py b/sf_manufacturing/wizard/rework_wizard.py index eeae9ae9..bcc8514b 100644 --- a/sf_manufacturing/wizard/rework_wizard.py +++ b/sf_manufacturing/wizard/rework_wizard.py @@ -62,6 +62,36 @@ class ReworkWizard(models.TransientModel): hidden_workorder_list.sort() item.hidden_workorder_ids = ','.join(hidden_workorder_list) + def efficacy_rework_wo(self, wk_ids): + """限制判断 """ + # 判断检测结果待处理所对应的工单是否勾选 + result_ids = self.production_id.detection_result_ids.filtered(lambda dr: dr.handle_result == '待处理') + work_id_list = [] + if result_ids: + work_id_list = [self.workorder_ids.filtered( + lambda wk: (wk.name == result_id.routing_type and wk.processing_panel == result_id.processing_panel + and wk.state == 'done')).id + for result_id in result_ids] + if len(wk_ids.filtered(lambda wk: wk.id in work_id_list)) != len(work_id_list): + raise ValidationError('存在【检测结果】为【待处理】所对应的工单未进行勾选!!!') + # 获取已完成的标准工单 + grouped_rw_ids = {key: list(group) for key, group in groupby(wk_ids, key=lambda w: w.processing_panel)} + for panel, panel_rw_ids in grouped_rw_ids.items(): + # 1、当制造订单内ZM面的工单都已完成时,返工勾选工序时只能勾选上ZM面的所有工序进行返工 + work_ids = self.workorder_ids.filtered(lambda w: w.state == 'done' and w.processing_panel == panel) + if len(work_ids) == 3 and len(panel_rw_ids) != 3: + raise ValidationError( + '因为[%s]面的工单已全部完成,如果要对[%s]面的工单进行返工,请勾选这个面的所有工单。' % (panel, panel)) + # 2、当FM工单在CNC工单进行选择返工,并将已全部完成的ZM面工序全部勾选上时,FM工单上所有的已完成的工单(装夹预调工单)也必须进行勾选 + if not wk_ids.filtered(lambda wk: wk.name == '装夹预调' and wk.processing_panel == panel): + if wk_ids.filtered(lambda wk: wk.name == 'CNC加工' and wk.processing_panel == panel): + sequence_max = wk_ids.filtered(lambda wk: wk.name == 'CNC加工' and wk.processing_panel == panel).sequence + for wk_id in wk_ids.filtered(lambda wk: wk.sequence < sequence_max): + if len(wk_ids.filtered(lambda wk: wk.processing_panel == wk_id.processing_panel)) == 3: + raise ValidationError( + '由于在[%s]面之前存在整个面进行了勾选的情况,所以在勾选了[%s]面的【CNC加工】工单的时,请勾选[%s]面的装夹预调工单!' % ( + panel, panel, panel)) + def confirm(self): if self.routing_type in ['装夹预调', 'CNC加工']: self.is_clamp_measure = False @@ -79,20 +109,8 @@ class ReworkWizard(models.TransientModel): if self.hidden_workorder_ids: hidden_workorder_list = self.hidden_workorder_ids.split(',') rework_workorder_ids = self.workorder_ids.filtered(lambda w: str(w.id) in hidden_workorder_list) - # 限制判断 - # 1、当制造订单内ZM面的工单都已完成时,返工勾选工序时只能勾选上ZM面的所有工序进行返工 - # 2、当FM工单在CNC工单进行选择返工,并将已全部完成的ZM面工序全部勾选上时,FM工单上所有的已完成的工单(装夹预调工单)也必须进行勾选 - # 获取已完成的标准工单 - # done_normative_workorder_ids = self.workorder_ids.filtered( - # lambda w: w.state == 'done' and w.processing_panel is not False) - # # 获取需要返工的标准工单 - # rework_normative_workorder_ids = rework_workorder_ids.filtered( - # lambda w: w.processing_panel is not False) - # if rework_normative_workorder_ids: - # for rw in rework_normative_workorder_ids: - # if len(done_normative_workorder_ids.filtered( - # lambda w: w.processing_panel == rw.processing_panel)) == 3: - # pass + # 调用效验方法 + self.efficacy_rework_wo(rework_workorder_ids) else: raise ValidationError('请选择返工工单!!!') if rework_workorder_ids: @@ -106,7 +124,7 @@ class ReworkWizard(models.TransientModel): for clamp_workorder_id in clamp_workorder_ids: self.production_id.workorder_ids.filtered( lambda wk: wk.processing_panel == clamp_workorder_id.processing_panel).write( - {'rfid_code': False}) + {'rfid_code': None}) # 返工工单状态设置为【返工】 rework_workorder_ids.write({'state': 'rework'}) # 查询返工工单对应的工艺设计记录,并调用方法拼接数据,用于创建新的工单 @@ -119,7 +137,7 @@ class ReworkWizard(models.TransientModel): and item.panel == work.processing_panel)) if route: work_list = self.env['mrp.workorder'].json_workorder_str(self.production_id, route[0]) - work_list[2].update({'tag_type': '重新加工'}) + work_list[2].update({'tag_type': '重新加工', 'sequence': 0}) workorders_values.append(work_list) # 创建新工单,并进行返工配置的相关操作 if workorders_values: diff --git a/sf_manufacturing/wizard/rework_wizard_views.xml b/sf_manufacturing/wizard/rework_wizard_views.xml index 05d1cc04..aad8a692 100644 --- a/sf_manufacturing/wizard/rework_wizard_views.xml +++ b/sf_manufacturing/wizard/rework_wizard_views.xml @@ -14,7 +14,7 @@ - + + + 下单时间 + @@ -215,8 +218,14 @@ 订单号 - 下单时间 + 下单日期 + + hide + + + +
@@ -200,7 +199,7 @@ - 1: + raise models.ValidationError("批量重新安排工单类型必须一致。") + show_json_popover = self.workorder_id.mapped('show_json_popover') + if any(not value for value in show_json_popover): + raise models.ValidationError("所选工单必须都为逾期状态") + failed_workorders = {} + for workorder_info in self.workorder_id: + try: + workorder_info.action_replan() + except Exception as e: + reason = str(e) + if reason in failed_workorders: + failed_workorders[reason].append( + workorder_info.production_id.name) + else: + failed_workorders[reason] = [workorder_info.production_id.name] + if failed_workorders: + error_messages = "\n".join( + [f"制造订单: {', '.join(workorder_names)}, 原因: {reason}" for reason, workorder_names in + failed_workorders.items()]) + return { + 'type': 'ir.actions.client', + 'tag': 'display_notification', + 'params': { + 'message': f"以下工单重新安排失败:\n{error_messages}", + 'sticky': False, + 'color': 'red', + 'next': { + 'type': 'ir.actions.act_window_close' + } + }, + } diff --git a/sf_manufacturing/wizard/mrp_workorder_batch_replan_wizard_views.xml b/sf_manufacturing/wizard/mrp_workorder_batch_replan_wizard_views.xml new file mode 100644 index 00000000..37d26ac7 --- /dev/null +++ b/sf_manufacturing/wizard/mrp_workorder_batch_replan_wizard_views.xml @@ -0,0 +1,31 @@ + + + + mrp.workorder.batch.replan.wizard.form.view + mrp.workorder.batch.replan.wizard + + + + + + + + + + + + + + 重新安排工单 + ir.actions.act_window + mrp.workorder.batch.replan.wizard + form + + new + {'default_workorder_id': active_ids} + + + \ No newline at end of file diff --git a/sf_manufacturing/wizard/production_technology_re_adjust_wizard_views.xml b/sf_manufacturing/wizard/production_technology_re_adjust_wizard_views.xml index 48346cb2..4ab7fc86 100644 --- a/sf_manufacturing/wizard/production_technology_re_adjust_wizard_views.xml +++ b/sf_manufacturing/wizard/production_technology_re_adjust_wizard_views.xml @@ -21,6 +21,26 @@