diff --git a/jikimo_purchase_request/models/mrp_production.py b/jikimo_purchase_request/models/mrp_production.py
index dd9d4aa9..ff352ff6 100644
--- a/jikimo_purchase_request/models/mrp_production.py
+++ b/jikimo_purchase_request/models/mrp_production.py
@@ -9,8 +9,7 @@ class MrpProduction(models.Model):
@api.depends('state')
def _compute_pr_mp_count(self):
for item in self:
- pr_ids = self.env['purchase.request'].sudo().search([('origin', 'like', item.name)])
- # 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.name), ('is_subcontract', '!=', 'True')])
if pr_ids:
item.pr_mp_count = len(pr_ids)
else:
@@ -21,8 +20,7 @@ class MrpProduction(models.Model):
采购请求
"""
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.name)])
+ pr_ids = self.env['purchase.request'].sudo().search([('origin', 'like', self.name),('is_subcontract', '!=', True)])
action = {
'res_model': 'purchase.request',
'type': 'ir.actions.act_window',
diff --git a/sf_dlm_management/models/mrp_routing_workcenter.py b/sf_dlm_management/models/mrp_routing_workcenter.py
index dd9e59e3..4a04eb87 100644
--- a/sf_dlm_management/models/mrp_routing_workcenter.py
+++ b/sf_dlm_management/models/mrp_routing_workcenter.py
@@ -1,16 +1,16 @@
-# import logging
-# from odoo import fields, models, api
-# from odoo.exceptions import UserError
-# from odoo.tools import str2bool
-#
-#
-# class ResMrpRoutingWorkcenter(models.Model):
-# _inherit = 'mrp.routing.workcenter'
-# def init(self):
-# super(ResMrpRoutingWorkcenter, self).init()
-# # 在模块初始化时触发计算字段的更新
-# records = self.search([])
-# if str2bool(self.env['ir.config_parameter'].get_param('sf.production.process.parameter.is_init_workcenter',default='False')):
-# return
-# records.optional_process_parameters_date()
-# self.env['ir.config_parameter'].set_param('sf.production.process.parameter.is_init_workcenter', True)
\ No newline at end of file
+import logging
+from odoo import fields, models, api
+from odoo.exceptions import UserError
+from odoo.tools import str2bool
+
+
+class ResMrpRoutingWorkcenter(models.Model):
+ _inherit = 'mrp.routing.workcenter'
+ def init(self):
+ super(ResMrpRoutingWorkcenter, self).init()
+ # 在模块初始化时触发计算字段的更新
+ records = self.search([])
+ if str2bool(self.env['ir.config_parameter'].get_param('sf.production.process.parameter.is_init_workcenter',default='False')):
+ return
+ records.optional_process_parameters_date()
+ self.env['ir.config_parameter'].set_param('sf.production.process.parameter.is_init_workcenter', True)
\ No newline at end of file
diff --git a/sf_dlm_management/models/sf_production_common.py b/sf_dlm_management/models/sf_production_common.py
index 42cb9ff2..637aeb26 100644
--- a/sf_dlm_management/models/sf_production_common.py
+++ b/sf_dlm_management/models/sf_production_common.py
@@ -1,85 +1,85 @@
-# # -*- coding: utf-8 -*-
-# import logging
-# from odoo import fields, models, api
-# from odoo.exceptions import UserError
-# from odoo.tools import str2bool
-#
-#
-# class SfProductionProcessParameter(models.Model):
-# _inherit = 'sf.production.process.parameter'
-#
-#
-# @api.model
-# def create(self, vals):
-# # if vals.get('code', '/') == '/' or vals.get('code', '/') is False:
-# # vals['code'] = '101'+self.routing_id.code +self.env['ir.sequence'].next_by_code('sf.production.process.parameter')
-# if vals.get('routing_id'):
-# # vals['gain_way'] = '外协'
-# routing_id = self.env['mrp.routing.workcenter'].browse(vals.get('routing_id'))
-# if routing_id.surface_technics_id and not vals.get('process_id'):
-# vals['process_id'] = routing_id.surface_technics_id.id
-# if vals.get('code', '/') == '/' or vals.get('code', '/') is False:
-# vals['code'] = '101' + routing_id.code + self.env['ir.sequence'].next_by_code(
-# 'sf.production.process.parameter')
-# obj = super(SfProductionProcessParameter, self).create(vals)
-# return obj
-# def create_service_product(self):
-# service_categ = self.env.ref(
-# 'sf_dlm.product_category_surface_technics_sf').sudo()
-#
-# product_name = f"{self.process_id.name}_{self.name}"
-# product_id = self.env['product.template'].search(
-# [("name", '=', product_name)])
-# if product_id:
-# product_id.server_product_process_parameters_id = self.id
-# else:
-# res_partner = self.env['res.partner'].search([('name','=','湖南傲派自动化设备有限公司')])
-# self.env['product.template'].create({
-# 'detailed_type': 'service',
-# 'name': product_name,
-# 'invoice_policy': 'delivery',
-# 'categ_id': service_categ.id,
-# 'description': f"基于{self.name}创建的服务产品",
-# 'sale_ok': True, # 可销售
-# 'purchase_ok': True, # 可采购
-# '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):
-# production_process_parameter = self
-# if not production_process_parameter.process_id:
-# return
-# if not production_process_parameter.routing_id:
-# workcenter_id = self.env['mrp.routing.workcenter'].search(
-# [("surface_technics_id", '=', production_process_parameter.process_id.id)])
-# if not workcenter_id:
-# outsourcing_work_center = self.env['mrp.workcenter'].search(
-# [("name", '=', '外协工作中心')])
-# routing_id = self.env['mrp.routing.workcenter'].create({
-# 'workcenter_ids': [(6, 0, outsourcing_work_center.ids)],
-# 'routing_tag': 'special',
-# 'routing_type': '表面工艺',
-# 'is_outsource': True,
-# 'surface_technics_id': production_process_parameter.process_id.id,
-# 'name': production_process_parameter.process_id.name,
-# })
-# production_process_parameter.routing_id = routing_id.id
-# else:
-# production_process_parameter.routing_id = workcenter_id.id
-#
-# def init(self):
-# super(SfProductionProcessParameter, self).init()
-# # 在模块初始化时触发计算字段的更新
-# records = self.search([])
-# if str2bool(self.env['ir.config_parameter'].get_param('sf.production.process.parameter.is_init_process',
-# default='False')):
-# return
-# for record in records:
-# if not record.outsourced_service_products:
-# record.create_service_product()
-# record.create_work_center()
-# self.env['ir.config_parameter'].set_param('sf.production.process.parameter.is_init_process', True)
+# -*- coding: utf-8 -*-
+import logging
+from odoo import fields, models, api
+from odoo.exceptions import UserError
+from odoo.tools import str2bool
+
+
+class SfProductionProcessParameter(models.Model):
+ _inherit = 'sf.production.process.parameter'
+
+
+ @api.model
+ def create(self, vals):
+ # if vals.get('code', '/') == '/' or vals.get('code', '/') is False:
+ # vals['code'] = '101'+self.routing_id.code +self.env['ir.sequence'].next_by_code('sf.production.process.parameter')
+ if vals.get('routing_id'):
+ # vals['gain_way'] = '外协'
+ routing_id = self.env['mrp.routing.workcenter'].browse(vals.get('routing_id'))
+ if routing_id.surface_technics_id and not vals.get('process_id'):
+ vals['process_id'] = routing_id.surface_technics_id.id
+ if vals.get('code', '/') == '/' or vals.get('code', '/') is False:
+ vals['code'] = '101' + routing_id.code + self.env['ir.sequence'].next_by_code(
+ 'sf.production.process.parameter')
+ obj = super(SfProductionProcessParameter, self).create(vals)
+ return obj
+ def create_service_product(self):
+ service_categ = self.env.ref(
+ 'sf_dlm.product_category_surface_technics_sf').sudo()
+
+ product_name = f"{self.process_id.name}_{self.name}"
+ product_id = self.env['product.template'].search(
+ [("name", '=', product_name)])
+ if product_id:
+ product_id.server_product_process_parameters_id = self.id
+ else:
+ res_partner = self.env['res.partner'].search([('name','=','湖南傲派自动化设备有限公司')])
+ self.env['product.template'].create({
+ 'detailed_type': 'service',
+ 'name': product_name,
+ 'invoice_policy': 'delivery',
+ 'categ_id': service_categ.id,
+ 'description': f"基于{self.name}创建的服务产品",
+ 'sale_ok': True, # 可销售
+ 'purchase_ok': True, # 可采购
+ '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):
+ production_process_parameter = self
+ if not production_process_parameter.process_id:
+ return
+ if not production_process_parameter.routing_id:
+ workcenter_id = self.env['mrp.routing.workcenter'].search(
+ [("surface_technics_id", '=', production_process_parameter.process_id.id)])
+ if not workcenter_id:
+ outsourcing_work_center = self.env['mrp.workcenter'].search(
+ [("name", '=', '外协工作中心')])
+ routing_id = self.env['mrp.routing.workcenter'].create({
+ 'workcenter_ids': [(6, 0, outsourcing_work_center.ids)],
+ 'routing_tag': 'special',
+ 'routing_type': '表面工艺',
+ 'is_outsource': True,
+ 'surface_technics_id': production_process_parameter.process_id.id,
+ 'name': production_process_parameter.process_id.name,
+ })
+ production_process_parameter.routing_id = routing_id.id
+ else:
+ production_process_parameter.routing_id = workcenter_id.id
+
+ def init(self):
+ super(SfProductionProcessParameter, self).init()
+ # 在模块初始化时触发计算字段的更新
+ records = self.search([])
+ if str2bool(self.env['ir.config_parameter'].get_param('sf.production.process.parameter.is_init_process',
+ default='False')):
+ return
+ for record in records:
+ if not record.outsourced_service_products:
+ record.create_service_product()
+ record.create_work_center()
+ self.env['ir.config_parameter'].set_param('sf.production.process.parameter.is_init_process', True)
diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py
index 25a016e3..df73fb72 100644
--- a/sf_manufacturing/models/mrp_production.py
+++ b/sf_manufacturing/models/mrp_production.py
@@ -900,40 +900,40 @@ class MrpProduction(models.Model):
for workorder in production.workorder_ids:
workorder.duration_expected = workorder._get_duration_expected()
- # def _create_subcontract_purchase_request(self, purchase_request_line):
- # sorted_list = sorted(purchase_request_line, key=itemgetter('name'))
- # grouped_purchase_request_line = {
- # k: list(g)
- # for k, g in groupby(sorted_list, key=itemgetter('name'))
- # }
- # for name, request_line in grouped_purchase_request_line.items():
- # request_line_sorted_list = sorted(request_line, key=itemgetter('product_id'))
- # grouped_purchase_request_line_sorted_list = {
- # k: list(g)
- # for k, g in groupby(request_line_sorted_list, key=itemgetter('product_id'))
- # }
- # purchase_request_model = self.env["purchase.request"]
- # origin = ", ".join({item['production_name'] for item in request_line_sorted_list if item.get('production_name')})
- # pr = purchase_request_model.create({
- # "origin": origin,
- # "company_id": self.company_id.id,
- # "picking_type_id": self.env.ref('stock.picking_type_in').id,
- # "group_id": request_line[0].get('group_id'),
- # "requested_by": self.env.context.get("uid", self.env.uid),
- # "assigned_to": False,
- # "bom_id": self[0].bom_id.id,
- # "is_subcontract":True,
- # })
- # self[0].bom_id.bom_line_ids.product_id.route_ids = [(4,self.env.ref(
- # 'sf_stock.stock_route_process_outsourcing').id)]
- # for product_id, request_line_list in grouped_purchase_request_line_sorted_list.items():
- # cur_request_line = request_line_list[0]
- # cur_request_line['product_qty'] = len(request_line_list)
- # cur_request_line['request_id'] = pr.id
- # cur_request_line['origin'] = ", ".join({item['production_name'] for item in request_line_list if item.get('production_name')})
- # cur_request_line.pop('group_id', None)
- # cur_request_line.pop('production_name', None)
- # self.env["purchase.request.line"].create(cur_request_line)
+ def _create_subcontract_purchase_request(self, purchase_request_line):
+ sorted_list = sorted(purchase_request_line, key=itemgetter('name'))
+ grouped_purchase_request_line = {
+ k: list(g)
+ for k, g in groupby(sorted_list, key=itemgetter('name'))
+ }
+ for name, request_line in grouped_purchase_request_line.items():
+ request_line_sorted_list = sorted(request_line, key=itemgetter('product_id'))
+ grouped_purchase_request_line_sorted_list = {
+ k: list(g)
+ for k, g in groupby(request_line_sorted_list, key=itemgetter('product_id'))
+ }
+ purchase_request_model = self.env["purchase.request"]
+ origin = ", ".join({item['production_name'] for item in request_line_sorted_list if item.get('production_name')})
+ pr = purchase_request_model.create({
+ "origin": origin,
+ "company_id": self.company_id.id,
+ "picking_type_id": self.env.ref('stock.picking_type_in').id,
+ "group_id": request_line[0].get('group_id'),
+ "requested_by": self.env.context.get("uid", self.env.uid),
+ "assigned_to": False,
+ "bom_id": self[0].bom_id.id,
+ "is_subcontract":True,
+ })
+ self[0].bom_id.bom_line_ids.product_id.route_ids = [(4,self.env.ref(
+ 'sf_stock.stock_route_process_outsourcing').id)]
+ for product_id, request_line_list in grouped_purchase_request_line_sorted_list.items():
+ cur_request_line = request_line_list[0]
+ cur_request_line['product_qty'] = len(request_line_list)
+ cur_request_line['request_id'] = pr.id
+ cur_request_line['origin'] = ", ".join({item['production_name'] for item in request_line_list if item.get('production_name')})
+ cur_request_line.pop('group_id', None)
+ cur_request_line.pop('production_name', None)
+ self.env["purchase.request.line"].create(cur_request_line)
# 外协出入库单处理
def get_subcontract_pick_purchase(self):
@@ -961,14 +961,14 @@ class MrpProduction(models.Model):
if not sorted_workorders:
return
for workorders in reversed(sorted_workorders):
- self.env['stock.picking'].create_outcontract_picking(workorders, production, sorted_workorders)
- self.env['purchase.order'].get_purchase_order(workorders, production, product_id_to_production_names)
- # purchase_request_line = purchase_request_line + self.env['purchase.order'].get_purchase_request(
- # workorders, production)
- # all_workorders += workorders
- # self._create_subcontract_purchase_request(purchase_request_line)
- # for workorder in all_workorders:
- # workorder._compute_pr_mp_count()
+ # self.env['stock.picking'].create_outcontract_picking(workorders, production, sorted_workorders)
+ # self.env['purchase.order'].get_purchase_order(workorders, production, product_id_to_production_names)
+ purchase_request_line = purchase_request_line + self.env['purchase.order'].get_purchase_request(
+ workorders, production)
+ all_workorders += workorders
+ 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):
for rec in self:
diff --git a/sf_manufacturing/models/mrp_routing_workcenter.py b/sf_manufacturing/models/mrp_routing_workcenter.py
index a1387595..6a2fb6f6 100644
--- a/sf_manufacturing/models/mrp_routing_workcenter.py
+++ b/sf_manufacturing/models/mrp_routing_workcenter.py
@@ -1,7 +1,7 @@
import logging
from odoo import fields, models, api
from odoo.exceptions import UserError
-# from odoo.tools import str2bool
+from odoo.tools import str2bool
class ResMrpRoutingWorkcenter(models.Model):
@@ -25,20 +25,20 @@ class ResMrpRoutingWorkcenter(models.Model):
workcenter_ids = fields.Many2many('mrp.workcenter', 'rel_workcenter_route', required=True)
bom_id = fields.Many2one('mrp.bom', required=False)
surface_technics_id = fields.Many2one('sf.production.process', string="表面工艺")
- # optional_process_parameters = fields.One2many('sf.production.process.parameter','routing_id',string='可选工艺参数')
+ optional_process_parameters = fields.One2many('sf.production.process.parameter','routing_id',string='可选工艺参数')
reserved_duration = fields.Float('预留时长', default=30, tracking=True)
is_outsource = fields.Boolean('外协', default=False)
individuation_page_ids = fields.Many2many('sf.work.individuation.page', string='个性化记录')
- # @api.onchange('surface_technics_id')
- # def optional_process_parameters_date(self):
- # for record in self:
- # if not record.surface_technics_id:
- # continue
- # parameter_ids = self.env['sf.production.process.parameter'].search([
- # ('process_id', '=', record.surface_technics_id.id),
- # ])
- # record.optional_process_parameters = parameter_ids.ids
+ @api.onchange('surface_technics_id')
+ def optional_process_parameters_date(self):
+ for record in self:
+ if not record.surface_technics_id:
+ continue
+ parameter_ids = self.env['sf.production.process.parameter'].search([
+ ('process_id', '=', record.surface_technics_id.id),
+ ])
+ record.optional_process_parameters = parameter_ids.ids
# @api.model
# def _auto_init(self):
diff --git a/sf_manufacturing/models/mrp_workcenter.py b/sf_manufacturing/models/mrp_workcenter.py
index 39c500dc..e18472d7 100644
--- a/sf_manufacturing/models/mrp_workcenter.py
+++ b/sf_manufacturing/models/mrp_workcenter.py
@@ -21,16 +21,16 @@ class ResWorkcenter(models.Model):
related='equipment_id.production_line_id', store=True)
is_process_outsourcing = fields.Boolean('工艺外协')
users_ids = fields.Many2many("res.users", 'users_workcenter', tracking=True)
- # @api.constrains('name')
- # def _check_unique_name_code(self):
- # for record in self:
- # # 检查是否已经存在相同的 name 和 code 组合
- # existing = self.search([
- # ('name', '=', record.name),
- # ('id', '!=', record.id) # 排除当前记录
- # ])
- # if existing:
- # raise ValueError('记录已存在')
+ @api.constrains('name')
+ def _check_unique_name_code(self):
+ for record in self:
+ # 检查是否已经存在相同的 name 和 code 组合
+ existing = self.search([
+ ('name', '=', record.name),
+ ('id', '!=', record.id) # 排除当前记录
+ ])
+ if existing:
+ raise ValueError('记录已存在')
def write(self, vals):
if 'users_ids' in vals:
old_users = self.users_ids
diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py
index 070ff404..3a9744d9 100644
--- a/sf_manufacturing/models/mrp_workorder.py
+++ b/sf_manufacturing/models/mrp_workorder.py
@@ -70,21 +70,21 @@ class ResMrpWorkOrder(models.Model):
delivery_warning = fields.Selection([('normal', '正常'), ('warning', '告警'), ('overdue', '逾期')], string='时效',
tracking=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)
- #
- # @api.depends('state')
- # def _compute_pr_mp_count(self):
- # for item in self:
- # if not item.is_subcontract:
- # item.pr_mp_count = 0
- # continue
- # pr_ids = self.env['purchase.request'].sudo().search(
- # [('origin', 'like', item.production_id.name), ('is_subcontract', '=', 'True'),
- # ('state', '!=', 'rejected')])
- # if pr_ids:
- # item.pr_mp_count = len(pr_ids)
- # else:
- # item.pr_mp_count = 0
+ pr_mp_count = fields.Integer('采购申请单数量', compute='_compute_pr_mp_count', store=True)
+
+ @api.depends('state')
+ def _compute_pr_mp_count(self):
+ for item in self:
+ if not item.is_subcontract:
+ item.pr_mp_count = 0
+ continue
+ pr_ids = self.env['purchase.request'].sudo().search(
+ [('origin', 'like', item.production_id.name), ('is_subcontract', '=', 'True'),
+ ('state', '!=', 'rejected')])
+ if pr_ids:
+ item.pr_mp_count = len(pr_ids)
+ else:
+ item.pr_mp_count = 0
@api.depends('state')
def _compute_back_button_display(self):
for record in self:
@@ -443,12 +443,11 @@ class ResMrpWorkOrder(models.Model):
def _compute_surface_technics_purchase_ids(self):
for order in self:
if order.routing_type == '表面工艺' and order.state not in ['cancel']:
+ # domain = [('group_id', '=', self.production_id.procurement_group_id.id),
+ # ('purchase_type', '=', 'consignment'), ('state', '!=', 'cancel')]
domain = [('purchase_type', '=', 'consignment'),
('origin', 'like', '%' + self.production_id.name + '%'),
('state', '!=', 'cancel')]
- # domain = [('purchase_type', '=', 'consignment'),
- # ('origin', 'like', '%' + self.production_id.name + '%'),
- # ('state', '!=', 'cancel')]
purchase = self.env['purchase.order'].search(domain)
order.surface_technics_purchase_count = 0
if not purchase:
@@ -461,30 +460,30 @@ class ResMrpWorkOrder(models.Model):
else:
order.surface_technics_purchase_count = 0
- # def action_view_pr_mrp_workorder(self):
- # """
- # 采购请求
- # """
- # self.ensure_one()
- # pr_ids = self.env['purchase.request'].sudo().search(
- # [('origin', 'like', self.production_id.name), ('is_subcontract', '=', 'True'),
- # ('state', '!=', 'rejected')])
- # action = {
- # 'res_model': 'purchase.request',
- # 'type': 'ir.actions.act_window',
- # }
- # if len(pr_ids) == 1:
- # action.update({
- # 'view_mode': 'form',
- # 'res_id': pr_ids[0].id,
- # })
- # else:
- # action.update({
- # 'name': _("从 %s生成采购请求单", self.name),
- # 'domain': [('id', 'in', pr_ids)],
- # 'view_mode': 'tree,form',
- # })
- # return action
+ def action_view_pr_mrp_workorder(self):
+ """
+ 采购请求
+ """
+ self.ensure_one()
+ pr_ids = self.env['purchase.request'].sudo().search(
+ [('origin', 'like', self.production_id.name), ('is_subcontract', '=', 'True'),
+ ('state', '!=', 'rejected')])
+ action = {
+ 'res_model': 'purchase.request',
+ 'type': 'ir.actions.act_window',
+ }
+ if len(pr_ids) == 1:
+ action.update({
+ 'view_mode': 'form',
+ 'res_id': pr_ids[0].id,
+ })
+ else:
+ action.update({
+ 'name': _("从 %s生成采购请求单", self.name),
+ 'domain': [('id', 'in', pr_ids)],
+ 'view_mode': 'tree,form',
+ })
+ return action
def action_view_surface_technics_purchase(self):
self.ensure_one()
# if self.routing_type == '表面工艺':
@@ -513,7 +512,7 @@ class ResMrpWorkOrder(models.Model):
return result
def _get_surface_technics_purchase_ids(self):
- domain = [('origin', 'like', '%' + self.production_id.name + '%'), ('purchase_type', '=', 'consignment'), ('state', '!=', 'cancel')]
+ domain = [('origin', 'like', '%' + self.production_id.name + '%'), ('purchase_type', '=', 'consignment'), ('is_subcontract', '=', 'True'), ('state', '!=', 'cancel')]
# domain = [('origin', 'like', '%' + self.production_id.name + '%'), ('purchase_type', '=', 'consignment')]
# domain = [('group_id', '=', self.production_id.procurement_group_id.id), ('purchase_type', '=', 'consignment')]
purchase_orders = self.env['purchase.order'].search(domain, order='id desc')
diff --git a/sf_manufacturing/models/purchase_order.py b/sf_manufacturing/models/purchase_order.py
index 9b682d83..9e11e7c0 100644
--- a/sf_manufacturing/models/purchase_order.py
+++ b/sf_manufacturing/models/purchase_order.py
@@ -59,6 +59,86 @@ class PurchaseOrder(models.Model):
production_id = self.env['mrp.production'].search([('origin', 'in', origins)])
purchase.production_count = len(production_id)
+ def process_replenish(self,production,total_qty):
+ record = self
+ bom_line_id = production.bom_id.bom_line_ids
+ replenish = self.env['stock.warehouse.orderpoint'].search([
+ ('product_id', '=', bom_line_id.product_id.id),
+ (
+ 'location_id', '=', self.env.ref('sf_stock.stock_location_outsourcing_material_receiving_area').id),
+ # ('state', 'in', ['draft', 'confirmed'])
+ ], limit=1)
+ if not replenish:
+ replenish_model = self.env['stock.warehouse.orderpoint']
+ replenish = replenish_model.create({
+ 'product_id': bom_line_id.product_id.id,
+ 'location_id': self.env.ref(
+ 'sf_stock.stock_location_outsourcing_material_receiving_area').id,
+ 'route_id': self.env.ref('sf_stock.stock_route_process_outsourcing').id,
+ 'group_id': record.group_id.id,
+ 'qty_to_order': total_qty,
+ 'origin': record.name,
+ })
+ else:
+ replenish.write({
+ 'product_id': bom_line_id.product_id.id,
+ 'location_id': self.env.ref(
+ 'sf_stock.stock_location_outsourcing_material_receiving_area').id,
+ 'route_id': self.env.ref('sf_stock.stock_route_process_outsourcing').id,
+ 'group_id': record.group_id.id,
+ 'qty_to_order': total_qty + replenish.qty_to_order,
+ 'origin': record.name + ',' + replenish.origin,
+ })
+ replenish.action_replenish()
+
+ def outsourcing_service_replenishment(self):
+ record = self
+ if record.purchase_type != 'consignment':
+ return
+ grouped_lines = {}
+ for line in record.order_line:
+ if line.related_product.id not in grouped_lines:
+ grouped_lines[line.related_product.id] = []
+ grouped_lines[line.related_product.id].append(line)
+ for product_id,lines in grouped_lines.items():
+ production = self.env['mrp.production'].search([('product_id', '=', product_id)], limit=1)
+ if not production:
+ continue
+ total_qty = sum(line.product_qty for line in lines)
+ record.process_replenish(production,total_qty)
+ for product_id,lines in grouped_lines.items():
+ productions = self.env['mrp.production'].search([('product_id', '=', product_id)], limit=1)
+ if not productions:
+ continue
+ # production.bom_id.bom_line_ids.product_id
+ location_id = self.env['stock.location'].search([('name', '=', '制造前')])
+ quants = self.env['stock.quant'].search([
+ ('product_id', '=', productions.bom_id.bom_line_ids.product_id.id),
+ ('location_id', '=', location_id.id)
+ ])
+ total_qty = sum(quants.mapped('quantity')) # 计算该位置的总库存量
+ is_available = total_qty > 0
+ if not is_available:
+ continue
+ for production_id in productions:
+ work_ids = production_id.workorder_ids.filtered(
+ lambda wk: wk.state not in ['done', 'rework', 'cancel'])
+ if not work_ids:
+ continue
+ min_sequence_wk = min(work_ids, key=lambda wk: wk.sequence)
+ if min_sequence_wk.is_subcontract:
+ picking_id = production_id.picking_ids.filtered(
+ lambda wk: wk.location_id.name == '制造前' and wk.location_dest_id.name == '外协加工区')
+ move_out = picking_id.move_ids
+ 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(production_id, min_sequence_wk))
+ # product = self.env['mrp.production'].search([('product_id', '=', product_id)], limit=1)
+ # match = re.search(r'(S\d{5}-\d)',product.name)
+ # pass
def button_confirm(self):
for record in self:
for line in record.order_line:
@@ -66,37 +146,7 @@ class PurchaseOrder(models.Model):
raise UserError('请对【产品】中的【数量】进行输入')
if line.price_unit <= 0:
raise UserError('请对【产品】中的【单价】进行输入')
- # if record.purchase_type == 'consignment':
- # bom_line_id = record.order_line[0].purchase_request_lines.request_id.bom_id.bom_line_ids
- # replenish = self.env['stock.warehouse.orderpoint'].search([
- # ('product_id', '=', bom_line_id.product_id.id),
- # (
- # 'location_id', '=', self.env.ref('sf_stock.stock_location_outsourcing_material_receiving_area').id),
- # # ('state', 'in', ['draft', 'confirmed'])
- # ], limit=1)
- # if not replenish:
- # replenish_model = self.env['stock.warehouse.orderpoint']
- # replenish = replenish_model.create({
- # 'product_id': bom_line_id.product_id.id,
- # 'location_id': self.env.ref(
- # 'sf_stock.stock_location_outsourcing_material_receiving_area').id,
- # 'route_id': self.env.ref('sf_stock.stock_route_process_outsourcing').id,
- # 'group_id': record.group_id.id,
- # 'qty_to_order': 1,
- # 'origin': record.name,
- # })
- # else:
- # replenish.write({
- # 'product_id': bom_line_id.product_id.id,
- # 'location_id': self.env.ref(
- # 'sf_stock.stock_location_outsourcing_material_receiving_area').id,
- # 'route_id': self.env.ref('sf_stock.stock_route_process_outsourcing').id,
- # 'group_id': record.group_id.id,
- # 'qty_to_order': 1 + replenish.qty_to_order,
- # 'origin': record.name + ',' + replenish.origin,
- # })
- # replenish.action_replenish()
-
+ record.outsourcing_service_replenishment()
return super(PurchaseOrder, self).button_confirm()
diff --git a/sf_manufacturing/models/purchase_request_line.py b/sf_manufacturing/models/purchase_request_line.py
index eca52d3b..b08bb3e7 100644
--- a/sf_manufacturing/models/purchase_request_line.py
+++ b/sf_manufacturing/models/purchase_request_line.py
@@ -1,30 +1,30 @@
-# # -*- coding: utf-8 -*-
-# import base64
-# import datetime
-# import logging
-# import json
-# import os
-# import re
-# import traceback
-# from operator import itemgetter
-#
-# import requests
-# from itertools import groupby
-# from collections import defaultdict, namedtuple
-#
-# from odoo import api, fields, models, SUPERUSER_ID, _
-# from odoo.exceptions import UserError, ValidationError
-# from odoo.tools import float_compare, float_round, float_is_zero, format_datetime
-#
-#
-# class PurchaseRequestLine(models.Model):
-# _inherit = 'purchase.request'
-# is_subcontract = fields.Boolean(string='是否外协',default=False)
-# class PurchaseRequestLine(models.Model):
-# _inherit = 'purchase.request.line'
-# is_subcontract = fields.Boolean(string='是否外协')
-#
-#
-# class PurchaseRequest(models.Model):
-# _inherit = 'purchase.request'
-# bom_id = fields.Many2one('mrp.bom')
+# -*- coding: utf-8 -*-
+import base64
+import datetime
+import logging
+import json
+import os
+import re
+import traceback
+from operator import itemgetter
+
+import requests
+from itertools import groupby
+from collections import defaultdict, namedtuple
+
+from odoo import api, fields, models, SUPERUSER_ID, _
+from odoo.exceptions import UserError, ValidationError
+from odoo.tools import float_compare, float_round, float_is_zero, format_datetime
+
+
+class PurchaseRequestLine(models.Model):
+ _inherit = 'purchase.request'
+ is_subcontract = fields.Boolean(string='是否外协',default=False)
+class PurchaseRequestLine(models.Model):
+ _inherit = 'purchase.request.line'
+ is_subcontract = fields.Boolean(string='是否外协')
+
+
+class PurchaseRequest(models.Model):
+ _inherit = 'purchase.request'
+ bom_id = fields.Many2one('mrp.bom')
diff --git a/sf_manufacturing/models/sf_production_common.py b/sf_manufacturing/models/sf_production_common.py
index 2cdfd750..1c066bbe 100644
--- a/sf_manufacturing/models/sf_production_common.py
+++ b/sf_manufacturing/models/sf_production_common.py
@@ -7,74 +7,74 @@ from odoo.exceptions import UserError, ValidationError
class SfProductionProcessParameter(models.Model):
_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(
- # 'product.template', # 另一个模型的名称
- # 'server_product_process_parameters_id', # 对应的 Many2one 字段名称
- # string='外协服务产品'
- # )
- # is_product_button = fields.Boolean(compute='_compute_is_product_button',default=False)
- # is_delete_button = fields.Boolean(compute='_compute_is_delete_button', default=False)
- # 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')
- # def _validate_partner_limit(self):
- # for record in self:
- # if len(record.outsourced_service_products) > 1:
- # raise ValidationError("工艺参数不能与多个产品关联")
- #
- # @api.onchange('outsourced_service_products')
- # def _onchange_validate_partner_limit(self):
- # for record in self:
- # if len(record.outsourced_service_products) > 1:
- # raise ValidationError("工艺参数不能与多个产品关联")
- # @api.depends('outsourced_service_products')
- # def _compute_is_product_button(self):
- # for record in self:
- # if record.outsourced_service_products:
- # record.is_product_button = True
- # else:
- # record.is_product_button = False
- #
- # def has_wksp_prefix(self):
- # """
- # 判断字符串是否以WKSP开头(不区分大小写)
- # :param text: 要检查的字符串
- # :return: True/False
- # """
- # return self.code.upper().startswith('101'+self.routing_id.code)
- # @api.depends('outsourced_service_products','code')
- # def _compute_is_delete_button(self):
- # for record in self:
- # if record.outsourced_service_products and record.has_wksp_prefix():
- # record.is_delete_button = False
- # elif record.outsourced_service_products:
- # record.is_delete_button = True
- # else:
- # record.is_delete_button = True
+ service_products = fields.Many2one(
+ 'product.template',
+ string='外协服务产品',compute='_compute_service_products',inverse='_inverse_service_products',
+ store=True
+ )
+ outsourced_service_products = fields.One2many(
+ 'product.template', # 另一个模型的名称
+ 'server_product_process_parameters_id', # 对应的 Many2one 字段名称
+ string='外协服务产品'
+ )
+ is_product_button = fields.Boolean(compute='_compute_is_product_button',default=False)
+ is_delete_button = fields.Boolean(compute='_compute_is_delete_button', default=False)
+ 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')
+ def _validate_partner_limit(self):
+ for record in self:
+ if len(record.outsourced_service_products) > 1:
+ raise ValidationError("工艺参数不能与多个产品关联")
+
+ @api.onchange('outsourced_service_products')
+ def _onchange_validate_partner_limit(self):
+ for record in self:
+ if len(record.outsourced_service_products) > 1:
+ raise ValidationError("工艺参数不能与多个产品关联")
+ @api.depends('outsourced_service_products')
+ def _compute_is_product_button(self):
+ for record in self:
+ if record.outsourced_service_products:
+ record.is_product_button = True
+ else:
+ record.is_product_button = False
+
+ def has_wksp_prefix(self):
+ """
+ 判断字符串是否以WKSP开头(不区分大小写)
+ :param text: 要检查的字符串
+ :return: True/False
+ """
+ return self.code.upper().startswith('101'+self.routing_id.code)
+ @api.depends('outsourced_service_products','code')
+ def _compute_is_delete_button(self):
+ for record in self:
+ if record.outsourced_service_products and record.has_wksp_prefix():
+ record.is_delete_button = False
+ elif record.outsourced_service_products:
+ record.is_delete_button = True
+ else:
+ record.is_delete_button = True
@api.model
def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None):
if self._context.get('route_id'):
@@ -90,19 +90,19 @@ class SfProductionProcessParameter(models.Model):
return self._search(domain, limit=limit, access_rights_uid=name_get_uid)
return super()._name_search(name, args, operator, limit, name_get_uid)
- # def action_create_service_product(self):
- # if self.id: # 如果是已存在的记录
- # self.write({}) # 空写入会触发保存
- # else: # 如果是新记录
- # self = self.create(self._convert_to_write(self.read()[0]))
- # return {
- # 'type': 'ir.actions.act_window',
- # 'name': '向导名称',
- # 'res_model': 'product.creation.wizard',
- # 'view_mode': 'form',
- # 'target': 'new',
- # 'context': {'default_process_parameter_id': self.id}, # 传递当前记录ID
- # }
+ def action_create_service_product(self):
+ if self.id: # 如果是已存在的记录
+ self.write({}) # 空写入会触发保存
+ else: # 如果是新记录
+ self = self.create(self._convert_to_write(self.read()[0]))
+ return {
+ 'type': 'ir.actions.act_window',
+ 'name': '向导名称',
+ 'res_model': 'product.creation.wizard',
+ 'view_mode': 'form',
+ 'target': 'new',
+ 'context': {'default_process_parameter_id': self.id}, # 传递当前记录ID
+ }
#
# return {
# 'name': '创建服务产品',
@@ -116,6 +116,6 @@ class SfProductionProcessParameter(models.Model):
# },
# }
- # def action_hide_service_products(self):
- # # self.outsourced_service_products.active = False
- # self.active = False
+ def action_hide_service_products(self):
+ # self.outsourced_service_products.active = False
+ self.active = False
diff --git a/sf_manufacturing/views/mrp_production_addional_change.xml b/sf_manufacturing/views/mrp_production_addional_change.xml
index 89c92117..ef4f6f25 100644
--- a/sf_manufacturing/views/mrp_production_addional_change.xml
+++ b/sf_manufacturing/views/mrp_production_addional_change.xml
@@ -383,7 +383,7 @@
+ options="{'no_create': True}" domain="[('routing_id', '=', 'route_id')]"/>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sf_manufacturing/views/mrp_workorder_view.xml b/sf_manufacturing/views/mrp_workorder_view.xml
index c519ff70..bf8ed141 100644
--- a/sf_manufacturing/views/mrp_workorder_view.xml
+++ b/sf_manufacturing/views/mrp_workorder_view.xml
@@ -144,17 +144,17 @@
statusbar_visible="pending,waiting,ready,progress,to be detected,done,rework"/>
-
-
-
-
-
-
-
-
-
-
-
+