Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
'wizard/production_wizard_views.xml',
|
||||
'wizard/production_technology_wizard_views.xml',
|
||||
'wizard/production_technology_re_adjust_wizard_views.xml',
|
||||
'wizard/mrp_workorder_batch_replan_wizard_views.xml',
|
||||
'views/mrp_views_menus.xml',
|
||||
'views/agv_scheduling_views.xml',
|
||||
'views/stock_lot_views.xml',
|
||||
@@ -38,6 +39,7 @@
|
||||
'views/sf_maintenance_equipment.xml',
|
||||
'views/res_config_settings_views.xml',
|
||||
'views/sale_order_views.xml',
|
||||
'views/mrp_workorder_batch_replan.xml',
|
||||
],
|
||||
'assets': {
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import re
|
||||
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.addons.sf_base.commons.common import Common
|
||||
@@ -18,6 +19,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 +36,29 @@ 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:
|
||||
logging.warning("No sale order found for production {} with product {} (name match: {})".format(
|
||||
production.id, production.product_id.name, result))
|
||||
except Exception as e:
|
||||
logging.error("Error while fetching sale order for production {}: {}".format(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:
|
||||
@@ -378,16 +403,37 @@ class MrpProduction(models.Model):
|
||||
if process_parameters:
|
||||
raise UserError(_("【工艺设计】-【参数】为%s的在【产品】中不存在,请先创建", ", ".join(process_parameters)))
|
||||
if production_confirmed:
|
||||
return {
|
||||
'name': _('退回调整'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'view_mode': 'form',
|
||||
'res_model': 'sf.production.technology.re_adjust.wizard',
|
||||
'target': 'new',
|
||||
'context': {
|
||||
'default_production_id': self.id,
|
||||
'default_origin': self.origin,
|
||||
}}
|
||||
production_count = self.env['mrp.production'].search_count([
|
||||
('origin', '=', self.origin),
|
||||
('product_id', '=', self.product_id.id),
|
||||
('state', '=', 'confirmed')
|
||||
])
|
||||
if production_count > 1:
|
||||
return {
|
||||
'name': _('退回调整'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'views': [(self.env.ref(
|
||||
'sf_manufacturing.sf_production_technology_re_adjust_wizard_form_view').id,
|
||||
'form')],
|
||||
'res_model': 'sf.production.technology.re_adjust.wizard',
|
||||
'target': 'new',
|
||||
'context': {
|
||||
'default_production_id': self.id,
|
||||
'default_origin': self.origin,
|
||||
}}
|
||||
else:
|
||||
return {
|
||||
'name': _('退回调整'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'views': [(self.env.ref(
|
||||
'sf_manufacturing.sf_production_technology_re_adjust_wizard_confirm_form_view').id,
|
||||
'form')],
|
||||
'res_model': 'sf.production.technology.re_adjust.wizard',
|
||||
'target': 'new',
|
||||
'context': {
|
||||
'default_production_id': self.id,
|
||||
'default_origin': self.origin,
|
||||
}}
|
||||
|
||||
# 工艺确认
|
||||
def technology_confirm(self):
|
||||
@@ -441,16 +487,37 @@ class MrpProduction(models.Model):
|
||||
error_panel.append(design.panel)
|
||||
else:
|
||||
if not error_panel and not process_parameters:
|
||||
return {
|
||||
'name': _('工艺确认'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'view_mode': 'form',
|
||||
'res_model': 'sf.production.technology.wizard',
|
||||
'target': 'new',
|
||||
'context': {
|
||||
'default_production_id': self.id,
|
||||
'default_origin': self.origin,
|
||||
}}
|
||||
production_count = self.env['mrp.production'].search_count([
|
||||
('origin', '=', self.origin),
|
||||
('product_id', '=', self.product_id.id),
|
||||
('state', '=', 'technology_to_confirmed')
|
||||
])
|
||||
if production_count > 1:
|
||||
return {
|
||||
'name': _('工艺确认'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'views': [(self.env.ref(
|
||||
'sf_manufacturing.sf_production_technology_wizard_form_view').id,
|
||||
'form')],
|
||||
'res_model': 'sf.production.technology.wizard',
|
||||
'target': 'new',
|
||||
'context': {
|
||||
'default_production_id': self.id,
|
||||
'default_origin': self.origin,
|
||||
}}
|
||||
else:
|
||||
return {
|
||||
'name': _('工艺确认'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'views': [(self.env.ref(
|
||||
'sf_manufacturing.sf_production_technology_wizard_confirm_form_view').id,
|
||||
'form')],
|
||||
'res_model': 'sf.production.technology.wizard',
|
||||
'target': 'new',
|
||||
'context': {
|
||||
'default_production_id': self.id,
|
||||
'default_origin': self.origin,
|
||||
}}
|
||||
if error_panel:
|
||||
raise UserError(_("【加工面】为%s的标准工序顺序有误,请调整后重试", ", ".join(error_panel)))
|
||||
return True
|
||||
@@ -762,7 +829,7 @@ class MrpProduction(models.Model):
|
||||
# 立即创建外协出入库单和采购订单
|
||||
# self.env['stock.picking'].create_outcontract_picking(workorder, production)
|
||||
# self.env['purchase.order'].get_purchase_order(workorder, production,
|
||||
# product_id_to_production_names)
|
||||
# product_id_to_production_names)
|
||||
consecutive_workorders = []
|
||||
|
||||
# 处理最后一个组,即使它可能只有一个工作订单
|
||||
@@ -774,6 +841,7 @@ class MrpProduction(models.Model):
|
||||
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:
|
||||
@@ -888,7 +956,7 @@ class MrpProduction(models.Model):
|
||||
# 对工单进行逐个插入
|
||||
for work_id in work_ids:
|
||||
for order_id in rec.workorder_ids.filtered(lambda item: item.sequence > 0):
|
||||
if work_id.name == order_id.name:
|
||||
if work_id.name == order_id.name and work_id.processing_panel == order_id.processing_panel:
|
||||
work_id.sequence = order_id.sequence + 1
|
||||
break
|
||||
# 对该工单之后的工单工序进行加一
|
||||
@@ -1170,7 +1238,9 @@ class MrpProduction(models.Model):
|
||||
lambda wk: (wk.name == result_id.routing_type and wk.processing_panel == result_id.processing_panel
|
||||
and wk.state == 'done')).id
|
||||
for result_id in result_ids]
|
||||
|
||||
workorder_ids = self.workorder_ids.filtered(
|
||||
lambda wk: wk.technology_design_id.routing_tag == 'standard' and wk.state not in ['rework', 'cancel'])
|
||||
logging.info('标准工艺工单【%s】' % workorder_ids)
|
||||
return {
|
||||
'name': _('返工'),
|
||||
'type': 'ir.actions.act_window',
|
||||
@@ -1179,7 +1249,7 @@ class MrpProduction(models.Model):
|
||||
'target': 'new',
|
||||
'context': {
|
||||
'default_production_id': self.id,
|
||||
'default_workorder_ids': self.workorder_ids.ids,
|
||||
'default_workorder_ids': workorder_ids.ids if workorder_ids.ids != [] else self.workorder_ids.ids,
|
||||
'default_hidden_workorder_ids': ','.join(map(str, work_id_list)) if work_id_list != [] else '',
|
||||
'default_reprogramming_num': cloud_programming['reprogramming_num'],
|
||||
'default_programming_state': cloud_programming['programming_state'],
|
||||
@@ -1435,6 +1505,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):
|
||||
"""
|
||||
@@ -1495,7 +1585,9 @@ class MrpProduction(models.Model):
|
||||
|
||||
def action_view_purchase_orders(self):
|
||||
self.ensure_one()
|
||||
if self.product_id.product_tmpl_id.single_manufacturing == True:
|
||||
if self.is_remanufacture:
|
||||
production = self
|
||||
elif self.product_id.product_tmpl_id.single_manufacturing == True:
|
||||
production = self.env['mrp.production'].search(
|
||||
[('origin', '=', self.origin), ('product_id', '=', self.product_id.id)], limit=1, order='id asc')
|
||||
else:
|
||||
|
||||
@@ -129,7 +129,7 @@ class ResMrpWorkOrder(models.Model):
|
||||
Y10_axis = fields.Float(default=0)
|
||||
Z10_axis = fields.Float(default=0)
|
||||
X_deviation_angle = fields.Integer(string="X轴偏差度", default=0)
|
||||
test_results = fields.Selection([("合格", "合格")], default='合格',
|
||||
test_results = fields.Selection([("合格", "合格"), ("返工", "返工"), ("报废", "报废")], default='合格',
|
||||
string="检测结果", tracking=True)
|
||||
cnc_ids = fields.One2many("sf.cnc.processing", 'workorder_id', string="CNC加工程序")
|
||||
cmm_ids = fields.One2many("sf.cmm.program", 'workorder_id', string="CMM程序")
|
||||
|
||||
@@ -656,8 +656,8 @@ class StockPicking(models.Model):
|
||||
def create_outcontract_picking(self, workorders, item, sorted_workorders):
|
||||
for workorder in workorders:
|
||||
if workorder.move_subcontract_workorder_ids:
|
||||
workorder.move_subcontract_workorder_ids.write({'state': 'draft'})
|
||||
workorder.move_subcontract_workorder_ids.picking_id.write({'state': 'draft'})
|
||||
workorder.move_subcontract_workorder_ids.write({'state': 'waiting'})
|
||||
workorder.move_subcontract_workorder_ids.picking_id.write({'state': 'waiting'})
|
||||
else:
|
||||
# 创建一个新的补货组
|
||||
procurement_group_id = self.env['procurement.group'].create({
|
||||
@@ -993,7 +993,8 @@ class ReStockMove(models.Model):
|
||||
production = self.env['mrp.production'].search([('name', '=', self[0].origin)], limit=1, order='id asc')
|
||||
productions = self.env['mrp.production'].search(
|
||||
[('origin', '=', production.origin), ('product_id', '=', production.product_id.id)])
|
||||
res['origin'] = ','.join(productions.mapped('name'))
|
||||
if productions.mapped('name'):
|
||||
res['origin'] = ','.join(productions.mapped('name'))
|
||||
res['retrospect_ref'] = production.product_id.name
|
||||
return res
|
||||
|
||||
|
||||
@@ -182,3 +182,5 @@ access_sf_manual_product_model_type_routing_sort_group_sf_mrp_user,sf_manual_pro
|
||||
access_sf_manual_product_model_type_routing_sort_manager,sf_manual_product_model_type_routing_sort,model_sf_manual_product_model_type_routing_sort,sf_base.group_sf_mrp_manager,1,1,1,1
|
||||
access_sf_manual_product_model_type_routing_sort_group_plan_dispatch,sf_manual_product_model_type_routing_sort_group_plan_dispatch,model_sf_manual_product_model_type_routing_sort,sf_base.group_plan_dispatch,1,0,0,0
|
||||
access_sf_detection_result_manager,sf_detection_result_manager,model_sf_detection_result,,1,1,1,1
|
||||
|
||||
access_mrp_workorder_batch_replan_wizard_group_plan_dispatch,mrp_workorder_batch_replan_wizard_group_plan_dispatch,model_mrp_workorder_batch_replan_wizard,sf_base.group_plan_dispatch,1,1,1,0
|
||||
|
@@ -43,6 +43,7 @@
|
||||
<field name="activity_ids" string="下一个活动" widget="list_activity" optional="hide"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='origin']" position="replace">
|
||||
<field name="sale_order_id" optional="show"/>
|
||||
<field name="origin" optional="hide"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='components_availability']" position="replace">
|
||||
@@ -123,6 +124,7 @@
|
||||
<field name="tool_state"
|
||||
attrs="{'invisible': [('production_type', 'not in', ['自动化产线加工'])]}"/>
|
||||
<field name="tool_state_remark" string="备注" attrs="{'invisible': [('tool_state', '!=', '1')]}"/>
|
||||
<field name="sale_order_id" readonly="1"/>
|
||||
<field name="deadline_of_delivery" readonly="1"/>
|
||||
<field name="tool_state_remark2" invisible="1"/>
|
||||
</xpath>
|
||||
@@ -584,6 +586,7 @@
|
||||
<searchpanel>
|
||||
<field name="state" icon="fa-filter" enable_counters="1"/>
|
||||
<field name="delivery_status" icon="fa-filter" enable_counters="1"/>
|
||||
<field name="production_type" icon="fa-filter" enable_counters="1"/>
|
||||
</searchpanel>
|
||||
</xpath>
|
||||
<filter name='todo' position="replace"/>
|
||||
|
||||
18
sf_manufacturing/views/mrp_workorder_batch_replan.xml
Normal file
18
sf_manufacturing/views/mrp_workorder_batch_replan.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<odoo>
|
||||
<data>
|
||||
<record id="mrp_production_workorder_tree_editable_view_inherit" model="ir.ui.view">
|
||||
<field name="name">>mrp.workorder.tree.editable.inherit</field>
|
||||
<field name="model">mrp.workorder</field>
|
||||
<field name="inherit_id" ref="mrp.mrp_production_workorder_tree_editable_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//tree/field[1]" position="before">
|
||||
<header>
|
||||
<button string="重新安排" name="%(sf_manufacturing.mrp_workorder_batch_replan_wizard)d" type="action"
|
||||
class="treeHeaderBtn"
|
||||
invisible="context.get('workorder_type') not in ('工件装夹中心','1#自动生产线','工件拆卸中心')"/>
|
||||
</header>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
@@ -104,8 +104,7 @@
|
||||
<!-- <field name="target">fullscreen</field>-->
|
||||
<field name="target">current</field>
|
||||
<field name="domain">[('state', '!=', 'cancel'),('schedule_state', '=', '已排')]</field>
|
||||
<field name="context">{'search_default_product': 1, 'search_default_workcenter_id':
|
||||
active_id,'search_default_filter_order_warning':1,'search_default_filter_order_overdue':1,'search_default_filter_order_normal':1}
|
||||
<field name="context">{'search_default_product': 1, 'search_default_workcenter_id': active_id}
|
||||
</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_workorder">
|
||||
@@ -200,7 +199,7 @@
|
||||
<!-- attrs="{'invisible': ['|', '|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '!=', 'blocked'),('state','=','done')]}"/> -->
|
||||
<!-- <button name="button_workpiece_delivery" type="object" string="工件配送" class="btn-primary"-->
|
||||
<!-- attrs="{'invisible': ['|','|','|','|',('routing_type','!=','装夹预调'),('is_delivery','=',True),('state','!=','done'),('is_rework','=',True),'&',('rfid_code','in',['',False]),('state','=','done')]}"/>-->
|
||||
<button name="button_rework_pre" type="object" string="异常反馈" invisible="1"
|
||||
<button name="button_rework_pre" type="object" string="异常反馈"
|
||||
class="btn-primary"
|
||||
attrs="{'invisible': ['|','|',('routing_type','!=','装夹预调'),('state','!=','progress'),('is_rework','=',True)]}"/>
|
||||
<button name="unbind_tray" type="object" string="解绑托盘"
|
||||
|
||||
@@ -3,3 +3,4 @@ from . import rework_wizard
|
||||
from . import production_wizard
|
||||
from . import production_technology_wizard
|
||||
from . import production_technology_re_adjust_wizard
|
||||
from . import mrp_workorder_batch_replan_wizard
|
||||
|
||||
70
sf_manufacturing/wizard/mrp_workorder_batch_replan_wizard.py
Normal file
70
sf_manufacturing/wizard/mrp_workorder_batch_replan_wizard.py
Normal file
@@ -0,0 +1,70 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import logging
|
||||
from datetime import datetime, timedelta
|
||||
from odoo import models, api, fields, _
|
||||
|
||||
|
||||
class MrpWorkorderBatchReplanWizard(models.TransientModel):
|
||||
_name = 'mrp.workorder.batch.replan.wizard'
|
||||
_description = '制造订单批量重新安排向导'
|
||||
|
||||
def _get_date_planned_start(self):
|
||||
planned_start_date = datetime.now() + timedelta(hours=2)
|
||||
logging.info('计划开始加工时间: %s', planned_start_date)
|
||||
return planned_start_date
|
||||
|
||||
def _get_default_workorder_count(self):
|
||||
active_ids = self.env.context.get('active_ids', [])
|
||||
return len(active_ids)
|
||||
|
||||
def _get_default_workorder_type(self):
|
||||
active_ids = self.env.context.get('active_ids', [])
|
||||
if active_ids:
|
||||
workorders = self.env['mrp.workorder'].browse(active_ids)
|
||||
if workorders:
|
||||
routing_type = set(workorders.mapped('routing_type'))
|
||||
return '/'.join(sorted(routing_type)) if routing_type else None
|
||||
return None
|
||||
|
||||
workorder_type = fields.Char(string='工单类型', default=_get_default_workorder_type, readonly=True)
|
||||
|
||||
workorder_count = fields.Integer(string='工单数量',
|
||||
default=_get_default_workorder_count,
|
||||
readonly=True)
|
||||
|
||||
workorder_id = fields.Many2many('mrp.workorder', string=u'工单')
|
||||
|
||||
def confirm(self):
|
||||
routing_type = set(self.workorder_id.mapped('routing_type'))
|
||||
if len(routing_type) > 1:
|
||||
raise models.ValidationError("批量重新安排工单类型必须一致。")
|
||||
show_json_popover = self.workorder_id.mapped('show_json_popover')
|
||||
if any(not value for value in show_json_popover):
|
||||
raise models.ValidationError("所选工单必须都为逾期状态")
|
||||
failed_workorders = {}
|
||||
for workorder_info in self.workorder_id:
|
||||
try:
|
||||
workorder_info.action_replan()
|
||||
except Exception as e:
|
||||
reason = str(e)
|
||||
if reason in failed_workorders:
|
||||
failed_workorders[reason].append(
|
||||
workorder_info.production_id.name)
|
||||
else:
|
||||
failed_workorders[reason] = [workorder_info.production_id.name]
|
||||
if failed_workorders:
|
||||
error_messages = "\n".join(
|
||||
[f"制造订单: {', '.join(workorder_names)}, 原因: {reason}" for reason, workorder_names in
|
||||
failed_workorders.items()])
|
||||
return {
|
||||
'type': 'ir.actions.client',
|
||||
'tag': 'display_notification',
|
||||
'params': {
|
||||
'message': f"以下工单重新安排失败:\n{error_messages}",
|
||||
'sticky': False,
|
||||
'color': 'red',
|
||||
'next': {
|
||||
'type': 'ir.actions.act_window_close'
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<record id="mrp_workorder_batch_replan_wizard_form" model="ir.ui.view">
|
||||
<field name="name">mrp.workorder.batch.replan.wizard.form.view</field>
|
||||
<field name="model">mrp.workorder.batch.replan.wizard</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<group>
|
||||
<field name="workorder_type"/>
|
||||
<field name="workorder_count"/>
|
||||
</group>
|
||||
<footer>
|
||||
<button string="确认" name="confirm" type="object" class="oe_highlight"/>
|
||||
<button string="取消" class="btn-primary" special="cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="mrp_workorder_batch_replan_wizard" model="ir.actions.act_window">
|
||||
<field name="name">重新安排工单</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">mrp.workorder.batch.replan.wizard</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="mrp_workorder_batch_replan_wizard_form"/>
|
||||
<field name="target">new</field>
|
||||
<field name="context">{'default_workorder_id': active_ids}</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -21,6 +21,26 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="sf_production_technology_re_adjust_wizard_confirm_form_view">
|
||||
<field name="name">sf.production.technology.re_adjust.wizard.form.view</field>
|
||||
<field name="model">sf.production.technology.re_adjust.wizard</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<sheet>
|
||||
<field name="production_id" invisible="1"/>
|
||||
<field name="origin" invisible="1"/>
|
||||
<div>
|
||||
是否确认退回调整
|
||||
</div>
|
||||
<footer>
|
||||
<button string="确认" name="confirm" type="object" class="oe_highlight"/>
|
||||
<button string="取消" class="btn btn-secondary" special="cancel"/>
|
||||
</footer>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_sf_production_technology_re_adjust_wizard" model="ir.actions.act_window">
|
||||
<field name="name">工艺退回调整</field>
|
||||
<field name="res_model">sf.production.technology.re_adjust.wizard</field>
|
||||
|
||||
@@ -14,7 +14,7 @@ class ProductionTechnologyWizard(models.TransientModel):
|
||||
is_technology_confirm = fields.Boolean(default=False)
|
||||
|
||||
def confirm(self):
|
||||
if self.is_technology_confirm is True and self.production_id.product_id.categ_id.type == '成品':
|
||||
if self.is_technology_confirm is True and self.production_id.product_id.categ_id.type in ['成品', '坯料']:
|
||||
domain = [('origin', '=', self.origin), ('state', '=', 'technology_to_confirmed'),
|
||||
('product_id', '=', self.production_id.product_id.id)]
|
||||
else:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record model="ir.ui.view" id="sf_production_technology_wizard_form_view">
|
||||
<record model="ir.ui.view" id="sf_production_technology_wizard_form_view">
|
||||
<field name="name">sf.production.technology.wizard.form.view</field>
|
||||
<field name="model">sf.production.technology.wizard</field>
|
||||
<field name="arch" type="xml">
|
||||
@@ -13,7 +13,28 @@
|
||||
对当前制造订单,同一销售订单相同产品所生成的制造订单统一进行工艺调整与确认
|
||||
</div>
|
||||
<footer>
|
||||
<button string="确认" name="confirm" type="object" class="oe_highlight" confirm="是否确认工艺调整"/>
|
||||
<button string="确认" name="confirm" type="object" class="oe_highlight"
|
||||
confirm="是否确认工艺调整"/>
|
||||
<button string="取消" class="btn btn-secondary" special="cancel"/>
|
||||
</footer>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="sf_production_technology_wizard_confirm_form_view">
|
||||
<field name="name">sf.production.technology.wizard.form.view</field>
|
||||
<field name="model">sf.production.technology.wizard</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<sheet>
|
||||
<field name="production_id" invisible="1"/>
|
||||
<field name="origin" invisible="1"/>
|
||||
<div>
|
||||
是否确认工艺调整
|
||||
</div>
|
||||
<footer>
|
||||
<button string="确认" name="confirm" type="object" class="oe_highlight"/>
|
||||
<button string="取消" class="btn btn-secondary" special="cancel"/>
|
||||
</footer>
|
||||
</sheet>
|
||||
|
||||
@@ -62,6 +62,36 @@ class ReworkWizard(models.TransientModel):
|
||||
hidden_workorder_list.sort()
|
||||
item.hidden_workorder_ids = ','.join(hidden_workorder_list)
|
||||
|
||||
def efficacy_rework_wo(self, wk_ids):
|
||||
"""限制判断 """
|
||||
# 判断检测结果待处理所对应的工单是否勾选
|
||||
result_ids = self.production_id.detection_result_ids.filtered(lambda dr: dr.handle_result == '待处理')
|
||||
work_id_list = []
|
||||
if result_ids:
|
||||
work_id_list = [self.workorder_ids.filtered(
|
||||
lambda wk: (wk.name == result_id.routing_type and wk.processing_panel == result_id.processing_panel
|
||||
and wk.state == 'done')).id
|
||||
for result_id in result_ids]
|
||||
if len(wk_ids.filtered(lambda wk: wk.id in work_id_list)) != len(work_id_list):
|
||||
raise ValidationError('存在【检测结果】为【待处理】所对应的工单未进行勾选!!!')
|
||||
# 获取已完成的标准工单
|
||||
grouped_rw_ids = {key: list(group) for key, group in groupby(wk_ids, key=lambda w: w.processing_panel)}
|
||||
for panel, panel_rw_ids in grouped_rw_ids.items():
|
||||
# 1、当制造订单内ZM面的工单都已完成时,返工勾选工序时只能勾选上ZM面的所有工序进行返工
|
||||
work_ids = self.workorder_ids.filtered(lambda w: w.state == 'done' and w.processing_panel == panel)
|
||||
if len(work_ids) == 3 and len(panel_rw_ids) != 3:
|
||||
raise ValidationError(
|
||||
'因为[%s]面的工单已全部完成,如果要对[%s]面的工单进行返工,请勾选这个面的所有工单。' % (panel, panel))
|
||||
# 2、当FM工单在CNC工单进行选择返工,并将已全部完成的ZM面工序全部勾选上时,FM工单上所有的已完成的工单(装夹预调工单)也必须进行勾选
|
||||
if not wk_ids.filtered(lambda wk: wk.name == '装夹预调' and wk.processing_panel == panel):
|
||||
if wk_ids.filtered(lambda wk: wk.name == 'CNC加工' and wk.processing_panel == panel):
|
||||
sequence_max = wk_ids.filtered(lambda wk: wk.name == 'CNC加工' and wk.processing_panel == panel).sequence
|
||||
for wk_id in wk_ids.filtered(lambda wk: wk.sequence < sequence_max):
|
||||
if len(wk_ids.filtered(lambda wk: wk.processing_panel == wk_id.processing_panel)) == 3:
|
||||
raise ValidationError(
|
||||
'由于在[%s]面之前存在整个面进行了勾选的情况,所以在勾选了[%s]面的【CNC加工】工单的时,请勾选[%s]面的装夹预调工单!' % (
|
||||
panel, panel, panel))
|
||||
|
||||
def confirm(self):
|
||||
if self.routing_type in ['装夹预调', 'CNC加工']:
|
||||
self.is_clamp_measure = False
|
||||
@@ -79,20 +109,8 @@ class ReworkWizard(models.TransientModel):
|
||||
if self.hidden_workorder_ids:
|
||||
hidden_workorder_list = self.hidden_workorder_ids.split(',')
|
||||
rework_workorder_ids = self.workorder_ids.filtered(lambda w: str(w.id) in hidden_workorder_list)
|
||||
# 限制判断
|
||||
# 1、当制造订单内ZM面的工单都已完成时,返工勾选工序时只能勾选上ZM面的所有工序进行返工
|
||||
# 2、当FM工单在CNC工单进行选择返工,并将已全部完成的ZM面工序全部勾选上时,FM工单上所有的已完成的工单(装夹预调工单)也必须进行勾选
|
||||
# 获取已完成的标准工单
|
||||
# done_normative_workorder_ids = self.workorder_ids.filtered(
|
||||
# lambda w: w.state == 'done' and w.processing_panel is not False)
|
||||
# # 获取需要返工的标准工单
|
||||
# rework_normative_workorder_ids = rework_workorder_ids.filtered(
|
||||
# lambda w: w.processing_panel is not False)
|
||||
# if rework_normative_workorder_ids:
|
||||
# for rw in rework_normative_workorder_ids:
|
||||
# if len(done_normative_workorder_ids.filtered(
|
||||
# lambda w: w.processing_panel == rw.processing_panel)) == 3:
|
||||
# pass
|
||||
# 调用效验方法
|
||||
self.efficacy_rework_wo(rework_workorder_ids)
|
||||
else:
|
||||
raise ValidationError('请选择返工工单!!!')
|
||||
if rework_workorder_ids:
|
||||
@@ -106,7 +124,7 @@ class ReworkWizard(models.TransientModel):
|
||||
for clamp_workorder_id in clamp_workorder_ids:
|
||||
self.production_id.workorder_ids.filtered(
|
||||
lambda wk: wk.processing_panel == clamp_workorder_id.processing_panel).write(
|
||||
{'rfid_code': False})
|
||||
{'rfid_code': None})
|
||||
# 返工工单状态设置为【返工】
|
||||
rework_workorder_ids.write({'state': 'rework'})
|
||||
# 查询返工工单对应的工艺设计记录,并调用方法拼接数据,用于创建新的工单
|
||||
@@ -119,7 +137,7 @@ class ReworkWizard(models.TransientModel):
|
||||
and item.panel == work.processing_panel))
|
||||
if route:
|
||||
work_list = self.env['mrp.workorder'].json_workorder_str(self.production_id, route[0])
|
||||
work_list[2].update({'tag_type': '重新加工'})
|
||||
work_list[2].update({'tag_type': '重新加工', 'sequence': 0})
|
||||
workorders_values.append(work_list)
|
||||
# 创建新工单,并进行返工配置的相关操作
|
||||
if workorders_values:
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<field name="processing_panel_id" invisible="1"/>
|
||||
<field name="hidden_workorder_ids" class="css_not_available_msg"/>
|
||||
<group>
|
||||
<field name="hidden_workorder_ids"/>
|
||||
<field name="hidden_workorder_ids" invisible="1"/>
|
||||
<field options="{'no_create': True,'no_open': True}" readonly="1" name="workorder_ids"
|
||||
widget="jikimo_subtree_selector_field"
|
||||
jikimo_selector="True" replace_context="hidden_workorder_ids" string="工序"
|
||||
|
||||
@@ -25,7 +25,7 @@ class SfQualityCncTest(models.Model):
|
||||
('pass', '合格'),
|
||||
('fail', '不合格')], string='判定结果')
|
||||
number = fields.Integer('数量', default=1)
|
||||
test_results = fields.Selection([("合格", "合格")], string="检测结果")
|
||||
test_results = fields.Selection([("合格", "合格"), ("返工", "返工"), ("报废", "报废")], string="检测结果")
|
||||
reason = fields.Selection(
|
||||
[("programming", "编程"), ("cutter", "刀具"), ("clamping", "装夹"), ("operate computer", "操机"),
|
||||
("technology", "工艺"), ("customer redrawing", "客户改图")], string="原因")
|
||||
|
||||
@@ -169,6 +169,9 @@
|
||||
<field name="manual_quotation" />
|
||||
<field name="is_incoming_material"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='date_order']" position="attributes">
|
||||
<attribute name="string">下单时间</attribute>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -215,8 +218,14 @@
|
||||
<attribute name="string">订单号</attribute>
|
||||
</field>
|
||||
<field name="create_date" position="attributes">
|
||||
<attribute name="string">下单时间</attribute>
|
||||
<attribute name="string">下单日期</attribute>
|
||||
</field>
|
||||
<xpath expr="//field[@name='activity_ids']" position="attributes">
|
||||
<attribute name="optional">hide</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='create_date']" position="after">
|
||||
<field name="deadline_of_delivery"/>
|
||||
</xpath>
|
||||
<!-- <field name="state" position="after">
|
||||
<field name="check_status" widget="badge"
|
||||
decoration-success="check_status == 'approved'"
|
||||
@@ -258,6 +267,15 @@
|
||||
<field name="amount_total" position="after">
|
||||
<field name="delivery_warning" invisible="1"/>
|
||||
</field>
|
||||
<xpath expr="//field[@name='date_order']" position="after">
|
||||
<field name="deadline_of_delivery"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='activity_ids']" position="attributes">
|
||||
<attribute name="optional">hide</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='invoice_status']" position="after">
|
||||
<field name="state"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -293,7 +311,7 @@
|
||||
|
||||
<record id="sale.action_orders" model="ir.actions.act_window">
|
||||
<field name="search_view_id" ref="sale_order_view_search_inherit_sale_message"/>
|
||||
<field name="context">{ 'search_default_filter_order_warning':1,'search_default_filter_order_overdue':1}
|
||||
<field name="context">{}
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<t t-if="record.workorder_count.raw_value > 0">
|
||||
<button class="btn btn-primary" name="action_work_order" type="object"
|
||||
attrs="{'invisible': [('name', '=', '功能刀具组装中心')]}"
|
||||
context="{'search_default_ready': 1, 'search_default_progress': 1}">
|
||||
context="{'search_default_ready': 1, 'search_default_progress': 1, 'workorder_type': name}">
|
||||
<span>工单</span>
|
||||
</button>
|
||||
</t>
|
||||
|
||||
Reference in New Issue
Block a user