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 @@