Compare commits

..

178 Commits

Author SHA1 Message Date
guanhuan
d896118ea9 报废不申请重新编程时新生成的制造订单没有程序 2025-01-21 16:23:23 +08:00
胡尧
39b29960e3 Accept Merge Request #1786: (feature/验证合并的逻辑 -> develop)
Merge Request: Merge branch 'develop' into feature/验证合并的逻辑

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1786?initial=true
2025-01-21 10:40:27 +08:00
胡尧
6abb237491 Merge branch 'develop' into feature/验证合并的逻辑 2025-01-21 10:39:41 +08:00
胡尧
b0c043676c Accept Merge Request #1785: (release/release_2.8 -> develop)
Merge Request: 优化工件下产线,修改CNC加工工单状态为待检测时,同步修改对应质检单状态为待处理

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1785?initial=true
2025-01-21 10:39:19 +08:00
yuxianghui
8f9b7b2fb0 优化工件下产线,修改CNC加工工单状态为待检测时,同步修改对应质检单状态为待处理 2025-01-20 15:39:08 +08:00
mgw
32255af3a3 申请编程状态 2025-01-20 14:53:26 +08:00
yuxianghui
955b6a6213 工单优化 2025-01-20 14:47:09 +08:00
yuxianghui
8e788d3745 处理CNC加工工单通过接口上产线下产线变更为待检测时,对应质检单还是等待状态问题 2025-01-20 14:18:02 +08:00
guanhuan
dc843588e9 制造列表新增编程状态显示 2025-01-20 14:09:23 +08:00
马广威
8bfe5eca03 Accept Merge Request #1783: (feature/制造功能优化 -> develop)
Merge Request: 申请编程状态控制

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1783?initial=true
2025-01-20 14:04:27 +08:00
mgw
dbcf8b1089 申请编程状态控制 2025-01-20 14:02:54 +08:00
yuxianghui
0bf701e743 质检单状态优化 2025-01-20 12:55:12 +08:00
yuxianghui
a96a9f5b75 1、修改工单检测结果只读条件;2、修改质检单完成时同步完成工单判断条件;3、去除只有配置后置三元检测的工单才能看到质检单对应字段、页签的判断条件 2025-01-20 12:47:11 +08:00
yuxianghui
9e2704f726 新增工单送检按钮显示的时候隐藏完成按钮 2025-01-20 10:34:32 +08:00
胡尧
c436bbea46 Merge branch 'release/release_2.8' into feature/验证合并的逻辑 2025-01-17 16:12:27 +08:00
胡尧
47c73ae66e 处理订单行参数说明的精度问题 2025-01-17 15:20:50 +08:00
黄焱
53ceed4649 Accept Merge Request #1782: (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/1782?initial=true
2025-01-17 14:22:56 +08:00
hyyy
e39e9d8812 放弃保存 -> 不保存 2025-01-17 14:17:46 +08:00
胡尧
0a01afc863 Accept Merge Request #1781: (feature/增加质检模块 -> develop)
Merge Request: 修复采购单没有接收产品的问题

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1781?initial=true
2025-01-17 12:55:39 +08:00
胡尧
98b338f33a 修复采购单没有接收产品的问题 2025-01-17 12:55:09 +08:00
胡尧
3c12b05b94 Accept Merge Request #1780: (feature/增加质检模块 -> develop)
Merge Request: 修复采购单没有接收产品的问题

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1780?initial=true
2025-01-17 11:27:40 +08:00
胡尧
b619c15231 修复采购单没有接收产品的问题 2025-01-17 11:27:04 +08:00
禹翔辉
bccdd93884 Accept Merge Request #1779: (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/1779?initial=true
2025-01-17 11:07:54 +08:00
yuxianghui
41cdeb7fd9 制造订单状态优化 2025-01-17 11:06:17 +08:00
马广威
57ab276c37 Accept Merge Request #1778: (feature/制造功能优化 -> develop)
Merge Request: 调整扫码字段位置

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1778?initial=true
2025-01-17 10:01:16 +08:00
mgw
f3e64b007e 调整扫码字段位置 2025-01-17 09:59:46 +08:00
mgw
eed89836e1 调整扫码字段位置 2025-01-17 09:36:37 +08:00
胡尧
19e1b16122 屏蔽将制造订单的补货组修改为不同的代码 2025-01-17 09:27:38 +08:00
马广威
9efa4636d9 Accept Merge Request #1777: (feature/制造功能优化 -> develop)
Merge Request: 恢复屏蔽

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1777?initial=true
2025-01-16 17:40:09 +08:00
mgw
0b2b9c2bf5 恢复屏蔽 2025-01-16 17:39:34 +08:00
马广威
cc5036ce64 Accept Merge Request #1776: (feature/制造功能优化 -> develop)
Merge Request: 调整扫码字段的位置

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1776?initial=true
2025-01-16 17:11:59 +08:00
mgw
2dc54792f4 调整扫码字段的位置 2025-01-16 17:10:55 +08:00
禹翔辉
5db877a54c Accept Merge Request #1775: (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/1775
2025-01-16 15:58:53 +08:00
yuxianghui
6bff1f2f64 优化工单的质量检查跳转按钮 2025-01-16 15:56:11 +08:00
禹翔辉
0aaa3bd5ba Accept Merge Request #1774: (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/1774
2025-01-16 15:42:18 +08:00
yuxianghui
39d6c8ae24 处理制造订单再次返工时,点击返工按钮报错 2025-01-16 15:41:07 +08:00
禹翔辉
2c56011502 Accept Merge Request #1773: (feature/质检单优化_1 -> develop)
Merge Request: Merge branch 'feature/制造订单状态优化' into feature/质检单优化_1

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1773
2025-01-16 14:53:50 +08:00
yuxianghui
1e71fc1b08 Merge branch 'feature/制造订单状态优化' into feature/质检单优化_1 2025-01-16 14:51:51 +08:00
yuxianghui
add528f0f3 1、质检单有关后置三元检测的字段和页签添加工单没有后置三元检测时隐藏的条件;2、工单添加质检单跳转按钮 2025-01-16 14:51:04 +08:00
马广威
b8cff4445d Accept Merge Request #1772: (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/1772?initial=true
2025-01-16 14:33:39 +08:00
mgw
a2d51ce04e Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2025-01-16 14:32:47 +08:00
mgw
109a093f86 调整审批状态 2025-01-16 14:32:21 +08:00
管欢
c7265bdb46 Accept Merge Request #1771: (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/1771
2025-01-16 12:50:47 +08:00
廖丹龙
f93edef2d3 Accept Merge Request #1770: (feature/customer_supply -> 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/1770
2025-01-16 12:42:28 +08:00
liaodanlong
5c780c7b82 客供料合并 2025-01-16 11:35:37 +08:00
liaodanlong
303fcd0430 修改采购单非询价状态只读 2025-01-16 11:24:21 +08:00
guanhuan
e57574783f 修复设备档案页面数据显示 2025-01-16 10:28:30 +08:00
禹翔辉
ff35374eee Accept Merge Request #1769: (feature/制造订单状态优化 -> develop)
Merge Request: Merge branch 'feature/返工功能优化' into feature/制造订单状态优化

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1769
2025-01-16 09:03:17 +08:00
yuxianghui
5b550952a2 Merge branch 'feature/返工功能优化' into feature/制造订单状态优化 2025-01-16 09:02:04 +08:00
yuxianghui
e3562e7ae3 1、制造订单状态优化 2025-01-16 09:01:11 +08:00
禹翔辉
229df40db4 Accept Merge Request #1768: (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/1768?initial=true
2025-01-15 15:52:44 +08:00
yuxianghui
5ff6fe73d4 点击制造订单触发返工的过滤条件优化 2025-01-15 15:40:19 +08:00
禹翔辉
1dd8eac32c Accept Merge Request #1767: (feature/返工功能优化 -> develop)
Merge Request: Merge branch 'feature/工单-制造订单优化' into feature/返工功能优化

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1767?initial=true
2025-01-15 14:47:16 +08:00
yuxianghui
93eb588f91 Merge branch 'feature/工单-制造订单优化' into feature/返工功能优化 2025-01-15 14:37:46 +08:00
yuxianghui
5297bf05d1 1、制造订单返工按钮添加新的显示条件;2、优化返工流程 2025-01-15 14:36:49 +08:00
马广威
9adfca6010 Accept Merge Request #1766: (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/1766?initial=true
2025-01-15 13:37:14 +08:00
mgw
03c317542a Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2025-01-15 13:36:34 +08:00
mgw
ece136e71e 解除屏蔽 2025-01-15 13:36:05 +08:00
马广威
e0452283f6 Accept Merge Request #1765: (feature/制造功能优化 -> develop)
Merge Request: 调整扫码widget

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1765?initial=true
2025-01-15 11:35:00 +08:00
禹翔辉
8ee98c52e4 Accept Merge Request #1764: (feature/工单-制造订单优化 -> develop)
Merge Request: Merge branch 'feature/质检单优化' into feature/工单-制造订单优化

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1764?initial=true
2025-01-15 11:27:55 +08:00
yuxianghui
1b9dbffcce Merge branch 'feature/质检单优化' into feature/工单-制造订单优化 2025-01-15 11:26:01 +08:00
yuxianghui
8d5d19ec69 1、质检单通过、失败按钮添加工单为返工时隐藏条件;2、处理夹具入库到夹具房时,夹具查询中夹具可用状态没有变更为可用问题;3、处理后置三元检测选择返工后制造订单状态没有变更为返工的问题 2025-01-15 11:25:00 +08:00
mgw
8bda70be71 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2025-01-15 10:19:42 +08:00
mgw
ca3015600a 调整扫码widget 2025-01-15 10:18:25 +08:00
马广威
09bd06774d Accept Merge Request #1763: (feature/制造功能优化 -> develop)
Merge Request: 调整下发更新进行中状态的制造订单

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1763?initial=true
2025-01-15 09:38:05 +08:00
mgw
eabe2aa9e9 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2025-01-15 09:37:20 +08:00
mgw
4b6fd72237 调整下发更新进行中状态的制造订单 2025-01-15 09:34:09 +08:00
胡尧
f79fa75a68 Accept Merge Request #1762: (feature/customer_supply -> 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/1762#mr-1762-review-218183
2025-01-15 08:43:31 +08:00
liaodanlong
f4f87555a8 排除坯料制造订单 2025-01-15 01:44:48 +08:00
liaodanlong
adbf5a6a0d 隐藏欠单 2025-01-14 21:03:27 +08:00
禹翔辉
19ff7b5eb4 Accept Merge Request #1761: (feature/质检单优化 -> develop)
Merge Request: Merge branch 'feature/工单-质检优化_3' into feature/质检单优化

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1761
2025-01-14 16:24:35 +08:00
yuxianghui
bf3256c4bc Merge branch 'feature/工单-质检优化_3' into feature/质检单优化 2025-01-14 16:22:59 +08:00
yuxianghui
847b7da8f7 处理 质检单确认合格或者不合格时报错 bug 2025-01-14 16:22:17 +08:00
马广威
61e08f20c7 Accept Merge Request #1760: (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/1760?initial=true
2025-01-14 16:22:08 +08:00
mgw
fc29791f1b Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2025-01-14 16:21:35 +08:00
mgw
2a9d19436a Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2025-01-14 16:21:07 +08:00
黄焱
e5762f7058 Accept Merge Request #1759: (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/1759?initial=true
2025-01-14 16:20:52 +08:00
hyyy
357bb15e72 修复-会计-供应商-发票账单新增明细行标题显示错位了 2025-01-14 16:18:34 +08:00
马广威
7de2e98464 Accept Merge Request #1758: (feature/制造功能优化 -> develop)
Merge Request: 直接使用recordset

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1758?initial=true
2025-01-14 16:04:22 +08:00
mgw
78a9c59cde 直接使用recordset 2025-01-14 16:03:28 +08:00
马广威
18365de57e Accept Merge Request #1757: (feature/制造功能优化 -> develop)
Merge Request: 调整取值对象

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1757?initial=true
2025-01-14 15:54:26 +08:00
mgw
90644a705b Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2025-01-14 15:53:35 +08:00
mgw
5106067882 调整取值对象 2025-01-14 15:52:09 +08:00
胡尧
79bd5344ad Accept Merge Request #1756: (feature/增加质检模块 -> develop)
Merge Request: 解决收藏报错的问题

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1756?initial=true
2025-01-14 15:50:21 +08:00
胡尧
833b7ff78b Accept Merge Request #1755: (feature/customer_supply -> 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/1755
2025-01-14 15:49:59 +08:00
胡尧
b9d95c0751 解决收藏报错的问题 2025-01-14 15:48:49 +08:00
liaodanlong
e5f15661ce 采购单重复产品限制去除 2025-01-14 15:10:22 +08:00
禹翔辉
33ee5cb172 Accept Merge Request #1754: (feature/工单-质检优化_3 -> develop)
Merge Request: Merge branch 'feature/工单-质检优化_2' into feature/工单-质检优化_3

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1754
2025-01-14 15:09:58 +08:00
yuxianghui
b433c6423b Merge branch 'feature/工单-质检优化_2' into feature/工单-质检优化_3 2025-01-14 15:08:42 +08:00
yuxianghui
eae310ddad 1、工单、质检单优化 2025-01-14 15:07:53 +08:00
廖丹龙
deff14b4d3 Accept Merge Request #1753: (feature/customer_supply -> 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/1753
2025-01-14 14:17:26 +08:00
liaodanlong
9d6baee082 客供料与非客供料分开合并 2025-01-14 14:12:08 +08:00
管欢
47c54107f1 Accept Merge Request #1752: (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/1752
2025-01-14 13:53:17 +08:00
马广威
551e6e0a02 Accept Merge Request #1751: (feature/制造功能优化 -> develop)
Merge Request: 调整提示词

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1751?initial=true
2025-01-14 13:29:08 +08:00
mgw
f992d625bb Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2025-01-14 13:28:33 +08:00
mgw
883d6938e5 调整提示词 2025-01-14 13:28:08 +08:00
胡尧
37a5e37ed4 Accept Merge Request #1750: (feature/增加质检模块 -> develop)
Merge Request: 修改模块翻译

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1750?initial=true
2025-01-14 13:26:48 +08:00
胡尧
4aa6b59204 修改模块翻译 2025-01-14 13:25:52 +08:00
马广威
489ecc8028 Accept Merge Request #1749: (feature/制造功能优化 -> develop)
Merge Request: 调整编程记录生成

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1749?initial=true
2025-01-14 11:13:10 +08:00
mgw
bb5126d4f5 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2025-01-14 11:12:41 +08:00
mgw
40603fea6a 调整编程记录生成 2025-01-14 11:12:07 +08:00
禹翔辉
0a718b9836 Accept Merge Request #1748: (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/1748?initial=true
2025-01-14 10:42:36 +08:00
yuxianghui
f44dff2106 Merge branch 'feature/工单-质检优化_1' into feature/工单-质检优化_2 2025-01-14 10:40:56 +08:00
yuxianghui
07d854a740 处理质检结果为返工时,制造订单状态没有更改为返工的问题 2025-01-14 09:25:06 +08:00
马广威
fa80d42fc0 Accept Merge Request #1747: (feature/制造功能优化 -> develop)
Merge Request: 调整判断条件

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1747?initial=true
2025-01-14 08:48:14 +08:00
mgw
86747b77a6 调整判断条件 2025-01-14 08:47:30 +08:00
马广威
cc6fc450d9 Accept Merge Request #1746: (feature/制造功能优化 -> develop)
Merge Request: 解除屏蔽

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1746?initial=true
2025-01-14 08:42:06 +08:00
mgw
5865aab25c 解除屏蔽 2025-01-14 08:41:41 +08:00
马广威
9292fa29e6 Accept Merge Request #1745: (feature/制造功能优化 -> develop)
Merge Request: 解除状态限制屏蔽

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1745?initial=true
2025-01-14 08:34:34 +08:00
mgw
8b5740ece2 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2025-01-14 08:33:57 +08:00
mgw
63ca6f5856 解除状态限制屏蔽 2025-01-14 08:33:34 +08:00
马广威
dfd2082871 Accept Merge Request #1744: (feature/制造功能优化 -> develop)
Merge Request: 调整首次下发理由

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1744?initial=true
2025-01-13 17:32:25 +08:00
mgw
587370fe54 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2025-01-13 17:31:23 +08:00
mgw
f29582ef07 调整首次下发理由 2025-01-13 17:30:23 +08:00
秦圣
0d3a1f063c Accept Merge Request #1743: (feature/customer_supply -> develop)
Merge Request: 代码合并

Created By: @廖丹龙
Accepted By: @秦圣
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1743
2025-01-13 17:16:56 +08:00
liaodanlong
6cf4bf1005 代码合并 2025-01-13 17:16:22 +08:00
黄焱
119e4b9590 Accept Merge Request #1742: (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/1742?initial=true
2025-01-13 17:09:07 +08:00
hyyy
4467865b86 取消 -> 放弃保存 2025-01-13 17:04:00 +08:00
秦圣
2756edd6bc Accept Merge Request #1741: (feature/customer_supply -> develop)
Merge Request: 采购单取消错误提示修改

Created By: @廖丹龙
Accepted By: @秦圣
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1741
2025-01-13 17:03:17 +08:00
liaodanlong
b87343f017 采购单取消错误提示修改 2025-01-13 17:02:41 +08:00
马广威
ece4a0adba Accept Merge Request #1740: (feature/制造功能优化 -> develop)
Merge Request: 调整写入编程记录的位置

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1740?initial=true
2025-01-13 16:58:14 +08:00
mgw
80384e3244 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化
# Conflicts:
#	sf_manufacturing/models/mrp_production.py
2025-01-13 16:56:49 +08:00
mgw
d8a816c90e 调整写入编程记录的位置 2025-01-13 16:51:25 +08:00
秦圣
266927f53b Accept Merge Request #1739: (feature/customer_supply -> develop)
Merge Request: 工艺确认后的错误提示

Created By: @廖丹龙
Accepted By: @秦圣
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1739
2025-01-13 16:47:45 +08:00
liaodanlong
b398d1236e 工艺确认后的错误提示 2025-01-13 16:46:13 +08:00
秦圣
d626303a2d Accept Merge Request #1738: (feature/customer_supply -> develop)
Merge Request: 采购单参考销售订单可见性设置

Created By: @廖丹龙
Accepted By: @秦圣
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1738
2025-01-13 16:11:13 +08:00
liaodanlong
a8271d851d 采购单参考销售订单可见性设置 2025-01-13 16:09:51 +08:00
liaodanlong
bf4d06e22b 制造订单调拨单合并排除自加工产品 2025-01-13 16:08:51 +08:00
禹翔辉
45baac492a Accept Merge Request #1737: (feature/工单-质检优化_1 -> develop)
Merge Request: Merge branch 'feature/工单-质检优化' into feature/工单-质检优化_1

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1737
2025-01-13 15:46:31 +08:00
yuxianghui
3de86cf538 Merge branch 'feature/工单-质检优化' into feature/工单-质检优化_1 2025-01-13 15:08:04 +08:00
yuxianghui
186dca4618 1、取消质量检查页面根据指令检查自动筛选;2、修改送检按钮隐藏条件;3、优化工单后置三元检测page页显示时,检测结果选择返工时制造订单没有生成检测结果记录问题 2025-01-13 15:07:08 +08:00
马广威
29a6102620 Accept Merge Request #1736: (feature/制造功能优化 -> develop)
Merge Request: 调整码值

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1736?initial=true
2025-01-13 14:00:52 +08:00
mgw
b2c6c9c27d 调整码值 2025-01-13 14:00:20 +08:00
马广威
8d130609f1 Accept Merge Request #1735: (feature/制造功能优化 -> develop)
Merge Request: 调整爆出位置

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1735?initial=true
2025-01-13 13:52:10 +08:00
mgw
ed6e326539 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2025-01-13 13:51:35 +08:00
mgw
be9846986f 调整爆出位置 2025-01-13 13:51:07 +08:00
秦圣
005fa10539 Accept Merge Request #1734: (feature/customer_supply -> develop)
Merge Request: cloud 静态资源库同步问题

Created By: @廖丹龙
Accepted By: @秦圣
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1734
2025-01-13 13:42:08 +08:00
liaodanlong
e8e05bbf6d cloud 镜头资源库同步问题 2025-01-13 13:40:28 +08:00
马广威
bfc4752e2c Accept Merge Request #1733: (feature/制造功能优化 -> develop)
Merge Request: 对程序用刀增加补充逻辑

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1733?initial=true
2025-01-13 13:16:50 +08:00
mgw
332a44e861 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2025-01-13 13:16:15 +08:00
mgw
d6325bd483 对程序用刀增加补充逻辑 2025-01-13 13:15:44 +08:00
廖丹龙
1820be6691 Accept Merge Request #1732: (feature/customer_supply -> 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/1732
2025-01-13 13:03:40 +08:00
liaodanlong
6ac3bbe2af 外协工单采购单关联产品展示 2025-01-13 12:57:21 +08:00
秦圣
a2a8ea5ab1 Accept Merge Request #1731: (feature/customer_supply -> develop)
Merge Request: 客供料合并,坯料制造订单问题处理

Created By: @廖丹龙
Accepted By: @秦圣
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1731
2025-01-13 11:35:03 +08:00
liaodanlong
d5c65fdc6c 客供料合并,坯料制造订单问题处理 2025-01-13 11:31:24 +08:00
马广威
922a8fca82 Accept Merge Request #1730: (feature/制造功能优化 -> develop)
Merge Request: 申请编程需求

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1730?initial=true
2025-01-13 11:12:33 +08:00
mgw
6a3a739e2c Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2025-01-13 11:11:33 +08:00
mgw
6b6f091da8 更新编程记录相关 2025-01-13 11:11:09 +08:00
管欢
a78b1c7eaf Accept Merge Request #1729: (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/1729
2025-01-13 10:56:28 +08:00
mgw
9dfe9ba572 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2025-01-13 09:08:38 +08:00
禹翔辉
0eaafbf11b Accept Merge Request #1727: (feature/工单-质检优化 -> develop)
Merge Request: Merge branch 'feature/质检优化_1' into feature/工单-质检优化

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1727
2025-01-10 17:27:37 +08:00
yuxianghui
66922f726a Merge branch 'feature/质检优化_1' into feature/工单-质检优化 2025-01-10 17:26:08 +08:00
yuxianghui
629995ad9c 1、完成<工单>通用调整配置优化;2、完成<工单>后置三元检测和质检单逻辑判断及结果同步优化;3、工单新增【送检】功能按钮; 2025-01-10 17:25:19 +08:00
管欢
2323c888b4 Accept Merge Request #1726: (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/1726
2025-01-10 13:22:38 +08:00
廖丹龙
52bba95c93 Accept Merge Request #1725: (feature/customer_supply -> 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/1725
2025-01-10 11:10:07 +08:00
liaodanlong
a6c8cd8784 采购单合并后确认工单外协工序为就绪问题 2025-01-10 11:08:45 +08:00
mgw
28d3d6fe60 更新编程记录 2025-01-10 10:20:23 +08:00
廖丹龙
5a4ca414a5 Accept Merge Request #1723: (feature/customer_supply -> 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/1723?initial=true
2025-01-10 10:03:02 +08:00
胡尧
64a0009692 Accept Merge Request #1724: (feature/增加质检模块 -> develop)
Merge Request: 检测结果增加创建人,时间,处理人,时间

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1724?initial=true
2025-01-10 09:58:53 +08:00
胡尧
22bac48a98 检测结果增加创建人,时间,处理人,时间 2025-01-10 09:57:06 +08:00
mgw
47f8e5dc1c Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2025-01-10 09:35:16 +08:00
mgw
8589da1b4d 增加多种状态对编程记录的更改 2025-01-10 09:34:38 +08:00
liaodanlong
5e8a69e252 Merge branch 'refs/heads/develop' into feature/customer_supply 2025-01-10 09:23:02 +08:00
禹翔辉
937145a542 Accept Merge Request #1722: (feature/质检优化_1 -> 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/1722
2025-01-09 17:24:29 +08:00
yuxianghui
4c97719e68 Merge branch 'feature/质检优化' into feature/质检优化_1 2025-01-09 17:22:54 +08:00
liaodanlong
7e9e6d0738 工艺确认修改采购单状态变动逻辑 2025-01-09 17:22:40 +08:00
liaodanlong
e27506fb07 错误信息修改与委外加工单报错处理 2025-01-09 17:22:03 +08:00
yuxianghui
8d0e993d1a 1、取消工单点击开始按钮二次确认;2、优化质量控制标准模型;3、完成<质量_质量检查>通用调整优化, 2025-01-09 17:20:18 +08:00
mgw
4b5661108a Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化
# Conflicts:
#	sf_manufacturing/security/ir.model.access.csv
2025-01-09 16:14:23 +08:00
liaodanlong
1084f4db12 错误信息修改 2025-01-09 16:12:56 +08:00
mgw
aaf72d5e35 调整数据源 2025-01-09 16:12:54 +08:00
廖丹龙
bb241095e2 Accept Merge Request #1721: (feature/customer_supply -> 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/1721
2025-01-09 14:35:09 +08:00
liaodanlong
ebf290fbb3 客供料调拨单合并 2025-01-09 14:32:17 +08:00
mgw
fc16c867aa 申请编程需求 2025-01-09 14:07:35 +08:00
禹翔辉
0d3d3284ff Accept Merge Request #1720: (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/1720?initial=true
2025-01-08 17:26:19 +08:00
yuxianghui
1a384b9902 1、优化制造-工序模块;2、新增工序个性化记录模型,并添加生成初始化值; 2025-01-08 17:24:58 +08:00
廖丹龙
c4b2a42ac5 Accept Merge Request #1719: (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/1719
2025-01-08 13:38:54 +08:00
liaodanlong
284234adf2 合并代码部分还原 2025-01-08 13:37:48 +08:00
44 changed files with 1082 additions and 343 deletions

View File

@@ -22,6 +22,7 @@
width: 50px; width: 50px;
height: 50px; height: 50px;
margin-bottom: 5px; margin-bottom: 5px;
margin-top: 15px;
} }
.item-label { .item-label {

View File

@@ -62,7 +62,7 @@ patch(FormStatusIndicator.prototype, 'jikimo_frontend.FormStatusIndicator', {
const dom1 = buttonsDom.children('.o_form_button_save') const dom1 = buttonsDom.children('.o_form_button_save')
const dom2 = buttonsDom.children('.o_form_button_cancel') const dom2 = buttonsDom.children('.o_form_button_cancel')
dom1.append('保存') dom1.append('保存')
dom2.append('取消') dom2.append('不保存')
} }
} catch (e) { } catch (e) {
console.log(e) console.log(e)
@@ -141,6 +141,9 @@ patch(ListRenderer.prototype, 'jikimo_frontend.ListRenderer', {
this.setRequired() this.setRequired()
this.listherHeaderBodyNum() this.listherHeaderBodyNum()
}) })
owl.onPatched(() => {
this.listherHeaderBodyNum()
})
return this._super(...arguments); return this._super(...arguments);
}, },
setRequired() { setRequired() {

View File

@@ -21,13 +21,23 @@ class jikimo_purchase_tier_validation(models.Model):
def button_confirm(self): def button_confirm(self):
for record in self: for record in self:
if record.need_validation and record.validation_status != 'validated': # if record.need_validation and record.validation_status != 'validated':
raise ValidationError(_('此操作需要至少对一条记录进行审批。\n请发起审批申请。')) # raise ValidationError(_('此操作需要至少对一条记录进行审批。\n请发起审批申请。'))
if record.state in ['to approve']: if record.state in ['to approve']:
raise ValidationError(_('请先完成审批。')) raise ValidationError(_('请先完成审批。'))
# if record.state == 'approved':
# record.state = 'purchase'
res = super(jikimo_purchase_tier_validation, self).button_confirm()
for record in self:
if record.state == 'approved': if record.state == 'approved':
record.state = 'purchase' record.order_line._validate_analytic_distribution()
return super().button_confirm() record._add_supplier_to_product()
# Deal with double validation process
if record._approval_allowed():
record.button_approve()
if record.partner_id not in record.message_partner_ids:
record.message_subscribe([record.partner_id.id])
return res
# def button_confirm(self): # def button_confirm(self):
# self = self.with_context(skip_validation=True) # self = self.with_context(skip_validation=True)
@@ -87,15 +97,14 @@ class jikimo_purchase_tier_validation(models.Model):
def _validate_tier(self, tiers=False): def _validate_tier(self, tiers=False):
res = super(jikimo_purchase_tier_validation, self)._validate_tier(tiers) res = super(jikimo_purchase_tier_validation, self)._validate_tier(tiers)
tier_reviews = tiers or self.review_ids
# 检查是否所有审批都已通过 # 检查是否所有审批都已通过
all_approved = all( all_approved = all(
tier_review.status == 'approved' tier_review.status == 'approved'
for tier_review in tier_reviews for tier_review in self.review_ids
) )
if all_approved and tier_reviews: # 确保有审批记录 if self.review_ids and all_approved: # 确保有审批记录
self.state = 'approved' self.state = 'approved'
return res return res
@@ -200,16 +209,16 @@ class jikimo_purchase_tier_validation(models.Model):
} }
class jikimo_purchase_request(models.Model): # class jikimo_purchase_request(models.Model):
_inherit = 'purchase.request' # _inherit = 'purchase.request'
_description = "采购申请" # _description = "采购申请"
class jikimo_account_payment(models.Model): # class jikimo_account_payment(models.Model):
_inherit = 'account.payment' # _inherit = 'account.payment'
_description = "付款单" # _description = "付款单"
class jikimo_account_move(models.Model): # class jikimo_account_move(models.Model):
_inherit = 'account.move' # _inherit = 'account.move'
_description = "发票账单" # _description = "发票账单"

View File

@@ -7,6 +7,7 @@
<field name="inherit_id" ref="mrp.mrp_production_workorder_form_view_inherit"/> <field name="inherit_id" ref="mrp.mrp_production_workorder_form_view_inherit"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//notebook/page[last()]" position="after"> <xpath expr="//notebook/page[last()]" position="after">
<field name="routing_type" invisible="1"/>
<page string="异常记录" name="workorder_exception" attrs="{'invisible': [('routing_type', '!=', 'CNC加工')]}"> <page string="异常记录" name="workorder_exception" attrs="{'invisible': [('routing_type', '!=', 'CNC加工')]}">
<field name="exception_ids" nolabel="1" readonly="1"> <field name="exception_ids" nolabel="1" readonly="1">
<tree create="false" delete="false" edit="false"> <tree create="false" delete="false" edit="false">

View File

@@ -140,7 +140,4 @@
</field> </field>
</record> </record>
<record id="quality_control.quality_check_action_main" model="ir.actions.act_window">
<field name="context">{'search_default_quality_checks': 1}</field>
</record>
</odoo> </odoo>

View File

@@ -16,6 +16,7 @@
'data/stock_data.xml', 'data/stock_data.xml',
'data/empty_racks_data.xml', 'data/empty_racks_data.xml',
'data/panel_data.xml', 'data/panel_data.xml',
'data/sf_work_individuation_page.xml',
'data/agv_scheduling_data.xml', 'data/agv_scheduling_data.xml',
'security/group_security.xml', 'security/group_security.xml',
'security/ir.model.access.csv', 'security/ir.model.access.csv',
@@ -25,6 +26,7 @@
'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', 'wizard/mrp_workorder_batch_replan_wizard_views.xml',
'wizard/sf_programming_reason_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',
@@ -57,6 +59,7 @@
'sf_manufacturing/static/src/js/agv_scheduling_cancel_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',
'sf_manufacturing/static/src/scss/equipment_spacing.scss',
] ]
}, },

View File

@@ -596,6 +596,9 @@ class Manufacturing_Connect(http.Controller):
if panel_workorder: if panel_workorder:
panel_workorder.write({'production_line_state': '已下产线'}) panel_workorder.write({'production_line_state': '已下产线'})
workorder.write({'state': 'to be detected'}) workorder.write({'state': 'to be detected'})
workorder.check_ids.filtered(
lambda ch: ch.quality_state == 'waiting').write(
{'quality_state': 'none'})
else: else:
res = {'Succeed': False, 'ErrorCode': 204, res = {'Succeed': False, 'ErrorCode': 204,
'Error': 'DeviceId为%s没有对应的已配送工件数据' % ret['DeviceId']} 'Error': 'DeviceId为%s没有对应的已配送工件数据' % ret['DeviceId']}

View File

@@ -0,0 +1,8 @@
<odoo>
<data noupdate="1">
<record model="sf.work.individuation.page" id="sf_work_individuation_page_1">
<field name="code">PTD</field>
<field name="name">后置三元检测</field>
</record>
</data>
</odoo>

View File

@@ -15,4 +15,5 @@ from . import sf_technology_design
from . import sf_production_common from . import sf_production_common
from . import sale_order from . import sale_order
from . import quick_easy_order from . import quick_easy_order
from . import purchase_order from . import purchase_order
from . import quality_check

View File

@@ -55,7 +55,7 @@ class MrpProduction(models.Model):
production.sale_order_id = sale_order.id production.sale_order_id = sale_order.id
else: else:
logging.warning("No sale order found for production {} with product {} (name match: {})".format( logging.warning("No sale order found for production {} with product {} (name match: {})".format(
production.id, production.product_id.name, result)) production.id, production.product_id.name, result))
except Exception as e: except Exception as e:
logging.error("Error while fetching sale order for production {}: {}".format(production.id, str(e))) logging.error("Error while fetching sale order for production {}: {}".format(production.id, str(e)))
@@ -311,13 +311,6 @@ class MrpProduction(models.Model):
elif production.state == 'cancel' or (production.move_finished_ids and all( elif production.state == 'cancel' or (production.move_finished_ids and all(
move.state == 'cancel' for move in production.move_finished_ids)): move.state == 'cancel' for move in production.move_finished_ids)):
production.state = 'cancel' production.state = 'cancel'
elif (
production.state == 'done'
or (production.move_raw_ids and all(
move.state in ('cancel', 'done') for move in production.move_raw_ids))
and all(move.state in ('cancel', 'done') for move in production.move_finished_ids)
):
production.state = 'done'
elif production.workorder_ids and all( elif production.workorder_ids and all(
wo_state in ('done', 'cancel') for wo_state in production.workorder_ids.mapped('state')): wo_state in ('done', 'cancel') for wo_state in production.workorder_ids.mapped('state')):
production.state = 'to_close' production.state = 'to_close'
@@ -351,30 +344,25 @@ class MrpProduction(models.Model):
production.state = 'technology_to_confirmed' production.state = 'technology_to_confirmed'
if production.state == 'confirmed' and production.schedule_state == '已排': if production.state == 'confirmed' and production.schedule_state == '已排':
production.state = 'pending_cam' production.state = 'pending_cam'
if production.state == 'progress':
if all(wo_state not in ('progress', 'done', 'rework', 'scrap') for wo_state in
production.workorder_ids.mapped('state')):
production.state = 'pending_cam'
if production.is_rework is True:
production.state = 'rework'
if (production.state == 'rework' and production.tool_state == '0' if (production.state == 'rework' and production.tool_state == '0'
and production.schedule_state == '已排' and production.is_rework is False): and production.schedule_state == '已排' and production.is_rework is False):
production.state = 'pending_cam' production.state = 'pending_cam'
# if production.state == 'pending_cam': if any((wo.test_results == '返工' and wo.state == 'done' and
# if all(wo_state in 'done' for wo_state in production.workorder_ids.mapped('state')): (production.programming_state in ['已编程'] or wo.individuation_page_PTD is True))
# production.state = 'done' or (wo.is_rework is True and wo.state == 'done' and production.programming_state in ['编程中', '已编程'])
if any((wo.test_results == '返工' and wo.state == 'done' and production.programming_state in ['已编程']) for wo in production.workorder_ids) or production.is_rework is True:
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.workorder_ids and all(
wo_state in ('done', 'rework', 'cancel') for wo_state in production.workorder_ids.mapped('state')):
if production.state not in ['scrap', 'rework', 'cancel']: if production.state not in ['scrap', 'rework', 'cancel']:
production.state = 'done' production.state = 'done'
elif production.state == 'done':
production.state = 'progress'
# 退回调整 # 退回调整
def technology_back_adjust(self): def technology_back_adjust(self):
@@ -432,7 +420,7 @@ class MrpProduction(models.Model):
# 工艺确认 # 工艺确认
def technology_confirm(self): def technology_confirm(self):
process_parameters = [] process_parameters = []
account_moves = [] purchase_orders = []
parameters_not = [] parameters_not = []
# 获取原有的工单对应的工序 # 获取原有的工单对应的工序
origin_designs = self.workorder_ids.technology_design_id origin_designs = self.workorder_ids.technology_design_id
@@ -442,10 +430,8 @@ class MrpProduction(models.Model):
for deleted_design in deleted_designs: for deleted_design in deleted_designs:
workorder = self.env['mrp.workorder'].search([('technology_design_id', '=', deleted_design.id)]) workorder = self.env['mrp.workorder'].search([('technology_design_id', '=', deleted_design.id)])
purchase = workorder._get_surface_technics_purchase_ids() purchase = workorder._get_surface_technics_purchase_ids()
account = self.env['account.move'].search([('id', 'in', purchase.invoice_ids.ids)]) if purchase.state not in ['cancel', 'draft', False]:
if account.state not in ['cancel', False]: purchase_orders.append(purchase.name)
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:
@@ -457,9 +443,8 @@ class MrpProduction(models.Model):
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)
if purchase_orders:
if account_moves: raise UserError(_("请联系工厂生产经理对该(%s)采购订单进行取消", ", ".join(purchase_orders)))
raise UserError(_("请联系工厂生产经理对会计凭证为%s生成的账单进行取消", ", ".join([move.name for move in account_moves])))
if parameters_not: if parameters_not:
raise UserError(_("【工艺设计】-【工序】为%s未选择参数,请选择", ", ".join(parameters_not))) raise UserError(_("【工艺设计】-【工序】为%s未选择参数,请选择", ", ".join(parameters_not)))
if process_parameters: if process_parameters:
@@ -580,7 +565,7 @@ class MrpProduction(models.Model):
for rp in reproduction: for rp in reproduction:
if rp.programming_no == item['programming_no']: if rp.programming_no == item['programming_no']:
rp.write({'programming_state': '已编程未下发' if item[ rp.write({'programming_state': '已编程未下发' if item[
'programming_state'] == '已编程' else '编程中'}) 'programming_state'] == '已编程' else '编程中'})
else: else:
return item return item
@@ -591,7 +576,8 @@ class MrpProduction(models.Model):
logging.info('cron_get_programming_state error:%s' % e) logging.info('cron_get_programming_state error:%s' % e)
# 编程单更新 # 编程单更新
def update_programming_state(self): # 增加触发时间参数
def update_programming_state(self, trigger_time=None):
try: try:
manufacturing_type = 'rework' manufacturing_type = 'rework'
if self.is_scrap: if self.is_scrap:
@@ -599,7 +585,8 @@ class MrpProduction(models.Model):
elif self.tool_state == '2': elif self.tool_state == '2':
manufacturing_type = 'invalid_tool_rework' manufacturing_type = 'invalid_tool_rework'
res = {'programming_no': self.programming_no, res = {'programming_no': self.programming_no,
'manufacturing_type': manufacturing_type} 'manufacturing_type': manufacturing_type,
'trigger_time': trigger_time}
logging.info('res=%s:' % res) logging.info('res=%s:' % res)
configsettings = self.env['res.config.settings'].get_values() configsettings = self.env['res.config.settings'].get_values()
config_header = Common.get_headers(self, configsettings['token'], configsettings['sf_secret_key']) config_header = Common.get_headers(self, configsettings['token'], configsettings['sf_secret_key'])
@@ -613,6 +600,45 @@ class MrpProduction(models.Model):
self.write({'is_rework': True}) self.write({'is_rework': True})
else: else:
raise UserError(ret['message']) raise UserError(ret['message'])
# # 增加对编程记录的更新
# cloud_programming = self._cron_get_programming_state()
# if manufacturing_type == 'rework':
# self.programming_record_ids.create({
# 'number': len(self.programming_record_ids) + 1,
# 'production_id': self.id,
# 'reason': '返工',
# 'programming_method': cloud_programming['programme_way'],
# 'current_programming_count': cloud_programming['reprogramming_num'],
# 'target_production_id': cloud_programming['production_order_no'],
# 'apply_time': trigger_time,
# 'send_time': cloud_programming['send_time'],
# })
# elif manufacturing_type == 'scrap':
# self.programming_record_ids.create({
# 'number': len(self.programming_record_ids) + 1,
# 'production_id': self.id,
# 'reason': '报废',
# 'programming_method': cloud_programming['programme_way'],
# 'current_programming_count': cloud_programming['reprogramming_num'],
# 'target_production_id': cloud_programming['production_order_no'],
# 'apply_time': trigger_time,
# 'send_time': cloud_programming['send_time'],
# })
# elif manufacturing_type == 'invalid_tool_rework':
# self.programming_record_ids.create({
# 'number': len(self.programming_record_ids) + 1,
# 'production_id': self.id,
# 'reason': '无效功能刀具',
# 'programming_method': cloud_programming['programme_way'],
# 'current_programming_count': cloud_programming['reprogramming_num'],
# 'target_production_id': cloud_programming['production_order_no'],
# 'apply_time': trigger_time,
# 'send_time': cloud_programming['send_time'],
# })
# else:
# logging.info('无对应状态,不需更新编程记录')
except Exception as e: except Exception as e:
logging.info('update_programming_state error:%s' % e) logging.info('update_programming_state error:%s' % e)
raise UserError("更新编程单状态失败,请联系管理员") raise UserError("更新编程单状态失败,请联系管理员")
@@ -805,7 +831,7 @@ class MrpProduction(models.Model):
if process_parameter_workorder: if process_parameter_workorder:
# 将这些特殊表面工艺工单的采购单与调拨单置为失效 # 将这些特殊表面工艺工单的采购单与调拨单置为失效
for workorder in process_parameter_workorder: for workorder in process_parameter_workorder:
workorder._get_surface_technics_purchase_ids().write({'state': 'cancel'}) # workorder._get_surface_technics_purchase_ids().write({'state': 'cancel'})
workorder.move_subcontract_workorder_ids.write({'state': 'cancel'}) workorder.move_subcontract_workorder_ids.write({'state': 'cancel'})
workorder.move_subcontract_workorder_ids.picking_id.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)
@@ -929,8 +955,8 @@ class MrpProduction(models.Model):
# 对工单进行逐个插入 # 对工单进行逐个插入
for work_id in work_ids: for work_id in work_ids:
order_rework_ids = rec.workorder_ids.filtered( order_rework_ids = rec.workorder_ids.filtered(
lambda item: (item.sequence > 0 and work_id.name == item.name lambda item: (item.sequence > 0 and work_id.name == item.name
and work_id.processing_panel == item.processing_panel)) and work_id.processing_panel == item.processing_panel))
order_rework_ids = sorted(order_rework_ids, key=lambda item: item.sequence, reverse=True) order_rework_ids = sorted(order_rework_ids, key=lambda item: item.sequence, reverse=True)
work_id.sequence = order_rework_ids[0].sequence + 1 work_id.sequence = order_rework_ids[0].sequence + 1
# 对该工单之后的工单工序进行加一 # 对该工单之后的工单工序进行加一
@@ -1208,6 +1234,8 @@ class MrpProduction(models.Model):
cloud_programming = None cloud_programming = None
if self.programming_state in ['已编程']: if self.programming_state in ['已编程']:
cloud_programming = self._cron_get_programming_state() cloud_programming = self._cron_get_programming_state()
elif self.programming_state is False:
cloud_programming = {}
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_id_list = [] work_id_list = []
if result_ids: if result_ids:
@@ -1228,9 +1256,9 @@ class MrpProduction(models.Model):
'default_production_id': self.id, 'default_production_id': self.id,
'default_workorder_ids': workorder_ids.ids if workorder_ids.ids != [] else self.workorder_ids.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_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.get('reprogramming_num') if cloud_programming else '',
'default_programming_state': cloud_programming['programming_state'], 'default_programming_state': cloud_programming.get('programming_state') if cloud_programming else '',
'default_is_reprogramming': True if cloud_programming['programming_state'] in ['已下发'] else False 'default_is_reprogramming': True if cloud_programming and (cloud_programming.get('programming_state') in ['已下发']) else False
} }
} }
@@ -1388,36 +1416,36 @@ class MrpProduction(models.Model):
# 'production_id': False}) # 'production_id': False})
# 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)])
for pick in stock_picking_remanufacture: # for pick in stock_picking_remanufacture:
if pick.name.startswith('WH/PC/') or pick.name.startswith('WH/INT/'): # if pick.name.startswith('WH/PC/') or pick.name.startswith('WH/INT/'):
if pick.move_ids: # if pick.move_ids:
product_type_id = pick.move_ids[0].product_id.categ_id # product_type_id = pick.move_ids[0].product_id.categ_id
if product_type_id.name == '坯料': # if product_type_id.name == '坯料':
location_id = self.env['stock.location'].search([('name', '=', '坯料存货区')]) # location_id = self.env['stock.location'].search([('name', '=', '坯料存货区')])
if not location_id: # if not location_id:
logging.info(f'没有搜索到【坯料存货区】: {location_id}') # logging.info(f'没有搜索到【坯料存货区】: {location_id}')
break # break
if pick.picking_type_id.name == '内部调拨': # if pick.picking_type_id.name == '内部调拨':
if pick.location_dest_id.product_type != product_type_id: # if pick.location_dest_id.product_type != product_type_id:
pick.location_dest_id = location_id.id # pick.location_dest_id = location_id.id
elif pick.picking_type_id.name == '生产发料': # elif pick.picking_type_id.name == '生产发料':
if pick.location_id.product_type != product_type_id: # if pick.location_id.product_type != product_type_id:
pick.location_id = location_id.id # pick.location_id = location_id.id
scarp_process_parameter_workorder = self.env['mrp.workorder'].search( # scarp_process_parameter_workorder = self.env['mrp.workorder'].search(
[('surface_technics_parameters_id', '!=', False), ('production_id', '=', self.id), # [('surface_technics_parameters_id', '!=', False), ('production_id', '=', self.id),
('is_subcontract', '=', True)]) # ('is_subcontract', '=', True)])
if scarp_process_parameter_workorder: # if scarp_process_parameter_workorder:
production_programming = self.env['mrp.production'].search( # production_programming = self.env['mrp.production'].search(
[('programming_no', '=', self.programming_no), ('id', '!=', productions.id)], order='name asc') # [('programming_no', '=', self.programming_no), ('id', '!=', productions.id)], order='name asc')
production_list = [production.name for production in production_programming] # production_list = [production.name for production in production_programming]
purchase_orders = self.env['purchase.order'].search([('origin', 'ilike', ','.join(production_list))]) # purchase_orders = self.env['purchase.order'].search([('origin', 'ilike', ','.join(production_list))])
for purchase_item in purchase_orders.order_line: # for purchase_item in purchase_orders.order_line:
for process_item in scarp_process_parameter_workorder: # for process_item in scarp_process_parameter_workorder:
if purchase_item.product_id.categ_type == '表面工艺': # if purchase_item.product_id.categ_type == '表面工艺':
if purchase_item.product_id.server_product_process_parameters_id == process_item.surface_technics_parameters_id: # if purchase_item.product_id.server_product_process_parameters_id == process_item.surface_technics_parameters_id:
if purchase_orders.origin.find(productions.name) == -1: # if purchase_orders.origin.find(productions.name) == -1:
purchase_orders.origin += ',' + productions.name # purchase_orders.origin += ',' + productions.name
if item['is_reprogramming'] is False: if item['is_reprogramming'] is False:
productions.programming_state = '已编程' productions.programming_state = '已编程'
else: else:
@@ -1487,6 +1515,7 @@ class MrpProduction(models.Model):
重载创建制造订单的方法,单个制造订单,同一成品只创建一个采购组,用于后续单据的创建 重载创建制造订单的方法,单个制造订单,同一成品只创建一个采购组,用于后续单据的创建
""" """
product_group_id = {} product_group_id = {}
is_custemer_group_id = {} # 客供料与非客供料
for vals in vals_list: for vals in vals_list:
if not vals.get('name', False) or vals['name'] == _('New'): if not vals.get('name', False) or vals['name'] == _('New'):
picking_type_id = vals.get('picking_type_id') picking_type_id = vals.get('picking_type_id')
@@ -1494,16 +1523,29 @@ class MrpProduction(models.Model):
picking_type_id = self._get_default_picking_type_id(vals.get('company_id', self.env.company.id)) picking_type_id = self._get_default_picking_type_id(vals.get('company_id', self.env.company.id))
vals['picking_type_id'] = picking_type_id vals['picking_type_id'] = picking_type_id
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()
product_id = self.env['product.product'].browse(vals['product_id'])
is_self_process = product_id.materials_type_id and product_id.materials_type_id.gain_way and product_id.materials_type_id.gain_way != '自加工'
is_customer_provided = product_id.is_customer_provided
key = f"{is_self_process}_{is_customer_provided}"
if not is_custemer_group_id.get(key):
is_custemer_group_id[key] = self.env["procurement.group"].create({'name': vals.get('name')}).id
# if not (is_first_customer or is_first_not_customer) and is_self_process:
# is_first = True
# group_id = self.env["procurement.group"].create({'name': vals.get('name')}).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'])
if product_id.product_tmpl_id.single_manufacturing: if product_id.product_tmpl_id.single_manufacturing:
if product_id.categ_id.name == '成品':
vals['procurement_group_id'] = is_custemer_group_id[key]
continue
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 procurement_group_id = self.env["procurement.group"].create(procurement_group_vals).id
vals['procurement_group_id'] = group_id vals['procurement_group_id'] = procurement_group_id
product_group_id[product_id.id] = group_id product_group_id[product_id.id] = procurement_group_id
else: else:
vals['procurement_group_id'] = product_group_id[product_id.id] vals['procurement_group_id'] = product_group_id[product_id.id]
else:
vals['procurement_group_id'] = is_custemer_group_id[key]
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', @api.depends('procurement_group_id.stock_move_ids.created_purchase_line_id.order_id',
@@ -1587,16 +1629,96 @@ class MrpProduction(models.Model):
_('You must enter a serial number for each line of %s') % sml.product_id.display_name) _('You must enter a serial number for each line of %s') % sml.product_id.display_name)
return True return True
reprogramming_count = fields.Integer(string='重新编程次数', default=0)
# 申请编程
def action_apply_programming(self):
"""
检查前置条件:制造订单【状态】=“待排程、待加工”,制造订单的【编程状态】=“已编程”。
"""
print('申请编程')
if len(self) > 1:
raise UserError('仅支持选择单个制造订单进行编程申请,请重新选择')
for production in self:
if production.state not in ['confirmed', 'pending_cam'] or production.programming_state != '已编程':
raise UserError('不可操作。所选制造订单必须同时满足如下条件:\n1、制造订单状态待排程 或 待加工;\n2、制造订单编程状态已编程。\n请检查!')
cloud_programming = production._cron_get_programming_state()
if cloud_programming['programming_state'] in ['待编程', '已编程', '编程中']:
raise UserError("当前编程单正在重新编程,请注意查看当前制造订单的“编程记录”确认进度!")
return {
'type': 'ir.actions.act_window',
'res_model': 'sf.programming.reason',
'view_mode': 'form',
'target': 'new',
'context': {
'default_production_id': self.id,
'active_id': self.id,
# 传当前时间
'default_apply_time': fields.Datetime.now(),
},
'view_id': self.env.ref('sf_manufacturing.sf_programming_reason_form_view').id,
}
# 编程记录
programming_record_ids = fields.One2many('sf.programming.record', 'production_id')
# 编程单更新
def re_programming_update_programming_state(self):
try:
res = {'programming_no': self.programming_no,
'manufacturing_type': ''}
logging.info('res=%s:' % res)
configsettings = self.env['res.config.settings'].get_values()
config_header = Common.get_headers(self, configsettings['token'], configsettings['sf_secret_key'])
url = '/api/intelligent_programming/reset_state_again'
config_url = configsettings['sf_url'] + url
ret = requests.post(config_url, json=res, data=None, headers=config_header)
# ret = ret.json()
# result = json.loads(ret['result'])
# logging.info('update_programming_state-ret:%s' % result)
# if result['status'] == 1:
# self.write({'is_rework': True})
# else:
# raise UserError(ret['message'])
except Exception as e:
logging.info('update_programming_state error:%s' % e)
raise UserError("更新编程单状态失败,请联系管理员")
# 编程记录
class sf_programming_record(models.Model):
_name = 'sf.programming.record'
_description = "编程记录"
production_id = fields.Many2one('mrp.production')
# 编号、编程原因、编程方式、当前编程次数、目标制造单号、申请时间、下发时间
number = fields.Char('编号')
reason = fields.Text('重新编程原因')
programming_method = fields.Selection([
('auto', '自动'),
('manual operation', '人工')], string="编程方式")
current_programming_count = fields.Integer('当前编程次数')
target_production_id = fields.Char('目标制造单号')
apply_time = fields.Datetime('申请时间')
send_time = fields.Datetime('下发时间')
class sf_detection_result(models.Model): class sf_detection_result(models.Model):
_name = 'sf.detection.result' _name = 'sf.detection.result'
_description = "检测结果" _description = "检测结果"
_order = 'handle_result_date desc, id asc'
production_id = fields.Many2one('mrp.production') production_id = fields.Many2one('mrp.production')
processing_panel = fields.Char('加工面') processing_panel = fields.Char('加工面')
routing_type = fields.Selection([ routing_type = fields.Selection([
('装夹预调', '装夹预调'), ('装夹预调', '装夹预调'),
('CNC加工', 'CNC加工')], string="工序类型") ('CNC加工', 'CNC加工'),
('解除装夹', '解除装夹'),
('切割', '切割'),
('表面工艺', '表面工艺'),
('线切割', '线切割'),
('人工线下加工', '人工线下加工')], string="工序类型")
rework_reason = fields.Selection( rework_reason = fields.Selection(
[("programming", "编程"), ("cutter", "刀具"), ("clamping", "装夹"), [("programming", "编程"), ("cutter", "刀具"), ("clamping", "装夹"),
@@ -1608,6 +1730,8 @@ class sf_detection_result(models.Model):
test_report = fields.Binary('检测报告', readonly=True) test_report = fields.Binary('检测报告', readonly=True)
handle_result = fields.Selection([("待处理", "待处理"), ("已处理", "已处理")], default='', string="处理结果", handle_result = fields.Selection([("待处理", "待处理"), ("已处理", "已处理")], default='', string="处理结果",
tracking=True) tracking=True)
handle_result_date = fields.Datetime('处理时间')
handle_result_user = fields.Many2one('res.users', '处理人')
# 查看检测报告 # 查看检测报告
def button_look_test_report(self): def button_look_test_report(self):
@@ -1619,6 +1743,12 @@ class sf_detection_result(models.Model):
'target': 'new' 'target': 'new'
} }
def write(self, vals):
if vals.get('handle_result') and vals.get('handle_result') == '已处理':
vals['handle_result_date'] = fields.Datetime.now()
vals['handle_result_user'] = self.env.user.id
return super(sf_detection_result, self).write(vals)
class sf_processing_panel(models.Model): class sf_processing_panel(models.Model):
_name = 'sf.processing.panel' _name = 'sf.processing.panel'

View File

@@ -25,6 +25,8 @@ class ResMrpRoutingWorkcenter(models.Model):
bom_id = fields.Many2one('mrp.bom', required=False) bom_id = fields.Many2one('mrp.bom', required=False)
surface_technics_id = fields.Many2one('sf.production.process', string="表面工艺") surface_technics_id = fields.Many2one('sf.production.process', string="表面工艺")
reserved_duration = fields.Float('预留时长', default=30, tracking=True) reserved_duration = fields.Float('预留时长', default=30, tracking=True)
is_outsource = fields.Boolean('外协', default=False)
individuation_page_ids = fields.Many2many('sf.work.individuation.page', string='个性化记录')
def get_no(self): def get_no(self):
international_standards = self.search( international_standards = self.search(
@@ -101,3 +103,10 @@ class ResMrpRoutingWorkcenter(models.Model):
domain = args + [('id', 'not in', route_workcenter_ids)] 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)
class WorkIndividuationPage(models.Model):
_name = 'sf.work.individuation.page'
code = fields.Char('编号')
name = fields.Char('名称')

View File

@@ -145,7 +145,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程序")
@@ -290,31 +290,18 @@ class ResMrpWorkOrder(models.Model):
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 == '表面工艺' and order.state not in ['cancel']: 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:buzhdiao
# 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', '=', order.production_id.name),
('state', '!=', 'cancel')] ('state', '!=', 'cancel')]
purchase = self.env['purchase.order'].search(domain) purchase = self.env['purchase.order'].search(domain)
purchase_num = 0 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 po in purchase: for po in purchase:
for line in po.order_line: if any(
if line.product_id.server_product_process_parameters_id == order.surface_technics_parameters_id: line.product_id and line.product_id.server_product_process_parameters_id == order.surface_technics_parameters_id
if line.product_qty == 1: for line in po.order_line):
purchase_num += 1 order.surface_technics_purchase_count = 1
order.surface_technics_purchase_count = purchase_num
else: else:
order.surface_technics_purchase_count = 0 order.surface_technics_purchase_count = 0
@@ -1282,24 +1269,25 @@ class ResMrpWorkOrder(models.Model):
record.production_id.process_state = '待加工' record.production_id.process_state = '待加工'
# 生成工件配送单 # 生成工件配送单
record.workpiece_delivery_ids = record._json_workpiece_delivery_list() record.workpiece_delivery_ids = record._json_workpiece_delivery_list()
if record.routing_type == 'CNC加工': if record.routing_type == 'CNC加工' or record.individuation_page_PTD is True:
record.process_state = '待解除装夹' if record.routing_type == 'CNC加工':
# record.write({'process_state': '待加工'}) record.process_state = '待解除装夹'
record.production_id.process_state = '待解除装夹' # record.write({'process_state': '待加工'})
self.env['sf.production.plan'].sudo().search([('name', '=', record.production_id.name)]).write({ record.production_id.process_state = '待解除装夹'
'state': 'finished', self.env['sf.production.plan'].sudo().search([('name', '=', record.production_id.name)]).write({
'actual_end_time': datetime.now() 'state': 'finished',
}) 'actual_end_time': datetime.now()
})
record.production_id.write({'detection_result_ids': [(0, 0, { record.production_id.write({'detection_result_ids': [(0, 0, {
'rework_reason': record.reason, 'rework_reason': record.reason,
'detailed_reason': record.detailed_reason, 'detailed_reason': record.detailed_reason,
'processing_panel': record.processing_panel, 'processing_panel': record.processing_panel,
'routing_type': record.routing_type, 'routing_type': record.routing_type,
'handle_result': '待处理' if record.test_results in ['返工', 'handle_result': '待处理' if record.test_results in ['返工', '报废'] or record.is_rework is True else '',
'报废'] or record.is_rework is True else '',
'test_results': record.test_results, 'test_results': record.test_results,
'test_report': record.detection_report})], 'test_report': record.detection_report})],
'is_scrap': True if record.test_results == '报废' else False}) 'is_scrap': True if record.test_results == '报废' else False
})
if record.routing_type == '解除装夹': if record.routing_type == '解除装夹':
''' '''
记录结束时间 记录结束时间
@@ -1312,7 +1300,7 @@ class ResMrpWorkOrder(models.Model):
raise UserError('请先完成该工单的工艺外协再进行操作') raise UserError('请先完成该工单的工艺外协再进行操作')
# 表面工艺外协,最后一张工单 # 表面工艺外协,最后一张工单
workorders = self.production_id.workorder_ids workorders = self.production_id.workorder_ids
subcontract_workorders = workorders.filtered(lambda wo: wo.is_subcontract == True).sorted('sequence') subcontract_workorders = workorders.filtered(lambda wo: wo.is_subcontract == True and wo.state != 'cancel').sorted('sequence')
if self == subcontract_workorders[-1]: if self == subcontract_workorders[-1]:
# 给下一个库存移动就绪 # 给下一个库存移动就绪
self.move_subcontract_workorder_ids[0].move_dest_ids._action_done() self.move_subcontract_workorder_ids[0].move_dest_ids._action_done()
@@ -1336,8 +1324,10 @@ class ResMrpWorkOrder(models.Model):
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 in ['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 ['装夹预调']): record.is_rework is True and record.routing_type in ['装夹预调']):
@@ -1370,6 +1360,22 @@ class ResMrpWorkOrder(models.Model):
record.production_id.button_mark_done1() record.production_id.button_mark_done1()
# record.production_id.state = 'done' # record.production_id.state = 'done'
# ============工单完成,修改对应[质检单]的值=====================
if record.check_ids.filtered(lambda qc: qc.quality_state in ('waiting', 'none')):
check_ids = record.check_ids.filtered(lambda qc: qc.quality_state in ('waiting', 'none'))
if record.test_results == '合格':
check_ids.write({'test_results': record.test_results})
for check_id in check_ids:
check_id.do_pass()
elif record.test_results in ('返工', '报废'):
check_ids.write({
'test_results': record.test_results,
'reason': record.reason,
'detailed_reason': record.detailed_reason})
for check_id in check_ids:
check_id.do_fail()
# ======================================================
# 解绑托盘 # 解绑托盘
def unbind_tray(self): def unbind_tray(self):
for item in self: for item in self:
@@ -1492,6 +1498,54 @@ class ResMrpWorkOrder(models.Model):
move_subcontract_workorder_ids = fields.One2many('stock.move', 'subcontract_workorder_id', string='组件') move_subcontract_workorder_ids = fields.One2many('stock.move', 'subcontract_workorder_id', string='组件')
# ==============================配置化页签--个性化记录===================================
routing_workcenter_id = fields.Many2one('mrp.routing.workcenter', compute='_compute_routing_workcenter_id',
store=True)
individuation_page_ids = fields.Many2many('sf.work.individuation.page', string='个性化记录', store=True,
compute='_compute_individuation_page_ids')
individuation_page_PTD = fields.Boolean('个性化记录(是否显示后置三元检测[PTD]页签)', default=False)
@api.depends('name')
def _compute_routing_workcenter_id(self):
for mw in self:
routing_workcenter_id = self.env['mrp.routing.workcenter'].sudo().search(
[('name', '=', mw.name), ('routing_type', '=', mw.routing_type)])
if routing_workcenter_id:
mw.routing_workcenter_id = routing_workcenter_id.id
@api.depends('routing_workcenter_id.individuation_page_ids')
def _compute_individuation_page_ids(self):
for mw in self:
if mw.routing_workcenter_id:
mw.individuation_page_ids = mw.routing_workcenter_id.individuation_page_ids.ids
# 初始化页签配置
mw.individuation_page_PTD = False
# 根据工单对应的【作业_个性化记录】配置页签
if any(item.code == 'PTD' for item in mw.routing_workcenter_id.individuation_page_ids):
mw.individuation_page_PTD = True
# =============================================================================================
is_inspect = fields.Boolean('需送检', compute='_compute_is_inspect', store=True, default=False)
@api.depends('check_ids.is_inspect')
def _compute_is_inspect(self):
for item in self:
if item.check_ids:
is_inspect = False
for check_id in item.check_ids:
if check_id.is_inspect:
is_inspect = True
break
item.is_inspect = is_inspect
def do_inspect(self):
"""送检"""
# 修改工单状态
self.write({'state': 'to be detected'})
# 若关联的【质量检查_需送检】=true则质量检查单的状态从“等待”更新为“待处理”
self.check_ids.filtered(lambda ch: ch.is_inspect is True and ch.quality_state == 'waiting').write(
{'quality_state': 'none'})
class CNCprocessing(models.Model): class CNCprocessing(models.Model):
_name = 'sf.cnc.processing' _name = 'sf.cnc.processing'

View File

@@ -4,6 +4,7 @@
from collections import defaultdict from collections import defaultdict
from odoo import api, fields, models, _ from odoo import api, fields, models, _
from odoo.exceptions import UserError
from odoo.tools import OrderedSet from odoo.tools import OrderedSet
@@ -16,6 +17,20 @@ class PurchaseOrder(models.Model):
compute='_compute_workorder_count', compute='_compute_workorder_count',
) )
def button_cancel(self):
account_moves = set() # 使用集合以避免重复,并提高查找速度
accounts = self.env['account.move'].search(
[('id', 'in', self.invoice_ids.ids), ('state', 'not in', ['cancel', False])])
# 直接筛选掉状态为'cancel'或False的记录避免多次迭代
for account in accounts:
account_moves.add(account.name) # 使用set的add方法避免重复添加
# 如果你需要list形式的结果可以将set转换为list
account_moves = list(account_moves)
if account_moves:
raise UserError(_("请联系工厂生产经理对该采购单的供应商账单进行取消"))
return super(PurchaseOrder, self).button_cancel()
def action_view_production(self): def action_view_production(self):
origins = [order.name for order in self.picking_ids] origins = [order.name for order in self.picking_ids]
production_id = self.env['mrp.production'].search([('origin', 'in', origins)]) production_id = self.env['mrp.production'].search([('origin', 'in', origins)])
@@ -93,15 +108,16 @@ class PurchaseOrder(models.Model):
class PurchaseOrderLine(models.Model): class PurchaseOrderLine(models.Model):
_inherit = 'purchase.order.line' _inherit = 'purchase.order.line'
part_number = fields.Char('零件图号', related='product_id.part_number', readonly=True) part_number = fields.Char('零件图号', related='product_id.part_number', readonly=True)
related_product = fields.Many2one('product.product', compute='_compute_related_product', string='关联产品', related_product = fields.Many2one('product.product', string='关联产品',
help='经此产品工艺加工成的成品') help='经此产品工艺加工成的成品')
@api.depends('order_id.origin') # @api.depends('order_id.origin')
def _compute_related_product(self): # def _compute_related_product(self):
for record in self: # for record in self:
if record.product_id.detailed_type: # if record.product_id.detailed_type:
production_id = self.env['mrp.production'].search([('name', '=', record.order_id.origin)]) # production_id = self.env['mrp.production'].search([('name', '=', record.order_id.origin)])
record.related_product = production_id.product_id if production_id else False # record.related_product = production_id.product_id if production_id else False
else: # else:
record.related_product = False # record.related_product = False

View File

@@ -0,0 +1,7 @@
from odoo import fields, models, api
class QualityCheck(models.Model):
_inherit = "quality.check"
is_inspect = fields.Boolean('需送检')

View File

@@ -72,35 +72,6 @@ class StockRule(models.Model):
moves_values_by_company = defaultdict(list) moves_values_by_company = defaultdict(list)
mtso_products_by_locations = defaultdict(list) mtso_products_by_locations = defaultdict(list)
# To handle the `mts_else_mto` procure method, we do a preliminary loop to
# isolate the products we would need to read the forecasted quantity,
# in order to to batch the read. We also make a sanitary check on the
# `location_src_id` field.
# list1 = []
# for item in procurements:
# num = int(item[0].product_qty)
# if num > 1:
# for no in range(1, num+1):
#
# Procurement = namedtuple('Procurement', ['product_id', 'product_qty',
# 'product_uom', 'location_id', 'name', 'origin',
# 'company_id',
# 'values'])
# s = Procurement(product_id=item[0].product_id,product_qty=1.0,product_uom=item[0].product_uom,
# location_id=item[0].location_id,
# name=item[0].name,
# origin=item[0].origin,
# company_id=item[0].company_id,
# values=item[0].values,
# )
# item1 = list(item)
# item1[0]=s
#
# list1.append(tuple(item1))
# else:
# list1.append(item)
for procurement, rule in procurements: for procurement, rule in procurements:
if not rule.location_src_id: if not rule.location_src_id:
msg = _('No source location defined on stock rule: %s!') % (rule.name,) msg = _('No source location defined on stock rule: %s!') % (rule.name,)
@@ -209,14 +180,14 @@ class StockRule(models.Model):
productions = self.env['mrp.production'].with_user(SUPERUSER_ID).sudo().with_company(company_id).create( productions = self.env['mrp.production'].with_user(SUPERUSER_ID).sudo().with_company(company_id).create(
productions_values) productions_values)
# 将这一批制造订单的采购组根据成品设置为不同的采购组 # 将这一批制造订单的采购组根据成品设置为不同的采购组
product_group_id = {} # product_group_id = {}
for index, production in enumerate(productions): # for index, production in enumerate(productions):
if production.product_id.id not in product_group_id.keys(): # if production.product_id.id not in product_group_id.keys():
product_group_id[production.product_id.id] = production.procurement_group_id.id # product_group_id[production.product_id.id] = production.procurement_group_id.id
else: # else:
productions_values[index].update({'name': production.name}) # productions_values[index].update({'name': production.name})
procurement_group_vals = production._prepare_procurement_group_vals(productions_values[index]) # procurement_group_vals = production._prepare_procurement_group_vals(productions_values[index])
production.procurement_group_id = self.env["procurement.group"].create(procurement_group_vals).id # production.procurement_group_id = self.env["procurement.group"].create(procurement_group_vals).id
# self.env['stock.move'].sudo().create(productions._get_moves_raw_values()) # self.env['stock.move'].sudo().create(productions._get_moves_raw_values())
# self.env['stock.move'].sudo().create(productions._get_moves_finished_values()) # self.env['stock.move'].sudo().create(productions._get_moves_finished_values())
@@ -618,15 +589,21 @@ class StockPicking(models.Model):
item.address_of_delivery = sale_info.address_of_delivery item.address_of_delivery = sale_info.address_of_delivery
# 设置外协出入单的名称 # 设置外协出入单的名称
def _get_name_Res(self, rescode): def _get_name_Res(self, rescode,sequence):
last_picking = self.sudo().search([('name', 'ilike', rescode)], order='create_date desc,id desc', limit=1) last_picking = self.sudo().search([('name', 'ilike', rescode)], order='name desc', limit=1)
if not last_picking: sequence_id = sequence.next_by_id()
num = "%04d" % 1 name_without_prefix = last_picking.name.removeprefix(rescode)
try:
name_value = int(name_without_prefix) # 假设 name 是一个数字字符串
except ValueError:
name_value = 0
if name_value >= int(sequence_id.removeprefix(rescode)):
sequence.write({
'number_next': name_value + 1,
})
return sequence.next_by_id()
else: else:
logging.info('编号:' + last_picking.name) return sequence_id
m = int(last_picking.name[-3:]) + 1
num = "%04d" % m
return '%s%s' % (rescode, num)
def button_validate(self): def button_validate(self):
res = super().button_validate() res = super().button_validate()
@@ -787,12 +764,15 @@ class ReStockMove(models.Model):
def _get_new_picking_values_Res(self, item, sorted_workorders, rescode): def _get_new_picking_values_Res(self, item, sorted_workorders, rescode):
picking_type_id = self.mapped('picking_type_id').id picking_type_id = self.mapped('picking_type_id').id
sequence = False
if rescode == 'WH/OCOUT/': if rescode == 'WH/OCOUT/':
picking_type_id = self.env.ref('sf_manufacturing.outcontract_picking_out').id picking_type_id = self.env.ref('sf_manufacturing.outcontract_picking_out').id
sequence = self.env.ref('sf_manufacturing.sequence_stock_picking_out')
elif rescode == 'WH/OCIN/': elif rescode == 'WH/OCIN/':
picking_type_id = self.env.ref('sf_manufacturing.outcontract_picking_in').id picking_type_id = self.env.ref('sf_manufacturing.outcontract_picking_in').id
sequence = self.env.ref('sf_manufacturing.sequence_stock_picking_in')
return { return {
'name': self.env['stock.picking']._get_name_Res(rescode), 'name': self.env['stock.picking']._get_name_Res(rescode,sequence),
'origin': item.name, 'origin': item.name,
'surface_technics_parameters_id': sorted_workorders.surface_technics_parameters_id.id, 'surface_technics_parameters_id': sorted_workorders.surface_technics_parameters_id.id,
'company_id': self.mapped('company_id').id, 'company_id': self.mapped('company_id').id,

View File

@@ -186,4 +186,9 @@ access_sf_detection_result_manager,sf_detection_result_manager,model_sf_detectio
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_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_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 access_mrp_workorder_group_purchase,mrp_workorder,model_mrp_workorder,sf_base.group_purchase,1,1,0,0
access_sf_programming_reason,sf_programming_reason,model_sf_programming_reason,base.group_user,1,1,1,0
access_sf_programming_record,sf_programming_record,model_sf_programming_record,base.group_user,1,1,1,0
access_sf_work_individuation_page,sf_work_individuation_page,model_sf_work_individuation_page,sf_base.group_sf_mrp_user,1,1,1,0
access_sf_work_individuation_page_group_plan_dispatch,sf_work_individuation_page_group_plan_dispatch,model_sf_work_individuation_page,sf_base.group_plan_dispatch,1,1,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
186
187
188
189
190
191
192
193
194

View File

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

View File

@@ -0,0 +1,3 @@
.my_custom_group_spacing {
margin-top: 30px; /* 调整组与上方元素的距离 */
}

View File

@@ -7,6 +7,10 @@
<field name="model">mrp.production</field> <field name="model">mrp.production</field>
<field name="inherit_id" ref="mrp.mrp_production_tree_view"/> <field name="inherit_id" ref="mrp.mrp_production_tree_view"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//header//button[last()]" position="after">
<button name="action_apply_programming" type="object" string="申请编程" class="oe_highlight"
groups="sf_base.group_sf_mrp_user"/>
</xpath>
<!-- <xpath expr="//button[@name='do_unreserve']" position="after">--> <!-- <xpath expr="//button[@name='do_unreserve']" position="after">-->
<!-- <button name="do_update_program" type="object" string="更新程序"--> <!-- <button name="do_update_program" type="object" string="更新程序"-->
<!-- groups="sf_base.group_sf_mrp_user"/>--> <!-- groups="sf_base.group_sf_mrp_user"/>-->
@@ -70,7 +74,9 @@
<xpath expr="//field[@name='production_real_duration']" position="attributes"> <xpath expr="//field[@name='production_real_duration']" position="attributes">
<attribute name="invisible">1</attribute> <attribute name="invisible">1</attribute>
</xpath> </xpath>
<xpath expr="//field[@name='state']" position="after">
<field name="programming_state" optional="hide"/>
</xpath>
</field> </field>
</record> </record>
@@ -81,6 +87,14 @@
<field name="model">mrp.production</field> <field name="model">mrp.production</field>
<field name="inherit_id" ref="mrp.mrp_production_form_view"/> <field name="inherit_id" ref="mrp.mrp_production_form_view"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//button[@name='action_view_mrp_production_backorders']" position="attributes">
<attribute name="attrs">{'invisible': True}</attribute>
</xpath>
<xpath expr="//header//button[last()]" position="after">
<button name="action_apply_programming" type="object" string="申请编程" class="oe_highlight"
attrs="{'invisible': ['|', ('state', 'not in', ['confirmed', 'pending_cam']), ('programming_state', '!=', '已编程')]}"
groups="sf_base.group_sf_mrp_user"/>
</xpath>
<xpath expr="//field[@name='state']" position="attributes"> <xpath expr="//field[@name='state']" position="attributes">
<!-- <attribute name="statusbar_visible">draft,confirmed,progress,pending_processing,completed,done --> <!-- <attribute name="statusbar_visible">draft,confirmed,progress,pending_processing,completed,done -->
<!-- </attribute> --> <!-- </attribute> -->
@@ -154,7 +168,7 @@
confirm="是否确认更新程序" confirm="是否确认更新程序"
attrs="{'invisible': ['|',('state', '!=', 'rework'),('programming_state', '!=', '已编程未下发')]}"/> attrs="{'invisible': ['|',('state', '!=', 'rework'),('programming_state', '!=', '已编程未下发')]}"/>
<button name="button_rework" string="返工" type="object" groups="sf_base.group_sf_mrp_user" <button name="button_rework" string="返工" type="object" groups="sf_base.group_sf_mrp_user"
attrs="{'invisible': ['|','|',('state', '!=', 'rework') ,('programming_state', '!=', '已编程'),('is_rework', '=', True)]}"/> attrs="{'invisible': ['|','|',('state', '!=', 'rework') ,('programming_state', 'not in', ('已编程', False)),('is_rework', '=', True)]}"/>
<button name="button_scrap_new" string="报废" type="object" <button name="button_scrap_new" string="报废" type="object"
groups="sf_base.group_sf_mrp_user" groups="sf_base.group_sf_mrp_user"
attrs="{'invisible': ['|',('is_scrap', '=', False),('state','=','cancel')]}"/> attrs="{'invisible': ['|',('is_scrap', '=', False),('state','=','cancel')]}"/>
@@ -335,6 +349,10 @@
<field name="detailed_reason"/> <field name="detailed_reason"/>
<field name="test_results"/> <field name="test_results"/>
<field name="handle_result"/> <field name="handle_result"/>
<field name="create_date" string="创建时间"/>
<field name="create_uid" string="创建人"/>
<field name="handle_result_date"/>
<field name="handle_result_user"/>
<field name="test_report" invisible="1"/> <field name="test_report" invisible="1"/>
<button name="button_look_test_report" string="查看测试报告" type="object" <button name="button_look_test_report" string="查看测试报告" type="object"
attrs="{'invisible': [('test_report', '=', False)]}" attrs="{'invisible': [('test_report', '=', False)]}"
@@ -397,6 +415,21 @@
position="replace"> position="replace">
<span class="o_stat_text">子MO</span> <span class="o_stat_text">子MO</span>
</xpath> </xpath>
<xpath expr="//sheet//notebook//page[last()]" position="after">
<page string="编程记录">
<field name="programming_record_ids" widget="one2many" attrs="{'readonly': [('id', '!=', False)]}">
<tree>
<field name="number"/>
<field name="reason"/>
<field name="programming_method"/>
<field name="current_programming_count"/>
<field name="target_production_id"/>
<field name="apply_time"/>
<field name="send_time"/>
</tree>
</field>
</page>
</xpath>
</field> </field>
</record> </record>

View File

@@ -17,6 +17,8 @@
<field name="bom_product_template_attribute_value_ids" position="after"> <field name="bom_product_template_attribute_value_ids" position="after">
<field name="routing_type" required="1"/> <field name="routing_type" required="1"/>
<field name="routing_tag" required="1" string="工序标签"/> <field name="routing_tag" required="1" string="工序标签"/>
<field name="is_outsource"/>
<field name="individuation_page_ids" widget="many2many_tags" options="{'create': False}"/>
<field name="is_repeat"/> <field name="is_repeat"/>
<field name="reserved_duration"/> <field name="reserved_duration"/>
</field> </field>

View File

@@ -87,7 +87,7 @@
<tree position="attributes"> <tree position="attributes">
<attribute name="multi_edit"></attribute> <attribute name="multi_edit"></attribute>
<attribute name="editable"></attribute> <attribute name="editable"></attribute>
<attribute name="create">False</attribute> <attribute name="create">false</attribute>
</tree> </tree>
</field> </field>
</record> </record>
@@ -126,6 +126,10 @@
<field name="model">mrp.workorder</field> <field name="model">mrp.workorder</field>
<field name="inherit_id" ref="mrp.mrp_production_workorder_form_view_inherit"/> <field name="inherit_id" ref="mrp.mrp_production_workorder_form_view_inherit"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//form" position="inside">
<!-- 其他可见字段 -->
<field name="_barcode_scanned" widget="barcode_handler"/>
</xpath>
<!-- <xpath expr="//form" position="inside"> --> <!-- <xpath expr="//form" position="inside"> -->
<!-- <script src="sf_manufacturing/static/src/js/customRFID.js"/> --> <!-- <script src="sf_manufacturing/static/src/js/customRFID.js"/> -->
<!-- </xpath> --> <!-- </xpath> -->
@@ -158,6 +162,7 @@
<field name='is_rework' invisible="1"/> <field name='is_rework' invisible="1"/>
<field name='is_delivery' invisible="1"/> <field name='is_delivery' invisible="1"/>
<field name="is_trayed" invisible="1"/> <field name="is_trayed" invisible="1"/>
<field name="is_inspect" invisible="1"/>
<!-- <field name='is_send_program_again' invisible="1"/>--> <!-- <field name='is_send_program_again' invisible="1"/>-->
<!-- 工单form页面的开始停工按钮等 --> <!-- 工单form页面的开始停工按钮等 -->
<!-- <button name="button_start" type="object" string="开始" class="btn-success" --> <!-- <button name="button_start" type="object" string="开始" class="btn-success" -->
@@ -172,12 +177,12 @@
<!-- <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"
attrs="{'invisible': [('state', '!=', 'ready')]}"/> attrs="{'invisible': [('state', '!=', 'ready')]}"/>
<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="是否确认完工"
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),'&amp;','&amp;',('state', 'in', ('progress')), ('is_inspect', '=', True), ('routing_type','!=','CNC加工')]}"/>
<button name="%(mrp.act_mrp_block_workcenter_wo)d" type="action" string="阻塞" <button name="%(mrp.act_mrp_block_workcenter_wo)d" type="action" string="阻塞"
context="{'default_workcenter_id': workcenter_id}" class="btn-danger" context="{'default_workcenter_id': workcenter_id}" class="btn-danger"
@@ -185,6 +190,8 @@
<button name="button_unblock" type="object" string="取消阻塞" <button name="button_unblock" type="object" string="取消阻塞"
context="{'default_workcenter_id': workcenter_id}" class="btn-danger" context="{'default_workcenter_id': workcenter_id}" class="btn-danger"
attrs="{'invisible': ['|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '!=', 'blocked')]}"/> attrs="{'invisible': ['|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '!=', 'blocked')]}"/>
<button name="do_inspect" type="object" string="送检" class="btn-success" confirm="是否确认送检"
attrs="{'invisible': ['|', '|', ('state', 'not in', ('progress')), ('is_inspect', '=', False), ('routing_type','=','CNC加工')]}"/>
<!-- <button name="%(mrp.act_mrp_block_workcenter_wo)d" type="action" string="停工" --> <!-- <button name="%(mrp.act_mrp_block_workcenter_wo)d" type="action" string="停工" -->
<!-- context="{'default_workcenter_id': workcenter_id}" class="btn-danger" --> <!-- context="{'default_workcenter_id': workcenter_id}" class="btn-danger" -->
@@ -305,7 +312,7 @@
<xpath expr="//page[1]" position="before"> <xpath expr="//page[1]" position="before">
<page string="工件装夹" attrs='{"invisible": [("routing_type","!=","装夹预调")]}'> <page string="工件装夹" attrs='{"invisible": [("routing_type","!=","装夹预调")]}'>
<group> <group>
<field name="_barcode_scanned" widget="barcode_handler"/> <!-- <field name="_barcode_scanned" widget="barcode_handler"/> -->
<group string="托盘"> <group string="托盘">
<field name="tray_serial_number" readonly="1" string="序列号"/> <field name="tray_serial_number" readonly="1" string="序列号"/>
</group> </group>
@@ -522,17 +529,19 @@
<xpath expr="//page[1]" position="before"> <xpath expr="//page[1]" position="before">
<field name="results" invisible="1"/> <field name="results" invisible="1"/>
<page string="后置三元检测" attrs='{"invisible": [("routing_type","!=","CNC加工")]}'> <field name="individuation_page_PTD" invisible="1"/>
<page string="后置三元检测" attrs='{"invisible": [("individuation_page_PTD", "=", False)]}'>
<group> <group>
<field name="test_results" <field name="test_results"
attrs='{"readonly":[("state","!=","to be detected")],"invisible":[("results","!=",False)]}'/> attrs='{"readonly":["&amp;","|",("state","!=","to be detected"), "|",("routing_type","=","CNC加工"),("is_inspect", "=", True),("state","in",["done","rework"])],
"invisible":[("results","!=",False)]}'/>
<!-- <field name="is_remanufacture" attrs='{"invisible":[("test_results","!=","报废")]}'/>--> <!-- <field name="is_remanufacture" attrs='{"invisible":[("test_results","!=","报废")]}'/>-->
<!-- <field name="is_fetchcnc"--> <!-- <field name="is_fetchcnc"-->
<!-- attrs='{"invisible":["|",("test_results","=","合格"),("is_remanufacture","=",False)]}'/>--> <!-- attrs='{"invisible":["|",("test_results","=","合格"),("is_remanufacture","=",False)]}'/>-->
<field name="reason" <field name="reason"
attrs='{"required":[("test_results","!=","合格")],"invisible":[("test_results","=","合格")]}'/> attrs='{"required":[("test_results","!=","合格")],"invisible":[("test_results","=","合格")],"readonly":[("state","in",("done", "rework"))]}'/>
<field name="detailed_reason" <field name="detailed_reason"
attrs='{"required":[("test_results","!=","合格")],"invisible":[("test_results","=","合格")]}'/> attrs='{"required":[("test_results","!=","合格")],"invisible":[("test_results","=","合格")],"readonly":[("state","in",("done", "rework"))]}'/>
<!-- <field name="results" readonly="1" attrs='{"invisible":[("results","!=","合格")]}'/>--> <!-- <field name="results" readonly="1" attrs='{"invisible":[("results","!=","合格")]}'/>-->
<field name="detection_report" attrs='{"invisible":[("results","!=",False)]}' <field name="detection_report" attrs='{"invisible":[("results","!=",False)]}'
widget="pdf_viewer" readonly="1"/> widget="pdf_viewer" readonly="1"/>

View File

@@ -4,8 +4,14 @@
<record model="ir.ui.view" id="view_purchase_order_line_form_inherit_sf1"> <record model="ir.ui.view" id="view_purchase_order_line_form_inherit_sf1">
<field name="name">purchase.order.form.inherit.sf</field> <field name="name">purchase.order.form.inherit.sf</field>
<field name="model">purchase.order</field> <field name="model">purchase.order</field>
<field name="inherit_id" ref="purchase.purchase_order_form"/> <field name="inherit_id" ref="purchase_order_approved.purchase_order_form"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<field name="order_line" position="attributes">
<attribute
name="attrs"
>{'readonly': [('state', '!=', 'draft')]}
</attribute>
</field>
<xpath expr="//field[@name='order_line']/tree/field[@name='name']" position="after"> <xpath expr="//field[@name='order_line']/tree/field[@name='name']" position="after">
<field name="related_product" optional="show"/> <field name="related_product" optional="show"/>
<field name="part_number" optional="show"/> <field name="part_number" optional="show"/>
@@ -25,9 +31,9 @@
<!-- 添加销售订单号字段--> <!-- 添加销售订单号字段-->
<xpath expr="//sheet/group/group[2]/div[@name='date_approve']" position="after"> <xpath expr="//sheet/group/group[2]/div[@name='date_approve']" position="after">
<field name="origin_sale_id" readonly="1" string="参考销售订单" <field name="origin_sale_id" readonly="1" string="参考销售订单"
attrs="{'invisible': [('origin_sale_id' , '=', False)]}"/> attrs="{'invisible': [('origin_sale_ids' , '!=', False)]}"/>
<field name="origin_sale_ids" readonly="1" string="参考销售订单" widget="many2many_tags" <field name="origin_sale_ids" readonly="1" string="参考销售订单" widget="many2many_tags"
attrs="{'invisible': [('origin_sale_ids' , '=', [])]}"/> attrs="{'invisible': [('origin_sale_ids' , '=', False)]}"/>
</xpath> </xpath>
</field> </field>
</record> </record>

View File

@@ -12,15 +12,16 @@
attrs="{'invisible': [('equipment_type', '!=', '机床')]}"> attrs="{'invisible': [('equipment_type', '!=', '机床')]}">
<button name="get_equipment_base_coordinate" string="获取基坐标数据" type="object" <button name="get_equipment_base_coordinate" string="获取基坐标数据" type="object"
class="oe_highlight"/> class="oe_highlight"/>
<separator invisible="0"/> <group class="my_custom_group_spacing">
<group>
<group> <group>
<field name="base_coordinate_fixture_model_id" options="{'no_create': True}"/> <field name="base_coordinate_fixture_model_id" options="{'no_create': True}"/>
<field name="base_coordinate_g_coordinate"/>
<field name="base_coordinate_x"/> <field name="base_coordinate_x"/>
<field name="base_coordinate_y"/>
<field name="base_coordinate_z"/> <field name="base_coordinate_z"/>
</group> </group>
<group>
<field name="base_coordinate_g_coordinate"/>
<field name="base_coordinate_y"/>
</group>
</group> </group>
</page> </page>
<page string="标准刀库" name="sf_equipment_product_template" <page string="标准刀库" name="sf_equipment_product_template"

View File

@@ -4,3 +4,4 @@ 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 from . import mrp_workorder_batch_replan_wizard
from . import sf_programming_reason

View File

@@ -91,4 +91,20 @@ class ProductionTechnologyWizard(models.TransientModel):
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 != '已编程':
workorder[0].state = 'waiting' workorder[0].state = 'waiting'
if item.is_remanufacture and item.programming_state == '已编程':
mrp_production = self.env['mrp.production'].sudo().search(
[('remanufacture_production_id', '=', item.name)])
workorder_ids = mrp_production.workorder_ids.filtered(
lambda ap: ap.routing_type in ('装夹预调', 'CNC加工'))
for workorder_id in workorder_ids:
workorder = item.workorder_ids.filtered(lambda
ap: ap.routing_type == workorder_id.routing_type and ap.processing_panel == workorder_id.processing_panel)
if workorder:
if workorder.routing_type == '装夹预调':
workorder.write(
{'processing_drawing': workorder_id.processing_drawing})
if workorder.routing_type == 'CNC加工':
workorder.write(
{'cnc_worksheet': workorder_id.cnc_worksheet, 'cnc_ids': workorder_id.cnc_ids,
'cmm_ids': workorder_id.cmm_ids})
return productions return productions

View File

@@ -51,6 +51,7 @@ class ProductionWizard(models.TransientModel):
if self.is_remanufacture is True: if self.is_remanufacture is True:
ret = {'programming_list': [], 'is_reprogramming': self.is_reprogramming} ret = {'programming_list': [], 'is_reprogramming': self.is_reprogramming}
if self.is_reprogramming is True: if self.is_reprogramming is True:
self.mrp_production_id.update_programming_state() self.mrp_production_id.update_programming_state(trigger_time=datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
new_production = self.mrp_production_id.recreateManufacturing(ret) new_production = self.mrp_production_id.recreateManufacturing(ret)
new_production.technology_design_ids = self.mrp_production_id.technology_design_ids
self.mrp_production_id.write({'remanufacture_production_id': new_production.id}) self.mrp_production_id.write({'remanufacture_production_id': new_production.id})

View File

@@ -24,7 +24,12 @@ class ReworkWizard(models.TransientModel):
detailed_reason = fields.Text('详细原因') detailed_reason = fields.Text('详细原因')
routing_type = fields.Selection([ routing_type = fields.Selection([
('装夹预调', '装夹预调'), ('装夹预调', '装夹预调'),
('CNC加工', 'CNC加工')], string="工序类型") ('CNC加工', 'CNC加工'),
('解除装夹', '解除装夹'),
('切割', '切割'),
('表面工艺', '表面工艺'),
('线切割', '线切割'),
('人工线下加工', '人工线下加工')], string="工序类型")
# 根据工单的加工面来显示 # 根据工单的加工面来显示
processing_panel_id = fields.Many2many('sf.processing.panel', string="加工面") processing_panel_id = fields.Many2many('sf.processing.panel', string="加工面")
is_reprogramming = fields.Boolean(string='申请重新编程', default=False) is_reprogramming = fields.Boolean(string='申请重新编程', default=False)
@@ -133,7 +138,10 @@ class ReworkWizard(models.TransientModel):
lambda item: (item.route_id.name in work.name and item.process_parameters_id lambda item: (item.route_id.name in work.name and item.process_parameters_id
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) or
(item.route_id == work.routing_workcenter_id
and not work.processing_panel
and not work.surface_technics_parameters_id))
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': '重新加工', 'sequence': 0}) work_list[2].update({'tag_type': '重新加工', 'sequence': 0})
@@ -273,7 +281,8 @@ class ReworkWizard(models.TransientModel):
{'programming_state': '编程中', 'work_state': '编程中', 'is_rework': True}) {'programming_state': '编程中', 'work_state': '编程中', 'is_rework': True})
# ================================================= # =================================================
if self.production_id.state == 'progress': if self.production_id.state == 'progress':
self.production_id.write({'programming_state': '已编程', 'work_state': '已编程'}) if self.programming_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 == '已编程':
productions_not_delivered = self.env['mrp.production'].search( productions_not_delivered = self.env['mrp.production'].search(
[('programming_no', '=', self.production_id.programming_no), [('programming_no', '=', self.production_id.programming_no),
@@ -284,7 +293,7 @@ class ReworkWizard(models.TransientModel):
'is_rework': False}) 'is_rework': False})
# ==================申请重新编程======================= # ==================申请重新编程=======================
if self.is_reprogramming is True: if self.is_reprogramming is True:
self.production_id.update_programming_state() self.production_id.update_programming_state(trigger_time=datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
self.production_id.write( self.production_id.write(
{'programming_state': '编程中', 'work_state': '编程中', 'state': 'progress'}) {'programming_state': '编程中', 'work_state': '编程中', 'state': 'progress'})
# ================= 返工完成,制造订单状态置为加工中 ============== # ================= 返工完成,制造订单状态置为加工中 ==============
@@ -299,9 +308,11 @@ class ReworkWizard(models.TransientModel):
if self.env.user.has_group('sf_base.group_sf_order_user'): if self.env.user.has_group('sf_base.group_sf_order_user'):
panel_ids = [] panel_ids = []
panel_arr = production_id.product_id.model_processing_panel panel_arr = production_id.product_id.model_processing_panel
if panel_arr is False:
break
for p in production_id.detection_result_ids.filtered( for p in production_id.detection_result_ids.filtered(
lambda ap1: ap1.handle_result == '待处理'): lambda ap1: ap1.handle_result == '待处理'):
if p.processing_panel not in panel_arr: if p.processing_panel is not False and p.processing_panel not in panel_arr:
panel_arr += ','.join(p.processing_panel) panel_arr += ','.join(p.processing_panel)
for item in panel_arr.split(','): for item in panel_arr.split(','):
panel = self.env['sf.processing.panel'].search( panel = self.env['sf.processing.panel'].search(

View File

@@ -0,0 +1,55 @@
from odoo import models, fields, api
class sf_programming_reason(models.TransientModel):
_name = 'sf.programming.reason'
_description = '重新编程原因'
production_id = fields.Many2one('mrp.production')
reason = fields.Text('重新编程原因')
reprogramming_count = fields.Integer(string='重新编程次数')
programming_state = fields.Char(string='编程状态')
@api.model
def default_get(self, fields):
res = super(sf_programming_reason, self).default_get(fields)
if self._context.get('active_id'):
production = self.env['mrp.production'].browse(self._context.get('active_id'))
res.update({
'reprogramming_count': production._cron_get_programming_state()['reprogramming_num'] if
production._cron_get_programming_state().get('reprogramming_num') else 0,
'programming_state': production.programming_state, # 假设制造订单模型中有这个字段
})
return res
def action_confirm(self):
print('self.production_id.programming_state:', self.production_id.programming_state)
self.production_id.re_programming_update_programming_state()
self.production_id.write(
{'programming_state': '编程中', 'work_state': '编程中'})
cloud_programming = self.production_id._cron_get_programming_state()
self.production_id.programming_record_ids.create({
'number': len(self.production_id.programming_record_ids) + 1,
'production_id': self.production_id.id,
'reason': self.reason,
'programming_method': cloud_programming['programme_way'],
'current_programming_count': cloud_programming['reprogramming_num'],
'target_production_id': self.production_id.name,
'apply_time': self._context.get('default_apply_time'),
'send_time': False,
})
# 返回弹窗提示“已下达编程任务和消息,请等待编程单下发”
return {
'type': 'ir.actions.act_window',
'res_model': 'sf.programming.reason',
'view_mode': 'form',
'target': 'new',
'context': {
'default_production_id': self.production_id.id,
'active_id': self.production_id.id,
},
'view_id': self.env.ref('sf_manufacturing.sf_programming_reason_message_view').id,
}

View File

@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record model="ir.ui.view" id="sf_programming_reason_form_view">
<field name="name">sf.programming.reason.form.view</field>
<field name="model">sf.programming.reason</field>
<field name="arch" type="xml">
<form>
<group>
<label for="reason" string="重新编程原因:"/>
<field name="reason" widget="textarea" nolabel="1"/>
<!-- <p class="text-muted">注意:该制造订单产品已申请重新编程次数为<field name="reprogramming_count" readonly="1" nolabel="1" class="oe_inline"/>,且当前编程状态为<field name="programming_state" readonly="1" nolabel="1" class="oe_inline"/></p> -->
</group>
<div attrs='{"invisible": [("reprogramming_count","=",0)]}'>
<span style='font-weight:bold;'>
注意: 该制造订单产品已申请重新编程次数为<field
name="reprogramming_count" string=""
readonly="1"
style='color:red;'/>,且当前编程状态为
<field name="programming_state" string=""
decoration-warning="programming_state =='编程中'"
decoration-success="programming_state =='已编程'" readonly="1"/>
</span>
</div>
<field name="production_id" invisible="True"/>
<footer>
<button name="action_confirm" string="确认" type="object" class="btn-primary"/>
<button string="丢弃" special="cancel" class="btn-secondary"/>
</footer>
</form>
</field>
</record>
<!-- 弹窗提示“已下达编程任务和消息,请等待编程单下发” -->
<record model="ir.ui.view" id="sf_programming_reason_message_view">
<field name="name">sf.programming.reason.message.view</field>
<field name="model">sf.programming.reason</field>
<field name="arch" type="xml">
<form>
<p>已下达编程任务和消息,请等待编程单下发!</p>
<footer>
<button string="关闭" special="cancel" class="btn-secondary"/>
</footer>
</form>
</field>
</record>
<!-- 重新编程原因弹窗 -->
<record id="sf_programming_reason_action" model="ir.actions.act_window">
<field name="name">重新编程原因</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">sf.programming.reason</field>
<field name="view_mode">form</field>
<field name="view_id" ref="sf_programming_reason_form_view"/>
<field name="target">new</field>
</record>
</odoo>

View File

@@ -29,7 +29,7 @@ class Sf_Mrs_Connect(http.Controller, MultiInheritController):
if ret['manufacturing_type'] in ('scrap', 'invalid_tool_rework', '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', 'progress'])]
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( productions_technology_to_confirmed = request.env['mrp.production'].with_user(
@@ -39,6 +39,7 @@ class Sf_Mrs_Connect(http.Controller, MultiInheritController):
res = {'status': -2, 'message': '查询到待工艺确认的制造订单'} res = {'status': -2, 'message': '查询到待工艺确认的制造订单'}
return json.JSONEncoder().encode(res) return json.JSONEncoder().encode(res)
if productions: if productions:
# 拉取所有加工面的程序文件 # 拉取所有加工面的程序文件
for r in ret['processing_panel'].split(','): for r in ret['processing_panel'].split(','):
program_path_tmp_r = os.path.join('/tmp', ret['folder_name'], 'return', r) program_path_tmp_r = os.path.join('/tmp', ret['folder_name'], 'return', r)
@@ -61,8 +62,8 @@ class Sf_Mrs_Connect(http.Controller, MultiInheritController):
# 查询状态为进行中且工序类型为CNC加工的工单 # 查询状态为进行中且工序类型为CNC加工的工单
cnc_workorder_has = production.workorder_ids.filtered( cnc_workorder_has = production.workorder_ids.filtered(
lambda ach: ach.routing_type == 'CNC加工' and ach.state not in ['progress', 'done', lambda ach: ach.routing_type == 'CNC加工' and ach.state not in ['progress', 'done',
'rework', 'rework',
'cancel'] and ach.processing_panel == panel) 'cancel'] and ach.processing_panel == panel)
if cnc_workorder_has: if cnc_workorder_has:
if cnc_workorder_has.cnc_ids: if cnc_workorder_has.cnc_ids:
cnc_workorder_has.cmm_ids.sudo().unlink() cnc_workorder_has.cmm_ids.sudo().unlink()
@@ -76,7 +77,7 @@ class Sf_Mrs_Connect(http.Controller, MultiInheritController):
# 查询状态为进行中且工序类型为CNC加工的工单 # 查询状态为进行中且工序类型为CNC加工的工单
cnc_workorder = productions.workorder_ids.filtered( cnc_workorder = productions.workorder_ids.filtered(
lambda ac: ac.routing_type == 'CNC加工' and ac.state not in ['progress', 'done', 'rework' lambda ac: ac.routing_type == 'CNC加工' and ac.state not in ['progress', 'done', 'rework'
'cancel'] and ac.processing_panel == panel) 'cancel'] and ac.processing_panel == panel)
if cnc_workorder: if cnc_workorder:
# program_path_tmp_panel = os.path.join('C://Users//43484//Desktop//fsdownload//test', # program_path_tmp_panel = os.path.join('C://Users//43484//Desktop//fsdownload//test',
# panel) # panel)
@@ -91,24 +92,160 @@ class Sf_Mrs_Connect(http.Controller, MultiInheritController):
cnc_workorder.write({'cnc_worksheet': base64.b64encode(open(panel_file_path, 'rb').read())}) cnc_workorder.write({'cnc_worksheet': base64.b64encode(open(panel_file_path, 'rb').read())})
pre_workorder = productions.workorder_ids.filtered( pre_workorder = productions.workorder_ids.filtered(
lambda ap: ap.routing_type == '装夹预调' and ap.state not in ['done', 'rework' lambda ap: ap.routing_type == '装夹预调' and ap.state not in ['done', 'rework'
'cancel'] and ap.processing_panel == panel) 'cancel'] and ap.processing_panel == panel)
if pre_workorder: if pre_workorder:
pre_workorder.write( pre_workorder.write(
{'processing_drawing': base64.b64encode(open(panel_file_path, 'rb').read())}) {'processing_drawing': base64.b64encode(open(panel_file_path, 'rb').read())})
productions.write({'programming_state': '已编程', 'work_state': '已编程'}) productions.write({'programming_state': '已编程', 'work_state': '已编程'})
logging.info('已更新制造订单编程状态:%s' % productions.ids) logging.info('已更新制造订单编程状态:%s' % productions.ids)
# 对制造订单所有面的cnc工单的程序用刀进行校验
try:
logging.info(f'已更新制造订单:{productions}')
re_tool_chekout = False
re_tool_chekout = productions.production_cnc_tool_checkout()
if re_tool_chekout:
return json.JSONEncoder().encode({'status': -3, 'message': '对cnc工单的程序用刀进行校验失败'})
except Exception as e:
res = {'status': -3, 'message': '对cnc工单的程序用刀进行校验报错'}
logging.info(f'对cnc工单的程序用刀进行校验报错{e}')
return json.JSONEncoder().encode(res)
productions_reprogram = ''
if productions:
productions_reprogram = ','.join(productions.mapped('name'))
# 更新编程记录
correct_record_ids_obj = None
correct_production_id = None
# rework_record_ids_obj = None
# rework_production_id = None
# scrap_record_ids_obj = None
# scrap_production_id = None
for production in productions:
logging.info('production====:%s' % production.name)
record_ids_obj = production.programming_record_ids.filtered(
lambda r: r.current_programming_count == ret['reprogramming_num'])
logging.info('record_ids_obj====:%s' % record_ids_obj)
if record_ids_obj:
logging.info('record_ids_obj.reason====:%s' % record_ids_obj.reason)
record_ids_obj.write(
{'send_time': ret['send_time'], 'target_production_id': productions_reprogram})
logging.info('已更新编程记录:%s' % record_ids_obj)
correct_record_ids_obj = record_ids_obj
correct_production_id = production.id
if ret['reprogramming_num'] == 0:
logging.info('首次下发')
production.programming_record_ids.create({
'number': 1,
'production_id': production.id,
'reason': '首次下发',
'programming_method': ret['programme_way'],
'current_programming_count': ret['reprogramming_num'],
'target_production_id': productions_reprogram,
'apply_time': False,
'send_time': ret['send_time'],
})
logging.info('已创建首次下发的编程记录:%s' % production.name)
elif ret['reset_flag']:
logging.info('重置状态')
production.programming_record_ids.create({
'number': len(production.programming_record_ids) + 1,
'production_id': production.id,
'reason': '重置状态',
'programming_method': ret['programme_way'],
'current_programming_count': ret['reprogramming_num'],
'target_production_id': productions_reprogram,
'apply_time': False,
'send_time': ret['send_time'],
})
logging.info('已创建重置状态的编程记录:%s' % production.name)
elif ret['manufacturing_type'] == 'rework':
logging.info('返工')
rework_record_ids_obj = production.programming_record_ids.create({
'number': len(production.programming_record_ids) + 1,
'production_id': production.id,
'reason': '返工',
'programming_method': ret['programme_way'],
'current_programming_count': ret['reprogramming_num'],
'target_production_id': productions_reprogram,
'apply_time': ret['trigger_time'],
'send_time': ret['send_time'],
})
logging.info('已创建返工的编程记录:%s' % production.name)
logging.info('rework_record_ids_obj====:%s' % rework_record_ids_obj)
# rework_production_id = production.id
# logging.info('rework_production_id====:%s' % rework_production_id)
elif ret['manufacturing_type'] == 'scrap':
production.programming_record_ids.create({
'number': len(production.programming_record_ids) + 1,
'production_id': production.id,
'reason': '报废',
'programming_method': ret['programme_way'],
'current_programming_count': ret['reprogramming_num'],
'target_production_id': productions_reprogram,
'apply_time': ret['trigger_time'],
'send_time': ret['send_time'],
})
elif ret['manufacturing_type'] == 'invalid_tool_rework':
logging.info('无效功能刀具')
production.programming_record_ids.create({
'number': len(production.programming_record_ids) + 1,
'production_id': production.id,
'reason': '无效功能刀具',
'programming_method': ret['programme_way'],
'current_programming_count': ret['reprogramming_num'],
'target_production_id': productions_reprogram,
'apply_time': ret['trigger_time'],
'send_time': ret['send_time'],
})
logging.info('已创建无效功能刀具的编程记录:%s' % production.name)
else:
logging.info('无对应状态,不需更新编程记录')
for production in productions:
logging.info('production====:%s' % production.name)
if correct_record_ids_obj:
logging.info('correct_record_ids_obj====:%s' % correct_record_ids_obj)
if production.id == correct_production_id:
logging.info('跳过正确的制造订单')
continue
else:
logging.info('创建正确的制造订单的编程记录')
production.programming_record_ids.create({
'number': len(production.programming_record_ids) + 1,
'production_id': production.id,
'reason': correct_record_ids_obj.reason,
'programming_method': correct_record_ids_obj.programming_method,
'current_programming_count': correct_record_ids_obj.current_programming_count,
'target_production_id': correct_record_ids_obj.target_production_id,
'apply_time': correct_record_ids_obj.apply_time,
'send_time': correct_record_ids_obj.send_time,
})
logging.info('已创建正确的制造订单的编程记录:%s' % production.name)
# if rework_record_ids_obj:
# logging.info('rework_record_ids_obj====:%s' % rework_record_ids_obj)
# if production.id == rework_production_id:
# continue
# else:
# logging.info('创建返工的制造订单的编程记录')
# production.programming_record_ids.create({
# 'number': len(production.programming_record_ids) + 1,
# 'production_id': production.id,
# 'reason': rework_record_ids_obj.reason,
# 'programming_method': rework_record_ids_obj.programming_method,
# 'current_programming_count': rework_record_ids_obj.current_programming_count,
# 'target_production_id': rework_record_ids_obj.target_production_id,
# 'apply_time': rework_record_ids_obj.apply_time,
# 'send_time': rework_record_ids_obj.send_time,
# })
# logging.info('已创建返工的制造订单的编程记录:%s' % production.name)
res.update({ res.update({
'production_ids': productions.ids 'production_ids': productions.ids
}) })
# 对制造订单所以面的cnc工单的程序用刀进行校验
try:
logging.info(f'已更新制造订单:{productions}')
productions.production_cnc_tool_checkout()
except Exception as e:
logging.info(f'对cnc工单的程序用刀进行校验报错{e}')
return json.JSONEncoder().encode(res)
return json.JSONEncoder().encode(res) return json.JSONEncoder().encode(res)
else: else:
res = {'status': 0, 'message': '没有查询到该制造订单'} res = {'status': 0, 'message': '没有查询到该制造订单'}

View File

@@ -3,9 +3,9 @@
<record model="ir.cron" id="ir_cron_sf_static_resource_datasync"> <record model="ir.cron" id="ir_cron_sf_static_resource_datasync">
<field name="name">制造-配置每日定时同步cloud的静态资源库</field> <field name="name">制造-配置每日定时同步cloud的静态资源库</field>
<field name="model_id" ref="model_sf_static_resource_datasync"/> <field name="model_id" ref="model_res_config_settings"/>
<field name="state">code</field> <field name="state">code</field>
<field name="code">model._cron_static_resource_yesterday_func()</field> <field name="code">model.sf_all_sync()</field>
<field name="interval_number">1</field> <field name="interval_number">1</field>
<field name="interval_type">days</field> <field name="interval_type">days</field>
<field name="numbercall">-1</field> <field name="numbercall">-1</field>

View File

@@ -17,7 +17,9 @@
'data': [ 'data': [
'security/ir.model.access.csv', 'security/ir.model.access.csv',
'views/view.xml', 'views/view.xml',
'views/quality_cnc_test_view.xml' 'views/quality_cnc_test_view.xml',
'views/mrp_workorder.xml',
'views/quality_check_view.xml'
], ],
'assets': { 'assets': {

View File

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

View File

@@ -11,3 +11,8 @@ class SfQualityPoint(models.Model):
"('product', 'consu')), '|', ('company_id', '=', False), ('company_id', '=', company_id)]", help= "('product', 'consu')), '|', ('company_id', '=', False), ('company_id', '=', company_id)]", help=
"Quality Point will apply to every selected Products.") "Quality Point will apply to every selected Products.")
is_inspect = fields.Boolean('需送检', default=False)
operation_id = fields.Many2one(
'mrp.routing.workcenter', 'Step', check_company=True,
domain="[('is_outsource', '=', False),('company_id', 'in', (company_id, False))]")

View File

@@ -0,0 +1,28 @@
from odoo import api, fields, models
class ResMrpWorkOrder(models.Model):
_inherit = 'mrp.workorder'
check_ids_state = fields.Selection([('none', '待处理'), ('pass', '通过的'), ('fail', '失败的')], store=True,
compute='_compute_check_ids_state')
@api.depends('check_ids.quality_state')
def _compute_check_ids_state(self):
for mw in self:
if mw.check_ids:
if all(check_id.quality_state == 'pass' for check_id in mw.check_ids):
mw.check_ids_state = 'pass'
elif any(check_id.quality_state == 'fail' for check_id in mw.check_ids):
mw.check_ids_state = 'fail'
else:
mw.check_ids_state = 'none'
def action_open_quality_check_work_sf(self):
return {
'res_model': 'quality.check',
'type': 'ir.actions.act_window',
'name': '质量检查',
'domain': [('workorder_id', '=', self.id)],
'view_mode': 'tree,form',
}

View File

@@ -10,6 +10,86 @@ from odoo.addons.sf_base.commons.common import Common
class QualityCheck(models.Model): class QualityCheck(models.Model):
_inherit = "quality.check" _inherit = "quality.check"
quality_state = fields.Selection([
('waiting', '等待'),
('none', '待处理'),
('pass', '通过的'),
('fail', '失败的')], string='状态', tracking=True, store=True,
default='none', copy=False, compute='_compute_quality_state')
individuation_page_PTD = fields.Boolean('个性化记录(是否显示后置三元检测[PTD]页签)', related='workorder_id.individuation_page_PTD')
work_state = fields.Selection(related='workorder_id.state', string='工单状态')
processing_panel = fields.Char(related='workorder_id.processing_panel', string='加工面')
production_line_id = fields.Many2one(related='workorder_id.production_line_id',
string='生产线')
equipment_id = fields.Many2one(related='workorder_id.equipment_id', string='加工设备')
model_file = fields.Binary(related='workorder_id.glb_file', string='加工模型')
detection_report = fields.Binary(related='workorder_id.detection_report', readonly=True, string='检测报告')
test_results = fields.Selection([("合格", "合格"), ("返工", "返工"), ("报废", "报废")], string="检测结果",
default='合格')
reason = fields.Selection(
[("programming", "编程"), ("cutter", "刀具"), ("clamping", "装夹"), ("operate computer", "操机"),
("technology", "工艺"), ("customer redrawing", "客户改图")], string="原因")
detailed_reason = fields.Text('详细原因')
machining_drawings = fields.Binary('2D加工图纸', related='workorder_id.machining_drawings')
quality_standard = fields.Binary('质检标准', related='workorder_id.quality_standard')
operation_id = fields.Many2one('mrp.routing.workcenter', '作业', store=True, compute='_compute_operation_id')
is_inspect = fields.Boolean('需送检', related='point_id.is_inspect')
@api.depends('point_id.operation_id')
def _compute_operation_id(self):
for qc in self:
if qc.point_id.operation_id:
qc.operation_id = qc.point_id.operation_id.id
@api.depends('point_id.is_inspect')
def _compute_quality_state(self):
for qc in self:
if qc.point_id.is_inspect and qc.quality_state == 'none' and qc.workorder_id.state != 'to be detected':
qc.quality_state = 'waiting'
elif not qc.point_id.is_inspect and qc.quality_state == 'waiting':
qc.quality_state = 'none'
@api.onchange('test_results')
def _onchange_test_results(self):
if self.test_results == '合格':
self.reason = False
self.detailed_reason = False
def do_pass(self):
self.ensure_one()
super().do_pass()
if self.workorder_id:
if self.workorder_id.state in ('pending', 'waiting'):
raise ValidationError('工单未就绪!')
# 1将页签“判定结果”的检测结果值同步到【工单_后置三元检测_检测结果】
if self.test_results in ['返工', '报废']:
raise ValidationError('请重新选择【判定结果】-【检测结果】')
if self.workorder_id.state not in ['done']:
self.workorder_id.write({'test_results': '合格'})
# 2将关联的工单状态更新为“已完成”
self.workorder_id.button_finish()
def do_fail(self):
self.ensure_one()
super().do_fail()
if self.workorder_id:
if self.workorder_id.state in ('pending', 'waiting'):
raise ValidationError('工单未就绪!')
# 1将页签“判定结果”的检测结果值同步到【工单_后置三元检测_检测结果】
if not self.test_results:
raise ValidationError('请填写【判定结果】里的信息')
if self.test_results == '合格':
raise ValidationError('请重新选择【判定结果】-【检测结果】')
if self.workorder_id.state not in ['done']:
self.workorder_id.write(
{'test_results': self.test_results, 'reason': self.reason, 'detailed_reason': self.detailed_reason})
# 2将关联的工单状态更新为“已完成”
self.workorder_id.button_finish()
# ==========零件特采接口========== # ==========零件特采接口==========
def _register_quality_check(self): def _register_quality_check(self):
config = self.env['res.config.settings'].get_values() config = self.env['res.config.settings'].get_values()
@@ -31,10 +111,3 @@ class QualityCheck(models.Model):
else: else:
raise ValidationError("零件特采发送失败") raise ValidationError("零件特采发送失败")
# def do_fail(self):
# self.write({
# 'quality_state': 'fail',
# 'user_id': self.env.user.id,
# 'control_date': datetime.now()})
# if self.picking_id and 'WH/MO/' in self.picking_id.origin:
# self._register_quality_check()

View File

@@ -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="原因")

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="mrp_workorder_quality_form_view_inherit" model="ir.ui.view">
<field name="name">mrp.workorder.view.form.inherit.quality</field>
<field name="model">mrp.workorder</field>
<field name="inherit_id" ref="mrp.mrp_production_workorder_form_view_inherit"/>
<field name="arch" type="xml">
<div name="button_box" position="inside">
<field name="check_ids_state" invisible="1"/>
<button name="action_open_quality_check_work_sf" groups="quality.group_quality_user" attrs="{'invisible': ['|',('check_ids_state', '!=', 'none'), ('check_ids', '=', [])]}" type="object" class="oe_stat_button" icon="fa-check">
<span class="o_stat_text">质量检查</span>
</button>
<button name="action_open_quality_check_work_sf" groups="quality.group_quality_user" attrs="{'invisible': ['|',('check_ids_state', '!=', 'pass'), ('check_ids', '=', [])]}" type="object" class="oe_stat_button text-success" icon="fa-check">
<span class="o_stat_text text-success">质量检查</span>
</button>
<button name="action_open_quality_check_work_sf" groups="quality.group_quality_user" attrs="{'invisible': ['|',('check_ids_state', '!=', 'fail'), ('check_ids', '=', [])]}" type="object" class="oe_stat_button text-danger" icon="fa-check">
<span class="o_stat_text text-danger">质量检查</span>
</button>
</div>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="sf_quality_check_view_form" model="ir.ui.view">
<field name="name">sf.quality.check.view.form</field>
<field name="model">quality.check</field>
<field name="inherit_id" ref="quality_control.quality_check_view_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='alert_ids']" position="after">
<field name="production_id" invisible="1"/>
<field name="work_state" invisible="1"/>
<field name="individuation_page_PTD" invisible="1"/>
<field name="production_line_id" attrs="{'invisible': [('production_id', '=', False)]}"/>
<field name="equipment_id" attrs="{'invisible': [('production_id', '=', False)]}"/>
<field name="model_file" widget="Viewer3D" string="模型" readonly="1" force_save="1"
attrs="{'invisible': ['|',('model_file', '=', False), ('production_id', '=', False)]}"/>
</xpath>
<xpath expr="//field[@name='partner_id']" position="after">
<field name="processing_panel" attrs="{'invisible': [('production_id', '=', False)]}"/>
<!-- <field name="production_id" string="制造订单" readonly="1"-->
<!-- attrs="{'invisible': [('production_id', '=', False)]}"/>-->
<field name="workorder_id" string="工单号" readonly="1"
attrs="{'invisible': [('production_id', '=', False)]}"/>
<field name="is_inspect" attrs="{'invisible': [('production_id', '=', False)]}"/>
</xpath>
<xpath expr="//page[@name='notes']" position="before">
<page string="检测报告" attrs="{'invisible': [('production_id', '=', False)]}">
<field name="detection_report" string="" widget="pdf_viewer"/>
</page>
<page string="判定结果" attrs="{'invisible': [('production_id', '=', False)]}">
<group>
<group>
<field name="test_results" attrs="{'readonly': [('quality_state','in', ['pass', 'fail'])]}"/>
<field name="reason"
attrs="{'required': [('test_results','in', ['返工','报废'])],'invisible': [('test_results','in', ['合格',False])],'readonly': [('quality_state','in', ['pass', 'fail'])]}"/>
<field name="detailed_reason"
attrs="{'required': [('reason','!=', False)],'invisible': [('test_results','in', ['合格',False])],'readonly': [('quality_state','in', ['pass', 'fail'])]}"/>
</group>
</group>
</page>
<page string="2D图纸" attrs="{'invisible': [('production_id', '=', False)]}">
<field name="machining_drawings" string="" widget="adaptive_viewer"/>
</page>
<page string="客户质量标准" attrs="{'invisible': [('production_id', '=', False)]}">
<field name="quality_standard" string="" widget="adaptive_viewer"/>
</page>
<page string="其他"
attrs="{'invisible': ['|',('quality_state', 'not in', ['pass', 'fail']), ('production_id', '=', False)]}">
<group>
<field name="write_uid" widget='many2one_avatar_user' string="判定人" readonly="1"/>
<field name="write_date" string="判定时间" readonly="1"/>
</group>
</page>
</xpath>
<xpath expr="//header//button[@name='do_pass'][1]" position="attributes">
<attribute name="string">合格</attribute>
</xpath>
<xpath expr="//header//button[@name='do_pass'][2]" position="attributes">
<attribute name="attrs">{'invisible': ['|',('quality_state', '!=', 'fail'),('work_state','in', ('done', 'rework'))]}</attribute>
<attribute name="string">合格</attribute>
</xpath>
<xpath expr="//header//button[@name='do_fail'][1]" position="attributes">
<attribute name="string">不合格</attribute>
</xpath>
<xpath expr="//header//button[@name='do_fail'][2]" position="attributes">
<attribute name="attrs">{'invisible': ['|',('quality_state', '!=', 'pass'),('work_state','in', ('done', 'rework'))]}</attribute>
<attribute name="string">不合格</attribute>
</xpath>
</field>
</record>
<record id="sf_quality_check_view_tree" model="ir.ui.view">
<field name="name">sf.quality.check.view.tree</field>
<field name="model">quality.check</field>
<field name="inherit_id" ref="quality_control.quality_check_view_tree"/>
<field name="arch" type="xml">
<xpath expr="//tree//field[@name='name']" position="after">
<field name="operation_id" invisible="1"/>
</xpath>
</field>
</record>
<record id="sf_quality_check_view_search" model="ir.ui.view">
<field name="name">sf.quality.check.view.search</field>
<field name="model">quality.check</field>
<field name="inherit_id" ref="quality_control.quality_check_view_search"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='quality_state']" position="after">
<field name="operation_id" icon="fa-filter" enable_counters="1"/>
</xpath>
<xpath expr="//field[@name='product_id']" position="after">
<field name="production_id"/>
</xpath>
</field>
</record>
</odoo>

View File

@@ -57,6 +57,10 @@
<attribute name="class">custom_required</attribute> <attribute name="class">custom_required</attribute>
<attribute name="required">1</attribute> <attribute name="required">1</attribute>
</xpath> </xpath>
<xpath expr="//sheet//group//group[1]//field[@name='operation_id']" position="after">
<field name="is_inspect" attrs="{'invisible': [('is_workorder_step', '=', False)]}"/>
</xpath>
</field> </field>
</record> </record>

View File

@@ -130,7 +130,10 @@ class ReSaleOrder(models.Model):
'order_id': self.id, 'order_id': self.id,
'product_id': product.id, 'product_id': product.id,
'name': '%s/%s/%s/%s/%s/%s' % ( 'name': '%s/%s/%s/%s/%s/%s' % (
product.model_long, product.model_width, product.model_height, product.model_volume, self.format_float(product.model_long),
self.format_float(product.model_width),
self.format_float(product.model_height),
self.format_float(product.model_volume),
machining_accuracy_name, machining_accuracy_name,
product.materials_id.name), product.materials_id.name),
'price_unit': product.list_price, 'price_unit': product.list_price,
@@ -143,6 +146,20 @@ class ReSaleOrder(models.Model):
} }
return self.env['sale.order.line'].with_context(skip_procurement=True).create(vals) return self.env['sale.order.line'].with_context(skip_procurement=True).create(vals)
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)
@api.constrains('order_line') @api.constrains('order_line')
def check_order_line(self): def check_order_line(self):
for item in self: for item in self:
@@ -346,7 +363,7 @@ class RePurchaseOrder(models.Model):
server_product_process = [] server_product_process = []
purchase_order = pp._get_surface_technics_purchase_ids() purchase_order = pp._get_surface_technics_purchase_ids()
if purchase_order: if purchase_order:
purchase_order.write({'state': 'draft'}) # purchase_order.write({'state': 'draft'})
pp.purchase_id = [(6, 0, [purchase_order.id])] pp.purchase_id = [(6, 0, [purchase_order.id])]
else: else:
server_template = self.env['product.template'].search( server_template = self.env['product.template'].search(
@@ -355,7 +372,8 @@ class RePurchaseOrder(models.Model):
server_product_process.append((0, 0, { server_product_process.append((0, 0, {
'product_id': server_template.product_variant_id.id, 'product_id': server_template.product_variant_id.id,
'product_qty': 1, 'product_qty': 1,
'product_uom': server_template.uom_id.id 'product_uom': server_template.uom_id.id,
'related_product': production.product_id.id,
})) }))
# 获取服务商品最后一个供应商的采购员 # 获取服务商品最后一个供应商的采购员
purchase_user_id = server_template.seller_ids[-1].partner_id.purchase_user_id purchase_user_id = server_template.seller_ids[-1].partner_id.purchase_user_id
@@ -370,15 +388,15 @@ class RePurchaseOrder(models.Model):
pp.purchase_id = [(6, 0, [purchase_order.id])] pp.purchase_id = [(6, 0, [purchase_order.id])]
# self.env.cr.commit() # self.env.cr.commit()
@api.onchange('order_line') # @api.onchange('order_line')
def _onchange_order_line(self): # def _onchange_order_line(self):
for order in self: # for order in self:
if order.order_line: # if order.order_line:
line = order.order_line # line = order.order_line
product = line.product_id # product = line.product_id
product_id = product.ids # product_id = product.ids
if len(product_id) != len(line): # if len(product_id) != len(line):
raise ValidationError('%s】已存在,请勿重复添加' % product[-1].name) # raise ValidationError('【%s】已存在请勿重复添加' % product[-1].name)
def button_confirm(self): def button_confirm(self):
result = super(RePurchaseOrder, self).button_confirm() result = super(RePurchaseOrder, self).button_confirm()
@@ -393,7 +411,7 @@ class RePurchaseOrder(models.Model):
if line.product_id.categ_type == '表面工艺': if line.product_id.categ_type == '表面工艺':
if item.origin: if item.origin:
for production_name in item.origin.split(','): for production_name in item.origin.split(','):
production = self.env['mrp.production'].search([('name', '=', production_name)]) production = self.env['mrp.production'].search([('name', '=', production_name.strip())])
for workorder in production.workorder_ids.filtered( for workorder in production.workorder_ids.filtered(
lambda wd: wd.routing_type == '表面工艺' and wd.state == 'waiting' and line.product_id.server_product_process_parameters_id == wd.surface_technics_parameters_id): lambda wd: wd.routing_type == '表面工艺' and wd.state == 'waiting' and line.product_id.server_product_process_parameters_id == wd.surface_technics_parameters_id):
workorder.state = 'ready' workorder.state = 'ready'

View File

@@ -285,7 +285,7 @@
<tree position="attributes"> <tree position="attributes">
<!-- <attribute name="default_order">schedule_status desc,date_order asc</attribute> --> <!-- <attribute name="default_order">schedule_status desc,date_order asc</attribute> -->
<attribute name="default_order">create_date desc</attribute> <attribute name="default_order">create_date desc</attribute>
<attribute name="create">False</attribute> <attribute name="create">false</attribute>
<attribute name="decoration-warning">delivery_warning == 'warning'</attribute> <attribute name="decoration-warning">delivery_warning == 'warning'</attribute>
<attribute name="decoration-danger">delivery_warning == 'overdue'</attribute> <attribute name="decoration-danger">delivery_warning == 'overdue'</attribute>
</tree> </tree>

View File

@@ -143,6 +143,10 @@ class StockLot(models.Model):
record.tool_material_status = '报废' record.tool_material_status = '报废'
else: else:
record.tool_material_status = '未入库' record.tool_material_status = '未入库'
elif record.product_id.categ_id.name in ['夹具']:
if record.quant_ids:
if record.quant_ids[-1].location_id.name in ['夹具房']:
record.tool_material_status = '可用'
@api.model @api.model
def name_search(self, name='', args=None, operator='ilike', limit=100): def name_search(self, name='', args=None, operator='ilike', limit=100):

View File

@@ -1,6 +1,7 @@
import json import json
import requests import requests
import logging import logging
from datetime import datetime
from odoo import fields, models, api from odoo import fields, models, api
from odoo.exceptions import ValidationError from odoo.exceptions import ValidationError
from odoo.addons.sf_base.commons.common import Common from odoo.addons.sf_base.commons.common import Common
@@ -196,12 +197,13 @@ class MrpProduction(models.Model):
}) })
# 自动调用重新获取编程的方法 # 自动调用重新获取编程的方法
logging.info('cnc用刀校验到无效刀自动调用重新编程方法update_programming_state()') logging.info('cnc用刀校验到无效刀自动调用重新编程方法update_programming_state()')
self[0].update_programming_state() self[0].update_programming_state(trigger_time=datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
self[0].write({'is_rework': False}) self[0].write({'is_rework': False})
# 修改制造订单 编程状态变为“编程中” # 修改制造订单 编程状态变为“编程中”
self.write({'programming_state': '编程中', 'work_state': '编程中'}) self.write({'programming_state': '编程中', 'work_state': '编程中'})
self[0].workorder_ids.filtered( self[0].workorder_ids.filtered(
lambda a: a.name == '装夹预调' and a.state not in ['rework', 'done', 'cancel'])._compute_state() lambda a: a.name == '装夹预调' and a.state not in ['rework', 'done', 'cancel'])._compute_state()
return True
if missing_tool_1: if missing_tool_1:
logging.info(f'线边、机内缺刀:{missing_tool_1}') logging.info(f'线边、机内缺刀:{missing_tool_1}')
# 修改 修改cnc程序的刀具状态 为 ‘缺刀’ # 修改 修改cnc程序的刀具状态 为 ‘缺刀’