diff --git a/sf_manufacturing/controllers/controllers.py b/sf_manufacturing/controllers/controllers.py
index 84ee9f46..6319c050 100644
--- a/sf_manufacturing/controllers/controllers.py
+++ b/sf_manufacturing/controllers/controllers.py
@@ -388,7 +388,7 @@ class Manufacturing_Connect(http.Controller):
ret = json.loads(datas)
request.env['center_control.interface.log'].sudo().create(
{'content': ret, 'name': 'AutoDeviceApi/LocationChange'})
- logging.info('LocationChange_ret===========:%s' % ret)
+ logging.info('库位变更LocationChange_ret:%s' % ret)
RfidCode = ret['RfidCode']
ChangeType = ret['ChangeType']
OldDeciveId = ret['OldDeciveId']
@@ -398,34 +398,79 @@ class Manufacturing_Connect(http.Controller):
OldDeciveStart = ret['OldDeciveStart']
OldDeciveEnd = ret['OldDeciveEnd']
- temp_val_sn_id = None
- old_localtion = None
- # if ChangeType == 'Part' or ChangeType == 'Tool':
- stock_lot_obj = request.env['stock.lot'].sudo().search(
- [('rfid', '=', RfidCode)], limit=1)
- logging.info('stock_lot_obj===========:%s' % stock_lot_obj)
- if not stock_lot_obj:
- res = {'Succeed': False, 'ErrorCode': 202, 'Error': '未根据RfidCode找到该产品'}
- return json.JSONEncoder().encode(res)
- if OldPosition:
- old_localtion = request.env['sf.shelf.location'].sudo().search(
- [('barcode', '=', OldPosition)], limit=1)
- logging.info('old_localtion===========:%s' % old_localtion)
- new_localtion = request.env['sf.shelf.location'].sudo().search(
- [('barcode', '=', NewPosition)], limit=1)
- logging.info('new_localtion===========:%s' % new_localtion)
- if not new_localtion:
- res = {'Succeed': False, 'ErrorCode': 202, 'Error': '没有该目标位置'}
- return json.JSONEncoder().encode(res)
- if old_localtion:
- temp_val_sn_id = old_localtion.product_sn_id
- logging.info('temp_val_sn_id===========:%s' % temp_val_sn_id)
- old_localtion.product_sn_id = None
- new_localtion.product_sn_id = temp_val_sn_id
- logging.info('====1======')
- else:
- new_localtion.product_sn_id = stock_lot_obj.id
- logging.info('=====2======')
+ if ChangeType == 'Part':
+ temp_val_sn_id = None
+ old_localtion = None
+ # if ChangeType == 'Part' or ChangeType == 'Tool':
+ stock_lot_obj = request.env['stock.lot'].sudo().search(
+ [('rfid', '=', RfidCode)], limit=1)
+ logging.info('stock_lot_obj===========:%s' % stock_lot_obj)
+ if not stock_lot_obj:
+ res = {'Succeed': False, 'ErrorCode': 202, 'Error': '未根据RfidCode找到该产品'}
+ return json.JSONEncoder().encode(res)
+ if OldPosition:
+ old_localtion = request.env['sf.shelf.location'].sudo().search(
+ [('barcode', '=', OldPosition)], limit=1)
+ logging.info('old_localtion===========:%s' % old_localtion)
+ new_localtion = request.env['sf.shelf.location'].sudo().search(
+ [('barcode', '=', NewPosition)], limit=1)
+ logging.info('new_localtion===========:%s' % new_localtion)
+ if not new_localtion:
+ res = {'Succeed': False, 'ErrorCode': 202, 'Error': '没有该目标位置'}
+ return json.JSONEncoder().encode(res)
+ if old_localtion:
+ temp_val_sn_id = old_localtion.product_sn_id
+ logging.info('temp_val_sn_id===========:%s' % temp_val_sn_id)
+ old_localtion.product_sn_id = None
+ new_localtion.product_sn_id = temp_val_sn_id
+ logging.info('====1======')
+ else:
+ new_localtion.product_sn_id = stock_lot_obj.id
+ logging.info('=====2======')
+ elif ChangeType == 'Tool':
+ # 对功能刀具库位变更信息进行更改
+ def write_tool(DeciveId):
+ if 'Tool' in DeciveId:
+ shelfinfo = list(filter(lambda x: x.get('DeviceId') == DeciveId,
+ request.env['sf.shelf.location'].sudo().get_sf_shelf_location_info(
+ DeciveId)))
+ total_data = request.env['sf.shelf.location.datasync'].sudo().get_total_data()
+ for item in shelfinfo:
+ shelf_barcode = request.env['sf.shelf.location.datasync'].sudo().find_our_code(
+ total_data, item['Postion'])
+ location_id = request.env['sf.shelf.location'].sudo().search(
+ [('barcode', '=', shelf_barcode)],
+ limit=1)
+ if location_id:
+ # 如果是线边刀库信息,则对功能刀具移动生成记录
+ if 'Tool' in item['Postion']:
+ tool = request.env['sf.functional.cutting.tool.entity'].sudo().search(
+ [('rfid', '=', item['RfidCode']), ('functional_tool_status', '!=', '已拆除')])
+ tool.sudo().tool_in_out_stock_location(location_id)
+ if tool:
+ location_id.product_sn_id = tool.barcode_id.id
+ # 修改功能刀具状态
+ tool_state = {'Nomal': '正常', 'Warning': '报警'}
+ if tool_state.get(item.get('State')):
+ if tool_state.get(item.get('State')) != tool.functional_tool_status:
+ tool.write({
+ 'functional_tool_status': tool_state.get(item['State'])
+ })
+ else:
+ location_id.product_sn_id = False
+ logging.info('货架已获取信息:%s' % item)
+ else:
+ equipment_id = request.env['maintenance.equipment'].sudo().search([('name', '=', DeciveId)])
+ if equipment_id:
+ equipment_id.sudo().register_equipment_tool()
+ else:
+ res_1 = {'Succeed': False, 'ErrorCode': 202, 'Error': f'设备【{DeciveId}】不存在'}
+ return json.JSONEncoder().encode(res_1)
+
+ if OldDeciveId:
+ write_tool(OldDeciveId)
+ elif NewDeciveId:
+ write_tool(NewDeciveId)
except Exception as e:
res = {'Succeed': False, 'ErrorCode': 202, 'Error': e}
logging.info('LocationChange error:%s' % e)
diff --git a/sf_sale/__manifest__.py b/sf_sale/__manifest__.py
index efe72de6..45c95030 100644
--- a/sf_sale/__manifest__.py
+++ b/sf_sale/__manifest__.py
@@ -20,7 +20,8 @@
'views/sale_order_view.xml',
'views/res_partner_view.xml',
'views/purchase_order_view.xml',
- 'views/quick_easy_order_view.xml'
+ 'views/quick_easy_order_view.xml',
+ 'views/purchase_menu.xml'
],
'assets': {
'web.assets_backend': [
diff --git a/sf_sale/models/sale_order.py b/sf_sale/models/sale_order.py
index a4027a47..348d6c79 100644
--- a/sf_sale/models/sale_order.py
+++ b/sf_sale/models/sale_order.py
@@ -13,6 +13,11 @@ READONLY_FIELD_STATES = {
class ReSaleOrder(models.Model):
_inherit = 'sale.order'
+ mrp_production_count = fields.Integer(
+ "Count of MO generated",
+ compute='_compute_mrp_production_ids',
+ groups='mrp.group_mrp_user,sf_base.group_sale_salemanager,sf_base.group_sale_director')
+
logistics_way = fields.Selection([('自提', '自提'), ('到付', '到付'), ('在线支付', '在线支付')], string='物流方式')
state = fields.Selection(
selection=[
diff --git a/sf_sale/security/ir.model.access.csv b/sf_sale/security/ir.model.access.csv
index 0e2f0684..0747340c 100644
--- a/sf_sale/security/ir.model.access.csv
+++ b/sf_sale/security/ir.model.access.csv
@@ -96,5 +96,28 @@ access_product_supplierinfo_group_plan_director,product.supplierinfo user,produc
access_product_category_group_plan_director,product.category user,product.model_product_category,sf_base.group_plan_director,1,1,1,0
+access_purchase_report_sf_base_group_purchase,purchase_report_sf_base_group_purchase,purchase.model_purchase_report,sf_base.group_purchase,1,0,0,0
+access_purchase_report_sf_base_group_purchase_director,purchase_report_sf_base_group_purchase_director,purchase.model_purchase_report,sf_base.group_purchase_director,1,0,0,0
+access_sale_order_sf_base_group_purchase,sale_order_sf_base_group_purchase,model_sale_order,sf_base.group_purchase,1,0,0,0
+access_sale_order_sf_base_group_purchase_director,sale_order_sf_base_group_purchase_director,model_sale_order,sf_base.group_purchase_director,1,0,0,0
+
+
+access_quality_check_group_sale_salemanager,quality_check_group_sale_salemanager,quality.model_quality_check,sf_base.group_sale_salemanager,1,0,0,0
+access_quality_check_group_sale_director,quality_check_group_sale_director,quality.model_quality_check,sf_base.group_sale_director,1,0,0,0
+access_stock_picking_group_sale_salemanager,stock_picking_group_sale_salemanager,stock.model_stock_picking,sf_base.group_sale_salemanager,1,0,0,0
+access_stock_picking_group_sale_director,stock_picking_group_sale_director,stock.model_stock_picking,sf_base.group_sale_director,1,0,0,0
+access_mrp_workorder_group_sale_salemanager,mrp_workorder_group_sale_salemanager,mrp.model_mrp_workorder,sf_base.group_sale_salemanager,1,0,0,0
+access_mrp_workorder_group_sale_director,mrp_workorder_group_sale_director,mrp.model_mrp_workorder,sf_base.group_sale_director,1,0,0,0
+access_mrp_unbuild_group_sale_salemanager,mrp_unbuild_group_sale_salemanager,mrp.model_mrp_unbuild,sf_base.group_sale_salemanager,1,0,0,0
+access_mrp_unbuild_group_sale_director,mrp_unbuild_group_sale_director,mrp.model_mrp_unbuild,sf_base.group_sale_director,1,0,0,0
+access_mrp_workcenter_productivity_group_sale_salemanager,mrp_workcenter_productivity_group_sale_salemanager,mrp.model_mrp_workcenter_productivity,sf_base.group_sale_salemanager,1,0,0,0
+access_mrp_workcenter_productivity_group_sale_director,mrp_workcenter_productivity_group_sale_director,mrp.model_mrp_workcenter_productivity,sf_base.group_sale_director,1,0,0,0
+access_sf_detection_result_group_sale_salemanager,sf_detection_result_group_sale_salemanager,sf_manufacturing.model_sf_detection_result,sf_base.group_sale_salemanager,1,0,0,0
+access_sf_detection_result_group_sale_director,sf_detection_result_group_sale_director,sf_manufacturing.model_sf_detection_result,sf_base.group_sale_director,1,0,0,0
+access_stock_scrap_group_sale_salemanager,stock_scrap_group_sale_salemanager,stock.model_stock_scrap,sf_base.group_sale_salemanager,1,0,0,0
+access_stock_scrap_group_sale_director,stock_scrap_group_sale_director,stock.model_stock_scrap,sf_base.group_sale_director,1,0,0,0
+
+
+
diff --git a/sf_sale/views/purchase_menu.xml b/sf_sale/views/purchase_menu.xml
new file mode 100644
index 00000000..3b92ca4b
--- /dev/null
+++ b/sf_sale/views/purchase_menu.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sf_sale/views/purchase_order_view.xml b/sf_sale/views/purchase_order_view.xml
index eda8e59d..a45d8049 100644
--- a/sf_sale/views/purchase_order_view.xml
+++ b/sf_sale/views/purchase_order_view.xml
@@ -86,6 +86,18 @@
+
+
+
+
{'readonly': [('state', 'in', ['purchase'])]}
diff --git a/sf_sale/views/sale_order_view.xml b/sf_sale/views/sale_order_view.xml
index 00cca206..ce27a4df 100644
--- a/sf_sale/views/sale_order_view.xml
+++ b/sf_sale/views/sale_order_view.xml
@@ -6,6 +6,13 @@
sale.order
+
+ sf_base.group_sale_salemanager,sf_base.group_sale_director
+
+
+ mrp.group_mrp_user,sf_base.group_sale_salemanager,sf_base.group_sale_director
+
+
@@ -35,12 +42,12 @@
+ attrs="{'invisible': ['|','&','|',('check_status', '!=', 'approved'),('state', 'in', ['draft','cancel']),'&','&',('check_status', '=', 'approved'),('state', 'in', ['sale','cancel']),('delivery_status', '!=', False),('state', 'in', ['cancel'])]}"/>
- {'invisible': ['|','&',('check_status', '!=', 'approved'),('state',
+ {'invisible': ['|','&','|', ('check_status', '!=', 'approved'),('state',
'in', ['draft','cancel']),'&','&',('check_status', '=', 'approved'),('state', 'in',
- ['sale','cancel']),('delivery_status', '!=', False)]}
+ ['sale','cancel']),('delivery_status', '!=', False), ('state', 'in', ['cancel'])]}
diff --git a/sf_tool_management/models/base.py b/sf_tool_management/models/base.py
index 65475333..2876bc8f 100644
--- a/sf_tool_management/models/base.py
+++ b/sf_tool_management/models/base.py
@@ -94,47 +94,47 @@ class MachineTableToolChangingApply(models.Model):
if len(records) > 1:
raise ValidationError('该刀位号已存在,请重新选择!!!')
- @api.constrains('functional_tool_status')
- def automation_apply_for_tool_change(self):
- """
- 自动申请换刀
- :return:
- """
- # 更新数据到机台换刀申请界面
- if self.functional_tool_status == '报警' and not self.sf_functional_tool_assembly_id:
- machine_table_tool_changing_apply = self.env['sf.machine.table.tool.changing.apply'].search(
- [('maintenance_equipment_id', '=', self.maintenance_equipment_id.id),
- ('cutter_spacing_code_id', '=', self.cutter_spacing_code_id.id)
- ])
-
- # 创建功能刀具预警记录
- self.env['sf.functional.tool.warning'].create_tool_warning_record({'tool_changing_apply_id': self})
-
- # 新建组装任务
- sf_functional_tool_assembly = self.env['sf.functional.tool.assembly'].create({
- 'functional_tool_name': self.functional_tool_name,
- 'functional_tool_type_id': self.functional_tool_type_id.id,
- 'functional_tool_diameter': self.diameter,
- 'knife_tip_r_angle': self.knife_tip_r_angle,
- 'coarse_middle_thin': '3',
- 'new_former': '0',
- 'functional_tool_length': self.extension_length,
- 'effective_length': self.effective_length,
- 'loading_task_source': '1',
- 'use_tool_time': fields.Datetime.now() + timedelta(hours=4),
- 'production_line_name_id': self.production_line_id.id,
- 'machine_tool_name_id': self.maintenance_equipment_id.id,
- 'applicant': '系统自动',
- 'apply_time': fields.Datetime.now(),
- 'cutter_spacing_code_id': self.cutter_spacing_code_id.id,
- 'whether_standard_knife': self.whether_standard_knife,
- 'reason_for_applying': '机台报警自动换刀',
- 'sf_machine_table_tool_changing_apply_id': self.id
- })
-
- machine_table_tool_changing_apply.write(
- {'status': '1',
- 'sf_functional_tool_assembly_id': sf_functional_tool_assembly.id})
+ # @api.constrains('functional_tool_status')
+ # def automation_apply_for_tool_change(self):
+ # """
+ # 自动申请换刀
+ # :return:
+ # """
+ # # 更新数据到机台换刀申请界面
+ # if self.functional_tool_status == '报警' and not self.sf_functional_tool_assembly_id:
+ # machine_table_tool_changing_apply = self.env['sf.machine.table.tool.changing.apply'].search(
+ # [('maintenance_equipment_id', '=', self.maintenance_equipment_id.id),
+ # ('cutter_spacing_code_id', '=', self.cutter_spacing_code_id.id)
+ # ])
+ #
+ # # 创建功能刀具预警记录
+ # self.env['sf.functional.tool.warning'].create_tool_warning_record({'tool_changing_apply_id': self})
+ #
+ # # 新建组装任务
+ # sf_functional_tool_assembly = self.env['sf.functional.tool.assembly'].create({
+ # 'functional_tool_name': self.functional_tool_name,
+ # 'functional_tool_type_id': self.functional_tool_type_id.id,
+ # 'functional_tool_diameter': self.diameter,
+ # 'knife_tip_r_angle': self.knife_tip_r_angle,
+ # 'coarse_middle_thin': '3',
+ # 'new_former': '0',
+ # 'functional_tool_length': self.extension_length,
+ # 'effective_length': self.effective_length,
+ # 'loading_task_source': '1',
+ # 'use_tool_time': fields.Datetime.now() + timedelta(hours=4),
+ # 'production_line_name_id': self.production_line_id.id,
+ # 'machine_tool_name_id': self.maintenance_equipment_id.id,
+ # 'applicant': '系统自动',
+ # 'apply_time': fields.Datetime.now(),
+ # 'cutter_spacing_code_id': self.cutter_spacing_code_id.id,
+ # 'whether_standard_knife': self.whether_standard_knife,
+ # 'reason_for_applying': '机台报警自动换刀',
+ # 'sf_machine_table_tool_changing_apply_id': self.id
+ # })
+ #
+ # machine_table_tool_changing_apply.write(
+ # {'status': '1',
+ # 'sf_functional_tool_assembly_id': sf_functional_tool_assembly.id})
def revocation_1(self):
"""
@@ -760,6 +760,15 @@ class FunctionalToolDismantle(models.Model):
functional_tool_id = fields.Many2one('sf.functional.cutting.tool.entity', '功能刀具', required=True, tracking=True,
domain=[('functional_tool_status', '!=', '已拆除'),
('current_location', '=', '刀具房')])
+
+ @api.onchange('functional_tool_id')
+ def _onchange_functional_tool_id(self):
+ for item in self:
+ if item:
+ dismantle_id = self.search([('functional_tool_id', '=', item.functional_tool_id.id)])
+ if dismantle_id:
+ raise ValidationError(f'Rfid为【{item.rfid}】的功能刀具已经存在拆解单,单号是【{dismantle_id[0].code}】')
+
tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', store=True,
compute='_compute_functional_tool_num')
tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', compute='_compute_functional_tool_num', store=True)
@@ -938,15 +947,23 @@ class FunctionalToolDismantle(models.Model):
if self.chuck_freight_id == self.pad_freight_id:
raise ValidationError('【夹头】和【刀盘】的目标货位重复,请重新选择!')
+ def tool_scrap(self):
+ self.scrap_boolean = True
+
+ def tool_no_scrap(self):
+ self.scrap_boolean = False
+
def confirmation_disassembly(self):
logging.info('%s刀具确认开始拆解' % self.dismantle_cause)
code = self.code
if self.functional_tool_id.functional_tool_status == '已拆除':
- raise ValidationError('Rfid为【%s】的功能刀具已经拆解,请勿重复操作!' % self.functional_tool_id.rfid_dismantle)
+ raise ValidationError('Rfid为【%s】名称为【%s】的功能刀具已经拆解,请勿重复操作!' % (
+ self.functional_tool_id.rfid_dismantle, self.name))
# 对拆解的功能刀具进行校验,只有在刀具房的功能刀具才能拆解
- if self.functional_tool_id.tool_room_num == 0:
- raise ValidationError('Rfid为【%s】的功能刀具当前位置为【%s】,不能进行拆解!' % (
- self.rfid, self.functional_tool_id.current_location))
+ elif self.functional_tool_id.functional_tool_status != '报警':
+ if self.functional_tool_id.tool_room_num == 0:
+ raise ValidationError('Rfid为【%s】的功能刀具当前位置为【%s】,不能进行拆解!' % (
+ self.rfid, self.functional_tool_id.current_location))
# 目标重复校验
self.location_duplicate_check()
datas = {'scrap': [], 'picking': []}
@@ -1005,6 +1022,14 @@ class FunctionalToolDismantle(models.Model):
'rfid': '%s(已拆解)' % self.rfid,
'state': '已拆解'
})
+ # ==================修改刀具预警信息的值============
+ warning_id = self.env['sf.functional.tool.warning'].sudo().search(
+ [('functional_tool_id', '=', self.functional_tool_id.id)])
+ if warning_id:
+ warning_id.sudo().write({
+ 'dispose_user': self.env.user.name,
+ 'dispose_time': fields.Datetime.now()
+ })
logging.info('【%s】刀具拆解成功!' % self.name)
def create_tool_picking_scrap(self, datas):
diff --git a/sf_tool_management/models/functional_tool.py b/sf_tool_management/models/functional_tool.py
index 0d9473ca..55a87339 100644
--- a/sf_tool_management/models/functional_tool.py
+++ b/sf_tool_management/models/functional_tool.py
@@ -11,6 +11,7 @@ from odoo.exceptions import ValidationError
class FunctionalCuttingToolEntity(models.Model):
_name = 'sf.functional.cutting.tool.entity'
_description = '功能刀具列表'
+ _order = 'functional_tool_status'
functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', string='功能刀具组装单', readonly=True)
@@ -53,6 +54,22 @@ class FunctionalCuttingToolEntity(models.Model):
safe_inventory_id = fields.Many2one('sf.real.time.distribution.of.functional.tools',
string='功能刀具安全库存', readonly=True)
+ @api.onchange('functional_tool_status')
+ def _onchange_functional_tool_status(self):
+ for item in self:
+ if item:
+ if item.functional_tool_status == '报警':
+ # 创建报警刀具拆解单
+ self.env['sf.functional.tool.dismantle'].sudo().create({
+ 'functional_tool_id': item.ids[0],
+ 'dismantle_cause': '寿命到期报废'
+ })
+ # 创建刀具报警记录
+ self.env['sf.functional.tool.warning'].sudo().create({
+ 'rfid': item.rfid,
+ 'functional_tool_id': item.ids[0]
+ })
+
@api.depends('barcode_id.quant_ids', 'barcode_id.quant_ids.location_id', 'functional_tool_status',
'current_shelf_location_id')
def _compute_current_location_id(self):
@@ -101,27 +118,28 @@ class FunctionalCuttingToolEntity(models.Model):
def tool_in_out_stock_location(self, location_id):
tool_room_id = self.env['stock.location'].search([('name', '=', '刀具房')])
pre_manufacturing_id = self.env['stock.location'].search([('name', '=', '制造前')])
- for item in self:
- # 中控反馈该位置有刀
- if item:
- # 系统该位置有刀
- if location_id.product_sn_id:
- # 中控反馈和系统中,该位置是同一把刀
- if item.barcode_id == location_id.product_sn_id:
- return True
- # 中控反馈和系统中,该位置不是同一把刀
- else:
- # 原刀从线边出库
- item.tool_in_out_stock_location_1(location_id, tool_room_id)
- # 新刀入库到线边
- item.create_stock_move(pre_manufacturing_id, location_id)
- item.current_shelf_location_id = location_id.id
+ if self:
+ for item in self:
+ # 中控反馈该位置有刀
+ if item:
+ # 系统该位置有刀
+ if location_id.product_sn_id:
+ # 中控反馈和系统中,该位置是同一把刀
+ if item.barcode_id == location_id.product_sn_id:
+ return True
+ # 中控反馈和系统中,该位置不是同一把刀
+ else:
+ # 原刀从线边出库
+ item.tool_in_out_stock_location_1(location_id, tool_room_id)
+ # 新刀入库到线边
+ item.create_stock_move(pre_manufacturing_id, location_id)
+ item.current_shelf_location_id = location_id.id
- # 中控反馈该位置没有刀
- else:
- # 系统该位置有刀
- if location_id.product_sn_id:
- item.tool_in_out_stock_location_1(location_id, tool_room_id)
+ # 中控反馈该位置没有刀
+ else:
+ # 系统该位置有刀
+ if location_id.product_sn_id:
+ self.tool_in_out_stock_location_1(location_id, tool_room_id)
def tool_in_out_stock_location_1(self, location_id, tool_room_id):
tool = self.env['sf.functional.cutting.tool.entity'].search(
@@ -238,10 +256,39 @@ class FunctionalCuttingToolEntity(models.Model):
functional_tool_model_ids.append(functional_tool_model.id)
return [(6, 0, functional_tool_model_ids)]
+ dismantle_num = fields.Integer('拆解单数量', compute='_compute_dismantle_num', store=True)
+ dismantle_ids = fields.One2many('sf.functional.tool.dismantle', 'functional_tool_id', '拆解单')
+
+ @api.depends('dismantle_ids')
+ def _compute_dismantle_num(self):
+ for item in self:
+ if item:
+ item.dismantle_num = len(item.dismantle_ids)
+
+ def open_functional_tool_dismantle_form(self):
+ self.ensure_one()
+ dismantle_ids = self.env['sf.functional.tool.dismantle'].sudo().search([('functional_tool_id', '=', self.id)])
+ action = {
+ 'res_model': 'sf.functional.tool.dismantle',
+ 'type': 'ir.actions.act_window',
+ 'name': '拆解单',
+ }
+ if len(dismantle_ids) == 1:
+ action.update({
+ 'view_mode': 'form',
+ 'res_id': dismantle_ids[0].id,
+ })
+ else:
+ action.update({
+ 'domain': [('id', 'in', dismantle_ids.ids)],
+ 'view_mode': 'tree,form',
+ })
+ return action
+
def open_functional_tool_warning(self):
action = self.env.ref('sf_tool_management.action_sf_functional_tool_warning')
result = action.read()[0]
- result['domain'] = [('functional_tool_name_id', '=', self.functional_tool_name_id.id)]
+ result['domain'] = [('functional_tool_id', '=', self.id)]
return result
def open_stock_move_line(self):
@@ -323,10 +370,10 @@ class FunctionalToolWarning(models.Model):
_name = 'sf.functional.tool.warning'
_description = '功能刀具预警'
- code = fields.Char('编码', related='functional_tool_name_id.code')
- rfid = fields.Char('Rfid', related='functional_tool_name_id.rfid')
- tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', related='functional_tool_name_id.tool_groups_id')
- name = fields.Char('名称', invisible=True, readonly=True, related='functional_tool_name_id.name')
+ code = fields.Char('编码', related='functional_tool_id.code')
+ rfid = fields.Char('Rfid', readonly=True)
+ tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', related='functional_tool_id.tool_groups_id')
+ name = fields.Char('名称', invisible=True, readonly=True, related='functional_tool_id.name')
# 机床信息
production_line_id = fields.Many2one('sf.production.line', string='生产线',
group_expand='_read_group_machine_table_name_ids')
@@ -337,52 +384,77 @@ class FunctionalToolWarning(models.Model):
cutter_spacing_code_id = fields.Many2one('maintenance.equipment.tool', string='刀位号',
domain="[('equipment_id', '=', maintenance_equipment_id)]")
# 功能刀具信息
- functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', string='功能刀具名称')
- barcode_id = fields.Many2one('stock.lot', string='功能刀具序列号', related='functional_tool_name_id.barcode_id')
- mrs_cutting_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型')
- diameter = fields.Float(string='刀具直径(mm)')
- knife_tip_r_angle = fields.Float(string='刀尖R角(mm)')
+ functional_tool_id = fields.Many2one('sf.functional.cutting.tool.entity', string='功能刀具', readonly=True)
+ barcode_id = fields.Many2one('stock.lot', string='序列号', related='functional_tool_id.barcode_id')
+ mrs_cutting_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型',
+ related='functional_tool_id.sf_cutting_tool_type_id')
+ diameter = fields.Float(string='刀具直径(mm)', related='functional_tool_id.functional_tool_diameter')
+ knife_tip_r_angle = fields.Float(string='刀尖R角(mm)', related='functional_tool_id.knife_tip_r_angle')
# 其他信息
install_tool_time = fields.Datetime("刀具组装时间", related='functional_tool_name_id.tool_loading_time')
on_board_time = fields.Datetime('上机装刀时间')
- max_lifetime_value = fields.Integer(string='最大寿命值(min)')
- alarm_value = fields.Integer(string='报警值(min)')
- used_value = fields.Integer(string='已使用值(min)')
+ max_lifetime_value = fields.Integer(string='最大寿命值(min)', related='functional_tool_id.max_lifetime_value')
+ alarm_value = fields.Integer(string='报警值(min)', related='functional_tool_id.alarm_value')
+ used_value = fields.Integer(string='已使用值(min)', related='functional_tool_id.used_value')
functional_tool_status = fields.Selection([('正常', '正常'), ('报警', '报警'), ('已拆除', '已拆除')], string='状态')
- alarm_time = fields.Datetime('报警时间')
- dispose_user = fields.Char('处理人')
- dispose_time = fields.Char('处理时间')
- dispose_func = fields.Char('处理方法/措施', readonly=False)
+ alarm_time = fields.Datetime('报警时间', default=lambda self: fields.Datetime.now(), readonly=True)
+ dispose_user = fields.Char('处理人', readonly=True)
+ dispose_time = fields.Char('处理时间', readonly=True)
+ dispose_func = fields.Char('处理方法/措施', readonly=True)
active = fields.Boolean(string='已归档', default=True)
+ functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', string='功能刀具名称')
+
@api.model
def _read_group_machine_table_name_ids(self, categories, domain, order):
machine_table_name_ids = categories._search([], order=order, access_rights_uid=SUPERUSER_ID)
return categories.browse(machine_table_name_ids)
- def create_tool_warning_record(self, obj):
- """
- 机台换刀申请报警状态时,创建功能刀具预警记录
- """
- if obj:
- for tool in obj.get('tool_changing_apply_id'):
- self.env['sf.functional.tool.warning'].create({
- 'production_line_id': tool.production_line_id.id,
- 'maintenance_equipment_id': tool.maintenance_equipment_id.id,
- 'machine_tool_code': tool.machine_tool_code,
- 'machine_table_type_id': tool.machine_table_type_id.id,
- 'cutter_spacing_code_id': tool.cutter_spacing_code_id.id,
- 'functional_tool_name_id': tool.functional_tool_name_id.id,
- 'barcode_id': tool.barcode_id.id,
- 'diameter': tool.diameter,
- 'knife_tip_r_angle': tool.knife_tip_r_angle,
- 'max_lifetime_value': tool.max_lifetime_value,
- 'alarm_value': tool.alarm_value,
- 'used_value': tool.used_value,
- 'functional_tool_status': tool.functional_tool_status,
- 'alarm_time': fields.Datetime.now(),
- })
+ def action_open_dismantle(self):
+ self.ensure_one()
+ dismantle_ids = self.env['sf.functional.tool.dismantle'].sudo().search(
+ [('functional_tool_id', '=', self.functional_tool_id.id)])
+ action = {
+ 'res_model': 'sf.functional.tool.dismantle',
+ 'type': 'ir.actions.act_window',
+ 'name': '拆解单'
+ }
+ if len(dismantle_ids) == 1:
+ action.update({
+ 'view_mode': 'form',
+ 'res_id': dismantle_ids.ids[0]
+ })
+ elif dismantle_ids:
+ action.update({
+ 'view_mode': 'tree,form',
+ 'domain': [('id', 'in', dismantle_ids.ids)],
+ })
+ else:
+ return False
+ return action
+ # def create_tool_warning_record(self, obj):
+ # """
+ # 机台换刀申请报警状态时,创建功能刀具预警记录
+ # """
+ # if obj:
+ # for tool in obj.get('tool_changing_apply_id'):
+ # self.env['sf.functional.tool.warning'].create({
+ # 'production_line_id': tool.production_line_id.id,
+ # 'maintenance_equipment_id': tool.maintenance_equipment_id.id,
+ # 'machine_tool_code': tool.machine_tool_code,
+ # 'machine_table_type_id': tool.machine_table_type_id.id,
+ # 'cutter_spacing_code_id': tool.cutter_spacing_code_id.id,
+ # 'functional_tool_name_id': tool.functional_tool_name_id.id,
+ # 'barcode_id': tool.barcode_id.id,
+ # 'diameter': tool.diameter,
+ # 'knife_tip_r_angle': tool.knife_tip_r_angle,
+ # 'max_lifetime_value': tool.max_lifetime_value,
+ # 'alarm_value': tool.alarm_value,
+ # 'used_value': tool.used_value,
+ # 'functional_tool_status': tool.functional_tool_status,
+ # 'alarm_time': fields.Datetime.now(),
+ # })
class StockMoveLine(models.Model):
diff --git a/sf_tool_management/models/maintenance_equipment.py b/sf_tool_management/models/maintenance_equipment.py
index 48bc531f..18142e24 100644
--- a/sf_tool_management/models/maintenance_equipment.py
+++ b/sf_tool_management/models/maintenance_equipment.py
@@ -53,7 +53,7 @@ class SfMaintenanceEquipment(models.Model):
params = {"DeviceId": self.name}
r = requests.get(crea_url, params=params, headers=headers)
ret = r.json()
- logging.info('register_equipment_tool:%s' % ret)
+ logging.info('机床刀库register_equipment_tool():%s' % ret)
datas = ret['Datas']
self.write_maintenance_equipment_tool(datas)
if ret['Succeed']:
diff --git a/sf_tool_management/views/functional_tool_views.xml b/sf_tool_management/views/functional_tool_views.xml
index 103583c2..b2e71fb3 100644
--- a/sf_tool_management/views/functional_tool_views.xml
+++ b/sf_tool_management/views/functional_tool_views.xml
@@ -25,7 +25,10 @@
-
+
@@ -48,6 +51,18 @@
+
+ options="{'no_create': True}"
+ attrs="{'readonly': ['|',('state', '=', '已拆解'),('id', '!=', False)]}"/>
@@ -833,10 +839,26 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
@@ -911,7 +933,7 @@
-
@@ -952,8 +974,9 @@
sf.functional.tool.dismantle
+
-
+
diff --git a/sf_tool_management/wizard/wizard.py b/sf_tool_management/wizard/wizard.py
index 7ae92d65..52dc8529 100644
--- a/sf_tool_management/wizard/wizard.py
+++ b/sf_tool_management/wizard/wizard.py
@@ -842,6 +842,8 @@ class StockPicking(models.Model):
stock_move_id = self.env['stock.move']
datas = {'data': [], 'picking_id': picking_id}
if obj.handle_code_id:
+ # 修改刀柄序列号状态为【在用】
+ obj.handle_code_id.sudo().write({'tool_material_status': '在用'})
datas['data'].append(
{'current_location_id': self.env['sf.shelf.location'], 'lot_id': obj.handle_code_id})
if obj.integral_product_id:
diff --git a/sf_tool_management/wizard/wizard_view.xml b/sf_tool_management/wizard/wizard_view.xml
index b6e15586..b5c2f82e 100644
--- a/sf_tool_management/wizard/wizard_view.xml
+++ b/sf_tool_management/wizard/wizard_view.xml
@@ -201,6 +201,11 @@
+
@@ -368,7 +373,7 @@
diff --git a/sf_warehouse/models/model.py b/sf_warehouse/models/model.py
index 5beeebc5..d3f9c585 100644
--- a/sf_warehouse/models/model.py
+++ b/sf_warehouse/models/model.py
@@ -507,13 +507,13 @@ class ShelfLocation(models.Model):
print('eeeeeee空闲', e)
# 调取获取货位信息接口
- def get_sf_shelf_location_info(self):
+ def get_sf_shelf_location_info(self, device_id='Cabinet-AL'):
config = self.env['res.config.settings'].get_values()
headers = {'Authorization': config['center_control_Authorization']}
crea_url = config['center_control_url'] + "/AutoDeviceApi/GetLocationInfos"
- params = {'DeviceId': 'Cabinet-AL'}
+ params = {'DeviceId': device_id}
r = requests.get(crea_url, params=params, headers=headers)
ret = r.json()
diff --git a/sf_warehouse/models/sync_common.py b/sf_warehouse/models/sync_common.py
index 3df97423..3d28583c 100644
--- a/sf_warehouse/models/sync_common.py
+++ b/sf_warehouse/models/sync_common.py
@@ -13,88 +13,92 @@ class MrsShelfLocationDataSync(models.Model):
_name = 'sf.shelf.location.datasync'
_description = '同步库存信息'
+ def get_total_data(self):
+
+ # 建立对应关系的函数
+ def align_data(my_data, their_data):
+ paired_data = list(zip(my_data, their_data))
+ return paired_data
+
+ logging.info('============================get_total_data()======================')
+ shelf_1_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-一号线边刀架')], limit=1)
+ tool_location_objs_1 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_1_obj.id)], order='id')
+
+ location_codes_1 = [location.barcode for location in tool_location_objs_1]
+ print(location_codes_1)
+ # 对方的数据列表
+ their_data_1 = [f"ToolCab1-{i:02}" for i in range(1, 73)]
+
+ # 执行对齐
+ aligned_data_1 = align_data(location_codes_1, their_data_1)
+
+ # 2
+ shelf_2_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-二号线边刀架')], limit=1)
+ tool_location_objs_2 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_2_obj.id)], order='id')
+
+ location_codes_2 = [location.barcode for location in tool_location_objs_2]
+ print(location_codes_2)
+ # 对方的数据列表
+ their_data_2 = [f"ToolCab2-{i:02}" for i in range(1, 73)]
+
+ # 执行对齐
+ aligned_data_2 = align_data(location_codes_2, their_data_2)
+
+ # 4
+ shelf_4_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-一号线边料架')], limit=1)
+ tool_location_objs_4 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_4_obj.id)], order='id')
+
+ location_codes_4 = [location.barcode for location in tool_location_objs_4]
+ print(location_codes_4)
+ # 对方的数据列表
+ their_data_4 = [f"PartCab4-{i:02}" for i in range(1, 17)]
+
+ # 执行对齐
+ aligned_data_4 = align_data(location_codes_4, their_data_4)
+
+ # 3
+ shelf_3_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-二号线边料架')], limit=1)
+ tool_location_objs_3 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_3_obj.id)], order='id')
+
+ location_codes_3 = [location.barcode for location in tool_location_objs_3]
+ print(location_codes_3)
+ # 对方的数据列表
+ their_data_3 = [f"PartCab3-{i:02}" for i in range(1, 13)]
+
+ # 执行对齐
+ aligned_data_3 = align_data(location_codes_3, their_data_3)
+
+ # 5
+ shelf_5_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-三号线边料架')], limit=1)
+ tool_location_objs_5 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_5_obj.id)], order='id')
+
+ location_codes_5 = [location.barcode for location in tool_location_objs_5]
+ print(location_codes_5)
+ # 对方的数据列表
+ their_data_5 = [f"PartCab5-{i:02}" for i in range(1, 13)]
+
+ # 执行对齐
+ aligned_data_5 = align_data(location_codes_5, their_data_5)
+
+ total_data = aligned_data_1 + aligned_data_2 + aligned_data_3 + aligned_data_4 + aligned_data_5
+ print(total_data)
+ logging.info(f"total_data: {total_data}")
+ return total_data
+
+ def find_our_code(self, total_data, their_code):
+ for code_pair in total_data:
+ if code_pair[1] == their_code:
+ return code_pair[0]
+ return None # 如果没有找到对应的值,返回None或适当的默认值
+
def _cron_shelf_location_datasync(self):
try:
- # 建立对应关系的函数
- def align_data(my_data, their_data):
- paired_data = list(zip(my_data, their_data))
- return paired_data
-
- shelf_1_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-一号线边刀架')], limit=1)
- tool_location_objs_1 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_1_obj.id)], order='id')
-
- location_codes_1 = [location.barcode for location in tool_location_objs_1]
- print(location_codes_1)
- # 对方的数据列表
- their_data_1 = [f"ToolCab1-{i:02}" for i in range(1, 73)]
-
- # 执行对齐
- aligned_data_1 = align_data(location_codes_1, their_data_1)
-
- # 2
- shelf_2_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-二号线边刀架')], limit=1)
- tool_location_objs_2 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_2_obj.id)], order='id')
-
- location_codes_2 = [location.barcode for location in tool_location_objs_2]
- print(location_codes_2)
- # 对方的数据列表
- their_data_2 = [f"ToolCab2-{i:02}" for i in range(1, 73)]
-
- # 执行对齐
- aligned_data_2 = align_data(location_codes_2, their_data_2)
-
- # 4
- shelf_4_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-一号线边料架')], limit=1)
- tool_location_objs_4 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_4_obj.id)], order='id')
-
- location_codes_4 = [location.barcode for location in tool_location_objs_4]
- print(location_codes_4)
- # 对方的数据列表
- their_data_4 = [f"PartCab4-{i:02}" for i in range(1, 17)]
-
- # 执行对齐
- aligned_data_4 = align_data(location_codes_4, their_data_4)
-
- # 3
- shelf_3_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-二号线边料架')], limit=1)
- tool_location_objs_3 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_3_obj.id)], order='id')
-
- location_codes_3 = [location.barcode for location in tool_location_objs_3]
- print(location_codes_3)
- # 对方的数据列表
- their_data_3 = [f"PartCab3-{i:02}" for i in range(1, 13)]
-
- # 执行对齐
- aligned_data_3 = align_data(location_codes_3, their_data_3)
-
- # 5
- shelf_5_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-三号线边料架')], limit=1)
- tool_location_objs_5 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_5_obj.id)], order='id')
-
- location_codes_5 = [location.barcode for location in tool_location_objs_5]
- print(location_codes_5)
- # 对方的数据列表
- their_data_5 = [f"PartCab5-{i:02}" for i in range(1, 13)]
-
- # 执行对齐
- aligned_data_5 = align_data(location_codes_5, their_data_5)
-
- total_data = aligned_data_1 + aligned_data_2 + aligned_data_3 + aligned_data_4 + aligned_data_5
- print(total_data)
- logging.info(f"total_data: {total_data}")
-
def find_their_code(my_code, aligned_data):
for code_pair in aligned_data:
if code_pair[0] == my_code:
return code_pair[1]
return None # 如果没有找到对应的值,返回None或适当的默认值
- def find_our_code(their_code, aligned_data):
- for code_pair in aligned_data:
- if code_pair[1] == their_code:
- return code_pair[0]
- return None # 如果没有找到对应的值,返回None或适当的默认值
-
# 定时更新所有设备机床刀库信息
equipment_ids = self.env['maintenance.equipment'].search(
[('equipment_type', '=', '机床'), ('function_type', '!=', False)])
@@ -103,9 +107,10 @@ class MrsShelfLocationDataSync(models.Model):
equipment_id.register_equipment_tool()
shelfinfo = self.env['sf.shelf.location'].get_sf_shelf_location_info()
+ total_data = self.get_total_data()
print('shelfinfo:', shelfinfo)
for item in shelfinfo:
- shelf_barcode = find_our_code(item['Postion'], total_data)
+ shelf_barcode = self.find_our_code(total_data, item['Postion'])
location_id = self.env['sf.shelf.location'].search([('barcode', '=', shelf_barcode)], limit=1)
if location_id:
# 如果是线边刀库信息,则对功能刀具移动生成记录
@@ -115,6 +120,13 @@ class MrsShelfLocationDataSync(models.Model):
tool.tool_in_out_stock_location(location_id)
if tool:
location_id.product_sn_id = tool.barcode_id.id
+ # 修改功能刀具状态
+ tool_state = {'Nomal': '正常', 'Warning': '报警'}
+ if tool_state.get(item.get('State')):
+ if tool_state.get(item.get('State')) != tool.functional_tool_status:
+ tool.write({
+ 'functional_tool_status': tool_state.get(item['State'])
+ })
else:
location_id.product_sn_id = False
else: