diff --git a/odoo.conf b/odoo.conf index 48ce1738..8db2413f 100644 --- a/odoo.conf +++ b/odoo.conf @@ -4,7 +4,7 @@ csv_internal_sep = , data_dir = /var/lib/odoo db_host = 172.17.0.2 db_maxconn = 64 -db_name = sf_t2cs_003 +db_name = sf_t_0430 db_password = sf db_port = 5432 db_sslmode = prefer diff --git a/sf_base/security/ir.model.access.csv b/sf_base/security/ir.model.access.csv index 3795e69b..88e056e6 100644 --- a/sf_base/security/ir.model.access.csv +++ b/sf_base/security/ir.model.access.csv @@ -11,7 +11,8 @@ access_sf_machine_control_system,sf_machine_control_system,model_sf_machine_cont access_sf_machine_control_system_admin,sf_machine_control_system_admin,model_sf_machine_control_system,base.group_system,1,1,1,0 access_sf_production_process_group_sale_director,sf_production_process_group_sale_director,model_sf_production_process,sf_base.group_sale_director,1,0,0,0 access_sf_production_process_group_sale_salemanager,sf_production_process_group_sale_salemanager,model_sf_production_process,sf_base.group_sale_salemanager,1,0,0,0 - +access_res_partner_category_group_sale_salemanager,res_partner_category_group_sale_salemanager,base.model_res_partner_category,sf_base.group_sale_salemanager,1,0,1,0 +access_res_partner_category_group_sale_director,res_partner_category_group_sale_director,base.model_res_partner_category,sf_base.group_sale_director,1,0,1,0 access_sf_production_process,sf_production_process,model_sf_production_process,base.group_user,1,1,1,0 access_sf_production_process_admin,sf_production_process_admin,model_sf_production_process,base.group_system,1,1,1,0 access_sf_production_materials,sf_production_materials,model_sf_production_materials,base.group_user,1,1,1,0 diff --git a/sf_dlm/models/product_supplierinfo.py b/sf_dlm/models/product_supplierinfo.py index 4141a363..2784cba0 100644 --- a/sf_dlm/models/product_supplierinfo.py +++ b/sf_dlm/models/product_supplierinfo.py @@ -37,7 +37,7 @@ class ResMrpBomMo(models.Model): 'product_qty': 1, 'product_uom_id': 1 } - return self.env['mrp.bom.line'].create(vals) + return self.env['mrp.bom.line'].sudo().create(vals) # 业务平台分配工厂后在智能工厂先创建销售订单再创建该产品后再次进行创建bom def bom_create(self, product, bom_type, product_type): @@ -64,7 +64,7 @@ class ResMrpBomMo(models.Model): qty = 1 if round(embryo.volume * raw_bom_line.materials_type_id.density / 1000000) > 1: qty = round(embryo.volume * raw_bom_line.materials_type_id.density / 1000000) - bom_line = self.env['mrp.bom.line'].create({ + bom_line = self.env['mrp.bom.line'].sudo().create({ 'bom_id': self.id, 'product_id': raw_bom_line.id, 'product_tmpl_id': raw_bom_line.product_tmpl_id.id, diff --git a/sf_manufacturing/__manifest__.py b/sf_manufacturing/__manifest__.py index 1c49c88b..54538a7d 100644 --- a/sf_manufacturing/__manifest__.py +++ b/sf_manufacturing/__manifest__.py @@ -13,6 +13,7 @@ 'depends': ['sf_base', 'sf_maintenance', 'web_widget_model_viewer', 'sf_warehouse'], 'data': [ 'data/stock_data.xml', + 'data/empty_racks_data.xml', 'security/group_security.xml', 'security/ir.model.access.csv', 'wizard/workpiece_delivery_views.xml', diff --git a/sf_manufacturing/controllers/controllers.py b/sf_manufacturing/controllers/controllers.py index 1568f7c7..80ae21e7 100644 --- a/sf_manufacturing/controllers/controllers.py +++ b/sf_manufacturing/controllers/controllers.py @@ -8,7 +8,7 @@ from odoo.http import request class Manufacturing_Connect(http.Controller): - @http.route('/AutoDeviceApi/GetWoInfo', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False, + @http.route('/AutoDeviceApi/GetWoInfo', type='json', auth='none', methods=['GET', 'POST'], csrf=False, cors="*") def get_Work_Info(self, **kw): """ @@ -21,6 +21,8 @@ class Manufacturing_Connect(http.Controller): res = {'Succeed': True, 'Datas': []} datas = request.httprequest.data ret = json.loads(datas) + request.env['center_control.interface.log'].sudo().create( + {'content': ret, 'name': 'AutoDeviceApi/GetWoInfo'}) logging.info('RfidCode:%s' % ret['RfidCode']) if 'RfidCode' in ret: workorder = request.env['mrp.workorder'].sudo().search([('rfid_code', '=', ret['RfidCode'])]) @@ -60,6 +62,8 @@ class Manufacturing_Connect(http.Controller): res = {'Succeed': True, 'Datas': []} datas = request.httprequest.data ret = json.loads(datas) + request.env['center_control.interface.log'].sudo().create( + {'content': ret, 'name': 'AutoDeviceApi/GetShiftPlan'}) if 'ProductionLine' in ret: workorder_ids = request.env['mrp.workorder'].sudo().get_plan_workorder(ret['ProductionLine']) else: @@ -113,6 +117,8 @@ class Manufacturing_Connect(http.Controller): res = {'Succeed': True, 'Datas': []} datas = request.httprequest.data ret = json.loads(datas) + request.env['center_control.interface.log'].sudo().create( + {'content': ret, 'name': 'AutoDeviceApi/QcCheck'}) logging.info('RfidCode:%s' % ret['RfidCode']) if 'RfidCode' in ret: workorder = request.env['mrp.workorder'].sudo().search( @@ -150,6 +156,8 @@ class Manufacturing_Connect(http.Controller): res = {'Succeed': True, 'Datas': ['工单已开始']} datas = request.httprequest.data ret = json.loads(datas) + request.env['center_control.interface.log'].sudo().create( + {'content': ret, 'name': 'AutoDeviceApi/FeedBackStart'}) production_id = ret['BillId'] routing_type = ret['CraftId'] equipment_id = ret["DeviceId"] @@ -193,6 +201,8 @@ class Manufacturing_Connect(http.Controller): res = {'Succeed': True, 'Datas': ['工单已结束']} datas = request.httprequest.data ret = json.loads(datas) + request.env['center_control.interface.log'].sudo().create( + {'content': ret, 'name': 'AutoDeviceApi/FeedBackEnd'}) production_id = ret['BillId'] routing_type = ret['CraftId'] workorder = request.env['mrp.workorder'].sudo().search( @@ -237,6 +247,8 @@ class Manufacturing_Connect(http.Controller): res = {'Succeed': True} datas = request.httprequest.data ret = json.loads(datas) + request.env['center_control.interface.log'].sudo().create( + {'content': ret, 'name': 'AutoDeviceApi/PartQualityInspect'}) production_id = ret['BillId'] routing_type = ret['CraftId'] workorder = request.env['mrp.workorder'].sudo().search( @@ -293,6 +305,8 @@ class Manufacturing_Connect(http.Controller): res = {'Succeed': True, 'Datas': []} datas = request.httprequest.data ret = json.loads(datas) + request.env['center_control.interface.log'].sudo().create( + {'content': ret, 'name': 'AutoDeviceApi/CMMProgDolod'}) if 'RfidCode' in ret: logging.info('RfidCode:%s' % ret['RfidCode']) workorder = request.env['mrp.workorder'].sudo().search( @@ -331,6 +345,8 @@ class Manufacturing_Connect(http.Controller): res = {'Succeed': True, 'Datas': []} datas = request.httprequest.data ret = json.loads(datas) + request.env['center_control.interface.log'].sudo().create( + {'content': ret, 'name': 'AutoDeviceApi/NCProgDolod'}) if 'RfidCode' in ret: logging.info('RfidCode:%s' % ret['RfidCode']) workorder = request.env['mrp.workorder'].sudo().search( @@ -370,6 +386,8 @@ class Manufacturing_Connect(http.Controller): res = {'Succeed': True, 'Datas': []} datas = request.httprequest.data ret = json.loads(datas) + request.env['center_control.interface.log'].sudo().create( + {'content': ret, 'name': 'AutoDeviceApi/LocationChange'}) logging.info('LocationChange_ret===========:%s' % ret) RfidCode = ret['RfidCode'] ChangeType = ret['ChangeType'] @@ -426,11 +444,13 @@ class Manufacturing_Connect(http.Controller): res = {'Succeed': True} datas = request.httprequest.data ret = json.loads(datas) + request.env['center_control.interface.log'].sudo().create( + {'content': ret, 'name': 'AutoDeviceApi/AGVToProduct'}) logging.info('ret:%s' % ret) if 'DeviceId' in ret: logging.info('DeviceId:%s' % ret['DeviceId']) if 'IsComplete' in ret: - if ret['IsComplete'] is True: + if ret['IsComplete'] is True or ret['IsComplete'] is False: for i in range(1, 5): logging.info('F-RfidCode:%s' % i) if f'RfidCode{i}' in ret: @@ -477,12 +497,14 @@ class Manufacturing_Connect(http.Controller): res = {'Succeed': True} datas = request.httprequest.data ret = json.loads(datas) + request.env['center_control.interface.log'].sudo().create( + {'content': ret, 'name': 'AutoDeviceApi/AGVDownProduct'}) logging.info('ret:%s' % ret) if 'DeviceId' in ret: logging.info('DeviceId:%s' % ret['DeviceId']) delivery_Arr = [] if 'IsComplete' in ret: - if ret['IsComplete'] is True: + if ret['IsComplete'] is True or ret['IsComplete'] is False: for i in range(1, 5): logging.info('F-RfidCode:%s' % i) if f'RfidCode{i}' in ret: @@ -538,6 +560,8 @@ class Manufacturing_Connect(http.Controller): res = {'Succeed': True} datas = request.httprequest.data ret = json.loads(datas) + request.env['center_control.interface.log'].sudo().create( + {'content': ret, 'name': 'AutoDeviceApi/EquipmentBaseCoordinate'}) if 'DeviceId' in ret: equipment = request.env['maintenance.equipment'].sudo().search('name', '=', ret['DeviceId']) if equipment: diff --git a/sf_manufacturing/controllers/workpiece.py b/sf_manufacturing/controllers/workpiece.py index 8cda129b..5c5d6f22 100644 --- a/sf_manufacturing/controllers/workpiece.py +++ b/sf_manufacturing/controllers/workpiece.py @@ -28,7 +28,7 @@ class Workpiece(http.Controller): req_codes = ret['reqCode'].split(',') for req_code in req_codes: workpiece_delivery = request.env['sf.workpiece.delivery'].sudo().search( - [('delivery_num', '=', req_code.strip()), ('task_completion_time', '=', False)]) + [('name', '=', req_code.strip()), ('task_completion_time', '=', False)]) if workpiece_delivery: workpiece_delivery.write({'status': '已配送', 'task_completion_time': datetime.now()}) else: diff --git a/sf_manufacturing/data/empty_racks_data.xml b/sf_manufacturing/data/empty_racks_data.xml new file mode 100644 index 00000000..1a2b313b --- /dev/null +++ b/sf_manufacturing/data/empty_racks_data.xml @@ -0,0 +1,48 @@ + + + + + 工件配送 + sf.workpiece.delivery + WDO%(year)s%(month)s%(day)s + 4 + + + + + 运送空料架路线:C01-A01 + 运送空料架 + + + + + + + 运送空料架路线:B01-B02 + 运送空料架 + + + + + + + 运送空料架路线:B01-A01 + 运送空料架 + + + + + + + 运送空料架路线:C01-B02 + 运送空料架 + + + + + + \ No newline at end of file diff --git a/sf_manufacturing/models/agv_setting.py b/sf_manufacturing/models/agv_setting.py index dad6ec4f..d0104bc3 100644 --- a/sf_manufacturing/models/agv_setting.py +++ b/sf_manufacturing/models/agv_setting.py @@ -32,6 +32,8 @@ class AgvSetting(models.Model): if da['DeviceId'] == item.name: if da['AtHome'] is True: item.state = '占用' + else: + item.state = '空闲' class AgvTaskRoute(models.Model): @@ -40,15 +42,20 @@ class AgvTaskRoute(models.Model): name = fields.Char('名称') type = fields.Selection([ - ('F01', '搬运'), ], string='类型', default="F01") + ('F01', '搬运'), ], string='任务类型', default="F01") + route_type = fields.Selection([ + ('上产线', '上产线'), ('下产线', '下产线'), ('运送空料架', '运送空料架')], string='类型') start_site_id = fields.Many2one('sf.agv.site', '起点接驳站位置编号') end_site_id = fields.Many2one('sf.agv.site', '终点接驳站位置编号') destination_production_line_id = fields.Many2one('sf.production.line', '目的生产线') - priority = fields.Selection([ - ('0', '正常'), - ('1', '低'), - ('2', '中'), - ('3', '高'), - ('4', '紧急'), - ], string='优先级', default='0') + active = fields.Boolean('有效', default=True) + + +class Center_controlInterfaceLog(models.Model): + _name = 'center_control.interface.log' + _description = '中控接口调用日志' + + name = fields.Char('接口名称') + content = fields.Char('接口内容') + interface_call_date = fields.Datetime("调用时间", default=fields.Datetime.now, readonly=True) active = fields.Boolean('有效', default=True) diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py index 82588ffe..e2d6616a 100644 --- a/sf_manufacturing/models/mrp_production.py +++ b/sf_manufacturing/models/mrp_production.py @@ -56,8 +56,9 @@ class MrpProduction(models.Model): glb_file = fields.Binary("glb模型文件") production_line_id = fields.Many2one('sf.production.line', string='生产线') plan_start_processing_time = fields.Datetime('计划开始加工时间') - production_line_state = fields.Selection([('待上产线', '待上产线'), ('已上产线', '已上产线'), ('已下产线', '已下产线')], - string='上/下产线', default='待上产线') + production_line_state = fields.Selection( + [('待上产线', '待上产线'), ('已上产线', '已上产线'), ('已下产线', '已下产线')], + string='上/下产线', default='待上产线') # 工序状态 # Todo 研究下用法 process_state = fields.Selection([ @@ -114,7 +115,7 @@ class MrpProduction(models.Model): # production.state = 'pending_processing' production.state = 'pending_cam' if production.state == 'progress' and production.schedule_state == '已排' and production.process_state == '待加工': - # if production.state == 'pending_cam' and production.process_state == '待加工': + # if production.state == 'pending_cam' and production.process_state == '待加工': production.state = 'pending_processing' elif production.state == 'progress' and production.process_state == '待解除装夹': production.state = 'pending_era_cam' @@ -262,10 +263,14 @@ class MrpProduction(models.Model): # 其他规则限制: 默认只分配给工作中心状态为非故障的工作中心; def _create_workorder3(self): + programming_no = None + product_id_new = None for production in self: if not production.bom_id or not production.product_id: continue workorders_values = [] + if product_id_new is None: + product_id_new = production.product_id product_qty = production.product_uom_id._compute_quantity(production.product_qty, production.bom_id.product_uom_id) @@ -290,7 +295,14 @@ class MrpProduction(models.Model): 'state': 'pending', }] if production.product_id.categ_id.type == '成品': - production.fetchCNC() + if programming_no is None: + production.fetchCNC() + programming_no = production.programming_no + else: + if production.product_id == product_id_new: + if not production.programming_no: + production.write({'programming_no': programming_no, 'programming_state': '编程中'}) + # 根据加工面板的面数及对应的工序模板生成工单 i = 0 processing_panel_len = len(production.product_id.model_processing_panel.split(',')) diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index b32ffdce..817e6421 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -180,6 +180,11 @@ class ResMrpWorkOrder(models.Model): detection_report = fields.Binary('检测报告', readonly=True) is_remanufacture = fields.Boolean(string='是否重新生成制造订单', default=True) + @api.onchange('rfid_code') + def _onchange(self): + if self.rfid_code and self.state == 'progress': + self.workpiece_delivery_ids[0].write({'rfid_code': self.rfid_code}) + def get_plan_workorder(self, production_line): tomorrow = (date.today() + timedelta(days=+1)).strftime("%Y-%m-%d") tomorrow_start = tomorrow + ' 00:00:00' @@ -422,19 +427,22 @@ class ResMrpWorkOrder(models.Model): if not item.route_id: raise UserError('【工件配送】明细中请选择【任务路线】') else: - if item.is_cnc_program_down is True: - if item.status == '待下发': - return { - 'name': _('确认'), - 'type': 'ir.actions.act_window', - 'view_mode': 'form', - 'res_model': 'sf.workpiece.delivery.wizard', - 'target': 'new', - 'context': { - 'default_workorder_id': self.id, - }} + if self.state == 'done': + if item.is_cnc_program_down is True: + if item.status == '待下发': + return { + 'name': _('确认'), + 'type': 'ir.actions.act_window', + 'view_mode': 'form', + 'res_model': 'sf.workpiece.delivery.wizard', + 'target': 'new', + 'context': { + 'default_workorder_id': self.id, + }} + else: + raise UserError(_("该制造订单还未下发CNC程序单,无法进行工件配送")) else: - raise UserError(_("该制造订单还未下发CNC程序单,无法进行工件配送")) + raise UserError(_("该工单暂未完成,无法进行工件配送")) # 拼接工单对象属性值 def json_workorder_str(self, k, production, route): @@ -485,9 +493,8 @@ class ResMrpWorkOrder(models.Model): def _json_workpiece_delivery_list(self, production): return [ - [0, '', {'production_id': production.id, 'type': '上产线', 'delivery_num': '%s-%s' % (production.name, 1)}], - [0, '', - {'production_id': production.id, 'type': '下产线', 'delivery_num': '%s-%s' % (production.name, 2)}]] + [0, '', {'production_id': production.id, 'type': '上产线'}], + [0, '', {'production_id': production.id, 'type': '下产线'}]] # 拼接工单对象属性值(表面工艺) def _json_workorder_surface_process_str(self, production, route, process_parameter, supplier_id): @@ -632,6 +639,33 @@ class ResMrpWorkOrder(models.Model): # 'domain': [('production_id', '=', self.id)], # 'target':'new' # } + @api.depends('production_availability', 'blocked_by_workorder_ids', 'blocked_by_workorder_ids.state') + def _compute_state(self): + for workorder in self: + if workorder.routing_type == '装夹预调': + if not workorder.cnc_ids: + workorder.state = 'waiting' + else: + for item in workorder.cnc_ids: + functional_cutting_tool = self.env['sf.functional.cutting.tool.entity'].search( + [('tool_name_id.name', '=', item.cutting_tool_name)]) + if not functional_cutting_tool: + workorder.state = 'waiting' + if workorder.state == 'pending': + if all([wo.state in ('done', 'cancel') for wo in workorder.blocked_by_workorder_ids]): + workorder.state = 'ready' if workorder.production_id.reservation_state == 'assigned' else 'waiting' + continue + if workorder.state not in ('waiting', 'ready'): + continue + if not all([wo.state in ('done', 'cancel') for wo in workorder.blocked_by_workorder_ids]): + workorder.state = 'pending' + continue + if workorder.production_id.reservation_state not in ('waiting', 'confirmed', 'assigned'): + continue + if workorder.production_id.reservation_state == 'assigned' and workorder.state == 'waiting': + workorder.state = 'ready' + elif workorder.production_id.reservation_state != 'assigned' and workorder.state == 'ready': + workorder.state = 'waiting' def recreateManufacturingOrWorkerOrder(self): """ @@ -701,7 +735,18 @@ class ResMrpWorkOrder(models.Model): def button_start(self): if self.routing_type == '装夹预调' and self.production_id.move_raw_ids[0].move_line_ids[0].lot_id.name: self.pro_code = self.production_id.move_raw_ids[0].move_line_ids[0].lot_id.name - + if self.routing_type == '装夹预调': + cnc_workorder = self.search( + [('production_id', '=', self.production_id.id), ('routing_type', '=', 'CNC加工')], + limit=1, order='id asc') + if not cnc_workorder: + raise UserError(_('该制造订单还未下发CNC程序,请稍后再试')) + else: + for item in cnc_workorder.cnc_ids: + functional_cutting_tool = self.env['sf.functional.cutting.tool.entity'].search( + [('tool_name_id.name', '=', item.cutting_tool_name)]) + if not functional_cutting_tool: + raise UserError(_('该制造订单的CNC程序为%s没有对应的功能刀具' % item.cutting_tool_name)) if self.routing_type == '解除装夹': ''' 记录开始时间 @@ -919,6 +964,9 @@ class CNCprocessing(models.Model): if workpiece_delivery: for item in workpiece_delivery: item.is_cnc_program_down = True + if item.workorder_id.state == 'waiting': + item.workorder_id.state = 'ready' + # cnc_workorder.time_ids.date_end = datetime.now() # cnc_workorder.button_finish() @@ -1005,9 +1053,13 @@ class SfWorkOrderBarcodes(models.Model): workorder = self.env['mrp.workorder'].browse(self.ids) # workorder_preset = self.env['mrp.workorder'].search( # [('routing_type', '=', '装夹预调'), ('rfid_code', '=', barcode)]) - workorder_old = self.env['mrp.workorder'].search([('rfid_code', '=', barcode)]) - if workorder_old: - raise UserError('该托盘已绑定【%s】制造订单,请先解除绑定!!!' % workorder_old.production_id.name) + workorder_olds = self.env['mrp.workorder'].search( + [('routing_type', '=', '装夹预调'), ('rfid_code', '=', barcode)]) + if workorder_olds: + name = '' + for workorder in workorder_olds: + name = '%s %s' % (name, workorder.production_id.name) + raise UserError('该托盘已绑定【%s】制造订单,请先解除绑定!!!' % name) if workorder: if workorder.routing_type == '装夹预调': if workorder.state in ['done']: @@ -1035,6 +1087,8 @@ class SfWorkOrderBarcodes(models.Model): for item in workorder_rfid: item.write({'rfid_code': barcode}) logging.info("Rfid绑定成功!!!") + else: + raise UserError('该Rfid【%s】绑定的是【%s】, 不是托盘!!!' % (barcode, lot.product_id.name)) self.process_state = '待检测' self.date_start = datetime.now() else: @@ -1094,12 +1148,12 @@ class WorkPieceDelivery(models.Model): _name = "sf.workpiece.delivery" _description = '工件配送' - delivery_num = fields.Char('工件配送编码') + name = fields.Char('单据编号') workorder_id = fields.Many2one('mrp.workorder', string='工单', readonly=True) + workorder_state = fields.Selection(related='workorder_id.state', string='工单状态') + rfid_code = fields.Char(related='workorder_id.rfid_code', string='rfid码', store=True) production_id = fields.Many2one('mrp.production', string='制造订单号', readonly=True) - production_line_id = fields.Many2one('sf.production.line', compute='_compute_production_line_id', - string='目的生产线', readonly=True, - store=True) + production_line_id = fields.Many2one('sf.production.line', string='目的生产线') plan_start_processing_time = fields.Datetime('计划开始加工时间', readonly=True) route_id = fields.Many2one('sf.agv.task.route', '任务路线') @@ -1113,9 +1167,24 @@ class WorkPieceDelivery(models.Model): status = fields.Selection( [('待下发', '待下发'), ('待配送', '待配送'), ('已配送', '已配送')], string='状态', default='待下发') is_cnc_program_down = fields.Boolean('程序是否下发', default=False) + active = fields.Boolean(string="有效", default=True) - # @api.model - # def create(self, vals): + @api.model + def create(self, vals): + if vals.get('name', '/') == '/' or vals.get('name', '/') is False: + vals['name'] = self.env['ir.sequence'].next_by_code('sf.workpiece.delivery') or '/' + obj = super(WorkPieceDelivery, self).create(vals) + return obj + + def action_delivery_history(self): + return { + 'name': _('配送历史'), + 'type': 'ir.actions.act_window', + 'view_mode': 'tree', + 'res_model': 'sf.workpiece.delivery', + 'view_id': self.env.ref('sf_manufacturing.sf_workpiece_delivery_empty_racks_tree').id, + 'domain': [('type', '=', '运送空料架'), ('route_id', '=', self.route_id.id), ('name', 'ilike', 'WDO')] + } @api.onchange('route_id') def onchange_route(self): @@ -1126,6 +1195,7 @@ class WorkPieceDelivery(models.Model): # 工件配送 def button_delivery(self): delivery_ids = [] + production_ids = [] is_cnc_down = 0 is_not_production_line = 0 is_not_route = 0 @@ -1136,29 +1206,44 @@ class WorkPieceDelivery(models.Model): num = 0 for item in self: num += 1 - if num > 4: - raise UserError('仅限于配送1-4个制造订单,请重新选择') - if item.route_id: - if same_route_id is None: - same_route_id = item.route_id.id - if item.route_id.id != same_route_id: - is_not_route += 1 - else: - raise UserError('请选择【任务路线】再进行配送') if production_type is None: production_type = item.type - if production_type != item.type: - raise UserError('请选择类型为%s的制造订单进行配送' % production_type) - if down_status != item.status: - raise UserError('请选择状态为【待下发】的制造订单进行配送') - 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: - is_not_production_line += 1 - if item.is_cnc_program_down is False: - is_cnc_down += 1 - if is_cnc_down == 0 and is_not_production_line == 0 and is_not_route == 0: - delivery_ids.append(item.id) + if item.type == "运送空料架": + if num >= 2: + raise UserError('仅选择一条路线进行配送,请重新选择') + else: + delivery_ids.append(item.id) + else: + if num > 4: + raise UserError('仅限于配送1-4个制造订单,请重新选择') + if item.status in ['待配送', '已配送']: + raise UserError('请选择状态为【待下发】的制造订单进行配送') + if item.route_id: + if same_route_id is None: + same_route_id = item.route_id.id + if item.route_id.id != same_route_id: + is_not_route += 1 + else: + raise UserError('请选择【任务路线】再进行配送') + if production_type != item.type: + raise UserError('请选择类型为%s的制造订单进行配送' % production_type) + if down_status != item.status: + up_workpiece = self.search([('type', '=', '上产线'), ('production_id', '=', item.production_id), + ('status', '=', '待下发')]) + if up_workpiece: + raise UserError('您所选择的制造订单暂未上产线,请在上产线后再进行配送') + else: + raise UserError('请选择状态为【待下发】的制造订单进行配送') + + 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: + is_not_production_line += 1 + if item.is_cnc_program_down is False: + is_cnc_down += 1 + if is_cnc_down == 0 and is_not_production_line == 0 and is_not_route == 0: + delivery_ids.append(item.id) + production_ids.append(item.production_id.id) if is_cnc_down >= 1: raise UserError('您所选择制造订单的【CNC程序】暂未下发,请在程序下发后再进行配送') if is_not_production_line >= 1: @@ -1176,9 +1261,17 @@ class WorkPieceDelivery(models.Model): 'target': 'new', 'context': { 'default_delivery_ids': [(6, 0, delivery_ids)], + 'default_production_ids': [(6, 0, production_ids)], + 'default_destination_production_line_id': same_production_line_id, + 'default_route_id': same_route_id, + 'default_type': production_type, }} else: - raise UserError("您所选择制造订单的【任务路线】的【终点接驳站】已占用,请在该接驳站空闲时进行配送") + if self.type == '运送空料架': + raise UserError("您所选择的【任务路线】的【终点接驳站】已占用,请在该接驳站空闲时进行配送") + else: + raise UserError( + "您所选择制造订单的【任务路线】的【终点接驳站】已占用,请在该接驳站空闲时或选择其他路线进行配送") # 验证agv站点是否可用 def _check_avgsite_state(self): @@ -1187,15 +1280,18 @@ class WorkPieceDelivery(models.Model): if agv_site: agv_site.update_site_state() for item in self: - if item.type in ["上产线", "下产线"]: - logging.info('工件配送-起点状态:%s-%s' % ( - item.feeder_station_start_id.name, item.feeder_station_start_id.state)) - logging.info('工件配送-终点状态:%s-%s' % ( - item.feeder_station_destination_id.name, item.feeder_station_destination_id.state)) + logging.info('工件配送-起点状态:%s-%s' % ( + item.feeder_station_start_id.name, item.feeder_station_start_id.state)) + logging.info('工件配送-终点状态:%s-%s' % ( + item.feeder_station_destination_id.name, item.feeder_station_destination_id.state)) + if item.type in ['上产线', '下产线']: if ( item.feeder_station_start_id.state == '占用' and item.feeder_station_destination_id.state == '空闲') or ( item.feeder_station_start_id.state == '空闲' and item.feeder_station_destination_id.state == '空闲'): is_free = True + else: + if item.feeder_station_destination_id.state == '空闲': + is_free = True logging.info('is_free:%s' % is_free) return is_free @@ -1206,12 +1302,23 @@ class WorkPieceDelivery(models.Model): delivery_Arr = [] feeder_station_start = None feeder_station_destination = None + route_id = None for item in self: - if feeder_station_start is None: - feeder_station_start = item.feeder_station_start_id.name - if feeder_station_destination is None: - feeder_station_destination = item.feeder_station_destination_id.name - delivery_Arr.append(item.delivery_num) + delivery_Arr.append(item.name) + if item.type in ['上产线', '下产线']: + 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.name + if feeder_station_destination is None: + feeder_station_destination = item.feeder_station_destination_id.name + item.route_id = route_id + 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_str = ','.join(map(str, delivery_Arr)) if feeder_station_start is not None: positionCode_Arr.append({ @@ -1240,24 +1347,19 @@ class WorkPieceDelivery(models.Model): req_codes = ret['reqCode'].split(',') for delivery_item in self: for req_code in req_codes: - if delivery_item.delivery_num == req_code.strip(): - logging.info('delivery_num:%s' % delivery_item.delivery_num) + 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': '待配送' }) - delivery_item.workorder_id.write({'is_delivery': True}) + if delivery_item == "上产线": + 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失败") - - @api.onchange('production_id.production_line_id') - def _compute_production_line_id(self): - if self.production_id.production_line_id: - self.production_line_id = self.production_id.production_line_id.id - self.plan_start_processing_time = self.production_id.plan_start_processing_time + raise UserError("工件配送请求agv失败:%s" % e) @api.depends('task_delivery_time', 'task_completion_time') def _compute_delivery_duration(self): diff --git a/sf_manufacturing/models/product_template.py b/sf_manufacturing/models/product_template.py index 16ea429a..4d07ae1c 100644 --- a/sf_manufacturing/models/product_template.py +++ b/sf_manufacturing/models/product_template.py @@ -399,7 +399,7 @@ class ResProductMo(models.Model): cutting_speed_ids = fields.One2many('sf.cutting.speed', 'product_template_id', string='切削速度Vc') feed_per_tooth_ids = fields.One2many('sf.feed.per.tooth', 'product_template_id', string='每齿走刀量fz') - cutting_tool_diameter = fields.Float('直径(mm)') + cutting_tool_diameter = fields.Float('刀具直径(mm)') cutting_tool_rear_angle = fields.Integer('后角(°)') cutting_tool_main_included_angle = fields.Integer('主偏角(°)') # 适用夹头型号可以多选 diff --git a/sf_manufacturing/security/ir.model.access.csv b/sf_manufacturing/security/ir.model.access.csv index e8c2449c..1798ba27 100644 --- a/sf_manufacturing/security/ir.model.access.csv +++ b/sf_manufacturing/security/ir.model.access.csv @@ -52,8 +52,8 @@ access_mrp_bom_manager_group_sf_mrp_user,mrp.bom.manager,mrp.model_mrp_bom,sf_ba access_mrp_bom_line_manager_group_sf_mrp_user,mrp.bom.line.manager,mrp.model_mrp_bom_line,sf_base.group_sf_mrp_user,1,1,1,0 access_mrp_bom_line_group_plan_director,mrp_bom_line_group_plan_director,mrp.model_mrp_bom_line,sf_base.group_plan_director,1,1,1,0 access_mrp_bom_line_group_sale_director,mrp_bom_line_group_sale_director,mrp.model_mrp_bom_line,sf_base.group_sale_director,1,1,1,0 +access_mrp_bom_line_group_sale_salemanager,mrp_bom_line_group_sale_salemanager,mrp.model_mrp_bom_line,sf_base.group_sale_salemanager,1,0,1,0 access_mrp_bom_line_group_purchase_director,mrp_bom_line_group_purchase_director,mrp.model_mrp_bom_line,sf_base.group_purchase_director,1,1,1,0 - access_mrp_bom_byproduct_manager_group_sf_mrp_user,mrp.bom.byproduct manager,mrp.model_mrp_bom_byproduct,sf_base.group_sf_mrp_user,1,1,1,0 access_mrp_production_stock_worker,mrp.production stock_worker,mrp.model_mrp_production,stock.group_stock_user,1,0,0,0 access_product_product_user_group_sf_mrp_user,product.product user,product.model_product_product,sf_base.group_sf_mrp_user,1,0,0,0 @@ -132,4 +132,5 @@ access_maintenance_equipment_tool_group_plan_dispatch,maintenance.equipment.tool access_sf_workpiece_delivery_group_plan_dispatch,sf.workpiece.delivery,sf_manufacturing.model_sf_workpiece_delivery,sf_base.group_plan_dispatch,1,0,0,0 access_sf_agv_site_group_sf_order_user,sf_agv_site_group_sf_order_user,model_sf_agv_site,sf_base.group_sf_order_user,1,1,1,0 -access_sf_agv_task_route_group_sf_order_user,sf_agv_task_route_group_sf_order_user,model_sf_agv_task_route,sf_base.group_sf_order_user,1,1,1,0 \ No newline at end of file +access_sf_agv_task_route_group_sf_order_user,sf_agv_task_route_group_sf_order_user,model_sf_agv_task_route,sf_base.group_sf_order_user,1,1,1,0 +access_center_control_interface_log_admin,center_control_interface_log_admin,model_center_control_interface_log,base.group_system,1,1,1,0 \ No newline at end of file diff --git a/sf_manufacturing/views/agv_setting_views.xml b/sf_manufacturing/views/agv_setting_views.xml index 61b25e10..e8bd9f61 100644 --- a/sf_manufacturing/views/agv_setting_views.xml +++ b/sf_manufacturing/views/agv_setting_views.xml @@ -34,7 +34,8 @@ - + + @@ -54,4 +55,36 @@ sequence="13" action="action_agv_task_route_form"/> + + + + center_control.interface.log + + + + + + + + + + + center_control.interface.log + + + + + + + + + + + + 中控调用日志 + center_control.interface.log + tree + + \ No newline at end of file diff --git a/sf_manufacturing/views/mrp_production_addional_change.xml b/sf_manufacturing/views/mrp_production_addional_change.xml index 0e1695ef..c5616242 100644 --- a/sf_manufacturing/views/mrp_production_addional_change.xml +++ b/sf_manufacturing/views/mrp_production_addional_change.xml @@ -78,13 +78,14 @@ + - + @@ -258,6 +259,18 @@ + + product.template.search + product.template + + + + + + + + + sf.mrp.production.workorder.tree.editable @@ -380,7 +393,7 @@ diff --git a/sf_manufacturing/views/mrp_workorder_view.xml b/sf_manufacturing/views/mrp_workorder_view.xml index b3164055..7fdf390d 100644 --- a/sf_manufacturing/views/mrp_workorder_view.xml +++ b/sf_manufacturing/views/mrp_workorder_view.xml @@ -43,7 +43,7 @@ {'invisible': ['|',("user_permissions","=",False),("name","=","获取CNC加工程序")]} - + 1 @@ -111,36 +111,38 @@ - - - - - - - - - + + + + + + + + +