+ options="{'no_create': True}" attrs="{‘readonly': [('state', '=', '已拆解')]}"/>
@@ -807,76 +812,103 @@
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
diff --git a/sf_tool_management/views/tool_material_search.xml b/sf_tool_management/views/tool_material_search.xml
index ee63ba26..d4772244 100644
--- a/sf_tool_management/views/tool_material_search.xml
+++ b/sf_tool_management/views/tool_material_search.xml
@@ -94,12 +94,5 @@
sf.tool.material.search
tree,form
-
From 307e052740fc030efdabe01185210c97095489c3 Mon Sep 17 00:00:00 2001
From: "jinling.yang"
Date: Tue, 23 Apr 2024 14:05:10 +0800
Subject: [PATCH 03/10] =?UTF-8?q?=E4=BC=98=E5=8C=96agv=E5=8F=8A=E7=AB=99?=
=?UTF-8?q?=E7=82=B9=E4=BD=8D=E7=BD=AE=E5=92=8C=E5=AF=B9=E5=BA=94=E6=8E=A5?=
=?UTF-8?q?=E5=8F=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
sf_manufacturing/controllers/controllers.py | 20 +-
sf_manufacturing/controllers/workpiece.py | 5 +
sf_manufacturing/models/agv_setting.py | 19 +
sf_manufacturing/models/mrp_workorder.py | 703 +++++++++---------
sf_manufacturing/models/product_template.py | 4 +-
.../wizard/workpiece_delivery_views.xml | 11 +-
.../wizard/workpiece_delivery_wizard.py | 2 -
sf_mrs_connect/models/res_config_setting.py | 4 +
.../views/res_config_settings_views.xml | 4 +
sf_sale/models/quick_easy_order.py | 4 +-
sf_sale/models/quick_easy_order_old.py | 4 +-
.../models/maintenance_equipment.py | 10 +-
12 files changed, 411 insertions(+), 379 deletions(-)
diff --git a/sf_manufacturing/controllers/controllers.py b/sf_manufacturing/controllers/controllers.py
index b9cef58e..bbd9cac9 100644
--- a/sf_manufacturing/controllers/controllers.py
+++ b/sf_manufacturing/controllers/controllers.py
@@ -432,7 +432,7 @@ class Manufacturing_Connect(http.Controller):
logging.info('DeviceId:%s' % ret['DeviceId'])
workpiece_delivery = request.env['sf.workpiece.delivery'].sudo().search(
[('feeder_station_start_id.name', '=', ret['DeviceId']),
- ('status', '=', '待配送')], limit=1, order='id asc')
+ ('status', '=', '已配送'), ('type', '=', '上产线')], order='id asc')
if workpiece_delivery:
for wd in workpiece_delivery:
logging.info('wd.production_id:%s' % wd.production_id.name)
@@ -441,7 +441,7 @@ class Manufacturing_Connect(http.Controller):
wd.production_id.write({'production_line_state': '已上产线'})
wd.write({'production_line_state': '已上产线'})
else:
- res = {'Succeed': False, 'ErrorCode': 203, 'Error': '该DeviceId没有对应的工件配送数据'}
+ res = {'Succeed': False, 'ErrorCode': 203, 'Error': '该DeviceId没有对应的已配送工件数据'}
else:
res = {'Succeed': False, 'ErrorCode': 201, 'Error': '未传DeviceId字段'}
except Exception as e:
@@ -466,26 +466,16 @@ class Manufacturing_Connect(http.Controller):
if 'DeviceId' in ret:
logging.info('DeviceId:%s' % ret['DeviceId'])
workpiece_delivery = request.env['sf.workpiece.delivery'].sudo().search(
- [('feeder_station_destination_id.name', '=', ret['DeviceId']),
- ('status', '=', '待配送')], limit=1, order='id asc')
+ [('feeder_station_start_id.name', '=', ret['DeviceId']),
+ ('status', '=', '已配送'), ('type', '=', '上产线')], order='id asc')
if workpiece_delivery:
for wd in workpiece_delivery:
logging.info('wd.production_id:%s' % wd.production_id.name)
if wd.workorder_id.state == 'done' and wd.production_id.production_line_state == '已上产线':
logging.info('wd.production_line_state:%s' % wd.production_id.production_line_state)
- workpiece_delivery_off = request.env['sf.workpiece.delivery'].sudo().create({
- 'production_id': wd.production_id.id,
- 'feeder_station_start_id': workpiece_delivery.feeder_station_start_id.id,
- 'feeder_station_destination_id': '',
- 'workorder_id': workpiece_delivery.workorder_id.id,
- 'workpiece_code': workpiece_delivery.workpiece_code,
- 'production_line_id': workpiece_delivery.production_line_id.id,
- 'task_delivery_time': datetime.now(),
- 'production_line_state': '已下产线'
- })
wd.production_id.write({'production_line_state': '已下产线'})
logging.info('开始向agv下发下产线任务')
- workpiece_delivery_off._delivery_avg()
+ wd._delivery_avg()
logging.info('agv下发下产线任务已配送')
else:
diff --git a/sf_manufacturing/controllers/workpiece.py b/sf_manufacturing/controllers/workpiece.py
index fcdcf606..775da5a0 100644
--- a/sf_manufacturing/controllers/workpiece.py
+++ b/sf_manufacturing/controllers/workpiece.py
@@ -28,6 +28,11 @@ class Workpiece(http.Controller):
[('production_id.name', '=', ret['reqCode']), ('agv_task_code'), '=', ret['taskCode']])
if workpiece_delivery:
workpiece_delivery.write({'status': '已配送', 'task_completion_time': ret['reqTime']})
+ if workpiece_delivery.type == '下产线':
+ workpiece_delivery_clear = request.env['sf.workpiece.delivery'].sudo().search(
+ [('production_id.name', '=', ret['reqCode']), ('type', '=', '运送空料架')])
+ if workpiece_delivery_clear:
+ workpiece_delivery_clear._delivery_avg()
else:
res = {'Succeed': False, 'ErrorCode': 203, 'Error': '该reqCode暂未查到对应的工件配送记录'}
else:
diff --git a/sf_manufacturing/models/agv_setting.py b/sf_manufacturing/models/agv_setting.py
index 22c486d1..70075285 100644
--- a/sf_manufacturing/models/agv_setting.py
+++ b/sf_manufacturing/models/agv_setting.py
@@ -1,4 +1,6 @@
# -*- coding: utf-8 -*-
+import requests
+import logging
from odoo import fields, models
@@ -13,6 +15,23 @@ class AgvSetting(models.Model):
('占用', '占用'),
('空闲', '空闲')], string='状态')
divide_the_work = fields.Char('主要分工')
+ active = fields.Boolean('有效', default=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"
+ center_control_r = requests.get(center_control_url, params={}, headers=headers)
+ ret = center_control_r.json()
+ logging.info('工件配送-请求中控站点信息:%s' % ret)
+ datas = ret['Datas']
+ for item in self:
+ for da in datas:
+ if da['DeviceId'] == item.name:
+ if da['AtHome'] is True:
+ item.state = '占用'
class AgvTaskRoute(models.Model):
diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py
index ab520434..2184e7d1 100644
--- a/sf_manufacturing/models/mrp_workorder.py
+++ b/sf_manufacturing/models/mrp_workorder.py
@@ -458,360 +458,376 @@ class ResMrpWorkOrder(models.Model):
'date_planned_finished': False,
'duration_expected': duration_expected,
'duration': 0,
- 'workpiece_delivery_ids': False if not route.routing_type == '装夹预调' else self.env[
- 'sf.workpiece.delivery'].create(
- {'production_id': production.id})
+ 'workpiece_delivery_ids': False if not route.routing_type == '装夹预调' else self._json_workpiece_delivery_list(
+ production)
}]
return workorders_values_str
- # 拼接工单对象属性值(表面工艺)
- def _json_workorder_surface_process_str(self, production, route, process_parameter, supplier_id):
- workorders_values_str = [0, '', {
- 'product_uom_id': production.product_uom_id.id,
- 'qty_producing': 0,
- 'operation_id': False,
- 'name': '%s-%s' % (route.name, process_parameter.name),
- 'processing_panel': '',
- 'routing_type': '表面工艺',
- 'surface_technics_parameters_id': process_parameter.id,
- 'work_state': '',
- 'supplier_id': supplier_id,
- 'is_subcontract': True if process_parameter.gain_way == '外协' else False,
- 'workcenter_id': self.env[
- 'mrp.workcenter'].get_process_outsourcing_workcenter() if process_parameter.gain_way == '外协' else
- self.env['mrp.routing.workcenter'].get_workcenter(route.workcenter_ids.ids,
- route.routing_type,
- production.product_id),
- 'date_planned_start': False,
- 'date_planned_finished': False,
- 'duration_expected': 60,
- 'duration': 0
- }]
- return workorders_values_str
+ def _json_workpiece_delivery_list(self, production):
+ return [
+ [0, '', {'production_id': production.id, 'type': '上产线'}],
+ [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):
+ workorders_values_str = [0, '', {
+ 'product_uom_id': production.product_uom_id.id,
+ 'qty_producing': 0,
+ 'operation_id': False,
+ 'name': '%s-%s' % (route.name, process_parameter.name),
+ 'processing_panel': '',
+ 'routing_type': '表面工艺',
+ 'surface_technics_parameters_id': process_parameter.id,
+ 'work_state': '',
+ 'supplier_id': supplier_id,
+ 'is_subcontract': True if process_parameter.gain_way == '外协' else False,
+ 'workcenter_id': self.env[
+ 'mrp.workcenter'].get_process_outsourcing_workcenter() if process_parameter.gain_way == '外协' else
+ self.env['mrp.routing.workcenter'].get_workcenter(route.workcenter_ids.ids,
+ route.routing_type,
+ production.product_id),
+ 'date_planned_start': False,
+ 'date_planned_finished': False,
+ 'duration_expected': 60,
+ 'duration': 0
+ }]
+ return workorders_values_str
+
+
+# 维修模块按钮
+def button_maintenance_req(self):
+ self.ensure_one()
+ return {
+ 'name': _('New Maintenance Request'),
+ 'view_mode': 'form',
+ 'views': [(self.env.ref('mrp_maintenance.maintenance_request_view_form_inherit_mrp').id, 'form')],
+ 'res_model': 'maintenance.request',
+ 'type': 'ir.actions.act_window',
+ 'context': {
+ 'default_company_id': self.company_id.id,
+ 'default_workorder_id': self.id,
+ 'default_production_id': self.production_id.id,
+ 'discard_on_footer_button': True,
+ },
+ 'target': 'new',
+ 'domain': [('workorder_id', '=', self.id)]
+ }
+
+
+# tray_id = fields.Many2one('sf.tray', string="托盘信息", tracking=True)
+
+# 扫码绑定托盘方法
+
+# def gettray(self):
+# if self.tray_code != False:
+# values = self.env['sf.tray'].search([("code", "=", self.tray_code)])
+# if values:
+# if values.state == "占用":
+# raise UserError('该托盘已占用')
+# if values.state == "报损":
+# raise UserError('该托盘已损坏')
+# else:
+# values.update({
+# 'workorder_id': self,
+# 'production_id': self.production_id,
+# 'state': '占用',
+# })
+# self.work_state = "已绑定"
+# orders = self.env['mrp.workorder'].search([('production_id', '=', self.production_id.id)])
+# for a in orders:
+# a.tray_id = values
+# else:
+# raise UserError('该托盘编码已失效')
+# else:
+# raise UserError('托盘码不能为空')
+
+# 验证坯料序列号是否正确
+def pro_code_is_ok(self, barcode):
+ if barcode is not False:
+ if barcode != self.pro_code:
+ raise UserError('坯料序列号错误')
+ return False
+ else:
+ return True
+
+
+pro_code = fields.Char(string='坯料序列号')
+
+pro_code_ok = fields.Boolean(default=False)
+
+
+# 托盘扫码绑定
+# def gettray_auto(self, barcode):
+# if barcode != False:
+# values = self.env['sf.tray'].search([("code", "=", barcode)])
+#
+# if values:
+# if values.state == "占用":
+# raise UserError('该托盘已占用')
+# if values.state == "报损":
+# raise UserError('该托盘已损坏')
+# else:
+# values.update({
+# 'workorder_id': self,
+# 'production_id': self.production_id,
+# 'state': '占用',
+# })
+# self.work_state = "已绑定"
+# orders = self.env['mrp.workorder'].search([('production_id', '=', self.production_id.id)])
+# for a in orders:
+# a.tray_id = values
+#
+# return values
+#
+# # return {
+# # 'name': _('New Maintenance Request'),
+# # 'view_mode': 'form',
+# # 'res_model': 'maintenance.request',
+# # 'type': 'ir.actions.act_window',
+# # 'context': {
+# # 'default_company_id': self.company_id.id,
+# # 'default_production_id': self.id,
+# # },
+# # 'domain': [('production_id', '=', self.id)],
+# # }
+# else:
+# raise UserError('该托盘编码已失效')
+# else:
+# raise UserError('托盘码不能为空')
+
+# 解除托盘绑定
+# def unbindtray(self):
+# tray = self.env['sf.tray'].search([("production_id", "=", self.production_id.id)])
+# if tray:
+# tray.unclamp()
+# self.tray_id = False
+
+# return {
+# 'name': _('New Maintenance Request'),
+# 'view_mode': 'form',
+# 'res_model': 'maintenance.request',
+# 'res_id':self.id,
+# 'type': 'ir.actions.act_window',
+# 'context': {
+# 'default_company_id': self.company_id.id,
+# 'default_production_id': self.id,
+# },
+# 'domain': [('production_id', '=', self.id)],
+# 'target':'new'
+# }
+
+def recreateManufacturingOrWorkerOrder(self):
+ """
+ 重新生成制造订单或者重新生成工单
+ """
+ if self.test_results == '报废':
+ values = self.env['mrp.production'].create_production1_values(self.production_id)
+ productions = self.env['mrp.production'].with_user(SUPERUSER_ID).sudo().with_company(
+ self.production_id.company_id).create(
+ values)
+ self.env['stock.move'].sudo().create(productions._get_moves_raw_values())
+ self.env['stock.move'].sudo().create(productions._get_moves_finished_values())
+ productions._create_workorder()
+ productions.filtered(lambda p: (not p.orderpoint_id and p.move_raw_ids) or \
+ (
+ p.move_dest_ids.procure_method != 'make_to_order' and
+ not p.move_raw_ids and not p.workorder_ids)).action_confirm()
+
+ for production in productions:
+ origin_production = production.move_dest_ids and production.move_dest_ids[
+ 0].raw_material_production_id or False
+ orderpoint = production.orderpoint_id
+ if orderpoint and orderpoint.create_uid.id == SUPERUSER_ID and orderpoint.trigger == 'manual':
+ production.message_post(
+ body=_('This production order has been created from Replenishment Report.'),
+ message_type='comment',
+ subtype_xmlid='mail.mt_note')
+ elif orderpoint:
+ production.message_post_with_view(
+ 'mail.message_origin_link',
+ values={'self': production, 'origin': orderpoint},
+ subtype_id=self.env.ref('mail.mt_note').id)
+ elif origin_production:
+ production.message_post_with_view(
+ 'mail.message_origin_link',
+ values={'self': production, 'origin': origin_production},
+ subtype_id=self.env.ref('mail.mt_note').id)
+ if self.test_results == '返工':
+ productions = self.production_id
+ # self.env['stock.move'].sudo().create(productions._get_moves_raw_values())
+ # self.env['stock.move'].sudo().create(productions._get_moves_finished_values())
+ productions._create_workorder2(self.processing_panel)
+ else:
+ self.results = '合格'
+
+
+def json_workorder_str1(self, k, production, route):
+ workorders_values_str = [0, '', {
+ 'product_uom_id': production.product_uom_id.id,
+ 'qty_producing': 0,
+ 'operation_id': False,
+ 'name': '%s(返工)' % route.route_workcenter_id.name,
+ 'processing_panel': k,
+ 'routing_type': route.routing_type,
+ 'work_state': '' if not route.routing_type == '获取CNC加工程序' else '待发起',
+ 'workcenter_id': self.env['mrp.routing.workcenter'].get_workcenter(route.workcenter_ids.ids,
+ route.routing_type,
+ production.product_id),
+ 'date_planned_start': False,
+ 'date_planned_finished': False,
+ 'duration_expected': 60,
+ 'duration': 0,
+
+ }]
+ return workorders_values_str
+
+
+# 重写工单开始按钮方法
+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.is_subcontract is True:
+ picking_out = self.env['stock.picking'].search([('id', '=', self.picking_out_id.id)])
+ if picking_out.state == 'confirmed':
+ picking_out.write({'state': 'assigned'})
+ if self.state == 'waiting' or self.state == 'ready' or self.state == 'progress':
+ self.move_raw_ids = self.production_id.move_raw_ids
+ self.move_raw_ids[0].write({
+ 'materiel_length': self.move_raw_ids[0].product_id.length,
+ 'materiel_width': self.move_raw_ids[0].product_id.width,
+ 'materiel_height': self.move_raw_ids[0].product_id.height
+ })
- # 维修模块按钮
- def button_maintenance_req(self):
self.ensure_one()
- return {
- 'name': _('New Maintenance Request'),
- 'view_mode': 'form',
- 'views': [(self.env.ref('mrp_maintenance.maintenance_request_view_form_inherit_mrp').id, 'form')],
- 'res_model': 'maintenance.request',
- 'type': 'ir.actions.act_window',
- 'context': {
- 'default_company_id': self.company_id.id,
- 'default_workorder_id': self.id,
- 'default_production_id': self.production_id.id,
- 'discard_on_footer_button': True,
- },
- 'target': 'new',
- 'domain': [('workorder_id', '=', self.id)]
- }
+ if any(not time.date_end for time in self.time_ids.filtered(lambda t: t.user_id.id == self.env.user.id)):
+ return True
+ # As button_start is automatically called in the new view
+ if self.state in ('done', 'cancel'):
+ return True
- # tray_id = fields.Many2one('sf.tray', string="托盘信息", tracking=True)
-
- # 扫码绑定托盘方法
-
- # def gettray(self):
- # if self.tray_code != False:
- # values = self.env['sf.tray'].search([("code", "=", self.tray_code)])
- # if values:
- # if values.state == "占用":
- # raise UserError('该托盘已占用')
- # if values.state == "报损":
- # raise UserError('该托盘已损坏')
- # else:
- # values.update({
- # 'workorder_id': self,
- # 'production_id': self.production_id,
- # 'state': '占用',
- # })
- # self.work_state = "已绑定"
- # orders = self.env['mrp.workorder'].search([('production_id', '=', self.production_id.id)])
- # for a in orders:
- # a.tray_id = values
- # else:
- # raise UserError('该托盘编码已失效')
- # else:
- # raise UserError('托盘码不能为空')
-
- # 验证坯料序列号是否正确
- def pro_code_is_ok(self, barcode):
- if barcode is not False:
- if barcode != self.pro_code:
- raise UserError('坯料序列号错误')
- return False
- else:
- return True
-
- pro_code = fields.Char(string='坯料序列号')
-
- pro_code_ok = fields.Boolean(default=False)
-
- # 托盘扫码绑定
- # def gettray_auto(self, barcode):
- # if barcode != False:
- # values = self.env['sf.tray'].search([("code", "=", barcode)])
- #
- # if values:
- # if values.state == "占用":
- # raise UserError('该托盘已占用')
- # if values.state == "报损":
- # raise UserError('该托盘已损坏')
- # else:
- # values.update({
- # 'workorder_id': self,
- # 'production_id': self.production_id,
- # 'state': '占用',
- # })
- # self.work_state = "已绑定"
- # orders = self.env['mrp.workorder'].search([('production_id', '=', self.production_id.id)])
- # for a in orders:
- # a.tray_id = values
- #
- # return values
- #
- # # return {
- # # 'name': _('New Maintenance Request'),
- # # 'view_mode': 'form',
- # # 'res_model': 'maintenance.request',
- # # 'type': 'ir.actions.act_window',
- # # 'context': {
- # # 'default_company_id': self.company_id.id,
- # # 'default_production_id': self.id,
- # # },
- # # 'domain': [('production_id', '=', self.id)],
- # # }
- # else:
- # raise UserError('该托盘编码已失效')
- # else:
- # raise UserError('托盘码不能为空')
-
- # 解除托盘绑定
- # def unbindtray(self):
- # tray = self.env['sf.tray'].search([("production_id", "=", self.production_id.id)])
- # if tray:
- # tray.unclamp()
- # self.tray_id = False
-
- # return {
- # 'name': _('New Maintenance Request'),
- # 'view_mode': 'form',
- # 'res_model': 'maintenance.request',
- # 'res_id':self.id,
- # 'type': 'ir.actions.act_window',
- # 'context': {
- # 'default_company_id': self.company_id.id,
- # 'default_production_id': self.id,
- # },
- # 'domain': [('production_id', '=', self.id)],
- # 'target':'new'
- # }
-
- def recreateManufacturingOrWorkerOrder(self):
- """
- 重新生成制造订单或者重新生成工单
- """
- if self.test_results == '报废':
- values = self.env['mrp.production'].create_production1_values(self.production_id)
- productions = self.env['mrp.production'].with_user(SUPERUSER_ID).sudo().with_company(
- self.production_id.company_id).create(
- values)
- self.env['stock.move'].sudo().create(productions._get_moves_raw_values())
- self.env['stock.move'].sudo().create(productions._get_moves_finished_values())
- productions._create_workorder()
- productions.filtered(lambda p: (not p.orderpoint_id and p.move_raw_ids) or \
- (
- p.move_dest_ids.procure_method != 'make_to_order' and
- not p.move_raw_ids and not p.workorder_ids)).action_confirm()
-
- for production in productions:
- origin_production = production.move_dest_ids and production.move_dest_ids[
- 0].raw_material_production_id or False
- orderpoint = production.orderpoint_id
- if orderpoint and orderpoint.create_uid.id == SUPERUSER_ID and orderpoint.trigger == 'manual':
- production.message_post(
- body=_('This production order has been created from Replenishment Report.'),
- message_type='comment',
- subtype_xmlid='mail.mt_note')
- elif orderpoint:
- production.message_post_with_view(
- 'mail.message_origin_link',
- values={'self': production, 'origin': orderpoint},
- subtype_id=self.env.ref('mail.mt_note').id)
- elif origin_production:
- production.message_post_with_view(
- 'mail.message_origin_link',
- values={'self': production, 'origin': origin_production},
- subtype_id=self.env.ref('mail.mt_note').id)
- if self.test_results == '返工':
- productions = self.production_id
- # self.env['stock.move'].sudo().create(productions._get_moves_raw_values())
- # self.env['stock.move'].sudo().create(productions._get_moves_finished_values())
- productions._create_workorder2(self.processing_panel)
+ if self.product_tracking == 'serial':
+ self.qty_producing = 1.0
else:
- self.results = '合格'
+ self.qty_producing = self.qty_remaining
- def json_workorder_str1(self, k, production, route):
- workorders_values_str = [0, '', {
- 'product_uom_id': production.product_uom_id.id,
- 'qty_producing': 0,
- 'operation_id': False,
- 'name': '%s(返工)' % route.route_workcenter_id.name,
- 'processing_panel': k,
- 'routing_type': route.routing_type,
- 'work_state': '' if not route.routing_type == '获取CNC加工程序' else '待发起',
- 'workcenter_id': self.env['mrp.routing.workcenter'].get_workcenter(route.workcenter_ids.ids,
- route.routing_type,
- production.product_id),
- 'date_planned_start': False,
- 'date_planned_finished': False,
- 'duration_expected': 60,
- 'duration': 0,
-
- }]
- return workorders_values_str
-
- # 重写工单开始按钮方法
- 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.is_subcontract is True:
- picking_out = self.env['stock.picking'].search([('id', '=', self.picking_out_id.id)])
- if picking_out.state == 'confirmed':
- picking_out.write({'state': 'assigned'})
- if self.state == 'waiting' or self.state == 'ready' or self.state == 'progress':
- self.move_raw_ids = self.production_id.move_raw_ids
- self.move_raw_ids[0].write({
- 'materiel_length': self.move_raw_ids[0].product_id.length,
- 'materiel_width': self.move_raw_ids[0].product_id.width,
- 'materiel_height': self.move_raw_ids[0].product_id.height
+ self.env['mrp.workcenter.productivity'].create(
+ self._prepare_timeline_vals(self.duration, datetime.now())
+ )
+ if self.production_id.state != 'progress':
+ self.production_id.write({
+ 'date_start': datetime.now(),
})
-
- self.ensure_one()
- if any(not time.date_end for time in self.time_ids.filtered(lambda t: t.user_id.id == self.env.user.id)):
- return True
- # As button_start is automatically called in the new view
- if self.state in ('done', 'cancel'):
- return True
-
- if self.product_tracking == 'serial':
- self.qty_producing = 1.0
- else:
- self.qty_producing = self.qty_remaining
-
- self.env['mrp.workcenter.productivity'].create(
- self._prepare_timeline_vals(self.duration, datetime.now())
- )
- if self.production_id.state != 'progress':
- self.production_id.write({
- 'date_start': datetime.now(),
- })
- if self.state == 'progress':
- return True
- start_date = datetime.now()
- vals = {
- 'state': 'progress',
- 'date_start': start_date,
- }
- if not self.leave_id:
- leave = self.env['resource.calendar.leaves'].create({
- 'name': self.display_name,
- 'calendar_id': self.workcenter_id.resource_calendar_id.id,
- 'date_from': start_date,
- 'date_to': start_date + relativedelta(minutes=self.duration_expected),
- 'resource_id': self.workcenter_id.resource_id.id,
- 'time_type': 'other'
- })
- vals['leave_id'] = leave.id
- return self.write(vals)
- else:
- if self.date_planned_start > start_date:
- vals['date_planned_start'] = start_date
- if self.date_planned_finished and self.date_planned_finished < start_date:
- vals['date_planned_finished'] = start_date
- return self.write(vals)
+ if self.state == 'progress':
+ return True
+ start_date = datetime.now()
+ vals = {
+ 'state': 'progress',
+ 'date_start': start_date,
+ }
+ if not self.leave_id:
+ leave = self.env['resource.calendar.leaves'].create({
+ 'name': self.display_name,
+ 'calendar_id': self.workcenter_id.resource_calendar_id.id,
+ 'date_from': start_date,
+ 'date_to': start_date + relativedelta(minutes=self.duration_expected),
+ 'resource_id': self.workcenter_id.resource_id.id,
+ 'time_type': 'other'
+ })
+ vals['leave_id'] = leave.id
+ return self.write(vals)
else:
- raise UserError(_('请先完成上一步工单'))
+ if self.date_planned_start > start_date:
+ vals['date_planned_start'] = start_date
+ if self.date_planned_finished and self.date_planned_finished < start_date:
+ vals['date_planned_finished'] = start_date
+ return self.write(vals)
+ else:
+ raise UserError(_('请先完成上一步工单'))
- def button_finish(self):
- if self.routing_type == '装夹预调':
- if not self.material_center_point and self.X_deviation_angle > 0:
- raise UserError("请对前置三元检测定位参数进行计算定位")
- if not self.rfid_code:
- raise UserError("请扫RFID码进行绑定")
- if self.picking_out_id:
- picking_out = self.env['stock.picking'].search([('id', '=', self.picking_out_id.id)])
- if picking_out.workorder_out_id:
- order_line_ids = []
- for item in picking_out.workorder_out_id:
- server_product = self.env['product.template'].search(
- [('server_product_process_parameters_id', '=', item.surface_technics_parameters_id.id),
- ('detailed_type', '=', 'service')])
- if server_product:
- order_line_ids.append((0, 0, {
- 'product_id': server_product.product_variant_id.id,
- 'product_qty': 1,
- 'product_uom': server_product.uom_id.id
- }))
- else:
- raise UserError(
- '请先在产品中配置表面工艺为%s相关的外协服务产品' % item.surface_technics_parameters_id.name)
- self.env['purchase.order'].create({
- 'partner_id': server_product.seller_ids.partner_id.id,
- 'state': 'draft',
- 'order_line': order_line_ids,
- })
- super().button_finish()
- is_production_id = True
+
+def button_finish(self):
+ if self.routing_type == '装夹预调':
+ if not self.material_center_point and self.X_deviation_angle > 0:
+ raise UserError("请对前置三元检测定位参数进行计算定位")
+ if not self.rfid_code:
+ raise UserError("请扫RFID码进行绑定")
+ if self.picking_out_id:
+ picking_out = self.env['stock.picking'].search([('id', '=', self.picking_out_id.id)])
+ if picking_out.workorder_out_id:
+ order_line_ids = []
+ for item in picking_out.workorder_out_id:
+ server_product = self.env['product.template'].search(
+ [('server_product_process_parameters_id', '=', item.surface_technics_parameters_id.id),
+ ('detailed_type', '=', 'service')])
+ if server_product:
+ order_line_ids.append((0, 0, {
+ 'product_id': server_product.product_variant_id.id,
+ 'product_qty': 1,
+ 'product_uom': server_product.uom_id.id
+ }))
+ else:
+ raise UserError(
+ '请先在产品中配置表面工艺为%s相关的外协服务产品' % item.surface_technics_parameters_id.name)
+ self.env['purchase.order'].create({
+ 'partner_id': server_product.seller_ids.partner_id.id,
+ 'state': 'draft',
+ 'order_line': order_line_ids,
+ })
+ super().button_finish()
+ is_production_id = True
+ for workorder in self.production_id.workorder_ids:
+ if workorder.state != 'done':
+ is_production_id = False
+ if is_production_id == True and self.name == '解除装夹':
for workorder in self.production_id.workorder_ids:
- if workorder.state != 'done':
- is_production_id = False
- if is_production_id == True and self.name == '解除装夹':
- for workorder in self.production_id.workorder_ids:
- workorder.rfid_code_old = workorder.rfid_code
- workorder.rfid_code = None
- for move_raw_id in self.production_id.move_raw_ids:
- move_raw_id.quantity_done = move_raw_id.product_uom_qty
- self.production_id.button_mark_done1()
- # self.production_id.state = 'done'
+ workorder.rfid_code_old = workorder.rfid_code
+ workorder.rfid_code = None
+ for move_raw_id in self.production_id.move_raw_ids:
+ move_raw_id.quantity_done = move_raw_id.product_uom_qty
+ self.production_id.button_mark_done1()
+ # self.production_id.state = 'done'
- # 将FTP的检测报告文件下载到临时目录
- def download_reportfile_tmp(self, workorder, reportpath):
- logging.info('reportpath:%s' % reportpath)
- production_no_ftp = reportpath.split('/')
- production_no = workorder.production_id.name.replace('/', '_')
- # ftp地址
- remotepath = os.path.join('/NC', production_no_ftp[1], 'detection')
- logging.info('ftp地址:%s' % remotepath)
- if reportpath.find(production_no) != -1:
- # 服务器内临时地址
- serverdir = os.path.join('/tmp', production_no_ftp[1], 'detection')
- ftp_resconfig = self.env['res.config.settings'].get_values()
- ftp = FtpController(str(ftp_resconfig['ftp_host']), int(ftp_resconfig['ftp_port']),
- ftp_resconfig['ftp_user'],
- ftp_resconfig['ftp_password'])
- download_state = ftp.download_reportfile_tree(remotepath, serverdir, reportpath)
- logging.info('download_state:%s' % download_state)
- else:
- download_state = 2
- return download_state
- # 根据中控系统提供的检测文件地址去ftp里对应的制造订单里获取
- def get_detection_file(self, workorder, reportPath):
- if reportPath.startswith('/'):
- reportPath = reportPath[1:]
- serverdir = os.path.join('/tmp', reportPath)
- logging.info('get_detection_file-serverdir:%s' % serverdir)
- serverdir_prefix = os.path.dirname(serverdir)
- for root, dirs, files in os.walk(serverdir_prefix):
- for filename in files:
- if filename == os.path.basename(reportPath):
- report_file_path = os.path.join(root, filename)
- logging.info('get_detection_file-report_file_path:%s' % report_file_path)
- workorder.detection_report = base64.b64encode(open(report_file_path, 'rb').read())
- return True
+# 将FTP的检测报告文件下载到临时目录
+def download_reportfile_tmp(self, workorder, reportpath):
+ logging.info('reportpath:%s' % reportpath)
+ production_no_ftp = reportpath.split('/')
+ production_no = workorder.production_id.name.replace('/', '_')
+ # ftp地址
+ remotepath = os.path.join('/NC', production_no_ftp[1], 'detection')
+ logging.info('ftp地址:%s' % remotepath)
+ if reportpath.find(production_no) != -1:
+ # 服务器内临时地址
+ serverdir = os.path.join('/tmp', production_no_ftp[1], 'detection')
+ ftp_resconfig = self.env['res.config.settings'].get_values()
+ ftp = FtpController(str(ftp_resconfig['ftp_host']), int(ftp_resconfig['ftp_port']),
+ ftp_resconfig['ftp_user'],
+ ftp_resconfig['ftp_password'])
+ download_state = ftp.download_reportfile_tree(remotepath, serverdir, reportpath)
+ logging.info('download_state:%s' % download_state)
+ else:
+ download_state = 2
+ return download_state
+
+
+# 根据中控系统提供的检测文件地址去ftp里对应的制造订单里获取
+def get_detection_file(self, workorder, reportPath):
+ if reportPath.startswith('/'):
+ reportPath = reportPath[1:]
+ serverdir = os.path.join('/tmp', reportPath)
+ logging.info('get_detection_file-serverdir:%s' % serverdir)
+ serverdir_prefix = os.path.dirname(serverdir)
+ for root, dirs, files in os.walk(serverdir_prefix):
+ for filename in files:
+ if filename == os.path.basename(reportPath):
+ report_file_path = os.path.join(root, filename)
+ logging.info('get_detection_file-report_file_path:%s' % report_file_path)
+ workorder.detection_report = base64.b64encode(open(report_file_path, 'rb').read())
+ return True
class CNCprocessing(models.Model):
@@ -1084,6 +1100,8 @@ class WorkPieceDelivery(models.Model):
feeder_station_destination_id = fields.Many2one('sf.agv.site', '目的接驳站')
task_delivery_time = fields.Datetime('任务下发时间')
task_completion_time = fields.Datetime('任务完成时间')
+ type = fields.Selection(
+ [('上产线', '上产线'), ('下产线', '下产线'), ('运送空料架', '运送空料架')], string='类型')
delivery_duration = fields.Float('配送时长', compute='_compute_delivery_duration')
status = fields.Selection(
[('待下发', '待下发'), ('待配送', '待配送'), ('已配送', '已配送')], string='状态',
@@ -1124,6 +1142,9 @@ class WorkPieceDelivery(models.Model):
# 配送至avg小车
def _delivery_avg(self):
+ agv_site = self.env['sf.agv.site'].search([])
+ if agv_site:
+ agv_site.update_site_state()
config = self.env['res.config.settings'].get_values()
positionCode_Arr = []
if self.feeder_station_start_id:
@@ -1143,7 +1164,7 @@ class WorkPieceDelivery(models.Model):
'podDir': '', 'materialLot': '', 'priority': '', 'taskCode': '', 'agvCode': '', 'materialLot': '',
'data': ''}
try:
- config['agv_rcs_url'] = 'http://172.16.10.114:8182/rcms/services/rest/hikRpcService/genAgvSchedulingTask'
+ # config['agv_rcs_url'] = 'http://172.16.10.114:8182/rcms/services/rest/hikRpcService/genAgvSchedulingTask'
logging.info('AGV请求路径:%s' % config['agv_rcs_url'])
logging.info('AGV-json:%s' % res)
headers = {'Content-Type': 'application/json'}
diff --git a/sf_manufacturing/models/product_template.py b/sf_manufacturing/models/product_template.py
index d766629c..16ea429a 100644
--- a/sf_manufacturing/models/product_template.py
+++ b/sf_manufacturing/models/product_template.py
@@ -7,8 +7,8 @@ import os
from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
from odoo.modules import get_resource_path
-# from OCC.Extend.DataExchange import read_step_file
-# from OCC.Extend.DataExchange import write_stl_file
+from OCC.Extend.DataExchange import read_step_file
+from OCC.Extend.DataExchange import write_stl_file
class ResProductMo(models.Model):
diff --git a/sf_manufacturing/wizard/workpiece_delivery_views.xml b/sf_manufacturing/wizard/workpiece_delivery_views.xml
index 34625878..83cfb89f 100644
--- a/sf_manufacturing/wizard/workpiece_delivery_views.xml
+++ b/sf_manufacturing/wizard/workpiece_delivery_views.xml
@@ -5,18 +5,11 @@
sf.workpiece.delivery.wizard
diff --git a/sf_manufacturing/wizard/workpiece_delivery_wizard.py b/sf_manufacturing/wizard/workpiece_delivery_wizard.py
index 1de3e84c..ab7f4556 100644
--- a/sf_manufacturing/wizard/workpiece_delivery_wizard.py
+++ b/sf_manufacturing/wizard/workpiece_delivery_wizard.py
@@ -11,8 +11,6 @@ class WorkpieceDeliveryWizard(models.TransientModel):
delivery_id = fields.Many2one('sf.workpiece.delivery', string='配送')
workorder_id = fields.Many2one('mrp.workorder', string='工单')
- route_id = fields.Many2one('sf.agv.task.route', '任务路线')
- is_ok = fields.Boolean('确认上述信息正确无误.')
def confirm(self):
if self.workorder_id:
diff --git a/sf_mrs_connect/models/res_config_setting.py b/sf_mrs_connect/models/res_config_setting.py
index ef2d93d8..035b10a0 100644
--- a/sf_mrs_connect/models/res_config_setting.py
+++ b/sf_mrs_connect/models/res_config_setting.py
@@ -17,6 +17,7 @@ class ResConfigSettings(models.TransientModel):
default='http://172.16.10.114:8182/rcms/services/rest/hikRpcService/genAgvSchedulingTask')
center_control_url = fields.Char(string='中控访问地址',
default='http://172.16.21.50:8001')
+ center_control_Authorization = fields.Char(string='中控访问认证')
wbcode = fields.Char('地码')
agv_code = fields.Char(string='agv编号')
task_type_no = fields.Char('任务单类型编号')
@@ -102,6 +103,7 @@ class ResConfigSettings(models.TransientModel):
wbcode = config.get_param('wbcode', default='')
agv_code = config.get_param('agv_code', default='')
center_control_url = config.get_param('center_control_url', default='')
+ center_control_Authorization = config.get_param('center_control_Authorization', default='')
ftp_host = config.get_param('ftp_host', default='')
ftp_port = config.get_param('ftp_port', default='')
ftp_user = config.get_param('ftp_user', default='')
@@ -115,6 +117,7 @@ class ResConfigSettings(models.TransientModel):
wbcode=wbcode,
agv_code=agv_code,
center_control_url=center_control_url,
+ center_control_Authorization=center_control_Authorization,
ftp_host=ftp_host,
ftp_port=ftp_port,
ftp_user=ftp_user,
@@ -132,6 +135,7 @@ class ResConfigSettings(models.TransientModel):
ir_config.set_param("wbcode", self.wbcode or "")
ir_config.set_param("agv_code", self.agv_code or "")
ir_config.set_param("center_control_url", self.center_control_url or "")
+ ir_config.set_param("center_control_Authorization", self.center_control_Authorization or "")
ir_config.set_param("ftp_host", self.ftp_host or "")
ir_config.set_param("ftp_port", self.ftp_port or "")
ir_config.set_param("ftp_user", self.ftp_user or "")
diff --git a/sf_mrs_connect/views/res_config_settings_views.xml b/sf_mrs_connect/views/res_config_settings_views.xml
index 0d1ccc3e..2be92365 100644
--- a/sf_mrs_connect/views/res_config_settings_views.xml
+++ b/sf_mrs_connect/views/res_config_settings_views.xml
@@ -106,6 +106,10 @@
+
+
+
+
diff --git a/sf_sale/models/quick_easy_order.py b/sf_sale/models/quick_easy_order.py
index ed52d9de..1ece6b86 100644
--- a/sf_sale/models/quick_easy_order.py
+++ b/sf_sale/models/quick_easy_order.py
@@ -8,8 +8,8 @@ from datetime import datetime
import requests
from odoo import http
from odoo.http import request
-# from OCC.Extend.DataExchange import read_step_file
-# from OCC.Extend.DataExchange import write_stl_file
+from OCC.Extend.DataExchange import read_step_file
+from OCC.Extend.DataExchange import write_stl_file
from odoo import models, fields, api
from odoo.modules import get_resource_path
from odoo.exceptions import ValidationError, UserError
diff --git a/sf_sale/models/quick_easy_order_old.py b/sf_sale/models/quick_easy_order_old.py
index 24bf5738..724d4369 100644
--- a/sf_sale/models/quick_easy_order_old.py
+++ b/sf_sale/models/quick_easy_order_old.py
@@ -6,8 +6,8 @@ import os
from datetime import datetime
from stl import mesh
# from OCC.Core.GProp import GProp_GProps
-# from OCC.Extend.DataExchange import read_step_file
-# from OCC.Extend.DataExchange import write_stl_file
+from OCC.Extend.DataExchange import read_step_file
+from OCC.Extend.DataExchange import write_stl_file
from odoo.addons.sf_base.commons.common import Common
from odoo import models, fields, api
from odoo.modules import get_resource_path
diff --git a/sf_tool_management/models/maintenance_equipment.py b/sf_tool_management/models/maintenance_equipment.py
index d39dc685..9932d135 100644
--- a/sf_tool_management/models/maintenance_equipment.py
+++ b/sf_tool_management/models/maintenance_equipment.py
@@ -43,12 +43,10 @@ class SfMaintenanceEquipment(models.Model):
# ==========机床当前刀库实时信息接口==========
def register_equipment_tool(self):
- # sf_sync_config = self.env['res.config.settings'].get_values()
- # token = sf_sync_config['token']
- # sf_secret_key = sf_sync_config['sf_secret_key']
- # headers = Common.get_headers(self, token, sf_secret_key)
- headers = {'Authorization': 'Ba F2CF5DCC-1A00-4234-9E95-65603F70CC8A'}
- crea_url = "https://x24467i973.zicp.fun/AutoDeviceApi/GetToolInfos"
+ 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']}
+ crea_url = config['center_control_url'] + "/AutoDeviceApi/GetToolInfos"
params = {"DeviceId": self.name}
r = requests.get(crea_url, params=params, headers=headers)
ret = r.json()
From 8bc23f5136a4063db6abcedefd8d8ca2f2c0cb8d Mon Sep 17 00:00:00 2001
From: yuxianghui <3437689193@qq.com>
Date: Tue, 23 Apr 2024 14:15:45 +0800
Subject: [PATCH 04/10] =?UTF-8?q?1=E3=80=81=E4=BC=98=E5=8C=96=E5=8A=9F?=
=?UTF-8?q?=E8=83=BD=E5=88=80=E5=85=B7=E6=8B=86=E8=A7=A3=E5=8D=95=E6=8B=86?=
=?UTF-8?q?=E8=A7=A3=E5=8E=9F=E5=9B=A0=E4=B8=BA=E6=9B=B4=E6=8D=A2=E5=85=B6?=
=?UTF-8?q?=E4=BB=96=E5=88=80=E5=85=B7=E6=97=B6=E7=9A=84=E6=89=AB=E7=A0=81?=
=?UTF-8?q?=E5=BD=95=E5=85=A5=E5=88=80=E5=85=B7=E7=89=A9=E6=96=99=E8=B4=A7?=
=?UTF-8?q?=E4=BD=8D=E4=BF=A1=E6=81=AF=E5=8A=9F=E8=83=BD=EF=BC=9B2?=
=?UTF-8?q?=E3=80=81=E4=BC=98=E5=8C=96=E5=8A=9F=E8=83=BD=E5=88=80=E5=85=B7?=
=?UTF-8?q?=E6=8B=86=E8=A7=A3=E5=8D=95=E7=A1=AE=E8=AE=A4=E6=8B=86=E8=A7=A3?=
=?UTF-8?q?=E5=90=8E=E7=9A=84=E5=88=80=E5=85=B7=E7=89=A9=E6=96=99=E6=8B=86?=
=?UTF-8?q?=E8=A7=A3=E6=B5=81=E7=A8=8B=EF=BC=8C=E5=8F=8A=E5=85=B6=E5=88=80?=
=?UTF-8?q?=E5=85=B7=E7=89=A9=E6=96=99=E5=8A=9F=E8=83=BD=E5=88=80=E5=85=B7?=
=?UTF-8?q?=E7=9A=84=E6=95=B0=E9=87=8F=E7=BB=9F=E8=AE=A1=E7=AD=89=EF=BC=9B?=
=?UTF-8?q?3=E3=80=81=E5=8A=9F=E8=83=BD=E5=88=80=E5=85=B7=E6=8B=86?=
=?UTF-8?q?=E8=A7=A3=E3=80=81=E5=8A=9F=E8=83=BD=E5=88=80=E5=85=B7=E6=A8=A1?=
=?UTF-8?q?=E5=9D=97=E6=B7=BB=E5=8A=A0=E5=8A=A8=E4=BD=9C=E8=BF=87=E6=BB=A4?=
=?UTF-8?q?=E5=B7=B2=E6=8B=86=E8=A7=A3=E7=8A=B6=E6=80=81=E7=9A=84=E8=AE=B0?=
=?UTF-8?q?=E5=BD=95=EF=BC=8C=E5=B9=B6=E6=B7=BB=E5=8A=A0=E7=AD=9B=E9=80=89?=
=?UTF-8?q?=E6=96=B9=E6=B3=95=EF=BC=9B4=E3=80=81=E5=8A=9F=E8=83=BD?=
=?UTF-8?q?=E5=88=80=E5=85=B7=E7=BB=84=E8=A3=85=E6=B5=81=E7=A8=8B=E6=B7=BB?=
=?UTF-8?q?=E5=8A=A0=E5=88=80=E5=85=B7=E7=89=A9=E6=96=99=E8=B4=A7=E4=BD=8D?=
=?UTF-8?q?=E6=95=B0=E9=87=8F=E6=A0=A1=E9=AA=8C=EF=BC=9B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
sf_tool_management/models/base.py | 79 +++++++++++++------
sf_tool_management/models/functional_tool.py | 11 ++-
.../models/maintenance_equipment.py | 2 +
.../models/tool_material_search.py | 4 +-
.../views/functional_tool_views.xml | 10 ++-
sf_tool_management/views/tool_base_views.xml | 31 +++++---
sf_tool_management/wizard/wizard.py | 35 ++++----
sf_tool_management/wizard/wizard_view.xml | 2 +-
8 files changed, 114 insertions(+), 60 deletions(-)
diff --git a/sf_tool_management/models/base.py b/sf_tool_management/models/base.py
index 350658a4..43baaab5 100644
--- a/sf_tool_management/models/base.py
+++ b/sf_tool_management/models/base.py
@@ -647,33 +647,56 @@ class FunctionalToolDismantle(models.Model):
"""
# 对barcode进行校验是否为货位编码
if not re.match(r'^[A-Za-z0-9]+-[A-Za-z0-9]+-\d{3}-\d{3}$', barcode):
- tool_id = self.env['sf.functional.cutting.tool.entity'].sudo().search([('rfid', '=', barcode)])
+ tool_id = self.env['sf.functional.cutting.tool.entity'].sudo().search(
+ [('rfid', '=', barcode), ('functional_tool_status', '!=', '已拆除')])
if tool_id:
self.functional_tool_id = tool_id.id
else:
raise ValidationError('Rfid为【%s】的功能刀具不存在,请重新扫描!' % barcode)
else:
- location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', barcode)])
- if not location:
- raise ValidationError('【%s】该货位不存在,请重新扫码!' % barcode)
- else:
- # 判断是否有夹头物料
- if not self.chuck_product_id:
- # 判断是否有整体式刀具物料
- if self.integral_product_id:
- # 判断货位是否为空货位 或者 是存有整体式刀具的货位
- if location.product_id in [False, self.integral_product_id]:
- self.integral_freight_id = location.id
- else:
- raise ValidationError('【%s】该货位已存在【%s】产品,请重新扫码!' % location.barcode,
- location.product_id.name)
- # 判断是否有刀片物料
- elif self.blade_product_id:
- # 判断是否有刀杆物料
- if self.bar_product_id:
- pass
+ if self.dismantle_cause == '更换为其他刀具':
+ location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', barcode)])
+ if not location:
+ raise ValidationError('【%s】该货位不存在,请重新扫码!' % barcode)
else:
- pass
+ if not location.product_id:
+ # 判断功能刀具存在哪些刀具物料需要录入库位
+ if self.chuck_product_id: # 夹头
+ if not self.chuck_freight_id:
+ self.chuck_freight_id = location.id
+ return True
+ if self.integral_product_id: # 整体式刀具
+ if not self.integral_freight_id:
+ self.integral_freight_id = location.id
+ return True
+ elif self.blade_product_id: # 刀片
+ if not self.blade_freight_id:
+ self.blade_freight_id = location.id
+ return True
+ if self.bar_product_id: # 刀杆
+ if not self.bar_freight_id:
+ self.bar_freight_id = location.id
+ return True
+ elif self.pad_product_id: # 刀盘
+ if not self.pad_freight_id:
+ self.pad_freight_id = location.id
+ return True
+ else:
+ # 判断货位存放的是那个刀具物料产品
+ if self.integral_product_id == location.product_id: # 整体式刀具
+ self.integral_freight_id = location.id
+ elif self.blade_product_id == location.product_id: # 刀片
+ self.blade_freight_id = location.id
+ elif self.bar_product_id == location.product_id: # 刀杆
+ self.bar_freight_id = location.id
+ elif self.pad_product_id == location.product_id: # 刀盘
+ self.pad_freight_id = location.id
+ elif self.chuck_product_id == location.product_id: # 夹头
+ self.chuck_freight_id = location.id
+ elif self.dismantle_cause in ['寿命到期报废', '崩刀报废']:
+ raise ValidationError('该功能刀具因为%s拆解,无需录入库位' % self.dismantle_cause)
+ else:
+ raise ValidationError('该功能刀具因为%s拆解,无需录入库位' % self.dismantle_cause)
name = fields.Char('名称', related='functional_tool_id.name')
@@ -698,6 +721,7 @@ class FunctionalToolDismantle(models.Model):
grinding_id = fields.Char('磨削单号', readonly=True)
state = fields.Selection([('待拆解', '待拆解'), ('已拆解', '已拆解')], default='待拆解')
+ active = fields.Boolean('有效', default=True)
# 刀柄
handle_product_id = fields.Many2one('product.product', string='刀柄', compute='_compute_functional_tool_num',
@@ -787,22 +811,24 @@ class FunctionalToolDismantle(models.Model):
item.chuck_product_id = False
def confirmation_disassembly(self):
- logging.info('%s刀具确认拆解' % self.dismantle_cause)
+ logging.info('%s刀具确认开始拆解' % self.dismantle_cause)
+ if self.functional_tool_id.functional_tool_status == '已拆除':
+ raise ValidationError('Rfid为【%s】的功能刀具已经拆解,请勿重复操作!' % self.functional_tool_id.rfid_dismantle)
location = self.env['stock.location'].search([('name', '=', '刀具组装位置')])
location_dest = self.env['stock.location'].search([('name', '=', '刀具房')])
# =================刀柄是否报废拆解=======
location_dest_scrap = self.env['stock.location'].search([('name', '=', 'Scrap')])
if self.handle_rfid:
- lot = self.env['stock.lot'].sudo().search([('name', '=', self.handle_rfid)])
+ lot = self.env['stock.lot'].sudo().search([('rfid', '=', self.handle_rfid)])
functional_tool_assembly = self.functional_tool_id.functional_tool_name_id
if self.scrap_boolean:
# 刀柄报废 入库到Scrap
lot.create_stock_quant(location, location_dest_scrap, functional_tool_assembly.id, '功能刀具拆解',
- functional_tool_assembly)
+ functional_tool_assembly, functional_tool_assembly.tool_groups_id)
else:
# 刀柄不报废 入库到刀具房
lot.create_stock_quant(location, location_dest, functional_tool_assembly.id, '功能刀具拆解',
- functional_tool_assembly)
+ functional_tool_assembly, functional_tool_assembly.tool_groups_id)
# ==============功能刀具报废拆解================
if self.dismantle_cause in ['寿命到期报废', '崩刀报废']:
# 除刀柄外物料报废 入库到Scrap
@@ -853,9 +879,12 @@ class FunctionalToolDismantle(models.Model):
# 修改拆解单的值
self.write({
'rfid_dismantle': self.rfid,
+ 'dismantle_data': fields.Datetime.now(),
+ 'dismantle_person': self.env.user.name,
'rfid': '',
'state': '已拆解'
})
+ logging.info('刀具拆解成功!')
class ProductProduct(models.Model):
diff --git a/sf_tool_management/models/functional_tool.py b/sf_tool_management/models/functional_tool.py
index d4718f34..eae00080 100644
--- a/sf_tool_management/models/functional_tool.py
+++ b/sf_tool_management/models/functional_tool.py
@@ -45,7 +45,7 @@ class FunctionalCuttingToolEntity(models.Model):
active = fields.Boolean(string='已归档', default=True)
- @api.depends('barcode_id.quant_ids')
+ @api.depends('barcode_id.quant_ids', 'functional_tool_status')
def _compute_current_location_id(self):
for record in self:
if record.barcode_id.quant_ids:
@@ -61,6 +61,12 @@ class FunctionalCuttingToolEntity(models.Model):
else:
record.current_location_id = False
record.current_location = False
+ if record.functional_tool_status == '已拆除':
+ record.current_location_id = False
+ record.current_location = False
+ record.tool_room_num = 0
+ record.line_edge_knife_library_num = 0
+ record.machine_knife_library_num = 0
def get_location_num(self):
"""
@@ -185,7 +191,8 @@ class FunctionalCuttingToolEntity(models.Model):
stock_location_id = self.env['stock.location'].search([('name', '=', '制造前')])
# 创建功能刀具该批次/序列号 库存移动和移动历史
self.barcode_id.create_stock_quant(location_inventory_id, stock_location_id,
- self.functional_tool_name_id.id, '机床装刀', self.functional_tool_name_id)
+ self.functional_tool_name_id.id, '机床装刀', self.functional_tool_name_id,
+ self.functional_tool_name_id.tool_groups_id)
# ==========刀具组接口==========
# def _register_functional_tool_groups(self, obj):
diff --git a/sf_tool_management/models/maintenance_equipment.py b/sf_tool_management/models/maintenance_equipment.py
index d39dc685..4452f768 100644
--- a/sf_tool_management/models/maintenance_equipment.py
+++ b/sf_tool_management/models/maintenance_equipment.py
@@ -112,6 +112,8 @@ class StockLot(models.Model):
record.tool_material_status = '可用'
elif record.quant_ids[-1].location_id.name == '刀具组装位置':
record.tool_material_status = '在用'
+ elif record.quant_ids[-1].location_id.name == 'Scrap':
+ record.tool_material_status = '报废'
else:
record.tool_material_status = '未入库'
if record.tool_material_search_id:
diff --git a/sf_tool_management/models/tool_material_search.py b/sf_tool_management/models/tool_material_search.py
index bfb8d64b..ee60c048 100644
--- a/sf_tool_management/models/tool_material_search.py
+++ b/sf_tool_management/models/tool_material_search.py
@@ -39,9 +39,7 @@ class ToolMaterial(models.Model):
usable_num += quant.quantity
elif location == '刀具组装位置':
have_been_used_num += quant.quantity
- elif location == '进货':
- pass
- elif location != 'Vendors':
+ elif location == 'Scrap':
scrap_num += quant.quantity
record.usable_num = usable_num
record.have_been_used_num = have_been_used_num
diff --git a/sf_tool_management/views/functional_tool_views.xml b/sf_tool_management/views/functional_tool_views.xml
index 82fbd8bc..53e050d9 100644
--- a/sf_tool_management/views/functional_tool_views.xml
+++ b/sf_tool_management/views/functional_tool_views.xml
@@ -85,7 +85,10 @@
-
+
+
@@ -202,6 +205,9 @@
+
+
+
@@ -218,6 +224,8 @@
sf.functional.cutting.tool.entity
tree,form,search
+
+ {'search_default_no_state_removed':1}
diff --git a/sf_tool_management/views/tool_base_views.xml b/sf_tool_management/views/tool_base_views.xml
index 944decd2..1db89ddb 100644
--- a/sf_tool_management/views/tool_base_views.xml
+++ b/sf_tool_management/views/tool_base_views.xml
@@ -783,6 +783,7 @@
+
@@ -794,20 +795,21 @@