销售订单与制造订单关联
This commit is contained in:
@@ -8,6 +8,9 @@ import re
|
||||
import requests
|
||||
from itertools import groupby
|
||||
from collections import defaultdict, namedtuple
|
||||
|
||||
from loguru import _logger
|
||||
|
||||
from odoo import api, fields, models, SUPERUSER_ID, _
|
||||
from odoo.exceptions import UserError, ValidationError
|
||||
from odoo.addons.sf_base.commons.common import Common
|
||||
@@ -18,6 +21,7 @@ class MrpProduction(models.Model):
|
||||
_inherit = 'mrp.production'
|
||||
_description = "制造订单"
|
||||
_order = 'create_date desc'
|
||||
sale_order_id = fields.Many2one('sale.order',string='销售订单', compute='_compute_sale_order_id', store=True)
|
||||
deadline_of_delivery = fields.Date('订单交期', tracking=True, compute='_compute_deadline_of_delivery')
|
||||
# tray_ids = fields.One2many('sf.tray', 'production_id', string="托盘")
|
||||
maintenance_count = fields.Integer(compute='_compute_maintenance_count', string="Number of maintenance requests")
|
||||
@@ -34,6 +38,28 @@ class MrpProduction(models.Model):
|
||||
tool_state_remark = fields.Text(string='功能刀具状态备注(缺刀)', compute='_compute_tool_state_remark', store=True)
|
||||
tool_state_remark2 = fields.Text(string='功能刀具状态备注(无效刀)', readonly=True)
|
||||
|
||||
@api.depends('procurement_group_id.mrp_production_ids.move_dest_ids.group_id.sale_id')
|
||||
def _compute_sale_order_id(self):
|
||||
for production in self:
|
||||
# 初始化 sale_order_id 为 False
|
||||
sale_order_id = False
|
||||
# 使用正则表达式查找产品名称中的 'S' 开头的字母数字字符串
|
||||
match = re.search(r'S\d+', production.product_id.with_context(lang='zh_CN').name) # 从字符串开始匹配
|
||||
|
||||
if match:
|
||||
result = match.group(0)
|
||||
try:
|
||||
# 查找与匹配的字符串相符的销售订单
|
||||
sale_order = self.env['sale.order'].search(
|
||||
[('name', '=', result)], limit=1, order='id asc'
|
||||
)
|
||||
if sale_order:
|
||||
production.sale_order_id = sale_order.id
|
||||
else:
|
||||
_logger.warning("No sale order found for production %s with product %s (name match: %s)",
|
||||
production.id, production.product_id.name, result)
|
||||
except Exception as e:
|
||||
_logger.error("Error while fetching sale order for production %s: %s", production.id, str(e))
|
||||
@api.depends('procurement_group_id.mrp_production_ids.move_dest_ids.group_id.sale_id')
|
||||
def _compute_deadline_of_delivery(self):
|
||||
for production in self:
|
||||
@@ -309,7 +335,8 @@ class MrpProduction(models.Model):
|
||||
for move in production.move_raw_ids if move.product_id):
|
||||
production.state = 'progress'
|
||||
# 新添加的状态逻辑
|
||||
if production.state in ['to_close', 'progress', 'technology_to_confirmed'] and production.schedule_state == '未排':
|
||||
if production.state in ['to_close', 'progress',
|
||||
'technology_to_confirmed'] and production.schedule_state == '未排':
|
||||
if not production.workorder_ids or production.is_adjust is True:
|
||||
production.state = 'technology_to_confirmed'
|
||||
else:
|
||||
@@ -320,11 +347,7 @@ class MrpProduction(models.Model):
|
||||
elif production.state == 'pending_cam' and production.schedule_state == '未排':
|
||||
production.state = 'confirmed'
|
||||
elif production.state == 'to_close' and production.schedule_state == '已排':
|
||||
if all(
|
||||
wo_state in ('done', 'cancel') for wo_state in production.workorder_ids.mapped('state')):
|
||||
production.state = 'done'
|
||||
else:
|
||||
production.state = 'pending_cam'
|
||||
production.state = 'pending_cam'
|
||||
elif production.state == 'confirmed' and production.is_adjust is True:
|
||||
production.state = 'technology_to_confirmed'
|
||||
if production.state == 'confirmed' and production.schedule_state == '已排':
|
||||
@@ -335,6 +358,9 @@ class MrpProduction(models.Model):
|
||||
production.state = 'pending_cam'
|
||||
if production.is_rework is True:
|
||||
production.state = 'rework'
|
||||
if (production.state == 'rework' and production.tool_state == '0'
|
||||
and production.schedule_state == '已排' and production.is_rework is False):
|
||||
production.state = 'pending_cam'
|
||||
# if production.state == 'pending_cam':
|
||||
# if all(wo_state in 'done' for wo_state in production.workorder_ids.mapped('state')):
|
||||
# production.state = 'done'
|
||||
@@ -721,10 +747,16 @@ class MrpProduction(models.Model):
|
||||
for product_id, pd in grouped_product_ids.items():
|
||||
product_id_to_production_names[product_id] = [p.name for p in pd]
|
||||
for production in production_all:
|
||||
proc_workorders = []
|
||||
process_parameter_workorder = self.env['mrp.workorder'].search(
|
||||
[('surface_technics_parameters_id', '!=', False), ('production_id', '=', production.id),
|
||||
('is_subcontract', '=', True)], order='sequence asc')
|
||||
('is_subcontract', '=', True), ('state', '!=', 'cancel')], order='sequence asc')
|
||||
if process_parameter_workorder:
|
||||
# 将这些特殊表面工艺工单的采购单与调拨单置为失效
|
||||
for workorder in process_parameter_workorder:
|
||||
workorder._get_surface_technics_purchase_ids().write({'state': 'cancel'})
|
||||
workorder.move_subcontract_workorder_ids.write({'state': 'cancel'})
|
||||
workorder.move_subcontract_workorder_ids.picking_id.write({'state': 'cancel'})
|
||||
consecutive_workorders = []
|
||||
sorted_workorders = sorted(process_parameter_workorder, key=lambda w: w.sequence)
|
||||
for i, workorder in enumerate(sorted_workorders):
|
||||
@@ -737,10 +769,11 @@ class MrpProduction(models.Model):
|
||||
else:
|
||||
# 处理连续组,如果它不为空
|
||||
if consecutive_workorders:
|
||||
proc_workorders.append(consecutive_workorders)
|
||||
# 创建外协出入库单和采购订单
|
||||
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production)
|
||||
self.env['purchase.order'].get_purchase_order(consecutive_workorders, production,
|
||||
product_id_to_production_names)
|
||||
# self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production, sorted_workorders)
|
||||
# self.env['purchase.order'].get_purchase_order(consecutive_workorders, production,
|
||||
# product_id_to_production_names)
|
||||
if i < len(sorted_workorders) - 1:
|
||||
# 重置连续组,并添加当前工作订单
|
||||
consecutive_workorders = [workorder]
|
||||
@@ -751,18 +784,22 @@ class MrpProduction(models.Model):
|
||||
i - 1].supplier_id.id:
|
||||
consecutive_workorders = [workorder]
|
||||
else:
|
||||
proc_workorders.append([workorder])
|
||||
# 立即创建外协出入库单和采购订单
|
||||
self.env['stock.picking'].create_outcontract_picking(workorder, production)
|
||||
self.env['purchase.order'].get_purchase_order(workorder, production,
|
||||
product_id_to_production_names)
|
||||
# self.env['stock.picking'].create_outcontract_picking(workorder, production)
|
||||
# self.env['purchase.order'].get_purchase_order(workorder, production,
|
||||
# product_id_to_production_names)
|
||||
consecutive_workorders = []
|
||||
|
||||
# 处理最后一个组,即使它可能只有一个工作订单
|
||||
if consecutive_workorders:
|
||||
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production)
|
||||
self.env['purchase.order'].get_purchase_order(consecutive_workorders, production,
|
||||
product_id_to_production_names)
|
||||
|
||||
proc_workorders.append(consecutive_workorders)
|
||||
# self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production)
|
||||
# self.env['purchase.order'].get_purchase_order(consecutive_workorders, production,
|
||||
# product_id_to_production_names)
|
||||
for workorders in reversed(proc_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)
|
||||
# 工单排序
|
||||
def _reset_work_order_sequence1(self, k):
|
||||
for rec in self:
|
||||
@@ -847,17 +884,22 @@ class MrpProduction(models.Model):
|
||||
# workorder.picking_ids.move_ids = False
|
||||
workorder.picking_ids = False
|
||||
purchase_order = self.env['purchase.order'].search(
|
||||
[('state', '=', 'draft'), ('origin', '=', ','.join(production_process)),
|
||||
[('state', '=', 'draft'), ('origin', '=', item.name),
|
||||
('purchase_type', '=', 'consignment')])
|
||||
for line in purchase_order.order_line:
|
||||
server_template = self.env['product.template'].search(
|
||||
[('server_product_process_parameters_id', '=', workorder.surface_technics_parameters_id.id),
|
||||
('detailed_type', '=', 'service')])
|
||||
purchase_order_line = self.env['purchase.order.line'].search(
|
||||
[('product_id', '=', server_template.product_variant_id.id), ('id', '=', line.id),
|
||||
('product_qty', '=', len(production_process))], limit=1, order='id desc')
|
||||
if purchase_order_line:
|
||||
line.unlink()
|
||||
server_template = self.env['product.template'].search(
|
||||
[('server_product_process_parameters_id', '=',
|
||||
workorder.surface_technics_parameters_id.id),
|
||||
('detailed_type', '=', 'service')])
|
||||
for po in purchase_order:
|
||||
for line in po.order_line:
|
||||
if line.product_id == server_template.product_variant_id:
|
||||
continue
|
||||
if server_template.server_product_process_parameters_id != line.product_id.server_product_process_parameters_id:
|
||||
purchase_order_line = self.env['purchase.order.line'].search(
|
||||
[('product_id', '=', server_template.product_variant_id.id), ('id', '=', line.id),
|
||||
('product_qty', '=', 1)], limit=1, order='id desc')
|
||||
if purchase_order_line:
|
||||
line.unlink()
|
||||
|
||||
def _reset_work_order_sequence(self):
|
||||
"""
|
||||
@@ -898,8 +940,6 @@ class MrpProduction(models.Model):
|
||||
for cw in cancel_work_ids:
|
||||
cw.sequence = sequence + 1
|
||||
|
||||
|
||||
|
||||
def _reset_work_order_sequence_1(self):
|
||||
"""
|
||||
工单工序排序方法(旧)
|
||||
@@ -1012,7 +1052,7 @@ class MrpProduction(models.Model):
|
||||
if self.production_type == '自动化产线加工':
|
||||
date_planned_start, date_planned_end, last_time = work.auto_production_process(last_time, count,
|
||||
type_map)
|
||||
elif self.production_type == '人工线下加工':
|
||||
elif self.production_type == '':
|
||||
date_planned_start, date_planned_end, last_time = work.manual_offline_process(last_time, index)
|
||||
work.update_work_start_end(date_planned_start, date_planned_end)
|
||||
|
||||
@@ -1324,11 +1364,10 @@ class MrpProduction(models.Model):
|
||||
move = self.env['stock.move'].search([('origin', '=', productions.name)], order='id desc')
|
||||
for mo in move:
|
||||
domain = []
|
||||
if mo.procure_method == 'make_to_order' and mo.name != productions.name:
|
||||
if mo.name == '/':
|
||||
domain = [('barcode', '=', 'WH-PC'), ('sequence_code', '=', 'PC')]
|
||||
elif mo.name == '拉':
|
||||
domain = [('barcode', '=', 'WH-INTERNAL'), ('sequence_code', '=', 'INT')]
|
||||
if mo.location_id.barcode == 'WH-POSTPRODUCTION' and mo.rule_id.picking_type_id.barcode == 'PC':
|
||||
domain = [('barcode', '=', 'WH-PC'), ('sequence_code', '=', 'PC')]
|
||||
elif mo.location_id.barcode == 'PL' and mo.rule_id.picking_type_id.barcode == 'INT':
|
||||
domain = [('barcode', '=', 'WH-INTERNAL'), ('sequence_code', '=', 'INT')]
|
||||
if domain:
|
||||
picking_type = self.env['stock.picking.type'].search(domain)
|
||||
mo.write({'picking_type_id': picking_type.id})
|
||||
@@ -1422,6 +1461,26 @@ class MrpProduction(models.Model):
|
||||
for production in self:
|
||||
production.production_type = '自动化产线加工' if not production.product_id.is_manual_processing else '人工线下加工'
|
||||
|
||||
@api.depends('procurement_group_id.mrp_production_ids.move_dest_ids.group_id.sale_id')
|
||||
def _compute_sale_order_count(self):
|
||||
for production in self:
|
||||
if production.sale_order_id:
|
||||
production.sale_order_count = 1
|
||||
else:
|
||||
production.sale_order_count = 0
|
||||
def action_view_sale_orders(self):
|
||||
if self.sale_order_id:
|
||||
action = {
|
||||
'res_model': 'sale.order',
|
||||
'type': 'ir.actions.act_window',
|
||||
}
|
||||
action.update({
|
||||
'view_mode': 'form',
|
||||
'res_id': self.sale_order_id.id,
|
||||
})
|
||||
return action
|
||||
|
||||
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user