Compare commits

...

213 Commits

Author SHA1 Message Date
胡尧
76597f6ccb 在下发编程单时,如果已经排程,在修改工单起止时间时先设置大的结束时间,避免设置时间出错 2024-10-31 11:15:06 +08:00
管欢
d7779e969d Accept Merge Request #1483: (feature/weid_sync_update -> develop)
Merge Request: 用户创建员工同时修改用户的企微id

Created By: @管欢
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @管欢
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1483
2024-10-29 15:55:39 +08:00
guanhuan
9d28eccd1b 用户创建员工同时修改用户的企微id 2024-10-29 15:50:38 +08:00
管欢
27339afaae Accept Merge Request #1482: (feature/weid_sync_update -> develop)
Merge Request: 修改员工绑定用户同时修改用户的企微id

Created By: @管欢
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @管欢
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1482
2024-10-29 15:05:59 +08:00
guanhuan
8dc3f2698b 修改员工绑定用户同时修改用户的企微id 2024-10-29 14:50:00 +08:00
马广威
4fd7ad8d03 Accept Merge Request #1481: (feature/制造功能优化 -> develop)
Merge Request: rfid手动输入推送

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1481?initial=true
2024-10-29 14:30:06 +08:00
mgw
3bc33fe2fc Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2024-10-29 14:28:44 +08:00
mgw
c21319a127 rfid手动输入推送 2024-10-29 14:28:24 +08:00
管欢
02e21a8fde Accept Merge Request #1480: (feature/weid_sync_update -> develop)
Merge Request: 修改和新增员工时根据邮箱获取企微id

Created By: @管欢
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @管欢
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1480
2024-10-29 11:10:47 +08:00
管欢
2cf578de65 Accept Merge Request #1479: (feature/message_update -> 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/1479
2024-10-29 09:02:03 +08:00
guanhuan
9665cdfc84 发送消息添加权限 2024-10-29 08:58:33 +08:00
胡尧
bef7376827 Accept Merge Request #1478: (feature/plan_slow -> develop)
Merge Request: 增加日志

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1478?initial=true
2024-10-28 17:43:21 +08:00
胡尧
e73e9d6960 增加日志 2024-10-28 17:42:44 +08:00
胡尧
892f5d0e70 Accept Merge Request #1477: (feature/plan_slow -> develop)
Merge Request: 增加销售订单确认日志

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1477?initial=true
2024-10-28 17:26:58 +08:00
胡尧
61339da204 增加销售订单确认日志 2024-10-28 17:26:27 +08:00
胡尧
25db392864 Accept Merge Request #1476: (feature/plan_slow -> develop)
Merge Request: 增加销售订单确认日志

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1476?initial=true
2024-10-28 17:23:00 +08:00
胡尧
745fd429c2 增加销售订单确认日志 2024-10-28 17:21:51 +08:00
胡尧
5c59a27a81 增加采购总监消息推送权限 2024-10-28 16:30:46 +08:00
管欢
9bac3675f6 Accept Merge Request #1475: (feature/message_update -> 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/1475
2024-10-28 11:54:04 +08:00
guanhuan
b4fbbd48fb 精度显示修改 2024-10-28 11:46:36 +08:00
guanhuan
3559d67c05 精度显示修改 2024-10-28 11:43:10 +08:00
禹翔辉
816623b1fe Accept Merge Request #1474: (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/1474
2024-10-28 11:00:03 +08:00
yuxianghui
91b913a7bd Merge branch 'feature/维保请求优化' into feature/工单优化_返工 2024-10-28 10:58:04 +08:00
yuxianghui
ba8393a8c7 返工操作时工单状态优化 2024-10-28 10:55:18 +08:00
管欢
06d061165b Accept Merge Request #1473: (feature/message_update -> 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/1473
2024-10-28 10:30:02 +08:00
guanhuan
18a7dbbff9 辅助文件上传 2024-10-28 10:21:33 +08:00
胡尧
dc545e6d49 Accept Merge Request #1472: (feature/plan_slow -> develop)
Merge Request: 修改排程逻辑

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1472?initial=true
2024-10-28 09:45:24 +08:00
胡尧
1467dbf88c 修改排程逻辑 2024-10-28 09:44:52 +08:00
胡尧
e9caf78b81 Accept Merge Request #1471: (feature/plan_slow -> develop)
Merge Request: 修复未编程的制造订单排程问题

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1471?initial=true
2024-10-28 09:43:42 +08:00
胡尧
aa1353cf99 修改排程逻辑 2024-10-28 09:38:50 +08:00
管欢
14d49f2944 Accept Merge Request #1469: (feature/message_update -> 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/1469
2024-10-25 17:41:02 +08:00
杨金灵
8560069b19 Accept Merge Request #1470: (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/1470
2024-10-25 17:24:07 +08:00
jinling.yang
8dc23a638f 去掉注释 2024-10-25 17:21:45 +08:00
guanhuan
5363557faf 快速订单创建报错 2024-10-25 16:36:54 +08:00
杨金灵
3c026004f3 Accept Merge Request #1468: (feature/修复CNC工单消息提醒跳转 -> 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/1468
2024-10-25 15:42:56 +08:00
jinling.yang
651c8f266b 修复CNC工单消息提醒跳转 2024-10-25 15:41:23 +08:00
杨金灵
a3bfbe66c4 Accept Merge Request #1467: (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/1467
2024-10-25 15:18:25 +08:00
jinling.yang
563e40adc6 修复工单链接跳转 2024-10-25 15:15:11 +08:00
jinling.yang
f88a784a87 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-10-25 14:58:44 +08:00
廖丹龙
01df5e86cd Accept Merge Request #1466: (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/1466
2024-10-25 14:42:12 +08:00
管欢
41f853b6c9 Accept Merge Request #1465: (feature/message_update -> 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/1465
2024-10-25 14:27:06 +08:00
liaodanlong
906a0ea767 采购按钮位置修改 2024-10-25 14:25:47 +08:00
jinling.yang
6162c731f2 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-10-25 14:11:56 +08:00
guanhuan
4f1d518ef3 加工精度修改 2024-10-25 14:02:37 +08:00
liaodanlong
06eaebd098 产品类别过滤缺陷 2024-10-25 14:02:37 +08:00
liaodanlong
8578a9a538 Merge remote-tracking branch 'origin/feature/machining_accuracy_sync' into feature/machining_accuracy_sync 2024-10-25 14:01:52 +08:00
liaodanlong
b9039ef466 刀具标准库page样式问题 2024-10-25 14:01:38 +08:00
杨金灵
a97f581c99 Accept Merge Request #1464: (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/1464?initial=true
2024-10-25 13:52:15 +08:00
jinling.yang
036179ec4d Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/工单消息提醒添加已排过滤 2024-10-25 13:50:28 +08:00
jinling.yang
d33188dedf Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-10-25 13:50:07 +08:00
jinling.yang
7033f95273 工单消息提醒添加已排过滤 2024-10-25 13:49:55 +08:00
管欢
00689d76cc Accept Merge Request #1463: (feature/message_update -> develop)
Merge Request: 工单下发url调整,加工精度取值调整,2D加工图纸和质检标准位置调整

Created By: @管欢
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @管欢
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1463
2024-10-25 13:38:25 +08:00
guanhuan
86d97ef331 2D加工图纸和质检标准位置调整 2024-10-25 11:55:43 +08:00
jinling.yang
05a183f46f Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-10-25 11:36:12 +08:00
jinling.yang
50959d2e9c Merge branch 'feature/修复消息提醒时区问题' into develop 2024-10-25 11:35:56 +08:00
guanhuan
519ce0d5bb 工单下发调整 2024-10-25 11:29:13 +08:00
杨金灵
f06842cdcb Accept Merge Request #1461: (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/1461
2024-10-25 11:28:41 +08:00
jinling.yang
d5a1caad10 还原代码 2024-10-25 11:26:18 +08:00
jinling.yang
e51fff4120 修复消息提醒时区问题 2024-10-25 11:25:37 +08:00
guanhuan
2fe8e0e356 工单下发调整 2024-10-25 11:11:24 +08:00
guanhuan
bbe2e5792f Merge branch 'refs/heads/develop' into feature/machining_accuracy_sync 2024-10-25 09:58:45 +08:00
jinling.yang
a1a520ec39 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/修复消息提醒时区问题 2024-10-25 09:55:12 +08:00
jinling.yang
1b714a9962 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-10-25 09:54:51 +08:00
jinling.yang
9d133096c7 修复消息提醒时区问题 2024-10-25 09:54:37 +08:00
guanhuan
69f3453134 加工精度修改 2024-10-25 09:48:57 +08:00
管欢
ab10271b4d Accept Merge Request #1460: (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/1460
2024-10-25 09:04:47 +08:00
guanhuan
516a98e102 Merge remote-tracking branch 'origin/feature/machining_accuracy_sync' into feature/machining_accuracy_sync 2024-10-25 08:58:34 +08:00
guanhuan
390213881a 加工精度修改 2024-10-25 08:58:05 +08:00
jinling.yang
ac2eba4734 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-10-24 17:39:36 +08:00
jinling.yang
b64893436b Merge branch 'feature/修复销售订单和工单消息提醒' into develop 2024-10-24 17:36:00 +08:00
杨金灵
ee148239d2 Accept Merge Request #1459: (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/1459
2024-10-24 17:35:44 +08:00
jinling.yang
4cc03aee9b 优化模版 2024-10-24 17:35:21 +08:00
jinling.yang
31a703952c 修复销售订单和工单消息提醒 2024-10-24 17:32:40 +08:00
guanhuan
69c63f708d 修改和新增员工时根据邮箱获取企微id 2024-10-24 17:06:31 +08:00
jinling.yang
ae08c5b56e Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-10-24 16:55:43 +08:00
jinling.yang
dc76dcdc2f Merge branch 'feature/修复销售订单完成时效' into develop 2024-10-24 16:52:08 +08:00
杨金灵
6a040d16ea Accept Merge Request #1458: (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/1458?initial=true
2024-10-24 16:51:52 +08:00
jinling.yang
30e8d04b70 添加销售订单是否完成并恢复正常时效定时器 2024-10-24 16:50:27 +08:00
jinling.yang
2b3375ad41 修复销售订单完成时效 2024-10-24 16:40:25 +08:00
jinling.yang
8a059a5520 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-10-24 16:20:38 +08:00
jinling.yang
49a2f02b54 Merge branch 'feature/修复工单提醒' into develop 2024-10-24 16:20:09 +08:00
禹翔辉
ef92f24d35 Accept Merge Request #1456: (feature/维保请求优化 -> develop)
Merge Request: 1、添加维保请求的相关权限;2、优化维保请求tree视图、form视图和搜索视图;

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1456
2024-10-24 16:18:08 +08:00
杨金灵
0207914592 Accept Merge Request #1457: (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/1457
2024-10-24 16:17:54 +08:00
jinling.yang
5776c97744 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/修复工单提醒 2024-10-24 16:16:11 +08:00
jinling.yang
180cdf2a08 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-10-24 16:15:51 +08:00
jinling.yang
47720948ff 修复工单提醒 2024-10-24 16:15:30 +08:00
yuxianghui
7814a2b622 Merge branch 'feature/工单状态优化' into feature/维保请求优化 2024-10-24 16:12:57 +08:00
yuxianghui
06981fb894 1、添加维保请求的相关权限;2、优化维保请求tree视图、form视图和搜索视图; 2024-10-24 16:12:09 +08:00
马广威
19dbd9901d Accept Merge Request #1455: (feature/制造功能优化 -> develop)
Merge Request: 处理工单的组件不存在时报错的问题

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1455?initial=true
2024-10-24 16:06:50 +08:00
mgw
4985b0a85d Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2024-10-24 16:05:03 +08:00
mgw
39f99d6ce7 处理工单的组件不存在时报错的问题 2024-10-24 16:04:38 +08:00
马广威
c8f25ea4b3 Accept Merge Request #1454: (feature/制造功能优化 -> develop)
Merge Request: 增加对Enter的判断

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1454?initial=true
2024-10-24 15:51:11 +08:00
mgw
cab9e08066 增加对Enter的判断 2024-10-24 15:50:32 +08:00
马广威
2b83f82989 Accept Merge Request #1453: (feature/制造功能优化 -> develop)
Merge Request: 将扫描rfid绑定并开启装夹工单写成widget形式

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1453
2024-10-24 15:34:06 +08:00
mgw
598e8fee9c Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2024-10-24 15:32:41 +08:00
mgw
6f3a788101 将扫描rfid绑定并开启装夹工单写成widget形式 2024-10-24 15:32:15 +08:00
jinling.yang
30ff349b37 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-10-24 15:17:59 +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
jinling.yang
4018797384 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-10-24 14:57:01 +08:00
guanhuan
f557cb8d10 零件图纸,质检标准显示位置修改 2024-10-24 14:55:36 +08:00
jinling.yang
a1efde6ef9 Merge branch 'feature/修复销售订单逾期过期' into develop 2024-10-24 14:41:10 +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
胡尧
3f84972bfd 删除多余代码 2024-10-24 13:57:26 +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
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
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
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
75 changed files with 1769 additions and 366 deletions

View File

@@ -21,8 +21,8 @@ class WorkorderExceptionConroller(http.Controller):
try:
res = {'Succeed': True, 'ErrorCode': 0, 'Error': ''}
datas = request.httprequest.data
ret = json.loads(datas)['Datas']
if not ret.get('RfidCode') or not ret.get('ErrorType'):
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)
@@ -38,7 +38,7 @@ class WorkorderExceptionConroller(http.Controller):
# 创建工单异常记录,关联工单
request.env['jikimo.workorder.exception'].sudo().create({
'workorder_id': workorder.id,
'exception_code': ret.get('ErrorType'),
'exception_code': ret.get('coding'),
'exception_content': ret.get('Error', '')
})

View File

@@ -1,2 +1,5 @@
"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
"access_jikimo_workorder_exception_group_quality","access.jikimo.workorder.exception.group_quality","model_jikimo_workorder_exception","sf_base.group_quality",1,1,1,0
"access_jikimo_workorder_exception_group_quality_director","access.jikimo.workorder.exception.group_quality_director","model_jikimo_workorder_exception","sf_base.group_quality_director",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
3 access_jikimo_workorder_exception_group_quality access.jikimo.workorder.exception.group_quality model_jikimo_workorder_exception sf_base.group_quality 1 1 1 0
4 access_jikimo_workorder_exception_group_quality_director access.jikimo.workorder.exception.group_quality_director model_jikimo_workorder_exception sf_base.group_quality_director 1 1 1 0
5

View File

@@ -10,7 +10,7 @@
<field name="urgency">urgent</field>
<field name="content">### 生产线无功能刀具提醒
单号:工单[{{workorder_id.production_id.name}}]({{url}})
原因:生产线无加工程序用的{{function_tool_name}}名称功能刀具</field>
原因:生产线无加工程序用的功能刀具</field>
</record>
<record id="template_no_position_data" model="jikimo.message.template">
<field name="name">工单无定位数据提醒</field>
@@ -19,7 +19,7 @@
<field name="bussiness_node_id" ref="bussiness_no_position_data"/>
<field name="msgtype">markdown</field>
<field name="urgency">urgent</field>
<field name="content">### 生产线无功能刀具提醒
<field name="content">### 工单无定位数据提醒
单号:工单[{{workorder_id.production_id.name}}]({{url}})
原因:无装夹定位测量数据</field>
</record>

View File

@@ -34,7 +34,7 @@ class JikimoWorkorderException(models.Model):
rec.add_queue('无定位数据')
elif rec.exception_code == 'YC0004':
# 无FTP文件调用cloud接口
data = {'name': rec.workorder_id.programming_no, 'exception_code': 'YC0004'}
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'

View File

@@ -14,12 +14,25 @@ class TestJikimoWorkorderExceptionNotify(TestJikimoWorkorderExceptionNotifyCommo
('model', '=', 'jikimo.workorder.exception')
]))
self.assertTrue(self.env['jikimo.message.template'].search([
('name', '=', '加工失败'),
('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程序'
})
def test_create_message_queue(self):
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',
@@ -43,7 +56,45 @@ class TestJikimoWorkorderExceptionNotify(TestJikimoWorkorderExceptionNotifyCommo
('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({

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,32 @@
# -*- 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)
@api.model
def search(self, args, limit=100, offset=0, order=None, count=False):
# 添加过滤条件,确保只返回名称不在指定列表中的记录
args += [('name', 'not in', ['Saleable', 'Expenses', 'Deliveries'])]
# 调用父类的 search 方法
return super(ProductCategory, self).search(args, limit=limit, offset=offset, order=order, count=count)

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

@@ -0,0 +1,125 @@
// 获取表格数据
function getDomData() {
const dom = $('div[name=cutting_speed_ids]')
if (!dom.length) return
const table = dom.find('.o_list_table')
const thead = table.children('thead')
const tbody = table.children('tbody')
const tbody_child = tbody.children()
const hideTheadDom = thead.find('[data-name=process_capability]')
hideTheadDom.hide().next().hide()
hideTheadDom.before('<th customTh>精加工</th><th customTh>粗加工</th>')
tbody_child.each(function () {
const dom = $(this).children('[name=process_capability]')
if(!dom.length) return
dom.css('cssText', 'display: none!important').next().css('cssText', 'display: none!important')
const isCu = dom.text() == '粗加工' // 是否粗加工
const v = dom.next().text() // 切削速度
dom.after(`<td customSpeed="1" name="process_capability" is="精加工" val="${ v }">${!isCu ? v : ''}</td><td customSpeed="1" name="process_capability" is="粗加工" val="${ v }">${isCu ? v : ''}</td>`)
setListenClick()
})
return;
handleTbody(tbody, newTableData, ΦList, table)
}
// 监听点击
function setListenClick() {
$(document).click(function (e) {
if ($(e.target).attr('customSpeed')) {
const orginV = $('[customInput=1]').children('input').val()
$('[customInput=1]').parent().html(orginV)
const v = $(e.target).attr('val')
const is = $(e.target).attr('is')
$(e.target).html('')
const input = $('<div customInput="1" is="' + is + '" class="o_field_widget o_field_char"><input class="o_input" type="text" autocomplete="off" maxlength="20"></div>')
input.children('input').val(v)
$(e.target).append(input)
input.children('input').focus()
input.children('input').select()
} else if ($(e.target).attr('customInput')) {
} else {
const orginV = $('[customInput=1]').children('input').val()
$('[customInput=1]').parent().html(orginV)
const v = $(e.target).attr('val')
}
})
$(document).off('change') // 防止重复绑定
$(document).on('change', '[customInput] input', async function () {
$(this).parents('td').attr('val', $(this).val())
$(this).parents('td').siblings('[customspeed]').attr('val', $(this).val())
var eve1 = new Event('change')
var eve2 = new Event('input')
var eve3 = new Event('click')
let patchSpeedDom = $(this).parents('td').siblings('[name=cutting_speed]')
let patchProcessDom = $(this).parents('td').siblings('[name=process_capability]')
$(this).parents('td').siblings('[customspeed]').text('') // 清空其他加工类型的数据
await timeOut(500)
patchProcessDom[0].dispatchEvent(eve3)
await timeOut(200)
const processVal = $(this).parent().attr('is')
patchProcessDom.find('select').val(`"${processVal}"`) // 设置源select的val为“加工类型 is”、
patchProcessDom.attr("data-tooltip", `${processVal}`)
patchProcessDom.find('select')[0].dispatchEvent(eve1)
patchSpeedDom[0].dispatchEvent(eve3)
await timeOut(200)
patchSpeedDom.find('input').val($(this).val())
await timeOut(50)
patchSpeedDom.find('input')[0].dispatchEvent(eve2)
patchSpeedDom.find('input')[0].dispatchEvent(eve1)
})
$(document).off('blur') // 防止重复绑定
$(document).on('blur', '[customInput] input', async function () {
if(!$(this).length) return
$(this).parents('td').siblings('[customspeed]').text('') // 清空其他加工类型的数据
let patchProcessDom = $(this).parents('td').siblings('[name=process_capability]')
try {
patchProcessDom[0].dispatchEvent(new Event('click'))
const processVal = $(this).parent().attr('is')
patchProcessDom.find('select').val(`"${processVal}"`) // 设置源select的val为“加工类型 is”、
patchProcessDom.attr("data-tooltip", `${processVal}`)
patchProcessDom.find('select')[0].dispatchEvent(new Event('change'))
} catch {
}
})
}
function timeOut(time) {
return new Promise(resolve => {
setTimeout(() => {
resolve()
}, time)
})
}
function listenAdd() {
$('td.o_field_x2many_list_row_add a').click(async function () {
await timeOut(500)
const tr = $('.o_list_table').children('tbody').children('tr').eq(-2)
if(tr.children('td').eq(2).text() == '') {
const dom = tr.children('[name=process_capability]')
if(!dom.length) return
dom.css('cssText', 'display: none!important').next().css('cssText', 'display: none!important')
const isCu = dom.text() == '粗加工' // 是否粗加工
const v = dom.next().text() // 切削速度
dom.after(`<td customSpeed="1" name="process_capability" is="精加工" val="${ v }">${!isCu ? v : ''}</td><td customSpeed="1" name="process_capability" is="粗加工" val="${ v }">${isCu ? v : ''}</td>`)
}
})
}
function listenSave() {
$('.o_form_button_save').click( async function () {
await timeOut(1000)
if($(this).parent().next().length) return
$('th[customTh],td[cusomSpeed]').remove()
getDomData()
})
}
listenAdd()
listenSave()
getDomData()

View File

@@ -0,0 +1,47 @@
// 因为表格可以拖动设置宽度所以需要用js设置初始宽度
function setBasicParamTableWidth() {
// const _100px = 'th[data-name="cutting_blade_length"],th[data-name="cutting_blade_length"],th[data-name="name"],th[data-name="tip_handling_size"],th[data-name="cutting_depth_max"],th[data-name="diameter_inner_circle"],th[data-name="diameter_mounting_hole" ],th[data-name="radius_tip_re" ],th[data-name="is_chip_breaker"],th[data-name="chip_breaker_type_code"],th[data-name="blade_profile"]'
// const _65px = 'th[data-name="edge_angle"],th[data-name="relief_angle"],[data-name="total_length"],th[data-name="length"],th[data-name="thickness"],th[data-name="blade_number"]'
// const _80px = 'th[data-name="arbor_diameter"],th[data-name="head_height"],th[data-name="head_width"],th[data-name="head_length"],th[data-name="blade_diameter"],th[data-name="blade_length"] ,th[data-name="neck_length"] ,th[data-name="neck_diameter"] ,th[data-name="shank_diameter"],th[data-name="shank_length"],th[data-name="tip_diameter"],th[data-name="knife_tip_taper"],th[data-name="blade_helix_angle"] ,th[data-name="blade_width"],th[data-name="blade_depth"]'
// const _50px = 'th[data-name="pitch"],th[data-name="width"],th[data-name="height"]'
const basicParamDom = $('.fixTableCss')
// const basicParamDom_100px = basicParamDom.find(_100px) // 四字以上
// const basicParamDom_65px = basicParamDom.find(_65px) // 大概三个字加单位
// const basicParamDom_80px = basicParamDom.find(_80px) // 大概四个字加单位
// const basicParamDom_50px= basicParamDom.find(_50px) // 大概两个字加单位
//
// basicParamDom_100px.css({'width': '100px', 'max-width': 'auto', ',min-width': 'auto'})
// basicParamDom_65px.css({'width': '65px', 'max-width': 'auto', ',min-width': 'auto'})
// basicParamDom_80px.css({'width': '80px', 'max-width': 'auto', ',min-width': 'auto'})
// basicParamDom_50px.css({'width': '50px', 'max-width': 'auto', ',min-width': 'auto'})
let dom = []
try {
dom = basicParamDom.find('table').find('thead').children().children()
} catch {
dom = []
}
if (!dom) return
dom.each(function () {
if ($(this).hasClass('row_no') >= 0) { // 序号列
// 不设置 通过css设置
}
const text = $(this).text().split('(')
if ($(this).attr('data-name') == 'name' || text[0].length > 4) {
$(this).width('100px')
} else if(text[0].length == 4){
$(this).width('80px')
} else if(text[0].length == 3){
$(this).width('65px')
} else if(text[0].length == 2){
$(this).width('50px')
}
})
}
setBasicParamTableWidth()
$('.o_field_many2one_selection').on('click', $('#cutting_tool_material_id + ul'), function () {
setTimeout(setBasicParamTableWidth, 500)
})

View File

@@ -0,0 +1,159 @@
// 获取表格数据
function getDomData() {
const dom = $('#updateTable').prev()
if (!dom.length) return
const table = $('#updateTable').prev().find('.o_list_table')
const customTable = table.clone()
customTable.addClass('customTable')
table.parent().append(customTable)
table.hide()
const thead = customTable.children('thead')
const tbody = customTable.children('tbody')
const tableData = []
const tbody_child = tbody.children()
const tbody_child_len = tbody_child.length
for (let v = 0; v < tbody_child_len; v++) { // 将数据取出来到tableData里面
const data = tbody_child[v].innerText.split('\t')
// console.log('dom data',data)
const [index, deep, name, Φ, value] = data
tableData.push({index, deep, name, Φ, value})
}
const ΦList = [...new Set(tableData.map(_ => _.name))] // ΦList去重
const newTableData = {}
tableData.forEach(_ => {
const key = _.deep + '|' + _.Φ
!newTableData[key] ? newTableData[key] = {i: _.index} : '';
if (_.Φ) { // 去除没有Φ的脏数据
newTableData[key]['Φ' + _.Φ] = _.value
newTableData[key]['Φ' + _.Φ + 'i'] = _.index
}
})
// console.log('qwdh',tableData, ΦList, newTableData);
if (ΦList.filter(_ => _).length == 0) return;
handleThead(thead, ΦList)
handleTbody(tbody, newTableData, ΦList, table)
}
// 重新设置表头、
function handleThead(thead, ΦList) {
const dom = thead.children().eq(0).children()
const len = dom.length
dom.eq(0).attr('rowspan', 2)
dom.eq(1).attr('rowspan', 2)
len == 5 ? dom.eq(2).attr('rowspan', 2) : ''
dom.eq(-2).attr('colspan', ΦList.length)
dom.eq(-1).remove()
const tr = document.createElement('tr')
for (let v = 0; v < ΦList.length; v++) {
const th = document.createElement('th')
th.innerText = 'Φ' + ΦList[v]
tr.append(th)
}
thead.append(tr)
}
// 重新设置表格
function handleTbody(tbody, newTableData, ΦList, table) {
console.log(newTableData)
tbody.html('')
let i = 0
const data = Object.keys(newTableData)
// data.sort((a, b) => {
// a = a.split('=')[1].split('%')[0]
// b = b.split('=')[1].split('%')[0]
// return a - b
// })
// console.log('wqoqw ',ΦList)
data.forEach(_ => {
i++
const tr = $('<tr class="o_data_row"></tr>')
const td0 = $('<td></td>')
td0.text(i)
tr.append(td0)
const lit = _.split('|')
//
const td1 = $('<td></td>')
const td2 = $('<td></td>')
td1.text(lit[0])
td2.text(lit[1] || '')
tr.append(td1)
tr.append(td2)
ΦList.forEach(Φ => {
const td = $('<td class="o_data_cell cursor-pointer o_field_cell o_list_char"></td>')
td.text(newTableData[_]['Φ' + Φ])
td.attr('col', newTableData[_]['Φ' + Φ + 'i'])
td.attr('val', newTableData[_]['Φ' + Φ])
td.attr('coustomTd', 1)
tr.append(td)
})
// // for (let j = 0; j < ΦList.length; j++) {
// // const td = document.createElement('td')
// // td.innerText = newTableData[data[v]][_]
// // th.append(td)
// // }
tbody.append(tr)
})
// $(document).click(function (e) {
// if ($(e.target).attr('coustomTd')) {
// const orginV = $('[coustomInput=1]').children('input').val()
// $('[coustomInput=1]').parent().html(orginV)
// const v = $(e.target).attr('val')
// console.log($(e.target));
// $(e.target).html('')
// const input = $('<div coustomInput="1" name="feed_per_tooth" class="o_field_widget o_field_char"><input class="o_input" type="text" autocomplete="off" maxlength="20"></div>')
// input.children('input').val(v)
// $(e.target).append(input)
// input.children('input').focus()
// input.children('input').select()
// } else if ($(e.target).attr('coustomInput')) {
//
// } else {
// const orginV = $('[coustomInput=1]').children('input').val()
// $('[coustomInput=1]').parent().html(orginV)
// const v = $(e.target).attr('val')
// }
// })
// $(document).off('change') // 防止重复绑定
// $(document).on('change', '[coustomInput] input', function () {
// $(this).parents('td').attr('val', $(this).val());
// var eve1 = new Event('change');
// var eve2 = new Event('input');
// var eve3 = new Event('click');
// const i = $(this).parents('td').attr('col');
// let patchDom = table.find('tbody').children('tr').eq(i - 1);
//
// if (patchDom.length === 0) {
// console.error('No such row found');
// return;
// }
//
// patchDom = patchDom.children().eq(-1);
//
// setTimeout(() => {
// if (patchDom.length === 0) {
// console.error('No such cell found');
// return;
// }
// patchDom[0].dispatchEvent(eve3); // Simulate click event
//
// setTimeout(() => {
// patchDom = patchDom.find('input');
// if (patchDom.length === 0) {
// console.error('No input found in the target cell');
// return;
// }
// patchDom.val($(this).val());
// patchDom[0].dispatchEvent(eve2);
// patchDom[0].dispatchEvent(eve1);
// }, 200);
// }, 500);
// });
}
getDomData()

View File

@@ -0,0 +1,52 @@
.o_list_renderer .o_list_table tbody > tr > td:not(.o_list_record_selector):not(.o_handle_cell):not(.o_list_button):not(.o_list_record_remove) {
white-space: nowrap !important;
}
.text-truncate {
overflow: unset !important;
text-overflow: unset !important;
white-space: unset !important;
}
// 设置表格不超出页面宽度
.o_form_view .o_field_widget .o_list_renderer {
width: calc(100% - 64px) !important;
margin:0 auto;
overflow: auto;
}
// 表格针对处理
.fixTableCss {
text-align: center;
.o_list_number_th,.o_list_number {
text-align: center!important;
}
.ui-sortable {
tr > td:first-child {
padding: 0!important;
}
}
.row_no {
padding: 0!important;;
width: 35px!important;
}
th[data-name="total_length"],th[data-name="length"],th[data-name="thickness"] {
.flex-row-reverse {
span {
text-align: center;
}
}
}
}
// 其他不能用js处理的表格
.otherTableFix {
th[data-name="cutting_tool_material_id"] {
width: 100px!important;
}
th[data-name="ramping_angle_max"],th[data-name="ramping_angle_min"] {
width: 200px!important;
}
}

View File

@@ -614,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

@@ -360,6 +360,7 @@
<field name="cooling_jacket"/>
</tree>
</field>
<script src="/sf_base/static/js/setTableWidth.js?time=3"></script>
</page>
<page string="切削速度Vc"
attrs="{'invisible': [('cutting_tool_type', 'not in', ('整体式刀具','刀片'))]}">
@@ -380,6 +381,9 @@
<field name="cutting_speed"/>
</tree>
</field>
<script src="/sf_base/static/js/customTable.js?time=3"></script>
<script src="/sf_base/static/js/setTableWidth.js?time=3"></script>
</page>
<page string="每齿走刀量fz"
attrs="{'invisible': [('cutting_tool_type', 'not in', ('整体式刀具','刀片'))]}">
@@ -392,6 +396,8 @@
<field name="feed_per_tooth"/>
</tree>
</field>
<div id="updateTable"></div>
<script src="/sf_base/static/js/updateTable.js?time=3"></script>
<field name="feed_per_tooth_ids_3"
attrs="{'invisible': [('cutting_tool_type', 'not in', ('刀片'))]}">
<tree editable="bottom" class="center" create="0" delete="0">

View File

@@ -36,6 +36,7 @@ class StatusChange(models.Model):
# 使用super()来调用原始方法(在本例中为'sale.order'模型的'action_confirm'方法)
try:
res = super(StatusChange, self).action_confirm()
logging.info('原生方法返回结果:%s' % res)
# 原有方法执行后进行额外的操作如调用外部API
process_start_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
config = self.env['res.config.settings'].get_values()
@@ -61,6 +62,7 @@ class StatusChange(models.Model):
traceback_error = traceback.format_exc()
logging.error("工厂加工同步订单状态失败:%s " % traceback_error)
raise UserError(e)
logging.info('最终返回值:%s' % res)
return res
def action_cancel(self):

View File

@@ -9,7 +9,7 @@
""",
'category': 'sf',
'website': 'https://www.sf.jikimo.com',
'depends': ['sf_sale', 'sf_dlm', 'sf_manufacturing'],
'depends': ['sf_sale', 'sf_dlm', 'sf_manufacturing','jikimo_attachment_viewer'],
'data': [
'data/stock_data.xml',
'views/product_template_management_view.xml',

View File

@@ -16,8 +16,6 @@
<field name='is_bfm' invisible="1"/>
<field name='categ_type' invisible="1"/>
<field name='part_number' attrs="{'invisible': [('categ_type', '!=', '成品')]}"/>
<!-- <field name='machining_drawings' attrs="{'invisible': [('categ_type', '!=', '成品')]}" widget="image"/>-->
<!-- <field name='quality_standard' attrs="{'invisible': [('categ_type', '!=', '成品')]}"/>-->
<field name='manual_quotation' attrs="{'invisible':[('upload_model_file', '=', [])]}"/>
<field name="upload_model_file"
widget="many2many_binary"
@@ -111,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

@@ -1272,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):
"""辅助函数:将查询结果转为字典"""
@@ -1332,6 +1333,35 @@ 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,
@@ -1343,6 +1373,9 @@ class Sf_Dashboard_Connect(http.Controller):
'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

@@ -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>

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):
@@ -122,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='检修时长')
@@ -129,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:
@@ -591,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
@@ -624,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
@@ -635,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
@@ -668,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
@@ -735,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:
@@ -743,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

@@ -88,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')
@@ -150,12 +213,11 @@ class SfMaintenanceEquipmentOEE(models.Model):
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,
(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)
if response.status_code == 200:
result = response.json()
print('============', result)

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,12 @@ 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_sf_group_equipment_user,equipment.request_sf_group_equipment_user,maintenance.model_maintenance_request,sf_group_equipment_user,1,1,1,0
access_maintenance_wizard_sf_group_equipment_user,maintenance_wizard_sf_group_equipment_user,model_maintenance_request_wizard,sf_group_equipment_user,1,1,1,0
access_maintenance_sf_group_equipment_manager,equipment.request_sf_group_equipment_manager,maintenance.model_maintenance_request,sf_group_equipment_manager,1,1,1,0
access_maintenance_wizard_sf_group_equipment_manager,maintenance_wizard_sf_group_equipment_manager,model_maintenance_request_wizard,sf_group_equipment_manager,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_sf_group_equipment_user maintenance_equipment_oee equipment.request_sf_group_equipment_user model_maintenance_equipment_oee maintenance.model_maintenance_request sf_base.group_plan_dispatch sf_group_equipment_user 1 0 1 0 1 0
23 access_sf_maintenance_logs_group_plan_dispatch access_maintenance_wizard_sf_group_equipment_user sf_maintenance_logs maintenance_wizard_sf_group_equipment_user model_sf_maintenance_logs model_maintenance_request_wizard sf_base.group_plan_dispatch sf_group_equipment_user 1 0 1 0 1 0
24 access_maintenance_sf_group_equipment_manager equipment.request_sf_group_equipment_manager maintenance.model_maintenance_request sf_group_equipment_manager 1 1 1 0
25 access_maintenance_wizard_sf_group_equipment_manager maintenance_wizard_sf_group_equipment_manager model_maintenance_request_wizard sf_group_equipment_manager 1 1 1 0
26 access_maintenance_equipment_group_plan_dispatch maintenance.equipment maintenance.model_maintenance_equipment sf_base.group_plan_dispatch 1 0 0 0
27 access_maintenance_equipment_oee_group_plan_dispatch maintenance_equipment_oee model_maintenance_equipment_oee sf_base.group_plan_dispatch 1 0 0 0
28 access_sf_maintenance_logs_group_plan_dispatch sf_maintenance_logs model_sf_maintenance_logs sf_base.group_plan_dispatch 1 0 0 0
29 access_maintenance_standard_image_group_plan_dispatch maintenance_standard_image model_maintenance_standard_image sf_base.group_plan_dispatch 1 0 0 0
30 access_equipment_maintenance_standards_group_plan_dispatch equipment_maintenance_standards model_equipment_maintenance_standards sf_base.group_plan_dispatch 1 0 0 0
31 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

@@ -76,33 +76,61 @@
<field name="equipment_maintenance_id"/>
</xpath>
<xpath expr="//field[@name='user_id']" position="replace">
<field name="user_id" string="维保人"/>
</xpath>
<xpath expr="//field[@name='close_date']" position="replace">
<field name="close_date" attrs="{'invisible': [('done', '!=', True)]}" readonly="True" string="维保日期"/>
</xpath>
<xpath expr="//field[@name='user_id']" position="replace">
<field name="user_id" string="维保人"/>
</xpath>
<xpath expr="//field[@name='close_date']" position="replace">
<field name="close_date" attrs="{'invisible': [('done', '!=', True)]}" readonly="True"
string="维保日期"/>
</xpath>
<xpath expr="//field[@name='request_date']" position="attributes">
<attribute name="string">计划维保日期</attribute>
</xpath>
<sheet>
<notebook>
<page string="维保标准" attrs="{'invisible': [('equipment_maintenance_id', '=', False)]}" context="{'default_standard_id': 'id'}">
<page string="维保标准" attrs="{'invisible': [('equipment_maintenance_id', '=', False)]}"
context="{'default_standard_id': 'id'}">
<field name="maintenance_standards" widget="one2many_list">
<tree multi_edit="" editable="">
<field name="name" class="table_custom_required"/>
<field name="maintenance_standards" class="table_custom_required"/>
<field name="images" force_save="1" required="1" class="table_custom_required">
<field name="name" class="table_custom_required"/>
<field name="maintenance_standards" class="table_custom_required"/>
<field name="images" force_save="1" required="1" class="table_custom_required">
</field>
<field name="remark" class="table_custom_required"/>
</tree>
</field>
</page>
</notebook>
</sheet>
</field>
</record>
<record id="maintenance_request_view_tree_sf" model="ir.ui.view">
<field name="name">maintenance.request.view.tree.sf</field>
<field name="model">maintenance.request</field>
<field name="inherit_id" ref="maintenance.hr_equipment_request_view_tree"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='request_date']" position="replace">
<field name="request_date" string="计划维保日期"/>
</xpath>
<xpath expr="//field[@name='user_id']" position="after">
<field name="sf_maintenance_type"/>
</xpath>
</field>
</record>
<record id="equipment_request_view_search_sf" model="ir.ui.view">
<field name="name">maintenance.request.view.search.sf</field>
<field name="model">maintenance.request</field>
<field name="inherit_id" ref="maintenance.hr_equipment_request_view_search"/>
<field name="arch" type="xml">
<xpath expr="//filter[@name='inactive']" position="replace">
<filter string="不活跃的" name="inactive" domain="[('archive', '=', True)]"/>
<filter string="已归档" name="in_active" domain="[('active', '=', False)]"/>
</xpath>
</field>
</record>
@@ -110,7 +138,7 @@
<record id="hr_equipment_request_action1" model="ir.actions.act_window">
<field name="name">维保计划</field>
<field name="res_model">maintenance.request</field>
<field name="view_mode">kanban,tree,form,pivot,graph,calendar</field>
<field name="view_mode">tree,kanban,form,pivot,graph,calendar</field>
<field name="view_id" ref="maintenance.hr_equipment_request_view_kanban"/>
<field name="context">{'default_user_id': uid}</field>
<field name="help" type="html">

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>
@@ -1189,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

@@ -10,7 +10,7 @@
""",
'category': 'sf',
'website': 'https://www.sf.jikimo.com',
'depends': ['sf_base', 'sf_maintenance', 'web_widget_model_viewer', 'sf_warehouse'],
'depends': ['sf_base', 'sf_maintenance', 'web_widget_model_viewer', 'sf_warehouse','jikimo_attachment_viewer'],
'data': [
'data/stock_data.xml',
'data/empty_racks_data.xml',
@@ -45,6 +45,8 @@
'sf_manufacturing/static/src/scss/kanban_change.scss',
'sf_manufacturing/static/src/xml/button_show_on_tree.xml',
'sf_manufacturing/static/src/js/workpiece_delivery_wizard_confirm.js',
'sf_manufacturing/static/src/js/qr.js',
'sf_manufacturing/static/src/xml/qr.xml',
]
},

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('零件图号', related='product_id.part_number', readonly=True)
# 上传零件图纸
part_drawing = fields.Binary('零件图纸')
part_drawing = fields.Binary('零件图纸', related='product_id.machining_drawings', readonly=True)
quality_standard = fields.Binary('质检标准', related='product_id.quality_standard', readonly=True)
@api.depends('product_id.manual_quotation')
def _compute_manual_quotation(self):
@@ -781,6 +806,8 @@ class MrpProduction(models.Model):
'date_to': date_planned_end,
})
# work.write({'date_planned_start': date_planned_start, 'date_planned_finished': date_planned_end})
# 设置一个较大的结束时间,防止在设置开始时间时,结束时间小于开始时间
work.date_planned_finished = datetime.datetime.today() + datetime.timedelta(days=100)
work.date_planned_start = date_planned_start
work.date_planned_finished = date_planned_end
routing_workcenter = self.env['mrp.routing.workcenter'].sudo().search(
@@ -948,6 +975,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:
@@ -960,12 +989,12 @@ class MrpProduction(models.Model):
productions_not_delivered.write(
{'state': 'progress', 'programming_state': '已编程', 'is_rework': False})
# 对制造订单所以面的cnc工单的程序用刀进行校验
try:
logging.info(f'已更新制造订单:{productions_not_delivered}')
productions_not_delivered.production_cnc_tool_checkout()
except Exception as e:
logging.info(f'对cnc工单的程序用刀进行校验报错{e}')
# 对制造订单所以面的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):

View File

@@ -59,7 +59,8 @@ class ResMrpWorkOrder(models.Model):
compute='_compute_state', store=True,
default='pending', copy=False, readonly=True, recursive=True, index=True, tracking=True)
delivery_warning = fields.Selection([('normal', '正常'), ('warning', '告警'), ('overdue', '逾期')], string='时效')
delivery_warning = fields.Selection([('normal', '正常'), ('warning', '告警'), ('overdue', '逾期')], string='时效',
tracking=True)
@api.depends('production_id.manual_quotation')
def _compute_manual_quotation(self):
@@ -225,6 +226,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([
('待装夹', '待装夹'),
@@ -302,6 +306,7 @@ class ResMrpWorkOrder(models.Model):
is_delivery = fields.Boolean('是否配送完成', default=False)
rfid_code = fields.Char('RFID码')
rfid_code_old = fields.Char('RFID码(已解除)')
is_test_env = fields.Boolean('测试环境', default=False)
production_line_id = fields.Many2one('sf.production.line', related='production_id.production_line_id',
string='生产线', store=True, tracking=True)
@@ -317,6 +322,9 @@ class ResMrpWorkOrder(models.Model):
detailed_reason = fields.Text('详细原因')
is_rework = fields.Boolean(string='是否返工', default=False)
def button_change_env(self):
self.is_test_env = not self.is_test_env
@api.constrains('blocked_by_workorder_ids')
def _check_no_cyclic_dependencies(self):
if self.production_id.state not in ['rework'] and self.state not in ['rework']:
@@ -1048,6 +1056,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']:
@@ -1091,9 +1110,11 @@ class ResMrpWorkOrder(models.Model):
if self.routing_type == '装夹预调':
# 判断是否有坯料的序列号信息
boolean = False
if self.production_id.move_raw_ids[0].move_line_ids:
if self.production_id.move_raw_ids[0].move_line_ids[0].lot_id.name:
boolean = True
if self.production_id.move_raw_ids:
if self.production_id.move_raw_ids[0].move_line_ids:
if self.production_id.move_raw_ids[0].move_line_ids:
if self.production_id.move_raw_ids[0].move_line_ids[0].lot_id.name:
boolean = True
if not boolean:
raise UserError('制造订单【%s】缺少组件的序列号信息!' % self.production_id.name)
self.pro_code = self.production_id.move_raw_ids[0].move_line_ids[0].lot_id.name
@@ -1826,7 +1847,7 @@ class WorkPieceDelivery(models.Model):
return is_free
else:
raise UserError("接驳站暂未反馈站点实时状态,请稍后再试")
def delivery_avg(self):
is_agv_task_dispatch = self.env['ir.config_parameter'].sudo().get_param('is_agv_task_dispatch')
if is_agv_task_dispatch:

View File

@@ -16,6 +16,12 @@ from OCC.Extend.DataExchange import write_stl_file
class ResProductMo(models.Model):
_inherit = 'product.template'
def _get_machining_precision(self):
machinings = self.env['sf.machining.accuracy'].sudo().search([])
list = [(m.sync_id, m.name) for m in machinings]
return list
model_file = fields.Binary('模型文件')
categ_type = fields.Selection(string='产品的类别', related='categ_id.type', store=True)
model_name = fields.Char('模型名称')
@@ -23,12 +29,7 @@ class ResProductMo(models.Model):
model_width = fields.Float('模型宽(mm)', digits=(16, 3))
model_height = fields.Float('模型高(mm)', digits=(16, 3))
model_volume = fields.Float('模型体积(m³)')
model_machining_precision = fields.Selection([
('0.10', '±0.10mm'),
('0.05', '±0.05mm'),
('0.03', '±0.03mm'),
('0.02', '±0.02mm'),
('0.01', '±0.01mm')], string='加工精度')
model_machining_precision = fields.Selection(selection=_get_machining_precision, string='加工精度')
model_processing_panel = fields.Char('模型加工面板')
model_remark = fields.Char('模型备注说明')
length = fields.Float('长(mm)', digits=(16, 3))
@@ -774,8 +775,8 @@ 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 = fields.Binary('2D加工图纸', readonly=True)
quality_standard = fields.Binary('质检标准', readonly=True)
@api.constrains('tool_length')
def _check_tool_length_size(self):
@@ -837,6 +838,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, mimetype):
attachment_info = self.env['ir.attachment'].sudo().search(
[('res_id', '=', res_id), ('res_field', '=', res_field)], limit=1)
attachment_info.write({'name': name, 'mimetype': mimetype})
# 业务平台分配工厂后在智能工厂先创建销售订单再创建该产品
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()
@@ -875,8 +881,9 @@ class ResProductMo(models.Model):
'manual_quotation': item['manual_quotation'] or False,
'part_number': item.get('part_number') or '',
'active': True,
# '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']),
'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')])
@@ -884,6 +891,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'] and item['machining_drawings_mimetype']:
self.attachment_update(item['machining_drawings_name'], copy_product_id.product_tmpl_id.id,
'machining_drawings', item['machining_drawings_mimetype'])
if item['quality_standard'] and item['quality_standard_name'] and item['quality_standard_mimetype']:
self.attachment_update(item['quality_standard_name'], copy_product_id.product_tmpl_id.id,
'quality_standard', item['quality_standard_mimetype'])
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)
@@ -267,11 +272,6 @@ class StockRule(models.Model):
workorder_duration += workorder.duration_expected
sale_order = self.env['sale.order'].sudo().search([('name', '=', production.origin)])
# 根据销售订单号查询快速订单
quick_easy_order = self.env['quick.easy.order'].sudo().search([('sale_order_id', '=', sale_order.id)])
if quick_easy_order:
production.write({'part_number': quick_easy_order.part_drawing_number,
'part_drawing': quick_easy_order.machining_drawings})
if sale_order:
# sale_order.write({'schedule_status': 'to schedule'})
self.env['sf.production.plan'].sudo().with_company(company_id).create({

View File

@@ -1,5 +1,9 @@
<odoo>
<data>
<data noupdate="1">
<record id="group_show_button" model="res.groups">
<field name="name">演示模式</field>
<field name="category_id" ref="base.module_category_hidden"/>
</record>
</data>
</odoo>
</odoo>

View File

@@ -103,7 +103,10 @@ 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
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_workcenter_productivity_loss_group_quality access_mrp_workcenter_group_quality mrp_workcenter_productivity_loss_group_quality mrp_workcenter_group_quality mrp.model_mrp_workcenter_productivity_loss model_mrp_workcenter sf_base.group_quality 1 0 0 0
106 access_mrp_workcenter_productivity_loss_group_quality_director access_mrp_workcenter_group_quality_director mrp_workcenter_productivity_loss_group_quality_director mrp_workcenter_group_quality_director mrp.model_mrp_workcenter_productivity_loss model_mrp_workcenter sf_base.group_quality_director 1 0 0 0
107 access_sf_detection_result_group_quality sf_detection_result_group_quality model_sf_detection_result sf_base.group_quality 1 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_group_quality access_mrp_workcenter_productivity_loss_group_quality_director mrp_workcenter_productivity_group_quality mrp_workcenter_productivity_loss_group_quality_director mrp.model_mrp_workcenter_productivity mrp.model_mrp_workcenter_productivity_loss sf_base.group_quality sf_base.group_quality_director 1 1 0 1 0 0
111 access_mrp_workcenter_productivity_group_quality_director access_mrp_workcenter_productivity_group_quality mrp_workcenter_productivity_group_quality_director mrp_workcenter_productivity_group_quality mrp.model_mrp_workcenter_productivity sf_base.group_quality_director sf_base.group_quality 1 1 1 0
112 access_mrp_production_group_plan_dispatch access_mrp_workcenter_productivity_group_quality_director mrp_production mrp_workcenter_productivity_group_quality_director model_mrp_production mrp.model_mrp_workcenter_productivity sf_base.group_plan_dispatch sf_base.group_quality_director 1 1 0 1 0

View File

@@ -0,0 +1,115 @@
/** @odoo-module **/
import { registry } from '@web/core/registry';
import { Component } from '@odoo/owl';
class QRCodeWidget extends Component {
// 初始化组件
setup() {
console.log('QRCodeWidget setup');
this.qrCodeValue = ''; // 初始化为空字符串,用于存储条码
this.inputBuffer = ''; // 存储临时输入的字符
this.inputTimer = null; // 定时器
// 显式绑定上下文
this.onGlobalKeyDown = this.onGlobalKeyDown.bind(this);
window.addEventListener('keydown', this.onGlobalKeyDown);
}
// 清理事件监听器,防止内存泄漏
willUnmount() {
window.removeEventListener('keydown', this.onGlobalKeyDown);
if (this.inputTimer) {
clearTimeout(this.inputTimer);
}
}
// 全局键盘事件监听器
onGlobalKeyDown(event) {
// 如果是Tab键表示扫码输入结束
if (event.key === 'Tab' || event.key === 'Enter') {
this.qrCodeValue = this.inputBuffer; // 完整条码赋值
console.log('完整条码:', this.qrCodeValue);
this.onQRCodeChange(this.qrCodeValue); // 调用父组件的 onQRCodeChange 方法
this.inputBuffer = ''; // 清空临时缓冲区
event.preventDefault(); // 阻止Tab键的默认行为
return;
}
// 只处理可打印字符
if (event.key.length === 1) {
this.inputBuffer += event.key; // 添加到缓冲区
// console.log('当前缓冲区:', this.inputBuffer);
// 清除之前的定时器,重新开始计时
if (this.inputTimer) {
clearTimeout(this.inputTimer);
}
// 启动一个定时器如果500ms内没有新的输入则认为条码输入完成
this.inputTimer = setTimeout(() => {
this.qrCodeValue = this.inputBuffer;
// console.log('定时器触发,完整条码:', this.qrCodeValue);
this.inputBuffer = ''; // 清空缓冲区
}, 500); // 可以根据需要调整时间
}
}
// 处理二维码输入变更
async onQRCodeChange(qrCodeValue) {
console.log('onQRCodeChange二维码输入变更', qrCodeValue); // 检查二维码的输入是否被捕获
if (qrCodeValue) {
// console.log('二维码输入变更');
try {
// 发起 RPC 请求
const result = await this.env.services.rpc('/web/dataset/call_kw', {
model: 'mrp.workorder',
method: 'search_read',
args: [
[['rfid_code', '=', qrCodeValue]], // 查询条件
['id'] // 返回的字段
],
kwargs: {}
});
if (result.length > 0) {
console.log('该二维码对应的工单存在!');
} else {
console.log('未找到对应的工单。');
const routingTypeField = document.querySelector('[name="routing_type"]');
if (routingTypeField) {
let fieldValue = routingTypeField.querySelector('span').getAttribute('raw-value');
console.log('Routing Type Value:', fieldValue);
// 清理多余的引号
fieldValue = fieldValue ? fieldValue.replace(/["]+/g, '') : null;
console.log(fieldValue);
if (fieldValue && fieldValue === '装夹预调') {
// console.log('routing_type 为装夹预调');
// 检查 RFID 值
if (!qrCodeValue || qrCodeValue.length <= 3) return;
// 查找 name="button_start" 按钮并触发点击事件
const startButton = document.querySelector('[name="button_start"]');
if (startButton) {
startButton.click();
}
}
}
}
} catch (error) {
console.error('查询工单时出错:', error);
}
}
}
// 返回模板名称
static template = 'sf_manufacturing.QRCodeWidgetTemplate';
}
// 将自定义字段注册到字段注册表
registry.category('fields').add('qrcode_widget', QRCodeWidget);

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates>
<t t-name="sf_manufacturing.QRCodeWidgetTemplate" owl="1">
<!-- <div> -->
<!-- <input type="text" t-att-value="props.value" placeholder="Scan QR code here" /> -->
<!-- </div> -->
<div t-esc="props.value">
</div>
</t>
</templates>

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">
@@ -328,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>

View File

@@ -102,7 +102,7 @@
<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}
active_id,'search_default_filter_order_warning':1,'search_default_filter_order_overdue':1,'search_default_filter_order_normal':1}
</field>
<field name="help" type="html">
<p class="o_view_nocontent_workorder">
@@ -125,9 +125,9 @@
<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="//form" position="inside">
<script src="sf_manufacturing/static/src/js/customRFID.js"/>
</xpath>
<!-- <xpath expr="//form" position="inside"> -->
<!-- <script src="sf_manufacturing/static/src/js/customRFID.js"/> -->
<!-- </xpath> -->
<xpath expr="//header/field[@name='state']" position="replace">
<field name="state" widget="statusbar"
statusbar_visible="pending,waiting,ready,progress,to be detected,done,rework"/>
@@ -225,6 +225,7 @@
<xpath expr="//label[1]" position="before">
<!-- -->
<field name="production_id" invisible="0"/>
<field name="routing_type" string="工单类型" readonly="1"/>
<field name="duration_expected" invisible="1"/>
<field name="date_planned_start" invisible="1"/>
<field name="date_planned_finished" invisible="1"/>
@@ -246,11 +247,24 @@
<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="0" cache="True"
attrs="{'invisible': [('rfid_code_old', '!=', False)]}"/>
<field name="is_test_env" invisible="1"/>
<field name="rfid_code" force_save="1" readonly="1" cache="True"
attrs="{'invisible': [('rfid_code_old', '!=', False)]}" widget='qrcode_widget'/>
<field name="rfid_code" string="RFID码(手动输入框)" force_save="1" readonly="0" cache="True"
attrs="{'invisible': ['|',('rfid_code_old', '!=', False), ('is_test_env', '=', False)]}"/>
<field name="rfid_code_old" readonly="1" attrs="{'invisible': [('rfid_code_old', '=', False)]}"/>
</xpath>
<xpath expr="//header" position="inside">
<div class="o_statusbar_buttons"><button name="button_change_env"
type="object"
string="演示模式"
class="btn-primary"
groups="sf_manufacturing.group_show_button"/>
</div>
</xpath>
<xpath expr="//form//sheet//group//group//div[2]" position="replace">
</xpath>
<xpath expr="//form//sheet//group//group//div[1]" position="after">
@@ -466,6 +480,15 @@
<field name='X_deviation_angle' readonly="1"/>
</group>
</page>
<page string="2D加工图纸" attrs="{'invisible': [('routing_type','!=','装夹预调')]}">
<field name="machining_drawings" widget="adaptive_viewer"/>
</page>
<page string="质检标准" attrs="{'invisible': [('routing_type','!=','装夹预调')]}">
<field name="quality_standard" widget="adaptive_viewer"/>
</page>
<page string="工件配送"
attrs="{'invisible': [('routing_type','!=','装夹预调')]}">
<field name="workpiece_delivery_ids">
@@ -519,6 +542,13 @@
<!-- attrs='{"invisible": ["|","|",("state","!=","progress"),("user_permissions","=",False),("results","=","合格")]}'/>-->
<!-- </div>-->
</page>
<page string="2D加工图纸" attrs='{"invisible": [("routing_type","!=","CNC加工")]}'>
<field name="machining_drawings" widget="adaptive_viewer"/>
</page>
<page string="质检标准" attrs='{"invisible": [("routing_type","!=","CNC加工")]}'>
<field name="quality_standard" widget="adaptive_viewer"/>
</page>
</xpath>
<xpath expr="//page[1]" position="before">
<page string="CNC程序" attrs='{"invisible": [("routing_type","!=","CNC加工")]}'>
@@ -589,7 +619,6 @@
mrp.group_mrp_manager,sf_base.group_sf_mrp_manager,sf_base.group_sf_equipment_user,sf_base.group_sf_order_user
</attribute>
</xpath>
</field>
</record>
@@ -630,6 +659,7 @@
<separator/>
<filter string="预警" name="filter_order_warning" domain="[('delivery_warning', '=', 'warning')]"/>
<filter string="逾期" name="filter_order_overdue" domain="[('delivery_warning', '=', 'overdue')]"/>
<filter string="正常" name="filter_order_normal" domain="[('delivery_warning', '=', 'normal')]"/>
<separator/>
</xpath>
</field>

View File

@@ -17,7 +17,7 @@
'data/cron_data.xml',
'data/template_data.xml',
'security/ir.model.access.csv',
'views/mrp_workorder_views.xml',
],
'test': [
],

View File

@@ -13,6 +13,19 @@
<field name="active" eval="True"/>
</record>
<record model="ir.cron" id="ir_cron_sale_order_recover_time_warning">
<field name="name">检查销售订单是否完成并恢复正常时效</field>
<field name="model_id" ref="model_sale_order"/>
<field name="state">code</field>
<field name="code">model._recover_sale_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"/>

View File

@@ -36,7 +36,7 @@
<field name="msgtype">markdown</field>
<field name="urgency">normal</field>
<field name="content">### 销售订单逾期预警
事项:共有[{{warning_num}}]({{url}})个销售订单有逾期风险
事项:[共有{{warning_num}}个销售订单有逾期风险]({{url}})
</field>
</record>
@@ -48,7 +48,7 @@
<field name="msgtype">markdown</field>
<field name="urgency">urgent</field>
<field name="content">### 销售订单已逾期提醒
事项:共有[{{overdue_num}}]({{url}})个销售订单已逾期
事项:[共有{{overdue_num}}个销售订单已逾期]({{url}})
</field>
</record>
@@ -97,7 +97,7 @@
<field name="send_type">timing</field>
<field name="urgency">normal</field>
<field name="content">### 工单逾期预警
事项:共有[{{warning_num}}]({{url}})工单有逾期风险</field>
事项:[共有{{warning_num}}个工单有逾期风险]({{url}})</field>
</record>
<record id="template_mrp_workorder_pre_overdue" model="jikimo.message.template">
@@ -109,7 +109,7 @@
<field name="send_type">timing</field>
<field name="urgency">normal</field>
<field name="content">### 工单已逾期提醒
事项:共有[{{overdue_num}}]({{url}})工单已逾期</field>
事项:[共有{{overdue_num}}个工单已逾期]({{url}})</field>
</record>
<record id="template_mrp_workorder_cnc_overdue_warning" model="jikimo.message.template">
@@ -121,7 +121,7 @@
<field name="send_type">timing</field>
<field name="urgency">normal</field>
<field name="content">### 工单逾期预警
事项:共有[{{warning_num}}]({{url}})工单有逾期风险</field>
事项:[共有{{warning_num}}个工单有逾期风险]({{url}})</field>
</record>
<record id="template_mrp_workorder_cnc_overdue" model="jikimo.message.template">
@@ -133,7 +133,7 @@
<field name="send_type">timing</field>
<field name="urgency">normal</field>
<field name="content">### 工单已逾期提醒
事项:共有[{{overdue_num}}]({{url}})工单已逾期</field>
事项:[共有{{overdue_num}}个工单已逾期]({{url}})</field>
</record>
<record id="template_mrp_workorder_unclamp_overdue_warning" model="jikimo.message.template">
@@ -145,7 +145,7 @@
<field name="send_type">timing</field>
<field name="urgency">normal</field>
<field name="content">### 工单逾期预警
事项:共有[{{warning_num}}]({{url}})工单有逾期风险</field>
事项:[共有{{warning_num}}个工单有逾期风险]({{url}})</field>
</record>
<record id="template_mrp_workorder_unclamp_overdue" model="jikimo.message.template">
@@ -157,7 +157,7 @@
<field name="send_type">timing</field>
<field name="urgency">normal</field>
<field name="content">### 工单已逾期提醒
事项:共有[{{overdue_num}}]({{url}})工单已逾期</field>
事项:[共有{{overdue_num}}个工单已逾期]({{url}})</field>
</record>
<record id="template_mrp_workorder_surface_overdue_warning" model="jikimo.message.template">
@@ -169,7 +169,7 @@
<field name="send_type">timing</field>
<field name="urgency">normal</field>
<field name="content">### 工单逾期预警
事项:共有[{{warning_num}}]({{url}})工单有逾期风险</field>
事项:[共有{{warning_num}}个工单有逾期风险]({{url}})</field>
</record>
<record id="template_mrp_workorder_surface_overdue" model="jikimo.message.template">
@@ -181,7 +181,7 @@
<field name="send_type">timing</field>
<field name="urgency">normal</field>
<field name="content">### 工单已逾期提醒
事项:共有[{{overdue_num}}]({{url}})工单已逾期</field>
事项:[共有{{overdue_num}}个工单已逾期]({{url}})</field>
</record>
@@ -262,7 +262,7 @@
<field name="msgtype">markdown</field>
<field name="urgency">normal</field>
<field name="content">### 待质量判定提醒
事项:共有[{{judge_num}}]({{url}})个工单需判定质量结果</field>
事项:[共有{{judge_num}}个工单需判定质量结果]({{url}})</field>
</record>
<record id="template_maintenance_logs" model="jikimo.message.template">
<field name="name">设备故障</field>

View File

@@ -1,14 +1,15 @@
# -*- 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
@api.model_create_multi
def create(self, vals_list):
res = super(SFMessageMaintenanceLogs, self).create(vals_list)
for rec in res:
rec.add_queue()
rec.add_queue('设备故障')
return res
def _get_message(self, message_queue_ids):

View File

@@ -34,18 +34,19 @@ class SFMessageSale(models.Model):
picking_id.procurement_group_id.stock_move_ids.move_orig_ids.purchase_line_id.order_id).ids
purchase_order_id.extend(purchase_order_ids)
if purchase_order_id:
purchase_order_list = self.env['purchase.order'].search([('id', 'in', purchase_order_id)])
purchase_order_list = self.env['purchase.order'].sudo().search([('id', 'in', purchase_order_id)])
for purchase_order_info in purchase_order_list:
purchase_order_info.add_queue('坯料采购提醒')
except Exception as e:
logging.info('add_queue error:%s' % e)
logging.info('action_confirm res:%s' % res)
return res
# 继承并重写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')
url = self.env['ir.config_parameter'].sudo().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')
@@ -60,7 +61,7 @@ class SFMessageSale(models.Model):
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))])
sale_order_line = self.env['sale.order.line'].sudo().search([('order_id', '=', int(item.res_id))])
product = sale_order_line[0].product_id.name if len(sale_order_line) == 1 else '%s...' % \
sale_order_line[
0].product_id.name
@@ -100,42 +101,97 @@ class SFMessageSale(models.Model):
# # 销售订单逾期预警和已逾期
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)])
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)
today_str = datetime.strptime(current_time, '%Y-%m-%d %H:%M:%S')
today = today_str.strftime("%Y-%m-%d")
# 计算下一天的日期
deadline_check_str = today_str + timedelta(days=1)
deadline_check = deadline_check_str.strftime("%Y-%m-%d")
logging.info(
f"today: {today}, deadline_check: {deadline_check},current_time_strf: {current_time_strf}, current_time: {current_time}'")
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 = self.env['mrp.production'].sudo().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) != item.mrp_production_count:
if deadline_check == item.deadline_of_delivery:
deadline_of_delivery = item.deadline_of_delivery.strftime("%Y-%m-%d")
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 == deadline_of_delivery and item.delivery_warning not in ['warning']:
item.delivery_warning = 'warning'
elif today == item.deadline_of_delivery:
elif today >= 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:
if deadline_check == deadline_of_delivery and item.delivery_warning not in ['warning']:
item.delivery_warning = 'warning'
elif today == item.deadline_of_delivery:
elif today >= 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:
message_template = self.env["jikimo.message.template"].search([
("model", "=", self._name),
("bussiness_node_id", "=", self.env.ref('sf_message.bussiness_sale_order_overdue_warning').id)
])
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:
if wo.delivery_warning == 'warning':
wo.add_queue('销售订单逾期预警')
elif wo.delivery_warning == 'overdue':
wo.add_queue('销售订单已逾期')
business_node_id = business_node_ids.get(wo.delivery_warning)
if business_node_id:
message_template = self.env["jikimo.message.template"].sudo().search([
("model", "=", self._name),
("bussiness_node_id", "=", business_node_id)
], limit=1)
sale_order_has = self.env['jikimo.message.queue'].sudo().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)
if wo.delivery_warning == 'overdue':
# 把消息队列中销售订单预警的状态改为取消发送
business_node_id_warning = business_node_ids['warning']
if business_node_id_warning:
message_template_warning = self.env["jikimo.message.template"].search([
("model", "=", self._name),
("bussiness_node_id", "=", business_node_id_warning)
], limit=1)
if message_template_warning:
sale_order_warning = self.env['jikimo.message.queue'].search([
('res_id', '=', wo.id),
('message_status', '=', 'pending'),
('message_template_id', '=', message_template_warning.id)
])
if sale_order_warning:
logging.info('取消发送:%s' % sale_order_warning)
sale_order_warning.write({'message_status': 'cancel'})
def _recover_sale_time_warning_func(self):
sale_order_done = self.sudo().search([('state', 'in', ['sale']), ('delivery_status', '=', 'full')])
sale_order_overdue = sale_order_done.filtered(lambda x: x.delivery_warning in ['overdue', 'warning'])
if sale_order_overdue:
sale_order_overdue.write({'delivery_warning': 'normal'})
message_queue_ids = self.env["jikimo.message.queue"].sudo().search([
("message_status", "=", "pending"),
("res_id", "in", [item.id for item in sale_order_overdue])
])
if message_queue_ids:
message_queue_ids.write({'message_status': 'cancel'})

View File

@@ -29,14 +29,14 @@ class SFMessageStockPicking(models.Model):
[('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)])
stock_picking_send = self.env["jikimo.message.queue"].sudo().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(
stock_picking = self.env['stock.picking'].sudo().search([('id', '=', int(message_queue_id.res_id))])
stock_picking_out = self.env['stock.picking'].sudo().search(
[('origin', '=', stock_picking.origin), ('state', '=', 'assigned'),
('picking_type_id.sequence_code', '=', 'OUT')])
if stock_picking_out and len(stock_picking_out) > 0:
@@ -54,10 +54,10 @@ class SFMessageStockPicking(models.Model):
i = 0
if message_queue_id.message_template_id.name == '坯料发料提醒':
content = message_queue_id.message_template_id.content
stock_picking_line = self.env['stock.picking'].search([('id', '=', int(message_queue_id.res_id))])
mrp_production_info = self.env['mrp.production'].search(
stock_picking_line = self.env['stock.picking'].sudo().search([('id', '=', int(message_queue_id.res_id))])
mrp_production_info = self.env['mrp.production'].sudo().search(
[('name', '=', stock_picking_line.origin)])
mrp_production_list = self.env['mrp.production'].search(
mrp_production_list = self.env['mrp.production'].sudo().search(
[('product_id', '=', mrp_production_info.product_id.id)])
for mrp_production_line in mrp_production_list:
picking_ids = mrp_production_line.picking_ids
@@ -87,9 +87,9 @@ class SFMessageStockPicking(models.Model):
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')
url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
action_id = self.env.ref('stock.stock_picking_type_action').id
menu_id = self.env['ir.model.data'].search([('name', '=', 'module_theme_treehouse')]).id
menu_id = self.env['ir.model.data'].sudo().search([('name', '=', 'module_theme_treehouse')]).id
# 查询参数
params = {'menu_id': menu_id, 'action': action_id, 'model': 'stock.picking',
'view_type': 'kanban'}
@@ -100,9 +100,9 @@ class SFMessageStockPicking(models.Model):
return full_url
def request_url1(self, id):
url = self.env['ir.config_parameter'].get_param('web.base.url')
url = self.env['ir.config_parameter'].sudo().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
menu_id = self.env['ir.model.data'].sudo().search([('name', '=', 'module_theme_treehouse')]).id
# 查询参数
params = {'id': id, 'menu_id': menu_id, 'action': action_id, 'model': 'stock.picking',
'view_type': 'form'}

View File

@@ -12,7 +12,7 @@ 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:
@@ -26,7 +26,7 @@ class SFMessageWork(models.Model):
contents = []
product_id = []
bussiness_node = None
url = self.env['ir.config_parameter'].get_param('web.base.url')
url = self.env['ir.config_parameter'].sudo().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')
@@ -39,8 +39,8 @@ class SFMessageWork(models.Model):
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_workorder_line = self.env['mrp.workorder'].search([('id', '=', int(message_queue_id.res_id))])
mrp_workorder_list = self.env['mrp.workorder'].search(
mrp_workorder_line = self.env['mrp.workorder'].sudo().search([('id', '=', int(message_queue_id.res_id))])
mrp_workorder_list = self.env['mrp.workorder'].sudo().search(
[('product_id', '=', mrp_workorder_line.product_id.id), ('state', '=', 'ready'),
('routing_type', '=', '装夹预调')])
if len(mrp_workorder_list) > 0 and mrp_workorder_line.product_id.id not in product_id:
@@ -61,20 +61,32 @@ class SFMessageWork(models.Model):
second=0,
microsecond=0
)
logging.info(current_time)
logging.info(target_time)
logging.info(target_time - time_range)
logging.info(target_time + time_range)
# 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))])
record = self.sudo().search(search_condition + [('id', '=', int(message_queue_id.res_id))])
if record:
bussiness_node = item.bussiness_node_id.name
# 分割业务节点名称,提取出业务节点关键字
business_node_key = bussiness_node.split('工单')[0].strip()
workcenter_mapping = {
'装夹预调': '工件装夹',
'CNC加工': '自动生产',
'解除装夹': '工件拆卸',
'表面工艺': '表面工艺外协',
}
workcenter_name = workcenter_mapping.get(business_node_key)
active_id = self.env['mrp.workcenter'].search([('name', 'ilike', workcenter_name)],
limit=1).id
i += 1
if i >= 1:
action_id = self.env.ref('sf_manufacturing.mrp_workorder_action_tablet').id
url_with_id = f"{url}/web#view_type=list&action={action_id}"
action_id = self.env.ref('sf_message.mrp_workorder_action_notify').id
url_with_id = f"{url}/web#view_type=list&action={action_id}&active_id={active_id}"
content_template = content.replace('{{url}}', url_with_id)
if bussiness_node in template_names['预警']:
content = content_template.replace('{{warning_num}}', str(i))
@@ -84,12 +96,13 @@ class SFMessageWork(models.Model):
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
menu_id = self.env['ir.model.data'].search([('name', '=', 'module_stock_dropshipping')]).id
url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
action_id = self.env.ref('sf_message.mrp_workorder_issued_action').id
menu_id = self.env['ir.model.data'].sudo().search([('name', '=', 'module_stock_dropshipping')]).id
active_id = self.env['mrp.workcenter'].sudo().search([('name', '=', '工件装夹中心')]).id
# 查询参数
params = {'menu_id': menu_id, 'action': action_id, 'model': 'mrp.workorder',
'view_type': 'list', 'active_id': 1}
'view_type': 'list', 'active_id': active_id}
# 拼接查询参数
query_string = urlencode(params)
# 拼接URL
@@ -97,7 +110,8 @@ class SFMessageWork(models.Model):
return full_url
def _overdue_or_warning_func(self):
workorders = self.env['mrp.workorder'].search([("state", "in", ["ready", "progress", "to be detected"])])
workorders = self.env['mrp.workorder'].search(
[("state", "in", ["ready", "progress", "to be detected"]), ('schedule_state', '=', '已排')])
grouped_workorders = {}
for workorder in workorders:
routing_type = workorder.routing_type
@@ -115,21 +129,26 @@ class SFMessageWork(models.Model):
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:
logging.info("------overdue-------")
logging.info(f"Workorder: {item.production_id.name}, Current Time: {current_time_datetime}, "
f"Planned Finish: {date_planned_finished}")
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:
logging.info("------warning-------")
logging.info(f"Workorder: {item.production_id.name}, Current Time: {current_time_datetime}, "
f"Planned Finish: {date_planned_finished}")
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,
'装夹预调_overdue': self.env.ref('sf_message.bussiness_mrp_workorder_pre_overdue').id,
'装夹预调_warning': self.env.ref('sf_message.bussiness_mrp_workorder_pre_overdue_warning').id,
'CNC加工_overdue': self.env.ref('sf_message.bussiness_mrp_workorder_cnc_overdue').id,
'CNC加工_warning': self.env.ref('sf_message.bussiness_mrp_workorder_cnc_overdue_warning').id,
'解除装夹_overdue': self.env.ref('sf_message.bussiness_mrp_workorder_unclamp_overdue').id,
'解除装夹_warning': self.env.ref('sf_message.bussiness_mrp_workorder_unclamp_overdue_warning').id,
'表面工艺_overdue': self.env.ref('sf_message.bussiness_mrp_workorder_surface_overdue').id,
'表面工艺_warning': 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),
@@ -137,13 +156,17 @@ class SFMessageWork(models.Model):
]) 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)
])
warning_type = 'warning' if item.delivery_warning == 'warning' else 'overdue'
key = f"{item.routing_type}_{warning_type}"
bussiness_node_id = business_node_ids.get(key, None)
if bussiness_node_id:
message_template = message_templates.get(key)
if message_template and message_template.id:
message_queue_ids = self.env["jikimo.message.queue"].sudo().search([
("message_template_id", "=", message_template.id),
("message_status", "=", "pending"),
("res_id", "=", item.id)
], limit=1)
if not message_queue_ids:
overdue_message = '工单已逾期' if item.delivery_warning == 'overdue' else '工单逾期预警'
queue_method_name = f'add_queue'
@@ -151,8 +174,33 @@ class SFMessageWork(models.Model):
args = [f'{item.routing_type}{overdue_message}']
# 获取add_queue方法并调用它传入参数列表
getattr(item, queue_method_name)(*args)
if item.delivery_warning == 'overdue':
# 把消息队列中销售订单预警的状态改为取消发送
key = f"{item.routing_type}_{'warning'}"
business_node_id_warning = business_node_ids.get(key, None)
if business_node_id_warning:
message_template_warning = self.env["jikimo.message.template"].search([
("model", "=", self._name),
("bussiness_node_id", "=", business_node_id_warning)
], limit=1)
if message_template_warning:
work_order_warning = self.env['jikimo.message.queue'].search([
('res_id', '=', item.id),
('message_status', '=', 'pending'),
('message_template_id', '=', message_template_warning.id)
])
if work_order_warning:
logging.info('取消发送:%s' % work_order_warning)
work_order_warning.write({'message_status': 'cancel'})
def _recover_time_warning_func(self):
workorder_done = self.env['mrp.workorder'].search([("state", "=", "done")])
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'})
if workorder_overdue:
workorder_overdue.write({'delivery_warning': 'normal'})
message_queue_ids = self.env["jikimo.message.queue"].sudo().search([
("message_status", "=", "pending"),
("res_id", "in", [item.id for item in workorder_overdue])
])
if message_queue_ids:
message_queue_ids.write({'message_status': 'cancel'})

View File

@@ -5,24 +5,28 @@ access_jikimo_message_template_group_purchase,jikimo_message_template,jikimo_mes
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_template_group_purchase_director,jikimo_message_template,jikimo_message_notify.model_jikimo_message_template,sf_base.group_purchase_director,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_bussiness_node_group_purchase_director,jikimo_message_bussiness_node,jikimo_message_notify.model_jikimo_message_bussiness_node,sf_base.group_purchase_director,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_queue_group_purchase_director,jikimo_message_queue,jikimo_message_notify.model_jikimo_message_queue,sf_base.group_purchase_director,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
access_jikimo_message_reminder_time_group_purchase_director,jikimo_message_reminder_time,jikimo_message_notify.model_jikimo_message_reminder_time,sf_base.group_purchase_director,1,1,1,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
5 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
6 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
7 access_jikimo_message_bussiness_node_group_sale_salemanager access_jikimo_message_template_group_purchase_director jikimo_message_bussiness_node jikimo_message_template jikimo_message_notify.model_jikimo_message_bussiness_node jikimo_message_notify.model_jikimo_message_template sf_base.group_sale_salemanager sf_base.group_purchase_director 1 1 1 0
8 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
9 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
10 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
11 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
12 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
13 access_jikimo_message_queue_group_sale_salemanager access_jikimo_message_bussiness_node_group_purchase_director jikimo_message_queue jikimo_message_bussiness_node jikimo_message_notify.model_jikimo_message_queue jikimo_message_notify.model_jikimo_message_bussiness_node sf_base.group_sale_salemanager sf_base.group_purchase_director 1 1 1 0
14 access_jikimo_message_queue_group_purchase access_jikimo_message_queue_group_sale_salemanager jikimo_message_queue jikimo_message_notify.model_jikimo_message_queue sf_base.group_purchase sf_base.group_sale_salemanager 1 1 1 0
15 access_jikimo_message_queue_group_purchase jikimo_message_queue jikimo_message_notify.model_jikimo_message_queue sf_base.group_purchase 1 1 1 0
16 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
17 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
18 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
19 access_jikimo_message_reminder_time_group_sale_salemanager access_jikimo_message_queue_group_purchase_director jikimo_message_reminder_time jikimo_message_queue jikimo_message_notify.model_jikimo_message_reminder_time jikimo_message_notify.model_jikimo_message_queue sf_base.group_sale_salemanager sf_base.group_purchase_director 1 1 1 0
20 access_jikimo_message_reminder_time_group_purchase access_jikimo_message_reminder_time_group_sale_salemanager jikimo_message_reminder_time jikimo_message_notify.model_jikimo_message_reminder_time sf_base.group_purchase sf_base.group_sale_salemanager 1 1 1 0
21 access_jikimo_message_reminder_time_group_sf_stock_user access_jikimo_message_reminder_time_group_purchase jikimo_message_reminder_time jikimo_message_notify.model_jikimo_message_reminder_time sf_base.group_sf_stock_user sf_base.group_purchase 1 1 1 0
22 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
23 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
24 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
25 access_jikimo_message_reminder_time_group_purchase_director jikimo_message_reminder_time jikimo_message_notify.model_jikimo_message_reminder_time sf_base.group_purchase_director 1 1 1 0
26
27
28
29
30
31
32

View File

@@ -0,0 +1,65 @@
<?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>
<record model="ir.actions.act_window" id="mrp_workorder_issued_action">
<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_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

@@ -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'],
"standard_tolerance": time['standard_tolerance'],
})

View File

@@ -219,7 +219,7 @@ class sf_production_plan(models.Model):
return num
def do_production_schedule(self, count=1):
def do_production_schedule(self):
"""
排程方法
"""
@@ -227,48 +227,46 @@ 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, count)
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
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 = '待装夹'
# self.env['sale.order'].browse(record.production_id.origin).schedule_status = 'to process'
# sale_obj = self.env['sale.order'].search([('name', '=', record.origin)])
# if 'S' in sale_obj.name:
# sale_obj.schedule_status = 'to process'
mrp_production_ids = record.production_id._get_children().ids
print('mrp_production_ids', mrp_production_ids)
for i in mrp_production_ids:
record.env['mrp.production'].sudo().browse(i).schedule_state = '已排'
# record.production_id.date_planned_start = record.date_planned_start
# record.production_id.date_planned_finished = record.date_planned_finished
record.sudo().production_id.production_line_id = record.production_line_id.id
if record.production_id.workorder_ids:
record.sudo().production_id.workorder_ids.filtered(
lambda b: b.routing_type == "装夹预调").workpiece_delivery_ids.write(
{'production_line_id': record.production_line_id.id,
'plan_start_processing_time': record.date_planned_start})
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.production_id.schedule_state = '已排'
record.sudo().production_id.schedule_state = '已排'
record.sudo().production_id.process_state = '待装夹'
# self.env['sale.order'].browse(record.production_id.origin).schedule_status = 'to process'
# sale_obj = self.env['sale.order'].search([('name', '=', record.origin)])
# if 'S' in sale_obj.name:
# sale_obj.schedule_status = 'to process'
mrp_production_ids = record.production_id._get_children().ids
print('mrp_production_ids', mrp_production_ids)
for i in mrp_production_ids:
record.env['mrp.production'].sudo().browse(i).schedule_state = '已排'
# record.production_id.date_planned_start = record.date_planned_start
# record.production_id.date_planned_finished = record.date_planned_finished
record.sudo().production_id.production_line_id = record.production_line_id.id
if record.production_id.workorder_ids:
record.sudo().production_id.workorder_ids.filtered(
lambda b: b.routing_type == "装夹预调").workpiece_delivery_ids.write(
{'production_line_id': record.production_line_id.id,
'plan_start_processing_time': record.date_planned_start})
# record.date_planned_finished = record.date_planned_start + timedelta(days=3)
# record.state = 'done'
@@ -282,54 +280,66 @@ class sf_production_plan(models.Model):
}
# 处理是否可排程
def deal_processing_schedule(self, date_planned_start, count):
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, count): # 判断生产线是否可排程
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,46 +31,10 @@ 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
count = len(temp_plan_ids) + 1
for plan in temp_plan_ids:
count = count - 1
# 处理每个计划
# 比如更新计划状态、分配资源等
# 示例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(count)
# plan_obj.state = 'done'
print('处理计划:', plan.id, '完成')
# # 获取当前生产线
# production_line_id = self.production_line_id
# # 获取当前生产线的所有生产订单
# production_order_ids = self.env['mrp.production'].search([('production_line_id', '=', production_line_id.id)])
# # 获取当前生产线的所有生产订单的id
# production_order_id_list = []
# for production_order_id in production_order_ids:
# production_order_id_list.append(production_order_id.id)
# # 获取当前生产线的所有生产订单的排程状态
# production_order_plan_state_list = []
# for production_order_id in production_order_ids:
# production_order_plan_state_list.append(production_order_id.plan_state)
# # 如果当前生产线的所有生产订单的排程状态都是已排程,则报错
# 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('当前生产线的所有生产订单都已取消,请勿重复排程!')
# # 如果当前生产线的所有生产订单的排程状态都是已暂停,则报错
# if all(production_order_plan_state == '已暂停' for production_order_plan_state in production
# 判断能否排成
self.plan_ids.deal_processing_schedule(self.date_planned_start)
self.plan_ids.do_production_schedule()
_logger.info('处理计划: %s 完成', self.plan_ids.ids)

View File

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

View File

@@ -31,8 +31,8 @@ class SfQualityCncTest(models.Model):
("technology", "工艺"), ("customer redrawing", "客户改图")], string="原因")
detailed_reason = fields.Text('详细原因')
# machining_drawings = fields.Binary(related='workorder_id.machining_drawings', string='2D加工图纸', readonly=True)
# quality_standard = fields.Binary(related='workorder_id.quality_standard', string='质检标准', readonly=True)
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 ['返工', '报废']:

View File

@@ -107,10 +107,10 @@
</group>
</page>
<page string="2D图纸">
<!-- <field name="machining_drawings" string="" widget="pdf_viewer"/>-->
<field name="machining_drawings" string="" widget="adaptive_viewer"/>
</page>
<page string="客户质量标准">
<!-- <field name="quality_standard" string=""/>-->
<field name="quality_standard" string="" widget="adaptive_viewer"/>
</page>
<page string="其他" attrs="{'invisible': [('state','=', 'waiting')]}">
<group>

View File

@@ -20,6 +20,12 @@ class QuickEasyOrder(models.Model):
_description = '简易下单'
_order = 'id desc'
def _get_machining_precision(self):
machinings = self.env['sf.machining.accuracy'].sudo().search([])
list = [(m.sync_id, m.name) for m in machinings]
return list
name = fields.Char('订单编号', default=lambda self: self.env['ir.sequence'].next_by_code('quick.easy.order'))
model_length = fields.Float('长(mm)', digits=(16, 3))
model_width = fields.Float('宽(mm)', digits=(16, 3))
@@ -27,12 +33,7 @@ class QuickEasyOrder(models.Model):
model_volume = fields.Float('体积(mm³)', digits=(16, 3))
model_processing_side = fields.Char('加工面', default='A')
model_feature = fields.Char('特征')
machining_precision = fields.Selection([
('0.10', '±0.10mm'),
('0.05', '±0.05mm'),
('0.03', '±0.03mm'),
('0.02', '±0.02mm'),
('0.01', '±0.01mm')], string='加工精度', default='0.10')
machining_precision = fields.Selection(selection=_get_machining_precision, string='加工精度')
material_id = fields.Many2one('sf.production.materials', '材料', tracking=True)
material_model_id = fields.Many2one('sf.materials.model', '型号', domain="[('materials_id', '=', material_id)]",
tracking=True)
@@ -219,7 +220,14 @@ class QuickEasyOrder(models.Model):
'total_amount': item.price,
'remark': '',
'manual_quotation': True,
'barcode': barcode
'barcode': barcode,
'part_number': item.part_drawing_number,
'machining_drawings_name': '',
'quality_standard_name': '',
'machining_drawings_mimetype': '',
'quality_standard_mimetype': '',
'machining_drawings': item.machining_drawings,
'quality_standard': '',
})
# res['bfm_process_order_list'] = json.dumps(res['bfm_process_order_list'])
product_id = self.env.ref('sf_dlm.product_template_sf').sudo()

View File

@@ -55,7 +55,8 @@ class ReSaleOrder(models.Model):
store=True, readonly=False, copy=False, precompute=True,
states=READONLY_FIELD_STATES, default=fields.Datetime.now)
delivery_warning = fields.Selection([('normal', '正常'), ('warning', '告警'), ('overdue', '逾期')], string='时效')
delivery_warning = fields.Selection([('normal', '正常'), ('warning', '告警'), ('overdue', '逾期')], string='时效',
tracking=True)
# 业务平台分配工厂后在智能工厂先创建销售订单
def sale_order_create(self, company_id, delivery_name, delivery_telephone, delivery_address,
@@ -117,12 +118,16 @@ class ReSaleOrder(models.Model):
# 业务平台分配工厂时在创建完产品后再创建销售明细信息
def sale_order_create_line(self, product, item):
machining_accuracy_name = ''
if product.model_machining_precision:
machining_accuracy_name = self.env['sf.machining.accuracy'].sudo().search(
[('sync_id', '=', product.model_machining_precision)]).name
vals = {
'order_id': self.id,
'product_id': product.id,
'name': '%s/%s/%s/%s/±%s/%s' % (
'name': '%s/%s/%s/%s/%s/%s' % (
product.model_long, product.model_width, product.model_height, product.model_volume,
product.model_machining_precision,
machining_accuracy_name,
product.materials_id.name),
'price_unit': product.list_price,
'product_uom_qty': item['number'],

View File

@@ -6,6 +6,31 @@
<field name="model">purchase.order</field>
<field name="inherit_id" ref="purchase.purchase_order_form"/>
<field name="arch" type="xml">
<xpath expr="//header/button[@name='action_view_picking']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//header/button[@name='action_rfq_send'][1]" position="before">
<button name="button_confirm" type="object" states="sent" string="Confirm Order"
context="{'validate_analytic': True}" class="oe_highlight" id="bid_confirm"
data-hotkey="v"/>
<button name="button_confirm" type="object" states="draft" context="{'validate_analytic': True}"
string="Confirm Order" id="draft_confirm"/>
<button name="action_view_picking"
string="接收产品" class="oe_highlight" type="object"
attrs="{'invisible': ['|', '|' , ('is_shipped', '=', True), ('state','not in', ('purchase','done')), ('incoming_picking_count', '=', 0)]}"
data-hotkey="y" groups="stock.group_stock_user"/>
<button name="button_cancel" states="draft,to approve,sent,purchase" string="取消" type="object" data-hotkey="x" />
</xpath>
<xpath expr="//header/button[@name='button_cancel'][2]" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//header/button[@name='button_confirm'][3]" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//header/button[@name='button_confirm'][4]" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<field name="partner_id" position="replace">
<field name="partner_id" widget="res_partner_many2one" context="{'is_supplier': True }"/>
</field>

View File

@@ -80,8 +80,8 @@
<field name="unit_price"/>
<field name="price" options="{'format': false}"/>
<field name="part_drawing_number"/>
<!-- <field name="machining_drawings" filename="machining_drawings_name" widget="pdf_viewer"/>-->
<!-- <field name="machining_drawings_name" invisible="1"/>-->
<field name="machining_drawings" filename="machining_drawings_name" widget="pdf_viewer"/>
<field name="machining_drawings_name" invisible="1"/>
<field name="sale_order_id"
attrs='{"invisible": [("sale_order_id","=",False)],"readonly": [("sale_order_id","!=",False)]}'/>
</group>

View File

@@ -95,7 +95,7 @@
<attribute name="attrs">{'readonly': [('state', 'in', ['cancel','sale'])]}</attribute>
</field>
<field name="payment_term_id" position="after">
<field name="deadline_of_delivery" readonly="1"/>
<field name="deadline_of_delivery" readonly="0"/>
<field name="payments_way" attrs="{'readonly': [('state', 'in', ('sale','cancel'))]}"/>
<field name="pay_way" attrs="{'readonly': [('state', 'in', ('sale','cancel'))]}"/>
<!-- <field name="schedule_status" readonly="1"/> -->

View File

@@ -51,6 +51,8 @@ class FunctionalCuttingToolEntity(models.Model):
string='位置', compute='_compute_current_location_id', store=True)
image = fields.Binary('图片', readonly=True)
stock_num = fields.Integer('库存变更次数', default=0)
safe_inventory_id = fields.Many2one('sf.real.time.distribution.of.functional.tools',
string='功能刀具安全库存', readonly=True)
@@ -71,7 +73,7 @@ class FunctionalCuttingToolEntity(models.Model):
})
@api.depends('barcode_id.quant_ids', 'barcode_id.quant_ids.location_id', 'functional_tool_status',
'current_shelf_location_id')
'current_shelf_location_id', 'stock_num')
def _compute_current_location_id(self):
for record in self:
if record.functional_tool_status == '已拆除':

View File

@@ -175,7 +175,9 @@ class MrpProduction(models.Model):
cnc_ids = self.env['sf.cnc.processing'].sudo().search(
[('workorder_id', 'in', workorder_ids.ids), ('cutting_tool_name', 'in', invalid_tool)])
if cnc_ids:
cnc_ids.write({'tool_state': '2'})
for cnc_id in cnc_ids:
cnc_id.tool_state = '2'
# cnc_ids.write({'tool_state': '2'})
# 创建制造订单无效刀检测结果记录
for production_id in self:
for processing_panel in list(set(invalid_tool_processing_panel)):
@@ -198,18 +200,22 @@ class MrpProduction(models.Model):
self[0].write({'is_rework': False})
# 修改制造订单 编程状态变为“编程中” 制造订单状态为‘返工’
self.write({'programming_state': '编程中', 'work_state': '编程中', 'state': 'rework'})
self[0].workorder_ids.filtered(
lambda a: a.name == '装夹预调' and a.state not in ['rework', 'done', 'cancel'])._compute_state()
if missing_tool_1:
logging.info(f'线边、机内缺刀:{missing_tool_1}')
# 修改 修改cnc程序的刀具状态 为 ‘缺刀’
cnc_ids = self.env['sf.cnc.processing'].sudo().search(
[('workorder_id', 'in', workorder_ids.ids), ('cutting_tool_name', 'in', missing_tool_1)])
if cnc_ids:
cnc_ids.write({'tool_state': '1'})
for cnc_id in cnc_ids:
cnc_id.tool_state = '1'
# cnc_ids.write({'tool_state': '1'})
if missing_tool_2 and invalid_tool == []:
logging.info(f'库存缺刀:{missing_tool_2}')
# 调用CAM工单程序用刀计划创建方法
cnc_ids = self.env['sf.cnc.processing'].sudo().search(
[('workorder_id', 'in', workorder_ids.filtered(lambda a: a.production_id == self[0].id).ids),
[('workorder_id', 'in', workorder_ids.filtered(lambda a: a.production_id == self[0]).ids),
('cutting_tool_name', 'in', missing_tool_2)])
if cnc_ids:
logging.info('调用CAM工单程序用刀计划创建方法')

View File

@@ -53,6 +53,13 @@ class StockMoveLine(models.Model):
[('barcode_id', '=', line_id.lot_id.id),
('functional_tool_status', '=', '正常')]).cnc_function_tool_use_verify()
for move_line in move_lines:
if move_line.lot_id:
tool_id = self.env['sf.functional.cutting.tool.entity'].sudo().search(
[('barcode_id', '=', move_line.lot_id.id),
('functional_tool_status', '=', '正常')])
tool_id.stock_num += tool_id.stock_num
class StockPicking(models.Model):
_inherit = 'stock.picking'