Compare commits

..

132 Commits

Author SHA1 Message Date
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
37 changed files with 900 additions and 288 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

@@ -200,16 +200,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

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

@@ -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 (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'),
'default_programming_state': cloud_programming['programming_state'], 'default_programming_state': cloud_programming.get('programming_state'),
'default_is_reprogramming': True if cloud_programming['programming_state'] in ['已下发'] else False 'default_is_reprogramming': True if cloud_programming.get('programming_state') in ['已下发'] else False
} }
} }
@@ -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,28 @@ 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
if not is_custemer_group_id.get(is_customer_provided) and is_self_process:
is_custemer_group_id[is_customer_provided] = 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 == '成品' and is_self_process:
vals['procurement_group_id'] = is_custemer_group_id[is_customer_provided]
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[is_customer_provided]
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 +1628,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 +1729,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 +1742,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

@@ -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,53 @@ 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).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,)
@@ -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"/>-->
@@ -81,6 +85,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 +166,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 +347,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 +413,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,9 @@
<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">
<form position="inside">
<field name="_barcode_scanned" widget="barcode_handler" invisible="1"/>
</form>
<!-- <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 +161,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,7 +176,7 @@
<!-- <button name="button_start" type="object" string="开始" class="btn-success" confirm="是否确认开始"--> <!-- <button name="button_start" type="object" string="开始" class="btn-success" confirm="是否确认开始"-->
<!-- attrs="{'invisible': ['|', '|', '|', ('production_state','in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('state', 'in', ('done', 'cancel','to be detected')), ('is_user_working', '!=', False)]}"/>--> <!-- attrs="{'invisible': ['|', '|', '|', ('production_state','in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('state', 'in', ('done', 'cancel','to be detected')), ('is_user_working', '!=', False)]}"/>-->
<button name="button_start" type="object" string="开始" class="btn-success" confirm="是否确认开始" <button name="button_start" type="object" string="开始" class="btn-success"
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)]}"/>
@@ -185,6 +189,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" -->
@@ -522,10 +528,12 @@
<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":[("state","!=","to be detected"), "|",("routing_type","=","CNC加工"),("is_inspect", "=", True)],
"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)]}'/>-->

View File

@@ -25,9 +25,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

@@ -51,6 +51,6 @@ 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)
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})
@@ -284,7 +292,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 +307,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,8 @@
'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/quality_check_view.xml'
], ],
'assets': { 'assets': {

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

@@ -10,6 +10,81 @@ 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')
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':
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:
# 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:
# 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 +106,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

@@ -0,0 +1,85 @@
<?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="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="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'][2]" position="attributes">
<attribute name="attrs">{'invisible': ['|',('quality_state', '!=', 'fail'),('work_state','in', ('done', 'rework'))]}</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>
</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

@@ -346,7 +346,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 +355,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 +371,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 +394,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程序的刀具状态 为 ‘缺刀’