Compare commits

..

42 Commits

Author SHA1 Message Date
马广威
9e56aeda67 Accept Merge Request #1093: (release/release_1.8 -> master)
Merge Request: 功能刀具、工件状态优化

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1093?initial=true
2024-06-24 21:38:15 +08:00
jinling.yang
828b4b0f6b 修复功能刀具清单列表 2024-06-24 16:55:42 +08:00
jinling.yang
ec30a07394 修复创建移动历史记录 2024-06-24 14:54:33 +08:00
jinling.yang
e453508f17 修改功能刀具清单查询列表:部分字段不可更改 2024-06-24 14:18:42 +08:00
jinling.yang
de6014d1dd 修复工件上下产线接口:当RFID不为空时,更改制造订单上下产线状态 2024-06-21 17:39:15 +08:00
马广威
ecf265fee7 Accept Merge Request #1084: (release/release1.7 -> master)
Merge Request: 迭代库存、制造逻辑

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1084?initial=true
2024-06-19 20:24:20 +08:00
yuxianghui
60560fe195 1、优化工单解绑Rfid 2024-06-19 17:40:49 +08:00
yuxianghui
21f2a704db 1、对刀仪接口获取的功能刀具半径值乘二后再赋值 2024-06-19 17:03:44 +08:00
yuxianghui
c0b673bfd0 添加注释 2024-06-19 11:23:25 +08:00
yuxianghui
6dae144d76 1、功能刀具拆解单优化;2、完成 需求坯料序列号生成规则优化2; 2024-06-19 11:19:47 +08:00
yuxianghui
4497fb04c1 1、优化 托盘绑定工单逻辑优化 ;2 完成 整体式刀具批次/序列号生成的优化需求; 3、完成 坯料序列号生成规则优化需求1。 2024-06-18 17:19:41 +08:00
马广威
903fdee420 Accept Merge Request #1081: (release/release1.6 -> master)
Merge Request: 功能升级

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1081?initial=true
2024-06-17 21:34:41 +08:00
禹翔辉
ee17889fe8 Accept Merge Request #1080: (feature/预调仪接口 -> develop)
Merge Request: 1、添加日志

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1080?initial=true
2024-06-17 17:27:27 +08:00
yuxianghui
5bec3d6061 1 2024-06-17 17:24:23 +08:00
杨金灵
0fc5b12894 Accept Merge Request #1079: (feature/修复快速订单 -> develop)
Merge Request: 修复快速订单

Created By: @杨金灵
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @杨金灵
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1079?initial=true
2024-06-17 16:39:55 +08:00
jinling.yang
3258b6cc75 修复快速订单 2024-06-17 16:38:14 +08:00
jinling.yang
017404fe45 Merge branch 'feature/优化工单结束接口' into develop 2024-06-17 16:17:54 +08:00
杨金灵
cde6c76f83 Accept Merge Request #1078: (feature/优化工单结束接口 -> develop)
Merge Request: 优化工单结束接口

Created By: @杨金灵
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @杨金灵
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1078?initial=true
2024-06-17 16:16:39 +08:00
jinling.yang
7dea8c7c1e 去掉返工和报废的代码 2024-06-17 16:16:22 +08:00
jinling.yang
8ade3b43c4 中控新增是否完成字段,该接口根据该字段对cnc加工工单进行完成操作 2024-06-17 16:06:49 +08:00
禹翔辉
c2b7abaae1 Accept Merge Request #1077: (hotfix/功能刀具出入库处理 -> develop)
Merge Request: 新增功能刀具出入库线边刀库记录

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1077
2024-06-17 14:40:14 +08:00
禹翔辉
c1f33c5e14 Merge branch refs/heads/develop into refs/heads/hotfix/功能刀具出入库处理 2024-06-17 14:36:00 +08:00
杨金灵
01f55350e2 Accept Merge Request #1076: (feature/去掉返工报废的代码 -> develop)
Merge Request: 去掉返工报废的代码

Created By: @杨金灵
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @杨金灵
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1076?initial=true
2024-06-17 11:56:45 +08:00
jinling.yang
9202409a89 去掉返工报废的代码 2024-06-17 11:53:38 +08:00
jinling.yang
2e779c4a68 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-06-17 11:50:25 +08:00
禹翔辉
5751837ddd Accept Merge Request #1075: (feature/刀具同步接口优化 -> develop)
Merge Request: 优化动态刀具按批次管理的数据同步接口

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1075?initial=true
2024-06-17 11:46:22 +08:00
yuxianghui
e2f86097a0 Merge branch 'feature/模型优化' into feature/刀具同步接口优化 2024-06-17 11:42:25 +08:00
yuxianghui
77ad0dd635 优化动态刀具按批次管理的数据同步接口 2024-06-17 11:40:12 +08:00
jinling.yang
73e03bd815 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-06-17 11:00:33 +08:00
jinling.yang
51cd156e75 Merge branch 'feature/去掉客户部分字段必填校验和返工报废代码' into develop 2024-06-17 11:00:02 +08:00
jinling.yang
e3911c8f5a Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-06-17 09:52:43 +08:00
yuxianghui
1e90b9a18a 1、功能刀具位置计算方法添加触发条件 2024-06-14 17:01:02 +08:00
jinling.yang
24edef023f Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-06-14 16:53:26 +08:00
yuxianghui
904c63bfcb 1、优化功能刀具安全库存数量计算方法;2、货位看板模型添加功能刀具Rfid、名称字段 2024-06-14 15:38:52 +08:00
yuxianghui
a86ceb951b 1、优化功能刀具安全库存数量计算方法;2、货位看板模型添加功能刀具Rfid、名称字段 2024-06-14 15:00:30 +08:00
jinling.yang
dd9015dff9 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-06-14 09:31:18 +08:00
yuxianghui
642877ff45 去除整体式刀产品的【粗/中/精】字段的必填 2024-06-13 17:28:44 +08:00
yuxianghui
aa0b6a9b21 1、新增功能刀具移动到线边刀库的出入库记录 2024-06-13 16:01:27 +08:00
yuxianghui
9c6ca3758b 1 2024-06-13 14:59:49 +08:00
yuxianghui
42644d449f 1、新增功能刀具移动历史,新增功能刀具入库到线边刀库 2024-06-13 14:45:29 +08:00
马广威
519c534a89 Accept Merge Request #1071: (release/release_1.5 -> master)
Merge Request: 添加刀具物料整个生命周期按批次管理

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1071?initial=true
2024-06-13 10:49:36 +08:00
yuxianghui
0f32b0acb1 1、新增功能刀具出入库 2024-06-12 14:08:21 +08:00
29 changed files with 465 additions and 311 deletions

View File

@@ -11,11 +11,10 @@ class Printer(models.Model):
class TableStyle(models.Model):
_name = 'label.style'
_name = 'table.style'
_description = '标签样式'
name = fields.Char(string='名称', required=True)
zpl_code = fields.Text(string='zpl指令')
# todo
@@ -26,5 +25,4 @@ class PrinterConfiguration(models.Model):
name = fields.Char(string='名称', required=True)
printer_id = fields.Many2one('printer', string='打印机')
model = fields.Many2one('ir.model', string='模型名称')
label_id = fields.Many2one('label.style', '标签')
# # 其他相关字段...

View File

@@ -43,19 +43,19 @@ class PrintingUtils(models.AbstractModel):
zpl_code += "^CI28\n"
# 设置二维码位置
zpl_code += "^FO50,260\n" # 调整二维码位置,使其与资产编号在同一行
zpl_code += f"^BQN,2,5^FDLM,B0093{code}^FS\n"
zpl_code += "^FO50,50\n" # 调整二维码位置,使其与资产编号在同一行
zpl_code += f"^BQN,2,6^FDLM,B0093{code}^FS\n"
# # 设置资产编号文本位置
# zpl_code += "^FO300,60\n" # 资产编号文本的位置,与二维码在同一行
# zpl_code += "^A1N,45,45^FD编码名称: ^FS\n"
# 设置资产编号文本位置
zpl_code += "^FO300,60\n" # 资产编号文本的位置,与二维码在同一行
zpl_code += "^A1N,45,45^FD编码名称: ^FS\n"
# 设置{code}文本位置
# 假设{code}文本需要位于资产编号和二维码下方,中间位置
# 设置{code}文本位置并启用自动换行
zpl_code += "^FO240,10\n" # {code}文本的起始位置
zpl_code += "^FB600,10,0,L,0\n" # 定义一个宽度为500点的文本框最多4行左对齐
zpl_code += f"^A1B,40,40^FD{code}^FS\n"
zpl_code += "^FO300,120\n" # {code}文本的起始位置
zpl_code += "^FB400,4,0,L,0\n" # 定义一个宽度为500点的文本框最多4行左对齐
zpl_code += f"^A1N,40,40^FD{code}^FS\n"
# 在{code}文本框周围绘制线框
# 假设线框的外部尺寸为宽度500点高度200点

View File

@@ -208,7 +208,6 @@ access_sf_machine_brand_tags_group_purchase_director,sf_machine_brand_tags_group
access_printer,printer,model_printer,base.group_user,1,1,1,1
access_printer_configuration,printer.configuration,model_printer_configuration,base.group_user,1,1,1,1
access_label_style,label.style,model_label_style,base.group_user,1,1,1,1
access_group_sf_mrp_user,sf_tool_inventory,model_sf_tool_inventory,base.group_user,1,1,1,0
access_group_sf_mrp_user_admin,sf_tool_inventory_admin,model_sf_tool_inventory,base.group_system,1,1,1,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
208 access_sf_fixture_material_group_purchase_director access_sf_multi_mounting_type_group_purchase_director sf_fixture_material_group_purchase_director sf_multi_mounting_type_group_purchase_director model_sf_fixture_material model_sf_multi_mounting_type sf_base.group_purchase_director 1 0 0 0
209 access_sf_multi_mounting_type_group_purchase_director access_sf_fixture_model_group_purchase_director sf_multi_mounting_type_group_purchase_director sf_fixture_model_group_purchase_director model_sf_multi_mounting_type model_sf_fixture_model sf_base.group_purchase_director 1 0 0 0
210 access_sf_fixture_model_group_purchase_director access_sf_fixture_materials_basic_parameters_group_purchase_director sf_fixture_model_group_purchase_director sf_fixture_materials_basic_parameters_group_purchase_director model_sf_fixture_model model_sf_fixture_materials_basic_parameters sf_base.group_purchase_director 1 0 0 0
access_sf_fixture_materials_basic_parameters_group_purchase_director sf_fixture_materials_basic_parameters_group_purchase_director model_sf_fixture_materials_basic_parameters sf_base.group_purchase_director 1 0 0 0
211 access_sf_machine_tool_type_group_purchase_director sf_machine_tool_type_group_purchase_director model_sf_machine_tool_type sf_base.group_purchase_director 1 0 0 0
212 access_sf_fixture_material_group_sale_director sf_fixture_material_group_sale_director model_sf_fixture_material sf_base.group_sale_director 1 0 0 0
213 access_sf_multi_mounting_type_group_sale_director sf_multi_mounting_type_group_sale_director model_sf_multi_mounting_type sf_base.group_sale_director 1 0 0 0

View File

@@ -38,7 +38,6 @@
<field name="name"/>
<field name="printer_id"/>
<field name="model"/>
<field name="label_id"/>
<!-- 其他字段... -->
</tree>
</field>
@@ -54,36 +53,6 @@
<field name="name"/>
<field name="printer_id"/>
<field name="model"/>
<field name="label_id"/>
<!-- 其他字段... -->
</group>
</sheet>
</form>
</field>
</record>
<record id="view_label_style_tree" model="ir.ui.view">
<field name="name">label.style.tree</field>
<field name="model">label.style</field>
<field name="arch" type="xml">
<tree string="label style">
<field name="name"/>
<!-- <field name="zpl_code"/> -->
<!-- 其他字段... -->
</tree>
</field>
</record>
<record id="view_label_style_form" model="ir.ui.view">
<field name="name">label.style.form</field>
<field name="model">label.style</field>
<field name="arch" type="xml">
<form string="label style">
<sheet>
<group>
<field name="name"/>
<field name="zpl_code"/>
<!-- 其他字段... -->
</group>
</sheet>
@@ -105,11 +74,6 @@
<field name="res_model">printer.configuration</field>
<field name="view_mode">tree,form</field>
</record>
<record id="action_label_style" model="ir.actions.act_window">
<field name="name">标签样式</field>
<field name="res_model">label.style</field>
<field name="view_mode">tree,form,kanban</field>
</record>
<!-- Add a menu item for the printer configuration -->
<!-- <record id="menu_printer_configuration" model="ir.ui.menu"> -->
@@ -144,12 +108,5 @@
sequence="2"
parent="printer_main_menu"/>
<menuitem
id="menu_label_style"
name="标签样式"
action="action_label_style"
sequence="3"
parent="printer_main_menu"/>
</data>
</odoo>

View File

@@ -555,9 +555,9 @@
<field name="model">sf.tool.inventory</field>
<field name="arch" type="xml">
<tree string="功能刀具清单" create="1" edit="1" delete="0" editable="bottom">
<field name="name"/>
<field name="name" attrs="{'readonly': [('id', '!=', False)]}"/>
<field name="functional_cutting_tool_model_id"/>
<field name="tool_groups_id"/>
<field name="tool_groups_id" required="1" attrs="{'readonly': [('id', '!=', False)]}"/>
<field name="work_material"/>
<field name="life_span"/>
<field name="prefix" optional="hide"/>

View File

@@ -305,7 +305,7 @@
<field name="cutting_tool_blade_type"
attrs="{'invisible': [('cutting_tool_type', '!=', '整体式刀具')],'readonly': [('id', '!=', False)]}"/>
<field name="cutting_tool_coarse_medium_fine" string="粗/中/精" placeholder="请选择"
attrs="{'required': [('cutting_tool_type','=','整体式刀具')],'invisible': [('cutting_tool_type', 'not in', ('整体式刀具','刀片'))],'readonly': [('id', '!=', False)]}"/>
attrs="{'invisible': [('cutting_tool_type', 'not in', ('整体式刀具','刀片'))],'readonly': [('id', '!=', False)]}"/>
<!--整体式刀具-->
<field name="cutting_tool_shank_diameter" string="柄部直径(mm)" class="diameter"
attrs="{'invisible': [('cutting_tool_type', '!=', '整体式刀具')],'readonly': [('id', '!=', False)]}"/>

View File

@@ -25,6 +25,9 @@
<filter string="人工编程" name="manual_quotation" domain="[('manual_quotation', '=', True)]"/>
<filter string="自动编程" name="no_manual_quotation" domain="[('manual_quotation', '=', False)]"/>
</xpath>
<xpath expr="//field[@name='production_id']" position="before">
<field name="product_tmpl_name"/>
</xpath>
</field>
</record>
</odoo>

View File

@@ -8,7 +8,7 @@ from odoo.http import request
class Manufacturing_Connect(http.Controller):
@http.route('/AutoDeviceApi/GetWoInfo', type='json', auth='none', methods=['GET', 'POST'], csrf=False,
@http.route('/AutoDeviceApi/GetWoInfo', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False,
cors="*")
def get_Work_Info(self, **kw):
"""
@@ -216,7 +216,8 @@ class Manufacturing_Connect(http.Controller):
res = {'Succeed': False, 'ErrorCode': 202, 'Error': '该工单未开始'}
return json.JSONEncoder().encode(res)
# workorder.write({'date_finished': datetime.now()})
workorder.button_finish()
if ret['IsComplete'] is True:
workorder.button_finish()
# workorder.process_state = '待解除装夹'
# workorder.sudo().production_id.process_state = '待解除装夹'
@@ -459,25 +460,27 @@ class Manufacturing_Connect(http.Controller):
if f'RfidCode{i}' in ret:
rfid_code = ret[f'RfidCode{i}']
logging.info('RfidCode:%s' % rfid_code)
domain = [
('rfid_code', '=', rfid_code),
('routing_type', '=', 'CNC加工')
]
workorder = request.env['mrp.workorder'].sudo().search(domain, order='id asc')
if workorder:
for order in workorder:
if order.production_id.production_line_state == '待上产线':
logging.info(
'制造订单产线状态:%s' % order.production_id.production_line_state)
order.production_id.write({'production_line_state': '已上产线'})
workpiece_delivery = request.env['sf.workpiece.delivery'].sudo().search([
('rfid_code', '=', rfid_code), ('type', '=', '上产线'),
('production_id', '=', order.production_id.id)])
if workpiece_delivery.status == '待下发':
workpiece_delivery.write({'is_manual_work': True})
else:
res = {'Succeed': False, 'ErrorCode': 204,
'Error': 'DeviceId为%s没有对应的已配送工件数据' % ret['DeviceId']}
if rfid_code is not None:
domain = [
('rfid_code', '=', rfid_code),
('routing_type', '=', 'CNC加工')
]
workorder = request.env['mrp.workorder'].sudo().search(domain, order='id asc')
if workorder:
for order in workorder:
if order.production_id.production_line_state == '待上产线':
logging.info(
'制造订单产线状态:%s' % order.production_id.production_line_state)
order.production_id.write({'production_line_state': '已上产线'})
workpiece_delivery = request.env['sf.workpiece.delivery'].sudo().search(
[
('rfid_code', '=', rfid_code), ('type', '=', '上产线'),
('production_id', '=', order.production_id.id)])
if workpiece_delivery.status == '待下发':
workpiece_delivery.write({'is_manual_work': True})
else:
res = {'Succeed': False, 'ErrorCode': 204,
'Error': 'DeviceId为%s没有对应的已配送工件数据' % ret['DeviceId']}
else:
res = {'Succeed': False, 'ErrorCode': 203, 'Error': '未传IsComplete字段'}
else:
@@ -514,24 +517,26 @@ class Manufacturing_Connect(http.Controller):
if f'RfidCode{i}' in ret:
rfid_code = ret[f'RfidCode{i}']
logging.info('RfidCode:%s' % rfid_code)
domain = [
('rfid_code', '=', rfid_code),
('routing_type', '=', 'CNC加工')
]
workorder = request.env['mrp.workorder'].sudo().search(domain, order='id asc')
if workorder:
for order in workorder:
if order.production_id.production_line_state == '已上产线':
logging.info(
'制造订单产线状态:%s' % order.production_id.production_line_state)
order.production_id.write({'production_line_state': '已下产线'})
workpiece_delivery = request.env['sf.workpiece.delivery'].sudo().search([
('rfid_code', '=', rfid_code), ('type', '=', '下产线'),
('production_id', '=', order.production_id.id)])
delivery_Arr.append(workpiece_delivery.id)
else:
res = {'Succeed': False, 'ErrorCode': 204,
'Error': 'DeviceId为%s没有对应的已配送工件数据' % ret['DeviceId']}
if rfid_code is not None:
domain = [
('rfid_code', '=', rfid_code),
('routing_type', '=', 'CNC加工')
]
workorder = request.env['mrp.workorder'].sudo().search(domain, order='id asc')
if workorder:
for order in workorder:
if order.production_id.production_line_state == '已上产线':
logging.info(
'制造订单产线状态:%s' % order.production_id.production_line_state)
order.production_id.write({'production_line_state': '已下产线'})
workpiece_delivery = request.env['sf.workpiece.delivery'].sudo().search(
[
('rfid_code', '=', rfid_code), ('type', '=', '下产线'),
('production_id', '=', order.production_id.id)])
delivery_Arr.append(workpiece_delivery.id)
else:
res = {'Succeed': False, 'ErrorCode': 204,
'Error': 'DeviceId为%s没有对应的已配送工件数据' % ret['DeviceId']}
if delivery_Arr:
logging.info('delivery_Arr:%s' % delivery_Arr)
delivery_workpiece = request.env['sf.workpiece.delivery'].sudo().search(

View File

@@ -178,7 +178,7 @@ class MrpProduction(models.Model):
raise UserError("更新程单失败,请联系管理员")
# cnc程序获取
def fetchCNC(self, production_names, scrap_production):
def fetchCNC(self, production_names):
cnc = self.env['mrp.production'].search([('id', '=', self.id)])
quick_order = self.env['quick.easy.order'].search(
[('name', '=', cnc.product_id.default_code.rsplit('-', 1)[0])])
@@ -194,8 +194,7 @@ class MrpProduction(models.Model):
'production_no': production_names,
'machine_tool_code': '',
'product_name': cnc.product_id.name,
'remanufacture_type': '' if not scrap_production else scrap_production.workorder_ids.filtered(
lambda b: b.routing_type == "CNC加工").test_results,
'remanufacture_type': '',
'model_code': cnc.product_id.model_code,
'material_code': self.env['sf.production.materials'].search(
[('id', '=', cnc.product_id.materials_id.id)]).materials_no,
@@ -337,8 +336,7 @@ class MrpProduction(models.Model):
[('product_id.id', '=', production.product_id.id), ('origin', '=', production.origin)],
limit=1, order='id asc')
if not production_programming.programming_no:
production.fetchCNC(', '.join(product_id_to_production_names[production.product_id.id]),
scrap_production)
production.fetchCNC(', '.join(product_id_to_production_names[production.product_id.id]))
else:
production.write({'programming_no': production_programming.programming_no,
'programming_state': '编程中'})

View File

@@ -21,6 +21,8 @@ class ResMrpWorkOrder(models.Model):
_inherit = 'mrp.workorder'
_order = 'sequence asc,create_date desc'
product_tmpl_name = fields.Char('坯料产品名称', related='production_bom_id.bom_line_ids.product_id.name')
product_tmpl_id_length = fields.Float(related='production_id.product_tmpl_id.length', readonly=True, store=True,
string="坯料长度(mm)")
product_tmpl_id_width = fields.Float(related='production_id.product_tmpl_id.width', readonly=True, store=True,
@@ -684,7 +686,7 @@ class ResMrpWorkOrder(models.Model):
values)
# self.env['stock.move'].sudo().create(productions._get_moves_raw_values())
self.env['stock.move'].sudo().create(productions._get_moves_finished_values())
productions._create_workorder(is_fetchcnc=self.is_fetchcnc, scrap_production=self.production_id)
productions._create_workorder()
productions.filtered(lambda p: (not p.orderpoint_id and p.move_raw_ids) or \
(
p.move_dest_ids.procure_method != 'make_to_order' and
@@ -849,12 +851,12 @@ class ResMrpWorkOrder(models.Model):
limit=1, order='id asc')
if not cnc_workorder.cnc_ids:
raise UserError(_('该制造订单还未下发CNC程序请稍后再试'))
else:
for item in cnc_workorder.cnc_ids:
functional_cutting_tool = self.env['sf.functional.cutting.tool.entity'].search(
[('tool_name_id.name', '=', item.cutting_tool_name)])
if not functional_cutting_tool:
raise UserError(_('该制造订单的CNC程序为%s没有对应的功能刀具' % item.cutting_tool_name))
# else:
# for item in cnc_workorder.cnc_ids:
# functional_cutting_tool = self.env['sf.functional.cutting.tool.entity'].search(
# [('tool_name_id.name', '=', item.cutting_tool_name)])
# if not functional_cutting_tool:
# raise UserError(_('该制造订单的CNC程序为%s没有对应的功能刀具' % item.cutting_tool_name))
if self.routing_type == '解除装夹':
'''
记录开始时间
@@ -1009,10 +1011,15 @@ class ResMrpWorkOrder(models.Model):
for workorder in record.production_id.workorder_ids:
if workorder.state != 'done':
is_production_id = False
if is_production_id is True and record.routing_type in ['解除装夹', '表面工艺']:
if record.routing_type == '解除装夹':
for workorder in record.production_id.workorder_ids:
workorder.rfid_code_old = workorder.rfid_code
workorder.rfid_code = None
if workorder.processing_panel == record.processing_panel:
rfid_code = workorder.rfid_code
workorder.write({'rfid_code_old': rfid_code,
'rfid_code': ''})
workorder.rfid_code_old = rfid_code
workorder.rfid_code = ''
if is_production_id is True and record.routing_type in ['解除装夹', '表面工艺']:
for move_raw_id in record.production_id.move_raw_ids:
move_raw_id.quantity_done = move_raw_id.product_uom_qty
record.process_state = '已完工'
@@ -1254,11 +1261,12 @@ class SfWorkOrderBarcodes(models.Model):
workorder.write(val)
self.write(val)
workorder_rfid = self.env['mrp.workorder'].search(
[('production_id', '=', workorder.production_id.id)])
[('production_id', '=', workorder.production_id.id),
('processing_panel', '=', workorder.processing_panel)])
if workorder_rfid:
for item in workorder_rfid:
item.write({'rfid_code': barcode})
logging.info("Rfid绑定成功")
logging.info("Rfid[%s]绑定成功!!!" % barcode)
else:
raise UserError('该Rfid【%s】绑定的是【%s】, 不是托盘!!!' % (barcode, lot.product_id.name))
self.process_state = '待检测'

View File

@@ -636,7 +636,7 @@ class ResProductMo(models.Model):
'model_remark': item['remark'],
'default_code': '%s-%s' % (order_number, i),
'manual_quotation': item['manual_quotation'] or False,
'part_number': item['part_number'] or '',
'part_number': item.get('part_number') or '',
'active': True,
}
copy_product_id.sudo().write(vals)

View File

@@ -208,7 +208,7 @@ class StockRule(models.Model):
'''
创建工单
'''
productions._create_workorder(is_fetchcnc=False, scrap_production=False)
productions._create_workorder()
productions.filtered(lambda p: (not p.orderpoint_id and p.move_raw_ids) or \
(
@@ -701,13 +701,36 @@ class ReStockMove(models.Model):
),
}
def put_move_line(self):
"""
确认订单时,自动分配序列号
"""
if self.product_id.tracking == "serial":
if self.product_id.categ_id.name == '刀具':
self.next_serial = self._get_tool_next_serial(self.company_id, self.product_id, self.origin)
else:
self.next_serial = self.env['stock.lot']._get_next_serial(self.company_id, self.product_id)
self._generate_serial_numbers()
for item in self.move_line_nosuggest_ids:
if item.lot_name:
lot_name = item.lot_name
if item.product_id.categ_id.name == '坯料':
lot_name = lot_name.split('[', 1)[0]
item.lot_qr_code = self.compute_lot_qr_code(lot_name)
def _put_tool_lot(self, company, product, origin):
if product.tracking == "lot" and self.product_id.categ_id.name == '刀具':
if not self.move_line_nosuggest_ids:
lot_names = self.env['stock.lot'].generate_lot_names(
'%s-%s-%s' % ('%s-T-DJWL-%s' % (
product.cutting_tool_model_id.code.split('-')[0], product.cutting_tool_material_id.code),
datetime.now().strftime("%Y%m%d"), origin), 1)
lot_code = '%s-%s-%s' % ('%s-T-DJWL-%s' % (
product.cutting_tool_model_id.code.split('-')[0], product.cutting_tool_material_id.code),
datetime.now().strftime("%Y%m%d"), origin)
move_line_ids = self.env['stock.move.line'].sudo().search([('lot_name', 'like', lot_code)], limit=1,
order='id desc')
if not move_line_ids:
lot_code = '%s-001' % lot_code
else:
lot_code = '%s-%03d' % (lot_code, int(move_line_ids.lot_name[-3:]) + 1)
lot_names = self.env['stock.lot'].generate_lot_names(lot_code, 1)
move_lines_commands = self._generate_serial_move_line_commands_tool_lot(lot_names)
self.write({'move_line_nosuggest_ids': move_lines_commands})
for item in self.move_line_nosuggest_ids:

View File

@@ -19,6 +19,7 @@
</field>
<field name="state" position="after">
<field name="work_state" optional="hide"/>
<field name="product_tmpl_name" invisible="1"/>
</field>
<field name="product_id" position="after">
<field name="equipment_id" optional="hide"/>
@@ -214,7 +215,7 @@
attrs='{"invisible": [("routing_type","!=","装夹预调")]}'/>
<field name="functional_fixture_type_id"
attrs='{"invisible": [("routing_type","!=","装夹预调")]}'/>
<field name="rfid_code" cache="True"
<field name="rfid_code" force_save="1" readonly="1" cache="True"
attrs="{'invisible': [('rfid_code_old', '!=', False)]}"/>
<field name="rfid_code_old" readonly="1" attrs="{'invisible': [('rfid_code_old', '=', False)]}"/>
</group>
@@ -477,13 +478,13 @@
<page string="后置三元检测" attrs='{"invisible": [("routing_type","!=","CNC加工")]}'>
<group>
<field name="test_results" attrs='{"invisible":[("results","!=",False)]}'/>
<field name="is_remanufacture" attrs='{"invisible":[("test_results","!=","报废")]}'/>
<field name="is_fetchcnc"
attrs='{"invisible":["|",("test_results","=","合格"),("is_remanufacture","=",False)]}'/>
<field name="reason"
attrs='{"required":[("test_results","!=","合格")],"invisible":[("test_results","=","合格")]}'/>
<field name="detailed_reason" attrs='{"invisible":[("test_results","=","合格")]}'/>
<field name="results" readonly="1" attrs='{"invisible":[("results","!=","合格")]}'/>
<!-- <field name="is_remanufacture" attrs='{"invisible":[("test_results","!=","报废")]}'/>-->
<!-- <field name="is_fetchcnc"-->
<!-- attrs='{"invisible":["|",("test_results","=","合格"),("is_remanufacture","=",False)]}'/>-->
<!-- <field name="reason"-->
<!-- attrs='{"required":[("test_results","!=","合格")],"invisible":[("test_results","=","合格")]}'/>-->
<!-- <field name="detailed_reason" attrs='{"invisible":[("test_results","=","合格")]}'/>-->
<!-- <field name="results" readonly="1" attrs='{"invisible":[("results","!=","合格")]}'/>-->
<field name="detection_report" attrs='{"invisible":[("results","!=",False)]}'
widget="pdf_viewer"/>
</group>

View File

@@ -41,8 +41,8 @@
<field name="model">stock.lot</field>
<field name="inherit_id" ref="stock.view_production_lot_tree"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='create_date']" position="after">
<field name="rfid" invisible="1"/>
<xpath expr="//field[@name='name']" position="after">
<field name="rfid"/>
</xpath>
</field>
</record>

View File

@@ -215,6 +215,17 @@ class RePurchaseOrder(models.Model):
if len(product_id) != len(line):
raise ValidationError('%s】已存在,请勿重复添加' % product[-1].name)
def button_confirm(self):
result = super(RePurchaseOrder, self).button_confirm()
for item in self:
# 确认订单时,自动分配序列号
if item.picking_ids:
for picking_id in item.picking_ids:
if picking_id.move_ids:
for move_id in picking_id.move_ids:
move_id.put_move_line()
return result
class ResPartnerToSale(models.Model):
_inherit = 'res.partner'

View File

@@ -22,6 +22,7 @@
'views/tool_material_search.xml',
'views/fixture_material_search_views.xml',
'views/menu_view.xml',
'views/stock.xml',
'data/tool_data.xml',
],
'demo': [

View File

@@ -109,6 +109,7 @@ class Manufacturing_Connect(http.Controller):
res = {'Succeed': True, 'Datas': []}
try:
datas = request.httprequest.data
logging.info('datas: %s' % datas)
ret = str(datas, 'utf-8')
data_lists = ret.split(",")
data_list = [data.replace('+', '') for data in data_lists]
@@ -120,7 +121,7 @@ class Manufacturing_Connect(http.Controller):
{'Succeed': False, 'ErrorCode': 201, 'code': data_list[0], 'Error': '没有找到正在组装的组装单!'})
tool_assembly.write({
'after_assembly_tool_loading_length': float(data_list[1] or "0"), # 高度(总长度)
'after_assembly_functional_tool_diameter': float(data_list[2] or "0"), # 直径
'after_assembly_functional_tool_diameter': float(data_list[2] or "0") * 2, # 直径
'after_assembly_knife_tip_r_angle': float(data_list[3] or "0") # R角
})
except Exception as e:

View File

@@ -7,4 +7,5 @@ from . import functional_tool_enroll
from . import fixture_material_search
from . import fixture_enroll
from . import temporary_data_processing_methods
from . import stock

View File

@@ -926,7 +926,7 @@ class FunctionalToolDismantle(models.Model):
location = self.env['stock.location'].search([('name', '=', '刀具组装位置')])
location_dest = self.env['stock.location'].search([('name', '=', '刀具房')])
# =================刀柄是否[报废]拆解=======
location_dest_scrap = self.env['stock.location'].search([('name', '=', 'Scrap')])
location_dest_scrap_ids = self.env['stock.location'].search([('name', 'in', ('Scrap', '报废'))])
if self.handle_rfid:
lot = self.env['stock.lot'].sudo().search([('rfid', '=', self.handle_rfid)])
if not lot:
@@ -934,30 +934,33 @@ class FunctionalToolDismantle(models.Model):
functional_tool_assembly = self.functional_tool_id.functional_tool_name_id
if self.scrap_boolean:
# 刀柄报废 入库到Scrap
lot.create_stock_quant(location, location_dest_scrap, functional_tool_assembly.id, code,
lot.create_stock_quant(location, location_dest_scrap_ids[-1], functional_tool_assembly.id, code,
functional_tool_assembly, functional_tool_assembly.tool_groups_id)
lot.tool_material_status = '报废'
else:
# 刀柄不报废 入库到刀具房
lot.create_stock_quant(location, location_dest, functional_tool_assembly.id, code,
functional_tool_assembly, functional_tool_assembly.tool_groups_id)
lot.tool_material_status = '可用'
# ==============功能刀具[报废]拆解================
if self.dismantle_cause in ['寿命到期报废', '崩刀报废']:
# 除刀柄外物料报废 入库到Scrap
if self.integral_product_id:
self.integral_product_id.dismantle_stock_moves(False, self.integral_lot_id, location,
location_dest_scrap, code)
location_dest_scrap_ids[-1], code)
elif self.blade_product_id:
self.blade_product_id.dismantle_stock_moves(False, self.blade_lot_id, location, location_dest_scrap,
code)
self.blade_product_id.dismantle_stock_moves(False, self.blade_lot_id, location,
location_dest_scrap_ids[-1], code)
if self.bar_product_id:
self.bar_product_id.dismantle_stock_moves(False, self.bar_lot_id, location, location_dest_scrap,
code)
self.bar_product_id.dismantle_stock_moves(False, self.bar_lot_id, location,
location_dest_scrap_ids[-1], code)
elif self.pad_product_id:
self.pad_product_id.dismantle_stock_moves(False, self.pad_lot_id, location, location_dest_scrap,
code)
self.pad_product_id.dismantle_stock_moves(False, self.pad_lot_id, location,
location_dest_scrap_ids[-1], code)
if self.chuck_product_id:
self.chuck_product_id.dismantle_stock_moves(False, self.chuck_lot_id, location, location_dest_scrap,
code)
self.chuck_product_id.dismantle_stock_moves(False, self.chuck_lot_id, location,
location_dest_scrap_ids[-1], code)
# ===========功能刀具[磨削]拆解==============
# elif self.dismantle_cause in ['刀具需磨削']:
# location_dest = self.env['stock.location'].search([('name', '=', '磨削房')])
@@ -1025,7 +1028,7 @@ class ProductProduct(models.Model):
'product_id': self.id,
'lot_id': lot_id.id,
'move_id': stock_move_id.id,
'destination_location_id': shelf_location_id.id,
'destination_location_id': shelf_location_id.id if shelf_location_id else False,
'install_tool_time': fields.Datetime.now(),
'qty_done': 1.0,
'state': 'done',

View File

@@ -34,15 +34,17 @@ class FunctionalCuttingToolEntity(models.Model):
handle_length = fields.Float(string='刀柄长度(mm)', readonly=True, digits=(10, 3))
functional_tool_length = fields.Float(string='伸出长(mm)', readonly=True, digits=(10, 3))
effective_length = fields.Float(string='有效长(mm)', readonly=True)
tool_room_num = fields.Integer(string='刀具房数量', readonly=True)
line_edge_knife_library_num = fields.Integer(string='线边刀库数量', readonly=True)
machine_knife_library_num = fields.Integer(string='机内刀库数量', readonly=True)
tool_room_num = fields.Integer(string='刀具房数量', compute='_compute_num', store=True)
line_edge_knife_library_num = fields.Integer(string='线边刀库数量', compute='_compute_num', store=True)
machine_knife_library_num = fields.Integer(string='机内刀库数量', compute='_compute_num', store=True)
max_lifetime_value = fields.Integer(string='最大寿命值(min)', readonly=True)
alarm_value = fields.Integer(string='报警值(min)', readonly=True)
used_value = fields.Integer(string='已使用值(min)', readonly=True)
functional_tool_status = fields.Selection([('正常', '正常'), ('报警', '报警'), ('已拆除', '已拆除')],
string='状态', store=True, default='正常')
current_location_id = fields.Many2one('stock.location', string='当前位置', readonly=True)
current_location_id = fields.Many2one('stock.location', string='当前位置', compute='_compute_current_location_id',
store=True)
current_shelf_location_id = fields.Many2one('sf.shelf.location', string='当前货位', readonly=True)
current_location = fields.Selection(
[('组装后', '组装后'), ('刀具房', '刀具房'), ('线边刀库', '线边刀库'), ('机内刀库', '机内刀库')],
string='位置', compute='_compute_current_location_id', store=True)
@@ -51,44 +53,113 @@ class FunctionalCuttingToolEntity(models.Model):
safe_inventory_id = fields.Many2one('sf.real.time.distribution.of.functional.tools',
string='功能刀具安全库存', readonly=True)
@api.depends('barcode_id.quant_ids', 'functional_tool_status')
@api.depends('barcode_id.quant_ids', 'functional_tool_status', 'current_shelf_location_id')
def _compute_current_location_id(self):
for record in self:
if record.barcode_id.quant_ids:
for quant_id in record.barcode_id.quant_ids:
if quant_id.inventory_quantity_auto_apply > 0:
record.current_location_id = quant_id.location_id
if quant_id.location_id.name == '制造前':
record.current_location = '机内刀库'
else:
record.current_location = quant_id.location_id.name
if record.current_location_id:
record.sudo().get_location_num()
else:
record.current_location_id = False
record.current_location = False
if record.functional_tool_status == '已拆除':
record.current_location_id = False
record.current_location = False
record.tool_room_num = 0
record.line_edge_knife_library_num = 0
record.machine_knife_library_num = 0
else:
if record.barcode_id.quant_ids:
for quant_id in record.barcode_id.quant_ids:
if quant_id.inventory_quantity_auto_apply > 0:
record.current_location_id = quant_id.location_id
if quant_id.location_id.name == '制造前':
if not record.current_shelf_location_id:
record.current_location = '机内刀库'
else:
record.current_location = '线边刀库'
else:
record.current_location = '刀具房'
else:
record.current_location_id = False
record.current_location = False
def get_location_num(self):
@api.depends('current_location', 'functional_tool_status')
def _compute_num(self):
"""
计算库存位置数量
"""
for obj in self:
if obj.current_location_id:
if obj.functional_tool_status == '已拆除':
obj.tool_room_num = 0
obj.line_edge_knife_library_num = 0
obj.machine_knife_library_num = 0
if obj.current_location in ['刀具房']:
obj.tool_room_num = 1
elif "线边刀库" in obj.current_location:
obj.line_edge_knife_library_num = 1
elif "机内刀库" in obj.current_location:
obj.machine_knife_library_num = 1
else:
if obj.current_location_id:
obj.tool_room_num = 0
obj.line_edge_knife_library_num = 0
obj.machine_knife_library_num = 0
if obj.current_location in ['刀具房']:
obj.tool_room_num = 1
elif "线边刀库" in obj.current_location:
obj.line_edge_knife_library_num = 1
elif "机内刀库" in obj.current_location:
obj.machine_knife_library_num = 1
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
# 中控反馈该位置没有刀
else:
# 系统该位置有刀
if location_id.product_sn_id:
item.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(
[('barcode_id', '=', location_id.product_sn_id.id)])
if tool.current_location == '线边刀库':
tool.create_stock_move(tool_room_id, False)
# 修改功能刀具的当前位置
tool.current_shelf_location_id = False
def create_stock_move(self, location_dest_id, destination_location_id):
# 创建库存移动记录
stock_move_id = self.env['stock.move'].sudo().create({
'name': '/',
'product_id': self.barcode_id.product_id.id,
'location_id': self.current_location_id.id,
'location_dest_id': location_dest_id.id,
'product_uom_qty': 1.00,
'state': 'done'
})
# 创建移动历史记录
stock_move_line_id = self.env['stock.move.line'].sudo().create({
'product_id': self.barcode_id.product_id.id,
'lot_id': self.barcode_id.id,
'move_id': stock_move_id.id,
'current_location_id': False if not self.current_shelf_location_id else self.current_shelf_location_id.id,
'destination_location_id': False if not destination_location_id else destination_location_id.id,
'qty_done': 1.0,
'state': 'done',
'functional_tool_type_id': self.sf_cutting_tool_type_id.id,
'diameter': self.functional_tool_diameter,
'knife_tip_r_angle': self.knife_tip_r_angle,
'code': self.code,
'rfid': self.rfid,
'functional_tool_name': self.name,
'tool_groups_id': self.tool_groups_id.id
})
return stock_move_id, stock_move_line_id
@api.model
def _read_group_mrs_cutting_tool_type_id(self, categories, domain, order):
@@ -191,12 +262,14 @@ class FunctionalCuttingToolEntity(models.Model):
机床当前刀库实时信息接口,功能刀具出库
"""
# 获取位置对象
location_inventory_id = self.current_location_id
stock_location_id = self.env['stock.location'].search([('name', '=', '制造前')])
# 创建功能刀具该批次/序列号 库存移动和移动历史
self.barcode_id.create_stock_quant(location_inventory_id, stock_location_id,
self.functional_tool_name_id.id, '机床装刀', self.functional_tool_name_id,
self.functional_tool_name_id.tool_groups_id)
self.create_stock_move(stock_location_id, False)
self.current_location_id = stock_location_id.id
self.current_shelf_location_id = False
# self.barcode_id.create_stock_quant(location_inventory_id, stock_location_id,
# self.functional_tool_name_id.id, '机床装刀', self.functional_tool_name_id,
# self.functional_tool_name_id.tool_groups_id)
# ==========刀具组接口==========
# def _register_functional_tool_groups(self, obj):
@@ -304,7 +377,7 @@ class StockMoveLine(models.Model):
functional_tool_name = fields.Char('刀具名称')
diameter = fields.Float(string='刀具直径(mm)')
knife_tip_r_angle = fields.Float(string='刀尖R角(mm)')
install_tool_time = fields.Datetime("刀具组装时间", default=fields.Datetime.now())
install_tool_time = fields.Datetime("刀具组装时间")
code = fields.Char('编码')
rfid = fields.Char('Rfid')
tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组')
@@ -327,12 +400,12 @@ class RealTimeDistributionOfFunctionalTools(models.Model):
group_expand='_read_mrs_cutting_tool_type_ids', store=True)
diameter = fields.Float(string='刀具直径(mm)', readonly=False)
knife_tip_r_angle = fields.Float(string='刀尖R角(mm)', readonly=False)
tool_stock_num = fields.Integer(string='刀具房数量')
side_shelf_num = fields.Integer(string='线边刀库数量')
on_tool_stock_num = fields.Integer(string='机内刀库数量')
tool_stock_total = fields.Integer(string='当前库存量', readonly=True)
min_stock_num = fields.Integer('最低库存量', tracking=True)
max_stock_num = fields.Integer('最高库存量', tracking=True)
tool_stock_num = fields.Integer(string='刀具房数量', compute='_compute_stock_num', store=True)
side_shelf_num = fields.Integer(string='线边刀库数量', compute='_compute_stock_num', store=True)
on_tool_stock_num = fields.Integer(string='机内刀库数量', compute='_compute_stock_num', store=True)
tool_stock_total = fields.Integer(string='当前库存量', compute='_compute_tool_stock_total', store=True)
min_stock_num = fields.Integer('最低库存量')
max_stock_num = fields.Integer('最高库存量')
batch_replenishment_num = fields.Integer('批次补货量', readonly=True, compute='_compute_batch_replenishment_num',
store=True)
unit = fields.Char('单位', default="")
@@ -403,10 +476,6 @@ class RealTimeDistributionOfFunctionalTools(models.Model):
def _compute_batch_replenishment_num(self):
for tool in self:
if tool:
# 计算刀具房数量、线边刀库数量、机内刀库数量
tool.sudo().get_stock_num(tool)
# 计算当前库存量
tool.sudo().tool_stock_total = tool.tool_stock_num + tool.side_shelf_num + tool.on_tool_stock_num
# 如果当前库存量小于最低库存量,计算批次补货量
tool.sudo().open_batch_replenishment_num(tool)
@@ -425,6 +494,38 @@ class RealTimeDistributionOfFunctionalTools(models.Model):
else:
tool.sudo().batch_replenishment_num = 0
@api.depends('sf_functional_tool_entity_ids', 'sf_functional_tool_entity_ids.tool_room_num',
'sf_functional_tool_entity_ids.line_edge_knife_library_num',
'sf_functional_tool_entity_ids.machine_knife_library_num')
def _compute_stock_num(self):
"""
计算刀具房数量、线边刀库数量、机内刀库数量
"""
for tool in self:
if tool:
tool.tool_stock_num = 0
tool.side_shelf_num = 0
tool.on_tool_stock_num = 0
if tool.sf_functional_tool_entity_ids:
for cutting_tool in tool.sf_functional_tool_entity_ids:
if cutting_tool.tool_room_num > 0:
tool.tool_stock_num += 1
elif cutting_tool.line_edge_knife_library_num > 0:
tool.side_shelf_num += 1
elif cutting_tool.machine_knife_library_num > 0:
tool.on_tool_stock_num += 1
else:
tool.tool_stock_num = 0
tool.side_shelf_num = 0
tool.on_tool_stock_num = 0
@api.depends('tool_stock_num', 'side_shelf_num', 'on_tool_stock_num')
def _compute_tool_stock_total(self):
for tool in self:
if tool:
# 计算当前库存量
tool.tool_stock_total = tool.tool_stock_num + tool.side_shelf_num + tool.on_tool_stock_num
def create_functional_tool_assembly(self, tool):
"""
创建功能刀具组装单
@@ -445,27 +546,6 @@ class RealTimeDistributionOfFunctionalTools(models.Model):
})
tool.sudo().sf_functional_tool_assembly_ids = [(4, functional_tool_assembly.id)]
def get_stock_num(self, tool):
"""
计算刀具房数量、线边刀库数量、机内刀库数量
"""
if tool:
tool.tool_stock_num = 0
tool.side_shelf_num = 0
tool.on_tool_stock_num = 0
if tool.sf_functional_tool_entity_ids:
for cutting_tool in tool.sf_functional_tool_entity_ids:
if cutting_tool.tool_room_num > 0:
tool.tool_stock_num += 1
elif cutting_tool.line_edge_knife_library_num > 0:
tool.side_shelf_num += 1
elif cutting_tool.machine_knife_library_num > 0:
tool.on_tool_stock_num += 1
else:
tool.tool_stock_num = 0
tool.side_shelf_num = 0
tool.on_tool_stock_num = 0
def create_or_edit_safety_stock(self, vals, sf_functional_tool_entity_ids):
"""
根据传入的信息新增或者更新功能刀具安全库存的信息

View File

@@ -80,7 +80,7 @@ class StockLot(models.Model):
headers = Common.get_headers(self, token, sf_secret_key)
str_url = sf_sync_config['sf_url'] + "/api/tool_material_stock/create"
product_ids = self.env['product.product'].sudo().search([('categ_type', '=', '刀具')]).ids
objs_all = self.env['stock.lot'].search([('rfid', '!=', False), ('product_id', 'in', product_ids)])
objs_all = self.env['stock.lot'].search([('product_id', 'in', product_ids)])
self._get_sync_stock_lot(objs_all, str_url, token, headers)
def _get_sync_stock_lot(self, objs_all, str_url, token, headers):
@@ -90,6 +90,7 @@ class StockLot(models.Model):
for item in objs_all:
val = {
'name': item.name,
'qty': item.product_qty,
'tool_material_status': item.tool_material_status,
'location': [] if not item.quant_ids else item.quant_ids[-1].location_id.name,
'tool_material_search_id': item.tool_material_search_id.id,
@@ -163,8 +164,6 @@ class ToolMaterial(models.Model):
logging.info("刀具物料同步失败:%s" % e)
class FunctionalCuttingToolEntity(models.Model):
_inherit = 'sf.functional.cutting.tool.entity'
_description = '功能刀具列表注册'
@@ -235,8 +234,7 @@ class FunctionalCuttingToolEntity(models.Model):
'blade_tip_characteristics_name': item.blade_tip_characteristics_id.name,
'handle_type_name': item.handle_type_id.name,
'cutting_direction_names': get_cutting_direction_names(item),
'suitable_coolant_names': get_suitable_coolant_names(item),
'active': item.active,
'suitable_coolant_names': get_suitable_coolant_names(item)
}
functional_tool_list.append(val)
kw = json.dumps(functional_tool_list, ensure_ascii=False)
@@ -251,8 +249,6 @@ class FunctionalCuttingToolEntity(models.Model):
logging.info("功能刀具同步失败:%s" % e)
class FunctionalToolWarning(models.Model):
_inherit = 'sf.functional.tool.warning'
_description = '功能刀具预警注册'

View File

@@ -44,71 +44,79 @@ class SfMaintenanceEquipment(models.Model):
# ==========机床当前刀库实时信息接口==========
def register_equipment_tool(self):
config = self.env['res.config.settings'].get_values()
# token = sf_sync_config['token'Ba F2CF5DCC-1A00-4234-9E95-65603F70CC8A]
headers = {'Authorization': config['center_control_Authorization']}
crea_url = config['center_control_url'] + "/AutoDeviceApi/GetToolInfos"
params = {"DeviceId": self.name}
r = requests.get(crea_url, params=params, headers=headers)
ret = r.json()
logging.info('register_equipment_tool:%s' % ret)
datas = ret['Datas']
self.write_maintenance_equipment_tool(datas)
if ret['Succeed']:
return "机床当前刀库实时信息指令发送成功"
else:
raise ValidationError("机床当前刀库实时信息指令发送失败")
try:
config = self.env['res.config.settings'].get_values()
# token = sf_sync_config['token'Ba F2CF5DCC-1A00-4234-9E95-65603F70CC8A]
headers = {'Authorization': config['center_control_Authorization']}
crea_url = config['center_control_url'] + "/AutoDeviceApi/GetToolInfos"
params = {"DeviceId": self.name}
r = requests.get(crea_url, params=params, headers=headers)
ret = r.json()
logging.info('register_equipment_tool:%s' % ret)
datas = ret['Datas']
self.write_maintenance_equipment_tool(datas)
if ret['Succeed']:
return "机床当前刀库实时信息指令发送成功"
else:
raise ValidationError("机床当前刀库实时信息指令发送失败")
except Exception as e:
logging.info("register_equipment_tool()捕获错误信息:%s" % e)
def write_maintenance_equipment_tool(self, datas):
if datas:
# 清除设备机床刀位的刀具信息
for obj in self.product_template_ids:
obj.write({
'functional_tool_name_id': False,
'tool_install_time': None
})
for data in datas:
maintenance_equipment_id = self.search([('name', '=', data['DeviceId'])])
if maintenance_equipment_id:
tool_id = '%s%s' % (data['ToolId'][0:1], data['ToolId'][1:].zfill(2))
equipment_tool_id = self.env['maintenance.equipment.tool'].sudo().search(
[('equipment_id', '=', maintenance_equipment_id.id), ('code', '=', tool_id)])
functional_tool_id = self.env['sf.functional.cutting.tool.entity'].sudo().search(
[('rfid', '=', data['RfidCode'])])
if functional_tool_id:
# 查询该功能刀具是否已经装在机床内其他位置,如果是就删除
equipment_tools = self.env['maintenance.equipment.tool'].sudo().search(
[('functional_tool_name_id', '=', functional_tool_id.id), ('code', '!=', tool_id)])
if equipment_tools:
for item in equipment_tools:
item.write({
'functional_tool_name_id': False,
'tool_install_time': None
})
try:
if datas:
# 清除设备机床刀位的刀具信息
for obj in self.product_template_ids:
obj.write({
'functional_tool_name_id': False,
'tool_install_time': None
})
for data in datas:
maintenance_equipment_id = self.search([('name', '=', data['DeviceId'])])
if maintenance_equipment_id:
tool_id = '%s%s' % (data['ToolId'][0:1], data['ToolId'][1:].zfill(2))
equipment_tool_id = self.env['maintenance.equipment.tool'].sudo().search(
[('equipment_id', '=', maintenance_equipment_id.id), ('code', '=', tool_id)])
functional_tool_id = self.env['sf.functional.cutting.tool.entity'].sudo().search(
[('rfid', '=', data['RfidCode'])])
if functional_tool_id:
if len(functional_tool_id) > 1:
functional_tool_id = functional_tool_id[-1]
# 查询该功能刀具是否已经装在机床内其他位置,如果是就删除
equipment_tools = self.env['maintenance.equipment.tool'].sudo().search(
[('functional_tool_name_id', '=', functional_tool_id.id), ('code', '!=', tool_id)])
if equipment_tools:
for item in equipment_tools:
item.write({
'functional_tool_name_id': False,
'tool_install_time': None
})
else:
logging.info('Rfid为【%s】的功能刀具不存在!' % data['RfidCode'])
time = None
if data['AddDatetime']:
datatime = str(data['AddDatetime'])
time = fields.Datetime.from_string(datatime[0:10] + ' ' + datatime[11:19])
if equipment_tool_id and functional_tool_id:
tool_install_time = {'Nomal': '正常', 'Warning': '报警'}
equipment_tool_id.write({
'functional_tool_name_id': functional_tool_id.id,
'tool_install_time': time
})
if functional_tool_id.current_location != '机内刀库':
# 对功能刀具进行移动到生产线
functional_tool_id.tool_inventory_displacement_out()
functional_tool_id.write({
'max_lifetime_value': data['MaxLife'],
'used_value': data['UseLife'],
'functional_tool_status': tool_install_time.get(data['State'])
})
else:
logging.info('Rfid为%s的功能刀具不存在!' % data['RfidCode'])
time = None
if data['AddDatetime']:
datatime = str(data['AddDatetime'])
time = fields.Datetime.from_string(datatime[0:10] + ' ' + datatime[11:19])
if equipment_tool_id and functional_tool_id:
tool_install_time = {'Nomal': '正常', 'Warning': '报警'}
equipment_tool_id.write({
'functional_tool_name_id': functional_tool_id.id,
'tool_install_time': time
})
if functional_tool_id.current_location_id.name != '制造前':
# 对功能刀具进行出库到生产线
functional_tool_id.tool_inventory_displacement_out()
functional_tool_id.write({
'max_lifetime_value': data['MaxLife'],
'used_value': data['UseLife'],
'functional_tool_status': tool_install_time.get(data['State'])
})
else:
raise ValidationError('获取的【%s】设备不存在!!!' % data['DeviceId'])
else:
raise ValidationError('没有获取到刀具库信息!!!')
logging.info('获取的%s设备不存在!' % data['DeviceId'])
else:
logging.info('没有获取到【%s】设备的刀具库信息!!!' % self.name)
except Exception as e:
logging.info("write_maintenance_equipment_tool()捕获错误信息:%s" % e)
class StockLot(models.Model):
@@ -134,9 +142,6 @@ class StockLot(models.Model):
record.tool_material_status = '报废'
else:
record.tool_material_status = '未入库'
if record.fixture_material_search_id:
# 注册夹具物料状态到cloud平台
record.enroll_fixture_material_stock()
@api.model
def name_search(self, name='', args=None, operator='ilike', limit=100):

View File

@@ -0,0 +1,23 @@
from odoo import api, fields, models, _
class ShelfLocation(models.Model):
_inherit = 'sf.shelf.location'
tool_rfid = fields.Char('Rfid', compute='_compute_tool', store=True)
tool_name_id = fields.Many2one('sf.functional.cutting.tool.entity', string='功能刀具名称', compute='_compute_tool',
store=True)
@api.depends('product_id')
def _compute_tool(self):
for item in self:
if item.product_id:
if item.product_id.categ_id.name == '功能刀具':
tool_id = self.env['sf.functional.cutting.tool.entity'].sudo().search(
[('barcode_id', '=', item.product_sn_id.id)])
if tool_id:
item.tool_rfid = tool_id.rfid
item.tool_name_id = tool_id.id
continue
item.tool_rfid = ''
item.tool_name_id = False

View File

@@ -29,6 +29,7 @@
<field name="current_location" string="当前位置"/>
<field name="current_location_id" invisible="1"/>
<field name="current_location" optional="hide"/>
<field name="sf_cutting_tool_type_id" invisible="True"/>
</tree>
</field>
@@ -173,7 +174,10 @@
<field name="cut_time" attrs="{'invisible': [('new_former','=','0')]}"/>
<field name="cut_length" attrs="{'invisible': [('new_former','=','0')]}"/>
<field name="cut_number" attrs="{'invisible': [('new_former','=','0')]}"/>
<field name="current_location_id" string="当前位置"/>
<field name="current_location" string="当前位置"/>
<field name="current_shelf_location_id" string="当前货位"
attrs="{'invisible': [('current_shelf_location_id', '=', False)]}"/>
</group>
</group>
</page>
@@ -189,6 +193,7 @@
<field name="arch" type="xml">
<search>
<field name="rfid"/>
<field name="barcode_id"/>
<field name="tool_name_id"/>
<field name="functional_tool_diameter"/>
<field name="knife_tip_r_angle"/>
@@ -204,8 +209,8 @@
domain="[('functional_tool_status', '!=', '已拆除')]"/>
<filter string="已拆除" name="state_removed" domain="[('functional_tool_status', '=', '已拆除')]"/>
<searchpanel>
<field name="functional_tool_status" icon="fa-building" enable_counters="1"/>
<field name="current_location" icon="fa-building" enable_counters="1"/>
<field name="functional_tool_status" icon="fa-building" enable_counters="1"/>
<field name="sf_cutting_tool_type_id" icon="fa-building" enable_counters="1"/>
</searchpanel>
<group expand="0">
@@ -482,7 +487,9 @@
<field name="knife_tip_r_angle"/>
<field name="install_tool_time"/>
<field name="location_id"/>
<field name="current_location_id"/>
<field name="location_dest_id"/>
<field name="destination_location_id"/>
<field name="date"/>
<field name="qty_done" string="数量"/>
<field name="functional_tool_type_id" invisible="True"/>
@@ -497,21 +504,20 @@
<field name="model">stock.move.line</field>
<field name="arch" type="xml">
<search>
<field name="reference"/>
<field name="lot_id"/>
<field name="rfid"/>
<field name="functional_tool_name"/>
<field name="diameter"/>
<field name="knife_tip_r_angle"/>
<field name="install_tool_time"/>
<field name="location_id"/>
<field name="location_dest_id"/>
<field name="date"/>
<field name="qty_done"/>
<field name="functional_tool_type_id" invisible="True"/>
<field name="reference"/>
<field name="lot_id"/>
<searchpanel>
<field name="functional_tool_type_id" enable_counters="1" icon="fa-building"/>
</searchpanel>
<group expand="0">
<filter string="功能刀具名称" name="functional_tool_name" domain="[]"
context="{'group_by': 'functional_tool_name'}"/>
<filter string="日期" name="date" domain="[]" context="{'group_by': 'date'}"/>
</group>
</search>
</field>
</record>
@@ -525,7 +531,7 @@
ref="sf_tool_management.sf_inbound_and_outbound_records_of_functional_tools_view_tree"/>
<field name="search_view_id"
ref="sf_tool_management.sf_inbound_and_outbound_records_of_functional_tools_view_search"/>
<field name="domain">[('functional_tool_name_id', '!=', False)]</field>
<field name="domain">[('functional_tool_name', '!=', False)]</field>
</record>
</data>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="view_shelf_location_tool" model="ir.ui.view">
<field name="name">sf.shelf.location.form.tool</field>
<field name="model">sf.shelf.location</field>
<field name="inherit_id" ref="sf_warehouse.view_shelf_location_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='product_id']" position="after">
<field name="tool_rfid" attrs="{'invisible': [('tool_name_id', '=', False)]}"/>
<field name="tool_name_id" attrs="{'invisible': [('tool_name_id', '=', False)]}"/>
</xpath>
</field>
</record>
</odoo>

View File

@@ -62,6 +62,7 @@
<tree>
<field name="name"/>
<field name="rfid"/>
<field name="product_qty"/>
<field name="tool_material_status"/>
<!-- <button name="enroll_tool_material_stock" string="序列号注册" type="object" class="btn-primary"/>-->
</tree>

View File

@@ -854,10 +854,10 @@ class ProductProduct(models.Model):
'company_id': self.env.company.id
})
# 获取位置对象
location_inventory_id = self.env['stock.location'].search([('name', '=', 'Production')])
location_inventory_ids = self.env['stock.location'].search([('name', 'in', ('Production', '生产'))])
stock_location_id = self.env['stock.location'].search([('name', '=', '组装后')])
# 创建功能刀具该批次/序列号 库存移动和移动历史
stock_lot.create_stock_quant(location_inventory_id, stock_location_id, functional_tool_assembly.id,
stock_lot.create_stock_quant(location_inventory_ids[-1], stock_location_id, functional_tool_assembly.id,
obj.assembly_order_code, obj, obj.after_tool_groups_id)
return stock_lot

View File

@@ -416,19 +416,19 @@ class ShelfLocation(models.Model):
host = printer_config.printer_id.ip_address
port = printer_config.printer_id.port
self.print_qr_code(barcode, host, port)
# # 获取当前wizard的视图ID或其他标识信息
# view_id = self.env.context.get('view_id')
# # 构造返回wizard页面的action字典
# action = {
# 'type': 'ir.actions.act_window',
# 'name': '返回 Wizard',
# 'res_model': 'sf.shelf', # 替换为你的wizard模型名称
# 'view_mode': 'form',
# 'view_id': view_id, # 如果需要基于特定的视图返回
# 'target': 'new', # 如果需要在新的窗口或标签页打开
# 'res_id': self.shelf_id, # 如果你想要返回当前记录的视图
# }
# return action
# 获取当前wizard的视图ID或其他标识信息
view_id = self.env.context.get('view_id')
# 构造返回wizard页面的action字典
action = {
'type': 'ir.actions.act_window',
'name': '返回 Wizard',
'res_model': 'sf.shelf', # 替换为你的wizard模型名称
'view_mode': 'form',
'view_id': view_id, # 如果需要基于特定的视图返回
'target': 'new', # 如果需要在新的窗口或标签页打开
'res_id': self.shelf_id, # 如果你想要返回当前记录的视图
}
return action
# # 仓库类别selection库区、库位、货位
# location_type = fields.Selection([
@@ -1143,7 +1143,10 @@ class CustomStockMove(models.Model):
move_lines = self.move_line_ids # 获取当前 stock.move 对应的所有 stock.move.line 记录
for line in move_lines:
if line.lot_name: # 确保 lot_name 存在
qr_data = self.compute_lot_qr_code(line.lot_name)
lot_name = line.lot_name
if line.product_id.categ_id.name == '坯料':
lot_name = lot_name.split('[', 1)[0]
qr_data = self.compute_lot_qr_code(lot_name)
# 假设 stock.move.line 模型中有一个字段叫做 lot_qr_code 用于存储二维码数据
line.lot_qr_code = qr_data
return result

View File

@@ -95,17 +95,34 @@ class MrsShelfLocationDataSync(models.Model):
return code_pair[0]
return None # 如果没有找到对应的值返回None或适当的默认值
# 定时更新所有设备机床刀库信息
equipment_ids = self.env['maintenance.equipment'].search(
[('equipment_type', '=', '机床'), ('function_type', '!=', False)])
for equipment_id in equipment_ids:
if equipment_id:
equipment_id.register_equipment_tool()
shelfinfo = self.env['sf.shelf.location'].get_sf_shelf_location_info()
print('shelfinfo:', shelfinfo)
for item in shelfinfo:
shelf_barcode = find_our_code(item['Postion'], total_data)
location_id = self.env['sf.shelf.location'].search([('barcode', '=', shelf_barcode)], limit=1)
if location_id:
stock_lot_obj = self.env['stock.lot'].search([('rfid', '=', item['RfidCode'])], limit=1)
if stock_lot_obj:
location_id.product_sn_id = stock_lot_obj.id
# 如果是线边刀库信息,则对功能刀具移动生成记录
if 'Tool' in item['Postion']:
tool = self.env['sf.functional.cutting.tool.entity'].sudo().search(
[('rfid', '=', item['RfidCode']), ('functional_tool_status', '!=', '已拆除')])
tool.tool_in_out_stock_location(location_id)
if tool:
location_id.product_sn_id = tool.barcode_id.id
else:
location_id.product_sn_id = False
else:
location_id.product_sn_id = False
stock_lot_obj = self.env['stock.lot'].search([('rfid', '=', item['RfidCode'])], limit=1)
if stock_lot_obj:
location_id.product_sn_id = stock_lot_obj.id
else:
location_id.product_sn_id = False
logging.info('货架已获取信息:%s' % item)
except Exception as e: