diff --git a/sf_manufacturing/__manifest__.py b/sf_manufacturing/__manifest__.py index cffc789a..c6f40b37 100644 --- a/sf_manufacturing/__manifest__.py +++ b/sf_manufacturing/__manifest__.py @@ -26,6 +26,7 @@ 'wizard/production_technology_wizard_views.xml', 'wizard/production_technology_re_adjust_wizard_views.xml', 'wizard/mrp_workorder_batch_replan_wizard_views.xml', + 'wizard/sf_programming_reason_views.xml', 'views/mrp_views_menus.xml', 'views/agv_scheduling_views.xml', 'views/stock_lot_views.xml', diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py index dd2bacc1..9a6465d2 100644 --- a/sf_manufacturing/models/mrp_production.py +++ b/sf_manufacturing/models/mrp_production.py @@ -596,7 +596,8 @@ class MrpProduction(models.Model): logging.info('cron_get_programming_state error:%s' % e) # 编程单更新 - def update_programming_state(self): + # 增加触发时间参数 + def update_programming_state(self, trigger_time=None): try: manufacturing_type = 'rework' if self.is_scrap: @@ -618,6 +619,45 @@ class MrpProduction(models.Model): self.write({'is_rework': True}) else: 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: logging.info('update_programming_state error:%s' % e) raise UserError("更新编程单状态失败,请联系管理员") @@ -1586,6 +1626,81 @@ class MrpProduction(models.Model): raise UserError( _('You must enter a serial number for each line of %s') % sml.product_id.display_name) 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): diff --git a/sf_manufacturing/security/ir.model.access.csv b/sf_manufacturing/security/ir.model.access.csv index 4626e3ca..e8c1882f 100644 --- a/sf_manufacturing/security/ir.model.access.csv +++ b/sf_manufacturing/security/ir.model.access.csv @@ -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,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_group_plan_dispatch,sf_work_individuation_page_group_plan_dispatch,model_sf_work_individuation_page,sf_base.group_plan_dispatch,1,1,0,0 \ No newline at end of file +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 diff --git a/sf_manufacturing/views/mrp_production_addional_change.xml b/sf_manufacturing/views/mrp_production_addional_change.xml index 9b3eded9..2525defd 100644 --- a/sf_manufacturing/views/mrp_production_addional_change.xml +++ b/sf_manufacturing/views/mrp_production_addional_change.xml @@ -7,6 +7,10 @@ mrp.production + + + @@ -81,6 +85,10 @@ mrp.production + + + @@ -401,6 +409,21 @@ position="replace"> 子MO + + + + + + + + + + + + + + + diff --git a/sf_manufacturing/wizard/__init__.py b/sf_manufacturing/wizard/__init__.py index 89bdc09b..6a0af9e5 100644 --- a/sf_manufacturing/wizard/__init__.py +++ b/sf_manufacturing/wizard/__init__.py @@ -4,3 +4,4 @@ from . import production_wizard from . import production_technology_wizard from . import production_technology_re_adjust_wizard from . import mrp_workorder_batch_replan_wizard +from . import sf_programming_reason diff --git a/sf_manufacturing/wizard/production_wizard.py b/sf_manufacturing/wizard/production_wizard.py index e3e07f80..aa2a4075 100644 --- a/sf_manufacturing/wizard/production_wizard.py +++ b/sf_manufacturing/wizard/production_wizard.py @@ -51,6 +51,6 @@ class ProductionWizard(models.TransientModel): if self.is_remanufacture is True: ret = {'programming_list': [], 'is_reprogramming': self.is_reprogramming} 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) self.mrp_production_id.write({'remanufacture_production_id': new_production.id}) diff --git a/sf_manufacturing/wizard/rework_wizard.py b/sf_manufacturing/wizard/rework_wizard.py index 148967be..90697391 100644 --- a/sf_manufacturing/wizard/rework_wizard.py +++ b/sf_manufacturing/wizard/rework_wizard.py @@ -284,7 +284,7 @@ class ReworkWizard(models.TransientModel): 'is_rework': False}) # ==================申请重新编程======================= 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( {'programming_state': '编程中', 'work_state': '编程中', 'state': 'progress'}) # ================= 返工完成,制造订单状态置为加工中 ============== diff --git a/sf_manufacturing/wizard/sf_programming_reason.py b/sf_manufacturing/wizard/sf_programming_reason.py new file mode 100644 index 00000000..d6744bed --- /dev/null +++ b/sf_manufacturing/wizard/sf_programming_reason.py @@ -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, + } + + diff --git a/sf_manufacturing/wizard/sf_programming_reason_views.xml b/sf_manufacturing/wizard/sf_programming_reason_views.xml new file mode 100644 index 00000000..02193bf6 --- /dev/null +++ b/sf_manufacturing/wizard/sf_programming_reason_views.xml @@ -0,0 +1,45 @@ + + + + sf.programming.reason.form.view + sf.programming.reason + + + + + + 注意:该制造订单产品已申请重新编程次数为,且当前编程状态为 + + + + + + + + + sf.programming.reason.message.view + sf.programming.reason + + + 已下达编程任务和消息,请等待编程单下发! + + + + + + + + 重新编程原因 + ir.actions.act_window + sf.programming.reason + form + + new + + + diff --git a/sf_mrs_connect/controllers/controllers.py b/sf_mrs_connect/controllers/controllers.py index 85b3d5fa..186cc7a5 100644 --- a/sf_mrs_connect/controllers/controllers.py +++ b/sf_mrs_connect/controllers/controllers.py @@ -97,6 +97,35 @@ class Sf_Mrs_Connect(http.Controller, MultiInheritController): {'processing_drawing': base64.b64encode(open(panel_file_path, 'rb').read())}) productions.write({'programming_state': '已编程', 'work_state': '已编程'}) 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({ 'production_ids': productions.ids }) diff --git a/sf_tool_management/models/mrp_workorder.py b/sf_tool_management/models/mrp_workorder.py index 655d759f..89d37e81 100644 --- a/sf_tool_management/models/mrp_workorder.py +++ b/sf_tool_management/models/mrp_workorder.py @@ -1,6 +1,7 @@ import json import requests import logging +from datetime import datetime from odoo import fields, models, api from odoo.exceptions import ValidationError from odoo.addons.sf_base.commons.common import Common @@ -196,7 +197,7 @@ class MrpProduction(models.Model): }) # 自动调用重新获取编程的方法 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.write({'programming_state': '编程中', 'work_state': '编程中'})
注意:该制造订单产品已申请重新编程次数为,且当前编程状态为
已下达编程任务和消息,请等待编程单下发!