Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化

This commit is contained in:
mgw
2025-02-05 17:42:10 +08:00
10 changed files with 114 additions and 30 deletions

View File

@@ -4,6 +4,7 @@ import json
import logging
from odoo.addons.sf_mrs_connect.controllers.controllers import Sf_Mrs_Connect
from odoo.addons.sf_manufacturing.controllers.controllers import Manufacturing_Connect
from datetime import datetime
_logger = logging.getLogger(__name__)
@@ -30,6 +31,7 @@ class WorkorderExceptionConroller(http.Controller):
workorder = request.env['mrp.workorder'].sudo().search([
('rfid_code', '=', ret['RfidCode']),
('routing_type', '=', 'CNC加工'),
('state', '!=', 'rework')
])
if not workorder:
res = {'Succeed': False, 'ErrorCode': 401, 'Error': '无效的工单'}
@@ -41,7 +43,10 @@ class WorkorderExceptionConroller(http.Controller):
'exception_code': ret.get('coding'),
'exception_content': ret.get('Error', '')
})
# 申请重新编程
workorder.production_id.update_programming_state(trigger_time=datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
reprogramming_reason=ret.get('Error', ''))
workorder.production_id.write({'programming_state': '编程中', 'work_state': '编程中', 'is_rework': False})
except Exception as e:
res = {'Succeed': False, 'ErrorCode': 202, 'Error': e}
_logger.info('workder_exception error:%s' % e)

View File

@@ -596,6 +596,9 @@ class Manufacturing_Connect(http.Controller):
if panel_workorder:
panel_workorder.write({'production_line_state': '已下产线'})
workorder.write({'state': 'to be detected'})
workorder.check_ids.filtered(
lambda ch: ch.quality_state == 'waiting').write(
{'quality_state': 'none'})
else:
res = {'Succeed': False, 'ErrorCode': 204,
'Error': 'DeviceId为%s没有对应的已配送工件数据' % ret['DeviceId']}

View File

@@ -577,16 +577,19 @@ class MrpProduction(models.Model):
# 编程单更新
# 增加触发时间参数
def update_programming_state(self, trigger_time=None):
def update_programming_state(self, trigger_time=None, reprogramming_reason=None):
try:
manufacturing_type = 'rework'
manufacturing_type = None
if self.is_scrap:
manufacturing_type = 'scrap'
elif self.tool_state == '2':
manufacturing_type = 'invalid_tool_rework'
elif self.is_rework:
manufacturing_type = 'rework'
res = {'programming_no': self.programming_no,
'manufacturing_type': manufacturing_type,
'trigger_time': trigger_time}
'trigger_time': trigger_time,
'reprogramming_reason': reprogramming_reason}
logging.info('res=%s:' % res)
configsettings = self.env['res.config.settings'].get_values()
config_header = Common.get_headers(self, configsettings['token'], configsettings['sf_secret_key'])

View File

@@ -455,6 +455,32 @@ class ResMrpWorkOrder(models.Model):
("technology", "工艺"), ("customer redrawing", "客户改图")], string="原因", tracking=True)
detailed_reason = fields.Text('详细原因')
is_rework = fields.Boolean(string='是否返工', default=False)
# rework_flag = fields.Boolean(string='返工标志', compute='_compute_rework_flag')
#
# @api.depends('state', 'production_line_state')
# def _compute_rework_flag(self):
# for record in self:
# if record.state == 'done' and record.routing_type == '装夹预调':
# next_workorder = record.production_id.workorder_ids.filtered(
# lambda w: w.sequence == record.sequence + 1)
# if next_workorder and next_workorder.routing_type == 'CNC加工' and next_workorder.state in ['ready',
# 'waiting',
# 'pending'] and next_workorder.production_line_state == '待上产线':
# record.rework_flag = False
# elif next_workorder and next_workorder.routing_type == '表面工艺' and next_workorder.state in ['ready',
# 'waiting',
# 'pending']:
# record.rework_flag = False
# else:
# record.rework_flag = True
# else:
# record.rework_flag = True
#
# def button_rework(self):
# for item in self:
# item.state = 'progress'
# for time_id in item.time_ids:
# time_id.write({'date_end': None})
def button_change_env(self):
self.is_test_env = not self.is_test_env
@@ -1543,7 +1569,8 @@ class ResMrpWorkOrder(models.Model):
# 修改工单状态
self.write({'state': 'to be detected'})
# 若关联的【质量检查_需送检】=true则质量检查单的状态从“等待”更新为“待处理”
self.check_ids.filtered(lambda ch: ch.is_inspect is True).write({'quality_state': 'none'})
self.check_ids.filtered(lambda ch: ch.is_inspect is True and ch.quality_state == 'waiting').write(
{'quality_state': 'none'})
class CNCprocessing(models.Model):

View File

@@ -180,14 +180,14 @@ class StockRule(models.Model):
productions = self.env['mrp.production'].with_user(SUPERUSER_ID).sudo().with_company(company_id).create(
productions_values)
# 将这一批制造订单的采购组根据成品设置为不同的采购组
product_group_id = {}
for index, production in enumerate(productions):
if production.product_id.id not in product_group_id.keys():
product_group_id[production.product_id.id] = production.procurement_group_id.id
else:
productions_values[index].update({'name': production.name})
procurement_group_vals = production._prepare_procurement_group_vals(productions_values[index])
production.procurement_group_id = self.env["procurement.group"].create(procurement_group_vals).id
# product_group_id = {}
# for index, production in enumerate(productions):
# if production.product_id.id not in product_group_id.keys():
# product_group_id[production.product_id.id] = production.procurement_group_id.id
# else:
# productions_values[index].update({'name': production.name})
# procurement_group_vals = production._prepare_procurement_group_vals(productions_values[index])
# production.procurement_group_id = self.env["procurement.group"].create(procurement_group_vals).id
# self.env['stock.move'].sudo().create(productions._get_moves_raw_values())
# self.env['stock.move'].sudo().create(productions._get_moves_finished_values())

View File

@@ -163,6 +163,7 @@
<field name='is_delivery' invisible="1"/>
<field name="is_trayed" invisible="1"/>
<field name="is_inspect" invisible="1"/>
<!-- <field name="rework_flag" invisible="1"/>-->
<!-- <field name='is_send_program_again' invisible="1"/>-->
<!-- 工单form页面的开始停工按钮等 -->
<!-- <button name="button_start" type="object" string="开始" class="btn-success" -->
@@ -182,7 +183,7 @@
<button name="button_pending" type="object" string="暂停" class="btn-warning"
attrs="{'invisible': ['|', '|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('is_user_working', '=', False)]}"/>
<button name="button_finish" type="object" string="完成" class="btn-success" confirm="是否确认完工"
attrs="{'invisible': ['|', '|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('is_user_working', '=', False)]}"/>
attrs="{'invisible': ['|', '|', '|',('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('is_user_working', '=', False),'&amp;','&amp;',('state', 'in', ('progress')), ('is_inspect', '=', True), ('routing_type','!=','CNC加工')]}"/>
<button name="%(mrp.act_mrp_block_workcenter_wo)d" type="action" string="阻塞"
context="{'default_workcenter_id': workcenter_id}" class="btn-danger"
@@ -211,6 +212,9 @@
attrs="{'invisible': ['|', '|', '|', ('routing_type','!=','装夹预调'),('state','!=','progress'), ('is_trayed', '=', False), ('state', 'in', ('done'))]}"/>
<button name="print_method" type="object" string="打印二维码" class="btn-primary"
attrs="{'invisible': ['|',('routing_type','!=','解除装夹'),('state','!=','done')]}"/>
<!-- <button type="object" class="oe_highlight jikimo_button_confirm" name="button_rework"-->
<!-- string="返工"-->
<!-- attrs='{"invisible": [("rework_flag","=",True)]}' confirm="是否返工"/>-->
</xpath>
<xpath expr="//page[1]" position="before">
<page string="开料要求" attrs='{"invisible": [("routing_type","not in",("切割", "线切割", "人工线下加工"))]}'>
@@ -533,7 +537,7 @@
<page string="后置三元检测" attrs='{"invisible": [("individuation_page_PTD", "=", False)]}'>
<group>
<field name="test_results"
attrs='{"readonly":[("state","!=","to be detected"), "|",("routing_type","=","CNC加工"),("is_inspect", "=", True)],
attrs='{"readonly":["&amp;","|",("state","!=","to be detected"), "|",("routing_type","=","CNC加工"),("is_inspect", "=", True),("state","in",["done","rework"])],
"invisible":[("results","!=",False)]}'/>
<!-- <field name="is_remanufacture" attrs='{"invisible":[("test_results","!=","报废")]}'/>-->
<!-- <field name="is_fetchcnc"-->

View File

@@ -200,6 +200,17 @@ class Sf_Mrs_Connect(http.Controller, MultiInheritController):
'send_time': ret['send_time'],
})
logging.info('已创建无效功能刀具的编程记录:%s' % production.name)
elif ret['reprogramming_reason']:
production.programming_record_ids.create({
'number': len(production.programming_record_ids) + 1,
'production_id': production.id,
'reason': ret['reprogramming_reason'],
'programming_method': ret['programme_way'],
'current_programming_count': ret['reprogramming_num'],
'target_production_id': productions_reprogram,
'apply_time': ret['trigger_time'],
'send_time': ret['send_time'],
})
else:
logging.info('无对应状态,不需更新编程记录')

View File

@@ -48,7 +48,7 @@ class QualityCheck(models.Model):
@api.depends('point_id.is_inspect')
def _compute_quality_state(self):
for qc in self:
if qc.point_id.is_inspect and qc.quality_state == 'none':
if qc.point_id.is_inspect and qc.quality_state == 'none' and qc.workorder_id.state != 'to be detected':
qc.quality_state = 'waiting'
elif not qc.point_id.is_inspect and qc.quality_state == 'waiting':
qc.quality_state = 'none'
@@ -62,7 +62,9 @@ class QualityCheck(models.Model):
def do_pass(self):
self.ensure_one()
super().do_pass()
if self.workorder_id and self.individuation_page_PTD is True:
if self.workorder_id:
if self.workorder_id.state in ('pending', 'waiting'):
raise ValidationError('工单未就绪!')
# 1将页签“判定结果”的检测结果值同步到【工单_后置三元检测_检测结果】
if self.test_results in ['返工', '报废']:
raise ValidationError('请重新选择【判定结果】-【检测结果】')
@@ -74,7 +76,9 @@ class QualityCheck(models.Model):
def do_fail(self):
self.ensure_one()
super().do_fail()
if self.workorder_id and self.individuation_page_PTD is True:
if self.workorder_id:
if self.workorder_id.state in ('pending', 'waiting'):
raise ValidationError('工单未就绪!')
# 1将页签“判定结果”的检测结果值同步到【工单_后置三元检测_检测结果】
if not self.test_results:
raise ValidationError('请填写【判定结果】里的信息')

View File

@@ -9,22 +9,24 @@
<field name="production_id" invisible="1"/>
<field name="work_state" invisible="1"/>
<field name="individuation_page_PTD" invisible="1"/>
<field name="production_line_id" attrs="{'invisible': ['|',('production_id', '=', False), ('individuation_page_PTD', '=', False)]}"/>
<field name="equipment_id" attrs="{'invisible': ['|',('production_id', '=', False), ('individuation_page_PTD', '=', False)]}"/>
<field name="production_line_id" attrs="{'invisible': [('production_id', '=', False)]}"/>
<field name="equipment_id" attrs="{'invisible': [('production_id', '=', False)]}"/>
<field name="model_file" widget="Viewer3D" string="模型" readonly="1" force_save="1"
attrs="{'invisible': ['|', '|',('model_file', '=', False), ('production_id', '=', False), ('individuation_page_PTD', '=', False)]}"/>
attrs="{'invisible': ['|',('model_file', '=', False), ('production_id', '=', False)]}"/>
</xpath>
<xpath expr="//field[@name='partner_id']" position="after">
<field name="processing_panel" attrs="{'invisible': ['|',('production_id', '=', False), ('individuation_page_PTD', '=', False)]}"/>
<field name="processing_panel" attrs="{'invisible': [('production_id', '=', False)]}"/>
<!-- <field name="production_id" string="制造订单" readonly="1"-->
<!-- attrs="{'invisible': [('production_id', '=', False)]}"/>-->
<field name="workorder_id" string="工单号" readonly="1"
attrs="{'invisible': ['|',('production_id', '=', False), ('individuation_page_PTD', '=', False)]}"/>
<field name="is_inspect" attrs="{'invisible': ['|',('production_id', '=', False), ('individuation_page_PTD', '=', False)]}"/>
attrs="{'invisible': [('production_id', '=', False)]}"/>
<field name="is_inspect" attrs="{'invisible': [('production_id', '=', False)]}"/>
</xpath>
<xpath expr="//page[@name='notes']" position="before">
<page string="检测报告" attrs="{'invisible': ['|',('production_id', '=', False), ('individuation_page_PTD', '=', False)]}">
<page string="检测报告" attrs="{'invisible': [('production_id', '=', False)]}">
<field name="detection_report" string="" widget="pdf_viewer"/>
</page>
<page string="判定结果" attrs="{'invisible': ['|',('production_id', '=', False), ('individuation_page_PTD', '=', False)]}">
<page string="判定结果" attrs="{'invisible': [('production_id', '=', False)]}">
<group>
<group>
<field name="test_results" attrs="{'readonly': [('quality_state','in', ['pass', 'fail'])]}"/>
@@ -35,25 +37,33 @@
</group>
</group>
</page>
<page string="2D图纸" attrs="{'invisible': ['|',('production_id', '=', False), ('individuation_page_PTD', '=', False)]}">
<page string="2D图纸" attrs="{'invisible': [('production_id', '=', False)]}">
<field name="machining_drawings" string="" widget="adaptive_viewer"/>
</page>
<page string="客户质量标准" attrs="{'invisible': ['|',('production_id', '=', False), ('individuation_page_PTD', '=', False)]}">
<page string="客户质量标准" attrs="{'invisible': [('production_id', '=', False)]}">
<field name="quality_standard" string="" widget="adaptive_viewer"/>
</page>
<page string="其他"
attrs="{'invisible': ['|','|', ('quality_state', 'not in', ['pass', 'fail']), ('production_id', '=', False),('individuation_page_PTD', '=', False)]}">
attrs="{'invisible': ['|',('quality_state', 'not in', ['pass', 'fail']), ('production_id', '=', False)]}">
<group>
<field name="write_uid" widget='many2one_avatar_user' string="判定人" readonly="1"/>
<field name="write_date" string="判定时间" readonly="1"/>
</group>
</page>
</xpath>
<xpath expr="//header//button[@name='do_pass'][1]" position="attributes">
<attribute name="string">合格</attribute>
</xpath>
<xpath expr="//header//button[@name='do_pass'][2]" position="attributes">
<attribute name="attrs">{'invisible': ['|',('quality_state', '!=', 'fail'),('work_state','in', ('done', 'rework'))]}</attribute>
<attribute name="string">合格</attribute>
</xpath>
<xpath expr="//header//button[@name='do_fail'][1]" position="attributes">
<attribute name="string">不合格</attribute>
</xpath>
<xpath expr="//header//button[@name='do_fail'][2]" position="attributes">
<attribute name="attrs">{'invisible': ['|',('quality_state', '!=', 'pass'),('work_state','in', ('done', 'rework'))]}</attribute>
<attribute name="string">不合格</attribute>
</xpath>
</field>
</record>

View File

@@ -130,7 +130,10 @@ class ReSaleOrder(models.Model):
'order_id': self.id,
'product_id': product.id,
'name': '%s/%s/%s/%s/%s/%s' % (
product.model_long, product.model_width, product.model_height, product.model_volume,
self.format_float(product.model_long),
self.format_float(product.model_width),
self.format_float(product.model_height),
self.format_float(product.model_volume),
machining_accuracy_name,
product.materials_id.name),
'price_unit': product.list_price,
@@ -143,6 +146,20 @@ class ReSaleOrder(models.Model):
}
return self.env['sale.order.line'].with_context(skip_procurement=True).create(vals)
def format_float(self, value):
# 将浮点数转换为字符串
value_str = str(value)
# 检查小数点的位置
if '.' in value_str:
# 获取小数部分
decimal_part = value_str.split('.')[1]
# 判断小数位数是否超过2位
if len(decimal_part) > 2:
# 超过2位则保留2位小数
return "{:.2f}".format(value)
# 否则保持原来的位数
return float(value_str)
@api.constrains('order_line')
def check_order_line(self):
for item in self: