Merge branch 'feature/销售单优化' into feature/销售、刀具模块优化

This commit is contained in:
yuxianghui
2024-08-16 16:02:19 +08:00
16 changed files with 499 additions and 253 deletions

View File

@@ -388,7 +388,7 @@ class Manufacturing_Connect(http.Controller):
ret = json.loads(datas) ret = json.loads(datas)
request.env['center_control.interface.log'].sudo().create( request.env['center_control.interface.log'].sudo().create(
{'content': ret, 'name': 'AutoDeviceApi/LocationChange'}) {'content': ret, 'name': 'AutoDeviceApi/LocationChange'})
logging.info('LocationChange_ret===========:%s' % ret) logging.info('库位变更LocationChange_ret:%s' % ret)
RfidCode = ret['RfidCode'] RfidCode = ret['RfidCode']
ChangeType = ret['ChangeType'] ChangeType = ret['ChangeType']
OldDeciveId = ret['OldDeciveId'] OldDeciveId = ret['OldDeciveId']
@@ -398,34 +398,77 @@ class Manufacturing_Connect(http.Controller):
OldDeciveStart = ret['OldDeciveStart'] OldDeciveStart = ret['OldDeciveStart']
OldDeciveEnd = ret['OldDeciveEnd'] OldDeciveEnd = ret['OldDeciveEnd']
temp_val_sn_id = None if ChangeType == 'Part':
old_localtion = None temp_val_sn_id = None
# if ChangeType == 'Part' or ChangeType == 'Tool': old_localtion = None
stock_lot_obj = request.env['stock.lot'].sudo().search( # if ChangeType == 'Part' or ChangeType == 'Tool':
[('rfid', '=', RfidCode)], limit=1) stock_lot_obj = request.env['stock.lot'].sudo().search(
logging.info('stock_lot_obj===========:%s' % stock_lot_obj) [('rfid', '=', RfidCode)], limit=1)
if not stock_lot_obj: logging.info('stock_lot_obj===========:%s' % stock_lot_obj)
res = {'Succeed': False, 'ErrorCode': 202, 'Error': '未根据RfidCode找到该产品'} if not stock_lot_obj:
return json.JSONEncoder().encode(res) res = {'Succeed': False, 'ErrorCode': 202, 'Error': '未根据RfidCode找到该产品'}
if OldPosition: return json.JSONEncoder().encode(res)
old_localtion = request.env['sf.shelf.location'].sudo().search( if OldPosition:
[('barcode', '=', OldPosition)], limit=1) old_localtion = request.env['sf.shelf.location'].sudo().search(
logging.info('old_localtion===========:%s' % old_localtion) [('barcode', '=', OldPosition)], limit=1)
new_localtion = request.env['sf.shelf.location'].sudo().search( logging.info('old_localtion===========:%s' % old_localtion)
[('barcode', '=', NewPosition)], limit=1) new_localtion = request.env['sf.shelf.location'].sudo().search(
logging.info('new_localtion===========:%s' % new_localtion) [('barcode', '=', NewPosition)], limit=1)
if not new_localtion: logging.info('new_localtion===========:%s' % new_localtion)
res = {'Succeed': False, 'ErrorCode': 202, 'Error': '没有该目标位置'} if not new_localtion:
return json.JSONEncoder().encode(res) res = {'Succeed': False, 'ErrorCode': 202, 'Error': '没有该目标位置'}
if old_localtion: return json.JSONEncoder().encode(res)
temp_val_sn_id = old_localtion.product_sn_id if old_localtion:
logging.info('temp_val_sn_id===========:%s' % temp_val_sn_id) temp_val_sn_id = old_localtion.product_sn_id
old_localtion.product_sn_id = None logging.info('temp_val_sn_id===========:%s' % temp_val_sn_id)
new_localtion.product_sn_id = temp_val_sn_id old_localtion.product_sn_id = None
logging.info('====1======') new_localtion.product_sn_id = temp_val_sn_id
else: logging.info('====1======')
new_localtion.product_sn_id = stock_lot_obj.id else:
logging.info('=====2======') 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_install_time = {'Nomal': '正常', 'Warning': '报警'}
# tool.write({
# 'functional_tool_status': tool_install_time.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: except Exception as e:
res = {'Succeed': False, 'ErrorCode': 202, 'Error': e} res = {'Succeed': False, 'ErrorCode': 202, 'Error': e}
logging.info('LocationChange error:%s' % e) logging.info('LocationChange error:%s' % e)

View File

@@ -20,7 +20,8 @@
'views/sale_order_view.xml', 'views/sale_order_view.xml',
'views/res_partner_view.xml', 'views/res_partner_view.xml',
'views/purchase_order_view.xml', 'views/purchase_order_view.xml',
'views/quick_easy_order_view.xml' 'views/quick_easy_order_view.xml',
'views/purchase_menu.xml'
], ],
'assets': { 'assets': {
'web.assets_backend': [ 'web.assets_backend': [

View File

@@ -13,6 +13,11 @@ READONLY_FIELD_STATES = {
class ReSaleOrder(models.Model): class ReSaleOrder(models.Model):
_inherit = 'sale.order' _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='物流方式') logistics_way = fields.Selection([('自提', '自提'), ('到付', '到付'), ('在线支付', '在线支付')], string='物流方式')
state = fields.Selection( state = fields.Selection(
selection=[ selection=[

View File

@@ -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_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
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
96 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
97 access_sale_order_sf_base_group_purchase sale_order_sf_base_group_purchase model_sale_order sf_base.group_purchase 1 0 0 0
98 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
99 access_quality_check_group_sale_salemanager quality_check_group_sale_salemanager quality.model_quality_check sf_base.group_sale_salemanager 1 0 0 0
100 access_quality_check_group_sale_director quality_check_group_sale_director quality.model_quality_check sf_base.group_sale_director 1 0 0 0
101 access_stock_picking_group_sale_salemanager stock_picking_group_sale_salemanager stock.model_stock_picking sf_base.group_sale_salemanager 1 0 0 0
102 access_stock_picking_group_sale_director stock_picking_group_sale_director stock.model_stock_picking sf_base.group_sale_director 1 0 0 0
103 access_mrp_workorder_group_sale_salemanager mrp_workorder_group_sale_salemanager mrp.model_mrp_workorder sf_base.group_sale_salemanager 1 0 0 0
104 access_mrp_workorder_group_sale_director mrp_workorder_group_sale_director mrp.model_mrp_workorder sf_base.group_sale_director 1 0 0 0
105 access_mrp_unbuild_group_sale_salemanager mrp_unbuild_group_sale_salemanager mrp.model_mrp_unbuild sf_base.group_sale_salemanager 1 0 0 0
106 access_mrp_unbuild_group_sale_director mrp_unbuild_group_sale_director mrp.model_mrp_unbuild sf_base.group_sale_director 1 0 0 0
107 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
108 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
109 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
110 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
111 access_stock_scrap_group_sale_salemanager stock_scrap_group_sale_salemanager stock.model_stock_scrap sf_base.group_sale_salemanager 1 0 0 0
112 access_stock_scrap_group_sale_director stock_scrap_group_sale_director stock.model_stock_scrap sf_base.group_sale_director 1 0 0 0
113
114
115
116
117
118
119
120
121
122
123

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!-- 采购-产品 -->
<menuitem id="purchase.menu_purchase_products" name="Products" parent="purchase.menu_purchase_root"
groups="sf_base.group_purchase_director,sf_base.group_purchase"
sequence="5"/>
<!-- 采购-产品-产品 -->
<menuitem id="purchase.menu_procurement_partner_contact_form" name="Products"
action="purchase.product_normal_action_puchased" parent="purchase.menu_purchase_products"
groups="sf_base.group_purchase_director,sf_base.group_purchase"
sequence="20"/>
<!-- 采购-报表 -->
<menuitem id="purchase.purchase_report_main" name="Reporting" parent="purchase.menu_purchase_root" sequence="99"
groups="purchase.group_purchase_manager,sf_base.group_purchase_director,sf_base.group_purchase"/>
<!-- 采购-报表-采购 -->
<menuitem id="purchase.purchase_report" name="Purchase" parent="purchase.purchase_report_main" sequence="99"
groups="purchase.group_purchase_manager,sf_base.group_purchase_director,sf_base.group_purchase"
action="purchase.action_purchase_order_report_all"/>
</odoo>

View File

@@ -86,6 +86,18 @@
</attribute> </attribute>
</xpath> </xpath>
<xpath expr="//form/sheet/div[@name='button_box']/button[@name='action_view_picking']"
position="replace">
<button type="object"
name="action_view_picking"
class="oe_stat_button"
icon="fa-truck" attrs="{'invisible':[('incoming_picking_count','=', 0)]}"
groups="stock.group_stock_user,sf_base.group_purchase,sf_base.group_purchase_director">
<field name="incoming_picking_count" widget="statinfo" string="收货"
help="Incoming Shipments"/>
</button>
</xpath>
<xpath expr="//field[@name='order_line']" position="attributes"> <xpath expr="//field[@name='order_line']" position="attributes">
<attribute name="attrs">{'readonly': [('state', 'in', ['purchase'])]} <attribute name="attrs">{'readonly': [('state', 'in', ['purchase'])]}
</attribute> </attribute>

View File

@@ -6,6 +6,13 @@
<field name="model">sale.order</field> <field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form"/> <field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//button[@name='action_view_delivery']" position="attributes">
<attribute name="groups">sf_base.group_sale_salemanager,sf_base.group_sale_director</attribute>
</xpath>
<xpath expr="//button[@name='action_view_mrp_production']" position="attributes">
<attribute name="groups">mrp.group_mrp_user,sf_base.group_sale_salemanager,sf_base.group_sale_director
</attribute>
</xpath>
<xpath expr="//field[@name='user_id']" position="replace"> <xpath expr="//field[@name='user_id']" position="replace">
<field name="user_id" widget="many2one_avatar_user" context="{'is_sale': True }"/> <field name="user_id" widget="many2one_avatar_user" context="{'is_sale': True }"/>
</xpath> </xpath>
@@ -35,12 +42,12 @@
<xpath expr="//form/header/button[@name='action_confirm'][2]" position="replace"> <xpath expr="//form/header/button[@name='action_confirm'][2]" position="replace">
<button name="action_confirm" data-hotkey="v" <button name="action_confirm" data-hotkey="v"
string="确认接单" type="object" context="{'validate_analytic': True}" string="确认接单" type="object" context="{'validate_analytic': True}"
attrs="{'invisible': ['|','&amp;',('check_status', '!=', 'approved'),('state', 'in', ['draft','cancel']),'&amp;','&amp;',('check_status', '=', 'approved'),('state', 'in', ['sale','cancel']),('delivery_status', '!=', False)]}"/> attrs="{'invisible': ['|','&amp;','|',('check_status', '!=', 'approved'),('state', 'in', ['draft','cancel']),'&amp;','&amp;',('check_status', '=', 'approved'),('state', 'in', ['sale','cancel']),('delivery_status', '!=', False),('state', 'in', ['cancel'])]}"/>
</xpath> </xpath>
<xpath expr="//form/header/button[@name='action_cancel']" position="attributes"> <xpath expr="//form/header/button[@name='action_cancel']" position="attributes">
<attribute name="attrs">{'invisible': ['|','&amp;',('check_status', '!=', 'approved'),('state', <attribute name="attrs">{'invisible': ['|','&amp;','|', ('check_status', '!=', 'approved'),('state',
'in', ['draft','cancel']),'&amp;','&amp;',('check_status', '=', 'approved'),('state', 'in', 'in', ['draft','cancel']),'&amp;','&amp;',('check_status', '=', 'approved'),('state', 'in',
['sale','cancel']),('delivery_status', '!=', False)]} ['sale','cancel']),('delivery_status', '!=', False), ('state', 'in', ['cancel'])]}
</attribute> </attribute>
</xpath> </xpath>
<xpath expr="//form/header/button[@name='action_draft']" position="attributes"> <xpath expr="//form/header/button[@name='action_draft']" position="attributes">

View File

@@ -94,47 +94,47 @@ class MachineTableToolChangingApply(models.Model):
if len(records) > 1: if len(records) > 1:
raise ValidationError('该刀位号已存在,请重新选择!!!') raise ValidationError('该刀位号已存在,请重新选择!!!')
@api.constrains('functional_tool_status') # @api.constrains('functional_tool_status')
def automation_apply_for_tool_change(self): # def automation_apply_for_tool_change(self):
""" # """
自动申请换刀 # 自动申请换刀
:return: # :return:
""" # """
# 更新数据到机台换刀申请界面 # # 更新数据到机台换刀申请界面
if self.functional_tool_status == '报警' and not self.sf_functional_tool_assembly_id: # 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( # machine_table_tool_changing_apply = self.env['sf.machine.table.tool.changing.apply'].search(
[('maintenance_equipment_id', '=', self.maintenance_equipment_id.id), # [('maintenance_equipment_id', '=', self.maintenance_equipment_id.id),
('cutter_spacing_code_id', '=', self.cutter_spacing_code_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}) # 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({ # sf_functional_tool_assembly = self.env['sf.functional.tool.assembly'].create({
'functional_tool_name': self.functional_tool_name, # 'functional_tool_name': self.functional_tool_name,
'functional_tool_type_id': self.functional_tool_type_id.id, # 'functional_tool_type_id': self.functional_tool_type_id.id,
'functional_tool_diameter': self.diameter, # 'functional_tool_diameter': self.diameter,
'knife_tip_r_angle': self.knife_tip_r_angle, # 'knife_tip_r_angle': self.knife_tip_r_angle,
'coarse_middle_thin': '3', # 'coarse_middle_thin': '3',
'new_former': '0', # 'new_former': '0',
'functional_tool_length': self.extension_length, # 'functional_tool_length': self.extension_length,
'effective_length': self.effective_length, # 'effective_length': self.effective_length,
'loading_task_source': '1', # 'loading_task_source': '1',
'use_tool_time': fields.Datetime.now() + timedelta(hours=4), # 'use_tool_time': fields.Datetime.now() + timedelta(hours=4),
'production_line_name_id': self.production_line_id.id, # 'production_line_name_id': self.production_line_id.id,
'machine_tool_name_id': self.maintenance_equipment_id.id, # 'machine_tool_name_id': self.maintenance_equipment_id.id,
'applicant': '系统自动', # 'applicant': '系统自动',
'apply_time': fields.Datetime.now(), # 'apply_time': fields.Datetime.now(),
'cutter_spacing_code_id': self.cutter_spacing_code_id.id, # 'cutter_spacing_code_id': self.cutter_spacing_code_id.id,
'whether_standard_knife': self.whether_standard_knife, # 'whether_standard_knife': self.whether_standard_knife,
'reason_for_applying': '机台报警自动换刀', # 'reason_for_applying': '机台报警自动换刀',
'sf_machine_table_tool_changing_apply_id': self.id # 'sf_machine_table_tool_changing_apply_id': self.id
}) # })
#
machine_table_tool_changing_apply.write( # machine_table_tool_changing_apply.write(
{'status': '1', # {'status': '1',
'sf_functional_tool_assembly_id': sf_functional_tool_assembly.id}) # 'sf_functional_tool_assembly_id': sf_functional_tool_assembly.id})
def revocation_1(self): 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, functional_tool_id = fields.Many2one('sf.functional.cutting.tool.entity', '功能刀具', required=True, tracking=True,
domain=[('functional_tool_status', '!=', '已拆除'), domain=[('functional_tool_status', '!=', '已拆除'),
('current_location', '=', '刀具房')]) ('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, tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', store=True,
compute='_compute_functional_tool_num') compute='_compute_functional_tool_num')
tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', compute='_compute_functional_tool_num', store=True) 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: if self.chuck_freight_id == self.pad_freight_id:
raise ValidationError('【夹头】和【刀盘】的目标货位重复,请重新选择!') raise ValidationError('【夹头】和【刀盘】的目标货位重复,请重新选择!')
def tool_scrap(self):
self.scrap_boolean = True
def tool_no_scrap(self):
self.scrap_boolean = False
def confirmation_disassembly(self): def confirmation_disassembly(self):
logging.info('%s刀具确认开始拆解' % self.dismantle_cause) logging.info('%s刀具确认开始拆解' % self.dismantle_cause)
code = self.code code = self.code
if self.functional_tool_id.functional_tool_status == '已拆除': 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: elif self.functional_tool_id.functional_tool_status != '报警':
raise ValidationError('Rfid为【%s】的功能刀具当前位置为【%s】,不能进行拆解!' % ( if self.functional_tool_id.tool_room_num == 0:
self.rfid, self.functional_tool_id.current_location)) raise ValidationError('Rfid为【%s】的功能刀具当前位置为【%s】,不能进行拆解!' % (
self.rfid, self.functional_tool_id.current_location))
# 目标重复校验 # 目标重复校验
self.location_duplicate_check() self.location_duplicate_check()
datas = {'scrap': [], 'picking': []} datas = {'scrap': [], 'picking': []}
@@ -1005,6 +1022,14 @@ class FunctionalToolDismantle(models.Model):
'rfid': '%s(已拆解)' % self.rfid, 'rfid': '%s(已拆解)' % self.rfid,
'state': '已拆解' '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) logging.info('%s】刀具拆解成功!' % self.name)
def create_tool_picking_scrap(self, datas): def create_tool_picking_scrap(self, datas):

View File

@@ -11,6 +11,7 @@ from odoo.exceptions import ValidationError
class FunctionalCuttingToolEntity(models.Model): class FunctionalCuttingToolEntity(models.Model):
_name = 'sf.functional.cutting.tool.entity' _name = 'sf.functional.cutting.tool.entity'
_description = '功能刀具列表' _description = '功能刀具列表'
_order = 'functional_tool_status'
functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', string='功能刀具组装单', readonly=True) functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', string='功能刀具组装单', readonly=True)
@@ -40,7 +41,7 @@ class FunctionalCuttingToolEntity(models.Model):
max_lifetime_value = fields.Integer(string='最大寿命值(min)', readonly=True) max_lifetime_value = fields.Integer(string='最大寿命值(min)', readonly=True)
alarm_value = fields.Integer(string='报警值(min)', readonly=True) alarm_value = fields.Integer(string='报警值(min)', readonly=True)
used_value = fields.Integer(string='已使用值(min)', readonly=True) used_value = fields.Integer(string='已使用值(min)', readonly=True)
functional_tool_status = fields.Selection([('正常', '正常'), ('报警', '报警'), ('已拆除', '已拆除')], functional_tool_status = fields.Selection([('报警', '报警'), ('正常', '正常'), ('已拆除', '已拆除')],
string='状态', store=True, default='正常') string='状态', store=True, default='正常')
current_location_id = fields.Many2one('stock.location', string='当前位置', compute='_compute_current_location_id', current_location_id = fields.Many2one('stock.location', string='当前位置', compute='_compute_current_location_id',
store=True) store=True)
@@ -53,6 +54,22 @@ class FunctionalCuttingToolEntity(models.Model):
safe_inventory_id = fields.Many2one('sf.real.time.distribution.of.functional.tools', safe_inventory_id = fields.Many2one('sf.real.time.distribution.of.functional.tools',
string='功能刀具安全库存', readonly=True) 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', @api.depends('barcode_id.quant_ids', 'barcode_id.quant_ids.location_id', 'functional_tool_status',
'current_shelf_location_id') 'current_shelf_location_id')
def _compute_current_location_id(self): def _compute_current_location_id(self):
@@ -101,27 +118,28 @@ class FunctionalCuttingToolEntity(models.Model):
def tool_in_out_stock_location(self, location_id): def tool_in_out_stock_location(self, location_id):
tool_room_id = self.env['stock.location'].search([('name', '=', '刀具房')]) tool_room_id = self.env['stock.location'].search([('name', '=', '刀具房')])
pre_manufacturing_id = self.env['stock.location'].search([('name', '=', '制造前')]) pre_manufacturing_id = self.env['stock.location'].search([('name', '=', '制造前')])
for item in self: if self:
# 中控反馈该位置有刀 for item in self:
if item: # 中控反馈该位置有刀
# 系统该位置有刀 if item:
if location_id.product_sn_id: # 系统该位置有刀
# 中控反馈和系统中,该位置是同一把刀 if location_id.product_sn_id:
if item.barcode_id == location_id.product_sn_id: # 中控反馈和系统中,该位置是同一把刀
return True if item.barcode_id == location_id.product_sn_id:
# 中控反馈和系统中,该位置不是同一把刀 return True
else: # 中控反馈和系统中,该位置不是同一把刀
# 原刀从线边出库 else:
item.tool_in_out_stock_location_1(location_id, tool_room_id) # 原刀从线边出库
# 新刀入库到线边 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 item.create_stock_move(pre_manufacturing_id, location_id)
item.current_shelf_location_id = location_id.id
# 中控反馈该位置没有刀 # 中控反馈该位置没有刀
else: else:
# 系统该位置有刀 # 系统该位置有刀
if location_id.product_sn_id: if location_id.product_sn_id:
item.tool_in_out_stock_location_1(location_id, tool_room_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): def tool_in_out_stock_location_1(self, location_id, tool_room_id):
tool = self.env['sf.functional.cutting.tool.entity'].search( tool = self.env['sf.functional.cutting.tool.entity'].search(
@@ -238,10 +256,30 @@ class FunctionalCuttingToolEntity(models.Model):
functional_tool_model_ids.append(functional_tool_model.id) functional_tool_model_ids.append(functional_tool_model.id)
return [(6, 0, functional_tool_model_ids)] return [(6, 0, functional_tool_model_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): def open_functional_tool_warning(self):
action = self.env.ref('sf_tool_management.action_sf_functional_tool_warning') action = self.env.ref('sf_tool_management.action_sf_functional_tool_warning')
result = action.read()[0] 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 return result
def open_stock_move_line(self): def open_stock_move_line(self):
@@ -323,10 +361,10 @@ class FunctionalToolWarning(models.Model):
_name = 'sf.functional.tool.warning' _name = 'sf.functional.tool.warning'
_description = '功能刀具预警' _description = '功能刀具预警'
code = fields.Char('编码', related='functional_tool_name_id.code') code = fields.Char('编码', related='functional_tool_id.code')
rfid = fields.Char('Rfid', related='functional_tool_name_id.rfid') rfid = fields.Char('Rfid', readonly=True)
tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', related='functional_tool_name_id.tool_groups_id') 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_name_id.name') name = fields.Char('名称', invisible=True, readonly=True, related='functional_tool_id.name')
# 机床信息 # 机床信息
production_line_id = fields.Many2one('sf.production.line', string='生产线', production_line_id = fields.Many2one('sf.production.line', string='生产线',
group_expand='_read_group_machine_table_name_ids') group_expand='_read_group_machine_table_name_ids')
@@ -337,52 +375,77 @@ class FunctionalToolWarning(models.Model):
cutter_spacing_code_id = fields.Many2one('maintenance.equipment.tool', string='刀位号', cutter_spacing_code_id = fields.Many2one('maintenance.equipment.tool', string='刀位号',
domain="[('equipment_id', '=', maintenance_equipment_id)]") domain="[('equipment_id', '=', maintenance_equipment_id)]")
# 功能刀具信息 # 功能刀具信息
functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', string='功能刀具名称') functional_tool_id = fields.Many2one('sf.functional.cutting.tool.entity', string='功能刀具', readonly=True)
barcode_id = fields.Many2one('stock.lot', string='功能刀具序列号', related='functional_tool_name_id.barcode_id') 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='功能刀具类型') mrs_cutting_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型',
diameter = fields.Float(string='刀具直径(mm)') related='functional_tool_id.sf_cutting_tool_type_id')
knife_tip_r_angle = fields.Float(string='尖R角(mm)') 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') install_tool_time = fields.Datetime("刀具组装时间", related='functional_tool_name_id.tool_loading_time')
on_board_time = fields.Datetime('上机装刀时间') on_board_time = fields.Datetime('上机装刀时间')
max_lifetime_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)') alarm_value = fields.Integer(string='报警值(min)', related='functional_tool_id.alarm_value')
used_value = fields.Integer(string='已使用值(min)') used_value = fields.Integer(string='已使用值(min)', related='functional_tool_id.used_value')
functional_tool_status = fields.Selection([('正常', '正常'), ('报警', '报警'), ('已拆除', '已拆除')], string='状态') functional_tool_status = fields.Selection([('正常', '正常'), ('报警', '报警'), ('已拆除', '已拆除')], string='状态')
alarm_time = fields.Datetime('报警时间') alarm_time = fields.Datetime('报警时间', default=lambda self: fields.Datetime.now(), readonly=True)
dispose_user = fields.Char('处理人') dispose_user = fields.Char('处理人', readonly=True)
dispose_time = fields.Char('处理时间') dispose_time = fields.Char('处理时间', readonly=True)
dispose_func = fields.Char('处理方法/措施', readonly=False) dispose_func = fields.Char('处理方法/措施', readonly=True)
active = fields.Boolean(string='已归档', default=True) active = fields.Boolean(string='已归档', default=True)
functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', string='功能刀具名称')
@api.model @api.model
def _read_group_machine_table_name_ids(self, categories, domain, order): def _read_group_machine_table_name_ids(self, categories, domain, order):
machine_table_name_ids = categories._search([], order=order, access_rights_uid=SUPERUSER_ID) machine_table_name_ids = categories._search([], order=order, access_rights_uid=SUPERUSER_ID)
return categories.browse(machine_table_name_ids) return categories.browse(machine_table_name_ids)
def create_tool_warning_record(self, obj): 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)])
if obj: action = {
for tool in obj.get('tool_changing_apply_id'): 'res_model': 'sf.functional.tool.dismantle',
self.env['sf.functional.tool.warning'].create({ 'type': 'ir.actions.act_window',
'production_line_id': tool.production_line_id.id, 'name': '拆解单'
'maintenance_equipment_id': tool.maintenance_equipment_id.id, }
'machine_tool_code': tool.machine_tool_code, if len(dismantle_ids) == 1:
'machine_table_type_id': tool.machine_table_type_id.id, action.update({
'cutter_spacing_code_id': tool.cutter_spacing_code_id.id, 'view_mode': 'form',
'functional_tool_name_id': tool.functional_tool_name_id.id, 'res_id': dismantle_ids.ids[0]
'barcode_id': tool.barcode_id.id, })
'diameter': tool.diameter, elif dismantle_ids:
'knife_tip_r_angle': tool.knife_tip_r_angle, action.update({
'max_lifetime_value': tool.max_lifetime_value, 'view_mode': 'tree,form',
'alarm_value': tool.alarm_value, 'domain': [('id', 'in', dismantle_ids.ids)],
'used_value': tool.used_value, })
'functional_tool_status': tool.functional_tool_status, else:
'alarm_time': fields.Datetime.now(), 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): class StockMoveLine(models.Model):

View File

@@ -53,7 +53,7 @@ class SfMaintenanceEquipment(models.Model):
params = {"DeviceId": self.name} params = {"DeviceId": self.name}
r = requests.get(crea_url, params=params, headers=headers) r = requests.get(crea_url, params=params, headers=headers)
ret = r.json() ret = r.json()
logging.info('register_equipment_tool:%s' % ret) logging.info('机床刀库register_equipment_tool():%s' % ret)
datas = ret['Datas'] datas = ret['Datas']
self.write_maintenance_equipment_tool(datas) self.write_maintenance_equipment_tool(datas)
if ret['Succeed']: if ret['Succeed']:

View File

@@ -25,7 +25,10 @@
<field name="max_lifetime_value"/> <field name="max_lifetime_value"/>
<field name="alarm_value"/> <field name="alarm_value"/>
<field name="used_value"/> <field name="used_value"/>
<field name="functional_tool_status"/> <field name="functional_tool_status" widget='badge'
decoration-success="functional_tool_status == '正常'"
decoration-muted="functional_tool_status == '已拆除'"
decoration-danger="functional_tool_status == '报警'"/>
<field name="current_location" string="当前位置"/> <field name="current_location" string="当前位置"/>
<field name="current_location_id" invisible="1"/> <field name="current_location_id" invisible="1"/>
@@ -48,6 +51,16 @@
<div class="oe_button_box" name="button_box"> <div class="oe_button_box" name="button_box">
<!-- <button name="button_safe_inventory_id" string="更新功能刀具关联的安全库存记录"--> <!-- <button name="button_safe_inventory_id" string="更新功能刀具关联的安全库存记录"-->
<!-- type="object" class="btn-primary"/>--> <!-- type="object" class="btn-primary"/>-->
<button class="oe_stat_button" groups="sf_base.group_sf_mrp_user"
name="open_functional_tool_dismantle_form"
icon="fa-list-ul"
type="object">
<div class="o_field_widget o_stat_info">
<span>
拆解单
</span>
</div>
</button>
<button class="oe_stat_button" groups="sf_base.group_sf_mrp_user" <button class="oe_stat_button" groups="sf_base.group_sf_mrp_user"
name="open_functional_tool_warning" name="open_functional_tool_warning"
icon="fa-list-ul" icon="fa-list-ul"
@@ -235,26 +248,29 @@
<field name="name">sf.functional.tool.warning.tree</field> <field name="name">sf.functional.tool.warning.tree</field>
<field name="model">sf.functional.tool.warning</field> <field name="model">sf.functional.tool.warning</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="功能刀具预警" create="0" edit="0" delete="0" editable="bottom"> <tree string="功能刀具预警" create="0" edit="0" delete="0" editable="bottom" default_order="id desc"
<field name="production_line_id" optional="hide"/> action="action_open_dismantle" type="object">
<field name="maintenance_equipment_id" optional="hide"/> <field name="production_line_id" invisible="1"/>
<field name="machine_tool_code"/> <field name="maintenance_equipment_id" invisible="1"/>
<field name="cutter_spacing_code_id"/> <field name="machine_tool_code" invisible="1"/>
<field name="barcode_id" invisible="1"/> <field name="cutter_spacing_code_id" invisible="1"/>
<field name="on_board_time" invisible="1"/>
<field name="functional_tool_status" invisible="1"/>
<field name="functional_tool_name_id" invisible="1"/>
<field name="rfid"/> <field name="rfid"/>
<field name="functional_tool_name_id"/> <field name="functional_tool_id"/>
<field name="diameter"/> <field name="barcode_id" optional="hide"/>
<field name="knife_tip_r_angle"/> <field name="diameter" optional="hide"/>
<field name="knife_tip_r_angle" optional="hide"/>
<field name="install_tool_time" optional="hide"/> <field name="install_tool_time" optional="hide"/>
<field name="on_board_time" optional="hide"/>
<field name="max_lifetime_value"/> <field name="max_lifetime_value"/>
<field name="alarm_value"/> <field name="alarm_value"/>
<field name="used_value"/> <field name="used_value"/>
<field name="functional_tool_status"/>
<field name="alarm_time"/> <field name="alarm_time"/>
<field name="dispose_user"/> <field name="dispose_user"/>
<field name="dispose_time"/> <field name="dispose_time"/>
<field name="dispose_func"/> <field name="dispose_func" optional="hide"/>
<!-- <button name="enroll_functional_tool_warning" string="刀具预警注册" type="object"--> <!-- <button name="enroll_functional_tool_warning" string="刀具预警注册" type="object"-->
<!-- class="btn-primary"/>--> <!-- class="btn-primary"/>-->
</tree> </tree>
@@ -266,31 +282,19 @@
<field name="model">sf.functional.tool.warning</field> <field name="model">sf.functional.tool.warning</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<search string="功能刀具预警"> <search string="功能刀具预警">
<field name="machine_tool_code"/>
<field name="cutter_spacing_code_id"/>
<field name="barcode_id"/> <field name="barcode_id"/>
<field name="rfid"/> <field name="rfid"/>
<field name="functional_tool_name_id"/> <field name="functional_tool_name_id"/>
<field name="diameter"/>
<field name="knife_tip_r_angle"/>
<field name="install_tool_time" optional="hide"/>
<field name="on_board_time" optional="hide"/>
<field name="max_lifetime_value"/>
<field name="alarm_value"/>
<field name="used_value"/>
<field name="functional_tool_status"/>
<field name="alarm_time"/>
<field name="dispose_user"/>
<field name="dispose_time"/>
<field name="dispose_func"/>
<field name="production_line_id" invisible="True"/>
<filter string="已归档" name="inactive" domain="[('active', '=', False)]"/>
<searchpanel> <searchpanel>
<field name="production_line_id" icon="fa-building" enable_counters="1"/> <field name="production_line_id" icon="fa-building" enable_counters="1"/>
<field name="maintenance_equipment_id" icon="fa-building" enable_counters="1"/> <field name="maintenance_equipment_id" icon="fa-building" enable_counters="1"/>
<field name="cutter_spacing_code_id" icon="fa-building" enable_counters="1"/> <field name="cutter_spacing_code_id" icon="fa-building" enable_counters="1"/>
<field name="functional_tool_status" icon="fa-building" enable_counters="1"/> <field name="functional_tool_status" icon="fa-building" enable_counters="1"/>
</searchpanel> </searchpanel>
<group expand="0">
<filter string="报警时间" name="alarm_time" domain="[]"
context="{'group_by': 'alarm_time'}"/>
</group>
</search> </search>
</field> </field>
</record> </record>

View File

@@ -704,10 +704,10 @@
<field name="model">sf.functional.tool.assembly</field> <field name="model">sf.functional.tool.assembly</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<search> <search>
<field name="functional_tool_name"/>
<field name="assembly_order_code"/> <field name="assembly_order_code"/>
<field name="code" string="功能刀具编码"/> <field name="code" string="功能刀具编码"/>
<field name="barcode_id"/> <field name="barcode_id"/>
<field name="functional_tool_name"/>
<field name="functional_tool_type_id"/> <field name="functional_tool_type_id"/>
<field name="tool_groups_id"/> <field name="tool_groups_id"/>
<field name="loading_task_source" string="任务来源"/> <field name="loading_task_source" string="任务来源"/>
@@ -800,10 +800,16 @@
</h1> </h1>
</div> </div>
<field name="_barcode_scanned" widget="barcode_handler"/> <field name="_barcode_scanned" widget="barcode_handler"/>
<script>
setTimeout(function(){
$('#functional_tool_id').blur()
}, 100)
</script>
<group> <group>
<group> <group>
<field name="functional_tool_id" placeholder="请选择将要拆解的功能刀具" <field name="functional_tool_id" placeholder="请选择将要拆解的功能刀具"
options="{'no_create': True}" attrs="{'readonly': [('state', '=', '已拆解')]}"/> options="{'no_create': True}"
attrs="{'readonly': ['|',('state', '=', '已拆解'),('id', '!=', False)]}"/>
<field name="rfid" attrs="{'invisible': [('rfid', '=', '')]}"/> <field name="rfid" attrs="{'invisible': [('rfid', '=', '')]}"/>
<field name="rfid_dismantle" attrs="{'invisible': [('rfid_dismantle', '=', False)]}"/> <field name="rfid_dismantle" attrs="{'invisible': [('rfid_dismantle', '=', False)]}"/>
<field name="tool_type_id"/> <field name="tool_type_id"/>
@@ -833,10 +839,26 @@
<notebook> <notebook>
<page string="物料组装信息"> <page string="物料组装信息">
<group> <group>
<group string="刀柄" attrs="{'invisible': [('handle_product_id', '=', False)]}"> <group string="刀柄" attrs="{'invisible': [('handle_product_id', '=', False)]}"
col="1">
<group attrs="{'invisible': [('dismantle_cause', 'not in', ['寿命到期报废','崩刀报废'])]}">
<group col="3">
<group>
<field name="scrap_boolean" string="是否报废"/>
</group>
<group></group>
<group>
<button string="报废" name="tool_scrap" type="object"
class="btn-primary" confirm="是否确认报废刀柄"
attrs="{'invisible': [('scrap_boolean', '=', True)]}"/>
<button string="取消" name="tool_no_scrap" type="object"
class="btn-primary" confirm="是否取消报废刀柄"
attrs="{'invisible': [('scrap_boolean', '=', False)]}"/>
<group></group>
</group>
</group>
</group>
<group> <group>
<field name="scrap_boolean" string="是否报废"
attrs="{'invisible': [('dismantle_cause', 'not in', ['寿命到期报废','崩刀报废'])], 'readonly': [('state', '=', '已拆解')]}"/>
<field name="handle_rfid" string="Rfid"/> <field name="handle_rfid" string="Rfid"/>
<field name="handle_lot_id" string="序列号"/> <field name="handle_lot_id" string="序列号"/>
<field name="handle_product_id" string="名称"/> <field name="handle_product_id" string="名称"/>
@@ -911,7 +933,7 @@
</group> </group>
</group> </group>
</page> </page>
<page string="报废" <page string="报废"
attrs="{'invisible':[('dismantle_cause', 'not in', ['寿命到期报废','崩刀报废'])]}"> attrs="{'invisible':[('dismantle_cause', 'not in', ['寿命到期报废','崩刀报废'])]}">
<field name="scrap_ids"> <field name="scrap_ids">
<tree> <tree>
@@ -952,8 +974,9 @@
<field name="model">sf.functional.tool.dismantle</field> <field name="model">sf.functional.tool.dismantle</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<search> <search>
<field name="rfid"/>
<field name="functional_tool_id"/> <field name="functional_tool_id"/>
<field name="code" string="拆解单编码"/> <field name="code" string="拆解单"/>
<filter name="no_dismantle_state" string="未拆解" domain="[('state','!=','已拆解')]"/> <filter name="no_dismantle_state" string="未拆解" domain="[('state','!=','已拆解')]"/>
<filter name="dismantle_state" string="已拆解" domain="[('state','=','已拆解')]"/> <filter name="dismantle_state" string="已拆解" domain="[('state','=','已拆解')]"/>
<separator/> <separator/>

View File

@@ -842,6 +842,8 @@ class StockPicking(models.Model):
stock_move_id = self.env['stock.move'] stock_move_id = self.env['stock.move']
datas = {'data': [], 'picking_id': picking_id} datas = {'data': [], 'picking_id': picking_id}
if obj.handle_code_id: if obj.handle_code_id:
# 修改刀柄序列号状态为【在用】
obj.handle_code_id.sudo().write({'tool_material_status': '在用'})
datas['data'].append( datas['data'].append(
{'current_location_id': self.env['sf.shelf.location'], 'lot_id': obj.handle_code_id}) {'current_location_id': self.env['sf.shelf.location'], 'lot_id': obj.handle_code_id})
if obj.integral_product_id: if obj.integral_product_id:

View File

@@ -201,6 +201,11 @@
</group> </group>
</group> </group>
</group> </group>
<script>
setTimeout(function(){
$('#handle_code_id').blur()
}, 100)
</script>
<group string="组装物料信息" col="1"> <group string="组装物料信息" col="1">
<field name="_barcode_scanned" widget="barcode_handler"/> <field name="_barcode_scanned" widget="barcode_handler"/>
<group col="1"> <group col="1">
@@ -368,7 +373,7 @@
<group> <group>
<field name="obtain_measurement_status" invisible="1"/> <field name="obtain_measurement_status" invisible="1"/>
<button name="get_tool_preset_parameter" string="获取测量值" type="object" <button name="get_tool_preset_parameter" string="获取测量值" type="object"
attrs="{'invisible': [('enable_tool_presetter', '=', False)]}" attrs="{'invisible': [('enable_tool_presetter', '=', False)]}"
class="btn-primary"/> class="btn-primary"/>
</group> </group>
</group> </group>

View File

@@ -507,13 +507,13 @@ class ShelfLocation(models.Model):
print('eeeeeee空闲', e) 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() config = self.env['res.config.settings'].get_values()
headers = {'Authorization': config['center_control_Authorization']} headers = {'Authorization': config['center_control_Authorization']}
crea_url = config['center_control_url'] + "/AutoDeviceApi/GetLocationInfos" 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) r = requests.get(crea_url, params=params, headers=headers)
ret = r.json() ret = r.json()

View File

@@ -13,88 +13,92 @@ class MrsShelfLocationDataSync(models.Model):
_name = 'sf.shelf.location.datasync' _name = 'sf.shelf.location.datasync'
_description = '同步库存信息' _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): def _cron_shelf_location_datasync(self):
try: 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): def find_their_code(my_code, aligned_data):
for code_pair in aligned_data: for code_pair in aligned_data:
if code_pair[0] == my_code: if code_pair[0] == my_code:
return code_pair[1] return code_pair[1]
return None # 如果没有找到对应的值返回None或适当的默认值 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_ids = self.env['maintenance.equipment'].search(
[('equipment_type', '=', '机床'), ('function_type', '!=', False)]) [('equipment_type', '=', '机床'), ('function_type', '!=', False)])
@@ -103,9 +107,10 @@ class MrsShelfLocationDataSync(models.Model):
equipment_id.register_equipment_tool() equipment_id.register_equipment_tool()
shelfinfo = self.env['sf.shelf.location'].get_sf_shelf_location_info() shelfinfo = self.env['sf.shelf.location'].get_sf_shelf_location_info()
total_data = self.get_total_data()
print('shelfinfo:', shelfinfo) print('shelfinfo:', shelfinfo)
for item in 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) location_id = self.env['sf.shelf.location'].search([('barcode', '=', shelf_barcode)], limit=1)
if location_id: if location_id:
# 如果是线边刀库信息,则对功能刀具移动生成记录 # 如果是线边刀库信息,则对功能刀具移动生成记录
@@ -115,6 +120,11 @@ class MrsShelfLocationDataSync(models.Model):
tool.tool_in_out_stock_location(location_id) tool.tool_in_out_stock_location(location_id)
if tool: if tool:
location_id.product_sn_id = tool.barcode_id.id location_id.product_sn_id = tool.barcode_id.id
# 修改功能刀具状态
# tool_install_time = {'Nomal': '正常', 'Warning': '报警'}
# tool.write({
# 'functional_tool_status': tool_install_time.get(item['State'])
# })
else: else:
location_id.product_sn_id = False location_id.product_sn_id = False
else: else: