diff --git a/sf_manufacturing/__manifest__.py b/sf_manufacturing/__manifest__.py index ca85c807..9ea3bb60 100644 --- a/sf_manufacturing/__manifest__.py +++ b/sf_manufacturing/__manifest__.py @@ -41,7 +41,8 @@ 'web.assets_backend': [ 'sf_manufacturing/static/src/xml/kanban_change.xml', 'sf_manufacturing/static/src/js/kanban_change.js', - 'sf_manufacturing/static/src/scss/kanban_change.scss' + 'sf_manufacturing/static/src/scss/kanban_change.scss', + 'sf_manufacturing/static/src/xml/button_show_on_tree.xml', ] }, diff --git a/sf_manufacturing/controllers/controllers.py b/sf_manufacturing/controllers/controllers.py index 27e18f25..6801f561 100644 --- a/sf_manufacturing/controllers/controllers.py +++ b/sf_manufacturing/controllers/controllers.py @@ -450,9 +450,8 @@ class Manufacturing_Connect(http.Controller): if 'DeviceId' in ret: logging.info('DeviceId:%s' % ret['DeviceId']) if 'IsComplete' in ret: - first_rfid_code = None - production_ids = [] - workpiece_validate = True + rfid_codes = [] + workorder_ids = [] if ret['IsComplete'] is True or ret['IsComplete'] is False: for i in range(1, 5): logging.info('F-RfidCode:%s' % i) @@ -460,7 +459,7 @@ class Manufacturing_Connect(http.Controller): rfid_code = ret[f'RfidCode{i}'] logging.info('RfidCode:%s' % rfid_code) if rfid_code is not None: - first_rfid_code = first_rfid_code or rfid_code + rfid_codes.append(rfid_code) domain = [ ('rfid_code', '=', rfid_code), ('routing_type', '=', 'CNC加工'), ('state', '!=', 'rework') @@ -468,7 +467,7 @@ class Manufacturing_Connect(http.Controller): workorder = request.env['mrp.workorder'].sudo().search(domain, order='id asc') if workorder: for order in workorder: - production_ids.append(order.production_id.id) + workorder_ids.append(order.id) if order.production_line_state == '待上产线': logging.info( '工单产线状态:%s' % order.production_line_state) @@ -487,19 +486,27 @@ class Manufacturing_Connect(http.Controller): # workpiece_delivery.write({'is_manual_work': True}) # 下发 else: - workpiece_validate = False res = {'Succeed': False, 'ErrorCode': 204, 'Error': 'DeviceId为%s没有对应的已配送工件数据' % ret['DeviceId']} if ret['IsComplete'] is True: # 将RFID_CODE对应的工件配送单对应的AGV任务调度状态设置为已配送 - request.env['sf.workpiece.delivery'].sudo().search( - [('rfid_code', '=', first_rfid_code)]).agv_scheduling_id.write({'state': '已配送'}) + # workorder_id = request.env['mrp.workorder'].sudo().search([ + # ('rfid_code', 'in', rfid_codes), + # ('routing_type', '=', '装夹预调'), ('state', '!=', 'rework') + # ]) + # workorder_id.agv_scheduling_ids.finish_scheduling() + # 将工件配送单状态设置为已配送 + request.env['sf.workpiece.delivery'].sudo().search([ + ('rfid_code', 'in', rfid_codes), + ('type', '=', '上产线'), + ('status', '=', '已下发') + ]).write({'state': '已配送'}) # 向AGV任务调度下发运送空料架任务 - productions = request.env['mrp.production'].sudo().search([('id', 'in', production_ids)]) # 获取设备ID对应的接驳站配置 agv_site = request.env['sf.agv.site'].sudo().search( [('name', '=', ret['DeviceId'])], limit=1) - request.env['sf.agv.scheduling'].add_scheduling(agv_site.id, '运送空料架', productions) + workorders = request.env['mrp.workorder'].browse(workorder_ids) + request.env['sf.agv.scheduling'].add_scheduling(agv_site.id, '运送空料架', workorders) else: res = {'Succeed': False, 'ErrorCode': 203, 'Error': '未传IsComplete字段'} else: @@ -511,7 +518,7 @@ class Manufacturing_Connect(http.Controller): logging.info('AGVToProduct error:%s' % e) return json.JSONEncoder().encode(res) - @http.route('/AutoDeviceApi/AGVDownProduct', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False, + @http.route('/AutoDeviceApi/AGVDownProduct', type='json', auth='public', methods=['GET', 'POST'], csrf=False, cors="*") def AGVDownProduct(self, **kw): """ @@ -530,7 +537,8 @@ class Manufacturing_Connect(http.Controller): logging.info('ret:%s' % ret) if 'DeviceId' in ret: logging.info('DeviceId:%s' % ret['DeviceId']) - delivery_Arr = [] + # delivery_Arr = [] + workorder_ids = [] if 'IsComplete' in ret: if ret['IsComplete'] is True or ret['IsComplete'] is False: for i in range(1, 5): @@ -546,6 +554,7 @@ class Manufacturing_Connect(http.Controller): workorder = request.env['mrp.workorder'].sudo().search(domain, order='id asc') if workorder: for order in workorder: + workorder_ids.append(order.id) if order.production_line_state == '已上产线': logging.info( '工单产线状态:%s' % order.production_line_state) @@ -555,33 +564,42 @@ class Manufacturing_Connect(http.Controller): if panel_workorder: panel_workorder.write({'production_line_state': '已下产线'}) workorder.write({'state': 'to be detected'}) - workpiece_delivery = request.env['sf.workpiece.delivery'].sudo().search( - [ - ('rfid_code', '=', rfid_code), ('type', '=', '下产线'), - ('production_id', '=', order.production_id.id), - ('workorder_id', '=', order.id), - ('workorder_state', '=', 'done')]) - if workpiece_delivery: - delivery_Arr.append(workpiece_delivery.id) + # workpiece_delivery = request.env['sf.workpiece.delivery'].sudo().search( + # [ + # ('rfid_code', '=', rfid_code), ('type', '=', '下产线'), + # ('production_id', '=', order.production_id.id), + # ('workorder_id', '=', order.id), + # ('workorder_state', '=', 'done')]) + # if workpiece_delivery: + # delivery_Arr.append(workpiece_delivery.id) else: res = {'Succeed': False, 'ErrorCode': 204, 'Error': 'DeviceId为%s没有对应的已配送工件数据' % ret['DeviceId']} - if delivery_Arr: - logging.info('delivery_Arr:%s' % delivery_Arr) - delivery_workpiece = request.env['sf.workpiece.delivery'].sudo().search( - [('id', 'in', delivery_Arr)]) - if delivery_workpiece: - logging.info('开始向agv下发下产线任务') - agv_site = request.env['sf.agv.site'].sudo().search([]) - if agv_site: - has_site = agv_site.update_site_state() - if has_site is True: - is_free = delivery_workpiece._check_avgsite_state() - if is_free is True: - delivery_workpiece._delivery_avg() - logging.info('agv下发下产线任务下发完成') + # if delivery_Arr: + # logging.info('delivery_Arr:%s' % delivery_Arr) + # delivery_workpiece = request.env['sf.workpiece.delivery'].sudo().search( + # [('id', 'in', delivery_Arr)]) + # if delivery_workpiece: + # logging.info('开始向agv下发下产线任务') + # agv_site = request.env['sf.agv.site'].sudo().search([]) + # if agv_site: + # has_site = agv_site.update_site_state() + # if has_site is True: + # is_free = delivery_workpiece._check_avgsite_state() + # if is_free is True: + # delivery_workpiece._delivery_avg() + # logging.info('agv下发下产线任务下发完成') + if ret['IsComplete'] is True: + # 向AGV任务调度下发下产线任务 + # 获取设备ID对应的接驳站配置 + agv_site = request.env['sf.agv.site'].sudo().search( + [('name', '=', ret['DeviceId'])], limit=1) + workorders = request.env['mrp.workorder'].browse(workorder_ids) + request.env['sf.agv.scheduling'].add_scheduling(agv_site.id, '下产线', workorders) else: res = {'Succeed': False, 'ErrorCode': 203, 'Error': '未传IsComplete字段'} + except RepeatTaskException as e: + logging.info('AGVToProduct error:%s' % e) except Exception as e: res = {'Succeed': False, 'ErrorCode': 202, 'Error': e} logging.info('AGVDownProduct error:%s' % e) @@ -640,7 +658,7 @@ class Manufacturing_Connect(http.Controller): logging.info('ret:%s' % ret) if 'DeviceId' in ret and 'AtHome' in ret: logging.info('DeviceId:%s, AtHome:%s' % (ret['DeviceId'], ret['AtHome'])) - request.env['sf.agv.site'].update_site_state(ret['DeviceId'], ret['AtHome']) + request.env['sf.agv.site'].update_site_state({ret['DeviceId']: '占用' if ret['AtHome'] else '空闲'}) except Exception as e: res = {'Succeed': False, 'ErrorCode': 202, 'Error': str(e)} logging.info('AGVDownProduct error:%s' % e) diff --git a/sf_manufacturing/models/agv_scheduling.py b/sf_manufacturing/models/agv_scheduling.py index 084dcf49..c3600df7 100644 --- a/sf_manufacturing/models/agv_scheduling.py +++ b/sf_manufacturing/models/agv_scheduling.py @@ -31,8 +31,7 @@ class AgvScheduling(models.Model): ('配送中', '配送中'), ('已配送', '已配送'), ('已取消', '已取消')], string='状态', default='待下发', tracking=True) - workorder_ids = fields.One2many('mrp.workorder', string='关联工单') - delivery_workpieces = fields.Char('配送工件', required=True, index=True) + workorder_ids = fields.Many2many('mrp.workorder', 'sf_agv_scheduling_mrp_workorder_ref', string='关联工单') task_create_time = fields.Datetime('任务创建时间') task_delivery_time = fields.Datetime('任务下发时间') task_completion_time = fields.Datetime('任务完成时间') @@ -41,13 +40,12 @@ class AgvScheduling(models.Model): @api.depends('agv_route_type') def _compute_delivery_workpieces(self): for record in self: - record.delivery_workpieces = '、'.join(record.workorder_ids.mapped('production_id.name')) if record.agv_route_type == '运送空料架': - record.delivery_workpieces_display = '/' + record.delivery_workpieces = '/' else: - record.delivery_workpieces_display = record.delivery_workpieces + record.delivery_workpieces = '、'.join(record.workorder_ids.mapped('production_id.name')) - delivery_workpieces_display = fields.Char('配送工件', compute=_compute_delivery_workpieces) + delivery_workpieces = fields.Char('配送工件', compute=_compute_delivery_workpieces) @api.depends('task_completion_time', 'task_delivery_time') def _compute_task_duration(self): @@ -64,28 +62,35 @@ class AgvScheduling(models.Model): vals['name'] = self.env['ir.sequence'].next_by_code('sf.agv.scheduling') or _('New') return super().create(vals_list) - def add_scheduling(self, agv_start_site_id, agv_route_type, productions, deliveries=None): - """ add_scheduling(agv_start_site_id, agv_route_type, productions, deliveries) -> agv_scheduling + def add_scheduling(self, agv_start_site_id, agv_route_type, workorders): + """ add_scheduling(agv_start_site_id, agv_route_type, workorders) -> agv_scheduling 新增AGV调度 params: agv_start_site_id: AGV起点接驳站ID agv_route_type: AGV任务类型 - productions: 制造订单 - deliveries: 工件配送单 + workorders: 工单 """ - # 如果存在配送工件完全相同的AGV调度任务,则不新增 - if self.sudo().search([ - ('delivery_workpieces', '=', '、'.join(productions.mapped('name'))), + if not workorders: + raise UserError(_('工单不能为空')) + # 如果存在相同任务类型工单的AGV调度任务,则提示错误 + agv_scheduling = self.sudo().search([ + ('workorder_ids', 'in', workorders.ids), ('agv_route_type', '=', agv_route_type), ('state', 'in', ['待下发', '配送中']) - ], limit=1): - raise RepeatTaskException('已存在相同的AGV调度任务,请勿重复下发!') + ], limit=1) + if agv_scheduling: + # 计算agv_scheduling.workorder_ids与workorders的交集 + repetitive_workorders = agv_scheduling.workorder_ids & workorders + raise RepeatTaskException( + '制造订单号【%s】已存在与【%s】AGV调度任务,请勿重复下发!' % + (','.join(repetitive_workorders.mapped('production_id.name')), agv_scheduling.name) + ) vals = { 'start_site_id': agv_start_site_id, 'agv_route_type': agv_route_type, - 'delivery_workpieces': '、'.join(productions.mapped('name')), - 'workpiece_delivery_ids': deliveries.mapped('id') if deliveries else [], + 'workorder_ids': workorders.ids, + # 'workpiece_delivery_ids': deliveries.mapped('id') if deliveries else [], 'task_create_time': fields.Datetime.now() } # 如果只有唯一任务路线,则自动赋予终点接驳站跟任务名称 @@ -95,26 +100,52 @@ class AgvScheduling(models.Model): ]) if len(agv_routes) == 1: vals.update({'end_site_id': agv_routes[0].end_site_id.id, 'agv_route_name': agv_routes[0].name}) + else: + # 判断终点接驳站是否为空闲 + idle_routes = agv_routes.filtered(lambda r: r.end_site_id.state == '空闲') + if idle_routes: + # 将空闲的路线按照终点接驳站名称排序 + idle_routes = sorted(idle_routes, key=lambda r: r.end_site_id.name) + vals.update({'end_site_id': idle_routes[0].end_site_id.id, 'agv_route_name': idle_routes[0].name}) try: - dispatch = self.env['sf.agv.scheduling'].sudo().create(vals) + scheduling = self.env['sf.agv.scheduling'].sudo().create(vals) + # 触发空闲接驳站状态更新,触发新任务下发 + if scheduling.end_site_id.state == '空闲': + scheduling.dispatch_scheduling(scheduling.end_site_id.id, scheduling.end_site_id.state) + except Exception as e: _logger.error('添加AGV调度任务失败: %s', e) raise UserError(_('添加AGV调度任务失败: %s', e)) - return dispatch + return scheduling def on_site_state_change(self, agv_site_id, agv_site_state): - agv_schedulings = self.env['sf.agv.scheduling'].sudo().search([('state', '=', '待下发')], order='id asc') - for scheduling in agv_schedulings: - if scheduling.end_site_id.id == agv_site_id and scheduling.site_state == '空闲': - # 下发AGV调度任务并修改接驳站状态为占用 - # self._delivery_avg() - # 修改AGV调度任务信息 - scheduling.state = '配送中' - scheduling.task_delivery_time = fields.Datetime.now() - scheduling.site_state = agv_site_state - # 更新接驳站状态 - self.env['sf.agv.site'].update_site_state(scheduling.end_site_id.name, True) + """ + 响应AGV接驳站站点状态变化 + params: + agv_site_id: 接驳站ID + agv_site_state: 站点状态('空闲', '占用') + """ + if agv_site_state == '空闲': + # 查询终点接驳站为agv_site_id的AGV路线 + task_routes = self.env['sf.agv.task.route'].sudo().search([('end_site_id', '=', agv_site_id)]) + agv_scheduling = self.env['sf.agv.scheduling'].sudo().search( + [('state', '=', '待下发'), ('agv_route_type', 'in', task_routes.mapped('route_type'))], + order='id asc', + limit=1 + ) + # 下发AGV调度任务并修改接驳站状态为占用 + agv_scheduling.dispatch_scheduling(agv_site_id, agv_site_state) + # 更新接驳站状态 + self.env['sf.agv.site'].update_site_state({agv_scheduling.end_site_id.name: '占用'}, False) + else: + # 如果终点接驳站变为占用,则认为任务完成 + agv_scheduling = self.env['sf.agv.scheduling'].sudo().search( + [('state', '=', '配送中'), ('end_site_id', '=', agv_site_id)], + order='id asc', + limit=1 + ) + agv_scheduling.finish_scheduling() def _delivery_avg(self): config = self.env['res.config.settings'].get_values() @@ -190,3 +221,36 @@ class AgvScheduling(models.Model): if rec.state != '待下发': raise UserError('只有待下发状态的AGV调度任务才能取消!') rec.state = '已取消' + + def finish_scheduling(self): + """ + 完成调度任务 + """ + for rec in self: + if rec.state != '配送中': + return False + rec.state = '已配送' + rec.task_completion_time = fields.Datetime.now() + + def dispatch_scheduling(self, agv_end_site_id, agv_site_state): + """ + 下发调度任务 + """ + for rec in self: + if rec.state != '待下发': + return False + # rec._delivery_avg() + rec.state = '配送中' + rec.task_delivery_time = fields.Datetime.now() + rec.site_state = agv_site_state + rec.end_site_id = agv_end_site_id + + +class ResMrpWorkOrder(models.Model): + _inherit = 'mrp.workorder' + + agv_scheduling_ids = fields.Many2many( + 'sf.agv.scheduling', + 'sf_agv_scheduling_mrp_workorder_ref', + string='AGV调度', + domain=[('state', '!=', '已取消')]) diff --git a/sf_manufacturing/models/agv_setting.py b/sf_manufacturing/models/agv_setting.py index 5f1f728e..820ed539 100644 --- a/sf_manufacturing/models/agv_setting.py +++ b/sf_manufacturing/models/agv_setting.py @@ -5,6 +5,8 @@ import time from odoo import fields, models, api from odoo.exceptions import UserError +_logger = logging.getLogger(__name__) + class AgvSetting(models.Model): _name = 'sf.agv.site' @@ -57,14 +59,23 @@ class AgvSetting(models.Model): # logging.error('工件配送-请求中控接口错误: %s', e) # return False - def update_site_state(self, agv_site_name, is_occupy): - if agv_site_name: - agv_site = self.env['sf.agv.site'].sudo().search([('name', '=', agv_site_name)]) - if agv_site: - agv_site.state = '占用' if is_occupy else '空闲' - self.env['sf.agv.scheduling'].on_site_state_change(agv_site.id, agv_site.state) - else: - raise UserError("更新失败:接驳站站点错误!") + def update_site_state(self, agv_site_state_arr, notify=True): + """ + 更新接驳站状态 + params: + agv_site_state_arr: {'A01': '空闲', 'B01': '占用'} + notify: 是否通知调度(非中控发起的状态改变不触发调度任务) + """ + if isinstance(agv_site_state_arr, dict): + for agv_site_name, is_occupy in agv_site_state_arr.items(): + agv_site = self.env['sf.agv.site'].sudo().search([('name', '=', agv_site_name)]) + if agv_site: + agv_site.state = is_occupy + if notify: + self.env['sf.agv.scheduling'].on_site_state_change(agv_site.id, agv_site.state) + else: + _logger.error("更新失败:接驳站站点错误!%s" % agv_site_name) + raise UserError("更新失败:接驳站站点错误!") class AgvTaskRoute(models.Model): diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index 2257fd51..36fab67c 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -1089,6 +1089,8 @@ class ResMrpWorkOrder(models.Model): record.process_state = '待加工' # record.write({'process_state': '待加工'}) record.production_id.process_state = '待加工' + # 生成工件配送单 + record.workpiece_delivery_ids = record._json_workpiece_delivery_list() if record.routing_type == 'CNC加工': record.process_state = '待解除装夹' # record.write({'process_state': '待加工'}) @@ -1190,8 +1192,7 @@ class ResMrpWorkOrder(models.Model): raw_move.write({'state': 'done'}) record.production_id.button_mark_done1() # record.production_id.state = 'done' - # 生成工件配送单 - record.workpiece_delivery_ids = record._json_workpiece_delivery_list() + # 将FTP的检测报告文件下载到临时目录 def download_reportfile_tmp(self, workorder, reportpath): @@ -1495,7 +1496,7 @@ class SfWorkOrderBarcodes(models.Model): class WorkPieceDelivery(models.Model): _name = "sf.workpiece.delivery" - _inherit = ['mail.thread', 'mail.activity.mixin', "barcodes.barcode_events_mixin"] + _inherit = ['mail.thread', 'mail.activity.mixin'] _description = '工件配送' name = fields.Char('单据编码') @@ -1573,12 +1574,12 @@ class WorkPieceDelivery(models.Model): # 工件配送 def button_delivery(self): - delivery_ids = [] + # delivery_ids = [] production_ids = [] + workorder_ids = [] is_cnc_down = 0 is_not_production_line = 0 same_production_line_id = None - same_route_id = None production_type = '上产线' max_num = 4 # 最大配送数量 if len(self) > max_num: @@ -1593,24 +1594,25 @@ class WorkPieceDelivery(models.Model): if item.is_cnc_program_down is False: is_cnc_down += 1 if is_cnc_down == 0 and is_not_production_line == 0: - delivery_ids.append(item.id) + # delivery_ids.append(item.id) production_ids.append(item.production_id.id) + workorder_ids.append(item.workorder_id.id) if is_cnc_down >= 1: raise UserError('您所选择制造订单的【CNC程序】暂未下发,请在程序下发后再进行配送') if is_not_production_line >= 1: raise UserError('您所选择制造订单的【目的生产线】不一致,请重新确认') - if delivery_ids: - return { - 'name': _('确认'), - 'type': 'ir.actions.act_window', - 'view_mode': 'form', - 'res_model': 'sf.workpiece.delivery.wizard', - 'target': 'new', - 'context': { - 'default_delivery_ids': [(6, 0, delivery_ids)], - 'default_production_ids': [(6, 0, production_ids)], - 'default_type': production_type, - }} + return { + 'name': _('确认'), + 'type': 'ir.actions.act_window', + 'view_mode': 'form', + 'res_model': 'sf.workpiece.delivery.wizard', + 'target': 'new', + 'context': { + # 'default_delivery_ids': [(6, 0, delivery_ids)], + 'default_production_ids': [(6, 0, production_ids)], + 'default_type': production_type, + 'default_workorder_ids': [(6, 0, workorder_ids)], + }} # 验证agv站点是否可用 @@ -1716,11 +1718,6 @@ class WorkPieceDelivery(models.Model): else: obj.delivery_duration = 0.0 - # agv调度单 - agv_scheduling_id = fields.Many2one('sf.agv.scheduling', 'agv调度单') - - def on_barcode_scanned(self, barcode): - logging.info('Rfid:%s' % barcode) class CMMprogram(models.Model): diff --git a/sf_manufacturing/static/src/xml/button_show_on_tree.xml b/sf_manufacturing/static/src/xml/button_show_on_tree.xml new file mode 100644 index 00000000..041b16a4 --- /dev/null +++ b/sf_manufacturing/static/src/xml/button_show_on_tree.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf_manufacturing/views/agv_scheduling_views.xml b/sf_manufacturing/views/agv_scheduling_views.xml index 4e7271f6..ff8dc9b5 100644 --- a/sf_manufacturing/views/agv_scheduling_views.xml +++ b/sf_manufacturing/views/agv_scheduling_views.xml @@ -18,7 +18,7 @@ - + diff --git a/sf_manufacturing/views/mrp_workorder_view.xml b/sf_manufacturing/views/mrp_workorder_view.xml index 60c0b8a0..8ef871b9 100644 --- a/sf_manufacturing/views/mrp_workorder_view.xml +++ b/sf_manufacturing/views/mrp_workorder_view.xml @@ -631,7 +631,7 @@
-
sf.workpiece.delivery.wizard.form.view sf.workpiece.delivery.wizard -
+ - - + + + -
- - -
diff --git a/sf_manufacturing/wizard/workpiece_delivery_wizard.py b/sf_manufacturing/wizard/workpiece_delivery_wizard.py index 6b9fb840..9f36622c 100644 --- a/sf_manufacturing/wizard/workpiece_delivery_wizard.py +++ b/sf_manufacturing/wizard/workpiece_delivery_wizard.py @@ -8,11 +8,12 @@ from odoo import models, api, fields, _ class WorkpieceDeliveryWizard(models.TransientModel): _name = 'sf.workpiece.delivery.wizard' + _inherit = ["barcodes.barcode_events_mixin"] _description = '工件配送' - delivery_ids = fields.Many2many('sf.workpiece.delivery', string='配送') + # delivery_ids = fields.Many2many('sf.workpiece.delivery', string='配送') rfid_code = fields.Char('rfid码') - workorder_id = fields.Many2one('mrp.workorder', string='工单') + workorder_ids = fields.Many2many('mrp.workorder', string='工单') production_ids = fields.Many2many('mrp.production', string='制造订单号') destination_production_line_id = fields.Many2one('sf.production.line', '目的生产线') route_id = fields.Many2one('sf.agv.task.route', '任务路线', domain=[('route_type', 'in', ['上产线', '下产线'])]) @@ -51,29 +52,27 @@ class WorkpieceDeliveryWizard(models.TransientModel): def confirm(self): try: - if self.workorder_id: - self.workorder_id.workpiece_delivery_ids[0].agv_scheduling_id() + # if self.workorder_id: + # self.workorder_id.workpiece_delivery_ids[0].agv_scheduling_id() + # else: + is_not_production_line = 0 + same_production_line_id = None + notsame_production_line_arr = [] + for item in self.production_ids: + if same_production_line_id is None: + same_production_line_id = item.production_line_id.id + if item.production_line_id.id != same_production_line_id: + notsame_production_line_arr.append(item.name) + notsame_production_line_str = ','.join(map(str, notsame_production_line_arr)) + if is_not_production_line >= 1: + raise UserError('制造订单号为%s的目的生产线不一致' % notsame_production_line_str) else: - is_not_production_line = 0 - same_production_line_id = None - notsame_production_line_arr = [] - for item in self.production_ids: - if same_production_line_id is None: - same_production_line_id = item.production_line_id.id - if item.production_line_id.id != same_production_line_id: - notsame_production_line_arr.append(item.name) - notsame_production_line_str = ','.join(map(str, notsame_production_line_arr)) - if is_not_production_line >= 1: - raise UserError('制造订单号为%s的目的生产线不一致' % notsame_production_line_str) - else: - # self.delivery_ids._delivery_avg() - agv_scheduling_id = self.env['sf.agv.scheduling'].add_scheduling( - agv_start_site_id=self.feeder_station_start_id.id, - agv_route_type=self.type, - productions=self.production_ids, - deliveries=self.delivery_ids - ) - self.delivery_ids.agv_scheduling_id = agv_scheduling_id + self.env['sf.agv.scheduling'].add_scheduling( + agv_start_site_id=self.feeder_station_start_id.id, + agv_route_type=self.type, + workorders=self.workorder_ids, + ) + except Exception as e: logging.info('工件配送任务下发失败:%s' % e) raise UserError('工件配送任务下发失败:%s' % e) @@ -122,3 +121,18 @@ class WorkpieceDeliveryWizard(models.TransientModel): if self.route_id: self.feeder_station_start_id = self.route_id.start_site_id.id self.feeder_station_destination_id = self.route_id.end_site_id.id + + def on_barcode_scanned(self, barcode): + workorder = self.env['mrp.workorder'].search( + [('production_line_state', '=', '待上产线'), ('rfid_code', '=', barcode), + ('state', '=', 'done')]) + if workorder: + if len(self.production_ids) > 0 and workorder.production_line_id.id != self.production_ids[0].production_line_id.id: + raise UserError('该rfid对应的制造订单号为%s的目的生产线不一致' % workorder.production_id.name) + + # 将对象添加到对应的同模型且是多对多类型里 + self.production_ids |= workorder.production_id + self.workorder_ids |= workorder + else: + raise UserError('该rfid码对应的工单不存在') + return