Accept Merge Request #2027: (feature/tool_standard_library_process -> develop)

Merge Request: 工艺相关展示调整

Created By: @廖丹龙
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @廖丹龙
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/2027
This commit is contained in:
廖丹龙
2025-04-22 13:49:59 +08:00
committed by Coding
10 changed files with 63 additions and 11 deletions

View File

@@ -33,6 +33,7 @@ class SfProductionProcessParameter(models.Model):
if product_id: if product_id:
product_id.server_product_process_parameters_id = self.id product_id.server_product_process_parameters_id = self.id
else: else:
res_partner = self.env['res.partner'].search('name', '=', '湖南傲派自动化设备有限公司')
self.env['product.template'].create({ self.env['product.template'].create({
'detailed_type': 'service', 'detailed_type': 'service',
'name': product_name, 'name': product_name,
@@ -42,6 +43,10 @@ class SfProductionProcessParameter(models.Model):
'sale_ok': True, # 可销售 'sale_ok': True, # 可销售
'purchase_ok': True, # 可采购 'purchase_ok': True, # 可采购
'server_product_process_parameters_id': self.id, 'server_product_process_parameters_id': self.id,
'seller_ids': [(0, 0, {
# 'delay': 1,
'partner_id': res_partner.id,
'price': 1, })],
}) })
def create_work_center(self): def create_work_center(self):

View File

@@ -41,7 +41,7 @@
attrs="{'invisible': [('categ_type', 'not in', ['成品','坯料', '原材料'])],'readonly': [('id', '!=', False)]}"/> attrs="{'invisible': [('categ_type', 'not in', ['成品','坯料', '原材料'])],'readonly': [('id', '!=', False)]}"/>
<field name="server_product_process_parameters_id" string="工艺参数" <field name="server_product_process_parameters_id" string="工艺参数"
options="{'no_create': True}" options="{'no_create': True}"
attrs="{'invisible': ['|',('detailed_type', '!=', '服务'),('detailed_type', '=', False)]}"/> attrs="{'invisible': ['|',('detailed_type', '!=', 'service'),('detailed_type', '=', False)]}"/>
<field name="cutting_tool_material_id" class="custom_required" <field name="cutting_tool_material_id" class="custom_required"
options="{'no_create': True}" options="{'no_create': True}"
attrs="{'invisible': [('categ_type', '!=', '刀具')],'required': [('categ_type', '=', '刀具')],'readonly': [('id', '!=', False)]}" attrs="{'invisible': [('categ_type', '!=', '刀具')],'required': [('categ_type', '=', '刀具')],'readonly': [('id', '!=', False)]}"

View File

@@ -924,6 +924,8 @@ class MrpProduction(models.Model):
"bom_id": self[0].bom_id.id, "bom_id": self[0].bom_id.id,
"is_subcontract":True, "is_subcontract":True,
}) })
self[0].bom_id.bom_line_ids.product_id.route_ids = [(4,self.env.ref(
'sf_stock.stock_location_outsourcing_material_receiving_area').id)]
for product_id, request_line_list in grouped_purchase_request_line_sorted_list.items(): for product_id, request_line_list in grouped_purchase_request_line_sorted_list.items():
cur_request_line = request_line_list[0] cur_request_line = request_line_list[0]
cur_request_line['product_qty'] = len(request_line_list) cur_request_line['product_qty'] = len(request_line_list)
@@ -943,6 +945,7 @@ class MrpProduction(models.Model):
product_id_to_production_names[product_id] = [p.name for p in pd] product_id_to_production_names[product_id] = [p.name for p in pd]
sorted_workorders = None sorted_workorders = None
purchase_request_line = [] purchase_request_line = []
all_workorders = []
for production in production_all: for production in production_all:
proc_workorders = [] proc_workorders = []
process_parameter_workorder = self.env['mrp.workorder'].search( process_parameter_workorder = self.env['mrp.workorder'].search(
@@ -962,8 +965,10 @@ class MrpProduction(models.Model):
# self.env['purchase.order'].get_purchase_order(workorders, production, product_id_to_production_names) # self.env['purchase.order'].get_purchase_order(workorders, production, product_id_to_production_names)
purchase_request_line = purchase_request_line + self.env['purchase.order'].get_purchase_request( purchase_request_line = purchase_request_line + self.env['purchase.order'].get_purchase_request(
workorders, production) workorders, production)
all_workorders += workorders
self._create_subcontract_purchase_request(purchase_request_line) self._create_subcontract_purchase_request(purchase_request_line)
for workorder in all_workorders:
workorder._compute_pr_mp_count()
# 工单排序 # 工单排序
def _reset_work_order_sequence1(self, k): def _reset_work_order_sequence1(self, k):
for rec in self: for rec in self:

View File

@@ -70,13 +70,16 @@ class ResMrpWorkOrder(models.Model):
tracking=True) tracking=True)
back_button_display = fields.Boolean(default=False, compute='_compute_back_button_display', store=True) back_button_display = fields.Boolean(default=False, compute='_compute_back_button_display', store=True)
pr_mp_count = fields.Integer('采购申请单数量', compute='_compute_pr_mp_count', store=True) pr_mp_count = fields.Integer('采购申请单数量', compute='_compute_pr_mp_count', store=True)
@api.depends('state') @api.depends('state')
def _compute_pr_mp_count(self): def _compute_pr_mp_count(self):
for item in self: for item in self:
if not item.is_subcontract: if not item.is_subcontract:
item.pr_mp_count = 0 item.pr_mp_count = 0
continue continue
pr_ids = self.env['purchase.request'].sudo().search([('origin', 'like', item.name),('is_subcontract','=','True')]) pr_ids = self.env['purchase.request'].sudo().search(
[('origin', 'like', item.production_id.name), ('is_subcontract', '=', 'True'),
('state', '!=', 'rejected')])
if pr_ids: if pr_ids:
item.pr_mp_count = len(pr_ids) item.pr_mp_count = len(pr_ids)
else: else:
@@ -461,7 +464,9 @@ class ResMrpWorkOrder(models.Model):
采购请求 采购请求
""" """
self.ensure_one() self.ensure_one()
pr_ids = self.env['purchase.request'].sudo().search([('origin', 'like', self.name),('is_subcontract', '=', True)]) pr_ids = self.env['purchase.request'].sudo().search(
[('origin', 'like', self.production_id.name), ('is_subcontract', '=', 'True'),
('state', '!=', 'rejected')])
action = { action = {
'res_model': 'purchase.request', 'res_model': 'purchase.request',
'type': 'ir.actions.act_window', 'type': 'ir.actions.act_window',

View File

@@ -7,6 +7,11 @@ from odoo.tools import str2bool
class SfProductionProcessParameter(models.Model): class SfProductionProcessParameter(models.Model):
_inherit = 'sf.production.process.parameter' _inherit = 'sf.production.process.parameter'
service_products = fields.Many2one(
'product.template',
string='外协服务产品',compute='_compute_service_products',inverse='_inverse_service_products',
store=True
)
outsourced_service_products = fields.One2many( outsourced_service_products = fields.One2many(
'product.template', # 另一个模型的名称 'product.template', # 另一个模型的名称
'server_product_process_parameters_id', # 对应的 Many2one 字段名称 'server_product_process_parameters_id', # 对应的 Many2one 字段名称
@@ -16,6 +21,25 @@ class SfProductionProcessParameter(models.Model):
is_delete_button = fields.Boolean(compute='_compute_is_delete_button', default=False) is_delete_button = fields.Boolean(compute='_compute_is_delete_button', default=False)
routing_id = fields.Many2one('mrp.routing.workcenter', string="工序") routing_id = fields.Many2one('mrp.routing.workcenter', string="工序")
@api.depends('outsourced_service_products')
def _compute_service_products(self):
for record in self:
# 假设取第一条作为主明细
record.service_products = record.outsourced_service_products.id if record.outsourced_service_products else False
def _inverse_service_products(self):
for record in self:
if record.service_products:
# 确保关联关系正确
record.outsourced_service_products = record.service_products.ids if record.service_products else False
else:
record.outsourced_service_products = False
def name_get(self):
result = []
for record in self:
name = f"{record.process_id.name} - {record.name}" # 自定义显示格式
result.append((record.id, name))
return result
@api.constrains('outsourced_service_products') @api.constrains('outsourced_service_products')
def _validate_partner_limit(self): def _validate_partner_limit(self):
for record in self: for record in self:
@@ -35,17 +59,17 @@ class SfProductionProcessParameter(models.Model):
else: else:
record.is_product_button = False record.is_product_button = False
def has_wksp_prefix(self,code): def has_wksp_prefix(self):
""" """
判断字符串是否以WKSP开头不区分大小写 判断字符串是否以WKSP开头不区分大小写
:param text: 要检查的字符串 :param text: 要检查的字符串
:return: True/False :return: True/False
""" """
return code.upper().startswith('WKSP') return self.code.upper().startswith('101'+self.routing_id.code)
@api.depends('outsourced_service_products','code') @api.depends('outsourced_service_products','code')
def _compute_is_delete_button(self): def _compute_is_delete_button(self):
for record in self: for record in self:
if record.outsourced_service_products and self.has_wksp_prefix(record.code): if record.outsourced_service_products and record.has_wksp_prefix():
record.is_delete_button = False record.is_delete_button = False
elif record.outsourced_service_products: elif record.outsourced_service_products:
record.is_delete_button = True record.is_delete_button = True

View File

@@ -30,7 +30,7 @@
<field name="is_delete_button" invisible="1"/> <field name="is_delete_button" invisible="1"/>
<field name="code" attrs="{'readonly': True}"/> <field name="code" attrs="{'readonly': True}"/>
<field name="name"/> <field name="name"/>
<field name="outsourced_service_products" domain="[('detailed_type', '=', 'service'),('server_product_process_parameters_id', '=', False)]"/> <field name="service_products" domain="[('detailed_type', '=', 'service'),('server_product_process_parameters_id', '=', False)]"/>
<!-- 按钮列 --> <!-- 按钮列 -->
<button name="action_create_service_product" string="创建服务产品" type="object" <button name="action_create_service_product" string="创建服务产品" type="object"
class="btn-primary" class="btn-primary"

View File

@@ -152,7 +152,7 @@
<span class="o_stat_value"> <span class="o_stat_value">
<field name="pr_mp_count"/> <field name="pr_mp_count"/>
</span> </span>
<span class="o_stat_text">采购</span> <span class="o_stat_text">采购申请</span>
</div> </div>
</button> </button>
<button type="object" name="action_view_surface_technics_purchase" class="oe_stat_button" <button type="object" name="action_view_surface_technics_purchase" class="oe_stat_button"

View File

@@ -28,7 +28,7 @@ class ProductCreationWizard(models.TransientModel):
'server_product_process_parameters_id': self.process_parameter_id.id, 'server_product_process_parameters_id': self.process_parameter_id.id,
} }
def action_create_product(self): def action_create_product(self):
service_categ = self.env.ref('sf_manufacturing.product_category_outsource_other_process').sudo() res_partner = self.env['res.partner'].search('name','=','湖南傲派自动化设备有限公司')
default_values = { default_values = {
'detailed_type': 'service', 'detailed_type': 'service',
'name': f"{self.process_parameter_id.process_id.name}{self.process_parameter_id.name}", 'name': f"{self.process_parameter_id.process_id.name}{self.process_parameter_id.name}",
@@ -38,5 +38,9 @@ class ProductCreationWizard(models.TransientModel):
'sale_ok': True, # 可销售 'sale_ok': True, # 可销售
'purchase_ok': True, # 可采购 'purchase_ok': True, # 可采购
'server_product_process_parameters_id': self.process_parameter_id.id, 'server_product_process_parameters_id': self.process_parameter_id.id,
'seller_ids': [(0, 0, {
# 'delay': 1,
'partner_id': res_partner.id,
'price': 1, })],
} }
self.env['product.template'].create(default_values) self.env['product.template'].create(default_values)

View File

@@ -2,6 +2,7 @@
import logging import logging
from itertools import groupby from itertools import groupby
from odoo import models, api, fields, _ from odoo import models, api, fields, _
from odoo.exceptions import UserError
class ProductionTechnologyReAdjustWizard(models.TransientModel): class ProductionTechnologyReAdjustWizard(models.TransientModel):
@@ -76,4 +77,11 @@ class ProductionTechnologyReAdjustWizard(models.TransientModel):
if workorders[ if workorders[
0].production_id.product_id.categ_id.type == '成品' and item.programming_state != '已编程': 0].production_id.product_id.categ_id.type == '成品' and item.programming_state != '已编程':
workorders[0].state = 'waiting' workorders[0].state = 'waiting'
pr_ids = self.env['purchase.request'].sudo().search(
[('origin', 'like', item.name), ('is_subcontract', '=', 'True'), ('state', '!=', 'rejected')])
if not pr_ids:
continue
if not all(pr.state == 'draft' for pr in pr_ids):
# 如果发现有记录的 state 不是 'draft',抛出异常
raise UserError("有采购申请的状态不是 '草稿'")
pr_ids.state = 'rejected'

View File

@@ -387,6 +387,7 @@ class RePurchaseOrder(models.Model):
server_template = self.env['product.template'].search( server_template = self.env['product.template'].search(
[('server_product_process_parameters_id', '=', pp.surface_technics_parameters_id.id), [('server_product_process_parameters_id', '=', pp.surface_technics_parameters_id.id),
('detailed_type', '=', 'service')]) ('detailed_type', '=', 'service')])
# route_ids
result.append({ result.append({
"product_id": server_template.product_variant_id.id, "product_id": server_template.product_variant_id.id,
"name": production.procurement_group_id.name, "name": production.procurement_group_id.name,