From 92b924754d376da2782716059fb591909e03eff0 Mon Sep 17 00:00:00 2001 From: mgw <1392924357@qq.com> Date: Tue, 26 Nov 2024 16:56:47 +0800 Subject: [PATCH 01/63] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=AE=A1=E5=88=92?= =?UTF-8?q?=E8=B0=83=E5=BA=A6=E5=B2=97=E5=92=8C=E7=94=9F=E4=BA=A7=E6=80=BB?= =?UTF-8?q?=E7=9B=91=E6=9D=83=E9=99=90=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/views/mrp_production_addional_change.xml | 7 +++++++ sf_sale/security/ir.model.access.csv | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/sf_manufacturing/views/mrp_production_addional_change.xml b/sf_manufacturing/views/mrp_production_addional_change.xml index 783f39dd..7a626ff2 100644 --- a/sf_manufacturing/views/mrp_production_addional_change.xml +++ b/sf_manufacturing/views/mrp_production_addional_change.xml @@ -737,5 +737,12 @@ + + \ No newline at end of file diff --git a/sf_sale/security/ir.model.access.csv b/sf_sale/security/ir.model.access.csv index 0747340c..64194f9a 100644 --- a/sf_sale/security/ir.model.access.csv +++ b/sf_sale/security/ir.model.access.csv @@ -117,7 +117,7 @@ access_sf_detection_result_group_sale_director,sf_detection_result_group_sale_di access_stock_scrap_group_sale_salemanager,stock_scrap_group_sale_salemanager,stock.model_stock_scrap,sf_base.group_sale_salemanager,1,0,0,0 access_stock_scrap_group_sale_director,stock_scrap_group_sale_director,stock.model_stock_scrap,sf_base.group_sale_director,1,0,0,0 - +access_account_move_group_plan_dispatch,account_move_group_plan_dispatch,account.model_account_move,sf_base.group_plan_dispatch,1,1,1,0 From 6be7c054150851646e3787beccd44d9deb26176a Mon Sep 17 00:00:00 2001 From: "jinling.yang" Date: Tue, 26 Nov 2024 17:05:45 +0800 Subject: [PATCH 02/63] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wizard/production_technology_re_adjust_wizard.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sf_manufacturing/wizard/production_technology_re_adjust_wizard.py b/sf_manufacturing/wizard/production_technology_re_adjust_wizard.py index 6a055aed..7c4000dc 100644 --- a/sf_manufacturing/wizard/production_technology_re_adjust_wizard.py +++ b/sf_manufacturing/wizard/production_technology_re_adjust_wizard.py @@ -49,8 +49,8 @@ class ProductionTechnologyReAdjustWizard(models.TransientModel): if ro.route_id.routing_type == '表面工艺': domain += [('process_parameters_id', '=', ro.process_parameters_id.id)] elif ro.route_id.routing_tag == 'special' and ro.is_auto is False: - display_name = ro.route_id.display_name - domain += [('name', 'ilike', display_name)] + # display_name = ro.route_id.display_name + domain += [('id', '=', ro.id)] elif ro.panel is not False: domain += [('panel', '=', ro.panel)] td_upd = self.env['sf.technology.design'].sudo().search(domain) @@ -67,7 +67,7 @@ class ProductionTechnologyReAdjustWizard(models.TransientModel): if special.process_parameters_id: domain += [('surface_technics_parameters_id', '=', special.process_parameters_id.id)] else: - domain += [('name', '=', special.route_id.name)] + domain += [('technology_design_id', '=', special.id)] workorder = self.env['mrp.workorder'].search(domain) if workorder.state != 'cancel': workorder.write({'state': 'cancel'}) From 56cfeac2140336ab48375807b70ba5e5d9ba2973 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Wed, 27 Nov 2024 11:16:11 +0800 Subject: [PATCH 03/63] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=9D=AF=E6=96=99?= =?UTF-8?q?=E5=86=97=E4=BD=99=E6=8F=8F=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/model_type.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sf_manufacturing/models/model_type.py b/sf_manufacturing/models/model_type.py index 0dd272bd..1fe36b90 100644 --- a/sf_manufacturing/models/model_type.py +++ b/sf_manufacturing/models/model_type.py @@ -7,7 +7,7 @@ class ModelType(models.Model): name = fields.Char('名称') # embryo_tolerance = fields.Char('坯料容余') - embryo_tolerance_id = fields.Many2one('sf.embryo.redundancy', string='坯料容余') + embryo_tolerance_id = fields.Many2one('sf.embryo.redundancy', string='坯料冗余') product_routing_tmpl_ids = fields.One2many('sf.product.model.type.routing.sort', 'product_model_type_id', '成品工序模板(自动化产线加工') embryo_routing_tmpl_ids = fields.One2many('sf.embryo.model.type.routing.sort', 'embryo_model_type_id', From df146a4b58c60ca73d6ee413b48a0710cc947b2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Wed, 27 Nov 2024 15:02:42 +0800 Subject: [PATCH 04/63] =?UTF-8?q?=E6=88=90=E5=93=81=E5=A7=94=E5=A4=96?= =?UTF-8?q?=EF=BC=8C=E5=9D=AF=E6=96=99=E8=87=AA=E5=8A=A0=E5=B7=A5=E7=9A=84?= =?UTF-8?q?=E5=88=B6=E9=80=A0=E6=8E=92=E7=A8=8B=E5=8D=95=E7=94=9F=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/product_template.py | 2 +- sf_manufacturing/models/stock.py | 22 ++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/sf_manufacturing/models/product_template.py b/sf_manufacturing/models/product_template.py index f5f685aa..6e211f09 100644 --- a/sf_manufacturing/models/product_template.py +++ b/sf_manufacturing/models/product_template.py @@ -884,7 +884,7 @@ class ResProductMo(models.Model): 'model_process_parameters_ids': [(6, 0, [])] if not item.get( 'process_parameters_code') else self.get_process_parameters_id(item['process_parameters_code']), 'model_remark': item['remark'], - 'single_manufacturing': True, + 'single_manufacturing': False, 'default_code': '%s-%s' % (order_number, i), 'manual_quotation': item['manual_quotation'] or False, 'part_number': item.get('part_number') or '', diff --git a/sf_manufacturing/models/stock.py b/sf_manufacturing/models/stock.py index ba4908a3..20e740f3 100644 --- a/sf_manufacturing/models/stock.py +++ b/sf_manufacturing/models/stock.py @@ -288,18 +288,18 @@ class StockRule(models.Model): sale_order = self.env['sale.order'].sudo().search([('name', '=', mrp_production.origin)]) else: mrp_production = production - if sale_order: + # 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', - }) + 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', + }) technology_design_values = [] all_production = productions grouped_product_ids = {k: list(g) for k, g in groupby(all_production, key=lambda x: x.product_id.id)} From d6c194eaa8ad5bca3af54631571c966f38ed03c1 Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Wed, 27 Nov 2024 16:18:18 +0800 Subject: [PATCH 05/63] =?UTF-8?q?=E5=A4=84=E7=90=86=E5=88=B6=E9=80=A0?= =?UTF-8?q?=E8=AE=A2=E5=8D=95=E7=8A=B6=E6=80=81=E9=97=AE=E9=A2=98=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/wizard/rework_wizard.py | 11 ++++++++++- sf_tool_management/models/mrp_workorder.py | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/sf_manufacturing/wizard/rework_wizard.py b/sf_manufacturing/wizard/rework_wizard.py index 6c723761..bb787c11 100644 --- a/sf_manufacturing/wizard/rework_wizard.py +++ b/sf_manufacturing/wizard/rework_wizard.py @@ -57,8 +57,17 @@ class ReworkWizard(models.TransientModel): # 限制判断 # 1、当制造订单内ZM面的工单都已完成时,返工勾选工序时只能勾选上ZM面的所有工序进行返工 # 2、当FM工单在CNC工单进行选择返工,并将已全部完成的ZM面工序全部勾选上时,FM工单上所有的已完成的工单(装夹预调工单)也必须进行勾选 - done_panel_workorder_ids = self.workorder_ids.filtered( + # 获取已完成的标准工单 + 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 else: raise ValidationError('请选择返工工单!!!') if rework_workorder_ids: diff --git a/sf_tool_management/models/mrp_workorder.py b/sf_tool_management/models/mrp_workorder.py index 8fe9748e..25ccc460 100644 --- a/sf_tool_management/models/mrp_workorder.py +++ b/sf_tool_management/models/mrp_workorder.py @@ -221,5 +221,6 @@ class MrpProduction(models.Model): logging.info('调用CAM工单程序用刀计划创建方法!!!') self.env['sf.cam.work.order.program.knife.plan'].sudo().create_cam_work_plan(cnc_ids) if not invalid_tool and not missing_tool_1: + self.sudo().write({'tool_state': '0'}) logging.info('校验cnc用刀正常!!!') logging.info('工单cnc程序用刀校验完成!!!') From c169c0a80b18aa69152d9bfbfcb85df58e5f68a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Wed, 27 Nov 2024 17:40:35 +0800 Subject: [PATCH 06/63] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E5=B7=A5=E5=8D=95?= =?UTF-8?q?=E5=AE=8C=E6=88=90=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_production.py | 6 +----- sf_manufacturing/models/mrp_workorder.py | 4 ++-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py index f43c7905..77f73444 100644 --- a/sf_manufacturing/models/mrp_production.py +++ b/sf_manufacturing/models/mrp_production.py @@ -320,11 +320,7 @@ class MrpProduction(models.Model): elif production.state == 'pending_cam' and production.schedule_state == '未排': production.state = 'confirmed' elif production.state == 'to_close' and production.schedule_state == '已排': - if all( - wo_state in ('done', 'cancel') for wo_state in production.workorder_ids.mapped('state')): - production.state = 'done' - else: - production.state = 'pending_cam' + production.state = 'pending_cam' elif production.state == 'confirmed' and production.is_adjust is True: production.state = 'technology_to_confirmed' if production.state == 'confirmed' and production.schedule_state == '已排': diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index 8de6cef7..4e94044a 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -1361,7 +1361,7 @@ class ResMrpWorkOrder(models.Model): # record.recreateManufacturingOrWorkerOrder() is_production_id = False rework_workorder = record.production_id.workorder_ids.filtered(lambda p: p.state == 'rework') - done_workorder = record.production_id.workorder_ids.filtered(lambda p1: p1.state == 'done') + done_workorder = record.production_id.workorder_ids.filtered(lambda p1: p1.state in ['done']) if (len(rework_workorder) + len(done_workorder) == len(record.production_id.workorder_ids)) or ( len(done_workorder) == len(record.production_id.workorder_ids)): is_production_id = True @@ -1378,7 +1378,7 @@ class ResMrpWorkOrder(models.Model): # workorder.rfid_code_old = rfid_code # workorder.rfid_code = False logging.info('workorder.rfid_code:%s' % workorder.rfid_code) - if is_production_id is True and record.routing_type in ['解除装夹', '表面工艺']: + if is_production_id is True and record.routing_type in ['解除装夹', '表面工艺', '切割']: logging.info('product_qty:%s' % record.production_id.product_qty) for move_raw_id in record.production_id.move_raw_ids: move_raw_id.quantity_done = move_raw_id.product_uom_qty From ecf683e66363e0ffff22e2a189cc112fa641bde4 Mon Sep 17 00:00:00 2001 From: "jinling.yang" Date: Wed, 27 Nov 2024 17:54:31 +0800 Subject: [PATCH 07/63] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=87=87=E8=B4=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_production.py | 9 ++++----- sf_manufacturing/models/mrp_routing_workcenter.py | 7 +++++-- sf_manufacturing/models/product_template.py | 4 ++-- sf_manufacturing/models/sf_production_common.py | 10 ++++++++-- .../views/mrp_production_addional_change.xml | 3 ++- sf_mrs_connect/controllers/controllers.py | 6 ++++++ sf_sale/models/quick_easy_order.py | 4 ++-- sf_sale/models/quick_easy_order_old.py | 4 ++-- 8 files changed, 31 insertions(+), 16 deletions(-) diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py index 58cbe7fa..9eee5fe1 100644 --- a/sf_manufacturing/models/mrp_production.py +++ b/sf_manufacturing/models/mrp_production.py @@ -1310,11 +1310,10 @@ class MrpProduction(models.Model): move = self.env['stock.move'].search([('origin', '=', productions.name)], order='id desc') for mo in move: domain = [] - if mo.procure_method == 'make_to_order' and mo.name != productions.name: - if mo.name == '/': - domain = [('barcode', '=', 'WH-PC'), ('sequence_code', '=', 'PC')] - elif mo.name == '拉': - domain = [('barcode', '=', 'WH-INTERNAL'), ('sequence_code', '=', 'INT')] + if mo.location_id.barcode == 'WH-POSTPRODUCTION' and mo.rule_id.picking_type_id.barcode == 'PC': + domain = [('barcode', '=', 'WH-PC'), ('sequence_code', '=', 'PC')] + elif mo.location_id.barcode == 'PL' and mo.rule_id.picking_type_id.barcode == 'INT': + domain = [('barcode', '=', 'WH-INTERNAL'), ('sequence_code', '=', 'INT')] if domain: picking_type = self.env['stock.picking.type'].search(domain) mo.write({'picking_type_id': picking_type.id}) diff --git a/sf_manufacturing/models/mrp_routing_workcenter.py b/sf_manufacturing/models/mrp_routing_workcenter.py index 537c6fd5..e28bd091 100644 --- a/sf_manufacturing/models/mrp_routing_workcenter.py +++ b/sf_manufacturing/models/mrp_routing_workcenter.py @@ -86,9 +86,12 @@ class ResMrpRoutingWorkcenter(models.Model): @api.model def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None): if self._context.get('production_id'): + route_ids = [] technology_design = self.env['sf.technology.design'].search( [('production_id', '=', self._context.get('production_id'))]) - route_ids = [t.route_id.id for t in technology_design] - domain = [('id', 'not in', route_ids)] + for t in technology_design.filtered(lambda a: a.routing_tag == 'special'): + if not t.process_parameters_id: + route_ids.append(t.route_id.surface_technics_id.id) + domain = [('id', 'not in', route_ids), ('routing_tag', '=', 'special')] return self._search(domain, limit=limit, access_rights_uid=name_get_uid) return super()._name_search(name, args, operator, limit, name_get_uid) diff --git a/sf_manufacturing/models/product_template.py b/sf_manufacturing/models/product_template.py index f5f685aa..ebbf5bd2 100644 --- a/sf_manufacturing/models/product_template.py +++ b/sf_manufacturing/models/product_template.py @@ -9,8 +9,8 @@ from odoo.exceptions import ValidationError, UserError from odoo.modules import get_resource_path -from OCC.Extend.DataExchange import read_step_file -from OCC.Extend.DataExchange import write_stl_file +# from OCC.Extend.DataExchange import read_step_file +# from OCC.Extend.DataExchange import write_stl_file class ResProductMo(models.Model): diff --git a/sf_manufacturing/models/sf_production_common.py b/sf_manufacturing/models/sf_production_common.py index dc9ff2a3..113858c1 100644 --- a/sf_manufacturing/models/sf_production_common.py +++ b/sf_manufacturing/models/sf_production_common.py @@ -10,8 +10,14 @@ class SfProductionProcessParameter(models.Model): @api.model def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None): if self._context.get('route_id'): + parameter = [] routing = self.env['mrp.routing.workcenter'].search([('id', '=', self._context.get('route_id'))]) - domain = [('process_id', '=', routing.surface_technics_id.id)] + technology_design = self.env['sf.technology.design'].search( + [('production_id', '=', self._context.get('production_id')), ('routing_tag', '=', 'special'), + ('route_id', '=', self._context.get('route_id'))]) + for t in technology_design: + if t.process_parameters_id: + parameter.append(t.process_parameters_id.id) + domain = [('process_id', '=', routing.surface_technics_id.id), ('id', 'not in', parameter)] return self._search(domain, limit=limit, access_rights_uid=name_get_uid) return super()._name_search(name, args, operator, limit, name_get_uid) - diff --git a/sf_manufacturing/views/mrp_production_addional_change.xml b/sf_manufacturing/views/mrp_production_addional_change.xml index 783f39dd..8a99a6d1 100644 --- a/sf_manufacturing/views/mrp_production_addional_change.xml +++ b/sf_manufacturing/views/mrp_production_addional_change.xml @@ -368,7 +368,8 @@ attrs="{'readonly': [('id', '!=', False)]}" options="{'no_create': True}"/> + string="参数" context="{'route_id':route_id,'production_id': production_id}" + options="{'no_create': True}"/> Date: Wed, 27 Nov 2024 17:54:59 +0800 Subject: [PATCH 08/63] =?UTF-8?q?1=E3=80=81=E6=B7=BB=E5=8A=A0=E8=BF=94?= =?UTF-8?q?=E5=B7=A5=E5=90=91=E5=AF=BC=E4=B8=AD=E9=80=89=E6=8B=A9=E8=BF=94?= =?UTF-8?q?=E5=B7=A5=E5=B7=A5=E5=8D=95=E9=99=90=E5=88=B6=E6=9D=A1=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/wizard/rework_wizard.py | 45 ++++++++++++++++++------ 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/sf_manufacturing/wizard/rework_wizard.py b/sf_manufacturing/wizard/rework_wizard.py index bb787c11..eeae9ae9 100644 --- a/sf_manufacturing/wizard/rework_wizard.py +++ b/sf_manufacturing/wizard/rework_wizard.py @@ -4,6 +4,7 @@ import logging from odoo.exceptions import UserError, ValidationError from datetime import datetime from odoo import models, api, fields, _ +from odoo.tools import groupby class ReworkWizard(models.TransientModel): @@ -37,6 +38,30 @@ class ReworkWizard(models.TransientModel): tool_state = fields.Selection(string='功能刀具状态', related='production_id.tool_state') + @api.onchange('hidden_workorder_ids') + def _onchange_hidden_workorder_ids(self): + for item in self: + if item.hidden_workorder_ids not in ['', None, False]: + hidden_workorder_list = item.hidden_workorder_ids.split(',') + # 获取加工面对应需要返工的工单 + rw_ids = item.workorder_ids.filtered( + lambda w: str(w.ids[0]) in hidden_workorder_list and w.processing_panel not in ['', None, False]) + grouped_rw_ids = {key: list(group) for key, group in groupby(rw_ids, key=lambda w: w.processing_panel)} + for panel, panel_rw_ids in grouped_rw_ids.items(): + work_ids = item.workorder_ids.filtered(lambda w: w.state == 'done' and w.processing_panel == panel) + if len(work_ids) == 3 and len(panel_rw_ids) != 3: + for work_id in work_ids: + if work_id not in panel_rw_ids: + hidden_workorder_list.append(str(work_id.ids[0])) + elif len(work_ids) == 2 and len(panel_rw_ids) < 2 and panel_rw_ids[0].name == 'CNC加工': + if rw_ids.filtered(lambda w: (w.sequence < panel_rw_ids[0].sequence + and w.processing_panel != panel_rw_ids[0].processing_panel)): + hidden_workorder_list.append(str(work_ids.filtered( + lambda w: (w.processing_panel == panel_rw_ids[0].processing_panel + and w.name == '装夹预调')).ids[0])) + hidden_workorder_list.sort() + item.hidden_workorder_ids = ','.join(hidden_workorder_list) + def confirm(self): if self.routing_type in ['装夹预调', 'CNC加工']: self.is_clamp_measure = False @@ -58,16 +83,16 @@ class ReworkWizard(models.TransientModel): # 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 + # 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 else: raise ValidationError('请选择返工工单!!!') if rework_workorder_ids: From c22b91f9d91991bd824e757005d4073c5c152764 Mon Sep 17 00:00:00 2001 From: "jinling.yang" Date: Thu, 28 Nov 2024 09:59:01 +0800 Subject: [PATCH 09/63] =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=87=87=E8=B4=AD?= =?UTF-8?q?=EF=BC=9A=E4=B8=80=E4=B8=AA=E5=88=B6=E9=80=A0=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E5=AF=B9=E5=BA=94=E4=B8=80=E4=B8=AA=E9=87=87=E8=B4=AD=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_production.py | 4 +- sf_manufacturing/models/mrp_workorder.py | 60 ++++++++++--------- sf_manufacturing/models/product_template.py | 4 +- sf_manufacturing/models/stock.py | 11 +++- .../production_technology_re_adjust_wizard.py | 6 +- .../wizard/production_technology_wizard.py | 2 +- sf_sale/models/quick_easy_order.py | 4 +- sf_sale/models/quick_easy_order_old.py | 4 +- sf_sale/models/sale_order.py | 37 ++++++------ 9 files changed, 71 insertions(+), 61 deletions(-) diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py index 9eee5fe1..02113cd5 100644 --- a/sf_manufacturing/models/mrp_production.py +++ b/sf_manufacturing/models/mrp_production.py @@ -842,7 +842,7 @@ class MrpProduction(models.Model): # workorder.picking_ids.move_ids = False workorder.picking_ids = False purchase_order = self.env['purchase.order'].search( - [('state', '=', 'draft'), ('origin', '=', ','.join(production_process)), + [('state', '=', 'draft'), ('origin', '=', item.name), ('purchase_type', '=', 'consignment')]) for line in purchase_order.order_line: server_template = self.env['product.template'].search( @@ -850,7 +850,7 @@ class MrpProduction(models.Model): ('detailed_type', '=', 'service')]) purchase_order_line = self.env['purchase.order.line'].search( [('product_id', '=', server_template.product_variant_id.id), ('id', '=', line.id), - ('product_qty', '=', len(production_process))], limit=1, order='id desc') + ('product_qty', '=', 1)], limit=1, order='id desc') if purchase_order_line: line.unlink() diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index 1600f9f7..f37aae72 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -241,9 +241,9 @@ class ResMrpWorkOrder(models.Model): ('production_id', '=', workorder.production_id.id)]) if previous_workorder: if previous_workorder.supplier_id != workorder.supplier_id: - process_product = self.env['product.template']._get_process_parameters_product( - previous_workorder.surface_technics_parameters_id) - domain += [('partner_id', '=', process_product.partner_id.id)] + # process_product = self.env['product.template']._get_process_parameters_product( + # previous_workorder.surface_technics_parameters_id) + domain += [('surface_technics_parameters_id', '=', workorder.surface_technics_parameters_id.id)] else: domain += [('surface_technics_parameters_id', '=', workorder.surface_technics_parameters_id.id)] picking_ids = self.env['stock.picking'].search(domain, order='id asc') @@ -270,55 +270,57 @@ class ResMrpWorkOrder(models.Model): def _compute_surface_technics_purchase_ids(self): for order in self: if order.routing_type == '表面工艺': - if order.production_id.production_type == '自动化产线加工': - domain = [('programming_no', '=', order.production_id.programming_no)] - else: - domain = [('origin', '=', order.production_id.origin)] - production_programming = self.env['mrp.production'].search(domain, order='name asc') - production_list = [production.name for production in production_programming] - production_no_remanufacture = production_programming.filtered(lambda a: a.is_remanufacture is False) + # if order.production_id.production_type == '自动化产线加工': + # domain = [('programming_no', '=', order.production_id.programming_no)] + # else: + # domain = [('origin', '=', order.production_id.origin)] + # production_programming = self.env['mrp.production'].search(domain, order='name asc') + # production_list = [production.name for production in production_programming] + # production_no_remanufacture = production_programming.filtered(lambda a: a.is_remanufacture is False) # technology_design = self.env['sf.technology.design'].search( # [('process_parameters_id', '=', order.surface_technics_parameters_id.id), # ('production_id', '=', order.production_id.id)]) # if technology_design.is_auto is False: # domain = [('origin', '=', order.production_id.name)] # else: - domain = [('purchase_type', '=', 'consignment'), ('origin', '=', ','.join(production_list))] + domain = [('purchase_type', '=', 'consignment'), ('origin', '=', order.production_id.name)] purchase = self.env['purchase.order'].search(domain) purchase_num = 0 if not purchase: order.surface_technics_purchase_count = 0 - for line in purchase.order_line: - if line.product_id.server_product_process_parameters_id == order.surface_technics_parameters_id: - if line.product_qty == len(production_no_remanufacture): - purchase_num += 1 - order.surface_technics_purchase_count = purchase_num + for po in purchase: + for line in po.order_line: + if line.product_id.server_product_process_parameters_id == order.surface_technics_parameters_id: + if line.product_qty == 1: + purchase_num += 1 + order.surface_technics_purchase_count = purchase_num else: order.surface_technics_purchase_count = 0 def action_view_surface_technics_purchase(self): self.ensure_one() - if self.routing_type == '表面工艺': - if self.production_id.production_type == '自动化产线加工': - domain = [('programming_no', '=', self.production_id.programming_no)] - else: - domain = [('origin', '=', self.production_id.origin)] - production_programming = self.env['mrp.production'].search(domain, order='name asc') - production_list = [production.name for production in production_programming] - production_no_remanufacture = production_programming.filtered(lambda a: a.is_remanufacture is False) + # if self.routing_type == '表面工艺': + # if self.production_id.production_type == '自动化产线加工': + # domain = [('programming_no', '=', self.production_id.programming_no)] + # else: + # domain = [('origin', '=', self.production_id.origin)] + # production_programming = self.env['mrp.production'].search(domain, order='name asc') + # production_list = [production.name for production in production_programming] + # production_no_remanufacture = production_programming.filtered(lambda a: a.is_remanufacture is False) # technology_design = self.env['sf.technology.design'].search( # [('process_parameters_id', '=', self.surface_technics_parameters_id.id), # ('production_id', '=', self.production_id.id)]) # if technology_design.is_auto is False: # domain = [('origin', '=', self.production_id.name)] # else: - domain = [('origin', '=', ','.join(production_list)), ('purchase_type', '=', 'consignment')] + domain = [('origin', '=', self.production_id.name), ('purchase_type', '=', 'consignment')] purchase_orders = self.env['purchase.order'].search(domain) purchase_orders_id = None - for line in purchase_orders.order_line: - if line.product_id.server_product_process_parameters_id == self.surface_technics_parameters_id: - if line.product_qty == len(production_no_remanufacture): - purchase_orders_id = line.order_id.id + for po in purchase_orders: + for line in po.order_line: + if line.product_id.server_product_process_parameters_id == self.surface_technics_parameters_id: + if line.product_qty == 1: + purchase_orders_id = line.order_id.id result = { "type": "ir.actions.act_window", "res_model": "purchase.order", diff --git a/sf_manufacturing/models/product_template.py b/sf_manufacturing/models/product_template.py index ebbf5bd2..f5f685aa 100644 --- a/sf_manufacturing/models/product_template.py +++ b/sf_manufacturing/models/product_template.py @@ -9,8 +9,8 @@ from odoo.exceptions import ValidationError, UserError from odoo.modules import get_resource_path -# from OCC.Extend.DataExchange import read_step_file -# from OCC.Extend.DataExchange import write_stl_file +from OCC.Extend.DataExchange import read_step_file +from OCC.Extend.DataExchange import write_stl_file class ResProductMo(models.Model): diff --git a/sf_manufacturing/models/stock.py b/sf_manufacturing/models/stock.py index fb42da12..a5205640 100644 --- a/sf_manufacturing/models/stock.py +++ b/sf_manufacturing/models/stock.py @@ -283,7 +283,8 @@ class StockRule(models.Model): 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) + 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: @@ -670,10 +671,14 @@ class StockPicking(models.Model): # 创建 外协出库入单 def create_outcontract_picking(self, sorted_workorders_arr, item): + domain = [('origin', '=', item.name), ('name', 'ilike', 'OCOUT')] if len(sorted_workorders_arr) > 1: sorted_workorders_arr = sorted_workorders_arr[0] - stock_picking = self.env['stock.picking'].search([('origin', '=', item.name), ('name', 'ilike', 'OCOUT')]) - if not stock_picking or sorted_workorders_arr: + else: + domain += [ + ('surface_technics_parameters_id', '=', sorted_workorders_arr[0].surface_technics_parameters_id.id)] + stock_picking = self.env['stock.picking'].search(domain) + if not stock_picking: for sorted_workorders in sorted_workorders_arr: # pick_ids = [] if not sorted_workorders.picking_ids: diff --git a/sf_manufacturing/wizard/production_technology_re_adjust_wizard.py b/sf_manufacturing/wizard/production_technology_re_adjust_wizard.py index 7c4000dc..14cebe41 100644 --- a/sf_manufacturing/wizard/production_technology_re_adjust_wizard.py +++ b/sf_manufacturing/wizard/production_technology_re_adjust_wizard.py @@ -99,7 +99,8 @@ class ProductionTechnologyReAdjustWizard(models.TransientModel): if workorder.sequence == 1: workorder.blocked_by_workorder_ids = None else: - workorder.blocked_by_workorder_ids = blocked_by_workorder_ids[0] + if workorder.blocked_by_workorder_ids: + workorder.blocked_by_workorder_ids = blocked_by_workorder_ids[0] productions._reset_work_order_sequence() if self.production_id.product_id.categ_id.type == '成品': productions._reset_subcontract_pick_purchase() @@ -109,5 +110,6 @@ class ProductionTechnologyReAdjustWizard(models.TransientModel): workorders = item.workorder_ids.filtered(lambda wo: wo.state not in ('cancel')).sorted( key=lambda a: a.sequence) if workorders[0].state in ['pending']: - if workorder[0].production_id.product_id.categ_id.type == '成品' and item.programming_state != '已编程': + if workorders[ + 0].production_id.product_id.categ_id.type == '成品' and item.programming_state != '已编程': workorders[0].state = 'waiting' diff --git a/sf_manufacturing/wizard/production_technology_wizard.py b/sf_manufacturing/wizard/production_technology_wizard.py index 630a272e..01103746 100644 --- a/sf_manufacturing/wizard/production_technology_wizard.py +++ b/sf_manufacturing/wizard/production_technology_wizard.py @@ -65,4 +65,4 @@ class ProductionTechnologyWizard(models.TransientModel): key=lambda a: a.sequence) if workorder[0].state in ['pending']: if workorder[0].production_id.product_id.categ_id.type == '成品' and item.programming_state != '已编程': - workorders[0].state = 'waiting' + workorder[0].state = 'waiting' diff --git a/sf_sale/models/quick_easy_order.py b/sf_sale/models/quick_easy_order.py index cb1886a1..081807a4 100644 --- a/sf_sale/models/quick_easy_order.py +++ b/sf_sale/models/quick_easy_order.py @@ -8,8 +8,8 @@ from datetime import datetime import requests from odoo import http from odoo.http import request -# from OCC.Extend.DataExchange import read_step_file -# from OCC.Extend.DataExchange import write_stl_file +from OCC.Extend.DataExchange import read_step_file +from OCC.Extend.DataExchange import write_stl_file from odoo import models, fields, api from odoo.modules import get_resource_path from odoo.exceptions import ValidationError, UserError diff --git a/sf_sale/models/quick_easy_order_old.py b/sf_sale/models/quick_easy_order_old.py index d963d021..87848e3a 100644 --- a/sf_sale/models/quick_easy_order_old.py +++ b/sf_sale/models/quick_easy_order_old.py @@ -5,8 +5,8 @@ import requests import os from datetime import datetime # from OCC.Core.GProp import GProp_GProps -# from OCC.Extend.DataExchange import read_step_file -# from OCC.Extend.DataExchange import write_stl_file +from OCC.Extend.DataExchange import read_step_file +from OCC.Extend.DataExchange import write_stl_file from odoo.addons.sf_base.commons.common import Common from odoo import models, fields, api from odoo.modules import get_resource_path diff --git a/sf_sale/models/sale_order.py b/sf_sale/models/sale_order.py index a73b0a35..9c0e0b09 100644 --- a/sf_sale/models/sale_order.py +++ b/sf_sale/models/sale_order.py @@ -250,35 +250,36 @@ class RePurchaseOrder(models.Model): server_product_process = [] production_process = product_id_to_production_names.get( production.product_id.id) + purchase_order = self.env['purchase.order'].search( + [('state', '=', 'draft'), ('origin', '=', production.name), + ('purchase_type', '=', 'consignment')], order='name asc') for pp in consecutive_process_parameters: server_template = self.env['product.template'].search( [('server_product_process_parameters_id', '=', pp.surface_technics_parameters_id.id), ('detailed_type', '=', 'service')]) - purchase_order_line = self.env['purchase.order.line'].search( - [('product_id', '=', server_template.product_variant_id.id), - ('product_qty', '=', len(production_process))], limit=1, order='id desc') - if not purchase_order_line: + if not purchase_order: server_product_process.append((0, 0, { 'product_id': server_template.product_variant_id.id, - 'product_qty': len(production_process), + 'product_qty': 1, 'product_uom': server_template.uom_id.id })) - else: - if production.name in production_process: - purchase_order = self.env['purchase.order'].search( - [('state', '=', 'draft'), ('origin', '=', ','.join(production_process)), - ('purchase_type', '=', 'consignment')]) - if not purchase_order: - server_product_process.append((0, 0, { - 'product_id': server_template.product_variant_id.id, - 'product_qty': len(production_process), - 'product_uom': server_template.uom_id.id - })) - + for purchase in purchase_order: + for po in purchase.order_line: + if server_template.server_product_process_parameters_id == pp.surface_technics_parameters_id: + purchase_order_line = self.env['purchase.order.line'].search( + [('product_id', '=', server_template.product_variant_id.id), + ('product_qty', '=', 1.0), ('id', '=', po.id)], limit=1, + order='id desc') + if not purchase_order_line and purchase not in purchase_order: + server_product_process.append((0, 0, { + 'product_id': server_template.product_variant_id.id, + 'product_qty': 1, + 'product_uom': server_template.uom_id.id + })) if server_product_process: self.env['purchase.order'].sudo().create({ 'partner_id': server_template.seller_ids[0].partner_id.id, - 'origin': ','.join(production_process), + 'origin': production.name, 'state': 'draft', 'purchase_type': 'consignment', 'order_line': server_product_process}) From d4ba58b55ab397b4c66534d6a617af197efb1401 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Thu, 28 Nov 2024 10:17:03 +0800 Subject: [PATCH 10/63] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=8E=92=E7=A8=8B?= =?UTF-8?q?=E5=8D=95=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_workorder.py | 3 +- sf_plan/models/custom_plan.py | 56 +++++++++++++++--------- 2 files changed, 38 insertions(+), 21 deletions(-) diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index 4e94044a..157717bc 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -1378,7 +1378,8 @@ class ResMrpWorkOrder(models.Model): # workorder.rfid_code_old = rfid_code # workorder.rfid_code = False logging.info('workorder.rfid_code:%s' % workorder.rfid_code) - if is_production_id is True and record.routing_type in ['解除装夹', '表面工艺', '切割']: + # if is_production_id is True and record.routing_type in ['解除装夹', '表面工艺', '切割']: + if is_production_id is True: logging.info('product_qty:%s' % record.production_id.product_qty) for move_raw_id in record.production_id.move_raw_ids: move_raw_id.quantity_done = move_raw_id.product_uom_qty diff --git a/sf_plan/models/custom_plan.py b/sf_plan/models/custom_plan.py index f0214c9a..e7785ad4 100644 --- a/sf_plan/models/custom_plan.py +++ b/sf_plan/models/custom_plan.py @@ -231,26 +231,42 @@ class sf_production_plan(models.Model): if not record.production_line_id: raise ValidationError("未选择生产线") else: - if record.production_id.workorder_ids: - last_cnc_start = record.date_planned_start if record.date_planned_start else datetime.now() - for item in record.production_id.workorder_ids: - if item.name == 'CNC加工': - # 将同一个面的所有工单筛选出来 - workorder_list = record.production_id.workorder_ids.filtered(lambda x: x.processing_panel == item.processing_panel) - routing_workcenter = record.env['mrp.routing.workcenter'].sudo().search( - [('name', '=', 'CNC加工')], limit=1) - # 设置一个小的开始时间 - item.date_planned_start = datetime.now() - timedelta(days=100) - item.date_planned_finished = last_cnc_start + timedelta( - minutes=routing_workcenter.time_cycle) - item.date_planned_start = last_cnc_start - record.sudo().production_id.plan_start_processing_time = item.date_planned_start - item.duration_expected = routing_workcenter.time_cycle - pre_duration , next_duration = record.calculate_plan_time(item, workorder_list) - record.date_planned_finished = item.date_planned_finished - # 计算下一个cnc工单的开始时间 - last_cnc_start = workorder_list[-1].date_planned_finished + timedelta(minutes=pre_duration) - # 没有工单也能排程 + # 自动化产线加工 + if record.production_id.production_type == '自动化产线加工': + if record.production_id.workorder_ids: + last_cnc_start = record.date_planned_start if record.date_planned_start else datetime.now() + for item in record.production_id.workorder_ids: + if item.name == 'CNC加工': + # 将同一个面的所有工单筛选出来 + workorder_list = record.production_id.workorder_ids.filtered(lambda x: x.processing_panel == item.processing_panel) + routing_workcenter = record.env['mrp.routing.workcenter'].sudo().search( + [('name', '=', 'CNC加工')], limit=1) + # 设置一个小的开始时间 + item.date_planned_start = datetime.now() - timedelta(days=100) + item.date_planned_finished = last_cnc_start + timedelta( + minutes=routing_workcenter.time_cycle) + item.date_planned_start = last_cnc_start + record.sudo().production_id.plan_start_processing_time = item.date_planned_start + item.duration_expected = routing_workcenter.time_cycle + pre_duration , next_duration = record.calculate_plan_time(item, workorder_list) + record.date_planned_finished = item.date_planned_finished + # 计算下一个cnc工单的开始时间 + last_cnc_start = workorder_list[-1].date_planned_finished + timedelta(minutes=pre_duration) + # 没有工单也能排程 + else: + # 人工线下加工只排第一张工单 + if record.production_id.workorder_ids: + item = record.production_id.workorder_ids[0] + last_wo_start = record.date_planned_start if record.date_planned_start else datetime.now() + routing_workcenter = record.env['mrp.routing.workcenter'].sudo().search( + [('name', '=', item.routing_type)], limit=1) + item.date_planned_start = datetime.now() - timedelta(days=100) + item.date_planned_finished = last_wo_start + timedelta( + minutes=routing_workcenter.time_cycle) + item.date_planned_start = last_wo_start + record.sudo().production_id.plan_start_processing_time = item.date_planned_start + item.duration_expected = routing_workcenter.time_cycle + record.calculate_plan_time(item, item) record.state = 'done' # record.production_id.schedule_state = '已排' record.sudo().production_id.schedule_state = '已排' From a80d498eabfcea52f34fea07a2278da7cc0979c1 Mon Sep 17 00:00:00 2001 From: "jinling.yang" Date: Thu, 28 Nov 2024 10:40:48 +0800 Subject: [PATCH 11/63] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=88=B6=E9=80=A0?= =?UTF-8?q?=E8=AE=A2=E5=8D=95-=E9=87=87=E8=B4=AD=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_workorder.py | 4 +- sf_manufacturing/views/mrp_workorder_view.xml | 2 +- .../production_technology_re_adjust_wizard.py | 11 +++- .../wizard/production_technology_wizard.py | 58 ++++++++++++++++++- 4 files changed, 68 insertions(+), 7 deletions(-) diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index f29b63db..9fc3138f 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -269,10 +269,10 @@ class ResMrpWorkOrder(models.Model): @api.depends('state', 'production_id.name') def _compute_surface_technics_purchase_ids(self): for order in self: - if order.routing_type == '表面工艺': + if order.routing_type == '表面工艺' and order.state not in ['cancel']: # if order.production_id.production_type == '自动化产线加工': # domain = [('programming_no', '=', order.production_id.programming_no)] - # else: + # else:buzhdiao # domain = [('origin', '=', order.production_id.origin)] # production_programming = self.env['mrp.production'].search(domain, order='name asc') # production_list = [production.name for production in production_programming] diff --git a/sf_manufacturing/views/mrp_workorder_view.xml b/sf_manufacturing/views/mrp_workorder_view.xml index c989faff..13fff868 100644 --- a/sf_manufacturing/views/mrp_workorder_view.xml +++ b/sf_manufacturing/views/mrp_workorder_view.xml @@ -139,7 +139,7 @@ + attrs="{'invisible': [('surface_technics_purchase_count', '=', 0)]}"> diff --git a/sf_manufacturing/wizard/production_technology_re_adjust_wizard.py b/sf_manufacturing/wizard/production_technology_re_adjust_wizard.py index 14cebe41..89ba95d0 100644 --- a/sf_manufacturing/wizard/production_technology_re_adjust_wizard.py +++ b/sf_manufacturing/wizard/production_technology_re_adjust_wizard.py @@ -62,6 +62,7 @@ class ProductionTechnologyReAdjustWizard(models.TransientModel): for special in special_design: workorders_values = [] if special.active is False: + is_cancel = False # 工单采购单外协出入库单皆需取消 domain = [('production_id', '=', special.production_id.id)] if special.process_parameters_id: @@ -69,7 +70,15 @@ class ProductionTechnologyReAdjustWizard(models.TransientModel): else: domain += [('technology_design_id', '=', special.id)] workorder = self.env['mrp.workorder'].search(domain) - if workorder.state != 'cancel': + previous_workorder = self.env['mrp.workorder'].search( + [('sequence', '=', workorder.sequence - 1), ('routing_type', '=', '表面工艺'), + ('production_id', '=', workorder.production_id.id)]) + if previous_workorder: + if previous_workorder.supplier_id != workorder.supplier_id: + is_cancel = True + else: + is_cancel = True + if workorder.state != 'cancel' and is_cancel is True: workorder.write({'state': 'cancel'}) workorder.picking_ids.write({'state': 'cancel'}) workorder.picking_ids.move_ids.write({'state': 'cancel'}) diff --git a/sf_manufacturing/wizard/production_technology_wizard.py b/sf_manufacturing/wizard/production_technology_wizard.py index 01103746..d81a89a0 100644 --- a/sf_manufacturing/wizard/production_technology_wizard.py +++ b/sf_manufacturing/wizard/production_technology_wizard.py @@ -53,9 +53,61 @@ class ProductionTechnologyWizard(models.TransientModel): td_upd = self.env['sf.technology.design'].sudo().search(domain) if td_upd: ro.write({'sequence': td_upd.sequence, 'active': td_upd.active}) - # special = production.technology_design_ids.filtered( - # lambda td: td.is_auto is False and td.process_parameters_id is not False) - # # if special: + special_design = self.env['sf.technology.design'].sudo().search( + [('routing_tag', '=', 'special'), ('production_id', '=', production.id), + ('is_auto', '=', False), ('active', 'in', [True, False])]) + for special in special_design: + workorders_values = [] + if special.active is False: + is_cancel = False + # 工单采购单外协出入库单皆需取消 + domain = [('production_id', '=', special.production_id.id)] + if special.process_parameters_id: + domain += [('surface_technics_parameters_id', '=', special.process_parameters_id.id)] + else: + domain += [('technology_design_id', '=', special.id)] + workorder = self.env['mrp.workorder'].search(domain) + previous_workorder = self.env['mrp.workorder'].search( + [('sequence', '=', workorder.sequence - 1), ('routing_type', '=', '表面工艺'), + ('production_id', '=', workorder.production_id.id)]) + if previous_workorder: + if previous_workorder.supplier_id != workorder.supplier_id: + is_cancel = True + else: + is_cancel = True + if workorder.state != 'cancel' and is_cancel is True: + workorder.write({'state': 'cancel'}) + workorder.picking_ids.write({'state': 'cancel'}) + workorder.picking_ids.move_ids.write({'state': 'cancel'}) + purchase_order = self.env['purchase.order'].search( + [('origin', '=', workorder.production_id.origin)]) + for line in purchase_order.order_line: + if line.product_id.server_product_process_parameters_id == workorder.surface_technics_parameters_id: + purchase_order.write({'state': 'cancel'}) + else: + if special.production_id.workorder_ids: + workorder = self.env['mrp.workorder'].search( + [('technology_design_id', '=', special.id), ('production_id', '=', special.production_id.id)]) + if not workorder: + if special.route_id.routing_type == '表面工艺': + product_production_process = self.env['product.template'].search( + [('server_product_process_parameters_id', '=', special.process_parameters_id.id)]) + workorders_values.append( + self.env[ + 'mrp.workorder']._json_workorder_surface_process_str(special.production_id, special, + product_production_process.seller_ids[ + 0].partner_id.id)) + else: + workorders_values.append( + self.env['mrp.workorder'].json_workorder_str(special.production_id, special)) + special.production_id.write({'workorder_ids': workorders_values}) + else: + if len(workorder.blocked_by_workorder_ids) > 1: + if workorder.sequence == 1: + workorder.blocked_by_workorder_ids = None + else: + if workorder.blocked_by_workorder_ids: + workorder.blocked_by_workorder_ids = blocked_by_workorder_ids[0] productions._create_workorder(False) if self.production_id.product_id.categ_id.type == '成品': productions.get_subcontract_pick_purchase() From f1e70d2c668f7f8026d067274a67a3c572ee059b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Thu, 28 Nov 2024 11:36:32 +0800 Subject: [PATCH 12/63] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E8=AF=A2=E4=BB=B7?= =?UTF-8?q?=E5=8D=95=E4=B8=AD=E8=87=AA=E5=8A=A8=E5=8C=96=E4=BA=A7=E7=BA=BF?= =?UTF-8?q?=E5=8A=A0=E5=B7=A5=E7=9A=84=E8=AE=A2=E5=8D=95=E4=B8=8D=E7=94=9F?= =?UTF-8?q?=E6=88=90=E7=BC=96=E7=A8=8B=E5=8D=95=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/stock.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sf_manufacturing/models/stock.py b/sf_manufacturing/models/stock.py index 20e740f3..25819fe1 100644 --- a/sf_manufacturing/models/stock.py +++ b/sf_manufacturing/models/stock.py @@ -317,7 +317,7 @@ class StockRule(models.Model): if production_item.product_id.id in product_id_to_production_names: # 同一个产品多个制造订单对应一个编程单和模型库 # 只调用一次fetchCNC,并将所有生产订单的名称作为字符串传递 - if not production_item.programming_no and production.production_type == '自动化产线加工': + if not production_item.programming_no and production_item.production_type == '自动化产线加工': if not production_programming.programming_no: production_item.fetchCNC( ', '.join(product_id_to_production_names[production_item.product_id.id])) From 5eea260618618a35f18870f164ee4d8ca5ed6c96 Mon Sep 17 00:00:00 2001 From: mgw <1392924357@qq.com> Date: Thu, 28 Nov 2024 13:38:14 +0800 Subject: [PATCH 13/63] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BB=93=E5=82=A8?= =?UTF-8?q?=E5=B2=97=E8=A7=92=E8=89=B2=E6=9D=83=E9=99=90=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/security/ir.model.access.csv | 1 + sf_manufacturing/views/mrp_production_addional_change.xml | 7 +++++++ sf_quality/security/ir.model.access.csv | 1 + 3 files changed, 9 insertions(+) diff --git a/sf_manufacturing/security/ir.model.access.csv b/sf_manufacturing/security/ir.model.access.csv index 24c38570..cdf62571 100644 --- a/sf_manufacturing/security/ir.model.access.csv +++ b/sf_manufacturing/security/ir.model.access.csv @@ -52,6 +52,7 @@ access_mrp_routing_workcenter_manager_group_sf_mrp_user,mrp.routing.workcenter.m access_mrp_bom_manager_group_sf_mrp_user,mrp.bom.manager,mrp.model_mrp_bom,sf_base.group_sf_mrp_user,1,1,1,0 access_mrp_bom_line_manager_group_sf_mrp_user,mrp.bom.line.manager,mrp.model_mrp_bom_line,sf_base.group_sf_mrp_user,1,1,1,0 access_mrp_bom_line_group_plan_director,mrp_bom_line_group_plan_director,mrp.model_mrp_bom_line,sf_base.group_plan_director,1,1,1,0 +access_mrp_bom_line_group_sf_stock_user,mrp_bom_line_group_sf_stock_user,mrp.model_mrp_bom_line,sf_base.group_sf_stock_user,1,1,1,0 access_mrp_bom_line_group_sale_director,mrp_bom_line_group_sale_director,mrp.model_mrp_bom_line,sf_base.group_sale_director,1,1,1,0 access_mrp_bom_line_group_sale_salemanager,mrp_bom_line_group_sale_salemanager,mrp.model_mrp_bom_line,sf_base.group_sale_salemanager,1,0,1,0 access_mrp_bom_line_group_purchase_director,mrp_bom_line_group_purchase_director,mrp.model_mrp_bom_line,sf_base.group_purchase_director,1,1,1,0 diff --git a/sf_manufacturing/views/mrp_production_addional_change.xml b/sf_manufacturing/views/mrp_production_addional_change.xml index 7a626ff2..461c2321 100644 --- a/sf_manufacturing/views/mrp_production_addional_change.xml +++ b/sf_manufacturing/views/mrp_production_addional_change.xml @@ -744,5 +744,12 @@ groups="sf_base.group_plan_dispatch,sf_base.group_sf_mrp_manager" sequence="1"/> + + \ No newline at end of file diff --git a/sf_quality/security/ir.model.access.csv b/sf_quality/security/ir.model.access.csv index 19818982..907c115b 100644 --- a/sf_quality/security/ir.model.access.csv +++ b/sf_quality/security/ir.model.access.csv @@ -11,6 +11,7 @@ access_quality_point_group_sf_mrp_manager,quality_point_group_sf_mrp_manager,qua access_quality_check_group_quality,quality_check_group_quality,quality.model_quality_check,sf_base.group_quality,1,1,1,0 access_quality_check_group_quality_director,quality_check_group_quality_director,quality.model_quality_check,sf_base.group_quality_director,1,1,1,0 access_quality_check_group_plan_dispatch,quality_check_group_plan_dispatch,quality.model_quality_check,sf_base.group_plan_dispatch,1,0,0,0 +access_quality_check_group_sf_stock_user,quality_check_group_sf_stock_user,quality.model_quality_check,sf_base.group_sf_stock_user,1,0,0,0 access_quality_check_group_plan_director,quality_check_group_plan_director,quality.model_quality_check,sf_base.group_plan_director,1,0,0,0 access_quality_check_group_purchase,quality_check_group_purchase,quality.model_quality_check,sf_base.group_purchase,1,0,0,0 access_quality_check_group_purchase_director,quality_check_group_purchase_director,quality.model_quality_check,sf_base.group_purchase_director,1,0,0,0 From 8ff73d564779a02ed0bf28e24e6738e28e78a431 Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Thu, 28 Nov 2024 15:09:11 +0800 Subject: [PATCH 14/63] =?UTF-8?q?=E5=B7=A5=E5=8D=95=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_workorder.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index d50b1df2..6858ccab 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -1095,8 +1095,7 @@ class ResMrpWorkOrder(models.Model): # ================= 如果制造订单刀具状态为[无效刀、缺刀] 或者 制造订单状态为[返工]========================== if (workorder.production_id.tool_state in ['1', '2'] or workorder.production_id.state == 'rework' or workorder.production_id.schedule_state != '已排' - or len( - workorder.production_id.picking_ids.filtered(lambda w: w.state not in ['done', 'cancel'])) != 0 + or workorder.production_id.reservation_state not in ['assigned'] or workorder.production_id.workorder_ids.filtered( lambda wk: wk.sequence == workorder.sequence - 1).test_results in ['报废', '返工']): if workorder.state != 'waiting': From 96171013d61c9b6542651291877cddbdc05b8eae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Thu, 28 Nov 2024 15:10:45 +0800 Subject: [PATCH 15/63] =?UTF-8?q?=E4=BF=AE=E6=94=B9=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 | 73 +++++++++++++++-------------------- 1 file changed, 31 insertions(+), 42 deletions(-) diff --git a/sf_plan/models/custom_plan.py b/sf_plan/models/custom_plan.py index e7785ad4..7fcec54e 100644 --- a/sf_plan/models/custom_plan.py +++ b/sf_plan/models/custom_plan.py @@ -232,41 +232,37 @@ class sf_production_plan(models.Model): raise ValidationError("未选择生产线") else: # 自动化产线加工 - if record.production_id.production_type == '自动化产线加工': - if record.production_id.workorder_ids: - last_cnc_start = record.date_planned_start if record.date_planned_start else datetime.now() - for item in record.production_id.workorder_ids: - if item.name == 'CNC加工': - # 将同一个面的所有工单筛选出来 - workorder_list = record.production_id.workorder_ids.filtered(lambda x: x.processing_panel == item.processing_panel) - routing_workcenter = record.env['mrp.routing.workcenter'].sudo().search( - [('name', '=', 'CNC加工')], limit=1) - # 设置一个小的开始时间 - item.date_planned_start = datetime.now() - timedelta(days=100) - item.date_planned_finished = last_cnc_start + timedelta( - minutes=routing_workcenter.time_cycle) - item.date_planned_start = last_cnc_start - record.sudo().production_id.plan_start_processing_time = item.date_planned_start - item.duration_expected = routing_workcenter.time_cycle - pre_duration , next_duration = record.calculate_plan_time(item, workorder_list) - record.date_planned_finished = item.date_planned_finished - # 计算下一个cnc工单的开始时间 - last_cnc_start = workorder_list[-1].date_planned_finished + timedelta(minutes=pre_duration) - # 没有工单也能排程 - else: - # 人工线下加工只排第一张工单 - if record.production_id.workorder_ids: - item = record.production_id.workorder_ids[0] - last_wo_start = record.date_planned_start if record.date_planned_start else datetime.now() - routing_workcenter = record.env['mrp.routing.workcenter'].sudo().search( - [('name', '=', item.routing_type)], limit=1) - item.date_planned_start = datetime.now() - timedelta(days=100) - item.date_planned_finished = last_wo_start + timedelta( + if record.production_id.workorder_ids: + # 自动化产线加工 + if record.production_id.production_type == '自动化产线加工': + # 找到第一张CNC加工工单 + first_cnc_workorder = record.production_id.workorder_ids.filtered(lambda x: x.name == 'CNC加工')[0] + date_start = record.date_planned_start if record.date_planned_start else datetime.now() + routing_workcenter = first_cnc_workorder.technology_design_id.route_id + # 设置一个小的开始时间 + first_cnc_workorder.date_planned_start = datetime.now() - timedelta(days=100) + first_cnc_workorder.date_planned_finished = date_start + timedelta( minutes=routing_workcenter.time_cycle) - item.date_planned_start = last_wo_start + first_cnc_workorder.date_planned_start = date_start + record.sudo().production_id.plan_start_processing_time = first_cnc_workorder.date_planned_start + first_cnc_workorder.duration_expected = routing_workcenter.time_cycle + record.calculate_plan_time(first_cnc_workorder, record.production_id.workorder_ids) + # 找到最后一张CNC加工工单 + last_cnc_workorder = record.production_id.workorder_ids.filtered(lambda x: x.name == 'CNC加工')[-1] + record.date_planned_finished = last_cnc_workorder.date_planned_finished + else: + # 人工线下加工只排第一张工单 + item = record.production_id.workorder_ids[0] + wo_start = record.date_planned_start if record.date_planned_start else datetime.now() + item.date_planned_start = datetime.now() - timedelta(days=100) + item.date_planned_finished = wo_start + timedelta( + minutes=routing_workcenter.time_cycle) + item.date_planned_start = wo_start record.sudo().production_id.plan_start_processing_time = item.date_planned_start item.duration_expected = routing_workcenter.time_cycle - record.calculate_plan_time(item, item) + record.calculate_plan_time(item, record.production_id.workorder_ids) + last_cnc_workorder = record.production_id.workorder_ids[-1] + record.date_planned_finished = last_cnc_workorder.date_planned_finished record.state = 'done' # record.production_id.schedule_state = '已排' record.sudo().production_id.schedule_state = '已排' @@ -328,38 +324,31 @@ class sf_production_plan(models.Model): if workorder.id == item.id: item_position = index break - routing_workcenters = self.env['mrp.routing.workcenter'].sudo().search([]) - # 记录所有前序工序时长 - previous_workorder_duration = 0 for i in range(item_position, -1, -1): if i < 1: break current_workorder = workorder_list[i] next_workorder = workorder_list[i - 1] - routing_workcenter = routing_workcenters.filtered(lambda x: x.name == next_workorder.name)[0] + routing_workcenter = next_workorder.technology_design_id.route_id # 设置一个小的开始时间 next_workorder.date_planned_start = datetime.now() - timedelta(days=100) next_workorder.date_planned_finished = current_workorder.date_planned_start next_workorder.date_planned_start = next_workorder.date_planned_finished - timedelta( minutes=routing_workcenter.time_cycle) next_workorder.duration_expected = routing_workcenter.time_cycle - previous_workorder_duration += routing_workcenter.time_cycle - # 记录所有后续工序时长 - next_workorder_duration = 0 + for i in range(item_position, len(workorder_list) - 1): if i > len(workorder_list) - 1: break current_workorder = workorder_list[i] next_workorder = workorder_list[i + 1] - routing_workcenter = routing_workcenters.filtered(lambda x: x.name == next_workorder.name)[0] + routing_workcenter = next_workorder.technology_design_id.route_id # 设置一个小的开始时间 next_workorder.date_planned_start = datetime.now() - timedelta(days=100) next_workorder.date_planned_finished = current_workorder.date_planned_finished + timedelta( minutes=routing_workcenter.time_cycle) next_workorder.date_planned_start = current_workorder.date_planned_finished next_workorder.duration_expected = routing_workcenter.time_cycle - next_workorder_duration += routing_workcenter.time_cycle - return previous_workorder_duration, next_workorder_duration def calculate_plan_time_after(self, item, workorder_id_list): """ From d57cc591159a69e1269eac3471edf9339ce11d5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Thu, 28 Nov 2024 15:20:56 +0800 Subject: [PATCH 16/63] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=8E=92=E7=A8=8B?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_plan/models/custom_plan.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sf_plan/models/custom_plan.py b/sf_plan/models/custom_plan.py index 7fcec54e..4c4e4b30 100644 --- a/sf_plan/models/custom_plan.py +++ b/sf_plan/models/custom_plan.py @@ -254,6 +254,7 @@ class sf_production_plan(models.Model): # 人工线下加工只排第一张工单 item = record.production_id.workorder_ids[0] wo_start = record.date_planned_start if record.date_planned_start else datetime.now() + routing_workcenter = item.technology_design_id.route_id item.date_planned_start = datetime.now() - timedelta(days=100) item.date_planned_finished = wo_start + timedelta( minutes=routing_workcenter.time_cycle) From 942aa469e3e167cc7ec574274b4cbee126bdcedc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Thu, 28 Nov 2024 15:21:54 +0800 Subject: [PATCH 17/63] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=8E=92=E7=A8=8B?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_plan/models/custom_plan.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sf_plan/models/custom_plan.py b/sf_plan/models/custom_plan.py index 4c4e4b30..147caa96 100644 --- a/sf_plan/models/custom_plan.py +++ b/sf_plan/models/custom_plan.py @@ -319,6 +319,9 @@ class sf_production_plan(models.Model): def calculate_plan_time(self, item, workorder_list): """ 根据CNC工单的时间去计算之前的其他工单的开始结束时间 + param: + item: 基准工单(根据该工单的开始结束时间去计算其他工单的开始结束时间) + workorder_list: 需排程的工单列表 """ item_position = 0 for index, workorder in enumerate(workorder_list): From 7362f0cd301d1b53bcfc0df461296d6b8ce4a0bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Thu, 28 Nov 2024 15:41:39 +0800 Subject: [PATCH 18/63] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=9D=AF=E6=96=99?= =?UTF-8?q?=E5=86=97=E4=BD=99=E6=8F=8F=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/views/model_type_view.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sf_manufacturing/views/model_type_view.xml b/sf_manufacturing/views/model_type_view.xml index f0ffd81a..0f8b3085 100644 --- a/sf_manufacturing/views/model_type_view.xml +++ b/sf_manufacturing/views/model_type_view.xml @@ -31,7 +31,7 @@ - + From 2c37dbf5c40afb045c801e5d049f41e73027e5b9 Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Thu, 28 Nov 2024 15:51:54 +0800 Subject: [PATCH 19/63] =?UTF-8?q?=E5=88=B6=E9=80=A0=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_production.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py index 232b4907..65be98c7 100644 --- a/sf_manufacturing/models/mrp_production.py +++ b/sf_manufacturing/models/mrp_production.py @@ -331,6 +331,9 @@ class MrpProduction(models.Model): production.state = 'pending_cam' if production.is_rework is True: production.state = 'rework' + if (production.state == 'rework' and production.tool_state == '0' + and production.schedule_state == '已排' and production.is_rework is False): + production.state = 'pending_cam' # if production.state == 'pending_cam': # if all(wo_state in 'done' for wo_state in production.workorder_ids.mapped('state')): # production.state = 'done' @@ -353,6 +356,7 @@ class MrpProduction(models.Model): if production.tool_state == '2': production.state = 'rework' + # 退回调整 def technology_back_adjust(self): process_parameters = [] From c42c053d664d1699d58469eac6cd89d93acb294e Mon Sep 17 00:00:00 2001 From: "jinling.yang" Date: Thu, 28 Nov 2024 15:59:17 +0800 Subject: [PATCH 20/63] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=A1=A8=E9=9D=A2?= =?UTF-8?q?=E5=B7=A5=E8=89=BA=E5=A4=96=E5=8D=8F=E5=8F=8A=E5=B7=A5=E8=89=BA?= =?UTF-8?q?=E8=AE=BE=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_workorder.py | 52 +++--- sf_manufacturing/models/product_template.py | 4 +- sf_manufacturing/models/stock.py | 162 ++++++++---------- .../production_technology_re_adjust_wizard.py | 2 +- .../wizard/production_technology_wizard.py | 2 +- sf_mrs_connect/controllers/controllers.py | 76 ++++---- sf_sale/models/quick_easy_order.py | 4 +- sf_sale/models/quick_easy_order_old.py | 4 +- 8 files changed, 147 insertions(+), 159 deletions(-) diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index ab4166ea..a0bc0bb6 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -1204,21 +1204,21 @@ class ResMrpWorkOrder(models.Model): if self.sequence == 1: # 判断工单状态是否为等待组件 - if self.state == 'waiting': - raise UserError('制造订单【%s】缺少组件信息!' % self.production_id.name) - # 判断是否有坯料的序列号信息 - boolean = False - if self.production_id.move_raw_ids: - if self.production_id.move_raw_ids[0].product_id.categ_type == '坯料': - if self.production_id.move_raw_ids[0].move_line_ids: - if self.production_id.move_raw_ids[0].move_line_ids: - if self.production_id.move_raw_ids[0].move_line_ids[0].lot_id.name: - boolean = True - else: - boolean = True - if not boolean: - raise UserError('制造订单【%s】缺少组件的序列号信息!' % self.production_id.name) - self.pro_code = self.production_id.move_raw_ids[0].move_line_ids[0].lot_id.name + # if self.state == 'waiting': + # raise UserError('制造订单【%s】缺少组件信息!' % self.production_id.name) + # # 判断是否有坯料的序列号信息 + # boolean = False + # if self.production_id.move_raw_ids: + # if self.production_id.move_raw_ids[0].product_id.categ_type == '坯料': + # if self.production_id.move_raw_ids[0].move_line_ids: + # if self.production_id.move_raw_ids[0].move_line_ids: + # if self.production_id.move_raw_ids[0].move_line_ids[0].lot_id.name: + # boolean = True + # else: + # boolean = True + # if not boolean: + # raise UserError('制造订单【%s】缺少组件的序列号信息!' % self.production_id.name) + # self.pro_code = self.production_id.move_raw_ids[0].move_line_ids[0].lot_id.name # cnc校验 if self.production_id.production_type == '自动化产线加工': cnc_workorder = self.search( @@ -1247,10 +1247,14 @@ class ResMrpWorkOrder(models.Model): [('barcode', 'ilike', 'WH-PREPRODUCTION')]).id), ('location_dest_id', '=', self.env['stock.location'].search( [('barcode', 'ilike', 'VL-SPOC')]).id), - ('origin', '=', self.production_id.name)]) - if move_out.state != 'done': - move_out.write({'state': 'assigned', 'production_id': False}) - self.env['stock.move.line'].create(move_out.get_move_line(self.production_id, self)) + ('origin', '=', self.production_id.name), ('state', 'not in', ['cancel', 'done'])]) + for mo in move_out: + pick = self.env['stock.picking'].search([('id', '=', mo.picking_id.id), ('name', 'ilike', 'OCOUT'), + ('partner_id', '=', self.supplier_id.id)]) + if pick: + if mo.state != 'done': + mo.write({'state': 'assigned', 'production_id': False}) + self.env['stock.move.line'].create(mo.get_move_line(self.production_id, self)) # move_out._action_assign() if self.state == 'waiting' or self.state == 'ready' or self.state == 'progress': @@ -1315,11 +1319,11 @@ class ResMrpWorkOrder(models.Model): def button_finish(self): for record in self: if record.routing_type == '装夹预调': - if not record.rfid_code and record.is_rework is False: - raise UserError("请扫RFID码进行绑定") - if record.is_rework is False: - if not record.material_center_point: - raise UserError("坯料中心点为空,请检查") + # if not record.rfid_code and record.is_rework is False: + # raise UserError("请扫RFID码进行绑定") + # if record.is_rework is False: + # if not record.material_center_point: + # raise UserError("坯料中心点为空,请检查") # if record.X_deviation_angle <= 0: # raise UserError("X偏差角度小于等于0,请检查!本次计算的X偏差角度为:%s" % record.X_deviation_angle) record.process_state = '待加工' diff --git a/sf_manufacturing/models/product_template.py b/sf_manufacturing/models/product_template.py index 6e211f09..fd0168fb 100644 --- a/sf_manufacturing/models/product_template.py +++ b/sf_manufacturing/models/product_template.py @@ -9,8 +9,8 @@ from odoo.exceptions import ValidationError, UserError from odoo.modules import get_resource_path -from OCC.Extend.DataExchange import read_step_file -from OCC.Extend.DataExchange import write_stl_file +# from OCC.Extend.DataExchange import read_step_file +# from OCC.Extend.DataExchange import write_stl_file class ResProductMo(models.Model): diff --git a/sf_manufacturing/models/stock.py b/sf_manufacturing/models/stock.py index 853634f7..1f540131 100644 --- a/sf_manufacturing/models/stock.py +++ b/sf_manufacturing/models/stock.py @@ -290,7 +290,7 @@ class StockRule(models.Model): else: mrp_production = production # if sale_order: - # sale_order.write({'schedule_status': 'to schedule'}) + # 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, @@ -301,7 +301,6 @@ class StockRule(models.Model): 'product_id': production.product_id.id, 'state': 'draft', }) - technology_design_values = [] 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对应的生产订单名称列表 @@ -311,6 +310,7 @@ class StockRule(models.Model): # 为同一个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)], @@ -325,70 +325,69 @@ class StockRule(models.Model): else: production_item.write({'programming_no': production_programming.programming_no, 'programming_state': '编程中'}) - if not technology_design_values: - 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)) - else: + 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(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: + self.env['sf.technology.design'].json_technology_design_str(k, 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_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_parameter = production_item.product_id.model_process_parameters_ids.filtered( - lambda pm: pm.process_id.id == p.id) - if process_parameter: - 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)) - productions.technology_design_ids = technology_design_values + 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_parameter = production_item.product_id.model_process_parameters_ids.filtered( + lambda pm: pm.process_id.id == p.id) + if process_parameter: + 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 @@ -634,39 +633,24 @@ class StockPicking(models.Model): return '%s%s' % (rescode, num) def button_validate(self): - if self.picking_type_id.barcode == 'OCOUT': - move_out = self.env['stock.move'].search( - [('location_id', '=', self.env['stock.location'].search( - [('barcode', 'ilike', 'WH-PREPRODUCTION')]).id), - ('location_dest_id', '=', self.env['stock.location'].search( - [('barcode', 'ilike', 'VL-SPOC')]).id), - ('origin', '=', self.origin)]) + res = super().button_validate() + if res is True and self.picking_type_id.sequence_code == 'OCOUT': + # if self.id == move_out.picking_id.id: + # if move_out.move_line_ids.workorder_id.state == 'progress': move_in = self.env['stock.move'].search( [('location_dest_id', '=', self.env['stock.location'].search( [('barcode', 'ilike', 'WH-PREPRODUCTION')]).id), ('location_id', '=', self.env['stock.location'].search( [('barcode', 'ilike', 'VL-SPOC')]).id), - ('origin', '=', self.origin), ('picking_id', '=', self.id)]) - if self.location_id == move_in.location_id and self.location_dest_id == move_in.location_dest_id: - if move_out.origin == move_in.origin: - move_in.write({'production_id': False}) - if move_out.picking_id.state != 'done': - raise UserError( - _('该入库单对应的单号为%s的出库单还未完成,不能进行验证操作!' % move_out.picking_id.name)) - res = super().button_validate() - if res is True and self.picking_type_id.barcode == 'OCIN': - if self.id == move_out.picking_id.id: - # if move_out.move_line_ids.workorder_id.state == 'progress': - move_in = self.env['stock.move'].search( - [('location_dest_id', '=', self.env['stock.location'].search( - [('barcode', 'ilike', 'WH-PREPRODUCTION')]).id), - ('location_id', '=', self.env['stock.location'].search( - [('barcode', 'ilike', 'VL-SPOC')]).id), - ('origin', '=', self.origin)]) - production = self.env['mrp.production'].search([('name', '=', self.origin)]) - if move_in.state != 'done': - move_in.write({'state': 'assigned'}) - self.env['stock.move.line'].create(move_in.get_move_line(production, None)) + ('origin', '=', self.origin), ('state', 'not in', ['cancel', 'done'])]) + production = self.env['mrp.production'].search([('name', '=', self.origin)]) + for mi in move_in: + pick = self.env['stock.picking'].search([('id', '=', mi.picking_id.id), ('name', 'ilike', 'OCIN'), + ('partner_id', '=', self.partner_id.id)]) + if pick: + if mi.state != 'done': + mi.write({'state': 'assigned'}) + self.env['stock.move.line'].create(mi.get_move_line(production, None)) return res diff --git a/sf_manufacturing/wizard/production_technology_re_adjust_wizard.py b/sf_manufacturing/wizard/production_technology_re_adjust_wizard.py index 89ba95d0..6d7e438f 100644 --- a/sf_manufacturing/wizard/production_technology_re_adjust_wizard.py +++ b/sf_manufacturing/wizard/production_technology_re_adjust_wizard.py @@ -83,7 +83,7 @@ class ProductionTechnologyReAdjustWizard(models.TransientModel): workorder.picking_ids.write({'state': 'cancel'}) workorder.picking_ids.move_ids.write({'state': 'cancel'}) purchase_order = self.env['purchase.order'].search( - [('origin', '=', workorder.production_id.origin)]) + [('origin', '=', workorder.production_id.name)]) for line in purchase_order.order_line: if line.product_id.server_product_process_parameters_id == workorder.surface_technics_parameters_id: purchase_order.write({'state': 'cancel'}) diff --git a/sf_manufacturing/wizard/production_technology_wizard.py b/sf_manufacturing/wizard/production_technology_wizard.py index d81a89a0..a02bb8f6 100644 --- a/sf_manufacturing/wizard/production_technology_wizard.py +++ b/sf_manufacturing/wizard/production_technology_wizard.py @@ -80,7 +80,7 @@ class ProductionTechnologyWizard(models.TransientModel): workorder.picking_ids.write({'state': 'cancel'}) workorder.picking_ids.move_ids.write({'state': 'cancel'}) purchase_order = self.env['purchase.order'].search( - [('origin', '=', workorder.production_id.origin)]) + [('origin', '=', workorder.production_id.name)]) for line in purchase_order.order_line: if line.product_id.server_product_process_parameters_id == workorder.surface_technics_parameters_id: purchase_order.write({'state': 'cancel'}) diff --git a/sf_mrs_connect/controllers/controllers.py b/sf_mrs_connect/controllers/controllers.py index 87aee0dd..a5f76710 100644 --- a/sf_mrs_connect/controllers/controllers.py +++ b/sf_mrs_connect/controllers/controllers.py @@ -40,21 +40,21 @@ class Sf_Mrs_Connect(http.Controller, MultiInheritController): return json.JSONEncoder().encode(res) if productions: # 拉取所有加工面的程序文件 - for r in ret['processing_panel'].split(','): - program_path_tmp_r = os.path.join('/tmp', ret['folder_name'], 'return', r) - if os.path.exists(program_path_tmp_r): - files_r = os.listdir(program_path_tmp_r) - if files_r: - for file_name in files_r: - file_path = os.path.join(program_path_tmp_r, file_name) - os.remove(file_path) - download_state = request.env['sf.cnc.processing'].with_user( - request.env.ref("base.user_admin")).download_file_tmp( - ret['folder_name'], r) - if download_state is False: - res['status'] = -2 - res['message'] = '编程单号为%s的CNC程序文件从FTP拉取失败' % (ret['programming_no']) - return json.JSONEncoder().encode(res) + # for r in ret['processing_panel'].split(','): + # program_path_tmp_r = os.path.join('/tmp', ret['folder_name'], 'return', r) + # if os.path.exists(program_path_tmp_r): + # files_r = os.listdir(program_path_tmp_r) + # if files_r: + # for file_name in files_r: + # file_path = os.path.join(program_path_tmp_r, file_name) + # os.remove(file_path) + # download_state = request.env['sf.cnc.processing'].with_user( + # request.env.ref("base.user_admin")).download_file_tmp( + # ret['folder_name'], r) + # if download_state is False: + # res['status'] = -2 + # res['message'] = '编程单号为%s的CNC程序文件从FTP拉取失败' % (ret['programming_no']) + # return json.JSONEncoder().encode(res) for production in productions: production.write({'programming_state': '已编程', 'work_state': '已编程'}) for panel in ret['processing_panel'].split(','): @@ -72,29 +72,29 @@ class Sf_Mrs_Connect(http.Controller, MultiInheritController): cnc_workorder_has.write( {'cnc_ids': cnc_workorder_has.cnc_ids.sudo()._json_cnc_processing(panel, ret), 'cmm_ids': cnc_workorder_has.cmm_ids.sudo()._json_cmm_program(panel, ret)}) - for panel in ret['processing_panel'].split(','): - # 查询状态为进行中且工序类型为CNC加工的工单 - cnc_workorder = productions.workorder_ids.filtered( - lambda ac: ac.routing_type == 'CNC加工' and ac.state not in ['progress', 'done', 'rework' - 'cancel'] and ac.processing_panel == panel) - if cnc_workorder: - # program_path_tmp_panel = os.path.join('C://Users//43484//Desktop//fsdownload//test', - # panel) - program_path_tmp_panel = os.path.join('/tmp', ret['folder_name'], 'return', panel) - files_panel = os.listdir(program_path_tmp_panel) - if files_panel: - for file in files_panel: - file_extension = os.path.splitext(file)[1] - if file_extension.lower() == '.pdf': - panel_file_path = os.path.join(program_path_tmp_panel, file) - logging.info('panel_file_path:%s' % panel_file_path) - cnc_workorder.write({'cnc_worksheet': base64.b64encode(open(panel_file_path, 'rb').read())}) - pre_workorder = productions.workorder_ids.filtered( - lambda ap: ap.routing_type == '装夹预调' and ap.state not in ['done', 'rework' - 'cancel'] and ap.processing_panel == panel) - if pre_workorder: - pre_workorder.write( - {'processing_drawing': base64.b64encode(open(panel_file_path, 'rb').read())}) + # for panel in ret['processing_panel'].split(','): + # # 查询状态为进行中且工序类型为CNC加工的工单 + # cnc_workorder = productions.workorder_ids.filtered( + # lambda ac: ac.routing_type == 'CNC加工' and ac.state not in ['progress', 'done', 'rework' + # 'cancel'] and ac.processing_panel == panel) + # if cnc_workorder: + # # program_path_tmp_panel = os.path.join('C://Users//43484//Desktop//fsdownload//test', + # # panel) + # program_path_tmp_panel = os.path.join('/tmp', ret['folder_name'], 'return', panel) + # files_panel = os.listdir(program_path_tmp_panel) + # if files_panel: + # for file in files_panel: + # file_extension = os.path.splitext(file)[1] + # if file_extension.lower() == '.pdf': + # panel_file_path = os.path.join(program_path_tmp_panel, file) + # logging.info('panel_file_path:%s' % panel_file_path) + # cnc_workorder.write({'cnc_worksheet': base64.b64encode(open(panel_file_path, 'rb').read())}) + # pre_workorder = productions.workorder_ids.filtered( + # lambda ap: ap.routing_type == '装夹预调' and ap.state not in ['done', 'rework' + # 'cancel'] and ap.processing_panel == panel) + # if pre_workorder: + # pre_workorder.write( + # {'processing_drawing': base64.b64encode(open(panel_file_path, 'rb').read())}) productions.write({'programming_state': '已编程', 'work_state': '已编程'}) logging.info('已更新制造订单编程状态:%s' % productions.ids) res.update({ diff --git a/sf_sale/models/quick_easy_order.py b/sf_sale/models/quick_easy_order.py index 081807a4..cb1886a1 100644 --- a/sf_sale/models/quick_easy_order.py +++ b/sf_sale/models/quick_easy_order.py @@ -8,8 +8,8 @@ from datetime import datetime import requests from odoo import http from odoo.http import request -from OCC.Extend.DataExchange import read_step_file -from OCC.Extend.DataExchange import write_stl_file +# from OCC.Extend.DataExchange import read_step_file +# from OCC.Extend.DataExchange import write_stl_file from odoo import models, fields, api from odoo.modules import get_resource_path from odoo.exceptions import ValidationError, UserError diff --git a/sf_sale/models/quick_easy_order_old.py b/sf_sale/models/quick_easy_order_old.py index 87848e3a..d963d021 100644 --- a/sf_sale/models/quick_easy_order_old.py +++ b/sf_sale/models/quick_easy_order_old.py @@ -5,8 +5,8 @@ import requests import os from datetime import datetime # from OCC.Core.GProp import GProp_GProps -from OCC.Extend.DataExchange import read_step_file -from OCC.Extend.DataExchange import write_stl_file +# from OCC.Extend.DataExchange import read_step_file +# from OCC.Extend.DataExchange import write_stl_file from odoo.addons.sf_base.commons.common import Common from odoo import models, fields, api from odoo.modules import get_resource_path From 20cfbf7230fb5abeb7018ea71a5f0787095c1688 Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Thu, 28 Nov 2024 17:50:12 +0800 Subject: [PATCH 21/63] =?UTF-8?q?=E5=A4=84=E7=90=86=20=20=E5=9D=AF?= =?UTF-8?q?=E6=96=99=E7=9A=84=E5=88=B6=E9=80=A0=E8=AE=A2=E5=8D=95=E7=94=9F?= =?UTF-8?q?=E6=88=90=E7=9A=84=E6=89=B9=E6=AC=A1=E5=BA=8F=E5=88=97=E5=8F=B7?= =?UTF-8?q?=E4=B8=8D=E5=AF=B9=20=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/stock.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sf_manufacturing/models/stock.py b/sf_manufacturing/models/stock.py index 4162ed68..b8cb237a 100644 --- a/sf_manufacturing/models/stock.py +++ b/sf_manufacturing/models/stock.py @@ -424,6 +424,8 @@ class ProductionLot(models.Model): """Generate `lot_names` from a string.""" if first_lot.__contains__(display_name): first_lot = first_lot[(len(display_name) + 1):] + else: + first_lot = first_lot[-3:] # We look if the first lot contains at least one digit. caught_initial_number = regex_findall(r"\d+", first_lot) From deb2f6ca6464f32ee13a335ab6b0415295bc6768 Mon Sep 17 00:00:00 2001 From: "jinling.yang" Date: Thu, 28 Nov 2024 18:01:29 +0800 Subject: [PATCH 22/63] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=87=87=E8=B4=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_production.py | 29 +++++++++++++---------- sf_sale/models/sale_order.py | 9 ++++--- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py index 65be98c7..9156dc38 100644 --- a/sf_manufacturing/models/mrp_production.py +++ b/sf_manufacturing/models/mrp_production.py @@ -309,7 +309,8 @@ class MrpProduction(models.Model): for move in production.move_raw_ids if move.product_id): production.state = 'progress' # 新添加的状态逻辑 - if production.state in ['to_close', 'progress', 'technology_to_confirmed'] and production.schedule_state == '未排': + if production.state in ['to_close', 'progress', + 'technology_to_confirmed'] and production.schedule_state == '未排': if not production.workorder_ids or production.is_adjust is True: production.state = 'technology_to_confirmed' else: @@ -356,7 +357,6 @@ class MrpProduction(models.Model): if production.tool_state == '2': production.state = 'rework' - # 退回调整 def technology_back_adjust(self): process_parameters = [] @@ -849,15 +849,20 @@ class MrpProduction(models.Model): purchase_order = self.env['purchase.order'].search( [('state', '=', 'draft'), ('origin', '=', item.name), ('purchase_type', '=', 'consignment')]) - for line in purchase_order.order_line: - server_template = self.env['product.template'].search( - [('server_product_process_parameters_id', '=', workorder.surface_technics_parameters_id.id), - ('detailed_type', '=', 'service')]) - purchase_order_line = self.env['purchase.order.line'].search( - [('product_id', '=', server_template.product_variant_id.id), ('id', '=', line.id), - ('product_qty', '=', 1)], limit=1, order='id desc') - if purchase_order_line: - line.unlink() + server_template = self.env['product.template'].search( + [('server_product_process_parameters_id', '=', + workorder.surface_technics_parameters_id.id), + ('detailed_type', '=', 'service')]) + for po in purchase_order: + for line in po.order_line: + if line.product_id == server_template.product_variant_id: + continue + if server_template.server_product_process_parameters_id != line.product_id.server_product_process_parameters_id: + purchase_order_line = self.env['purchase.order.line'].search( + [('product_id', '=', server_template.product_variant_id.id), ('id', '=', line.id), + ('product_qty', '=', 1)], limit=1, order='id desc') + if purchase_order_line: + line.unlink() def _reset_work_order_sequence(self): """ @@ -898,8 +903,6 @@ class MrpProduction(models.Model): for cw in cancel_work_ids: cw.sequence = sequence + 1 - - def _reset_work_order_sequence_1(self): """ 工单工序排序方法(旧) diff --git a/sf_sale/models/sale_order.py b/sf_sale/models/sale_order.py index 9c0e0b09..e225c274 100644 --- a/sf_sale/models/sale_order.py +++ b/sf_sale/models/sale_order.py @@ -265,17 +265,20 @@ class RePurchaseOrder(models.Model): })) for purchase in purchase_order: for po in purchase.order_line: - if server_template.server_product_process_parameters_id == pp.surface_technics_parameters_id: + if po.product_id == server_template.product_variant_id: + continue + if server_template.server_product_process_parameters_id != po.product_id.server_product_process_parameters_id: purchase_order_line = self.env['purchase.order.line'].search( [('product_id', '=', server_template.product_variant_id.id), - ('product_qty', '=', 1.0), ('id', '=', po.id)], limit=1, + ('product_qty', '=', 1.0), ('id', '=', purchase.id)], limit=1, order='id desc') - if not purchase_order_line and purchase not in purchase_order: + if not purchase_order_line: server_product_process.append((0, 0, { 'product_id': server_template.product_variant_id.id, 'product_qty': 1, 'product_uom': server_template.uom_id.id })) + if server_product_process: self.env['purchase.order'].sudo().create({ 'partner_id': server_template.seller_ids[0].partner_id.id, From 9a9e47b4ff6bd3fad1d06a19ec25ee322bf7c444 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Fri, 29 Nov 2024 08:59:52 +0800 Subject: [PATCH 23/63] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E7=B2=BE=E5=9D=AF?= =?UTF-8?q?=E6=96=99=E8=AE=A1=E7=AE=97=E7=B2=BE=E5=BA=A6=E9=97=AE=E9=A2=98?= =?UTF-8?q?=EF=BC=8C=E6=8E=92=E7=A8=8B=E5=8A=A0=E4=B8=8A=E9=A2=84=E7=95=99?= =?UTF-8?q?=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/product_template.py | 24 ++++++++++++++++----- sf_plan/models/custom_plan.py | 16 +++++++------- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/sf_manufacturing/models/product_template.py b/sf_manufacturing/models/product_template.py index 6e211f09..fb6f92ce 100644 --- a/sf_manufacturing/models/product_template.py +++ b/sf_manufacturing/models/product_template.py @@ -859,12 +859,12 @@ class ResProductMo(models.Model): raise UserError('请先配置模型类型内的坯料冗余') vals = { 'name': '%s-%s-%s' % ('P', order_id.name, i), - 'model_long': item['model_long'] + embryo_redundancy_id.long, - 'model_width': item['model_width'] + embryo_redundancy_id.width, - 'model_height': item['model_height'] + embryo_redundancy_id.height, - 'model_volume': (item['model_long'] + embryo_redundancy_id.long) * ( + 'model_long': self.format_float(item['model_long'] + embryo_redundancy_id.long), + 'model_width': self.format_float(item['model_width'] + embryo_redundancy_id.width), + 'model_height': self.format_float(item['model_height'] + embryo_redundancy_id.height), + 'model_volume': self.format_float((item['model_long'] + embryo_redundancy_id.long) * ( item['model_width'] + embryo_redundancy_id.width) * ( - item['model_height'] + embryo_redundancy_id.height), + item['model_height'] + embryo_redundancy_id.height)), 'product_model_type_id': model_type.id, 'model_processing_panel': item['processing_panel_detail'], 'model_machining_precision': item['model_machining_precision'], @@ -907,6 +907,20 @@ class ResProductMo(models.Model): self.attachment_update(item['quality_standard_name'], copy_product_id.product_tmpl_id.id, 'quality_standard', item['quality_standard_mimetype']) return copy_product_id + + def format_float(self, value): + # 将浮点数转换为字符串 + value_str = str(value) + # 检查小数点的位置 + if '.' in value_str: + # 获取小数部分 + decimal_part = value_str.split('.')[1] + # 判断小数位数是否超过2位 + if len(decimal_part) > 2: + # 超过2位则保留2位小数 + return "{:.2f}".format(value) + # 否则保持原来的位数 + return float(value_str) def _get_ids(self, param): type_ids = [] diff --git a/sf_plan/models/custom_plan.py b/sf_plan/models/custom_plan.py index 147caa96..6ee1d3ee 100644 --- a/sf_plan/models/custom_plan.py +++ b/sf_plan/models/custom_plan.py @@ -242,10 +242,10 @@ class sf_production_plan(models.Model): # 设置一个小的开始时间 first_cnc_workorder.date_planned_start = datetime.now() - timedelta(days=100) first_cnc_workorder.date_planned_finished = date_start + timedelta( - minutes=routing_workcenter.time_cycle) + minutes=routing_workcenter.time_cycle + routing_workcenter.reserved_duration) first_cnc_workorder.date_planned_start = date_start record.sudo().production_id.plan_start_processing_time = first_cnc_workorder.date_planned_start - first_cnc_workorder.duration_expected = routing_workcenter.time_cycle + first_cnc_workorder.duration_expected = routing_workcenter.time_cycle + routing_workcenter.reserved_duration record.calculate_plan_time(first_cnc_workorder, record.production_id.workorder_ids) # 找到最后一张CNC加工工单 last_cnc_workorder = record.production_id.workorder_ids.filtered(lambda x: x.name == 'CNC加工')[-1] @@ -257,10 +257,10 @@ class sf_production_plan(models.Model): routing_workcenter = item.technology_design_id.route_id item.date_planned_start = datetime.now() - timedelta(days=100) item.date_planned_finished = wo_start + timedelta( - minutes=routing_workcenter.time_cycle) + minutes=routing_workcenter.time_cycle + routing_workcenter.reserved_duration) item.date_planned_start = wo_start record.sudo().production_id.plan_start_processing_time = item.date_planned_start - item.duration_expected = routing_workcenter.time_cycle + item.duration_expected = routing_workcenter.time_cycle + routing_workcenter.reserved_duration record.calculate_plan_time(item, record.production_id.workorder_ids) last_cnc_workorder = record.production_id.workorder_ids[-1] record.date_planned_finished = last_cnc_workorder.date_planned_finished @@ -338,8 +338,8 @@ class sf_production_plan(models.Model): next_workorder.date_planned_start = datetime.now() - timedelta(days=100) next_workorder.date_planned_finished = current_workorder.date_planned_start next_workorder.date_planned_start = next_workorder.date_planned_finished - timedelta( - minutes=routing_workcenter.time_cycle) - next_workorder.duration_expected = routing_workcenter.time_cycle + minutes=routing_workcenter.time_cycle + routing_workcenter.reserved_duration) + next_workorder.duration_expected = routing_workcenter.time_cycle + routing_workcenter.reserved_duration for i in range(item_position, len(workorder_list) - 1): if i > len(workorder_list) - 1: @@ -350,9 +350,9 @@ class sf_production_plan(models.Model): # 设置一个小的开始时间 next_workorder.date_planned_start = datetime.now() - timedelta(days=100) next_workorder.date_planned_finished = current_workorder.date_planned_finished + timedelta( - minutes=routing_workcenter.time_cycle) + minutes=routing_workcenter.time_cycle + routing_workcenter.reserved_duration) next_workorder.date_planned_start = current_workorder.date_planned_finished - next_workorder.duration_expected = routing_workcenter.time_cycle + next_workorder.duration_expected = routing_workcenter.time_cycle + routing_workcenter.reserved_duration def calculate_plan_time_after(self, item, workorder_id_list): """ From db8bd659c3762e341657871fbe5ae4ca23dc2a6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Fri, 29 Nov 2024 09:45:06 +0800 Subject: [PATCH 24/63] =?UTF-8?q?=E5=A4=84=E7=90=86=E5=B7=A5=E5=8D=95?= =?UTF-8?q?=E4=B8=AD=E7=9A=84=E5=B7=A5=E8=89=BA=E5=A4=96=E5=8D=8F=E6=8C=89?= =?UTF-8?q?=E9=92=AE=E7=82=B9=E5=87=BB=E6=8A=A5=E9=94=99=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/views/stock_picking_view.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sf_manufacturing/views/stock_picking_view.xml b/sf_manufacturing/views/stock_picking_view.xml index 2fae1fac..30264f89 100644 --- a/sf_manufacturing/views/stock_picking_view.xml +++ b/sf_manufacturing/views/stock_picking_view.xml @@ -51,5 +51,10 @@ + + + + \ No newline at end of file From a7dc3a122700e854cf155a4226f065a4ddb6fee7 Mon Sep 17 00:00:00 2001 From: "jinling.yang" Date: Fri, 29 Nov 2024 10:03:44 +0800 Subject: [PATCH 25/63] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=A1=A8=E9=9D=A2?= =?UTF-8?q?=E5=A4=96=E5=8D=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/product_template.py | 4 ++-- .../wizard/production_technology_re_adjust_wizard.py | 1 + sf_sale/models/quick_easy_order.py | 4 ++-- sf_sale/models/quick_easy_order_old.py | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/sf_manufacturing/models/product_template.py b/sf_manufacturing/models/product_template.py index fd0168fb..6e211f09 100644 --- a/sf_manufacturing/models/product_template.py +++ b/sf_manufacturing/models/product_template.py @@ -9,8 +9,8 @@ from odoo.exceptions import ValidationError, UserError from odoo.modules import get_resource_path -# from OCC.Extend.DataExchange import read_step_file -# from OCC.Extend.DataExchange import write_stl_file +from OCC.Extend.DataExchange import read_step_file +from OCC.Extend.DataExchange import write_stl_file class ResProductMo(models.Model): diff --git a/sf_manufacturing/wizard/production_technology_re_adjust_wizard.py b/sf_manufacturing/wizard/production_technology_re_adjust_wizard.py index 6d7e438f..80a02b2b 100644 --- a/sf_manufacturing/wizard/production_technology_re_adjust_wizard.py +++ b/sf_manufacturing/wizard/production_technology_re_adjust_wizard.py @@ -104,6 +104,7 @@ class ProductionTechnologyReAdjustWizard(models.TransientModel): self.env['mrp.workorder'].json_workorder_str(special.production_id, special)) special.production_id.write({'workorder_ids': workorders_values}) else: + logging.info(workorder.blocked_by_workorder_ids) if len(workorder.blocked_by_workorder_ids) > 1: if workorder.sequence == 1: workorder.blocked_by_workorder_ids = None diff --git a/sf_sale/models/quick_easy_order.py b/sf_sale/models/quick_easy_order.py index cb1886a1..081807a4 100644 --- a/sf_sale/models/quick_easy_order.py +++ b/sf_sale/models/quick_easy_order.py @@ -8,8 +8,8 @@ from datetime import datetime import requests from odoo import http from odoo.http import request -# from OCC.Extend.DataExchange import read_step_file -# from OCC.Extend.DataExchange import write_stl_file +from OCC.Extend.DataExchange import read_step_file +from OCC.Extend.DataExchange import write_stl_file from odoo import models, fields, api from odoo.modules import get_resource_path from odoo.exceptions import ValidationError, UserError diff --git a/sf_sale/models/quick_easy_order_old.py b/sf_sale/models/quick_easy_order_old.py index d963d021..87848e3a 100644 --- a/sf_sale/models/quick_easy_order_old.py +++ b/sf_sale/models/quick_easy_order_old.py @@ -5,8 +5,8 @@ import requests import os from datetime import datetime # from OCC.Core.GProp import GProp_GProps -# from OCC.Extend.DataExchange import read_step_file -# from OCC.Extend.DataExchange import write_stl_file +from OCC.Extend.DataExchange import read_step_file +from OCC.Extend.DataExchange import write_stl_file from odoo.addons.sf_base.commons.common import Common from odoo import models, fields, api from odoo.modules import get_resource_path From 9955157dd3dbdf016d6d72cbea82914fdee79c6e Mon Sep 17 00:00:00 2001 From: "jinling.yang" Date: Fri, 29 Nov 2024 10:07:17 +0800 Subject: [PATCH 26/63] =?UTF-8?q?=E8=BF=98=E5=8E=9F=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_workorder.py | 40 ++++++------ sf_mrs_connect/controllers/controllers.py | 76 +++++++++++------------ 2 files changed, 58 insertions(+), 58 deletions(-) diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index d4d97a2e..7bd9d1c8 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -1203,21 +1203,21 @@ class ResMrpWorkOrder(models.Model): if self.sequence == 1: # 判断工单状态是否为等待组件 - # if self.state == 'waiting': - # raise UserError('制造订单【%s】缺少组件信息!' % self.production_id.name) - # # 判断是否有坯料的序列号信息 - # boolean = False - # if self.production_id.move_raw_ids: - # if self.production_id.move_raw_ids[0].product_id.categ_type == '坯料': - # if self.production_id.move_raw_ids[0].move_line_ids: - # if self.production_id.move_raw_ids[0].move_line_ids: - # if self.production_id.move_raw_ids[0].move_line_ids[0].lot_id.name: - # boolean = True - # else: - # boolean = True - # if not boolean: - # raise UserError('制造订单【%s】缺少组件的序列号信息!' % self.production_id.name) - # self.pro_code = self.production_id.move_raw_ids[0].move_line_ids[0].lot_id.name + if self.state == 'waiting': + raise UserError('制造订单【%s】缺少组件信息!' % self.production_id.name) + # 判断是否有坯料的序列号信息 + boolean = False + if self.production_id.move_raw_ids: + if self.production_id.move_raw_ids[0].product_id.categ_type == '坯料': + if self.production_id.move_raw_ids[0].move_line_ids: + if self.production_id.move_raw_ids[0].move_line_ids: + if self.production_id.move_raw_ids[0].move_line_ids[0].lot_id.name: + boolean = True + else: + boolean = True + if not boolean: + raise UserError('制造订单【%s】缺少组件的序列号信息!' % self.production_id.name) + self.pro_code = self.production_id.move_raw_ids[0].move_line_ids[0].lot_id.name # cnc校验 if self.production_id.production_type == '自动化产线加工': cnc_workorder = self.search( @@ -1318,11 +1318,11 @@ class ResMrpWorkOrder(models.Model): def button_finish(self): for record in self: if record.routing_type == '装夹预调': - # if not record.rfid_code and record.is_rework is False: - # raise UserError("请扫RFID码进行绑定") - # if record.is_rework is False: - # if not record.material_center_point: - # raise UserError("坯料中心点为空,请检查") + if not record.rfid_code and record.is_rework is False: + raise UserError("请扫RFID码进行绑定") + if record.is_rework is False: + if not record.material_center_point: + raise UserError("坯料中心点为空,请检查") # if record.X_deviation_angle <= 0: # raise UserError("X偏差角度小于等于0,请检查!本次计算的X偏差角度为:%s" % record.X_deviation_angle) record.process_state = '待加工' diff --git a/sf_mrs_connect/controllers/controllers.py b/sf_mrs_connect/controllers/controllers.py index a5f76710..87aee0dd 100644 --- a/sf_mrs_connect/controllers/controllers.py +++ b/sf_mrs_connect/controllers/controllers.py @@ -40,21 +40,21 @@ class Sf_Mrs_Connect(http.Controller, MultiInheritController): return json.JSONEncoder().encode(res) if productions: # 拉取所有加工面的程序文件 - # for r in ret['processing_panel'].split(','): - # program_path_tmp_r = os.path.join('/tmp', ret['folder_name'], 'return', r) - # if os.path.exists(program_path_tmp_r): - # files_r = os.listdir(program_path_tmp_r) - # if files_r: - # for file_name in files_r: - # file_path = os.path.join(program_path_tmp_r, file_name) - # os.remove(file_path) - # download_state = request.env['sf.cnc.processing'].with_user( - # request.env.ref("base.user_admin")).download_file_tmp( - # ret['folder_name'], r) - # if download_state is False: - # res['status'] = -2 - # res['message'] = '编程单号为%s的CNC程序文件从FTP拉取失败' % (ret['programming_no']) - # return json.JSONEncoder().encode(res) + for r in ret['processing_panel'].split(','): + program_path_tmp_r = os.path.join('/tmp', ret['folder_name'], 'return', r) + if os.path.exists(program_path_tmp_r): + files_r = os.listdir(program_path_tmp_r) + if files_r: + for file_name in files_r: + file_path = os.path.join(program_path_tmp_r, file_name) + os.remove(file_path) + download_state = request.env['sf.cnc.processing'].with_user( + request.env.ref("base.user_admin")).download_file_tmp( + ret['folder_name'], r) + if download_state is False: + res['status'] = -2 + res['message'] = '编程单号为%s的CNC程序文件从FTP拉取失败' % (ret['programming_no']) + return json.JSONEncoder().encode(res) for production in productions: production.write({'programming_state': '已编程', 'work_state': '已编程'}) for panel in ret['processing_panel'].split(','): @@ -72,29 +72,29 @@ class Sf_Mrs_Connect(http.Controller, MultiInheritController): cnc_workorder_has.write( {'cnc_ids': cnc_workorder_has.cnc_ids.sudo()._json_cnc_processing(panel, ret), 'cmm_ids': cnc_workorder_has.cmm_ids.sudo()._json_cmm_program(panel, ret)}) - # for panel in ret['processing_panel'].split(','): - # # 查询状态为进行中且工序类型为CNC加工的工单 - # cnc_workorder = productions.workorder_ids.filtered( - # lambda ac: ac.routing_type == 'CNC加工' and ac.state not in ['progress', 'done', 'rework' - # 'cancel'] and ac.processing_panel == panel) - # if cnc_workorder: - # # program_path_tmp_panel = os.path.join('C://Users//43484//Desktop//fsdownload//test', - # # panel) - # program_path_tmp_panel = os.path.join('/tmp', ret['folder_name'], 'return', panel) - # files_panel = os.listdir(program_path_tmp_panel) - # if files_panel: - # for file in files_panel: - # file_extension = os.path.splitext(file)[1] - # if file_extension.lower() == '.pdf': - # panel_file_path = os.path.join(program_path_tmp_panel, file) - # logging.info('panel_file_path:%s' % panel_file_path) - # cnc_workorder.write({'cnc_worksheet': base64.b64encode(open(panel_file_path, 'rb').read())}) - # pre_workorder = productions.workorder_ids.filtered( - # lambda ap: ap.routing_type == '装夹预调' and ap.state not in ['done', 'rework' - # 'cancel'] and ap.processing_panel == panel) - # if pre_workorder: - # pre_workorder.write( - # {'processing_drawing': base64.b64encode(open(panel_file_path, 'rb').read())}) + for panel in ret['processing_panel'].split(','): + # 查询状态为进行中且工序类型为CNC加工的工单 + cnc_workorder = productions.workorder_ids.filtered( + lambda ac: ac.routing_type == 'CNC加工' and ac.state not in ['progress', 'done', 'rework' + 'cancel'] and ac.processing_panel == panel) + if cnc_workorder: + # program_path_tmp_panel = os.path.join('C://Users//43484//Desktop//fsdownload//test', + # panel) + program_path_tmp_panel = os.path.join('/tmp', ret['folder_name'], 'return', panel) + files_panel = os.listdir(program_path_tmp_panel) + if files_panel: + for file in files_panel: + file_extension = os.path.splitext(file)[1] + if file_extension.lower() == '.pdf': + panel_file_path = os.path.join(program_path_tmp_panel, file) + logging.info('panel_file_path:%s' % panel_file_path) + cnc_workorder.write({'cnc_worksheet': base64.b64encode(open(panel_file_path, 'rb').read())}) + pre_workorder = productions.workorder_ids.filtered( + lambda ap: ap.routing_type == '装夹预调' and ap.state not in ['done', 'rework' + 'cancel'] and ap.processing_panel == panel) + if pre_workorder: + pre_workorder.write( + {'processing_drawing': base64.b64encode(open(panel_file_path, 'rb').read())}) productions.write({'programming_state': '已编程', 'work_state': '已编程'}) logging.info('已更新制造订单编程状态:%s' % productions.ids) res.update({ From a927d0e9cbbd8eb0aba82323465f760de71a92f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Fri, 29 Nov 2024 10:44:48 +0800 Subject: [PATCH 27/63] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E5=8D=95=E4=B8=AA?= =?UTF-8?q?=E5=88=B6=E9=80=A0=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jikimo_sale_multiple_supply_methods/models/sale_order.py | 2 ++ sf_manufacturing/models/product_template.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/jikimo_sale_multiple_supply_methods/models/sale_order.py b/jikimo_sale_multiple_supply_methods/models/sale_order.py index b7e25835..a56721a2 100644 --- a/jikimo_sale_multiple_supply_methods/models/sale_order.py +++ b/jikimo_sale_multiple_supply_methods/models/sale_order.py @@ -43,6 +43,8 @@ class SaleOrder(models.Model): # 复制成品模板上的属性 line.product_id.product_tmpl_id.copy_template(product_template_id) + # 将模板上的single_manufacturing属性复制到成品上 + line.product_id.single_manufacturing = product_template_id.single_manufacturing order_id = self product = line.product_id diff --git a/sf_manufacturing/models/product_template.py b/sf_manufacturing/models/product_template.py index fb6f92ce..460fd994 100644 --- a/sf_manufacturing/models/product_template.py +++ b/sf_manufacturing/models/product_template.py @@ -884,7 +884,7 @@ class ResProductMo(models.Model): 'model_process_parameters_ids': [(6, 0, [])] if not item.get( 'process_parameters_code') else self.get_process_parameters_id(item['process_parameters_code']), 'model_remark': item['remark'], - 'single_manufacturing': False, + 'single_manufacturing': True, 'default_code': '%s-%s' % (order_number, i), 'manual_quotation': item['manual_quotation'] or False, 'part_number': item.get('part_number') or '', From 22a69df31beccba24610ec5faefa84c7fd36fb49 Mon Sep 17 00:00:00 2001 From: mgw <1392924357@qq.com> Date: Fri, 29 Nov 2024 11:24:27 +0800 Subject: [PATCH 28/63] =?UTF-8?q?=E8=B0=83=E6=95=B4=E8=AE=A1=E5=88=92?= =?UTF-8?q?=E8=B0=83=E5=BA=A6=E5=B2=97=E5=AF=B9=E5=B7=A5=E5=8D=95=E7=9A=84?= =?UTF-8?q?=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/security/ir.model.access.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sf_manufacturing/security/ir.model.access.csv b/sf_manufacturing/security/ir.model.access.csv index cdf62571..32d0f971 100644 --- a/sf_manufacturing/security/ir.model.access.csv +++ b/sf_manufacturing/security/ir.model.access.csv @@ -117,7 +117,7 @@ access_mrp_production_group_quality,mrp_production,model_mrp_production,sf_base. access_mrp_production_group_quality_director,mrp_production,model_mrp_production,sf_base.group_quality_director,1,1,0,0 access_mrp_workorder_group_quality,mrp_workorder,model_mrp_workorder,sf_base.group_quality,1,1,0,0 access_mrp_workorder_group_quality_director,mrp_workorder,model_mrp_workorder,sf_base.group_quality_director,1,1,0,0 -access_mrp_workorder,mrp_workorder,model_mrp_workorder,sf_base.group_plan_dispatch,1,1,0,0 +access_mrp_workorder,mrp_workorder,model_mrp_workorder,sf_base.group_plan_dispatch,1,1,1,0 access_sf_production_line_group_plan_dispatch,sf.production.line,model_sf_production_line,sf_base.group_plan_dispatch,1,0,0,0 access_sf_production_line_group_plan_director,sf.production.line,model_sf_production_line,sf_base.group_plan_director,1,1,1,0 access_sf_production_line,sf.production.line,model_sf_production_line,sf_maintenance.sf_group_equipment_user,1,1,1,0 From 6690d3f2cbe659cbb263318f3859220768af59f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Fri, 29 Nov 2024 14:14:14 +0800 Subject: [PATCH 29/63] =?UTF-8?q?=E6=9D=83=E9=99=90=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/security/ir.model.access.csv | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sf_manufacturing/security/ir.model.access.csv b/sf_manufacturing/security/ir.model.access.csv index 32d0f971..2880e662 100644 --- a/sf_manufacturing/security/ir.model.access.csv +++ b/sf_manufacturing/security/ir.model.access.csv @@ -167,10 +167,12 @@ access_sf_agv_scheduling_group_sf_mrp_manager,sf_agv_scheduling_group_sf_mrp_man access_sf_agv_scheduling_group_sf_equipment_user,sf_agv_scheduling_group_sf_equipment_user,model_sf_agv_scheduling,sf_base.group_sf_equipment_user,1,1,1,0 access_sf_technology_design_group_plan_dispatch,sf_technology_design_group_plan_dispatch,model_sf_technology_design,sf_base.group_plan_dispatch,1,1,1,0 -access_sf_technology_design_group_sf_mrp_manager,sf_technology_design_group_sf_mrp_manager,model_sf_technology_design,sf_base.group_sf_mrp_manager,1,1,1,0 +access_sf_technology_design_group_sf_mrp_manager,sf_technology_design_group_sf_mrp_manager,model_sf_technology_design,sf_base.group_sf_mrp_manager,1,0,0,0 access_sf_technology_design_group_production_engineer,sf_technology_design_group_production_engineer,model_sf_technology_design,sf_base.group_production_engineer,1,1,1,0 +access_sf_technology_design_group_sf_equipment_user,sf_technology_design_group_sf_equipment_user,model_sf_technology_design,sf_base.group_sf_equipment_user,1,0,0,0 +access_sf_technology_design_group_sf_order_user,sf_technology_design_group_sf_order_user,model_sf_technology_design,sf_base.group_sf_order_user,1,0,0,0 access_sf_production_technology_wizard_group_plan_dispatch,sf_production_technology_wizard_group_plan_dispatch,model_sf_production_technology_wizard,sf_base.group_plan_dispatch,1,1,1,0 -access_sf_production_technology_wizard_group_sf_mrp_manager,sf_production_technology_wizard_group_sf_mrp_manager,model_sf_production_technology_wizard,sf_base.group_sf_mrp_manager,1,1,1,0 +access_sf_production_technology_wizard_group_sf_mrp_manager,sf_production_technology_wizard_group_sf_mrp_manager,model_sf_production_technology_wizard,sf_base.group_sf_mrp_manager,1,0,0,0 access_sf_production_technology_wizard_group_production_engineer,sf_production_technology_wizard_group_production_engineer,model_sf_production_technology_wizard,sf_base.group_production_engineer,1,1,1,0 access_sf_production_technology_re_adjust_wizard_group_plan_dispatch,sf_production_technology_re_adjust_wizard_group_plan_dispatch,model_sf_production_technology_re_adjust_wizard,sf_base.group_plan_dispatch,1,1,1,0 access_sf_production_technology_re_adjust_wizard_group_sf_mrp_manager,sf_production_technology_re_adjust_wizard_group_sf_mrp_manager,model_sf_production_technology_re_adjust_wizard,sf_base.group_sf_mrp_manager,1,1,1,0 From a783f9c271c150f0f47fca78243f8d733528d27f Mon Sep 17 00:00:00 2001 From: mgw <1392924357@qq.com> Date: Fri, 29 Nov 2024 14:32:58 +0800 Subject: [PATCH 30/63] =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=86=85=E9=83=A8?= =?UTF-8?q?=E8=BD=AC=E8=B4=A6=E7=BF=BB=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_plan_management/i18n/zh_CN.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sf_plan_management/i18n/zh_CN.po b/sf_plan_management/i18n/zh_CN.po index 20b7f9f3..8863c213 100644 --- a/sf_plan_management/i18n/zh_CN.po +++ b/sf_plan_management/i18n/zh_CN.po @@ -15907,7 +15907,7 @@ msgstr "内部参考" #: model_terms:ir.ui.view,arch_db:account.account_journal_dashboard_kanban_view #, python-format msgid "Internal Transfer" -msgstr "内部转账" +msgstr "厂内出入库" #. module: account #: model:ir.model.fields,field_description:account.field_res_config_settings__transfer_account_id From 8d461e61b378510d360926fff0da3147aacc16ee Mon Sep 17 00:00:00 2001 From: hy <123@qq.com> Date: Fri, 29 Nov 2024 14:37:48 +0800 Subject: [PATCH 31/63] =?UTF-8?q?=E7=94=98=E7=89=B9=E5=9B=BE=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web_gantt/static/src/js/gantt_row.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web_gantt/static/src/js/gantt_row.js b/web_gantt/static/src/js/gantt_row.js index fb7ffab7..cae52879 100644 --- a/web_gantt/static/src/js/gantt_row.js +++ b/web_gantt/static/src/js/gantt_row.js @@ -602,7 +602,7 @@ var GanttRow = Widget.extend({ // pill._color = self._getColor(pill[self.colorField]); // 设置pill背景颜色2 修改时间2024年6月25日17:09:43 let isDelay = false - if(pill.state != 'processing' && pill.state != 'finished') { // 判断待加工 + if(pill.state != 'processing' && pill.state != 'finished' && pill.order_deadline) { // 判断待加工 isDelay = pill.order_deadline.isBefore(new Date()) } if(isDelay) { From 1f1bdd08ed8fad993c8b2c7f82a05d20bf062b1e Mon Sep 17 00:00:00 2001 From: mgw <1392924357@qq.com> Date: Fri, 29 Nov 2024 15:59:04 +0800 Subject: [PATCH 32/63] =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=BA=93=E5=AD=98?= =?UTF-8?q?=E6=A6=82=E8=A7=88=E7=BF=BB=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_plan_management/i18n/zh_CN.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sf_plan_management/i18n/zh_CN.po b/sf_plan_management/i18n/zh_CN.po index 8863c213..91b32d41 100644 --- a/sf_plan_management/i18n/zh_CN.po +++ b/sf_plan_management/i18n/zh_CN.po @@ -16133,7 +16133,7 @@ msgstr "库存概览" #. module: stock #: model:ir.actions.act_window,name:stock.stock_picking_type_action msgid "Internal Transfers" -msgstr "厂内出入库" +msgstr "库存概览" #. module: stock #: model:ir.model.fields,field_description:stock.field_stock_quant__inventory_quantity_set From dc68ecb58439cd47f8bd27a19678f18fa36bfc2d Mon Sep 17 00:00:00 2001 From: hy <123@qq.com> Date: Fri, 29 Nov 2024 16:26:32 +0800 Subject: [PATCH 33/63] =?UTF-8?q?=E8=AE=A1=E5=88=92=E6=8E=92=E7=A8=8B?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E5=92=8C=E5=B7=A5=E5=8D=95=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E7=AD=9B=E9=80=89=E9=A1=B9=E5=92=8C=E6=95=B0=E9=87=8F=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E9=87=8D=E5=8F=A0=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jikimo_frontend/static/src/scss/custom_style.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/jikimo_frontend/static/src/scss/custom_style.scss b/jikimo_frontend/static/src/scss/custom_style.scss index 8eb76259..6904dbac 100644 --- a/jikimo_frontend/static/src/scss/custom_style.scss +++ b/jikimo_frontend/static/src/scss/custom_style.scss @@ -536,3 +536,7 @@ div:has(.o_required_modifier) > label::before { position: unset; } +// 修复搜索面板checkbox样式 +.o_search_panel .form-check .form-check-label span { + position: relative; +} \ No newline at end of file From 4baa7a9b445b9d86f06f1e96b9d56e73e445f354 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Mon, 2 Dec 2024 10:06:11 +0800 Subject: [PATCH 34/63] =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E7=BB=93=E6=9E=84=EF=BC=8C=E8=A7=A3=E5=86=B3=E4=BE=9D=E8=B5=96?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jikimo_sale_multiple_supply_methods/controllers/__init__.py | 1 - jikimo_sale_multiple_supply_methods/models/__init__.py | 1 - sf_manufacturing/controllers/__init__.py | 1 + .../controllers/main.py | 0 sf_manufacturing/models/__init__.py | 2 ++ .../models/quick_easy_order.py | 0 .../models/sale_order.py | 0 7 files changed, 3 insertions(+), 2 deletions(-) rename {jikimo_sale_multiple_supply_methods => sf_manufacturing}/controllers/main.py (100%) rename {jikimo_sale_multiple_supply_methods => sf_manufacturing}/models/quick_easy_order.py (100%) rename {jikimo_sale_multiple_supply_methods => sf_manufacturing}/models/sale_order.py (100%) diff --git a/jikimo_sale_multiple_supply_methods/controllers/__init__.py b/jikimo_sale_multiple_supply_methods/controllers/__init__.py index cd4d6a8b..40a96afc 100644 --- a/jikimo_sale_multiple_supply_methods/controllers/__init__.py +++ b/jikimo_sale_multiple_supply_methods/controllers/__init__.py @@ -1,2 +1 @@ # -*- coding: utf-8 -*- -from . import main \ No newline at end of file diff --git a/jikimo_sale_multiple_supply_methods/models/__init__.py b/jikimo_sale_multiple_supply_methods/models/__init__.py index 6629e86d..0674dbe8 100644 --- a/jikimo_sale_multiple_supply_methods/models/__init__.py +++ b/jikimo_sale_multiple_supply_methods/models/__init__.py @@ -1,4 +1,3 @@ # -*- coding: utf-8 -*- from . import product_template -from . import sale_order from . import mrp_bom diff --git a/sf_manufacturing/controllers/__init__.py b/sf_manufacturing/controllers/__init__.py index 4d20cb33..4b95e252 100644 --- a/sf_manufacturing/controllers/__init__.py +++ b/sf_manufacturing/controllers/__init__.py @@ -1,2 +1,3 @@ from . import controllers from . import workpiece +from . import main diff --git a/jikimo_sale_multiple_supply_methods/controllers/main.py b/sf_manufacturing/controllers/main.py similarity index 100% rename from jikimo_sale_multiple_supply_methods/controllers/main.py rename to sf_manufacturing/controllers/main.py diff --git a/sf_manufacturing/models/__init__.py b/sf_manufacturing/models/__init__.py index b0c295f5..9f77d841 100644 --- a/sf_manufacturing/models/__init__.py +++ b/sf_manufacturing/models/__init__.py @@ -13,3 +13,5 @@ from . import agv_scheduling from . import res_config_setting from . import sf_technology_design from . import sf_production_common +from . import sale_order +from . import quick_easy_order diff --git a/jikimo_sale_multiple_supply_methods/models/quick_easy_order.py b/sf_manufacturing/models/quick_easy_order.py similarity index 100% rename from jikimo_sale_multiple_supply_methods/models/quick_easy_order.py rename to sf_manufacturing/models/quick_easy_order.py diff --git a/jikimo_sale_multiple_supply_methods/models/sale_order.py b/sf_manufacturing/models/sale_order.py similarity index 100% rename from jikimo_sale_multiple_supply_methods/models/sale_order.py rename to sf_manufacturing/models/sale_order.py From 7c13e57ea2318dcd12f6674b7f96de6da0ca9659 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Mon, 2 Dec 2024 10:36:06 +0800 Subject: [PATCH 35/63] =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jikimo_sale_multiple_supply_methods/__manifest__.py | 1 - sf_manufacturing/__manifest__.py | 1 + .../views/sale_order_views.xml | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename {jikimo_sale_multiple_supply_methods => sf_manufacturing}/views/sale_order_views.xml (100%) diff --git a/jikimo_sale_multiple_supply_methods/__manifest__.py b/jikimo_sale_multiple_supply_methods/__manifest__.py index a7d39ac7..735593cb 100644 --- a/jikimo_sale_multiple_supply_methods/__manifest__.py +++ b/jikimo_sale_multiple_supply_methods/__manifest__.py @@ -11,7 +11,6 @@ 'security/ir.model.access.csv', 'data/stock_routes.xml', 'data/product_data.xml', - 'views/sale_order_views.xml', # 'views/product_product_views.xml', ],'assets': { # 'web.assets_backend': [ diff --git a/sf_manufacturing/__manifest__.py b/sf_manufacturing/__manifest__.py index 35620913..991b26ab 100644 --- a/sf_manufacturing/__manifest__.py +++ b/sf_manufacturing/__manifest__.py @@ -37,6 +37,7 @@ 'views/agv_setting_views.xml', 'views/sf_maintenance_equipment.xml', 'views/res_config_settings_views.xml', + 'views/sale_order_views.xml', ], 'assets': { diff --git a/jikimo_sale_multiple_supply_methods/views/sale_order_views.xml b/sf_manufacturing/views/sale_order_views.xml similarity index 100% rename from jikimo_sale_multiple_supply_methods/views/sale_order_views.xml rename to sf_manufacturing/views/sale_order_views.xml From 5406224c6fe77468defb217232a9ab7569ec8d7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Mon, 2 Dec 2024 11:02:32 +0800 Subject: [PATCH 36/63] =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/views/sale_order_views.xml | 12 ------------ sf_stock/__manifest__.py | 3 ++- sf_stock/views/sale_order_view.xml | 14 ++++++++++++++ 3 files changed, 16 insertions(+), 13 deletions(-) create mode 100644 sf_stock/views/sale_order_view.xml diff --git a/sf_manufacturing/views/sale_order_views.xml b/sf_manufacturing/views/sale_order_views.xml index 8b1a85d0..5de69b64 100644 --- a/sf_manufacturing/views/sale_order_views.xml +++ b/sf_manufacturing/views/sale_order_views.xml @@ -1,17 +1,5 @@ - - view.sale.order.form.inherit.sf - - sale.order - - - - - - - - view.sale.order.form.inherit.supply.method diff --git a/sf_stock/__manifest__.py b/sf_stock/__manifest__.py index 1b5f44c4..574bccdc 100644 --- a/sf_stock/__manifest__.py +++ b/sf_stock/__manifest__.py @@ -25,7 +25,8 @@ 'data': [ # 'security/ir.model.access.csv', 'views/stock_picking.xml', - 'views/stock_product_template.xml' + 'views/stock_product_template.xml', + 'views/sale_order_view.xml', ], # only loaded in demonstration mode 'demo': [ diff --git a/sf_stock/views/sale_order_view.xml b/sf_stock/views/sale_order_view.xml new file mode 100644 index 00000000..81e9f7d8 --- /dev/null +++ b/sf_stock/views/sale_order_view.xml @@ -0,0 +1,14 @@ + + + + view.sale.order.form.inherit.sf + + sale.order + + + + + + + + \ No newline at end of file From 7025bde56e2bf7461b2bcdcea2ff072d99df342c Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Mon, 2 Dec 2024 13:46:20 +0800 Subject: [PATCH 37/63] =?UTF-8?q?=E9=9A=90=E8=97=8F=E6=89=8B=E5=8A=A8?= =?UTF-8?q?=E8=BF=94=E5=B7=A5=E6=8A=A5=E5=BA=9F=E5=85=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_workorder.py | 2 +- sf_manufacturing/views/mrp_workorder_view.xml | 2 +- sf_quality/models/quality_cnc_test.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index 7bd9d1c8..4ea08f94 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -126,7 +126,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/views/mrp_workorder_view.xml b/sf_manufacturing/views/mrp_workorder_view.xml index 13fff868..be1a6523 100644 --- a/sf_manufacturing/views/mrp_workorder_view.xml +++ b/sf_manufacturing/views/mrp_workorder_view.xml @@ -200,7 +200,7 @@ - Date: Mon, 2 Dec 2024 16:29:33 +0800 Subject: [PATCH 38/63] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jikimo_sale_multiple_supply_methods/__manifest__.py | 1 + .../views/sale_order_view.xml | 0 sf_stock/__manifest__.py | 1 - 3 files changed, 1 insertion(+), 1 deletion(-) rename {sf_stock => jikimo_sale_multiple_supply_methods}/views/sale_order_view.xml (100%) diff --git a/jikimo_sale_multiple_supply_methods/__manifest__.py b/jikimo_sale_multiple_supply_methods/__manifest__.py index 735593cb..e4b94ff4 100644 --- a/jikimo_sale_multiple_supply_methods/__manifest__.py +++ b/jikimo_sale_multiple_supply_methods/__manifest__.py @@ -11,6 +11,7 @@ 'security/ir.model.access.csv', 'data/stock_routes.xml', 'data/product_data.xml', + 'views/sale_order_view.xml', # 'views/product_product_views.xml', ],'assets': { # 'web.assets_backend': [ diff --git a/sf_stock/views/sale_order_view.xml b/jikimo_sale_multiple_supply_methods/views/sale_order_view.xml similarity index 100% rename from sf_stock/views/sale_order_view.xml rename to jikimo_sale_multiple_supply_methods/views/sale_order_view.xml diff --git a/sf_stock/__manifest__.py b/sf_stock/__manifest__.py index 574bccdc..0f1f72f6 100644 --- a/sf_stock/__manifest__.py +++ b/sf_stock/__manifest__.py @@ -26,7 +26,6 @@ # 'security/ir.model.access.csv', 'views/stock_picking.xml', 'views/stock_product_template.xml', - 'views/sale_order_view.xml', ], # only loaded in demonstration mode 'demo': [ From 5739e167f495c4e557d7d39ebcd1c7bc15001268 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Mon, 2 Dec 2024 19:46:45 +0800 Subject: [PATCH 39/63] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../__manifest__.py | 3 +-- .../views/sale_order_view.xml | 14 -------------- sf_manufacturing/views/sale_order_views.xml | 12 +++++++++++- 3 files changed, 12 insertions(+), 17 deletions(-) delete mode 100644 jikimo_sale_multiple_supply_methods/views/sale_order_view.xml diff --git a/jikimo_sale_multiple_supply_methods/__manifest__.py b/jikimo_sale_multiple_supply_methods/__manifest__.py index e4b94ff4..cfc56321 100644 --- a/jikimo_sale_multiple_supply_methods/__manifest__.py +++ b/jikimo_sale_multiple_supply_methods/__manifest__.py @@ -6,12 +6,11 @@ 'author': 'fox', 'website': '', 'category': '', - 'depends': ['sf_dlm', 'sale_stock', 'sf_sale'], + 'depends': ['sf_dlm', 'sale_stock', 'sf_sale', 'sale'], "data": [ 'security/ir.model.access.csv', 'data/stock_routes.xml', 'data/product_data.xml', - 'views/sale_order_view.xml', # 'views/product_product_views.xml', ],'assets': { # 'web.assets_backend': [ diff --git a/jikimo_sale_multiple_supply_methods/views/sale_order_view.xml b/jikimo_sale_multiple_supply_methods/views/sale_order_view.xml deleted file mode 100644 index 81e9f7d8..00000000 --- a/jikimo_sale_multiple_supply_methods/views/sale_order_view.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - view.sale.order.form.inherit.sf - - sale.order - - - - - - - - \ No newline at end of file diff --git a/sf_manufacturing/views/sale_order_views.xml b/sf_manufacturing/views/sale_order_views.xml index 5de69b64..ba26134d 100644 --- a/sf_manufacturing/views/sale_order_views.xml +++ b/sf_manufacturing/views/sale_order_views.xml @@ -91,6 +91,16 @@ - + + view.sale.order.form.inherit.jikimo + + sale.order + + + + + + + From fedb79a1424c2b7be1c28434d585a3b38a9c25dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Tue, 3 Dec 2024 10:03:05 +0800 Subject: [PATCH 40/63] =?UTF-8?q?=E5=8E=BB=E6=8E=89=E5=A4=9A=E4=BD=99?= =?UTF-8?q?=E7=9A=84=E8=A7=86=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/views/sale_order_views.xml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/sf_manufacturing/views/sale_order_views.xml b/sf_manufacturing/views/sale_order_views.xml index ba26134d..1e5c4587 100644 --- a/sf_manufacturing/views/sale_order_views.xml +++ b/sf_manufacturing/views/sale_order_views.xml @@ -90,17 +90,5 @@ - - - view.sale.order.form.inherit.jikimo - - sale.order - - - - - - - From d6afd556d3e62b08f99010a225e3b714d1331a24 Mon Sep 17 00:00:00 2001 From: guanhuan Date: Tue, 3 Dec 2024 15:59:10 +0800 Subject: [PATCH 41/63] =?UTF-8?q?=E8=AF=A2=E4=BB=B7=E5=8D=95=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_workorder.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index 4ea08f94..2f36ad79 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -283,7 +283,8 @@ class ResMrpWorkOrder(models.Model): # if technology_design.is_auto is False: # domain = [('origin', '=', order.production_id.name)] # else: - domain = [('purchase_type', '=', 'consignment'), ('origin', '=', order.production_id.name)] + domain = [('purchase_type', '=', 'consignment'), ('origin', '=', order.production_id.name), + ('state', '!=', 'cancel')] purchase = self.env['purchase.order'].search(domain) purchase_num = 0 if not purchase: @@ -313,7 +314,8 @@ class ResMrpWorkOrder(models.Model): # if technology_design.is_auto is False: # domain = [('origin', '=', self.production_id.name)] # else: - domain = [('origin', '=', self.production_id.name), ('purchase_type', '=', 'consignment')] + domain = [('origin', '=', self.production_id.name), ('purchase_type', '=', 'consignment'), + ('state', '!=', 'cancel')] purchase_orders = self.env['purchase.order'].search(domain) purchase_orders_id = None for po in purchase_orders: From 21af36806820348cd090f73d4f1fa930d1555fd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Wed, 4 Dec 2024 10:16:30 +0800 Subject: [PATCH 42/63] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E5=A4=96=E5=8D=8F?= =?UTF-8?q?=E8=B0=83=E6=8B=A8=E5=8D=95=E4=B8=8D=E8=83=BD=E5=AE=8C=E6=88=90?= =?UTF-8?q?=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/stock.py | 38 +++++++++++++++++++------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/sf_manufacturing/models/stock.py b/sf_manufacturing/models/stock.py index 0c01a57c..50c7e672 100644 --- a/sf_manufacturing/models/stock.py +++ b/sf_manufacturing/models/stock.py @@ -649,10 +649,10 @@ class StockPicking(models.Model): for mi in move_in: pick = self.env['stock.picking'].search([('id', '=', mi.picking_id.id), ('name', 'ilike', 'OCIN'), ('partner_id', '=', self.partner_id.id)]) - if pick: - if mi.state != 'done': - mi.write({'state': 'assigned'}) - self.env['stock.move.line'].create(mi.get_move_line(production, None)) + # if pick: + # if mi.state != 'done': + # mi.write({'state': 'assigned'}) + # self.env['stock.move.line'].create(mi.get_move_line(production, None)) return res @@ -671,6 +671,11 @@ class StockPicking(models.Model): if not sorted_workorders.picking_ids: # outcontract_stock_move = self.env['stock.move'].search([('production_id', '=', item.id)]) # if not outcontract_stock_move: + # 创建一个新的补货组 + procurement_group_id = self.env['procurement.group'].create({ + 'name': sorted_workorders.name, + 'partner_id': self.partner_id.id, + }) new_picking = True location_id = self.env['stock.location'].search( [('barcode', 'ilike', 'VL-SPOC')]).id, @@ -680,24 +685,25 @@ class StockPicking(models.Model): 'sf_manufacturing.outcontract_picking_in').id, outcontract_picking_type_out = self.env.ref( 'sf_manufacturing.outcontract_picking_out').id, - moves_out = self.env['stock.move'].sudo().create( - self.env['stock.move']._get_stock_move_values_Res(item, location_dest_id, location_id, - outcontract_picking_type_out)) - picking_out = self.create( - moves_out._get_new_picking_values_Res(item, sorted_workorders, 'WH/OCOUT/')) - # pick_ids.append(picking_out.id) - moves_out.write( - {'picking_id': picking_out.id, 'state': 'waiting'}) - moves_out._assign_picking_post_process(new=new_picking) moves_in = self.env['stock.move'].sudo().create( self.env['stock.move']._get_stock_move_values_Res(item, location_id, location_dest_id, - outcontract_picking_type_in)) + outcontract_picking_type_in, procurement_group_id.id)) picking_in = self.create( moves_in._get_new_picking_values_Res(item, sorted_workorders, 'WH/OCIN/')) # pick_ids.append(picking_in.id) moves_in.write( {'picking_id': picking_in.id, 'state': 'waiting'}) moves_in._assign_picking_post_process(new=new_picking) + moves_out = self.env['stock.move'].sudo().create( + self.env['stock.move']._get_stock_move_values_Res(item, location_dest_id, location_id, + outcontract_picking_type_out, procurement_group_id.id, moves_in.id)) + picking_out = self.create( + moves_out._get_new_picking_values_Res(item, sorted_workorders, 'WH/OCOUT/')) + # pick_ids.append(picking_out.id) + moves_out.write( + {'picking_id': picking_out.id, 'state': 'waiting'}) + moves_out._assign_picking_post_process(new=new_picking) + class ReStockMove(models.Model): @@ -707,7 +713,7 @@ class ReStockMove(models.Model): materiel_width = fields.Float(string='物料宽度', digits=(16, 4)) materiel_height = fields.Float(string='物料高度', digits=(16, 4)) - def _get_stock_move_values_Res(self, item, location_src_id, location_dest_id, picking_type_id): + def _get_stock_move_values_Res(self, item, location_src_id, location_dest_id, picking_type_id, group_id, move_dest_ids=False): route = self.env['stock.route'].sudo().search([('name', '=', '表面工艺外协')]) move_values = { 'name': '推', @@ -718,6 +724,8 @@ class ReStockMove(models.Model): 'location_id': location_src_id, 'location_dest_id': location_dest_id, 'origin': item.name, + 'group_id': group_id, + 'move_dest_ids': [(6, 0, [move_dest_ids])] if move_dest_ids else False, # 'route_ids': False if not route else [(4, route.id)], 'date_deadline': datetime.now(), 'picking_type_id': picking_type_id, From 4387d343b5ca89079c3422a9e87c196df98a6296 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Wed, 4 Dec 2024 10:22:50 +0800 Subject: [PATCH 43/63] =?UTF-8?q?=E5=A4=84=E7=90=86=E6=8A=A5=E9=94=99?= =?UTF-8?q?=E6=98=AF=E8=8B=B1=E6=96=87=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jikimo_hide_options/models/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jikimo_hide_options/models/models.py b/jikimo_hide_options/models/models.py index 8f30543c..6386192d 100644 --- a/jikimo_hide_options/models/models.py +++ b/jikimo_hide_options/models/models.py @@ -190,7 +190,7 @@ def _create(self, data_list): # 如果该用户组被限制创建或更新操作 if rec['is_create_or_update']: raise UserError( - _("You are restricted from performing this operation. Please contact the administrator.")) + _("您没有执行此操作的权限。请联系管理员")) else: # 如果 'access.right' 模型不存在,可以在这里定义备选逻辑 # 例如,记录日志、发送通知或者简单地跳过这部分逻辑 From 9a1cde6abcef47f36cfe2c795faa3dd63c796e88 Mon Sep 17 00:00:00 2001 From: liaodanlong Date: Wed, 4 Dec 2024 10:45:46 +0800 Subject: [PATCH 44/63] =?UTF-8?q?=E8=A1=A8=E9=9D=A2=E5=B7=A5=E8=89=BA?= =?UTF-8?q?=E9=87=87=E8=B4=AD=E5=8D=95=E4=B8=8E=E8=B0=83=E6=8B=A8=E5=8D=95?= =?UTF-8?q?=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 | 38 ++++------------------- sf_manufacturing/models/mrp_workorder.py | 14 ++++----- sf_sale/models/sale_order.py | 3 +- 3 files changed, 14 insertions(+), 41 deletions(-) diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py index 9156dc38..f24eb6b9 100644 --- a/sf_manufacturing/models/mrp_production.py +++ b/sf_manufacturing/models/mrp_production.py @@ -729,40 +729,14 @@ class MrpProduction(models.Model): sorted_workorders = sorted(process_parameter_workorder, key=lambda w: w.sequence) for i, workorder in enumerate(sorted_workorders): # 检查当前工作订单和下一个工作订单是否连续,并且供应商相同 - if i == 0: - consecutive_workorders.append(workorder) - elif workorder.sequence == sorted_workorders[ - i - 1].sequence + 1 and workorder.supplier_id.id == sorted_workorders[i - 1].supplier_id.id: - consecutive_workorders.append(workorder) - else: - # 处理连续组,如果它不为空 - if consecutive_workorders: - # 创建外协出入库单和采购订单 - self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production) - self.env['purchase.order'].get_purchase_order(consecutive_workorders, production, - product_id_to_production_names) - if i < len(sorted_workorders) - 1: - # 重置连续组,并添加当前工作订单 - consecutive_workorders = [workorder] - else: - # 判断最后一笔: - if workorder.sequence == sorted_workorders[ - i - 1].sequence and workorder.supplier_id.id == sorted_workorders[ - i - 1].supplier_id.id: - consecutive_workorders = [workorder] - else: - # 立即创建外协出入库单和采购订单 - self.env['stock.picking'].create_outcontract_picking(workorder, production) - self.env['purchase.order'].get_purchase_order(workorder, production, - product_id_to_production_names) - consecutive_workorders = [] - - # 处理最后一个组,即使它可能只有一个工作订单 - if consecutive_workorders: - self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production) - self.env['purchase.order'].get_purchase_order(consecutive_workorders, production, + if not workorder.picking_ids: + self.env['stock.picking'].create_outcontract_picking(workorder, production) + # if not workorder. + if not workorder.purchase_id: + self.env['purchase.order'].get_purchase_order(workorder, production, product_id_to_production_names) + # 工单排序 def _reset_work_order_sequence1(self, k): for rec in self: diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index 4ea08f94..a55523a0 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -135,7 +135,7 @@ class ResMrpWorkOrder(models.Model): is_subcontract = fields.Boolean(string='是否外协') surface_technics_parameters_id = fields.Many2one('sf.production.process.parameter', string="表面工艺可选参数") picking_ids = fields.Many2many('stock.picking', string='外协出入库单') - # purchase_id = fields.Many2one('purchase.order', string='外协采购单') + purchase_id = fields.Many2many('purchase.order', string='外协采购单') surface_technics_picking_count = fields.Integer("外协出入库", compute='_compute_surface_technics_picking_ids') surface_technics_purchase_count = fields.Integer("外协采购", compute='_compute_surface_technics_purchase_ids') @@ -239,13 +239,11 @@ class ResMrpWorkOrder(models.Model): previous_workorder = self.env['mrp.workorder'].search( [('sequence', '=', workorder.sequence - 1), ('routing_type', '=', '表面工艺'), ('production_id', '=', workorder.production_id.id)]) - if previous_workorder: - if previous_workorder.supplier_id != workorder.supplier_id: - # process_product = self.env['product.template']._get_process_parameters_product( - # previous_workorder.surface_technics_parameters_id) - domain += [('surface_technics_parameters_id', '=', workorder.surface_technics_parameters_id.id)] - else: - domain += [('surface_technics_parameters_id', '=', workorder.surface_technics_parameters_id.id)] + # if previous_workorder: + # if previous_workorder.supplier_id != workorder.supplier_id: + # domain += [('surface_technics_parameters_id', '=', workorder.surface_technics_parameters_id.id)] + # else: + domain += [('surface_technics_parameters_id', '=', workorder.surface_technics_parameters_id.id)] picking_ids = self.env['stock.picking'].search(domain, order='id asc') workorder.surface_technics_picking_count = len(picking_ids) workorder.picking_ids = picking_ids.ids diff --git a/sf_sale/models/sale_order.py b/sf_sale/models/sale_order.py index e225c274..3879860e 100644 --- a/sf_sale/models/sale_order.py +++ b/sf_sale/models/sale_order.py @@ -280,12 +280,13 @@ class RePurchaseOrder(models.Model): })) if server_product_process: - self.env['purchase.order'].sudo().create({ + purchase_order = self.env['purchase.order'].sudo().create({ 'partner_id': server_template.seller_ids[0].partner_id.id, 'origin': production.name, 'state': 'draft', 'purchase_type': 'consignment', 'order_line': server_product_process}) + consecutive_process_parameters.purchase_id = [(6, 0, [purchase_order.id])] # self.env.cr.commit() @api.onchange('order_line') From e260ef01f0788374b24eb82c8dd81ade7089112f Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Wed, 4 Dec 2024 11:43:02 +0800 Subject: [PATCH 45/63] =?UTF-8?q?=E9=9A=90=E8=97=8F=E9=94=80=E5=94=AE?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E7=9A=84=20=E5=BF=AB=E9=80=9F=E8=AE=A2?= =?UTF-8?q?=E5=8D=95=20=E8=8F=9C=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_sale/views/quick_easy_order_view.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sf_sale/views/quick_easy_order_view.xml b/sf_sale/views/quick_easy_order_view.xml index 3b386062..89792a49 100644 --- a/sf_sale/views/quick_easy_order_view.xml +++ b/sf_sale/views/quick_easy_order_view.xml @@ -128,9 +128,9 @@ - + + + + \ No newline at end of file From d933416b2d14ff4436a3812eb2d0b32b320886e4 Mon Sep 17 00:00:00 2001 From: mgw <1392924357@qq.com> Date: Wed, 4 Dec 2024 11:52:52 +0800 Subject: [PATCH 46/63] =?UTF-8?q?=E5=A4=84=E7=90=86=E2=80=9C=E5=88=B6?= =?UTF-8?q?=E9=80=A0=E8=AE=A2=E5=8D=95=E9=80=80=E5=9B=9E=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E7=89=B9=E6=AE=8A=E8=A1=A8=E9=9D=A2=E5=B7=A5?= =?UTF-8?q?=E8=89=BA=E5=90=8E=E5=AF=B9=E5=BA=94=E5=9D=AF=E6=96=99=E7=9A=84?= =?UTF-8?q?=E9=87=87=E8=B4=AD=E5=8D=95=E4=B9=9F=E5=8F=98=E6=88=90=E5=8F=96?= =?UTF-8?q?=E6=B6=88=E7=8A=B6=E6=80=81=E4=BA=86=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/wizard/production_technology_wizard.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sf_manufacturing/wizard/production_technology_wizard.py b/sf_manufacturing/wizard/production_technology_wizard.py index a02bb8f6..5fbdb7d7 100644 --- a/sf_manufacturing/wizard/production_technology_wizard.py +++ b/sf_manufacturing/wizard/production_technology_wizard.py @@ -80,7 +80,7 @@ class ProductionTechnologyWizard(models.TransientModel): workorder.picking_ids.write({'state': 'cancel'}) workorder.picking_ids.move_ids.write({'state': 'cancel'}) purchase_order = self.env['purchase.order'].search( - [('origin', '=', workorder.production_id.name)]) + [('origin', '=', workorder.production_id.name), ('purchase_type', '=', 'consignment')]) for line in purchase_order.order_line: if line.product_id.server_product_process_parameters_id == workorder.surface_technics_parameters_id: purchase_order.write({'state': 'cancel'}) From 5b43cceb94d8bd1669cc956760a7fd70b50f9620 Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Wed, 4 Dec 2024 11:56:38 +0800 Subject: [PATCH 47/63] =?UTF-8?q?=E8=AE=A1=E5=88=92=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E7=9A=84=E3=80=90=E5=88=B6=E9=80=A0=E8=AE=A2=E5=8D=95=E7=94=9F?= =?UTF-8?q?=E4=BA=A7=E8=AE=A1=E5=88=92=E3=80=91=E9=A1=B5=E9=9D=A2=E8=8F=9C?= =?UTF-8?q?=E5=8D=95=E5=90=8D=E7=A7=B0=E6=94=B9=E4=B8=BA=E3=80=90CNC?= =?UTF-8?q?=E4=BA=A7=E7=BA=BF=E8=AE=A1=E5=88=92=E6=8E=92=E7=A8=8B=E3=80=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_plan/views/view.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sf_plan/views/view.xml b/sf_plan/views/view.xml index fad3d779..47e1dd54 100644 --- a/sf_plan/views/view.xml +++ b/sf_plan/views/view.xml @@ -257,7 +257,7 @@ - 制造订单生产计划 + CNC产线计划排程 ir.actions.act_window sf.production.plan gantt,tree,form From 6366904c91e0312844553ae1332e4744c304dfac Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Wed, 4 Dec 2024 15:37:58 +0800 Subject: [PATCH 48/63] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=AE=A2=E4=BE=9B?= =?UTF-8?q?=E6=96=99=E5=85=A5=E5=BA=93=E5=8D=95=E7=9A=84=E5=90=88=E5=B9=B6?= =?UTF-8?q?=E9=80=89=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/stock.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sf_manufacturing/models/stock.py b/sf_manufacturing/models/stock.py index 0c01a57c..898bec06 100644 --- a/sf_manufacturing/models/stock.py +++ b/sf_manufacturing/models/stock.py @@ -957,7 +957,7 @@ class ReStockMove(models.Model): 合并制造订单的完成move单据 """ res = super(ReStockMove, self)._merge_moves_fields() - if self[0].origin and self.picking_type_id.name in ['生产发料', '内部调拨', '生产入库']: + if self[0].origin and self.picking_type_id.name in ['生产发料', '内部调拨', '生产入库', '客供料入库']: 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)]) From 27ec5b1b74f02a3f6d803dee8930afd76ed48f95 Mon Sep 17 00:00:00 2001 From: guanhuan Date: Wed, 4 Dec 2024 16:13:55 +0800 Subject: [PATCH 49/63] =?UTF-8?q?=E5=A4=9A=E4=B8=AA=E5=88=B6=E9=80=A0?= =?UTF-8?q?=E8=AE=A2=E5=8D=95=E8=8F=9C=E5=8D=95=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/views/mrp_production_addional_change.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sf_manufacturing/views/mrp_production_addional_change.xml b/sf_manufacturing/views/mrp_production_addional_change.xml index 5f9a7ef3..fd0a5ead 100644 --- a/sf_manufacturing/views/mrp_production_addional_change.xml +++ b/sf_manufacturing/views/mrp_production_addional_change.xml @@ -738,7 +738,7 @@ - Date: Wed, 4 Dec 2024 16:41:42 +0800 Subject: [PATCH 50/63] =?UTF-8?q?=E5=9D=AF=E6=96=99=E9=95=BF=E5=AE=BD?= =?UTF-8?q?=E9=AB=98=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_workorder.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index 0750313b..cb8d37ee 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -23,12 +23,15 @@ class ResMrpWorkOrder(models.Model): product_tmpl_name = fields.Char('坯料产品名称', related='production_bom_id.bom_line_ids.product_id.name') - product_tmpl_id_length = fields.Float(related='production_id.product_tmpl_id.length', readonly=True, store=True, - string="坯料长度(mm)") - product_tmpl_id_width = fields.Float(related='production_id.product_tmpl_id.width', readonly=True, store=True, - string="坯料宽度(mm)") - product_tmpl_id_height = fields.Float(related='production_id.product_tmpl_id.height', readonly=True, store=True, - string="坯料高度(mm)") + product_tmpl_id_length = fields.Float(string='坯料长度(mm)', related='material_length', readonly=True, store=False) + product_tmpl_id_width = fields.Float(string='坯料宽度(mm)', related='material_width', readonly=True, store=False) + product_tmpl_id_height = fields.Float(string='坯料高度(mm)', related='material_height', readonly=True, store=False) + # product_tmpl_id_length = fields.Float(related='production_id.product_tmpl_id.length', readonly=True, store=True, + # string="坯料长度(mm)") + # product_tmpl_id_width = fields.Float(related='production_id.product_tmpl_id.width', readonly=True, store=True, + # string="坯料宽度(mm)") + # product_tmpl_id_height = fields.Float(related='production_id.product_tmpl_id.height', readonly=True, store=True, + # string="坯料高度(mm)") product_tmpl_id_materials_id = fields.Many2one(related='production_id.product_tmpl_id.materials_id', readonly=True, store=True, check_company=True, string="材料") product_tmpl_id_materials_type_id = fields.Many2one(related='production_id.product_tmpl_id.materials_type_id', From ef60f36c90d16263766203a536c43c9e25f678c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Wed, 4 Dec 2024 20:42:34 +0800 Subject: [PATCH 51/63] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=B7=A5=E8=89=BA?= =?UTF-8?q?=E5=A4=96=E5=8D=8F=E5=B7=A5=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_production.py | 26 ++-- sf_manufacturing/models/mrp_workorder.py | 168 +++++++++++++--------- sf_manufacturing/models/stock.py | 88 ++++++------ sf_sale/views/quick_easy_order_view.xml | 4 +- 4 files changed, 163 insertions(+), 123 deletions(-) diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py index 9156dc38..d1349671 100644 --- a/sf_manufacturing/models/mrp_production.py +++ b/sf_manufacturing/models/mrp_production.py @@ -721,6 +721,7 @@ class MrpProduction(models.Model): for product_id, pd in grouped_product_ids.items(): product_id_to_production_names[product_id] = [p.name for p in pd] for production in production_all: + proc_workorders = [] process_parameter_workorder = self.env['mrp.workorder'].search( [('surface_technics_parameters_id', '!=', False), ('production_id', '=', production.id), ('is_subcontract', '=', True)], order='sequence asc') @@ -737,10 +738,11 @@ class MrpProduction(models.Model): else: # 处理连续组,如果它不为空 if consecutive_workorders: + proc_workorders.append(consecutive_workorders) # 创建外协出入库单和采购订单 - self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production) - self.env['purchase.order'].get_purchase_order(consecutive_workorders, production, - product_id_to_production_names) + # self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production, sorted_workorders) + # self.env['purchase.order'].get_purchase_order(consecutive_workorders, production, + # product_id_to_production_names) if i < len(sorted_workorders) - 1: # 重置连续组,并添加当前工作订单 consecutive_workorders = [workorder] @@ -751,18 +753,22 @@ class MrpProduction(models.Model): i - 1].supplier_id.id: consecutive_workorders = [workorder] else: + proc_workorders.append([workorder]) # 立即创建外协出入库单和采购订单 - self.env['stock.picking'].create_outcontract_picking(workorder, production) - self.env['purchase.order'].get_purchase_order(workorder, production, - product_id_to_production_names) + # self.env['stock.picking'].create_outcontract_picking(workorder, production) + # self.env['purchase.order'].get_purchase_order(workorder, production, + # product_id_to_production_names) consecutive_workorders = [] # 处理最后一个组,即使它可能只有一个工作订单 if consecutive_workorders: - self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production) - self.env['purchase.order'].get_purchase_order(consecutive_workorders, production, - product_id_to_production_names) - + proc_workorders.append(consecutive_workorders) + # self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production) + # self.env['purchase.order'].get_purchase_order(consecutive_workorders, production, + # product_id_to_production_names) + 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: diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index 7bd9d1c8..ee5a034b 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -313,14 +313,7 @@ class ResMrpWorkOrder(models.Model): # if technology_design.is_auto is False: # domain = [('origin', '=', self.production_id.name)] # else: - domain = [('origin', '=', self.production_id.name), ('purchase_type', '=', 'consignment')] - purchase_orders = self.env['purchase.order'].search(domain) - purchase_orders_id = None - for po in purchase_orders: - for line in po.order_line: - if line.product_id.server_product_process_parameters_id == self.surface_technics_parameters_id: - if line.product_qty == 1: - purchase_orders_id = line.order_id.id + purchase_orders_id = self._get_surface_technics_purchase_ids() result = { "type": "ir.actions.act_window", "res_model": "purchase.order", @@ -330,6 +323,17 @@ class ResMrpWorkOrder(models.Model): 'view_mode': 'form', } return result + + def _get_surface_technics_purchase_ids(self): + domain = [('origin', '=', self.production_id.name), ('purchase_type', '=', 'consignment')] + purchase_orders = self.env['purchase.order'].search(domain) + purchase_orders_id = None + for po in purchase_orders: + for line in po.order_line: + if line.product_id.server_product_process_parameters_id == self.surface_technics_parameters_id: + if line.product_qty == 1: + purchase_orders_id = line.order_id.id + return purchase_orders_id supplier_id = fields.Many2one('res.partner', string='外协供应商') equipment_id = fields.Many2one('maintenance.equipment', string='加工设备', tracking=True) @@ -1027,47 +1031,47 @@ class ResMrpWorkOrder(models.Model): 'production_id.programming_state') def _compute_state(self): # super()._compute_state() - for workorder in self: - if workorder.sequence != 1: - previous_workorder = self.env['mrp.workorder'].search( - [('production_id', '=', workorder.production_id.id), - ('sequence', '=', workorder.sequence - 1)]) - if workorder.state == 'pending': - if all([wo.state in ('done', 'cancel') for wo in workorder.blocked_by_workorder_ids]): - if workorder.production_id.reservation_state == 'assigned' and workorder.production_id.schedule_state == '已排': - if ((workorder.sequence == 1 and not workorder.blocked_by_workorder_ids) - or (workorder.blocked_by_workorder_ids.state in ('done', 'cancel') - and workorder.blocked_by_workorder_ids.test_results not in ['报废', '返工']) - or (previous_workorder.state in ('done', 'cancel') - and not workorder.blocked_by_workorder_ids - and previous_workorder.test_results not in ['报废', '返工']) - ): - workorder.state = 'ready' - continue - if workorder.production_id.schedule_state == '未排' and workorder.state in ('waiting', 'ready'): - if workorder.sequence != 1: - workorder.state = 'pending' - continue - if workorder.state not in ('waiting', 'ready'): - continue - if workorder.state in ( - 'waiting') and workorder.sequence == 1 and workorder.production_id.schedule_state == '已排': - workorder.state = 'ready' - continue - if not all([wo.state in ('done', 'cancel') for wo in workorder.blocked_by_workorder_ids]): - workorder.state = 'pending' - if workorder.state in ['waiting']: - if previous_workorder.state == 'waiting': - workorder.state = 'pending' - if workorder.sequence == 1 and workorder.state == 'pending': - workorder.state = 'waiting' - continue - if workorder.production_id.reservation_state not in ('waiting', 'confirmed', 'assigned'): - continue - if workorder.production_id.reservation_state == 'assigned' and workorder.state == 'waiting' and workorder.production_id.schedule_state == '已排': - workorder.state = 'ready' - elif workorder.production_id.reservation_state != 'assigned' and workorder.state == 'ready': - workorder.state = 'waiting' + # for workorder in self: + # if workorder.sequence != 1: + # previous_workorder = self.env['mrp.workorder'].search( + # [('production_id', '=', workorder.production_id.id), + # ('sequence', '=', workorder.sequence - 1)]) + # if workorder.state == 'pending': + # if all([wo.state in ('done', 'cancel') for wo in workorder.blocked_by_workorder_ids]): + # if workorder.production_id.reservation_state == 'assigned' and workorder.production_id.schedule_state == '已排': + # if ((workorder.sequence == 1 and not workorder.blocked_by_workorder_ids) + # or (workorder.blocked_by_workorder_ids.state in ('done', 'cancel') + # and workorder.blocked_by_workorder_ids.test_results not in ['报废', '返工']) + # or (previous_workorder.state in ('done', 'cancel') + # and not workorder.blocked_by_workorder_ids + # and previous_workorder.test_results not in ['报废', '返工']) + # ): + # workorder.state = 'ready' + # continue + # if workorder.production_id.schedule_state == '未排' and workorder.state in ('waiting', 'ready'): + # if workorder.sequence != 1: + # workorder.state = 'pending' + # continue + # if workorder.state not in ('waiting', 'ready'): + # continue + # if workorder.state in ( + # 'waiting') and workorder.sequence == 1 and workorder.production_id.schedule_state == '已排': + # workorder.state = 'ready' + # continue + # if not all([wo.state in ('done', 'cancel') for wo in workorder.blocked_by_workorder_ids]): + # workorder.state = 'pending' + # if workorder.state in ['waiting']: + # if previous_workorder.state == 'waiting': + # workorder.state = 'pending' + # if workorder.sequence == 1 and workorder.state == 'pending': + # workorder.state = 'waiting' + # continue + # if workorder.production_id.reservation_state not in ('waiting', 'confirmed', 'assigned'): + # continue + # if workorder.production_id.reservation_state == 'assigned' and workorder.state == 'waiting' and workorder.production_id.schedule_state == '已排': + # workorder.state = 'ready' + # elif workorder.production_id.reservation_state != 'assigned' and workorder.state == 'ready': + # workorder.state = 'waiting' for workorder in self: # 如果工单的工序没有进行排序则跳出循环 @@ -1118,21 +1122,27 @@ class ResMrpWorkOrder(models.Model): if workorder.is_subcontract is False: workorder.state = 'ready' else: - production_programming = self.env['mrp.production'].search( - [('origin', '=', self.production_id.origin)], order='name asc') - production_no_remanufacture = production_programming.filtered( - lambda a: a.is_remanufacture is False) - production_list = [production.name for production in production_programming] - purchase_orders = self.env['purchase.order'].search( - [('origin', 'ilike', ','.join(production_list))]) - for line in purchase_orders.order_line: - if ( - line.product_id.server_product_process_parameters_id == workorder.surface_technics_parameters_id - and line.product_qty == len(production_no_remanufacture)): - if all(pur_order.state == 'purchase' for pur_order in purchase_orders): - workorder.state = 'ready' - else: - workorder.state = 'waiting' + # production_programming = self.env['mrp.production'].search( + # [('origin', '=', self.production_id.origin)], order='name asc') + # production_no_remanufacture = production_programming.filtered( + # lambda a: a.is_remanufacture is False) + # production_list = [production.name for production in production_programming] + # purchase_orders = self.env['purchase.order'].search( + # [('origin', 'ilike', ','.join(production_list))]) + # for line in purchase_orders.order_line: + # if ( + # line.product_id.server_product_process_parameters_id == workorder.surface_technics_parameters_id + # and line.product_qty == len(production_no_remanufacture)): + # if all(pur_order.state == 'purchase' for pur_order in purchase_orders): + # workorder.state = 'ready' + # else: + # workorder.state = 'waiting' + purchase_orders_id = self._get_surface_technics_purchase_ids() + if purchase_orders_id: + purchase_order = self.env['purchase.order'].browse(purchase_orders_id) + workorder.state = 'ready' if purchase_order.state == 'purchase' else 'waiting' + else: + workorder.state = 'waiting' # re_work = self.env['mrp.workorder'].search([('production_id', '=', workorder.production_id.id), # ('processing_panel', '=', workorder.processing_panel), @@ -1241,12 +1251,13 @@ class ResMrpWorkOrder(models.Model): # 表面工艺外协出库单 if self.routing_type == '表面工艺': if self.is_subcontract is True: - move_out = self.env['stock.move'].search( - [('location_id', '=', self.env['stock.location'].search( - [('barcode', 'ilike', 'WH-PREPRODUCTION')]).id), - ('location_dest_id', '=', self.env['stock.location'].search( - [('barcode', 'ilike', 'VL-SPOC')]).id), - ('origin', '=', self.production_id.name), ('state', 'not in', ['cancel', 'done'])]) + move_out = self.move_subcontract_workorder_ids[1] + # move_out = self.env['stock.move'].search( + # [('location_id', '=', self.env['stock.location'].search( + # [('barcode', 'ilike', 'WH-PREPRODUCTION')]).id), + # ('location_dest_id', '=', self.env['stock.location'].search( + # [('barcode', 'ilike', 'VL-SPOC')]).id), + # ('origin', '=', self.production_id.name), ('state', 'not in', ['cancel', 'done'])]) for mo in move_out: pick = self.env['stock.picking'].search([('id', '=', mo.picking_id.id), ('name', 'ilike', 'OCOUT'), ('partner_id', '=', self.supplier_id.id)]) @@ -1254,6 +1265,21 @@ class ResMrpWorkOrder(models.Model): if mo.state != 'done': mo.write({'state': 'assigned', 'production_id': False}) self.env['stock.move.line'].create(mo.get_move_line(self.production_id, self)) + product_qty = mo.product_uom._compute_quantity( + mo.product_uom_qty, mo.product_id.uom_id, rounding_method='HALF-UP') + available_quantity = self.env['stock.quant']._get_available_quantity( + mo.product_id, + mo.location_id, + lot_id=mo.move_line_ids.lot_id, + strict=False, + ) + mo._update_reserved_quantity( + product_qty, + available_quantity, + mo.location_id, + lot_id=mo.move_line_ids.lot_id, + strict=False, + ) # move_out._action_assign() if self.state == 'waiting' or self.state == 'ready' or self.state == 'progress': @@ -1526,6 +1552,8 @@ class ResMrpWorkOrder(models.Model): 'default_confirm_button': '确认解除', # 'default_feeder_station_start_id': feeder_station_start_id, }} + + move_subcontract_workorder_ids = fields.One2many('stock.move', 'subcontract_workorder_id', string='组件') class CNCprocessing(models.Model): diff --git a/sf_manufacturing/models/stock.py b/sf_manufacturing/models/stock.py index 50c7e672..cfa35887 100644 --- a/sf_manufacturing/models/stock.py +++ b/sf_manufacturing/models/stock.py @@ -634,71 +634,74 @@ class StockPicking(models.Model): num = "%04d" % m return '%s%s' % (rescode, num) - def button_validate(self): - res = super().button_validate() - if res is True and self.picking_type_id.sequence_code == 'OCOUT': - # if self.id == move_out.picking_id.id: - # if move_out.move_line_ids.workorder_id.state == 'progress': - move_in = self.env['stock.move'].search( - [('location_dest_id', '=', self.env['stock.location'].search( - [('barcode', 'ilike', 'WH-PREPRODUCTION')]).id), - ('location_id', '=', self.env['stock.location'].search( - [('barcode', 'ilike', 'VL-SPOC')]).id), - ('origin', '=', self.origin), ('state', 'not in', ['cancel', 'done'])]) - production = self.env['mrp.production'].search([('name', '=', self.origin)]) - for mi in move_in: - pick = self.env['stock.picking'].search([('id', '=', mi.picking_id.id), ('name', 'ilike', 'OCIN'), - ('partner_id', '=', self.partner_id.id)]) - # if pick: - # if mi.state != 'done': - # mi.write({'state': 'assigned'}) - # self.env['stock.move.line'].create(mi.get_move_line(production, None)) + # def button_validate(self): + # res = super().button_validate() + # if res is True and self.picking_type_id.sequence_code == 'OCOUT': + # # if self.id == move_out.picking_id.id: + # # if move_out.move_line_ids.workorder_id.state == 'progress': + # move_in = self.env['stock.move'].search( + # [('location_dest_id', '=', self.env['stock.location'].search( + # [('barcode', 'ilike', 'WH-PREPRODUCTION')]).id), + # ('location_id', '=', self.env['stock.location'].search( + # [('barcode', 'ilike', 'VL-SPOC')]).id), + # ('origin', '=', self.origin), ('state', 'not in', ['cancel', 'done'])]) + # production = self.env['mrp.production'].search([('name', '=', self.origin)]) + # for mi in move_in: + # pick = self.env['stock.picking'].search([('id', '=', mi.picking_id.id), ('name', 'ilike', 'OCIN'), + # ('partner_id', '=', self.partner_id.id)]) + # if pick: + # if mi.state != 'done': + # mi.write({'state': 'assigned'}) + # self.env['stock.move.line'].create(mi.get_move_line(production, None)) - return res + # return res # 创建 外协出库入单 - def create_outcontract_picking(self, sorted_workorders_arr, item): + def create_outcontract_picking(self, workorders, item, sorted_workorders): domain = [('origin', '=', item.name), ('name', 'ilike', 'OCOUT')] - if len(sorted_workorders_arr) > 1: - sorted_workorders_arr = sorted_workorders_arr[0] + if len(workorders) > 1: + workorders = workorders[0] else: domain += [ - ('surface_technics_parameters_id', '=', sorted_workorders_arr[0].surface_technics_parameters_id.id)] + ('surface_technics_parameters_id', '=', workorders[0].surface_technics_parameters_id.id)] stock_picking = self.env['stock.picking'].search(domain) if not stock_picking: - for sorted_workorders in sorted_workorders_arr: + for workorder in workorders: # pick_ids = [] - if not sorted_workorders.picking_ids: + if not workorder.picking_ids: # outcontract_stock_move = self.env['stock.move'].search([('production_id', '=', item.id)]) # if not outcontract_stock_move: # 创建一个新的补货组 procurement_group_id = self.env['procurement.group'].create({ - 'name': sorted_workorders.name, + 'name': workorder.name, 'partner_id': self.partner_id.id, }) + move_dest_id = False + # 如果当前工单是制造订单的最后一个工单 + # if workorder == item.workorder_ids[-1]: + # # 找到制造订单对应的move + # move_dest_id = item.move_raw_ids[0].move_orig_ids[0].id + # else: + # # 从sorted_workorders中找到上一工单的move + # move_dest_id = sorted_workorders[sorted_workorders.index(workorder) - 1].move_subcontract_workorder_ids[1].id new_picking = True - location_id = self.env['stock.location'].search( - [('barcode', 'ilike', 'VL-SPOC')]).id, - location_dest_id = self.env['stock.location'].search( - [('barcode', 'ilike', 'WH-PREPRODUCTION')]).id, outcontract_picking_type_in = self.env.ref( 'sf_manufacturing.outcontract_picking_in').id, outcontract_picking_type_out = self.env.ref( 'sf_manufacturing.outcontract_picking_out').id, moves_in = self.env['stock.move'].sudo().create( - self.env['stock.move']._get_stock_move_values_Res(item, location_id, location_dest_id, - outcontract_picking_type_in, procurement_group_id.id)) + self.env['stock.move']._get_stock_move_values_Res(item, outcontract_picking_type_in, procurement_group_id.id, move_dest_id)) picking_in = self.create( - moves_in._get_new_picking_values_Res(item, sorted_workorders, 'WH/OCIN/')) + moves_in._get_new_picking_values_Res(item, workorder, 'WH/OCIN/')) # pick_ids.append(picking_in.id) moves_in.write( {'picking_id': picking_in.id, 'state': 'waiting'}) moves_in._assign_picking_post_process(new=new_picking) moves_out = self.env['stock.move'].sudo().create( - self.env['stock.move']._get_stock_move_values_Res(item, location_dest_id, location_id, - outcontract_picking_type_out, procurement_group_id.id, moves_in.id)) + self.env['stock.move']._get_stock_move_values_Res(item, outcontract_picking_type_out, procurement_group_id.id, moves_in.id)) + workorder.write({'move_subcontract_workorder_ids': [(6, 0, [moves_in.id, moves_out.id])]}) picking_out = self.create( - moves_out._get_new_picking_values_Res(item, sorted_workorders, 'WH/OCOUT/')) + moves_out._get_new_picking_values_Res(item, workorder, 'WH/OCOUT/')) # pick_ids.append(picking_out.id) moves_out.write( {'picking_id': picking_out.id, 'state': 'waiting'}) @@ -713,16 +716,17 @@ class ReStockMove(models.Model): materiel_width = fields.Float(string='物料宽度', digits=(16, 4)) materiel_height = fields.Float(string='物料高度', digits=(16, 4)) - def _get_stock_move_values_Res(self, item, location_src_id, location_dest_id, picking_type_id, group_id, move_dest_ids=False): - route = self.env['stock.route'].sudo().search([('name', '=', '表面工艺外协')]) + def _get_stock_move_values_Res(self, item, picking_type_id, group_id, move_dest_ids=False): + route_id = self.env.ref('sf_manufacturing.route_surface_technology_outsourcing').id + stock_rule = self.env['stock.rule'].sudo().search([('route_id', '=', route_id), ('picking_type_id', '=', picking_type_id)]) move_values = { 'name': '推', 'company_id': item.company_id.id, 'product_id': item.bom_id.bom_line_ids.product_id.id, 'product_uom': item.bom_id.bom_line_ids.product_uom_id.id, 'product_uom_qty': 1.0, - 'location_id': location_src_id, - 'location_dest_id': location_dest_id, + 'location_id': stock_rule.location_src_id.id, + 'location_dest_id': stock_rule.location_dest_id.id, 'origin': item.name, 'group_id': group_id, 'move_dest_ids': [(6, 0, [move_dest_ids])] if move_dest_ids else False, @@ -991,6 +995,8 @@ class ReStockMove(models.Model): res['origin'] = ','.join(productions.mapped('name')) res['retrospect_ref'] = production.product_id.name return res + + subcontract_workorder_id = fields.Many2one('mrp.workorder', '外协工单组件', check_company=True, index='btree_not_null') class ReStockQuant(models.Model): diff --git a/sf_sale/views/quick_easy_order_view.xml b/sf_sale/views/quick_easy_order_view.xml index 3b386062..e0fa6dbd 100644 --- a/sf_sale/views/quick_easy_order_view.xml +++ b/sf_sale/views/quick_easy_order_view.xml @@ -128,9 +128,9 @@ - + groups="sales_team.group_sale_salesman,sf_base.group_sale_salemanager,sf_base.group_sale_director"/> --> \ No newline at end of file From 5f12976d8f78f7c0a4ce500ca85b2602c22aa57b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Thu, 5 Dec 2024 01:33:46 +0800 Subject: [PATCH 52/63] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=A1=A8=E9=9D=A2?= =?UTF-8?q?=E5=B7=A5=E8=89=BA=E5=A4=96=E5=8D=8F=E5=B7=A5=E5=8D=95=E6=B5=81?= =?UTF-8?q?=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_workorder.py | 59 +++++++++++---------- sf_manufacturing/models/stock.py | 66 +++++++++++++----------- 2 files changed, 69 insertions(+), 56 deletions(-) diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index ee5a034b..35238598 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -317,7 +317,7 @@ class ResMrpWorkOrder(models.Model): result = { "type": "ir.actions.act_window", "res_model": "purchase.order", - "res_id": purchase_orders_id, + "res_id": purchase_orders_id.id, # "domain": [['id', 'in', self.purchase_id]], "name": _("Purchase Orders"), 'view_mode': 'form', @@ -332,7 +332,7 @@ class ResMrpWorkOrder(models.Model): for line in po.order_line: if line.product_id.server_product_process_parameters_id == self.surface_technics_parameters_id: if line.product_qty == 1: - purchase_orders_id = line.order_id.id + purchase_orders_id = line.order_id return purchase_orders_id supplier_id = fields.Many2one('res.partner', string='外协供应商') @@ -1139,8 +1139,7 @@ class ResMrpWorkOrder(models.Model): # workorder.state = 'waiting' purchase_orders_id = self._get_surface_technics_purchase_ids() if purchase_orders_id: - purchase_order = self.env['purchase.order'].browse(purchase_orders_id) - workorder.state = 'ready' if purchase_order.state == 'purchase' else 'waiting' + workorder.state = 'ready' if purchase_orders_id.state == 'purchase' else 'waiting' else: workorder.state = 'waiting' @@ -1205,6 +1204,10 @@ class ResMrpWorkOrder(models.Model): # 重写工单开始按钮方法 def button_start(self): + # 判断工单状态是否为等待组件 + if self.state in ['waiting', 'pending']: + raise UserError('制造订单【%s】缺少组件信息!' % self.production_id.name) + if self.routing_type == 'CNC加工': self.env['sf.production.plan'].sudo().search([('name', '=', self.production_id.name)]).write({ 'state': 'processing', @@ -1212,9 +1215,6 @@ class ResMrpWorkOrder(models.Model): }) if self.sequence == 1: - # 判断工单状态是否为等待组件 - if self.state == 'waiting': - raise UserError('制造订单【%s】缺少组件信息!' % self.production_id.name) # 判断是否有坯料的序列号信息 boolean = False if self.production_id.move_raw_ids: @@ -1259,27 +1259,25 @@ class ResMrpWorkOrder(models.Model): # [('barcode', 'ilike', 'VL-SPOC')]).id), # ('origin', '=', self.production_id.name), ('state', 'not in', ['cancel', 'done'])]) for mo in move_out: - pick = self.env['stock.picking'].search([('id', '=', mo.picking_id.id), ('name', 'ilike', 'OCOUT'), - ('partner_id', '=', self.supplier_id.id)]) - if pick: - if mo.state != 'done': - mo.write({'state': 'assigned', 'production_id': False}) + 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(self.production_id, self)) - product_qty = mo.product_uom._compute_quantity( - mo.product_uom_qty, mo.product_id.uom_id, rounding_method='HALF-UP') - available_quantity = self.env['stock.quant']._get_available_quantity( - mo.product_id, - mo.location_id, - lot_id=mo.move_line_ids.lot_id, - strict=False, - ) - mo._update_reserved_quantity( - product_qty, - available_quantity, - mo.location_id, - lot_id=mo.move_line_ids.lot_id, - strict=False, - ) + # product_qty = mo.product_uom._compute_quantity( + # mo.product_uom_qty, mo.product_id.uom_id, rounding_method='HALF-UP') + # available_quantity = self.env['stock.quant']._get_available_quantity( + # mo.product_id, + # mo.location_id, + # lot_id=mo.move_line_ids.lot_id, + # strict=False, + # ) + # mo._update_reserved_quantity( + # product_qty, + # available_quantity, + # mo.location_id, + # lot_id=mo.move_line_ids.lot_id, + # strict=False, + # ) # move_out._action_assign() if self.state == 'waiting' or self.state == 'ready' or self.state == 'progress': @@ -1384,6 +1382,13 @@ class ResMrpWorkOrder(models.Model): picks = record.picking_ids.filtered(lambda p: p.state not in ('done')) if picks: raise UserError('请先完成该工单的工艺外协再进行操作') + # 表面工艺外协,最后一张工单 + workorders = self.production_id.workorder_ids + subcontract_workorders = workorders.filtered(lambda wo: wo.is_subcontract == True).sorted('sequence') + if self == subcontract_workorders[-1]: + # 给下一个库存移动就绪 + self.move_subcontract_workorder_ids[0].move_dest_ids._action_done() + # self.production_id.button_mark_done() tem_date_planned_finished = record.date_planned_finished tem_date_finished = record.date_finished logging.info('routing_type:%s' % record.routing_type) diff --git a/sf_manufacturing/models/stock.py b/sf_manufacturing/models/stock.py index cfa35887..45d90bb8 100644 --- a/sf_manufacturing/models/stock.py +++ b/sf_manufacturing/models/stock.py @@ -634,27 +634,23 @@ class StockPicking(models.Model): num = "%04d" % m return '%s%s' % (rescode, num) - # def button_validate(self): - # res = super().button_validate() - # if res is True and self.picking_type_id.sequence_code == 'OCOUT': - # # if self.id == move_out.picking_id.id: - # # if move_out.move_line_ids.workorder_id.state == 'progress': - # move_in = self.env['stock.move'].search( - # [('location_dest_id', '=', self.env['stock.location'].search( - # [('barcode', 'ilike', 'WH-PREPRODUCTION')]).id), - # ('location_id', '=', self.env['stock.location'].search( - # [('barcode', 'ilike', 'VL-SPOC')]).id), - # ('origin', '=', self.origin), ('state', 'not in', ['cancel', 'done'])]) - # production = self.env['mrp.production'].search([('name', '=', self.origin)]) - # for mi in move_in: - # pick = self.env['stock.picking'].search([('id', '=', mi.picking_id.id), ('name', 'ilike', 'OCIN'), - # ('partner_id', '=', self.partner_id.id)]) - # if pick: - # if mi.state != 'done': - # mi.write({'state': 'assigned'}) - # self.env['stock.move.line'].create(mi.get_move_line(production, None)) - - # return res + def button_validate(self): + res = super().button_validate() + picking_type_in = self.env.ref('sf_manufacturing.outcontract_picking_in').id + if res is True and self.picking_type_id.id == picking_type_in: + # 如果是最后一张外协入库单,则设置库存位置的预留数量 + move_in = self.move_ids + if move_in: + workorder = move_in.subcontract_workorder_id + workorders = workorder.production_id.workorder_ids + subcontract_workorders = workorders.filtered(lambda wo: wo.is_subcontract == True).sorted('sequence') + if workorder == subcontract_workorders[-1]: + self.env['stock.quant']._update_reserved_quantity( + move_in.product_id, move_in.location_dest_id, move_in.product_uom_qty, lot_id=move_in.move_line_ids.lot_id, + package_id=False, owner_id=False, strict=False + ) + + return res # 创建 外协出库入单 def create_outcontract_picking(self, workorders, item, sorted_workorders): @@ -677,13 +673,12 @@ class StockPicking(models.Model): 'partner_id': self.partner_id.id, }) move_dest_id = False - # 如果当前工单是制造订单的最后一个工单 - # if workorder == item.workorder_ids[-1]: - # # 找到制造订单对应的move - # move_dest_id = item.move_raw_ids[0].move_orig_ids[0].id - # else: - # # 从sorted_workorders中找到上一工单的move - # move_dest_id = sorted_workorders[sorted_workorders.index(workorder) - 1].move_subcontract_workorder_ids[1].id + # 如果当前工单是是制造订单的最后一个工单 + if workorder == item.workorder_ids[-1]: + move_dest_id = item.move_raw_ids[0].id + else: + # 从sorted_workorders中找到上一工单的move + move_dest_id = sorted_workorders[sorted_workorders.index(workorder) - 1].move_subcontract_workorder_ids[1].id new_picking = True outcontract_picking_type_in = self.env.ref( 'sf_manufacturing.outcontract_picking_in').id, @@ -706,7 +701,20 @@ class StockPicking(models.Model): moves_out.write( {'picking_id': picking_out.id, 'state': 'waiting'}) moves_out._assign_picking_post_process(new=new_picking) + return moves_in, moves_out + @api.depends('move_type', 'immediate_transfer', 'move_ids.state', 'move_ids.picking_id') + def _compute_state(self): + super(StockPicking, self)._compute_state() + for picking in self: + # 外协出库单根据工单状态,采购单状态来确定 + picking_type_id = self.env.ref('sf_manufacturing.outcontract_picking_out').id + if picking.picking_type_id.id == picking_type_id: + if picking.move_ids: + workorder = picking.move_ids[0].subcontract_workorder_id + if picking.state == 'assigned': + if workorder.state in ['pending', 'waiting'] or workorder._get_surface_technics_purchase_ids().state in ['draft', 'sent']: + picking.state = 'waiting' class ReStockMove(models.Model): @@ -753,7 +761,7 @@ class ReStockMove(models.Model): 'picking_type_id': picking_type_id, 'location_id': self.mapped('location_id').id, 'location_dest_id': self.mapped('location_dest_id').id, - 'state': 'confirmed', + 'state': 'waiting', } def get_move_line(self, production_id, sorted_workorders): From e011e4cfd60be272f7f753d70644be4543a61f05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Thu, 5 Dec 2024 09:31:06 +0800 Subject: [PATCH 53/63] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E8=A1=A8=E9=9D=A2?= =?UTF-8?q?=E5=B7=A5=E8=89=BA=E5=B7=A5=E5=8D=95=E5=AE=8C=E6=88=90=E5=90=8E?= =?UTF-8?q?=EF=BC=8C=E7=94=9F=E4=BA=A7=E5=85=A5=E5=BA=93=E5=8D=95=E6=9C=AA?= =?UTF-8?q?=E5=B0=B1=E7=BB=AA=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_workorder.py | 14 +++++++------- sf_sale/models/sale_order.py | 16 ++++++++-------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index 4967b32d..24bad9e7 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -1433,13 +1433,13 @@ class ResMrpWorkOrder(models.Model): move_raw_id.quantity_done = move_raw_id.product_uom_qty record.process_state = '已完工' record.production_id.process_state = '已完工' - if record.routing_type in ['表面工艺']: - raw_move = self.env['stock.move'].sudo().search( - [('origin', '=', record.production_id.name), - ('procure_method', 'in', ['make_to_order', 'make_to_stock']), - ('state', '!=', 'done')]) - if raw_move: - raw_move.write({'state': 'done'}) + # if record.routing_type in ['表面工艺']: + # raw_move = self.env['stock.move'].sudo().search( + # [('origin', '=', record.production_id.name), + # ('procure_method', 'in', ['make_to_order', 'make_to_stock']), + # ('state', '!=', 'done')]) + # if raw_move: + # raw_move.write({'state': 'done'}) record.production_id.button_mark_done1() # record.production_id.state = 'done' diff --git a/sf_sale/models/sale_order.py b/sf_sale/models/sale_order.py index 3879860e..6a1d3023 100644 --- a/sf_sale/models/sale_order.py +++ b/sf_sale/models/sale_order.py @@ -279,14 +279,14 @@ class RePurchaseOrder(models.Model): 'product_uom': server_template.uom_id.id })) - if server_product_process: - purchase_order = self.env['purchase.order'].sudo().create({ - 'partner_id': server_template.seller_ids[0].partner_id.id, - 'origin': production.name, - 'state': 'draft', - 'purchase_type': 'consignment', - 'order_line': server_product_process}) - consecutive_process_parameters.purchase_id = [(6, 0, [purchase_order.id])] + if server_product_process: + purchase_order = self.env['purchase.order'].sudo().create({ + 'partner_id': server_template.seller_ids[0].partner_id.id, + 'origin': production.name, + 'state': 'draft', + 'purchase_type': 'consignment', + 'order_line': server_product_process}) + pp.purchase_id = [(6, 0, [purchase_order.id])] # self.env.cr.commit() @api.onchange('order_line') From 58b33b6c8df4853c2c3c3de5a74e8b8c931fa3a4 Mon Sep 17 00:00:00 2001 From: mgw <1392924357@qq.com> Date: Thu, 5 Dec 2024 11:05:43 +0800 Subject: [PATCH 54/63] =?UTF-8?q?=E5=88=B6=E9=80=A0=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E9=80=80=E5=9B=9E=E8=B0=83=E6=95=B4-=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E8=A1=A8=E9=9D=A2=E5=B7=A5=E8=89=BA=E5=90=8E=E5=AF=B9=E5=BA=94?= =?UTF-8?q?=E7=9A=84=E5=A4=96=E5=8D=8F=E5=87=BA=E5=85=A5=E5=BA=93=E5=8D=95?= =?UTF-8?q?=E6=B2=A1=E6=9C=89=E5=8F=98=E6=88=90=E5=8F=96=E6=B6=88=E7=8A=B6?= =?UTF-8?q?=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_workorder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index 2f36ad79..19be2289 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -134,7 +134,7 @@ class ResMrpWorkOrder(models.Model): glb_file = fields.Binary("glb模型文件", related='production_id.model_file') is_subcontract = fields.Boolean(string='是否外协') surface_technics_parameters_id = fields.Many2one('sf.production.process.parameter', string="表面工艺可选参数") - picking_ids = fields.Many2many('stock.picking', string='外协出入库单') + picking_ids = fields.Many2many('stock.picking', string='外协出入库单', compute='_compute_surface_technics_picking_ids') # purchase_id = fields.Many2one('purchase.order', string='外协采购单') surface_technics_picking_count = fields.Integer("外协出入库", compute='_compute_surface_technics_picking_ids') surface_technics_purchase_count = fields.Integer("外协采购", compute='_compute_surface_technics_purchase_ids') From dbf75684ee3235a07bc7697cf5a0faeaa85f3f15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Thu, 5 Dec 2024 13:42:07 +0800 Subject: [PATCH 55/63] =?UTF-8?q?=E7=89=B9=E6=AE=8A=E8=A1=A8=E9=9D=A2?= =?UTF-8?q?=E5=B7=A5=E8=89=BA=E5=B7=A5=E5=8D=95=E6=B2=A1=E6=9C=89=E5=AE=8C?= =?UTF-8?q?=E6=88=90=E5=AF=B9=E5=BA=94=E9=87=87=E8=B4=AD=E5=8D=95=E6=97=B6?= =?UTF-8?q?=E5=B7=A5=E5=8D=95=E5=A4=84=E4=BA=8E=E7=AD=89=E5=BE=85=E7=BB=84?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_workorder.py | 11 ++++++++++- sf_manufacturing/models/stock.py | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index 24bad9e7..b6173d78 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -1098,7 +1098,16 @@ class ResMrpWorkOrder(models.Model): and workorder.production_id.schedule_state == '已排' and len(workorder.production_id.picking_ids.filtered( lambda w: w.state not in ['done', 'cancel'])) == 0): - workorder.state = 'ready' + if workorder.is_subcontract is True: + purchase_orders_id = self._get_surface_technics_purchase_ids() + if purchase_orders_id.state == 'purchase': + workorder.state = 'ready' + continue + else: + workorder.state = 'waiting' + continue + else: + workorder.state = 'ready' continue # ================= 如果制造订单刀具状态为[无效刀、缺刀] 或者 制造订单状态为[返工]========================== if (workorder.production_id.tool_state in ['1', '2'] or workorder.production_id.state == 'rework' diff --git a/sf_manufacturing/models/stock.py b/sf_manufacturing/models/stock.py index e464e995..8597942f 100644 --- a/sf_manufacturing/models/stock.py +++ b/sf_manufacturing/models/stock.py @@ -701,7 +701,7 @@ class StockPicking(models.Model): moves_out.write( {'picking_id': picking_out.id, 'state': 'waiting'}) moves_out._assign_picking_post_process(new=new_picking) - return moves_in, moves_out + @api.depends('move_type', 'immediate_transfer', 'move_ids.state', 'move_ids.picking_id') def _compute_state(self): From 52ab962ace34eacf671d255384c18689c2d20e70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Thu, 5 Dec 2024 15:09:04 +0800 Subject: [PATCH 56/63] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E8=A1=A8=E9=9D=A2=E5=B7=A5=E8=89=BA=EF=BC=8C=E5=A4=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E4=BA=86=E9=87=87=E8=B4=AD=E5=8D=95=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_production.py | 7 +- sf_manufacturing/models/mrp_workorder.py | 2 +- sf_manufacturing/models/stock.py | 87 +++++++++---------- .../production_technology_re_adjust_wizard.py | 49 ++++++----- .../wizard/production_technology_wizard.py | 8 +- sf_sale/models/sale_order.py | 33 ++----- 6 files changed, 83 insertions(+), 103 deletions(-) diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py index d1349671..f11a32ac 100644 --- a/sf_manufacturing/models/mrp_production.py +++ b/sf_manufacturing/models/mrp_production.py @@ -724,8 +724,13 @@ class MrpProduction(models.Model): proc_workorders = [] process_parameter_workorder = self.env['mrp.workorder'].search( [('surface_technics_parameters_id', '!=', False), ('production_id', '=', production.id), - ('is_subcontract', '=', True)], order='sequence asc') + ('is_subcontract', '=', True), ('state', '!=', 'cancel')], order='sequence asc') if process_parameter_workorder: + # 将这些特殊表面工艺工单的采购单与调拨单置为失效 + for workorder in process_parameter_workorder: + workorder._get_surface_technics_purchase_ids().write({'state': 'cancel'}) + workorder.move_subcontract_workorder_ids.write({'state': 'cancel'}) + workorder.move_subcontract_workorder_ids.picking_id.write({'state': 'cancel'}) consecutive_workorders = [] sorted_workorders = sorted(process_parameter_workorder, key=lambda w: w.sequence) for i, workorder in enumerate(sorted_workorders): diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index b6173d78..c840ff17 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -329,7 +329,7 @@ class ResMrpWorkOrder(models.Model): def _get_surface_technics_purchase_ids(self): domain = [('origin', '=', self.production_id.name), ('purchase_type', '=', 'consignment')] purchase_orders = self.env['purchase.order'].search(domain) - purchase_orders_id = None + purchase_orders_id = self.env['purchase.order'] for po in purchase_orders: for line in po.order_line: if line.product_id.server_product_process_parameters_id == self.surface_technics_parameters_id: diff --git a/sf_manufacturing/models/stock.py b/sf_manufacturing/models/stock.py index 8597942f..01c7bd93 100644 --- a/sf_manufacturing/models/stock.py +++ b/sf_manufacturing/models/stock.py @@ -654,54 +654,47 @@ class StockPicking(models.Model): # 创建 外协出库入单 def create_outcontract_picking(self, workorders, item, sorted_workorders): - domain = [('origin', '=', item.name), ('name', 'ilike', 'OCOUT')] - if len(workorders) > 1: - workorders = workorders[0] - else: - domain += [ - ('surface_technics_parameters_id', '=', workorders[0].surface_technics_parameters_id.id)] - stock_picking = self.env['stock.picking'].search(domain) - if not stock_picking: - for workorder in workorders: - # pick_ids = [] - if not workorder.picking_ids: - # outcontract_stock_move = self.env['stock.move'].search([('production_id', '=', item.id)]) - # if not outcontract_stock_move: - # 创建一个新的补货组 - procurement_group_id = self.env['procurement.group'].create({ - 'name': workorder.name, - 'partner_id': self.partner_id.id, - }) - move_dest_id = False - # 如果当前工单是是制造订单的最后一个工单 - if workorder == item.workorder_ids[-1]: - move_dest_id = item.move_raw_ids[0].id - else: - # 从sorted_workorders中找到上一工单的move + 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'}) + else: + # 创建一个新的补货组 + procurement_group_id = self.env['procurement.group'].create({ + 'name': workorder.name, + 'partner_id': self.partner_id.id, + }) + move_dest_id = False + # 如果当前工单是是制造订单的最后一个工单 + if workorder == item.workorder_ids[-1]: + move_dest_id = item.move_raw_ids[0].id + else: + # 从sorted_workorders中找到上一工单的move + if sorted_workorders.index(workorder) > 0: move_dest_id = sorted_workorders[sorted_workorders.index(workorder) - 1].move_subcontract_workorder_ids[1].id - new_picking = True - outcontract_picking_type_in = self.env.ref( - 'sf_manufacturing.outcontract_picking_in').id, - outcontract_picking_type_out = self.env.ref( - 'sf_manufacturing.outcontract_picking_out').id, - moves_in = self.env['stock.move'].sudo().create( - self.env['stock.move']._get_stock_move_values_Res(item, outcontract_picking_type_in, procurement_group_id.id, move_dest_id)) - picking_in = self.create( - moves_in._get_new_picking_values_Res(item, workorder, 'WH/OCIN/')) - # pick_ids.append(picking_in.id) - moves_in.write( - {'picking_id': picking_in.id, 'state': 'waiting'}) - moves_in._assign_picking_post_process(new=new_picking) - moves_out = self.env['stock.move'].sudo().create( - self.env['stock.move']._get_stock_move_values_Res(item, outcontract_picking_type_out, procurement_group_id.id, moves_in.id)) - workorder.write({'move_subcontract_workorder_ids': [(6, 0, [moves_in.id, moves_out.id])]}) - picking_out = self.create( - moves_out._get_new_picking_values_Res(item, workorder, 'WH/OCOUT/')) - # pick_ids.append(picking_out.id) - moves_out.write( - {'picking_id': picking_out.id, 'state': 'waiting'}) - moves_out._assign_picking_post_process(new=new_picking) - + new_picking = True + outcontract_picking_type_in = self.env.ref( + 'sf_manufacturing.outcontract_picking_in').id, + outcontract_picking_type_out = self.env.ref( + 'sf_manufacturing.outcontract_picking_out').id, + moves_in = self.env['stock.move'].sudo().create( + self.env['stock.move']._get_stock_move_values_Res(item, outcontract_picking_type_in, procurement_group_id.id, move_dest_id)) + picking_in = self.create( + moves_in._get_new_picking_values_Res(item, workorder, 'WH/OCIN/')) + # pick_ids.append(picking_in.id) + moves_in.write( + {'picking_id': picking_in.id, 'state': 'waiting'}) + moves_in._assign_picking_post_process(new=new_picking) + moves_out = self.env['stock.move'].sudo().create( + self.env['stock.move']._get_stock_move_values_Res(item, outcontract_picking_type_out, procurement_group_id.id, moves_in.id)) + workorder.write({'move_subcontract_workorder_ids': [(6, 0, [moves_in.id, moves_out.id])]}) + picking_out = self.create( + moves_out._get_new_picking_values_Res(item, workorder, 'WH/OCOUT/')) + # pick_ids.append(picking_out.id) + moves_out.write( + {'picking_id': picking_out.id, 'state': 'waiting'}) + moves_out._assign_picking_post_process(new=new_picking) + @api.depends('move_type', 'immediate_transfer', 'move_ids.state', 'move_ids.picking_id') def _compute_state(self): diff --git a/sf_manufacturing/wizard/production_technology_re_adjust_wizard.py b/sf_manufacturing/wizard/production_technology_re_adjust_wizard.py index 80a02b2b..efc0e449 100644 --- a/sf_manufacturing/wizard/production_technology_re_adjust_wizard.py +++ b/sf_manufacturing/wizard/production_technology_re_adjust_wizard.py @@ -66,30 +66,30 @@ class ProductionTechnologyReAdjustWizard(models.TransientModel): # 工单采购单外协出入库单皆需取消 domain = [('production_id', '=', special.production_id.id)] if special.process_parameters_id: - domain += [('surface_technics_parameters_id', '=', special.process_parameters_id.id)] + domain += [('surface_technics_parameters_id', '=', special.process_parameters_id.id), ('state', '!=', 'cancel')] else: - domain += [('technology_design_id', '=', special.id)] + domain += [('technology_design_id', '=', special.id), ('state', '!=', 'cancel')] workorder = self.env['mrp.workorder'].search(domain) - previous_workorder = self.env['mrp.workorder'].search( - [('sequence', '=', workorder.sequence - 1), ('routing_type', '=', '表面工艺'), - ('production_id', '=', workorder.production_id.id)]) - if previous_workorder: - if previous_workorder.supplier_id != workorder.supplier_id: - is_cancel = True - else: - is_cancel = True - if workorder.state != 'cancel' and is_cancel is True: - workorder.write({'state': 'cancel'}) - workorder.picking_ids.write({'state': 'cancel'}) - workorder.picking_ids.move_ids.write({'state': 'cancel'}) - purchase_order = self.env['purchase.order'].search( - [('origin', '=', workorder.production_id.name)]) - for line in purchase_order.order_line: - if line.product_id.server_product_process_parameters_id == workorder.surface_technics_parameters_id: - purchase_order.write({'state': 'cancel'}) + # previous_workorder = self.env['mrp.workorder'].search( + # [('sequence', '=', workorder.sequence - 1), ('routing_type', '=', '表面工艺'), + # ('production_id', '=', workorder.production_id.id)]) + # if previous_workorder: + # if previous_workorder.supplier_id != workorder.supplier_id: + # is_cancel = True + # else: + # is_cancel = True + # if workorder.state != 'cancel' and is_cancel is True: + # workorder.write({'state': 'cancel'}) + # workorder.picking_ids.write({'state': 'cancel'}) + # workorder.picking_ids.move_ids.write({'state': 'cancel'}) + # purchase_order = self.env['purchase.order'].search( + # [('origin', '=', workorder.production_id.name)]) + # for line in purchase_order.order_line: + # if line.product_id.server_product_process_parameters_id == workorder.surface_technics_parameters_id: + # purchase_order.write({'state': 'cancel'}) else: workorder = self.env['mrp.workorder'].search( - [('technology_design_id', '=', special.id), ('production_id', '=', special.production_id.id)]) + [('technology_design_id', '=', special.id), ('production_id', '=', special.production_id.id), ('state', '!=', 'cancel')]) if not workorder: if special.route_id.routing_type == '表面工艺': product_production_process = self.env['product.template'].search( @@ -110,11 +110,12 @@ class ProductionTechnologyReAdjustWizard(models.TransientModel): workorder.blocked_by_workorder_ids = None else: if workorder.blocked_by_workorder_ids: - workorder.blocked_by_workorder_ids = blocked_by_workorder_ids[0] + workorder.blocked_by_workorder_ids = workorder.blocked_by_workorder_ids[0] productions._reset_work_order_sequence() - if self.production_id.product_id.categ_id.type == '成品': - productions._reset_subcontract_pick_purchase() - productions.get_subcontract_pick_purchase() + # 退回时不对外协出入库单和采购单做处理 + # if self.production_id.product_id.categ_id.type == '成品': + # productions._reset_subcontract_pick_purchase() + # productions.get_subcontract_pick_purchase() productions.is_adjust = True for item in productions: workorders = item.workorder_ids.filtered(lambda wo: wo.state not in ('cancel')).sorted( diff --git a/sf_manufacturing/wizard/production_technology_wizard.py b/sf_manufacturing/wizard/production_technology_wizard.py index 5fbdb7d7..8700dfb5 100644 --- a/sf_manufacturing/wizard/production_technology_wizard.py +++ b/sf_manufacturing/wizard/production_technology_wizard.py @@ -63,9 +63,9 @@ class ProductionTechnologyWizard(models.TransientModel): # 工单采购单外协出入库单皆需取消 domain = [('production_id', '=', special.production_id.id)] if special.process_parameters_id: - domain += [('surface_technics_parameters_id', '=', special.process_parameters_id.id)] + domain += [('surface_technics_parameters_id', '=', special.process_parameters_id.id), ('state', '!=', 'cancel')] else: - domain += [('technology_design_id', '=', special.id)] + domain += [('technology_design_id', '=', special.id), ('state', '!=', 'cancel')] workorder = self.env['mrp.workorder'].search(domain) previous_workorder = self.env['mrp.workorder'].search( [('sequence', '=', workorder.sequence - 1), ('routing_type', '=', '表面工艺'), @@ -87,7 +87,7 @@ class ProductionTechnologyWizard(models.TransientModel): else: if special.production_id.workorder_ids: workorder = self.env['mrp.workorder'].search( - [('technology_design_id', '=', special.id), ('production_id', '=', special.production_id.id)]) + [('technology_design_id', '=', special.id), ('production_id', '=', special.production_id.id), ('state', '!=', 'cancel')]) if not workorder: if special.route_id.routing_type == '表面工艺': product_production_process = self.env['product.template'].search( @@ -100,7 +100,7 @@ class ProductionTechnologyWizard(models.TransientModel): else: workorders_values.append( self.env['mrp.workorder'].json_workorder_str(special.production_id, special)) - special.production_id.write({'workorder_ids': workorders_values}) + special.production_id.write({'workorder_ids': workorders_values}) else: if len(workorder.blocked_by_workorder_ids) > 1: if workorder.sequence == 1: diff --git a/sf_sale/models/sale_order.py b/sf_sale/models/sale_order.py index 6a1d3023..fb9d1d5b 100644 --- a/sf_sale/models/sale_order.py +++ b/sf_sale/models/sale_order.py @@ -248,38 +248,19 @@ class RePurchaseOrder(models.Model): def get_purchase_order(self, consecutive_process_parameters, production, product_id_to_production_names): server_product_process = [] - production_process = product_id_to_production_names.get( - production.product_id.id) - purchase_order = self.env['purchase.order'].search( - [('state', '=', 'draft'), ('origin', '=', production.name), - ('purchase_type', '=', 'consignment')], order='name asc') for pp in consecutive_process_parameters: - server_template = self.env['product.template'].search( - [('server_product_process_parameters_id', '=', pp.surface_technics_parameters_id.id), - ('detailed_type', '=', 'service')]) - if not purchase_order: + purchase_order = pp._get_surface_technics_purchase_ids() + if purchase_order: + purchase_order.write({'state': 'draft'}) + else: + server_template = self.env['product.template'].search( + [('server_product_process_parameters_id', '=', pp.surface_technics_parameters_id.id), + ('detailed_type', '=', 'service')]) server_product_process.append((0, 0, { 'product_id': server_template.product_variant_id.id, 'product_qty': 1, 'product_uom': server_template.uom_id.id })) - for purchase in purchase_order: - for po in purchase.order_line: - if po.product_id == server_template.product_variant_id: - continue - if server_template.server_product_process_parameters_id != po.product_id.server_product_process_parameters_id: - purchase_order_line = self.env['purchase.order.line'].search( - [('product_id', '=', server_template.product_variant_id.id), - ('product_qty', '=', 1.0), ('id', '=', purchase.id)], limit=1, - order='id desc') - if not purchase_order_line: - server_product_process.append((0, 0, { - 'product_id': server_template.product_variant_id.id, - 'product_qty': 1, - 'product_uom': server_template.uom_id.id - })) - - if server_product_process: purchase_order = self.env['purchase.order'].sudo().create({ 'partner_id': server_template.seller_ids[0].partner_id.id, 'origin': production.name, From 54c502dd649a7774e9580542722a024d9d13412b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Thu, 5 Dec 2024 16:36:33 +0800 Subject: [PATCH 57/63] =?UTF-8?q?=E5=A4=84=E7=90=86=E4=BE=9B=E5=BA=94?= =?UTF-8?q?=E5=95=86=E7=9B=B8=E5=90=8C=E7=9A=84=E7=89=B9=E6=AE=8A=E8=A1=A8?= =?UTF-8?q?=E9=9D=A2=E5=B7=A5=E8=89=BA=E4=B8=8D=E8=83=BD=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wizard/production_technology_wizard.py | 34 +++++++++---------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/sf_manufacturing/wizard/production_technology_wizard.py b/sf_manufacturing/wizard/production_technology_wizard.py index 8700dfb5..f49480aa 100644 --- a/sf_manufacturing/wizard/production_technology_wizard.py +++ b/sf_manufacturing/wizard/production_technology_wizard.py @@ -59,7 +59,7 @@ class ProductionTechnologyWizard(models.TransientModel): for special in special_design: workorders_values = [] if special.active is False: - is_cancel = False + # is_cancel = False # 工单采购单外协出入库单皆需取消 domain = [('production_id', '=', special.production_id.id)] if special.process_parameters_id: @@ -67,23 +67,21 @@ class ProductionTechnologyWizard(models.TransientModel): else: domain += [('technology_design_id', '=', special.id), ('state', '!=', 'cancel')] workorder = self.env['mrp.workorder'].search(domain) - previous_workorder = self.env['mrp.workorder'].search( - [('sequence', '=', workorder.sequence - 1), ('routing_type', '=', '表面工艺'), - ('production_id', '=', workorder.production_id.id)]) - if previous_workorder: - if previous_workorder.supplier_id != workorder.supplier_id: - is_cancel = True - else: - is_cancel = True - if workorder.state != 'cancel' and is_cancel is True: - workorder.write({'state': 'cancel'}) - workorder.picking_ids.write({'state': 'cancel'}) - workorder.picking_ids.move_ids.write({'state': 'cancel'}) - purchase_order = self.env['purchase.order'].search( - [('origin', '=', workorder.production_id.name), ('purchase_type', '=', 'consignment')]) - for line in purchase_order.order_line: - if line.product_id.server_product_process_parameters_id == workorder.surface_technics_parameters_id: - purchase_order.write({'state': 'cancel'}) + # previous_workorder = self.env['mrp.workorder'].search( + # [('sequence', '=', workorder.sequence - 1), ('routing_type', '=', '表面工艺'), + # ('production_id', '=', workorder.production_id.id)]) + # if previous_workorder: + # if previous_workorder.supplier_id != workorder.supplier_id: + # is_cancel = True + # if workorder.state != 'cancel' and is_cancel is True: + workorder.write({'state': 'cancel'}) + workorder.picking_ids.write({'state': 'cancel'}) + workorder.picking_ids.move_ids.write({'state': 'cancel'}) + purchase_order = self.env['purchase.order'].search( + [('origin', '=', workorder.production_id.name), ('purchase_type', '=', 'consignment')]) + for line in purchase_order.order_line: + if line.product_id.server_product_process_parameters_id == workorder.surface_technics_parameters_id: + purchase_order.write({'state': 'cancel'}) else: if special.production_id.workorder_ids: workorder = self.env['mrp.workorder'].search( From 5b94a0624c83a24d2872d408489804a960c80bef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Thu, 5 Dec 2024 16:55:51 +0800 Subject: [PATCH 58/63] =?UTF-8?q?=E5=B7=A5=E8=89=BA=E8=AE=BE=E8=AE=A1?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=B7=A5=E5=BA=8F=E5=8F=AA=E9=80=89=E6=8B=A9?= =?UTF-8?q?=E4=BA=86=E5=8F=82=E6=95=B0=E6=97=B6=E7=A1=AE=E8=AE=A4=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/sf_technology_design.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/sf_manufacturing/models/sf_technology_design.py b/sf_manufacturing/models/sf_technology_design.py index a38e7897..392aa021 100644 --- a/sf_manufacturing/models/sf_technology_design.py +++ b/sf_manufacturing/models/sf_technology_design.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- -from odoo import fields, models +from odoo import fields, models, api, _ +from odoo.exceptions import ValidationError class sf_technology_design(models.Model): @@ -29,3 +30,11 @@ class sf_technology_design(models.Model): def unlink_technology_design(self): self.active = False + + + @api.model_create_multi + def create(self, vals_list): + for vals in vals_list: + if not vals.get('route_id'): + raise ValidationError(_("工序不能为空")) + return super(sf_technology_design, self).create(vals_list) From 08e4541a962cf5053d318b6295c9f366d8670e78 Mon Sep 17 00:00:00 2001 From: mgw <1392924357@qq.com> Date: Thu, 5 Dec 2024 17:01:10 +0800 Subject: [PATCH 59/63] =?UTF-8?q?=E7=89=B9=E6=AE=8A=E8=A1=A8=E9=9D=A2?= =?UTF-8?q?=E5=B7=A5=E8=89=BA=E9=87=87=E8=B4=AD=E5=8D=95=E8=BF=98=E6=98=AF?= =?UTF-8?q?=E6=9C=89=E5=90=88=E5=B9=B6=E7=9A=84=E6=83=85=E5=86=B5-?= =?UTF-8?q?=E4=B8=94=E9=87=8D=E5=A4=8D=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_sale/models/sale_order.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sf_sale/models/sale_order.py b/sf_sale/models/sale_order.py index fb9d1d5b..ca851fc6 100644 --- a/sf_sale/models/sale_order.py +++ b/sf_sale/models/sale_order.py @@ -247,8 +247,8 @@ class RePurchaseOrder(models.Model): raise UserError('请对【产品】中的【税】进行选择') def get_purchase_order(self, consecutive_process_parameters, production, product_id_to_production_names): - server_product_process = [] for pp in consecutive_process_parameters: + server_product_process = [] purchase_order = pp._get_surface_technics_purchase_ids() if purchase_order: purchase_order.write({'state': 'draft'}) From 37c47b0a54610ddebdba1944b9c7dd4ff10f3d6d Mon Sep 17 00:00:00 2001 From: mgw <1392924357@qq.com> Date: Thu, 5 Dec 2024 18:14:19 +0800 Subject: [PATCH 60/63] =?UTF-8?q?=E5=AF=B9=E5=90=88=E5=B9=B6=E5=90=8E?= =?UTF-8?q?=E7=9A=84=E9=87=87=E8=B4=AD=E5=8D=95=E4=BF=AE=E6=94=B9=E5=8C=B9?= =?UTF-8?q?=E9=85=8D=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_dlm/models/stock_rule_inherit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sf_dlm/models/stock_rule_inherit.py b/sf_dlm/models/stock_rule_inherit.py index b1e5b911..4a40ca2f 100644 --- a/sf_dlm/models/stock_rule_inherit.py +++ b/sf_dlm/models/stock_rule_inherit.py @@ -44,7 +44,7 @@ class StockRuleInherit(models.Model): po = self.env['purchase.order'].sudo().search([ ('partner_id', '=', supplier.partner_id.id), ('company_id', '=', procurement.company_id.id), # 保证公司一致 - ('origin', '=', procurement.origin), # 根据来源匹配 + ('origin', 'like', procurement.origin), # 根据来源匹配 ('state', '=', 'draft') # 状态为草稿 ], limit=1) logging.info("po=: %s", po) From ab692dfb250782e50ec6bb2adcef7945c52769aa Mon Sep 17 00:00:00 2001 From: mgw <1392924357@qq.com> Date: Thu, 5 Dec 2024 18:25:08 +0800 Subject: [PATCH 61/63] =?UTF-8?q?Merge=20branch=20'develop'=20of=20https:/?= =?UTF-8?q?/e.coding.net/jikimo-hn/jikimo=5Fsfs/jikimo=5Fsf=20into=20featu?= =?UTF-8?q?re/=E5=88=B6=E9=80=A0=E5=8A=9F=E8=83=BD=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_dlm/models/stock_rule_inherit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sf_dlm/models/stock_rule_inherit.py b/sf_dlm/models/stock_rule_inherit.py index b1e5b911..4a40ca2f 100644 --- a/sf_dlm/models/stock_rule_inherit.py +++ b/sf_dlm/models/stock_rule_inherit.py @@ -44,7 +44,7 @@ class StockRuleInherit(models.Model): po = self.env['purchase.order'].sudo().search([ ('partner_id', '=', supplier.partner_id.id), ('company_id', '=', procurement.company_id.id), # 保证公司一致 - ('origin', '=', procurement.origin), # 根据来源匹配 + ('origin', 'like', procurement.origin), # 根据来源匹配 ('state', '=', 'draft') # 状态为草稿 ], limit=1) logging.info("po=: %s", po) From a6979b213bac33ec54cea90a1a847ce0b707e613 Mon Sep 17 00:00:00 2001 From: guanhuan Date: Mon, 9 Dec 2024 09:35:41 +0800 Subject: [PATCH 62/63] =?UTF-8?q?=E6=89=8B=E5=8A=A8=E5=88=9B=E5=BB=BA?= =?UTF-8?q?=E7=9A=84=E9=87=87=E8=B4=AD=E5=8D=95=E7=94=9F=E6=88=90=E7=9A=84?= =?UTF-8?q?=E5=86=85=E9=83=A8=E8=B0=83=E6=8B=A8=E5=8D=95=E6=B2=A1=E6=9C=89?= =?UTF-8?q?=E6=BA=90=E5=8D=95=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/stock.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sf_manufacturing/models/stock.py b/sf_manufacturing/models/stock.py index 0c01a57c..ea8ca7c6 100644 --- a/sf_manufacturing/models/stock.py +++ b/sf_manufacturing/models/stock.py @@ -980,7 +980,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 From 1c4a6ca85e781a6338e4c6b80c66e2ee3526d3e2 Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Mon, 9 Dec 2024 16:07:34 +0800 Subject: [PATCH 63/63] =?UTF-8?q?=E5=BC=80=E6=94=BE=E8=BF=94=E5=B7=A5?= =?UTF-8?q?=E5=85=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_workorder.py | 2 +- sf_manufacturing/views/mrp_workorder_view.xml | 2 +- sf_quality/models/quality_cnc_test.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) 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/views/mrp_workorder_view.xml b/sf_manufacturing/views/mrp_workorder_view.xml index be1a6523..13fff868 100644 --- a/sf_manufacturing/views/mrp_workorder_view.xml +++ b/sf_manufacturing/views/mrp_workorder_view.xml @@ -200,7 +200,7 @@ -