From 4d38a11c3ca8ba294b97ec5346c42833bffe9248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Tue, 25 Mar 2025 15:58:24 +0800 Subject: [PATCH 01/15] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=A2=E4=BB=B7?= =?UTF-8?q?=E5=8D=95=E5=88=A4=E6=96=AD=E8=A1=8C=E9=A1=B9=E7=9B=AE=E4=BB=B7?= =?UTF-8?q?=E6=A0=BC=E4=B8=8D=E8=83=BD=E4=B8=BA0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/purchase_order.py | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/sf_manufacturing/models/purchase_order.py b/sf_manufacturing/models/purchase_order.py index 3d71b6c7..d05e6b63 100644 --- a/sf_manufacturing/models/purchase_order.py +++ b/sf_manufacturing/models/purchase_order.py @@ -58,19 +58,7 @@ class PurchaseOrder(models.Model): origins = [order.name for order in purchase.picking_ids] production_id = self.env['mrp.production'].search([('origin', 'in', origins)]) purchase.production_count = len(production_id) - - # def button_confirm(self): - # super().button_confirm() - # workorders = self.env['mrp.workorder'].search([('purchase_id', '=', self.id), ('state', '!=', 'cancel')]) - # for workorder in workorders: - # if workorder.routing_type == '表面工艺' and workorder.is_subcontract is True: - # move_out = workorder.move_subcontract_workorder_ids[1] - # for mo in move_out: - # 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(workorder.production_id, workorder)) - # return True + origin_sale_id = fields.Many2one('sale.order', string='销售订单号', store=True, compute='_compute_origin_sale_id') origin_sale_ids = fields.Many2many('sale.order', string='销售订单号(多个)', store=True, @@ -146,4 +134,11 @@ class PurchaseOrderLine(models.Model): # 如果手动设置了 part_name,使用手动设置的值 record.part_name = record.manual_part_name if record.manual_part_number: - record.part_number = record.manual_part_number \ No newline at end of file + record.part_number = record.manual_part_number + + def write(self, vals): + if 'product_qty' in vals and vals.get('product_qty') <= 0: + raise UserError('请对【产品】中的【数量】进行输入') + if 'price_unit' in vals and vals.get('price_unit') <= 0: + raise UserError('请对【产品】中的【单价】进行输入') + return super(PurchaseOrderLine, self).write(vals) \ No newline at end of file From 03539c7ed3f8eb859a31ef4ab14fa2c716716d29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Tue, 25 Mar 2025 16:20:54 +0800 Subject: [PATCH 02/15] =?UTF-8?q?=E8=AF=A2=E4=BB=B7=E5=8D=95=E8=A1=8C?= =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E4=BB=B7=E6=A0=BC=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/purchase_order.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/sf_manufacturing/models/purchase_order.py b/sf_manufacturing/models/purchase_order.py index d05e6b63..3cc0d877 100644 --- a/sf_manufacturing/models/purchase_order.py +++ b/sf_manufacturing/models/purchase_order.py @@ -58,6 +58,15 @@ class PurchaseOrder(models.Model): origins = [order.name for order in purchase.picking_ids] production_id = self.env['mrp.production'].search([('origin', 'in', origins)]) purchase.production_count = len(production_id) + + def write(self, vals): + for record in self: + for line in record.order_line: + if line.product_qty <= 0: + raise UserError('请对【产品】中的【数量】进行输入') + if line.price_unit <= 0: + raise UserError('请对【产品】中的【单价】进行输入') + return super(PurchaseOrder, self).write(vals) origin_sale_id = fields.Many2one('sale.order', string='销售订单号', store=True, compute='_compute_origin_sale_id') @@ -134,11 +143,4 @@ class PurchaseOrderLine(models.Model): # 如果手动设置了 part_name,使用手动设置的值 record.part_name = record.manual_part_name if record.manual_part_number: - record.part_number = record.manual_part_number - - def write(self, vals): - if 'product_qty' in vals and vals.get('product_qty') <= 0: - raise UserError('请对【产品】中的【数量】进行输入') - if 'price_unit' in vals and vals.get('price_unit') <= 0: - raise UserError('请对【产品】中的【单价】进行输入') - return super(PurchaseOrderLine, self).write(vals) \ No newline at end of file + record.part_number = record.manual_part_number \ No newline at end of file From 8ec746858c97e68979b0cfa8fee3068000e6e372 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Tue, 25 Mar 2025 16:25:05 +0800 Subject: [PATCH 03/15] =?UTF-8?q?=E8=AF=A2=E4=BB=B7=E5=8D=95=E8=A1=8C?= =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E4=BB=B7=E6=A0=BC=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/purchase_order.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sf_manufacturing/models/purchase_order.py b/sf_manufacturing/models/purchase_order.py index 3cc0d877..5ee7d8f2 100644 --- a/sf_manufacturing/models/purchase_order.py +++ b/sf_manufacturing/models/purchase_order.py @@ -60,13 +60,14 @@ class PurchaseOrder(models.Model): purchase.production_count = len(production_id) def write(self, vals): + res = super(PurchaseOrder, self).write(vals) for record in self: for line in record.order_line: if line.product_qty <= 0: raise UserError('请对【产品】中的【数量】进行输入') if line.price_unit <= 0: raise UserError('请对【产品】中的【单价】进行输入') - return super(PurchaseOrder, self).write(vals) + return res origin_sale_id = fields.Many2one('sale.order', string='销售订单号', store=True, compute='_compute_origin_sale_id') From 4ca655ad511e2c53e25639a84477cd4a9e5aa7b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Tue, 25 Mar 2025 17:09:22 +0800 Subject: [PATCH 04/15] =?UTF-8?q?=E9=87=87=E8=B4=AD=E7=94=B3=E8=AF=B7?= =?UTF-8?q?=E8=B7=B3=E8=BD=AC=E5=88=B0=E9=87=87=E8=B4=AD=E5=8D=95=EF=BC=8C?= =?UTF-8?q?=E4=B8=8D=E9=BB=98=E8=AE=A4=E7=AD=9B=E9=80=89=E8=AF=A2=E4=BB=B7?= =?UTF-8?q?=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jikimo_purchase_request/models/purchase_request.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/jikimo_purchase_request/models/purchase_request.py b/jikimo_purchase_request/models/purchase_request.py index 4b5f86ba..9e610612 100644 --- a/jikimo_purchase_request/models/purchase_request.py +++ b/jikimo_purchase_request/models/purchase_request.py @@ -1,4 +1,5 @@ import re +import ast from odoo import models, fields, api @@ -20,6 +21,13 @@ class PurchaseRequest(models.Model): if pr.state != 'draft' and pr.rule_new_add: pr.rule_new_add = False + def action_view_purchase_order(self): + action = super(PurchaseRequest, self).action_view_purchase_order() + origin_context = ast.literal_eval(action['context']) + if 'search_default_draft' in origin_context: + origin_context.pop('search_default_draft') + action['context'] = origin_context + return action class PurchaseRequestLine(models.Model): _inherit = 'purchase.request.line' From 40dcd11da85ad088b47eaa2ad9f9263cb4ee22eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Wed, 26 Mar 2025 08:42:08 +0800 Subject: [PATCH 05/15] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E4=BE=9B=E8=B4=A7?= =?UTF-8?q?=E8=B7=AF=E7=BA=BF=E9=80=89=E6=8B=A9=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../__init__.py | 3 ++ .../__manifest__.py | 28 +++++++++++++++++++ .../models/__init__.py | 3 ++ .../models/models.py | 24 ++++++++++++++++ .../static/src/js/ir_model_extend.js | 14 ++++++++++ sf_manufacturing/models/purchase_order.py | 5 ++-- 6 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 jikimo_purchase_request_tier_validation/__init__.py create mode 100644 jikimo_purchase_request_tier_validation/__manifest__.py create mode 100644 jikimo_purchase_request_tier_validation/models/__init__.py create mode 100644 jikimo_purchase_request_tier_validation/models/models.py create mode 100644 jikimo_purchase_request_tier_validation/static/src/js/ir_model_extend.js diff --git a/jikimo_purchase_request_tier_validation/__init__.py b/jikimo_purchase_request_tier_validation/__init__.py new file mode 100644 index 00000000..cde864ba --- /dev/null +++ b/jikimo_purchase_request_tier_validation/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import models diff --git a/jikimo_purchase_request_tier_validation/__manifest__.py b/jikimo_purchase_request_tier_validation/__manifest__.py new file mode 100644 index 00000000..403297ab --- /dev/null +++ b/jikimo_purchase_request_tier_validation/__manifest__.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +{ + 'name': "机企猫 采购审批流程", + + 'summary': """ + Short (1 phrase/line) summary of the module's purpose, used as + subtitle on modules listing or apps.openerp.com""", + + 'description': """ + Long description of module's purpose + """, + + 'author': "My Company", + 'website': "https://www.yourcompany.com", + + # Categories can be used to filter modules in modules listing + # Check https://github.com/odoo/odoo/blob/16.0/odoo/addons/base/data/ir_module_category_data.xml + # for the full list + 'category': 'Uncategorized', + 'version': '0.1', + + # any module necessary for this one to work correctly + 'depends': ['purchase_request_tier_validation'], + + # always loaded + 'data': [ + ], +} diff --git a/jikimo_purchase_request_tier_validation/models/__init__.py b/jikimo_purchase_request_tier_validation/models/__init__.py new file mode 100644 index 00000000..5305644d --- /dev/null +++ b/jikimo_purchase_request_tier_validation/models/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import models \ No newline at end of file diff --git a/jikimo_purchase_request_tier_validation/models/models.py b/jikimo_purchase_request_tier_validation/models/models.py new file mode 100644 index 00000000..4d8e9b3d --- /dev/null +++ b/jikimo_purchase_request_tier_validation/models/models.py @@ -0,0 +1,24 @@ +from odoo import models, fields, api, _ +from odoo.exceptions import ValidationError +import logging + +_logger = logging.getLogger(__name__) + + +class PurchaseRequestTierValidation(models.Model): + _name = 'purchase.request.tier.validation' + + + def _validate_tier(self, tiers=False): + res = super(PurchaseRequestTierValidation, self)._validate_tier(tiers) + + # 检查是否所有审批都已通过 + all_approved = all( + tier_review.status == 'approved' + for tier_review in self.review_ids + ) + + if self.review_ids and all_approved: # 确保有审批记录 + self.state = 'approved' + + return res diff --git a/jikimo_purchase_request_tier_validation/static/src/js/ir_model_extend.js b/jikimo_purchase_request_tier_validation/static/src/js/ir_model_extend.js new file mode 100644 index 00000000..97d6f38c --- /dev/null +++ b/jikimo_purchase_request_tier_validation/static/src/js/ir_model_extend.js @@ -0,0 +1,14 @@ +/** @odoo-module **/ + +import {registerPatch} from "@mail/model/model_core"; + +registerPatch({ + name: "ir.model.review", + fields: { + availableWebViews: { + compute() { + return ["list", "form", "activity"]; + }, + }, + }, +}); \ No newline at end of file diff --git a/sf_manufacturing/models/purchase_order.py b/sf_manufacturing/models/purchase_order.py index 5ee7d8f2..044b68e1 100644 --- a/sf_manufacturing/models/purchase_order.py +++ b/sf_manufacturing/models/purchase_order.py @@ -59,15 +59,14 @@ class PurchaseOrder(models.Model): production_id = self.env['mrp.production'].search([('origin', 'in', origins)]) purchase.production_count = len(production_id) - def write(self, vals): - res = super(PurchaseOrder, self).write(vals) + def button_confirm(self): for record in self: for line in record.order_line: if line.product_qty <= 0: raise UserError('请对【产品】中的【数量】进行输入') if line.price_unit <= 0: raise UserError('请对【产品】中的【单价】进行输入') - return res + return super(PurchaseOrder, self).button_confirm() origin_sale_id = fields.Many2one('sale.order', string='销售订单号', store=True, compute='_compute_origin_sale_id') From 2e74c76e079cc74e4d70bc35966c462bd71320cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Wed, 26 Mar 2025 08:43:18 +0800 Subject: [PATCH 06/15] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E4=BE=9B=E8=B4=A7?= =?UTF-8?q?=E8=B7=AF=E7=BA=BF=E9=80=89=E6=8B=A9=E6=8A=A5=E9=94=99=EF=BC=8C?= =?UTF-8?q?=E9=87=87=E8=B4=AD=E7=94=B3=E8=AF=B7=E5=AE=A1=E6=89=B9=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E7=BC=96=E7=A8=8B=E5=B7=B2=E5=AE=A1=E6=89=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../static/src/js/ir_model_extend.js | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 jikimo_purchase_request_tier_validation/static/src/js/ir_model_extend.js diff --git a/jikimo_purchase_request_tier_validation/static/src/js/ir_model_extend.js b/jikimo_purchase_request_tier_validation/static/src/js/ir_model_extend.js deleted file mode 100644 index 97d6f38c..00000000 --- a/jikimo_purchase_request_tier_validation/static/src/js/ir_model_extend.js +++ /dev/null @@ -1,14 +0,0 @@ -/** @odoo-module **/ - -import {registerPatch} from "@mail/model/model_core"; - -registerPatch({ - name: "ir.model.review", - fields: { - availableWebViews: { - compute() { - return ["list", "form", "activity"]; - }, - }, - }, -}); \ No newline at end of file From bdb8763fea7c7e0186f3dfa731a3a64e6c7a6ec3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Wed, 26 Mar 2025 09:07:01 +0800 Subject: [PATCH 07/15] =?UTF-8?q?=E9=87=87=E8=B4=AD=E7=94=B3=E8=AF=B7?= =?UTF-8?q?=E5=AE=A1=E6=89=B9=E5=AE=8C=E6=88=90=E5=90=8E=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E5=8F=98=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jikimo_purchase_request_tier_validation/models/models.py | 6 +++--- jikimo_purchase_tier_validation/__manifest__.py | 8 +++----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/jikimo_purchase_request_tier_validation/models/models.py b/jikimo_purchase_request_tier_validation/models/models.py index 4d8e9b3d..0070a4c7 100644 --- a/jikimo_purchase_request_tier_validation/models/models.py +++ b/jikimo_purchase_request_tier_validation/models/models.py @@ -5,12 +5,12 @@ import logging _logger = logging.getLogger(__name__) -class PurchaseRequestTierValidation(models.Model): - _name = 'purchase.request.tier.validation' +class PurchaseRequest(models.Model): + _inherit = 'purchase.request' def _validate_tier(self, tiers=False): - res = super(PurchaseRequestTierValidation, self)._validate_tier(tiers) + res = super(PurchaseRequest, self)._validate_tier(tiers) # 检查是否所有审批都已通过 all_approved = all( diff --git a/jikimo_purchase_tier_validation/__manifest__.py b/jikimo_purchase_tier_validation/__manifest__.py index 4d676d8f..ed0cecb7 100644 --- a/jikimo_purchase_tier_validation/__manifest__.py +++ b/jikimo_purchase_tier_validation/__manifest__.py @@ -1,14 +1,12 @@ # -*- coding: utf-8 -*- { - 'name': "机企猫 采购审批流程", + 'name': "机企猫 采购申请审批流程", 'summary': """ - Short (1 phrase/line) summary of the module's purpose, used as - subtitle on modules listing or apps.openerp.com""", + 采购申请审批流程""", 'description': """ - Long description of module's purpose - """, + 采购申请审批流程""", 'author': "My Company", 'website': "https://www.yourcompany.com", From 236158d556ca50a2a96e7a1bb24f5c854cafbfa2 Mon Sep 17 00:00:00 2001 From: guanhuan Date: Wed, 26 Mar 2025 13:35:28 +0800 Subject: [PATCH 08/15] =?UTF-8?q?=E8=B0=83=E6=8B=A8=E5=8D=95=E9=9B=B6?= =?UTF-8?q?=E4=BB=B6=E5=9B=BE=E5=8F=B7=E4=BF=A1=E6=81=AF=E6=90=9C=E7=B4=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/product_template.py | 26 ++----------------- sf_manufacturing/models/stock.py | 12 +++++++++ sf_manufacturing/views/stock_picking_view.xml | 13 +++------- 3 files changed, 18 insertions(+), 33 deletions(-) diff --git a/sf_manufacturing/models/product_template.py b/sf_manufacturing/models/product_template.py index fbea675c..fc12ca79 100644 --- a/sf_manufacturing/models/product_template.py +++ b/sf_manufacturing/models/product_template.py @@ -777,33 +777,11 @@ class ResProductMo(models.Model): manual_quotation = fields.Boolean('人工编程', default=False, readonly=True) machining_drawings = fields.Binary('2D加工图纸', readonly=True) quality_standard = fields.Binary('质检标准', readonly=True) - part_name = fields.Char(string='零件名称', compute='_compute_related_product', readonly=True, store=True) - part_number = fields.Char(string='零件图号', compute='_compute_related_product', readonly=True, store=True) + part_name = fields.Char(string='零件名称', readonly=True) + part_number = fields.Char(string='零件图号', readonly=True) machining_drawings_name = fields.Char(string='零件图号名称', readonly=True) machining_drawings_mimetype = fields.Char(string='零件图号类型', readonly=True) - @api.depends('name') - def _compute_related_product(self): - for record in self: - if record.categ_id.name == '坯料': - product_name = '' - match = re.search(r'(S\d{5}-\d)', record.name) - # 如果匹配成功,提取结果 - if match: - product_name = match.group(0) - sale_order_name = '' - match_sale = re.search(r'S(\d+)', record.name) - if match_sale: - sale_order_name = match_sale.group(0) - sale_order = self.env['sale.order'].sudo().search( - [('name', '=', sale_order_name)]) - if sale_order: - filtered_order_line = sale_order.order_line.filtered( - lambda order_line: re.search(f'{product_name}$', order_line.product_id.name) - ) - record.part_number = filtered_order_line.product_id.part_number if filtered_order_line else None - record.part_name = filtered_order_line.product_id.part_name if filtered_order_line else None - @api.constrains('tool_length') def _check_tool_length_size(self): if self.tool_length > 1000000: diff --git a/sf_manufacturing/models/stock.py b/sf_manufacturing/models/stock.py index 8f5e0023..c5047f6c 100644 --- a/sf_manufacturing/models/stock.py +++ b/sf_manufacturing/models/stock.py @@ -562,6 +562,18 @@ class StockPicking(models.Model): sale_order_id = fields.Many2one('sale.order', '销售单号', compute='_compute_move_ids', store=True) picking_type_sequence_code = fields.Char(related='picking_type_id.sequence_code') + part_numbers = fields.Char(string="零件图号", compute='_compute_part_info', store=True, index=True) + part_names = fields.Char(string="零件名称", compute='_compute_part_info', store=True, index=True) + + @api.depends('move_ids_without_package.part_number', 'move_ids_without_package.part_name') + def _compute_part_info(self): + for picking in self: + # 聚合所有关联行的 part_number 和 part_name + part_numbers = picking.move_ids_without_package.mapped('part_number') + part_names = picking.move_ids_without_package.mapped('part_name') + picking.part_numbers = ','.join(filter(None, part_numbers)) + picking.part_names = ','.join(filter(None, part_names)) + @api.depends('move_ids', 'move_ids.product_id') def _compute_move_ids(self): for item in self: diff --git a/sf_manufacturing/views/stock_picking_view.xml b/sf_manufacturing/views/stock_picking_view.xml index 3cb877a9..f5b1941b 100644 --- a/sf_manufacturing/views/stock_picking_view.xml +++ b/sf_manufacturing/views/stock_picking_view.xml @@ -68,14 +68,8 @@ context="{'group_by': 'retrospect_ref'}"/> - - + + @@ -97,7 +91,8 @@ True - From 6a70f3b88a4dd937dc95d1987ed56edd593650a6 Mon Sep 17 00:00:00 2001 From: guanhuan Date: Wed, 26 Mar 2025 14:32:53 +0800 Subject: [PATCH 09/15] =?UTF-8?q?=E5=9D=AF=E6=96=99=E5=86=97=E4=BD=99?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=8F=8F=E8=BF=B0=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_base/models/base.py | 1 + sf_base/views/base_view.xml | 1 + sf_mrs_connect/models/sync_common.py | 2 ++ 3 files changed, 4 insertions(+) diff --git a/sf_base/models/base.py b/sf_base/models/base.py index d7a71e1e..54a1fe1f 100644 --- a/sf_base/models/base.py +++ b/sf_base/models/base.py @@ -421,3 +421,4 @@ class EmbryoRedundancy(models.Model): width = fields.Float('宽度(mm)', required=True) height = fields.Float('高度(mm)', required=True) active = fields.Boolean('有效', default=True) + remark = fields.Char('描述') diff --git a/sf_base/views/base_view.xml b/sf_base/views/base_view.xml index bd6f103b..ccac31c9 100644 --- a/sf_base/views/base_view.xml +++ b/sf_base/views/base_view.xml @@ -645,6 +645,7 @@ + diff --git a/sf_mrs_connect/models/sync_common.py b/sf_mrs_connect/models/sync_common.py index cd0d8405..652ec3eb 100644 --- a/sf_mrs_connect/models/sync_common.py +++ b/sf_mrs_connect/models/sync_common.py @@ -3214,6 +3214,7 @@ class EmbryoRedundancySync(models.Model): embryo_redundancy.width = item['width'] embryo_redundancy.height = item['height'] embryo_redundancy.active = item['active'] + embryo_redundancy.remark = item['remark'] else: self.env['sf.embryo.redundancy'].sudo().create({ "name": item['name'], @@ -3222,4 +3223,5 @@ class EmbryoRedundancySync(models.Model): "width": item['width'], "height": item['height'], "active": item['active'], + "remark": item['remark'], }) \ No newline at end of file From 11a52174301574349a492c815aa089cc75b43a7e Mon Sep 17 00:00:00 2001 From: liaodanlong Date: Wed, 26 Mar 2025 16:57:47 +0800 Subject: [PATCH 10/15] =?UTF-8?q?=E5=AD=90=E5=88=B6=E9=80=A0=E8=AE=A2?= =?UTF-8?q?=E5=8D=95=E9=9B=B6=E4=BB=B6=E5=9B=BE=E5=8F=B7=E4=B8=8E=E9=9B=B6?= =?UTF-8?q?=E4=BB=B6=E5=90=8D=E7=A7=B0=E8=8E=B7=E5=8F=96=E6=96=B9=E5=BC=8F?= =?UTF-8?q?=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_production.py | 38 +++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py index 15715be4..12ff3eda 100644 --- a/sf_manufacturing/models/mrp_production.py +++ b/sf_manufacturing/models/mrp_production.py @@ -5,6 +5,8 @@ import logging import json import os import re +import traceback + import requests from itertools import groupby from collections import defaultdict, namedtuple @@ -257,14 +259,46 @@ class MrpProduction(models.Model): ], string='工序状态', default='待装夹') # 零件图号 - part_number = fields.Char('零件图号', related='product_id.part_number', readonly=True) + part_number = fields.Char('零件图号', compute='_compute_part_info', store=True) # 上传零件图纸 part_drawing = fields.Binary('零件图纸', related='product_id.machining_drawings', readonly=True) quality_standard = fields.Binary('质检标准', related='product_id.quality_standard', readonly=True) - part_name = fields.Char(string='零件名称', related='product_id.part_name', readonly=True) + part_name = fields.Char(string='零件名称', compute='_compute_part_info', store=True) + @api.depends('product_id') + def _compute_part_info(self): + try: + for production_id in self: + if production_id.product_id.categ_id.type == '成品': + production_id.part_number = production_id.product_id.part_number + production_id.part_name = production_id.product_id.part_name + elif production_id.product_id.categ_id.type == '坯料': + product_name = '' + match = re.search(r'(S\d{5}-\d)', production_id.product_id.name) + # 如果匹配成功,提取结果 + if match: + product_name = match.group(0) + if production_id.picking_id.sale_order_id: + sale_order = production_id.picking_id.sale_order_id + else: + sale_order_name = '' + match = re.search(r'(S\d+)', production_id.product_id.name) + if match: + sale_order_name = match.group(0) + sale_order = self.env['sale.order'].sudo().search( + [('name', '=', sale_order_name)]) + filtered_order_line = sale_order.order_line.filtered( + lambda production: re.search(f'{product_name}$', production.product_id.name) + ) + + if filtered_order_line: + production_id.part_number = filtered_order_line.part_number + production_id.part_name = filtered_order_line.part_name + except Exception as e: + traceback_error = traceback.format_exc() + logging.error("制造订单零件图号 零件名称获取失败:%s" % traceback_error) # 判断制造的产品类型 production_product_type = fields.Selection([ From dd6e8b67077e0ea7a2fc0dfff15c676e45dbd126 Mon Sep 17 00:00:00 2001 From: liaodanlong Date: Thu, 27 Mar 2025 15:21:15 +0800 Subject: [PATCH 11/15] =?UTF-8?q?=E8=B0=83=E8=AF=95=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_production.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py index 12ff3eda..971f331e 100644 --- a/sf_manufacturing/models/mrp_production.py +++ b/sf_manufacturing/models/mrp_production.py @@ -289,10 +289,10 @@ class MrpProduction(models.Model): sale_order_name = match.group(0) sale_order = self.env['sale.order'].sudo().search( [('name', '=', sale_order_name)]) + logging.info("product_name is :%s" % product_name) filtered_order_line = sale_order.order_line.filtered( lambda production: re.search(f'{product_name}$', production.product_id.name) ) - if filtered_order_line: production_id.part_number = filtered_order_line.part_number production_id.part_name = filtered_order_line.part_name From 4b6f04aa9d283f7c6c37bdfbc556a403b8f85b12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Thu, 27 Mar 2025 15:51:16 +0800 Subject: [PATCH 12/15] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/views/sale_order_views.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sf_manufacturing/views/sale_order_views.xml b/sf_manufacturing/views/sale_order_views.xml index 10700231..a6bebf9c 100644 --- a/sf_manufacturing/views/sale_order_views.xml +++ b/sf_manufacturing/views/sale_order_views.xml @@ -18,7 +18,7 @@ - + From 4cbcf08da8503bd6b9cdb23d6974fcb1b22453d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Thu, 27 Mar 2025 16:10:07 +0800 Subject: [PATCH 13/15] =?UTF-8?q?=E9=94=80=E5=94=AE=E5=8D=95=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E7=AD=9B=E9=80=89=E4=BE=9B=E8=B4=A7=E6=96=B9=E5=BC=8F?= =?UTF-8?q?=E5=BE=85=E7=A1=AE=E8=AE=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/views/sale_order_views.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sf_manufacturing/views/sale_order_views.xml b/sf_manufacturing/views/sale_order_views.xml index a6bebf9c..8366a972 100644 --- a/sf_manufacturing/views/sale_order_views.xml +++ b/sf_manufacturing/views/sale_order_views.xml @@ -71,7 +71,7 @@ - {'search_default_draft': 1} + {'search_default_supply_method': 1} From 77744e75d7bd4e15220e28d92020ab6b59f030ea Mon Sep 17 00:00:00 2001 From: liaodanlong Date: Thu, 27 Mar 2025 16:38:57 +0800 Subject: [PATCH 14/15] =?UTF-8?q?=E5=AD=90=E5=88=B6=E9=80=A0=E8=AE=A2?= =?UTF-8?q?=E5=8D=95=E9=9B=B6=E4=BB=B6=E5=9B=BE=E5=8F=B7=E9=9B=B6=E4=BB=B6?= =?UTF-8?q?=E5=90=8D=E7=A7=B0=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 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py index 971f331e..52c5f463 100644 --- a/sf_manufacturing/models/mrp_production.py +++ b/sf_manufacturing/models/mrp_production.py @@ -280,8 +280,8 @@ class MrpProduction(models.Model): # 如果匹配成功,提取结果 if match: product_name = match.group(0) - if production_id.picking_id.sale_order_id: - sale_order = production_id.picking_id.sale_order_id + if production_id.sale_order_id: + sale_order = production_id.sale_order_id else: sale_order_name = '' match = re.search(r'(S\d+)', production_id.product_id.name) From f34c01d1b0a3a5306b19dbf5c6fe2b8a52f51c7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Fri, 28 Mar 2025 13:37:29 +0800 Subject: [PATCH 15/15] =?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=A4=96=E5=8D=8F=E8=B0=83=E6=8B=A8=E5=8D=95?= =?UTF-8?q?=E9=AA=8C=E8=AF=81=E6=8A=A5=E9=94=99=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 | 13 ++++++++++++- sf_manufacturing/models/stock.py | 12 +++++++++++- sf_message/models/sf_message_workorder.py | 7 ++++--- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index b8ea6eec..ea2923bd 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -1533,7 +1533,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: logging.info('product_qty:%s' % record.production_id.product_qty) for move_raw_id in record.production_id.move_raw_ids: @@ -1548,6 +1548,17 @@ class ResMrpWorkOrder(models.Model): # if raw_move: # raw_move.write({'state': 'done'}) if record.production_id.state != 'rework': + # 如果工单包含了外协工序,需要预留数量 + if self.move_raw_ids.move_orig_ids.subcontract_workorder_id: + location_id = self.move_raw_ids.location_id + quant = self.move_raw_ids.lot_ids.quant_ids.filtered(lambda q: q.location_id.id == location_id.id) + if quant.reserved_quantity == 0: + self.env['stock.quant']._update_reserved_quantity( + self.move_raw_ids.product_id, + location_id, + quant.quantity, + lot_id=quant.lot_id, + ) record.production_id.button_mark_done1() # record.production_id.state = 'done' diff --git a/sf_manufacturing/models/stock.py b/sf_manufacturing/models/stock.py index 051f0507..1f1e45b6 100644 --- a/sf_manufacturing/models/stock.py +++ b/sf_manufacturing/models/stock.py @@ -690,7 +690,8 @@ class StockPicking(models.Model): # 如果当前工单是是制造订单的最后一个工艺外协工单 if workorder == next((workorder for workorder in reversed(sorted_workorders) if workorder.is_subcontract), None): - move_dest_id = item.move_raw_ids[0].id + if item.move_raw_ids: + move_dest_id = item.move_raw_ids[0].id else: # 从sorted_workorders中找到上一工单的move if len(sorted_workorders) > 1: @@ -726,6 +727,7 @@ class StockPicking(models.Model): moves_out._action_confirm() 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): super(StockPicking, self)._compute_state() @@ -849,6 +851,7 @@ class ReStockMove(models.Model): # 'route_ids': False if not route else [(4, route.id)], 'date_deadline': datetime.now(), 'picking_type_id': picking_type_id, + # 'is_subcontract': True, } return move_values @@ -1118,6 +1121,13 @@ class ReStockMove(models.Model): if self.state != 'assigned': self.state = 'assigned' return self.action_show_details() + + def _prepare_move_line_vals(self, quantity=None, reserved_quant=None): + res = super(ReStockMove, self)._prepare_move_line_vals(quantity, reserved_quant) + if self.subcontract_workorder_id: + if self.subcontract_workorder_id.production_id.move_raw_ids.move_line_ids: + res['lot_id'] = self.subcontract_workorder_id.production_id.move_raw_ids.move_line_ids[0].lot_id.id + return res class ReStockQuant(models.Model): diff --git a/sf_message/models/sf_message_workorder.py b/sf_message/models/sf_message_workorder.py index 42b03139..5b73565e 100644 --- a/sf_message/models/sf_message_workorder.py +++ b/sf_message/models/sf_message_workorder.py @@ -191,7 +191,8 @@ class SFMessageWork(models.Model): def write(self, vals): res = super(SFMessageWork, self).write(vals) - if ('leave_id' in vals and vals['leave_id'] is False or 'date_planned_start' in vals and vals['date_planned_start'] is False) \ - and self.schedule_state != '未排': - self.add_queue('计划数据异常跟踪') + for record in self: + if ('leave_id' in vals and vals['leave_id'] is False or 'date_planned_start' in vals and vals['date_planned_start'] is False) \ + and record.schedule_state != '未排': + record.add_queue('计划数据异常跟踪') return res