Compare commits

...

502 Commits

Author SHA1 Message Date
liaodanlong
284234adf2 合并代码部分还原 2025-01-08 13:37:48 +08:00
liaodanlong
3ba79d88b5 修改错误提示 2025-01-08 11:36:28 +08:00
liaodanlong
c5755c318c Merge branch 'refs/heads/release/release_2.7' into feature/part_number
# Conflicts:
#	sf_manufacturing/models/mrp_workorder.py
2025-01-08 11:26:16 +08:00
liaodanlong
dcaca89c6f 外协工单关联采购单数量计算 2025-01-08 10:47:31 +08:00
liaodanlong
5774f241a0 外协工艺合并采购单处理 2025-01-08 09:36:38 +08:00
liaodanlong
ad02cbf8cb sf-制造订单-工单添加外协工序,制造订单状态变成已完成,销售订单的收货中没有该产品的调拨 2025-01-07 13:40:17 +08:00
liaodanlong
196b427867 状态计算 2025-01-06 13:39:21 +08:00
liaodanlong
b6f3382e5d 状态计算 2025-01-06 13:34:57 +08:00
liaodanlong
f2ee382205 状态计算 2025-01-06 13:33:02 +08:00
liaodanlong
081880b4bb 状态计算 2025-01-06 13:20:10 +08:00
yuxianghui
bc475441a2 1、去除工单开始按钮的二次确认;2、优化托盘入库后夹具物料查询中的状态还是未入库的问题 2025-01-06 13:11:22 +08:00
liaodanlong
a7c3a604a6 Merge remote-tracking branch 'origin/release/release_2.7' into release/release_2.7 2025-01-06 13:03:30 +08:00
liaodanlong
0bd65b5da8 状态计算 2025-01-06 13:03:15 +08:00
liaodanlong
79d561ba68 状态计算 2025-01-06 13:01:58 +08:00
guanhuan
63d9b4bf39 Merge branch 'refs/heads/develop' into release/release_2.7 2025-01-06 12:51:14 +08:00
管欢
2619953be1 Accept Merge Request #1710: (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/1710
2025-01-06 12:49:14 +08:00
guanhuan
9f1514bd14 修复销售单号和追溯参考为空问题 2025-01-06 11:44:33 +08:00
liaodanlong
6e46d1d8dc Merge branch 'refs/heads/release/release_2.7' into feature/part_number 2025-01-06 11:20:44 +08:00
liaodanlong
403e64a957 表面工艺外协关联采购单查询条件修改 2025-01-06 11:09:22 +08:00
mgw
aaded331cd 解除装夹方法增加前置判断 2025-01-06 10:11:44 +08:00
liaodanlong
5d2ddfb510 Merge branch 'refs/heads/develop' into feature/part_number 2025-01-06 08:46:19 +08:00
mgw
f68453a0c6 Merge branch 'release/release_2.7' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into release/release_2.7 2025-01-03 15:26:20 +08:00
mgw
5cff411aaf r环境审批问题 2025-01-03 15:25:47 +08:00
guanhuan
ef5a3decd4 Merge remote-tracking branch 'origin/release/release_2.7' into release/release_2.7 2025-01-03 15:17:26 +08:00
guanhuan
ce1860b283 Merge branch 'refs/heads/develop' into release/release_2.7 2025-01-03 15:16:57 +08:00
mgw
b3f56754cd 修改翻译 2025-01-03 15:09:03 +08:00
管欢
202db10cea Accept Merge Request #1709: (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/1709
2025-01-03 15:06:29 +08:00
guanhuan
6b61df9d50 工序外协发料通知跳转 2025-01-03 15:04:22 +08:00
guanhuan
1cac579a1f Merge remote-tracking branch 'origin/develop' into release/release_2.7 2025-01-03 12:59:19 +08:00
管欢
53ca78a6a3 Accept Merge Request #1708: (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/1708
2025-01-03 12:54:37 +08:00
mgw
0d28df0415 适配多层审批 2025-01-03 12:52:27 +08:00
guanhuan
d182641d81 外购订单采购单提醒 2025-01-03 12:52:24 +08:00
马广威
7789c901b2 Accept Merge Request #1707: (feature/制造功能优化 -> develop)
Merge Request: 调整状态字段名称

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1707?initial=true
2025-01-03 11:43:55 +08:00
mgw
aa4b73e406 调整状态字段名称 2025-01-03 11:43:27 +08:00
马广威
1ca8ebe3cc Accept Merge Request #1706: (feature/制造功能优化 -> develop)
Merge Request: Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1706?initial=true
2025-01-03 11:33:28 +08:00
mgw
c34cdd595d Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2025-01-03 11:32:48 +08:00
mgw
1936b512c2 调整多层审批需求 2025-01-03 11:32:24 +08:00
胡尧
3c470093d3 Merge branch 'develop' into release/release_2.7 2025-01-03 10:24:24 +08:00
管欢
b483097907 Accept Merge Request #1705: (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/1705?initial=true
2025-01-03 10:21:33 +08:00
guanhuan
c6aeff2006 待质检提醒 2025-01-03 10:17:33 +08:00
胡尧
170309b3c0 修改依赖 2025-01-03 10:01:52 +08:00
liaodanlong
58acdc4913 工艺确认重置表面工艺工单的关联采购单代码还原 2025-01-02 16:38:26 +08:00
管欢
d4537fe73d Accept Merge Request #1704: (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/1704
2025-01-02 14:24:53 +08:00
guanhuan
eaaa13fb9a 待质检提醒 2025-01-02 14:21:18 +08:00
guanhuan
f92bd8263c 待质检提醒 2025-01-02 14:20:31 +08:00
廖丹龙
5f3957864a Accept Merge Request #1703: (feature/part_number -> 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/1703
2025-01-02 13:43:03 +08:00
liaodanlong
f884963abc 工艺确认重置表面工艺工单的关联采购单为草稿 2025-01-02 13:34:09 +08:00
廖丹龙
1e17ac07a9 Accept Merge Request #1702: (feature/part_number -> 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/1702
2025-01-02 12:52:02 +08:00
liaodanlong
2f3e12e3af 表面工艺采购单确认订单限制,自动化产线加工路线逻辑矫正 2025-01-02 12:50:39 +08:00
liaodanlong
0ce51a4a66 添加人工线下加工工单排序 2025-01-02 12:49:46 +08:00
liaodanlong
a1bf997d51 采购岗与采购总监岗位添加工单操作权限 2025-01-02 12:49:05 +08:00
马广威
e6c125cae6 Accept Merge Request #1701: (feature/制造功能优化 -> develop)
Merge Request: Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1701?initial=true
2025-01-02 11:34:28 +08:00
mgw
ac968b0d6e Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2025-01-02 10:59:27 +08:00
mgw
81bebf836d sf-采购-询价单状态流转多余按钮影响现有按钮功能 2025-01-02 10:59:03 +08:00
黄焱
d47d3f1638 Accept Merge Request #1700: (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/1700?initial=true
2025-01-02 10:31:33 +08:00
hy
614447d56e 解开屏蔽的方法 2025-01-02 10:28:40 +08:00
廖丹龙
bf13edc1be Accept Merge Request #1699: (feature/part_number -> 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/1699
2025-01-02 09:08:27 +08:00
liaodanlong
e99b8692ea Merge branch 'refs/heads/develop' into feature/part_number 2025-01-02 09:06:41 +08:00
liaodanlong
701decb38f 表面工艺采购单确认订单进行限制 2024-12-31 17:08:38 +08:00
管欢
3c61726fd3 Accept Merge Request #1698: (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/1698?initial=true
2024-12-31 16:42:34 +08:00
guanhuan
247bebbd75 询价单审批 2024-12-31 16:39:09 +08:00
胡尧
c3ceda2ba9 Accept Merge Request #1697: (feature/sale_order_route_pick -> develop)
Merge Request: 特殊表面工艺外协采购单发起人修改为供应商的采购员

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1697?initial=true
2024-12-31 16:01:03 +08:00
胡尧
281f3c67c3 特殊表面工艺外协采购单发起人修改为供应商的采购员 2024-12-31 16:00:24 +08:00
禹翔辉
641a669f46 Accept Merge Request #1696: (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/1696
2024-12-31 15:53:53 +08:00
yuxianghui
94b1c7d258 关闭报废入口 2024-12-31 15:50:51 +08:00
廖丹龙
b06b690ae9 Accept Merge Request #1695: (feature/part_number -> 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/1695
2024-12-31 14:05:55 +08:00
liaodanlong
37476bcc88 回退代码 2024-12-31 14:03:15 +08:00
管欢
af7eeb55f1 Accept Merge Request #1694: (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/1694
2024-12-31 13:32:34 +08:00
guanhuan
39ed32f3e9 修复成品调拨出库订单的状态没变 2024-12-31 13:08:00 +08:00
廖丹龙
79ec60bd6b Accept Merge Request #1693: (feature/part_number -> 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/1693
2024-12-31 12:55:17 +08:00
liaodanlong
4b7308fdcd sf-制造-外协工单-调拨单已取消问题 2024-12-31 12:54:16 +08:00
胡尧
198f1145d7 Accept Merge Request #1692: (feature/sale_order_route_pick -> develop)
Merge Request: 修改退回工艺设计后再确认,采购单编程草稿状态

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1692?initial=true
2024-12-31 11:40:03 +08:00
胡尧
64eb66c334 修改退回工艺设计后再确认,采购单编程草稿状态 2024-12-31 11:39:36 +08:00
禹翔辉
cff21a4bcc Accept Merge Request #1691: (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/1691?initial=true
2024-12-31 11:35:30 +08:00
yuxianghui
2373f33315 采购单源单据为入库单时,自动计算对应参考销售订单的值 2024-12-31 11:34:21 +08:00
禹翔辉
d6e2e554a8 Accept Merge Request #1690: (feature/采购单链接销售单 -> develop)
Merge Request: 采购订单的关联销售订单字段从销售模块搬迁到制造模块,并新增一个many2many类型字段,且对字段的自动计算方法进行优化。

Created By: @禹翔辉
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1690
2024-12-31 10:58:54 +08:00
yuxianghui
6c45a0bf4a Merge branch 'feature/入库单优化' into feature/采购单链接销售单 2024-12-31 10:57:09 +08:00
yuxianghui
4902fc5d9a 1、采购订单的关联销售订单字段从销售模块搬迁到制造模块,并新增一个many2many类型字段,且对字段的自动计算方法进行优化。 2024-12-31 10:56:07 +08:00
黄焱
9e5dbc0104 Accept Merge Request #1688: (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/1688?initial=true
2024-12-31 10:00:18 +08:00
管欢
c57918736d Accept Merge Request #1689: (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/1689
2024-12-31 10:00:01 +08:00
guanhuan
78a456849c 修复成品调拨出库订单的状态没变 2024-12-31 09:55:16 +08:00
hy
1816f1a497 修复表格对不齐问题 2024-12-31 09:45:56 +08:00
禹翔辉
da815c8ea1 Accept Merge Request #1686: (feature/入库单优化 -> develop)
Merge Request: 1、采购订单form页买家改名为采购员;2、优化成品入库单的的坯料委外加工链接;

Created By: @禹翔辉
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1686
2024-12-31 08:57:15 +08:00
yuxianghui
32e3c2f79f 采购订单源文档字段名称改为源单据 2024-12-31 08:56:41 +08:00
胡尧
c478b72e04 Accept Merge Request #1687: (feature/sale_order_route_pick -> develop)
Merge Request: 创建成品时从模板上获取供应商价格

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1687?initial=true
2024-12-31 08:54:23 +08:00
胡尧
78b0529809 创建成品时从模板上获取供应商价格 2024-12-31 08:54:02 +08:00
yuxianghui
17ffac63cb Merge branch 'feature/夹具查询优化_2' into feature/入库单优化 2024-12-31 08:48:50 +08:00
yuxianghui
acee32cc39 1、采购订单form页买家改名为采购员;2、优化成品入库单的的坯料委外加工链接; 2024-12-31 08:47:44 +08:00
马广威
b36cf745c2 Accept Merge Request #1685: (feature/制造功能优化 -> develop)
Merge Request: 添加提交审批的通知消息

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1685?initial=true
2024-12-30 21:38:17 +08:00
mgw
a24279f6e6 添加提交审批的通知消息 2024-12-30 21:37:10 +08:00
马广威
68b89999a9 Accept Merge Request #1684: (feature/制造功能优化 -> develop)
Merge Request: 修改展示名称

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1684?initial=true
2024-12-30 20:29:57 +08:00
mgw
7c38c7f643 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2024-12-30 20:28:49 +08:00
mgw
4937c3a812 修改展示名称 2024-12-30 20:27:57 +08:00
马广威
05469c71b8 Accept Merge Request #1683: (feature/制造功能优化 -> develop)
Merge Request: 修改展示名称

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1683?initial=true
2024-12-30 19:25:14 +08:00
mgw
210eea3b0b 修改展示名称 2024-12-30 19:24:45 +08:00
马广威
f58d1058f7 Accept Merge Request #1682: (feature/制造功能优化 -> develop)
Merge Request: Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1682?initial=true
2024-12-30 18:00:08 +08:00
mgw
0622d7525f Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2024-12-30 17:59:36 +08:00
mgw
7556c09ac2 增加活动项 2024-12-30 17:59:11 +08:00
禹翔辉
5344e97b7e Accept Merge Request #1681: (feature/夹具查询优化_2 -> develop)
Merge Request: Merge branch 'feature/成品调拨单优化_1' into feature/夹具查询优化_2

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1681?initial=true
2024-12-30 17:33:58 +08:00
yuxianghui
1b10b7bb53 Merge branch 'feature/成品调拨单优化_1' into feature/夹具查询优化_2 2024-12-30 17:32:28 +08:00
yuxianghui
9ab164f0fe 1 2024-12-30 17:31:22 +08:00
马广威
3b07b26303 Accept Merge Request #1680: (feature/制造功能优化 -> develop)
Merge Request: Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1680?initial=true
2024-12-30 17:28:41 +08:00
管欢
29a32be8d2 Accept Merge Request #1679: (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/1679
2024-12-30 17:28:15 +08:00
mgw
3620412a13 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2024-12-30 17:27:46 +08:00
mgw
5e72e3d1dd 审批明细问题 2024-12-30 17:27:00 +08:00
guanhuan
4137b304f3 消息提醒 2024-12-30 17:25:32 +08:00
马广威
caac651ab4 Accept Merge Request #1678: (feature/制造功能优化 -> develop)
Merge Request: Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1678?initial=true
2024-12-30 17:12:01 +08:00
mgw
30e496442f Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2024-12-30 17:11:31 +08:00
mgw
c28c00a47b 调整description 2024-12-30 17:11:08 +08:00
禹翔辉
4f4fdeecb5 Accept Merge Request #1677: (feature/成品调拨单优化_1 -> develop)
Merge Request: 1、询价单的确认按钮权限添加;2、成品调拨单添加对应的坯料采购单和坯料外协单跳转链接

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1677?initial=true
2024-12-30 17:07:07 +08:00
yuxianghui
8742f9b98b Merge branch 'feature/成品调拨单优化' into feature/成品调拨单优化_1 2024-12-30 17:05:45 +08:00
yuxianghui
d7ce69f474 1、询价单的确认按钮权限添加;2、成品调拨单添加对应的坯料采购单和坯料外协单跳转链接 2024-12-30 17:04:59 +08:00
胡尧
cf46cff7e5 Accept Merge Request #1676: (feature/sale_order_route_pick -> develop)
Merge Request: 屏蔽前端代码

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1676?initial=true
2024-12-30 16:33:41 +08:00
胡尧
c124e2962c 屏蔽前端代码 2024-12-30 16:32:36 +08:00
管欢
f4312c4d4e Accept Merge Request #1675: (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/1675
2024-12-30 16:20:37 +08:00
guanhuan
5928456ffe 提示优化 2024-12-30 16:19:17 +08:00
马广威
305ea9dff7 Accept Merge Request #1674: (feature/制造功能优化 -> develop)
Merge Request: Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1674?initial=true
2024-12-30 16:04:59 +08:00
mgw
bdfc393099 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2024-12-30 16:04:10 +08:00
mgw
1e1bd63acf 调整提示语句格式 2024-12-30 16:03:46 +08:00
马广威
fa20bb6eb5 Accept Merge Request #1673: (feature/制造功能优化 -> develop)
Merge Request: sf-询价单-新增状态及修改未审批的提示语句

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1673?initial=true
2024-12-30 15:51:19 +08:00
mgw
c82db7159d sf-询价单-新增状态及修改未审批的提示语句 2024-12-30 15:50:25 +08:00
廖丹龙
89d6752012 Accept Merge Request #1672: (feature/part_number -> 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/1672
2024-12-30 15:40:36 +08:00
liaodanlong
3060b35ab2 销售订单交付状态修改 2024-12-30 15:38:43 +08:00
廖丹龙
17ad976a32 Accept Merge Request #1671: (feature/part_number -> 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/1671
2024-12-30 15:28:57 +08:00
liaodanlong
9f3b351544 sf-工序外协调拨单-外协出库单多生成了一张外协出库调拨单 2024-12-30 15:25:20 +08:00
黄焱
5dc7dc8e0a Accept Merge Request #1670: (feature/前端样式修改 -> develop)
Merge Request: 修复会计列表表头少了列bug

Created By: @黄焱
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @黄焱
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1670?initial=true
2024-12-30 14:40:22 +08:00
hy
f1868168af 修复会计列表表头少了列bug 2024-12-30 14:38:45 +08:00
guanhuan
f084b5d765 提示优化 2024-12-30 14:12:54 +08:00
guanhuan
854c3ceef2 提示优化 2024-12-30 13:51:31 +08:00
管欢
4269ce58db Accept Merge Request #1668: (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/1668?initial=true
2024-12-30 11:37:04 +08:00
guanhuan
3555be86c6 提示优化 2024-12-30 11:35:08 +08:00
廖丹龙
764472111f Accept Merge Request #1667: (feature/part_number -> 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/1667?initial=true
2024-12-30 10:31:05 +08:00
liaodanlong
ce4fc8b8ab 批量调拨 2024-12-30 10:29:29 +08:00
马广威
67f4917491 Accept Merge Request #1666: (feature/制造功能优化 -> develop)
Merge Request: Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1666?initial=true
2024-12-30 10:02:51 +08:00
mgw
ad885f1e39 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2024-12-30 10:02:09 +08:00
mgw
993d720c40 sf-采购询价单【上传合同】按钮展示条件修改 2024-12-30 10:01:43 +08:00
禹翔辉
da75a8cd35 Accept Merge Request #1665: (feature/夹具物料查询优化_1 -> develop)
Merge Request: 调整托盘解绑修改顺序

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1665
2024-12-30 09:59:32 +08:00
yuxianghui
b35f842915 调整托盘解绑修改顺序 2024-12-30 09:57:36 +08:00
guanhuan
4e7993d035 追溯参考号 2024-12-30 09:56:49 +08:00
禹翔辉
946f02003e Accept Merge Request #1664: (feature/夹具物料查询优化_1 -> develop)
Merge Request: 添加点击工单的解绑托盘按钮时,修改对应托盘状态为空闲

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1664?initial=true
2024-12-30 09:54:58 +08:00
yuxianghui
435315a166 Merge branch 'feature/夹具物料查询优化' into feature/夹具物料查询优化_1 2024-12-30 09:53:49 +08:00
yuxianghui
676f8eb7eb 添加点击工单的解绑托盘按钮时,修改对应托盘状态为空闲 2024-12-30 09:52:32 +08:00
管欢
6e9f66506a Accept Merge Request #1663: (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/1663
2024-12-30 09:48:30 +08:00
guanhuan
f3e08f5ccc 新增零件名称,零件图号 2024-12-30 09:43:20 +08:00
廖丹龙
c9d7d70d3c Accept Merge Request #1662: (feature/part_number -> 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/1662?initial=true
2024-12-30 09:41:08 +08:00
liaodanlong
ee6e457bbd 委外加工采购单与制造订单进行关联 2024-12-30 09:38:51 +08:00
guanhuan
ab5b4c477f 新增零件名称,零件图号 2024-12-30 09:33:00 +08:00
mgw
9330be3753 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2024-12-30 08:57:49 +08:00
mgw
a3a2c96d00 添加紧急采购字段 2024-12-30 08:57:05 +08:00
禹翔辉
31187755b9 Accept Merge Request #1661: (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/1661
2024-12-30 08:42:16 +08:00
yuxianghui
178f538997 Merge branch 'feature/销售、采购页面优化' into feature/夹具物料查询优化 2024-12-30 08:34:58 +08:00
马广威
304f6ad5ba Accept Merge Request #1659: (feature/part_number -> develop)
Merge Request: 销售订单交付状态修改

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1659?initial=true
2024-12-28 14:55:55 +08:00
liaodanlong
8b40714dad 销售订单交付状态修改 2024-12-28 14:55:17 +08:00
马广威
cb8e415e60 Accept Merge Request #1658: (feature/part_number -> 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/1658
2024-12-28 14:30:47 +08:00
liaodanlong
889049b107 表面工艺确认回退再重新确认调拨单报错问题 2024-12-28 14:28:34 +08:00
廖丹龙
610028c5f4 Accept Merge Request #1657: (feature/part_number -> develop)
Merge Request: sorted_workorders变量过滤

Created By: @廖丹龙
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @廖丹龙
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1657
2024-12-28 09:13:42 +08:00
liaodanlong
abfac28094 sorted_workorders变量过滤 2024-12-28 09:12:27 +08:00
廖丹龙
24d8d37e0a Accept Merge Request #1656: (feature/part_number -> develop)
Merge Request: sorted_workorders变量定义

Created By: @廖丹龙
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @廖丹龙
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1656?initial=true
2024-12-28 09:08:20 +08:00
liaodanlong
6780d4e758 sorted_workorders变量定义 2024-12-28 09:07:02 +08:00
马广威
a1d4e74056 Accept Merge Request #1655: (feature/制造功能优化 -> develop)
Merge Request: Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1655?initial=true
2024-12-28 08:26:44 +08:00
mgw
3c8fbcf9f9 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2024-12-28 08:24:55 +08:00
mgw
c0bb07efb2 修改提示方式 2024-12-28 08:24:31 +08:00
yuxianghui
675fb54d37 夹具物料查询优化 2024-12-27 17:28:24 +08:00
廖丹龙
ead54cfc87 Accept Merge Request #1654: (feature/part_number -> 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/1654
2024-12-27 17:08:40 +08:00
liaodanlong
e990f24615 两张外协工单报错问题 2024-12-27 16:21:36 +08:00
胡尧
dc871e0a1d Accept Merge Request #1653: (feature/sale_order_route_pick -> develop)
Merge Request: 修改消息通知

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1653
2024-12-27 13:57:06 +08:00
胡尧
f71246e9fb 解决冲突 2024-12-27 13:56:41 +08:00
胡尧
133c1a87f2 修改消息通知 2024-12-27 13:53:10 +08:00
管欢
6f14a39347 Accept Merge Request #1652: (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/1652
2024-12-26 17:18:09 +08:00
guanhuan
6e2ee60616 工单已下发提醒 2024-12-26 17:15:48 +08:00
马广威
3efb30cece Accept Merge Request #1651: (feature/制造功能优化 -> develop)
Merge Request: 修改确认订单时的判定逻辑,调整提示词

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1651?initial=true
2024-12-26 16:35:57 +08:00
mgw
e56df3d7b9 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2024-12-26 16:34:11 +08:00
mgw
253a06ceaf 修改确认订单时的判定逻辑,调整提示词 2024-12-26 16:33:43 +08:00
禹翔辉
28c6c841be Accept Merge Request #1650: (feature/销售、采购页面优化 -> develop)
Merge Request: 1、订单详情字段显示优化;2、采购单页面优化

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1650?initial=true
2024-12-26 16:32:56 +08:00
yuxianghui
f948bf445a Merge branch 'feature/无效刀自动返工优化' into feature/销售、采购页面优化 2024-12-26 16:29:27 +08:00
yuxianghui
1b278a1432 1、订单详情字段显示优化;2、采购单页面优化 2024-12-26 16:28:39 +08:00
马广威
3fcb3b250f Accept Merge Request #1649: (feature/制造功能优化 -> develop)
Merge Request: Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1649?initial=true
2024-12-26 15:44:28 +08:00
mgw
57c689b03b Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2024-12-26 15:43:51 +08:00
mgw
158ca95dbb 去掉对审批的跳过 2024-12-26 15:42:43 +08:00
guanhuan
e059d9266d 坯料发料提醒 2024-12-26 15:26:12 +08:00
马广威
8de2a59b88 Accept Merge Request #1648: (feature/制造功能优化 -> develop)
Merge Request: Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1648?initial=true
2024-12-26 14:48:01 +08:00
mgw
9ac60ae283 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2024-12-26 14:47:20 +08:00
mgw
07356b5bb2 sf-询价单-【发起审批】按钮,及必填字段问题 2024-12-26 14:46:17 +08:00
禹翔辉
96c79a78ab Accept Merge Request #1647: (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/1647?initial=true
2024-12-26 13:55:49 +08:00
yuxianghui
b03eafcf94 取消自动返工时修改制造订单状态 2024-12-26 13:54:59 +08:00
禹翔辉
0b7d7959c5 Accept Merge Request #1646: (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/1646
2024-12-26 13:25:05 +08:00
yuxianghui
40865b7c6c 取消制造订单功能刀具状态为无效刀时自动返工修改制造订单的状态; 2024-12-26 13:24:04 +08:00
马广威
8abb6447d2 Accept Merge Request #1645: (feature/制造功能优化 -> develop)
Merge Request: 调整按钮位置

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1645?initial=true
2024-12-26 13:17:33 +08:00
mgw
394c3f9870 调整按钮位置 2024-12-26 13:16:04 +08:00
马广威
b254624d68 Accept Merge Request #1644: (feature/制造功能优化 -> develop)
Merge Request: Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1644
2024-12-26 11:28:47 +08:00
mgw
87b2c0b0f8 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2024-12-26 11:22:53 +08:00
mgw
b0e993dd53 完善采购合同上传功能 2024-12-26 11:22:16 +08:00
廖丹龙
79183761ae Accept Merge Request #1642: (feature/part_number -> 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/1642
2024-12-26 10:20:43 +08:00
liaodanlong
c448088906 采购单关联产品 2024-12-26 10:18:17 +08:00
禹翔辉
a7a1779e61 Accept Merge Request #1643: (feature/销售订单优化 -> develop)
Merge Request: 1、采购入库,选取目标货位去重校验优化;2、添加功能刀具自动计算当前目标货位的值;

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1643?initial=true
2024-12-26 10:03:13 +08:00
yuxianghui
06842c6df9 1、采购入库,选取目标货位去重校验优化;2、添加功能刀具自动计算当前目标货位的值; 2024-12-26 10:01:42 +08:00
liaodanlong
6532af500f 质量检测添加零件图号与零件名称 2024-12-26 08:57:31 +08:00
liaodanlong
1fb88960db Merge branch 'refs/heads/develop' into feature/part_number 2024-12-25 17:29:48 +08:00
liaodanlong
4c8071fea2 多制造订单生成工艺有误 2024-12-25 17:16:30 +08:00
禹翔辉
4aac3d42b6 Accept Merge Request #1641: (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/1641?initial=true
2024-12-25 17:14:44 +08:00
yuxianghui
0f4d25abb4 Merge branch 'feature/工单按钮优化' into feature/销售订单优化 2024-12-25 17:13:24 +08:00
yuxianghui
14cc285ee2 1、销售订单供货方式为委外加工时生成的采购单问题优化 2024-12-25 17:12:38 +08:00
廖丹龙
54b896004b Accept Merge Request #1640: (feature/part_number -> 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/1640?initial=true
2024-12-25 15:16:26 +08:00
liaodanlong
7a1237ddf8 时间获取修改 2024-12-25 15:14:07 +08:00
廖丹龙
f80aaf978b Accept Merge Request #1639: (feature/part_number -> 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/1639
2024-12-25 14:57:16 +08:00
liaodanlong
64f35b5633 工艺确认统一工艺设计 2024-12-25 14:49:05 +08:00
禹翔辉
9e887076f2 Accept Merge Request #1638: (feature/工单按钮优化 -> develop)
Merge Request: 1、制造订单状态优化

Created By: @禹翔辉
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1638?initial=true
2024-12-25 14:20:31 +08:00
yuxianghui
78fff46452 1、制造订单状态优化 2024-12-25 14:16:34 +08:00
禹翔辉
a6d4f99710 Accept Merge Request #1637: (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/1637?initial=true
2024-12-25 13:22:25 +08:00
yuxianghui
05f1f1a983 去除工单多余的开始按钮 2024-12-25 13:13:38 +08:00
禹翔辉
f719135abb Accept Merge Request #1636: (feature/制造、采购优化 -> develop)
Merge Request: 1、处理制造订单返工确认后,状态还是返工的bug;2、隐藏已取消状态的采购单【确认订单】按钮

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1636?initial=true
2024-12-25 13:05:14 +08:00
yuxianghui
82983871fc Merge branch 'feature/制造订单优化' into feature/制造、采购优化 2024-12-25 13:03:44 +08:00
yuxianghui
7f17ff8b78 1、处理制造订单返工确认后,状态还是返工的bug;2、隐藏已取消状态的采购单【确认订单】按钮 2024-12-25 13:02:49 +08:00
胡尧
9efece315f Accept Merge Request #1635: (feature/sale_order_route_pick -> develop)
Merge Request: 解决手工创建表面工艺采购单由于没有源单据报错

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1635?initial=true
2024-12-25 11:32:36 +08:00
胡尧
d82cb1e64c 解决手工创建表面工艺采购单由于没有源单据报错 2024-12-25 11:31:27 +08:00
mgw
7ab2894ae8 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2024-12-25 11:02:29 +08:00
mgw
0991888494 采购合同上传基础功能 2024-12-25 11:02:00 +08:00
禹翔辉
42937bcf76 Accept Merge Request #1634: (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/1634
2024-12-25 09:43:29 +08:00
yuxianghui
32fb6eadbc 1 2024-12-25 09:43:04 +08:00
yuxianghui
5a1ebabc87 处理没有工单时,制造订单就已经完成的问题 2024-12-25 09:41:07 +08:00
马广威
57f51d7cfa Accept Merge Request #1633: (feature/制造功能优化 -> develop)
Merge Request: 询价单字段排版及增加逻辑验证

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1633?initial=true
2024-12-24 20:42:18 +08:00
mgw
d2ec0cacc3 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2024-12-24 17:27:36 +08:00
mgw
aaf3b20e65 询价单字段排版及增加逻辑验证 2024-12-24 17:27:08 +08:00
禹翔辉
5912a170f1 Accept Merge Request #1632: (feature/制造订单优化 -> develop)
Merge Request: 1、制造订单隐藏不必的取消按钮、添加取消按钮的隐藏条件;2、添加返工完成后制造订单状态置为加工中

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1632
2024-12-24 17:21:36 +08:00
yuxianghui
ed3feaf2a0 优化制造订单状态方法 2024-12-24 17:17:53 +08:00
yuxianghui
d953f4e4a0 Merge branch 'feature/采购、外协优化' into feature/制造订单优化 2024-12-24 16:48:19 +08:00
yuxianghui
c2d346282c 1、制造订单隐藏不必的取消按钮、添加取消按钮的隐藏条件;2、添加返工完成后制造订单状态置为加工中 2024-12-24 16:47:10 +08:00
管欢
9d85f56af3 Accept Merge Request #1631: (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/1631
2024-12-24 15:00:25 +08:00
guanhuan
78eea6aad0 消息提醒 2024-12-24 14:49:17 +08:00
廖丹龙
5306e45f83 Accept Merge Request #1630: (feature/part_number -> 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/1630?initial=true
2024-12-24 09:08:58 +08:00
liaodanlong
4bd40aeeb0 工艺确认报错问题解决 2024-12-24 09:07:11 +08:00
禹翔辉
f6d69ea193 Accept Merge Request #1629: (feature/采购、外协优化 -> develop)
Merge Request: 1、采购单的采购类型优化,外协优化

Created By: @禹翔辉
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1629?initial=true
2024-12-23 17:15:43 +08:00
yuxianghui
fe5990ff9a Merge branch 'feature/制造、采购、工单优化' into feature/采购、外协优化 2024-12-23 17:14:00 +08:00
yuxianghui
6db5e72752 1、采购单的采购类型优化,外协优化 2024-12-23 17:13:12 +08:00
廖丹龙
62fcc93a21 Accept Merge Request #1628: (feature/part_number -> 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/1628?initial=true
2024-12-23 15:44:40 +08:00
liaodanlong
d6c8120b7c 工艺确认创建工单通过工艺设计排序再进行数据生成 2024-12-23 15:42:07 +08:00
管欢
20994e6656 Accept Merge Request #1627: (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/1627
2024-12-23 14:27:24 +08:00
禹翔辉
7a64851761 Accept Merge Request #1626: (feature/制造、采购、工单优化 -> develop)
Merge Request: 1、优化销售订单状态;2、优化夹具物料查询的托盘可用状态;3、优化工单开始按键;4、优化采购订单的采购类型,根据销售订单的供货方式和工艺确认时是否外协自动选择对应采购类型;

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1626
2024-12-23 14:22:58 +08:00
guanhuan
88f3155132 Merge remote-tracking branch 'refs/remotes/origin/develop' into feature/消息提醒优化
# Conflicts:
#	sf_sale/views/purchase_order_view.xml
2024-12-23 14:06:11 +08:00
yuxianghui
8bd2250d45 Merge branch 'feature/工单rfid优化' into feature/制造、采购、工单优化 2024-12-23 13:47:22 +08:00
yuxianghui
0e7e7af85a 1、优化销售订单状态;2、优化夹具物料查询的托盘可用状态;3、优化工单开始按键;4、优化采购订单的采购类型,根据销售订单的供货方式和工艺确认时是否外协自动选择对应采购类型; 2024-12-23 13:46:30 +08:00
yuxianghui
098e8c2518 工单工序优化 2024-12-20 17:22:56 +08:00
guanhuan
5a06811732 发送消息 2024-12-20 16:12:30 +08:00
guanhuan
c4b02f7717 发送消息 2024-12-20 15:31:55 +08:00
廖丹龙
a2f29766e6 Accept Merge Request #1625: (feature/part_number -> 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/1625
2024-12-20 15:25:27 +08:00
liaodanlong
091b9940ef 零件图号零件名称 2024-12-20 14:59:26 +08:00
liaodanlong
c0db279414 Merge branch 'refs/heads/develop' into feature/part_number
# Conflicts:
#	sf_manufacturing/models/purchase_order.py
2024-12-20 14:56:46 +08:00
liaodanlong
41096c9c65 零件图号零件名称 2024-12-20 14:55:04 +08:00
guanhuan
bf227e3e92 交期状态 2024-12-20 14:33:23 +08:00
胡尧
fa9ed5885b Accept Merge Request #1624: (feature/sale_order_route_pick -> develop)
Merge Request: 修复 工艺外协工序采购单已创建账单并且过账,退回调整删除后报错的问题

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1624?initial=true
2024-12-20 14:16:59 +08:00
胡尧
c8df5ed179 修复 工艺外协工序采购单已创建账单并且过账,退回调整删除后报错的问题 2024-12-20 14:16:25 +08:00
guanhuan
9d883d112c 消息提醒 2024-12-20 13:51:11 +08:00
胡尧
142b94139c Accept Merge Request #1623: (feature/sale_order_route_pick -> develop)
Merge Request: 选择工序时,排除已经选择的工序

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1623?initial=true
2024-12-20 13:02:37 +08:00
胡尧
2a20d54530 选择工序时,排除已经选择的工序 2024-12-20 13:02:10 +08:00
胡尧
f2e8d0175b 选择工序时,排除已经选择的工序 2024-12-20 12:51:42 +08:00
禹翔辉
690e8ca1b2 Accept Merge Request #1622: (feature/工单rfid优化 -> develop)
Merge Request: 1、处理工单返工时就解除rfid绑定问题;2、同步bfm的订单状态到销售订单 

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1622?initial=true
2024-12-20 11:09:07 +08:00
yuxianghui
18073cb726 Merge branch 'feature/制造、工单优化' into feature/工单rfid优化 2024-12-20 11:07:48 +08:00
yuxianghui
bdac1e7460 1、处理工单返工时就解除rfid绑定问题;2、同步bfm的订单状态到销售订单 2024-12-20 11:06:41 +08:00
廖丹龙
8cfccfb2e0 Accept Merge Request #1621: (feature/delivery_status -> 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/1621?initial=true
2024-12-20 10:36:46 +08:00
禹翔辉
283950db39 Accept Merge Request #1620: (feature/制造、工单优化 -> develop)
Merge Request: 1、隐藏返工状态工单的开始按钮;2、优化工单状态方法;3、优化制造订单状态

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1620
2024-12-19 17:22:40 +08:00
yuxianghui
9cb1cff671 Merge branch 'feature/销售、制造、返工优化' into feature/制造、工单优化 2024-12-19 17:21:04 +08:00
yuxianghui
03dbeaf988 1、隐藏返工状态工单的开始按钮;2、优化工单状态方法;3、优化制造订单状态 2024-12-19 17:14:48 +08:00
胡尧
bef8ba46cd Accept Merge Request #1619: (feature/sale_order_route_pick -> develop)
Merge Request: 增加agv配送重新下发与取消

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1619?initial=true
2024-12-19 17:02:34 +08:00
胡尧
23afbc14c9 增加agv配送重新下发与取消 2024-12-19 17:00:40 +08:00
guanhuan
72bf8ad011 消息提醒 2024-12-19 14:36:16 +08:00
禹翔辉
93b87ec8ff Accept Merge Request #1618: (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/1618?initial=true
2024-12-19 13:47:26 +08:00
yuxianghui
d4fb6ef049 Merge branch 'feature/返工、工序优化' into feature/销售、制造、返工优化 2024-12-19 13:46:01 +08:00
yuxianghui
97facdaf9c 1、销售订单状态添加【加工中】、【物流中】、【已交付】三种状态;2、优化 获取mrs下发的编程单 接口,添加对返工重新编程的处理 2024-12-19 13:45:10 +08:00
guanhuan
5eda4427df 消息提醒 2024-12-19 13:09:20 +08:00
马广威
6b2b792df8 Accept Merge Request #1617: (feature/制造功能优化 -> develop)
Merge Request: sf-创建员工时提示员工已存在

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1617?initial=true
2024-12-18 16:58:50 +08:00
mgw
aad68b23ac Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2024-12-18 16:56:53 +08:00
mgw
ff91aa1ad6 sf-创建员工时提示员工已存在 2024-12-18 16:56:26 +08:00
yuxianghui
15eb36a5bc 1、优化销售订单列表页、详情页字段显示;2、优化新增采购订单列表页、详情页字段显示; 2024-12-18 16:39:54 +08:00
guanhuan
79d188fb5c 消息提醒 2024-12-18 16:26:28 +08:00
guanhuan
42444e6c83 消息提醒 2024-12-17 17:21:36 +08:00
guanhuan
d7a25580d1 消息提醒 2024-12-17 14:42:15 +08:00
guanhuan
1da3989fa3 消息提醒 2024-12-17 11:34:24 +08:00
yuxianghui
202fafac84 采购模块界面优化、采购类型新增【工序外协】、【外购订单】选项 2024-12-16 17:22:39 +08:00
yuxianghui
2b9a44761f 1、采购单详情页添加销售订单号关联字段,关联跳转至对应销售订单;2、采购页面优化 2024-12-13 17:03:45 +08:00
管欢
d24b0e8af8 Accept Merge Request #1616: (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/1616
2024-12-13 16:29:45 +08:00
guanhuan
b551777d49 逾期工单不能批量重新安排的优化需求 2024-12-13 16:24:25 +08:00
yuxianghui
3253b26818 1、报价、销售订单列表视图添加平台订单号字段。2、销售订单详情的采购链接按采购类型拆分为委外加工和采购的跳转链接; 2024-12-13 13:38:22 +08:00
liaodanlong
9f67dbe9aa 工序外协工单没有自动触发工单开始、结束的优化需求处理 2024-12-12 16:06:55 +08:00
guanhuan
01fa7bbe87 批量重新安排 2024-12-12 14:39:10 +08:00
廖丹龙
e8644962c5 Accept Merge Request #1614: (feature/delivery_status -> 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/1614?initial=true
2024-12-12 09:32:37 +08:00
guanhuan
c793089131 工艺确认弹框优化 2024-12-12 09:29:48 +08:00
禹翔辉
8fe7a47367 Accept Merge Request #1615: (feature/返工、工序优化 -> develop)
Merge Request: 1、制造订单点击返工按钮添加新的过滤条件;2、优化工单工序逻辑;3、返工添加校验限制条件;

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1615
2024-12-11 17:27:19 +08:00
yuxianghui
b7e35ce5e5 Merge branch 'feature/制造、销售、采购优化' into feature/返工、工序优化 2024-12-11 17:25:24 +08:00
yuxianghui
7c17241882 1、制造订单点击返工按钮添加新的过滤条件;2、优化工单工序逻辑;3、返工添加校验限制条件; 2024-12-11 17:24:32 +08:00
liaodanlong
ab32f881c2 制造订单退回调整删除表面工艺再次确认后-没被删除的表面工艺的外协出入库单变成了草稿状态问题处理 2024-12-11 17:09:51 +08:00
廖丹龙
b06becead4 Accept Merge Request #1613: (feature/delivery_status -> 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/1613
2024-12-11 11:23:34 +08:00
liaodanlong
f32ca13dff 修改日志的使用库 2024-12-11 11:05:25 +08:00
禹翔辉
83028b3b3d Accept Merge Request #1612: (feature/制造、销售、采购优化 -> develop)
Merge Request: 1、去除工单页面的时效状态自动筛选项;2、坯料制造订单添加批量确认加工工艺功能;3、处理返工新生成的工单工序错误问题;4、采购、销售页面优化

Created By: @禹翔辉
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1612
2024-12-11 10:36:24 +08:00
yuxianghui
ad74fd989b Merge branch 'feature/返工入口' into feature/制造、销售、采购优化 2024-12-11 10:34:09 +08:00
yuxianghui
179ce86bef 1、去除工单页面的时效状态自动筛选项;2、坯料制造订单添加批量确认加工工艺功能;3、处理返工新生成的工单工序错误问题;4、采购、销售页面优化 2024-12-11 10:33:10 +08:00
廖丹龙
1b321b424e Accept Merge Request #1611: (feature/delivery_status -> 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/1611
2024-12-11 10:16:19 +08:00
liaodanlong
d1ba2cc3d4 Merge branch 'refs/heads/develop' into feature/delivery_status
# Conflicts:
#	sf_manufacturing/models/mrp_production.py
2024-12-11 10:07:34 +08:00
liaodanlong
4738b03a45 销售订单与制造订单关联 2024-12-11 10:03:20 +08:00
guanhuan
83e57b63ec 报废新生成的制造订单没关联新采购单 2024-12-10 17:18:33 +08:00
禹翔辉
e14e750bd9 Accept Merge Request #1610: (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/1610?initial=true
2024-12-09 16:08:52 +08:00
yuxianghui
1c4a6ca85e 开放返工入口 2024-12-09 16:07:34 +08:00
管欢
c922ae1571 Accept Merge Request #1609: (feature/manufactur_order -> 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/1609
2024-12-09 09:48:12 +08:00
guanhuan
ed6189a963 Merge remote-tracking branch 'origin/feature/manufactur_order' into feature/manufactur_order 2024-12-09 09:36:08 +08:00
guanhuan
a6979b213b 手动创建的采购单生成的内部调拨单没有源单据 2024-12-09 09:35:41 +08:00
马广威
f873ebe079 Accept Merge Request #1608: (release/release_2.6 -> develop)
Merge Request: Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1608
2024-12-05 18:26:29 +08:00
mgw
ab692dfb25 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2024-12-05 18:25:08 +08:00
马广威
e50b601ccf Accept Merge Request #1607: (feature/制造功能优化 -> develop)
Merge Request: 对合并后的采购单修改匹配逻辑

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1607?initial=true
2024-12-05 18:15:09 +08:00
mgw
37c47b0a54 对合并后的采购单修改匹配逻辑 2024-12-05 18:14:19 +08:00
马广威
6f9cea2759 Accept Merge Request #1606: (feature/制造功能优化 -> develop)
Merge Request: 特殊表面工艺采购单还是有合并的情况-且重复了

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1606?initial=true
2024-12-05 17:03:08 +08:00
mgw
0601e123fb Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2024-12-05 17:01:36 +08:00
mgw
08e4541a96 特殊表面工艺采购单还是有合并的情况-且重复了 2024-12-05 17:01:10 +08:00
胡尧
66acc19e89 Accept Merge Request #1605: (feature/sale_order_route_pick -> develop)
Merge Request: 工艺设计新增工序只选择了参数时确认增加提示

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1605?initial=true
2024-12-05 16:56:20 +08:00
胡尧
5b94a0624c 工艺设计新增工序只选择了参数时确认增加提示 2024-12-05 16:55:51 +08:00
胡尧
1b5b2fd6f9 Accept Merge Request #1604: (feature/sale_order_route_pick -> develop)
Merge Request: 处理供应商相同的特殊表面工艺不能删除的问题

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1604?initial=true
2024-12-05 16:36:55 +08:00
胡尧
54c502dd64 处理供应商相同的特殊表面工艺不能删除的问题 2024-12-05 16:36:33 +08:00
胡尧
e3db40ae25 Accept Merge Request #1603: (feature/sale_order_route_pick -> develop)
Merge Request: 解决删除表面工艺,多增加了采购单的bug

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1603
2024-12-05 15:09:49 +08:00
胡尧
52ab962ace 解决删除表面工艺,多增加了采购单的bug 2024-12-05 15:09:04 +08:00
胡尧
05247ee8d9 Accept Merge Request #1602: (feature/sale_order_route_pick -> develop)
Merge Request: 特殊表面工艺工单没有完成对应采购单时工单处于等待组件

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1602?initial=true
2024-12-05 13:42:33 +08:00
胡尧
dbf75684ee 特殊表面工艺工单没有完成对应采购单时工单处于等待组件 2024-12-05 13:42:07 +08:00
马广威
cb2319492b Accept Merge Request #1601: (feature/制造功能优化 -> develop)
Merge Request: 制造订单退回调整-删除表面工艺后对应的外协出入库单没有变成取消状态

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1601
2024-12-05 11:49:03 +08:00
mgw
731e6abc90 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化
# Conflicts:
#	sf_manufacturing/models/mrp_workorder.py
2024-12-05 11:48:07 +08:00
mgw
58b33b6c8d 制造订单退回调整-删除表面工艺后对应的外协出入库单没有变成取消状态 2024-12-05 11:05:43 +08:00
胡尧
43c8bbda71 Accept Merge Request #1600: (feature/sale_order_route_pick -> develop)
Merge Request: 解决表面工艺工单完成后,生产入库单未就绪的问题

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1600?initial=true
2024-12-05 09:32:00 +08:00
胡尧
e011e4cfd6 解决表面工艺工单完成后,生产入库单未就绪的问题 2024-12-05 09:31:06 +08:00
胡尧
c8fd2d69bd Accept Merge Request #1599: (feature/sale_order_route_pick -> develop)
Merge Request: 修改工艺外协工单

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1599?initial=true
2024-12-05 08:37:05 +08:00
胡尧
ef1f7b1d08 解决冲突 2024-12-05 08:36:48 +08:00
胡尧
5f12976d8f 修改表面工艺外协工单流程 2024-12-05 01:33:46 +08:00
胡尧
ef60f36c90 修改工艺外协工单 2024-12-04 20:42:34 +08:00
廖丹龙
c8ed45b1a7 Accept Merge Request #1598: (feature/manufactur_order -> 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/1598?initial=true
2024-12-04 16:43:58 +08:00
liaodanlong
57fe68bae8 Merge remote-tracking branch 'origin/feature/manufactur_order' into feature/manufactur_order 2024-12-04 16:42:13 +08:00
liaodanlong
aa32fdcd07 坯料长宽高修改 2024-12-04 16:41:42 +08:00
管欢
d0d59135e3 Accept Merge Request #1597: (feature/manufactur_order -> 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/1597
2024-12-04 16:39:44 +08:00
guanhuan
27ec5b1b74 多个制造订单菜单修复 2024-12-04 16:13:55 +08:00
禹翔辉
2c1caabce6 Accept Merge Request #1596: (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/1596
2024-12-04 15:41:11 +08:00
yuxianghui
8f3cd9ff36 Merge branch 'feature/隐藏返工入口' into feature/界面优化 2024-12-04 15:39:05 +08:00
yuxianghui
6366904c91 添加客供料入库单的合并选项 2024-12-04 15:37:58 +08:00
马广威
7f3e6de127 Accept Merge Request #1595: (feature/制造功能优化 -> develop)
Merge Request: 处理“制造订单退回调整删除特殊表面工艺后对应坯料的采购单也变成取消状态了”

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1595?initial=true
2024-12-04 12:24:18 +08:00
yuxianghui
5b43cceb94 计划模块的【制造订单生产计划】页面菜单名称改为【CNC产线计划排程】 2024-12-04 11:56:38 +08:00
mgw
d933416b2d 处理“制造订单退回调整删除特殊表面工艺后对应坯料的采购单也变成取消状态了” 2024-12-04 11:52:52 +08:00
yuxianghui
e260ef01f0 隐藏销售模块的 快速订单 菜单 2024-12-04 11:43:02 +08:00
廖丹龙
0fef3d7a63 Accept Merge Request #1594: (feature/manufactur_order -> 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/1594?initial=true
2024-12-04 10:49:12 +08:00
liaodanlong
dc5c0b1d1e Merge branch 'refs/heads/develop' into feature/manufactur_order 2024-12-04 10:46:38 +08:00
liaodanlong
9a1cde6abc 表面工艺采购单与调拨单拆分 2024-12-04 10:45:46 +08:00
胡尧
29864b8bb2 Accept Merge Request #1591: (feature/manufactur_order -> 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/1591
2024-12-04 10:23:35 +08:00
胡尧
aa5294f110 Accept Merge Request #1593: (feature/sale_order_route_pick -> develop)
Merge Request: 处理报错是英文的问题

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1593?initial=true
2024-12-04 10:23:19 +08:00
胡尧
4387d343b5 处理报错是英文的问题 2024-12-04 10:22:50 +08:00
胡尧
ff979aa34b Accept Merge Request #1592: (feature/sale_order_route_pick -> develop)
Merge Request: 解决外协调拨单不能完成的bug

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1592?initial=true
2024-12-04 10:17:34 +08:00
胡尧
21af368068 解决外协调拨单不能完成的bug 2024-12-04 10:16:30 +08:00
guanhuan
d6afd556d3 询价单查询 2024-12-03 15:59:10 +08:00
胡尧
778d2c4ec5 Accept Merge Request #1590: (feature/sale_order_route_pick -> develop)
Merge Request: 去掉多余的视图

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1590?initial=true
2024-12-03 10:04:29 +08:00
禹翔辉
fff29b36ee Accept Merge Request #1587: (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/1587
2024-12-03 10:04:23 +08:00
胡尧
fedb79a142 去掉多余的视图 2024-12-03 10:03:05 +08:00
胡尧
d06816052f Accept Merge Request #1589: (feature/sale_order_route_pick -> develop)
Merge Request: 修改文件位置

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1589?initial=true
2024-12-02 19:48:02 +08:00
胡尧
5739e167f4 修改文件位置 2024-12-02 19:46:45 +08:00
胡尧
a249548a20 Accept Merge Request #1588: (feature/sale_order_route_pick -> develop)
Merge Request: 修改文件位置

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1588?initial=true
2024-12-02 16:37:26 +08:00
胡尧
7b6538d01e 修改文件位置 2024-12-02 16:29:33 +08:00
yuxianghui
7025bde56e 隐藏手动返工报废入口 2024-12-02 13:46:20 +08:00
胡尧
3585af0cea Accept Merge Request #1586: (feature/sale_order_route_pick -> develop)
Merge Request: 调整文件结构

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1586?initial=true
2024-12-02 11:03:46 +08:00
胡尧
5406224c6f 调整文件结构 2024-12-02 11:02:32 +08:00
胡尧
18ff0bba54 Accept Merge Request #1585: (feature/sale_order_route_pick -> develop)
Merge Request: 调整文件结构

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1585?initial=true
2024-12-02 10:36:36 +08:00
胡尧
7c13e57ea2 调整文件结构 2024-12-02 10:36:06 +08:00
胡尧
b8605b9a97 Accept Merge Request #1584: (feature/sale_order_route_pick -> develop)
Merge Request: 调整文件结构,解决依赖问题

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1584?initial=true
2024-12-02 10:07:11 +08:00
胡尧
4baa7a9b44 调整文件结构,解决依赖问题 2024-12-02 10:06:11 +08:00
黄焱
3af2f3e03b Accept Merge Request #1583: (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/1583?initial=true
2024-11-29 16:27:46 +08:00
hy
dc68ecb584 计划排程列表和工单列表筛选项和数量显示重叠了 2024-11-29 16:26:32 +08:00
马广威
421f107728 Accept Merge Request #1582: (feature/制造功能优化 -> develop)
Merge Request: 调整库存概览翻译

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1582?initial=true
2024-11-29 15:59:40 +08:00
mgw
1f1bdd08ed 调整库存概览翻译 2024-11-29 15:59:04 +08:00
黄焱
1a7059aad1 Accept Merge Request #1581: (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/1581
2024-11-29 14:40:43 +08:00
hy
8d461e61b3 甘特图增加判断 2024-11-29 14:37:48 +08:00
马广威
fa0ca83709 Accept Merge Request #1580: (feature/制造功能优化 -> develop)
Merge Request: 调整内部转账翻译

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1580?initial=true
2024-11-29 14:33:46 +08:00
mgw
a783f9c271 调整内部转账翻译 2024-11-29 14:32:58 +08:00
胡尧
b4901e89d6 Accept Merge Request #1579: (feature/sale_order_route_pick -> develop)
Merge Request: 权限调整

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1579
2024-11-29 14:15:06 +08:00
胡尧
6690d3f2cb 权限调整 2024-11-29 14:14:14 +08:00
马广威
21d6989182 Accept Merge Request #1578: (feature/制造功能优化 -> develop)
Merge Request: 调整计划调度岗对工单的权限

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1578?initial=true
2024-11-29 11:30:30 +08:00
mgw
97ad3567e3 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2024-11-29 11:24:50 +08:00
mgw
22a69df31b 调整计划调度岗对工单的权限 2024-11-29 11:24:27 +08:00
胡尧
c0ad9d8977 Accept Merge Request #1577: (feature/sale_order_route_pick -> develop)
Merge Request: 解决单个制造的bug

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1577?initial=true
2024-11-29 10:49:24 +08:00
胡尧
a927d0e9cb 解决单个制造的bug 2024-11-29 10:44:48 +08:00
杨金灵
5759ca1ca5 Accept Merge Request #1576: (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/1576
2024-11-29 10:07:57 +08:00
jinling.yang
9955157dd3 还原代码 2024-11-29 10:07:17 +08:00
jinling.yang
d42de42709 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/修复外协出入库单 2024-11-29 10:04:23 +08:00
jinling.yang
a7dc3a1227 修复表面外协 2024-11-29 10:03:44 +08:00
胡尧
9c5f525e90 Accept Merge Request #1575: (feature/sale_order_route_pick -> develop)
Merge Request: 处理工单中的工艺外协按钮点击报错的问题

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1575?initial=true
2024-11-29 09:45:38 +08:00
胡尧
db8bd659c3 处理工单中的工艺外协按钮点击报错的问题 2024-11-29 09:45:06 +08:00
胡尧
0dab394d1b Accept Merge Request #1574: (feature/sale_order_route_pick -> develop)
Merge Request: 解决精坯料计算精度问题,排程加上预留时间

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1574?initial=true
2024-11-29 09:00:32 +08:00
胡尧
9a9e47b4ff 解决精坯料计算精度问题,排程加上预留时间 2024-11-29 08:59:52 +08:00
jinling.yang
deb2f6ca64 修复采购 2024-11-28 18:01:29 +08:00
禹翔辉
5bce9bb816 Accept Merge Request #1573: (feature/坯料制造序号优化 -> develop)
Merge Request: 处理 坯料的制造订单生成的批次序列号不对 的bug

Created By: @禹翔辉
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1573
2024-11-28 17:52:46 +08:00
yuxianghui
ccda6b627d Merge branch 'feature/制造订单状态优化_1' into feature/坯料制造序号优化 2024-11-28 17:51:22 +08:00
yuxianghui
20cfbf7230 处理 坯料的制造订单生成的批次序列号不对 的bug 2024-11-28 17:50:12 +08:00
jinling.yang
805eabd07e Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/修复外协出入库单 2024-11-28 16:01:11 +08:00
jinling.yang
c42c053d66 修复表面工艺外协及工艺设计 2024-11-28 15:59:17 +08:00
禹翔辉
d8e51f44ac Accept Merge Request #1572: (feature/制造订单状态优化_1 -> develop)
Merge Request: 制造订单状态优化

Created By: @禹翔辉
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1572
2024-11-28 15:54:12 +08:00
yuxianghui
0b5645496b Merge branch 'feature/工单状态优化_2' into feature/制造订单状态优化_1 2024-11-28 15:52:31 +08:00
yuxianghui
2c37dbf5c4 制造订单状态优化 2024-11-28 15:51:54 +08:00
胡尧
cd6dc7a47e Accept Merge Request #1571: (feature/sale_order_route_pick -> develop)
Merge Request: 修改坯料冗余描述

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1571?initial=true
2024-11-28 15:42:05 +08:00
胡尧
7362f0cd30 修改坯料冗余描述 2024-11-28 15:41:39 +08:00
胡尧
de2924883c Accept Merge Request #1570: (feature/sale_order_route_pick -> develop)
Merge Request: 修改排程逻辑

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1570?initial=true
2024-11-28 15:22:23 +08:00
胡尧
942aa469e3 修改排程逻辑 2024-11-28 15:21:54 +08:00
胡尧
d57cc59115 修改排程逻辑 2024-11-28 15:20:56 +08:00
禹翔辉
f8ff3a18a0 Accept Merge Request #1569: (feature/工单状态优化_2 -> 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/1569?initial=true
2024-11-28 15:11:30 +08:00
胡尧
96171013d6 修改排程 2024-11-28 15:10:45 +08:00
yuxianghui
d741d6ccf5 Merge branch 'feature/制造订单状态优化' into feature/工单状态优化_2 2024-11-28 15:09:51 +08:00
yuxianghui
8ff73d5647 工单状态优化 2024-11-28 15:09:11 +08:00
胡尧
5d3d04b5d3 Accept Merge Request #1567: (feature/sale_order_route_pick -> develop)
Merge Request: 解决询价单中自动化产线加工的订单不生成编程单的问题

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1567
2024-11-28 15:05:57 +08:00
马广威
75ed1a6889 Accept Merge Request #1568: (feature/制造功能优化 -> develop)
Merge Request: 修复仓储岗角色权限问题

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1568?initial=true
2024-11-28 13:39:47 +08:00
mgw
9bfbea11db Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2024-11-28 13:38:43 +08:00
mgw
5eea260618 修复仓储岗角色权限问题 2024-11-28 13:38:14 +08:00
胡尧
f1e70d2c66 解决询价单中自动化产线加工的订单不生成编程单的问题 2024-11-28 11:36:32 +08:00
jinling.yang
da22cb301e Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-11-28 10:48:28 +08:00
jinling.yang
2b93f2a253 Merge branch 'feature/修复制造订单-采购单' into develop 2024-11-28 10:46:42 +08:00
杨金灵
8ab42ff7da Accept Merge Request #1566: (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/1566?initial=true
2024-11-28 10:45:25 +08:00
jinling.yang
9bf57005f0 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/修复制造订单-采购单 2024-11-28 10:41:13 +08:00
jinling.yang
a80d498eab 修复制造订单-采购单 2024-11-28 10:40:48 +08:00
胡尧
4847596072 Accept Merge Request #1565: (feature/sale_order_route_pick -> develop)
Merge Request: 修改排程单的问题

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1565?initial=true
2024-11-28 10:18:35 +08:00
胡尧
d4ba58b55a 修改排程单的问题 2024-11-28 10:17:03 +08:00
liaodanlong
73ab43f16a 人工线下加工 2024-11-28 10:05:17 +08:00
杨金灵
306d5074f2 Accept Merge Request #1563: (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/1563
2024-11-28 10:03:05 +08:00
马广威
745abaab2e Accept Merge Request #1564: (feature/制造功能优化 -> develop)
Merge Request: 修复计划调度岗和生产总监权限问题

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1564?initial=true
2024-11-28 10:00:24 +08:00
jinling.yang
c22b91f9d9 优化采购:一个制造订单对应一个采购单 2024-11-28 09:59:01 +08:00
yuxianghui
0bea93ea46 1、添加返工向导中选择返工工单限制条件 2024-11-27 17:54:59 +08:00
jinling.yang
ecf683e663 修复采购 2024-11-27 17:54:31 +08:00
胡尧
0af7ef905d Accept Merge Request #1562: (feature/sale_order_route_pick -> develop)
Merge Request: 解决工单完成的问题

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1562?initial=true
2024-11-27 17:40:58 +08:00
胡尧
c169c0a80b 解决工单完成的问题 2024-11-27 17:40:35 +08:00
禹翔辉
878d62f483 Accept Merge Request #1561: (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/1561?initial=true
2024-11-27 16:31:34 +08:00
yuxianghui
8a33cea8bd Merge branch 'feature/工序排序优化' into feature/制造订单状态优化 2024-11-27 16:19:18 +08:00
yuxianghui
d6c194eaa8 处理制造订单状态问题。 2024-11-27 16:18:18 +08:00
胡尧
13d32c26b6 Accept Merge Request #1560: (feature/sale_order_route_pick -> develop)
Merge Request: 成品委外,坯料自加工的制造排程单生成

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1560?initial=true
2024-11-27 15:03:51 +08:00
胡尧
df146a4b58 成品委外,坯料自加工的制造排程单生成 2024-11-27 15:02:42 +08:00
廖丹龙
4a02034ee3 Accept Merge Request #1559: (feature/delivery_status -> 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/1559
2024-11-27 14:52:18 +08:00
liaodanlong
acb24d69e3 排程 采购单条件判断 2024-11-27 14:42:41 +08:00
胡尧
56cfeac214 修改坯料冗余描述 2024-11-27 11:16:11 +08:00
胡尧
b86ad6e5bb Accept Merge Request #1558: (release/release_2.6 -> develop)
Merge Request: 修改数据初始化

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1558?initial=true
2024-11-27 11:15:36 +08:00
胡尧
f57c95496a 修改数据初始化 2024-11-27 11:06:05 +08:00
禹翔辉
826b2c3e94 Accept Merge Request #1557: (feature/工序排序优化 -> develop)
Merge Request: 1、工序排序方法优化;2、返工优化

Created By: @禹翔辉
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1557?initial=true
2024-11-27 11:05:30 +08:00
yuxianghui
29b43c6ab8 Merge branch 'feature/返工优化_5' into feature/工序排序优化 2024-11-27 11:01:49 +08:00
yuxianghui
a434227807 1、工序排序方法优化;2、返工优化 2024-11-27 11:01:10 +08:00
胡尧
3a7fb81276 Accept Merge Request #1556: (feature/sale_order_route_pick -> develop)
Merge Request: 解决工单开始结束的问题

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1556?initial=true
2024-11-27 09:54:04 +08:00
胡尧
12224fc892 解决工单开始结束的问题 2024-11-27 09:53:17 +08:00
胡尧
64fdedf726 修改工单开始 2024-11-27 08:37:12 +08:00
yuxianghui
d3b61f320f 1、返工优化 2024-11-26 18:01:02 +08:00
jinling.yang
6be7c05415 优化代码 2024-11-26 17:05:45 +08:00
mgw
92b924754d 修复计划调度岗和生产总监权限问题 2024-11-26 16:56:47 +08:00
jinling.yang
40ddfdd48f Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-11-26 16:47:22 +08:00
杨金灵
afa5ad36f2 Accept Merge Request #1554: (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/1554
2024-11-26 16:32:47 +08:00
黄焱
916a5c1054 Accept Merge Request #1555: (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/1555?initial=true
2024-11-26 16:31:28 +08:00
jinling.yang
ea914be4c7 修复采购链接 2024-11-26 16:21:17 +08:00
jinling.yang
e6eb41ad24 优化代码 2024-11-26 16:15:50 +08:00
jinling.yang
43ee2d1836 回滚代码 2024-11-26 16:08:30 +08:00
jinling.yang
3bd4e6723e Merge branch 'feature/修复表面工艺' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/修复表面工艺 2024-11-26 16:05:52 +08:00
jinling.yang
0e763c2ca6 还原代码 2024-11-26 16:05:37 +08:00
jinling.yang
34353e3614 修复表面工艺 2024-11-26 16:05:23 +08:00
jinling.yang
d91c7b22d7 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-11-26 16:04:10 +08:00
jinling.yang
ac4861c76e Merge branch 'feature/修复表面工艺' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/修复表面工艺 2024-11-26 16:01:59 +08:00
jinling.yang
6edd124556 优化 2024-11-26 16:01:20 +08:00
jinling.yang
f426183d22 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/修复表面工艺 2024-11-26 15:59:31 +08:00
jinling.yang
33db91f799 Revert "修复表面工艺"
This reverts commit b5beaad7bf.
2024-11-26 15:56:22 +08:00
jinling.yang
8803380a30 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/new1 2024-11-26 15:37:40 +08:00
jinling.yang
b5beaad7bf 修复表面工艺 2024-11-26 15:37:19 +08:00
hy
304259c653 增加列表多选配置 2024-11-26 15:22:41 +08:00
胡尧
5ccc836b20 Accept Merge Request #1553: (feature/sale_order_route_pick -> develop)
Merge Request: 修改排程单bug

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1553?initial=true
2024-11-26 11:51:47 +08:00
胡尧
087bb0e8fe 取消制造订单排程时,将其下所有子制造订单改为已排状态的逻辑 2024-11-26 11:51:09 +08:00
胡尧
09a476ffa5 修改子制造订单的销售订单 2024-11-26 11:26:17 +08:00
禹翔辉
429ad2b77c Accept Merge Request #1552: (feature/返工优化_5 -> develop)
Merge Request: 1、返工向导模型添加新的工单字段;2、工单tree视图添加重新加工分类

Created By: @禹翔辉
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1552
2024-11-26 11:17:22 +08:00
yuxianghui
c215e3dc27 Merge branch 'feature/采购优化' into feature/返工优化_5 2024-11-26 11:15:56 +08:00
yuxianghui
0a1da79487 1、返工向导模型添加新的工单字段;2、工单tree视图添加重新加工分类 2024-11-26 11:14:45 +08:00
jinling.yang
42e4e15cdb Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-11-26 10:58:20 +08:00
胡尧
a3e7a23979 Accept Merge Request #1551: (feature/sale_order_route_pick -> develop)
Merge Request: 采购单根据采购类型拆分

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1551
2024-11-26 10:48:25 +08:00
胡尧
430a628e18 Merge branch 'develop' into feature/sale_order_route_pick 2024-11-26 10:47:32 +08:00
胡尧
5f70690af5 采购单根据采购类型拆分 2024-11-26 10:45:43 +08:00
杨金灵
b852933a9e Accept Merge Request #1550: (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/1550
2024-11-26 10:44:56 +08:00
jinling.yang
074c45aa3d Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/修复制造订单问题
# Conflicts:
#	sf_manufacturing/models/stock.py
2024-11-26 10:41:30 +08:00
jinling.yang
a52545d19a Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-11-26 10:39:23 +08:00
jinling.yang
3e55bb4717 修复制造订单批量调整 2024-11-26 10:39:04 +08:00
jinling.yang
be408b98de 修复制造订单相关问题 2024-11-25 18:00:06 +08:00
马广威
12cc5fd0d2 Accept Merge Request #1549: (feature/制造功能优化 -> develop)
Merge Request: 内部调拨单缺少源单据

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1549?initial=true
2024-11-25 17:25:38 +08:00
mgw
589df289be 内部调拨单缺少源单据 2024-11-25 17:24:14 +08:00
胡尧
7abc88f2c3 Accept Merge Request #1548: (feature/sale_order_route_pick -> develop)
Merge Request: 测试坯料采购单根据采购类型合并

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1548?initial=true
2024-11-25 17:19:22 +08:00
胡尧
f318dc758b 测试坯料采购单根据采购类型合并 2024-11-25 17:18:57 +08:00
胡尧
6628e22ac0 Accept Merge Request #1547: (feature/sale_order_route_pick -> develop)
Merge Request: 子制造订单增加拍承担

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1547?initial=true
2024-11-25 16:46:33 +08:00
管欢
c4cf4e2392 Accept Merge Request #1546: (feature/model_type_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/1546?initial=true
2024-11-25 16:44:45 +08:00
胡尧
56dfb98df5 子制造订单增加拍承担 2024-11-25 16:43:46 +08:00
guanhuan
4251e6dec7 修复模型类型详情界面的配置工序不能删除 2024-11-25 16:41:47 +08:00
jinling.yang
bcc9f0301c Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-11-25 16:23:09 +08:00
jinling.yang
17f2571be3 Merge branch 'feature/修复工序' into develop 2024-11-25 16:22:53 +08:00
杨金灵
a9b24f7961 Accept Merge Request #1545: (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/1545
2024-11-25 16:22:38 +08:00
jinling.yang
321125adf6 还原代码 2024-11-25 16:18:41 +08:00
jinling.yang
5c0db45223 修复工单开始 2024-11-25 16:03:40 +08:00
jinling.yang
76cc8845d2 修复工序 2024-11-25 15:40:41 +08:00
jinling.yang
38031a2537 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-11-25 15:02:08 +08:00
jinling.yang
1fe64e2b5d Merge branch 'feature/修复制造订单问题' into develop 2024-11-25 15:01:26 +08:00
杨金灵
d572529a9d Accept Merge Request #1544: (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/1544
2024-11-25 15:00:40 +08:00
jinling.yang
cb29baa698 还原代码 2024-11-25 14:31:02 +08:00
jinling.yang
696d0e2a40 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/修复制造订单问题 2024-11-25 14:00:04 +08:00
jinling.yang
75bbcd23a4 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-11-25 13:59:40 +08:00
jinling.yang
25002406b8 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/修复制造订单问题 2024-11-25 13:59:22 +08:00
廖丹龙
ed3ea32f45 Accept Merge Request #1543: (feature/delivery_status -> 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/1543
2024-11-25 11:52:20 +08:00
jinling.yang
63b1f732db 注释代码 2024-11-25 11:40:33 +08:00
liaodanlong
84ebce0786 智能工厂空模型处理 2024-11-25 11:40:01 +08:00
胡尧
ed747ae4d9 Accept Merge Request #1542: (feature/sale_order_route_pick -> develop)
Merge Request: 人工编程不能选择自动化产线加工

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1542?initial=true
2024-11-25 10:44:10 +08:00
胡尧
8a103a7555 人工编程不能选择自动化产线加工 2024-11-25 10:43:34 +08:00
jinling.yang
e8c166be31 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-11-25 10:25:52 +08:00
120 changed files with 3668 additions and 1019 deletions

View File

@@ -139,6 +139,7 @@ patch(ListRenderer.prototype, 'jikimo_frontend.ListRenderer', {
owl.onMounted(() => { owl.onMounted(() => {
this.activeElement = this.uiService.activeElement; this.activeElement = this.uiService.activeElement;
this.setRequired() this.setRequired()
this.listherHeaderBodyNum()
}) })
return this._super(...arguments); return this._super(...arguments);
}, },
@@ -165,6 +166,26 @@ patch(ListRenderer.prototype, 'jikimo_frontend.ListRenderer', {
} catch (e) { } catch (e) {
console.log(e) console.log(e)
} }
},
listherHeaderBodyNum() {
const dom = this.tableRef.el
try {
const thead = $(dom).children('thead')
const tbody = $(dom).children('tbody')
const thead_tr = thead.children().eq(0)
const tbody_tr = tbody.children().eq(0)
const thead_th_num = thead_tr.children().length
const tbody_tr_num = tbody_tr.children().length
const num = thead_th_num - tbody_tr_num
if(num == -1) {
tbody.children('tr').each(function () {
$(this).children('td').eq(0).remove()
})
}
} catch (e) {
console.log(e)
}
} }
}) })

View File

@@ -536,3 +536,7 @@ div:has(.o_required_modifier) > label::before {
position: unset; position: unset;
} }
// 修复搜索面板checkbox样式
.o_search_panel .form-check .form-check-label span {
position: relative;
}

View File

@@ -190,7 +190,7 @@ def _create(self, data_list):
# 如果该用户组被限制创建或更新操作 # 如果该用户组被限制创建或更新操作
if rec['is_create_or_update']: if rec['is_create_or_update']:
raise UserError( raise UserError(
_("You are restricted from performing this operation. Please contact the administrator.")) _("您没有执行此操作的权限。请联系管理员"))
else: else:
# 如果 'access.right' 模型不存在,可以在这里定义备选逻辑 # 如果 'access.right' 模型不存在,可以在这里定义备选逻辑
# 例如,记录日志、发送通知或者简单地跳过这部分逻辑 # 例如,记录日志、发送通知或者简单地跳过这部分逻辑

View File

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

View File

@@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
{
'name': "机企猫 采购审批流程",
'summary': """
Short (1 phrase/line) summary of the module's purpose, used as
subtitle on modules listing or apps.openerp.com""",
'description': """
Long description of module's purpose
""",
'author': "My Company",
'website': "https://www.yourcompany.com",
# Categories can be used to filter modules in modules listing
# Check https://github.com/odoo/odoo/blob/16.0/odoo/addons/base/data/ir_module_category_data.xml
# for the full list
'category': 'Uncategorized',
'version': '0.1',
# any module necessary for this one to work correctly
'depends': ['purchase', 'purchase_tier_validation', 'documents', 'purchase_request', 'account', 'purchase_order_approved'],
# always loaded
'data': [
'security/ir.model.access.csv',
'data/documents_data.xml',
'wizards/upload_file_wizard_view.xml',
'views/views.xml',
],
# only loaded in demonstration mode
'demo': [
'demo/demo.xml',
],
'assets': {
'web.assets_backend': [
'jikimo_purchase_tier_validation/static/src/js/ir_model_extend.js',
],
},
}

View File

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

View File

@@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
# from odoo import http
# class JikimoPurchaseTierValidation(http.Controller):
# @http.route('/jikimo_purchase_tier_validation/jikimo_purchase_tier_validation', auth='public')
# def index(self, **kw):
# return "Hello, world"
# @http.route('/jikimo_purchase_tier_validation/jikimo_purchase_tier_validation/objects', auth='public')
# def list(self, **kw):
# return http.request.render('jikimo_purchase_tier_validation.listing', {
# 'root': '/jikimo_purchase_tier_validation/jikimo_purchase_tier_validation',
# 'objects': http.request.env['jikimo_purchase_tier_validation.jikimo_purchase_tier_validation'].search([]),
# })
# @http.route('/jikimo_purchase_tier_validation/jikimo_purchase_tier_validation/objects/<model("jikimo_purchase_tier_validation.jikimo_purchase_tier_validation"):obj>', auth='public')
# def object(self, obj, **kw):
# return http.request.render('jikimo_purchase_tier_validation.object', {
# 'object': obj
# })

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<!-- 创建采购合同文件夹 -->
<record id="documents_purchase_contracts_folder" model="documents.folder">
<field name="name">采购合同</field>
<field name="description">存放采购合同相关文件</field>
<field name="sequence">10</field>
</record>
</data>
</odoo>

View File

@@ -0,0 +1,30 @@
<odoo>
<data>
<!--
<record id="object0" model="jikimo_purchase_tier_validation.jikimo_purchase_tier_validation">
<field name="name">Object 0</field>
<field name="value">0</field>
</record>
<record id="object1" model="jikimo_purchase_tier_validation.jikimo_purchase_tier_validation">
<field name="name">Object 1</field>
<field name="value">10</field>
</record>
<record id="object2" model="jikimo_purchase_tier_validation.jikimo_purchase_tier_validation">
<field name="name">Object 2</field>
<field name="value">20</field>
</record>
<record id="object3" model="jikimo_purchase_tier_validation.jikimo_purchase_tier_validation">
<field name="name">Object 3</field>
<field name="value">30</field>
</record>
<record id="object4" model="jikimo_purchase_tier_validation.jikimo_purchase_tier_validation">
<field name="name">Object 4</field>
<field name="value">40</field>
</record>
-->
</data>
</odoo>

View File

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

View File

@@ -0,0 +1,215 @@
from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
import logging
_logger = logging.getLogger(__name__)
class jikimo_purchase_tier_validation(models.Model):
_name = 'purchase.order'
_inherit = ['purchase.order', 'tier.validation']
_description = "采购订单"
_tier_validation_buttons_xpath = "/form/header/button[@id='draft_confirm'][1]"
contract_document_id = fields.Many2one('documents.document', string='合同文件')
contract_file = fields.Binary(related='contract_document_id.datas', string='合同文件内容')
contract_file_name = fields.Char(related='contract_document_id.attachment_id.name', string='文件名')
# 是否已上传合同文件
is_upload_contract_file = fields.Boolean(string='是否已上传合同文件', default=False)
def button_confirm(self):
for record in self:
if record.need_validation and record.validation_status != 'validated':
raise ValidationError(_('此操作需要至少对一条记录进行审批。\n请发起审批申请。'))
if record.state in ['to approve']:
raise ValidationError(_('请先完成审批。'))
if record.state == 'approved':
record.state = 'purchase'
return super().button_confirm()
# def button_confirm(self):
# self = self.with_context(skip_validation=True)
# return super().button_confirm()
#
# def _check_state_conditions(self, vals):
# self.ensure_one()
# if self._context.get('skip_validation'):
# return False
# return (
# self._check_state_from_condition()
# and vals.get(self._state_field) in self._state_to
# )
def request_validation(self):
for record in self:
error_messages = []
# 检查必填字段
required_fields = {
'partner_ref': '合同名称',
'contract_number': '合同编号'
}
missing_fields = [
name for field, name in required_fields.items()
if not record[field]
]
if missing_fields:
error_messages.append('* 如下字段要求必须填写:%s' % ''.join(missing_fields))
# 检查合同文件
if not record.contract_document_id:
error_messages.append('* 必须点击上传合同文件')
# 如果有任何错误,一次性显示所有错误信息
if error_messages:
raise ValidationError('\n'.join(error_messages))
# 添加通知消息
if hasattr(record, 'message_post'):
current_user = self.env.user.name
record.message_post(
body=f"<strong>{current_user}</strong> 提交审批",
message_type='notification',
subtype_xmlid='mail.mt_note'
)
res = super(jikimo_purchase_tier_validation, self).request_validation()
self.state = 'to approve'
return res
def restart_validation(self):
res = super(jikimo_purchase_tier_validation, self).restart_validation()
self.state = 'draft'
return res
def _validate_tier(self, tiers=False):
res = super(jikimo_purchase_tier_validation, self)._validate_tier(tiers)
tier_reviews = tiers or self.review_ids
# 检查是否所有审批都已通过
all_approved = all(
tier_review.status == 'approved'
for tier_review in tier_reviews
)
if all_approved and tier_reviews: # 确保有审批记录
self.state = 'approved'
return res
def _rejected_tier(self, tiers=False):
res = super(jikimo_purchase_tier_validation, self)._rejected_tier(tiers)
self.state = 'draft'
return res
@api.model
def _get_under_validation_exceptions(self):
res = super(jikimo_purchase_tier_validation, self)._get_under_validation_exceptions()
res.append("state")
return res
# 上传合同文件
def upload_contract_file(self):
print('upload_contract_file===========================')
# self.ensure_one()
# return {
# 'name': _('上传合同文件'),
# 'type': 'ir.actions.act_window',
# 'res_model': 'ir.attachment',
# 'view_mode': 'form',
# 'view_type': 'form',
# 'target': 'new',
# 'context': {
# 'default_res_model': self._name,
# 'default_res_id': self.id,
# 'default_type': 'binary',
# 'default_mimetype': 'application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,image/jpeg,image/png',
# }
# }
self.ensure_one()
action = {
'type': 'ir.actions.act_window',
'name': _('上传合同文件'),
'res_model': 'ir.attachment.wizard', # 我们需要创建一个新的向导模型
'view_mode': 'form',
'target': 'new',
'context': {
'default_res_model': self._name,
'default_res_id': self.id,
}
}
return action
# 删除合同文件
def delete_contract_file(self):
self.ensure_one()
if self.contract_document_id:
try:
document = self.contract_document_id
# 清空关联
self.write({
'contract_document_id': False,
'contract_file': False,
'contract_file_name': False
})
# 删除文档
if document:
document.with_context(no_attachment=True).sudo().unlink()
self.is_upload_contract_file = False
# 返回视图动作来刷新当前表单
return {
'type': 'ir.actions.act_window',
'res_model': 'purchase.order',
'res_id': self.id,
'view_mode': 'form',
'view_type': 'form',
'target': 'current',
'flags': {'mode': 'readonly'},
}
except Exception as e:
_logger.error('删除合同文件时出错: %s', str(e))
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': _('错误'),
'message': _('删除文件时出现错误'),
'type': 'danger',
'sticky': True,
}
}
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': _('提示'),
'message': _('没有需要删除的合同文件'),
'type': 'warning',
'sticky': False,
}
}
class jikimo_purchase_request(models.Model):
_inherit = 'purchase.request'
_description = "采购申请"
class jikimo_account_payment(models.Model):
_inherit = 'account.payment'
_description = "付款单"
class jikimo_account_move(models.Model):
_inherit = 'account.move'
_description = "发票账单"

View File

@@ -0,0 +1,2 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_ir_attachment_wizard,ir.attachment.wizard,model_ir_attachment_wizard,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_ir_attachment_wizard ir.attachment.wizard model_ir_attachment_wizard base.group_user 1 1 1 1

View File

@@ -0,0 +1,14 @@
/** @odoo-module **/
import {registerPatch} from "@mail/model/model_core";
registerPatch({
name: "ir.model.review",
fields: {
availableWebViews: {
compute() {
return ["list", "form", "activity"];
},
},
},
});

View File

@@ -0,0 +1,24 @@
<odoo>
<data>
<!--
<template id="listing">
<ul>
<li t-foreach="objects" t-as="object">
<a t-attf-href="#{ root }/objects/#{ object.id }">
<t t-esc="object.display_name"/>
</a>
</li>
</ul>
</template>
<template id="object">
<h1><t t-esc="object.display_name"/></h1>
<dl>
<t t-foreach="object._fields" t-as="field">
<dt><t t-esc="field"/></dt>
<dd><t t-esc="object[field]"/></dd>
</t>
</dl>
</template>
-->
</data>
</odoo>

View File

@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<data>
<record model="ir.ui.view" id="tier_validation_view_approved_purchase_order_form_inherit">
<field name="name">tier_validation_view_approved_purchase_order_form_inherit</field>
<field name="model">purchase.order</field>
<field name="inherit_id" ref="purchase_order_approved.purchase_order_form"/>
<field name="arch" type="xml">
<xpath expr="//button[@name='button_release']" position="replace">
</xpath>
</field>
</record>
<record model="ir.ui.view" id="tier_validation_view_purchase_order_form_inherit">
<field name="name">tier_validation_view_purchase_order_form_inherit</field>
<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='button_approve']" position="replace">
</xpath>
<xpath expr="//header/button[@name='button_cancel']" position="replace">
</xpath>
<xpath expr="//header/field[@name='state']" position="replace">
<field name="state" widget="statusbar" statusbar_visible="draft,sent,to approve, approved, purchase" readonly="1"/>
</xpath>
<xpath expr="//header/button[last()]" position="after">
<button name="button_cancel" states="draft,to approve,sent,purchase" string="取消" type="object" data-hotkey="x" />
</xpath>
<xpath expr="//header/button[@name='action_rfq_send'][1]" position="before">
<field name="validation_status" invisible="1"/>
<field name="is_upload_contract_file" invisible="1"/>
<button name="upload_contract_file" string="上传合同" type="object" class="oe_highlight" attrs="{'invisible': ['|', '|', ('validation_status', '!=', 'no'), ('is_upload_contract_file', '=', True), ('state', 'not in', ['draft', 'sent'])]}"/>]}"/>
<button name="delete_contract_file" string="删除合同" type="object" class="oe_highlight" attrs="{'invisible': ['|', ('validation_status', '!=', 'no'), ('is_upload_contract_file', '=', False)]}"/>
</xpath>
<xpath expr="//notebook/page[1]" position="before">
<page string="合同" name="contract_documents"
attrs="{'invisible': [('contract_document_id', '=', False)]}"
autofocus="autofocus">
<group>
<group>
<field name="contract_document_id" invisible="1"/>
<field name="contract_file_name" invisible="1"/>
<field name="contract_file"
widget="adaptive_viewer"
filename="contract_file_name"/>
</group>
</group>
</page>
</xpath>
</field>
</record>
<!-- actions opening views on models -->
<!--
<record model="ir.actions.act_window" id="jikimo_purchase_tier_validation.action_window">
<field name="name">jikimo_purchase_tier_validation window</field>
<field name="res_model">jikimo_purchase_tier_validation.jikimo_purchase_tier_validation</field>
<field name="view_mode">tree,form</field>
</record>
-->
<!-- server action to the one above -->
<!--
<record model="ir.actions.server" id="jikimo_purchase_tier_validation.action_server">
<field name="name">jikimo_purchase_tier_validation server</field>
<field name="model_id" ref="model_jikimo_purchase_tier_validation_jikimo_purchase_tier_validation"/>
<field name="state">code</field>
<field name="code">
action = {
"type": "ir.actions.act_window",
"view_mode": "tree,form",
"res_model": model._name,
}
</field>
</record>
-->
<!-- Top menu item -->
<!--
<menuitem name="jikimo_purchase_tier_validation" id="jikimo_purchase_tier_validation.menu_root"/>
-->
<!-- menu categories -->
<!--
<menuitem name="Menu 1" id="jikimo_purchase_tier_validation.menu_1" parent="jikimo_purchase_tier_validation.menu_root"/>
<menuitem name="Menu 2" id="jikimo_purchase_tier_validation.menu_2" parent="jikimo_purchase_tier_validation.menu_root"/>
-->
<!-- actions -->
<!--
<menuitem name="List" id="jikimo_purchase_tier_validation.menu_1_list" parent="jikimo_purchase_tier_validation.menu_1"
action="jikimo_purchase_tier_validation.action_window"/>
<menuitem name="Server to list" id="jikimo_purchase_tier_validation" parent="jikimo_purchase_tier_validation.menu_2"
action="jikimo_purchase_tier_validation.action_server"/>
-->
</data>
</odoo>

View File

@@ -0,0 +1,2 @@
from . import upload_file_wizard
from . import comment_wizard

View File

@@ -0,0 +1,15 @@
from odoo import models, fields
class CommentWizard(models.TransientModel):
_inherit = "comment.wizard"
def add_comment(self):
rec = self.env[self.res_model].browse(self.res_id)
self.review_ids = rec.review_ids
result = super(CommentWizard, self).add_comment()
return result

View File

@@ -0,0 +1,114 @@
from odoo import models, fields, api, _
class IrAttachmentWizard(models.TransientModel):
_name = 'ir.attachment.wizard'
_description = '文件上传向导'
attachment = fields.Binary(string='选择文件', required=True)
filename = fields.Char(string='文件名')
res_model = fields.Char()
res_id = fields.Integer()
# def action_upload_file(self):
# self.ensure_one()
# # 首先创建 ir.attachment
# attachment = self.env['ir.attachment'].create({
# 'name': self.filename,
# 'type': 'binary',
# 'datas': self.attachment,
# 'res_model': self.res_model,
# 'res_id': self.res_id,
# })
#
# # 获取默认的文档文件夹
# workspace = self.env['documents.folder'].search([('name', '=', '采购合同')], limit=1)
#
# # 创建 documents.document 记录
# document = self.env['documents.document'].create({
# 'name': self.filename,
# 'attachment_id': attachment.id,
# 'folder_id': workspace.id,
# 'res_model': self.res_model,
# 'res_id': self.res_id,
# })
#
# return {
# 'type': 'ir.actions.client',
# 'tag': 'display_notification',
# 'params': {
# 'title': _('成功'),
# 'message': _('文件上传成功'),
# 'type': 'success',
# }
# }
def action_upload_file(self):
self.ensure_one()
# 获取当前用户的 partner_id
current_partner = self.env.user.partner_id
# 首先创建 ir.attachment
attachment = self.env['ir.attachment'].create({
'name': self.filename,
'type': 'binary',
'datas': self.attachment,
'res_model': self.res_model,
'res_id': self.res_id,
})
# 获取默认的文档文件夹
workspace = self.env['documents.folder'].search([('name', '=', '采购合同')], limit=1)
# 创建 documents.document 记录
document = self.env['documents.document'].create({
'name': self.filename,
'attachment_id': attachment.id,
'folder_id': workspace.id,
'res_model': self.res_model,
'res_id': self.res_id,
'partner_id': current_partner.id,
})
# 更新采购订单的合同文档字段
purchase_order = self.env['purchase.order'].browse(self.res_id)
purchase_order.write({
'contract_document_id': document.id,
'is_upload_contract_file': True
})
# 显示成功消息并关闭向导
message = {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': _('成功'),
'message': _('文件上传成功'),
'type': 'success',
'sticky': False, # 自动消失
'next': {
'type': 'ir.actions.act_window_close'
}
}
}
return message
# def action_upload_file(self):
# self.ensure_one()
# attachment = self.env['ir.attachment'].create({
# 'name': self.filename,
# 'type': 'binary',
# 'datas': self.attachment,
# 'res_model': self.res_model,
# 'res_id': self.res_id,
# })
# return {
# 'type': 'ir.actions.client',
# 'tag': 'display_notification',
# 'params': {
# 'title': _('成功'),
# 'message': _('文件上传成功'),
# 'type': 'success',
# }
# }

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_upload_file_wizard_form" model="ir.ui.view">
<field name="name">ir.attachment.wizard.form</field>
<field name="model">ir.attachment.wizard</field>
<field name="arch" type="xml">
<form string="上传文件">
<group>
<field name="attachment" widget="binary" filename="filename" options="{'accepted_file_extensions': '.pdf,.doc,.docx,.jpg,.jpeg,.png'}"/>
<field name="filename" invisible="1"/>
<field name="res_model" invisible="1"/>
<field name="res_id" invisible="1"/>
</group>
<footer>
<button name="action_upload_file" string="确认上传" type="object" class="btn-primary"/>
<button string="取消" class="btn-secondary" special="cancel"/>
</footer>
</form>
</field>
</record>
</odoo>

View File

@@ -12,10 +12,6 @@ def _data_install(cr, registry):
env.ref('jikimo_sale_multiple_supply_methods.product_template_default').product_variant_id.write({'active': False, 'is_bfm': True}) env.ref('jikimo_sale_multiple_supply_methods.product_template_default').product_variant_id.write({'active': False, 'is_bfm': True})
env.ref('jikimo_sale_multiple_supply_methods.product_template_embryo_customer_provided').product_variant_id.write({'active': False}) env.ref('jikimo_sale_multiple_supply_methods.product_template_embryo_customer_provided').product_variant_id.write({'active': False})
env.ref('jikimo_sale_multiple_supply_methods.product_template_outsourcing').product_variant_id.write({'active': False, 'is_bfm': True}) env.ref('jikimo_sale_multiple_supply_methods.product_template_outsourcing').product_variant_id.write({'active': False, 'is_bfm': True})
env.ref('sf_dlm.product_embryo_sf_self_machining').product_tmpl_id.write({'categ_type': '坯料'})
env.ref('sf_dlm.product_template_sf').product_tmpl_id.write({'categ_type': '成品'})
env.ref('sf_dlm.product_embryo_sf_outsource').product_tmpl_id.write({'categ_type': '坯料'})
env.ref('sf_dlm.product_embryo_sf_purchase').product_tmpl_id.write({'categ_type': '坯料'})
# 为三步制造增加规则 # 为三步制造增加规则
warehouse = env['stock.warehouse'].search([('company_id', '=', env.company.id)], limit=1) warehouse = env['stock.warehouse'].search([('company_id', '=', env.company.id)], limit=1)

View File

@@ -6,12 +6,11 @@
'author': 'fox', 'author': 'fox',
'website': '', 'website': '',
'category': '', 'category': '',
'depends': ['sf_dlm', 'sale_stock', 'sf_sale'], 'depends': ['sf_dlm', 'sale_stock', 'sf_sale', 'sale'],
"data": [ "data": [
'security/ir.model.access.csv', 'security/ir.model.access.csv',
'data/stock_routes.xml', 'data/stock_routes.xml',
'data/product_data.xml', 'data/product_data.xml',
'views/sale_order_views.xml',
# 'views/product_product_views.xml', # 'views/product_product_views.xml',
],'assets': { ],'assets': {
# 'web.assets_backend': [ # 'web.assets_backend': [

View File

@@ -1,2 +1 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from . import main

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from . import product_template from . import product_template
from . import sale_order
from . import mrp_bom from . import mrp_bom

View File

@@ -23,4 +23,4 @@ class ProductTemplate(models.Model):
self.is_bfm = product_template_id.is_bfm self.is_bfm = product_template_id.is_bfm
self.is_manual_processing = product_template_id.is_manual_processing self.is_manual_processing = product_template_id.is_manual_processing
# 复制 seller_ids # 复制 seller_ids
self.seller_ids = [(0, 0, {'partner_id': seller.partner_id.id, 'delay': 1.0}) for seller in product_template_id.seller_ids] self.seller_ids = [(0, 0, {'partner_id': seller.partner_id.id, 'delay': 1.0, 'price': seller.price}) for seller in product_template_id.seller_ids]

View File

@@ -51,11 +51,11 @@ class JikimoWorkorderException(models.Model):
return res return res
def _get_message(self, message_queue_ids): def _get_message(self, message_queue_ids):
contents = super(JikimoWorkorderException, self)._get_message(message_queue_ids) contents, _ = super(JikimoWorkorderException, self)._get_message(message_queue_ids)
url = self.env['ir.config_parameter'].get_param('web.base.url') url = self.env['ir.config_parameter'].get_param('web.base.url')
action_id = self.env.ref('mrp.mrp_production_action').id action_id = self.env.ref('mrp.mrp_production_action').id
for index, content in enumerate(contents): for index, content in enumerate(contents):
exception_id = self.env['jikimo.workorder.exception'].browse(message_queue_ids[index].res_id) exception_id = self.env['jikimo.workorder.exception'].browse(message_queue_ids[index].res_id)
url = url + '/web#id=%s&view_type=form&action=%s' % (exception_id.workorder_id.production_id.id, action_id) url = url + '/web#id=%s&view_type=form&action=%s' % (exception_id.workorder_id.production_id.id, action_id)
contents[index] = content.replace('{{url}}', url) contents[index] = content.replace('{{url}}', url)
return contents return contents, message_queue_ids

View File

@@ -138,7 +138,7 @@ if env.user.has_group('mrp.group_mrp_workorder_dependencies'):
<button name="openMenuPopup" t-att-disabled="isBlocked" class="btn btn-secondary o_workorder_icon_btn fa fa-bars" type="workorder_event" title="menu"/> <button name="openMenuPopup" t-att-disabled="isBlocked" class="btn btn-secondary o_workorder_icon_btn fa fa-bars" type="workorder_event" title="menu"/>
<span groups="mrp_workorder.group_mrp_wo_tablet_timer"> <span groups="mrp_workorder.group_mrp_wo_tablet_timer">
<button name="button_pending" type="object" class="btn btn-secondary" attrs="{'invisible': ['|', ('is_user_working', '=', False), ('working_state', '=', 'blocked')]}" barcode_trigger="pause" string="PAUSE"/> <button name="button_pending" type="object" class="btn btn-secondary" attrs="{'invisible': ['|', ('is_user_working', '=', False), ('working_state', '=', 'blocked')]}" barcode_trigger="pause" string="PAUSE"/>
<button name="button_start" type="object" class="btn btn-warning" attrs="{'invisible': ['|', '|', ('is_user_working', '=', True), ('working_state', '=', 'blocked'), ('state', '=', ('done', 'cancel'))]}" barcode_trigger="pause" string="CONTINUE"/> <button name="button_start" type="object" class="btn btn-warning" attrs="{'invisible': ['|', '|', ('is_user_working', '=', True), ('working_state', '=', 'blocked'), ('state', '=', ('done','rework', 'cancel'))]}" barcode_trigger="pause" string="CONTINUE"/>
<button name="button_unblock" type="object" class="btn btn-secondary btn-danger o_unblock" attrs="{'invisible': [('working_state', '!=', 'blocked')]}">Unblock</button> <button name="button_unblock" type="object" class="btn btn-secondary btn-danger o_unblock" attrs="{'invisible': [('working_state', '!=', 'blocked')]}">Unblock</button>
<field name="duration" widget="mrp_timer" class="ms-1" readonly="1"/> <field name="duration" widget="mrp_timer" class="ms-1" readonly="1"/>
</span> </span>

View File

@@ -8,7 +8,7 @@
'sequence': 120, 'sequence': 120,
'summary': 'Control the quality of your products', 'summary': 'Control the quality of your products',
'website': 'https://www.odoo.com/app/quality', 'website': 'https://www.odoo.com/app/quality',
'depends': ['quality'], 'depends': ['quality', 'sf_manufacturing'],
'description': """ 'description': """
Quality Control Quality Control
=============== ===============

View File

@@ -7,6 +7,7 @@ from datetime import datetime
import random import random
from odoo import api, models, fields, _ from odoo import api, models, fields, _
from odoo.api import depends
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT, float_round from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT, float_round
from odoo.osv.expression import OR from odoo.osv.expression import OR
@@ -122,7 +123,13 @@ class QualityPoint(models.Model):
class QualityCheck(models.Model): class QualityCheck(models.Model):
_inherit = "quality.check" _inherit = "quality.check"
part_name = fields.Char('零件名称', compute='_compute_part_name_number', readonly=True)
part_number = fields.Char('零件图号', compute='_compute_part_name_number', readonly=True)
@depends('product_id')
def _compute_part_name_number(self):
for record in self:
record.part_number = record.product_id.part_number
record.part_name = record.product_id.part_name
failure_message = fields.Html(related='point_id.failure_message', readonly=True) failure_message = fields.Html(related='point_id.failure_message', readonly=True)
measure = fields.Float('Measure', default=0.0, digits='Quality Tests', tracking=True) measure = fields.Float('Measure', default=0.0, digits='Quality Tests', tracking=True)
measure_success = fields.Selection([ measure_success = fields.Selection([
@@ -152,6 +159,34 @@ class QualityCheck(models.Model):
is_lot_tested_fractionally = fields.Boolean(related='point_id.is_lot_tested_fractionally') is_lot_tested_fractionally = fields.Boolean(related='point_id.is_lot_tested_fractionally')
testing_percentage_within_lot = fields.Float(related="point_id.testing_percentage_within_lot") testing_percentage_within_lot = fields.Float(related="point_id.testing_percentage_within_lot")
product_tracking = fields.Selection(related='product_id.tracking') product_tracking = fields.Selection(related='product_id.tracking')
quality_check_type = fields.Selection([
('采购入库检', '采购入库检'),
('客供料入库检', '客供料入库检'),
('退货入库检', '退货入库检'),
('生产入库检', '生产入库检'),
('外协入库检', '外协入库检'),
('成品发货检', '成品发货检'),
('工序外协发货检', '工序外协发货检'),
('委外坯料发货检', '委外坯料发货检')], string='类型', compute='_compute_quality_check_type', store=True)
@api.depends('picking_id')
def _compute_quality_check_type(self):
for check in self:
if check.picking_id:
picking_type = check.picking_id.picking_type_id.sequence_code
type_mapping = {
'IN': '采购入库检',
'DL': '客供料入库检',
'RET': '退货入库检',
'SFP': '生产入库检',
'OCIN': '外协入库检',
'OUT': '成品发货检',
'OCOUT': '工序外协发货检',
'RES': '委外坯料发货检',
}
check.quality_check_type = type_mapping.get(picking_type, False)
else:
check.quality_check_type = False
@api.depends('measure_success') @api.depends('measure_success')
def _compute_warning_message(self): def _compute_warning_message(self):
@@ -294,6 +329,19 @@ class QualityAlert(models.Model):
_inherit = "quality.alert" _inherit = "quality.alert"
title = fields.Char('Title') title = fields.Char('Title')
part_number = fields.Char(string='零件图号', compute='_compute_part_info', store=True)
part_name = fields.Char(string='零件名称', compute='_compute_part_info', store=True)
@api.depends('product_id', 'picking_id')
def _compute_part_info(self):
for alert in self:
if alert.product_tmpl_id.categ_id.name == '成品':
alert.part_number = alert.product_id.part_number
alert.part_name = alert.product_id.part_name
elif alert.product_id.categ_id.name == '坯料':
if alert.picking_id.move_ids_without_package:
alert.part_number = alert.picking_id.move_ids_without_package[0].part_number
alert.part_name = alert.picking_id.move_ids_without_package[0].part_name
def action_see_check(self): def action_see_check(self):
return { return {

View File

@@ -90,6 +90,8 @@
<field name="lot_id" context="{'default_product_id': product_id}" <field name="lot_id" context="{'default_product_id': product_id}"
groups="stock.group_production_lot"/> groups="stock.group_production_lot"/>
<field name="picking_id"/> <field name="picking_id"/>
<field name="part_name"/>
<field name="part_number"/>
</group> </group>
<group> <group>
<field name="team_id"/> <field name="team_id"/>
@@ -150,6 +152,10 @@
<field name="date_assign" position="after"> <field name="date_assign" position="after">
<field name="company_id" groups="base.main_company"/> <field name="company_id" groups="base.main_company"/>
</field> </field>
<field name="product_tmpl_id" position="after">
<field name="part_name" optional="show"/>
<field name="part_number" optional="show"/>
</field>
</field> </field>
</record> </record>
@@ -260,6 +266,8 @@
<field name="company_id" invisible="1"/> <field name="company_id" invisible="1"/>
<field name="product_id" attrs="{'invisible' : [('measure_on', '=', 'operation')]}"/> <field name="product_id" attrs="{'invisible' : [('measure_on', '=', 'operation')]}"/>
<field name="measure_on" attrs="{'readonly': [('point_id', '!=', False)]}"/> <field name="measure_on" attrs="{'readonly': [('point_id', '!=', False)]}"/>
<field name="part_name"/>
<field name="part_number"/>
<field name="show_lot_text" invisible="1"/> <field name="show_lot_text" invisible="1"/>
<field name="move_line_id" invisible="1"/> <field name="move_line_id" invisible="1"/>
<field name="product_tracking" invisible="1"/> <field name="product_tracking" invisible="1"/>
@@ -389,6 +397,8 @@
<field name="name" decoration-bf="1"/> <field name="name" decoration-bf="1"/>
<field name="measure_on" optional="show"/> <field name="measure_on" optional="show"/>
<field name='product_id' optional="show"/> <field name='product_id' optional="show"/>
<field name="part_name" optional="hide"/>
<field name='part_number' optional="show"/>
<field name="lot_id" invisible="context.get('show_lots_text')"/> <field name="lot_id" invisible="context.get('show_lots_text')"/>
<field name="lot_name" invisible="not context.get('show_lots_text')"/> <field name="lot_name" invisible="not context.get('show_lots_text')"/>
<field name="picking_id" optional="hide" string="Transfer"/> <field name="picking_id" optional="hide" string="Transfer"/>
@@ -446,6 +456,10 @@
<filter string="Control Point" name="groupby_point_id" context="{'group_by': 'point_id'}"/> <filter string="Control Point" name="groupby_point_id" context="{'group_by': 'point_id'}"/>
<filter string="Team" name="groupby_team_id" context="{'group_by': 'team_id'}"/> <filter string="Team" name="groupby_team_id" context="{'group_by': 'team_id'}"/>
</group> </group>
<searchpanel>
<field name="quality_check_type" icon="fa-filter" enable_counters="1"/>
<field name="quality_state" icon="fa-filter" enable_counters="1"/>
</searchpanel>
</search> </search>
</field> </field>
</record> </record>
@@ -505,6 +519,7 @@
<field name="name">Quality Checks</field> <field name="name">Quality Checks</field>
<field name="res_model">quality.check</field> <field name="res_model">quality.check</field>
<field name="view_mode">tree,kanban,form,pivot,graph</field> <field name="view_mode">tree,kanban,form,pivot,graph</field>
<field name="context">{'is_web_request': True}</field>
<field name="help" type="html"> <field name="help" type="html">
<p class="o_view_nocontent_smiling_face"> <p class="o_view_nocontent_smiling_face">
No quality check found No quality check found

View File

@@ -1,6 +1,8 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import json import json
import logging import logging
import traceback
from odoo import http from odoo import http
from odoo.http import request from odoo.http import request
@@ -123,7 +125,8 @@ class Sf_Bf_Connect(http.Controller):
res['factory_order_no'] = order_id.name res['factory_order_no'] = order_id.name
return json.JSONEncoder().encode(res) return json.JSONEncoder().encode(res)
except Exception as e: except Exception as e:
logging.info('get_bfm_process_order_list error:%s' % e) traceback_error = traceback.format_exc()
logging.error('get_bfm_process_order_list error: %s' % traceback_error)
res['status'] = -1 res['status'] = -1
res['message'] = '工厂创建销售订单和产品失败,请联系管理员' res['message'] = '工厂创建销售订单和产品失败,请联系管理员'
request.cr.rollback() request.cr.rollback()

View File

@@ -151,6 +151,12 @@ class JdEclp(models.Model):
_logger.info('准备调接口1') _logger.info('准备调接口1')
url1 = config['bfm_url_new'] + '/api/create/jd/order' url1 = config['bfm_url_new'] + '/api/create/jd/order'
requests.post(url1, json=json1, data=None) requests.post(url1, json=json1, data=None)
# ===============修改销售订单状态为【物流中】===================
item = self.env['sale.order'].sudo().search([('name', '=', self.origin)])
if not item:
raise ValidationError('没有查询到订单号为【%s】的销售订单!' % self.origin)
else:
item.write({'state': 'physical_distribution'})
_logger.info('调用成功1') _logger.info('调用成功1')
_logger.info('准备调接口2') _logger.info('准备调接口2')
json2 = { json2 = {

View File

@@ -36,6 +36,8 @@ class StatusChange(models.Model):
# 使用super()来调用原始方法(在本例中为'sale.order'模型的'action_confirm'方法) # 使用super()来调用原始方法(在本例中为'sale.order'模型的'action_confirm'方法)
try: try:
res = super(StatusChange, self).action_confirm() res = super(StatusChange, self).action_confirm()
# 修改销售订单状态为【加工中】
self.write({'state': 'processing'})
logging.info('原生方法返回结果:%s' % res) logging.info('原生方法返回结果:%s' % res)
# 原有方法执行后进行额外的操作如调用外部API # 原有方法执行后进行额外的操作如调用外部API
process_start_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S') process_start_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')

View File

@@ -1,4 +1,5 @@
import logging import logging
from itertools import groupby
from odoo import models, fields, api, _ from odoo import models, fields, api, _
@@ -7,11 +8,10 @@ class StockRuleInherit(models.Model):
@api.model @api.model
def _run_buy(self, procurements): def _run_buy(self, procurements):
# 首先调用父类的 _run_buy 方法,以保留原有逻辑 # 判断补货组的采购类型
super(StockRuleInherit, self)._run_buy(procurements) procurements_group = {'standard': [], 'outsourcing': []}
# 然后在这里添加自定义的逻辑
for procurement, rule in procurements: for procurement, rule in procurements:
is_outsourcing = False
product = procurement.product_id product = procurement.product_id
# 获取主 BOM # 获取主 BOM
bom = self.env['mrp.bom'].search([('product_tmpl_id', '=', product.product_tmpl_id.id)], limit=1) bom = self.env['mrp.bom'].search([('product_tmpl_id', '=', product.product_tmpl_id.id)], limit=1)
@@ -23,21 +23,65 @@ class StockRuleInherit(models.Model):
# 检查路线 # 检查路线
for route in raw_material.route_ids: for route in raw_material.route_ids:
# print('route.name:', route.name) # print('route.name:', route.name)
if route.name == '按订单补给外包商': # 或者用 route.id 检查精确的路线 if route.name == '按订单补给外包商':
print("按订单补给外包商============是") is_outsourcing = True
# 使用 procurement.values['supplier'] 获取供应商
supplier = procurement.values.get('supplier') if is_outsourcing:
if supplier: procurements_group['outsourcing'].append((procurement, rule))
domain = rule._make_po_get_domain(procurement.company_id, procurement.values, else:
supplier.partner_id) procurements_group['standard'].append((procurement, rule))
logging.info("domain=============: %s", domain)
po = self.env['purchase.order'].sudo().search([ for key, value in procurements_group.items():
('partner_id', '=', supplier.partner_id.id), super(StockRuleInherit, self)._run_buy(value)
('company_id', '=', procurement.company_id.id), # 保证公司一致
('origin', '=', procurement.origin), # 根据来源匹配 if key == 'outsourcing':
('state', '=', 'draft') # 状态为草稿 for procurement, rule in value:
], limit=1) supplier = procurement.values.get('supplier')
logging.info("po=: %s", po) if supplier:
if po: domain = rule._make_po_get_domain(procurement.company_id, procurement.values,
po.write({'purchase_type': 'consignment'}) supplier.partner_id)
break logging.info("domain=============: %s", domain)
po = self.env['purchase.order'].sudo().search([
('partner_id', '=', supplier.partner_id.id),
('company_id', '=', procurement.company_id.id), # 保证公司一致
('origin', 'like', procurement.origin), # 根据来源匹配
('state', '=', 'draft') # 状态为草稿
], limit=1)
logging.info("po=: %s", po)
if po:
po.write({'purchase_type': 'outsourcing'})
# # 首先调用父类的 _run_buy 方法,以保留原有逻辑
# super(StockRuleInherit, self)._run_buy(procurements)
# 然后在这里添加自定义的逻辑
# for procurement, rule in procurements:
# product = procurement.product_id
# # 获取主 BOM
# bom = self.env['mrp.bom'].search([('product_tmpl_id', '=', product.product_tmpl_id.id)], limit=1)
# if bom:
# # 遍历 BOM 中的组件(即坯料等)
# for line in bom.bom_line_ids:
# raw_material = line.product_id
# # 检查路线
# for route in raw_material.route_ids:
# # print('route.name:', route.name)
# if route.name == '按订单补给外包商': # 或者用 route.id 检查精确的路线
# print("按订单补给外包商============是")
# # 使用 procurement.values['supplier'] 获取供应商
# supplier = procurement.values.get('supplier')
# if supplier:
# domain = rule._make_po_get_domain(procurement.company_id, procurement.values,
# supplier.partner_id)
# logging.info("domain=============: %s", domain)
# po = self.env['purchase.order'].sudo().search([
# ('partner_id', '=', supplier.partner_id.id),
# ('company_id', '=', procurement.company_id.id), # 保证公司一致
# ('origin', '=', procurement.origin), # 根据来源匹配
# ('state', '=', 'draft') # 状态为草稿
# ], limit=1)
# logging.info("po=: %s", po)
# if po:
# po.write({'purchase_type': 'outsourcing'})
# break

View File

@@ -23,6 +23,16 @@ class JkmPracticeEmployee(models.Model):
vals["we_id"] = self._get_we_id(vals.get('work_email')) vals["we_id"] = self._get_we_id(vals.get('work_email'))
return super(JkmPracticeEmployee, self).write(vals) return super(JkmPracticeEmployee, self).write(vals)
def unlink(self):
for record in self:
res_partner_obj = record.env['res.partner'].sudo().search([('email', '=', record.work_email)])
if res_partner_obj:
res_partner_obj.unlink()
res = super(JkmPracticeEmployee, self).unlink()
return res
@api.depends('work_contact_id', 'work_contact_id.mobile', 'work_contact_id.email') @api.depends('work_contact_id', 'work_contact_id.mobile', 'work_contact_id.email')
def _compute_work_contact_details(self): def _compute_work_contact_details(self):
for employee in self: for employee in self:

View File

@@ -25,7 +25,7 @@
# 只有它被屏蔽了 # 只有它被屏蔽了
# 'views/SfWorkOrderBarcodes.xml', # 'views/SfWorkOrderBarcodes.xml',
'views/WorkCenterBarcodes.xml', 'views/WorkCenterBarcodes.xml',
'views/Stock_picking_Barcodes.xml', # 'views/Stock_picking_Barcodes.xml',
'views/machine_monitor.xml', 'views/machine_monitor.xml',
'views/machine_info_present.xml', 'views/machine_info_present.xml',
'views/delivery_record.xml', 'views/delivery_record.xml',

View File

@@ -12,6 +12,7 @@
<field name="state" select="multi" string="状态" icon="fa-building" enable_counters="1"/> <field name="state" select="multi" string="状态" icon="fa-building" enable_counters="1"/>
<field name="construction_period_status" select="multi" icon="fa-building" enable_counters="1"/> <field name="construction_period_status" select="multi" icon="fa-building" enable_counters="1"/>
<field name="tag_type" select="multi" icon="fa-building" enable_counters="1"/>
<!-- <field name="manual_quotation" select="multi" string="" icon="fa-building" enable_counters="1"/>--> <!-- <field name="manual_quotation" select="multi" string="" icon="fa-building" enable_counters="1"/>-->
</searchpanel> </searchpanel>

View File

@@ -2,7 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details. # Part of Odoo. See LICENSE file for full copyright and licensing details.
{ {
'name': '机企猫智能工厂 制造管理', 'name': '机企猫智能工厂 制造管理',
'version': '1.0', 'version': '1.1',
'summary': '智能工厂制造模块', 'summary': '智能工厂制造模块',
'sequence': 1, 'sequence': 1,
'description': """ 'description': """
@@ -24,6 +24,7 @@
'wizard/production_wizard_views.xml', 'wizard/production_wizard_views.xml',
'wizard/production_technology_wizard_views.xml', 'wizard/production_technology_wizard_views.xml',
'wizard/production_technology_re_adjust_wizard_views.xml', 'wizard/production_technology_re_adjust_wizard_views.xml',
'wizard/mrp_workorder_batch_replan_wizard_views.xml',
'views/mrp_views_menus.xml', 'views/mrp_views_menus.xml',
'views/agv_scheduling_views.xml', 'views/agv_scheduling_views.xml',
'views/stock_lot_views.xml', 'views/stock_lot_views.xml',
@@ -37,6 +38,9 @@
'views/agv_setting_views.xml', 'views/agv_setting_views.xml',
'views/sf_maintenance_equipment.xml', 'views/sf_maintenance_equipment.xml',
'views/res_config_settings_views.xml', 'views/res_config_settings_views.xml',
'views/sale_order_views.xml',
'views/mrp_workorder_batch_replan.xml',
'views/purchase_order_view.xml',
], ],
'assets': { 'assets': {
@@ -49,6 +53,8 @@
'sf_manufacturing/static/src/scss/kanban_change.scss', 'sf_manufacturing/static/src/scss/kanban_change.scss',
'sf_manufacturing/static/src/xml/button_show_on_tree.xml', '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/workpiece_delivery_wizard_confirm.js',
'sf_manufacturing/static/src/js/agv_scheduling_resend_confirm.js',
'sf_manufacturing/static/src/js/agv_scheduling_cancel_confirm.js',
'sf_manufacturing/static/src/js/qr.js', 'sf_manufacturing/static/src/js/qr.js',
'sf_manufacturing/static/src/xml/qr.xml', 'sf_manufacturing/static/src/xml/qr.xml',
] ]

View File

@@ -1,2 +1,3 @@
from . import controllers from . import controllers
from . import workpiece from . import workpiece
from . import main

View File

@@ -1,5 +1,7 @@
import logging import logging
import json import json
import traceback
from odoo import http from odoo import http
from odoo.http import request from odoo.http import request
from odoo.addons.sf_bf_connect.controllers.controllers import Sf_Bf_Connect from odoo.addons.sf_bf_connect.controllers.controllers import Sf_Bf_Connect
@@ -25,7 +27,7 @@ class JikimoSaleRoutePicking(Sf_Bf_Connect):
bfm_process_order_list = json.loads(kw['bfm_process_order_list']) bfm_process_order_list = json.loads(kw['bfm_process_order_list'])
order_id = request.env['sale.order'].with_user(request.env.ref("base.user_admin")).sale_order_create( order_id = request.env['sale.order'].with_user(request.env.ref("base.user_admin")).sale_order_create(
company_id, kw['delivery_name'], kw['delivery_telephone'], kw['delivery_address'], company_id, kw['delivery_name'], kw['delivery_telephone'], kw['delivery_address'],
kw['delivery_end_date'], kw['payments_way'], kw['pay_way'], state='draft') kw['delivery_end_date'], kw['payments_way'], kw['pay_way'], kw['order_number'], state='draft')
i = 1 i = 1
# 给sale_order的default_code字段赋值 # 给sale_order的default_code字段赋值
# aa = request.env['sale.order'].sudo().search([('name', '=', order_id.name)]) # aa = request.env['sale.order'].sudo().search([('name', '=', order_id.name)])
@@ -44,7 +46,8 @@ class JikimoSaleRoutePicking(Sf_Bf_Connect):
i += 1 i += 1
res['factory_order_no'] = order_id.name res['factory_order_no'] = order_id.name
except Exception as e: except Exception as e:
_logger.info('get_bfm_process_order_list error:%s' % e) traceback_error = traceback.format_exc()
logging.error('get_bfm_process_order_list error: %s' % traceback_error)
res['status'] = -1 res['status'] = -1
res['message'] = '工厂创建销售订单和产品失败,请联系管理员' res['message'] = '工厂创建销售订单和产品失败,请联系管理员'
request.cr.rollback() request.cr.rollback()

View File

@@ -0,0 +1,21 @@
#. module: sf_manufacturing
#. odoo-python
#: code:addons/sf_manufacturing/models/mrp_production.py:0
#, python-format
msgid "You must enter a serial number for %s"
msgstr "您必须为%s输入一个序列号。"
#. module: sf_manufacturing
#. odoo-python
#: code:addons/sf_manufacturing/models/mrp_production.py:0
#, python-format
msgid "You must enter a serial number for each line of %s"
msgstr "您必须为以下各%s行输入序列号"
#. module: sf_manufacturing
#. odoo-python
#: code:addons/sf_manufacturing/models/mrp_production.py:0
#, python-format
msgid "You have %s incomplete supplies: %s"
msgstr "您有%s补给未完成: %s"

View File

@@ -0,0 +1,12 @@
# migrations/1.1.0/post-migrate.py
from odoo import api, SUPERUSER_ID
def migrate(cr, version):
# 获取环境
env = api.Environment(cr, SUPERUSER_ID, {})
# 示例:添加新字段
env.ref('sf_dlm.product_embryo_sf_self_machining').product_tmpl_id.write({'categ_type': '坯料'})
env.ref('sf_dlm.product_template_sf').product_tmpl_id.write({'categ_type': '成品'})
env.ref('sf_dlm.product_embryo_sf_outsource').product_tmpl_id.write({'categ_type': '坯料'})
env.ref('sf_dlm.product_embryo_sf_purchase').product_tmpl_id.write({'categ_type': '坯料'})

View File

@@ -13,3 +13,6 @@ from . import agv_scheduling
from . import res_config_setting from . import res_config_setting
from . import sf_technology_design from . import sf_technology_design
from . import sf_production_common from . import sf_production_common
from . import sale_order
from . import quick_easy_order
from . import purchase_order

View File

@@ -1,6 +1,7 @@
import logging import logging
import requests import requests
from datetime import timedelta
from odoo import models, fields, api, _ from odoo import models, fields, api, _
from odoo.exceptions import UserError from odoo.exceptions import UserError
@@ -210,9 +211,18 @@ class AgvScheduling(models.Model):
def button_cancel(self): def button_cancel(self):
# 弹出二次确认窗口后执行 # 弹出二次确认窗口后执行
for rec in self: for rec in self:
if rec.state != '待下发':
raise UserError('只有待下发状态的AGV调度任务才能取消')
rec.state = '已取消' rec.state = '已取消'
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'target': 'new',
'params': {
'message': '任务取消成功!',
'type': 'success',
'sticky': False,
'next': {'type': 'ir.actions.act_window_close'},
}
}
def finish_scheduling(self): def finish_scheduling(self):
""" """
@@ -232,7 +242,7 @@ class AgvScheduling(models.Model):
agv_route sf.agv.task.route对象 agv_route sf.agv.task.route对象
""" """
for rec in self: for rec in self:
if rec.state != '待下发': if rec.state not in ['待下发', '配送中']:
return False return False
_logger.info('AGV任务调度下发调度任务路线为%s' % agv_task_route) _logger.info('AGV任务调度下发调度任务路线为%s' % agv_task_route)
rec.state = '配送中' rec.state = '配送中'
@@ -264,7 +274,45 @@ class AgvScheduling(models.Model):
'task_delivery_time': fields.Datetime.now() 'task_delivery_time': fields.Datetime.now()
}) })
return super().write(vals) return super().write(vals)
def button_cancel_confirm(self):
if self.task_delivery_time > fields.Datetime.now() - timedelta(minutes=10):
return {
'type': 'ir.actions.client',
'tag': 'agv_scheduling_cancel_confirm',
'params': {
'agv_scheduling_id': self.id,
}
}
else:
return self.button_cancel()
def button_resend_confirm(self):
if self.task_delivery_time > fields.Datetime.now() - timedelta(minutes=10):
return {
'type': 'ir.actions.client',
'tag': 'agv_scheduling_resend_confirm',
'params': {
'agv_scheduling_id': self.id,
'context': self.env.context,
}
}
else:
return self.button_resend()
def button_resend(self):
self.dispatch_scheduling(self.agv_route_id)
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'target': 'new',
'params': {
'message': '任务重新下发成功!',
'type': 'success',
'sticky': False,
'next': {'type': 'ir.actions.act_window_close'},
}
}
class ResMrpWorkOrder(models.Model): class ResMrpWorkOrder(models.Model):
_inherit = 'mrp.workorder' _inherit = 'mrp.workorder'

View File

@@ -7,7 +7,7 @@ class ModelType(models.Model):
name = fields.Char('名称') name = fields.Char('名称')
# embryo_tolerance = fields.Char('坯料容余') # embryo_tolerance = fields.Char('坯料容余')
embryo_tolerance_id = fields.Many2one('sf.embryo.redundancy', string='坯料') embryo_tolerance_id = fields.Many2one('sf.embryo.redundancy', string='坯料')
product_routing_tmpl_ids = fields.One2many('sf.product.model.type.routing.sort', 'product_model_type_id', product_routing_tmpl_ids = fields.One2many('sf.product.model.type.routing.sort', 'product_model_type_id',
'成品工序模板(自动化产线加工') '成品工序模板(自动化产线加工')
embryo_routing_tmpl_ids = fields.One2many('sf.embryo.model.type.routing.sort', 'embryo_model_type_id', embryo_routing_tmpl_ids = fields.One2many('sf.embryo.model.type.routing.sort', 'embryo_model_type_id',
@@ -75,7 +75,7 @@ class ManualProductModelTypeRoutingSort(models.Model):
_description = '成品工序排序(人工线下加工)' _description = '成品工序排序(人工线下加工)'
sequence = fields.Integer('Sequence') sequence = fields.Integer('Sequence')
route_workcenter_id = fields.Many2one('mrp.routing.workcenter') route_workcenter_id = fields.Many2one('mrp.routing.workcenter', domain=[('routing_type', 'in', ['人工线下加工'])])
is_repeat = fields.Boolean('重复', related='route_workcenter_id.is_repeat') is_repeat = fields.Boolean('重复', related='route_workcenter_id.is_repeat')
routing_type = fields.Selection(string="工序类型", related='route_workcenter_id.routing_type') routing_type = fields.Selection(string="工序类型", related='route_workcenter_id.routing_type')
workcenter_ids = fields.Many2many('mrp.workcenter', required=False, related='route_workcenter_id.workcenter_ids') workcenter_ids = fields.Many2many('mrp.workcenter', required=False, related='route_workcenter_id.workcenter_ids')

View File

@@ -8,6 +8,7 @@ import re
import requests import requests
from itertools import groupby from itertools import groupby
from collections import defaultdict, namedtuple from collections import defaultdict, namedtuple
from odoo import api, fields, models, SUPERUSER_ID, _ from odoo import api, fields, models, SUPERUSER_ID, _
from odoo.exceptions import UserError, ValidationError from odoo.exceptions import UserError, ValidationError
from odoo.addons.sf_base.commons.common import Common from odoo.addons.sf_base.commons.common import Common
@@ -18,6 +19,7 @@ class MrpProduction(models.Model):
_inherit = 'mrp.production' _inherit = 'mrp.production'
_description = "制造订单" _description = "制造订单"
_order = 'create_date desc' _order = 'create_date desc'
sale_order_id = fields.Many2one('sale.order', string='销售订单', compute='_compute_sale_order_id', store=True)
deadline_of_delivery = fields.Date('订单交期', tracking=True, compute='_compute_deadline_of_delivery') deadline_of_delivery = fields.Date('订单交期', tracking=True, compute='_compute_deadline_of_delivery')
# tray_ids = fields.One2many('sf.tray', 'production_id', string="托盘") # tray_ids = fields.One2many('sf.tray', 'production_id', string="托盘")
maintenance_count = fields.Integer(compute='_compute_maintenance_count', string="Number of maintenance requests") maintenance_count = fields.Integer(compute='_compute_maintenance_count', string="Number of maintenance requests")
@@ -34,6 +36,29 @@ class MrpProduction(models.Model):
tool_state_remark = fields.Text(string='功能刀具状态备注(缺刀)', compute='_compute_tool_state_remark', store=True) tool_state_remark = fields.Text(string='功能刀具状态备注(缺刀)', compute='_compute_tool_state_remark', store=True)
tool_state_remark2 = fields.Text(string='功能刀具状态备注(无效刀)', readonly=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_sale_order_id(self):
for production in self:
# 初始化 sale_order_id 为 False
sale_order_id = False
# 使用正则表达式查找产品名称中的 'S' 开头的字母数字字符串
match = re.search(r'S\d+', production.product_id.with_context(lang='zh_CN').name) # 从字符串开始匹配
if match:
result = match.group(0)
try:
# 查找与匹配的字符串相符的销售订单
sale_order = self.env['sale.order'].search(
[('name', '=', result)], limit=1, order='id asc'
)
if sale_order:
production.sale_order_id = sale_order.id
else:
logging.warning("No sale order found for production {} with product {} (name match: {})".format(
production.id, production.product_id.name, result))
except Exception as e:
logging.error("Error while fetching sale order for production {}: {}".format(production.id, str(e)))
@api.depends('procurement_group_id.mrp_production_ids.move_dest_ids.group_id.sale_id') @api.depends('procurement_group_id.mrp_production_ids.move_dest_ids.group_id.sale_id')
def _compute_deadline_of_delivery(self): def _compute_deadline_of_delivery(self):
for production in self: for production in self:
@@ -278,7 +303,7 @@ class MrpProduction(models.Model):
@api.depends( @api.depends(
'move_raw_ids.state', 'move_raw_ids.quantity_done', 'move_finished_ids.state', 'tool_state', 'move_raw_ids.state', 'move_raw_ids.quantity_done', 'move_finished_ids.state', 'tool_state',
'workorder_ids.state', 'product_qty', 'qty_producing', 'schedule_state', 'programming_state') 'workorder_ids.state', 'product_qty', 'qty_producing', 'schedule_state', 'programming_state', 'is_adjust')
def _compute_state(self): def _compute_state(self):
for production in self: for production in self:
if not production.state or not production.product_uom_id: if not production.state or not production.product_uom_id:
@@ -309,43 +334,47 @@ class MrpProduction(models.Model):
for move in production.move_raw_ids if move.product_id): for move in production.move_raw_ids if move.product_id):
production.state = 'progress' production.state = 'progress'
# 新添加的状态逻辑 # 新添加的状态逻辑
if ( if production.state in ['to_close', 'progress',
production.state == 'to_close' or production.state == 'progress') and production.schedule_state == '未排': 'technology_to_confirmed'] and production.schedule_state == '未排':
if not production.workorder_ids or production.is_adjust is True: if not production.workorder_ids or production.is_adjust is True:
production.state = 'technology_to_confirmed' production.state = 'technology_to_confirmed'
else: else:
production.state = 'confirmed' if production.is_adjust is True:
production.state = 'technology_to_confirmed'
else:
production.state = 'confirmed'
elif production.state == 'pending_cam' and production.schedule_state == '未排': elif production.state == 'pending_cam' and production.schedule_state == '未排':
production.state = 'confirmed' production.state = 'confirmed'
elif production.state == 'to_close' and production.schedule_state == '已排': elif production.state == 'to_close' and production.schedule_state == '已排':
production.state = 'pending_cam' production.state = 'pending_cam'
elif production.state == 'confirmed' and production.is_adjust is True:
production.state = 'technology_to_confirmed'
if production.state == 'confirmed' and production.schedule_state == '已排':
production.state = 'pending_cam'
if production.state == 'progress': if production.state == 'progress':
if all(wo_state not in ('progress', 'done', 'rework', 'scrap') for wo_state in if all(wo_state not in ('progress', 'done', 'rework', 'scrap') for wo_state in
production.workorder_ids.mapped('state')): production.workorder_ids.mapped('state')):
production.state = 'pending_cam' production.state = 'pending_cam'
if production.is_rework is True: if production.is_rework is True:
production.state = 'rework' production.state = 'rework'
if (production.state == 'rework' and production.tool_state == '0'
and production.schedule_state == '已排' and production.is_rework is False):
production.state = 'pending_cam'
# if production.state == 'pending_cam': # if production.state == 'pending_cam':
# if all(wo_state in 'done' for wo_state in production.workorder_ids.mapped('state')): # if all(wo_state in 'done' for wo_state in production.workorder_ids.mapped('state')):
# production.state = 'done' # production.state = 'done'
if any( if any((wo.test_results == '返工' and wo.state == 'done' and production.programming_state in ['已编程'])
( or (wo.is_rework is True and wo.state == 'done' and production.programming_state in ['编程中', '已编程'])
wo.test_results == '返工' and wo.state == 'done' and production.programming_state in [ for wo in production.workorder_ids):
'已编程']) or (
wo.state == 'rework' and production.programming_state == '编程中') or (
wo.is_rework is True and wo.state == 'done' and production.programming_state in ['编程中',
'已编程'])
for wo in
production.workorder_ids):
production.state = 'rework' production.state = 'rework'
if any(wo.test_results == '报废' and wo.state == 'done' for wo in production.workorder_ids): if any(wo.test_results == '报废' and wo.state == 'done' for wo in production.workorder_ids):
production.state = 'scrap' production.state = 'scrap'
if any(dr.test_results == '报废' and dr.handle_result == '已处理' for dr in if any(dr.test_results == '报废' and dr.handle_result == '已处理' for dr in
production.detection_result_ids): production.detection_result_ids):
production.state = 'cancel' production.state = 'cancel'
# 如果制造订单的功能刀具为【无效刀】则制造订单状态改为返工 if production.workorder_ids and all(wo_state in ('done', 'rework', 'cancel') for wo_state in production.workorder_ids.mapped('state')):
if production.tool_state == '2': if production.state not in ['scrap', 'rework', 'cancel']:
production.state = 'rework' production.state = 'done'
# 退回调整 # 退回调整
def technology_back_adjust(self): def technology_back_adjust(self):
@@ -368,37 +397,71 @@ class MrpProduction(models.Model):
if process_parameters: if process_parameters:
raise UserError(_("【工艺设计】-【参数】为%s的在【产品】中不存在,请先创建", ", ".join(process_parameters))) raise UserError(_("【工艺设计】-【参数】为%s的在【产品】中不存在,请先创建", ", ".join(process_parameters)))
if production_confirmed: if production_confirmed:
return { production_count = self.env['mrp.production'].search_count([
'name': _('退回调整'), ('origin', '=', self.origin),
'type': 'ir.actions.act_window', ('product_id', '=', self.product_id.id),
'view_mode': 'form', ('state', '=', 'confirmed')
'res_model': 'sf.production.technology.re_adjust.wizard', ])
'target': 'new', if production_count > 1:
'context': { return {
'default_production_id': self.id, 'name': _('退回调整'),
'default_origin': self.origin, 'type': 'ir.actions.act_window',
}} 'views': [(self.env.ref(
'sf_manufacturing.sf_production_technology_re_adjust_wizard_form_view').id,
'form')],
'res_model': 'sf.production.technology.re_adjust.wizard',
'target': 'new',
'context': {
'default_production_id': self.id,
'default_origin': self.origin,
}}
else:
return {
'name': _('退回调整'),
'type': 'ir.actions.act_window',
'views': [(self.env.ref(
'sf_manufacturing.sf_production_technology_re_adjust_wizard_confirm_form_view').id,
'form')],
'res_model': 'sf.production.technology.re_adjust.wizard',
'target': 'new',
'context': {
'default_production_id': self.id,
'default_origin': self.origin,
}}
# 工艺确认 # 工艺确认
def technology_confirm(self): def technology_confirm(self):
process_parameters = [] process_parameters = []
account_moves = [] account_moves = []
parameters_not = []
# 获取原有的工单对应的工序
origin_designs = self.workorder_ids.technology_design_id
# 获取已删除的工序
deleted_designs = origin_designs - self.technology_design_ids
if deleted_designs:
for deleted_design in deleted_designs:
workorder = self.env['mrp.workorder'].search([('technology_design_id', '=', deleted_design.id)])
purchase = workorder._get_surface_technics_purchase_ids()
account = self.env['account.move'].search([('id', 'in', purchase.invoice_ids.ids)])
if account.state not in ['cancel', False]:
if purchase.name not in account_moves:
account_moves.append(purchase.name)
special_design = self.technology_design_ids.filtered( special_design = self.technology_design_ids.filtered(
lambda a: a.routing_tag == 'special' and a.is_auto is False) lambda a: a.routing_tag == 'special' and a.is_auto is False)
for special in special_design: for special in special_design:
if special.route_id.routing_type == '表面工艺' and not special.process_parameters_id:
parameters_not.append(special.route_id.name)
if special.process_parameters_id: if special.process_parameters_id:
product_production_process = self.env['product.template'].search( product_production_process = self.env['product.template'].search(
[('server_product_process_parameters_id', '=', special.process_parameters_id.id)]) [('server_product_process_parameters_id', '=', special.process_parameters_id.id)])
if not product_production_process: if not product_production_process:
if special.process_parameters_id not in process_parameters: if special.process_parameters_id not in process_parameters:
process_parameters.append(special.process_parameters_id.display_name) process_parameters.append(special.process_parameters_id.display_name)
purchase = self.env['purchase.order'].search([('origin', '=', special.production_id.name)])
account = self.env['account.move'].search([('id', 'in', purchase.invoice_ids)])
if account.state not in ['cancel', False]:
if purchase.name not in account_moves:
account_moves.append(purchase.name)
if account_moves: if account_moves:
raise UserError(_("请联系工厂生产经理对采购订单%s生成的账单进行取消", ", ".join(account_moves))) raise UserError(_("请联系工厂生产经理对会计凭证%s生成的账单进行取消", ", ".join([move.name for move in account_moves])))
if parameters_not:
raise UserError(_("【工艺设计】-【工序】为%s未选择参数,请选择", ", ".join(parameters_not)))
if process_parameters: if process_parameters:
raise UserError(_("【工艺设计】-【参数】为%s的在【产品】中不存在,请先创建", ", ".join(process_parameters))) raise UserError(_("【工艺设计】-【参数】为%s的在【产品】中不存在,请先创建", ", ".join(process_parameters)))
# 判断同一个加工面的标准工序的顺序是否依次排序 # 判断同一个加工面的标准工序的顺序是否依次排序
@@ -426,16 +489,37 @@ class MrpProduction(models.Model):
error_panel.append(design.panel) error_panel.append(design.panel)
else: else:
if not error_panel and not process_parameters: if not error_panel and not process_parameters:
return { production_count = self.env['mrp.production'].search_count([
'name': _('工艺确认'), ('origin', '=', self.origin),
'type': 'ir.actions.act_window', ('product_id', '=', self.product_id.id),
'view_mode': 'form', ('state', '=', 'technology_to_confirmed')
'res_model': 'sf.production.technology.wizard', ])
'target': 'new', if production_count > 1:
'context': { return {
'default_production_id': self.id, 'name': _('工艺确认'),
'default_origin': self.origin, 'type': 'ir.actions.act_window',
}} 'views': [(self.env.ref(
'sf_manufacturing.sf_production_technology_wizard_form_view').id,
'form')],
'res_model': 'sf.production.technology.wizard',
'target': 'new',
'context': {
'default_production_id': self.id,
'default_origin': self.origin,
}}
else:
return {
'name': _('工艺确认'),
'type': 'ir.actions.act_window',
'views': [(self.env.ref(
'sf_manufacturing.sf_production_technology_wizard_confirm_form_view').id,
'form')],
'res_model': 'sf.production.technology.wizard',
'target': 'new',
'context': {
'default_production_id': self.id,
'default_origin': self.origin,
}}
if error_panel: if error_panel:
raise UserError(_("【加工面】为%s的标准工序顺序有误,请调整后重试", ", ".join(error_panel))) raise UserError(_("【加工面】为%s的标准工序顺序有误,请调整后重试", ", ".join(error_panel)))
return True return True
@@ -640,8 +724,8 @@ class MrpProduction(models.Model):
if self.move_finished_ids.filtered(lambda m: m.product_id == self.product_id).move_line_ids: if self.move_finished_ids.filtered(lambda m: m.product_id == self.product_id).move_line_ids:
self.move_finished_ids.filtered( self.move_finished_ids.filtered(
lambda m: m.product_id == self.product_id).move_line_ids.lot_id = self.lot_producing_id lambda m: m.product_id == self.product_id).move_line_ids.lot_id = self.lot_producing_id
if self.product_id.tracking == 'serial': # if self.product_id.tracking == 'serial':
self._set_qty_producing() # self._set_qty_producing()
# 重载根据工序生成工单的程序如果产品BOM中没有工序时 # 重载根据工序生成工单的程序如果产品BOM中没有工序时
# 根据产品对应的模板类型中工序,去生成工单; # 根据产品对应的模板类型中工序,去生成工单;
@@ -679,9 +763,10 @@ class MrpProduction(models.Model):
}] }]
if production.product_id.categ_id.type in ['成品', '坯料']: if production.product_id.categ_id.type in ['成品', '坯料']:
# # 根据工序设计生成工单 # # 根据工序设计生成工单
for route in production.technology_design_ids: technology_design_ids = sorted(production.technology_design_ids, key=lambda x: x.sequence)
for route in technology_design_ids:
workorder_has = self.env['mrp.workorder'].search( workorder_has = self.env['mrp.workorder'].search(
[('name', '=', route.route_id.name), ('production_id', '=', production.id)]) [('technology_design_id', '=', route.id), ('production_id', '=', production.id)])
if not workorder_has: if not workorder_has:
if route.route_id.routing_type not in ['表面工艺']: if route.route_id.routing_type not in ['表面工艺']:
workorders_values.append( workorders_values.append(
@@ -705,48 +790,24 @@ class MrpProduction(models.Model):
groupby(production_all, key=lambda x: x.product_id.id)} groupby(production_all, key=lambda x: x.product_id.id)}
for product_id, pd in grouped_product_ids.items(): for product_id, pd in grouped_product_ids.items():
product_id_to_production_names[product_id] = [p.name for p in pd] product_id_to_production_names[product_id] = [p.name for p in pd]
sorted_workorders = None
for production in production_all: for production in production_all:
proc_workorders = []
process_parameter_workorder = self.env['mrp.workorder'].search( process_parameter_workorder = self.env['mrp.workorder'].search(
[('surface_technics_parameters_id', '!=', False), ('production_id', '=', production.id), [('surface_technics_parameters_id', '!=', False), ('production_id', '=', production.id),
('is_subcontract', '=', True)], order='sequence asc') ('is_subcontract', '=', True), ('state', '!=', 'cancel')], order='sequence asc')
if process_parameter_workorder: if process_parameter_workorder:
consecutive_workorders = [] # 将这些特殊表面工艺工单的采购单与调拨单置为失效
for workorder in process_parameter_workorder:
workorder._get_surface_technics_purchase_ids().write({'state': 'cancel'})
workorder.move_subcontract_workorder_ids.write({'state': 'cancel'})
workorder.move_subcontract_workorder_ids.picking_id.write({'state': 'cancel'})
sorted_workorders = sorted(process_parameter_workorder, key=lambda w: w.sequence) sorted_workorders = sorted(process_parameter_workorder, key=lambda w: w.sequence)
for i, workorder in enumerate(sorted_workorders): if not sorted_workorders:
# 检查当前工作订单和下一个工作订单是否连续,并且供应商相同 return
if i == 0: for workorders in reversed(sorted_workorders):
consecutive_workorders.append(workorder) self.env['stock.picking'].create_outcontract_picking(workorders, production, sorted_workorders)
elif workorder.sequence == sorted_workorders[ self.env['purchase.order'].get_purchase_order(workorders, production, product_id_to_production_names)
i - 1].sequence + 1 and workorder.supplier_id.id == sorted_workorders[i - 1].supplier_id.id:
consecutive_workorders.append(workorder)
else:
# 处理连续组,如果它不为空
if consecutive_workorders:
# 创建外协出入库单和采购订单
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production)
self.env['purchase.order'].get_purchase_order(consecutive_workorders, production,
product_id_to_production_names)
if i < len(sorted_workorders) - 1:
# 重置连续组,并添加当前工作订单
consecutive_workorders = [workorder]
else:
# 判断最后一笔:
if workorder.sequence == sorted_workorders[
i - 1].sequence and workorder.supplier_id.id == sorted_workorders[
i - 1].supplier_id.id:
consecutive_workorders = [workorder]
else:
# 立即创建外协出入库单和采购订单
self.env['stock.picking'].create_outcontract_picking(workorder, production)
self.env['purchase.order'].get_purchase_order(workorder, production,
product_id_to_production_names)
consecutive_workorders = []
# 处理最后一个组,即使它可能只有一个工作订单
if consecutive_workorders:
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production)
self.env['purchase.order'].get_purchase_order(consecutive_workorders, production,
product_id_to_production_names)
# 工单排序 # 工单排序
def _reset_work_order_sequence1(self, k): def _reset_work_order_sequence1(self, k):
@@ -832,17 +893,22 @@ class MrpProduction(models.Model):
# workorder.picking_ids.move_ids = False # workorder.picking_ids.move_ids = False
workorder.picking_ids = False workorder.picking_ids = False
purchase_order = self.env['purchase.order'].search( purchase_order = self.env['purchase.order'].search(
[('state', '=', 'draft'), ('origin', '=', ','.join(production_process)), [('state', '=', 'draft'), ('origin', '=', item.name),
('purchase_type', '=', 'consignment')]) ('purchase_type', '=', 'consignment')])
for line in purchase_order.order_line: server_template = self.env['product.template'].search(
server_template = self.env['product.template'].search( [('server_product_process_parameters_id', '=',
[('server_product_process_parameters_id', '=', workorder.surface_technics_parameters_id.id), workorder.surface_technics_parameters_id.id),
('detailed_type', '=', 'service')]) ('detailed_type', '=', 'service')])
purchase_order_line = self.env['purchase.order.line'].search( for po in purchase_order:
[('product_id', '=', server_template.product_variant_id.id), ('id', '=', line.id), for line in po.order_line:
('product_qty', '=', len(production_process))], limit=1, order='id desc') if line.product_id == server_template.product_variant_id:
if purchase_order_line: continue
line.unlink() if server_template.server_product_process_parameters_id != line.product_id.server_product_process_parameters_id:
purchase_order_line = self.env['purchase.order.line'].search(
[('product_id', '=', server_template.product_variant_id.id), ('id', '=', line.id),
('product_qty', '=', 1)], limit=1, order='id desc')
if purchase_order_line:
line.unlink()
def _reset_work_order_sequence(self): def _reset_work_order_sequence(self):
""" """
@@ -856,10 +922,11 @@ class MrpProduction(models.Model):
work_ids = workorder_ids.filtered(lambda item: item.sequence == 0) work_ids = workorder_ids.filtered(lambda item: item.sequence == 0)
# 对工单进行逐个插入 # 对工单进行逐个插入
for work_id in work_ids: for work_id in work_ids:
for order_id in rec.workorder_ids.filtered(lambda item: item.sequence > 0): order_rework_ids = rec.workorder_ids.filtered(
if work_id.name == order_id.name: lambda item: (item.sequence > 0 and work_id.name == item.name
work_id.sequence = order_id.sequence + 1 and work_id.processing_panel == item.processing_panel))
break order_rework_ids = sorted(order_rework_ids, key=lambda item: item.sequence, reverse=True)
work_id.sequence = order_rework_ids[0].sequence + 1
# 对该工单之后的工单工序进行加一 # 对该工单之后的工单工序进行加一
work_order_ids = rec.workorder_ids.filtered( work_order_ids = rec.workorder_ids.filtered(
lambda item: item.sequence >= work_id.sequence and item.id != work_id.id) lambda item: item.sequence >= work_id.sequence and item.id != work_id.id)
@@ -874,8 +941,16 @@ class MrpProduction(models.Model):
and item.process_parameters_id == work.surface_technics_parameters_id) or and item.process_parameters_id == work.surface_technics_parameters_id) or
(item.route_id.name == work.name and item.panel (item.route_id.name == work.name and item.panel
and item.panel == work.processing_panel)) and item.panel == work.processing_panel))
if work.name == '人工线下加工':
td_ids = technology_design_ids.filtered(lambda item: (item.route_id.name in work.name))
if td_ids: if td_ids:
work.sequence = td_ids[0].sequence work.sequence = td_ids[0].sequence
cancel_work_ids = workorder_ids.filtered(lambda item: item.state in ('已取消', 'cancel'))
if cancel_work_ids:
sequence = max(workorder_ids.filtered(lambda item: item.state not in ('已取消', 'cancel')),
key=lambda w: w.sequence).sequence
for cw in cancel_work_ids:
cw.sequence = sequence + 1
def _reset_work_order_sequence_1(self): def _reset_work_order_sequence_1(self):
""" """
@@ -1127,13 +1202,15 @@ class MrpProduction(models.Model):
if self.programming_state in ['已编程']: if self.programming_state in ['已编程']:
cloud_programming = self._cron_get_programming_state() cloud_programming = self._cron_get_programming_state()
result_ids = self.detection_result_ids.filtered(lambda dr: dr.handle_result == '待处理') result_ids = self.detection_result_ids.filtered(lambda dr: dr.handle_result == '待处理')
work_ids = [] work_id_list = []
if result_ids: if result_ids:
for result_id in result_ids: work_id_list = [self.workorder_ids.filtered(
work_ids.append(self.workorder_ids.filtered( lambda wk: (wk.name == result_id.routing_type and wk.processing_panel == result_id.processing_panel
lambda wk: (wk.name == result_id.routing_type and wk.state == 'done')).id
and wk.processing_panel == result_id.processing_panel for result_id in result_ids]
and wk.state == 'done')).id) workorder_ids = self.workorder_ids.filtered(
lambda wk: wk.technology_design_id.routing_tag == 'standard' and wk.state not in ['rework', 'cancel'])
logging.info('标准工艺工单【%s' % workorder_ids)
return { return {
'name': _('返工'), 'name': _('返工'),
'type': 'ir.actions.act_window', 'type': 'ir.actions.act_window',
@@ -1142,7 +1219,8 @@ class MrpProduction(models.Model):
'target': 'new', 'target': 'new',
'context': { 'context': {
'default_production_id': self.id, 'default_production_id': self.id,
'default_workorder_ids': work_ids, 'default_workorder_ids': workorder_ids.ids if workorder_ids.ids != [] else self.workorder_ids.ids,
'default_hidden_workorder_ids': ','.join(map(str, work_id_list)) if work_id_list != [] else '',
'default_reprogramming_num': cloud_programming['reprogramming_num'], 'default_reprogramming_num': cloud_programming['reprogramming_num'],
'default_programming_state': cloud_programming['programming_state'], 'default_programming_state': cloud_programming['programming_state'],
'default_is_reprogramming': True if cloud_programming['programming_state'] in ['已下发'] else False 'default_is_reprogramming': True if cloud_programming['programming_state'] in ['已下发'] else False
@@ -1296,14 +1374,14 @@ class MrpProduction(models.Model):
raise_user_error=not self.env.context.get('from_orderpoint')) raise_user_error=not self.env.context.get('from_orderpoint'))
productions = self.env['mrp.production'].sudo().search( productions = self.env['mrp.production'].sudo().search(
[('origin', '=', self.origin)], order='id desc', limit=1) [('origin', '=', self.origin)], order='id desc', limit=1)
productions.write({'programming_no': self.programming_no, 'is_remanufacture': True})
move = self.env['stock.move'].search([('origin', '=', productions.name)], order='id desc') move = self.env['stock.move'].search([('origin', '=', productions.name)], order='id desc')
for mo in move: for mo in move:
domain = [] domain = []
if mo.procure_method == 'make_to_order' and mo.name != productions.name: if mo.location_id.barcode == 'WH-POSTPRODUCTION' and mo.rule_id.picking_type_id.barcode == 'PC':
if mo.name == '/': domain = [('barcode', '=', 'WH-PC'), ('sequence_code', '=', 'PC')]
domain = [('barcode', '=', 'WH-PC'), ('sequence_code', '=', 'PC')] elif mo.location_id.barcode == 'PL' and mo.rule_id.picking_type_id.barcode == 'INT':
elif mo.name == '': domain = [('barcode', '=', 'WH-INTERNAL'), ('sequence_code', '=', 'INT')]
domain = [('barcode', '=', 'WH-INTERNAL'), ('sequence_code', '=', 'INT')]
if domain: if domain:
picking_type = self.env['stock.picking.type'].search(domain) picking_type = self.env['stock.picking.type'].search(domain)
mo.write({'picking_type_id': picking_type.id}) mo.write({'picking_type_id': picking_type.id})
@@ -1322,7 +1400,6 @@ class MrpProduction(models.Model):
mo_move.write({'reference': sfp_move.reference, 'partner_id': sfp_move.partner_id.id, mo_move.write({'reference': sfp_move.reference, 'partner_id': sfp_move.partner_id.id,
'picking_id': sfp_move.picking_id.id, 'picking_type_id': sfp_move.picking_type_id.id, 'picking_id': sfp_move.picking_id.id, 'picking_type_id': sfp_move.picking_type_id.id,
'production_id': False}) 'production_id': False})
productions.write({'programming_no': self.programming_no, 'is_remanufacture': True})
# productions.procurement_group_id.mrp_production_ids.move_dest_ids.write( # productions.procurement_group_id.mrp_production_ids.move_dest_ids.write(
# {'group_id': self.env['procurement.group'].search([('name', '=', sale_order.name)])}) # {'group_id': self.env['procurement.group'].search([('name', '=', sale_order.name)])})
stock_picking_remanufacture = self.env['stock.picking'].search([('origin', '=', productions.name)]) stock_picking_remanufacture = self.env['stock.picking'].search([('origin', '=', productions.name)])
@@ -1397,7 +1474,27 @@ class MrpProduction(models.Model):
def _compute_production_type(self): def _compute_production_type(self):
for production in self: for production in self:
production.production_type = '自动化产线加工' if not production.product_id.is_manual_processing else '人工线下加工' production.production_type = '自动化产线加工' if not production.product_id.is_manual_processing else '人工线下加工'
@api.depends('procurement_group_id.mrp_production_ids.move_dest_ids.group_id.sale_id')
def _compute_sale_order_count(self):
for production in self:
if production.sale_order_id:
production.sale_order_count = 1
else:
production.sale_order_count = 0
def action_view_sale_orders(self):
if self.sale_order_id:
action = {
'res_model': 'sale.order',
'type': 'ir.actions.act_window',
}
action.update({
'view_mode': 'form',
'res_id': self.sale_order_id.id,
})
return action
@api.model_create_multi @api.model_create_multi
def create(self, vals_list): def create(self, vals_list):
""" """
@@ -1413,7 +1510,7 @@ class MrpProduction(models.Model):
vals['name'] = self.env['stock.picking.type'].browse(picking_type_id).sequence_id.next_by_id() vals['name'] = self.env['stock.picking.type'].browse(picking_type_id).sequence_id.next_by_id()
if not vals.get('procurement_group_id'): if not vals.get('procurement_group_id'):
product_id = self.env['product.product'].browse(vals['product_id']) product_id = self.env['product.product'].browse(vals['product_id'])
if product_id.product_tmpl_id.single_manufacturing: if product_id.product_tmpl_id.single_manufacturing:
if product_id.id not in product_group_id.keys(): if product_id.id not in product_group_id.keys():
procurement_group_vals = self._prepare_procurement_group_vals(vals) procurement_group_vals = self._prepare_procurement_group_vals(vals)
group_id = self.env["procurement.group"].create(procurement_group_vals).id group_id = self.env["procurement.group"].create(procurement_group_vals).id
@@ -1423,23 +1520,29 @@ class MrpProduction(models.Model):
vals['procurement_group_id'] = product_group_id[product_id.id] vals['procurement_group_id'] = product_group_id[product_id.id]
return super(MrpProduction, self).create(vals_list) return super(MrpProduction, self).create(vals_list)
@api.depends('procurement_group_id.stock_move_ids.created_purchase_line_id.order_id', 'procurement_group_id.stock_move_ids.move_orig_ids.purchase_line_id.order_id') @api.depends('procurement_group_id.stock_move_ids.created_purchase_line_id.order_id',
'procurement_group_id.stock_move_ids.move_orig_ids.purchase_line_id.order_id')
def _compute_purchase_order_count(self): def _compute_purchase_order_count(self):
for production in self: for production in self:
# 找到来源的第一张制造订单的采购组 # 找到来源的第一张制造订单的采购组
if production.product_id.product_tmpl_id.single_manufacturing == True: if production.product_id.product_tmpl_id.single_manufacturing == True:
first_production = self.env['mrp.production'].search([('origin', '=', production.origin), ('product_id', '=', production.product_id.id)], limit=1, order='id asc') first_production = self.env['mrp.production'].search(
production.purchase_order_count = len(first_production.procurement_group_id.stock_move_ids.created_purchase_line_id.order_id | [('origin', '=', production.origin), ('product_id', '=', production.product_id.id)], limit=1,
first_production.procurement_group_id.stock_move_ids.move_orig_ids.purchase_line_id.order_id) order='id asc')
production.purchase_order_count = len(
first_production.procurement_group_id.stock_move_ids.created_purchase_line_id.order_id |
first_production.procurement_group_id.stock_move_ids.move_orig_ids.purchase_line_id.order_id)
else: else:
production.purchase_order_count = len(production.procurement_group_id.stock_move_ids.created_purchase_line_id.order_id | production.purchase_order_count = len(
production.procurement_group_id.stock_move_ids.move_orig_ids.purchase_line_id.order_id) production.procurement_group_id.stock_move_ids.created_purchase_line_id.order_id |
production.procurement_group_id.stock_move_ids.move_orig_ids.purchase_line_id.order_id)
@api.depends('procurement_group_id', 'procurement_group_id.stock_move_ids.group_id') @api.depends('procurement_group_id', 'procurement_group_id.stock_move_ids.group_id')
def _compute_picking_ids(self): def _compute_picking_ids(self):
for order in self: for order in self:
if order.product_id.product_tmpl_id.single_manufacturing == True: if order.product_id.product_tmpl_id.single_manufacturing == True:
first_order = self.env['mrp.production'].search([('origin', '=', order.origin), ('product_id', '=', order.product_id.id)], limit=1, order='id asc') first_order = self.env['mrp.production'].search(
[('origin', '=', order.origin), ('product_id', '=', order.product_id.id)], limit=1, order='id asc')
order.picking_ids = self.env['stock.picking'].search([ order.picking_ids = self.env['stock.picking'].search([
('group_id', '=', first_order.procurement_group_id.id), ('group_id', '!=', False), ('group_id', '=', first_order.procurement_group_id.id), ('group_id', '!=', False),
]) ])
@@ -1450,6 +1553,55 @@ class MrpProduction(models.Model):
]) ])
order.delivery_count = len(order.picking_ids) order.delivery_count = len(order.picking_ids)
def action_view_purchase_orders(self):
self.ensure_one()
if self.is_remanufacture:
production = self
elif self.product_id.product_tmpl_id.single_manufacturing == True:
production = self.env['mrp.production'].search(
[('origin', '=', self.origin), ('product_id', '=', self.product_id.id)], limit=1, order='id asc')
else:
production = self
purchase_order_ids = (
production.procurement_group_id.stock_move_ids.created_purchase_line_id.order_id | production.procurement_group_id.stock_move_ids.move_orig_ids.purchase_line_id.order_id).ids
action = {
'res_model': 'purchase.order',
'type': 'ir.actions.act_window',
}
if len(purchase_order_ids) == 1:
action.update({
'view_mode': 'form',
'res_id': purchase_order_ids[0],
})
else:
action.update({
'name': _("Purchase Order generated from %s", self.name),
'domain': [('id', 'in', purchase_order_ids)],
'view_mode': 'tree,form',
})
return action
def _subcontract_sanity_check(self):
for production in self:
if production.product_tracking != 'none' and not self.lot_producing_id:
raise UserError(_('You must enter a serial number for %s') % production.product_id.name)
for sml in production.move_raw_ids.move_line_ids:
if sml.tracking != 'none' and not sml.lot_id:
picking_ids = production.picking_ids.filtered(
lambda p: p.state not in ['done', 'cancel'])
picking_num = len(picking_ids)
picking_info = ', '.join(
['%s:%s' % (picking.picking_type_id.name, picking.name) for picking in picking_ids]
)
if picking_info:
raise UserError(_('You have %s incomplete supplies: %s') % (
picking_num, picking_info))
else:
raise UserError(
_('You must enter a serial number for each line of %s') % sml.product_id.display_name)
return True
class sf_detection_result(models.Model): class sf_detection_result(models.Model):
_name = 'sf.detection.result' _name = 'sf.detection.result'
_description = "检测结果" _description = "检测结果"

View File

@@ -86,9 +86,18 @@ class ResMrpRoutingWorkcenter(models.Model):
@api.model @api.model
def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None): def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None):
if self._context.get('production_id'): if self._context.get('production_id'):
route_ids = []
technology_design = self.env['sf.technology.design'].search( technology_design = self.env['sf.technology.design'].search(
[('production_id', '=', self._context.get('production_id'))]) [('production_id', '=', self._context.get('production_id'))])
route_ids = [t.route_id.id for t in technology_design] for t in technology_design.filtered(lambda a: a.routing_tag == 'special'):
domain = [('id', 'not in', route_ids)] if not t.process_parameters_id:
route_ids.append(t.route_id.surface_technics_id.id)
domain = [('id', 'not in', route_ids), ('routing_tag', '=', 'special')]
return self._search(domain, limit=limit, access_rights_uid=name_get_uid)
if self._context.get('is_duplicate') and self._context.get('model_name'):
# 查询出已经选择的工序
model_type = self.env[self._context.get('model_name')].search_read([],['route_workcenter_id'])
route_workcenter_ids = [item['route_workcenter_id'][0] if item['route_workcenter_id'] else False for item in model_type]
domain = args + [('id', 'not in', route_workcenter_ids)]
return self._search(domain, limit=limit, access_rights_uid=name_get_uid) return self._search(domain, limit=limit, access_rights_uid=name_get_uid)
return super()._name_search(name, args, operator, limit, name_get_uid) return super()._name_search(name, args, operator, limit, name_get_uid)

View File

@@ -17,23 +17,27 @@ from odoo.exceptions import UserError, ValidationError
from odoo.addons.sf_mrs_connect.models.ftp_operate import FtpController from odoo.addons.sf_mrs_connect.models.ftp_operate import FtpController
class ResMrpWorkOrder(models.Model): class ResMrpWorkOrder(models.Model):
_inherit = 'mrp.workorder' _inherit = 'mrp.workorder'
_order = 'sequence asc' _order = 'sequence asc'
product_tmpl_name = fields.Char('坯料产品名称', related='production_bom_id.bom_line_ids.product_id.name') product_tmpl_name = fields.Char('坯料产品名称', related='production_bom_id.bom_line_ids.product_id.name')
product_tmpl_id_length = fields.Float(related='production_id.product_tmpl_id.length', readonly=True, store=True, product_tmpl_id_length = fields.Float(string='坯料长度(mm)', related='material_length', readonly=True, store=False)
string="坯料度(mm)") product_tmpl_id_width = fields.Float(string='坯料度(mm)', related='material_width', readonly=True, store=False)
product_tmpl_id_width = fields.Float(related='production_id.product_tmpl_id.width', readonly=True, store=True, product_tmpl_id_height = fields.Float(string='坯料高度(mm)', related='material_height', readonly=True, store=False)
string="坯料宽度(mm)") # product_tmpl_id_length = fields.Float(related='production_id.product_tmpl_id.length', readonly=True, store=True,
product_tmpl_id_height = fields.Float(related='production_id.product_tmpl_id.height', readonly=True, store=True, # string="坯料长度(mm)")
string="坯料高度(mm)") # product_tmpl_id_width = fields.Float(related='production_id.product_tmpl_id.width', readonly=True, store=True,
# string="坯料宽度(mm)")
# product_tmpl_id_height = fields.Float(related='production_id.product_tmpl_id.height', readonly=True, store=True,
# string="坯料高度(mm)")
product_tmpl_id_materials_id = fields.Many2one(related='production_id.product_tmpl_id.materials_id', readonly=True, product_tmpl_id_materials_id = fields.Many2one(related='production_id.product_tmpl_id.materials_id', readonly=True,
store=True, check_company=True, string="材料") store=True, check_company=True, string="材料")
product_tmpl_id_materials_type_id = fields.Many2one(related='production_id.product_tmpl_id.materials_type_id', product_tmpl_id_materials_type_id = fields.Many2one(related='production_id.product_tmpl_id.materials_type_id',
readonly=True, store=True, check_company=True, string="型号") readonly=True, store=True, check_company=True, string="型号")
workcenter_id = fields.Many2one('mrp.workcenter', string='工作中心', required=False) # workcenter_id = fields.Many2one('mrp.workcenter', string='工作中心', required=False)
users_ids = fields.Many2many("res.users", 'users_workorder', related="workcenter_id.users_ids") users_ids = fields.Many2many("res.users", 'users_workorder', related="workcenter_id.users_ids")
processing_panel = fields.Char('加工面') processing_panel = fields.Char('加工面')
sequence = fields.Integer(string='工序') sequence = fields.Integer(string='工序')
@@ -126,7 +130,7 @@ class ResMrpWorkOrder(models.Model):
Y10_axis = fields.Float(default=0) Y10_axis = fields.Float(default=0)
Z10_axis = fields.Float(default=0) Z10_axis = fields.Float(default=0)
X_deviation_angle = fields.Integer(string="X轴偏差度", default=0) X_deviation_angle = fields.Integer(string="X轴偏差度", default=0)
test_results = fields.Selection([("合格", "合格"), ("返工", "返工"), ("报废", "报废")], default='合格', test_results = fields.Selection([("合格", "合格"), ("返工", "返工")], default='合格',
string="检测结果", tracking=True) string="检测结果", tracking=True)
cnc_ids = fields.One2many("sf.cnc.processing", 'workorder_id', string="CNC加工程序") cnc_ids = fields.One2many("sf.cnc.processing", 'workorder_id', string="CNC加工程序")
cmm_ids = fields.One2many("sf.cmm.program", 'workorder_id', string="CMM程序") cmm_ids = fields.One2many("sf.cmm.program", 'workorder_id', string="CMM程序")
@@ -134,8 +138,11 @@ class ResMrpWorkOrder(models.Model):
glb_file = fields.Binary("glb模型文件", related='production_id.model_file') glb_file = fields.Binary("glb模型文件", related='production_id.model_file')
is_subcontract = fields.Boolean(string='是否外协') is_subcontract = fields.Boolean(string='是否外协')
surface_technics_parameters_id = fields.Many2one('sf.production.process.parameter', string="表面工艺可选参数") surface_technics_parameters_id = fields.Many2one('sf.production.process.parameter', string="表面工艺可选参数")
picking_ids = fields.Many2many('stock.picking', string='外协出入库单')
# purchase_id = fields.Many2one('purchase.order', string='外协采购单') picking_ids = fields.Many2many('stock.picking', string='外协出入库单',
compute='_compute_surface_technics_picking_ids')
purchase_id = fields.Many2many('purchase.order', string='外协采购单')
surface_technics_picking_count = fields.Integer("外协出入库", compute='_compute_surface_technics_picking_ids') surface_technics_picking_count = fields.Integer("外协出入库", compute='_compute_surface_technics_picking_ids')
surface_technics_purchase_count = fields.Integer("外协采购", compute='_compute_surface_technics_purchase_ids') surface_technics_purchase_count = fields.Integer("外协采购", compute='_compute_surface_technics_purchase_ids')
@@ -235,15 +242,15 @@ class ResMrpWorkOrder(models.Model):
for workorder in self: for workorder in self:
if workorder.routing_type == '表面工艺': if workorder.routing_type == '表面工艺':
domain = [('origin', '=', workorder.production_id.name), ('state', 'not in', ['cancel']), domain = [('origin', '=', workorder.production_id.name), ('state', 'not in', ['cancel']),
('partner_id', '!=', False)] ('partner_id', '=', workorder.supplier_id.id)]
previous_workorder = self.env['mrp.workorder'].search( previous_workorder = self.env['mrp.workorder'].search(
[('sequence', '=', workorder.sequence - 1), ('routing_type', '=', '表面工艺'), [('sequence', '=', workorder.sequence - 1), ('routing_type', '=', '表面工艺'),
('production_id', '=', workorder.production_id.id)]) ('production_id', '=', workorder.production_id.id)])
if previous_workorder: # if previous_workorder:
if previous_workorder.supplier_id != workorder.supplier_id: # if previous_workorder.supplier_id != workorder.supplier_id:
process_product = self.env['product.template']._get_process_parameters_product( # domain += [('surface_technics_parameters_id', '=', workorder.surface_technics_parameters_id.id)]
previous_workorder.surface_technics_parameters_id) # else:
domain += [('partner_id', '=', process_product.partner_id.id)] domain += [('surface_technics_parameters_id', '=', workorder.surface_technics_parameters_id.id)]
picking_ids = self.env['stock.picking'].search(domain, order='id asc') picking_ids = self.env['stock.picking'].search(domain, order='id asc')
workorder.surface_technics_picking_count = len(picking_ids) workorder.surface_technics_picking_count = len(picking_ids)
workorder.picking_ids = picking_ids.ids workorder.picking_ids = picking_ids.ids
@@ -267,58 +274,60 @@ class ResMrpWorkOrder(models.Model):
@api.depends('state', 'production_id.name') @api.depends('state', 'production_id.name')
def _compute_surface_technics_purchase_ids(self): def _compute_surface_technics_purchase_ids(self):
for order in self: for order in self:
if order.routing_type == '表面工艺': if order.routing_type == '表面工艺' and order.state not in ['cancel']:
if order.production_id.production_type == '自动化产线加工': domain = [('purchase_type', '=', 'consignment'),
domain = [('programming_no', '=', order.production_id.programming_no)] ('origin', 'like', '%' + self.production_id.name + '%'),
else: ('state', '!=', 'cancel')]
domain = [('origin', '=', order.production_id.origin)]
production_programming = self.env['mrp.production'].search(domain, order='name asc')
production_list = [production.name for production in production_programming]
production_no_remanufacture = production_programming.filtered(lambda a: a.is_remanufacture is False)
# technology_design = self.env['sf.technology.design'].search(
# [('process_parameters_id', '=', order.surface_technics_parameters_id.id),
# ('production_id', '=', order.production_id.id)])
# if technology_design.is_auto is False:
# domain = [('origin', '=', order.production_id.name)]
# else:
domain = [('purchase_type', '=', 'consignment'),('origin', '=', ','.join(production_list))]
purchase = self.env['purchase.order'].search(domain) purchase = self.env['purchase.order'].search(domain)
order.surface_technics_purchase_count = 0
if not purchase: if not purchase:
order.surface_technics_purchase_count = 0 order.surface_technics_purchase_count = 0
for line in purchase.order_line: for po in purchase:
if line.product_id.server_product_process_parameters_id == order.surface_technics_parameters_id: if any(
if line.product_qty == len(production_no_remanufacture): line.product_id and line.product_id.server_product_process_parameters_id == order.surface_technics_parameters_id
order.surface_technics_purchase_count = len(purchase) for line in po.order_line):
order.surface_technics_purchase_count = 1
else: else:
order.surface_technics_purchase_count = 0 order.surface_technics_purchase_count = 0
def action_view_surface_technics_purchase(self): def action_view_surface_technics_purchase(self):
self.ensure_one() self.ensure_one()
if self.routing_type == '表面工艺': # if self.routing_type == '表面工艺':
if self.production_id.production_type == '自动化产线加工': # if self.production_id.production_type == '自动化产线加工':
domain = [('programming_no', '=', self.production_id.programming_no)] # domain = [('programming_no', '=', self.production_id.programming_no)]
else: # else:
domain = [('origin', '=', self.production_id.origin)] # domain = [('origin', '=', self.production_id.origin)]
production_programming = self.env['mrp.production'].search(domain, order='name asc') # production_programming = self.env['mrp.production'].search(domain, order='name asc')
production_list = [production.name for production in production_programming] # production_list = [production.name for production in production_programming]
# production_no_remanufacture = production_programming.filtered(lambda a: a.is_remanufacture is False)
# technology_design = self.env['sf.technology.design'].search( # technology_design = self.env['sf.technology.design'].search(
# [('process_parameters_id', '=', self.surface_technics_parameters_id.id), # [('process_parameters_id', '=', self.surface_technics_parameters_id.id),
# ('production_id', '=', self.production_id.id)]) # ('production_id', '=', self.production_id.id)])
# if technology_design.is_auto is False: # if technology_design.is_auto is False:
# domain = [('origin', '=', self.production_id.name)] # domain = [('origin', '=', self.production_id.name)]
# else: # else:
domain = [('origin', '=', ','.join(production_list)), ('purchase_type', '=', 'consignment')] purchase_orders_id = self._get_surface_technics_purchase_ids()
purchase_orders = self.env['purchase.order'].search(domain)
result = { result = {
"type": "ir.actions.act_window", "type": "ir.actions.act_window",
"res_model": "purchase.order", "res_model": "purchase.order",
"res_id": purchase_orders.id, "res_id": purchase_orders_id.id,
# "domain": [['id', 'in', self.purchase_id]], # "domain": [['id', 'in', self.purchase_id]],
"name": _("Purchase Orders"), "name": _("Purchase Orders"),
'view_mode': 'form', 'view_mode': 'form',
} }
return result return result
def _get_surface_technics_purchase_ids(self):
domain = [('origin', 'like', '%' + self.production_id.name + '%'), ('purchase_type', '=', 'consignment')]
purchase_orders = self.env['purchase.order'].search(domain)
purchase_orders_id = self.env['purchase.order']
for po in purchase_orders:
for line in po.order_line:
if line.product_id.server_product_process_parameters_id == self.surface_technics_parameters_id:
if line.product_qty == 1:
purchase_orders_id = line.order_id
return purchase_orders_id
supplier_id = fields.Many2one('res.partner', string='外协供应商') supplier_id = fields.Many2one('res.partner', string='外协供应商')
equipment_id = fields.Many2one('maintenance.equipment', string='加工设备', tracking=True) equipment_id = fields.Many2one('maintenance.equipment', string='加工设备', tracking=True)
# 保存名称 # 保存名称
@@ -1014,55 +1023,12 @@ class ResMrpWorkOrder(models.Model):
'production_id.tool_state', 'production_id.schedule_state', 'sequence', 'production_id.tool_state', 'production_id.schedule_state', 'sequence',
'production_id.programming_state') 'production_id.programming_state')
def _compute_state(self): def _compute_state(self):
# super()._compute_state()
for workorder in self:
if workorder.sequence != 1:
previous_workorder = self.env['mrp.workorder'].search(
[('production_id', '=', workorder.production_id.id),
('sequence', '=', workorder.sequence - 1)])
if workorder.state == 'pending':
if all([wo.state in ('done', 'cancel') for wo in workorder.blocked_by_workorder_ids]):
if workorder.production_id.reservation_state == 'assigned' and workorder.production_id.schedule_state == '已排':
if ((workorder.sequence == 1 and not workorder.blocked_by_workorder_ids)
or (workorder.blocked_by_workorder_ids.state in ('done', 'cancel')
and workorder.blocked_by_workorder_ids.test_results not in ['报废', '返工'])
or (previous_workorder.state in ('done', 'cancel')
and not workorder.blocked_by_workorder_ids
and previous_workorder.test_results not in ['报废', '返工'])
):
workorder.state = 'ready'
continue
if workorder.production_id.schedule_state == '未排' and workorder.state in ('waiting', 'ready'):
if workorder.sequence != 1:
workorder.state = 'pending'
continue
if workorder.state not in ('waiting', 'ready'):
continue
if workorder.state in (
'waiting') and workorder.sequence == 1 and workorder.production_id.schedule_state == '已排':
workorder.state = 'ready'
continue
if not all([wo.state in ('done', 'cancel') for wo in workorder.blocked_by_workorder_ids]):
workorder.state = 'pending'
if workorder.state in ['waiting']:
if previous_workorder.state == 'waiting':
workorder.state = 'pending'
if workorder.sequence == 1 and workorder.state == 'pending':
workorder.state = 'waiting'
continue
if workorder.production_id.reservation_state not in ('waiting', 'confirmed', 'assigned'):
continue
if workorder.production_id.reservation_state == 'assigned' and workorder.state == 'waiting' and workorder.production_id.schedule_state == '已排':
workorder.state = 'ready'
elif workorder.production_id.reservation_state != 'assigned' and workorder.state == 'ready':
workorder.state = 'waiting'
for workorder in self: for workorder in self:
# 如果工单的工序没有进行排序则跳出循环 # 如果工单的工序没有进行排序则跳出循环
if workorder.production_id.workorder_ids.filtered(lambda wk: wk.sequence == 0): if workorder.production_id.workorder_ids.filtered(lambda wk: wk.sequence == 0):
continue continue
# ===== 对所有按序号排序的非[进行中、完成、返工、取消]状态的工单,除了第一条之外的工单状态都设置为[等待其他工单] ===== # ===== 对所有按序号排序的非[进行中、完成、返工、取消]状态的工单,除了第一条之外的工单状态都设置为[等待其他工单] =====
logging.info(workorder.state) # logging.info(workorder.state)
work_ids = workorder.production_id.workorder_ids.filtered( work_ids = workorder.production_id.workorder_ids.filtered(
lambda wk: wk.state not in ['done', 'rework', 'cancel']) lambda wk: wk.state not in ['done', 'rework', 'cancel'])
if not work_ids: if not work_ids:
@@ -1075,13 +1041,33 @@ class ResMrpWorkOrder(models.Model):
if workorder.state != 'pending': if workorder.state != 'pending':
workorder.state = 'pending' workorder.state = 'pending'
continue continue
# ================= 如果制造订单制造类型为【人工线下加工】==========================
if (workorder.production_id.production_type == '人工线下加工'
and workorder.production_id.schedule_state == '已排'
and len(workorder.production_id.picking_ids.filtered(
lambda w: w.state not in ['done', 'cancel'])) == 0):
if workorder.is_subcontract is True:
purchase_orders_id = self._get_surface_technics_purchase_ids()
if purchase_orders_id.state == 'purchase':
workorder.state = 'ready'
move_out = workorder.move_subcontract_workorder_ids[1]
for mo in move_out:
if mo.state != 'done':
mo.write({'state': 'assigned', 'production_id': False})
if not mo.move_line_ids:
self.env['stock.move.line'].create(
mo.get_move_line(workorder.production_id, workorder))
continue
else:
workorder.state = 'waiting'
continue
else:
workorder.state = 'ready'
continue
# ================= 如果制造订单刀具状态为[无效刀、缺刀] 或者 制造订单状态为[返工]========================== # ================= 如果制造订单刀具状态为[无效刀、缺刀] 或者 制造订单状态为[返工]==========================
if (workorder.production_id.tool_state in ['1', '2'] or workorder.production_id.state == 'rework' if (workorder.production_id.tool_state in ['1', '2'] or workorder.production_id.state == 'rework'
or workorder.production_id.schedule_state != '已排' or workorder.production_id.schedule_state != '已排'
or len( or workorder.production_id.reservation_state not in ['assigned']):
workorder.production_id.picking_ids.filtered(lambda w: w.state not in ['done', 'cancel'])) != 0
or workorder.production_id.workorder_ids.filtered(
lambda wk: wk.sequence == workorder.sequence - 1).test_results in ['报废', '返工']):
if workorder.state != 'waiting': if workorder.state != 'waiting':
workorder.state = 'waiting' workorder.state = 'waiting'
continue continue
@@ -1100,83 +1086,28 @@ class ResMrpWorkOrder(models.Model):
if workorder.is_subcontract is False: if workorder.is_subcontract is False:
workorder.state = 'ready' workorder.state = 'ready'
else: else:
production_programming = self.env['mrp.production'].search( if len(workorder.production_id.picking_ids.filtered(
[('origin', '=', self.production_id.origin)], order='name asc') lambda w: w.state not in ['done',
production_no_remanufacture = production_programming.filtered( 'cancel'])) == 0 and workorder.production_id.programming_state == '已编程':
lambda a: a.is_remanufacture is False) purchase_orders_id = self._get_surface_technics_purchase_ids()
production_list = [production.name for production in production_programming] if purchase_orders_id:
purchase_orders = self.env['purchase.order'].search( if purchase_orders_id.state == 'purchase':
[('origin', 'ilike', ','.join(production_list))])
for line in purchase_orders.order_line:
if (
line.product_id.server_product_process_parameters_id == workorder.surface_technics_parameters_id
and line.product_qty == len(production_no_remanufacture)):
if purchase_orders.state == 'purchase':
workorder.state = 'ready' workorder.state = 'ready'
move_out = workorder.move_subcontract_workorder_ids[1]
for mo in move_out:
if mo.state != 'done':
mo.write({'state': 'assigned', 'production_id': False})
if not mo.move_line_ids:
self.env['stock.move.line'].create(
mo.get_move_line(workorder.production_id, workorder))
else: else:
workorder.state = 'waiting' workorder.state = 'waiting'
# re_work = self.env['mrp.workorder'].search([('production_id', '=', workorder.production_id.id),
# ('processing_panel', '=', workorder.processing_panel),
# ('is_rework', '=', True), ('state', 'in', ['done', 'rework'])])
# cnc_workorder = self.env['mrp.workorder'].search(
# [('production_id', '=', workorder.production_id.id),
# ('processing_panel', '=', workorder.processing_panel),
# ('routing_type', '=', 'CNC加工'), ('state', 'in', ['done', 'rework']),
# ('test_results', '=', '返工')])
# cnc_workorder_pending = self.env['mrp.workorder'].search(
# [('production_id', '=', workorder.production_id.id),
# ('processing_panel', '=', workorder.processing_panel),
# ('routing_type', '=', 'CNC加工'), ('state', 'in', ['pending'])])
# unclamp_workorder = self.env['mrp.workorder'].search(
# [('production_id', '=', workorder.production_id.id),
# ('sequence', '=', workorder.sequence - 1),
# ('state', 'in', ['done'])])
# if workorder.state not in ['cancel', 'progress', 'rework']:
# if workorder.production_id.state == 'rework':
# if workorder.routing_type == '装夹预调':
# # # 有返工工单
# # if re_work:
# # 新工单
# if workorder.is_rework is False:
# if (workorder.production_id.programming_state == '已编程'
# and workorder.production_id.is_rework is False):
# if re_work or cnc_workorder:
# workorder.state = 'ready'
# else:
# if workorder.production_id.is_rework is True:
# if re_work or cnc_workorder:
# workorder.state = 'waiting'
#
# elif workorder.routing_type == 'CNC加工':
# pre_workorder = self.env['mrp.workorder'].search(
# [('production_id', '=', workorder.production_id.id),
# ('processing_panel', '=', workorder.processing_panel),
# ('routing_type', '=', '装夹预调'), ('state', '=', 'done')])
# if pre_workorder:
# if re_work:
# workorder.state = 'waiting'
# elif workorder.routing_type == '解除装夹':
# if cnc_workorder:
# if not cnc_workorder_pending or unclamp_workorder.test_results == '报废':
# workorder.state = 'waiting'
# # else:
# # if workorder.production_id.is_rework is True:
# # workorder.state = 'waiting'
# elif workorder.production_id.state == 'progress':
# if (workorder.routing_type == '装夹预调' and workorder.production_id.programming_state == '已编程'
# and workorder.is_rework is False and workorder.state not in ['done', 'rework', 'cancel']):
# if workorder.production_id.is_rework is False:
# if re_work or cnc_workorder or unclamp_workorder:
# workorder.state = 'ready'
# # if (re_work or cnc_workorder) and workorder.production_id.is_rework is False:
# # workorder.state = 'ready'
# elif workorder.production_id.state == 'scrap':
# if workorder.routing_type == '解除装夹' and unclamp_workorder.test_results == '报废':
# workorder.state = 'waiting'
# 重写工单开始按钮方法 # 重写工单开始按钮方法
def button_start(self): def button_start(self):
# 判断工单状态是否为等待组件
if self.state in ['waiting', 'pending']:
raise UserError('制造订单【%s】缺少组件信息!' % self.production_id.name)
if self.routing_type == 'CNC加工': if self.routing_type == 'CNC加工':
self.env['sf.production.plan'].sudo().search([('name', '=', self.production_id.name)]).write({ self.env['sf.production.plan'].sudo().search([('name', '=', self.production_id.name)]).write({
'state': 'processing', 'state': 'processing',
@@ -1187,19 +1118,23 @@ class ResMrpWorkOrder(models.Model):
# 判断是否有坯料的序列号信息 # 判断是否有坯料的序列号信息
boolean = False boolean = False
if self.production_id.move_raw_ids: 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].product_id.categ_type == '坯料':
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: if self.production_id.move_raw_ids[0].move_line_ids:
boolean = True if self.production_id.move_raw_ids[0].move_line_ids[0].lot_id.name:
boolean = True
else:
boolean = True
if not boolean: if not boolean:
raise UserError('制造订单【%s】缺少组件的序列号信息!' % self.production_id.name) raise UserError('制造订单【%s】缺少组件的序列号信息!' % self.production_id.name)
self.pro_code = self.production_id.move_raw_ids[0].move_line_ids[0].lot_id.name self.pro_code = self.production_id.move_raw_ids[0].move_line_ids[0].lot_id.name
# cnc校验 # cnc校验
cnc_workorder = self.search( if self.production_id.production_type == '自动化产线加工':
[('production_id', '=', self.production_id.id), ('routing_type', '=', 'CNC加工')], cnc_workorder = self.search(
limit=1, order='id asc') [('production_id', '=', self.production_id.id), ('routing_type', '=', 'CNC加工')],
if not cnc_workorder.cnc_ids: limit=1, order='id asc')
raise UserError(_('该制造订单还未下发CNC程序请稍后再试')) # if not cnc_workorder.cnc_ids:
# raise UserError(_('该制造订单还未下发CNC程序请稍后再试'))
else: else:
if self.production_id.tool_state in ['1', '2']: if self.production_id.tool_state in ['1', '2']:
if self.production_id.tool_state == '1': if self.production_id.tool_state == '1':
@@ -1216,15 +1151,33 @@ class ResMrpWorkOrder(models.Model):
# 表面工艺外协出库单 # 表面工艺外协出库单
if self.routing_type == '表面工艺': if self.routing_type == '表面工艺':
if self.is_subcontract is True: if self.is_subcontract is True:
move_out = self.env['stock.move'].search( move_out = self.move_subcontract_workorder_ids[1]
[('location_id', '=', self.env['stock.location'].search( # move_out = self.env['stock.move'].search(
[('barcode', 'ilike', 'WH-PREPRODUCTION')]).id), # [('location_id', '=', self.env['stock.location'].search(
('location_dest_id', '=', self.env['stock.location'].search( # [('barcode', 'ilike', 'WH-PREPRODUCTION')]).id),
[('barcode', 'ilike', 'VL-SPOC')]).id), # ('location_dest_id', '=', self.env['stock.location'].search(
('origin', '=', self.production_id.name)]) # [('barcode', 'ilike', 'VL-SPOC')]).id),
if move_out.state != 'done': # ('origin', '=', self.production_id.name), ('state', 'not in', ['cancel', 'done'])])
move_out.write({'state': 'assigned', 'production_id': False}) for mo in move_out:
self.env['stock.move.line'].create(move_out.get_move_line(self.production_id, self)) if mo.state != 'done':
mo.write({'state': 'assigned', 'production_id': False})
if not mo.move_line_ids:
self.env['stock.move.line'].create(mo.get_move_line(self.production_id, self))
# product_qty = mo.product_uom._compute_quantity(
# mo.product_uom_qty, mo.product_id.uom_id, rounding_method='HALF-UP')
# available_quantity = self.env['stock.quant']._get_available_quantity(
# mo.product_id,
# mo.location_id,
# lot_id=mo.move_line_ids.lot_id,
# strict=False,
# )
# mo._update_reserved_quantity(
# product_qty,
# available_quantity,
# mo.location_id,
# lot_id=mo.move_line_ids.lot_id,
# strict=False,
# )
# move_out._action_assign() # move_out._action_assign()
if self.state == 'waiting' or self.state == 'ready' or self.state == 'progress': if self.state == 'waiting' or self.state == 'ready' or self.state == 'progress':
@@ -1329,6 +1282,13 @@ class ResMrpWorkOrder(models.Model):
picks = record.picking_ids.filtered(lambda p: p.state not in ('done')) picks = record.picking_ids.filtered(lambda p: p.state not in ('done'))
if picks: if picks:
raise UserError('请先完成该工单的工艺外协再进行操作') raise UserError('请先完成该工单的工艺外协再进行操作')
# 表面工艺外协,最后一张工单
workorders = self.production_id.workorder_ids
subcontract_workorders = workorders.filtered(lambda wo: wo.is_subcontract == True and wo.state != 'cancel').sorted('sequence')
if self == subcontract_workorders[-1]:
# 给下一个库存移动就绪
self.move_subcontract_workorder_ids[0].move_dest_ids._action_done()
# self.production_id.button_mark_done()
tem_date_planned_finished = record.date_planned_finished tem_date_planned_finished = record.date_planned_finished
tem_date_finished = record.date_finished tem_date_finished = record.date_finished
logging.info('routing_type:%s' % record.routing_type) logging.info('routing_type:%s' % record.routing_type)
@@ -1347,41 +1307,48 @@ class ResMrpWorkOrder(models.Model):
# record.recreateManufacturingOrWorkerOrder() # record.recreateManufacturingOrWorkerOrder()
is_production_id = False is_production_id = False
rework_workorder = record.production_id.workorder_ids.filtered(lambda p: p.state == 'rework') rework_workorder = record.production_id.workorder_ids.filtered(lambda p: p.state == 'rework')
done_workorder = record.production_id.workorder_ids.filtered(lambda p1: p1.state == 'done') done_workorder = record.production_id.workorder_ids.filtered(lambda p1: p1.state in ['done'])
if (len(rework_workorder) + len(done_workorder) == len(record.production_id.workorder_ids)) or ( if (len(rework_workorder) + len(done_workorder) == len(
len(done_workorder) == len(record.production_id.workorder_ids)): record.production_id.workorder_ids.filtered(lambda wo: wo.state != 'cancel'))) or (
len(done_workorder) == len(
record.production_id.workorder_ids.filtered(lambda wo: wo.state != 'cancel'))):
is_production_id = True is_production_id = True
if record.routing_type in ['解除装夹'] or ( if record.routing_type in ['解除装夹'] or (
record.is_rework is True and record.routing_type in ['装夹预调']) or ( record.is_rework is True and record.routing_type in ['装夹预调']):
record.test_results in ['返工', '报废'] and record.routing_type in ['CNC加工']):
for workorder in record.production_id.workorder_ids: for workorder in record.production_id.workorder_ids:
if workorder.processing_panel == record.processing_panel: if workorder.processing_panel == record.processing_panel:
rfid_code = workorder.rfid_code rfid_code = workorder.rfid_code
workorder.write({'rfid_code_old': rfid_code, workorder.write({'rfid_code_old': rfid_code,
'rfid_code': False}) 'rfid_code': False})
self.env['stock.lot'].sudo().search([('rfid', '=', rfid_code)]).write(
{'tool_material_status': '可用'})
if workorder.rfid_code: if workorder.rfid_code:
raise ValidationError(f'{workorder.name}】工单解绑失败,请重新点击完成按钮!!!') raise ValidationError(f'{workorder.name}】工单解绑失败,请重新点击完成按钮!!!')
# workorder.rfid_code_old = rfid_code # workorder.rfid_code_old = rfid_code
# workorder.rfid_code = False # workorder.rfid_code = False
logging.info('workorder.rfid_code:%s' % workorder.rfid_code) logging.info('workorder.rfid_code:%s' % workorder.rfid_code)
if is_production_id is True and record.routing_type in ['解除装夹', '表面工艺']: # if is_production_id is True and record.routing_type in ['解除装夹', '表面工艺', '切割']:
if is_production_id is True:
logging.info('product_qty:%s' % record.production_id.product_qty) logging.info('product_qty:%s' % record.production_id.product_qty)
for move_raw_id in record.production_id.move_raw_ids: for move_raw_id in record.production_id.move_raw_ids:
move_raw_id.quantity_done = move_raw_id.product_uom_qty move_raw_id.quantity_done = move_raw_id.product_uom_qty
record.process_state = '已完工' record.process_state = '已完工'
record.production_id.process_state = '已完工' record.production_id.process_state = '已完工'
if record.routing_type in ['表面工艺']: # if record.routing_type in ['表面工艺']:
raw_move = self.env['stock.move'].sudo().search( # raw_move = self.env['stock.move'].sudo().search(
[('origin', '=', record.production_id.name), # [('origin', '=', record.production_id.name),
('procure_method', 'in', ['make_to_order', 'make_to_stock']), # ('procure_method', 'in', ['make_to_order', 'make_to_stock']),
('state', '!=', 'done')]) # ('state', '!=', 'done')])
if raw_move: # if raw_move:
raw_move.write({'state': 'done'}) # raw_move.write({'state': 'done'})
record.production_id.button_mark_done1() record.production_id.button_mark_done1()
# record.production_id.state = 'done' # record.production_id.state = 'done'
# 解绑托盘 # 解绑托盘
def unbind_tray(self): def unbind_tray(self):
for item in self:
self.env['stock.lot'].sudo().search([('rfid', '=', item.rfid_code)]).write(
{'tool_material_status': '可用'})
self.production_id.workorder_ids.write({ self.production_id.workorder_ids.write({
'rfid_code': False, 'rfid_code': False,
'tray_serial_number': False, 'tray_serial_number': False,
@@ -1497,6 +1464,8 @@ class ResMrpWorkOrder(models.Model):
# 'default_feeder_station_start_id': feeder_station_start_id, # 'default_feeder_station_start_id': feeder_station_start_id,
}} }}
move_subcontract_workorder_ids = fields.One2many('stock.move', 'subcontract_workorder_id', string='组件')
class CNCprocessing(models.Model): class CNCprocessing(models.Model):
_name = 'sf.cnc.processing' _name = 'sf.cnc.processing'
@@ -1705,6 +1674,7 @@ class SfWorkOrderBarcodes(models.Model):
if workorder_rfid: if workorder_rfid:
for item in workorder_rfid: for item in workorder_rfid:
item.write({'rfid_code': barcode}) item.write({'rfid_code': barcode})
lot.sudo().write({'tool_material_status': '在用'})
logging.info("Rfid[%s]绑定成功!!!" % barcode) logging.info("Rfid[%s]绑定成功!!!" % barcode)
else: else:
raise UserError('该Rfid【%s】绑定的是【%s】, 不是托盘!!!' % (barcode, lot.product_id.name)) raise UserError('该Rfid【%s】绑定的是【%s】, 不是托盘!!!' % (barcode, lot.product_id.name))

View File

@@ -774,11 +774,10 @@ class ResProductMo(models.Model):
# bfm下单 # bfm下单
manual_quotation = fields.Boolean('人工编程', default=False, readonly=True) manual_quotation = fields.Boolean('人工编程', default=False, readonly=True)
part_number = fields.Char(string='零件图号', readonly=True)
machining_drawings = fields.Binary('2D加工图纸', readonly=True) machining_drawings = fields.Binary('2D加工图纸', readonly=True)
quality_standard = fields.Binary('质检标准', readonly=True) quality_standard = fields.Binary('质检标准', readonly=True)
part_name = fields.Char(string='零件名称', readonly=True) part_name = fields.Char(string='零件名称', readonly=True)
part_number = fields.Char(string='零件图号', readonly=True)
@api.constrains('tool_length') @api.constrains('tool_length')
def _check_tool_length_size(self): def _check_tool_length_size(self):
if self.tool_length > 1000000: if self.tool_length > 1000000:
@@ -859,12 +858,12 @@ class ResProductMo(models.Model):
raise UserError('请先配置模型类型内的坯料冗余') raise UserError('请先配置模型类型内的坯料冗余')
vals = { vals = {
'name': '%s-%s-%s' % ('P', order_id.name, i), 'name': '%s-%s-%s' % ('P', order_id.name, i),
'model_long': item['model_long'] + embryo_redundancy_id.long, 'model_long': self.format_float(item['model_long'] + embryo_redundancy_id.long),
'model_width': item['model_width'] + embryo_redundancy_id.width, 'model_width': self.format_float(item['model_width'] + embryo_redundancy_id.width),
'model_height': item['model_height'] + embryo_redundancy_id.height, 'model_height': self.format_float(item['model_height'] + embryo_redundancy_id.height),
'model_volume': (item['model_long'] + embryo_redundancy_id.long) * ( 'model_volume': self.format_float((item['model_long'] + embryo_redundancy_id.long) * (
item['model_width'] + embryo_redundancy_id.width) * ( item['model_width'] + embryo_redundancy_id.width) * (
item['model_height'] + embryo_redundancy_id.height), item['model_height'] + embryo_redundancy_id.height)),
'product_model_type_id': model_type.id, 'product_model_type_id': model_type.id,
'model_processing_panel': item['processing_panel_detail'], 'model_processing_panel': item['processing_panel_detail'],
'model_machining_precision': item['model_machining_precision'], 'model_machining_precision': item['model_machining_precision'],
@@ -874,8 +873,8 @@ class ResProductMo(models.Model):
'height': item['model_height'], 'height': item['model_height'],
'volume': item['model_long'] * item['model_width'] * item['model_height'], 'volume': item['model_long'] * item['model_width'] * item['model_height'],
'model_file': '' if not item['model_file'] else base64.b64decode(item['model_file']), 'model_file': '' if not item['model_file'] else base64.b64decode(item['model_file']),
'model_name': attachment.name, 'model_name': attachment.name if attachment else None,
'upload_model_file': [(6, 0, [attachment.id])], 'upload_model_file': [(6, 0, [attachment.id])] if attachment else None,
'list_price': item['price'], 'list_price': item['price'],
'materials_id': self.env['sf.production.materials'].search( 'materials_id': self.env['sf.production.materials'].search(
[('materials_no', '=', item['texture_code'])]).id, [('materials_no', '=', item['texture_code'])]).id,
@@ -892,7 +891,7 @@ class ResProductMo(models.Model):
'machining_drawings': '' if not item['machining_drawings'] else base64.b64decode( 'machining_drawings': '' if not item['machining_drawings'] else base64.b64decode(
item['machining_drawings']), item['machining_drawings']),
'quality_standard': '' if not item['quality_standard'] else base64.b64decode(item['quality_standard']), 'quality_standard': '' if not item['quality_standard'] else base64.b64decode(item['quality_standard']),
'part_name': item['part_name'], 'part_name': item.get('part_name') or '',
} }
tax_id = self.env['account.tax'].sudo().search( tax_id = self.env['account.tax'].sudo().search(
[('type_tax_use', '=', 'sale'), ('amount', '=', item.get('tax')), ('price_include', '=', 'True')]) [('type_tax_use', '=', 'sale'), ('amount', '=', item.get('tax')), ('price_include', '=', 'True')])
@@ -907,6 +906,20 @@ class ResProductMo(models.Model):
self.attachment_update(item['quality_standard_name'], copy_product_id.product_tmpl_id.id, self.attachment_update(item['quality_standard_name'], copy_product_id.product_tmpl_id.id,
'quality_standard', item['quality_standard_mimetype']) 'quality_standard', item['quality_standard_mimetype'])
return copy_product_id return copy_product_id
def format_float(self, value):
# 将浮点数转换为字符串
value_str = str(value)
# 检查小数点的位置
if '.' in value_str:
# 获取小数部分
decimal_part = value_str.split('.')[1]
# 判断小数位数是否超过2位
if len(decimal_part) > 2:
# 超过2位则保留2位小数
return "{:.2f}".format(value)
# 否则保持原来的位数
return float(value_str)
def _get_ids(self, param): def _get_ids(self, param):
type_ids = [] type_ids = []
@@ -924,6 +937,8 @@ class ResProductMo(models.Model):
return [(6, 0, process_parameters_ids)] return [(6, 0, process_parameters_ids)]
def attachment_create(self, name, data): def attachment_create(self, name, data):
if not data:
return None
attachment = self.env['ir.attachment'].create({ attachment = self.env['ir.attachment'].create({
'datas': base64.b64decode(data), 'datas': base64.b64decode(data),
'type': 'binary', 'type': 'binary',

View File

@@ -0,0 +1,107 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from collections import defaultdict
from odoo import api, fields, models, _
from odoo.tools import OrderedSet
# _get_surface_technics_purchase_ids
class PurchaseOrder(models.Model):
_inherit = 'purchase.order'
production_count = fields.Integer(
"关联制造订单",
compute='_compute_workorder_count',
)
def action_view_production(self):
origins = [order.name for order in self.picking_ids]
production_id = self.env['mrp.production'].search([('origin', 'in', origins)])
if not production_id:
return
action = {
'res_model': 'mrp.production',
'type': 'ir.actions.act_window',
}
if len(production_id) == 1:
action.update({
'view_mode': 'form',
'res_id': production_id.id,
})
else:
action.update({
'name': _("制造订单列表"),
'domain': [('id', 'in', production_id.ids)],
'view_mode': 'tree,form',
})
return action
def _compute_workorder_count(self):
for purchase in self:
origins = [order.name for order in purchase.picking_ids]
production_id = self.env['mrp.production'].search([('origin', 'in', origins)])
purchase.production_count = len(production_id)
# def button_confirm(self):
# super().button_confirm()
# workorders = self.env['mrp.workorder'].search([('purchase_id', '=', self.id), ('state', '!=', 'cancel')])
# for workorder in workorders:
# if workorder.routing_type == '表面工艺' and workorder.is_subcontract is True:
# move_out = workorder.move_subcontract_workorder_ids[1]
# for mo in move_out:
# if mo.state != 'done':
# mo.write({'state': 'assigned', 'production_id': False})
# if not mo.move_line_ids:
# self.env['stock.move.line'].create(mo.get_move_line(workorder.production_id, workorder))
# return True
origin_sale_id = fields.Many2one('sale.order', string='销售订单号', store=True, compute='_compute_origin_sale_id')
origin_sale_ids = fields.Many2many('sale.order', string='销售订单号(多个)', store=True,
compute='_compute_origin_sale_id')
@api.depends('origin')
def _compute_origin_sale_id(self):
for purchase in self:
if not purchase.origin:
continue
elif 'MO' in purchase.origin:
mp_name_list = [name.strip() for name in purchase['origin'].split(',')]
os_ids = list({mp_id.sale_order_id.id for mp_id in self.env['mrp.production'].sudo().search([
('name', 'in', mp_name_list)])})
if len(os_ids) == 1:
purchase.origin_sale_id = os_ids[0]
elif len(os_ids) >= 2:
purchase.origin_sale_ids = os_ids
elif 'S' in purchase.origin:
os_name_list = [name.strip() for name in purchase['origin'].split(',')]
os_ids = self.env['sale.order'].sudo().search([('name', 'in', os_name_list)])
if len(os_ids) == 1:
purchase.origin_sale_id = os_ids.id
elif len(os_ids) >= 2:
purchase.origin_sale_ids = os_ids.ids
elif 'IN' in purchase.origin:
sp_name_list = [name.strip() for name in purchase['origin'].split(',')]
os_ids = list({sp_id.sale_order_id.id for sp_id in self.env['stock.picking'].sudo().search([
('name', 'in', sp_name_list)])})
if len(os_ids) == 1:
purchase.origin_sale_id = os_ids[0]
elif len(os_ids) >= 2:
purchase.origin_sale_ids = os_ids
class PurchaseOrderLine(models.Model):
_inherit = 'purchase.order.line'
part_number = fields.Char('零件图号', related='product_id.part_number', readonly=True)
related_product = fields.Many2one('product.product', compute='_compute_related_product', string='关联产品',
help='经此产品工艺加工成的成品')
@api.depends('order_id.origin')
def _compute_related_product(self):
for record in self:
if record.product_id.detailed_type:
production_id = self.env['mrp.production'].search([('name', '=', record.order_id.origin)])
record.related_product = production_id.product_id if production_id else False
else:
record.related_product = False

View File

@@ -13,6 +13,9 @@ class SaleOrder(models.Model):
('sent', "报价已发送"), ('sent', "报价已发送"),
('supply method', "供货方式待确认"), ('supply method', "供货方式待确认"),
('sale', "销售订单"), ('sale', "销售订单"),
('processing', "加工中"),
('physical_distribution', "物流中"),
('delivered', "已交付"),
('done', "已锁定"), ('done', "已锁定"),
('cancel', "已取消"), ('cancel', "已取消"),
]) ])
@@ -43,6 +46,8 @@ class SaleOrder(models.Model):
# 复制成品模板上的属性 # 复制成品模板上的属性
line.product_id.product_tmpl_id.copy_template(product_template_id) line.product_id.product_tmpl_id.copy_template(product_template_id)
# 将模板上的single_manufacturing属性复制到成品上
line.product_id.single_manufacturing = product_template_id.single_manufacturing
order_id = self order_id = self
product = line.product_id product = line.product_id
@@ -147,7 +152,7 @@ class SaleOrder(models.Model):
class SaleOrderLine(models.Model): class SaleOrderLine(models.Model):
_inherit = 'sale.order.line' _inherit = 'sale.order.line'
part_number = fields.Char('零件图号', related='product_id.part_number', readonly=True)
# 供货方式 # 供货方式
supply_method = fields.Selection([ supply_method = fields.Selection([
('automation', "自动化产线加工"), ('automation', "自动化产线加工"),
@@ -155,3 +160,10 @@ class SaleOrderLine(models.Model):
('purchase', "外购"), ('purchase', "外购"),
('outsourcing', "委外加工"), ('outsourcing', "委外加工"),
], string='供货方式') ], string='供货方式')
def write(self, vals):
if 'supply_method' in vals:
for line in self:
if vals['supply_method'] == 'automation' and line.manual_quotation:
raise UserError('当前(%s)产品为人工编程产品,不能选择自动化产线加工' % ','.join(line.mapped('product_id.name')))
return super(SaleOrderLine, self).write(vals)

View File

@@ -10,8 +10,14 @@ class SfProductionProcessParameter(models.Model):
@api.model @api.model
def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None): def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None):
if self._context.get('route_id'): if self._context.get('route_id'):
parameter = []
routing = self.env['mrp.routing.workcenter'].search([('id', '=', self._context.get('route_id'))]) routing = self.env['mrp.routing.workcenter'].search([('id', '=', self._context.get('route_id'))])
domain = [('process_id', '=', routing.surface_technics_id.id)] technology_design = self.env['sf.technology.design'].search(
[('production_id', '=', self._context.get('production_id')), ('routing_tag', '=', 'special'),
('route_id', '=', self._context.get('route_id'))])
for t in technology_design:
if t.process_parameters_id:
parameter.append(t.process_parameters_id.id)
domain = [('process_id', '=', routing.surface_technics_id.id), ('id', 'not in', parameter)]
return self._search(domain, limit=limit, access_rights_uid=name_get_uid) return self._search(domain, limit=limit, access_rights_uid=name_get_uid)
return super()._name_search(name, args, operator, limit, name_get_uid) return super()._name_search(name, args, operator, limit, name_get_uid)

View File

@@ -1,11 +1,14 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from odoo import fields, models from collections import Counter
from odoo import fields, models, api, _
from odoo.exceptions import ValidationError
class sf_technology_design(models.Model): class sf_technology_design(models.Model):
_name = 'sf.technology.design' _name = 'sf.technology.design'
_description = "工艺设计" _description = "工艺设计"
group_uniq_id = fields.Integer('同一制造订单唯一id',default=0)
sequence = fields.Integer('序号') sequence = fields.Integer('序号')
route_id = fields.Many2one('mrp.routing.workcenter', '工序') route_id = fields.Many2one('mrp.routing.workcenter', '工序')
process_parameters_id = fields.Many2one('sf.production.process.parameter', string='表面工艺参数') process_parameters_id = fields.Many2one('sf.production.process.parameter', string='表面工艺参数')
@@ -16,6 +19,11 @@ class sf_technology_design(models.Model):
is_auto = fields.Boolean('是否自动生成', default=False) is_auto = fields.Boolean('是否自动生成', default=False)
active = fields.Boolean('有效', default=True) active = fields.Boolean('有效', default=True)
# @api.depends('production_id')
# def _compute_group_uniq_id(self):
# for record in self:
def json_technology_design_str(self, k, route, i, process_parameter): def json_technology_design_str(self, k, route, i, process_parameter):
workorders_values_str = [0, '', { workorders_values_str = [0, '', {
'route_id': route.id if route.routing_type in ['表面工艺'] else route.route_workcenter_id.id, 'route_id': route.id if route.routing_type in ['表面工艺'] else route.route_workcenter_id.id,
@@ -27,5 +35,75 @@ class sf_technology_design(models.Model):
'is_auto': True}] 'is_auto': True}]
return workorders_values_str return workorders_values_str
def write(self, vals):
return super(sf_technology_design, self).write(vals)
def unlink_technology_design(self): def unlink_technology_design(self):
self.active = False self.active = False
@api.model_create_multi
def create(self, vals_list):
for vals in vals_list:
if not vals.get('route_id'):
raise ValidationError(_("工序不能为空"))
result = super(sf_technology_design, self).create(vals_list)
for res in result:
record = self.search([('production_id', '=', res.production_id.id), ('active', 'in', [True, False])], order='group_uniq_id desc', limit=1)
res.group_uniq_id=record.group_uniq_id + 1
return result
def get_duplicates_with_inactive(self,technology_designs):
# 统计每个 'sequence' 出现的次数
sequence_count = Counter(technology_design.sequence for technology_design in technology_designs)
# 筛选出 'sequence' 重复且 'active' 为 False 的元素
result = [
technology_design for technology_design in technology_designs
if sequence_count[technology_design.sequence] > 1 and technology_design.active is False
]
return result
# def rearrange_numbering(self,self_technology_designs):
# inactive_designs = self.get_duplicates_with_inactive(self_technology_designs)
# if inactive_designs:
# max_design = max(self_technology_designs, key=lambda x: x.sequence)
# max_sequence = max_design.sequence if max_design else 0
# for designs in inactive_designs:
# max_sequence += 1
# designs.sequence = max_sequence
# self_technology_designs.sorted(key=lambda techology_design:techology_design.sequence)
# return self_technology_designs
def get_technology_design(self):
return {
'sequence':self.sequence,
'route_id': self.route_id.id,
'process_parameters_id': self.process_parameters_id.id,
'panel': self.panel,
'routing_tag': self.routing_tag,
'time_cycle_manual': self.time_cycle_manual,
'is_auto': self.is_auto,
'active': self.active,
'group_uniq_id':self.group_uniq_id,
}
def sync_technology_designs(self,production_technology_designs, self_technology_designs):
production_id = production_technology_designs[0].production_id.id
self_technology_design_dict = {item.group_uniq_id:item for item in self_technology_designs}
production_technology_designs_dict = {item.group_uniq_id:item for item in production_technology_designs}
for technology_design in production_technology_designs:
if not self_technology_design_dict.get(technology_design.group_uniq_id):
technology_design.write({'production_id': False})
else:
technology_design.write(self_technology_design_dict.get(technology_design.group_uniq_id).get_technology_design())
for technology_design in self_technology_designs:
if not production_technology_designs_dict.get(technology_design.group_uniq_id):
technology_design = technology_design.get_technology_design()
technology_design.update({'production_id': production_id})
technology_design.pop('group_uniq_id')
self.env['sf.technology.design'].create(technology_design)
def unified_procedure_multiple_work_orders(self,self_technology_designs,production_item):
technology_designs = self.env['sf.technology.design'].sudo().search(
[('production_id', '=', production_item.id), ('active', 'in', [True, False])])
self.sync_technology_designs(self_technology_designs=self_technology_designs,production_technology_designs=technology_designs)

View File

@@ -281,19 +281,26 @@ class StockRule(models.Model):
workorder_duration += workorder.duration_expected workorder_duration += workorder.duration_expected
sale_order = self.env['sale.order'].sudo().search([('name', '=', production.origin)]) sale_order = self.env['sale.order'].sudo().search([('name', '=', production.origin)])
if sale_order: # 如果订单为空,则获取来源制造订单的销售单
# sale_order.write({'schedule_status': 'to schedule'}) if not sale_order:
self.env['sf.production.plan'].sudo().with_company(company_id).create({ mrp_production = self.env['mrp.production'].sudo().search([('name', '=', production.origin)],
'name': production.name, limit=1)
'order_deadline': sale_order.deadline_of_delivery, if mrp_production:
'production_id': production.id, sale_order = self.env['sale.order'].sudo().search([('name', '=', mrp_production.origin)])
'date_planned_start': production.date_planned_start, else:
'origin': production.origin, mrp_production = production
'product_qty': production.product_qty, # if sale_order:
'product_id': production.product_id.id, # sale_order.write({'schedule_status': 'to schedule'})
'state': 'draft', self.env['sf.production.plan'].sudo().with_company(company_id).create({
}) 'name': production.name,
technology_design_values = [] 'order_deadline': sale_order.deadline_of_delivery,
'production_id': production.id,
'date_planned_start': production.date_planned_start,
'origin': mrp_production.origin,
'product_qty': production.product_qty,
'product_id': production.product_id.id,
'state': 'draft',
})
all_production = productions all_production = productions
grouped_product_ids = {k: list(g) for k, g in groupby(all_production, key=lambda x: x.product_id.id)} grouped_product_ids = {k: list(g) for k, g in groupby(all_production, key=lambda x: x.product_id.id)}
# 初始化一个字典来存储每个product_id对应的生产订单名称列表 # 初始化一个字典来存储每个product_id对应的生产订单名称列表
@@ -303,6 +310,7 @@ class StockRule(models.Model):
# 为同一个product_id创建一个生产订单名称列表 # 为同一个product_id创建一个生产订单名称列表
product_id_to_production_names[product_id] = [production.name for production in all_production] product_id_to_production_names[product_id] = [production.name for production in all_production]
for production_item in productions: for production_item in productions:
technology_design_values = []
production_programming = self.env['mrp.production'].search( production_programming = self.env['mrp.production'].search(
[('product_id.id', '=', production_item.product_id.id), [('product_id.id', '=', production_item.product_id.id),
('origin', '=', production_item.origin)], ('origin', '=', production_item.origin)],
@@ -310,77 +318,77 @@ class StockRule(models.Model):
if production_item.product_id.id in product_id_to_production_names: if production_item.product_id.id in product_id_to_production_names:
# 同一个产品多个制造订单对应一个编程单和模型库 # 同一个产品多个制造订单对应一个编程单和模型库
# 只调用一次fetchCNC并将所有生产订单的名称作为字符串传递 # 只调用一次fetchCNC并将所有生产订单的名称作为字符串传递
if not production_item.programming_no and production.production_type == '自动化产线加工': if not production_item.programming_no and production_item.production_type == '自动化产线加工':
if not production_programming.programming_no: if not production_programming.programming_no:
production_item.fetchCNC( production_item.fetchCNC(
', '.join(product_id_to_production_names[production_item.product_id.id])) ', '.join(product_id_to_production_names[production_item.product_id.id]))
else: else:
production_item.write({'programming_no': production_programming.programming_no, production_item.write({'programming_no': production_programming.programming_no,
'programming_state': '编程中'}) 'programming_state': '编程中'})
if not technology_design_values: i = 0
i = 0 if production_item.product_id.categ_id.type == '成品':
if production_item.product_id.categ_id.type == '成品': # 根据加工面板的面数及成品工序模板生成工序设计
# 根据加工面板的面数及成品工序模板生成工序设计 if production_item.production_type == '自动化产线加工':
if production_item.production_type == '自动化产线加工': model = 'sf.product.model.type.routing.sort'
model = 'sf.product.model.type.routing.sort' domain = [
domain = [ ('product_model_type_id', '=', production_item.product_id.product_model_type_id.id)]
('product_model_type_id', '=', production_item.product_id.product_model_type_id.id)] else:
else: model = 'sf.manual.product.model.type.routing.sort'
model = 'sf.manual.product.model.type.routing.sort' domain = [('manual_product_model_type_id', '=',
domain = [('manual_product_model_type_id', '=', production_item.product_id.product_model_type_id.id)]
production_item.product_id.product_model_type_id.id)] product_routing_workcenter = self.env[model].search(domain, order='sequence asc')
product_routing_workcenter = self.env[model].search(domain, order='sequence asc') if production_item.production_type == '自动化产线加工':
if production_item.production_type == '自动化产线加工': for k in (production_item.product_id.model_processing_panel.split(',')):
for k in (production_item.product_id.model_processing_panel.split(',')):
i += 1
for route in product_routing_workcenter:
technology_design_values.append(
self.env['sf.technology.design'].json_technology_design_str(k, route, i, False))
else:
for route in product_routing_workcenter: for route in product_routing_workcenter:
i += 1 i += 1
technology_design_values.append( technology_design_values.append(
self.env['sf.technology.design'].json_technology_design_str(False, route, i, False)) self.env['sf.technology.design'].json_technology_design_str(k, route, i, False))
elif production_item.product_id.categ_id.type == '坯料': else:
embryo_routing_workcenter = self.env['sf.embryo.model.type.routing.sort'].search( for route in product_routing_workcenter:
[('embryo_model_type_id', '=', production_item.product_id.embryo_model_type_id.id)],
order='sequence asc'
)
for route_embryo in embryo_routing_workcenter:
i += 1 i += 1
technology_design_values.append( technology_design_values.append(
self.env['sf.technology.design'].json_technology_design_str(False, route_embryo, i, self.env['sf.technology.design'].json_technology_design_str(False, route, i, False))
False)) elif production_item.product_id.categ_id.type == '坯料':
surface_technics_arr = [] embryo_routing_workcenter = self.env['sf.embryo.model.type.routing.sort'].search(
route_workcenter_arr = [] [('embryo_model_type_id', '=', production_item.product_id.embryo_model_type_id.id)],
for item in production_item.product_id.product_model_type_id.surface_technics_routing_tmpl_ids: order='sequence asc'
if item.route_workcenter_id.surface_technics_id.id: )
for process_param in production_item.product_id.model_process_parameters_ids: for route_embryo in embryo_routing_workcenter:
if item.route_workcenter_id.surface_technics_id == process_param.process_id: i += 1
surface_technics_arr.append( technology_design_values.append(
item.route_workcenter_id.surface_technics_id.id) self.env['sf.technology.design'].json_technology_design_str(False, route_embryo, i,
route_workcenter_arr.append(item.route_workcenter_id.id) False))
if surface_technics_arr: surface_technics_arr = []
production_process = self.env['sf.production.process'].search( route_workcenter_arr = []
[('id', 'in', surface_technics_arr)], for item in production_item.product_id.product_model_type_id.surface_technics_routing_tmpl_ids:
order='sequence asc' if item.route_workcenter_id.surface_technics_id.id:
) for process_param in production_item.product_id.model_process_parameters_ids:
for p in production_process: if item.route_workcenter_id.surface_technics_id == process_param.process_id:
logging.info('production_process:%s' % p.name) surface_technics_arr.append(
process_parameter = production_item.product_id.model_process_parameters_ids.filtered( item.route_workcenter_id.surface_technics_id.id)
lambda pm: pm.process_id.id == p.id) route_workcenter_arr.append(item.route_workcenter_id.id)
if process_parameter: if surface_technics_arr:
i += 1 production_process = self.env['sf.production.process'].search(
route_production_process = self.env[ [('id', 'in', surface_technics_arr)],
'mrp.routing.workcenter'].search( order='sequence asc'
[('surface_technics_id', '=', p.id), )
('id', 'in', route_workcenter_arr)]) for p in production_process:
technology_design_values.append( logging.info('production_process:%s' % p.name)
self.env['sf.technology.design'].json_technology_design_str(False, process_parameter = production_item.product_id.model_process_parameters_ids.filtered(
route_production_process, lambda pm: pm.process_id.id == p.id)
i, if process_parameter:
process_parameter)) i += 1
productions.technology_design_ids = technology_design_values route_production_process = self.env[
'mrp.routing.workcenter'].search(
[('surface_technics_id', '=', p.id),
('id', 'in', route_workcenter_arr)])
technology_design_values.append(
self.env['sf.technology.design'].json_technology_design_str(False,
route_production_process,
i,
process_parameter))
production_item.technology_design_ids = technology_design_values
productions.write({'state': 'technology_to_confirmed'})
return True return True
@@ -415,6 +423,8 @@ class ProductionLot(models.Model):
"""Generate `lot_names` from a string.""" """Generate `lot_names` from a string."""
if first_lot.__contains__(display_name): if first_lot.__contains__(display_name):
first_lot = first_lot[(len(display_name) + 1):] first_lot = first_lot[(len(display_name) + 1):]
else:
first_lot = first_lot[-3:]
# We look if the first lot contains at least one digit. # We look if the first lot contains at least one digit.
caught_initial_number = regex_findall(r"\d+", first_lot) caught_initial_number = regex_findall(r"\d+", first_lot)
@@ -578,40 +588,34 @@ class StockPicking(models.Model):
address_of_delivery = fields.Char('联系地址', compute='_compute_move_ids', store=True) address_of_delivery = fields.Char('联系地址', compute='_compute_move_ids', store=True)
retrospect_ref = fields.Char('追溯参考', compute='_compute_move_ids', store=True) retrospect_ref = fields.Char('追溯参考', compute='_compute_move_ids', store=True)
sale_order_id = fields.Many2one('sale.order', '销售单号', compute='_compute_move_ids', store=True)
picking_type_sequence_code = fields.Char(related='picking_type_id.sequence_code') picking_type_sequence_code = fields.Char(related='picking_type_id.sequence_code')
@api.depends('move_ids', 'move_ids.product_id') @api.depends('move_ids', 'move_ids.product_id')
def _compute_move_ids(self): def _compute_move_ids(self):
for item in self: for item in self:
if item.move_ids: if item.move_ids:
if item.picking_type_id.sequence_code == 'DL': product_id = item.move_ids[0].product_id
sale_name = item.move_ids[0].product_id.name.split('-')[1] if product_id:
if 'S' in sale_name: sale_info = None
sale_id = self.env['sale.order'].sudo().search([('name', '=', sale_name)]) if product_id.categ_id.type == '坯料' and product_id.name.startswith('R-S'):
item.person_of_delivery = sale_id.person_of_delivery parts = product_id.name.split('-')
item.telephone_of_delivery = sale_id.telephone_of_delivery if len(parts) >= 3:
item.address_of_delivery = sale_id.address_of_delivery sale_name = parts[1]
sale_info = self.env['sale.order'].sudo().search(
[('name', '=', sale_name)])
else: else:
raise ValidationError('坯料名称格式错误,正确格式为[R-S???-?]') sale_order_line = self.env['sale.order.line'].sudo().search(
move_ids = [] [('product_id', '=', product_id.id)])
for move_id in item.move_ids: if sale_order_line:
move_ids.append(move_id.product_id.id) sale_info = sale_order_line[0].order_id
boms = self.env['mrp.bom'].sudo().search([('bom_line_ids.product_id', 'in', move_ids)]) if sale_info:
if boms: item.sale_order_id = sale_info.id
codes_list = [] item.retrospect_ref = sale_info.order_code
for bom in boms: if item.picking_type_id.sequence_code == 'DL':
if bom.product_tmpl_id.default_code: item.person_of_delivery = sale_info.person_of_delivery
code_list = bom.product_tmpl_id.default_code.split('-') item.telephone_of_delivery = sale_info.telephone_of_delivery
if len(code_list) >= 4: item.address_of_delivery = sale_info.address_of_delivery
code = '-'.join(code_list[:4])
if code not in codes_list:
codes_list.append(code)
else:
raise ValidationError('坯料成品的内部参考值格式错误')
item.retrospect_ref = ','.join(codes_list)
elif item.picking_type_id.sequence_code in ['INT', 'PC']:
pass
# 设置外协出入单的名称 # 设置外协出入单的名称
def _get_name_Res(self, rescode): def _get_name_Res(self, rescode):
@@ -625,80 +629,103 @@ class StockPicking(models.Model):
return '%s%s' % (rescode, num) return '%s%s' % (rescode, num)
def button_validate(self): def button_validate(self):
if self.picking_type_id.barcode == 'OCOUT':
move_out = self.env['stock.move'].search(
[('location_id', '=', self.env['stock.location'].search(
[('barcode', 'ilike', 'WH-PREPRODUCTION')]).id),
('location_dest_id', '=', self.env['stock.location'].search(
[('barcode', 'ilike', 'VL-SPOC')]).id),
('origin', '=', self.origin)])
move_in = self.env['stock.move'].search(
[('location_dest_id', '=', self.env['stock.location'].search(
[('barcode', 'ilike', 'WH-PREPRODUCTION')]).id),
('location_id', '=', self.env['stock.location'].search(
[('barcode', 'ilike', 'VL-SPOC')]).id),
('origin', '=', self.origin), ('picking_id', '=', self.id)])
if self.location_id == move_in.location_id and self.location_dest_id == move_in.location_dest_id:
if move_out.origin == move_in.origin:
move_in.write({'production_id': False})
if move_out.picking_id.state != 'done':
raise UserError(
_('该入库单对应的单号为%s的出库单还未完成,不能进行验证操作!' % move_out.picking_id.name))
res = super().button_validate() res = super().button_validate()
if res is True and self.picking_type_id.barcode == 'OCIN': picking_type_in = self.env.ref('sf_manufacturing.outcontract_picking_in').id
if self.id == move_out.picking_id.id: if res is True and self.picking_type_id.id == picking_type_in:
# if move_out.move_line_ids.workorder_id.state == 'progress': # 如果是最后一张外协入库单,则设置库存位置的预留数量
move_in = self.env['stock.move'].search( move_in = self.move_ids
[('location_dest_id', '=', self.env['stock.location'].search( if move_in:
[('barcode', 'ilike', 'WH-PREPRODUCTION')]).id), workorder = move_in.subcontract_workorder_id
('location_id', '=', self.env['stock.location'].search( workorders = workorder.production_id.workorder_ids
[('barcode', 'ilike', 'VL-SPOC')]).id), subcontract_workorders = workorders.filtered(lambda wo: wo.is_subcontract == True and wo.state!='cancel').sorted('sequence')
('origin', '=', self.origin)]) if workorder == subcontract_workorders[-1]:
production = self.env['mrp.production'].search([('name', '=', self.origin)]) self.env['stock.quant']._update_reserved_quantity(
if move_in.state != 'done': move_in.product_id, move_in.location_dest_id, move_in.product_uom_qty,
move_in.write({'state': 'assigned'}) lot_id=move_in.move_line_ids.lot_id,
self.env['stock.move.line'].create(move_in.get_move_line(production, None)) package_id=False, owner_id=False, strict=False
)
workorder.button_finish()
picking_type_out = self.env.ref('sf_manufacturing.outcontract_picking_out').id
if res and self.picking_type_id.id == picking_type_out:
move_out = self.move_ids
if move_out:
workorder = move_out.subcontract_workorder_id
workorder.button_start()
if self.location_id.name == '成品存货区' and self.location_dest_id.name == '客户':
sale_id = self.env['sale.order'].sudo().search(
[('name', '=', self.origin)])
stock_picking_list = self.env['stock.picking'].sudo().search(
[('id', 'in', sale_id.picking_ids.ids)])
stock_picking = stock_picking_list.filtered(lambda p: p.state not in ("done", "cancel"))
if sale_id and not stock_picking:
sale_id.write({'state': 'delivered'})
return res return res
# 创建 外协出库入单 # 创建 外协出库入单
def create_outcontract_picking(self, sorted_workorders_arr, item): def create_outcontract_picking(self, workorders, item, sorted_workorders):
if len(sorted_workorders_arr) > 1: for workorder in workorders:
sorted_workorders_arr = sorted_workorders_arr[0] if workorder.move_subcontract_workorder_ids:
stock_picking = self.env['stock.picking'].search([('origin', '=', item.name), ('name', 'ilike', 'OCOUT')]) workorder.move_subcontract_workorder_ids.write({'state': 'cancel'})
if not stock_picking or sorted_workorders_arr: workorder.move_subcontract_workorder_ids.picking_id.write({'state': 'cancel'})
for sorted_workorders in sorted_workorders_arr: # 创建一个新的补货组
# pick_ids = [] procurement_group_id = self.env['procurement.group'].create({
if not sorted_workorders.picking_ids: 'name': workorder.name,
# outcontract_stock_move = self.env['stock.move'].search([('production_id', '=', item.id)]) 'partner_id': self.partner_id.id,
# if not outcontract_stock_move: })
new_picking = True move_dest_id = False
location_id = self.env['stock.location'].search( # 如果当前工单是是制造订单的最后一个工艺外协工单
[('barcode', 'ilike', 'VL-SPOC')]).id, if workorder == next((workorder for workorder in reversed(sorted_workorders) if workorder.is_subcontract),
location_dest_id = self.env['stock.location'].search( None):
[('barcode', 'ilike', 'WH-PREPRODUCTION')]).id, move_dest_id = item.move_raw_ids[0].id
outcontract_picking_type_in = self.env.ref( else:
'sf_manufacturing.outcontract_picking_in').id, # 从sorted_workorders中找到上一工单的move
outcontract_picking_type_out = self.env.ref( if len(sorted_workorders) > 1:
'sf_manufacturing.outcontract_picking_out').id, move_dest_id = \
moves_out = self.env['stock.move'].sudo().create( sorted_workorders[sorted_workorders.index(workorder) + 1].move_subcontract_workorder_ids[1].id
self.env['stock.move']._get_stock_move_values_Res(item, location_dest_id, location_id, new_picking = True
outcontract_picking_type_out)) outcontract_picking_type_in = self.env.ref(
picking_out = self.create( 'sf_manufacturing.outcontract_picking_in').id,
moves_out._get_new_picking_values_Res(item, sorted_workorders, 'WH/OCOUT/')) outcontract_picking_type_out = self.env.ref(
# pick_ids.append(picking_out.id) 'sf_manufacturing.outcontract_picking_out').id,
moves_out.write( context = dict(self.env.context)
{'picking_id': picking_out.id, 'state': 'waiting'}) context.update({
moves_out._assign_picking_post_process(new=new_picking) 'default_production_id': item.id, # 添加额外信息到 context 中
moves_in = self.env['stock.move'].sudo().create( })
self.env['stock.move']._get_stock_move_values_Res(item, location_id, location_dest_id, moves_in = self.env['stock.move'].sudo().with_context(context).create(
outcontract_picking_type_in)) self.env['stock.move']._get_stock_move_values_Res(item, outcontract_picking_type_in,
picking_in = self.create( procurement_group_id.id, move_dest_id))
moves_in._get_new_picking_values_Res(item, sorted_workorders, 'WH/OCIN/')) picking_in = self.create(
# pick_ids.append(picking_in.id) moves_in._get_new_picking_values_Res(item, workorder, 'WH/OCIN/'))
moves_in.write( # pick_ids.append(picking_in.id)
{'picking_id': picking_in.id, 'state': 'waiting'}) moves_in.write(
moves_in._assign_picking_post_process(new=new_picking) {'picking_id': picking_in.id, 'state': 'waiting'})
moves_in._assign_picking_post_process(new=new_picking)
# self.env.context.get('default_production_id')
moves_out = self.env['stock.move'].sudo().with_context(context).create(
self.env['stock.move']._get_stock_move_values_Res(item, outcontract_picking_type_out,
procurement_group_id.id, moves_in.id))
workorder.write({'move_subcontract_workorder_ids': [(6, 0, [moves_in.id, moves_out.id])]})
picking_out = self.create(
moves_out._get_new_picking_values_Res(item, workorder, 'WH/OCOUT/'))
# pick_ids.append(picking_out.id)
moves_out.write(
{'picking_id': picking_out.id, 'state': 'waiting'})
moves_out._assign_picking_post_process(new=new_picking)
@api.depends('move_type', 'immediate_transfer', 'move_ids.state', 'move_ids.picking_id')
def _compute_state(self):
super(StockPicking, self)._compute_state()
for picking in self:
# 外协出库单根据工单状态,采购单状态来确定
picking_type_id = self.env.ref('sf_manufacturing.outcontract_picking_out').id
if picking.picking_type_id.id == picking_type_id:
if picking.move_ids:
workorder = picking.move_ids[0].subcontract_workorder_id
if picking.state == 'assigned':
if workorder.state in ['pending',
'waiting'] or workorder._get_surface_technics_purchase_ids().state in [
'draft', 'sent']:
picking.state = 'waiting'
class ReStockMove(models.Model): class ReStockMove(models.Model):
@@ -707,18 +734,51 @@ class ReStockMove(models.Model):
materiel_length = fields.Float(string='物料长度', digits=(16, 4)) materiel_length = fields.Float(string='物料长度', digits=(16, 4))
materiel_width = fields.Float(string='物料宽度', digits=(16, 4)) materiel_width = fields.Float(string='物料宽度', digits=(16, 4))
materiel_height = fields.Float(string='物料高度', digits=(16, 4)) materiel_height = fields.Float(string='物料高度', digits=(16, 4))
part_number = fields.Char(string='零件图号', compute='_compute_part_info', store=True)
part_name = fields.Char(string='零件名称', compute='_compute_part_info', store=True)
def _get_stock_move_values_Res(self, item, location_src_id, location_dest_id, picking_type_id): @api.depends('product_id')
route = self.env['stock.route'].sudo().search([('name', '=', '表面工艺外协')]) def _compute_part_info(self):
for move in self:
if move.product_id.categ_id.type == '成品':
move.part_number = move.product_id.part_number
move.part_name = move.product_id.part_name
elif move.product_id.categ_id.type == '坯料':
if move.origin:
origin = move.origin.split(',')[0] if ',' in move.origin else move.origin
mrp_productio_info = self.env['mrp.production'].sudo().search(
[('name', '=', origin)])
if mrp_productio_info:
move.part_number = mrp_productio_info.part_number
move.part_name = mrp_productio_info.part_name
else:
purchase_order_info = self.env['purchase.order'].sudo().search(
[('name', '=', origin)])
if purchase_order_info:
mrp_production_ids = purchase_order_info._get_mrp_productions().ids
if mrp_production_ids:
mrp_productio_info = self.env['mrp.production'].sudo().search(
[('id', '=', mrp_production_ids[0])])
if mrp_productio_info:
move.part_number = mrp_productio_info.part_number
move.part_name = mrp_productio_info.part_name
def _get_stock_move_values_Res(self, item, picking_type_id, group_id, move_dest_ids=False):
route_id = self.env.ref('sf_manufacturing.route_surface_technology_outsourcing').id
stock_rule = self.env['stock.rule'].sudo().search(
[('route_id', '=', route_id), ('picking_type_id', '=', picking_type_id)])
move_values = { move_values = {
'name': '', 'name': '',
'company_id': item.company_id.id, 'company_id': item.company_id.id,
'product_id': item.bom_id.bom_line_ids.product_id.id, 'product_id': item.bom_id.bom_line_ids.product_id.id,
'product_uom': item.bom_id.bom_line_ids.product_uom_id.id, 'product_uom': item.bom_id.bom_line_ids.product_uom_id.id,
'product_uom_qty': 1.0, 'product_uom_qty': 1.0,
'location_id': location_src_id, 'location_id': stock_rule.location_src_id.id,
'location_dest_id': location_dest_id, 'location_dest_id': stock_rule.location_dest_id.id,
'origin': item.name, 'origin': item.name,
'group_id': group_id,
'move_dest_ids': [(6, 0, [move_dest_ids])] if move_dest_ids else False,
# 'production_id': item.id,
# 'route_ids': False if not route else [(4, route.id)], # 'route_ids': False if not route else [(4, route.id)],
'date_deadline': datetime.now(), 'date_deadline': datetime.now(),
'picking_type_id': picking_type_id, 'picking_type_id': picking_type_id,
@@ -742,7 +802,7 @@ class ReStockMove(models.Model):
'picking_type_id': picking_type_id, 'picking_type_id': picking_type_id,
'location_id': self.mapped('location_id').id, 'location_id': self.mapped('location_id').id,
'location_dest_id': self.mapped('location_dest_id').id, 'location_dest_id': self.mapped('location_dest_id').id,
'state': 'confirmed', 'state': 'waiting',
} }
def get_move_line(self, production_id, sorted_workorders): def get_move_line(self, production_id, sorted_workorders):
@@ -958,7 +1018,7 @@ class ReStockMove(models.Model):
合并制造订单的完成move单据 合并制造订单的完成move单据
""" """
res = super(ReStockMove, self)._merge_moves_fields() res = super(ReStockMove, self)._merge_moves_fields()
if self[0].origin and self.picking_type_id.name in ['生产发料', '内部调拨']: if self[0].origin and self.picking_type_id.name in ['生产发料', '内部调拨', '生产入库', '客供料入库']:
production = self.env['mrp.production'].search([('name', '=', self[0].origin)], limit=1, order='id asc') production = self.env['mrp.production'].search([('name', '=', self[0].origin)], limit=1, order='id asc')
productions = self.env['mrp.production'].search( productions = self.env['mrp.production'].search(
[('origin', '=', production.origin), ('product_id', '=', production.product_id.id)]) [('origin', '=', production.origin), ('product_id', '=', production.product_id.id)])
@@ -970,18 +1030,24 @@ class ReStockMove(models.Model):
创建调拨单时,在此新增或修改调拨单的数据 创建调拨单时,在此新增或修改调拨单的数据
""" """
res = super(ReStockMove, self)._get_new_picking_values() res = super(ReStockMove, self)._get_new_picking_values()
if self[0].origin and self.picking_type_id.name in ['生产发料', '内部调拨']: ## 制造订单报废生成的新制造订单不走合并
production = self.env['mrp.production'].search([('name', '=', self[0].origin)], limit=1, order='id asc') production_remanufacture = None
productions = self.env['mrp.production'].search( if 'origin' in res:
[('origin', '=', production.origin), ('product_id', '=', production.product_id.id)]) if self.picking_type_id.name in ['生产发料', '内部调拨']:
res['origin'] = ','.join(productions.mapped('name')) production_remanufacture = self.env['mrp.production'].search(
res['retrospect_ref'] = production.product_id.name [('name', '=', res['origin']), ('is_remanufacture', '=', True)])
if not production_remanufacture:
if self[0].origin and self.picking_type_id.name in ['生产发料', '内部调拨']:
production = self.env['mrp.production'].search([('name', '=', self[0].origin)], limit=1, order='id asc')
productions = self.env['mrp.production'].search(
[('origin', '=', production.origin), ('product_id', '=', production.product_id.id)])
if productions.mapped('name'):
res['origin'] = ','.join(productions.mapped('name'))
res['retrospect_ref'] = production.product_id.name
return res return res
def _single_manufactuing_mo_generate_origin(self, res): subcontract_workorder_id = fields.Many2one('mrp.workorder', '外协工单组件', check_company=True,
""" index='btree_not_null')
单个制造订单的完成move单据修改来源为该制造订单关联的销售订单下所有成品相同的制造订单
"""
class ReStockQuant(models.Model): class ReStockQuant(models.Model):

View File

@@ -11,11 +11,11 @@ access_sf_model_type_group_sale_director,sf_model_type_group_sale_director,model
access_sf_model_type_group_purchase_director,sf_model_type_group_purchase_director,model_sf_model_type,sf_base.group_purchase_director,1,0,0,0 access_sf_model_type_group_purchase_director,sf_model_type_group_purchase_director,model_sf_model_type,sf_base.group_purchase_director,1,0,0,0
access_sf_model_type_group_plan_director,sf_model_type_group_plan_director,model_sf_model_type,sf_base.group_plan_director,1,0,0,0 access_sf_model_type_group_plan_director,sf_model_type_group_plan_director,model_sf_model_type,sf_base.group_plan_director,1,0,0,0
access_sf_product_model_type_routing_sort_group_sf_mrp_user,sf_product_model_type_routing_sort,model_sf_product_model_type_routing_sort,sf_base.group_sf_mrp_user,1,0,0,0 access_sf_product_model_type_routing_sort_group_sf_mrp_user,sf_product_model_type_routing_sort,model_sf_product_model_type_routing_sort,sf_base.group_sf_mrp_user,1,0,0,0
access_sf_product_model_type_routing_sort_manager,sf_product_model_type_routing_sort,model_sf_product_model_type_routing_sort,sf_base.group_sf_mrp_manager,1,1,1,0 access_sf_product_model_type_routing_sort_manager,sf_product_model_type_routing_sort,model_sf_product_model_type_routing_sort,sf_base.group_sf_mrp_manager,1,1,1,1
access_sf_embryo_model_type_routing_sort_group_sf_mrp_user,sf_embryo_model_type_routing_sort,model_sf_embryo_model_type_routing_sort,sf_base.group_sf_mrp_user,1,0,0,0 access_sf_embryo_model_type_routing_sort_group_sf_mrp_user,sf_embryo_model_type_routing_sort,model_sf_embryo_model_type_routing_sort,sf_base.group_sf_mrp_user,1,0,0,0
access_sf_embryo_model_type_routing_sort_manager,sf_embryo_model_type_routing_sort,model_sf_embryo_model_type_routing_sort,sf_base.group_sf_mrp_manager,1,1,1,0 access_sf_embryo_model_type_routing_sort_manager,sf_embryo_model_type_routing_sort,model_sf_embryo_model_type_routing_sort,sf_base.group_sf_mrp_manager,1,1,1,1
access_sf_surface_technics_model_type_routing_sort,sf_surface_technics_model_type_routing_sort,model_sf_surface_technics_model_type_routing_sort,sf_base.group_sf_mrp_user,1,0,0,0 access_sf_surface_technics_model_type_routing_sort,sf_surface_technics_model_type_routing_sort,model_sf_surface_technics_model_type_routing_sort,sf_base.group_sf_mrp_user,1,0,0,0
access_sf_surface_technics_model_type_routing_sort_manager,sf_surface_technics_model_type_routing_sort,model_sf_surface_technics_model_type_routing_sort,sf_base.group_sf_mrp_manager,1,1,1,0 access_sf_surface_technics_model_type_routing_sort_manager,sf_surface_technics_model_type_routing_sort,model_sf_surface_technics_model_type_routing_sort,sf_base.group_sf_mrp_manager,1,1,1,1
access_sf_production_line_group_sf_mrp_user,sf.production.line,model_sf_production_line,sf_base.group_sf_mrp_user,1,1,1,0 access_sf_production_line_group_sf_mrp_user,sf.production.line,model_sf_production_line,sf_base.group_sf_mrp_user,1,1,1,0
access_sf_production_line_manager,sf.production.line,model_sf_production_line,sf_base.group_sf_mrp_manager,1,1,1,0 access_sf_production_line_manager,sf.production.line,model_sf_production_line,sf_base.group_sf_mrp_manager,1,1,1,0
access_maintenance_equipment_tool_group_sf_mrp_user,maintenance_equipment_tool,model_maintenance_equipment_tool,sf_base.group_sf_mrp_user,1,0,0,0 access_maintenance_equipment_tool_group_sf_mrp_user,maintenance_equipment_tool,model_maintenance_equipment_tool,sf_base.group_sf_mrp_user,1,0,0,0
@@ -52,6 +52,7 @@ access_mrp_routing_workcenter_manager_group_sf_mrp_user,mrp.routing.workcenter.m
access_mrp_bom_manager_group_sf_mrp_user,mrp.bom.manager,mrp.model_mrp_bom,sf_base.group_sf_mrp_user,1,1,1,0 access_mrp_bom_manager_group_sf_mrp_user,mrp.bom.manager,mrp.model_mrp_bom,sf_base.group_sf_mrp_user,1,1,1,0
access_mrp_bom_line_manager_group_sf_mrp_user,mrp.bom.line.manager,mrp.model_mrp_bom_line,sf_base.group_sf_mrp_user,1,1,1,0 access_mrp_bom_line_manager_group_sf_mrp_user,mrp.bom.line.manager,mrp.model_mrp_bom_line,sf_base.group_sf_mrp_user,1,1,1,0
access_mrp_bom_line_group_plan_director,mrp_bom_line_group_plan_director,mrp.model_mrp_bom_line,sf_base.group_plan_director,1,1,1,0 access_mrp_bom_line_group_plan_director,mrp_bom_line_group_plan_director,mrp.model_mrp_bom_line,sf_base.group_plan_director,1,1,1,0
access_mrp_bom_line_group_sf_stock_user,mrp_bom_line_group_sf_stock_user,mrp.model_mrp_bom_line,sf_base.group_sf_stock_user,1,1,1,0
access_mrp_bom_line_group_sale_director,mrp_bom_line_group_sale_director,mrp.model_mrp_bom_line,sf_base.group_sale_director,1,1,1,0 access_mrp_bom_line_group_sale_director,mrp_bom_line_group_sale_director,mrp.model_mrp_bom_line,sf_base.group_sale_director,1,1,1,0
access_mrp_bom_line_group_sale_salemanager,mrp_bom_line_group_sale_salemanager,mrp.model_mrp_bom_line,sf_base.group_sale_salemanager,1,0,1,0 access_mrp_bom_line_group_sale_salemanager,mrp_bom_line_group_sale_salemanager,mrp.model_mrp_bom_line,sf_base.group_sale_salemanager,1,0,1,0
access_mrp_bom_line_group_purchase_director,mrp_bom_line_group_purchase_director,mrp.model_mrp_bom_line,sf_base.group_purchase_director,1,1,1,0 access_mrp_bom_line_group_purchase_director,mrp_bom_line_group_purchase_director,mrp.model_mrp_bom_line,sf_base.group_purchase_director,1,1,1,0
@@ -116,7 +117,7 @@ access_mrp_production_group_quality,mrp_production,model_mrp_production,sf_base.
access_mrp_production_group_quality_director,mrp_production,model_mrp_production,sf_base.group_quality_director,1,1,0,0 access_mrp_production_group_quality_director,mrp_production,model_mrp_production,sf_base.group_quality_director,1,1,0,0
access_mrp_workorder_group_quality,mrp_workorder,model_mrp_workorder,sf_base.group_quality,1,1,0,0 access_mrp_workorder_group_quality,mrp_workorder,model_mrp_workorder,sf_base.group_quality,1,1,0,0
access_mrp_workorder_group_quality_director,mrp_workorder,model_mrp_workorder,sf_base.group_quality_director,1,1,0,0 access_mrp_workorder_group_quality_director,mrp_workorder,model_mrp_workorder,sf_base.group_quality_director,1,1,0,0
access_mrp_workorder,mrp_workorder,model_mrp_workorder,sf_base.group_plan_dispatch,1,1,0,0 access_mrp_workorder,mrp_workorder,model_mrp_workorder,sf_base.group_plan_dispatch,1,1,1,0
access_sf_production_line_group_plan_dispatch,sf.production.line,model_sf_production_line,sf_base.group_plan_dispatch,1,0,0,0 access_sf_production_line_group_plan_dispatch,sf.production.line,model_sf_production_line,sf_base.group_plan_dispatch,1,0,0,0
access_sf_production_line_group_plan_director,sf.production.line,model_sf_production_line,sf_base.group_plan_director,1,1,1,0 access_sf_production_line_group_plan_director,sf.production.line,model_sf_production_line,sf_base.group_plan_director,1,1,1,0
access_sf_production_line,sf.production.line,model_sf_production_line,sf_maintenance.sf_group_equipment_user,1,1,1,0 access_sf_production_line,sf.production.line,model_sf_production_line,sf_maintenance.sf_group_equipment_user,1,1,1,0
@@ -166,16 +167,23 @@ access_sf_agv_scheduling_group_sf_mrp_manager,sf_agv_scheduling_group_sf_mrp_man
access_sf_agv_scheduling_group_sf_equipment_user,sf_agv_scheduling_group_sf_equipment_user,model_sf_agv_scheduling,sf_base.group_sf_equipment_user,1,1,1,0 access_sf_agv_scheduling_group_sf_equipment_user,sf_agv_scheduling_group_sf_equipment_user,model_sf_agv_scheduling,sf_base.group_sf_equipment_user,1,1,1,0
access_sf_technology_design_group_plan_dispatch,sf_technology_design_group_plan_dispatch,model_sf_technology_design,sf_base.group_plan_dispatch,1,1,1,0 access_sf_technology_design_group_plan_dispatch,sf_technology_design_group_plan_dispatch,model_sf_technology_design,sf_base.group_plan_dispatch,1,1,1,0
access_sf_technology_design_group_sf_mrp_manager,sf_technology_design_group_sf_mrp_manager,model_sf_technology_design,sf_base.group_sf_mrp_manager,1,1,1,0 access_sf_technology_design_group_sf_mrp_manager,sf_technology_design_group_sf_mrp_manager,model_sf_technology_design,sf_base.group_sf_mrp_manager,1,0,0,0
access_sf_technology_design_group_production_engineer,sf_technology_design_group_production_engineer,model_sf_technology_design,sf_base.group_production_engineer,1,1,1,0 access_sf_technology_design_group_production_engineer,sf_technology_design_group_production_engineer,model_sf_technology_design,sf_base.group_production_engineer,1,1,1,0
access_sf_technology_design_group_sf_equipment_user,sf_technology_design_group_sf_equipment_user,model_sf_technology_design,sf_base.group_sf_equipment_user,1,0,0,0
access_sf_technology_design_group_sf_order_user,sf_technology_design_group_sf_order_user,model_sf_technology_design,sf_base.group_sf_order_user,1,0,0,0
access_sf_production_technology_wizard_group_plan_dispatch,sf_production_technology_wizard_group_plan_dispatch,model_sf_production_technology_wizard,sf_base.group_plan_dispatch,1,1,1,0 access_sf_production_technology_wizard_group_plan_dispatch,sf_production_technology_wizard_group_plan_dispatch,model_sf_production_technology_wizard,sf_base.group_plan_dispatch,1,1,1,0
access_sf_production_technology_wizard_group_sf_mrp_manager,sf_production_technology_wizard_group_sf_mrp_manager,model_sf_production_technology_wizard,sf_base.group_sf_mrp_manager,1,1,1,0 access_sf_production_technology_wizard_group_sf_mrp_manager,sf_production_technology_wizard_group_sf_mrp_manager,model_sf_production_technology_wizard,sf_base.group_sf_mrp_manager,1,0,0,0
access_sf_production_technology_wizard_group_production_engineer,sf_production_technology_wizard_group_production_engineer,model_sf_production_technology_wizard,sf_base.group_production_engineer,1,1,1,0 access_sf_production_technology_wizard_group_production_engineer,sf_production_technology_wizard_group_production_engineer,model_sf_production_technology_wizard,sf_base.group_production_engineer,1,1,1,0
access_sf_production_technology_re_adjust_wizard_group_plan_dispatch,sf_production_technology_re_adjust_wizard_group_plan_dispatch,model_sf_production_technology_re_adjust_wizard,sf_base.group_plan_dispatch,1,1,1,0 access_sf_production_technology_re_adjust_wizard_group_plan_dispatch,sf_production_technology_re_adjust_wizard_group_plan_dispatch,model_sf_production_technology_re_adjust_wizard,sf_base.group_plan_dispatch,1,1,1,0
access_sf_production_technology_re_adjust_wizard_group_sf_mrp_manager,sf_production_technology_re_adjust_wizard_group_sf_mrp_manager,model_sf_production_technology_re_adjust_wizard,sf_base.group_sf_mrp_manager,1,1,1,0 access_sf_production_technology_re_adjust_wizard_group_sf_mrp_manager,sf_production_technology_re_adjust_wizard_group_sf_mrp_manager,model_sf_production_technology_re_adjust_wizard,sf_base.group_sf_mrp_manager,1,1,1,0
access_sf_production_technology_re_adjust_wizard_group_production_engineer,sf_production_technology_re_adjust_wizard_group_production_engineer,model_sf_production_technology_re_adjust_wizard,sf_base.group_production_engineer,1,1,1,0 access_sf_production_technology_re_adjust_wizard_group_production_engineer,sf_production_technology_re_adjust_wizard_group_production_engineer,model_sf_production_technology_re_adjust_wizard,sf_base.group_production_engineer,1,1,1,0
access_sf_manual_product_model_type_routing_sort_group_sf_mrp_user,sf_manual_product_model_type_routing_sort,model_sf_manual_product_model_type_routing_sort,sf_base.group_sf_mrp_user,1,0,0,0 access_sf_manual_product_model_type_routing_sort_group_sf_mrp_user,sf_manual_product_model_type_routing_sort,model_sf_manual_product_model_type_routing_sort,sf_base.group_sf_mrp_user,1,0,0,0
access_sf_manual_product_model_type_routing_sort_manager,sf_manual_product_model_type_routing_sort,model_sf_manual_product_model_type_routing_sort,sf_base.group_sf_mrp_manager,1,1,1,0 access_sf_manual_product_model_type_routing_sort_manager,sf_manual_product_model_type_routing_sort,model_sf_manual_product_model_type_routing_sort,sf_base.group_sf_mrp_manager,1,1,1,1
access_sf_manual_product_model_type_routing_sort_group_plan_dispatch,sf_manual_product_model_type_routing_sort_group_plan_dispatch,model_sf_manual_product_model_type_routing_sort,sf_base.group_plan_dispatch,1,0,0,0 access_sf_manual_product_model_type_routing_sort_group_plan_dispatch,sf_manual_product_model_type_routing_sort_group_plan_dispatch,model_sf_manual_product_model_type_routing_sort,sf_base.group_plan_dispatch,1,0,0,0
access_sf_detection_result_manager,sf_detection_result_manager,model_sf_detection_result,,1,1,1,1 access_sf_detection_result_manager,sf_detection_result_manager,model_sf_detection_result,,1,1,1,1
access_mrp_workorder_batch_replan_wizard_group_plan_dispatch,mrp_workorder_batch_replan_wizard_group_plan_dispatch,model_mrp_workorder_batch_replan_wizard,sf_base.group_plan_dispatch,1,1,1,0
access_mrp_workorder_group_purchase_director,mrp_workorder,model_mrp_workorder,sf_base.group_purchase_director,1,1,0,0
access_mrp_workorder_group_purchase,mrp_workorder,model_mrp_workorder,sf_base.group_purchase,1,1,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
11 access_sf_model_type_group_purchase_director sf_model_type_group_purchase_director model_sf_model_type sf_base.group_purchase_director 1 0 0 0
12 access_sf_model_type_group_plan_director sf_model_type_group_plan_director model_sf_model_type sf_base.group_plan_director 1 0 0 0
13 access_sf_product_model_type_routing_sort_group_sf_mrp_user sf_product_model_type_routing_sort model_sf_product_model_type_routing_sort sf_base.group_sf_mrp_user 1 0 0 0
14 access_sf_product_model_type_routing_sort_manager sf_product_model_type_routing_sort model_sf_product_model_type_routing_sort sf_base.group_sf_mrp_manager 1 1 1 0 1
15 access_sf_embryo_model_type_routing_sort_group_sf_mrp_user sf_embryo_model_type_routing_sort model_sf_embryo_model_type_routing_sort sf_base.group_sf_mrp_user 1 0 0 0
16 access_sf_embryo_model_type_routing_sort_manager sf_embryo_model_type_routing_sort model_sf_embryo_model_type_routing_sort sf_base.group_sf_mrp_manager 1 1 1 0 1
17 access_sf_surface_technics_model_type_routing_sort sf_surface_technics_model_type_routing_sort model_sf_surface_technics_model_type_routing_sort sf_base.group_sf_mrp_user 1 0 0 0
18 access_sf_surface_technics_model_type_routing_sort_manager sf_surface_technics_model_type_routing_sort model_sf_surface_technics_model_type_routing_sort sf_base.group_sf_mrp_manager 1 1 1 0 1
19 access_sf_production_line_group_sf_mrp_user sf.production.line model_sf_production_line sf_base.group_sf_mrp_user 1 1 1 0
20 access_sf_production_line_manager sf.production.line model_sf_production_line sf_base.group_sf_mrp_manager 1 1 1 0
21 access_maintenance_equipment_tool_group_sf_mrp_user maintenance_equipment_tool model_maintenance_equipment_tool sf_base.group_sf_mrp_user 1 0 0 0
52 access_mrp_bom_line_manager_group_sf_mrp_user mrp.bom.line.manager mrp.model_mrp_bom_line sf_base.group_sf_mrp_user 1 1 1 0
53 access_mrp_bom_line_group_plan_director mrp_bom_line_group_plan_director mrp.model_mrp_bom_line sf_base.group_plan_director 1 1 1 0
54 access_mrp_bom_line_group_sale_director access_mrp_bom_line_group_sf_stock_user mrp_bom_line_group_sale_director mrp_bom_line_group_sf_stock_user mrp.model_mrp_bom_line sf_base.group_sale_director sf_base.group_sf_stock_user 1 1 1 0
55 access_mrp_bom_line_group_sale_director mrp_bom_line_group_sale_director mrp.model_mrp_bom_line sf_base.group_sale_director 1 1 1 0
56 access_mrp_bom_line_group_sale_salemanager mrp_bom_line_group_sale_salemanager mrp.model_mrp_bom_line sf_base.group_sale_salemanager 1 0 1 0
57 access_mrp_bom_line_group_purchase_director mrp_bom_line_group_purchase_director mrp.model_mrp_bom_line sf_base.group_purchase_director 1 1 1 0
58 access_mrp_bom_byproduct_manager_group_sf_mrp_user mrp.bom.byproduct manager mrp.model_mrp_bom_byproduct sf_base.group_sf_mrp_user 1 1 1 0
117 access_mrp_workorder_group_quality mrp_workorder model_mrp_workorder sf_base.group_quality 1 1 0 0
118 access_mrp_workorder_group_quality_director mrp_workorder model_mrp_workorder sf_base.group_quality_director 1 1 0 0
119 access_mrp_workorder mrp_workorder model_mrp_workorder sf_base.group_plan_dispatch 1 1 0 1 0
120 access_sf_production_line_group_plan_dispatch sf.production.line model_sf_production_line sf_base.group_plan_dispatch 1 0 0 0
121 access_sf_production_line_group_plan_director sf.production.line model_sf_production_line sf_base.group_plan_director 1 1 1 0
122 access_sf_production_line sf.production.line model_sf_production_line sf_maintenance.sf_group_equipment_user 1 1 1 0
123 access_mrp_workcenter mrp_workcenter model_mrp_workcenter sf_base.group_plan_dispatch 1 1 1 0
167 access_sf_production_technology_re_adjust_wizard_group_production_engineer access_sf_production_technology_re_adjust_wizard_group_plan_dispatch sf_production_technology_re_adjust_wizard_group_production_engineer sf_production_technology_re_adjust_wizard_group_plan_dispatch model_sf_production_technology_re_adjust_wizard sf_base.group_production_engineer sf_base.group_plan_dispatch 1 1 1 0
168 access_sf_manual_product_model_type_routing_sort_group_sf_mrp_user access_sf_production_technology_re_adjust_wizard_group_sf_mrp_manager sf_manual_product_model_type_routing_sort sf_production_technology_re_adjust_wizard_group_sf_mrp_manager model_sf_manual_product_model_type_routing_sort model_sf_production_technology_re_adjust_wizard sf_base.group_sf_mrp_user sf_base.group_sf_mrp_manager 1 0 1 0 1 0
169 access_sf_manual_product_model_type_routing_sort_manager access_sf_production_technology_re_adjust_wizard_group_production_engineer sf_manual_product_model_type_routing_sort sf_production_technology_re_adjust_wizard_group_production_engineer model_sf_manual_product_model_type_routing_sort model_sf_production_technology_re_adjust_wizard sf_base.group_sf_mrp_manager sf_base.group_production_engineer 1 1 1 0
170 access_sf_manual_product_model_type_routing_sort_group_plan_dispatch access_sf_manual_product_model_type_routing_sort_group_sf_mrp_user sf_manual_product_model_type_routing_sort_group_plan_dispatch sf_manual_product_model_type_routing_sort model_sf_manual_product_model_type_routing_sort sf_base.group_plan_dispatch sf_base.group_sf_mrp_user 1 0 0 0
171 access_sf_detection_result_manager access_sf_manual_product_model_type_routing_sort_manager sf_detection_result_manager sf_manual_product_model_type_routing_sort model_sf_detection_result model_sf_manual_product_model_type_routing_sort sf_base.group_sf_mrp_manager 1 1 1 1
172 access_sf_manual_product_model_type_routing_sort_group_plan_dispatch sf_manual_product_model_type_routing_sort_group_plan_dispatch model_sf_manual_product_model_type_routing_sort sf_base.group_plan_dispatch 1 0 0 0
173 access_sf_detection_result_manager sf_detection_result_manager model_sf_detection_result 1 1 1 1
174 access_mrp_workorder_batch_replan_wizard_group_plan_dispatch mrp_workorder_batch_replan_wizard_group_plan_dispatch model_mrp_workorder_batch_replan_wizard sf_base.group_plan_dispatch 1 1 1 0
175 access_mrp_workorder_group_purchase_director mrp_workorder model_mrp_workorder sf_base.group_purchase_director 1 1 0 0
176 access_mrp_workorder_group_purchase mrp_workorder model_mrp_workorder sf_base.group_purchase 1 1 0 0
177
178
179
180
181
182
183
184
185
186
187
188
189

View File

@@ -0,0 +1,50 @@
odoo.define('sf_manufacturing.agv_scheduling_button_confirm', function (require) {
const core = require('web.core');
const ajax = require('web.ajax');
const Dialog = require('web.Dialog');
var rpc = require('web.rpc');
var _t = core._t;
async function agv_scheduling_cancel_confirm(parent, {params}) {
const dialog = new Dialog(parent, {
title: "确认",
$content: $('<div>').append("工件正在配送中,确定取消"),
buttons: [
{ text: "确认", classes: 'btn-primary', close: true, click: () => dispatchConfirmed(parent, params) },
{ text: "取消", close: true },
],
});
dialog.open();
async function dispatchConfirmed(parent, params) {
rpc.query({
model: 'sf.agv.scheduling',
method: 'button_cancel',
args: [params.agv_scheduling_id],
kwargs: {
context: params.context,
}
}).then(res => {
parent.services.action.doAction({
'type': 'ir.actions.client',
'tag': 'display_notification',
'target': 'new',
'params': {
'message': '取消成功!',
'type': 'success',
'sticky': false,
'next': {'type': 'ir.actions.act_window_close'},
}
});
parent.services.action.doAction({
'type': 'ir.actions.client',
'tag': 'reload',
});
})
}
}
core.action_registry.add('agv_scheduling_cancel_confirm', agv_scheduling_cancel_confirm);
return agv_scheduling_cancel_confirm;
});

View File

@@ -0,0 +1,50 @@
odoo.define('sf_manufacturing.agv_scheduling_resend_confirm', function (require) {
const core = require('web.core');
const ajax = require('web.ajax');
const Dialog = require('web.Dialog');
var rpc = require('web.rpc');
var _t = core._t;
async function agv_scheduling_resend_confirm(parent, {params}) {
const dialog = new Dialog(parent, {
title: "确认",
$content: $('<div>').append("工件正在配送中,确定重新下发"),
buttons: [
{ text: "确认", classes: 'btn-primary', close: true, click: () => dispatchConfirmed(parent, params) },
{ text: "取消", close: true },
],
});
dialog.open();
async function dispatchConfirmed(parent, params) {
rpc.query({
model: 'sf.agv.scheduling',
method: 'button_resend',
args: [params.agv_scheduling_id],
kwargs: {
context: params.context,
}
}).then(res => {
parent.services.action.doAction({
'type': 'ir.actions.client',
'tag': 'display_notification',
'target': 'new',
'params': {
'message': '重新下发成功!',
'type': 'success',
'sticky': false,
'next': {'type': 'ir.actions.act_window_close'},
}
});
parent.services.action.doAction({
'type': 'ir.actions.client',
'tag': 'reload',
});
})
}
}
core.action_registry.add('agv_scheduling_resend_confirm', agv_scheduling_resend_confirm );
return agv_scheduling_resend_confirm;
});

View File

@@ -22,8 +22,7 @@ odoo.define('sf_manufacturing.action_dispatch_confirm', function (require) {
rpc.query({ rpc.query({
model: 'sf.workpiece.delivery.wizard', model: 'sf.workpiece.delivery.wizard',
method: 'confirm', method: 'confirm',
args: [params.active_id] args: [params.active_id],
,
kwargs: { kwargs: {
context: params.context, context: params.context,
} }

View File

@@ -33,6 +33,20 @@
class="btn-danger" class="btn-danger"
confirm="你确定要取消这条记录吗?" confirm="你确定要取消这条记录吗?"
/> />
<button
name="button_cancel_confirm"
string="取消" type="object"
attrs="{'invisible': [('state', '!=', '配送中')]}"
icon="fa-times"
class="btn-danger"
/>
<button
name="button_resend_confirm"
string="重新下发" type="object"
attrs="{'invisible': [('state', '!=', '配送中')]}"
icon="fa-circle-o-notch"
class="btn-success "
/>
</tree> </tree>
</field> </field>
</record> </record>

View File

@@ -3,7 +3,7 @@
<data> <data>
#------------------模型类型------------------ #------------------模型类型------------------
<record model="ir.ui.view" id="search_sf_model_type_view"> <record model="ir.ui.view" id="search_sf_model_name_view">
<field name="name">search.sf.model.type</field> <field name="name">search.sf.model.type</field>
<field name="model">sf.model.type</field> <field name="model">sf.model.type</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
@@ -14,7 +14,7 @@
</field> </field>
</record> </record>
<record model="ir.ui.view" id="tree_sf_model_type_view"> <record model="ir.ui.view" id="tree_sf_model_name_view">
<field name="name">tree.sf.model.type</field> <field name="name">tree.sf.model.type</field>
<field name="model">sf.model.type</field> <field name="model">sf.model.type</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
@@ -24,20 +24,20 @@
</field> </field>
</record> </record>
<record model="ir.ui.view" id="form_sf_model_type"> <record model="ir.ui.view" id="form_sf_model_name">
<field name="name">form.sf.model.type</field> <field name="name">form.sf.model.type</field>
<field name="model">sf.model.type</field> <field name="model">sf.model.type</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<form string="模型类型"> <form string="模型类型">
<group> <group>
<field name="name" required="1"/> <field name="name" required="1"/>
<field name="embryo_tolerance_id" required="1" string="坯料容余(mm)"/> <field name="embryo_tolerance_id" required="1"/>
</group> </group>
<group> <group>
<field name='product_routing_tmpl_ids'> <field name='product_routing_tmpl_ids'>
<tree editable='bottom'> <tree editable='bottom'>
<field name="sequence" widget="handle" string="序号"/> <field name="sequence" widget="handle" string="序号"/>
<field name="route_workcenter_id" string="工序" options="{'no_create': True}"/> <field name="route_workcenter_id" string="工序" options="{'no_create': True}" context="{'is_duplicate': True, 'model_name': 'sf.product.model.type.routing.sort'}"/>
<field name="routing_type" string="类型"/> <field name="routing_type" string="类型"/>
<field name="is_repeat" string="重复"/> <field name="is_repeat" string="重复"/>
<field name="workcenter_ids" string="工作中心" widget="many2many_tags"/> <field name="workcenter_ids" string="工作中心" widget="many2many_tags"/>
@@ -48,7 +48,7 @@
<field name='manual_product_routing_tmpl_ids'> <field name='manual_product_routing_tmpl_ids'>
<tree editable='bottom'> <tree editable='bottom'>
<field name="sequence" widget="handle" string="序号"/> <field name="sequence" widget="handle" string="序号"/>
<field name="route_workcenter_id" string="工序" options="{'no_create': True}"/> <field name="route_workcenter_id" string="工序" options="{'no_create': True}" context="{'is_duplicate': True, 'model_name': 'sf.manual.product.model.type.routing.sort'}"/>
<field name="routing_type" string="类型"/> <field name="routing_type" string="类型"/>
<field name="is_repeat" string="重复"/> <field name="is_repeat" string="重复"/>
<field name="workcenter_ids" string="工作中心" widget="many2many_tags"/> <field name="workcenter_ids" string="工作中心" widget="many2many_tags"/>
@@ -59,7 +59,7 @@
<field name='embryo_routing_tmpl_ids'> <field name='embryo_routing_tmpl_ids'>
<tree editable='bottom'> <tree editable='bottom'>
<field name="sequence" widget="handle" string="序号"/> <field name="sequence" widget="handle" string="序号"/>
<field name="route_workcenter_id" string="工序" options="{'no_create': True}"/> <field name="route_workcenter_id" string="工序" options="{'no_create': True}" context="{'is_duplicate': True, 'model_name': 'sf.embryo.model.type.routing.sort'}"/>
<field name="routing_type" string="类型"/> <field name="routing_type" string="类型"/>
<field name="is_repeat" string="重复"/> <field name="is_repeat" string="重复"/>
<field name="workcenter_ids" string="工作中心" widget="many2many_tags"/> <field name="workcenter_ids" string="工作中心" widget="many2many_tags"/>
@@ -70,7 +70,7 @@
<field name='surface_technics_routing_tmpl_ids' style="white-space: pre-wrap;"> <field name='surface_technics_routing_tmpl_ids' style="white-space: pre-wrap;">
<tree editable='bottom'> <tree editable='bottom'>
<field name="sequence" widget="handle" string="序号"/> <field name="sequence" widget="handle" string="序号"/>
<field name="route_workcenter_id" string="工序" options="{'no_create': True}"/> <field name="route_workcenter_id" string="工序" options="{'no_create': True}" context="{'is_duplicate': True, 'model_name': 'sf.surface_technics.model.type.routing.sort'}"/>
<field name="routing_type" string="类型"/> <field name="routing_type" string="类型"/>
<field name="is_repeat" string="重复"/> <field name="is_repeat" string="重复"/>
<field name="workcenter_ids" string="工作中心" widget="many2many_tags"/> <field name="workcenter_ids" string="工作中心" widget="many2many_tags"/>
@@ -81,7 +81,7 @@
</field> </field>
</record> </record>
<record id="action_sf_model_type" model="ir.actions.act_window"> <record id="action_sf_model_name" model="ir.actions.act_window">
<field name="name">模型类型</field> <field name="name">模型类型</field>
<field name="type">ir.actions.act_window</field> <field name="type">ir.actions.act_window</field>
<field name="res_model">sf.model.type</field> <field name="res_model">sf.model.type</field>
@@ -96,11 +96,11 @@
</record> </record>
<menuitem <menuitem
id="menu_sf_model_type" id="menu_sf_model_name"
name="模型类型" name="模型类型"
parent="mrp.menu_mrp_configuration" parent="mrp.menu_mrp_configuration"
sequence="9" sequence="9"
action="action_sf_model_type" action="action_sf_model_name"
/> />
</data> </data>
</odoo> </odoo>

View File

@@ -18,9 +18,12 @@
<xpath expr="//field[@name='date_deadline']" position="replace"/> <xpath expr="//field[@name='date_deadline']" position="replace"/>
<xpath expr="//field[@name='name']" position="after"> <xpath expr="//field[@name='name']" position="after">
<field name="product_id" readonly="1" optional="show"/> <field name="product_id" readonly="1" optional="show"/>
<field name="part_name" readonly="1" optional="hide"/>
<field name="part_number" readonly="1" optional="show"/>
</xpath> </xpath>
<xpath expr="//field[@name='product_id']" position="after"> <xpath expr="//field[@name='product_id']" position="after">
<field name="product_qty" sum="Total Qty" string="数量" readonly="1" optional="show"/> <field name="product_qty" sum="Total Qty" string="数量" readonly="1" optional="show"/>
<field name="deadline_of_delivery" optional="show"/>
</xpath> </xpath>
<xpath expr="//field[@name='product_qty']" position="after"> <xpath expr="//field[@name='product_qty']" position="after">
<field name="product_uom_id" string="计量单位" options="{'no_open':True,'no_create':True}" <field name="product_uom_id" string="计量单位" options="{'no_open':True,'no_create':True}"
@@ -43,6 +46,7 @@
<field name="activity_ids" string="下一个活动" widget="list_activity" optional="hide"/> <field name="activity_ids" string="下一个活动" widget="list_activity" optional="hide"/>
</xpath> </xpath>
<xpath expr="//field[@name='origin']" position="replace"> <xpath expr="//field[@name='origin']" position="replace">
<field name="sale_order_id" optional="show"/>
<field name="origin" optional="hide"/> <field name="origin" optional="hide"/>
</xpath> </xpath>
<xpath expr="//field[@name='components_availability']" position="replace"> <xpath expr="//field[@name='components_availability']" position="replace">
@@ -120,16 +124,13 @@
<!-- <field name="production_line_state" readonly="1"/>--> <!-- <field name="production_line_state" readonly="1"/>-->
<field name="part_name"/> <field name="part_name"/>
<field name="part_number" string="零件图号"/> <field name="part_number" string="零件图号"/>
<field name="tool_state" attrs="{'invisible': [('production_type', 'not in', ['自动化产线加工'])]}"/> <field name="tool_state"
attrs="{'invisible': [('production_type', 'not in', ['自动化产线加工'])]}"/>
<field name="tool_state_remark" string="备注" attrs="{'invisible': [('tool_state', '!=', '1')]}"/> <field name="tool_state_remark" string="备注" attrs="{'invisible': [('tool_state', '!=', '1')]}"/>
<field name="sale_order_id" readonly="1"/>
<field name="deadline_of_delivery" readonly="1"/> <field name="deadline_of_delivery" readonly="1"/>
<field name="tool_state_remark2" invisible="1"/> <field name="tool_state_remark2" invisible="1"/>
</xpath> </xpath>
<xpath expr="//header//button[@name='action_cancel']" position="replace">
<button name="action_cancel" type="object" string="取消" data-hotkey="z"
attrs="{'invisible': ['|', '|', ('id', '=', False), ('state', 'in', ('done', 'cancel')), ('confirm_cancel', '=', True)]}"
groups="sf_base.group_sf_mrp_user"/>
</xpath>
<xpath expr="(//header//button[@name='button_mark_done'])[1]" position="replace"> <xpath expr="(//header//button[@name='button_mark_done'])[1]" position="replace">
<button name="button_mark_done" <button name="button_mark_done"
attrs="{'invisible': ['|', '|', ('state', 'in', ('draft', 'cancel', 'done', 'to_close')), ('qty_producing', '=', 0), ('move_raw_ids', '!=', [])]}" attrs="{'invisible': ['|', '|', ('state', 'in', ('draft', 'cancel', 'done', 'to_close')), ('qty_producing', '=', 0), ('move_raw_ids', '!=', [])]}"
@@ -254,13 +255,6 @@
type="object" groups="sf_base.group_sf_mrp_user"/> type="object" groups="sf_base.group_sf_mrp_user"/>
</xpath> </xpath>
<xpath expr="//header//button[@name='action_cancel']" position="replace">
<button name="action_cancel" type="object" string="Cancel" data-hotkey="z"
attrs="{'invisible': ['|', '|', ('id', '=', False), ('state', 'in', ('done', 'cancel')), ('confirm_cancel', '=', False)]}"
confirm="Some product moves have already been confirmed, this manufacturing order can't be completely cancelled. Are you still sure you want to process ?"
groups="sf_base.group_sf_mrp_user"/>
</xpath>
<xpath expr="//header//button[@name='button_unbuild']" position="replace"> <xpath expr="//header//button[@name='button_unbuild']" position="replace">
<button name="button_unbuild" type="object" string="拆单" <button name="button_unbuild" type="object" string="拆单"
attrs="{'invisible': [('state', '!=', 'done')]}" data-hotkey="shift+v" attrs="{'invisible': [('state', '!=', 'done')]}" data-hotkey="shift+v"
@@ -304,12 +298,14 @@
type="object" groups="sf_base.group_sf_mrp_user"/> type="object" groups="sf_base.group_sf_mrp_user"/>
</xpath> </xpath>
<xpath expr="//header//button[@name='action_cancel']" position="replace"> <xpath expr="//header//button[@name='action_cancel'][2]" position="replace">
<button name="action_cancel" type="object" string="取消" data-hotkey="z" <button name="action_cancel" type="object" string="取消" data-hotkey="z"
attrs="{'invisible': ['|', '|', ('id', '=', False), ('state', 'in', ('done', 'cancel')), ('confirm_cancel', '=', False)]}" attrs="{'invisible': ['|', '|', ('id', '=', False), ('state', 'in', ('done', 'rework', 'cancel')), ('confirm_cancel', '=', False)]}"
confirm="Some product moves have already been confirmed, this manufacturing order can't be completely cancelled. Are you still sure you want to process ?" confirm="Some product moves have already been confirmed, this manufacturing order can't be completely cancelled. Are you still sure you want to process ?"
groups="sf_base.group_sf_mrp_user"/> groups="sf_base.group_sf_mrp_user"/>
</xpath> </xpath>
<xpath expr="//header//button[@name='action_cancel'][1]" position="replace"></xpath>
<xpath expr="//header//button[@name='button_unbuild']" position="replace"> <xpath expr="//header//button[@name='button_unbuild']" position="replace">
<button name="button_unbuild" type="object" string="拆单" <button name="button_unbuild" type="object" string="拆单"
attrs="{'invisible': [('state', '!=', 'done')]}" data-hotkey="shift+v" attrs="{'invisible': [('state', '!=', 'done')]}" data-hotkey="shift+v"
@@ -365,8 +361,10 @@
<field name="sequence" widget="handle"/> <field name="sequence" widget="handle"/>
<field name="route_id" context="{'production_id': production_id}" <field name="route_id" context="{'production_id': production_id}"
attrs="{'readonly': [('id', '!=', False)]}" options="{'no_create': True}"/> attrs="{'readonly': [('id', '!=', False)]}" options="{'no_create': True}"/>
<field name="process_parameters_id" attrs="{'readonly': [('id', '!=', False)]}" <field name="process_parameters_id"
string="参数" context="{'route_id':route_id}" options="{'no_create': True}"/> attrs="{'readonly': [('id', '!=', False),('routing_tag', '=', 'standard')]}"
string="参数" context="{'route_id':route_id,'production_id': production_id}"
options="{'no_create': True}"/>
<field name="panel" readonly="1"/> <field name="panel" readonly="1"/>
<field name="routing_tag" readonly="1" widget="badge" <field name="routing_tag" readonly="1" widget="badge"
decoration-success="routing_tag == 'standard'" decoration-success="routing_tag == 'standard'"
@@ -387,13 +385,16 @@
</page> </page>
</xpath> </xpath>
<xpath expr="//sheet/group/group/div[@class='d-flex flex-row align-items-start']/span[last()]" position="attributes"> <xpath expr="//sheet/group/group/div[@class='d-flex flex-row align-items-start']/span[last()]"
position="attributes">
<attribute name="invisible">True</attribute> <attribute name="invisible">True</attribute>
</xpath> </xpath>
<xpath expr="//sheet/group/group/div[@class='d-flex flex-row align-items-start']/button[@name='action_product_forecast_report']" position="attributes"> <xpath expr="//sheet/group/group/div[@class='d-flex flex-row align-items-start']/button[@name='action_product_forecast_report']"
position="attributes">
<attribute name="invisible">True</attribute> <attribute name="invisible">True</attribute>
</xpath> </xpath>
<xpath expr="//sheet/div[@class='oe_button_box']/button[@name='action_view_mrp_production_childs']/div/span[last()]" position="replace"> <xpath expr="//sheet/div[@class='oe_button_box']/button[@name='action_view_mrp_production_childs']/div/span[last()]"
position="replace">
<span class="o_stat_text">子MO</span> <span class="o_stat_text">子MO</span>
</xpath> </xpath>
</field> </field>
@@ -433,9 +434,7 @@
<xpath expr="//tree//button[@name='button_start']" position="replace"> <xpath expr="//tree//button[@name='button_start']" position="replace">
<field name="routing_type" invisible="True"/> <field name="routing_type" invisible="True"/>
<button name="button_start" type="object" string="开始" class="btn-success" confirm="是否确认开始?" <button name="button_start" type="object" string="开始" class="btn-success" confirm="是否确认开始?"
attrs="{'invisible': ['|', '|', '|','|', ('production_state','in', ('draft', 'done', 'cancel')), attrs="{'invisible': [('state', '!=', 'ready')]}"
('working_state', '=', 'blocked'), ('state', 'in', ('done', 'cancel')), ('is_user_working', '!=',
False), ('routing_type', '=', 'CNC加工')]}"
groups="sf_base.group_sf_mrp_user"/> groups="sf_base.group_sf_mrp_user"/>
</xpath> </xpath>
<xpath expr="//tree//button[@name='button_pending']" position="replace"> <xpath expr="//tree//button[@name='button_pending']" position="replace">
@@ -578,6 +577,7 @@
<searchpanel> <searchpanel>
<field name="state" icon="fa-filter" enable_counters="1"/> <field name="state" icon="fa-filter" enable_counters="1"/>
<field name="delivery_status" icon="fa-filter" enable_counters="1"/> <field name="delivery_status" icon="fa-filter" enable_counters="1"/>
<field name="production_type" icon="fa-filter" enable_counters="1"/>
</searchpanel> </searchpanel>
</xpath> </xpath>
<filter name='todo' position="replace"/> <filter name='todo' position="replace"/>
@@ -732,5 +732,19 @@
<!-- parent="mrp.menu_mrp_manufacturing"--> <!-- parent="mrp.menu_mrp_manufacturing"-->
<!-- sequence="1"/>--> <!-- sequence="1"/>-->
<menuitem id="mrp.menu_mrp_production_action"
name="制造订单"
parent="mrp.menu_mrp_manufacturing"
action="mrp.mrp_production_action"
groups="sf_base.group_plan_dispatch,sf_base.group_sf_mrp_manager"
sequence="1"/>
<menuitem id="stock_picking_type_menu"
name="驾驶舱"
parent="stock.menu_stock_root"
action="stock.stock_picking_type_action"
groups="sf_base.group_sf_stock_user"
sequence="0"/>
</data> </data>
</odoo> </odoo>

View File

@@ -0,0 +1,18 @@
<odoo>
<data>
<record id="mrp_production_workorder_tree_editable_view_inherit" model="ir.ui.view">
<field name="name">>mrp.workorder.tree.editable.inherit</field>
<field name="model">mrp.workorder</field>
<field name="inherit_id" ref="mrp.mrp_production_workorder_tree_editable_view"/>
<field name="arch" type="xml">
<xpath expr="//tree/field[1]" position="before">
<header>
<button string="重新安排" name="%(sf_manufacturing.mrp_workorder_batch_replan_wizard)d" type="action"
class="treeHeaderBtn"
invisible="context.get('workorder_type') not in ('工件装夹中心','1#自动生产线','工件拆卸中心')"/>
</header>
</xpath>
</field>
</record>
</data>
</odoo>

View File

@@ -29,9 +29,12 @@
</field> </field>
<field name="product_id" position="after"> <field name="product_id" position="after">
<field name="equipment_id" optional="hide"/> <field name="equipment_id" optional="hide"/>
<field name="part_name" optional="hide"/>
<field name="part_number" optional="show"/>
</field> </field>
<xpath expr="//field[@name='qty_remaining']" position="after"> <xpath expr="//field[@name='qty_remaining']" position="after">
<field name="manual_quotation" optional="show"/> <field name="manual_quotation" optional="show"/>
<field name="tag_type" optional="show"/>
<field name="construction_period_status" optional="show" widget="badge" <field name="construction_period_status" optional="show" widget="badge"
decoration-success="construction_period_status == '正常'" decoration-success="construction_period_status == '正常'"
decoration-warning="construction_period_status == '预警'" decoration-warning="construction_period_status == '预警'"
@@ -52,10 +55,7 @@
<!-- 'cancel')), ('working_state', '=', 'blocked'), ('state', 'in', ('done', 'cancel')),--> <!-- 'cancel')), ('working_state', '=', 'blocked'), ('state', 'in', ('done', 'cancel')),-->
<!-- ('is_user_working', '!=', False),("user_permissions","=",False),("name","=","CNC加工")]}--> <!-- ('is_user_working', '!=', False),("user_permissions","=",False),("name","=","CNC加工")]}-->
<!-- </attribute>--> <!-- </attribute>-->
<attribute name="attrs">{'invisible': ['|', '|', '|','|','|', ('production_state','in', ('draft', <attribute name="attrs">{'invisible': [('state', '!=', 'ready')]}
'done',
'cancel')), ('working_state', '=', 'blocked'), ('state', 'in', ('done', 'cancel')),
('is_user_working', '!=', False),("user_permissions","=",False),("name","in",("CNC加工","解除装夹"))]}
</attribute> </attribute>
</xpath> </xpath>
<xpath expr="//button[@name='%(mrp.act_mrp_block_workcenter_wo)d']" position="attributes"> <xpath expr="//button[@name='%(mrp.act_mrp_block_workcenter_wo)d']" position="attributes">
@@ -103,8 +103,7 @@
<!-- <field name="target">fullscreen</field>--> <!-- <field name="target">fullscreen</field>-->
<field name="target">current</field> <field name="target">current</field>
<field name="domain">[('state', '!=', 'cancel'),('schedule_state', '=', '已排')]</field> <field name="domain">[('state', '!=', 'cancel'),('schedule_state', '=', '已排')]</field>
<field name="context">{'search_default_product': 1, 'search_default_workcenter_id': <field name="context">{'search_default_product': 1, 'search_default_workcenter_id': active_id}
active_id,'search_default_filter_order_warning':1,'search_default_filter_order_overdue':1,'search_default_filter_order_normal':1}
</field> </field>
<field name="help" type="html"> <field name="help" type="html">
<p class="o_view_nocontent_workorder"> <p class="o_view_nocontent_workorder">
@@ -138,7 +137,7 @@
<button type="object" name="action_view_surface_technics_purchase" class="oe_stat_button" <button type="object" name="action_view_surface_technics_purchase" class="oe_stat_button"
icon="fa-credit-card" icon="fa-credit-card"
groups="base.group_user,sf_base.group_sf_order_user" groups="base.group_user,sf_base.group_sf_order_user"
attrs="{'invisible': [('surface_technics_purchase_count', '=', 0),('routing_type', '!=', '表面工艺')]}"> attrs="{'invisible': [('surface_technics_purchase_count', '=', 0)]}">
<div class="o_field_widget o_stat_info"> <div class="o_field_widget o_stat_info">
<span class="o_stat_value"> <span class="o_stat_value">
<field name="surface_technics_purchase_count"/> <field name="surface_technics_purchase_count"/>
@@ -174,9 +173,7 @@
<!-- <button name="button_start" type="object" string="开始" class="btn-success" confirm="是否确认开始"--> <!-- <button name="button_start" type="object" string="开始" class="btn-success" confirm="是否确认开始"-->
<!-- attrs="{'invisible': ['|', '|', '|', ('production_state','in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('state', 'in', ('done', 'cancel','to be detected')), ('is_user_working', '!=', False)]}"/>--> <!-- attrs="{'invisible': ['|', '|', '|', ('production_state','in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('state', 'in', ('done', 'cancel','to be detected')), ('is_user_working', '!=', False)]}"/>-->
<button name="button_start" type="object" string="开始" class="btn-success" confirm="是否确认开始" <button name="button_start" type="object" string="开始" class="btn-success" confirm="是否确认开始"
attrs="{'invisible': ['|', '|', '|', '|', '|', ('routing_type', '=', '装夹预调'), ('routing_type', '=', '解除装夹'), ('production_state','in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('state', 'in', ('done', 'cancel','to be detected')), ('is_user_working', '!=', False)]}"/> attrs="{'invisible': [('state', '!=', 'ready')]}"/>
<button name="button_start" type="object" string="开始" class="btn-success"
attrs="{'invisible': ['|', '|', '|', '|', ('routing_type', '!=', '装夹预调'), ('production_state','in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('state', 'in', ('done', 'cancel','to be detected')), ('is_user_working', '!=', False)]}"/>
<button name="button_pending" type="object" string="暂停" class="btn-warning" <button name="button_pending" type="object" string="暂停" class="btn-warning"
attrs="{'invisible': ['|', '|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('is_user_working', '=', False)]}"/> attrs="{'invisible': ['|', '|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('is_user_working', '=', False)]}"/>
<button name="button_finish" type="object" string="完成" class="btn-success" confirm="是否确认完工" <button name="button_finish" type="object" string="完成" class="btn-success" confirm="是否确认完工"
@@ -251,7 +248,7 @@
decoration-danger="tag_type == '重新加工'"/> decoration-danger="tag_type == '重新加工'"/>
<field name="is_test_env" invisible="1"/> <field name="is_test_env" invisible="1"/>
<field name="rfid_code" force_save="1" readonly="1" cache="True" <field name="rfid_code" force_save="1" readonly="1" cache="True"
attrs="{'invisible': [('rfid_code_old', '!=', False)]}" /> attrs="{'invisible': [('rfid_code_old', '!=', False)]}" widget="qrcode_widget"/>
<field name="rfid_code" string="RFID码(手动输入框)" force_save="1" readonly="0" cache="True" <field name="rfid_code" string="RFID码(手动输入框)" force_save="1" readonly="0" cache="True"
attrs="{'invisible': ['|',('rfid_code_old', '!=', False), ('is_test_env', '=', False)]}"/> attrs="{'invisible': ['|',('rfid_code_old', '!=', False), ('is_test_env', '=', False)]}"/>
<field name="rfid_code_old" readonly="1" attrs="{'invisible': [('rfid_code_old', '=', False)]}"/> <field name="rfid_code_old" readonly="1" attrs="{'invisible': [('rfid_code_old', '=', False)]}"/>

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<data>
<record model="ir.ui.view" id="view_purchase_order_line_form_inherit_sf1">
<field name="name">purchase.order.form.inherit.sf</field>
<field name="model">purchase.order</field>
<field name="inherit_id" ref="purchase.purchase_order_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='order_line']/tree/field[@name='name']" position="after">
<field name="related_product" optional="show"/>
<field name="part_number" optional="show"/>
</xpath>
<xpath expr="//sheet//div[@class='oe_button_box']" position="inside">
<button class="oe_stat_button" name="action_view_production" type="object" icon="fa-wrench"
attrs="{'invisible': [('production_count', '=', 0)]}"
>
<div class="o_field_widget o_stat_info">
<span class="o_stat_value">
<field name="production_count"/>
</span>
<span class="o_stat_text">制造订单</span>
</div>
</button>
</xpath>
<!-- 添加销售订单号字段-->
<xpath expr="//sheet/group/group[2]/div[@name='date_approve']" position="after">
<field name="origin_sale_id" readonly="1" string="参考销售订单"
attrs="{'invisible': [('origin_sale_id' , '=', False)]}"/>
<field name="origin_sale_ids" readonly="1" string="参考销售订单" widget="many2many_tags"
attrs="{'invisible': [('origin_sale_ids' , '=', [])]}"/>
</xpath>
</field>
</record>
</data>
</odoo>

View File

@@ -1,17 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<record id="view_order_form_inherit_sf" model="ir.ui.view">
<field name="name">view.sale.order.form.inherit.sf</field>
<field name="inherit_id" ref="sale_stock.view_order_form_inherit_sale_stock_qty"/>
<field name="model">sale.order</field>
<field name="arch" type="xml">
<xpath expr="//page/field[@name='order_line']/form/group/group/div[@name='ordered_qty']/widget[@name='qty_at_date_widget']" position="replace">
</xpath>
<xpath expr="//page/field[@name='order_line']/tree/widget[@name='qty_at_date_widget']" position="replace">
</xpath>
</field>
</record>
<record id="view_order_form_inherit_supply_method" model="ir.ui.view"> <record id="view_order_form_inherit_supply_method" model="ir.ui.view">
<field name="name">view.sale.order.form.inherit.supply.method</field> <field name="name">view.sale.order.form.inherit.supply.method</field>
<field name="inherit_id" ref="sf_sale.view_sale_order_form_inherit_sf"/> <field name="inherit_id" ref="sf_sale.view_sale_order_form_inherit_sf"/>
@@ -25,11 +13,15 @@
<button name="action_confirm" string="供货方式确认" type="object" attrs="{'invisible': [('state', '!=', 'supply method')]}" confirm="确认供货方式"/> <button name="action_confirm" string="供货方式确认" type="object" attrs="{'invisible': [('state', '!=', 'supply method')]}" confirm="确认供货方式"/>
</xpath> </xpath>
<xpath expr="//header/field[@name='state']" position="attributes"> <xpath expr="//header/field[@name='state']" position="attributes">
<attribute name="statusbar_visible">draft,sent,supply method,sale</attribute> <attribute name="statusbar_visible">supply method,sale,processing,physical_distribution,delivered</attribute>
</xpath> </xpath>
<xpath expr="//page/field[@name='order_line']/tree/field[@name='remark']" position="before"> <xpath expr="//page/field[@name='order_line']/tree/field[@name='remark']" position="before">
<field name="supply_method" attrs="{'invisible': [('state', '=', 'draft')], 'required': [('state', '=', 'supply method')]}" /> <field name="supply_method" attrs="{'invisible': [('state', '=', 'draft')], 'required': [('state', '=', 'supply method')]}" />
</xpath> </xpath>
<xpath expr="//field[@name='order_line']/tree/field[@name='model_glb_file']" position="before">
<field name="part_number" optional="show"/>
</xpath>
<xpath expr="//header/button[@name='action_cancel']" position="attributes"> <xpath expr="//header/button[@name='action_cancel']" position="attributes">
<attribute name="attrs">{'invisible': [('state', '!=', 'draft')]}</attribute> <attribute name="attrs">{'invisible': [('state', '!=', 'draft')]}</attribute>
</xpath> </xpath>
@@ -102,7 +94,5 @@
<record id="sale.res_partner_menu" model="ir.ui.menu"> <record id="sale.res_partner_menu" model="ir.ui.menu">
<field name="groups_id" eval="[(4, ref('sf_base.group_production_engineer'))]"/> <field name="groups_id" eval="[(4, ref('sf_base.group_production_engineer'))]"/>
</record> </record>
</odoo> </odoo>

View File

@@ -17,6 +17,12 @@
<field name="model">stock.picking</field> <field name="model">stock.picking</field>
<field name="inherit_id" ref="stock.view_picking_form"/> <field name="inherit_id" ref="stock.view_picking_form"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//field[@name='backorder_id']" position="after">
<field name="retrospect_ref"/>
</xpath>
<xpath expr="//field[@name='origin']" position="after">
<field name="sale_order_id"/>
</xpath>
<xpath expr="//field[@name='user_id']" position="after"> <xpath expr="//field[@name='user_id']" position="after">
<field name="picking_type_sequence_code" invisible="1"/> <field name="picking_type_sequence_code" invisible="1"/>
<field name="retrospect_ref" <field name="retrospect_ref"
@@ -26,6 +32,10 @@
attrs="{'invisible':[('picking_type_sequence_code','!=','DL')]}"/> attrs="{'invisible':[('picking_type_sequence_code','!=','DL')]}"/>
<field name="address_of_delivery" attrs="{'invisible':[('picking_type_sequence_code','!=','DL')]}"/> <field name="address_of_delivery" attrs="{'invisible':[('picking_type_sequence_code','!=','DL')]}"/>
</xpath> </xpath>
<xpath expr="//field[@name='product_id']" position="after">
<field name="part_number" optional="show"/>
<field name="part_name" optional="show"/>
</xpath>
</field> </field>
</record> </record>
@@ -34,6 +44,9 @@
<field name="model">stock.picking</field> <field name="model">stock.picking</field>
<field name="inherit_id" ref="stock.vpicktree"/> <field name="inherit_id" ref="stock.vpicktree"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//field[@name='origin']" position="before">
<field name="sale_order_id" string="销售单号"/>
</xpath>
<xpath expr="//field[@name='origin']" position="after"> <xpath expr="//field[@name='origin']" position="after">
<field name="retrospect_ref"/> <field name="retrospect_ref"/>
</xpath> </xpath>
@@ -45,11 +58,21 @@
<field name="model">stock.picking</field> <field name="model">stock.picking</field>
<field name="inherit_id" ref="stock.view_picking_internal_search"/> <field name="inherit_id" ref="stock.view_picking_internal_search"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//field[@name='name']" position="replace">
<field name="name"/>
<field name="retrospect_ref"/>
<field name="sale_order_id" string="销售单号"/>
</xpath>
<xpath expr="//filter[@name='picking_type']" position="after"> <xpath expr="//filter[@name='picking_type']" position="after">
<filter string="追溯参考" name="retrospect_ref" domain="[]" <filter string="追溯参考" name="retrospect" domain="[]"
context="{'group_by': 'retrospect_ref'}"/> context="{'group_by': 'retrospect_ref'}"/>
</xpath> </xpath>
</field> </field>
</record> </record>
<record id="stock.action_picking_tree_all" model="ir.actions.act_window">
<field name="view_ids" eval="[(5, 0, 0),
(0, 0, {'view_mode': 'tree', 'view_id': ref('stock.vpicktree')})]"/>
</record>
</data> </data>
</odoo> </odoo>

View File

@@ -3,3 +3,4 @@ from . import rework_wizard
from . import production_wizard from . import production_wizard
from . import production_technology_wizard from . import production_technology_wizard
from . import production_technology_re_adjust_wizard from . import production_technology_re_adjust_wizard
from . import mrp_workorder_batch_replan_wizard

View File

@@ -0,0 +1,70 @@
# -*- coding: utf-8 -*-
import logging
from datetime import datetime, timedelta
from odoo import models, api, fields, _
class MrpWorkorderBatchReplanWizard(models.TransientModel):
_name = 'mrp.workorder.batch.replan.wizard'
_description = '制造订单批量重新安排向导'
def _get_date_planned_start(self):
planned_start_date = datetime.now() + timedelta(hours=2)
logging.info('计划开始加工时间: %s', planned_start_date)
return planned_start_date
def _get_default_workorder_count(self):
active_ids = self.env.context.get('active_ids', [])
return len(active_ids)
def _get_default_workorder_type(self):
active_ids = self.env.context.get('active_ids', [])
if active_ids:
workorders = self.env['mrp.workorder'].browse(active_ids)
if workorders:
routing_type = set(workorders.mapped('routing_type'))
return '/'.join(sorted(routing_type)) if routing_type else None
return None
workorder_type = fields.Char(string='工单类型', default=_get_default_workorder_type, readonly=True)
workorder_count = fields.Integer(string='工单数量',
default=_get_default_workorder_count,
readonly=True)
workorder_id = fields.Many2many('mrp.workorder', string=u'工单')
def confirm(self):
routing_type = set(self.workorder_id.mapped('routing_type'))
if len(routing_type) > 1:
raise models.ValidationError("批量重新安排工单类型必须一致。")
show_json_popover = self.workorder_id.mapped('show_json_popover')
if any(not value for value in show_json_popover):
raise models.ValidationError("所选工单必须都为逾期状态")
failed_workorders = {}
for workorder_info in self.workorder_id:
try:
workorder_info.action_replan()
except Exception as e:
reason = str(e)
if reason in failed_workorders:
failed_workorders[reason].append(
workorder_info.production_id.name)
else:
failed_workorders[reason] = [workorder_info.production_id.name]
if failed_workorders:
error_messages = "\n".join(
[f"制造订单: {', '.join(workorder_names)}, 原因: {reason}" for reason, workorder_names in
failed_workorders.items()])
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'message': f"以下工单重新安排失败:\n{error_messages}",
'sticky': False,
'color': 'red',
'next': {
'type': 'ir.actions.act_window_close'
}
},
}

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="mrp_workorder_batch_replan_wizard_form" model="ir.ui.view">
<field name="name">mrp.workorder.batch.replan.wizard.form.view</field>
<field name="model">mrp.workorder.batch.replan.wizard</field>
<field name="arch" type="xml">
<form>
<group>
<field name="workorder_type"/>
<field name="workorder_count"/>
</group>
<footer>
<button string="确认" name="confirm" type="object" class="oe_highlight"/>
<button string="取消" class="btn-primary" special="cancel"/>
</footer>
</form>
</field>
</record>
<record id="mrp_workorder_batch_replan_wizard" model="ir.actions.act_window">
<field name="name">重新安排工单</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">mrp.workorder.batch.replan.wizard</field>
<field name="view_mode">form</field>
<field name="view_id" ref="mrp_workorder_batch_replan_wizard_form"/>
<field name="target">new</field>
<field name="context">{'default_workorder_id': active_ids}</field>
</record>
</odoo>

View File

@@ -10,11 +10,11 @@ class ProductionTechnologyReAdjustWizard(models.TransientModel):
production_id = fields.Many2one('mrp.production', string='制造订单号') production_id = fields.Many2one('mrp.production', string='制造订单号')
origin = fields.Char(string='源单据') origin = fields.Char(string='源单据')
is_technology_re_adjust = fields.Boolean(default=False) is_technology_re_adjust = fields.Boolean(default=True)
def confirm(self): def confirm(self):
if self.is_technology_re_adjust is True: if self.is_technology_re_adjust is True:
domain = [('origin', '=', self.origin), ('state', '=', 'technology_to_confirmed'), domain = [('origin', '=', self.origin), ('state', '=', 'confirmed'),
('product_id', '=', self.production_id.product_id.id)] ('product_id', '=', self.production_id.product_id.id)]
else: else:
domain = [('id', '=', self.production_id.id)] domain = [('id', '=', self.production_id.id)]
@@ -24,67 +24,24 @@ class ProductionTechnologyReAdjustWizard(models.TransientModel):
for production_item in productions: for production_item in productions:
# 该制造订单的其他同一销售订单的制造订单的工艺设计处理 # 该制造订单的其他同一销售订单的制造订单的工艺设计处理
if production_item != self.production_id: if production_item != self.production_id:
for td_other in production_item.technology_design_ids: self.env['sf.technology.design'].sudo().unified_procedure_multiple_work_orders(technology_designs, production_item)
if td_other.is_auto is False:
td_del = technology_designs.filtered(lambda tdo: tdo.route_id.id == td_other.route_id.id)
if not td_del or td_del.active is False:
td_other.write({'active': False})
for td_main in technology_designs:
route_other = production_item.technology_design_ids.filtered(
lambda td: td.route_id.id == td_main.route_id.id)
if not route_other and td_main.active is True:
production_item.write({'technology_design_ids': [(0, 0, {
'route_id': td_main.route_id.id,
'process_parameters_id': False if td_main.process_parameters_id is False else
self.env[
'sf.production.process.parameter'].search(
[('id', '=', td_main.process_parameters_id.id)]).id,
'sequence': td_main.sequence,
'is_auto': td_main.is_auto})]})
else:
for ro in route_other:
domain = [('production_id', '=', self.production_id.id),
('active', 'in', [True, False]),
('route_id', '=', ro.route_id.id)]
if ro.route_id.routing_type == '表面工艺':
domain += [('process_parameters_id', '=', ro.process_parameters_id.id)]
elif ro.route_id.routing_tag == 'special' and ro.is_auto is False:
display_name = ro.route_id.display_name
domain += [('name', 'ilike', display_name)]
elif ro.panel is not False:
domain += [('panel', '=', ro.panel)]
td_upd = self.env['sf.technology.design'].sudo().search(domain)
if td_upd:
ro.write({'sequence': td_upd.sequence, 'active': td_upd.active})
special_design = self.env['sf.technology.design'].sudo().search( special_design = self.env['sf.technology.design'].sudo().search(
[('routing_tag', '=', 'special'), ('production_id', '=', production_item.id), [('routing_tag', '=', 'special'), ('production_id', '=', production_item.id),
('is_auto', '=', False), ('active', 'in', [True, False])]) ('is_auto', '=', False), ('active', 'in', [True, False])])
for special in special_design: for special in special_design:
workorders_values = [] workorders_values = []
if special.active is False: if special.active is False:
is_cancel = False
# 工单采购单外协出入库单皆需取消 # 工单采购单外协出入库单皆需取消
domain = [('production_id', '=', special.production_id.id)] domain = [('production_id', '=', special.production_id.id)]
if special.process_parameters_id: if special.process_parameters_id:
domain += [('surface_technics_parameters_id', '=', special.process_parameters_id.id)] domain += [('surface_technics_parameters_id', '=', special.process_parameters_id.id), ('state', '!=', 'cancel')]
else: else:
domain += [('name', '=', special.route_id.name)] domain += [('technology_design_id', '=', special.id), ('state', '!=', 'cancel')]
workorder = self.env['mrp.workorder'].search(domain) workorder = self.env['mrp.workorder'].search(domain)
if workorder.state != 'cancel':
workorder.write({'state': 'cancel'})
workorder.picking_ids.write({'state': 'cancel'})
workorder.picking_ids.move_ids.write({'state': 'cancel'})
purchase_order = self.env['purchase.order'].search(
[('origin', '=', workorder.production_id.origin)])
for line in purchase_order.order_line:
if line.product_id.server_product_process_parameters_id == workorder.surface_technics_parameters_id:
purchase_order.write({'state': 'cancel'})
else: else:
if special.route_id.routing_type == '表面工艺':
display_name = special.process_parameters_id.display_name
else:
display_name = special.route_id.display_name
workorder = self.env['mrp.workorder'].search( workorder = self.env['mrp.workorder'].search(
[('name', '=', display_name), ('production_id', '=', special.production_id.id)]) [('technology_design_id', '=', special.id), ('production_id', '=', special.production_id.id), ('state', '!=', 'cancel')])
if not workorder: if not workorder:
if special.route_id.routing_type == '表面工艺': if special.route_id.routing_type == '表面工艺':
product_production_process = self.env['product.template'].search( product_production_process = self.env['product.template'].search(
@@ -99,19 +56,24 @@ class ProductionTechnologyReAdjustWizard(models.TransientModel):
self.env['mrp.workorder'].json_workorder_str(special.production_id, special)) self.env['mrp.workorder'].json_workorder_str(special.production_id, special))
special.production_id.write({'workorder_ids': workorders_values}) special.production_id.write({'workorder_ids': workorders_values})
else: else:
logging.info(workorder.blocked_by_workorder_ids)
if len(workorder.blocked_by_workorder_ids) > 1: if len(workorder.blocked_by_workorder_ids) > 1:
if workorder.sequence == 1: if workorder.sequence == 1:
workorder.blocked_by_workorder_ids = None workorder.blocked_by_workorder_ids = None
else: else:
workorder.blocked_by_workorder_ids = blocked_by_workorder_ids[0] if workorder.blocked_by_workorder_ids:
workorder.blocked_by_workorder_ids = workorder.blocked_by_workorder_ids[0]
productions._reset_work_order_sequence() productions._reset_work_order_sequence()
if self.production_id.product_id.categ_id.type == '成品': # 退回时不对外协出入库单和采购单做处理
productions._reset_subcontract_pick_purchase() # if self.production_id.product_id.categ_id.type == '成品':
productions.get_subcontract_pick_purchase() # productions._reset_subcontract_pick_purchase()
# productions.get_subcontract_pick_purchase()
productions.is_adjust = True productions.is_adjust = True
for item in productions: for item in productions:
workorders = item.workorder_ids.filtered(lambda wo: wo.state not in ('cancel')).sorted( workorders = item.workorder_ids.filtered(lambda wo: wo.state not in ('cancel')).sorted(
key=lambda a: a.sequence) key=lambda a: a.sequence)
if workorders[0].state in ['pending']: if workorders[0].state in ['pending']:
if workorder[0].production_id.product_id.categ_id.type == '成品' and item.programming_state != '已编程': if workorders[
0].production_id.product_id.categ_id.type == '成品' and item.programming_state != '已编程':
workorders[0].state = 'waiting' workorders[0].state = 'waiting'

View File

@@ -21,6 +21,26 @@
</field> </field>
</record> </record>
<record model="ir.ui.view" id="sf_production_technology_re_adjust_wizard_confirm_form_view">
<field name="name">sf.production.technology.re_adjust.wizard.form.view</field>
<field name="model">sf.production.technology.re_adjust.wizard</field>
<field name="arch" type="xml">
<form>
<sheet>
<field name="production_id" invisible="1"/>
<field name="origin" invisible="1"/>
<div>
是否确认退回调整
</div>
<footer>
<button string="确认" name="confirm" type="object" class="oe_highlight"/>
<button string="取消" class="btn btn-secondary" special="cancel"/>
</footer>
</sheet>
</form>
</field>
</record>
<record id="action_sf_production_technology_re_adjust_wizard" model="ir.actions.act_window"> <record id="action_sf_production_technology_re_adjust_wizard" model="ir.actions.act_window">
<field name="name">工艺退回调整</field> <field name="name">工艺退回调整</field>
<field name="res_model">sf.production.technology.re_adjust.wizard</field> <field name="res_model">sf.production.technology.re_adjust.wizard</field>

View File

@@ -11,51 +11,76 @@ class ProductionTechnologyWizard(models.TransientModel):
production_id = fields.Many2one('mrp.production', string='制造订单号') production_id = fields.Many2one('mrp.production', string='制造订单号')
origin = fields.Char(string='源单据') origin = fields.Char(string='源单据')
is_technology_confirm = fields.Boolean(default=False) is_technology_confirm = fields.Boolean(default=True)
def confirm(self): def confirm(self):
if self.is_technology_confirm is True and self.production_id.product_id.categ_id.type == '成品': if self.is_technology_confirm is True and self.production_id.product_id.categ_id.type in ['成品', '坯料']:
domain = [('origin', '=', self.origin), ('state', '=', 'technology_to_confirmed'), domain = [('origin', '=', self.origin), ('state', '=', 'technology_to_confirmed'),
('product_id', '=', self.production_id.product_id.id)] ('product_id', '=', self.production_id.product_id.id)]
else: else:
domain = [('id', '=', self.production_id.id)] domain = [('id', '=', self.production_id.id)]
technology_designs = self.production_id.technology_design_ids technology_designs = self.env['sf.technology.design'].sudo().search(
[('production_id', '=', self.production_id.id), ('active', 'in', [True, False])])
# technology_designs = self.production_id.technology_design_ids
productions = self.env['mrp.production'].search(domain) productions = self.env['mrp.production'].search(domain)
for production in productions: for production in productions:
if production != self.production_id: if production != self.production_id:
for td_other in production.technology_design_ids: self.env['sf.technology.design'].sudo().unified_procedure_multiple_work_orders(technology_designs,
if td_other.is_auto is False: production)
td_del = technology_designs.filtered(lambda tdo: tdo.route_id.id == td_other.route_id.id) # 特殊表面工艺
if not td_del or td_del.active is False: special_design = self.env['sf.technology.design'].sudo().search(
td_other.write({'active': False}) [('routing_tag', '=', 'special'), ('production_id', '=', production.id),
for td_main in technology_designs: ('is_auto', '=', False), ('active', 'in', [True, False])])
route_other = production.technology_design_ids.filtered( for special in special_design:
lambda td: td.route_id.id == td_main.route_id.id) workorders_values = []
if not route_other and td_main.active is True: if special.active is False:
production.write({'technology_design_ids': [(0, 0, { # is_cancel = False
'route_id': td_main.route_id.id, # 工单采购单外协出入库单皆需取消
'process_parameters_id': False if td_main.process_parameters_id is False else self.env[ domain = [('production_id', '=', special.production_id.id)]
'sf.production.process.parameter'].search( if special.process_parameters_id:
[('id', '=', td_main.process_parameters_id.id)]).id, domain += [('surface_technics_parameters_id', '=', special.process_parameters_id.id), ('state', '!=', 'cancel')]
'sequence': td_main.sequence})]}) else:
domain += [('technology_design_id', '=', special.id), ('state', '!=', 'cancel')]
workorder = self.env['mrp.workorder'].search(domain)
# previous_workorder = self.env['mrp.workorder'].search(
# [('sequence', '=', workorder.sequence - 1), ('routing_type', '=', '表面工艺'),
# ('production_id', '=', workorder.production_id.id)])
# if previous_workorder:
# if previous_workorder.supplier_id != workorder.supplier_id:
# is_cancel = True
# if workorder.state != 'cancel' and is_cancel is True:
workorder.write({'state': 'cancel'})
workorder.picking_ids.write({'state': 'cancel'})
workorder.picking_ids.move_ids.write({'state': 'cancel'})
purchase_order = self.env['purchase.order'].search(
[('origin', '=', workorder.production_id.name), ('purchase_type', '=', 'consignment')])
for line in purchase_order.order_line:
if line.product_id.server_product_process_parameters_id == workorder.surface_technics_parameters_id:
purchase_order.write({'state': 'cancel'})
else:
if special.production_id.workorder_ids:
workorder = self.env['mrp.workorder'].search(
[('technology_design_id', '=', special.id), ('production_id', '=', special.production_id.id), ('state', '!=', 'cancel')])
if not workorder:
if special.route_id.routing_type == '表面工艺':
product_production_process = self.env['product.template'].search(
[('server_product_process_parameters_id', '=', special.process_parameters_id.id)])
workorders_values.append(
self.env[
'mrp.workorder']._json_workorder_surface_process_str(special.production_id, special,
product_production_process.seller_ids[
0].partner_id.id))
else:
workorders_values.append(
self.env['mrp.workorder'].json_workorder_str(special.production_id, special))
special.production_id.write({'workorder_ids': workorders_values})
else: else:
for ro in route_other: if len(workorder.blocked_by_workorder_ids) > 1:
domain = [('production_id', '=', self.production_id.id), if workorder.sequence == 1:
('active', 'in', [True, False]), workorder.blocked_by_workorder_ids = None
('route_id', '=', ro.route_id.id)] else:
if ro.route_id.routing_type == '表面工艺': if workorder.blocked_by_workorder_ids:
domain += [('process_parameters_id', '=', ro.process_parameters_id.id)] workorder.blocked_by_workorder_ids = blocked_by_workorder_ids[0]
elif ro.route_id.routing_tag == 'special' and ro.is_auto is False:
display_name = ro.route_id.display_name
domain += [('name', 'ilike', display_name)]
elif ro.panel is not False:
domain += [('panel', '=', ro.panel)]
td_upd = self.env['sf.technology.design'].sudo().search(domain)
if td_upd:
ro.write({'sequence': td_upd.sequence, 'active': td_upd.active})
# special = production.technology_design_ids.filtered(
# lambda td: td.is_auto is False and td.process_parameters_id is not False)
# # if special:
productions._create_workorder(False) productions._create_workorder(False)
if self.production_id.product_id.categ_id.type == '成品': if self.production_id.product_id.categ_id.type == '成品':
productions.get_subcontract_pick_purchase() productions.get_subcontract_pick_purchase()
@@ -65,4 +90,5 @@ class ProductionTechnologyWizard(models.TransientModel):
key=lambda a: a.sequence) key=lambda a: a.sequence)
if workorder[0].state in ['pending']: if workorder[0].state in ['pending']:
if workorder[0].production_id.product_id.categ_id.type == '成品' and item.programming_state != '已编程': if workorder[0].production_id.product_id.categ_id.type == '成品' and item.programming_state != '已编程':
workorders[0].state = 'waiting' workorder[0].state = 'waiting'
return productions

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<odoo> <odoo>
<record model="ir.ui.view" id="sf_production_technology_wizard_form_view"> <record model="ir.ui.view" id="sf_production_technology_wizard_form_view">
<field name="name">sf.production.technology.wizard.form.view</field> <field name="name">sf.production.technology.wizard.form.view</field>
<field name="model">sf.production.technology.wizard</field> <field name="model">sf.production.technology.wizard</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
@@ -13,7 +13,28 @@
对当前制造订单,同一销售订单相同产品所生成的制造订单统一进行工艺调整与确认 对当前制造订单,同一销售订单相同产品所生成的制造订单统一进行工艺调整与确认
</div> </div>
<footer> <footer>
<button string="确认" name="confirm" type="object" class="oe_highlight" confirm="是否确认工艺调整"/> <button string="确认" name="confirm" type="object" class="oe_highlight"
confirm="是否确认工艺调整"/>
<button string="取消" class="btn btn-secondary" special="cancel"/>
</footer>
</sheet>
</form>
</field>
</record>
<record model="ir.ui.view" id="sf_production_technology_wizard_confirm_form_view">
<field name="name">sf.production.technology.wizard.form.view</field>
<field name="model">sf.production.technology.wizard</field>
<field name="arch" type="xml">
<form>
<sheet>
<field name="production_id" invisible="1"/>
<field name="origin" invisible="1"/>
<div>
是否确认工艺调整
</div>
<footer>
<button string="确认" name="confirm" type="object" class="oe_highlight"/>
<button string="取消" class="btn btn-secondary" special="cancel"/> <button string="取消" class="btn btn-secondary" special="cancel"/>
</footer> </footer>
</sheet> </sheet>

View File

@@ -4,6 +4,7 @@ import logging
from odoo.exceptions import UserError, ValidationError from odoo.exceptions import UserError, ValidationError
from datetime import datetime from datetime import datetime
from odoo import models, api, fields, _ from odoo import models, api, fields, _
from odoo.tools import groupby
class ReworkWizard(models.TransientModel): class ReworkWizard(models.TransientModel):
@@ -15,6 +16,7 @@ class ReworkWizard(models.TransientModel):
production_id = fields.Many2one('mrp.production', string='制造订单号') production_id = fields.Many2one('mrp.production', string='制造订单号')
workorder_ids = fields.Many2many('mrp.workorder', 'rework_wizard_to_work_order', string='所有工单', workorder_ids = fields.Many2many('mrp.workorder', 'rework_wizard_to_work_order', string='所有工单',
domain="[('production_id', '=', production_id),('state','=','done')]") domain="[('production_id', '=', production_id),('state','=','done')]")
hidden_workorder_ids = fields.Char('')
rework_reason = fields.Selection( rework_reason = fields.Selection(
[("programming", "编程"), ("cutter", "刀具"), ("clamping", "装夹"), [("programming", "编程"), ("cutter", "刀具"), ("clamping", "装夹"),
("operate computer", "操机"), ("operate computer", "操机"),
@@ -36,6 +38,61 @@ class ReworkWizard(models.TransientModel):
tool_state = fields.Selection(string='功能刀具状态', related='production_id.tool_state') tool_state = fields.Selection(string='功能刀具状态', related='production_id.tool_state')
@api.onchange('hidden_workorder_ids')
def _onchange_hidden_workorder_ids(self):
for item in self:
if item.hidden_workorder_ids not in ['', None, False]:
hidden_workorder_list = item.hidden_workorder_ids.split(',')
# 获取加工面对应需要返工的工单
rw_ids = item.workorder_ids.filtered(
lambda w: str(w.ids[0]) in hidden_workorder_list and w.processing_panel not in ['', None, False])
grouped_rw_ids = {key: list(group) for key, group in groupby(rw_ids, key=lambda w: w.processing_panel)}
for panel, panel_rw_ids in grouped_rw_ids.items():
work_ids = item.workorder_ids.filtered(lambda w: w.state == 'done' and w.processing_panel == panel)
if len(work_ids) == 3 and len(panel_rw_ids) != 3:
for work_id in work_ids:
if work_id not in panel_rw_ids:
hidden_workorder_list.append(str(work_id.ids[0]))
elif len(work_ids) == 2 and len(panel_rw_ids) < 2 and panel_rw_ids[0].name == 'CNC加工':
if rw_ids.filtered(lambda w: (w.sequence < panel_rw_ids[0].sequence
and w.processing_panel != panel_rw_ids[0].processing_panel)):
hidden_workorder_list.append(str(work_ids.filtered(
lambda w: (w.processing_panel == panel_rw_ids[0].processing_panel
and w.name == '装夹预调')).ids[0]))
hidden_workorder_list.sort()
item.hidden_workorder_ids = ','.join(hidden_workorder_list)
def efficacy_rework_wo(self, wk_ids):
"""限制判断 """
# 判断检测结果待处理所对应的工单是否勾选
result_ids = self.production_id.detection_result_ids.filtered(lambda dr: dr.handle_result == '待处理')
work_id_list = []
if result_ids:
work_id_list = [self.workorder_ids.filtered(
lambda wk: (wk.name == result_id.routing_type and wk.processing_panel == result_id.processing_panel
and wk.state == 'done')).id
for result_id in result_ids]
if len(wk_ids.filtered(lambda wk: wk.id in work_id_list)) != len(work_id_list):
raise ValidationError('存在【检测结果】为【待处理】所对应的工单未进行勾选!!!')
# 获取已完成的标准工单
grouped_rw_ids = {key: list(group) for key, group in groupby(wk_ids, key=lambda w: w.processing_panel)}
for panel, panel_rw_ids in grouped_rw_ids.items():
# 1、当制造订单内ZM面的工单都已完成时返工勾选工序时只能勾选上ZM面的所有工序进行返工
work_ids = self.workorder_ids.filtered(lambda w: w.state == 'done' and w.processing_panel == panel)
if len(work_ids) == 3 and len(panel_rw_ids) != 3:
raise ValidationError(
'因为[%s]面的工单已全部完成,如果要对[%s]面的工单进行返工,请勾选这个面的所有工单。' % (panel, panel))
# 2、当FM工单在CNC工单进行选择返工并将已全部完成的ZM面工序全部勾选上时FM工单上所有的已完成的工单装夹预调工单也必须进行勾选
if not wk_ids.filtered(lambda wk: wk.name == '装夹预调' and wk.processing_panel == panel):
if wk_ids.filtered(lambda wk: wk.name == 'CNC加工' and wk.processing_panel == panel):
sequence_max = wk_ids.filtered(
lambda wk: wk.name == 'CNC加工' and wk.processing_panel == panel).sequence
for wk_id in wk_ids.filtered(lambda wk: wk.sequence < sequence_max):
if len(wk_ids.filtered(lambda wk: wk.processing_panel == wk_id.processing_panel)) == 3:
raise ValidationError(
'由于在[%s]面之前存在整个面进行了勾选的情况,所以在勾选了[%s]面的【CNC加工】工单的时请勾选[%s]面的装夹预调工单!' % (
panel, panel, panel))
def confirm(self): def confirm(self):
if self.routing_type in ['装夹预调', 'CNC加工']: if self.routing_type in ['装夹预调', 'CNC加工']:
self.is_clamp_measure = False self.is_clamp_measure = False
@@ -50,22 +107,25 @@ class ReworkWizard(models.TransientModel):
'test_report': self.workorder_id.detection_report})]}) 'test_report': self.workorder_id.detection_report})]})
self.workorder_id.button_finish() self.workorder_id.button_finish()
else: else:
if self.workorder_ids: if self.hidden_workorder_ids:
rework_workorder_ids = self.production_id.workorder_ids.filtered( hidden_workorder_list = self.hidden_workorder_ids.split(',')
lambda ap: ap.id in self.workorder_ids.ids) rework_workorder_ids = self.workorder_ids.filtered(lambda w: str(w.id) in hidden_workorder_list)
clamp_workorder_ids = None # 调用效验方法
if rework_workorder_ids: self.efficacy_rework_wo(rework_workorder_ids)
# 限制 else:
# 1、单独返工CNC工单则不解绑托盘RFID如单独返工装夹预调工单则自动解绑托盘RFID raise ValidationError('请选择返工工单!!!')
# 2、返工CNC工单和装夹预调工单则自动解绑RFID if rework_workorder_ids:
clamp_workorder_ids = rework_workorder_ids.filtered(lambda rp: rp.routing_type == '装夹预调') # 限制
if clamp_workorder_ids: # 1、单独返工CNC工单则不解绑托盘RFID如单独返工装夹预调工单则自动解绑托盘RFID
for clamp_workorder_id in clamp_workorder_ids: # 2、返工CNC工单和装夹预调工单则自动解绑RFID
self.production_id.workorder_ids.filtered( clamp_workorder_ids = rework_workorder_ids.filtered(lambda rp: rp.routing_type == '装夹预调')
lambda wk: wk.processing_panel == clamp_workorder_id.processing_panel).write( if clamp_workorder_ids:
{'rfid_code': False}) for clamp_workorder_id in clamp_workorder_ids:
# 返工工单状态设置为【返工】 self.production_id.workorder_ids.filtered(
rework_workorder_ids.write({'state': 'rework'}) lambda wk: wk.processing_panel == clamp_workorder_id.processing_panel).write(
{'rfid_code': None})
# 返工工单状态设置为【返工】
rework_workorder_ids.write({'state': 'rework'})
# 查询返工工单对应的工艺设计记录,并调用方法拼接数据,用于创建新的工单 # 查询返工工单对应的工艺设计记录,并调用方法拼接数据,用于创建新的工单
workorders_values = [] workorders_values = []
for work in rework_workorder_ids: for work in rework_workorder_ids:
@@ -76,7 +136,7 @@ class ReworkWizard(models.TransientModel):
and item.panel == work.processing_panel)) and item.panel == work.processing_panel))
if route: if route:
work_list = self.env['mrp.workorder'].json_workorder_str(self.production_id, route[0]) work_list = self.env['mrp.workorder'].json_workorder_str(self.production_id, route[0])
work_list[2].update({'tag_type': '重新加工'}) work_list[2].update({'tag_type': '重新加工', 'sequence': 0})
workorders_values.append(work_list) workorders_values.append(work_list)
# 创建新工单,并进行返工配置的相关操作 # 创建新工单,并进行返工配置的相关操作
if workorders_values: if workorders_values:
@@ -86,6 +146,11 @@ class ReworkWizard(models.TransientModel):
new_pre_workorder_ids = self.production_id.workorder_ids.filtered( new_pre_workorder_ids = self.production_id.workorder_ids.filtered(
lambda kw: kw.routing_type == '装夹预调' and kw.sequence == 0) lambda kw: kw.routing_type == '装夹预调' and kw.sequence == 0)
self.production_id._reset_work_order_sequence() self.production_id._reset_work_order_sequence()
# ====新工单绑定rfid===
for new_work_id in new_work_ids:
if new_work_id.routing_type in ['CNC加工', '解除装夹']:
new_work_id.write({'rfid_code': self.production_id.workorder_ids.filtered(
lambda wk: wk.sequence == new_work_id.sequence - 1).rfid_code})
self.production_id.detection_result_ids.filtered( self.production_id.detection_result_ids.filtered(
lambda ap1: ap1.handle_result == '待处理').write({'handle_result': '已处理'}) lambda ap1: ap1.handle_result == '待处理').write({'handle_result': '已处理'})
panels = [] # 返工的加工面 panels = [] # 返工的加工面
@@ -206,11 +271,7 @@ class ReworkWizard(models.TransientModel):
elif self.programming_state in ['待编程', '编程中']: elif self.programming_state in ['待编程', '编程中']:
self.production_id.write( self.production_id.write(
{'programming_state': '编程中', 'work_state': '编程中', 'is_rework': True}) {'programming_state': '编程中', 'work_state': '编程中', 'is_rework': True})
# ==================申请重新编程======================= # =================================================
if self.is_reprogramming is True:
self.production_id.update_programming_state()
self.production_id.write(
{'programming_state': '编程中', 'work_state': '编程中'})
if self.production_id.state == 'progress': if self.production_id.state == 'progress':
self.production_id.write({'programming_state': '已编程', 'work_state': '已编程'}) self.production_id.write({'programming_state': '已编程', 'work_state': '已编程'})
if self.reprogramming_num >= 1 and self.programming_state == '已编程': if self.reprogramming_num >= 1 and self.programming_state == '已编程':
@@ -221,6 +282,13 @@ class ReworkWizard(models.TransientModel):
productions_not_delivered.write( productions_not_delivered.write(
{'state': 'progress', 'programming_state': '已编程', 'work_state': '已编程', {'state': 'progress', 'programming_state': '已编程', 'work_state': '已编程',
'is_rework': False}) 'is_rework': False})
# ==================申请重新编程=======================
if self.is_reprogramming is True:
self.production_id.update_programming_state()
self.production_id.write(
{'programming_state': '编程中', 'work_state': '编程中', 'state': 'progress'})
# ================= 返工完成,制造订单状态置为加工中 ==============
self.production_id.write({'state': 'progress', 'is_rework': False})
@api.onchange('production_id') @api.onchange('production_id')
def onchange_processing_panel_id(self): def onchange_processing_panel_id(self):

View File

@@ -12,9 +12,15 @@
<field name="tool_state" invisible="True"/> <field name="tool_state" invisible="True"/>
<field name="routing_type" invisible="True"/> <field name="routing_type" invisible="True"/>
<field name="processing_panel_id" invisible="1"/> <field name="processing_panel_id" invisible="1"/>
<field name="hidden_workorder_ids" class="css_not_available_msg"/>
<group> <group>
<field name="workorder_ids" string="工序" attrs='{"invisible": [("routing_type","=","装夹预调")]}'> <field name="hidden_workorder_ids" invisible="1"/>
<field options="{'no_create': True,'no_open': True}" readonly="1" name="workorder_ids"
widget="jikimo_subtree_selector_field"
jikimo_selector="True" replace_context="hidden_workorder_ids" string="工序"
attrs='{"invisible": [("routing_type","=","装夹预调")]}'>
<tree create="0" editable='bottom' delete="0"> <tree create="0" editable='bottom' delete="0">
<field name="sequence" readonly="1" string="工序"/>
<field name="processing_panel" readonly="1"/> <field name="processing_panel" readonly="1"/>
<field name="name" readonly="1"/> <field name="name" readonly="1"/>
</tree> </tree>

View File

@@ -207,8 +207,9 @@ class WorkpieceDeliveryWizard(models.TransientModel):
workorder.production_line_id.id != self.production_ids[0].production_line_id.id): workorder.production_line_id.id != self.production_ids[0].production_line_id.id):
raise UserError(f'该rfid对应的制造订单号为{workorder.production_id.name}的目的生产线不一致') raise UserError(f'该rfid对应的制造订单号为{workorder.production_id.name}的目的生产线不一致')
# 调用打印成品条码方法 if workorder.routing_type == '解除装夹':
workorder.print_method() # 调用打印成品条码方法
workorder.print_method()
# 将对象添加到对应的同模型且是多对多类型里 # 将对象添加到对应的同模型且是多对多类型里
self.production_ids |= workorder.production_id self.production_ids |= workorder.production_id

View File

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

View File

@@ -4,10 +4,12 @@ import logging
from odoo import http from odoo import http
from odoo.http import request from odoo.http import request
from odoo.addons.sf_mrs_connect.controllers.controllers import Sf_Mrs_Connect from odoo.addons.sf_mrs_connect.controllers.controllers import Sf_Mrs_Connect
from odoo.addons.sf_bf_connect.controllers.controllers import Sf_Bf_Connect
from odoo.addons.sf_base.commons.common import Common from odoo.addons.sf_base.commons.common import Common
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
class MessageSfMrsConnect(Sf_Mrs_Connect): class MessageSfMrsConnect(Sf_Mrs_Connect):
@http.route('/api/cnc_processing/create', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False, @http.route('/api/cnc_processing/create', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False,
@@ -39,7 +41,8 @@ class MessageSfMrsConnect(Sf_Mrs_Connect):
_logger.info('无效用刀异常消息推送接口:%s' % e) _logger.info('无效用刀异常消息推送接口:%s' % e)
return json.JSONEncoder().encode(res) return json.JSONEncoder().encode(res)
@http.route('/api/maintenance_logs/notify', type='json', auth='public', methods=['GET', 'POST'], csrf=False, cors="*") @http.route('/api/maintenance_logs/notify', type='json', auth='public', methods=['GET', 'POST'], csrf=False,
cors="*")
def maintenance_logs_notify(self, **kw): def maintenance_logs_notify(self, **kw):
res = {'code': 200, 'message': '设备故障日志信息推送成功'} res = {'code': 200, 'message': '设备故障日志信息推送成功'}
datas = request.httprequest.data datas = request.httprequest.data
@@ -51,10 +54,26 @@ class MessageSfMrsConnect(Sf_Mrs_Connect):
try: try:
if not isinstance(log_id, list): if not isinstance(log_id, list):
log_id = [log_id] log_id = [log_id]
maintenance_logs = request.env['sf.maintenance.logs'].sudo().search([('id', 'in', [int(id) for id in log_id])]) maintenance_logs = request.env['sf.maintenance.logs'].sudo().search(
[('id', 'in', [int(id) for id in log_id])])
if maintenance_logs: if maintenance_logs:
maintenance_logs.add_queue('设备故障') maintenance_logs.add_queue('设备故障')
except Exception as e: except Exception as e:
res = {'code': 400, 'message': '设备故障信息推送失败', 'error': str(e)} res = {'code': 400, 'message': '设备故障信息推送失败', 'error': str(e)}
return json.JSONEncoder().encode(res) return json.JSONEncoder().encode(res)
class MessageSfBfConnect(Sf_Bf_Connect):
@http.route('/api/bfm_process_order/list', type='http', auth='sf_token', methods=['GET', 'POST'], csrf=False,
cors="*")
def get_bfm_process_order_list(self, **kw):
res = super(MessageSfBfConnect, self).get_bfm_process_order_list(**kw)
response_data = json.loads(res.data.decode('utf-8'))
if response_data['status'] == 1:
try:
_logger.info('已进入待接单消息推送:%s' % response_data)
sale_order = request.env['sale.order'].sudo().search([('name', '=', response_data['factory_order_no'])])
sale_order.add_queue('待接单')
except Exception as e:
logging.info('add_queue error:%s' % e)
return res

View File

@@ -22,6 +22,15 @@
<field name="model">sale.order</field> <field name="model">sale.order</field>
</record> </record>
<record id="bussiness_supply_method" model="jikimo.message.bussiness.node">
<field name="name">待确认供货方式</field>
<field name="model">sale.order</field>
</record>
<record id="bussiness_technology_to_confirmed" model="jikimo.message.bussiness.node">
<field name="name">待确认加工路线</field>
<field name="model">mrp.production</field>
</record>
<record id="transfer_inventory" model="jikimo.message.bussiness.node"> <record id="transfer_inventory" model="jikimo.message.bussiness.node">
<field name="name">调拨入库</field> <field name="name">调拨入库</field>
@@ -47,7 +56,7 @@
<!--工单--> <!--工单-->
<record id="bussiness_mrp_workorder_remind" model="jikimo.message.bussiness.node"> <record id="bussiness_mrp_workorder_remind" model="jikimo.message.bussiness.node">
<field name="name">工单已下发通知</field> <field name="name">工单已下发通知</field>
<field name="model">mrp.workorder</field> <field name="model">product.product</field>
</record> </record>
<!--发货调拨--> <!--发货调拨-->
<record id="production_completed_warehouse_reminder" model="jikimo.message.bussiness.node"> <record id="production_completed_warehouse_reminder" model="jikimo.message.bussiness.node">
@@ -106,5 +115,45 @@
<field name="name">设备故障</field> <field name="name">设备故障</field>
<field name="model">sf.maintenance.logs</field> <field name="model">sf.maintenance.logs</field>
</record> </record>
<record id="bussiness_state_draft" model="jikimo.message.bussiness.node">
<field name="name">待排程</field>
<field name="model">mrp.production</field>
</record>
<record id="bussiness_outsourcing" model="jikimo.message.bussiness.node">
<field name="name">委外加工采购单提醒</field>
<field name="model">purchase.order</field>
</record>
<record id="bussiness_purchase" model="jikimo.message.bussiness.node">
<field name="name">外购订单采购单提醒</field>
<field name="model">purchase.order</field>
</record>
<record id="bussiness_process_outsourcing" model="jikimo.message.bussiness.node">
<field name="name">工序外协采购单通知</field>
<field name="model">purchase.order</field>
</record>
<record id="bussiness_outsourced_outbound" model="jikimo.message.bussiness.node">
<field name="name">工序外协发料通知</field>
<field name="model">mrp.production</field>
</record>
<record id="bussiness_purchase_order_warning" model="jikimo.message.bussiness.node">
<field name="name">采购订单预警提醒</field>
<field name="model">purchase.order</field>
</record>
<record id="bussiness_purchase_order_overdue" model="jikimo.message.bussiness.node">
<field name="name">采购单已逾期提醒</field>
<field name="model">purchase.order</field>
</record>
<record id="bussiness_quality_check" model="jikimo.message.bussiness.node">
<field name="name">待质检提醒</field>
<field name="model">product.product</field>
</record>
</data> </data>
</odoo> </odoo>

View File

@@ -10,7 +10,7 @@
<field name="msgtype">markdown</field> <field name="msgtype">markdown</field>
<field name="urgency">normal</field> <field name="urgency">normal</field>
<field name="content">### 待接单提醒: <field name="content">### 待接单提醒:
单号:销售订单[{{name}}]({{url}}) 单号:询价单[{{name}}]({{url}})
事项:请确认是否接单。 事项:请确认是否接单。
</field> </field>
</record> </record>
@@ -72,14 +72,14 @@
<field name="msgtype">markdown</field> <field name="msgtype">markdown</field>
<field name="urgency">normal</field> <field name="urgency">normal</field>
<field name="content">### 坯料发料提醒: <field name="content">### 坯料发料提醒:
单号:产品[{{product_id}}]({{request_url}}) 单号:发料单[{{name}}]({{request_url}})
事项:共{{number}}个生产发料单待确认处理</field> 事项:请确认坯料发料单并处理</field>
</record> </record>
<record id="template_mrp_workorder_remind" model="jikimo.message.template"> <record id="template_mrp_workorder_remind" model="jikimo.message.template">
<field name="name">工单已下发通知</field> <field name="name">工单已下发通知</field>
<field name="model_id" ref="mrp_workorder.model_mrp_workorder"/> <field name="model_id" ref="product.model_product_product"/>
<field name="model">mrp.workorder</field> <field name="model">product.product</field>
<field name="bussiness_node_id" ref="bussiness_mrp_workorder_remind"/> <field name="bussiness_node_id" ref="bussiness_mrp_workorder_remind"/>
<field name="msgtype">markdown</field> <field name="msgtype">markdown</field>
<field name="urgency">normal</field> <field name="urgency">normal</field>
@@ -275,5 +275,131 @@
机台号:[{{maintenance_equipment_id.name}}]({{url}}) 机台号:[{{maintenance_equipment_id.name}}]({{url}})
事项:{{create_date}}故障报警</field> 事项:{{create_date}}故障报警</field>
</record> </record>
<record id="template_supply_method" model="jikimo.message.template">
<field name="name">待确认供货方式</field>
<field name="model_id" ref="sale.model_sale_order"/>
<field name="model">sale.order</field>
<field name="bussiness_node_id" ref="bussiness_supply_method"/>
<field name="msgtype">markdown</field>
<field name="urgency">normal</field>
<field name="content">### 待确认供货方式提醒:
单号:销售订单[{{name}}]({{url}})
事项:请确认供货方式。
</field>
</record>
<record id="template_technology_to_confirmed" model="jikimo.message.template">
<field name="name">待确认加工路线</field>
<field name="model_id" ref="mrp.model_mrp_production"/>
<field name="model">mrp.production</field>
<field name="bussiness_node_id" ref="bussiness_technology_to_confirmed"/>
<field name="msgtype">markdown</field>
<field name="urgency">normal</field>
<field name="content">### 待确认加工路线提醒:
单号:产品[{{name}}]({{url}})
事项:有{{production_num}}个制造订单需要确认加工路线。
</field>
</record>
<record id="template_state_draft" model="jikimo.message.template">
<field name="name">待排程</field>
<field name="model_id" ref="mrp.model_mrp_production"/>
<field name="model">mrp.production</field>
<field name="bussiness_node_id" ref="bussiness_state_draft"/>
<field name="msgtype">markdown</field>
<field name="urgency">normal</field>
<field name="content">### 待排程提醒:
单号:产品[{{name}}]({{url}})
事项:有{{production_num}}个制造订单待排程。
</field>
</record>
<record id="template_outsourcing_remind" model="jikimo.message.template">
<field name="name">委外加工采购单提醒</field>
<field name="model_id" ref="purchase.model_purchase_order"/>
<field name="model">purchase.order</field>
<field name="bussiness_node_id" ref="bussiness_outsourcing"/>
<field name="msgtype">markdown</field>
<field name="urgency">normal</field>
<field name="content">### 委外加工采购通知:
单号:委外加工采购单[{{name}}]({{request_url}})
事项:请确认委外采购单并处理。</field>
</record>
<record id="template_purchase_remind" model="jikimo.message.template">
<field name="name">外购订单采购单提醒</field>
<field name="model_id" ref="purchase.model_purchase_order"/>
<field name="model">purchase.order</field>
<field name="bussiness_node_id" ref="bussiness_purchase"/>
<field name="msgtype">markdown</field>
<field name="urgency">normal</field>
<field name="content">### 外购订单采购通知:
单号:外购采购单[{{name}}]({{request_url}})
事项:请确认外购采购单并处理。</field>
</record>
<record id="template_process_outsourcing_remind" model="jikimo.message.template">
<field name="name">工序外协采购单通知</field>
<field name="model_id" ref="purchase.model_purchase_order"/>
<field name="model">purchase.order</field>
<field name="bussiness_node_id" ref="bussiness_process_outsourcing"/>
<field name="msgtype">markdown</field>
<field name="urgency">normal</field>
<field name="content">### 工序外协采购单通知:
单号:工序外协采购,产品[{{name}}]({{url}})
事项:请确认{{num}}个工序外协采购单并处理。</field>
</record>
<record id="template_outsourced_outbound_remind" model="jikimo.message.template">
<field name="name">工序外协发料通知</field>
<field name="model_id" ref="mrp.model_mrp_production"/>
<field name="model">mrp.production</field>
<field name="bussiness_node_id" ref="bussiness_outsourced_outbound"/>
<field name="msgtype">markdown</field>
<field name="urgency">normal</field>
<field name="content">### 工序外协发料提醒:
单号:产品[{{name}}]({{url}})发料单
事项:请确认{{num}}个工序外协发料单并发料处理。</field>
</record>
<record id="template_purchase_order_warning" model="jikimo.message.template">
<field name="name">采购订单预警提醒</field>
<field name="model_id" ref="purchase.model_purchase_order"/>
<field name="model">purchase.order</field>
<field name="bussiness_node_id" ref="bussiness_purchase_order_warning"/>
<field name="msgtype">markdown</field>
<field name="send_type">timing</field>
<field name="urgency">normal</field>
<field name="content">### 采购订单预警提醒
事项:[共有{{num}}个采购订单有逾期风险]({{url}})
</field>
</record>
<record id="template_purchase_order_overdue" model="jikimo.message.template">
<field name="name">采购单已逾期提醒</field>
<field name="model_id" ref="purchase.model_purchase_order"/>
<field name="model">purchase.order</field>
<field name="bussiness_node_id" ref="bussiness_purchase_order_overdue"/>
<field name="msgtype">markdown</field>
<field name="send_type">timing</field>
<field name="urgency">normal</field>
<field name="content">### 采购单已逾期提醒
事项:[共有{{num}}个采购订单已逾期]({{url}})
</field>
</record>
<record id="template_quality_check" model="jikimo.message.template">
<field name="name">待质检提醒</field>
<field name="model_id" ref="product.model_product_product"/>
<field name="model">product.product</field>
<field name="bussiness_node_id" ref="bussiness_quality_check"/>
<field name="msgtype">markdown</field>
<field name="urgency">normal</field>
<field name="content">### 待质检提醒:
单号:产品[{{name}}]({{url}})
事项:有{{num}}个质检单需要处理。</field>
</record>
</data> </data>
</odoo> </odoo>

View File

@@ -10,3 +10,7 @@ from . import sf_message_functional_tool_dismantle
from . import sf_message_mrp_production from . import sf_message_mrp_production
from . import sf_message_quality_cnc_test from . import sf_message_quality_cnc_test
from . import sf_message_maintenance_logs from . import sf_message_maintenance_logs
from . import sf_message_mrp_production_wizard
from . import sf_message_mrp_production_adjust_wizard
from . import sf_message_product
from . import sf_message_quality_check

View File

@@ -13,11 +13,11 @@ class SFMessageMaintenanceLogs(models.Model):
return res return res
def _get_message(self, message_queue_ids): def _get_message(self, message_queue_ids):
contents = super(SFMessageMaintenanceLogs, self)._get_message(message_queue_ids) contents, _ = super(SFMessageMaintenanceLogs, self)._get_message(message_queue_ids)
url = self.env['ir.config_parameter'].get_param('web.base.url') url = self.env['ir.config_parameter'].get_param('web.base.url')
action_id = self.env.ref('sf_maintenance.action_maintenance_logs').id action_id = self.env.ref('sf_maintenance.action_maintenance_logs').id
for index, content in enumerate(contents): for index, content in enumerate(contents):
maintenance_logs_id = self.env['sf.maintenance.logs'].browse(message_queue_ids[index].res_id) maintenance_logs_id = self.env['sf.maintenance.logs'].browse(message_queue_ids[index].res_id)
url = url + '/web#id=%s&view_type=form&action=%s' % (maintenance_logs_id.id, action_id) url = url + '/web#id=%s&view_type=form&action=%s' % (maintenance_logs_id.id, action_id)
contents[index] = content.replace('{{url}}', url) contents[index] = content.replace('{{url}}', url)
return contents return contents, message_queue_ids

View File

@@ -14,19 +14,24 @@ class SFMessageMrpProduction(models.Model):
'workorder_ids.state', 'product_qty', 'qty_producing') 'workorder_ids.state', 'product_qty', 'qty_producing')
def _compute_state(self): def _compute_state(self):
super(SFMessageMrpProduction, self)._compute_state() super(SFMessageMrpProduction, self)._compute_state()
for record in self: try:
if record.state in ['scrap', 'done']: for record in self:
# 查询制造订单下的所有未完成的生产订单 if record.state in ['scrap', 'done']:
mrp_production = record.env['mrp.production'].search( # 查询制造订单下的所有未完成的生产订单
[('origin', '=', record.origin), ('state', 'not in', ['scrap', 'done'])]) mrp_production = record.env['mrp.production'].search(
if not mrp_production: [('origin', '=', record.origin), ('state', 'not in', ['scrap', 'done'])])
mrp_production_queue = self.env["jikimo.message.queue"].search([('res_id', '=', record.id)]) if not mrp_production:
if not mrp_production_queue: mrp_production_queue = self.env["jikimo.message.queue"].search([('res_id', '=', record.id)])
record.add_queue('生产完工入库提醒') if not mrp_production_queue:
record.add_queue('生产完工入库提醒')
except Exception as e:
logging.info('add_queue生产完工入库提醒 error:%s' % e)
# 获取发送消息内容 # 获取发送消息内容
def _get_message(self, message_queue_ids): def _get_message(self, message_queue_ids):
contents = [] contents = []
unique_products = set()
technology_to_confirmed = set()
for message_queue_id in message_queue_ids: for message_queue_id in message_queue_ids:
if message_queue_id.message_template_id.name == '生产完工入库提醒': if message_queue_id.message_template_id.name == '生产完工入库提醒':
content = message_queue_id.message_template_id.content content = message_queue_id.message_template_id.content
@@ -40,7 +45,58 @@ class SFMessageMrpProduction(models.Model):
content = content.replace('{{name}}', stock_picking_sfp.name).replace( content = content.replace('{{name}}', stock_picking_sfp.name).replace(
'{{sale_order_name}}', mrp_production.origin).replace('{{request_url}}', url) '{{sale_order_name}}', mrp_production.origin).replace('{{request_url}}', url)
contents.append(content) contents.append(content)
if message_queue_id.message_template_id.name == '待确认加工路线':
content = message_queue_id.message_template_id.content
mrp_production = self.env['mrp.production'].sudo().search([('id', '=', int(message_queue_id.res_id))])
technology_to_confirmed.add(mrp_production.product_id.id)
if message_queue_id.message_template_id.name == '待排程':
content = message_queue_id.message_template_id.content
mrp_production = self.env['mrp.production'].sudo().search([('id', '=', int(message_queue_id.res_id))])
unique_products.add(mrp_production.product_id.id)
if message_queue_id.message_template_id.name == '工序外协发料通知':
content = message_queue_id.message_template_id.content
mrp_production = self.env['mrp.production'].sudo().search([('id', '=', int(message_queue_id.res_id))])
mrp_production_list = self.env['mrp.production'].sudo().search(
[('product_id', '=', mrp_production.product_id.id)])
mrp_production_names = mrp_production_list.mapped('name')
stock_picking_num = self.env['stock.picking'].sudo().search_count(
[('origin', 'in', mrp_production_names), ('state', '=', 'assigned')])
if stock_picking_num >= 1:
url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
action_id = self.env.ref('sf_message.action_picking_outsourced_tree_ready').id
menu_id = self.env.ref('stock.menu_stock_root').id
url_with_id = f"{url}/web#view_type=list&action={action_id}&menu_id={menu_id}"
content = content.replace('{{name}}', mrp_production.product_id.name).replace('{{url}}',
url_with_id).replace(
'{{num}}', str(stock_picking_num))
contents.append(content)
if unique_products:
action_id = self.env.ref('sf_plan.sf_production_plan_action1').id
unique_products_contents = self.get_production_info(content, unique_products, 'confirmed',
action_id)
contents.extend(unique_products_contents)
if technology_to_confirmed:
action_id = self.env.ref('mrp.mrp_production_action').id
technology_to_confirmed_contents = self.get_production_info(content, technology_to_confirmed,
'technology_to_confirmed',
action_id)
contents.extend(technology_to_confirmed_contents)
logging.info('生产完工入库提醒: %s' % contents) logging.info('生产完工入库提醒: %s' % contents)
return contents, message_queue_ids
def get_production_info(self, content, product_ids, state, action_id):
contents = []
for products_id in product_ids:
product_name = self.env['product.product'].sudo().search([('id', '=', products_id)]).name
production_num = self.env['mrp.production'].sudo().search_count(
[('product_id', '=', products_id), ('state', '=', state)])
if production_num >= 1:
url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
url_with_id = f"{url}/web#view_type=list&action={action_id}"
new_content = (content.replace('{{name}}', product_name)
.replace('{{url}}', url_with_id)
.replace('{{production_num}}', str(production_num)))
contents.append(new_content)
return contents return contents
def request_url(self, id): def request_url(self, id):
@@ -48,7 +104,7 @@ class SFMessageMrpProduction(models.Model):
action_id = self.env.ref('stock.action_picking_tree_all').id 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'].search([('name', '=', 'module_theme_treehouse')]).id
# 查询参数 # 查询参数
params = {'id': id, 'menu_id': menu_id, 'action': action_id, 'model': 'mrp.production', params = {'id': id, 'menu_id': menu_id, 'action': action_id, 'model': 'mrp.production',
'view_type': 'form'} 'view_type': 'form'}
# 拼接查询参数 # 拼接查询参数
query_string = urlencode(params) query_string = urlencode(params)

View File

@@ -0,0 +1,17 @@
import logging
from odoo import models, fields, api, _
class SFMessageMrpProductionAdjustWizard(models.TransientModel):
_name = 'sf.production.technology.re_adjust.wizard'
_description = "制造订单工艺调整"
_inherit = ['sf.production.technology.re_adjust.wizard', 'jikimo.message.dispatch']
def confirm(self):
super(SFMessageMrpProductionAdjustWizard, self).confirm()
try:
for production_info in self.production_id:
if production_info.state == 'technology_to_confirmed':
production_info.add_queue('待确认加工路线')
except Exception as e:
logging.info('add_queue待确认加工路线 error:%s' % e)

View File

@@ -0,0 +1,23 @@
import logging
from odoo import models, fields, api, _
class SFMessageMrpProductionWizard(models.TransientModel):
_name = 'sf.production.technology.wizard'
_description = "制造订单工艺确认向导"
_inherit = ['sf.production.technology.wizard', 'jikimo.message.dispatch']
def confirm(self):
productions = super(SFMessageMrpProductionWizard, self).confirm()
try:
for production_info in self.production_id:
if production_info.state == 'confirmed' and production_info.product_id.categ_id.type == '成品':
production_info.add_queue('待排程')
for production_id in productions:
workorder_ids = production_id.workorder_ids.filtered(
lambda p: p.routing_type == '表面工艺' and p.state != 'cancel')
for workorder_id in workorder_ids:
purchase_orders_id = workorder_id._get_surface_technics_purchase_ids()
purchase_orders_id.add_queue('工序外协采购单通知')
except Exception as e:
logging.info('add_queue待排程 error:%s' % e)

View File

@@ -0,0 +1,57 @@
# -*- coding: utf-8 -*-
from odoo import models, fields, api, _
from urllib.parse import urlencode
class SFMessageProduct(models.Model):
_name = 'product.product'
_inherit = ['product.product', 'jikimo.message.dispatch']
def _get_message(self, message_queue_ids):
contents = []
for message_queue_id in message_queue_ids:
if message_queue_id.message_template_id.name == '工单已下发通知':
content = message_queue_id.message_template_id.content
product_product = self.env['product.product'].sudo().search([('id', '=', int(message_queue_id.res_id))])
mrp_production_list = self.env['mrp.production'].sudo().search(
[('product_id', '=', product_product.id)])
production_num = 0
for mrp_production_info in mrp_production_list:
routing_type = '人工线下加工' if mrp_production_info.production_type == '人工线下加工' else '装夹预调'
mrp_production_ready = mrp_production_info.workorder_ids.filtered(
lambda w: w.routing_type == routing_type and w.state == 'ready')
if mrp_production_ready:
production_num += 1
if production_num >= 1:
url = self.get_request_url()
content = content.replace('{{product_id}}', product_product.name).replace(
'{{number}}', str(production_num)).replace(
'{{request_url}}', url)
contents.append(content)
if message_queue_id.message_template_id.name == '待质检提醒':
content = message_queue_id.message_template_id.content
product_product = self.env['product.product'].sudo().search([('id', '=', int(message_queue_id.res_id))])
quality_check_num = self.env['quality.check'].sudo().search_count(
[('product_id', '=', product_product.id), ('quality_state', '=', 'none')])
if quality_check_num >= 1:
url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
action_id = self.env.ref('quality_control.quality_check_action_report').id
url_with_id = f"{url}/web#view_type=list&action={action_id}"
content = content.replace('{{name}}', product_product.name).replace('{{url}}', url_with_id).replace(
'{{num}}', str(quality_check_num))
contents.append(content)
return contents, message_queue_ids
def get_request_url(self):
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.ref('mrp.menu_mrp_root').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': active_id}
# 拼接查询参数
query_string = urlencode(params)
# 拼接URL
full_url = url + "/web#" + query_string
return full_url

View File

@@ -8,20 +8,62 @@ class SFMessagePurchase(models.Model):
def _get_message(self, message_queue_ids): def _get_message(self, message_queue_ids):
contents = [] contents = []
process_outsourcing = set()
for message_queue_id in message_queue_ids: for message_queue_id in message_queue_ids:
if message_queue_id.message_template_id.name == '坯料采购提醒': if message_queue_id.message_template_id.name in (
'坯料采购提醒', '委外加工采购单提醒', '外购订单采购单提醒'):
content = message_queue_id.message_template_id.content content = message_queue_id.message_template_id.content
url = self.request_url(int(message_queue_id.res_id)) url = self.request_url(int(message_queue_id.res_id))
purchase_order_line = self.env['purchase.order'].search([('id', '=', int(message_queue_id.res_id))]) purchase_order_line = self.env['purchase.order'].search([('id', '=', int(message_queue_id.res_id))])
content = content.replace('{{name}}', purchase_order_line.name).replace( content = content.replace('{{name}}', purchase_order_line.name).replace(
'{{request_url}}', url) '{{request_url}}', url)
contents.append(content) contents.append(content)
return contents if message_queue_id.message_template_id.name == '工序外协采购单通知':
content = message_queue_id.message_template_id.content
purchase_order_line = self.env['purchase.order'].sudo().search(
[('id', '=', int(message_queue_id.res_id))])
mrp_production = self.env['mrp.production'].sudo().search([('name', '=', purchase_order_line.origin)])
process_outsourcing.add(mrp_production.product_id.id)
if message_queue_id.message_template_id.name in ('采购订单预警提醒', '采购单已逾期提醒'):
content = message_queue_id.message_template_id.content
if message_queue_id.message_template_id.name == '采购订单预警提醒':
domain = [('delivery_warning', '=', 'warning')]
action_id = self.env.ref("sf_message.purchase_form_warning_action").id
else:
domain = [('delivery_warning', '=', 'overdue')]
action_id = self.env.ref("sf_message.purchase_form_overdue_action").id
purchase_order_num = self.env['purchase.order'].sudo().search_count(domain)
if purchase_order_num >= 1:
url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
menu_id = self.env.ref('purchase.menu_purchase_form_action').id
url_with_id = f"{url}/web#view_type=list&action={action_id}&menu_id={menu_id}"
content = content.replace('{{url}}', url_with_id).replace('{{num}}', str(purchase_order_num))
contents.append(content)
if process_outsourcing:
content_info = content
for products_id in process_outsourcing:
production_num = 0
product_name = self.env['product.product'].sudo().search([('id', '=', products_id)]).name
production_list = self.env['mrp.production'].sudo().search(
[('product_id', '=', products_id), ('state', '=', 'confirmed')])
for production_info in production_list:
workorder_ids = len(production_info.workorder_ids.filtered(
lambda p: p.routing_type == '表面工艺' and p.state != 'cancel'))
production_num += workorder_ids
if production_num >= 1:
url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
action_id = self.env.ref('purchase.purchase_form_action').id
url_with_id = f"{url}/web#view_type=list&action={action_id}"
new_content = (content_info.replace('{{name}}', product_name)
.replace('{{url}}', url_with_id)
.replace('{{num}}', str(production_num)))
contents.append(new_content)
return contents, message_queue_ids
def request_url(self, id): def request_url(self, id):
url = self.env['ir.config_parameter'].get_param('web.base.url') url = self.env['ir.config_parameter'].get_param('web.base.url')
action_id = self.env.ref('purchase.purchase_form_action').id action_id = self.env.ref('purchase.purchase_form_action').id
menu_id = self.env['ir.model.data'].search([('name', '=', 'module_website_payment')]).id menu_id = self.env.ref('purchase.menu_purchase_form_action').id
# 查询参数 # 查询参数
params = {'id': id, 'menu_id': menu_id, 'action': action_id, params = {'id': id, 'menu_id': menu_id, 'action': action_id,
'model': 'purchase.order', 'model': 'purchase.order',
@@ -31,3 +73,27 @@ class SFMessagePurchase(models.Model):
# 拼接URL # 拼接URL
full_url = url + "/web#" + query_string full_url = url + "/web#" + query_string
return full_url return full_url
def _overdue_or_warning_func(self):
last_overdue_order, last_warning_order = super(SFMessagePurchase, self)._overdue_or_warning_func()
if last_overdue_order:
business_node_id = self.env.ref('sf_message.template_purchase_order_overdue').id
purchase_order_has = self._get_message_queue(business_node_id)
if not purchase_order_has:
last_overdue_order.add_queue("采购单已逾期提醒")
if last_warning_order:
business_node_id = self.env.ref('sf_message.template_purchase_order_warning').id
purchase_order_has = self._get_message_queue(business_node_id)
if not purchase_order_has:
last_warning_order.add_queue("采购订单预警提醒")
def _get_message_queue(self, business_node_id):
message_template = self.env["jikimo.message.template"].sudo().search([
("model", "=", self._name),
("bussiness_node_id", "=", business_node_id)
], limit=1)
purchase_order_has = self.env['jikimo.message.queue'].sudo().search([
('message_status', '=', 'pending'),
('message_template_id', '=', message_template.id)
])
return purchase_order_has

View File

@@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
import logging
from odoo import models, fields, api, _
class SFMessageQualityCheck(models.Model):
_name = 'quality.check'
_inherit = ['quality.check', 'jikimo.message.dispatch']
@api.model_create_multi
def create(self, vals_list):
result = super().create(vals_list)
try:
# 判断是否为web页面创建请求
is_web_request = self.env.context.get('is_web_request', False)
if not is_web_request:
for obj in result:
jikimo_message_queue = self.get_message_queue(obj.product_id.id)
if not jikimo_message_queue:
obj.product_id.add_queue('待质检提醒')
except Exception as e:
logging.info('add_queue待质检提醒 error:%s' % e)
return result
def get_message_queue(self, res_id):
business_node_id = self.env.ref('sf_message.bussiness_quality_check').id
message_template = self.env["jikimo.message.template"].sudo().search([
("name", "=", '待质检提醒'),
("bussiness_node_id", "=", business_node_id)
], limit=1)
jikimo_message_queue = self.env['jikimo.message.queue'].sudo().search(
[('res_id', '=', res_id), ("message_status", "in", ("pending", "sent")),
('message_template_id', '=', message_template.id)])
return jikimo_message_queue

View File

@@ -33,4 +33,4 @@ class SFMessageQualityCncTest(models.Model):
content_template = content.replace('{{judge_num}}', str(i)) content_template = content.replace('{{judge_num}}', str(i))
content_template = content_template.replace('{{url}}', url_with_id) content_template = content_template.replace('{{url}}', url_with_id)
contents.append(content_template) contents.append(content_template)
return contents return contents, message_queue_ids

View File

@@ -8,17 +8,6 @@ class SFMessageSale(models.Model):
_name = 'sale.order' _name = 'sale.order'
_inherit = ['sale.order', 'jikimo.message.dispatch'] _inherit = ['sale.order', 'jikimo.message.dispatch']
@api.model_create_multi
def create(self, vals_list):
res = super(SFMessageSale, self).create(vals_list)
if res:
try:
logging.info('add_queue res:%s' % res)
res.add_queue('待接单')
except Exception as e:
logging.info('add_queue error:%s' % e)
return res
# 确认接单 # 确认接单
def action_confirm(self): def action_confirm(self):
res = super(SFMessageSale, self).action_confirm() res = super(SFMessageSale, self).action_confirm()
@@ -29,19 +18,34 @@ class SFMessageSale(models.Model):
purchase_order_id = [] purchase_order_id = []
if picking_ids: if picking_ids:
for picking_id in picking_ids: for picking_id in picking_ids:
picking_id.add_queue('待确认加工路线')
purchase_order_ids = ( purchase_order_ids = (
picking_id.procurement_group_id.stock_move_ids.created_purchase_line_id.order_id | picking_id.procurement_group_id.stock_move_ids.created_purchase_line_id.order_id |
picking_id.procurement_group_id.stock_move_ids.move_orig_ids.purchase_line_id.order_id).ids picking_id.procurement_group_id.stock_move_ids.move_orig_ids.purchase_line_id.order_id).ids
purchase_order_id.extend(purchase_order_ids) purchase_order_id.extend(purchase_order_ids)
if purchase_order_id: if purchase_order_id:
purchase_order_list = self.env['purchase.order'].sudo().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: for purchase_order_info in purchase_order_list:
purchase_order_info.add_queue('坯料采购提醒') purchase_order_info.add_queue('坯料采购提醒')
purchase_order_ids = self.order_line.purchase_line_ids.order_id | self.procurement_group_id.stock_move_ids.created_purchase_line_id.order_id | self.procurement_group_id.stock_move_ids.move_orig_ids.purchase_line_id.order_id
for purchase_order_id in purchase_order_ids:
if purchase_order_id.purchase_type == 'outsourcing':
purchase_order_id.add_queue('委外加工采购单提醒')
if purchase_order_id.purchase_type == 'outside':
purchase_order_id.add_queue('外购订单采购单提醒')
except Exception as e: except Exception as e:
logging.info('add_queue error:%s' % e) logging.info('add_queue error:%s' % e)
logging.info('action_confirm res:%s' % res) logging.info('action_confirm res:%s' % res)
return res return res
def confirm_to_supply_method(self):
super(SFMessageSale, self).confirm_to_supply_method()
try:
self.add_queue('待确认供货方式')
except Exception as e:
logging.info('add_queue待确认供货方式 error:%s' % e)
# 继承并重写jikimo.message.dispatch的_get_message() # 继承并重写jikimo.message.dispatch的_get_message()
def _get_message(self, message_queue_ids): def _get_message(self, message_queue_ids):
contents = [] contents = []
@@ -53,14 +57,16 @@ class SFMessageSale(models.Model):
time_range = timedelta(minutes=2) time_range = timedelta(minutes=2)
i = 0 i = 0
for item in message_queue_ids: for item in message_queue_ids:
if item.message_template_id.bussiness_node_id.name == '待接单': if item.message_template_id.bussiness_node_id.name in ('待接单', '待确认供货方式'):
content = super(SFMessageSale, self)._get_message(item) content, _ = super(SFMessageSale, self)._get_message(item)
action_id = self.env.ref('sale.action_quotations_with_onboarding').id action_id = self.env.ref('sale.action_quotations_with_onboarding').id \
if item.message_template_id.bussiness_node_id.name == '待接单' \
else self.env.ref('sale.action_orders').id
url_with_id = f"{url}/web#id={item.res_id}&view_type=form&action={action_id}" url_with_id = f"{url}/web#id={item.res_id}&view_type=form&action={action_id}"
content = content[0].replace('{{url}}', url_with_id) content = content[0].replace('{{url}}', url_with_id)
contents.append(content) contents.append(content)
elif item.message_template_id.bussiness_node_id.name == '确认接单': elif item.message_template_id.bussiness_node_id.name == '确认接单':
content = super(SFMessageSale, self)._get_message(item) content, _ = super(SFMessageSale, self)._get_message(item)
sale_order_line = self.env['sale.order.line'].sudo().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...' % \ product = sale_order_line[0].product_id.name if len(sale_order_line) == 1 else '%s...' % \
sale_order_line[ sale_order_line[
@@ -97,7 +103,7 @@ class SFMessageSale(models.Model):
elif bussiness_node == '销售订单已逾期': elif bussiness_node == '销售订单已逾期':
content = content_template.replace('{{overdue_num}}', str(i)) content = content_template.replace('{{overdue_num}}', str(i))
contents.append(content) contents.append(content)
return contents return contents, message_queue_ids
# # 销售订单逾期预警和已逾期 # # 销售订单逾期预警和已逾期
def _overdue_or_warning_func(self): def _overdue_or_warning_func(self):

View File

@@ -12,26 +12,44 @@ class SFMessageStockPicking(models.Model):
@api.model_create_multi @api.model_create_multi
def create(self, vals): def create(self, vals):
result = super(SFMessageStockPicking, self).create(vals) result = super(SFMessageStockPicking, self).create(vals)
for obj in result: try:
if obj.location_id.name == '进货' and obj.location_dest_id.name == '刀具房': for obj in result:
obj.add_queue('调拨入库') if obj.location_id.name == '进货' and obj.location_dest_id.name == '刀具房':
obj.add_queue('调拨入库')
except Exception as e:
logging.info('add_queue调拨入库 error:%s' % e)
return result return result
@api.depends('move_type', 'immediate_transfer', 'move_ids.state', 'move_ids.picking_id') @api.depends('move_type', 'immediate_transfer', 'move_ids.state', 'move_ids.picking_id')
def _compute_state(self): def _compute_state(self):
super(SFMessageStockPicking, self)._compute_state() super(SFMessageStockPicking, self)._compute_state()
for record in self: try:
if record.state == 'assigned' and record.check_in == 'PC': for record in self:
record.add_queue('坯料发料提醒') if (record.state == 'assigned' and record.picking_type_id.sequence_code == 'PC'
and record.product_id.categ_id.type == '坯料'):
record.add_queue('坯料发料提醒')
if record.picking_type_id.sequence_code == 'SFP' and record.state == 'done': if record.picking_type_id.sequence_code == 'SFP' and record.state == 'done':
stock_picking_sfp = record.env['stock.picking'].search( stock_picking_sfp = record.env['stock.picking'].search(
[('origin', '=', record.origin), ('state', '!=', 'done'), [('origin', '=', record.origin), ('state', '!=', 'done'),
('picking_type_id.sequence_code', '=', 'SFP')]) ('picking_type_id.sequence_code', '=', 'SFP')])
if not stock_picking_sfp: if not stock_picking_sfp:
stock_picking_send = self.env["jikimo.message.queue"].sudo().search([('res_id', '=', record.id)]) stock_picking_send = self.env["jikimo.message.queue"].sudo().search(
if not stock_picking_send: [('res_id', '=', record.id)])
record.add_queue('订单发货提醒') if not stock_picking_send:
record.add_queue('订单发货提醒')
if record.picking_type_id.sequence_code == 'OCOUT' and record.state == 'assigned':
mrp_production = self.env['mrp.production'].sudo().search([('name', '=', record.origin)])
production_list = self.env['mrp.production'].sudo().search(
[('product_id', '=', mrp_production.product_id.id)])
manufacturing_order_names = production_list.mapped('name')
stock_picking_list = self.env['stock.picking'].sudo().search(
[('origin', 'in', manufacturing_order_names), ('picking_type_id.sequence_code', '=', 'OCOUT')])
all_ready_or_done = all(picking.state in ['assigned', 'done'] for picking in stock_picking_list)
if all_ready_or_done:
mrp_production.add_queue('工序外协发料通知')
except Exception as e:
logging.info('add_queue_compute_state error:%s' % e)
def deal_stock_picking_sfp(self, message_queue_id): # 处理订单发货提醒 def deal_stock_picking_sfp(self, message_queue_id): # 处理订单发货提醒
content = None content = None
@@ -49,32 +67,23 @@ class SFMessageStockPicking(models.Model):
def _get_message(self, message_queue_ids): def _get_message(self, message_queue_ids):
contents = [] contents = []
product_id = []
for message_queue_id in message_queue_ids: for message_queue_id in message_queue_ids:
i = 0
if message_queue_id.message_template_id.name == '坯料发料提醒': if message_queue_id.message_template_id.name == '坯料发料提醒':
content = message_queue_id.message_template_id.content content = message_queue_id.message_template_id.content
stock_picking_line = self.env['stock.picking'].sudo().search([('id', '=', int(message_queue_id.res_id))]) stock_picking_line = self.env['stock.picking'].sudo().search(
mrp_production_info = self.env['mrp.production'].sudo().search( [('id', '=', int(message_queue_id.res_id))])
[('name', '=', stock_picking_line.origin)]) url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
mrp_production_list = self.env['mrp.production'].sudo().search( action_id = self.env.ref('stock.action_picking_tree_ready').id
[('product_id', '=', mrp_production_info.product_id.id)]) menu_id = self.env.ref('stock.menu_stock_root').id
for mrp_production_line in mrp_production_list: url_with_id = f"{url}/web#view_type=form&action={action_id}&menu_id={menu_id}&id={stock_picking_line.id}"
picking_ids = mrp_production_line.picking_ids content = content.replace('{{name}}', stock_picking_line.name).replace(
for picking_id in picking_ids: '{{request_url}}', url_with_id)
if picking_id.state == 'assigned' and picking_id.check_in == 'PC': contents.append(content)
i += 1
if i > 0 and mrp_production_info.product_id.id not in product_id:
url = self.request_url()
content = content.replace('{{product_id}}', mrp_production_info.product_id.name).replace(
'{{number}}', str(i)).replace('{{request_url}}', url)
product_id.append(mrp_production_info.product_id.id)
contents.append(content)
elif message_queue_id.message_template_id.name == '订单发货提醒': elif message_queue_id.message_template_id.name == '订单发货提醒':
content = self.deal_stock_picking_sfp(message_queue_id) content = self.deal_stock_picking_sfp(message_queue_id)
if content: if content:
contents.append(content) contents.append(content)
return contents return contents, message_queue_ids
def get_special_url(self, id, tmplate_name, special_name, model_id): def get_special_url(self, id, tmplate_name, special_name, model_id):
menu_id = 0 menu_id = 0
@@ -86,19 +95,6 @@ class SFMessageStockPicking(models.Model):
else: else:
return super(SFMessageStockPicking, self).get_special_url(id, tmplate_name, special_name, model_id) return super(SFMessageStockPicking, self).get_special_url(id, tmplate_name, special_name, model_id)
def request_url(self):
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'].sudo().search([('name', '=', 'module_theme_treehouse')]).id
# 查询参数
params = {'menu_id': menu_id, 'action': action_id, 'model': 'stock.picking',
'view_type': 'kanban'}
# 拼接查询参数
query_string = urlencode(params)
# 拼接URL
full_url = url + "/web#" + query_string
return full_url
def request_url1(self, id): def request_url1(self, id):
url = self.env['ir.config_parameter'].sudo().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 action_id = self.env.ref('stock.action_picking_tree_all').id

View File

@@ -16,4 +16,6 @@ class SfMessageTemplate(models.Model):
res.append('mrp.workorder') res.append('mrp.workorder')
res.append('sf.maintenance.logs') res.append('sf.maintenance.logs')
res.append('quality.cnc.test') res.append('quality.cnc.test')
res.append('mrp.production')
res.append('product.product')
return res return res

View File

@@ -12,19 +12,30 @@ class SFMessageWork(models.Model):
_name = 'mrp.workorder' _name = 'mrp.workorder'
_inherit = ['mrp.workorder', 'jikimo.message.dispatch'] _inherit = ['mrp.workorder', 'jikimo.message.dispatch']
@api.depends('production_availability', 'blocked_by_workorder_ids.state', 'production_id.tool_state') @api.depends('production_availability', 'blocked_by_workorder_ids', 'blocked_by_workorder_ids.state',
'production_id.tool_state', 'production_id.schedule_state', 'sequence',
'production_id.programming_state')
def _compute_state(self): def _compute_state(self):
super(SFMessageWork, self)._compute_state() super(SFMessageWork, self)._compute_state()
for workorder in self: for workorder in self:
if workorder.state == 'ready' and workorder.routing_type == '装夹预调': min_sequence_wk = None
work_ids = workorder.production_id.workorder_ids.filtered(lambda w: w.routing_type == '装夹预调')
if work_ids:
min_sequence_wk = work_ids.sorted(key=lambda w: w.sequence)[0]
if (
workorder.state == 'ready' and workorder.routing_type == '装夹预调' and workorder.id == min_sequence_wk.id) or (
workorder.state == 'ready' and workorder.routing_type == '人工线下加工'):
message_template = self.env["jikimo.message.template"].sudo().search(
[("name", "=", '工单已下发通知')], limit=1)
jikimo_message_queue = self.env['jikimo.message.queue'].sudo().search( jikimo_message_queue = self.env['jikimo.message.queue'].sudo().search(
[('res_id', '=', workorder.id), ("message_status", "=", "pending")]) [('res_id', '=', workorder.production_id.product_id.id),
("message_status", "in", ("pending", "sent")),
('message_template_id', '=', message_template.id)])
if not jikimo_message_queue: if not jikimo_message_queue:
workorder.add_queue('工单已下发通知') workorder.production_id.product_id.add_queue('工单已下发通知')
def _get_message(self, message_queue_ids): def _get_message(self, message_queue_ids):
contents = [] contents = []
product_id = []
bussiness_node = None bussiness_node = None
url = self.env['ir.config_parameter'].sudo().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_strf = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
@@ -37,20 +48,7 @@ class SFMessageWork(models.Model):
} }
i = 0 i = 0
for message_queue_id in message_queue_ids: for message_queue_id in message_queue_ids:
if message_queue_id.message_template_id.name == '工单已下发通知': if message_queue_id.message_template_id.name in template_names['预警'] + template_names['已逾期']:
content = message_queue_id.message_template_id.content
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:
url = self.request_url()
content = content.replace('{{product_id}}', mrp_workorder_line.product_id.name).replace(
'{{number}}', str(len(mrp_workorder_list))).replace(
'{{request_url}}', url)
product_id.append(mrp_workorder_line.product_id.id)
contents.append(content)
elif message_queue_id.message_template_id.name in template_names['预警'] + template_names['已逾期']:
item = message_queue_id.message_template_id item = message_queue_id.message_template_id
bussiness_node = item.bussiness_node_id.name bussiness_node = item.bussiness_node_id.name
for reminder_time in item.reminder_time_ids: for reminder_time in item.reminder_time_ids:
@@ -93,21 +91,7 @@ class SFMessageWork(models.Model):
elif bussiness_node in template_names['已逾期']: elif bussiness_node in template_names['已逾期']:
content = content_template.replace('{{overdue_num}}', str(i)) content = content_template.replace('{{overdue_num}}', str(i))
contents.append(content) contents.append(content)
return contents return contents, message_queue_ids
def request_url(self):
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': active_id}
# 拼接查询参数
query_string = urlencode(params)
# 拼接URL
full_url = url + "/web#" + query_string
return full_url
def _overdue_or_warning_func(self): def _overdue_or_warning_func(self):
workorders = self.env['mrp.workorder'].search( workorders = self.env['mrp.workorder'].search(

View File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="purchase_form_warning_action" model="ir.actions.act_window">
<field name="name">采购订单</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">purchase.order</field>
<field name="view_mode">tree,kanban,form,pivot,graph,calendar,activity</field>
<field name="view_ids" eval="[(5, 0, 0),
(0, 0, {'view_mode': 'tree', 'view_id': ref('purchase.purchase_order_view_tree')}),
(0, 0, {'view_mode': 'kanban', 'view_id': ref('purchase.purchase_order_view_kanban_without_dashboard')}),
]"/>
<field name="domain">[('state','in',('purchase', 'done'))]</field>
<field name="search_view_id" ref="purchase.purchase_order_view_search"/>
<field name="context">{'search_default_filter_order_warning':1}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
还没有采购订单, 我们先创建一个!
</p>
<p>
当您下单到您的供应商,确定您的询价它会变成采购订单.
</p>
</field>
</record>
<record id="purchase_form_overdue_action" model="ir.actions.act_window">
<field name="name">采购订单</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">purchase.order</field>
<field name="view_mode">tree,kanban,form,pivot,graph,calendar,activity</field>
<field name="view_ids" eval="[(5, 0, 0),
(0, 0, {'view_mode': 'tree', 'view_id': ref('purchase.purchase_order_view_tree')}),
(0, 0, {'view_mode': 'kanban', 'view_id': ref('purchase.purchase_order_view_kanban_without_dashboard')}),
]"/>
<field name="domain">[('state','in',('purchase', 'done'))]</field>
<field name="search_view_id" ref="purchase.purchase_order_view_search"/>
<field name="context">{'search_default_filter_order_overdue':1}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
还没有采购订单, 我们先创建一个!
</p>
<p>
当您下单到您的供应商,确定您的询价它会变成采购订单.
</p>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="view_picking_internal_search_sf" model="ir.ui.view">
<field name="name">stock.picking.search</field>
<field name="model">stock.picking</field>
<field name="inherit_id" ref="stock.view_picking_internal_search"/>
<field name="arch" type="xml">
<xpath expr="//filter[@name='activities_exception']" position="before">
<filter name="outsourced" string="外协出库" domain="[('picking_type_id.name', '=', '外协出库')]"
invisible="1"/>
<separator/>
</xpath>
</field>
</record>
<record id="action_picking_outsourced_tree_ready" model="ir.actions.act_window">
<field name="name">待办</field>
<field name="res_model">stock.picking</field>
<field name="type">ir.actions.act_window</field>
<field name="view_mode">tree,kanban,form,calendar</field>
<field name="domain"></field>
<field name="context">{'search_default_outsourced': 1,'contact_display': 'partner_address',
'search_default_available': 1}
</field>
<field name="search_view_id" ref="stock.view_picking_internal_search"/>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
没有仓库调拨。 让我们创建一个!
</p>
<p>
移动允许您将产品从一个位置移动到另外一个位置。
</p>
</field>
</record>
</odoo>

View File

@@ -26,12 +26,18 @@ class Sf_Mrs_Connect(http.Controller, MultiInheritController):
ret = json.loads(ret['result']) ret = json.loads(ret['result'])
logging.info('下发编程单:%s' % ret) logging.info('下发编程单:%s' % ret)
domain = [('programming_no', '=', ret['programming_no'])] domain = [('programming_no', '=', ret['programming_no'])]
if ret['manufacturing_type'] in ('scrap', 'invalid_tool_rework'): if ret['manufacturing_type'] in ('scrap', 'invalid_tool_rework', 'rework'):
domain += [('state', 'not in', ['done', 'scrap', 'cancel'])] domain += [('state', 'not in', ['done', 'scrap', 'cancel'])]
else: else:
domain += [('state', 'in', ['confirmed', 'pending_cam'])] domain += [('state', 'in', ['confirmed', 'pending_cam'])]
productions = request.env['mrp.production'].with_user( productions = request.env['mrp.production'].with_user(
request.env.ref("base.user_admin")).search(domain) request.env.ref("base.user_admin")).search(domain)
productions_technology_to_confirmed = request.env['mrp.production'].with_user(
request.env.ref("base.user_admin")).search(
[('programming_no', '=', ret['programming_no']), ('state', 'in', ['technology_to_confirmed'])])
if productions_technology_to_confirmed:
res = {'status': -2, 'message': '查询到待工艺确认的制造订单'}
return json.JSONEncoder().encode(res)
if productions: if productions:
# 拉取所有加工面的程序文件 # 拉取所有加工面的程序文件
for r in ret['processing_panel'].split(','): for r in ret['processing_panel'].split(','):
@@ -50,7 +56,7 @@ class Sf_Mrs_Connect(http.Controller, MultiInheritController):
res['message'] = '编程单号为%s的CNC程序文件从FTP拉取失败' % (ret['programming_no']) res['message'] = '编程单号为%s的CNC程序文件从FTP拉取失败' % (ret['programming_no'])
return json.JSONEncoder().encode(res) return json.JSONEncoder().encode(res)
for production in productions: for production in productions:
production.write({'programming_state': '已编程', 'work_state': '已编程'}) production.write({'programming_state': '已编程', 'work_state': '已编程', 'is_rework': False})
for panel in ret['processing_panel'].split(','): for panel in ret['processing_panel'].split(','):
# 查询状态为进行中且工序类型为CNC加工的工单 # 查询状态为进行中且工序类型为CNC加工的工单
cnc_workorder_has = production.workorder_ids.filtered( cnc_workorder_has = production.workorder_ids.filtered(

View File

@@ -13,7 +13,8 @@ class sf_production_plan(models.Model):
_description = 'sf_production_plan' _description = 'sf_production_plan'
_inherit = ['mail.thread'] _inherit = ['mail.thread']
# _order = 'state desc, write_date desc' # _order = 'state desc, write_date desc'
part_name = fields.Char('零件名称', related='product_id.part_name', readonly=True)
part_number = fields.Char('零件图号', related='product_id.part_number', readonly=True)
state = fields.Selection([ state = fields.Selection([
('draft', '待排程'), ('draft', '待排程'),
('done', '已排程'), ('done', '已排程'),
@@ -231,26 +232,39 @@ class sf_production_plan(models.Model):
if not record.production_line_id: if not record.production_line_id:
raise ValidationError("未选择生产线") raise ValidationError("未选择生产线")
else: else:
# 自动化产线加工
if record.production_id.workorder_ids: 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 record.production_id.production_type == '自动化产线加工':
if item.name == 'CNC加工': # 找到第一张CNC加工工单
# 将同一个面的所有工单筛选出来 first_cnc_workorder = record.production_id.workorder_ids.filtered(lambda x: x.name == 'CNC加工')[0]
workorder_list = record.production_id.workorder_ids.filtered(lambda x: x.processing_panel == item.processing_panel) date_start = record.date_planned_start if record.date_planned_start else datetime.now()
routing_workcenter = record.env['mrp.routing.workcenter'].sudo().search( routing_workcenter = first_cnc_workorder.technology_design_id.route_id
[('name', '=', 'CNC加工')], limit=1) # 设置一个小的开始时间
# 设置一个小的开始时间 first_cnc_workorder.date_planned_start = datetime.now() - timedelta(days=100)
item.date_planned_start = datetime.now() - timedelta(days=100) first_cnc_workorder.date_planned_finished = date_start + timedelta(
item.date_planned_finished = last_cnc_start + timedelta( minutes=routing_workcenter.time_cycle + routing_workcenter.reserved_duration)
minutes=routing_workcenter.time_cycle) first_cnc_workorder.date_planned_start = date_start
item.date_planned_start = last_cnc_start record.sudo().production_id.plan_start_processing_time = first_cnc_workorder.date_planned_start
record.sudo().production_id.plan_start_processing_time = item.date_planned_start first_cnc_workorder.duration_expected = routing_workcenter.time_cycle + routing_workcenter.reserved_duration
item.duration_expected = routing_workcenter.time_cycle record.calculate_plan_time(first_cnc_workorder, record.production_id.workorder_ids)
pre_duration , next_duration = record.calculate_plan_time(item, workorder_list) # 找到最后一张CNC加工工单
record.date_planned_finished = item.date_planned_finished last_cnc_workorder = record.production_id.workorder_ids.filtered(lambda x: x.name == 'CNC加工')[-1]
# 计算下一个cnc工单的开始时间 record.date_planned_finished = last_cnc_workorder.date_planned_finished
last_cnc_start = workorder_list[-1].date_planned_finished + timedelta(minutes=pre_duration) else:
# 没有工单也能排程 # 人工线下加工只排第一张工单
item = record.production_id.workorder_ids[0]
wo_start = record.date_planned_start if record.date_planned_start else datetime.now()
routing_workcenter = item.technology_design_id.route_id
item.date_planned_start = datetime.now() - timedelta(days=100)
item.date_planned_finished = wo_start + timedelta(
minutes=routing_workcenter.time_cycle + routing_workcenter.reserved_duration)
item.date_planned_start = wo_start
record.sudo().production_id.plan_start_processing_time = item.date_planned_start
item.duration_expected = routing_workcenter.time_cycle + routing_workcenter.reserved_duration
record.calculate_plan_time(item, record.production_id.workorder_ids)
last_cnc_workorder = record.production_id.workorder_ids[-1]
record.date_planned_finished = last_cnc_workorder.date_planned_finished
record.state = 'done' record.state = 'done'
# record.production_id.schedule_state = '已排' # record.production_id.schedule_state = '已排'
record.sudo().production_id.schedule_state = '已排' record.sudo().production_id.schedule_state = '已排'
@@ -259,10 +273,10 @@ class sf_production_plan(models.Model):
# sale_obj = self.env['sale.order'].search([('name', '=', record.origin)]) # sale_obj = self.env['sale.order'].search([('name', '=', record.origin)])
# if 'S' in sale_obj.name: # if 'S' in sale_obj.name:
# sale_obj.schedule_status = 'to process' # sale_obj.schedule_status = 'to process'
mrp_production_ids = record.production_id._get_children().ids # mrp_production_ids = record.production_id._get_children().ids
print('mrp_production_ids', mrp_production_ids) # print('mrp_production_ids', mrp_production_ids)
for i in mrp_production_ids: # for i in mrp_production_ids:
record.env['mrp.production'].sudo().browse(i).schedule_state = '已排' # record.env['mrp.production'].sudo().browse(i).schedule_state = '已排'
# record.production_id.date_planned_start = record.date_planned_start # record.production_id.date_planned_start = record.date_planned_start
# record.production_id.date_planned_finished = record.date_planned_finished # record.production_id.date_planned_finished = record.date_planned_finished
record.sudo().production_id.production_line_id = record.production_line_id.id record.sudo().production_id.production_line_id = record.production_line_id.id
@@ -306,44 +320,40 @@ class sf_production_plan(models.Model):
def calculate_plan_time(self, item, workorder_list): def calculate_plan_time(self, item, workorder_list):
""" """
根据CNC工单的时间去计算之前的其他工单的开始结束时间 根据CNC工单的时间去计算之前的其他工单的开始结束时间
param:
item: 基准工单(根据该工单的开始结束时间去计算其他工单的开始结束时间)
workorder_list: 需排程的工单列表
""" """
item_position = 0 item_position = 0
for index, workorder in enumerate(workorder_list): for index, workorder in enumerate(workorder_list):
if workorder.id == item.id: if workorder.id == item.id:
item_position = index item_position = index
break break
routing_workcenters = self.env['mrp.routing.workcenter'].sudo().search([])
# 记录所有前序工序时长
previous_workorder_duration = 0
for i in range(item_position, -1, -1): for i in range(item_position, -1, -1):
if i < 1: if i < 1:
break break
current_workorder = workorder_list[i] current_workorder = workorder_list[i]
next_workorder = workorder_list[i - 1] next_workorder = workorder_list[i - 1]
routing_workcenter = routing_workcenters.filtered(lambda x: x.name == next_workorder.name)[0] routing_workcenter = next_workorder.technology_design_id.route_id
# 设置一个小的开始时间 # 设置一个小的开始时间
next_workorder.date_planned_start = datetime.now() - timedelta(days=100) next_workorder.date_planned_start = datetime.now() - timedelta(days=100)
next_workorder.date_planned_finished = current_workorder.date_planned_start next_workorder.date_planned_finished = current_workorder.date_planned_start
next_workorder.date_planned_start = next_workorder.date_planned_finished - timedelta( next_workorder.date_planned_start = next_workorder.date_planned_finished - timedelta(
minutes=routing_workcenter.time_cycle) minutes=routing_workcenter.time_cycle + routing_workcenter.reserved_duration)
next_workorder.duration_expected = routing_workcenter.time_cycle next_workorder.duration_expected = routing_workcenter.time_cycle + routing_workcenter.reserved_duration
previous_workorder_duration += routing_workcenter.time_cycle
# 记录所有后续工序时长
next_workorder_duration = 0
for i in range(item_position, len(workorder_list) - 1): for i in range(item_position, len(workorder_list) - 1):
if i > len(workorder_list) - 1: if i > len(workorder_list) - 1:
break break
current_workorder = workorder_list[i] current_workorder = workorder_list[i]
next_workorder = workorder_list[i + 1] next_workorder = workorder_list[i + 1]
routing_workcenter = routing_workcenters.filtered(lambda x: x.name == next_workorder.name)[0] routing_workcenter = next_workorder.technology_design_id.route_id
# 设置一个小的开始时间 # 设置一个小的开始时间
next_workorder.date_planned_start = datetime.now() - timedelta(days=100) next_workorder.date_planned_start = datetime.now() - timedelta(days=100)
next_workorder.date_planned_finished = current_workorder.date_planned_finished + timedelta( next_workorder.date_planned_finished = current_workorder.date_planned_finished + timedelta(
minutes=routing_workcenter.time_cycle) minutes=routing_workcenter.time_cycle + routing_workcenter.reserved_duration)
next_workorder.date_planned_start = current_workorder.date_planned_finished next_workorder.date_planned_start = current_workorder.date_planned_finished
next_workorder.duration_expected = routing_workcenter.time_cycle next_workorder.duration_expected = routing_workcenter.time_cycle + routing_workcenter.reserved_duration
next_workorder_duration += routing_workcenter.time_cycle
return previous_workorder_duration, next_workorder_duration
def calculate_plan_time_after(self, item, workorder_id_list): def calculate_plan_time_after(self, item, workorder_id_list):
""" """

View File

@@ -17,6 +17,8 @@
decoration-danger="state == 'finished'"/> decoration-danger="state == 'finished'"/>
<field name="name"/> <field name="name"/>
<field name="origin"/> <field name="origin"/>
<field name="part_number" optional="show"/>
<field name="part_name" optional="hide"/>
<field name="order_deadline" widget="date"/> <field name="order_deadline" widget="date"/>
<field name="product_qty"/> <field name="product_qty"/>
<field name="production_line_id"/> <field name="production_line_id"/>
@@ -257,7 +259,7 @@
<record id="sf_production_plan_action" model="ir.actions.act_window"> <record id="sf_production_plan_action" model="ir.actions.act_window">
<field name="name">制造订单生产计划</field> <field name="name">CNC产线计划排程</field>
<field name="type">ir.actions.act_window</field> <field name="type">ir.actions.act_window</field>
<field name="res_model">sf.production.plan</field> <field name="res_model">sf.production.plan</field>
<field name="view_mode">gantt,tree,form</field> <field name="view_mode">gantt,tree,form</field>

View File

@@ -2023,6 +2023,11 @@ msgstr "<span class=\"o_stat_text\">损失</span>"
msgid "<span class=\"o_stat_text\">Maintenance</span>" msgid "<span class=\"o_stat_text\">Maintenance</span>"
msgstr "" msgstr ""
#. module: sf_manufacturing
#: model:ir.model.fields.selection,name:sf_manufacturing.selection__mrp_production__state__confirmed
msgid "待排程"
msgstr "待排程"
#. module: mrp #. module: mrp
#: model_terms:ir.ui.view,arch_db:mrp.product_product_form_view_bom_button #: model_terms:ir.ui.view,arch_db:mrp.product_product_form_view_bom_button
#: model_terms:ir.ui.view,arch_db:mrp.product_template_form_view_bom_button #: model_terms:ir.ui.view,arch_db:mrp.product_template_form_view_bom_button
@@ -6678,7 +6683,7 @@ msgstr "账单状态"
#: model_terms:ir.ui.view,arch_db:account.account_journal_dashboard_kanban_view #: model_terms:ir.ui.view,arch_db:account.account_journal_dashboard_kanban_view
#, python-format #, python-format
msgid "Bills" msgid "Bills"
msgstr "账单" msgstr "发票账单"
#. module: account #. module: account
#: model_terms:ir.ui.view,arch_db:account.account_journal_dashboard_kanban_view #: model_terms:ir.ui.view,arch_db:account.account_journal_dashboard_kanban_view
@@ -15907,7 +15912,7 @@ msgstr "内部参考"
#: model_terms:ir.ui.view,arch_db:account.account_journal_dashboard_kanban_view #: model_terms:ir.ui.view,arch_db:account.account_journal_dashboard_kanban_view
#, python-format #, python-format
msgid "Internal Transfer" msgid "Internal Transfer"
msgstr "内部转账" msgstr "厂内出入库"
#. module: account #. module: account
#: model:ir.model.fields,field_description:account.field_res_config_settings__transfer_account_id #: model:ir.model.fields,field_description:account.field_res_config_settings__transfer_account_id
@@ -16133,7 +16138,7 @@ msgstr "库存概览"
#. module: stock #. module: stock
#: model:ir.actions.act_window,name:stock.stock_picking_type_action #: model:ir.actions.act_window,name:stock.stock_picking_type_action
msgid "Internal Transfers" msgid "Internal Transfers"
msgstr "厂内出入库" msgstr "库存概览"
#. module: stock #. module: stock
#: model:ir.model.fields,field_description:stock.field_stock_quant__inventory_quantity_set #: model:ir.model.fields,field_description:stock.field_stock_quant__inventory_quantity_set
@@ -23023,7 +23028,7 @@ msgstr "支付:支付收据"
#: model_terms:ir.ui.view,arch_db:account.view_account_payment_search #: model_terms:ir.ui.view,arch_db:account.view_account_payment_search
#, python-format #, python-format
msgid "Payments" msgid "Payments"
msgstr "付" msgstr "付款单"
#. module: account #. module: account
#: model_terms:ir.actions.act_window,help:account.action_account_payments #: model_terms:ir.actions.act_window,help:account.action_account_payments

View File

@@ -16,7 +16,7 @@ class SfQualityCncTest(models.Model):
equipment_id = fields.Many2one(related='workorder_id.equipment_id', string='加工设备') equipment_id = fields.Many2one(related='workorder_id.equipment_id', string='加工设备')
production_line_id = fields.Many2one(related='workorder_id.production_line_id', production_line_id = fields.Many2one(related='workorder_id.production_line_id',
string='生产线') string='生产线')
part_number = fields.Char(related='workorder_id.part_number', string='成品零件图号') part_number = fields.Char(related='workorder_id.part_number', string='零件图号')
detection_report = fields.Binary(related='workorder_id.detection_report', readonly=True, string='检测报告') detection_report = fields.Binary(related='workorder_id.detection_report', readonly=True, string='检测报告')
state = fields.Selection([ state = fields.Selection([
('waiting', '待判定'), ('waiting', '待判定'),
@@ -25,7 +25,7 @@ class SfQualityCncTest(models.Model):
('pass', '合格'), ('pass', '合格'),
('fail', '不合格')], string='判定结果') ('fail', '不合格')], string='判定结果')
number = fields.Integer('数量', default=1) number = fields.Integer('数量', default=1)
test_results = fields.Selection([("合格", "合格"), ("返工", "返工"), ("报废", "报废")], string="检测结果") test_results = fields.Selection([("合格", "合格"), ("返工", "返工")], string="检测结果")
reason = fields.Selection( reason = fields.Selection(
[("programming", "编程"), ("cutter", "刀具"), ("clamping", "装夹"), ("operate computer", "操机"), [("programming", "编程"), ("cutter", "刀具"), ("clamping", "装夹"), ("operate computer", "操机"),
("technology", "工艺"), ("customer redrawing", "客户改图")], string="原因") ("technology", "工艺"), ("customer redrawing", "客户改图")], string="原因")

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