From 7124eebabecb07aefd1645fffd559549766c6a23 Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Thu, 20 Mar 2025 17:01:36 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E9=87=87=E8=B4=AD=E5=8D=95=E9=87=87?= =?UTF-8?q?=E8=B4=AD=E7=B1=BB=E5=9E=8B=E8=AE=A1=E7=AE=97=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=96=B0=E5=88=A4=E6=96=AD=E6=9D=A1=E4=BB=B6?= 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, 2 insertions(+) diff --git a/sf_sale/models/sale_order.py b/sf_sale/models/sale_order.py index b4aca0dc..51e7ca3c 100644 --- a/sf_sale/models/sale_order.py +++ b/sf_sale/models/sale_order.py @@ -313,6 +313,8 @@ class RePurchaseOrder(models.Model): @api.depends('origin') def _compute_purchase_type(self): for purchase in self: + if not purchase.origin: + continue origin = [origin.replace(' ', '') for origin in purchase.origin.split(',')] order_ids = self.env['sale.order'].sudo().search([('name', 'in', origin)]) if order_ids: From 86d2fb1ac213d8d1ef4e9b5cd4560480ab4a25da Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Fri, 21 Mar 2025 11:20:24 +0800 Subject: [PATCH 2/2] =?UTF-8?q?efms-purchase=5Frequest=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E4=BF=AE=E6=94=B9=E4=BB=A3=E7=A0=81=E6=90=AC?= =?UTF-8?q?=E8=BF=81=E5=88=B0sf-jikimo=5Fpurchase=5Frequest=E6=A8=A1?= =?UTF-8?q?=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jikimo_purchase_request/__init__.py | 1 + jikimo_purchase_request/__manifest__.py | 2 + jikimo_purchase_request/models/__init__.py | 1 + .../models/purchase_request.py | 43 ++++++++- jikimo_purchase_request/models/stock_rule.py | 44 +++++++++ .../views/purchase_request_view.xml | 15 +++ jikimo_purchase_request/wizard/__init__.py | 3 + ...rchase_request_line_make_purchase_order.py | 94 +++++++++++++++++++ ..._request_line_make_purchase_order_view.xml | 13 +++ 9 files changed, 215 insertions(+), 1 deletion(-) create mode 100644 jikimo_purchase_request/models/stock_rule.py create mode 100644 jikimo_purchase_request/views/purchase_request_view.xml create mode 100644 jikimo_purchase_request/wizard/__init__.py create mode 100644 jikimo_purchase_request/wizard/purchase_request_line_make_purchase_order.py create mode 100644 jikimo_purchase_request/wizard/purchase_request_line_make_purchase_order_view.xml diff --git a/jikimo_purchase_request/__init__.py b/jikimo_purchase_request/__init__.py index a0fdc10f..408a6001 100644 --- a/jikimo_purchase_request/__init__.py +++ b/jikimo_purchase_request/__init__.py @@ -1,2 +1,3 @@ # -*- coding: utf-8 -*- from . import models +from . import wizard diff --git a/jikimo_purchase_request/__manifest__.py b/jikimo_purchase_request/__manifest__.py index 683c4311..d919b25d 100644 --- a/jikimo_purchase_request/__manifest__.py +++ b/jikimo_purchase_request/__manifest__.py @@ -9,6 +9,8 @@ 'depends': ['sf_manufacturing', 'purchase_request'], 'data': [ 'views/sale_order_view.xml', + 'views/purchase_request_view.xml', + 'wizard/purchase_request_line_make_purchase_order_view.xml', ], # 'assets': { # 'web.assets_backend': [ diff --git a/jikimo_purchase_request/models/__init__.py b/jikimo_purchase_request/models/__init__.py index 284002d0..6942c727 100644 --- a/jikimo_purchase_request/models/__init__.py +++ b/jikimo_purchase_request/models/__init__.py @@ -2,3 +2,4 @@ from . import product_template from . import purchase_request from . import sale_order +from . import stock_rule diff --git a/jikimo_purchase_request/models/purchase_request.py b/jikimo_purchase_request/models/purchase_request.py index 1ddedda7..f2a78bda 100644 --- a/jikimo_purchase_request/models/purchase_request.py +++ b/jikimo_purchase_request/models/purchase_request.py @@ -1,4 +1,4 @@ -from odoo import models, fields +from odoo import models, fields, api class PurchaseRequest(models.Model): @@ -11,7 +11,48 @@ class PurchaseRequest(models.Model): ondelete={'cancel': 'set default'} # 添加 ondelete 策略 ) + rule_new_add = fields.Boolean('采购请求为规则创建', default=False, compute='_compute_state', store=True) + + @api.depends('state') + def _compute_state(self): + for pr in self: + if pr.state != 'draft' and pr.rule_new_add: + pr.rule_new_add = False + class PurchaseRequestLine(models.Model): _inherit = 'purchase.request.line' _description = '采购申请明细' + + origin = fields.Char(string="Source Document") + supply_method = fields.Selection([ + ('automation', "自动化产线加工"), + ('manual', "人工线下加工"), + ('purchase', "外购"), + ('outsourcing', "委外加工"), + ], string='供货方式', compute='_compute_supply_method', store=True) + + @api.depends('origin') + def _compute_supply_method(self): + for prl in self: + order_ids = [] + if not prl.origin: + continue + origin = [origin.replace(' ', '') for origin in prl.origin.split(',')] + if 'S' in prl.origin: + # 原单据是销售订单 + order_ids = self.env['sale.order'].sudo().search([('name', 'in', origin)]).ids + elif 'MO' in prl.origin: + # 原单据是制造订单 + mp_ids = self.env['mrp.production'].sudo().search([('name', 'in', origin)]) + order_ids = [mp_id.sale_order_id.id for mp_id in mp_ids] if mp_ids else [] + elif 'WH' in prl.origin: + # 原单据是调拨单 + sp_ids = self.env['stock.picking'].sudo().search([('name', 'in', origin)]) + order_ids = [sp_id.sale_order_id.id for sp_id in sp_ids] if sp_ids else [] + order_line = self.env['sale.order.line'].sudo().search( + [('product_id', '=', prl.product_id.id), ('order_id', 'in', order_ids)]) + if order_line: + prl.supply_method = order_line[0].supply_method + else: + prl.supply_method = None diff --git a/jikimo_purchase_request/models/stock_rule.py b/jikimo_purchase_request/models/stock_rule.py new file mode 100644 index 00000000..7920433f --- /dev/null +++ b/jikimo_purchase_request/models/stock_rule.py @@ -0,0 +1,44 @@ +from odoo import api, fields, models + + +class StockRule(models.Model): + _inherit = "stock.rule" + + def create_purchase_request(self, procurement_group): + """ + Create a purchase request containing procurement order product. + """ + procurement = procurement_group[0] + rule = procurement_group[1] + purchase_request_model = self.env["purchase.request"] + purchase_request_line_model = self.env["purchase.request.line"] + cache = {} + pr = self.env["purchase.request"] + domain = rule._make_pr_get_domain(procurement.values) + if domain in cache: + pr = cache[domain] + elif domain: + pr = self.env["purchase.request"].search([dom for dom in domain]) + pr = pr[0] if pr else False + cache[domain] = pr + if not pr: + request_data = rule._prepare_purchase_request( + procurement.origin, procurement.values + ) + request_data.update({'rule_new_add': True}) + pr = purchase_request_model.create(request_data) + cache[domain] = pr + elif ( + not pr.origin + or procurement.origin not in pr.origin.split(", ") + and procurement.origin != "/" + ): + if pr.origin: + if procurement.origin: + pr.write({"origin": pr.origin + ", " + procurement.origin}) + else: + pr.write({"origin": procurement.origin}) + # Create Line + request_line_data = rule._prepare_purchase_request_line(pr, procurement) + request_line_data.update({'origin': procurement.origin}) + purchase_request_line_model.create(request_line_data) diff --git a/jikimo_purchase_request/views/purchase_request_view.xml b/jikimo_purchase_request/views/purchase_request_view.xml new file mode 100644 index 00000000..66a62bbf --- /dev/null +++ b/jikimo_purchase_request/views/purchase_request_view.xml @@ -0,0 +1,15 @@ + + + purchase.request.sf.form + purchase.request + + + + 重置草稿 + + + + + + + \ No newline at end of file diff --git a/jikimo_purchase_request/wizard/__init__.py b/jikimo_purchase_request/wizard/__init__.py new file mode 100644 index 00000000..0a2ad149 --- /dev/null +++ b/jikimo_purchase_request/wizard/__init__.py @@ -0,0 +1,3 @@ +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0) + +from . import purchase_request_line_make_purchase_order diff --git a/jikimo_purchase_request/wizard/purchase_request_line_make_purchase_order.py b/jikimo_purchase_request/wizard/purchase_request_line_make_purchase_order.py new file mode 100644 index 00000000..dd246a5d --- /dev/null +++ b/jikimo_purchase_request/wizard/purchase_request_line_make_purchase_order.py @@ -0,0 +1,94 @@ +# Copyright 2018-2019 ForgeFlow, S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). +from datetime import datetime + +from odoo import _, api, fields, models +from odoo.exceptions import UserError, ValidationError +from odoo.tools import get_lang + + +class PurchaseRequestLineMakePurchaseOrder(models.TransientModel): + _inherit = "purchase.request.line.make.purchase.order" + + def make_purchase_order(self): + res = [] + purchase_obj = self.env["purchase.order"] + po_line_obj = self.env["purchase.order.line"] + purchase = False + + if len(set([item_id.line_id.supply_method for item_id in self.item_ids])) > 1: + raise ValidationError('不同供货方式不可合并创建询价单!') + + for item in self.item_ids: + line = item.line_id + if item.product_qty <= 0.0: + raise UserError(_("Enter a positive quantity.")) + if self.purchase_order_id: + purchase = self.purchase_order_id + if not purchase: + po_data = self._prepare_purchase_order( + line.request_id.picking_type_id, + line.request_id.group_id, + line.company_id, + line.request_id.origin, + ) + purchase = purchase_obj.create(po_data) + + # Look for any other PO line in the selected PO with same + # product and UoM to sum quantities instead of creating a new + # po line + domain = self._get_order_line_search_domain(purchase, item) + available_po_lines = po_line_obj.search(domain) + new_pr_line = True + # If Unit of Measure is not set, update from wizard. + if not line.product_uom_id: + line.product_uom_id = item.product_uom_id + # Allocation UoM has to be the same as PR line UoM + alloc_uom = line.product_uom_id + wizard_uom = item.product_uom_id + if available_po_lines and not item.keep_description: + new_pr_line = False + po_line = available_po_lines[0] + po_line.purchase_request_lines = [(4, line.id)] + po_line.move_dest_ids |= line.move_dest_ids + po_line_product_uom_qty = po_line.product_uom._compute_quantity( + po_line.product_uom_qty, alloc_uom + ) + wizard_product_uom_qty = wizard_uom._compute_quantity( + item.product_qty, alloc_uom + ) + all_qty = min(po_line_product_uom_qty, wizard_product_uom_qty) + self.create_allocation(po_line, line, all_qty, alloc_uom) + else: + po_line_data = self._prepare_purchase_order_line(purchase, item) + if item.keep_description: + po_line_data["name"] = item.name + po_line = po_line_obj.create(po_line_data) + po_line_product_uom_qty = po_line.product_uom._compute_quantity( + po_line.product_uom_qty, alloc_uom + ) + wizard_product_uom_qty = wizard_uom._compute_quantity( + item.product_qty, alloc_uom + ) + all_qty = min(po_line_product_uom_qty, wizard_product_uom_qty) + self.create_allocation(po_line, line, all_qty, alloc_uom) + self._post_process_po_line(item, po_line, new_pr_line) + res.append(purchase.id) + + purchase_requests = self.item_ids.mapped("request_id") + purchase_requests.button_in_progress() + return { + "domain": [("id", "in", res)], + "name": _("RFQ"), + "view_mode": "tree,form", + "res_model": "purchase.order", + "view_id": False, + "context": False, + "type": "ir.actions.act_window", + } + + +class PurchaseRequestLineMakePurchaseOrderItem(models.TransientModel): + _inherit = "purchase.request.line.make.purchase.order.item" + + supply_method = fields.Selection(related='line_id.supply_method', string='供货方式') diff --git a/jikimo_purchase_request/wizard/purchase_request_line_make_purchase_order_view.xml b/jikimo_purchase_request/wizard/purchase_request_line_make_purchase_order_view.xml new file mode 100644 index 00000000..4d519a2e --- /dev/null +++ b/jikimo_purchase_request/wizard/purchase_request_line_make_purchase_order_view.xml @@ -0,0 +1,13 @@ + + + + Purchase Request Line Make Purchase Order sf + purchase.request.line.make.purchase.order + + + + + + + +