From 9dbea66b73f0316ec8cf6a02453c6a014e069bd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Fri, 9 Aug 2024 17:32:46 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9AGV=E8=B0=83=E5=BA=A6?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/__manifest__.py | 4 +- sf_manufacturing/controllers/controllers.py | 63 +++++- ...patch_data.xml => agv_scheduling_data.xml} | 6 +- sf_manufacturing/models/__init__.py | 2 +- sf_manufacturing/models/agv_dispatch.py | 76 ------- sf_manufacturing/models/agv_scheduling.py | 191 ++++++++++++++++++ sf_manufacturing/models/agv_setting.py | 80 +++++--- sf_manufacturing/models/mrp_workcenter.py | 2 +- sf_manufacturing/models/mrp_workorder.py | 2 +- sf_manufacturing/security/ir.model.access.csv | 2 +- ...tch_views.xml => agv_scheduling_views.xml} | 38 ++-- .../views/mrp_workcenter_views.xml | 2 +- .../wizard/workpiece_delivery_views.xml | 2 +- .../wizard/workpiece_delivery_wizard.py | 48 +++-- 14 files changed, 349 insertions(+), 169 deletions(-) rename sf_manufacturing/data/{agv_dispatch_data.xml => agv_scheduling_data.xml} (66%) delete mode 100644 sf_manufacturing/models/agv_dispatch.py create mode 100644 sf_manufacturing/models/agv_scheduling.py rename sf_manufacturing/views/{agv_dispatch_views.xml => agv_scheduling_views.xml} (56%) diff --git a/sf_manufacturing/__manifest__.py b/sf_manufacturing/__manifest__.py index f17a40df..ca85c807 100644 --- a/sf_manufacturing/__manifest__.py +++ b/sf_manufacturing/__manifest__.py @@ -15,14 +15,14 @@ 'data/stock_data.xml', 'data/empty_racks_data.xml', 'data/panel_data.xml', - 'data/agv_dispatch_data.xml', + 'data/agv_scheduling_data.xml', 'security/group_security.xml', 'security/ir.model.access.csv', 'wizard/workpiece_delivery_views.xml', 'wizard/rework_wizard_views.xml', 'wizard/production_wizard_views.xml', 'views/mrp_views_menus.xml', - 'views/agv_dispatch_views.xml', + 'views/agv_scheduling_views.xml', 'views/stock_lot_views.xml', 'views/mrp_production_addional_change.xml', 'views/mrp_routing_workcenter_view.xml', diff --git a/sf_manufacturing/controllers/controllers.py b/sf_manufacturing/controllers/controllers.py index 037730bc..27e18f25 100644 --- a/sf_manufacturing/controllers/controllers.py +++ b/sf_manufacturing/controllers/controllers.py @@ -2,6 +2,8 @@ import logging import json from datetime import datetime + +from odoo.addons.sf_manufacturing.models.agv_scheduling import RepeatTaskException from odoo import http from odoo.http import request @@ -448,6 +450,9 @@ 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 if ret['IsComplete'] is True or ret['IsComplete'] is False: for i in range(1, 5): logging.info('F-RfidCode:%s' % i) @@ -455,6 +460,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 domain = [ ('rfid_code', '=', rfid_code), ('routing_type', '=', 'CNC加工'), ('state', '!=', 'rework') @@ -462,6 +468,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) if order.production_line_state == '待上产线': logging.info( '工单产线状态:%s' % order.production_line_state) @@ -470,23 +477,37 @@ class Manufacturing_Connect(http.Controller): ('processing_panel', '=', order.processing_panel)]) if panel_workorder: panel_workorder.write({'production_line_state': '已上产线'}) - 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.status == '待下发': - workpiece_delivery.write({'is_manual_work': True}) + # 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.status == '待下发': + # 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': '已配送'}) + # 向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) else: res = {'Succeed': False, 'ErrorCode': 203, 'Error': '未传IsComplete字段'} else: res = {'Succeed': False, 'ErrorCode': 201, 'Error': '未传DeviceId字段'} + except RepeatTaskException as e: + logging.info('AGVToProduct error:%s' % e) except Exception as e: - res = {'Succeed': False, 'ErrorCode': 202, 'Error': e} + res = {'Succeed': False, 'ErrorCode': 202, 'Error': str(e)} logging.info('AGVToProduct error:%s' % e) return json.JSONEncoder().encode(res) @@ -600,3 +621,27 @@ class Manufacturing_Connect(http.Controller): res = {'Succeed': False, 'ErrorCode': 202, 'Error': e} logging.info('AGVDownProduct error:%s' % e) return json.JSONEncoder().encode(res) + + @http.route('/AutoDeviceApi/GetAgvStationState', type='json', auth='public', methods=['GET', 'POST'], csrf=False, + cors="*") + def AGVStationState(self, **kw): + """ + 中控推送接驳站状态 + :param kw: + :return: + """ + logging.info('AGVStationState:%s' % kw) + try: + res = {'Succeed': True} + datas = request.httprequest.data + ret = json.loads(datas) + request.env['center_control.interface.log'].sudo().create( + {'content': ret, 'name': 'AutoDeviceApi/AGVStationState'}) + 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']) + except Exception as e: + res = {'Succeed': False, 'ErrorCode': 202, 'Error': str(e)} + logging.info('AGVDownProduct error:%s' % e) + return json.JSONEncoder().encode(res) \ No newline at end of file diff --git a/sf_manufacturing/data/agv_dispatch_data.xml b/sf_manufacturing/data/agv_scheduling_data.xml similarity index 66% rename from sf_manufacturing/data/agv_dispatch_data.xml rename to sf_manufacturing/data/agv_scheduling_data.xml index 32b76406..c5f6d6a1 100644 --- a/sf_manufacturing/data/agv_dispatch_data.xml +++ b/sf_manufacturing/data/agv_scheduling_data.xml @@ -1,9 +1,9 @@ - - + + AGV调度 - sf.agv.dispatch + sf.agv.scheduling B%(year)s%(month)s%(day)s 4 diff --git a/sf_manufacturing/models/__init__.py b/sf_manufacturing/models/__init__.py index 0b212cdb..b93d613e 100644 --- a/sf_manufacturing/models/__init__.py +++ b/sf_manufacturing/models/__init__.py @@ -9,4 +9,4 @@ from . import stock from . import res_user from . import production_line_base from . import agv_setting -from . import agv_dispatch +from . import agv_scheduling diff --git a/sf_manufacturing/models/agv_dispatch.py b/sf_manufacturing/models/agv_dispatch.py deleted file mode 100644 index 74c981f1..00000000 --- a/sf_manufacturing/models/agv_dispatch.py +++ /dev/null @@ -1,76 +0,0 @@ -from odoo import models, fields, api, _ -from odoo.exceptions import UserError - -import logging - -_logger = logging.getLogger(__name__) - - -class AgvDispatch(models.Model): - _name = 'sf.agv.dispatch' - _description = 'agv调度' - - name = fields.Char('任务单号', index=True, copy=False) - - def _get_agv_route_type_selection(self): - return self.env['sf.agv.task.route'].fields_get(['route_type'])['route_type']['selection'] - - agv_route_type = fields.Selection(selection=_get_agv_route_type_selection, string='任务类型', required=True) - agv_route_name = fields.Char('任务路线名称') - start_site_id = fields.Many2one('sf.agv.site', '起点接驳站', required=True) - end_site_id = fields.Many2one('sf.agv.site', '终点接驳站', tracking=True) - site_state = fields.Selection([ - ('占用', '占用'), - ('空闲', '空闲')], string='终点接驳站状态') - state = fields.Selection([ - ('待下发', '待下发'), - ('配送中', '配送中'), - ('已配送', '已配送'), - ('已取消', '已取消')], string='状态', default='待下发', tracking=True) - productions = fields.Char('制造订单', compute='_compute_productions') - workpiece_delivery_ids = fields.One2many('sf.workpiece.delivery', 'agv_dispatch_id', string='工件配送单') - delivery_workpieces = fields.Char('配送工件', compute='_compute_delivery_workpieces') - - @api.depends('workpiece_delivery_ids') - def _compute_delivery_workpieces(self): - for rec in self: - rec.delivery_workpieces = '\\'.join(rec.workpiece_delivery_ids.mapped('name')) - - task_create_time = fields.Datetime('任务创建时间') - task_delivery_time = fields.Datetime('任务下发时间') - task_completion_time = fields.Datetime('任务完成时间') - task_duration = fields.Char('任务时长', compute='_compute_task_duration') - - @api.depends('task_completion_time', 'task_delivery_time') - def _compute_task_duration(self): - for rec in self: - if rec.task_completion_time and rec.task_delivery_time: - rec.task_duration = str(rec.task_completion_time - rec.task_delivery_time) - else: - rec.task_duration = '' - - @api.model_create_multi - def create(self, vals_list): - # We generate a standard reference - for vals in vals_list: - vals['name'] = self.env['ir.sequence'].next_by_code('sf.agv.dispatch') or _('New') - return super().create(vals_list) - - def add_queue(self, agv_start_site_id, agv_route_type, production_ids, delivery_ids): - """ - 根据参数增加AGV调度任务 - """ - vals = { - 'start_site_id': agv_start_site_id, - 'agv_route_type': agv_route_type, - 'productions': '、'.join(production_ids.mapped('name')), - 'workpiece_delivery_ids': delivery_ids or [], - 'task_create_time': fields.Datetime.now() - } - try: - dispatch = self.env['sf.agv.dispatch'].sudo().create(vals) - except Exception as e: - _logger.error('添加AGV调度任务失败: %s', e) - raise UserError(e) - - return dispatch diff --git a/sf_manufacturing/models/agv_scheduling.py b/sf_manufacturing/models/agv_scheduling.py new file mode 100644 index 00000000..f550149c --- /dev/null +++ b/sf_manufacturing/models/agv_scheduling.py @@ -0,0 +1,191 @@ +from odoo import models, fields, api, _ +from odoo.exceptions import UserError + +import logging + +_logger = logging.getLogger(__name__) + + +class RepeatTaskException(UserError): + pass + + +class AgvScheduling(models.Model): + _name = 'sf.agv.scheduling' + _description = 'agv调度' + + name = fields.Char('任务单号', index=True, copy=False) + + def _get_agv_route_type_selection(self): + return self.env['sf.agv.task.route'].fields_get(['route_type'])['route_type']['selection'] + + agv_route_type = fields.Selection(selection=_get_agv_route_type_selection, string='任务类型', required=True) + agv_route_name = fields.Char('任务路线名称') + start_site_id = fields.Many2one('sf.agv.site', '起点接驳站', required=True) + end_site_id = fields.Many2one('sf.agv.site', '终点接驳站', tracking=True) + site_state = fields.Selection([ + ('占用', '占用'), + ('空闲', '空闲')], string='终点接驳站状态', default='占用') + state = fields.Selection([ + ('待下发', '待下发'), + ('配送中', '配送中'), + ('已配送', '已配送'), + ('已取消', '已取消')], string='状态', default='待下发', tracking=True) + workpiece_delivery_ids = fields.One2many('sf.workpiece.delivery', 'agv_scheduling_id', string='工件配送单') + delivery_workpieces = fields.Char('配送工件', required=True, index=True) + task_create_time = fields.Datetime('任务创建时间') + task_delivery_time = fields.Datetime('任务下发时间') + task_completion_time = fields.Datetime('任务完成时间') + task_duration = fields.Char('任务时长', compute='_compute_task_duration') + + @api.depends('agv_route_type') + def _compute_delivery_workpieces(self): + for record in self: + if record.agv_route_type == '运送空料架': + record.delivery_workpieces_display = '/' + else: + record.delivery_workpieces_display = record.delivery_workpieces + + delivery_workpieces_display = fields.Char('配送工件', compute=_compute_delivery_workpieces) + + @api.depends('task_completion_time', 'task_delivery_time') + def _compute_task_duration(self): + for rec in self: + if rec.task_completion_time and rec.task_delivery_time: + rec.task_duration = str(rec.task_completion_time - rec.task_delivery_time) + else: + rec.task_duration = '' + + @api.model_create_multi + def create(self, vals_list): + # We generate a standard reference + for vals in vals_list: + 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 + 新增AGV调度 + params: + agv_start_site_id: AGV起点接驳站ID + agv_route_type: AGV任务类型 + productions: 制造订单 + deliveries: 工件配送单 + """ + # 如果存在配送工件完全相同的AGV调度任务,则不新增 + if self.sudo().search([ + ('delivery_workpieces', '=', '、'.join(productions.mapped('name'))), + ('agv_route_type', '=', agv_route_type), + ('state', 'in', ['待下发', '配送中']) + ], limit=1): + raise RepeatTaskException('已存在相同的AGV调度任务,请勿重复下发!') + + 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 [], + 'task_create_time': fields.Datetime.now() + } + # 如果只有唯一任务路线,则自动赋予终点接驳站跟任务名称 + agv_routes = self.env['sf.agv.task.route'].sudo().search([ + ('route_type', '=', agv_route_type), + ('start_site_id', '=', agv_start_site_id) + ]) + if len(agv_routes) == 1: + vals.update({'end_site_id': agv_routes[0].end_site_id.id, 'agv_route_name': agv_routes[0].name}) + try: + dispatch = self.env['sf.agv.scheduling'].sudo().create(vals) + except Exception as e: + _logger.error('添加AGV调度任务失败: %s', e) + raise UserError(_('添加AGV调度任务失败: %s', e)) + + return dispatch + + 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) + + def _delivery_avg(self): + config = self.env['res.config.settings'].get_values() + positionCode_Arr = [] + delivery_Arr = [] + feeder_station_start = None + feeder_station_destination = None + route_id = None + for item in self: + if route_id is None: + route_id = item.route_id.id + if feeder_station_start is None: + feeder_station_start = item.feeder_station_start_id + if feeder_station_destination is None: + feeder_station_destination = item.feeder_station_destination_id + if item.type in ['上产线', '下产线']: + item.route_id = route_id + item.feeder_station_start_id = feeder_station_start.id + item.feeder_station_destination_id = feeder_station_destination.id + delivery_Arr.append(item.name) + else: + self = self.create( + {'name': self.env['ir.sequence'].next_by_code('sf.workpiece.delivery'), + 'route_id': self.route_id.id, + 'feeder_station_start_id': self.feeder_station_start_id.id, + 'feeder_station_destination_id': self.feeder_station_destination_id.id}) + delivery_Arr.append(self.name) + delivery_str = ','.join(map(str, delivery_Arr)) + if feeder_station_start is not None: + positionCode_Arr.append({ + 'positionCode': feeder_station_start.name, + 'code': '00' + }) + if feeder_station_destination is not None: + positionCode_Arr.append({ + 'positionCode': feeder_station_destination.name, + 'code': '00' + }) + res = {'reqCode': delivery_str, 'reqTime': '', 'clientCode': '', 'tokenCode': '', + 'taskTyp': 'F01', 'ctnrTyp': '', 'ctnrCode': '', 'wbCode': config['wbcode'], + 'positionCodePath': positionCode_Arr, + 'podCode': '', + 'podDir': '', 'materialLot': '', 'priority': '', 'taskCode': '', 'agvCode': '', 'materialLot': '', + 'data': ''} + try: + logging.info('AGV请求路径:%s' % config['agv_rcs_url']) + logging.info('AGV-json:%s' % res) + headers = {'Content-Type': 'application/json'} + ret = requests.post((config['agv_rcs_url']), json=res, headers=headers) + ret = ret.json() + logging.info('config-ret:%s' % ret) + if ret['code'] == 0: + req_codes = ret['reqCode'].split(',') + for delivery_item in self: + for req_code in req_codes: + if delivery_item.name == req_code.strip(): + logging.info('delivery_item-name:%s' % delivery_item.name) + delivery_item.write({ + 'task_delivery_time': fields.Datetime.now(), + 'status': '待配送' + }) + if delivery_item.type == "上产线": + delivery_item.workorder_id.write({'is_delivery': True}) + else: + raise UserError(ret['message']) + except Exception as e: + logging.info('config-e:%s' % e) + raise UserError("工件配送请求agv失败:%s" % e) + + def button_cancel(self): + # 弹出二次确认窗口后执行 + for rec in self: + if rec.state != '待下发': + raise UserError('只有待下发状态的AGV调度任务才能取消!') + rec.state = '已取消' diff --git a/sf_manufacturing/models/agv_setting.py b/sf_manufacturing/models/agv_setting.py index 8fe22715..5f1f728e 100644 --- a/sf_manufacturing/models/agv_setting.py +++ b/sf_manufacturing/models/agv_setting.py @@ -18,39 +18,53 @@ class AgvSetting(models.Model): divide_the_work = fields.Char('主要分工') active = fields.Boolean('有效', default=True) workcenter_id = fields.Many2one(string='所属区域', comodel_name='mrp.workcenter', tracking=True, - domain=[('is_agv_dispatch', '=', True)]) + domain=[('is_agv_scheduling', '=', True)]) - def update_site_state(self): - # 调取中控的接驳站接口并修改对应站点的状态 - config = self.env['res.config.settings'].get_values() - # token = sf_sync_config['token'Ba F2CF5DCC-1A00-4234-9E95-65603F70CC8A] - headers = {'Authorization': config['center_control_Authorization']} - center_control_url = config['center_control_url'] + "/AutoDeviceApi/GetAgvStationState?date=" - timestamp = int(time.time()) - center_control_url += str(timestamp) - logging.info('工件配送-请求中控地址:%s' % center_control_url) - try: - center_control_r = requests.get(center_control_url, headers=headers, timeout=10) # 设置超时为60秒 - ret = center_control_r.json() - logging.info('工件配送-请求中控站点信息:%s' % ret) - self.env['center_control.interface.log'].sudo().create( - {'content': ret, 'name': 'AutoDeviceApi/GetAgvStationState?date=%s' % str(timestamp)}) - if ret['Succeed'] is True: - datas = ret['Datas'] - for item in self: - for da in datas: - if da['DeviceId'] == item.name: - if da['AtHome'] is True: - item.state = '占用' - else: - item.state = '空闲' - return True - except requests.exceptions.Timeout: - logging.error('工件配送-请求中控接口超时') - return False - except requests.exceptions.RequestException as e: - logging.error('工件配送-请求中控接口错误: %s', e) - return False + # name必须唯一 + _sql_constraints = [ + ('name_uniq', 'unique (name)', '站点编号必须唯一!'), + ] + + # def update_site_state(self): + # # 调取中控的接驳站接口并修改对应站点的状态 + # config = self.env['res.config.settings'].get_values() + # # token = sf_sync_config['token'Ba F2CF5DCC-1A00-4234-9E95-65603F70CC8A] + # headers = {'Authorization': config['center_control_Authorization']} + # center_control_url = config['center_control_url'] + "/AutoDeviceApi/GetAgvStationState?date=" + # timestamp = int(time.time()) + # center_control_url += str(timestamp) + # logging.info('工件配送-请求中控地址:%s' % center_control_url) + # try: + # center_control_r = requests.get(center_control_url, headers=headers, timeout=10) # 设置超时为60秒 + # ret = center_control_r.json() + # logging.info('工件配送-请求中控站点信息:%s' % ret) + # self.env['center_control.interface.log'].sudo().create( + # {'content': ret, 'name': 'AutoDeviceApi/GetAgvStationState?date=%s' % str(timestamp)}) + # if ret['Succeed'] is True: + # datas = ret['Datas'] + # for item in self: + # for da in datas: + # if da['DeviceId'] == item.name: + # if da['AtHome'] is True: + # item.state = '占用' + # else: + # item.state = '空闲' + # return True + # except requests.exceptions.Timeout: + # logging.error('工件配送-请求中控接口超时') + # return False + # except requests.exceptions.RequestException as e: + # 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("更新失败:接驳站站点错误!") class AgvTaskRoute(models.Model): @@ -73,7 +87,7 @@ class AgvTaskRoute(models.Model): if self.end_site_id == self.start_site_id: raise UserError("您选择的终点接驳站与起点接驳站重复,请重新选择") - workcenter_id = fields.Many2one(string='所属区域', comodel_name='mrp.workcenter', domain=[('is_agv_dispatch', '=', True)], + workcenter_id = fields.Many2one(string='所属区域', comodel_name='mrp.workcenter', domain=[('is_agv_scheduling', '=', True)], compute="_compute_region") @api.depends('end_site_id') diff --git a/sf_manufacturing/models/mrp_workcenter.py b/sf_manufacturing/models/mrp_workcenter.py index 8fb62e7d..461ef6ad 100644 --- a/sf_manufacturing/models/mrp_workcenter.py +++ b/sf_manufacturing/models/mrp_workcenter.py @@ -125,7 +125,7 @@ class ResWorkcenter(models.Model): return res # AGV是否可配送 - is_agv_dispatch = fields.Boolean(string="AGV配送", tracking=True) + is_agv_scheduling = fields.Boolean(string="AGV所属区域", tracking=True) class ResWorkcenterProductivity(models.Model): _inherit = 'mrp.workcenter.productivity' diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index 792ecb9f..2257fd51 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -1717,7 +1717,7 @@ class WorkPieceDelivery(models.Model): obj.delivery_duration = 0.0 # agv调度单 - agv_dispatch_id = fields.Many2one('sf.agv.dispatch', 'agv调度单') + agv_scheduling_id = fields.Many2one('sf.agv.scheduling', 'agv调度单') def on_barcode_scanned(self, barcode): logging.info('Rfid:%s' % barcode) diff --git a/sf_manufacturing/security/ir.model.access.csv b/sf_manufacturing/security/ir.model.access.csv index 2fd16b53..f8affb19 100644 --- a/sf_manufacturing/security/ir.model.access.csv +++ b/sf_manufacturing/security/ir.model.access.csv @@ -150,7 +150,7 @@ access_sf_processing_panel_group_sf_order_user,sf_processing_panel_group_sf_orde access_sf_production_wizard_group_sf_order_user,sf_production_wizard_group_sf_order_user,model_sf_production_wizard,sf_base.group_sf_order_user,1,1,1,0 access_sf_processing_panel_group_plan_dispatch,sf_processing_panel_group_plan_dispatch,model_sf_processing_panel,sf_base.group_plan_dispatch,1,1,1,0 -access_sf_agv_dispatch_admin,sf_agv_dispatch_admin,model_sf_agv_dispatch,base.group_system,1,1,1,1 +access_sf_agv_scheduling_admin,sf_agv_scheduling_admin,model_sf_agv_scheduling,base.group_system,1,1,1,1 diff --git a/sf_manufacturing/views/agv_dispatch_views.xml b/sf_manufacturing/views/agv_scheduling_views.xml similarity index 56% rename from sf_manufacturing/views/agv_dispatch_views.xml rename to sf_manufacturing/views/agv_scheduling_views.xml index 5cf608b6..4e7271f6 100644 --- a/sf_manufacturing/views/agv_dispatch_views.xml +++ b/sf_manufacturing/views/agv_scheduling_views.xml @@ -2,9 +2,9 @@ - + agv调度 - sf.agv.dispatch + sf.agv.scheduling - + +