Compare commits

...

248 Commits

Author SHA1 Message Date
guanhuan
9d28eccd1b 用户创建员工同时修改用户的企微id 2024-10-29 15:50:38 +08:00
guanhuan
8dc3f2698b 修改员工绑定用户同时修改用户的企微id 2024-10-29 14:50:00 +08:00
guanhuan
69c63f708d 修改和新增员工时根据邮箱获取企微id 2024-10-24 17:06:31 +08:00
管欢
e264306fed Accept Merge Request #1452: (feature/auxiliary_files_upload -> 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/1452
2024-10-24 14:58:34 +08:00
guanhuan
f557cb8d10 零件图纸,质检标准显示位置修改 2024-10-24 14:55:36 +08:00
杨金灵
cf34e28e35 Accept Merge Request #1451: (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/1451?initial=true
2024-10-24 14:40:28 +08:00
jinling.yang
b7595fe4ec Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/修复销售订单逾期过期 2024-10-24 14:28:07 +08:00
jinling.yang
2551d82a99 修复销售订单逾期过期 2024-10-24 14:27:44 +08:00
管欢
0cedba8ea4 Accept Merge Request #1450: (feature/auxiliary_files_upload -> 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/1450
2024-10-24 14:24:18 +08:00
guanhuan
d64a814251 制造订单零件图纸,质检标准显示 2024-10-24 11:33:10 +08:00
胡尧
86d5de4fa1 Accept Merge Request #1449: (feature/plan_slow -> develop)
Merge Request: 解决排程报错

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1449?initial=true
2024-10-24 11:30:06 +08:00
胡尧
ed15958319 解决报错 2024-10-24 11:29:36 +08:00
廖丹龙
0bf9c752f6 Accept Merge Request #1442: (feature/machining_accuracy_sync -> develop)
Merge Request: sf优化

Created By: @廖丹龙
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @廖丹龙
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1442
2024-10-24 11:23:20 +08:00
杨金灵
e62eb060fb Accept Merge Request #1448: (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/1448?initial=true
2024-10-24 10:54:00 +08:00
jinling.yang
563b44adb1 添加输出 2024-10-24 10:53:04 +08:00
liaodanlong
a094946428 按钮位置修改 2024-10-24 10:37:50 +08:00
jinling.yang
d28fd5d787 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-10-24 10:35:52 +08:00
jinling.yang
41c357d124 Merge branch 'feature/修复设备文件' into develop 2024-10-24 10:32:46 +08:00
杨金灵
f94d52a4d9 Accept Merge Request #1447: (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/1447?initial=true
2024-10-24 10:30:39 +08:00
jinling.yang
74dc31b083 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-10-24 10:28:41 +08:00
jinling.yang
3b1fca529a Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-10-24 10:28:07 +08:00
jinling.yang
843eeb8a89 修复设备文件 2024-10-24 10:27:46 +08:00
胡尧
12e81ec702 Accept Merge Request #1446: (feature/plan_slow -> develop)
Merge Request: 解决排程慢的问题

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1446
2024-10-24 10:15:55 +08:00
jinling.yang
fe2af8a4ce Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-10-24 10:13:28 +08:00
jinling.yang
f337a30aba Merge branch 'feature/优化加工质检' into develop 2024-10-24 10:09:45 +08:00
杨金灵
7f3a8d877f Accept Merge Request #1445: (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/1445
2024-10-24 10:09:29 +08:00
jinling.yang
5e6a7d0a39 还原代码 2024-10-24 10:07:56 +08:00
jinling.yang
5788a157c5 还原代码 2024-10-24 10:03:18 +08:00
胡尧
0b70447333 修改排程逻辑 2024-10-24 09:47:20 +08:00
jinling.yang
de8ba77bef 优化加工质检页面 2024-10-24 09:22:35 +08:00
胡尧
1026c0edd0 修改排程逻辑 2024-10-24 09:18:21 +08:00
管欢
f366b650d0 Accept Merge Request #1444: (feature/auxiliary_files_upload -> 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/1444
2024-10-23 17:54:42 +08:00
guanhuan
6054ce39f3 附件文件名 2024-10-23 17:43:03 +08:00
禹翔辉
e1e9dc425b Accept Merge Request #1443: (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/1443
2024-10-23 17:12:17 +08:00
yuxianghui
3a2a942f3b Merge branch 'feature/设备维保优化' into feature/工单状态优化 2024-10-23 17:05:47 +08:00
yuxianghui
bf9d848f10 1、工单状态优化 2024-10-23 17:04:35 +08:00
liaodanlong
add7d404a0 质检单类型翻译 2024-10-23 17:03:16 +08:00
liaodanlong
7e6fa7b6c7 产品类别隐藏 2024-10-23 17:02:24 +08:00
禹翔辉
3fd17302f5 Accept Merge Request #1440: (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/1440
2024-10-23 15:51:06 +08:00
胡尧
db9cee3e28 Accept Merge Request #1441: (feature/workorder_exceptions -> develop)
Merge Request: 修改工单通知筛选条件

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1441?initial=true
2024-10-23 15:50:31 +08:00
胡尧
97a26dfa06 修改工单通知筛选条件 2024-10-23 15:50:01 +08:00
yuxianghui
cebd895811 Merge branch 'feature/设备模块优化' into feature/设备维保优化 2024-10-23 15:49:13 +08:00
yuxianghui
bb6c208d37 设备维保计划优化 2024-10-23 15:48:33 +08:00
胡尧
921f2c3503 Accept Merge Request #1439: (feature/workorder_exceptions -> develop)
Merge Request: 修改工单通知筛选条件

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1439?initial=true
2024-10-23 15:38:55 +08:00
胡尧
1224e0e094 修改工单通知筛选条件 2024-10-23 15:38:09 +08:00
胡尧
a571a870d3 修改工单通知筛选条件 2024-10-23 15:33:48 +08:00
胡尧
a28d20b3bf 修改排程逻辑 2024-10-23 15:30:05 +08:00
管欢
d4e0d36166 Accept Merge Request #1438: (feature/machining_accuracy_sync -> 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/1438
2024-10-23 14:00:41 +08:00
jinling.yang
39579aef10 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化加工质检
# Conflicts:
#	sf_message/models/sf_message_maintenance_logs.py
2024-10-23 11:56:16 +08:00
jinling.yang
1fe8fd6933 优化定时器代码 2024-10-23 11:55:43 +08:00
liaodanlong
3b1caca62b 还原 2024-10-23 11:00:19 +08:00
liaodanlong
3fe8c957be 加工精度字段信息修改 2024-10-23 10:41:32 +08:00
yuxianghui
98923c1797 1、设备维保优化 2024-10-22 17:52:20 +08:00
guanhuan
8661dd16c1 加工精度同步 2024-10-22 15:37:41 +08:00
guanhuan
7157ea1587 加工精度同步 2024-10-22 15:35:34 +08:00
廖丹龙
a580a12d69 Accept Merge Request #1437: (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/1437?initial=true
2024-10-22 13:56:38 +08:00
liaodanlong
0d512e2e43 制造订单添加订单交期字段信息 2024-10-22 13:55:24 +08:00
廖丹龙
103069c554 Accept Merge Request #1436: (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/1436?initial=true
2024-10-22 13:48:28 +08:00
yuxianghui
f2482b5128 处理功能刀具产生库存移动时,功能刀具列表的功能刀具位置没有实时发生变更的问题 2024-10-22 13:45:08 +08:00
liaodanlong
da38d24111 制造订单添加订单交期字段信息 2024-10-22 13:33:53 +08:00
廖丹龙
1f0ebe71c7 Accept Merge Request #1435: (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/1435?initial=true
2024-10-22 11:56:28 +08:00
liaodanlong
f897955f68 制造订单添加订单交期字段信息 2024-10-22 11:45:08 +08:00
胡尧
451e70b7c7 Accept Merge Request #1434: (feature/workorder_exceptions -> develop)
Merge Request: 修改无功能刀具原因话术

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1434
2024-10-21 17:03:34 +08:00
胡尧
6c1c2ca0fc 修改无功能刀具原因话术 2024-10-21 17:02:59 +08:00
廖丹龙
e7420365cf Accept Merge Request #1433: (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/1433
2024-10-21 16:09:08 +08:00
liaodanlong
736a18518c 制造订单添加订单交期字段信息 2024-10-21 16:07:43 +08:00
liaodanlong
41b287d559 制造订单添加订单交期字段信息 2024-10-21 16:06:03 +08:00
胡尧
5d8e0bda08 Accept Merge Request #1432: (feature/workorder_exceptions -> develop)
Merge Request: 处理设备故障的问题

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1432?initial=true
2024-10-21 15:41:06 +08:00
胡尧
e9dbbaedf4 处理设备故障的问题 2024-10-21 15:40:38 +08:00
胡尧
92ae6be3bd Accept Merge Request #1431: (feature/workorder_exceptions -> develop)
Merge Request: 修改模板标题

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1431
2024-10-21 14:59:57 +08:00
胡尧
b00038aaed 修改YC0004消息推送 2024-10-21 14:59:16 +08:00
胡尧
86c1880cdb 修改模板标题 2024-10-21 14:41:09 +08:00
廖丹龙
cfd2dda4e6 Accept Merge Request #1430: (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/1430
2024-10-21 14:34:07 +08:00
liaodanlong
c01e9a4d39 制造订单添加订单交期字段信息 2024-10-21 14:18:53 +08:00
廖丹龙
88ff4bbaa9 Accept Merge Request #1429: (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/1429?initial=true
2024-10-21 14:01:20 +08:00
liaodanlong
f62c70d354 Merge branch 'refs/heads/develop' into feature/销售和排程添加消息推送 2024-10-21 13:57:24 +08:00
liaodanlong
22c9de86f6 制造订单添加订单交期字段信息 2024-10-21 13:56:34 +08:00
胡尧
b362f74336 Accept Merge Request #1428: (feature/workorder_exceptions -> develop)
Merge Request: 修改接口参数

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1428?initial=true
2024-10-21 13:47:36 +08:00
胡尧
81cfbfb540 修改接口参数 2024-10-21 11:46:14 +08:00
胡尧
668db4475f Accept Merge Request #1427: (feature/workorder_exceptions -> develop)
Merge Request: 修改单元测试

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1427?initial=true
2024-10-21 11:37:48 +08:00
胡尧
2af21bc4ee 修改单元测试 2024-10-21 11:37:01 +08:00
管欢
e6614a624f Accept Merge Request #1426: (feature/auxiliary_files_upload -> 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/1426
2024-10-21 10:11:36 +08:00
guanhuan
124bc8478e 辅助文件上传 2024-10-21 10:09:19 +08:00
guanhuan
1a3a178ec6 Revert "辅助文件上传"
This reverts commit cae5149fba.
2024-10-21 10:08:35 +08:00
guanhuan
cae5149fba 辅助文件上传 2024-10-21 10:07:49 +08:00
管欢
5c4c036948 Accept Merge Request #1425: (feature/auxiliary_files_upload -> 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/1425
2024-10-21 10:01:22 +08:00
guanhuan
4003d6a652 Merge branch 'refs/heads/develop' into feature/auxiliary_files_upload
# Conflicts:
#	sf_dlm_management/views/product_template_management_view.xml
2024-10-21 09:50:09 +08:00
胡嘉莹
0e8e81e4cb Accept Merge Request #1423: (feature/临时分支 -> develop)
Merge Request: sf销售订单明细新增是否带料及带料尺寸字段

Created By: @胡嘉莹
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @胡嘉莹
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1423
2024-10-18 16:44:46 +08:00
hujiaying
8cff3d8377 sf销售订单详情新增是否带料,带料尺寸,修改bfm分配工厂,sf接收订单生成销售订单新增两个字段,并修改订单详情及订单详情表单新增字段显示 2024-10-18 16:39:15 +08:00
guanhuan
b132771c92 辅助文件上传 2024-10-18 14:32:20 +08:00
马广威
cbaf0d79c1 Accept Merge Request #1422: (feature/制造功能优化 -> develop)
Merge Request: 增加设备oee处获取数据的定时器

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1422?initial=true
2024-10-18 10:18:28 +08:00
mgw
953d675dcf Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2024-10-18 10:17:38 +08:00
mgw
182eb83090 暂时屏蔽24数据 2024-10-18 10:17:22 +08:00
mgw
67a607b053 增加设备oee处获取数据的定时器 2024-10-18 10:05:55 +08:00
guanhuan
00a04af94f 加工精度 2024-10-18 09:30:20 +08:00
禹翔辉
33d23c28b1 Accept Merge Request #1421: (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/1421
2024-10-18 09:21:43 +08:00
yuxianghui
571fb29482 Merge branch 'feature/用刀校验优化' into feature/工单状态优化 2024-10-18 09:14:39 +08:00
yuxianghui
1dae20e055 处理制造订单、工单的状态计算方法没有触发的问题 2024-10-18 09:13:34 +08:00
hujiaying
6be9d44572 Merge remote-tracking branch 'origin/develop' into feature/临时分支 2024-10-18 08:40:57 +08:00
mgw
8a459e7e90 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2024-10-17 17:54:59 +08:00
mgw
4c486e53aa 设备oee界面数据准备 2024-10-17 17:54:32 +08:00
yuxianghui
19509a3ce2 1 2024-10-17 17:54:08 +08:00
胡嘉莹
4d424e90d3 Accept Merge Request #1420: (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/1420?initial=true
2024-10-17 17:49:26 +08:00
hujiaying
9bbf613bcb 修改生成完工入库提醒,订单发货提醒跳转到表单详情 2024-10-17 17:39:43 +08:00
guanhuan
cc40d479a9 加工精度同步 2024-10-17 17:20:51 +08:00
禹翔辉
f5ea0ec153 Accept Merge Request #1419: (feature/用刀校验优化 -> develop)
Merge Request: 优化手动返工时,cnc用刀校验逻辑

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1419?initial=true
2024-10-17 17:04:12 +08:00
yuxianghui
ea6c0f7d0b Merge branch 'feature/程序用刀校验优化' into feature/用刀校验优化 2024-10-17 17:02:17 +08:00
yuxianghui
763009a3c0 1、优化手动返工时,cnc用刀校验逻辑 2024-10-17 17:01:20 +08:00
guanhuan
cf34ac5bbc 辅助文件上传 2024-10-17 16:31:13 +08:00
禹翔辉
0faedd35d7 Accept Merge Request #1418: (feature/程序用刀校验优化 -> develop)
Merge Request: 修改调用创建cam程序用刀计划方法的判断条件

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1418
2024-10-17 16:01:42 +08:00
yuxianghui
135b97d4f8 1 2024-10-17 16:00:44 +08:00
yuxianghui
61f3aff768 Merge branch 'feature/制造订单状态优化_3' into feature/程序用刀校验优化 2024-10-17 15:52:06 +08:00
yuxianghui
9e369f0150 修改调用创建cam程序用刀计划方法的判断条件 2024-10-17 15:51:00 +08:00
杨金灵
16d50f5bf2 Accept Merge Request #1417: (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/1417?initial=true
2024-10-17 15:40:23 +08:00
jinling.yang
80f0454996 工作中心添加质检权限 2024-10-17 15:37:08 +08:00
jinling.yang
9b9d811594 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-10-17 15:33:51 +08:00
jinling.yang
008ae20329 Merge branch 'feature/检测结果添加质检权限' into develop 2024-10-17 15:33:29 +08:00
杨金灵
80b3b4b0f7 Accept Merge Request #1416: (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/1416
2024-10-17 15:26:29 +08:00
jinling.yang
d64b480496 检测结果添加质检权限 2024-10-17 15:25:13 +08:00
禹翔辉
854ec8da4e Accept Merge Request #1415: (feature/制造订单状态优化_3 -> 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/1415?initial=true
2024-10-17 14:43:48 +08:00
yuxianghui
d25b871854 1 2024-10-17 14:42:35 +08:00
禹翔辉
37aafe7b30 Accept Merge Request #1414: (feature/制造订单状态优化_3 -> develop)
Merge Request: 1、优化手动获取编程的接口,添加获取编程完成之后进行用刀校验;2、处理 权限问题-工单详情缺少【时间跟踪】tab;3、用刀校验方法添加日志

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1414
2024-10-17 14:29:32 +08:00
yuxianghui
26910f7b15 Merge branch 'feature/制造订单状态优化_2' into feature/制造订单状态优化_3 2024-10-17 14:25:05 +08:00
杨金灵
3ea2acd46e Accept Merge Request #1413: (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/1413?initial=true
2024-10-17 14:23:36 +08:00
yuxianghui
303462ba9c Merge branch 'feature/制造订单状态优化_1' into feature/制造订单状态优化_2 2024-10-17 14:22:59 +08:00
jinling.yang
53fad50af6 修复工单定时器 2024-10-17 14:22:43 +08:00
yuxianghui
1245323b9d 1、优化手动获取编程的接口,添加获取编程完成之后进行用刀校验;2、处理 权限问题-工单详情缺少【时间跟踪】tab;3、用刀校验方法添加日志 2024-10-17 14:22:09 +08:00
杨金灵
4d8e86cff3 Accept Merge Request #1412: (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/1412
2024-10-17 14:08:18 +08:00
jinling.yang
7bc7d2059c 还原代码 2024-10-17 14:06:16 +08:00
jinling.yang
f9c209e85c Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-10-17 13:47:40 +08:00
jinling.yang
6ae783387c Merge branch 'feature/修复加工质检' into develop 2024-10-17 13:47:18 +08:00
杨金灵
7c0202afc6 Accept Merge Request #1411: (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/1411?initial=true
2024-10-17 13:47:00 +08:00
jinling.yang
9ad582612b 还原注释代码 2024-10-17 13:43:43 +08:00
jinling.yang
d1db917432 修复加工质检 2024-10-17 11:58:54 +08:00
杨金灵
847293385d Accept Merge Request #1410: (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/1410?initial=true
2024-10-17 11:34:40 +08:00
jinling.yang
4e8eccfd0b 还原代码 2024-10-17 11:33:20 +08:00
jinling.yang
5cb5306471 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-10-17 11:19:28 +08:00
jinling.yang
9a5b45b969 Merge branch 'feature/加工质检添加权限' into develop 2024-10-17 11:19:04 +08:00
杨金灵
7c82bbf3da Accept Merge Request #1409: (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/1409?initial=true
2024-10-17 11:18:39 +08:00
jinling.yang
9177acf277 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/加工质检添加权限
# Conflicts:
#	sf_quality/views/quality_cnc_test_view.xml
2024-10-17 11:03:08 +08:00
jinling.yang
93187d7f4a Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-10-17 11:01:57 +08:00
jinling.yang
94b1551de2 加工质检添加权限 2024-10-17 11:01:42 +08:00
马广威
1c713d3278 Accept Merge Request #1408: (feature/制造功能优化 -> develop)
Merge Request: 修改维护翻译为设备

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1408?initial=true
2024-10-17 10:26:36 +08:00
禹翔辉
bdef93fca3 Accept Merge Request #1407: (feature/制造订单状态优化_1 -> 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/1407?initial=true
2024-10-17 10:17:02 +08:00
yuxianghui
e9e55c72b9 Merge branch 'feature/制造订单状态优化' into feature/制造订单状态优化_1 2024-10-17 10:15:23 +08:00
yuxianghui
919450aafb 优化制造订单无效刀自动编程方法 2024-10-17 10:13:54 +08:00
jinling.yang
78f486ad7c Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-10-17 10:12:36 +08:00
jinling.yang
ccdfcb5e50 Merge branch 'feature/优化加工质检' into develop 2024-10-17 10:12:20 +08:00
杨金灵
9b275536e9 Accept Merge Request #1406: (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/1406?initial=true
2024-10-17 10:10:51 +08:00
jinling.yang
bf39ed10b4 还原代码 2024-10-17 10:03:45 +08:00
jinling.yang
0e8bda3369 修复加工质检 2024-10-17 09:58:24 +08:00
mgw
87bb22857a 修改维护翻译为设备 2024-10-17 09:19:47 +08:00
jinling.yang
9cd8d9d823 修复验证 2024-10-16 17:59:34 +08:00
马广威
931732f75e Accept Merge Request #1405: (feature/制造功能优化 -> develop)
Merge Request: CNC自动生产线生产业绩看板优化需求

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1405?initial=true
2024-10-16 17:33:34 +08:00
mgw
35ace3b3eb Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2024-10-16 17:29:41 +08:00
mgw
4b4601ae85 CNC自动生产线生产业绩看板优化需求 2024-10-16 17:29:25 +08:00
禹翔辉
46337855a4 Accept Merge Request #1404: (feature/制造订单状态优化 -> develop)
Merge Request: 1、处理 因为权限导致的功能刀具安全库存列表点击任意数据报错; 2、处理 下发程序校验刀具有无效刀时制造订单状态不对问题

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1404?initial=true
2024-10-16 17:04:00 +08:00
yuxianghui
43f8aec70a Merge branch 'feature/刀具页面存档权限设置' into feature/制造订单状态优化 2024-10-16 17:02:18 +08:00
yuxianghui
a21b4302d4 1、处理 因为权限导致的功能刀具安全库存列表点击任意数据报错; 2、处理 下发程序校验刀具有无效刀时制造订单状态不对问题 2024-10-16 17:01:15 +08:00
jinling.yang
4adc3b700a Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/工单定时器修复时区问题 2024-10-16 15:32:47 +08:00
杨金灵
42b5a32708 Accept Merge Request #1403: (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/1403?initial=true
2024-10-16 15:00:58 +08:00
jinling.yang
296e30e5fd Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-10-16 14:59:16 +08:00
jinling.yang
90718cc989 Merge branch 'feature/修复工单write方法' into develop 2024-10-16 14:53:37 +08:00
杨金灵
857930e169 Accept Merge Request #1402: (feature/修复工单write方法 -> develop)
Merge Request: 修复工单write方法

Created By: @杨金灵
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @杨金灵
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1402
2024-10-16 14:50:14 +08:00
jinling.yang
9b1b6e2b72 修复工单修改方法 2024-10-16 14:49:54 +08:00
jinling.yang
37217b0dd9 修复工单write方法 2024-10-16 14:46:31 +08:00
杨金灵
f138eab47a Accept Merge Request #1401: (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/1401?initial=true
2024-10-16 14:16:54 +08:00
jinling.yang
4e4c53927b 下发编程单接口添加输出 2024-10-16 14:15:37 +08:00
jinling.yang
fab1d77d64 还原注释代码 2024-10-16 14:07:35 +08:00
jinling.yang
f4f7087465 添加2D图纸和质量标准2个字段 2024-10-16 14:06:18 +08:00
jinling.yang
020da1d510 Merge branch 'feature/auxiliary_files_upload' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化加工质检 2024-10-16 11:49:37 +08:00
jinling.yang
2956f13ee7 优化加工质检 2024-10-16 11:49:05 +08:00
guanhuan
939f3d58f4 产品新增2D加工图纸,质检标准 2024-10-16 11:41:15 +08:00
胡尧
3d85b7863c Accept Merge Request #1400: (feature/workorder_exceptions -> develop)
Merge Request: 工单异常记录及消息通知

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1400?initial=true
2024-10-16 10:23:19 +08:00
胡尧
54abb7a9f7 增加备注 2024-10-16 10:22:30 +08:00
胡尧
9ca9b337ef 解决sf_quality报错问题,增加单元测试 2024-10-16 10:19:41 +08:00
胡尧
92c4bcb049 解决冲突 2024-10-15 15:25:31 +08:00
胡尧
ce5cb17e31 工单异常处理 2024-10-15 15:14:16 +08:00
杨金灵
6330929c04 Accept Merge Request #1399: (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/1399?initial=true
2024-10-15 11:56:14 +08:00
jinling.yang
79a753b609 优化质检生产仓看板 2024-10-15 11:55:10 +08:00
jinling.yang
30ebc62697 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-10-15 09:30:58 +08:00
jinling.yang
28b218a13b Merge branch 'feature/销售订单和工单逾期消息推送' into develop 2024-10-15 09:30:25 +08:00
杨金灵
cd24430ea9 Accept Merge Request #1398: (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/1398
2024-10-15 09:30:08 +08:00
jinling.yang
f4daf94f7b 还原代码 2024-10-15 09:29:23 +08:00
jinling.yang
4acce194d9 Merge branch 'feature/销售订单和工单逾期消息推送' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/销售订单和工单逾期消息推送 2024-10-15 09:27:16 +08:00
jinling.yang
761e8d4579 还原代码 2024-10-15 09:26:55 +08:00
杨金灵
284c66ad86 Merge branch refs/heads/develop into refs/heads/feature/销售订单和工单逾期消息推送 2024-10-15 09:17:21 +08:00
jinling.yang
6c7c10924a 还原注释代码 2024-10-15 09:07:11 +08:00
jinling.yang
8f2d5129b1 还原代码 2024-10-15 09:06:13 +08:00
jinling.yang
2a067778bc 优化质量检测(加工检测)及消息推送 2024-10-14 17:53:38 +08:00
禹翔辉
299cc2f12f Accept Merge Request #1397: (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/1397?initial=true
2024-10-14 16:04:41 +08:00
yuxianghui
ce705abd20 刀具页面存档权限设置为只有超级管理员才能存档 2024-10-14 16:03:21 +08:00
胡尧
e2bd36ca16 工单异常处理 2024-10-14 15:18:27 +08:00
禹翔辉
e2dbd41e8f Accept Merge Request #1396: (feature/工单form视图优化 -> 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/1396
2024-10-14 13:47:43 +08:00
yuxianghui
050a61f334 Merge branch 'feature/制造订单功能刀具状态优化' into feature/工单form视图优化 2024-10-14 13:45:24 +08:00
马广威
0fa7c1b2d7 Accept Merge Request #1395: (feature/制造功能优化 -> develop)
Merge Request: 调整“驾驶舱”的机床状态与工厂产线实际不一致的问题

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1395?initial=true
2024-10-14 13:45:17 +08:00
yuxianghui
e1af6ba2f5 1、完成 工件装夹工单详情页版面优化需求 2024-10-14 13:41:52 +08:00
禹翔辉
4a928735eb Accept Merge Request #1394: (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/1394?initial=true
2024-10-11 17:59:10 +08:00
yuxianghui
fdc2af4a39 Merge branch 'feature/销售订单按钮优化' into feature/制造订单功能刀具状态优化 2024-10-11 17:56:51 +08:00
yuxianghui
70b3daad73 1、删除功能刀具tree视图图片字段;2、修改货位看板关联展示字段;3、获取编程单接口调用cnc用刀校验方法添加报错处理; 2024-10-11 17:53:12 +08:00
jinling.yang
d8bade64e1 优化质量:添加加工质检 2024-10-11 17:52:33 +08:00
胡尧
f779c492d8 Accept Merge Request #1393: (feature/流程用扫码完成 -> develop)
Merge Request: 解决销售单不能新增的bug

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1393?initial=true
2024-10-11 15:04:50 +08:00
胡尧
a7b98f1e5e 解决销售单不能新增的bug 2024-10-11 15:03:46 +08:00
胡嘉莹
797eb9b159 Accept Merge Request #1392: (feature/临时分支 -> develop)
Merge Request: 修改消息发送前已入库或已发货消息发送内容为null

Created By: @胡嘉莹
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @胡嘉莹
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1392?initial=true
2024-10-11 10:10:57 +08:00
hujiaying
c3e40fd3aa 修改消息发送前已入库或已发货消息发送内容为null 2024-10-11 09:52:42 +08:00
胡嘉莹
0ed07b024a Accept Merge Request #1391: (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/1391?initial=true
2024-10-11 08:54:03 +08:00
hujiaying
22da51729b 修改项目升级初始化数据问题 2024-10-11 08:47:56 +08:00
廖丹龙
c3be2894c9 Accept Merge Request #1386: (feature/销售和排程添加消息推送 -> develop)
Merge Request: 产品 qty_available字段名称修改为库存数量

Created By: @廖丹龙
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @廖丹龙
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1386
2024-10-10 17:55:49 +08:00
胡嘉莹
e08f968f1a Accept Merge Request #1390: (feature/临时分支 -> develop)
Merge Request: 新增sf生产完工入库提醒,订单发货提醒代码

Created By: @胡嘉莹
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @胡嘉莹
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1390
2024-10-10 17:53:57 +08:00
jinling.yang
351815ad91 优化销售订单+工单逾期预警和已1逾期代码 2024-10-10 17:36:35 +08:00
yuxianghui
25a90f3966 1、获取mrs编程接口优化,重新编程接口优化,创建CAM方法优化,cnc用刀校验逻辑优化 2024-10-10 17:31:56 +08:00
hujiaying
50bb50f5ab 修改计划排程,超过小时产能提示产线的小时产能以及超出的件数 2024-10-10 16:47:25 +08:00
hujiaying
d1ff7c196d 解决合并冲突 2024-10-10 16:08:23 +08:00
hujiaying
298d2391de Merge remote-tracking branch 'origin/develop' into feature/临时分支
# Conflicts:
#	sf_message/models/sf_message_stock_picking.py
2024-10-10 15:54:07 +08:00
hujiaying
49cbeee261 编写sf生产完工入库提醒,订单发货提醒代码 2024-10-10 15:52:14 +08:00
mgw
b104b358ea Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2024-10-10 14:01:56 +08:00
mgw
786fca2937 调整“驾驶舱”的机床状态与工厂产线实际不一致的问题 2024-10-10 14:01:39 +08:00
马广威
ca6d1f51df Accept Merge Request #1388: (feature/制造功能优化 -> develop)
Merge Request: 调整24h开机时长为0的问题;去掉x偏差角度的控制

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1388?initial=true
2024-10-10 11:49:22 +08:00
mgw
f324453351 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2024-10-10 11:36:35 +08:00
mgw
d0f5aca707 调整24h开机时长为0的问题;去掉x偏差角度的控制 2024-10-10 11:36:18 +08:00
胡尧
f0cb047e8c Accept Merge Request #1387: (release/release_2.4 -> develop)
Merge Request: 解决空料架配送的问题

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1387
2024-10-10 11:06:01 +08:00
jinling.yang
02467d5220 优化工单消息推送 2024-10-09 17:58:47 +08:00
yuxianghui
f18c0e3eaf 1、重构cnc用刀校验方法,优化下发编程单后校验cnc用刀的逻辑;2、优化CAM创建方法;3、优化获取mrs编程单接口、优化编程单更新接口; 2024-10-09 17:52:20 +08:00
liaodanlong
c55f0b4c39 产品 qty_available字段名称修改为库存数量 2024-10-09 17:45:57 +08:00
jinling.yang
2639a6ac6b 优化销售订单逾期和预警消息推送 2024-10-09 16:42:53 +08:00
廖丹龙
52c1992814 Accept Merge Request #1383: (feature/销售和排程添加消息推送 -> develop)
Merge Request: 消息推送url链接逻辑修改

Created By: @廖丹龙
Reviewed By: @胡尧 @胡嘉莹
Approved By: @胡尧 
Accepted By: @廖丹龙
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1383
2024-10-09 16:35:27 +08:00
胡嘉莹
b1fbf4344e Accept Merge Request #1385: (feature/临时分支 -> develop)
Merge Request: 修改custom_many2many_checkboxes组件,优化图片展示方式,及点击图片放大的预览样式

Created By: @胡嘉莹
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @胡嘉莹
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1385
2024-10-09 16:28:52 +08:00
hujiaying
a1b9f2dd3b 产品看板新增品牌字段,如果产品没有品牌字段则不展示品牌字段 2024-10-09 16:21:14 +08:00
hujiaying
441cfaffce 优化代码 2024-10-09 16:01:27 +08:00
hujiaying
75e1f5387d 修改coustom_many2many_checkboxes组件的展示方式,控制图片展示大小,修改点击预览图展示的样式优化 2024-10-09 16:01:12 +08:00
马广威
3f0fda7aac Accept Merge Request #1384: (feature/制造功能优化 -> develop)
Merge Request: 调整依赖、配置

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1384?initial=true
2024-10-09 10:50:58 +08:00
liaodanlong
cc5452d14c 消息推送url链接逻辑修改 2024-10-09 10:26:20 +08:00
liaodanlong
5aff8c1737 消息推送url链接逻辑修改 2024-10-09 10:14:48 +08:00
jinling.yang
a00f4af923 优化销售订单逾期 2024-10-08 17:50:59 +08:00
yuxianghui
62a2aed7d9 销售订单按钮顺序优化为: 确认接单/拒绝接单/创建结算单/通过Email发送 2024-10-08 14:26:12 +08:00
胡尧
e99f01104e Accept Merge Request #1382: (release/release_2.4 -> develop)
Merge Request: 解决logo不显示的问题

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1382?initial=true
2024-10-08 09:20:31 +08:00
mgw
1de4704046 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化
# Conflicts:
#	sf_message/__manifest__.py
2024-09-30 10:51:54 +08:00
mgw
0d65e67140 调整依赖 2024-09-30 10:48:40 +08:00
jinling.yang
ccd01c9c75 优化合并多条发送销售订单逾期预警 2024-09-29 17:51:50 +08:00
liaodanlong
0b127ff419 Merge remote-tracking branch 'origin/feature/销售和排程添加消息推送' into feature/销售和排程添加消息推送 2024-09-29 17:12:25 +08:00
liaodanlong
d4a01d9b8a 处理会计凭证生成重复名称报错问题 2024-09-29 17:11:37 +08:00
jinling.yang
c6065653f0 优化逾期 2024-09-29 16:40:52 +08:00
jinling.yang
fd0de5ae09 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/销售订单和工单逾期消息推送
# Conflicts:
#	sf_message/__manifest__.py
#	sf_message/data/bussiness_node.xml
#	sf_message/models/sf_message_sale.py
2024-09-29 15:43:19 +08:00
mgw
83ca18d7d5 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2024-09-29 14:02:04 +08:00
mgw
11666b9ae1 静态数据时序库移位后的相应配置调整 2024-09-29 14:01:44 +08:00
jinling.yang
7235f242b2 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/销售订单和工单逾期消息推送
# Conflicts:
#	sf_message/__manifest__.py
#	sf_message/data/bussiness_node.xml
2024-09-27 09:11:56 +08:00
jinling.yang
7fef8f4c77 添加业务节点 2024-09-25 17:50:00 +08:00
jinling.yang
2e3a9a8b80 添加提醒时间 2024-09-25 11:18:37 +08:00
116 changed files with 6804 additions and 800 deletions

View File

@@ -3,8 +3,8 @@
'name': "jikimo_account_process",
'summary': """
Short (1 phrase/line) summary of the module's purpose, used as
subtitle on modules listing or apps.openerp.com""",
处理会计凭证生成重复名称报错问题
""",
'description': """
Long description of module's purpose

View File

@@ -1,41 +1,99 @@
.zoomed {
position: fixed !important;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(10);
.processing-capabilities-grid {
display: grid;
grid-template-columns: repeat(6, 1fr);
gap: 10px;
width: 100%;
}
.many2many_flex {
display: flex;
.grid-item {
display: flex;
align-items: center;
}
.many2many_flex>div {
margin-right: 15px;
display: flex;
flex-direction: column;
align-items: center;
.item-content {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
}
/*控制图片大小*/
.item-icon {
width: 50px;
height: 50px;
margin-bottom: 5px;
}
.many2many_flex>div>:nth-child(2) {
position: relative;
.item-label {
font-size: 12px;
word-break: break-word;
}
.close {
width: 20px;
height: 20px;
position: absolute;
top: -8.8px;
right: -8.8px;
color: #fff;
background-color: #000;
opacity: 0;
text-align: center;
line-height: 20px;
font-size: 18px;
@media (max-width: 1200px) {
.processing-capabilities-grid {
grid-template-columns: repeat(4, 1fr);
}
}
.img_close {
opacity: 1;
transform: scale(0.1);
cursor: pointer;
@media (max-width: 768px) {
.processing-capabilities-grid {
grid-template-columns: repeat(3, 1fr);
}
}
@media (max-width: 480px) {
.processing-capabilities-grid {
grid-template-columns: repeat(2, 1fr);
}
}
.image-preview-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.9);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
opacity: 0;
transition: opacity 0.3s ease;
}
.image-preview-container.show {
opacity: 1;
}
.image-preview {
max-width: 90%;
max-height: 90%;
object-fit: contain;
box-shadow: 0 0 20px rgba(255, 255, 255, 0.2);
border-radius: 5px;
transform: scale(0.9);
transition: transform 0.3s ease;
}
.image-preview-container.show .image-preview {
transform: scale(1);
}
.image-preview-close {
position: absolute;
top: 20px;
right: 30px;
color: #fff;
font-size: 40px;
font-weight: bold;
transition: 0.3s;
cursor: pointer;
opacity: 0.7;
}
.image-preview-close:hover,
.image-preview-close:focus {
opacity: 1;
text-decoration: none;
cursor: pointer;
}

View File

@@ -4,35 +4,57 @@ import {Many2ManyCheckboxesField} from "@web/views/fields/many2many_checkboxes/m
import {registry} from "@web/core/registry";
export class MyCustomWidget extends Many2ManyCheckboxesField {
// 你可以重写或者添加一些方法和属性
// 例如你可以重写setup方法来添加一些事件监听器或者初始化一些变量
setup() {
super.setup(); // 调用父类的setup方法
// 你自己的代码
super.setup();
}
onImageClick(event) {
// 放大图片逻辑
// 获取图片元素
const img = event.target;
const close = img.nextSibling;
onImageClick(event, src) {
event.preventDefault();
event.stopPropagation();
// 实现放大图片逻辑
// 比如使用 CSS 放大
img.parentElement.classList.add('zoomed');
close.classList.add('img_close');
}
// 创建预览框
const previewContainer = document.createElement('div');
previewContainer.className = 'image-preview-container';
onCloseClick(event) {
const close = event.target;
const img = close.previousSibling;
img.parentElement.classList.remove('zoomed');
close.classList.remove('img_close');
const previewImg = document.createElement('img');
previewImg.src = src;
previewImg.className = 'image-preview';
// 设置放大的预览图片大小
previewImg.style.width = '600px';
previewImg.style.height = 'auto'; // 保持宽高比
const closeButton = document.createElement('span');
closeButton.innerHTML = '×';
closeButton.className = 'image-preview-close';
previewContainer.appendChild(previewImg);
previewContainer.appendChild(closeButton);
document.body.appendChild(previewContainer);
// 添加关闭预览的事件监听器
const closePreview = () => {
previewContainer.classList.remove('show');
setTimeout(() => {
document.body.removeChild(previewContainer);
}, 300);
};
closeButton.addEventListener('click', closePreview);
// 点击预览框外部也可以关闭
previewContainer.addEventListener('click', (e) => {
if (e.target === previewContainer) {
closePreview();
}
});
// 使用 setTimeout 来触发过渡效果
setTimeout(() => {
previewContainer.classList.add('show');
}, 10);
}
}
MyCustomWidget.template = "jikimo_frontend.MyCustomWidget";
// MyCustomWidget.supportedTypes = ['many2many'];
registry.category("fields").add("custom_many2many_checkboxes", MyCustomWidget);
registry.category("fields").add("custom_many2many_checkboxes", MyCustomWidget);

View File

@@ -2,27 +2,22 @@
<templates xml:space="preserve">
<t t-name="jikimo_frontend.MyCustomWidget" owl="1">
<div aria-atomic="true" class="many2many_flex">
<div aria-atomic="true" class="many2many_flex processing-capabilities-grid">
<t t-foreach="items" t-as="item" t-key="item[0]">
<div>
<div class="grid-item">
<CheckBox
value="isSelected(item)"
disabled="props.readonly"
onChange="(ev) => this.onChange(item[0], ev)"
>
<t t-esc="item[1]"/>
<div class="item-content">
<img t-att-src="item[2]" class="item-icon" t-on-click="(ev) => this.onImageClick(ev, item[2])"/>
<span class="item-label"><t t-esc="item[1]"/></span>
</div>
</CheckBox>
<div t-on-dblclick="onImageClick">
<t>
<img t-att-src="item[2]" width="50" height="50"/>
<div class="close" t-on-click="onCloseClick">×</div>
</t>
</div>
</div>
</t>
</div>
</t>
</templates>
</templates>

View File

@@ -108,6 +108,10 @@ td.o_required_modifier {
}
.color_3 {
background-color: #808080;
}
.color_4 {
background-color: rgb(255, 150, 0);
}

View File

@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
from . import models
from . import controllers

View File

@@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name': '机企猫 工单异常记录',
'version': '1.0',
'summary': '记录工单的异常日志',
'sequence': 1,
'category': 'sf',
'website': 'https://www.sf.jikimo.com',
'depends': ['sf_manufacturing', 'sf_mrs_connect'],
'data': [
'views/mrp_workorder_views.xml',
'security/ir.model.access.csv',
],
'demo': [
],
'license': 'LGPL-3',
'installable': True,
'application': False,
'auto_install': False,
}

View File

@@ -0,0 +1 @@
from . import main

View File

@@ -0,0 +1,89 @@
from odoo import http, fields
from odoo.http import request
import json
import logging
from odoo.addons.sf_mrs_connect.controllers.controllers import Sf_Mrs_Connect
from odoo.addons.sf_manufacturing.controllers.controllers import Manufacturing_Connect
_logger = logging.getLogger(__name__)
class WorkorderExceptionConroller(http.Controller):
@http.route('/AutoDeviceApi/BillError', type='json', auth='public', methods=['GET', 'POST'], csrf=False,
cors="*")
def workder_exception(self, **kw):
"""
记录工单异常
:param kw:
:return:
"""
_logger.info('workder_exception:%s' % kw)
try:
res = {'Succeed': True, 'ErrorCode': 0, 'Error': ''}
datas = request.httprequest.data
ret = json.loads(datas)
if not ret.get('RfidCode') or not ret.get('coding'):
res = {'Succeed': False, 'ErrorCode': 400, 'Error': '参数错误'}
return json.JSONEncoder().encode(res)
# 通过RfidCode获取就绪的CNC工单
workorder = request.env['mrp.workorder'].sudo().search([
('rfid_code', '=', ret['RfidCode']),
('routing_type', '=', 'CNC加工'),
])
if not workorder:
res = {'Succeed': False, 'ErrorCode': 401, 'Error': '无效的工单'}
return json.JSONEncoder().encode(res)
# 创建工单异常记录,关联工单
request.env['jikimo.workorder.exception'].sudo().create({
'workorder_id': workorder.id,
'exception_code': ret.get('coding'),
'exception_content': ret.get('Error', '')
})
except Exception as e:
res = {'Succeed': False, 'ErrorCode': 202, 'Error': e}
_logger.info('workder_exception error:%s' % e)
return json.JSONEncoder().encode(res)
class SfMrsConnectController(Sf_Mrs_Connect):
@http.route('/api/cnc_processing/create', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False,
cors="*")
def get_cnc_processing_create(self, **kw):
"""
更新工单异常记录【'YC001', 'YC004'
"""
res = super(SfMrsConnectController, self).get_cnc_processing_create(**kw)
# 如果有未完成的YC0001、YC0004异常记录则标记为完成
res = json.loads(res)
_logger.info('已进入工单异常:%s' % res)
if res.get('production_ids'):
try:
productions = request.env['mrp.production'].sudo().search([('id', 'in', res.get('production_ids'))])
if productions.workorder_ids:
productions.workorder_ids.handle_exception(['YC0001', 'YC0004'])
except Exception as e:
_logger.info('更新工单异常记录失败:%s' % e)
return json.JSONEncoder().encode(res)
class ManufactruingController(Manufacturing_Connect):
@http.route('/AutoDeviceApi/FeedBackStart', type='json', auth='none', methods=['GET', 'POST'], csrf=False,
cors="*")
def button_Work_START(self, **kw):
"""
更新工单异常记录【'YC0002', 'YC0003'
"""
res = super(ManufactruingController, self).button_Work_START(**kw)
res = json.loads(res)
_logger.info('已进入工单异常:%s' % res)
if res.get('workorder_id'):
try:
workorder = request.env['mrp.workorder'].sudo().browse(int(res.get('workorder_id')))
workorder.handle_exception(['YC0002', 'YC0003'])
except Exception as e:
_logger.info('更新工单异常记录失败:%s' % e)
return json.JSONEncoder().encode(res)

View File

@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import jikimo_workorder_exception
from . import mrp_workorder

View File

@@ -0,0 +1,14 @@
from odoo import models, fields
class JikimoWorkorderException(models.Model):
_name = 'jikimo.workorder.exception'
_description = '工单异常记录'
_order = 'id desc'
workorder_id = fields.Many2one('mrp.workorder', string='工单')
exception_code = fields.Char('异常编码')
exception_content = fields.Char('反馈的异常/问题信息')
completion_time = fields.Datetime('处理完成时间')
state = fields.Selection([('pending', '进行中'), ('done', '已处理')], string='状态', default='pending')

View File

@@ -0,0 +1,40 @@
from odoo import models, fields
import logging
_logger = logging.getLogger(__name__)
class MrpWorkorder(models.Model):
_inherit = 'mrp.workorder'
exception_ids = fields.One2many('jikimo.workorder.exception', 'workorder_id', string='工单异常记录')
def write(self, values):
if values.get('test_results') and self.exception_ids:
pending_exception = self.exception_ids.filtered(
lambda exc: exc.state == 'pending' and exc.exception_code == 'YC0005'
)
if pending_exception:
pending_exception.write({
'completion_time': fields.Datetime.now(),
'state': 'done'
})
return super(MrpWorkorder, self).write(values)
def handle_exception(self, exception_codes):
"""
处理异常
:param exception_codes: 需要处理的异常编码列表
"""
if not isinstance(exception_codes, list):
exception_codes = [exception_codes]
if self.exception_ids:
_logger.info('workorder.exception_ids:%s' % self.exception_ids)
pending_exception = self.exception_ids.filtered(
lambda exc: exc.state == 'pending' and exc.exception_code in exception_codes
)
_logger.info('pending_exception:%s' % pending_exception)
if pending_exception:
pending_exception.write({
'completion_time': fields.Datetime.now(),
'state': 'done'
})

View File

@@ -0,0 +1,2 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
"access_jikimo_workorder_exception","access.jikimo.workorder.exception","model_jikimo_workorder_exception","mrp.group_mrp_user",1,1,1,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_jikimo_workorder_exception access.jikimo.workorder.exception model_jikimo_workorder_exception mrp.group_mrp_user 1 1 1 0

View File

@@ -0,0 +1,2 @@
from . import common
from . import test_jikimo_workorder_exception

View File

@@ -0,0 +1,48 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields, Command
from odoo.tests.common import TransactionCase, HttpCase, tagged, Form
import json
import time
import base64
from lxml import etree
@tagged('post_install', '-at_install')
class TestJikimoWorkorderExceptionCommon(TransactionCase):
def setUp(self):
super(TestJikimoWorkorderExceptionCommon, self).setUp()
# 获取名字为“1#自动生产线”的制造中心
workcenter = self.env['mrp.workcenter'].search([('name', '=', '1#自动生产线')], limit=1)
# 创建一个产品
product_product = self.env['product.product'].create({
'name': '测试产品',
'type': 'product',
})
uom_unit = self.env.ref('uom.product_uom_unit')
# 创建一个bom
self.bom = self.env['mrp.bom'].create({
'product_id': product_product.id,
'product_tmpl_id': product_product.product_tmpl_id.id,
'product_uom_id': uom_unit.id,
'product_qty': 1.0,
'type': 'normal',
})
# 创建一个制造订单
self.production = self.env['mrp.production'].create({
'name': 'Test Production',
'product_id': product_product.id,
'bom_id': self.bom.id,
'company_id': self.env.ref('base.main_company').id,
})
# 创建一个测试工单
self.workorder = self.env['mrp.workorder'].create({
'name': 'Test order',
'workcenter_id': workcenter.id,
'product_uom_id': self.bom.product_uom_id.id,
'production_id': self.production.id,
'duration_expected': 1.0,
'rfid_code': 'test-123456',
'routing_type': 'CNC加工'
})

View File

@@ -0,0 +1,53 @@
import json
from datetime import datetime
from odoo.addons.jikimo_workorder_exception.tests.common import TestJikimoWorkorderExceptionCommon
class TestJikimoWorkorderException(TestJikimoWorkorderExceptionCommon):
def test_create_exception_record(self):
exception_record = self.env['jikimo.workorder.exception'].create({
'workorder_id': self.workorder.id,
'exception_code': 'YC0001',
'exception_content': '无CNC编程'
})
self.assertTrue(exception_record)
self.assertEqual(exception_record.exception_content, '无CNC编程')
self.assertEqual(exception_record.workorder_id.id, self.workorder.id)
self.assertEqual(exception_record.exception_code, 'YC0001')
def test_handle_exception(self):
exception_record = self.env['jikimo.workorder.exception'].create({
'workorder_id': self.workorder.id,
'exception_code': 'YC0001',
'exception_content': '无CNC编程'
})
self.workorder.handle_exception('YC0001')
self.assertEqual(exception_record.state, 'done')
# 判断完成时间是否为当前分钟
self.assertEqual(exception_record.completion_time.minute, datetime.now().minute)
def test_handle_exception_with_invalid_code(self):
exception_record = self.env['jikimo.workorder.exception'].create({
'workorder_id': self.workorder.id,
'exception_code': 'YC0001',
'exception_content': '无CNC编程'
})
self.workorder.handle_exception(['YC0002', 'YC0004'])
self.assertEqual(exception_record.state, 'pending')
self.assertEqual(exception_record.completion_time, False)
def test_handle_exception_with_test_results(self):
exception_record = self.env['jikimo.workorder.exception'].create({
'workorder_id': self.workorder.id,
'exception_code': 'YC0005',
'exception_content': '工单加工失败'
})
self.workorder.write({
'test_results': '返工',
'reason': 'cutter',
'detailed_reason': '刀坏了',
})
self.assertEqual(exception_record.state, 'done')
self.assertEqual(exception_record.completion_time.minute, datetime.now().minute)

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data>
<record id="jikimo_workorder_exception_form_view_inherit" model="ir.ui.view">
<field name="name">mrp.workorder.form</field>
<field name="model">mrp.workorder</field>
<field name="inherit_id" ref="mrp.mrp_production_workorder_form_view_inherit"/>
<field name="arch" type="xml">
<xpath expr="//notebook/page[last()]" position="after">
<page string="异常记录" name="workorder_exception" attrs="{'invisible': [('routing_type', '!=', 'CNC加工')]}">
<field name="exception_ids" nolabel="1" readonly="1">
<tree create="false" delete="false" edit="false">
<field name="exception_content" string="反馈的异常/问题信息"/>
<field name="create_date" string="时间"/>
<field name="completion_time"/>
</tree>
</field>
</page>
</xpath>
</field>
</record>
</data>
</odoo>

View File

@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
from . import models

View File

@@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name': '机企猫 工单异常消息通知',
'version': '1.0',
'summary': '当产生工单异常时,发送消息通知',
'sequence': 1,
'category': 'sf',
'website': 'https://www.sf.jikimo.com',
'depends': ['jikimo_workorder_exception', 'jikimo_message_notify'],
'data': [
'data/bussiness_node.xml',
'data/template_data.xml',
# 'security/ir.model.access.csv',
],
'demo': [
],
'license': 'LGPL-3',
'installable': True,
'application': False,
'auto_install': False,
}

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" ?>
<odoo>
<data noupdate="1">
<record id="bussiness_no_functional_tool" model="jikimo.message.bussiness.node">
<field name="name">无功能刀具</field>
<field name="model">jikimo.workorder.exception</field>
</record>
<record id="bussiness_no_position_data" model="jikimo.message.bussiness.node">
<field name="name">无定位数据</field>
<field name="model">jikimo.workorder.exception</field>
</record>
<record id="bussiness_processing_failure" model="jikimo.message.bussiness.node">
<field name="name">加工失败</field>
<field name="model">jikimo.workorder.exception</field>
</record>
</data>
</odoo>

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" ?>
<odoo>
<data noupdate="1">
<record id="template_no_function_tool" model="jikimo.message.template">
<field name="name">生产线无功能刀具提醒</field>
<field name="model_id" ref="jikimo_workorder_exception_notify.model_jikimo_workorder_exception"/>
<field name="model">jikimo.workorder.exception</field>
<field name="bussiness_node_id" ref="bussiness_no_functional_tool"/>
<field name="msgtype">markdown</field>
<field name="urgency">urgent</field>
<field name="content">### 生产线无功能刀具提醒
单号:工单[{{workorder_id.production_id.name}}]({{url}})
原因:生产线无加工程序要用的功能刀具</field>
</record>
<record id="template_no_position_data" model="jikimo.message.template">
<field name="name">工单无定位数据提醒</field>
<field name="model_id" ref="jikimo_workorder_exception_notify.model_jikimo_workorder_exception"/>
<field name="model">jikimo.workorder.exception</field>
<field name="bussiness_node_id" ref="bussiness_no_position_data"/>
<field name="msgtype">markdown</field>
<field name="urgency">urgent</field>
<field name="content">### 工单无定位数据提醒
单号:工单[{{workorder_id.production_id.name}}]({{url}})
原因:无装夹定位测量数据</field>
</record>
<record id="template_processing_failure" model="jikimo.message.template">
<field name="name">工单加工失败提醒</field>
<field name="model_id" ref="jikimo_workorder_exception_notify.model_jikimo_workorder_exception"/>
<field name="model">jikimo.workorder.exception</field>
<field name="bussiness_node_id" ref="bussiness_processing_failure"/>
<field name="msgtype">markdown</field>
<field name="urgency">urgent</field>
<field name="content">### 工单加工失败提醒
单号:工单[{{workorder_id.production_id.name}}]({{url}})
原因:加工失败,工件下产线处理</field>
</record>
</data>
</odoo>

View File

@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import jikimo_message_template
from . import jikimo_workorder_exception

View File

@@ -0,0 +1,10 @@
from odoo import models
class JikimoMessageTemplate(models.Model):
_inherit = "jikimo.message.template"
def _get_message_model(self):
res = super(JikimoMessageTemplate, self)._get_message_model()
res.append('jikimo.workorder.exception')
return res

View File

@@ -0,0 +1,61 @@
from odoo import models, api
from odoo.addons.sf_base.commons.common import Common
import requests, logging
_logger = logging.getLogger(__name__)
class JikimoWorkorderException(models.Model):
_name = 'jikimo.workorder.exception'
_inherit = ['jikimo.workorder.exception', 'jikimo.message.dispatch']
@api.model_create_multi
def create(self, vals_list):
res = super(JikimoWorkorderException, self).create(vals_list)
# 根据异常编码发送消息提醒
try:
for rec in res:
if rec.exception_code == 'YC0001':
# 无CNC程序调用cloud接口
data = {'name': rec.workorder_id.production_id.programming_no, 'exception_code': 'YC0001'}
configsettings = self.env['res.config.settings'].sudo().get_values()
config_header = Common.get_headers(self, configsettings['token'], configsettings['sf_secret_key'])
url = '/api/message/workorder_exception'
config_url = configsettings['sf_url'] + url
data['token'] = configsettings['token']
ret = requests.post(config_url, json=data, headers=config_header)
ret = ret.json()
_logger.info('无CNC程序异常消息推送接口:%s' % ret)
elif rec.exception_code == 'YC0002':
# 无功能刀具
rec.add_queue('无功能刀具')
elif rec.exception_code == 'YC0003':
# 无定位数据
rec.add_queue('无定位数据')
elif rec.exception_code == 'YC0004':
# 无FTP文件调用cloud接口
data = {'name': rec.workorder_id.production_id.programming_no, 'exception_code': 'YC0004'}
configsettings = self.env['res.config.settings'].sudo().get_values()
config_header = Common.get_headers(self, configsettings['token'], configsettings['sf_secret_key'])
url = '/api/message/workorder_exception'
config_url = configsettings['sf_url'] + url
data['token'] = configsettings['token']
ret = requests.post(config_url, json=data, headers=config_header)
ret = ret.json()
_logger.info('无FTP文件异常消息推送接口:%s' % ret)
elif rec.exception_code == 'YC0005':
# 加工失败
rec.add_queue('加工失败')
except Exception as e:
_logger.error('异常编码发送消息提醒失败:%s' % e)
return res
def _get_message(self, message_queue_ids):
contents = super(JikimoWorkorderException, self)._get_message(message_queue_ids)
url = self.env['ir.config_parameter'].get_param('web.base.url')
action_id = self.env.ref('mrp.mrp_production_action').id
for index, content in enumerate(contents):
exception_id = self.env['jikimo.workorder.exception'].browse(message_queue_ids[index].res_id)
url = url + '/web#id=%s&view_type=form&action=%s' % (exception_id.workorder_id.production_id.id, action_id)
contents[index] = content.replace('{{url}}', url)
return contents

View File

@@ -0,0 +1,2 @@
from . import common
from . import test_jikimo_workorder_exception_notify

View File

@@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields, Command
from odoo.tests.common import TransactionCase, HttpCase, tagged, Form
import json
import time
import base64
from lxml import etree
@tagged('post_install', '-at_install')
class TestJikimoWorkorderExceptionNotifyCommonNotify(TransactionCase):
def setUp(self):
super(TestJikimoWorkorderExceptionNotifyCommonNotify, self).setUp()
# 获取最后一个工单
self.workorder = self.env['mrp.workorder'].search([], order='id desc', limit=1)

View File

@@ -0,0 +1,113 @@
import json
from datetime import datetime
from odoo.addons.jikimo_workorder_exception_notify.tests.common import TestJikimoWorkorderExceptionNotifyCommonNotify
class TestJikimoWorkorderExceptionNotify(TestJikimoWorkorderExceptionNotifyCommonNotify):
def test_create_message_template(self):
self.assertTrue(self.env['jikimo.message.template'].search([
('name', '=', '生产线无功能刀具提醒'),
('model', '=', 'jikimo.workorder.exception')
]))
self.assertTrue(self.env['jikimo.message.template'].search([
('name', '=', '工单无定位数据提醒'),
('model', '=', 'jikimo.workorder.exception')
]))
self.assertTrue(self.env['jikimo.message.template'].search([
('name', '=', '工单加工失败提醒'),
('model', '=', 'jikimo.workorder.exception')
]))
def test_create_message_queue_yc0001(self):
exception_record = self.env['jikimo.workorder.exception'].create({
'workorder_id': self.workorder.id,
'exception_code': 'YC0001',
'exception_content': '无CNC程序'
})
message_record = self.env['jikimo.message.queue'].search([
('res_id', '=', exception_record.id),
('model', '=', 'jikimo.workorder.exception'),
('message_status', '=', 'pending')
])
self.assertFalse(message_record)
def test_create_message_queue_yc0002(self):
exception_record = self.env['jikimo.workorder.exception'].create({
'workorder_id': self.workorder.id,
'exception_code': 'YC0002',
'exception_content': '无功能刀具'
})
bussiness_node = self.env['jikimo.message.bussiness.node'].search([
('name', '=', '无功能刀具'),
('model', '=', 'jikimo.workorder.exception')
])
message_template = self.env['jikimo.message.template'].search([
('bussiness_node_id', '=', bussiness_node.id),
('model', '=', 'jikimo.workorder.exception')
])
message_record = self.env['jikimo.message.queue'].search([
('res_id', '=', exception_record.id),
('model', '=', 'jikimo.workorder.exception'),
('message_status', '=', 'pending'),
('message_template_id', '=', message_template.id)
])
self.assertTrue(message_record)
def test_create_message_queue_yc0003(self):
exception_record = self.env['jikimo.workorder.exception'].create({
'workorder_id': self.workorder.id,
'exception_code': 'YC0003',
'exception_content': '无定位数据'
})
bussiness_node = self.env['jikimo.message.bussiness.node'].search([
('name', '=', '无定位数据'),
('model', '=', 'jikimo.workorder.exception')
])
message_template = self.env['jikimo.message.template'].search([
('bussiness_node_id', '=', bussiness_node.id),
('model', '=', 'jikimo.workorder.exception')
])
message_record = self.env['jikimo.message.queue'].search([
('res_id', '=', exception_record.id),
('model', '=', 'jikimo.workorder.exception'),
('message_status', '=', 'pending'),
('message_template_id', '=', message_template.id)
])
self.assertTrue(message_record)
def test_create_message_queue_yc0004(self):
exception_record = self.env['jikimo.workorder.exception'].create({
'workorder_id': self.workorder.id,
'exception_code': 'YC0004',
'exception_content': '无CNC程序'
})
message_record = self.env['jikimo.message.queue'].search([
('res_id', '=', exception_record.id),
('model', '=', 'jikimo.workorder.exception'),
('message_status', '=', 'pending')
])
self.assertFalse(message_record)
def test_get_message(self):
exception_record = self.env['jikimo.workorder.exception'].create({
'workorder_id': self.workorder.id,
'exception_code': 'YC0002',
'exception_content': '无功能刀具'
})
message_queue_ids = self.env['jikimo.message.queue'].search([
('res_id', '=', exception_record.id),
('model', '=', 'jikimo.workorder.exception'),
('message_status', '=', 'pending')
])
message = self.env['jikimo.workorder.exception']._get_message(message_queue_ids)
self.assertTrue(message)

View File

@@ -1273,3 +1273,18 @@ msgstr ""
#: model:product.template,description_sale:mrp_workorder.product_template_stool_top
msgid "wooden stool top"
msgstr ""
#. module: mrp_workorder
#: model:quality.point.test_type,name:mrp_workorder.test_type_register_consumed_materials
msgid "Register Consumed Materials"
msgstr "登记消耗材料"
#. module: mrp_workorder
#: model:quality.point.test_type,name:mrp_workorder.test_type_register_byproducts
msgid "Register By-products"
msgstr "按产品注册"
#. module: mrp_workorder
#: model:quality.point.test_type,name:mrp_workorder.test_type_print_label
msgid "Print label"
msgstr "打印标签"

View File

@@ -1050,3 +1050,13 @@ msgstr "工作中心故障"
#: model:ir.model.fields,field_description:quality.field_quality_point_test_type__active
msgid "active"
msgstr "有效"
#. module: quality
#: model:quality.point.test_type,name:quality.test_type_instructions
msgid "Instructions"
msgstr "使用说明"
#. module: quality
#: model:quality.point.test_type,name:quality.test_type_picture
msgid "Take a Picture"
msgstr "照片"

View File

@@ -15,7 +15,7 @@ class TestType(models.Model):
_description = "Quality Control Test Type"
# Used instead of selection field in order to hide a choice depending on the view.
name = fields.Char('Name', required=True)
name = fields.Char('Name', required=True,translate=True)
technical_name = fields.Char('Technical name', required=True)
active = fields.Boolean('active', default=True)

View File

@@ -1185,3 +1185,14 @@ msgstr "请先进行质量检查!"
#: model_terms:ir.ui.view,arch_db:quality_control.quality_alert_team_view_form
msgid "e.g. The QA Masters"
msgstr "例如QA大师"
#. module: quality_control
#: model:quality.point.test_type,name:quality_control.test_type_passfail
msgid "Pass - Fail"
msgstr "通过-失败"
#. module: quality_control
#: model:quality.point.test_type,name:quality_control.test_type_measure
msgid "Measure"
msgstr "测量"

View File

@@ -6,3 +6,4 @@ from . import stock_move
from . import stock_move_line
from . import stock_picking
from . import stock_lot
from . import product_category

View File

@@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from math import sqrt
from dateutil.relativedelta import relativedelta
from datetime import datetime
import random
from odoo import api, models, fields, _
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT, float_round
from odoo.osv.expression import OR
class ProductCategory(models.Model):
_inherit = 'product.category'
@api.model
def name_search(self, name='', args=None, operator='ilike', limit=100):
if args is None:
args = []
# 添加过滤条件,确保只返回名称为 'abc' 的记录
args += [('name', 'not in', ['Saleable', 'Expenses', 'Deliveries'])]
# 调用父类的 name_search 方法
return super(ProductCategory, self).name_search(name, args=args, operator=operator, limit=limit)

View File

@@ -1033,7 +1033,7 @@
name="Overview"
action="quality_alert_team_action"
parent="menu_quality_root"
sequence="5"/>
sequence="5" active="False"/>
<menuitem
id="menu_quality_control"

View File

@@ -38,3 +38,17 @@ class Manufacturing_Connect(http.Controller):
res = {'Succeed': False, 'ErrorCode': 202, 'Error': e}
logging.info('get_maintenance_tool_groups_Info error:%s' % e)
return json.JSONEncoder().encode(res)
class MultiInheritController():
_sub_classes = []
def __init_subclass__(cls):
"""
多继承解决多个字类时方法调用super的问题
"""
super().__init_subclass__()
if len(cls._sub_classes) > 0 and cls not in cls._sub_classes:
cls.__bases__ = (cls._sub_classes[-1],)
if cls not in cls._sub_classes:
cls._sub_classes.append(cls)

View File

@@ -394,3 +394,11 @@ class MachineToolCategory(models.Model):
active = fields.Boolean('有效', default=True)
category = fields.Selection([('shukong', u'数控'), ('putong', u'普通')], string=u'机床类别',
default='shukong')
class MachiningAccuracy(models.Model):
_name = 'sf.machining.accuracy'
_description = '加工精度'
name = fields.Char('一般公差', index=True)
standard_tolerance = fields.Char(string="标准公差")
sync_id = fields.Char('同步ID')

View File

@@ -247,3 +247,7 @@ access_sf_cutting_tool_type_group_sf_stock_manager,sf_cutting_tool_type_group_sf
access_sf_cutting_tool_material_group_plan_dispatch,sf_cutting_tool_material_group_plan_dispatch,model_sf_cutting_tool_material,sf_base.group_plan_dispatch,1,0,0,0
access_sf_functional_cutting_tool_model_group_plan_dispatch,sf_functional_cutting_tool_model_group_plan_dispatch,model_sf_functional_cutting_tool_model,sf_base.group_plan_dispatch,1,0,0,0
access_sf_cutting_tool_type_group_plan_dispatch,sf_cutting_tool_type_group_plan_dispatch,model_sf_cutting_tool_type,sf_base.group_plan_dispatch,1,0,0,0
access_sf_machining_accuracy,sf_machining_accuracy,model_sf_machining_accuracy,base.group_user,1,0,0,0
access_sf_machining_accuracy_admin,sf_machining_accuracy_admin,model_sf_machining_accuracy,base.group_system,1,0,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
247
248
249
250
251
252
253

View File

@@ -109,7 +109,7 @@
<field name="name">form.sf.machine_tool.type</field>
<field name="model">sf.machine_tool.type</field>
<field name="arch" type="xml">
<form string="机床型号" delete="0">
<form string="机床型号" delete="0">
<sheet>
<div class="oe_title">
<h1>
@@ -129,31 +129,28 @@
<field name="machine_tool_picture" widget="image" nolabel="1"/>
</group>
</group>
<group string="加工能力">
<group string="加工能力">
<div>
<field name='jg_image_id' widget="custom_many2many_checkboxes">
<field name='jg_image_id' widget="custom_many2many_checkboxes">
<tree>
<field name="name"/>
<field name="image" widget="image"/>
<tree>
<field name="name"/>
<field name="image" widget="image"
options="{'size': [100, 100], 'click enlarge': True}"/>
</tree>
</field>
</tree>
</field>
</div>
</group>
<group string="冷却方式">
<div>
<field name='lq_image_id' widget="custom_many2many_checkboxes">
<field name='lq_image_id' widget="custom_many2many_checkboxes">
<tree>
<field name="name"/>
<field name="image" widget="image"
options="{'size': [100, 100], 'click enlarge': True}"/>
<tree>
<field name="name"/>
<field name="image" widget="image"/>
</tree>
</field>
</tree>
</field>
</div>
</group>
@@ -178,7 +175,7 @@
<field name="workbench_H" class="o_address_zip" required="1"
options="{'format': false}"/>
</div>
<field name="workpiece_load"/>
<field name="workpiece_load"/>
<label for="machine_tool_L" string="机床尺寸(mm)"/>
<div class="test_model">
<label for="machine_tool_L" string="长"/>
@@ -192,7 +189,7 @@
<field name="machine_tool_H" class="o_address_zip"
options="{'format': false}"/>
</div>
<label for="T_trough_num" string="T型槽尺寸:"/>
<label for="T_trough_num" string="T型槽尺寸:"/>
<div class="test_model">
<label for="T_trough_num" string="槽数"/>
<field name="T_trough_num" class="o_address_zip"
@@ -205,20 +202,20 @@
<field name="T_trough_distance" class="o_address_zip"
options="{'format': false}"/>
</div>
<!-- <field name="feed_speed" required="1"/>-->
<!-- <label for="precision_min" string="X轴定位精度(mm)"/>-->
<!-- <div class="test_model">-->
<!-- <label for="precision_min" string="最小(min)"/>-->
<!-- <field name="precision_min" class="o_address_zip" required="1"-->
<!-- options="{'format': false}"/>-->
<!-- <span>&amp;nbsp;</span>-->
<!-- <label for="precision_max" string="最大(max)"/>-->
<!-- <field name="precision_max" class="o_address_zip" required="1"-->
<!-- options="{'format': false}"/>-->
<!-- </div>-->
<!-- <field name="feed_speed" required="1"/>-->
<!-- <label for="precision_min" string="X轴定位精度(mm)"/>-->
<!-- <div class="test_model">-->
<!-- <label for="precision_min" string="最小(min)"/>-->
<!-- <field name="precision_min" class="o_address_zip" required="1"-->
<!-- options="{'format': false}"/>-->
<!-- <span>&amp;nbsp;</span>-->
<!-- <label for="precision_max" string="最大(max)"/>-->
<!-- <field name="precision_max" class="o_address_zip" required="1"-->
<!-- options="{'format': false}"/>-->
<!-- </div>-->
<!-- <field name="lead_screw" required="1"/>-->
<!-- <field name="guide_rail" required="1"/>-->
<!-- <field name="lead_screw" required="1"/>-->
<!-- <field name="guide_rail" required="1"/>-->
<field name="number_of_axles" required="1" widget="radio"
options="{'horizontal': true}"/>
<label for="x_axis" string="加工行程(mm)"
@@ -258,7 +255,7 @@
</group>
<group string="主轴">
<field name="taper_type_id" required="1"/>
<label for="distance_min" string="主轴端面-工作台距离(mm)"/>
<label for="distance_min" string="主轴端面-工作台距离(mm)"/>
<div class="test_model">
<label for="distance_min" string="最小(min)"/>
<field name="distance_min" class="o_address_zip"
@@ -268,7 +265,7 @@
<field name="distance_max" class="o_address_zip"
options="{'format': false}"/>
</div>
<field name="rotate_speed" string="主轴最高转速(r/min)"
<field name="rotate_speed" string="主轴最高转速(r/min)"
options="{'format': false}"/>
<field name="spindle_center_distance"/>
<field name="spindle_continuous_power"/>
@@ -286,50 +283,50 @@
<page string="进给/精度参数">
<group>
<group string="进给参数">
<field name="X_axis_rapid_traverse_speed"/>
<field name="Y_axis_rapid_traverse_speed"/>
<field name="Z_axis_rapid_traverse_speed"/>
<field name="a_axis_rapid_traverse_speed"/>
<field name="b_axis_rapid_traverse_speed"/>
<field name="c_axis_rapid_traverse_speed"/>
<field name="straight_cutting_feed_rate"/>
<field name="rotary_cutting_feed_rate"/>
<field name="X_axis_rapid_traverse_speed"/>
<field name="Y_axis_rapid_traverse_speed"/>
<field name="Z_axis_rapid_traverse_speed"/>
<field name="a_axis_rapid_traverse_speed"/>
<field name="b_axis_rapid_traverse_speed"/>
<field name="c_axis_rapid_traverse_speed"/>
<field name="straight_cutting_feed_rate"/>
<field name="rotary_cutting_feed_rate"/>
</group>
<group string="精度参数">
<field name="X_precision"/>
<field name="X_precision_repeat"/>
<field name="Y_precision"/>
<field name="Y_precision_repeat"/>
<field name="Z_precision"/>
<field name="Z_precision_repeat"/>
<field name="a_precision"/>
<field name="a_precision_repeat"/>
<field name="b_precision"/>
<field name="b_precision_repeat"/>
<field name="c_precision"/>
<field name="c_precision_repeat"/>
<field name="X_precision"/>
<field name="X_precision_repeat"/>
<field name="Y_precision"/>
<field name="Y_precision_repeat"/>
<field name="Z_precision"/>
<field name="Z_precision_repeat"/>
<field name="a_precision"/>
<field name="a_precision_repeat"/>
<field name="b_precision"/>
<field name="b_precision_repeat"/>
<field name="c_precision"/>
<field name="c_precision_repeat"/>
</group>
</group>
</page>
<page string="刀库参数">
<group>
<page string="刀库参数">
<group>
<group string="刀具">
<!-- <field name="knife_type" required="1"/>-->
<!-- <field name="knife_type" required="1"/>-->
<field name="number_of_knife_library" required="1" options="{'format': false}"/>
<!-- <field name="tool_speed" required="1"/>-->
<!-- <field name="tool_speed" required="1"/>-->
<field name="tool_full_diameter_max"/>
<field name="tool_perimeter_diameter_max"/>
<field name="tool_long_max"/>
<!-- <label for="tool_diameter_min" string="刀具刀径(mm)"/>-->
<!-- <div class="test_model">-->
<!-- <label for="tool_diameter_min" string="最小(min)"/>-->
<!-- <field name="tool_diameter_min" class="o_address_zip" required="1"-->
<!-- options="{'format': false}"/>-->
<!-- <span>&amp;nbsp;</span>-->
<!-- <label for="tool_diameter_max" string="最大(max)"/>-->
<!-- <field name="tool_diameter_max" class="o_address_zip" required="1"-->
<!-- options="{'format': false}"/>-->
<!-- </div>-->
<!-- <label for="tool_diameter_min" string="刀具刀径(mm)"/>-->
<!-- <div class="test_model">-->
<!-- <label for="tool_diameter_min" string="最小(min)"/>-->
<!-- <field name="tool_diameter_min" class="o_address_zip" required="1"-->
<!-- options="{'format': false}"/>-->
<!-- <span>&amp;nbsp;</span>-->
<!-- <label for="tool_diameter_max" string="最大(max)"/>-->
<!-- <field name="tool_diameter_max" class="o_address_zip" required="1"-->
<!-- options="{'format': false}"/>-->
<!-- </div>-->
<field name="tool_quality_max"/>
<field name="T_tool_time"/>
<field name="C_tool_time"/>
@@ -617,4 +614,23 @@
<field name="res_model">sf.machine.control_system</field>
<field name="view_mode">tree</field>
</record>
#------------------加工精度------------------
<record model="ir.ui.view" id="tree_sf_machining_accuracy_view">
<field name="name">tree.sf.machining.accuracy</field>
<field name="model">sf.machining.accuracy</field>
<field name="arch" type="xml">
<tree string="加工精度" create="0" edit="0" delete="0">
<field name="name"/>
<field name="standard_tolerance"/>
</tree>
</field>
</record>
<record id="action_sf_machining_accuracy" model="ir.actions.act_window">
<field name="name">加工精度</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">sf.machining.accuracy</field>
<field name="view_mode">tree</field>
</record>
</odoo>

View File

@@ -141,12 +141,18 @@
sequence="1"
action="action_sf_machine_brand"/>
<menuitem
id="menu_sf_machining_accuracy"
parent="menu_sf_base"
name="加工精度"
sequence="1"
action="action_sf_machining_accuracy"/>
<menuitem
id="menu_sf_machine_control_system"
parent="menu_sf_base"
name="数控系统"
sequence="1"
sequence="2"
action="action_sf_machine_control_system"/>

View File

@@ -10,7 +10,7 @@
""",
'category': 'sf',
'website': 'https://www.sf.jikimo.com',
'depends': ['sf_base', 'web_widget_model_viewer', 'mrp_subcontracting', 'purchase_stock', 'uom', ],
'depends': ['sf_base', 'mrp_subcontracting', 'purchase_stock', 'uom'],
'data': [
'data/product_data.xml',
'data/uom_data.xml',

View File

@@ -109,6 +109,19 @@
'刀具')], 'required': True}
</attribute>
</xpath>
<xpath expr="//sheet//notebook" position="inside">
<page string="2D加工图纸">
<field name='machining_drawings' attrs="{'invisible': [('categ_type', '!=', '成品')]}"
widget="adaptive_viewer"/>
</page>
</xpath>
<xpath expr="//sheet//notebook" position="inside">
<page string="质检标准">
<field name='quality_standard' attrs="{'invisible': [('categ_type', '!=', '成品')]}"
widget="adaptive_viewer"/>
</page>
</xpath>
<!-- <xpath expr="//field[@name='default_code']" position="attributes">-->
<!-- <attribute name="attrs">{'readonly': [('categ_type', '=', '刀具')], 'invisible':-->
<!-- [('product_variant_count', '>' , 1)]}-->

View File

@@ -2,3 +2,4 @@
from . import hr_employee
from . import res_config_setting
from . import res_users

View File

@@ -11,6 +11,42 @@ class JkmPracticeEmployee(models.Model):
we_id = fields.Char(string='企微ID', index=True)
@api.model_create_multi
def create(self, vals_list):
for val in vals_list:
if 'work_email' in val:
val["we_id"] = self._get_we_id(val.get('work_email'))
return super(JkmPracticeEmployee, self).create(vals_list)
def write(self, vals):
if 'work_email' in vals:
vals["we_id"] = self._get_we_id(vals.get('work_email'))
return super(JkmPracticeEmployee, self).write(vals)
@api.depends('work_contact_id', 'work_contact_id.mobile', 'work_contact_id.email')
def _compute_work_contact_details(self):
for employee in self:
if employee.work_contact_id:
employee.mobile_phone = employee.work_contact_id.mobile
employee.work_email = employee.work_contact_id.email
if employee.work_contact_id.email:
employee.we_id = self._get_we_id(employee.work_contact_id.email)
def _get_we_id(self, work_email):
json1 = {
'params': {
'work_email': work_email
}
}
url = '/api/get/we_id/info'
config = self.env['res.config.settings'].get_values()
ret = requests.post((config['ims_url'] + url), json=json1, data={})
result = ret.json()['result']
if result['code'] == 200:
if result['we_id']:
return result['we_id']
return None
def _employee_info_sync(self):
url = '/api/get/organization'
config = self.env['res.config.settings'].get_values()

15
sf_hr/models/res_users.py Normal file
View File

@@ -0,0 +1,15 @@
# -*- coding: utf-8 -*-
import random
from odoo import models, fields, api
from odoo.http import request
from odoo.exceptions import AccessDenied
import logging
_logger = logging.getLogger(__name__)
class ResUsers(models.Model):
_inherit = 'res.users'
we_employee_id = fields.Char(string=u'企业微信账号', related='employee_id.we_id', default="")

View File

@@ -12,7 +12,7 @@
'category': 'sf',
'author': 'jikimo',
'website': 'https://sf.cs.jikimo.com',
'depends': ['web', 'mail', 'sf_base', 'sf_manufacturing', 'barcodes', ],
'depends': ['web', 'sf_manufacturing', 'barcodes'],
'data': [
# 定义权限组放在最上面
# 权限组

View File

@@ -15,7 +15,7 @@ db_config = {
"user": "postgres",
"password": "postgres",
"port": "5432",
"host": "172.16.10.113"
"host": "172.16.10.131"
}
@@ -24,6 +24,8 @@ def convert_to_seconds(time_str):
if time_str is None:
return 0
if time_str == 0:
return 0
pattern = r"(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?"
@@ -400,20 +402,45 @@ class Sf_Dashboard_Connect(http.Controller):
try:
plan_obj = request.env['sf.production.plan'].sudo()
production_obj = request.env['mrp.production'].sudo()
work_order_obj = request.env['mrp.workorder'].sudo()
line_list = ast.literal_eval(kw['line_list'])
# print('line_list: %s' % line_list)
for line in line_list:
# 工单计划量
plan_data_total_counts = production_obj.search_count(
[('production_line_id.name', '=', line), ('state', 'not in', ['cancel']),
('active', '=', True)])
# 工单完成量
plan_data_finish_counts = plan_obj.search_count(
[('production_line_id.name', '=', line), ('state', 'in', ['finished'])])
# # 工单计划量
# plan_data_plan_counts = plan_obj.search_count(
# [('production_line_id.name', '=', line), ('state', 'not in', ['finished'])])
# plan_data_total_counts = production_obj.search_count(
# [('production_line_id.name', '=', line), ('state', 'not in', ['cancel']),
# ('active', '=', True)])
# 工单计划量切换为CNC工单
plan_data_total_counts = work_order_obj.search_count(
[('production_id.production_line_id.name', '=', line),
('state', 'in', ['ready', 'progress', 'done']), ('routing_type', '=', 'CNC加工')])
# # 工单完成量
# plan_data_finish_counts = plan_obj.search_count(
# [('production_line_id.name', '=', line), ('state', 'in', ['finished'])])
# 工单完成量切换为CNC工单
plan_data_finish_counts = work_order_obj.search_count(
[('production_id.production_line_id.name', '=', line),
('state', 'in', ['done']), ('routing_type', '=', 'CNC加工')])
# 超期完成量
# 搜索所有已经完成的工单
plan_data_overtime = work_order_obj.search([
('production_id.production_line_id.name', '=', line),
('state', 'in', ['done']),
('routing_type', '=', 'CNC加工')
])
# 使用 filtered 进行字段比较
plan_data_overtime_counts = plan_data_overtime.filtered(
lambda order: order.date_finished > order.date_planned_finished
)
# 获取数量
plan_data_overtime_counts = len(plan_data_overtime_counts)
# 查找符合条件的生产计划记录
plan_data = plan_obj.search([
@@ -515,7 +542,10 @@ class Sf_Dashboard_Connect(http.Controller):
'on_time_rate': on_time_rate,
# 'detection_data': detection_data,
'detection_data': plan_data_finish_counts,
'pass_rate': (plan_data_finish_counts - plan_data_fault_counts) / plan_data_finish_counts
'pass_rate': (plan_data_finish_counts - plan_data_fault_counts) / plan_data_finish_counts,
'plan_data_overtime_counts': plan_data_overtime_counts,
'overtime_rate': plan_data_overtime_counts / plan_data_finish_counts
if plan_data_finish_counts > 0 else 0,
}
res['data'][line] = data
@@ -1242,6 +1272,7 @@ class Sf_Dashboard_Connect(http.Controller):
time_threshold = datetime.now() - timedelta(days=1)
alarm_last_24_time = 0.0
alarm_all_time = 0.0
def fetch_result_as_dict(cursor):
"""辅助函数:将查询结果转为字典"""
@@ -1302,17 +1333,49 @@ class Sf_Dashboard_Connect(http.Controller):
alarm_last_24_time += float(result[0])
else:
alarm_last_24_time += 0.0
alarm_all_nums = []
with conn.cursor() as cur:
cur.execute("""
SELECT DISTINCT ON (alarm_start_time) alarm_time, alarm_start_time
FROM device_data
WHERE device_name = %s
AND alarm_start_time IS NOT NULL;
""", (item,))
results = cur.fetchall()
for result in results:
alarm_all_nums.append(result[1])
if result[0]:
if float(result[0]) >= 1000:
continue
alarm_all_time += float(result[0])
else:
alarm_all_time += 0.0
# with conn.cursor() as cur:
# cur.execute("""
# SELECT * FROM device_data
# WHERE device_name = %s
# AND total_count IS NOT NULL
# ORDER BY time ASC
# LIMIT 1;
# """, (item, ))
# total_count = fetch_result_as_dict(cur)
# 返回数据
res['data'][item] = {
'wait_time': last_all_time['run_time'] if last_all_time['run_time'] is not None else 0,
'cut_time': last_all_time['process_time'] if last_all_time['process_time'] is not None else 0,
'cut_24_time': last_24_time['process_time'] if last_24_time['process_time'] is not None else 0,
'cut_24_time': last_24_time['process_time'] if last_24_time else 0,
'power_on_time': last_all_time['power_on_time'] if last_all_time['power_on_time'] is not None else 0,
'power_on_24_time': last_24_time['power_on_time'] if last_24_time['power_on_time'] is not None else 0,
'power_on_24_time': last_24_time['power_on_time'] if last_24_time else 0,
'alarm_last_24_time': alarm_last_24_time,
'alarm_last_24_nums': len(list(set(alarm_last_24_nums))),
'idle_count': idle_count,
'first_online_time': first_online_duration,
'alarm_all_time': alarm_all_time,
'alarm_all_nums': len(list(set(alarm_all_nums)))
# 'total_count': total_count['total_count'] if total_count else 0
}
conn.close()

View File

@@ -217,7 +217,7 @@ class Machine_ftp(models.Model):
status = fields.Boolean('机床在线状态', readonly=True)
# run_status = fields.Selection([('0', '空闲中'), ('1', '加工中'), ('2', '加工中'), ('3', '加工中')], string='机床运行状态',
# readonly=True, default='0')
run_status = fields.Char('机床运行状态', readonly=True)
# run_status = fields.Char('机床运行状态', readonly=True)
run_time = fields.Char('机床累计运行时长', readonly=True)
# 机床系统日期
system_date = fields.Char('机床系统日期', readonly=True)

View File

@@ -2,3 +2,4 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import models
from . import wizard

View File

@@ -11,12 +11,14 @@
'security/group_security.xml',
'security/ir.model.access.csv',
'security/ir_rule_data.xml',
'data/scheduled_actions.xml',
'views/maintenance_logs_views.xml',
'views/maintenance_equipment_oee_views.xml',
'views/maintenance_views.xml',
'views/equipment_maintenance_standards_views.xml',
'views/maintenance_request_views.xml',
'views/maintenance_equipment_category_views.xml',
'wizard/maintenance_request_wizard.xml',
],
'installable': True,
'application': False,

View File

@@ -0,0 +1,14 @@
<odoo>
<data noupdate="1">
<record id="ir_cron_oee_get_running_datas" model="ir.cron">
<field name="name">设备运行数据</field>
<field name="model_id" ref="model_maintenance_equipment_oee"/>
<field name="state">code</field>
<field name="code">model.get_running_datas()</field>
<field name="interval_number">15</field>
<field name="interval_type">minutes</field>
<field name="numbercall">-1</field>
<field name="active" eval="True"/>
</record>
</data>
</odoo>

3583
sf_maintenance/i18n/zh_CN.po Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,12 @@
# -*- coding: utf-8 -*-
import json
import base64
import logging
from datetime import timedelta
import requests
from odoo.addons.sf_base.commons.common import Common
from odoo import api, fields, models, _
from odoo.exceptions import UserError
from odoo.exceptions import UserError, ValidationError
class SfMaintenanceEquipmentCategory(models.Model):
@@ -38,6 +39,8 @@ class SfMaintenanceEquipment(models.Model):
crea_url = "/api/machine_tool/create"
run_status = fields.Char('机床运行状态', readonly=True)
# AGV运行日志
agv_logs = fields.One2many('maintenance.equipment.agv.log', 'equipment_id', string='AGV运行日志')
# 1212修改后的字段
@@ -120,6 +123,13 @@ class SfMaintenanceEquipment(models.Model):
'sf_maintenance_equipment_ids', string='设备维保标准')
eq_maintenance_id = fields.Many2one('equipment.maintenance.standards', string='设备保养标准',
domain="[('maintenance_type','=','保养')]")
initial_action_date = fields.Date(string='重置保养日期')
initial_action_date_old = fields.Date(string='重置保养日期(旧)')
next_action_date = fields.Date(string='下次预防保养')
initial_overhaul_date = fields.Date(string='重置维修日期')
initial_overhaul_date_old = fields.Date(string='重置维修日期(旧)')
overhaul_date = fields.Date(string='下次预防检修')
overhaul_period = fields.Integer(string='预防检修频次')
overhaul_duration = fields.Float(string='检修时长')
@@ -127,6 +137,61 @@ class SfMaintenanceEquipment(models.Model):
overhaul_id = fields.Many2one('equipment.maintenance.standards', string='设备检修标准',
domain="[('maintenance_type','=','检修')]")
def confirm_maintenance(self):
"""
确认保养/检修
"""
context = self.env.context
if context['type'] == '保养':
if not self.initial_action_date:
raise ValidationError('重置保养日期不能为空!!')
elif self.initial_action_date < fields.Date.today():
raise ValidationError('重置保养日期不能小于当前日期!!')
elif context['type'] == '检修':
if not self.initial_overhaul_date:
raise ValidationError('重置检修日期不能为空!!')
elif self.initial_overhaul_date < fields.Date.today():
raise ValidationError('重置检修日期不能小于当前日期!!')
request_ids = self.env['maintenance.request'].search([('stage_id.done', '=', False),
('equipment_id', '=', self.id),
('maintenance_type', '=', 'preventive'),
('sf_maintenance_type', '=', context['type'])])
if not request_ids:
return self.create_maintenance_request(context['type'])
else:
return {
"type": "ir.actions.act_window",
"res_model": "maintenance.request.wizard",
"views": [[False, "form"]],
"target": "new",
'context': {
'equipment_id': self.id
}
}
def create_maintenance_request(self, maintenance_request_type):
"""
根据条件创建维保计划
"""
if maintenance_request_type == '保养':
self._create_new_request(self.initial_action_date + timedelta(days=self.period))
self.initial_action_date_old = self.initial_action_date
elif maintenance_request_type == '检修':
self._create_new_request1(self.initial_overhaul_date + timedelta(days=self.overhaul_period))
self.initial_overhaul_date_old = self.initial_overhaul_date
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': f'创建{maintenance_request_type}计划',
'message': f'{maintenance_request_type}维保计划创建成功',
'type': 'success',
'next': {'type': 'ir.actions.act_window_close'},
}
}
@api.onchange('eq_maintenance_id', 'overhaul_id')
def _compute_equipment_maintenance_standards_ids(self):
for record in self:
@@ -589,11 +654,13 @@ class SfMaintenanceEquipment(models.Model):
('equipment_id', '=', equipment.id),
('sf_maintenance_type', '=', '保养'),
('stage_id.done', '!=', True),
('active', '!=', False),
('close_date', '=', False)], order="request_date asc", limit=1)
last_maintenance_done = self.env['maintenance.request'].search([
('equipment_id', '=', equipment.id),
('sf_maintenance_type', '=', '保养'),
('stage_id.done', '=', True),
('active', '!=', False),
('close_date', '!=', False)], order="close_date desc", limit=1)
if next_maintenance_todo and last_maintenance_done:
next_date = next_maintenance_todo.request_date
@@ -622,7 +689,7 @@ class SfMaintenanceEquipment(models.Model):
if next_date < date_now:
next_date = date_now
else:
next_date = equipment.effective_date + timedelta(days=equipment.period)
next_date = equipment.initial_action_date + timedelta(days=equipment.period)
equipment.next_action_date = next_date
else:
self.next_action_date = False
@@ -633,11 +700,13 @@ class SfMaintenanceEquipment(models.Model):
('equipment_id', '=', equipment.id),
('sf_maintenance_type', '=', '检修'),
('stage_id.done', '!=', True),
('active', '!=', False),
('close_date', '=', False)], order="request_date asc", limit=1)
last_maintenance_done = self.env['maintenance.request'].search([
('equipment_id', '=', equipment.id),
('sf_maintenance_type', '=', '检修'),
('stage_id.done', '=', True),
('active', '!=', False),
('close_date', '!=', False)], order="close_date desc", limit=1)
if next_maintenance_todo and last_maintenance_done:
next_date = next_maintenance_todo.request_date
@@ -666,7 +735,7 @@ class SfMaintenanceEquipment(models.Model):
if next_date < date_now:
next_date = date_now
else:
next_date = equipment.effective_date + timedelta(days=equipment.overhaul_period)
next_date = equipment.initial_overhaul_date + timedelta(days=equipment.overhaul_period)
equipment.overhaul_date = next_date
else:
self.overhaul_date = False
@@ -733,6 +802,7 @@ class SfMaintenanceEquipment(models.Model):
next_requests = self.env['maintenance.request'].search([('stage_id.done', '=', False),
('equipment_id', '=', equipment.id),
('maintenance_type', '=', 'preventive'),
('active', '=', True),
('request_date', '=', equipment.next_action_date),
('sf_maintenance_type', '=', '保养')])
if not next_requests:
@@ -741,6 +811,7 @@ class SfMaintenanceEquipment(models.Model):
next_requests = self.env['maintenance.request'].search([('stage_id.done', '=', False),
('equipment_id', '=', equipment.id),
('maintenance_type', '=', 'preventive'),
('active', '=', True),
('request_date', '=', equipment.overhaul_date),
('sf_maintenance_type', '=', '检修')])
if not next_requests:

View File

@@ -12,6 +12,8 @@ def convert_to_seconds(time_str):
if time_str is None:
return 0
if time_str == 0:
return 0
pattern = r"(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?"
@@ -86,6 +88,69 @@ class SfMaintenanceEquipmentOEE(models.Model):
begin_time = fields.Date('开始时间')
end_time = fields.Date('结束时间')
def get_running_datas(self):
base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
url_time = base_url + '/api/RunningTimeDetail'
cnc_list_obj = self.env['maintenance.equipment'].sudo().search(
[('function_type', '!=', False), ('active', '=', True)])
machine_list = list(map(lambda x: x.code, cnc_list_obj))
# print('machine_list: %s' % machine_list)
data_time = {
"machine_list": str(machine_list)
}
# 发送POST请求
response_time = requests.post(url_time, json={}, data=data_time)
# print(response_time.json())
if response_time.status_code == 200:
result_time = response_time.json()
if result_time['status'] == 1:
real_dict = result_time['data']
for key in real_dict:
# print(key)
equipment_obj = self.env['maintenance.equipment.oee'].sudo().search([('equipment_code', '=', key)])
if real_dict[key]['power_on_time'] == 0:
equipment_obj.online_time = 0
equipment_obj.idle_time = 0
equipment_obj.idle_rate = 0
equipment_obj.work_rate = 0
equipment_obj.fault_time = 0
equipment_obj.fault_rate = 0
equipment_obj.fault_nums = 0
equipment_obj.idle_nums = 0
equipment_obj.work_time = 0
else:
equipment_obj.online_time = round(convert_to_seconds(real_dict[key]['power_on_time']) / 3600, 2)
equipment_obj.work_time = round(convert_to_seconds(real_dict[key]['cut_time']) / 3600, 2)
equipment_obj.fault_nums = real_dict[key]['alarm_all_nums']
equipment_obj.idle_nums = real_dict[key]['idle_count']
equipment_obj.fault_time = round((float(real_dict[key]['alarm_all_time']) if real_dict[key][
'alarm_all_time'] else 0) / 3600, 2)
equipment_obj.idle_time = float(equipment_obj.online_time) - float(
equipment_obj.work_time) if equipment_obj.online_time and equipment_obj.work_time else 0
equipment_obj.idle_rate = round(
float(equipment_obj.idle_time) / (
float(equipment_obj.online_time) if equipment_obj.online_time else 1) * 100, 2)
equipment_obj.work_rate = round(
float(equipment_obj.work_time) / (
float(equipment_obj.online_time) if equipment_obj.online_time else 1) * 100, 2)
equipment_obj.fault_rate = round(
float(equipment_obj.fault_time) / (
float(equipment_obj.online_time) if equipment_obj.online_time else 1) * 100, 2)
# 获取当前时间的时间戳
current_timestamp = datetime.datetime.now().timestamp()
# 机床上线时间段
first_online_duration = current_timestamp - int(equipment_obj.equipment_id.first_online_time.timestamp())
if equipment_obj.online_time:
equipment_obj.offline_time = round((first_online_duration - float(equipment_obj.online_time)) / 3600, 2)
else:
equipment_obj.offline_time = False
# equipment_obj.offline_time = equipment_obj.equipment_id.first_online_time - (
# float(equipment_obj.online_time) if equipment_obj.online_time else 0)
# 获取日志详情
def get_day_logs(self):
base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
@@ -122,24 +187,36 @@ class SfMaintenanceEquipmentOEE(models.Model):
real_dict = result_time['data'][self.equipment_code]
print('=', result_time)
if result_time['status'] == 1:
self.online_time = round((convert_to_seconds(real_dict['power_on_time']) - convert_to_seconds(
real_dict['power_on_24_time'])) / 3600, 2)
self.work_time = round(
(convert_to_seconds(real_dict['cut_time']) - convert_to_seconds(real_dict['cut_24_time'])) / 3600,
2)
if real_dict['power_on_24_time'] == 0:
self.online_time = 0
self.idle_time = 0
self.idle_rate = 0
self.work_rate = 0
self.fault_time = 0
self.fault_rate = 0
self.fault_nums = 0
self.idle_nums = 0
self.work_time = 0
else:
self.online_time = round((convert_to_seconds(real_dict['power_on_time']) - convert_to_seconds(
real_dict['power_on_24_time'])) / 3600, 2)
self.idle_time = float(self.online_time) - float(
self.work_time) if self.online_time and self.work_time else 0
self.idle_rate = round(
float(self.idle_time) / (float(self.online_time) if self.online_time else 1) * 100, 2)
self.work_rate = round(
float(self.work_time) / (float(self.online_time) if self.online_time else 1) * 100, 2)
self.fault_time = (float(real_dict['alarm_last_24_time']) if real_dict[
'alarm_last_24_time'] else 0) / 3600
self.fault_rate = round(
float(self.fault_time) / (float(self.online_time) if self.online_time else 1) * 100, 2)
self.fault_nums = real_dict['alarm_last_24_nums']
self.idle_nums = real_dict['idle_count']
self.work_time = round(
(convert_to_seconds(real_dict['cut_time']) - convert_to_seconds(
real_dict['cut_24_time'])) / 3600,
2)
self.offline_time = 24 - (float(self.online_time) if self.online_time else 0)
self.idle_time = float(self.online_time) - float(
self.work_time) if self.online_time and self.work_time else 0
self.idle_rate = round(
float(self.idle_time) / (float(self.online_time) if self.online_time else 1) * 100, 2)
self.work_rate = round(
float(self.work_time) / (float(self.online_time) if self.online_time else 1) * 100, 2)
self.fault_time = (float(real_dict['alarm_last_24_time']) if real_dict[
'alarm_last_24_time'] else 0) / 3600
self.fault_rate = round(
float(self.fault_time) / (float(self.online_time) if self.online_time else 1) * 100, 2)
self.fault_nums = real_dict['alarm_last_24_nums']
self.idle_nums = real_dict['idle_count']
if response.status_code == 200:
result = response.json()

View File

@@ -14,6 +14,8 @@ class SfMaintenanceEquipmentCategory(models.Model):
equipment_maintenance_id = fields.Many2one('equipment.maintenance.standards', string='设备维保标准',
domain="[('maintenance_type','=',sf_maintenance_type)]")
active = fields.Boolean('有效', default=True)
@api.onchange('sf_maintenance_type')
def _compute_equipment_maintenance_request_id(self):
for record in self:

View File

@@ -20,7 +20,8 @@ access_maintenance_equipment_agv_log,maintenance_equipment_agv_log,model_mainten
access_maintenance_system_user,equipment.request system user,maintenance.model_maintenance_request,base.group_user,1,0,0,0
access_maintenance_system_user,equipment.request system user,maintenance.model_maintenance_request,base.group_user,1,1,1,0
access_maintenance_wizard_system_user,maintenance.request.wizard system user,model_maintenance_request_wizard,base.group_user,1,1,1,0
access_maintenance_equipment_group_plan_dispatch,maintenance.equipment,maintenance.model_maintenance_equipment,sf_base.group_plan_dispatch,1,0,0,0
access_maintenance_equipment_oee_group_plan_dispatch,maintenance_equipment_oee,model_maintenance_equipment_oee,sf_base.group_plan_dispatch,1,0,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
20 access_maintenance_system_user equipment.request system user maintenance.model_maintenance_request base.group_user 1 0 1 0 1 0
21 access_maintenance_equipment_group_plan_dispatch access_maintenance_wizard_system_user maintenance.equipment maintenance.request.wizard system user maintenance.model_maintenance_equipment model_maintenance_request_wizard sf_base.group_plan_dispatch base.group_user 1 0 1 0 1 0
22 access_maintenance_equipment_oee_group_plan_dispatch access_maintenance_equipment_group_plan_dispatch maintenance_equipment_oee maintenance.equipment model_maintenance_equipment_oee maintenance.model_maintenance_equipment sf_base.group_plan_dispatch 1 0 0 0
23 access_sf_maintenance_logs_group_plan_dispatch access_maintenance_equipment_oee_group_plan_dispatch sf_maintenance_logs maintenance_equipment_oee model_sf_maintenance_logs model_maintenance_equipment_oee sf_base.group_plan_dispatch 1 0 0 0
24 access_sf_maintenance_logs_group_plan_dispatch sf_maintenance_logs model_sf_maintenance_logs sf_base.group_plan_dispatch 1 0 0 0
25 access_maintenance_standard_image_group_plan_dispatch maintenance_standard_image model_maintenance_standard_image sf_base.group_plan_dispatch 1 0 0 0
26 access_equipment_maintenance_standards_group_plan_dispatch equipment_maintenance_standards model_equipment_maintenance_standards sf_base.group_plan_dispatch 1 0 0 0
27 access_maintenance_standards_group_plan_dispatch maintenance_standards model_maintenance_standards sf_base.group_plan_dispatch 1 0 0 0

View File

@@ -79,12 +79,12 @@
</group>
</group>
<notebook>
<page string="24H日志详情">
<group>
<button name="get_day_logs" type="object" string="查看24H日志" t-attf-style="white-space:nowrap;"/>
</group>
<field name="day_logs_detail" readonly="1" widget="html"/>
<!-- <notebook> -->
<!-- <page string="24H日志详情"> -->
<!-- <group> -->
<!-- <button name="get_day_logs" type="object" string="查看24H日志" t-attf-style="white-space:nowrap;"/> -->
<!-- </group> -->
<!-- <field name="day_logs_detail" readonly="1" widget="html"/> -->
<!-- <field name="page_num"/> -->
<!-- <group> -->
<!-- <group> -->
@@ -109,7 +109,7 @@
<!-- </div> -->
<!-- </div> -->
<!-- </group> -->
</page>
<!-- </page> -->
<!-- <page string="历史日志详情"> -->
<!-- <group> -->
<!-- <group> -->
@@ -132,7 +132,7 @@
<!-- </group> -->
<!-- <field name="history_logs_detail"/> -->
<!-- </page> -->
</notebook>
<!-- </notebook> -->
</sheet>
</form>
</field>

View File

@@ -60,9 +60,9 @@
<field name="function_type"/>
<field name="code" readonly="1"/>
<field name="equipment_type" invisible="1"/>
<field name="brand_id" force_save="1" />
<field name="brand_id" force_save="1"/>
<field name="type_id" attrs="{'required': [('equipment_type', '=', '机床')]}"
domain="[('brand_id', '=', brand_id)]" />
domain="[('brand_id', '=', brand_id)]"/>
<field name="machine_tool_category" readonly="1" attrs="{'invisible': [('type_id', '=', False)]}"
force_save="1"/>
<field name="run_time" force_save="1"/>
@@ -73,7 +73,7 @@
<group>
<group string="基础参数">
<field name="control_system_id" attrs="{'required': [('equipment_type', '=', '机床')]}"
options="{'no_create': True}" />
options="{'no_create': True}"/>
<label for="workbench_L" string="工作台尺寸(mm)"/>
<div class="test_model">
<label for="workbench_L" string="长"/>
@@ -85,7 +85,7 @@
<field name="workbench_W" class="o_address_zip"
attrs="{'required': [('equipment_type', '=', '机床')]}"
options="{'format': false}"/>
<span>&amp;nbsp;</span>
<span>&amp;nbsp;</span>
<label for="workbench_H" string="高"/>
<field name="workbench_H" class="o_address_zip"
attrs="{'required': [('equipment_type', '=', '机床')]}"
@@ -134,7 +134,7 @@
<!-- <field name="guide_rail" required="1"/>-->
<field name="number_of_axles" attrs="{'required': [('equipment_type', '=', '机床')]}"
widget="radio"
options="{'horizontal': true}" />
options="{'horizontal': true}"/>
<label for="x_axis" string="加工行程(mm)"
attrs="{'invisible': [('number_of_axles', '=', False)]}"/>
<div class="test_model"
@@ -196,8 +196,8 @@
<field name="T_tool_time"/>
<field name="C_tool_time"/>
</group>
<group string="主轴">
<field name="taper_type_id" attrs="{'required': [('equipment_type', '=', '机床')]}" />
<group string="主轴">
<field name="taper_type_id" attrs="{'required': [('equipment_type', '=', '机床')]}"/>
<label for="distance_min" string="主轴端面-工作台距离(mm)"/>
<div class="test_model">
<label for="distance_min" string="最小(min)"/>
@@ -237,7 +237,7 @@
<field name="c_precision"/>
<field name="c_precision_repeat"/>
</group>
<group string="进给参数">
<group string="进给参数">
<field name="X_axis_rapid_traverse_speed"/>
<field name="Y_axis_rapid_traverse_speed"/>
<field name="Z_axis_rapid_traverse_speed"/>
@@ -252,21 +252,21 @@
</page>
<page string="AGV运行日志" name="sf_equipment"
<page string="AGV运行日志" name="sf_equipment"
attrs="{'invisible': [('equipment_type', '!=', 'AGV小车')]}">
<field name="agv_logs">
<tree create="1" edit="1" delete="1" editable="bottom">
<field name = 'run_type'/>
<field name = 'run_code'/>
<field name = 'run_first'/>
<field name = 'run_last'/>
<field name = 'production_line'/>
<field name = 'workorder'/>
<field name = 'time'/>
<field name = 'state'/>
</tree>
</field>
</page>
<field name="agv_logs">
<tree create="1" edit="1" delete="1" editable="bottom">
<field name='run_type'/>
<field name='run_code'/>
<field name='run_first'/>
<field name='run_last'/>
<field name='production_line'/>
<field name='workorder'/>
<field name='time'/>
<field name='state'/>
</tree>
</field>
</page>
<page string="设备参数" name="sf_equipment"
attrs="{'invisible': [('equipment_type', '!=', 'AGV小车')]}">
@@ -979,31 +979,58 @@
</group>
</xpath>
<xpath expr="//field[@name='next_action_date']" position="before">
<field name='eq_maintenance_id' force_save="1" widget="many2one"/>
<xpath expr="//page[@name='maintenance']" position="replace">
<page string="维保" name="maintenance">
<group>
<group string="保养">
<field name='eq_maintenance_id' force_save="1" widget="many2one"/>
<field name="initial_action_date"/>
<field name="next_action_date" string="下次预防保养"/>
<label for="period" string="预防保养频次"/>
<div class="o_row">
<field name="period"/>
days
</div>
<label for="maintenance_duration" string="保养时长"/>
<div class="o_row">
<field name="maintenance_duration"/>
hours
</div>
<div class="col-12 col-lg-6 o_setting_box" style="white-space: nowrap">
<button name="confirm_maintenance" string="确认保养" type="object"
class="oe_highlight" context="{'type': '保养'}"/>
</div>
</group>
<group string="检修">
<field name='overhaul_id'/>
<field name="initial_overhaul_date"/>
<field name="overhaul_date" string="下次预防检修"/>
<label for="overhaul_period" string="预防检修频次"/>
<div class="o_row">
<field name="overhaul_period"/>
days
</div>
<label for="overhaul_duration" string="检修时长"/>
<div class="o_row">
<field name="overhaul_duration"/>
hours
</div>
<field name='equipment_maintenance_standards_ids' widget="many2many_tags"
invisible="1"/>
<div class="col-12 col-lg-6 o_setting_box" style="white-space: nowrap">
<button name="confirm_maintenance" string="确认检修" type="object"
class="oe_highlight" context="{'type': '检修'}"/>
</div>
</group>
</group>
</page>
</xpath>
<xpath expr="//div[hasclass('o_row')][field[@name='maintenance_duration']]" position="after">
<field name='overhaul_id' options="{'no_create':True}"/>
<field name="overhaul_date" string="下次预防检修"/>
<label for="overhaul_period" string="预防检修频次"/>
<div class="o_row">
<field name="overhaul_period"/>
days
</div>
<label for="overhaul_duration" string="检修时长"/>
<div class="o_row">
<field name="overhaul_duration"/>
hours
</div>
<field name='equipment_maintenance_standards_ids' widget="many2many_tags" invisible="1"/>
</xpath>
<xpath expr="//page[@name='description']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
@@ -1142,14 +1169,16 @@
</div>
<div class="show_state" t-attf-class="oe_kanban_global_click o_kanban_record_has_image_fill o_hr_kanban_record oe_kanban_card oe_kanban_global_click
">
<div t-attf-class="#{record.state.raw_value == '正常' ? 'color_1' : ''}"></div>
<div t-attf-class="#{record.state.raw_value == '故障' ? 'color_2' : ''}"></div>
<div t-attf-class="#{record.state.raw_value == '不可用' ? 'color_3' : ''}"></div>
<div t-attf-class="#{record.run_status.raw_value == '运行中' ? 'color_1' : ''}"></div>
<div t-attf-class="#{record.run_status.raw_value == '待机' ? 'color_4' : ''}"></div>
<div t-attf-class="#{record.run_status.raw_value == '故障' ? 'color_2' : ''}"></div>
<div t-attf-class="#{record.run_status.raw_value == '离线' ? 'color_3' : ''}"></div>
<p class="o_kanban_record_bottom state_zc"
t-attf-class="#{record.state.raw_value == '正常' ? 'font_color_1' : ''}
#{record.state.raw_value == '故障' ? 'font_color_2' : ''}
#{record.state.raw_value == '不可用' ? 'font_color_3' : ''}">
<field name="state"/>
t-attf-class="#{record.run_status.raw_value == '运行中' ? 'font_color_1' : ''}
#{record.run_status.raw_value == '待机' ? 'font_color_4' : ''}
#{record.run_status.raw_value == '故障' ? 'font_color_2' : ''}
#{record.run_status.raw_value == '离线' ? 'font_color_3' : ''}">
<field name="run_status"/>
</p>
</div>
</div>
@@ -1187,7 +1216,7 @@
<field name="name" readonly="1"/>
<field name="type" readonly="1"/>
<field name="image" widget="image" readonly="1"/>
<!-- <field name="equipment_id"/>-->
<!-- <field name="equipment_id"/>-->
<field name="active" invisible="1"/>
</tree>
</field>

View File

@@ -0,0 +1 @@
from . import maintenance_request_wizard

View File

@@ -0,0 +1,26 @@
from odoo import fields, models
class MaintenanceRequestWizard(models.TransientModel):
_name = 'maintenance.request.wizard'
_description = '维保二次确认弹窗'
name = fields.Char('')
def submit(self):
context = self.env.context
equipment_id = self.env['maintenance.equipment'].sudo().search([('id', '=', context['equipment_id'])])
request_ids = self.env['maintenance.request'].search([('stage_id.done', '=', False),
('equipment_id', '=', equipment_id.id),
('maintenance_type', '=', 'preventive'),
('sf_maintenance_type', '=', context['type'])])
request_ids.write({'active': False})
return equipment_id.create_maintenance_request(context['type'])
def cancel(self):
context = self.env.context
equipment_id = self.env['maintenance.equipment'].sudo().search([('id', '=', context['equipment_id'])])
if context['type'] == '保养':
equipment_id.initial_action_date = equipment_id.initial_action_date_old
elif context['type'] == '检修':
equipment_id.initial_overhaul_date = equipment_id.initial_overhaul_date_old

View File

@@ -0,0 +1,29 @@
<openerp>
<data>
<record id="action_maintenance_request_wizard" model="ir.actions.act_window">
<field name="name">维保计划</field>
<field name="res_model">maintenance.request.wizard</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
<record model="ir.ui.view" id="maintenance_request_wizard_form_view">
<field name="name">maintenance.request.wizard.form.view</field>
<field name="model">maintenance.request.wizard</field>
<field name="arch" type="xml">
<form>
<div>
<field name="name" invisible="1"/>
有未执行的历史维保计划,是否创建新维保计划!!
</div>
<footer>
<button string="确认" name="submit" type="object" class="oe_highlight"/>
<button string="取消" name="cancel" type="object" class="oe_highlight"/>
</footer>
</form>
</field>
</record>
</data>
</openerp>

View File

@@ -189,6 +189,7 @@ class Manufacturing_Connect(http.Controller):
request.env['sf.production.plan'].sudo().search([('production_id', '=', production_id)]).write(
{'actual_start_time': workorder.date_start,
'state': 'processing'})
res.update({'workorder_id': workorder.id})
except Exception as e:
res = {'Succeed': False, 'ErrorCode': 202, 'Error': e}
@@ -595,14 +596,6 @@ class Manufacturing_Connect(http.Controller):
if panel_workorder:
panel_workorder.write({'production_line_state': '已下产线'})
workorder.write({'state': 'to be detected'})
# workpiece_delivery = request.env['sf.workpiece.delivery'].sudo().search(
# [
# ('rfid_code', '=', rfid_code), ('type', '=', '下产线'),
# ('production_id', '=', order.production_id.id),
# ('workorder_id', '=', order.id),
# ('workorder_state', '=', 'done')])
# if workpiece_delivery:
# delivery_Arr.append(workpiece_delivery.id)
else:
res = {'Succeed': False, 'ErrorCode': 204,
'Error': 'DeviceId为%s没有对应的已配送工件数据' % ret['DeviceId']}
@@ -695,4 +688,4 @@ class Manufacturing_Connect(http.Controller):
except Exception as e:
res = {'Succeed': False, 'ErrorCode': 202, 'Error': str(e)}
logging.info('AGVDownProduct error:%s' % e)
return json.JSONEncoder().encode(res)
return json.JSONEncoder().encode(res)

View File

@@ -18,7 +18,7 @@ class MrpProduction(models.Model):
_inherit = 'mrp.production'
_description = "制造订单"
_order = 'create_date desc'
deadline_of_delivery = fields.Date('订单交期', tracking=True, compute='_compute_deadline_of_delivery')
# tray_ids = fields.One2many('sf.tray', 'production_id', string="托盘")
maintenance_count = fields.Integer(compute='_compute_maintenance_count', string="Number of maintenance requests")
request_ids = fields.One2many('maintenance.request', 'production_id')
@@ -34,6 +34,29 @@ class MrpProduction(models.Model):
tool_state_remark = fields.Text(string='功能刀具状态备注(缺刀)', compute='_compute_tool_state_remark', store=True)
tool_state_remark2 = fields.Text(string='功能刀具状态备注(无效刀)', readonly=True)
@api.depends('procurement_group_id.mrp_production_ids.move_dest_ids.group_id.sale_id')
def _compute_deadline_of_delivery(self):
for production in self:
# 确保 procurement_group_id 和相关字段存在
if production.procurement_group_id:
# 获取相关的 sale_id
sale_order_id = production.procurement_group_id.mrp_production_ids.mapped(
'move_dest_ids.group_id.sale_id')
# 确保 sale_order_id 是有效的 ID 列表
if sale_order_id:
# 获取 sale.order 记录
sale_id = self.env['sale.order'].sudo().browse(sale_order_id.ids) # 使用 mapped 返回的 ID 列表
# 处理 sale_id
if sale_id:
# 假设我们只需要第一个 sale_id
production.deadline_of_delivery = sale_id[0].deadline_of_delivery if sale_id else False
else:
production.deadline_of_delivery = False
else:
production.deadline_of_delivery = False
@api.depends('workorder_ids.tool_state_remark')
def _compute_tool_state_remark(self):
for item in self:
@@ -118,10 +141,12 @@ class MrpProduction(models.Model):
], string='工序状态', default='待装夹')
# 零件图号
part_number = fields.Char('零件图号')
part_number = fields.Char('零件图号', readonly=True)
# 上传零件图纸
part_drawing = fields.Binary('零件图纸')
part_drawing = fields.Binary('零件图纸', readonly=True)
quality_standard = fields.Binary('质检标准', readonly=True)
@api.depends('product_id.manual_quotation')
def _compute_manual_quotation(self):
@@ -296,8 +321,13 @@ class MrpProduction(models.Model):
# 编程单更新
def update_programming_state(self):
try:
manufacturing_type = 'rework'
if self.is_scrap:
manufacturing_type = 'scrap'
elif self.tool_state == '2':
manufacturing_type = 'invalid_tool_rework'
res = {'programming_no': self.programming_no,
'manufacturing_type': 'rework' if self.is_scrap is False else 'scrap'}
'manufacturing_type': manufacturing_type}
logging.info('res=%s:' % res)
configsettings = self.env['res.config.settings'].get_values()
config_header = Common.get_headers(self, configsettings['token'], configsettings['sf_secret_key'])
@@ -943,6 +973,8 @@ class MrpProduction(models.Model):
if production.programming_no in program_to_production_names:
productions_not_delivered = self.env['mrp.production'].search(
[('programming_no', '=', production.programming_no), ('programming_state', '=', '已编程未下发')])
productions = self.env['mrp.production'].search(
[('programming_no', '=', production.programming_no), ('state', 'not in', ('cancel', 'done'))])
rework_workorder = production.workorder_ids.filtered(lambda m: m.state == 'rework')
if rework_workorder:
for rework_item in rework_workorder:
@@ -955,6 +987,13 @@ class MrpProduction(models.Model):
productions_not_delivered.write(
{'state': 'progress', 'programming_state': '已编程', 'is_rework': False})
# 对制造订单所以面的cnc工单的程序用刀进行校验
try:
logging.info(f'已更新制造订单:{productions_not_delivered}')
productions.production_cnc_tool_checkout()
except Exception as e:
logging.info(f'对cnc工单的程序用刀进行校验报错{e}')
# 从cloud获取重新编程过的最新程序
def get_new_program(self, processing_panel):
try:

View File

@@ -40,7 +40,7 @@ class ResMrpRoutingWorkcenter(models.Model):
def get_company_id(self):
self.company_id = self.env.user.company_id.id
company_id = fields.Many2one('res.company', compute="get_company_id", related=False)
company_id = fields.Many2one('res.company', compute="get_company_id", related=False, store=True)
# 排产的时候, 根据坯料的长宽高比对一下机床的最大加工尺寸.不符合就不要分配给这个加工中心(机床).
# 工单对应的工作中心,根据工序中的工作中心去匹配,

View File

@@ -231,13 +231,13 @@ class ResWorkcenter(models.Model):
default_capacity = round(
self.production_line_hour_capacity * date_planned_working_hours, 2)
_logger.info('排程日期:%s,计划数量:%s,日产能:%s,日工时:%s' % (
date_planned, sum_qty, default_capacity, date_planned_working_hours))
date_planned, sum_qty, default_capacity, date_planned_working_hours))
if sum_qty >= default_capacity:
return False
return True
# 处理排程是否超过小时产能
def deal_available_single_machine_capacity(self, date_planned):
def deal_available_single_machine_capacity(self, date_planned, count):
date_planned_start = date_planned.strftime('%Y-%m-%d %H:00:00')
date_planned_end = date_planned + timedelta(hours=1)
@@ -249,7 +249,11 @@ class ResWorkcenter(models.Model):
if plan_ids:
sum_qty = sum([p.product_qty for p in plan_ids])
if sum_qty >= self.production_line_hour_capacity:
production_line_hour_capacity = self.production_line_hour_capacity
if sum_qty >= production_line_hour_capacity:
message = '当前计划开始时间不能预约排程,超过生产线小时产能(%d件)%d' % (
production_line_hour_capacity, count)
raise UserError(message)
return False
return True

View File

@@ -59,7 +59,7 @@ class ResMrpWorkOrder(models.Model):
compute='_compute_state', store=True,
default='pending', copy=False, readonly=True, recursive=True, index=True, tracking=True)
# state = fields.Selection(selection_add=[('to be detected', "待检测"), ('rework', '返工')], tracking=True)
delivery_warning = fields.Selection([('normal', '正常'), ('warning', '告警'), ('overdue', '逾期')], string='时效')
@api.depends('production_id.manual_quotation')
def _compute_manual_quotation(self):
@@ -225,6 +225,9 @@ class ResMrpWorkOrder(models.Model):
material_height = fields.Float(string='')
# 零件图号
part_number = fields.Char(related='production_id.part_number', string='零件图号')
machining_drawings = fields.Binary('2D加工图纸', related='production_id.part_drawing', readonly=True)
quality_standard = fields.Binary('质检标准', related='production_id.quality_standard', readonly=True)
# 工序状态
process_state = fields.Selection([
('待装夹', '待装夹'),
@@ -1048,6 +1051,17 @@ class ResMrpWorkOrder(models.Model):
if workorder.production_id.tool_state in ['1', '2'] and workorder.state == 'ready':
workorder.state = 'waiting'
continue
if (workorder.production_id.tool_state in ['1', '2']
and not workorder.production_id.workorder_ids.filtered(lambda a: a.sequence == 0)
and workorder.production_id.programming_state == '编程中' and workorder.name == '装夹预调'):
if workorder.state == 'pending' and workorder == self.search(
[('production_id', '=', workorder.production_id.id),
('routing_type', '=', '装夹预调'),
('state', 'not in', ['rework', 'done', 'cancel'])],
limit=1,
order="sequence"):
workorder.state = 'waiting'
continue
# elif workorder.routing_type == 'CNC加工' and workorder.state not in ['done', 'cancel', 'progress',
# 'rework']:
@@ -1197,8 +1211,8 @@ class ResMrpWorkOrder(models.Model):
if record.is_rework is False:
if not record.material_center_point:
raise UserError("坯料中心点为空,请检查")
if record.X_deviation_angle <= 0:
raise UserError("X偏差角度小于等于0请检查本次计算的X偏差角度为%s" % record.X_deviation_angle)
# if record.X_deviation_angle <= 0:
# raise UserError("X偏差角度小于等于0请检查本次计算的X偏差角度为%s" % record.X_deviation_angle)
record.process_state = '待加工'
# record.write({'process_state': '待加工'})
record.production_id.process_state = '待加工'

View File

@@ -774,6 +774,10 @@ class ResProductMo(models.Model):
# bfm下单
manual_quotation = fields.Boolean('人工编程', default=False, readonly=True)
part_number = fields.Char(string='零件图号', readonly=True)
machining_drawings = fields.Binary('2D加工图纸', readonly=True)
quality_standard = fields.Binary('质检标准', readonly=True)
machining_drawings_name = fields.Char('2D加工图纸名', readonly=True)
quality_standard_name = fields.Char('质检标准名', readonly=True)
@api.constrains('tool_length')
def _check_tool_length_size(self):
@@ -835,6 +839,11 @@ class ResProductMo(models.Model):
else:
return self.env.ref('sf_dlm.product_uom_cubic_millimeter')
def attachment_update(self, name, res_id, res_field):
attachment_info = self.env['ir.attachment'].sudo().search(
[('res_id', '=', res_id), ('res_field', '=', res_field)], limit=1)
attachment_info.write({'name': name})
# 业务平台分配工厂后在智能工厂先创建销售订单再创建该产品
def product_create(self, product_id, item, order_id, order_number, i):
copy_product_id = product_id.with_user(self.env.ref("base.user_admin")).copy()
@@ -873,6 +882,11 @@ class ResProductMo(models.Model):
'manual_quotation': item['manual_quotation'] or False,
'part_number': item.get('part_number') or '',
'active': True,
'machining_drawings_name': item['machining_drawings_name'],
'quality_standard_name': item['quality_standard_name'],
'machining_drawings': '' if not item['machining_drawings'] else base64.b64decode(
item['machining_drawings']),
'quality_standard': '' if not item['quality_standard'] else base64.b64decode(item['quality_standard']),
}
tax_id = self.env['account.tax'].sudo().search(
[('type_tax_use', '=', 'sale'), ('amount', '=', item.get('tax')), ('price_include', '=', 'True')])
@@ -880,6 +894,12 @@ class ResProductMo(models.Model):
vals.update({'taxes_id': [(6, 0, [int(tax_id)])]})
copy_product_id.sudo().write(vals)
product_id.product_tmpl_id.active = False
if item['machining_drawings'] and item['machining_drawings_name']:
self.attachment_update(item['machining_drawings_name'], copy_product_id.product_tmpl_id.id,
'machining_drawings')
if item['quality_standard'] and item['quality_standard_name']:
self.attachment_update(item['quality_standard_name'], copy_product_id.product_tmpl_id.id,
'quality_standard')
return copy_product_id
def _get_ids(self, param):

View File

@@ -182,6 +182,11 @@ class StockRule(models.Model):
moves._action_confirm()
return True
def attachment_update(self, name, res_id, res_field):
attachment_info = self.env['ir.attachment'].sudo().search(
[('res_id', '=', res_id), ('res_field', '=', res_field)], limit=1)
attachment_info.write({'name': name})
@api.model
def _run_manufacture(self, procurements):
productions_values_by_company = defaultdict(list)
@@ -272,6 +277,16 @@ class StockRule(models.Model):
if quick_easy_order:
production.write({'part_number': quick_easy_order.part_drawing_number,
'part_drawing': quick_easy_order.machining_drawings})
else:
production.write({'part_number': production.product_id.part_number,
'part_drawing': production.product_id.machining_drawings,
'quality_standard': production.product_id.quality_standard})
if production.product_id.machining_drawings and production.product_id.machining_drawings_name:
self.attachment_update(production.product_id.machining_drawings_name, production.id,
'part_drawing')
if production.product_id.quality_standard and production.product_id.quality_standard_name:
self.attachment_update(production.product_id.quality_standard_name, production.id,
'quality_standard')
if sale_order:
# sale_order.write({'schedule_status': 'to schedule'})
self.env['sf.production.plan'].sudo().with_company(company_id).create({

View File

@@ -103,10 +103,20 @@ access_mrp_production_split_multi_group_sf_mrp_user,access.mrp.production.split.
access_mrp_production_split_group_sf_mrp_user,access.mrp.production.split,mrp.model_mrp_production_split,sf_base.group_sf_mrp_user,1,1,1,0
access_mrp_production_split_line_group_sf_mrp_user,access.mrp.production.split.line,mrp.model_mrp_production_split_line,sf_base.group_sf_mrp_user,1,1,1,0
access_mrp_workcenter_capacity_manager_group_sf_mrp_user,mrp.workcenter.capacity.manager,mrp.model_mrp_workcenter_capacity,sf_base.group_sf_mrp_user,1,1,1,0
access_mrp_workcenter_group_quality,mrp_workcenter_group_quality,model_mrp_workcenter,sf_base.group_quality,1,0,0,0
access_mrp_workcenter_group_quality_director,mrp_workcenter_group_quality_director,model_mrp_workcenter,sf_base.group_quality_director,1,0,0,0
access_sf_detection_result_group_quality,sf_detection_result_group_quality,model_sf_detection_result,sf_base.group_quality,1,0,1,0
access_sf_detection_result_group_quality_director,sf_detection_result_group_quality_director,model_sf_detection_result,sf_base.group_quality_director,1,0,1,0
access_mrp_workcenter_productivity_loss_group_quality,mrp_workcenter_productivity_loss_group_quality,mrp.model_mrp_workcenter_productivity_loss,sf_base.group_quality,1,0,0,0
access_mrp_workcenter_productivity_loss_group_quality_director,mrp_workcenter_productivity_loss_group_quality_director,mrp.model_mrp_workcenter_productivity_loss,sf_base.group_quality_director,1,0,0,0
access_mrp_workcenter_productivity_group_quality,mrp_workcenter_productivity_group_quality,mrp.model_mrp_workcenter_productivity,sf_base.group_quality,1,1,1,0
access_mrp_workcenter_productivity_group_quality_director,mrp_workcenter_productivity_group_quality_director,mrp.model_mrp_workcenter_productivity,sf_base.group_quality_director,1,1,1,0
access_mrp_production_group_plan_dispatch,mrp_production,model_mrp_production,sf_base.group_plan_dispatch,1,1,0,0
access_mrp_workorder,mrp_workorder,model_mrp_workorder,sf_base.group_plan_dispatch,1,1,1,0
access_mrp_production_group_quality,mrp_production,model_mrp_production,sf_base.group_quality,1,1,0,0
access_mrp_production_group_quality_director,mrp_production,model_mrp_production,sf_base.group_quality_director,1,1,0,0
access_mrp_workorder_group_quality,mrp_workorder,model_mrp_workorder,sf_base.group_quality,1,1,0,0
access_mrp_workorder_group_quality_director,mrp_workorder,model_mrp_workorder,sf_base.group_quality_director,1,1,0,0
access_mrp_workorder,mrp_workorder,model_mrp_workorder,sf_base.group_plan_dispatch,1,1,0,0
access_sf_production_line_group_plan_dispatch,sf.production.line,model_sf_production_line,sf_base.group_plan_dispatch,1,0,0,0
access_sf_production_line_group_plan_director,sf.production.line,model_sf_production_line,sf_base.group_plan_director,1,1,1,0
access_sf_production_line,sf.production.line,model_sf_production_line,sf_maintenance.sf_group_equipment_user,1,1,1,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
103 access_mrp_production_split_line_group_sf_mrp_user access.mrp.production.split.line mrp.model_mrp_production_split_line sf_base.group_sf_mrp_user 1 1 1 0
104 access_mrp_workcenter_capacity_manager_group_sf_mrp_user mrp.workcenter.capacity.manager mrp.model_mrp_workcenter_capacity sf_base.group_sf_mrp_user 1 1 1 0
105 access_mrp_production_group_plan_dispatch access_mrp_workcenter_group_quality mrp_production mrp_workcenter_group_quality model_mrp_production model_mrp_workcenter sf_base.group_plan_dispatch sf_base.group_quality 1 1 0 0 0
106 access_mrp_workorder access_mrp_workcenter_group_quality_director mrp_workorder mrp_workcenter_group_quality_director model_mrp_workorder model_mrp_workcenter sf_base.group_plan_dispatch sf_base.group_quality_director 1 1 0 1 0 0
107 access_sf_production_line_group_plan_dispatch access_sf_detection_result_group_quality sf.production.line sf_detection_result_group_quality model_sf_production_line model_sf_detection_result sf_base.group_plan_dispatch sf_base.group_quality 1 0 0 1 0
108 access_sf_detection_result_group_quality_director sf_detection_result_group_quality_director model_sf_detection_result sf_base.group_quality_director 1 0 1 0
109 access_mrp_workcenter_productivity_loss_group_quality mrp_workcenter_productivity_loss_group_quality mrp.model_mrp_workcenter_productivity_loss sf_base.group_quality 1 0 0 0
110 access_mrp_workcenter_productivity_loss_group_quality_director mrp_workcenter_productivity_loss_group_quality_director mrp.model_mrp_workcenter_productivity_loss sf_base.group_quality_director 1 0 0 0
111 access_mrp_workcenter_productivity_group_quality mrp_workcenter_productivity_group_quality mrp.model_mrp_workcenter_productivity sf_base.group_quality 1 1 1 0
112 access_mrp_workcenter_productivity_group_quality_director mrp_workcenter_productivity_group_quality_director mrp.model_mrp_workcenter_productivity sf_base.group_quality_director 1 1 1 0
113 access_mrp_production_group_plan_dispatch mrp_production model_mrp_production sf_base.group_plan_dispatch 1 1 0 0
114 access_sf_production_line_group_plan_director access_mrp_production_group_quality sf.production.line mrp_production model_sf_production_line model_mrp_production sf_base.group_plan_director sf_base.group_quality 1 1 1 0 0
115 access_sf_production_line access_mrp_production_group_quality_director sf.production.line mrp_production model_sf_production_line model_mrp_production sf_maintenance.sf_group_equipment_user sf_base.group_quality_director 1 1 1 0 0
116 access_mrp_workorder_group_quality mrp_workorder model_mrp_workorder sf_base.group_quality 1 1 0 0
117 access_mrp_workorder_group_quality_director mrp_workorder model_mrp_workorder sf_base.group_quality_director 1 1 0 0
118 access_mrp_workorder mrp_workorder model_mrp_workorder sf_base.group_plan_dispatch 1 1 0 0
119 access_sf_production_line_group_plan_dispatch sf.production.line model_sf_production_line sf_base.group_plan_dispatch 1 0 0 0
120 access_mrp_workcenter access_sf_production_line_group_plan_director mrp_workcenter sf.production.line model_mrp_workcenter model_sf_production_line sf_base.group_plan_dispatch sf_base.group_plan_director 1 1 1 0
121 access_mrp_bom_group_plan_dispatch access_sf_production_line mrp.bom sf.production.line mrp.model_mrp_bom model_sf_production_line sf_base.group_plan_dispatch sf_maintenance.sf_group_equipment_user 1 0 1 0 1 0
122 access_mrp_bom_line access_mrp_workcenter mrp.bom.line mrp_workcenter mrp.model_mrp_bom_line model_mrp_workcenter sf_base.group_plan_dispatch 1 0 1 0 1 0

View File

@@ -98,9 +98,9 @@
<field name="production_line_id" readonly="1"/>
<!-- <field name="production_line_state" readonly="1"/>-->
<field name="part_number" string="成品的零件图号"/>
<field name="part_drawing"/>
<field name="tool_state"/>
<field name="tool_state_remark" string="备注" attrs="{'invisible': [('tool_state', '!=', '1')]}"/>
<field name="deadline_of_delivery" readonly="1"/>
<field name="tool_state_remark2" invisible="1"/>
</xpath>
<xpath expr="//header//button[@name='action_cancel']" position="replace">
@@ -296,8 +296,11 @@
</attribute>
</xpath>
<xpath expr="//sheet//notebook//page[@name='operations']//field[@name='workorder_ids']" position="replace">
<field name="workorder_ids" attrs="{'readonly': ['|', ('state', '!=', 'test_value'), '&amp;', ('state', '=', 'done'), ('is_locked', '=', True)]}" context="{'tree_view_ref': 'mrp.mrp_production_workorder_tree_editable_view', 'default_product_uom_id': product_uom_id, 'from_manufacturing_order': True}"/>
<xpath expr="//sheet//notebook//page[@name='operations']//field[@name='workorder_ids']"
position="replace">
<field name="workorder_ids"
attrs="{'readonly': ['|', ('state', '!=', 'test_value'), '&amp;', ('state', '=', 'done'), ('is_locked', '=', True)]}"
context="{'tree_view_ref': 'mrp.mrp_production_workorder_tree_editable_view', 'default_product_uom_id': product_uom_id, 'from_manufacturing_order': True}"/>
</xpath>
<xpath expr="//sheet//notebook//page[@name='operations']" position="after">
@@ -325,6 +328,16 @@
<xpath expr="//field[@name='components_availability']" position="attributes">
<attribute name="string">投料状态</attribute>
</xpath>
<xpath expr="//sheet//notebook" position="inside">
<page string="零件图纸">
<field name="part_drawing" widget="adaptive_viewer"/>
</page>
</xpath>
<xpath expr="//sheet//notebook" position="inside">
<page string="质检标准">
<field name="quality_standard" widget="adaptive_viewer"/>
</page>
</xpath>
</field>
</record>
@@ -348,8 +361,11 @@
<field name="arch" type="xml">
<xpath expr="//tree" position="attributes">
<attribute name="default_order">sequence</attribute>
<attribute name="decoration-warning">delivery_warning == 'warning'</attribute>
<attribute name="decoration-danger">delivery_warning == 'overdue'</attribute>
</xpath>
<xpath expr="//field[@name='state']" position="replace">
<field name="delivery_warning" invisible="True"/>
<field name="state" widget="badge" decoration-warning="state == 'progress'"
decoration-success="state == 'done'" decoration-danger="state in ('cancel','rework')"
decoration-muted="state == 'to be detected'"
@@ -556,7 +572,12 @@
</div>
<field name="priority" widget="priority"/>
</div>
<t t-if="record.brand_id.raw_value">
<div class="mt-1">
品牌:
<field name="brand_id"></field>
</div>
</t>
<div name="product_specification_id" class="mt-1">
规格:
<field name="specification_id"/>

View File

@@ -101,7 +101,9 @@
<!-- <field name="target">fullscreen</field>-->
<field name="target">current</field>
<field name="domain">[('state', '!=', 'cancel'),('schedule_state', '=', '已排')]</field>
<field name="context">{'search_default_product': 1, 'search_default_workcenter_id': active_id}</field>
<field name="context">{'search_default_product': 1, 'search_default_workcenter_id':
active_id,'search_default_filter_order_warning':1,'search_default_filter_order_overdue':1}
</field>
<field name="help" type="html">
<p class="o_view_nocontent_workorder">
没有工单要做!
@@ -221,15 +223,52 @@
</page>
</xpath>
<xpath expr="//label[1]" position="before">
<field name='routing_type' readonly="1"/>
<field name='process_state' attrs='{"invisible": [("routing_type","!=","装夹预调")]}'/>
<!-- -->
<field name="production_id" invisible="0"/>
<field name="duration_expected" invisible="1"/>
<field name="date_planned_start" invisible="1"/>
<field name="date_planned_finished" invisible="1"/>
<field name="duration" widget="mrp_timer"
invisible="1" sum="real duration"/>
<field name="glb_file" readonly="1" widget="Viewer3D" string="加工模型"/>
<field name="manual_quotation" readonly="1"
attrs="{'invisible': [('routing_type', '!=', 'CNC加工')]}"/>
<field name="processing_panel" readonly="1"
attrs='{"invisible": [("routing_type","in",("获取CNC加工程序","切割"))]}'/>
<field name="equipment_id" readonly="1"
attrs='{"invisible": [("routing_type","in",("获取CNC加工程序","切割","装夹预调"))]}'/>
<field name="production_line_id"
attrs='{"invisible": [("routing_type","in",("获取CNC加工程序","切割","装夹预调"))]}'/>
<field name="production_line_state" readonly="1"
attrs='{"invisible": [("routing_type","in",("获取CNC加工程序","切割","装夹预调"))]}'/>
<field name='routing_type' invisible="1"/>
<field name='process_state' invisible="1"/>
<field name='tag_type' readonly="1" attrs='{"invisible": [("tag_type","=",False)]}'
decoration-danger="tag_type == '重新加工'"/>
<field name="rfid_code" force_save="1" readonly="1" cache="True"
<field name="rfid_code" force_save="1" readonly="0" cache="True"
attrs="{'invisible': [('rfid_code_old', '!=', False)]}"/>
<field name="rfid_code_old" readonly="1" attrs="{'invisible': [('rfid_code_old', '=', False)]}"/>
</xpath>
<xpath expr="//form//sheet//group//group//div[2]" position="replace">
</xpath>
<xpath expr="//form//sheet//group//group//div[1]" position="after">
<field name="save_name" widget="CopyClipboardChar"
attrs="{'invisible':[('routing_type','!=','装夹预调')]}"/>
<label for="material_length" string="物料尺寸"/>
<div class="o_address_format">
<label for="material_length" string="长"/>
<field name="material_length" class="o_address_zip"/>
<span>&amp;nbsp;</span>
<label for="material_width" string="宽"/>
<field name="material_width" class="o_address_zip"/>
<span>&amp;nbsp;</span>
<label for="material_height" string="高"/>
<field name="material_height" class="o_address_zip"/>
</div>
<field name="part_number" string="成品的零件图号"/>
</xpath>
<xpath expr="//label[1]" position="attributes">
<attribute name="string">计划加工时间</attribute>
</xpath>
@@ -246,76 +285,12 @@
<field name='materiel_width' string="宽"/>
<field name='materiel_height' string="高"/>
</xpath>
<field name="production_id" position="after" invisible="0">
<group>
<field name="date_planned_start" invisible="1"/>
<field name="date_planned_finished" invisible="1"/>
<!-- <field name="production_id" readonly="1"/>-->
<field name="duration" widget="mrp_timer"
attrs="{'invisible': [('production_state','=', 'draft')], 'readonly': [('is_user_working', '=', True)]}"
sum="real duration"/>
<field name="glb_file" readonly="1" widget="Viewer3D" string="加工模型"/>
<field name="manual_quotation" readonly="1"
attrs="{'invisible': [('routing_type', '!=', 'CNC加工')]}"/>
<field name="processing_panel" readonly="1"
attrs='{"invisible": [("routing_type","in",("获取CNC加工程序","切割"))]}'/>
<field name="equipment_id" readonly="1"
attrs='{"invisible": [("routing_type","in",("获取CNC加工程序","切割","装夹预调"))]}'/>
<field name="production_line_id"
attrs='{"invisible": [("routing_type","in",("获取CNC加工程序","切割"))]}'/>
<field name="production_line_state" readonly="1"
attrs='{"invisible": [("routing_type","in",("获取CNC加工程序","切割","装夹预调"))]}'/>
<!-- <field name="functional_fixture_id" -->
<!-- attrs='{"invisible": [("routing_type","!=","装夹预调")]}'/> -->
<!-- <field name="functional_fixture_code" force_save="1" -->
<!-- attrs='{"invisible": [("routing_type","!=","装夹预调")]}'/> -->
<!-- <field name="functional_fixture_type_id" -->
<!-- attrs='{"invisible": [("routing_type","!=","装夹预调")]}'/> -->
</group>
<!-- <group>-->
<!-- <div>-->
<!-- <label for="glb_file" string="加工模型"/>-->
<!-- <field name="glb_file" readonly="1" widget="Viewer3D"/>-->
<!-- </div>-->
<!-- &lt;!&ndash; <field name="glb_file" string="模型" readonly="1" widget="Viewer3D"/>&ndash;&gt;-->
<!-- </group>-->
<!-- <field name="processing_panel" readonly="1" attrs="{'invisible': [('routing_type', 'in', ('获取CNC加工程序','装夹','解除装夹',-->
<!-- '前置三元定位检测','后置三元质量检测','解除装夹'))]}"/>-->
</field>
<!-- <page string="Components" name="components">-->
<xpath expr="//page[1]" position="before">
<!-- <page string="装夹托盘" attrs='{"invisible": [("routing_type","!=","装夹")]}'>-->
<!-- <group>-->
<!-- <field name="routing_type" invisible="1"/>-->
<!-- <field name="tray_code"/>-->
<!-- <field name="tray_id" readonly="1"/>-->
<!-- </group>-->
<!-- <group>-->
<!-- <field name="pro_code" readonly="1" attrs='{"invisible": [("pro_code_ok","=",False)]}'-->
<!-- style="color:green"/>-->
<!-- <field name="pro_code" readonly="1" attrs='{"invisible": [("pro_code_ok","!=",False)]}'/>-->
<!-- <div>-->
<!-- <field name="pro_code_ok" invisible="1"/>-->
<!-- </div>-->
<!-- </group>-->
<!-- <div class="col-12 col-lg-6 o_setting_box">-->
<!-- <button type="object" class="oe_highlight" name="gettray" string="绑定托盘"-->
<!-- attrs='{"invisible": ["|","|",("tray_id","!=",False),("state","!=","progress"),("production_id","=",False)]}'/>-->
<!-- </div>-->
<!-- </page>-->
<page string="工件装夹" attrs='{"invisible": [("routing_type","!=","装夹预调")]}'>
<group>
<field name="_barcode_scanned" widget="barcode_handler"/>
<!-- <group string="卡盘">-->
<!-- <field name="chuck_serial_number"/>-->
<!-- <field name="chuck_name"/>-->
<!-- <field name="chuck_brand_id"/>-->
<!-- <field name="chuck_type_id"/>-->
<!-- <field name="chuck_model_id"/>-->
<!-- </group>-->
<group string="托盘">
<field name="tray_serial_number" readonly="1" string="序列号"/>
</group>
@@ -330,10 +305,6 @@
<field name="tray_model_id" readonly="1" string="型号"/>
</group>
</group>
<group string="加工图纸">
<!-- 隐藏加工图纸字段名 -->
<field name="processing_drawing" widget="pdf_viewer" string="" readonly="1"/>
</group>
<group string="预调程序信息">
<field name="preset_program_information" colspan="2" nolabel="1"
placeholder="如有预调程序信息请在此处输入....."/>
@@ -520,7 +491,8 @@
<xpath expr="//form//header" position="inside">
<button type="object" class="oe_highlight jikimo_button_confirm" name="get_three_check_datas"
string="获取数据" attrs='{"invisible": ["|", ("state","!=","progress"), ("routing_type","!=","装夹预调")]}'/>
string="获取数据"
attrs='{"invisible": ["|", ("state","!=","progress"), ("routing_type","!=","装夹预调")]}'/>
</xpath>
@@ -571,9 +543,7 @@
<!-- <field name="button_state" invisible="1"/>-->
</tree>
</field>
<group>
<field name="cnc_worksheet" string="工作指令" widget="pdf_viewer"/>
</group>
</page>
<page string="CMM程序" attrs='{"invisible": [("routing_type","!=","CNC加工")]}'>
<field name="cmm_ids" widget="one2many" string="CMM程序" readonly="1">
@@ -602,33 +572,60 @@
</page>
</xpath>
<xpath expr="//form//sheet//group//group//div[1]" position="after">
<label for="date_start" string="实际加工时间"/>
<div class="oe_inline">
<field name="date_start" class="mr8 oe_inline"/>
<strong class="mr8 oe_inline"></strong>
<field name="date_finished" class="oe_inline"/>
</div>
<!-- <xpath expr="//form//sheet//group//group//div[1]" position="after">-->
<!-- <label for="date_start" string="实际加工时间"/>-->
<!-- <div class="oe_inline">-->
<!-- <field name="date_start" class="mr8 oe_inline"/>-->
<!-- <strong class="mr8 oe_inline">到</strong>-->
<!-- <field name="date_finished" class="oe_inline"/>-->
<!-- </div>-->
<!-- </xpath>-->
<xpath expr="//page[@name='time_tracking']//field[@name='time_ids']//tree//field[@name='date_end']"
position="after">
<field name="duration" string="实际时长"/>
</xpath>
<xpath expr="//form//sheet//group//group//div[3]" position="after">
<field name="save_name" widget="CopyClipboardChar"
attrs="{'invisible':[('routing_type','!=','装夹预调')]}"/>
<label for="material_length" string="物料尺寸"/>
<div class="o_address_format">
<label for="material_length" string="长"/>
<field name="material_length" class="o_address_zip"/>
<span>&amp;nbsp;</span>
<label for="material_width" string="宽"/>
<field name="material_width" class="o_address_zip"/>
<span>&amp;nbsp;</span>
<label for="material_height" string="高"/>
<field name="material_height" class="o_address_zip"/>
</div>
<field name="part_number" string="成品的零件图号"/>
<xpath expr="//page[@name='time_tracking']" position="attributes">
<attribute name="groups">
mrp.group_mrp_manager,sf_base.group_sf_mrp_manager,sf_base.group_sf_equipment_user,sf_base.group_sf_order_user
</attribute>
</xpath>
<xpath expr="//sheet//notebook" position="inside">
<page string="2D加工图纸">
<field name="machining_drawings" widget="adaptive_viewer"
attrs="{'invisible': [('routing_type', '!=', 'CNC加工')]}"/>
</page>
</xpath>
<xpath expr="//sheet//notebook" position="inside">
<page string="质检标准">
<field name="quality_standard" widget="adaptive_viewer"
attrs="{'invisible': [('routing_type', '!=', 'CNC加工')]}"/>
</page>
</xpath>
</field>
</record>
<record id="view_mrp_production_workorder_tray_form_inherit_sf_1" model="ir.ui.view">
<field name="name">mrp.production.workorder.tray.form.inherit.sf.1</field>
<field name="model">mrp.workorder</field>
<field name="inherit_id" ref="sf_manufacturing.view_mrp_production_workorder_tray_form_inherit_sf"/>
<field name="arch" type="xml">
<xpath expr="//form//sheet//group//group[2]" position="replace">
<group string="装夹图纸" attrs="{'invisible': [('routing_type', '!=', '装夹预调')]}">
<!-- 隐藏加工图纸字段名 -->
<field name="processing_drawing" widget="pdf_viewer" string="" readonly="1"/>
<!-- <field name="production_id" invisible="0"/>-->
</group>
<group string="工作指令" attrs="{'invisible': [('routing_type', '!=', 'CNC加工')]}">
<field name="cnc_worksheet" string="" widget="pdf_viewer"/>
</group>
</xpath>
<!-- <xpath expr="//form//sheet//group//group[1]" position="before">-->
<!-- <field name="production_id"/>-->
<!-- </xpath>-->
</field>
</record>
<record id="workcenter_form_workorder_search" model="ir.ui.view">
<field name="name">custom.workorder.search</field>
<field name="model">mrp.workorder</field>
@@ -640,6 +637,12 @@
<xpath expr="//filter[@name='progress']" position="after">
<filter string="待检测" name="state" domain="[('state','=','to be detected')]"/>
</xpath>
<xpath expr="//filter[@name='date_start_filter']" position="before">
<separator/>
<filter string="预警" name="filter_order_warning" domain="[('delivery_warning', '=', 'warning')]"/>
<filter string="逾期" name="filter_order_overdue" domain="[('delivery_warning', '=', 'overdue')]"/>
<separator/>
</xpath>
</field>
</record>

View File

@@ -11,12 +11,13 @@
""",
'category': 'sf',
'website': 'https://www.sf.jikimo.com',
'depends': ['sale', 'purchase', 'sf_plan', 'jikimo_message_notify', 'stock'],
'depends': ['sale', 'purchase', 'sf_plan', 'jikimo_message_notify', 'stock', 'sf_quality', 'mrp'],
'data': [
'data/bussiness_node.xml',
# 'data/cron_data.xml',
'data/cron_data.xml',
'data/template_data.xml',
'security/ir.model.access.csv',
'views/mrp_workorder_views.xml',
],
'test': [
],

View File

@@ -1 +1 @@
from . import main
from . import main

View File

@@ -15,12 +15,13 @@ class MessageSfMrsConnect(Sf_Mrs_Connect):
def get_cnc_processing_create(self, **kw):
res = super(MessageSfMrsConnect, self).get_cnc_processing_create(**kw)
res = json.loads(res)
_logger.info('已进入消息推送:%s' % res)
if res.get('production_ids'):
try:
_logger.info('已编程的制造订单:%s' % res.get('production_ids'))
productions = request.env['mrp.production'].sudo().search([('id', 'in', res.get('production_ids'))])
# 过滤programming_state为已编程,tool_state为2的制造订单
tool_state_valid_productions = productions.filtered(lambda x: x.programming_state == '已编程' and x.tool_state == '2')
tool_state_valid_productions = productions.filtered(lambda x: x.tool_state == '2')
if tool_state_valid_productions:
data = {
'name': tool_state_valid_productions[0].programming_no
@@ -38,3 +39,22 @@ class MessageSfMrsConnect(Sf_Mrs_Connect):
_logger.info('无效用刀异常消息推送接口:%s' % e)
return json.JSONEncoder().encode(res)
@http.route('/api/maintenance_logs/notify', type='json', auth='public', methods=['GET', 'POST'], csrf=False, cors="*")
def maintenance_logs_notify(self, **kw):
res = {'code': 200, 'message': '设备故障日志信息推送成功'}
datas = request.httprequest.data
ret = json.loads(datas)
log_id = ret.get('log_id')
if not log_id:
res = {'code': 400, 'message': '设备故障日志id不能为空'}
return json.JSONEncoder().encode(res)
try:
if not isinstance(log_id, list):
log_id = [log_id]
maintenance_logs = request.env['sf.maintenance.logs'].sudo().search([('id', 'in', [int(id) for id in log_id])])
if maintenance_logs:
maintenance_logs.add_queue('设备故障')
except Exception as e:
res = {'code': 400, 'message': '设备故障信息推送失败', 'error': str(e)}
return json.JSONEncoder().encode(res)

View File

@@ -12,15 +12,16 @@
<field name="model">sale.order</field>
</record>
<!-- <record id="bussiness_sale_order_overdue_warning" model="jikimo.message.bussiness.node">-->
<!-- <field name="name">销售订单逾期预警</field>-->
<!-- <field name="model">sale.order</field>-->
<!-- </record>-->
<record id="bussiness_sale_order_overdue_warning" model="jikimo.message.bussiness.node">
<field name="name">销售订单逾期预警</field>
<field name="model">sale.order</field>
</record>
<record id="bussiness_sale_order_overdue" model="jikimo.message.bussiness.node">
<field name="name">销售订单已逾期</field>
<field name="model">sale.order</field>
</record>
<!-- <record id="bussiness_sale_order_overdue" model="jikimo.message.bussiness.node">-->
<!-- <field name="name">销售订单已逾期</field>-->
<!-- <field name="model">sale.order</field>-->
<!-- </record>-->
<record id="transfer_inventory" model="jikimo.message.bussiness.node">
<field name="name">调拨入库</field>
@@ -48,42 +49,62 @@
<field name="name">工单已下发通知</field>
<field name="model">mrp.workorder</field>
</record>
<!-- <record id="bussiness_mrp_workorder_pre_overdue_warning" model="jikimo.message.bussiness.node">-->
<!-- <field name="name">装夹预调工单逾期预警</field>-->
<!-- <field name="model">mrp.workorder</field>-->
<!-- </record>-->
<!-- <record id="bussiness_mrp_workorder_pre_overdue" model="jikimo.message.bussiness.node">-->
<!-- <field name="name">装夹预调工单已逾期</field>-->
<!-- <field name="model">mrp.workorder</field>-->
<!-- </record>-->
<!--发货调拨-->
<record id="production_completed_warehouse_reminder" model="jikimo.message.bussiness.node">
<field name="name">生产完工入库提醒</field>
<field name="model">mrp.production</field>
</record>
<record id="order_delivery_reminder" model="jikimo.message.bussiness.node">
<field name="name">订单发货提醒</field>
<field name="model">stock.picking</field>
</record>
<!-- <record id="bussiness_mrp_workorder_cnc_overdue_warning" model="jikimo.message.bussiness.node">-->
<!-- <field name="name">CNC工单逾期预警</field>-->
<!-- <field name="model">mrp.workorder</field>-->
<!-- </record>-->
<!-- <record id="bussiness_mrp_workorder_cnc_overdue" model="jikimo.message.bussiness.node">-->
<!-- <field name="name">CNC工单已逾期</field>-->
<!-- <field name="model">mrp.workorder</field>-->
<!-- </record>-->
<record id="bussiness_mrp_workorder_pre_overdue_warning" model="jikimo.message.bussiness.node">
<field name="name">装夹预调工单逾期预警</field>
<field name="model">mrp.workorder</field>
</record>
<record id="bussiness_mrp_workorder_pre_overdue" model="jikimo.message.bussiness.node">
<field name="name">装夹预调工单已逾期</field>
<field name="model">mrp.workorder</field>
</record>
<!-- <record id="bussiness_mrp_workorder_unclamp_overdue_warning" model="jikimo.message.bussiness.node">-->
<!-- <field name="name">解除装夹工单逾期预警</field>-->
<!-- <field name="model">mrp.workorder</field>-->
<!-- </record>-->
<record id="bussiness_mrp_workorder_cnc_overdue_warning" model="jikimo.message.bussiness.node">
<field name="name">CNC加工工单逾期预警</field>
<field name="model">mrp.workorder</field>
</record>
<record id="bussiness_mrp_workorder_cnc_overdue" model="jikimo.message.bussiness.node">
<field name="name">CNC加工工单已逾期</field>
<field name="model">mrp.workorder</field>
</record>
<!-- <record id="bussiness_mrp_workorder_unclamp_overdue" model="jikimo.message.bussiness.node">-->
<!-- <field name="name">解除装夹工单逾期</field>-->
<!-- <field name="model">mrp.workorder</field>-->
<!-- </record>-->
<record id="bussiness_mrp_workorder_unclamp_overdue_warning" model="jikimo.message.bussiness.node">
<field name="name">解除装夹工单逾期预警</field>
<field name="model">mrp.workorder</field>
</record>
<!-- <record id="bussiness_mrp_workorder_surface_overdue_warning" model="jikimo.message.bussiness.node">-->
<!-- <field name="name">表面工艺工单逾期预警</field>-->
<!-- <field name="model">mrp.workorder</field>-->
<!-- </record>-->
<record id="bussiness_mrp_workorder_unclamp_overdue" model="jikimo.message.bussiness.node">
<field name="name">解除装夹工单逾期</field>
<field name="model">mrp.workorder</field>
</record>
<!-- <record id="bussiness_mrp_workorder_surface_overdue" model="jikimo.message.bussiness.node">-->
<!-- <field name="name">表面工艺工单逾期</field>-->
<!-- <field name="model">mrp.workorder</field>-->
<!-- </record>-->
<record id="bussiness_mrp_workorder_surface_overdue_warning" model="jikimo.message.bussiness.node">
<field name="name">表面工艺工单逾期预警</field>
<field name="model">mrp.workorder</field>
</record>
<record id="bussiness_mrp_workorder_surface_overdue" model="jikimo.message.bussiness.node">
<field name="name">表面工艺工单已逾期</field>
<field name="model">mrp.workorder</field>
</record>
<record id="bussiness_quality_cnc_test" model="jikimo.message.bussiness.node">
<field name="name">待质量判定</field>
<field name="model">quality.cnc.test</field>
</record>
<record id="bussiness_maintenance_logs" model="jikimo.message.bussiness.node">
<field name="name">设备故障</field>
<field name="model">sf.maintenance.logs</field>
</record>
</data>
</odoo>

View File

@@ -1,24 +1,11 @@
<odoo>
<data noupdate="1">
<record model="ir.cron" id="ir_cron_sale_order_overdue_warning">
<field name="name">销售订单逾期预警</field>
<field name="name">检查销售订单是否已逾期预警和逾期</field>
<field name="model_id" ref="model_sale_order"/>
<field name="state">code</field>
<field name="code">model._overdue_warning_func()</field>
<field name="interval_number">1</field>
<field name="interval_type">minutes</field>
<field name="numbercall">-1</field>
<field name="doall" eval="False"/>
<field name="user_id" ref="base.user_root"/>
<field name="active" eval="True"/>
</record>
<record model="ir.cron" id="ir_cron_sale_order_overdue">
<field name="name">销售订单已逾期</field>
<field name="model_id" ref="model_sale_order"/>
<field name="state">code</field>
<field name="code">model._overdue_func()</field>
<field name="interval_number">1</field>
<field name="code">model._overdue_or_warning_func()</field>
<field name="interval_number">10</field>
<field name="interval_type">minutes</field>
<field name="numbercall">-1</field>
<field name="doall" eval="False"/>
@@ -27,11 +14,11 @@
</record>
<record model="ir.cron" id="ir_cron_mrp_workorder_overdue_warning">
<field name="name">装夹预调工单逾期预警</field>
<field name="name">检查工单是否已逾期预警和逾期</field>
<field name="model_id" ref="model_mrp_workorder"/>
<field name="state">code</field>
<field name="code">model._overdue_warning_func()</field>
<field name="interval_number">1</field>
<field name="code">model._overdue_or_warning_func()</field>
<field name="interval_number">10</field>
<field name="interval_type">minutes</field>
<field name="numbercall">-1</field>
<field name="doall" eval="False"/>
@@ -39,122 +26,17 @@
<field name="active" eval="True"/>
</record>
<record model="ir.cron" id="ir_cron_mrp_workorder_overdue">
<field name="name">工单已逾期</field>
<record model="ir.cron" id="ir_cron_mrp_workorder_recover_time_warning">
<field name="name">检查工单是否完成并恢复正常时效</field>
<field name="model_id" ref="model_mrp_workorder"/>
<field name="state">code</field>
<field name="code">model._overdue_func()</field>
<field name="interval_number">1</field>
<field name="code">model._recover_time_warning_func()</field>
<field name="interval_number">10</field>
<field name="interval_type">minutes</field>
<field name="numbercall">-1</field>
<field name="doall" eval="False"/>
<field name="user_id" ref="base.user_root"/>
<field name="active" eval="True"/>
</record>
<!-- -->
<!-- <record model="ir.cron" id="ir_cron_mrp_workorder_overdue_warning">-->
<!-- <field name="name">工单逾期预警</field>-->
<!-- <field name="model_id" ref="model_mrp_workorder"/>-->
<!-- <field name="state">code</field>-->
<!-- <field name="code">model._overdue_warning_func()</field>-->
<!-- <field name="interval_number">1</field>-->
<!-- <field name="interval_type">minutes</field>-->
<!-- <field name="numbercall">-1</field>-->
<!-- <field name="doall" eval="False"/>-->
<!-- <field name="user_id" ref="base.user_root"/>-->
<!-- <field name="active" eval="True"/>-->
<!-- </record>-->
<!-- <record model="ir.cron" id="ir_cron_mrp_workorder_pre_overdue">-->
<!-- <field name="name">工单已逾期</field>-->
<!-- <field name="model_id" ref="model_mrp_workorder"/>-->
<!-- <field name="state">code</field>-->
<!-- <field name="code">model._overdue_func()</field>-->
<!-- <field name="interval_number">1</field>-->
<!-- <field name="interval_type">minutes</field>-->
<!-- <field name="numbercall">-1</field>-->
<!-- <field name="doall" eval="False"/>-->
<!-- <field name="user_id" ref="base.user_root"/>-->
<!-- <field name="active" eval="True"/>-->
<!-- </record>-->
<!-- -->
<!-- <record model="ir.cron" id="ir_cron_mrp_workorder_pre_overdue_warning">-->
<!-- <field name="name">工单逾期预警</field>-->
<!-- <field name="model_id" ref="model_mrp_workorder"/>-->
<!-- <field name="state">code</field>-->
<!-- <field name="code">model._overdue_warning_func()</field>-->
<!-- <field name="interval_number">1</field>-->
<!-- <field name="interval_type">minutes</field>-->
<!-- <field name="numbercall">-1</field>-->
<!-- <field name="doall" eval="False"/>-->
<!-- <field name="user_id" ref="base.user_root"/>-->
<!-- <field name="active" eval="True"/>-->
<!-- </record>-->
<!-- <record model="ir.cron" id="ir_cron_mrp_workorder_pre_overdue">-->
<!-- <field name="name">工单已逾期</field>-->
<!-- <field name="model_id" ref="model_mrp_workorder"/>-->
<!-- <field name="state">code</field>-->
<!-- <field name="code">model._overdue_func()</field>-->
<!-- <field name="interval_number">1</field>-->
<!-- <field name="interval_type">minutes</field>-->
<!-- <field name="numbercall">-1</field>-->
<!-- <field name="doall" eval="False"/>-->
<!-- <field name="user_id" ref="base.user_root"/>-->
<!-- <field name="active" eval="True"/>-->
<!-- </record>-->
<!-- -->
<!-- -->
<!-- <record model="ir.cron" id="ir_cron_mrp_workorder_pre_overdue_warning">-->
<!-- <field name="name">工单逾期预警</field>-->
<!-- <field name="model_id" ref="model_mrp_workorder"/>-->
<!-- <field name="state">code</field>-->
<!-- <field name="code">model._overdue_warning_func()</field>-->
<!-- <field name="interval_number">1</field>-->
<!-- <field name="interval_type">minutes</field>-->
<!-- <field name="numbercall">-1</field>-->
<!-- <field name="doall" eval="False"/>-->
<!-- <field name="user_id" ref="base.user_root"/>-->
<!-- <field name="active" eval="True"/>-->
<!-- </record>-->
<!-- <record model="ir.cron" id="ir_cron_mrp_workorder_pre_overdue">-->
<!-- <field name="name">工单已逾期</field>-->
<!-- <field name="model_id" ref="model_mrp_workorder"/>-->
<!-- <field name="state">code</field>-->
<!-- <field name="code">model._overdue_func()</field>-->
<!-- <field name="interval_number">1</field>-->
<!-- <field name="interval_type">minutes</field>-->
<!-- <field name="numbercall">-1</field>-->
<!-- <field name="doall" eval="False"/>-->
<!-- <field name="user_id" ref="base.user_root"/>-->
<!-- <field name="active" eval="True"/>-->
<!-- </record>-->
<!-- -->
<!-- <record model="ir.cron" id="ir_cron_mrp_workorder_pre_overdue_warning">-->
<!-- <field name="name">工单逾期预警</field>-->
<!-- <field name="model_id" ref="model_mrp_workorder"/>-->
<!-- <field name="state">code</field>-->
<!-- <field name="code">model._overdue_warning_func()</field>-->
<!-- <field name="interval_number">1</field>-->
<!-- <field name="interval_type">minutes</field>-->
<!-- <field name="numbercall">-1</field>-->
<!-- <field name="doall" eval="False"/>-->
<!-- <field name="user_id" ref="base.user_root"/>-->
<!-- <field name="active" eval="True"/>-->
<!-- </record>-->
<!-- <record model="ir.cron" id="ir_cron_mrp_workorder_pre_overdue">-->
<!-- <field name="name">工单已逾期</field>-->
<!-- <field name="model_id" ref="model_mrp_workorder"/>-->
<!-- <field name="state">code</field>-->
<!-- <field name="code">model._overdue_func()</field>-->
<!-- <field name="interval_number">1</field>-->
<!-- <field name="interval_type">minutes</field>-->
<!-- <field name="numbercall">-1</field>-->
<!-- <field name="doall" eval="False"/>-->
<!-- <field name="user_id" ref="base.user_root"/>-->
<!-- <field name="active" eval="True"/>-->
<!-- </record>-->
</data>
</odoo>

View File

@@ -2,7 +2,7 @@
<odoo>
<data noupdate="1">
<record id="template_pending_order" model="jikimo.message.template">
<record id="template_pending_order" model="jikimo.message.template">
<field name="name">待接单</field>
<field name="model_id" ref="sale.model_sale_order"/>
<field name="model">sale.order</field>
@@ -16,7 +16,7 @@
</record>
<record id="template_to_be_confirm" model="jikimo.message.template">
<field name="name">确认接单</field>
<field name="name">待排程提醒</field>
<field name="model_id" ref="sale.model_sale_order"/>
<field name="model">sale.order</field>
<field name="bussiness_node_id" ref="bussiness_to_be_confirm"/>
@@ -27,6 +27,31 @@
事项:{{mrp_production_count}}个制造订单待计划排程
</field>
</record>
<record id="template_sale_order_overdue_warning" model="jikimo.message.template">
<field name="name">销售订单逾期预警</field>
<field name="model_id" ref="sale.model_sale_order"/>
<field name="model">sale.order</field>
<field name="bussiness_node_id" ref="bussiness_sale_order_overdue_warning"/>
<field name="msgtype">markdown</field>
<field name="urgency">normal</field>
<field name="content">### 销售订单逾期预警
事项:共有[{{warning_num}}]({{url}})个销售订单有逾期风险
</field>
</record>
<record id="template_sale_order_overdue" model="jikimo.message.template">
<field name="name">销售订单已逾期</field>
<field name="model_id" ref="sale.model_sale_order"/>
<field name="model">sale.order</field>
<field name="bussiness_node_id" ref="bussiness_sale_order_overdue"/>
<field name="msgtype">markdown</field>
<field name="urgency">urgent</field>
<field name="content">### 销售订单已逾期提醒
事项:共有[{{overdue_num}}]({{url}})个销售订单已逾期
</field>
</record>
<record id="template_material_purchase_remind" model="jikimo.message.template">
<field name="name">坯料采购提醒</field>
<field name="model_id" ref="purchase.model_purchase_order"/>
@@ -63,11 +88,107 @@
事项:共{{number}}个工单已下发,请查收知悉</field>
</record>
<record id="template_mrp_workorder_pre_overdue_warning" model="jikimo.message.template">
<field name="name">装夹预调工单逾期预警</field>
<field name="model_id" ref="mrp_workorder.model_mrp_workorder"/>
<field name="model">mrp.workorder</field>
<field name="bussiness_node_id" ref="bussiness_mrp_workorder_pre_overdue_warning"/>
<field name="msgtype">markdown</field>
<field name="send_type">timing</field>
<field name="urgency">normal</field>
<field name="content">### 工单逾期预警
事项:共有[{{warning_num}}]({{url}})工单有逾期风险</field>
</record>
<record id="template_mrp_workorder_pre_overdue" model="jikimo.message.template">
<field name="name">装夹预调工单已逾期</field>
<field name="model_id" ref="mrp_workorder.model_mrp_workorder"/>
<field name="model">mrp.workorder</field>
<field name="bussiness_node_id" ref="bussiness_mrp_workorder_pre_overdue"/>
<field name="msgtype">markdown</field>
<field name="send_type">timing</field>
<field name="urgency">normal</field>
<field name="content">### 工单已逾期提醒
事项:共有[{{overdue_num}}]({{url}})工单已逾期</field>
</record>
<record id="template_mrp_workorder_cnc_overdue_warning" model="jikimo.message.template">
<field name="name">CNC加工工单逾期预警</field>
<field name="model_id" ref="mrp_workorder.model_mrp_workorder"/>
<field name="model">mrp.workorder</field>
<field name="bussiness_node_id" ref="bussiness_mrp_workorder_cnc_overdue_warning"/>
<field name="msgtype">markdown</field>
<field name="send_type">timing</field>
<field name="urgency">normal</field>
<field name="content">### 工单逾期预警
事项:共有[{{warning_num}}]({{url}})工单有逾期风险</field>
</record>
<record id="template_mrp_workorder_cnc_overdue" model="jikimo.message.template">
<field name="name">CNC加工工单已逾期</field>
<field name="model_id" ref="mrp_workorder.model_mrp_workorder"/>
<field name="model">mrp.workorder</field>
<field name="bussiness_node_id" ref="bussiness_mrp_workorder_cnc_overdue"/>
<field name="msgtype">markdown</field>
<field name="send_type">timing</field>
<field name="urgency">normal</field>
<field name="content">### 工单已逾期提醒
事项:共有[{{overdue_num}}]({{url}})工单已逾期</field>
</record>
<record id="template_mrp_workorder_unclamp_overdue_warning" model="jikimo.message.template">
<field name="name">解除装夹工单逾期预警</field>
<field name="model_id" ref="mrp_workorder.model_mrp_workorder"/>
<field name="model">mrp.workorder</field>
<field name="bussiness_node_id" ref="bussiness_mrp_workorder_unclamp_overdue_warning"/>
<field name="msgtype">markdown</field>
<field name="send_type">timing</field>
<field name="urgency">normal</field>
<field name="content">### 工单逾期预警
事项:共有[{{warning_num}}]({{url}})工单有逾期风险</field>
</record>
<record id="template_mrp_workorder_unclamp_overdue" model="jikimo.message.template">
<field name="name">解除装夹工单已逾期</field>
<field name="model_id" ref="mrp_workorder.model_mrp_workorder"/>
<field name="model">mrp.workorder</field>
<field name="bussiness_node_id" ref="bussiness_mrp_workorder_unclamp_overdue"/>
<field name="msgtype">markdown</field>
<field name="send_type">timing</field>
<field name="urgency">normal</field>
<field name="content">### 工单已逾期提醒
事项:共有[{{overdue_num}}]({{url}})工单已逾期</field>
</record>
<record id="template_mrp_workorder_surface_overdue_warning" model="jikimo.message.template">
<field name="name">表面工艺工单逾期预警</field>
<field name="model_id" ref="mrp_workorder.model_mrp_workorder"/>
<field name="model">mrp.workorder</field>
<field name="bussiness_node_id" ref="bussiness_mrp_workorder_surface_overdue_warning"/>
<field name="msgtype">markdown</field>
<field name="send_type">timing</field>
<field name="urgency">normal</field>
<field name="content">### 工单逾期预警
事项:共有[{{warning_num}}]({{url}})工单有逾期风险</field>
</record>
<record id="template_mrp_workorder_surface_overdue" model="jikimo.message.template">
<field name="name">表面工艺工单已逾期</field>
<field name="model_id" ref="mrp_workorder.model_mrp_workorder"/>
<field name="model">mrp.workorder</field>
<field name="bussiness_node_id" ref="bussiness_mrp_workorder_surface_overdue"/>
<field name="msgtype">markdown</field>
<field name="send_type">timing</field>
<field name="urgency">normal</field>
<field name="content">### 工单已逾期提醒
事项:共有[{{overdue_num}}]({{url}})工单已逾期</field>
</record>
<record id="template_transfer_inventory_remind" model="jikimo.message.template">
<field name="menu_id" ref="stock.menu_stock_root"/>
<field name="action_id" ref="stock.action_picking_tree_ready"/>
<!-- <field name="menu_id" ref="stock.menu_stock_root"/>-->
<!-- <field name="action_id" ref="stock.action_picking_tree_ready"/>-->
<field name="name">调拨入库</field>
<field name="model_id" ref="stock.model_stock_picking"/>
<field name="model">stock.picking</field>
@@ -75,13 +196,13 @@
<field name="msgtype">markdown</field>
<field name="urgency">normal</field>
<field name="content">### 调拨入库通知:
单号:调拨入库单[{{name}}]({{request_url}})
单号:调拨入库单[{{name}}]({{transfer_inventory_special_url}})
事项:完成刀具物料上架入库</field>
</record>
<record id="template_tool_expired_remind" model="jikimo.message.template">
<field name="menu_id" ref="mrp.menu_mrp_root"/>
<field name="action_id" ref="sf_tool_management.sf_functional_tool_dismantle_view_act"/>
<!-- <field name="menu_id" ref="mrp.menu_mrp_root"/>-->
<!-- <field name="action_id" ref="sf_tool_management.sf_functional_tool_dismantle_view_act"/>-->
<field name="name">功能刀具寿命到期</field>
<field name="model_id" ref="sf_tool_management.model_sf_functional_tool_dismantle"/>
<field name="model">sf.functional.tool.dismantle</field>
@@ -89,13 +210,13 @@
<field name="msgtype">markdown</field>
<field name="urgency">normal</field>
<field name="content">### 功能刀具寿命到期提醒:
单号:拆解单[{{code}}]({{request_url}})
单号:拆解单[{{code}}]({{tool_expired_remind_special_url}})
事项:{{functional_tool_id.tool_name_id.name}}寿命已到期,需拆解</field>
</record>
<record id="template_tool_assembly_remind" model="jikimo.message.template">
<field name="menu_id" ref="mrp.menu_mrp_root"/>
<field name="action_id" ref="sf_tool_management.sf_functional_tool_assembly_view_act"/>
<!-- <field name="menu_id" ref="mrp.menu_mrp_root"/>-->
<!-- <field name="action_id" ref="sf_tool_management.sf_functional_tool_assembly_view_act"/>-->
<field name="name">功能刀具组装</field>
<field name="model_id" ref="sf_tool_management.model_sf_functional_tool_assembly"/>
<field name="model">sf.functional.tool.assembly</field>
@@ -103,8 +224,56 @@
<field name="msgtype">markdown</field>
<field name="urgency">normal</field>
<field name="content">### 功能刀具组装通知:
单号:组装任务单[{{name}}]({{request_url}})
单号:组装任务单[{{name}}]({{tool_assembly_special_url}})
事项:{{use_tool_time}}前完成组装</field>
</record>
<record id="template_production_completed_remind" model="jikimo.message.template">
<!-- <field name="menu_id" ref="mrp.menu_mrp_root"/>-->
<!-- <field name="action_id" ref="mrp.mrp_production_action"/>-->
<field name="name">生产完工入库提醒</field>
<field name="model_id" ref="mrp.model_mrp_production"/>
<field name="model">mrp.production</field>
<field name="bussiness_node_id" ref="production_completed_warehouse_reminder"/>
<field name="msgtype">markdown</field>
<field name="urgency">normal</field>
<field name="content">### 生产完工入库提醒:
单号:生产入库单[{{name}}]({{request_url}})
事项:销售订单{{sale_order_name}}已全部产出,请入库处理</field>
</record>
<record id="template_order_delivery_remind" model="jikimo.message.template">
<!-- <field name="menu_id" ref="stock.menu_stock_root"/>-->
<!-- <field name="action_id" ref="stock.action_picking_tree_ready"/>-->
<field name="name">订单发货提醒</field>
<field name="model_id" ref="stock.model_stock_picking"/>
<field name="model">stock.picking</field>
<field name="bussiness_node_id" ref="order_delivery_reminder"/>
<field name="msgtype">markdown</field>
<field name="urgency">normal</field>
<field name="content">### 订单发货提醒:
单号:发料出库单[{{name}}]({{request_url}})
事项:销售订单{{sale_order_name}}已全部产出并入库,请及时发货</field>
</record>
<record id="template_quality_cnc_test" model="jikimo.message.template">
<field name="name">待质量判定</field>
<field name="model_id" ref="sf_quality.model_quality_cnc_test"/>
<field name="model">quality.cnc.test</field>
<field name="bussiness_node_id" ref="bussiness_quality_cnc_test"/>
<field name="msgtype">markdown</field>
<field name="urgency">normal</field>
<field name="content">### 待质量判定提醒
事项:共有[{{judge_num}}]({{url}})个工单需判定质量结果</field>
</record>
<record id="template_maintenance_logs" model="jikimo.message.template">
<field name="name">设备故障</field>
<field name="model_id" ref="sf_maintenance.model_sf_maintenance_logs"/>
<field name="model">sf.maintenance.logs</field>
<field name="bussiness_node_id" ref="bussiness_maintenance_logs"/>
<field name="msgtype">markdown</field>
<field name="urgency">urgent</field>
<field name="content">### 设备故障及异常提醒:
机台号:[{{maintenance_equipment_id.name}}]({{url}})
事项:{{create_date}}故障报警</field>
</record>
</data>
</odoo>

View File

@@ -7,3 +7,6 @@ from . import sf_message_functional_tool_assembly
from . import sf_message_purchase
from . import sf_message_workorder
from . import sf_message_functional_tool_dismantle
from . import sf_message_mrp_production
from . import sf_message_quality_cnc_test
from . import sf_message_maintenance_logs

View File

@@ -13,3 +13,14 @@ class SFMessagefunctionalToolAssembly(models.Model):
if obj.loading_task_source == '0' and obj.assemble_status == '0':
obj.add_queue('功能刀具组装')
return result
def get_special_url(self,id,tmplate_name,special_name,model_id):
menu_id = 0
action_id = 0
if tmplate_name=='调拨入库' and special_name== 'tool_assembly_special_url':
menu_id = self.env.ref('mrp.menu_mrp_root').id
action_id = self.env.ref('sf_tool_management.sf_functional_tool_assembly_view_act').id
return super(SFMessagefunctionalToolAssembly, self).get_url(id, menu_id, action_id,model_id)
else:
return super(SFMessagefunctionalToolAssembly, self).get_special_url(id, tmplate_name, special_name, model_id)

View File

@@ -17,3 +17,13 @@ class SFMessagefunctionalToolDismantle(models.Model):
if obj.dismantle_cause in ['寿命到期报废', '崩刀报废'] and obj.state == '待拆解':
obj.add_queue('功能刀具寿命到期')
return result
def get_special_url(self,id,tmplate_name,special_name,model_id):
menu_id = 0
action_id = 0
if tmplate_name=='调拨入库' and special_name== 'tool_expired_remind_special_url':
menu_id = self.env.ref('mrp.menu_mrp_root').id
action_id = self.env.ref('sf_tool_management.sf_functional_tool_dismantle_view_act').id
return super(SFMessagefunctionalToolDismantle, self).get_url(id, menu_id, action_id,model_id)
else:
return super(SFMessagefunctionalToolDismantle, self).get_special_url(id, tmplate_name, special_name, model_id)

View File

@@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
from odoo import models, fields, api
class SFMessageMaintenanceLogs(models.Model):
_name = 'sf.maintenance.logs'
_inherit = ['sf.maintenance.logs', 'jikimo.message.dispatch']
@api.model_create_multi
def create(self, vals_list):
res = super(SFMessageMaintenanceLogs, self).create(vals_list)
for rec in res:
rec.add_queue('设备故障')
return res
def _get_message(self, message_queue_ids):
contents = super(SFMessageMaintenanceLogs, self)._get_message(message_queue_ids)
url = self.env['ir.config_parameter'].get_param('web.base.url')
action_id = self.env.ref('sf_maintenance.action_maintenance_logs').id
for index, content in enumerate(contents):
maintenance_logs_id = self.env['sf.maintenance.logs'].browse(message_queue_ids[index].res_id)
url = url + '/web#id=%s&view_type=form&action=%s' % (maintenance_logs_id.id, action_id)
contents[index] = content.replace('{{url}}', url)
return contents

View File

@@ -0,0 +1,57 @@
import logging
import re
from odoo import models, fields, api, _
from urllib.parse import urlencode
class SFMessageMrpProduction(models.Model):
_name = 'mrp.production'
_description = "制造订单"
_inherit = ['mrp.production', 'jikimo.message.dispatch']
@api.depends(
'move_raw_ids.state', 'move_raw_ids.quantity_done', 'move_finished_ids.state',
'workorder_ids.state', 'product_qty', 'qty_producing')
def _compute_state(self):
super(SFMessageMrpProduction, self)._compute_state()
for record in self:
if record.state in ['scrap', 'done']:
# 查询制造订单下的所有未完成的生产订单
mrp_production = record.env['mrp.production'].search(
[('origin', '=', record.origin), ('state', 'not in', ['scrap', 'done'])])
if not mrp_production:
mrp_production_queue = self.env["jikimo.message.queue"].search([('res_id', '=', record.id)])
if not mrp_production_queue:
record.add_queue('生产完工入库提醒')
# 获取发送消息内容
def _get_message(self, message_queue_ids):
contents = []
for message_queue_id in message_queue_ids:
if message_queue_id.message_template_id.name == '生产完工入库提醒':
content = message_queue_id.message_template_id.content
mrp_production = self.env['mrp.production'].search([('id', '=', int(message_queue_id.res_id))])
if mrp_production and len(mrp_production) > 0:
stock_picking_sfp = self.env['stock.picking'].search(
[('origin', '=', mrp_production.origin), ('picking_type_id.sequence_code', '=', 'SFP'),
('state', '=', 'assigned')], limit=1)
if stock_picking_sfp:
url = self.request_url(stock_picking_sfp.id)
content = content.replace('{{name}}', stock_picking_sfp.name).replace(
'{{sale_order_name}}', mrp_production.origin).replace('{{request_url}}', url)
contents.append(content)
logging.info('生产完工入库提醒: %s' % contents)
return contents
def request_url(self, id):
url = self.env['ir.config_parameter'].get_param('web.base.url')
action_id = self.env.ref('stock.action_picking_tree_all').id
menu_id = self.env['ir.model.data'].search([('name', '=', 'module_theme_treehouse')]).id
# 查询参数
params = {'id': id, 'menu_id': menu_id, 'action': action_id, 'model': 'mrp.production',
'view_type': 'form'}
# 拼接查询参数
query_string = urlencode(params)
# 拼接URL
full_url = url + "/web#" + query_string
return full_url

View File

@@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
import logging
from datetime import datetime, timedelta
from odoo import models, fields, api, _
class SFMessageQualityCncTest(models.Model):
_name = 'quality.cnc.test'
_inherit = ['quality.cnc.test', 'jikimo.message.dispatch']
def create(self, vals_list):
res = super(SFMessageQualityCncTest, self).create(vals_list)
if res:
try:
logging.info('add_queue res:%s' % res)
res.add_queue('待质量判定')
except Exception as e:
logging.info('add_queue error:%s' % e)
return res
# 继承并重写jikimo.message.dispatch的_get_message()
def _get_message(self, message_queue_ids):
contents = []
url = self.env['ir.config_parameter'].get_param('web.base.url')
i = 0
for item in message_queue_ids:
if item.message_template_id.bussiness_node_id.name == '待质量判定':
content = item.message_template_id.content
i += 1
if i >= 1:
action_id = self.env.ref('sf_quality.action_quality_cnc_test').id
url_with_id = f"{url}/web#view_type=list&action={action_id}"
content_template = content.replace('{{judge_num}}', str(i))
content_template = content_template.replace('{{url}}', url_with_id)
contents.append(content_template)
return contents

View File

@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
import logging
from datetime import datetime, timedelta
from odoo import models, fields, api, _
@@ -7,10 +8,12 @@ class SFMessageSale(models.Model):
_name = 'sale.order'
_inherit = ['sale.order', 'jikimo.message.dispatch']
@api.model_create_multi
def create(self, vals_list):
res = super(SFMessageSale, self).create(vals_list)
if res:
try:
logging.info('add_queue res:%s' % res)
res.add_queue('待接单')
except Exception as e:
logging.info('add_queue error:%s' % e)
@@ -41,16 +44,20 @@ class SFMessageSale(models.Model):
# 继承并重写jikimo.message.dispatch的_get_message()
def _get_message(self, message_queue_ids):
contents = []
bussiness_node = None
url = self.env['ir.config_parameter'].get_param('web.base.url')
current_time_strf = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
current_time = self.env['sf.sync.common'].sudo().get_add_time(current_time_strf)
current_time_datetime = datetime.strptime(current_time, '%Y-%m-%d %H:%M:%S')
time_range = timedelta(minutes=2)
i = 0
for item in message_queue_ids:
# 待接单的处理
if item.message_template_id.bussiness_node_id.name == '待接单':
content = super(SFMessageSale, self)._get_message(item)
action_id = self.env.ref('sale.action_quotations_with_onboarding').id
url = f"{url}/web#id={item.res_id}&view_type=form&action={action_id}"
content = content[0].replace('{{url}}', url)
url_with_id = f"{url}/web#id={item.res_id}&view_type=form&action={action_id}"
content = content[0].replace('{{url}}', url_with_id)
contents.append(content)
# 确认接单的处理
elif item.message_template_id.bussiness_node_id.name == '确认接单':
content = super(SFMessageSale, self)._get_message(item)
sale_order_line = self.env['sale.order.line'].search([('order_id', '=', int(item.res_id))])
@@ -58,16 +65,96 @@ class SFMessageSale(models.Model):
sale_order_line[
0].product_id.name
action_id = self.env.ref('sf_plan.sf_production_plan_action1').id
url = f"{url}/web#view_type=list&action={action_id}"
content = content[0].replace('{{product_id}}', product).replace('{{url}}', url)
url_with_id = f"{url}/web#view_type=list&action={action_id}"
content = content[0].replace('{{product_id}}', product).replace('{{url}}', url_with_id)
contents.append(content)
elif item.message_template_id.bussiness_node_id.name in ['销售订单逾期预警', '销售订单已逾期']:
bussiness_node = item.message_template_id.bussiness_node_id.name
for reminder_time in item.message_template_id.reminder_time_ids:
content = item.message_template_id.content
target_time = datetime.combine(current_time_datetime.date(), datetime.min.time()).replace(
hour=reminder_time.time_point,
minute=0,
second=0,
microsecond=0
)
logging.info(current_time)
logging.info(target_time)
if target_time - time_range <= current_time_datetime <= target_time + time_range:
search_condition = [
('delivery_warning', '=', 'warning')] if bussiness_node == '销售订单逾期预警' else [
('delivery_warning', '=', 'overdue')]
record = self.sudo().search(search_condition + [('id', '=', int(item.res_id))])
if record:
i += 1
if i >= 1:
action_id = self.env.ref('sale.action_orders').id
url_with_id = f"{url}/web#view_type=list&action={action_id}"
content_template = content.replace('{{url}}', url_with_id)
if bussiness_node == '销售订单逾期预警':
content = content_template.replace('{{warning_num}}', str(i))
elif bussiness_node == '销售订单已逾期':
content = content_template.replace('{{overdue_num}}', str(i))
contents.append(content)
return contents
# # 销售订单逾期预警
# def _overdue_warning_func(self):
# sale_order_
# return 1
#
# # 销售订单已逾期
# def _overdue_func(self):
# return 1
# # 销售订单逾期预警和已逾期
def _overdue_or_warning_func(self):
today = datetime.today().date()
deadline_check = today + timedelta(days=1)
logging.info(f"today: {today}, deadline_check: {deadline_check}")
sale_order = self.sudo().search(
[('state', 'in', ['sale']), ('deadline_of_delivery', '!=', False), ('delivery_status', '!=', 'full')])
for item in sale_order:
production = self.env['mrp.production'].search([('origin', '=', item.name)])
production_not_done = production.filtered(lambda p: p.state not in ['done', 'scrap', 'cancel'])
production_done_count = len(production.filtered(lambda p: p.state in ['done', 'scrap', 'cancel']))
if (len(production_not_done) >= 1 and len(production_not_done) != item.mrp_production_count) or len(
production_not_done) != production_done_count:
logging.info("-----不等于----")
logging.info(f"name: {item.name}")
logging.info(
f"production_not_done: {len(production_not_done)}, production_done_count: {production_done_count}")
logging.info(f"deadline_of_delivery: {item.deadline_of_delivery}")
if deadline_check == item.deadline_of_delivery and item.delivery_warning not in ['warning']:
item.delivery_warning = 'warning'
elif today >= item.deadline_of_delivery and item.delivery_warning not in ['overdue']:
item.delivery_warning = 'overdue'
elif production_done_count == item.mrp_production_count:
logging.info("-----等于----")
logging.info(f"name: {item.name}")
logging.info(
f"production_not_done: {len(production_not_done)}, production_done_count: {production_done_count}")
logging.info(f"deadline_of_delivery: {item.deadline_of_delivery}")
if item.delivery_status in ['pending', 'partial']:
if deadline_check == item.deadline_of_delivery and item.delivery_warning not in ['warning']:
item.delivery_warning = 'warning'
elif today >= item.deadline_of_delivery and item.delivery_warning not in ['overdue']:
item.delivery_warning = 'overdue'
else:
logging.info("-----1111111----")
logging.info(f"name: {item.name}")
logging.info(
f"production_not_done: {len(production_not_done)}, production_done_count: {production_done_count}")
continue
# 获取业务节点
business_node_ids = {
'warning': self.env.ref('sf_message.bussiness_sale_order_overdue_warning').id,
'overdue': self.env.ref('sf_message.bussiness_sale_order_overdue').id
}
overdue_orders = self.sudo().search([('delivery_warning', 'in', ['warning', 'overdue'])])
for wo in overdue_orders:
business_node_id = business_node_ids.get(wo.delivery_warning)
if business_node_id:
message_template = self.env["jikimo.message.template"].search([
("model", "=", self._name),
("bussiness_node_id", "=", business_node_id)
], limit=1)
sale_order_has = self.env['jikimo.message.queue'].search([
('res_id', '=', wo.id),
('message_status', '=', 'pending'),
('message_template_id', '=', message_template.id)
])
if not sale_order_has:
message_name = '销售订单逾期预警' if wo.delivery_warning == 'warning' else '销售订单已逾期'
wo.add_queue(message_name)

View File

@@ -1,3 +1,4 @@
import logging
import re
from odoo import models, fields, api, _
from urllib.parse import urlencode
@@ -23,6 +24,29 @@ class SFMessageStockPicking(models.Model):
if record.state == 'assigned' and record.check_in == 'PC':
record.add_queue('坯料发料提醒')
if record.picking_type_id.sequence_code == 'SFP' and record.state == 'done':
stock_picking_sfp = record.env['stock.picking'].search(
[('origin', '=', record.origin), ('state', '!=', 'done'),
('picking_type_id.sequence_code', '=', 'SFP')])
if not stock_picking_sfp:
stock_picking_send = self.env["jikimo.message.queue"].search([('res_id', '=', record.id)])
if not stock_picking_send:
record.add_queue('订单发货提醒')
def deal_stock_picking_sfp(self, message_queue_id): # 处理订单发货提醒
content = None
stock_picking = self.env['stock.picking'].search([('id', '=', int(message_queue_id.res_id))])
stock_picking_out = self.env['stock.picking'].search(
[('origin', '=', stock_picking.origin), ('state', '=', 'assigned'),
('picking_type_id.sequence_code', '=', 'OUT')])
if stock_picking_out and len(stock_picking_out) > 0:
content = message_queue_id.message_template_id.content
url = self.request_url1(stock_picking_out.id)
content = content.replace('{{name}}', stock_picking_out.name).replace(
'{{sale_order_name}}', stock_picking_out.origin).replace('{{request_url}}', url)
logging.info('订单发货提醒: %s' % content)
return content
def _get_message(self, message_queue_ids):
contents = []
product_id = []
@@ -46,10 +70,21 @@ class SFMessageStockPicking(models.Model):
'{{number}}', str(i)).replace('{{request_url}}', url)
product_id.append(mrp_production_info.product_id.id)
contents.append(content)
return contents
else:
res = super(SFMessageStockPicking, self)._get_message(message_queue_id)
return res
elif message_queue_id.message_template_id.name == '订单发货提醒':
content = self.deal_stock_picking_sfp(message_queue_id)
if content:
contents.append(content)
return contents
def get_special_url(self, id, tmplate_name, special_name, model_id):
menu_id = 0
action_id = 0
if tmplate_name == '调拨入库' and special_name == 'transfer_inventory_special_url':
menu_id = self.env.ref('stock.menu_stock_root').id
action_id = self.env.ref('stock.action_picking_tree_ready').id
return super(SFMessageStockPicking, self).get_url(id, menu_id, action_id, model_id)
else:
return super(SFMessageStockPicking, self).get_special_url(id, tmplate_name, special_name, model_id)
def request_url(self):
url = self.env['ir.config_parameter'].get_param('web.base.url')
@@ -63,3 +98,16 @@ class SFMessageStockPicking(models.Model):
# 拼接URL
full_url = url + "/web#" + query_string
return full_url
def request_url1(self, id):
url = self.env['ir.config_parameter'].get_param('web.base.url')
action_id = self.env.ref('stock.action_picking_tree_all').id
menu_id = self.env['ir.model.data'].search([('name', '=', 'module_theme_treehouse')]).id
# 查询参数
params = {'id': id, 'menu_id': menu_id, 'action': action_id, 'model': 'stock.picking',
'view_type': 'form'}
# 拼接查询参数
query_string = urlencode(params)
# 拼接URL
full_url = url + "/web#" + query_string
return full_url

View File

@@ -14,4 +14,6 @@ class SfMessageTemplate(models.Model):
res.append('sf.functional.tool.dismantle')
res.append('purchase.order')
res.append('mrp.workorder')
res.append('sf.maintenance.logs')
res.append('quality.cnc.test')
return res

View File

@@ -1,3 +1,4 @@
from datetime import datetime, timedelta
from odoo import models, fields, api, _
import logging, json
import requests
@@ -6,11 +7,12 @@ from urllib.parse import urlencode
_logger = logging.getLogger(__name__)
class SFMessageWork(models.Model):
_name = 'mrp.workorder'
_inherit = ['mrp.workorder', 'jikimo.message.dispatch']
@api.depends('production_availability', 'blocked_by_workorder_ids.state')
@api.depends('production_availability', 'blocked_by_workorder_ids.state', 'production_id.tool_state')
def _compute_state(self):
super(SFMessageWork, self)._compute_state()
for workorder in self:
@@ -23,6 +25,17 @@ class SFMessageWork(models.Model):
def _get_message(self, message_queue_ids):
contents = []
product_id = []
bussiness_node = None
url = self.env['ir.config_parameter'].get_param('web.base.url')
current_time_strf = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
current_time = self.env['sf.sync.common'].sudo().get_add_time(current_time_strf)
current_time_datetime = datetime.strptime(current_time, '%Y-%m-%d %H:%M:%S')
time_range = timedelta(minutes=2)
template_names = {
'预警': ['装夹预调工单逾期预警', 'CNC加工工单逾期预警', '解除装夹工单逾期预警', '表面工艺工单逾期预警'],
'已逾期': ['装夹预调工单已逾期', 'CNC加工工单已逾期', '解除装夹工单已逾期', '表面工艺工单已逾期']
}
i = 0
for message_queue_id in message_queue_ids:
if message_queue_id.message_template_id.name == '工单已下发通知':
content = message_queue_id.message_template_id.content
@@ -37,11 +50,42 @@ class SFMessageWork(models.Model):
'{{request_url}}', url)
product_id.append(mrp_workorder_line.product_id.id)
contents.append(content)
elif message_queue_id.message_template_id.name in template_names['预警'] + template_names['已逾期']:
item = message_queue_id.message_template_id
bussiness_node = item.bussiness_node_id.name
for reminder_time in item.reminder_time_ids:
content = item.content
target_time = datetime.combine(current_time_datetime.date(), datetime.min.time()).replace(
hour=reminder_time.time_point,
minute=0,
second=0,
microsecond=0
)
logging.info(current_time)
logging.info(target_time)
logging.info(target_time - time_range)
logging.info(target_time + time_range)
if target_time - time_range <= current_time_datetime <= target_time + time_range:
search_condition = [
('delivery_warning', '=', 'warning')] if bussiness_node in template_names['预警'] else [
('delivery_warning', '=', 'overdue')]
record = self.sudo().search(search_condition + [('id', '=', int(item.res_id))])
if record:
i += 1
if i >= 1:
action_id = self.env.ref('sf_message.mrp_workorder_action_notify').id
url_with_id = f"{url}/web#view_type=list&action={action_id}"
content_template = content.replace('{{url}}', url_with_id)
if bussiness_node in template_names['预警']:
content = content_template.replace('{{warning_num}}', str(i))
elif bussiness_node in template_names['已逾期']:
content = content_template.replace('{{overdue_num}}', str(i))
contents.append(content)
return contents
def request_url(self):
url = self.env['ir.config_parameter'].get_param('web.base.url')
action_id = self.env.ref('sf_manufacturing.mrp_workorder_action_tablet').id
action_id = self.env.ref('sf_message.mrp_workorder_action_notify').id
menu_id = self.env['ir.model.data'].search([('name', '=', 'module_stock_dropshipping')]).id
# 查询参数
params = {'menu_id': menu_id, 'action': action_id, 'model': 'mrp.workorder',
@@ -52,3 +96,64 @@ class SFMessageWork(models.Model):
full_url = url + "/web#" + query_string
return full_url
def _overdue_or_warning_func(self):
workorders = self.env['mrp.workorder'].search([("state", "in", ["ready", "progress", "to be detected"])])
grouped_workorders = {}
for workorder in workorders:
routing_type = workorder.routing_type
if routing_type not in grouped_workorders:
grouped_workorders[routing_type] = []
grouped_workorders[routing_type].append(workorder)
for routing_type, orders in grouped_workorders.items():
print(f"Routing Type: {routing_type}, Orders: {len(orders)}")
for item in orders:
if item.date_planned_finished:
current_time_str = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
current_time = self.env['sf.sync.common'].sudo().get_add_time(current_time_str)
current_time_datetime = datetime.strptime(current_time, '%Y-%m-%d %H:%M:%S')
date_planned_finished_str = self.env['sf.sync.common'].sudo().get_add_time(
item.date_planned_finished.strftime("%Y-%m-%d %H:%M:%S"))
date_planned_finished = datetime.strptime(date_planned_finished_str, '%Y-%m-%d %H:%M:%S')
twelve_hours_ago = current_time_datetime - timedelta(hours=12)
if current_time_datetime >= date_planned_finished and item.delivery_warning not in ['overdue']:
logging.info("------overdue-------")
logging.info(f"Workorder: {item.production_id.name}, Current Time: {current_time_datetime}, "
f"Planned Finish: {date_planned_finished}")
item.delivery_warning = 'overdue'
elif twelve_hours_ago <= current_time_datetime <= date_planned_finished and item.delivery_warning not in [
'warning']:
logging.info("------warning-------")
logging.info(f"Workorder: {item.production_id.name}, Current Time: {current_time_datetime}, "
f"Planned Finish: {date_planned_finished}")
item.delivery_warning = 'warning'
business_node_ids = {
'装夹预调': self.env.ref('sf_message.bussiness_mrp_workorder_pre_overdue_warning').id,
'CNC加工': self.env.ref('sf_message.bussiness_mrp_workorder_cnc_overdue_warning').id,
'解除装夹': self.env.ref('sf_message.bussiness_mrp_workorder_unclamp_overdue_warning').id,
'表面工艺': self.env.ref('sf_message.bussiness_mrp_workorder_surface_overdue_warning').id,
}
message_templates = {key: self.env["jikimo.message.template"].sudo().search([
("model", "=", self._name),
("bussiness_node_id", "=", business_node_ids[key])
]) for key in business_node_ids}
for item in orders:
if item.delivery_warning in ['overdue', 'warning']:
bussiness_node_id = business_node_ids.get(item.routing_type)
if bussiness_node_id and message_templates[item.routing_type]:
message_queue_ids = self.env["jikimo.message.queue"].sudo().search([
("message_template_id", "=", message_templates[item.routing_type].id),
("message_status", "=", "pending"),
("res_id", "=", item.id)
])
if not message_queue_ids:
overdue_message = '工单已逾期' if item.delivery_warning == 'overdue' else '工单逾期预警'
queue_method_name = f'add_queue'
# 构建参数列表其中包含item.routing_type和overdue_message
args = [f'{item.routing_type}{overdue_message}']
# 获取add_queue方法并调用它传入参数列表
getattr(item, queue_method_name)(*args)
def _recover_time_warning_func(self):
workorder_done = self.env['mrp.workorder'].search([("state", "in", ["done", "rework", "cancel"])])
workorder_overdue = workorder_done.filtered(lambda x: x.delivery_warning in ['overdue', 'warning'])
workorder_overdue.write({'delivery_warning': 'normal'})

View File

@@ -1,22 +1,28 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_jikimo_message_template_group_sale_salemanager,jikimo_message_template,model_jikimo_message_template,sf_base.group_sale_salemanager,1,1,1,0
access_jikimo_message_template_group_purchase,jikimo_message_template,model_jikimo_message_template,sf_base.group_purchase,1,1,1,0
access_jikimo_message_template_group_sf_stock_user,jikimo_message_template,model_jikimo_message_template,sf_base.group_sf_stock_user,1,1,1,0
access_jikimo_message_template_group_sf_order_user,jikimo_message_template,model_jikimo_message_template,sf_base.group_sf_order_user,1,1,1,0
access_jikimo_message_template_group_sf_tool_user,jikimo_message_template,model_jikimo_message_template,sf_base.group_sf_tool_user,1,1,1,0
access_jikimo_message_template_group_sale_salemanager,jikimo_message_template,jikimo_message_notify.model_jikimo_message_template,sf_base.group_sale_salemanager,1,1,1,0
access_jikimo_message_template_group_purchase,jikimo_message_template,jikimo_message_notify.model_jikimo_message_template,sf_base.group_purchase,1,1,1,0
access_jikimo_message_template_group_sf_stock_user,jikimo_message_template,jikimo_message_notify.model_jikimo_message_template,sf_base.group_sf_stock_user,1,1,1,0
access_jikimo_message_template_group_sf_order_user,jikimo_message_template,jikimo_message_notify.model_jikimo_message_template,sf_base.group_sf_order_user,1,1,1,0
access_jikimo_message_template_group_sf_tool_user,jikimo_message_template,jikimo_message_notify.model_jikimo_message_template,sf_base.group_sf_tool_user,1,1,1,0
access_jikimo_message_bussiness_node_group_sale_salemanager,jikimo_message_bussiness_node,model_jikimo_message_bussiness_node,sf_base.group_sale_salemanager,1,1,1,0
access_jikimo_message_bussiness_node_group_purchase,jikimo_message_bussiness_node,model_jikimo_message_bussiness_node,sf_base.group_purchase,1,1,1,0
access_jikimo_message_bussiness_node_group_sf_stock_user,jikimo_message_bussiness_node,model_jikimo_message_bussiness_node,sf_base.group_sf_stock_user,1,1,1,0
access_jikimo_message_bussiness_node_group_sf_order_user,jikimo_message_bussiness_node,model_jikimo_message_bussiness_node,sf_base.group_sf_order_user,1,1,1,0
access_jikimo_message_bussiness_node_group_sf_tool_user,jikimo_message_bussiness_node,model_jikimo_message_bussiness_node,sf_base.group_sf_tool_user,1,1,1,0
access_jikimo_message_bussiness_node_group_sale_salemanager,jikimo_message_bussiness_node,jikimo_message_notify.model_jikimo_message_bussiness_node,sf_base.group_sale_salemanager,1,1,1,0
access_jikimo_message_bussiness_node_group_purchase,jikimo_message_bussiness_node,jikimo_message_notify.model_jikimo_message_bussiness_node,sf_base.group_purchase,1,1,1,0
access_jikimo_message_bussiness_node_group_sf_stock_user,jikimo_message_bussiness_node,jikimo_message_notify.model_jikimo_message_bussiness_node,sf_base.group_sf_stock_user,1,1,1,0
access_jikimo_message_bussiness_node_group_sf_order_user,jikimo_message_bussiness_node,jikimo_message_notify.model_jikimo_message_bussiness_node,sf_base.group_sf_order_user,1,1,1,0
access_jikimo_message_bussiness_node_group_sf_tool_user,jikimo_message_bussiness_node,jikimo_message_notify.model_jikimo_message_bussiness_node,sf_base.group_sf_tool_user,1,1,1,0
access_jikimo_message_queue_group_sale_salemanager,jikimo_message_queue,model_jikimo_message_queue,sf_base.group_sale_salemanager,1,1,1,0
access_jikimo_message_queue_group_purchase,jikimo_message_queue,model_jikimo_message_queue,sf_base.group_purchase,1,1,1,0
access_jikimo_message_queue_group_sf_stock_user,jikimo_message_queue,model_jikimo_message_queue,sf_base.group_sf_stock_user,1,1,1,0
access_jikimo_message_queue_group_sf_order_user,jikimo_message_queue,model_jikimo_message_queue,sf_base.group_sf_order_user,1,1,1,0
access_jikimo_message_queue_group_sf_tool_user,jikimo_message_queue,model_jikimo_message_queue,sf_base.group_sf_tool_user,1,1,1,0
access_jikimo_message_queue_group_sale_salemanager,jikimo_message_queue,jikimo_message_notify.model_jikimo_message_queue,sf_base.group_sale_salemanager,1,1,1,0
access_jikimo_message_queue_group_purchase,jikimo_message_queue,jikimo_message_notify.model_jikimo_message_queue,sf_base.group_purchase,1,1,1,0
access_jikimo_message_queue_group_sf_stock_user,jikimo_message_queue,jikimo_message_notify.model_jikimo_message_queue,sf_base.group_sf_stock_user,1,1,1,0
access_jikimo_message_queue_group_sf_order_user,jikimo_message_queue,jikimo_message_notify.model_jikimo_message_queue,sf_base.group_sf_order_user,1,1,1,0
access_jikimo_message_queue_group_sf_tool_user,jikimo_message_queue,jikimo_message_notify.model_jikimo_message_queue,sf_base.group_sf_tool_user,1,1,1,0
access_jikimo_message_reminder_time_group_sale_salemanager,jikimo_message_reminder_time,jikimo_message_notify.model_jikimo_message_reminder_time,sf_base.group_sale_salemanager,1,1,1,0
access_jikimo_message_reminder_time_group_purchase,jikimo_message_reminder_time,jikimo_message_notify.model_jikimo_message_reminder_time,sf_base.group_purchase,1,1,1,0
access_jikimo_message_reminder_time_group_sf_stock_user,jikimo_message_reminder_time,jikimo_message_notify.model_jikimo_message_reminder_time,sf_base.group_sf_stock_user,1,1,1,0
access_jikimo_message_reminder_time_group_sf_order_user,jikimo_message_reminder_time,jikimo_message_notify.model_jikimo_message_reminder_time,sf_base.group_sf_order_user,1,1,1,0
access_jikimo_message_reminder_time_group_sf_tool_user,jikimo_message_reminder_time,jikimo_message_notify.model_jikimo_message_reminder_time,sf_base.group_sf_tool_user,1,1,1,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_jikimo_message_template_group_sale_salemanager jikimo_message_template model_jikimo_message_template jikimo_message_notify.model_jikimo_message_template sf_base.group_sale_salemanager 1 1 1 0
3 access_jikimo_message_template_group_purchase jikimo_message_template model_jikimo_message_template jikimo_message_notify.model_jikimo_message_template sf_base.group_purchase 1 1 1 0
4 access_jikimo_message_template_group_sf_stock_user jikimo_message_template model_jikimo_message_template jikimo_message_notify.model_jikimo_message_template sf_base.group_sf_stock_user 1 1 1 0
5 access_jikimo_message_template_group_sf_order_user jikimo_message_template model_jikimo_message_template jikimo_message_notify.model_jikimo_message_template sf_base.group_sf_order_user 1 1 1 0
6 access_jikimo_message_template_group_sf_tool_user jikimo_message_template model_jikimo_message_template jikimo_message_notify.model_jikimo_message_template sf_base.group_sf_tool_user 1 1 1 0
7 access_jikimo_message_bussiness_node_group_sale_salemanager jikimo_message_bussiness_node model_jikimo_message_bussiness_node jikimo_message_notify.model_jikimo_message_bussiness_node sf_base.group_sale_salemanager 1 1 1 0
8 access_jikimo_message_bussiness_node_group_purchase jikimo_message_bussiness_node model_jikimo_message_bussiness_node jikimo_message_notify.model_jikimo_message_bussiness_node sf_base.group_purchase 1 1 1 0
9 access_jikimo_message_bussiness_node_group_sf_stock_user jikimo_message_bussiness_node model_jikimo_message_bussiness_node jikimo_message_notify.model_jikimo_message_bussiness_node sf_base.group_sf_stock_user 1 1 1 0
10 access_jikimo_message_bussiness_node_group_sf_order_user jikimo_message_bussiness_node model_jikimo_message_bussiness_node jikimo_message_notify.model_jikimo_message_bussiness_node sf_base.group_sf_order_user 1 1 1 0
11 access_jikimo_message_bussiness_node_group_sf_tool_user jikimo_message_bussiness_node model_jikimo_message_bussiness_node jikimo_message_notify.model_jikimo_message_bussiness_node sf_base.group_sf_tool_user 1 1 1 0
12 access_jikimo_message_queue_group_sale_salemanager jikimo_message_queue model_jikimo_message_queue jikimo_message_notify.model_jikimo_message_queue sf_base.group_sale_salemanager 1 1 1 0
13 access_jikimo_message_queue_group_purchase jikimo_message_queue model_jikimo_message_queue jikimo_message_notify.model_jikimo_message_queue sf_base.group_purchase 1 1 1 0
14 access_jikimo_message_queue_group_sf_stock_user jikimo_message_queue model_jikimo_message_queue jikimo_message_notify.model_jikimo_message_queue sf_base.group_sf_stock_user 1 1 1 0
15 access_jikimo_message_queue_group_sf_order_user jikimo_message_queue model_jikimo_message_queue jikimo_message_notify.model_jikimo_message_queue sf_base.group_sf_order_user 1 1 1 0
16 access_jikimo_message_queue_group_sf_tool_user jikimo_message_queue model_jikimo_message_queue jikimo_message_notify.model_jikimo_message_queue sf_base.group_sf_tool_user 1 1 1 0
17 access_jikimo_message_reminder_time_group_sale_salemanager jikimo_message_reminder_time jikimo_message_notify.model_jikimo_message_reminder_time sf_base.group_sale_salemanager 1 1 1 0
18 access_jikimo_message_reminder_time_group_purchase jikimo_message_reminder_time jikimo_message_notify.model_jikimo_message_reminder_time sf_base.group_purchase 1 1 1 0
19 access_jikimo_message_reminder_time_group_sf_stock_user jikimo_message_reminder_time jikimo_message_notify.model_jikimo_message_reminder_time sf_base.group_sf_stock_user 1 1 1 0
20 access_jikimo_message_reminder_time_group_sf_order_user jikimo_message_reminder_time jikimo_message_notify.model_jikimo_message_reminder_time sf_base.group_sf_order_user 1 1 1 0
21 access_jikimo_message_reminder_time_group_sf_tool_user jikimo_message_reminder_time jikimo_message_notify.model_jikimo_message_reminder_time sf_base.group_sf_tool_user 1 1 1 0
22
23
24
25
26
27
28

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record model="ir.actions.act_window" id="mrp_workorder_action_notify">
<field name="name">工单</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">mrp.workorder</field>
<field name="view_mode">tree,form</field>
<field name="view_ids" eval="[(5, 0, 0),
(0, 0, {'view_mode': 'tree', 'view_id': ref('mrp.mrp_production_workorder_tree_editable_view')}) ]"/>
<!-- (0, 0, {'view_mode': 'kanban', 'view_id': ref('mrp.workcenter_line_kanban')})-->
<!-- <field name="target">fullscreen</field>-->
<field name="target">current</field>
<field name="domain">[('state', '!=', 'cancel'),('schedule_state', '=', '已排')]</field>
<field name="context">{'search_default_product': 1, 'search_default_workcenter_id':
active_id,'search_default_filter_order_warning':1,'search_default_filter_order_overdue':1,
'search_default_ready': 1, 'search_default_progress': 1}
</field>
<field name="help" type="html">
<p class="o_view_nocontent_workorder">
没有工单要做!
</p>
<p>
工作订单是作为制造订单的一部分执行的操作。
工序在物料清单中定义或直接添加到制造订单中。
</p>
<p>
使用工作台工作中心控制面板直接登记车间中的操作.
平板电脑为您的工人提供工作表,并允许他们报废产品,跟踪时间,
发起维护请求,执行质量测试等.
</p>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- © <2016> <top hy>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<odoo>
<data>
</data>
</odoo>

View File

@@ -1,76 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- © <2016> <top hy>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<odoo>
<data>
<record id="sf_message_template_view_form" model="ir.ui.view">
<field name="name">sf.message.template.view.form</field>
<field name="model">message.template</field>
<field name="arch" type="xml">
<form string="消息模板">
<sheet>
<div class="oe_title">
<label for="name"/>
<h1>
<field name="name" class="w-100" required="1"/>
</h1>
</div>
<group>
<!-- <field name="type"/>-->
<field name="notify_model_id"/>
<field name="content" widget="html" class="oe-bordered-editor"
options="{'style-inline': true, 'codeview': true, 'dynamic_placeholder': true}"/>
<field name="description"/>
<field name="msgtype"/>
<field name="notification_department_id"/>
<field name="notification_employee_ids" widget="many2many_tags"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="sf_message_template_view_tree" model="ir.ui.view">
<field name="name">sf.message.template.view.tree</field>
<field name="model">message.template</field>
<field name="arch" type="xml">
<tree string="消息模板">
<field name="name"/>
<!-- <field name="type"/>-->
<field name="content"/>
<field name="msgtype"/>
<field name="notification_department_id"/>
<field name="notification_employee_ids" widget="many2many_tags"/>
<field name="description"/>
</tree>
</field>
</record>
<record id="sf_message_template_search_view" model="ir.ui.view">
<field name="name">sf.message.template.search.view</field>
<field name="model">message.template</field>
<field name="arch" type="xml">
<search>
<field name="name" string="模糊搜索"
filter_domain="['|','|',('name','like',self),('description','like',self)]"/>
<field name="name"/>
<filter name="filter_active" string="已归档" domain="[('active','=',False)]"/>
</search>
</field>
</record>
<!--定义单证类型视图动作-->
<record id="sf_message_template_action" model="ir.actions.act_window">
<field name="name">消息模板</field>
<field name="res_model">message.template</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="sf_message_template_view_tree"/>
</record>
<menuitem id="msg_set_menu" name="消息设置" parent="base.menu_administration" sequence="1"/>
<menuitem id="sf_message_template_send_menu" name="消息模板" parent="msg_set_menu"
action="sf_message_template_action" sequence="1"/>
</data>
</odoo>

View File

@@ -3,11 +3,12 @@ import logging
import os
import json
import base64
from odoo import http
from odoo import http, fields, models
from odoo.http import request
from odoo.addons.sf_base.controllers.controllers import MultiInheritController
class Sf_Mrs_Connect(http.Controller):
class Sf_Mrs_Connect(http.Controller, MultiInheritController):
@http.route('/api/cnc_processing/create', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False,
cors="*")
@@ -25,7 +26,7 @@ class Sf_Mrs_Connect(http.Controller):
ret = json.loads(ret['result'])
logging.info('下发编程单:%s' % ret)
domain = [('programming_no', '=', ret['programming_no'])]
if ret['manufacturing_type'] == 'scrap':
if ret['manufacturing_type'] in ('scrap', 'invalid_tool_rework'):
domain += [('state', 'not in', ['done', 'scrap', 'cancel'])]
productions = request.env['mrp.production'].with_user(
request.env.ref("base.user_admin")).search(domain)
@@ -81,26 +82,40 @@ class Sf_Mrs_Connect(http.Controller):
if files_panel:
for file in files_panel:
file_extension = os.path.splitext(file)[1]
logging.info('file_extension:%s' % file_extension)
if file_extension.lower() == '.pdf':
panel_file_path = os.path.join(program_path_tmp_panel, file)
logging.info('panel_file_path:%s' % panel_file_path)
logging.info('更新工作指令:%s' % cnc_workorder)
cnc_workorder.write({'cnc_worksheet': base64.b64encode(open(panel_file_path, 'rb').read())})
logging.info('更新工作指令完成:%s' % cnc_workorder)
pre_workorder = productions.workorder_ids.filtered(
lambda ap: ap.routing_type == '装夹预调' and ap.state not in ['done', 'rework'
'cancel'] and ap.processing_panel == panel)
if pre_workorder:
logging.info('更新加工图纸:%s' % pre_workorder)
pre_workorder.write(
{'processing_drawing': base64.b64encode(open(panel_file_path, 'rb').read())})
logging.info('更新加工图纸完成:%s' % pre_workorder)
productions.write({'programming_state': '已编程', 'work_state': '已编程'})
logging.info('已更新制造订单编程状态:%s' % productions.ids)
res.update({
'production_ids': productions.ids
})
# 对制造订单所以面的cnc工单的程序用刀进行校验
try:
logging.info(f'已更新制造订单:{productions}')
productions.production_cnc_tool_checkout()
except Exception as e:
logging.info(f'对cnc工单的程序用刀进行校验报错{e}')
return json.JSONEncoder().encode(res)
return json.JSONEncoder().encode(res)
else:
res = {'status': 0, 'message': '该制造订单暂未开始'}
return json.JSONEncoder().encode(res)
except Exception as e:
res = {'status': -1, 'message': '系统解析失败'}
request.cr.rollback()
logging.info('get_cnc_processing_create error:%s' % e)
return json.JSONEncoder().encode(res)

View File

@@ -84,6 +84,8 @@ class ResConfigSettings(models.TransientModel):
_logger.info("同步刀具物料切削速度完成")
self.env['sf.feed.per.tooth'].sync_all_feed_per_tooth()
_logger.info("同步刀具物料每齿走刀量完成")
self.env['sf.machining.accuracy'].sync_machining_accuracy_all()
_logger.info("同步加工精度完成")
except Exception as e:
_logger.info("sf_all_sync error: %s" % e)

View File

@@ -74,6 +74,8 @@ class MrStaticResourceDataSync(models.Model):
_logger.info("同步刀具物料切削速度完成")
self.env['sf.feed.per.tooth'].sync_feed_per_tooth_yesterday()
_logger.info("同步刀具物料每齿走刀量完成")
self.env['sf.machining.accuracy'].sync_machining_accuracy_all()
_logger.info("同步加工精度完成")
except Exception as e:
traceback_error = traceback.format_exc()
logging.error("同步静态资源库失败:%s" % traceback_error)
@@ -3133,3 +3135,36 @@ class CuttingToolBasicParameters(models.Model):
})
else:
raise ValidationError("刀具物料基本参数认证未通过")
class MachiningAccuracySync(models.Model):
_inherit = 'sf.machining.accuracy'
_description = '加工精度'
url = '/api/machining_accuracy/list'
def sync_machining_accuracy_all(self):
config = self.env['res.config.settings'].get_values()
headers = Common.get_headers(self, config['token'], config['sf_secret_key'])
strUrl = config['sf_url'] + self.url
r = requests.post(strUrl, json={}, data=None, headers=headers)
r = r.json()
result = json.loads(r['result'])
_logger.info('加工精度:%s' % result)
if result['status'] == 1:
machining_accuracy_all_list = result['machining_accuracy_all_list']
# 获取同步的id集合
ids = [obj['id'] for obj in machining_accuracy_all_list]
self.env['sf.machining.accuracy'].sudo().search(
[('sync_id', 'not in', ids)]).unlink()
for time in machining_accuracy_all_list:
machining_accuracy = self.env['sf.machining.accuracy'].sudo().search(
[('sync_id', '=', time['id'])])
if machining_accuracy:
machining_accuracy.name = time['name']
machining_accuracy.standard_tolerance = time['standard_tolerance']
else:
self.env['sf.machining.accuracy'].sudo().create({
"sync_id": time['id'],
"name": time['name'],
"discount": time['discount'],
})

View File

@@ -75,7 +75,7 @@ class sf_production_plan(models.Model):
if self.date_planned_start:
self.date_planned_finished = self.date_planned_start + timedelta(hours=1)
#处理计划状态非待排程,计划结束时间为空的数据处理
# 处理计划状态非待排程,计划结束时间为空的数据处理
def deal_no_date_planned_finished(self):
plans = self.env['sf.production.plan'].search(
[('date_planned_finished', '=', False), ('state', 'in', ['processing', 'done', 'finished'])])
@@ -90,6 +90,7 @@ class sf_production_plan(models.Model):
for item in plans:
if item.date_planned_start:
item.order_deadline = item.date_planned_start + timedelta(days=7)
@api.model
def search_read(self, domain=None, fields=None, offset=0, limit=None, order=None):
@@ -226,29 +227,26 @@ class sf_production_plan(models.Model):
if not record.production_line_id:
raise ValidationError("未选择生产线")
else:
is_schedule = self.deal_processing_schedule(record.date_planned_start)
if not is_schedule:
raise ValidationError("排程失败")
workorder_id_list = record.production_id.workorder_ids.ids
if record.production_id:
if record.production_id.workorder_ids:
for item in record.production_id.workorder_ids:
if item.name == 'CNC加工':
item.date_planned_finished = datetime.now() + timedelta(days=100)
item.date_planned_start = self.date_planned_start if self.date_planned_start else datetime.now()
record.sudo().production_id.plan_start_processing_time = item.date_planned_start
item.date_planned_finished = item.date_planned_start + timedelta(
minutes=record.env['mrp.routing.workcenter'].sudo().search(
[('name', '=', 'CNC加工')]).time_cycle)
item.duration_expected = record.env['mrp.routing.workcenter'].sudo().search(
[('name', '=', 'CNC加工')]).time_cycle
record.calculate_plan_time_before(item, workorder_id_list)
record.calculate_plan_time_after(item, workorder_id_list)
record.date_planned_start, record.date_planned_finished = \
item.date_planned_start, item.date_planned_finished
if record.production_id.workorder_ids:
last_cnc_start = record.date_planned_start if record.date_planned_start else datetime.now()
for item in record.production_id.workorder_ids:
if item.name == 'CNC加工':
# 将同一个面的所有工单筛选出来
workorder_list = record.production_id.workorder_ids.filtered(lambda x: x.processing_panel == item.processing_panel)
routing_workcenter = record.env['mrp.routing.workcenter'].sudo().search(
[('name', '=', 'CNC加工')], limit=1)
# 设置一个小的开始时间
item.date_planned_start = datetime.now() - timedelta(days=100)
item.date_planned_finished = last_cnc_start + timedelta(
minutes=routing_workcenter.time_cycle)
item.date_planned_start = last_cnc_start
record.sudo().production_id.plan_start_processing_time = item.date_planned_start
item.duration_expected = routing_workcenter.time_cycle
pre_duration , next_duration = record.calculate_plan_time(item, workorder_list)
record.date_planned_finished = item.date_planned_finished
# 计算下一个cnc工单的开始时间
last_cnc_start = workorder_list[-1].date_planned_finished + timedelta(minutes=pre_duration)
record.state = 'done'
record.date_planned_finished = record.date_planned_start + timedelta(
minutes=60) if not record.date_planned_finished else record.date_planned_finished
# record.production_id.schedule_state = '已排'
record.sudo().production_id.schedule_state = '已排'
record.sudo().production_id.process_state = '待装夹'
@@ -281,54 +279,66 @@ class sf_production_plan(models.Model):
}
# 处理是否可排程
def deal_processing_schedule(self, date_planned_start):
for record in self:
workcenter_ids = record.production_line_id.mrp_workcenter_ids
if not workcenter_ids:
raise UserError('生产线没有配置工作中心')
production_lines = workcenter_ids.filtered(lambda b: "自动生产线" in b.name)
if not production_lines: # 判断是否配置了自动生产线
raise UserError('生产线没有配置自动生产线')
if date_planned_start < datetime.now(): # 判断计划开始时间是否小于当前时间
raise UserError('计划开始时间不能小于当前时间')
if all(not production_line.deal_with_workcenter_calendar(date_planned_start) for production_line in
production_lines): # 判断计划开始时间是否在配置的工作中心的工作日历内
raise UserError('当前计划开始时间不能预约排程,请在工作时间内排程')
if not production_lines.deal_available_default_capacity(date_planned_start): # 判断生产线是否可排程
raise UserError('当前计划开始时间不能预约排程,生产线今日没有可排程的资源')
if not production_lines.deal_available_single_machine_capacity(date_planned_start): # 判断生产线是否可排程
raise UserError('当前计划开始时间不能预约排程,生产线该时间段没有可排程的资源')
def deal_processing_schedule(self, date_planned_start,):
count = len(self)
workcenter_ids = self.production_line_id.mrp_workcenter_ids
if not workcenter_ids:
raise UserError('生产线没有配置工作中心')
production_lines = workcenter_ids.filtered(lambda b: "自动生产线" in b.name)
if not production_lines: # 判断是否配置了自动生产线
raise UserError('生产线没有配置自动生产线')
if date_planned_start < datetime.now(): # 判断计划开始时间是否小于当前时间
raise UserError('计划开始时间不能小于当前时间')
if all(not production_line.deal_with_workcenter_calendar(date_planned_start) for production_line in
production_lines): # 判断计划开始时间是否在配置的工作中心的工作日历内
raise UserError('当前计划开始时间不能预约排程,请在工作时间内排程')
if not production_lines.deal_available_default_capacity(date_planned_start): # 判断生产线是否可排程
raise UserError('当前计划开始时间不能预约排程,生产线今日没有可排程的资源')
if not production_lines.deal_available_single_machine_capacity(date_planned_start, count): # 判断生产线是否可排程
raise UserError('当前计划开始时间不能预约排程,生产线该时间段没有可排程的资源')
return True
def calculate_plan_time_before(self, item, workorder_id_list):
def calculate_plan_time(self, item, workorder_list):
"""
根据CNC工单的时间去计算之前的其他工单的开始结束时间
"""
sequence = workorder_id_list.index(item.id) - 1
# 计算CNC加工之前工单的开始结束时间
for i in range(1 if sequence == 0 else sequence):
current_workorder_id = (item.id - (i + 1))
current_workorder_obj = self.env['mrp.workorder'].sudo().search(
[('id', '=', current_workorder_id)])
old_workorder_obj = self.env['mrp.workorder'].sudo().search(
[('id', '=', (current_workorder_id + 1))])
work_order = self.env['mrp.workorder'].sudo().search(
[('production_id', '=', self.production_id.id), ('id', '=', current_workorder_id)])
work_order.date_planned_finished = datetime.now() + timedelta(days=100)
work_order.date_planned_start = old_workorder_obj.date_planned_start - timedelta(
minutes=self.env['mrp.routing.workcenter'].sudo().search(
[('name', '=', current_workorder_obj.name)]).time_cycle)
work_order.date_planned_finished = old_workorder_obj.date_planned_start
work_order.duration_expected = self.env['mrp.routing.workcenter'].sudo().search(
[('name', '=', current_workorder_obj.name)]).time_cycle
first_workorder = self.env['mrp.workorder'].sudo().search([('id', '=', workorder_id_list[0])])
second_workorder = self.env['mrp.workorder'].sudo().search([('id', '=', workorder_id_list[1])])
if second_workorder.date_planned_start < first_workorder.date_planned_finished:
item.date_planned_start += timedelta(minutes=60)
item.date_planned_finished += timedelta(minutes=60)
item.duration_expected = self.env['mrp.routing.workcenter'].sudo().search(
[('name', '=', 'CNC加工')]).time_cycle
self.calculate_plan_time_before(item, workorder_id_list)
item_position = 0
for index, workorder in enumerate(workorder_list):
if workorder.id == item.id:
item_position = index
break
routing_workcenters = self.env['mrp.routing.workcenter'].sudo().search([])
# 记录所有前序工序时长
previous_workorder_duration = 0
for i in range(item_position, -1, -1):
if i < 1:
break
current_workorder = workorder_list[i]
next_workorder = workorder_list[i - 1]
routing_workcenter = routing_workcenters.filtered(lambda x: x.name == next_workorder.name)[0]
# 设置一个小的开始时间
next_workorder.date_planned_start = datetime.now() - timedelta(days=100)
next_workorder.date_planned_finished = current_workorder.date_planned_start
next_workorder.date_planned_start = next_workorder.date_planned_finished - timedelta(
minutes=routing_workcenter.time_cycle)
next_workorder.duration_expected = routing_workcenter.time_cycle
previous_workorder_duration += routing_workcenter.time_cycle
# 记录所有后续工序时长
next_workorder_duration = 0
for i in range(item_position, len(workorder_list) - 1):
if i > len(workorder_list) - 1:
break
current_workorder = workorder_list[i]
next_workorder = workorder_list[i + 1]
routing_workcenter = routing_workcenters.filtered(lambda x: x.name == next_workorder.name)[0]
# 设置一个小的开始时间
next_workorder.date_planned_start = datetime.now() - timedelta(days=100)
next_workorder.date_planned_finished = current_workorder.date_planned_finished + timedelta(
minutes=routing_workcenter.time_cycle)
next_workorder.date_planned_start = current_workorder.date_planned_finished
next_workorder.duration_expected = routing_workcenter.time_cycle
next_workorder_duration += routing_workcenter.time_cycle
return previous_workorder_duration, next_workorder_duration
def calculate_plan_time_after(self, item, workorder_id_list):
"""

View File

@@ -31,20 +31,24 @@ class Action_Plan_All_Wizard(models.TransientModel):
# 确认排程按钮
def action_plan_all(self):
# 使用传递过来的计划ID
temp_plan_ids = self.plan_ids
self.plan_ids.production_line_id = self.production_line_id.id
self.plan_ids.date_planned_start = self.date_planned_start
# 在这里添加您的逻辑来处理这些ID
for plan in temp_plan_ids:
# 处理每个计划
# 比如更新计划状态、分配资源等
# 示例plan.state = 'scheduled'
print('处理计划:', plan.id)
# 拿到计划对象
plan_obj = self.env['sf.production.plan'].browse(plan.id)
plan_obj.production_line_id = self.production_line_id.id
plan.date_planned_start = self.date_planned_start
plan_obj.do_production_schedule()
# 判断能否排成
self.plan_ids.deal_processing_schedule(self.date_planned_start)
self.plan_ids.do_production_schedule()
# for plan in temp_plan_ids:
# # 处理每个计划
# # 比如更新计划状态、分配资源等
# # 示例plan.state = 'scheduled'
# print('处理计划:', plan.id)
# # 拿到计划对象
# plan_obj = self.env['sf.production.plan'].browse(plan.id)
# plan_obj.production_line_id = self.production_line_id.id
# plan.date_planned_start = self.date_planned_start
# plan_obj.do_production_schedule()
# plan_obj.state = 'done'
print('处理计划:', plan.id, '完成')
_logger.info('处理计划: %s 完成', self.plan_ids.ids)
# # 获取当前生产线
# production_line_id = self.production_line_id
@@ -71,4 +75,14 @@ class Action_Plan_All_Wizard(models.TransientModel):
# if all(production_order_plan_state == '已取消' for production_order_plan_state in production_order_plan_state_list):
# raise UserError('当前生产线的所有生产订单都已取消,请勿重复排程!')
# # 如果当前生产线的所有生产订单的排程状态都是已暂停,则报错
# if all(production_order_plan_state == '已暂停' for production_order_plan_state in production
# if all(production_order_plan_state == '已暂停' for production_order_plan_state in production_order_plan_state_list):
# raise UserError('当前生产线的所有生产订单都已暂停,请勿重复排程!')
# # 如果当前生产线的所有生产订单的排程状态都是已完成,则报错
# if all(production_order_plan_state == '已完成' for production_order_plan_state in production_order_plan_state_list):
# raise UserError('当前生产线的所有生产订单都已完成,请勿重复排程!')
# # 如果当前生产线的所有生产订单的排程状态都是已取消,则报错
# if all(production_order_plan_state == '已取消' for production_order_plan_state in production_order_plan_state_list):
# raise UserError('当前生产线的所有生产订单都已取消,请勿重复排程!')
# # 如果当前生产线的所有生产订单的排程状态都是已暂停,则报错
# if all(production_order_plan_state == '已暂停' for production_order_plan_state in production_order_plan_state_list):
# raise UserError('当前生产线的所有生产订单都已暂停,请勿重复排程!')

View File

@@ -13,10 +13,11 @@
'author': 'jikimo',
'website': 'https://sf.cs.jikimo.com',
# 此处依赖sf_manufacturing是因为我要重写其中的一个字段operation_id的string故需要sf_manufacturing先安装
'depends': ['quality_control'],
'depends': ['quality_control', 'web_widget_model_viewer', 'sf_manufacturing'],
'data': [
'security/ir.model.access.csv',
'views/view.xml'
'views/view.xml',
'views/quality_cnc_test_view.xml'
],
'assets': {

View File

@@ -3,3 +3,4 @@
from . import custom_quality
from . import quality
from . import quality_cnc_test

View File

@@ -0,0 +1,82 @@
# -*- coding: utf-8 -*-
from odoo import models, fields, api, _
from odoo.exceptions import UserError
class SfQualityCncTest(models.Model):
_name = 'quality.cnc.test'
_description = 'CNC加工质检'
name = fields.Char('单号', default=lambda self: self.env['ir.sequence'].next_by_code('quality.cnc.test'))
workorder_id = fields.Many2one('mrp.workorder')
production_id = fields.Many2one(related='workorder_id.production_id', string='制造订单')
product_id = fields.Many2one(related='workorder_id.product_id', string='产品')
model_file = fields.Binary(related='workorder_id.glb_file', string='加工模型')
processing_panel = fields.Char(related='workorder_id.processing_panel', string='加工面')
equipment_id = fields.Many2one(related='workorder_id.equipment_id', string='加工设备')
production_line_id = fields.Many2one(related='workorder_id.production_line_id',
string='生产线')
part_number = fields.Char(related='workorder_id.part_number', string='成品零件图号')
detection_report = fields.Binary(related='workorder_id.detection_report', readonly=True, string='检测报告')
state = fields.Selection([
('waiting', '待判定'),
('done', '已完成')], string='状态', default='waiting')
result = fields.Selection([
('pass', '合格'),
('fail', '不合格')], string='判定结果')
number = fields.Integer('数量', default=1)
test_results = fields.Selection([("合格", "合格"), ("返工", "返工"), ("报废", "报废")], string="检测结果")
reason = fields.Selection(
[("programming", "编程"), ("cutter", "刀具"), ("clamping", "装夹"), ("operate computer", "操机"),
("technology", "工艺"), ("customer redrawing", "客户改图")], string="原因")
detailed_reason = fields.Text('详细原因')
machining_drawings = fields.Binary('2D加工图纸', related='workorder_id.machining_drawings', readonly=True)
quality_standard = fields.Binary('质检标准', related='workorder_id.quality_standard', readonly=True)
def submit_pass(self):
if self.test_results in ['返工', '报废']:
raise UserError(_('请重新选择【判定结果】-【检测结果】'))
self.write({'result': 'pass', 'test_results': '合格', 'state': 'done'})
self.workorder_id.write({'test_results': self.test_results})
self.workorder_id.button_finish()
def submit_fail(self):
if not self.test_results:
raise UserError(_('请填写【判定结果】里的信息'))
if self.test_results == '合格':
raise UserError(_('请重新选择【判定结果】-【检测结果】'))
self.write({'result': 'fail', 'test_results': self.test_results, 'state': 'done'})
self.workorder_id.write(
{'test_results': self.test_results, 'reason': self.reason, 'detailed_reason': self.detailed_reason})
self.workorder_id.button_finish()
@api.onchange('test_results')
def _onchange_test_results(self):
if self.test_results == '合格':
self.reason = False
self.detailed_reason = False
class SfQualityWorkOrder(models.Model):
_inherit = 'mrp.workorder'
def button_finish(self):
super(SfQualityWorkOrder, self).button_finish()
if self.routing_type == 'CNC加工':
quality_cnc_test = self.env['quality.cnc.test'].search([('workorder_id', '=', self.id)])
if quality_cnc_test:
quality_cnc_test.write({'result': 'fail' if self.test_results in ['返工', '报废'] else 'pass',
'test_results': self.test_results, 'state': 'done',
'reason': self.reason,
'detailed_reason': self.detailed_reason,
'detection_report': self.detection_report})
def write(self, vals):
res = super(SfQualityWorkOrder, self).write(vals)
for item in self:
if item.state == 'to be detected':
quality_cnc_test = self.env['quality.cnc.test'].search([('workorder_id', '=', item.id)])
if not quality_cnc_test:
self.env['quality.cnc.test'].sudo().create({'workorder_id': item.id})
return res

View File

@@ -67,5 +67,11 @@ access_quality_alert_stage,quality.alert.stage,quality.model_quality_alert_stage
access_stock_move_group_quality,stock_move_group_quality,stock.model_stock_move,sf_base.group_quality,1,1,0,0
access_stock_move_group_quality_director,stock_move_group_quality_director,stock.model_stock_move,sf_base.group_quality_director,1,1,0,0
access_quality_cnc_test_group_quality,quality_cnc_test_group_quality,model_quality_cnc_test,sf_base.group_quality,1,1,0,0
access_quality_cnc_test_group_quality_director,quality_cnc_test_group_quality_director,model_quality_cnc_test,sf_base.group_quality_director,1,1,0,0
access_quality_cnc_test_group_sf_equipment_user,quality_cnc_test_group_sf_equipment_user,model_quality_cnc_test,sf_base.group_sf_equipment_user,1,1,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
67
68
69
70
71
72
73
74
75
76
77

View File

@@ -0,0 +1,195 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="sequence_quality_cnc_test" model="ir.sequence">
<field name="name">加工质检单编码规则</field>
<field name="code">quality.cnc.test</field>
<field name="prefix">QCT</field>
<field name="padding">5</field>
<field name="company_id" eval="False"/>
</record>
<record id="quality_cnc_test_view_tree" model="ir.ui.view">
<field name="name">quality.cnc.test.view.tree</field>
<field name="model">quality.cnc.test</field>
<field name="arch" type="xml">
<tree sample="1">
<field name="name"/>
<field name="production_id"/>
<field name="processing_panel"/>
<field name="product_id"/>
<field name="part_number"/>
<field name="number"/>
<field name="state" widget="badge"
decoration-success="state == 'done'"
decoration-warning="state == 'waiting'"/>
<field name="result" widget="badge"
decoration-success="result == 'pass'"
decoration-danger="result == 'fail'"/>
</tree>
</field>
</record>
<record model="ir.ui.view" id="quality_cnc_test_search">
<field name="name">search.quality.cnc.test</field>
<field name="model">quality.cnc.test</field>
<field name="arch" type="xml">
<search string="加工质检">
<filter name="filter_waiting" string="待判定" domain="[('state', '=', 'waiting')]"/>
<separator/>
<field name="production_id" string="制造订单"
filter_domain="[('production_id', 'ilike', self)]"/>
<field name="product_id" string="产品"
filter_domain="[('product_id', 'ilike', self)]"/>
<searchpanel>
<field name="state" icon="fa-filter" enable_counters="1"/>
<field name="result" icon="fa-filter" enable_counters="1"/>
</searchpanel>
</search>
</field>
</record>
<record id="action_quality_cnc_test" model="ir.actions.act_window">
<field name="name">加工质检</field>
<field name="res_model">quality.cnc.test</field>
<field name="view_mode">tree,form</field>
<field name="context">{ 'search_default_filter_waiting':1}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
暂无加工质检单
</p>
</field>
</record>
<record model="ir.ui.view" id="quality_cnc_test_view_form">
<field name="name">quality.cnc.test.form.</field>
<field name="model">quality.cnc.test</field>
<field name="arch" type="xml">
<form>
<header>
<button string="合格" type="object" name="submit_pass"
class="oe_highlight" confirm="是否确认提交?"
attrs="{'invisible': [('result','!=', False)]}"/>
<button string="不合格" type="object" name="submit_fail"
class="oe_highlight" confirm="是否确认提交?"
attrs="{'invisible': [('result','!=', False)]}"/>
<field name="state" widget="statusbar"/>
<field name="result" invisible="1"/>
</header>
<sheet>
<h2>
<field name="name" readonly="1"/>
</h2>
<group>
<group>
<field name="production_id"/>
<field name="product_id"/>
<field name="production_line_id"/>
<field name="equipment_id"/>
<field name="model_file" widget="Viewer3D"/>
</group>
<group>
<field name="part_number"/>
<field name="processing_panel"/>
</group>
</group>
<notebook>
<page string="检测报告">
<field name="detection_report" string="" widget="pdf_viewer"/>
</page>
<page string="判定结果">
<group>
<field name="test_results" attrs="{'readonly': [('state','=', 'done')]}"/>
<field name="reason"
attrs="{'readonly': [('state','=', 'done')],'required': [('test_results','in', ['返工','报废'])],'invisible': [('test_results','in', ['合格',False])]}"/>
<field name="detailed_reason"
attrs="{'readonly': [('state','=', 'done')],'required': [('reason','!=', False)],'invisible': [('test_results','in', ['合格',False])]}"/>
</group>
</page>
<page string="2D图纸">
<field name="machining_drawings" string="" widget="adaptive_viewer"/>
</page>
<page string="客户质量标准">
<field name="quality_standard" string="" widget="adaptive_viewer"/>
</page>
<page string="其他" attrs="{'invisible': [('state','=', 'waiting')]}">
<group>
<field name="write_uid" widget='many2one_avatar_user' string="判定人" readonly="1"/>
<field name="write_date" string="判定时间" readonly="1"/>
</group>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<record id="quality_cnc_test_view_kanban" model="ir.ui.view">
<field name="name">quality.cnc.test.view.kanban</field>
<field name="model">quality.cnc.test</field>
<field name="arch" type="xml">
<kanban sample="1" class="o_kanban_product_template">
<templates>
<t t-name="kanban-box">
<div class="oe_kanban_card oe_kanban_global_click">
<div class="oe_kanban_details">
<div class="o_kanban_record_top mb-0">
<div class="o_kanban_record_headings">
<strong class="o_kanban_record_title">
<field name="name"/>
</strong>
</div>
</div>
<div>
<div>
<field name="production_id"/>
</div>
<div>
<field name="processing_panel"/>
</div>
<div>
<field name="test_results"
widget="label_selection"
options="{'classes': {'合格': 'success', '返工': 'warning', '报废': 'danger'}}"/>
</div>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<menuitem
id="menu_quality_cnc_test"
name="加工质检"
action="action_quality_cnc_test"
sequence="21"
parent="quality_control.menu_quality_control"
/>
<record id="action_quality_cnc_test_kanban" model="ir.actions.act_window">
<field name="name">驾驶舱</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">quality.cnc.test</field>
<field name="view_mode">kanban,tree,form</field>
<field name="view_id" ref="quality_cnc_test_view_kanban"/>
<field name="search_view_id" ref="quality_cnc_test_search"/>
<field name="domain">[]</field>
<field name="context">{ 'search_default_filter_waiting':1}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
暂无加工质检单
</p>
</field>
</record>
<menuitem id="menu_quality_cnc_test_dashboard"
name="驾驶舱"
action="action_quality_cnc_test_kanban"
parent="quality_control.menu_quality_root"
sequence="5"/>
</odoo>

Some files were not shown because too many files have changed in this diff Show More