Accept Merge Request #1730: (feature/制造功能优化 -> develop)

Merge Request: 申请编程需求

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1730?initial=true
This commit is contained in:
马广威
2025-01-13 11:12:33 +08:00
committed by Coding
11 changed files with 276 additions and 5 deletions

View File

@@ -26,6 +26,7 @@
'wizard/production_technology_wizard_views.xml', 'wizard/production_technology_wizard_views.xml',
'wizard/production_technology_re_adjust_wizard_views.xml', 'wizard/production_technology_re_adjust_wizard_views.xml',
'wizard/mrp_workorder_batch_replan_wizard_views.xml', 'wizard/mrp_workorder_batch_replan_wizard_views.xml',
'wizard/sf_programming_reason_views.xml',
'views/mrp_views_menus.xml', 'views/mrp_views_menus.xml',
'views/agv_scheduling_views.xml', 'views/agv_scheduling_views.xml',
'views/stock_lot_views.xml', 'views/stock_lot_views.xml',

View File

@@ -596,7 +596,8 @@ class MrpProduction(models.Model):
logging.info('cron_get_programming_state error:%s' % e) logging.info('cron_get_programming_state error:%s' % e)
# 编程单更新 # 编程单更新
def update_programming_state(self): # 增加触发时间参数
def update_programming_state(self, trigger_time=None):
try: try:
manufacturing_type = 'rework' manufacturing_type = 'rework'
if self.is_scrap: if self.is_scrap:
@@ -618,6 +619,45 @@ class MrpProduction(models.Model):
self.write({'is_rework': True}) self.write({'is_rework': True})
else: else:
raise UserError(ret['message']) raise UserError(ret['message'])
# 增加对编程记录的更新
cloud_programming = self._cron_get_programming_state()
if manufacturing_type == 'rework':
self.programming_record_ids.create({
'number': len(self.programming_record_ids) + 1,
'production_id': self.id,
'reason': '返工',
'programming_method': cloud_programming['programme_way'],
'current_programming_count': cloud_programming['reprogramming_num'],
'target_production_id': cloud_programming['production_order_no'],
'apply_time': trigger_time,
'send_time': cloud_programming['send_time'],
})
elif manufacturing_type == 'scrap':
self.programming_record_ids.create({
'number': len(self.programming_record_ids) + 1,
'production_id': self.id,
'reason': '报废',
'programming_method': cloud_programming['programme_way'],
'current_programming_count': cloud_programming['reprogramming_num'],
'target_production_id': cloud_programming['production_order_no'],
'apply_time': trigger_time,
'send_time': cloud_programming['send_time'],
})
elif manufacturing_type == 'invalid_tool_rework':
self.programming_record_ids.create({
'number': len(self.programming_record_ids) + 1,
'production_id': self.id,
'reason': '无效功能刀具',
'programming_method': cloud_programming['programme_way'],
'current_programming_count': cloud_programming['reprogramming_num'],
'target_production_id': cloud_programming['production_order_no'],
'apply_time': trigger_time,
'send_time': cloud_programming['send_time'],
})
else:
logging.info('无对应状态,不需更新编程记录')
except Exception as e: except Exception as e:
logging.info('update_programming_state error:%s' % e) logging.info('update_programming_state error:%s' % e)
raise UserError("更新编程单状态失败,请联系管理员") raise UserError("更新编程单状态失败,请联系管理员")
@@ -1586,6 +1626,81 @@ class MrpProduction(models.Model):
raise UserError( raise UserError(
_('You must enter a serial number for each line of %s') % sml.product_id.display_name) _('You must enter a serial number for each line of %s') % sml.product_id.display_name)
return True return True
reprogramming_count = fields.Integer(string='重新编程次数', default=0)
# 申请编程
def action_apply_programming(self):
"""
检查前置条件:制造订单【状态】=“待排程、待加工”,制造订单的【编程状态】=“已编程”。
"""
print('申请编程')
if len(self) > 1:
raise UserError('仅支持选择单个制造订单进行编程申请,请重新选择')
# problem_productions = []
# for production in self:
# if production.state not in ['待排程', '待加工'] or production.programming_state != '已编程':
# problem_productions.append(production.name)
# if problem_productions:
# raise UserError('以下制造订单状态或编程状态不符合要求: %s' % ', '.join(problem_productions))
# 上述通过后返回一个action id为sf_programming_reason_action用作二次确认wizard显示“重新编程原因XXXXX用户录入注意该制造订单产品已申请重新编程次数为N且当前编程状态为XXX”
cloud_programming = self._cron_get_programming_state()
return {
'type': 'ir.actions.act_window',
'res_model': 'sf.programming.reason',
'view_mode': 'form',
'target': 'new',
'context': {
'default_production_id': self.id,
'active_id': self.id,
# 传当前时间
'default_apply_time': fields.Datetime.now(),
},
'view_id': self.env.ref('sf_manufacturing.sf_programming_reason_form_view').id,
}
# 编程记录
programming_record_ids = fields.One2many('sf.programming.record', 'production_id')
# 编程单更新
def re_programming_update_programming_state(self):
try:
res = {'programming_no': self.programming_no,
'manufacturing_type': ''}
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'])
url = '/api/intelligent_programming/reset_state_again'
config_url = configsettings['sf_url'] + url
ret = requests.post(config_url, json=res, data=None, headers=config_header)
ret = ret.json()
result = json.loads(ret['result'])
logging.info('update_programming_state-ret:%s' % result)
if result['status'] == 1:
self.write({'is_rework': True})
else:
raise UserError(ret['message'])
except Exception as e:
logging.info('update_programming_state error:%s' % e)
raise UserError("更新编程单状态失败,请联系管理员")
# 编程记录
class sf_programming_record(models.Model):
_name = 'sf.programming.record'
_description = "编程记录"
production_id = fields.Many2one('mrp.production')
# 编号、编程原因、编程方式、当前编程次数、目标制造单号、申请时间、下发时间
number = fields.Char('编号')
reason = fields.Text('重新编程原因')
programming_method = fields.Selection([
('auto', '自动'),
('manual operation', '人工')], string="编程方式")
current_programming_count = fields.Integer('当前编程次数')
target_production_id = fields.Char('目标制造单号')
apply_time = fields.Datetime('申请时间')
send_time = fields.Datetime('下发时间')
class sf_detection_result(models.Model): class sf_detection_result(models.Model):

View File

@@ -188,5 +188,7 @@ access_mrp_workorder_batch_replan_wizard_group_plan_dispatch,mrp_workorder_batch
access_mrp_workorder_group_purchase_director,mrp_workorder,model_mrp_workorder,sf_base.group_purchase_director,1,1,0,0 access_mrp_workorder_group_purchase_director,mrp_workorder,model_mrp_workorder,sf_base.group_purchase_director,1,1,0,0
access_mrp_workorder_group_purchase,mrp_workorder,model_mrp_workorder,sf_base.group_purchase,1,1,0,0 access_mrp_workorder_group_purchase,mrp_workorder,model_mrp_workorder,sf_base.group_purchase,1,1,0,0
access_sf_programming_reason,sf_programming_reason,model_sf_programming_reason,base.group_user,1,1,1,0
access_sf_programming_record,sf_programming_record,model_sf_programming_record,base.group_user,1,1,1,0
access_sf_work_individuation_page,sf_work_individuation_page,model_sf_work_individuation_page,sf_base.group_sf_mrp_user,1,1,1,0 access_sf_work_individuation_page,sf_work_individuation_page,model_sf_work_individuation_page,sf_base.group_sf_mrp_user,1,1,1,0
access_sf_work_individuation_page_group_plan_dispatch,sf_work_individuation_page_group_plan_dispatch,model_sf_work_individuation_page,sf_base.group_plan_dispatch,1,1,0,0 access_sf_work_individuation_page_group_plan_dispatch,sf_work_individuation_page_group_plan_dispatch,model_sf_work_individuation_page,sf_base.group_plan_dispatch,1,1,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
188
189
190
191
192
193
194

View File

@@ -7,6 +7,10 @@
<field name="model">mrp.production</field> <field name="model">mrp.production</field>
<field name="inherit_id" ref="mrp.mrp_production_tree_view"/> <field name="inherit_id" ref="mrp.mrp_production_tree_view"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//header//button[last()]" position="after">
<button name="action_apply_programming" type="object" string="申请编程" class="oe_highlight"
groups="sf_base.group_sf_mrp_user"/>
</xpath>
<!-- <xpath expr="//button[@name='do_unreserve']" position="after">--> <!-- <xpath expr="//button[@name='do_unreserve']" position="after">-->
<!-- <button name="do_update_program" type="object" string="更新程序"--> <!-- <button name="do_update_program" type="object" string="更新程序"-->
<!-- groups="sf_base.group_sf_mrp_user"/>--> <!-- groups="sf_base.group_sf_mrp_user"/>-->
@@ -81,6 +85,10 @@
<field name="model">mrp.production</field> <field name="model">mrp.production</field>
<field name="inherit_id" ref="mrp.mrp_production_form_view"/> <field name="inherit_id" ref="mrp.mrp_production_form_view"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//header//button[last()]" position="after">
<button name="action_apply_programming" type="object" string="申请编程" class="oe_highlight"
groups="sf_base.group_sf_mrp_user"/>
</xpath>
<xpath expr="//field[@name='state']" position="attributes"> <xpath expr="//field[@name='state']" position="attributes">
<!-- <attribute name="statusbar_visible">draft,confirmed,progress,pending_processing,completed,done --> <!-- <attribute name="statusbar_visible">draft,confirmed,progress,pending_processing,completed,done -->
<!-- </attribute> --> <!-- </attribute> -->
@@ -401,6 +409,21 @@
position="replace"> position="replace">
<span class="o_stat_text">子MO</span> <span class="o_stat_text">子MO</span>
</xpath> </xpath>
<xpath expr="//sheet//notebook//page[last()]" position="after">
<page string="编程记录">
<field name="programming_record_ids" widget="one2many" attrs="{'readonly': [('id', '!=', False)]}">
<tree>
<field name="number"/>
<field name="reason"/>
<field name="programming_method"/>
<field name="current_programming_count"/>
<field name="target_production_id"/>
<field name="apply_time"/>
<field name="send_time"/>
</tree>
</field>
</page>
</xpath>
</field> </field>
</record> </record>

View File

@@ -4,3 +4,4 @@ from . import production_wizard
from . import production_technology_wizard from . import production_technology_wizard
from . import production_technology_re_adjust_wizard from . import production_technology_re_adjust_wizard
from . import mrp_workorder_batch_replan_wizard from . import mrp_workorder_batch_replan_wizard
from . import sf_programming_reason

View File

@@ -51,6 +51,6 @@ class ProductionWizard(models.TransientModel):
if self.is_remanufacture is True: if self.is_remanufacture is True:
ret = {'programming_list': [], 'is_reprogramming': self.is_reprogramming} ret = {'programming_list': [], 'is_reprogramming': self.is_reprogramming}
if self.is_reprogramming is True: if self.is_reprogramming is True:
self.mrp_production_id.update_programming_state() self.mrp_production_id.update_programming_state(trigger_time=datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
new_production = self.mrp_production_id.recreateManufacturing(ret) new_production = self.mrp_production_id.recreateManufacturing(ret)
self.mrp_production_id.write({'remanufacture_production_id': new_production.id}) self.mrp_production_id.write({'remanufacture_production_id': new_production.id})

View File

@@ -284,7 +284,7 @@ class ReworkWizard(models.TransientModel):
'is_rework': False}) 'is_rework': False})
# ==================申请重新编程======================= # ==================申请重新编程=======================
if self.is_reprogramming is True: if self.is_reprogramming is True:
self.production_id.update_programming_state() self.production_id.update_programming_state(trigger_time=datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
self.production_id.write( self.production_id.write(
{'programming_state': '编程中', 'work_state': '编程中', 'state': 'progress'}) {'programming_state': '编程中', 'work_state': '编程中', 'state': 'progress'})
# ================= 返工完成,制造订单状态置为加工中 ============== # ================= 返工完成,制造订单状态置为加工中 ==============

View File

@@ -0,0 +1,54 @@
from odoo import models, fields, api
class sf_programming_reason(models.TransientModel):
_name = 'sf.programming.reason'
_description = '重新编程原因'
production_id = fields.Many2one('mrp.production')
reason = fields.Text('重新编程原因')
reprogramming_count = fields.Integer(string='重新编程次数')
programming_state = fields.Char(string='编程状态')
@api.model
def default_get(self, fields):
res = super(sf_programming_reason, self).default_get(fields)
if self._context.get('active_id'):
production = self.env['mrp.production'].browse(self._context.get('active_id'))
res.update({
'reprogramming_count': production._cron_get_programming_state()['reprogramming_num'],
'programming_state': production.programming_state, # 假设制造订单模型中有这个字段
})
return res
def action_confirm(self):
print('self.production_id.programming_state:', self.production_id.programming_state)
self.production_id.re_programming_update_programming_state()
self.production_id.write(
{'programming_state': '编程中', 'work_state': '编程中'})
cloud_programming = self.production_id._cron_get_programming_state()
self.production_id.programming_record_ids.create({
'number': len(self.production_id.programming_record_ids) + 1,
'production_id': self.production_id.id,
'reason': self.reason,
'programming_method': cloud_programming['programme_way'],
'current_programming_count': cloud_programming['reprogramming_num'],
'target_production_id': cloud_programming['production_order_no'],
'apply_time': self._context.get('default_apply_time'),
'send_time': False,
})
# 返回弹窗提示“已下达编程任务和消息,请等待编程单下发”
return {
'type': 'ir.actions.act_window',
'res_model': 'sf.programming.reason',
'view_mode': 'form',
'target': 'new',
'context': {
'default_production_id': self.production_id.id,
'active_id': self.production_id.id,
},
'view_id': self.env.ref('sf_manufacturing.sf_programming_reason_message_view').id,
}

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record model="ir.ui.view" id="sf_programming_reason_form_view">
<field name="name">sf.programming.reason.form.view</field>
<field name="model">sf.programming.reason</field>
<field name="arch" type="xml">
<form>
<group>
<label for="reason" string="重新编程原因:"/>
<field name="reason" widget="textarea" nolabel="1"/>
<p class="text-muted">注意:该制造订单产品已申请重新编程次数为<field name="reprogramming_count" readonly="1" nolabel="1" class="oe_inline"/>,且当前编程状态为<field name="programming_state" readonly="1" nolabel="1" class="oe_inline"/></p>
</group>
<field name="production_id" invisible="True"/>
<footer>
<button name="action_confirm" string="确认" type="object" class="btn-primary"/>
<button string="丢弃" special="cancel" class="btn-secondary"/>
</footer>
</form>
</field>
</record>
<!-- 弹窗提示“已下达编程任务和消息,请等待编程单下发” -->
<record model="ir.ui.view" id="sf_programming_reason_message_view">
<field name="name">sf.programming.reason.message.view</field>
<field name="model">sf.programming.reason</field>
<field name="arch" type="xml">
<form>
<p>已下达编程任务和消息,请等待编程单下发!</p>
<footer>
<button string="关闭" special="cancel" class="btn-secondary"/>
</footer>
</form>
</field>
</record>
<!-- 重新编程原因弹窗 -->
<record id="sf_programming_reason_action" model="ir.actions.act_window">
<field name="name">重新编程原因</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">sf.programming.reason</field>
<field name="view_mode">form</field>
<field name="view_id" ref="sf_programming_reason_form_view"/>
<field name="target">new</field>
</record>
</odoo>

View File

@@ -97,6 +97,35 @@ class Sf_Mrs_Connect(http.Controller, MultiInheritController):
{'processing_drawing': base64.b64encode(open(panel_file_path, 'rb').read())}) {'processing_drawing': base64.b64encode(open(panel_file_path, 'rb').read())})
productions.write({'programming_state': '已编程', 'work_state': '已编程'}) productions.write({'programming_state': '已编程', 'work_state': '已编程'})
logging.info('已更新制造订单编程状态:%s' % productions.ids) logging.info('已更新制造订单编程状态:%s' % productions.ids)
# 更新编程记录
for production in productions:
record_ids_obj = production.programming_record_ids.filtered(lambda r: r.current_programming_count == ret['reprogramming_num'])
if record_ids_obj:
record_ids_obj.write({'send_time': ret['send_time']})
if ret['reprogramming_num'] == 0:
production.programming_record_ids.create({
'number': 1,
'production_id': production.id,
'reason': '',
'programming_method': ret['programme_way'],
'current_programming_count': ret['reprogramming_num'],
'target_production_id': ret['production_order_no'],
'apply_time': False,
'send_time': ret['send_time'],
})
if ret['reset_flag']:
production.programming_record_ids.create({
'number': len(production.programming_record_ids) + 1,
'production_id': production.id,
'reason': '重置状态',
'programming_method': ret['programme_way'],
'current_programming_count': ret['reprogramming_num'],
'target_production_id': ret['production_order_no'],
'apply_time': False,
'send_time': ret['send_time'],
})
res.update({ res.update({
'production_ids': productions.ids 'production_ids': productions.ids
}) })

View File

@@ -1,6 +1,7 @@
import json import json
import requests import requests
import logging import logging
from datetime import datetime
from odoo import fields, models, api from odoo import fields, models, api
from odoo.exceptions import ValidationError from odoo.exceptions import ValidationError
from odoo.addons.sf_base.commons.common import Common from odoo.addons.sf_base.commons.common import Common
@@ -196,7 +197,7 @@ class MrpProduction(models.Model):
}) })
# 自动调用重新获取编程的方法 # 自动调用重新获取编程的方法
logging.info('cnc用刀校验到无效刀自动调用重新编程方法update_programming_state()') logging.info('cnc用刀校验到无效刀自动调用重新编程方法update_programming_state()')
self[0].update_programming_state() self[0].update_programming_state(trigger_time=datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
self[0].write({'is_rework': False}) self[0].write({'is_rework': False})
# 修改制造订单 编程状态变为“编程中” # 修改制造订单 编程状态变为“编程中”
self.write({'programming_state': '编程中', 'work_state': '编程中'}) self.write({'programming_state': '编程中', 'work_state': '编程中'})