Compare commits

...

510 Commits

Author SHA1 Message Date
hujiaying
b1a08be57b bfm加工订单隐藏字段 ,待发货明细中,接单日期、发货日期顺序改变,欠单如果没有发货不要显示发货时间 、更改逾期状态逻辑。 2024-09-23 12:27:31 +08:00
禹翔辉
a3356fe195 Accept Merge Request #1324: (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/1324
2024-09-19 17:29:29 +08:00
yuxianghui
3c70e1623e Merge branch 'feature/工单状态优化' into feature/库存优化 2024-09-19 17:27:44 +08:00
yuxianghui
51628c081a 1、禁用超级管理员之外的角色通过库存概览跳转到调拨单界面的调拨单创建按钮,隐藏制造作业类型的单据;2、优化移动历史记录。 2024-09-19 17:27:02 +08:00
杨金灵
18ebe6bcb4 Accept Merge Request #1323: (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/1323
2024-09-19 17:25:05 +08:00
jinling.yang
63ac4f2b44 返工工单添加标签字段 2024-09-19 17:23:01 +08:00
马广威
2966260f51 Accept Merge Request #1322: (feature/优化制造功能 -> develop)
Merge Request: 解除装夹处,扫码同步打印成品条码

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1322?initial=true
2024-09-19 15:03:30 +08:00
mgw
c4069995e0 解除装夹处,扫码同步打印成品条码 2024-09-19 14:38:24 +08:00
管欢
54920982a2 Accept Merge Request #1319: (feature/org_info_synchronous -> develop)
Merge Request: 员工信息企微id同步

Created By: @管欢
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @管欢
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1319
2024-09-19 13:52:30 +08:00
廖丹龙
f947a3ed58 Accept Merge Request #1321: (feature/tax_sync -> develop)
Merge Request: bom清单问题修复

Created By: @廖丹龙
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @廖丹龙
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1321?initial=true
2024-09-19 13:50:43 +08:00
liaodanlong
5e86d67316 bom清单问题修复 2024-09-19 13:42:52 +08:00
马广威
7354a19696 Accept Merge Request #1320: (feature/优化制造功能 -> develop)
Merge Request: 扫码获取装夹检测结果

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1320?initial=true
2024-09-19 10:51:20 +08:00
mgw
78e3d77000 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化制造功能 2024-09-19 10:50:06 +08:00
mgw
47ad2410cf 调整agv参数位置 2024-09-19 10:16:09 +08:00
mgw
fa2eb7b3cf 增加是否获取文件判断 2024-09-19 10:07:26 +08:00
guanhuan
0cee6ebd77 员工信息同步 2024-09-19 09:48:01 +08:00
杨金灵
73f161ffa4 Accept Merge Request #1318: (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/1318?initial=true
2024-09-19 09:34:41 +08:00
jinling.yang
ff06d5c3be 消息模版添加时间节点 2024-09-19 09:32:04 +08:00
liaodanlong
78cb177ac5 Merge remote-tracking branch 'origin/develop' into develop 2024-09-19 09:14:33 +08:00
liaodanlong
9601502360 视图菜单与action顺序调整 2024-09-19 09:12:38 +08:00
mgw
739b7e600c Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化制造功能 2024-09-19 09:04:20 +08:00
mgw
27da7639b2 增加扫码点击按钮功能 2024-09-19 09:04:05 +08:00
mgw
258e3bdb9f 一般设置页增加重新获取检测文件配置项目 2024-09-19 09:03:07 +08:00
jinling.yang
7f3e9927d5 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-09-19 08:52:34 +08:00
jinling.yang
927f726030 Merge branch 'feature/优化消息模版' into develop 2024-09-19 08:52:25 +08:00
杨金灵
7576200fc4 Accept Merge Request #1315: (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/1315?initial=true
2024-09-19 08:52:10 +08:00
胡尧
4ffb9d636f Accept Merge Request #1316: (feature/流程用扫码完成 -> develop)
Merge Request: 修改扫码判断起点接驳站逻辑

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1316?initial=true
2024-09-19 08:51:03 +08:00
jinling.yang
24f0547343 消息模块添加销售依赖 2024-09-19 08:50:24 +08:00
胡尧
402a323673 修改扫码判断起点接驳站逻辑 2024-09-19 08:49:23 +08:00
jinling.yang
5e1685417f Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-09-19 08:46:01 +08:00
jinling.yang
9dfe34ce9a 还原注释代码 2024-09-19 08:45:50 +08:00
jinling.yang
190d6da217 还原代码 2024-09-18 17:59:08 +08:00
胡嘉莹
8946b44280 Accept Merge Request #1313: (feature/update_production_line -> develop)
Merge Request: 修改计划排程,新增处理排程计划订单交货时间为null数据处理的方法

Created By: @胡嘉莹
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @胡嘉莹
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1313
2024-09-18 17:44:45 +08:00
廖丹龙
f21d085462 Accept Merge Request #1314: (feature/tax_sync -> develop)
Merge Request: 适用刀具物料类型字段 设置只能去选择。取消必填

Created By: @廖丹龙
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @廖丹龙
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1314
2024-09-18 17:42:28 +08:00
jinling.yang
43f53197c4 优化消息模版 2024-09-18 17:39:06 +08:00
liaodanlong
ac43be1262 适用刀具物料类型字段 设置只能去选择。取消必填 2024-09-18 16:36:52 +08:00
jinling.yang
8bf1c56efd Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化消息模版
# Conflicts:
#	sf_tool_management/models/base.py
2024-09-18 15:40:54 +08:00
jinling.yang
d66791dc41 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-09-18 15:39:50 +08:00
jinling.yang
ce6b36a77e 12 2024-09-18 15:39:42 +08:00
hujiaying
4acae01009 修改计划排程,新增处理排程计划订单交货时间为null数据处理的方法 2024-09-18 15:34:04 +08:00
胡尧
213b76a280 Accept Merge Request #1312: (feature/流程用扫码完成 -> develop)
Merge Request: 解除装夹工单页面进入时失去焦点

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1312
2024-09-18 15:15:10 +08:00
胡尧
c675e1d67c 解除装夹工单页面进入时失去焦点 2024-09-18 15:13:20 +08:00
胡嘉莹
8a9f6ab34f Accept Merge Request #1311: (feature/update_production_line -> 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/1311
2024-09-18 14:14:50 +08:00
hujiaying
8aca6ce084 修改计划排程甘特图界面不显示已经排程的制造订单 2024-09-18 14:03:04 +08:00
禹翔辉
cb0c093006 Accept Merge Request #1310: (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/1310?initial=true
2024-09-18 11:56:37 +08:00
yuxianghui
1e7d7008b4 Merge branch 'feature/工单优化' into feature/工单状态优化 2024-09-18 11:55:02 +08:00
yuxianghui
ef453dbc1e 工单状态优化 2024-09-18 11:53:46 +08:00
jinling.yang
9f1e635c8d Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-09-18 10:23:51 +08:00
jinling.yang
92037f3f04 注释OCC代码 2024-09-18 10:23:42 +08:00
禹翔辉
4ba0566d27 Accept Merge Request #1309: (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/1309?initial=true
2024-09-18 09:46:36 +08:00
yuxianghui
5d870d53f6 Merge branch 'feature/刀具拆解单优化' into feature/工单优化 2024-09-18 09:30:49 +08:00
yuxianghui
6a674cdb5b 工单状态优化 2024-09-18 09:28:36 +08:00
胡嘉莹
fbce132173 Accept Merge Request #1308: (feature/update_production_line -> 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/1308
2024-09-14 17:45:18 +08:00
guanhuan
98e13cba99 员工信息企微id同步 2024-09-14 17:45:00 +08:00
liaodanlong
7ce2f6c797 历史销售订单价格问题 2024-09-14 17:40:45 +08:00
hujiaying
7502792438 修改计划排程列表进入待排程的制造订单详情进行排程-报错 2024-09-14 17:26:24 +08:00
hujiaying
9efb13cf01 修改排程计划开始时间修改 2024-09-14 16:34:47 +08:00
管欢
b14e263a2e Accept Merge Request #1306: (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/1306
2024-09-14 14:40:58 +08:00
马广威
6f41ef3047 Accept Merge Request #1307: (feature/优化制造功能 -> develop)
Merge Request: 增加拉取文件之前的检查

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1307?initial=true
2024-09-14 14:34:02 +08:00
mgw
de29f0c938 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化制造功能 2024-09-14 14:32:55 +08:00
mgw
589a24f595 增加拉取文件之前的检查 2024-09-14 14:32:40 +08:00
胡嘉莹
85186f94f5 Accept Merge Request #1302: (feature/update_production_line -> develop)
Merge Request: 优化计划开始时间默认往后延迟10分钟

Created By: @胡嘉莹
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @胡嘉莹
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1302
2024-09-14 14:31:56 +08:00
廖丹龙
ffc363a31c Accept Merge Request #1305: (feature/tax_sync -> develop)
Merge Request: 功能刀具清单 bom添加查询排序与清单明细行删除校验

Created By: @廖丹龙
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @廖丹龙
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1305?initial=true
2024-09-14 14:30:59 +08:00
胡尧
a047ad3bb6 Accept Merge Request #1304: (feature/流程用扫码完成 -> develop)
Merge Request: 去掉多余的js引用,将工件配送页面起点接驳站修改为当前接驳站

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1304?initial=true
2024-09-14 14:09:29 +08:00
胡尧
cc3289c834 将工件配送页面起点接驳站修改为当前接驳站 2024-09-14 13:49:46 +08:00
胡尧
e1093a3c69 去掉多余的js引用 2024-09-14 13:42:38 +08:00
guanhuan
ba955ca658 快速订单上传模型文件检查文件后缀 2024-09-14 08:46:32 +08:00
禹翔辉
946abc5cf7 Accept Merge Request #1303: (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/1303?initial=true
2024-09-13 17:42:16 +08:00
yuxianghui
57ea9ed8f4 Merge branch 'feature/组装单重构_2' into feature/刀具拆解单优化 2024-09-13 17:38:19 +08:00
hujiaying
f8a12b1fe3 优化计划开始时间默认往后延迟10分钟 2024-09-13 17:37:57 +08:00
yuxianghui
722f6257ae 1、优化刀具拆解单 2024-09-13 17:37:20 +08:00
guanhuan
ccbe311c58 快速订单填写的零件图号和零件图纸传给制造订单 2024-09-13 10:45:08 +08:00
管欢
0f6ca0876c Accept Merge Request #1300: (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/1300
2024-09-13 10:41:19 +08:00
马广威
bb60fd0339 Accept Merge Request #1301: (feature/优化制造功能 -> develop)
Merge Request: 优化dashboard接口,及装夹bug

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1301?initial=true
2024-09-13 10:40:58 +08:00
mgw
eefbd5939b Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化制造功能 2024-09-13 10:38:23 +08:00
mgw
7c01196f17 修复“装夹预调工单没有测量数据时点击左上角的【完成】按钮直接完成工单了” 2024-09-13 10:37:50 +08:00
guanhuan
4c58f4d7f3 快速订单填写的零件图号和零件图纸传给制造订单 2024-09-13 10:22:14 +08:00
胡嘉莹
c741587341 Accept Merge Request #1299: (feature/update_production_line -> 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/1299?initial=true
2024-09-13 10:21:11 +08:00
hujiaying
6ad2fa80f1 修改销售,采购,制造,仓库产品设置产品类型为默认分组 2024-09-13 10:15:26 +08:00
胡尧
55694ae303 Merge branch 'develop' into feature/流程用扫码完成 2024-09-13 08:53:16 +08:00
禹翔辉
8423b12119 Accept Merge Request #1298: (feature/组装单重构_2 -> develop)
Merge Request: 组装单重构

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1298?initial=true
2024-09-12 17:27:42 +08:00
jinling.yang
5a7ba7f87e Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-09-12 17:24:43 +08:00
jinling.yang
d36da3df24 Merge branch 'feature/新增消息提醒模版' into develop 2024-09-12 17:24:35 +08:00
杨金灵
302a5f0cf1 Accept Merge Request #1297: (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/1297
2024-09-12 17:24:18 +08:00
yuxianghui
b4fef421dd Merge branch 'feature/功能刀具重构_1' into feature/组装单重构_2 2024-09-12 17:24:13 +08:00
jinling.yang
5f5e991d33 优化页面 2024-09-12 17:24:01 +08:00
yuxianghui
43a49242c5 1、组装单布局调整 2024-09-12 17:21:37 +08:00
yuxianghui
2e5694cd1a 1、优化组装单扫描验证物料方法;2、对组装单物料批次进行调整,删除部分字段和方法;优化获取BOM并自动初始化物料数据方法;3、货位批次模型新增物料字段,新增tree视图,并且除刀柄外物料点击【更多】时跳转至不同的货位批次模型tree视图;4、添加刀柄和其他物料在点击【更多】按钮后选取新物料点击【确认】后回填物料信息到组装单并给出提示信息;5、添加组装物料信息校验功能,初始化或重新选取物料后需进行验证才能进行组装;6、组装单form视图布局调整; 2024-09-12 17:20:58 +08:00
jinling.yang
3c123a07ea Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/新增消息提醒模版 2024-09-12 17:06:33 +08:00
jinling.yang
dec5ddd154 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-09-12 17:06:24 +08:00
jinling.yang
22864b9669 新增消息提醒模版 2024-09-12 17:06:16 +08:00
管欢
528fa483a2 Accept Merge Request #1296: (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/1296
2024-09-12 16:48:28 +08:00
guanhuan
b5a3815f1f 设备维保标准筛选添加已归档 2024-09-12 16:43:54 +08:00
mgw
1719e0394e 去掉run_time返回 2024-09-12 16:33:55 +08:00
mgw
eae902ee92 调整设备运行时长 2024-09-12 15:36:30 +08:00
liaodanlong
01c57a8691 去除无用代码添加描述信息 2024-09-12 15:17:47 +08:00
liaodanlong
2808005ce9 错误处理 2024-09-12 15:17:09 +08:00
mgw
06c5f65df2 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化制造功能 2024-09-12 11:08:41 +08:00
mgw
e0bad6ed40 优化当班计划量,完成量数据 2024-09-12 11:08:24 +08:00
jinling.yang
35c8b9316e Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/new 2024-09-12 10:46:40 +08:00
jinling.yang
2ddfbb0dde Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-09-12 10:46:29 +08:00
guanhuan
988c4a460d 2D加工图纸改为pdf 2024-09-12 10:24:45 +08:00
guanhuan
c050e2f11a 供应商详情的采购员去掉必填 2024-09-12 10:14:38 +08:00
mgw
95e49c7b0f 优化打印输出 2024-09-12 09:17:52 +08:00
管欢
e46a13889e Accept Merge Request #1295: (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/1295
2024-09-12 08:38:01 +08:00
mgw
335151f6ca Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化制造功能 2024-09-11 18:11:07 +08:00
mgw
908e4a3df6 调整通过数量取值 2024-09-11 18:07:21 +08:00
胡嘉莹
6b403f2c1e Accept Merge Request #1294: (feature/update_production_line -> 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/1294?initial=true
2024-09-11 17:58:51 +08:00
yuxianghui
da5e322229 1、组装单新增五种物料的【更多】按钮,点击按钮跳转至新的弹窗界面,根据功能刀具清单BOM的配置,搜索出全部满足条件的刀柄产品或者其他刀具物料对应的批次、货位,使用tree视图提供选择。2、新增产品tree、search视图 2024-09-11 17:49:43 +08:00
hujiaying
4f9ac16a07 修改计划排程,已取消的不占用小时或日产数量 2024-09-11 17:48:08 +08:00
mgw
4342844845 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化制造功能 2024-09-11 17:41:49 +08:00
guanhuan
8bc68e1edd 表面工艺参数取消必填 2024-09-11 17:40:28 +08:00
mgw
763d64a1ca 增加设备运行时长效率接口 2024-09-11 14:57:42 +08:00
胡嘉莹
8a10d18f37 Accept Merge Request #1293: (feature/update_production_line -> 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/1293?initial=true
2024-09-11 12:15:17 +08:00
hujiaying
181f490d47 修改计划排程时间范围内判断取值向上取整 2024-09-11 11:53:17 +08:00
mgw
322718d19a Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化制造功能 2024-09-11 11:45:36 +08:00
mgw
96eeb1cab7 调整检测量、合格量 2024-09-11 11:45:14 +08:00
胡尧
d5c82e4a28 修改代码问题 2024-09-11 10:40:26 +08:00
liaodanlong
436adc5ff6 功能刀具清单 bom添加查询排序与清单明细行删除校验 2024-09-11 10:39:27 +08:00
廖丹龙
97a5d91fce Accept Merge Request #1292: (feature/tax_sync -> develop)
Merge Request: 功能刀具清单 bom添加查询排序与清单明细行删除校验

Created By: @廖丹龙
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @廖丹龙
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1292?initial=true
2024-09-11 10:30:08 +08:00
liaodanlong
9eee8557c2 功能刀具清单 bom添加查询排序与清单明细行删除校验 2024-09-11 10:23:02 +08:00
mgw
4394dd023e 增加交付准时率 2024-09-11 10:11:22 +08:00
胡尧
d39bbe4f99 Accept Merge Request #1291: (feature/流程用扫码完成 -> develop)
Merge Request: 工件配送,解除装夹使用扫码完成

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1291
2024-09-11 09:15:48 +08:00
胡尧
b188c8adfe 修改异常提示 2024-09-11 09:14:00 +08:00
guanhuan
ea6fd42b2e SF快速订单优化 2024-09-11 09:01:24 +08:00
guanhuan
625499f758 SF快速订单优化 2024-09-11 08:59:44 +08:00
guanhuan
0c2d6dd582 SF快速订单优化 2024-09-11 08:52:28 +08:00
mgw
f6a9c97e7f 优化产量部分 2024-09-11 08:51:01 +08:00
yuxianghui
e2d741937e 1、实现功能刀具点击开始组装时,自动获取功能刀具清单BOM信息,并根据规则匹配刀具物料信息进行信息初始化;2、对组装单form界面进行调整,并隐藏夹头物料的所以信息; 2024-09-10 17:52:40 +08:00
胡尧
9a3404f4b8 去掉屏蔽的代码 2024-09-10 17:51:27 +08:00
胡尧
d000aa095f 对于测试用例进行修改 2024-09-10 17:49:52 +08:00
胡尧
8945801db8 解决冲突 2024-09-10 16:16:30 +08:00
胡尧
40f327ea17 修改工件拆卸 2024-09-10 16:13:57 +08:00
mgw
44a2604dbd Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化制造功能 2024-09-10 16:13:17 +08:00
mgw
0ae7424f04 获取数据按钮增加调用服务功能 2024-09-10 16:12:24 +08:00
胡嘉莹
091af92e8d Accept Merge Request #1290: (feature/update_production_line -> 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/1290
2024-09-10 15:56:16 +08:00
hujiaying
3ed338ed64 修改计划-生产订单列表只显示制造订单 2024-09-10 14:50:24 +08:00
hujiaying
65781570e7 修改计划-生产订单列表只显示制造订单 2024-09-10 14:38:25 +08:00
liaodanlong
e1f7aeaa96 修改字段位置 2024-09-10 13:53:23 +08:00
胡嘉莹
a0a580588c Accept Merge Request #1289: (feature/update_production_line -> 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/1289?initial=true
2024-09-10 11:26:52 +08:00
mgw
a2f2a21a4c Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化制造功能 2024-09-10 11:17:23 +08:00
hujiaying
1ddb446bc6 修改计划排程单小时产能取值 2024-09-10 11:15:00 +08:00
廖丹龙
dcdc6851b6 Accept Merge Request #1288: (feature/tax_sync -> develop)
Merge Request: bom物料清单添加错误信息,添加刀具物料字段展示

Created By: @廖丹龙
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @廖丹龙
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1288
2024-09-10 09:23:31 +08:00
liaodanlong
ece4e56118 Merge branch 'refs/heads/develop' into feature/tax_sync 2024-09-10 09:19:48 +08:00
liaodanlong
7cd104c047 bom物料清单添加错误信息,添加刀具物料字段展示 2024-09-10 09:18:43 +08:00
yuxianghui
80a7dd75c8 Merge branch 'feature/功能刀具重构' into feature/功能刀具重构_1 2024-09-10 08:28:47 +08:00
hujiaying
ec2ef752b3 补充模块注释 2024-09-09 18:04:10 +08:00
廖丹龙
57d5c57048 Accept Merge Request #1287: (feature/tax_sync -> develop)
Merge Request: bom物料清单,sf与cloud数据同步

Created By: @廖丹龙
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @廖丹龙
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1287
2024-09-09 18:00:55 +08:00
yuxianghui
9b7c22c35e 1、对组装单物料批次号获取逻辑进行优化,更改form视图批次字段显示条件;2、开发 寿命到期功能刀具完成拆解后关联生成并跳转到组装单的需求 需求 2024-09-09 17:54:10 +08:00
liaodanlong
6711f6f6e6 Merge branch 'refs/heads/develop' into feature/tax_sync 2024-09-09 17:37:21 +08:00
liaodanlong
7ac7077f8c bom物料清单 2024-09-09 17:36:23 +08:00
胡尧
ed20249988 Accept Merge Request #1286: (feature/流程用扫码完成 -> develop)
Merge Request: 扫码触发页面按钮,解除装夹起始站点根据下产线终点站点自动赋值

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1286
2024-09-09 17:31:25 +08:00
liaodanlong
dba8d23348 销售订单价格问题 2024-09-09 17:11:33 +08:00
胡嘉莹
ab9062983c Accept Merge Request #1285: (feature/update_production_line -> 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/1285?initial=true
2024-09-09 14:16:31 +08:00
hujiaying
37493a4688 sf计划排程计算排程时间日排程的制造订单总数量不能超过产线日产能数量,计算排程时间制造订单每小时排程不能超过产线小时产能 2024-09-09 14:08:39 +08:00
胡嘉莹
689d149edc Accept Merge Request #1282: (feature/仓库发货下发bfm -> 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/1282
2024-09-09 11:02:17 +08:00
管欢
9b9106c5da Accept Merge Request #1283: (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/1283
2024-09-09 10:53:20 +08:00
liaodanlong
9a43af98c3 cloud 与 sf 静态资源同步问题 2024-09-09 10:46:05 +08:00
yuxianghui
1eae92f2b2 1、功能刀具组装单添加物料校验标签字段、新增扫描校验功能、优化相关计算方法;2、添加新旧、粗中精字段值根据所选物料自动计算方法,伸出长自动计算方法;3、去除部分字段的校验方法;4、组装单form、tree视图布局调整,tree视图状态字段添加背景颜色,变更筛选条件; 2024-09-06 17:55:59 +08:00
hujiaying
4560bbc0ed sf计划排程计算生产线是否配置生产线,计算排程时间是否在工作时间内,计算生产线是否有可排程的资源, 2024-09-06 17:48:27 +08:00
胡尧
2d5ef0aae4 解除装夹起点从下产线agv调度任务关联带出 2024-09-06 15:34:30 +08:00
胡尧
096542c8ff 扫码触发按键功能 2024-09-06 09:37:05 +08:00
hujiaying
d123ca5173 修改日有效工作时长计算规则 2024-09-06 09:13:38 +08:00
胡尧
388929f207 扫码触发按键功能 2024-09-05 17:59:55 +08:00
yuxianghui
29b9223a14 1、将功能刀具组装弹窗模型的组装流程以及其中相关的业务逻辑,移动到组装单模型并进行优化;2、功能刀具组装单模型新增部分字段的自动计算方法;新增部分物料字段; 2024-09-05 17:57:23 +08:00
hujiaying
cf283377cd 计划排程考虑CNC生产线日产能的优化需求,新增可用机台数量,单台小时产能,日有效工作时长计算规则 2024-09-05 17:39:36 +08:00
hujiaying
5f218e69d4 计划排程考虑CNC生产线日产能的优化需求,新增可用机台数量,单台小时产能,日有效工作时长计算规则 2024-09-05 17:39:09 +08:00
mgw
7f5fb165de Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化制造功能 2024-09-05 10:30:21 +08:00
mgw
eec79d7d3e 优化图片返回为url 2024-09-05 10:30:04 +08:00
hujiaying
00809d88f6 修改打印日志 2024-09-05 09:53:32 +08:00
hujiaying
18b0cc6ea0 Merge remote-tracking branch 'origin/develop' into feature/仓库发货下发bfm 2024-09-05 09:38:40 +08:00
hujiaying
54d9902ae4 撤回修改 2024-09-05 09:26:05 +08:00
hujiaying
eff39a39e3 修改 cloud端新建表面工艺参数必填参数不能填写 2024-09-05 09:24:45 +08:00
guanhuan
005a7bb68e 建立设备维保标准,建立设备维保标准修复 2024-09-05 08:51:36 +08:00
胡嘉莹
afc1701150 Accept Merge Request #1281: (feature/仓库发货下发bfm -> develop)
Merge Request: 工厂发货下发bfm

Created By: @胡嘉莹
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @胡嘉莹
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1281?initial=true
2024-09-04 18:24:24 +08:00
yuxianghui
72eada0639 1、功能刀具组装tree、form视图布局调整;2、部分字段内容进行调整;3、功能刀具组装单编码自动生成方法添加新逻辑; 2024-09-04 17:55:24 +08:00
jinling.yang
979e8a47ab Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-09-04 17:45:02 +08:00
jinling.yang
e119a364c1 Merge branch 'feature/优化返工-保留装夹测量数据' into develop 2024-09-04 17:44:50 +08:00
杨金灵
c7b9bbb18d Accept Merge Request #1280: (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/1280
2024-09-04 17:44:07 +08:00
jinling.yang
3cb3dce247 优化返工代码 2024-09-04 17:43:48 +08:00
jinling.yang
a7e1c89e66 还原代码 2024-09-04 17:36:41 +08:00
jinling.yang
ca1060ada5 去掉注释代码 2024-09-04 17:33:54 +08:00
hujiaying
69578ab054 bfm新增库存菜单,代发货菜单,处理sf一次性发货,bfm生成代发货名字规则 2024-09-04 17:28:26 +08:00
jinling.yang
511bed47ff 优化返工-保留装夹测量数据 2024-09-04 16:58:55 +08:00
jinling.yang
26a0412649 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-09-04 15:00:47 +08:00
杨金灵
4989ff773c Accept Merge Request #1279: (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/1279
2024-09-04 14:59:59 +08:00
jinling.yang
04c0d68763 接口暂时去掉身份验证 2024-09-04 14:58:04 +08:00
hujiaying
589035d42b 处理采购订单代发货数量修改及创建欠单,处理sf发货单下发不需要创建欠单,处理bfm发货单下发内部管理,内部管理处理不需要创建欠单 2024-09-03 19:14:48 +08:00
mgw
5726d50106 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化制造功能 2024-09-03 17:26:56 +08:00
liaodanlong
6e9c326a52 智能工厂数据同步任务的错误提示优化 2024-09-03 13:56:16 +08:00
hujiaying
fc1cdf4d0e 联调接口数据,处理修改sf下发代发货,bfm接收代发货消息,下发到内部管理,处理采购订单代发货数量修改及创建欠单 2024-09-02 19:02:53 +08:00
杨金灵
45178ac38b Accept Merge Request #1278: (hotfix/修复报废-外协入库验证 -> 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/1278
2024-09-02 17:48:53 +08:00
jinling.yang
09ee1c26b1 修复报废-外协入库验证 2024-09-02 17:33:06 +08:00
liaodanlong
64180ca57f Merge branch 'refs/heads/develop' into feature/tax_sync 2024-09-02 15:43:25 +08:00
jinling.yang
0c052a118c Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-09-02 14:44:59 +08:00
mgw
cb9fd43f11 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化制造功能 2024-09-02 09:04:59 +08:00
mgw
1dc55c2770 调整不良工单逻辑 2024-09-02 09:04:42 +08:00
hujiaying
0ca6d46a7b 修改sf下发欠单,bfm接收下发欠单,及处理发货单的关系 2024-08-31 21:09:56 +08:00
liaodanlong
3624ef4755 销售订单价格问题处理 2024-08-30 16:30:34 +08:00
胡尧
f07a003f2c Accept Merge Request #1277: (hotfix/修改agv回调接口授权 -> develop)
Merge Request: 将agv回调接口授权改为none

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1277?initial=true
2024-08-30 09:46:45 +08:00
胡尧
0ef46407dd 将agv回调接口授权改为none 2024-08-30 09:35:08 +08:00
jinling.yang
f7f3c005f8 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-08-30 08:59:09 +08:00
马广威
cae5e14587 Accept Merge Request #1276: (release/release_2.3 -> master)
Merge Request: SPRINT-MES-2024-05

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1276?initial=true
2024-08-29 22:02:45 +08:00
胡尧
a2990b8f2e Accept Merge Request #1275: (feature/agv_dispatch -> develop)
Merge Request: 修改agv相关接口请求授权用户

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1275
2024-08-29 20:21:33 +08:00
胡尧
5121e455d2 修改agv相关接口请求授权用户 2024-08-29 20:20:39 +08:00
马广威
4a14fa6bf6 Accept Merge Request #1274: (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/1274
2024-08-29 19:55:09 +08:00
jinling.yang
f251878637 优化工单工序,优化表面工艺排序 2024-08-29 19:53:37 +08:00
jinling.yang
9a5aa52801 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-08-29 19:45:53 +08:00
jinling.yang
5b3193d3ff Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/new 2024-08-29 19:45:44 +08:00
禹翔辉
52befb6233 Accept Merge Request #1273: (feature/工单优化_2 -> develop)
Merge Request: 电解电镀-电解电镀

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1273
2024-08-29 19:25:22 +08:00
yuxianghui
9ce1963d44 Merge branch 'feature/工单优化_1' into feature/工单优化_2 2024-08-29 19:23:55 +08:00
yuxianghui
1b710b205f 工单优化 2024-08-29 19:23:15 +08:00
禹翔辉
0d253c54c8 Accept Merge Request #1272: (feature/工单优化_1 -> develop)
Merge Request: 优化工单

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1272
2024-08-29 18:19:22 +08:00
yuxianghui
d2c5fdb509 优化工单 2024-08-29 18:18:19 +08:00
马广威
40209958f2 Accept Merge Request #1271: (feature/优化制造功能 -> develop)
Merge Request: 修复验证代码

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1271?initial=true
2024-08-29 17:53:39 +08:00
mgw
778896a670 修复验证代码 2024-08-29 17:52:56 +08:00
禹翔辉
fcacf609e9 Accept Merge Request #1270: (feature/工单优化_1 -> develop)
Merge Request: 优化工单工序排序方法

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1270
2024-08-29 17:36:11 +08:00
yuxianghui
5cd134758a Merge branch 'feature/工单工序排序方法优化' into feature/工单优化_1 2024-08-29 17:33:06 +08:00
yuxianghui
b8f8e90444 Merge branch 'feature/刀具组装扫码优化' into feature/工单工序排序方法优化 2024-08-29 17:31:39 +08:00
jinling.yang
b50a852f77 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-08-29 17:31:38 +08:00
yuxianghui
ea94d74657 优化工单工序排序方法 2024-08-29 17:30:54 +08:00
jinling.yang
b5bea1f811 Merge branch 'feature/修复销售-表面工艺外协' into develop 2024-08-29 17:30:47 +08:00
杨金灵
8416630593 Accept Merge Request #1269: (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/1269
2024-08-29 17:30:32 +08:00
jinling.yang
6572ca25fe 优化提示 2024-08-29 17:30:16 +08:00
jinling.yang
6a7e6ee5c5 修复销售-表面工艺外协 2024-08-29 17:24:09 +08:00
杨金灵
aff35f2dd4 Accept Merge Request #1268: (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/1268
2024-08-29 15:25:11 +08:00
jinling.yang
8ead5655cf 修复外协采购 2024-08-29 15:23:28 +08:00
jinling.yang
d6b3a5a3f1 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-08-29 14:26:34 +08:00
jinling.yang
19d8f6ae73 Merge branch 'feature/优化工单' into develop 2024-08-29 14:26:24 +08:00
杨金灵
ae8e304d7f Accept Merge Request #1267: (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/1267
2024-08-29 14:25:52 +08:00
jinling.yang
e154f5b763 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化工单
# Conflicts:
#	sf_manufacturing/models/mrp_workorder.py
2024-08-29 14:22:50 +08:00
jinling.yang
804bdb60e8 修复外协采购单 2024-08-29 14:21:18 +08:00
马广威
302636635c Accept Merge Request #1266: (feature/优化制造功能 -> develop)
Merge Request: 翻译持久化

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1266?initial=true
2024-08-28 20:32:23 +08:00
mgw
c465822774 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化制造功能 2024-08-28 20:31:35 +08:00
mgw
f9063bf3d9 翻译持久化 2024-08-28 20:31:20 +08:00
马广威
ea6fb5e570 Accept Merge Request #1265: (feature/优化制造功能 -> develop)
Merge Request: 修复装夹判断逻辑

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1265?initial=true
2024-08-28 18:08:16 +08:00
mgw
0e672aef79 修复装夹判断逻辑 2024-08-28 18:07:34 +08:00
马广威
11ec04de5b Accept Merge Request #1264: (feature/优化制造功能 -> develop)
Merge Request: 修改装夹提示词

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1264?initial=true
2024-08-28 17:43:15 +08:00
mgw
efe98b5133 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化制造功能 2024-08-28 17:42:38 +08:00
mgw
2d2abfce25 修改提示词 2024-08-28 17:42:23 +08:00
jinling.yang
821a7a63be 优化工单 2024-08-28 17:30:46 +08:00
廖丹龙
de221ba67e Accept Merge Request #1263: (feature/tax_sync -> develop)
Merge Request: 多面工艺排程问题

Created By: @廖丹龙
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @廖丹龙
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1263
2024-08-28 14:55:40 +08:00
liaodanlong
c5bb9a32d0 多面工艺排程问题 2024-08-28 14:50:39 +08:00
杨金灵
925fc2f2b3 Accept Merge Request #1262: (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/1262
2024-08-28 10:42:53 +08:00
jinling.yang
41f379ef5f 优化下发编程单 2024-08-28 10:41:16 +08:00
jinling.yang
acc791978d Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-08-28 10:39:11 +08:00
jinling.yang
f24c1ab4a5 Merge branch 'feature/修复报废-下发编程单' into develop 2024-08-28 10:31:04 +08:00
杨金灵
179899e483 Accept Merge Request #1261: (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/1261
2024-08-28 10:30:45 +08:00
jinling.yang
b8d21b7fa5 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/修复报废-下发编程单 2024-08-28 10:29:14 +08:00
jinling.yang
295f7ecae3 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-08-28 10:28:10 +08:00
jinling.yang
d2a76a03d2 修复报废-下发编程单 2024-08-28 10:28:01 +08:00
hujiaying
1e172cb4e3 处理代发货下发 2024-08-27 17:24:04 +08:00
马广威
4424cb58f4 Accept Merge Request #1260: (feature/优化制造功能 -> develop)
Merge Request: 接口优化

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1260?initial=true
2024-08-27 17:08:35 +08:00
jinling.yang
cd0ea08b21 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-08-27 17:00:57 +08:00
jinling.yang
10065e95d3 Merge branch 'feature/修复报废-时间' into develop 2024-08-27 17:00:45 +08:00
杨金灵
2c06c6f6a1 Accept Merge Request #1259: (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/1259?initial=true
2024-08-27 17:00:09 +08:00
jinling.yang
1eeaf2f85d Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-08-27 16:58:41 +08:00
jinling.yang
aa96e63fff 修复报废-时间 2024-08-27 16:58:32 +08:00
胡尧
7ac09653c3 Accept Merge Request #1258: (feature/agv_dispatch -> develop)
Merge Request: 修改日期序列的bug

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1258
2024-08-27 16:49:35 +08:00
胡尧
9c3ed0166b 修改日期序列的bug 2024-08-27 16:49:04 +08:00
廖丹龙
3c8ce870df Accept Merge Request #1257: (feature/tax_sync -> develop)
Merge Request: 错误处理

Created By: @廖丹龙
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @廖丹龙
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1257?initial=true
2024-08-27 16:38:22 +08:00
liaodanlong
d8e65a20d5 Merge branch 'refs/heads/develop' into feature/tax_sync 2024-08-27 16:34:57 +08:00
liaodanlong
10a622b52d 错误处理 2024-08-27 16:34:27 +08:00
禹翔辉
c1ffd3f870 Accept Merge Request #1255: (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/1255
2024-08-27 16:18:05 +08:00
jinling.yang
a98b7456c0 Merge branch 'feature/修复报废-坯料序列号' into develop 2024-08-27 16:16:01 +08:00
杨金灵
7e3d40bd38 Accept Merge Request #1256: (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/1256
2024-08-27 16:15:12 +08:00
jinling.yang
83d45b6d3f Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/修复报废-坯料序列号 2024-08-27 16:13:06 +08:00
jinling.yang
fe237dc742 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-08-27 16:12:57 +08:00
jinling.yang
35c13dc51c 修复报废-坯料序列号 2024-08-27 16:12:48 +08:00
yuxianghui
08477e4d94 Merge branch 'feature/收藏无法删除缺陷优化' into feature/刀具组装扫码优化 2024-08-27 14:43:16 +08:00
yuxianghui
069d1f50b0 解决刀具组装时,扫描刚刚拆解完的刀柄状态没有实时更新为可用的问题。 2024-08-27 14:39:49 +08:00
廖丹龙
dd60dee22d Accept Merge Request #1254: (feature/tax_sync -> develop)
Merge Request: 多面加工工单排程优化

Created By: @廖丹龙
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @廖丹龙
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1254
2024-08-27 14:10:43 +08:00
liaodanlong
e49362e2e3 Merge branch 'refs/heads/develop' into feature/tax_sync 2024-08-27 14:04:13 +08:00
liaodanlong
d5b5231873 多面加工工单排程优化 2024-08-27 14:03:41 +08:00
mgw
2b080c1639 优化完成量接口 2024-08-27 11:43:56 +08:00
jinling.yang
bd3bfc979e Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-08-27 11:39:48 +08:00
jinling.yang
5a3233d539 Merge branch 'feature/优化表面工艺排序' into develop 2024-08-27 11:39:04 +08:00
杨金灵
3e8f045a40 Accept Merge Request #1253: (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/1253
2024-08-27 11:38:47 +08:00
jinling.yang
d1fab6aab0 还原代码 2024-08-27 11:38:30 +08:00
jinling.yang
a3357e01aa Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化表面工艺排序
# Conflicts:
#	sf_manufacturing/models/stock.py
#	sf_mrs_connect/controllers/controllers.py
2024-08-27 11:34:39 +08:00
jinling.yang
c46a148856 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-08-27 11:33:33 +08:00
jinling.yang
5794f75f0b Merge branch 'feature/修复报废' into develop 2024-08-27 11:33:04 +08:00
杨金灵
01d9d4a636 Accept Merge Request #1252: (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/1252
2024-08-27 11:32:46 +08:00
jinling.yang
2931d6a92d 去掉不要的代码 2024-08-27 11:32:16 +08:00
jinling.yang
5e6ae1ff55 去掉设置token代码 2024-08-27 11:29:17 +08:00
jinling.yang
d7a0dc578b Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/修复报废
# Conflicts:
#	sf_manufacturing/models/mrp_workorder.py
2024-08-27 11:27:42 +08:00
jinling.yang
44a11c839f 修复下发编程单(报废) 2024-08-27 11:25:12 +08:00
jinling.yang
9808f49b3d Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-08-27 11:24:13 +08:00
jinling.yang
b40a87df88 修复报废 2024-08-27 11:24:04 +08:00
胡尧
72e9443048 Accept Merge Request #1251: (feature/agv_dispatch -> develop)
Merge Request: 修复工件配送后没有同步任务下发时间的bug,AGV配置中增加是否下发AGV任务

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1251?initial=true
2024-08-27 10:43:44 +08:00
胡尧
c6f6927d57 修复工件配送后没有同步任务下发时间的bug,AGV配置中增加是否下发AGV任务 2024-08-27 10:42:24 +08:00
mgw
ade7588a9c 修改返回数据顺序 2024-08-27 10:23:53 +08:00
mgw
281f03670e Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化制造功能 2024-08-27 10:20:13 +08:00
mgw
7356e0afb7 接口优化 2024-08-27 10:19:53 +08:00
胡尧
fcd86e230a Accept Merge Request #1250: (feature/update_process_start_time -> 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/1250
2024-08-27 10:05:55 +08:00
guanhuan
bf1271a742 Merge remote-tracking branch 'origin/feature/update_process_start_time' into feature/update_process_start_time 2024-08-27 10:02:31 +08:00
guanhuan
324ed283c4 员工对象内”工作电子邮件“字段变为必填项 2024-08-27 10:01:22 +08:00
hujiaying
ebb8007549 销售订单内”取消“按钮变为”拒绝接单“按钮 2024-08-27 09:46:34 +08:00
胡尧
361f187026 Accept Merge Request #1249: (feature/agv_dispatch -> develop)
Merge Request: 修改人工报价流程

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1249
2024-08-27 09:23:50 +08:00
胡尧
b35f444e49 修改人工报价流程 2024-08-27 09:23:18 +08:00
马广威
9b2a2d644d Accept Merge Request #1248: (feature/优化制造功能 -> develop)
Merge Request: 优化运行信息接口、优化次数接口;增加oee接口

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1248?initial=true
2024-08-27 08:57:22 +08:00
mgw
93ca2000a1 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化制造功能 2024-08-27 08:56:13 +08:00
胡尧
ca43aa836e Accept Merge Request #1247: (feature/agv_dispatch -> develop)
Merge Request: 修改人工报价流程

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1247?initial=true
2024-08-27 08:55:15 +08:00
mgw
26ad5b5b3f 优化运行信息接口、优化次数接口 2024-08-27 08:55:01 +08:00
胡尧
937ea42af3 修改人工报价流程 2024-08-27 08:54:33 +08:00
jinling.yang
9b957848c2 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/修复报废 2024-08-27 08:53:29 +08:00
jinling.yang
36579d22ac Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-08-27 08:53:15 +08:00
jinling.yang
e662490cb5 修复报废 2024-08-26 17:31:14 +08:00
mgw
038ce8e139 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化制造功能 2024-08-26 17:21:02 +08:00
mgw
e1a4784092 增加设备oee数据 2024-08-26 17:20:46 +08:00
禹翔辉
6d4d393b9b Accept Merge Request #1246: (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/1246?initial=true
2024-08-26 17:08:53 +08:00
yuxianghui
c956b06f57 Merge branch 'feature/线边料架接口优化' into feature/收藏无法删除缺陷优化 2024-08-26 17:00:48 +08:00
yuxianghui
da02d68c12 1、将销售单的【取消】改为【拒绝接单】;2、取消功能刀具拆解单的刀柄是否报废按钮; 2024-08-26 16:58:54 +08:00
yuxianghui
eb9b43dc91 解决 【库存概览内增加收藏的默认筛选项后,删除报错(原生报错)】 缺陷 2024-08-26 16:11:40 +08:00
胡嘉莹
ab66e24c9d Accept Merge Request #1244: (feature/update_process_start_time -> 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/1244?initial=true
2024-08-26 15:06:43 +08:00
hujiaying
fbbce6332d 修改表面工艺同步测试,删除同步交期,同步周期菜单及同步接口 2024-08-26 15:02:33 +08:00
马广威
554b86e641 Accept Merge Request #1245: (feature/优化制造功能 -> develop)
Merge Request: 修复coding问题,增加机床类型返回

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1245
2024-08-26 13:25:08 +08:00
mgw
54317a529e Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化制造功能 2024-08-26 13:24:00 +08:00
mgw
78d00e9157 修复coding问题,增加机床类型返回 2024-08-26 13:23:44 +08:00
hujiaying
89cb61f244 修改同步表面工艺 2024-08-26 12:47:15 +08:00
hujiaying
deef246a6d 修改表面工艺字段同步 2024-08-26 11:10:52 +08:00
hujiaying
9de201705f Merge branch 'develop' into feature/update_process_start_time 2024-08-26 10:35:59 +08:00
廖丹龙
8f8d83d4cb Accept Merge Request #1243: (feature/tax_sync -> develop)
Merge Request: 会计凭证处理

Created By: @廖丹龙
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @廖丹龙
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1243
2024-08-26 10:34:58 +08:00
liaodanlong
c703012ec4 会计凭证处理 2024-08-26 10:08:40 +08:00
jinling.yang
f1780181fa 修复报废向导 2024-08-25 17:36:07 +08:00
jinling.yang
f5e36f601c 还原注释代码 2024-08-25 15:01:11 +08:00
jinling.yang
6c0b84ec43 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/修复报废 2024-08-25 14:58:57 +08:00
jinling.yang
3e438a10ee 优化表面工艺排序 2024-08-25 14:58:40 +08:00
jinling.yang
9218633a5e 优化表面工艺 2024-08-23 17:32:35 +08:00
hujiaying
c646e70a66 Merge branch 'develop' into feature/update_process_start_time 2024-08-23 16:28:42 +08:00
jinling.yang
40521e06a8 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-08-23 16:13:35 +08:00
jinling.yang
7fee98cdee 修复报废 2024-08-23 16:13:03 +08:00
马广威
4b7c277a25 Accept Merge Request #1242: (feature/优化制造功能 -> develop)
Merge Request: cnc工单开始二次确认

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1242?initial=true
2024-08-23 12:05:03 +08:00
mgw
064397b32b Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化制造功能 2024-08-23 12:04:03 +08:00
mgw
048155bc9c Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化制造功能 2024-08-23 12:03:48 +08:00
马广威
d439c9140d Accept Merge Request #1241: (feature/优化制造功能 -> develop)
Merge Request: 增加异常明细

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1241?initial=true
2024-08-23 11:44:51 +08:00
mgw
296659ebb0 增加异常明细 2024-08-23 11:44:05 +08:00
马广威
a82063d078 Accept Merge Request #1233: (feature/优化制造功能 -> develop)
Merge Request: 增加工单相关接口

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1233
2024-08-23 10:07:41 +08:00
mgw
f17ff2bc57 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化制造功能 2024-08-23 10:05:30 +08:00
mgw
5df3de7dcd 增加返工数量等 2024-08-23 10:05:17 +08:00
胡尧
b37738fbc3 Accept Merge Request #1240: (feature/agv_dispatch -> develop)
Merge Request: 屏蔽下发agv小车任务

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1240?initial=true
2024-08-22 15:57:49 +08:00
胡尧
79f3dce0ec 屏蔽下发agv小车任务 2024-08-22 15:57:17 +08:00
胡尧
4b87ea3f0e Accept Merge Request #1239: (feature/agv_dispatch -> develop)
Merge Request: 修改下发agv任务逻辑

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1239?initial=true
2024-08-22 15:43:01 +08:00
胡尧
098ac0e7e9 修改下发agv任务逻辑 2024-08-22 15:42:34 +08:00
jinling.yang
6825364a2b Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-08-22 11:33:53 +08:00
jinling.yang
0cac8fbb4f Merge branch 'feature/修复报废-拣货单(sfp)' into develop 2024-08-22 10:55:12 +08:00
杨金灵
dce748c6a7 Accept Merge Request #1238: (feature/修复报废-拣货单(sfp) -> develop)
Merge Request: 修复报废-拣货单(sfp)

Created By: @杨金灵
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @杨金灵
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1238
2024-08-22 10:54:59 +08:00
jinling.yang
536c766272 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/修复报废-拣货单(sfp) 2024-08-22 10:52:38 +08:00
jinling.yang
422edbcb02 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-08-22 10:52:28 +08:00
jinling.yang
d13961ff5f 修复报废-拣货单(sfp) 2024-08-22 10:52:19 +08:00
禹翔辉
b603934637 Accept Merge Request #1237: (feature/线边料架接口优化 -> develop)
Merge Request: 1、优化货位信息接口、库位变更接口。

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1237?initial=true
2024-08-22 10:36:34 +08:00
yuxianghui
62d303168e Merge branch 'feature/销售、刀具模块优化_1' into feature/线边料架接口优化 2024-08-22 10:32:47 +08:00
yuxianghui
39bc206344 1、优化货位信息接口、库位变更接口。 2024-08-22 10:31:22 +08:00
胡尧
715d835633 Accept Merge Request #1236: (feature/agv_dispatch -> develop)
Merge Request: 修改接驳站状态接口

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1236
2024-08-22 10:23:52 +08:00
胡尧
9e356682dc 修改接驳站状态接口 2024-08-22 10:22:35 +08:00
胡尧
5dc392a27b Accept Merge Request #1235: (feature/agv_dispatch -> develop)
Merge Request: 修复配送完成修改工件配送单的bug

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1235
2024-08-21 20:19:13 +08:00
胡尧
3d2c62f5db 修复配送完成修改工件配送单的bug 2024-08-21 20:16:41 +08:00
mgw
1e3f0d5ee5 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化制造功能 2024-08-21 17:44:37 +08:00
mgw
b26919a40d 优化接口,使其易于取值 2024-08-21 17:44:22 +08:00
jinling.yang
9ffe338532 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-08-21 17:00:01 +08:00
jinling.yang
08d333e4e2 Merge branch 'feature/修复报废-工单状态' into develop 2024-08-21 16:59:29 +08:00
杨金灵
47c501c6c6 Accept Merge Request #1234: (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/1234
2024-08-21 16:59:13 +08:00
jinling.yang
335c79e618 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-08-21 16:54:11 +08:00
jinling.yang
ba986995ed 修复报废-工单状态 2024-08-21 16:53:32 +08:00
马广威
2a45cdd53a Accept Merge Request #1232: (feature/agv_dispatch -> 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/1232#mr-1232-review-178956
2024-08-21 16:25:05 +08:00
胡尧
0cdf37bb50 修改接口名字 2024-08-21 16:20:45 +08:00
mgw
bae2592587 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化制造功能 2024-08-21 15:38:21 +08:00
mgw
c86cc27510 增加工单相关接口 2024-08-21 15:38:05 +08:00
胡尧
2dded43e39 Accept Merge Request #1231: (feature/agv_dispatch -> develop)
Merge Request: 开启agv任务下发代码

Created By: @胡尧
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1231
2024-08-21 15:10:07 +08:00
胡尧
eb6e638018 开启agv任务下发代码 2024-08-21 15:06:06 +08:00
jinling.yang
f64c21dacd Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-08-21 14:50:12 +08:00
jinling.yang
426aa78ed4 Merge branch 'feature/修复报废bug' into develop 2024-08-21 14:49:59 +08:00
杨金灵
42c65496ff Accept Merge Request #1230: (feature/修复报废bug -> develop)
Merge Request: 修复报废bug

Created By: @杨金灵
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @杨金灵
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1230
2024-08-21 14:47:23 +08:00
jinling.yang
e893abd83e 还原接口代码 2024-08-21 14:46:37 +08:00
jinling.yang
78e2e7184e Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/修复报废bug 2024-08-21 14:43:44 +08:00
jinling.yang
ce575adc88 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-08-21 14:43:33 +08:00
jinling.yang
6668e0ee2f 还原OCC代码 2024-08-21 14:43:22 +08:00
胡尧
647d21dea3 Accept Merge Request #1229: (feature/agv_dispatch -> develop)
Merge Request: 放开下发agv小车任务代码

Created By: @胡尧
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1229
2024-08-21 11:32:50 +08:00
胡尧
0e13e2190e 屏蔽agv任务下发代码 2024-08-21 11:31:09 +08:00
胡尧
7f3d50a130 开启agv小车任务下发代码 2024-08-21 10:03:03 +08:00
jinling.yang
7b2908defa 修复报废bug 2024-08-20 17:52:36 +08:00
胡尧
a8211171b0 增加以日、月、年为日期期间的序列,工件配送单状态同步,返工时不生成工件配送单 2024-08-20 16:18:47 +08:00
yuxianghui
c57daa2c52 1、处理销售订单确认接单后,确认接单、取消按钮没有隐藏问题 2024-08-20 16:13:30 +08:00
jinling.yang
4ed7ecf628 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-08-20 14:45:39 +08:00
jinling.yang
8a6ebb331a Merge branch 'feature/优化最新版报废' into develop 2024-08-20 14:39:21 +08:00
杨金灵
b333e27c51 Accept Merge Request #1228: (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/1228
2024-08-20 14:39:03 +08:00
jinling.yang
6761851407 还原代码 2024-08-20 14:38:42 +08:00
胡尧
ada7936d1b Accept Merge Request #1227: (feature/agv_dispatch -> develop)
Merge Request: 增加可以移除焦点的controller

Created By: @胡尧
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1227
2024-08-20 14:36:43 +08:00
胡尧
9c40aa9a7e 修复更新agv站点同时下发任务的bug 2024-08-20 14:36:02 +08:00
jinling.yang
0694541653 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-08-20 14:34:34 +08:00
jinling.yang
e4e2dca22c 还原注释代码 2024-08-20 14:34:25 +08:00
jinling.yang
e259fd0c05 优化报废 2024-08-20 14:30:42 +08:00
胡尧
a767c6491f 增加移除焦点的controller 2024-08-20 14:05:05 +08:00
马广威
6c2045d0c3 Accept Merge Request #1222: (feature/优化制造功能 -> develop)
Merge Request: 运行日志数据接入;大屏对接

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1222
2024-08-20 11:28:33 +08:00
mgw
6fe56605ab Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化制造功能 2024-08-20 11:27:34 +08:00
mgw
bf2c7fd3c5 增加解绑托盘功能 2024-08-20 11:27:18 +08:00
胡尧
54fc91baa2 去掉js中的日志 2024-08-20 10:50:55 +08:00
黄焱
376f2b3079 Accept Merge Request #1226: (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/1226?initial=true
2024-08-20 10:50:39 +08:00
hy
3c50f19e2d 保存、取消按钮增加文字提示 2024-08-20 10:48:42 +08:00
胡尧
08622b10b9 Accept Merge Request #1225: (feature/agv_dispatch -> develop)
Merge Request: 生产总监、机床操作岗增加agv调度菜单权限,AGV下发任务界面需二次确认

Created By: @胡尧
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1225
2024-08-20 10:48:35 +08:00
胡尧
dc5b68cca0 生产总监、机床操作岗增加agv调度菜单权限,AGV下发任务界面需二次确认 2024-08-20 10:45:31 +08:00
mgw
1d399527e0 增加装夹预调工单扫码开启 2024-08-20 10:42:36 +08:00
禹翔辉
b3bfa69656 Accept Merge Request #1224: (feature/销售、刀具模块优化_1 -> develop)
Merge Request: 销售、刀具模块优化

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1224?initial=true
2024-08-20 09:05:57 +08:00
yuxianghui
96e226836e Merge branch 'feature/销售、刀具模块优化' into feature/销售、刀具模块优化_1 2024-08-20 09:02:52 +08:00
yuxianghui
062ca66328 1、库位变更接口、库位信息接口优化;2、功能刀具模型from页面按钮样式及显示优化; 2024-08-19 17:29:09 +08:00
胡尧
7ab8269088 Accept Merge Request #1223: (feature/agv_dispatch -> develop)
Merge Request: 修复agv调度bug

Created By: @胡尧
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1223
2024-08-19 14:40:04 +08:00
胡尧
1241737dea 修改agv调度搜索条件 2024-08-19 14:37:55 +08:00
mgw
813e424ec9 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化制造功能 2024-08-19 14:25:43 +08:00
mgw
8c08893aa1 修复“制造订单详情多了一个没有文案的按钮” 2024-08-19 14:25:26 +08:00
胡尧
5ad35de76b 修复agv调度bug 2024-08-19 11:22:30 +08:00
jinling.yang
3c8dac799d 修复报废 2024-08-16 17:28:21 +08:00
mgw
29c1c7a54d 调整日志顺序;增加订单名返回 2024-08-16 17:19:54 +08:00
胡尧
2c27a9b575 Accept Merge Request #1221: (feature/agv_dispatch -> develop)
Merge Request: 装夹工单完成后生成工件配送单同时绑定rfid

Created By: @胡尧
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1221
2024-08-16 17:13:46 +08:00
胡尧
0e4b9e44f8 修改下发agv调度任务参数 2024-08-16 17:12:34 +08:00
mgw
a07a1ba268 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化制造功能 2024-08-16 16:57:47 +08:00
mgw
f537fbc597 运行日志数据接入 2024-08-16 16:57:32 +08:00
胡尧
a6b7167f3b 修改创建调度任务逻辑,不匹配的路线返回错误信息 2024-08-16 16:49:30 +08:00
胡尧
c4de966dea 装夹工单完成后生成工件配送单同时绑定rfid 2024-08-16 16:31:54 +08:00
yuxianghui
03cfc00be5 Merge branch 'feature/销售单优化' into feature/销售、刀具模块优化 2024-08-16 16:02:19 +08:00
yuxianghui
cc05e8423e 1、注释重写的销售单交货按钮代码 2024-08-16 16:01:24 +08:00
yuxianghui
e78516f73c 1、 完成 功能刀具组装和拆解页面扫描操作优化需求 2024-08-16 15:59:24 +08:00
胡尧
a277bb402e Accept Merge Request #1220: (feature/agv_dispatch -> develop)
Merge Request: 装夹预调绑定rfid时,不绑定工件配送单的rfid

Created By: @胡尧
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1220?initial=true
2024-08-16 15:24:27 +08:00
胡尧
e5793638f7 屏蔽开始装夹预调绑定rfid时,不绑定工件配送的rfid 2024-08-16 15:21:08 +08:00
胡尧
9673fd165d Accept Merge Request #1219: (feature/agv_dispatch -> develop)
Merge Request: agv任务调度功能

Created By: @胡尧
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1219?initial=true
2024-08-16 10:41:30 +08:00
胡尧
e92905fe32 修改agv小车相关接口 2024-08-16 10:36:01 +08:00
胡尧
1b521ae460 解决冲突 2024-08-16 09:50:31 +08:00
胡尧
4e0d8f1c88 修改AGV调度 2024-08-16 09:43:03 +08:00
胡尧
aecf2121a1 agv调度开发 2024-08-15 17:41:25 +08:00
jinling.yang
e2d7576a5e 优化报废 2024-08-15 17:31:37 +08:00
mgw
cc13e5cd9a Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化制造功能 2024-08-15 17:14:40 +08:00
mgw
271f34a03b 增加开动率采集 2024-08-15 17:14:07 +08:00
yuxianghui
366e816268 1、优化货位变更接口、优化同步库存信息接口;2、隐藏已取消状态的销售订单的【确认接单】和【取消】按钮;3、处理功能刀具从线边刀库到刀具房没有生成移动历史问题; 2024-08-15 16:45:39 +08:00
胡尧
1532184008 Merge branch 'feature/agv_dispatch' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/agv_dispatch 2024-08-15 15:02:16 +08:00
胡尧
9f180e307d agv调度开发 2024-08-15 15:02:13 +08:00
hy
f0a4cf1d0f 弹窗取消聚焦 2024-08-15 15:01:10 +08:00
胡尧
6c734eead4 agv调度开发 2024-08-15 11:34:38 +08:00
胡尧
f7e4ce416a AGV任务调度开发 2024-08-14 17:34:50 +08:00
hujiaying
5a60eed5b1 联调加工订单从待确认到加工中,经过的内部管理系统,bfm,sf接口测试联调,修改对应接收的参数值改变。采购订单加工中同步到内部管理系统失败,则新增到同步表,由同步表定时发起接口重试 2024-08-14 12:48:40 +08:00
yuxianghui
bf34de58fc 1、优化功能刀具预警记录跳转功能刀具拆解单链接方法;2、优化功能刀具预警界面及搜索等方法;3、优化拆解单功能及界面;4、处理功能刀具组装时,刀柄状态不实时变更问题 2024-08-13 17:30:19 +08:00
jinling.yang
cccc2f8493 优化报废 2024-08-12 17:30:53 +08:00
yuxianghui
894d3b9ea3 1、功能刀具拆解单添加功能刀具唯一校验;2、功能刀具模型tree视图的状态字段根据不同状态添加不同颜色;当功能刀具状态为报警时,自动创建拆解单和预警记录,并添加拆解单链接按钮;添加tree视图按状态排序,将报警状态刀具记录显示在最前面;3、优化功能刀具预警模型字段及关联关系,添加预警记录跳转到对应由该功能刀具生成的拆解单链接; 2024-08-12 17:25:56 +08:00
胡尧
0b85f29262 修改agv调度 2024-08-12 11:08:04 +08:00
胡尧
9dbea66b73 修改AGV调度系统 2024-08-09 17:32:46 +08:00
jinling.yang
9a7ac4dfa6 优化制造订单报废向导 2024-08-09 17:26:57 +08:00
yuxianghui
e6ca4c27ac 1、库位变更接口、库位信息接口优化;2、功能刀具预警模型优化; 2024-08-09 17:19:03 +08:00
jinling.yang
a8560a0684 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化最新版报废 2024-08-09 15:45:11 +08:00
jinling.yang
4f74996f24 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-08-09 15:44:48 +08:00
jinling.yang
5b26abc203 Merge branch 'feature/优化表面工艺外协' into develop 2024-08-09 15:43:52 +08:00
杨金灵
49654f1ff6 Accept Merge Request #1218: (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/1218
2024-08-09 15:43:33 +08:00
jinling.yang
a9b7f99944 修复表面工艺外协 2024-08-09 15:39:58 +08:00
jinling.yang
34e858ffe4 添加表面工艺服务产品验证 2024-08-09 11:31:30 +08:00
jinling.yang
41efe81119 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化表面工艺外协 2024-08-09 10:43:34 +08:00
jinling.yang
7cab8cd287 调拨单新增表面工艺参数字段 2024-08-09 10:42:59 +08:00
jinling.yang
5f9c5961a5 报废 2024-08-09 10:39:48 +08:00
胡尧
a79500d0ad 增加agv调度系统 2024-08-08 17:47:03 +08:00
jinling.yang
4399700c3d 优化报废向导 2024-08-08 17:24:41 +08:00
yuxianghui
36fd17b6c7 1、处理 智能工厂,销售角色与采购角色权限更新 需求 2024-08-08 17:03:36 +08:00
杨金灵
9d52466f61 Accept Merge Request #1217: (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/1217?initial=true
2024-08-08 16:24:06 +08:00
jinling.yang
112efccb7c 修复表面工艺外协采购 2024-08-08 16:21:15 +08:00
jinling.yang
45b9177da4 优化工单 2024-08-08 16:09:00 +08:00
jinling.yang
745658eff2 1.制造订单添加报废状态,
2.返工操作制造订单添加过滤条件:状态为报废
3.cnc工单完成检测结果添加报废
2024-08-08 15:40:29 +08:00
jinling.yang
ce8b0127b8 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-08-08 15:08:17 +08:00
jinling.yang
f58fb2ea13 Merge branch 'feature/优化表面工艺' into develop 2024-08-08 15:08:08 +08:00
杨金灵
d333621c7a Accept Merge Request #1216: (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/1216
2024-08-08 15:07:37 +08:00
jinling.yang
563023fa3c 中控接口身份验证放开 2024-08-08 15:07:22 +08:00
jinling.yang
3d2c7425c4 还原代码 2024-08-08 15:03:45 +08:00
jinling.yang
aaa19b96fd 还原注释代码 2024-08-08 14:57:55 +08:00
胡尧
5d8f0f83b2 增加AGV调度功能,工单页面增加自定义筛选字段 2024-08-07 17:44:43 +08:00
jinling.yang
1547a6064f 优化表面工艺 2024-08-07 17:30:29 +08:00
禹翔辉
55b2daa0a3 Accept Merge Request #1215: (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/1215
2024-08-07 17:13:57 +08:00
yuxianghui
d469c09f15 Merge branch 'feature/制造订单优化' into feature/销售单优化 2024-08-07 17:11:57 +08:00
yuxianghui
a03cb31b29 1、处理 SF销售单需求优化 需求 2024-08-07 17:11:12 +08:00
廖丹龙
d2b20761b5 Accept Merge Request #1214: (feature/tax_sync -> develop)
Merge Request: bom原材料查询出现多条会导致bfm 分配工厂时报错

Created By: @廖丹龙
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @廖丹龙
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1214
2024-08-07 09:49:20 +08:00
liaodanlong
0f47b4b8c3 bom原材料查询限制只拿一条 2024-08-07 09:44:04 +08:00
liaodanlong
0cfb16b9d9 Merge remote-tracking branch 'origin/develop' into develop 2024-08-06 09:09:59 +08:00
廖丹龙
8ec5e05739 Accept Merge Request #1213: (feature/tax_sync -> develop)
Merge Request: bfm 加工订单税信息同步

Created By: @廖丹龙
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @廖丹龙
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1213
2024-08-06 09:09:37 +08:00
jinling.yang
5393ef686a 优化表面工艺 2024-08-05 17:28:48 +08:00
yuxianghui
e92c9675b6 1、 处理 内部调拨单,在选择目标货位时,隐藏带循环货位标签的货位不进行展示 2024-08-05 17:18:54 +08:00
liaodanlong
e6bad80031 Merge branch 'refs/heads/feature/tax_sync' into develop 2024-08-05 17:12:37 +08:00
yuxianghui
070890e3b6 解决 SF,根据制造订单生成的采购单坯料入库时到原材料库BUG 2024-08-05 16:26:54 +08:00
mgw
6e50774b23 调整机床列表接口位置;增加机床品牌型号返回 2024-08-05 16:23:27 +08:00
mgw
fc18d34495 增加大屏用获取cnc机床列表接口 2024-08-05 16:04:53 +08:00
jinling.yang
ed0d57c364 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化表面工艺
# Conflicts:
#	sf_manufacturing/models/mrp_production.py
#	sf_manufacturing/models/mrp_workorder.py
2024-08-02 14:41:42 +08:00
禹翔辉
3f27ae0f35 Accept Merge Request #1212: (feature/bug优化 -> develop)
Merge Request: 修改夹具重量单位为kg

Created By: @禹翔辉
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1212
2024-08-02 11:22:06 +08:00
yuxianghui
cec426920b Merge branch 'feature/优化工单状态' into feature/bug优化 2024-08-02 11:19:45 +08:00
mgw
09a6255d9c 去掉无用文件夹及未用po 2024-08-02 09:57:52 +08:00
马广威
d187bb2bba Accept Merge Request #1211: (release/release_2.2 -> master)
Merge Request: SPRINT-MES-F-2024-04、05版本更新

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1211
2024-08-01 21:58:11 +08:00
yuxianghui
a5da18bbc7 1、修改夹具重量单位为kg 2024-08-01 11:34:20 +08:00
liaodanlong
510e8d49fb 功能刀具拆解失败问题 2024-08-01 10:46:14 +08:00
liaodanlong
051273017d Merge remote-tracking branch 'refs/remotes/origin/develop' into feature/tax_sync 2024-08-01 10:45:09 +08:00
yuxianghui
f49557090a 1、优化刀具拆解单拆解时生成的调拨单单据验证出现数据缺失问题 2024-08-01 10:40:25 +08:00
liaodanlong
115a3e0712 Merge remote-tracking branch 'refs/remotes/origin/develop' into feature/tax_sync 2024-07-31 14:41:02 +08:00
liaodanlong
d49e8779f9 Merge remote-tracking branch 'refs/remotes/origin/develop' into feature/tax_sync 2024-07-30 09:24:48 +08:00
liaodanlong
81dbbf980c Merge remote-tracking branch 'refs/remotes/origin/develop' into feature/tax_sync 2024-07-29 15:09:37 +08:00
jinling.yang
39214e5352 注释代码 2024-07-28 11:47:12 +08:00
jinling.yang
36a2bcca6e 优化表面工yi 2024-07-26 15:49:25 +08:00
jinling.yang
19c4b99bae 创建制造订单后生成询价单 2024-07-25 17:21:44 +08:00
jinling.yang
33fdd0f051 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化表面工艺 2024-07-25 15:44:01 +08:00
jinling.yang
2deaffb4eb 添加表面工艺产品校验 2024-07-25 14:07:36 +08:00
liaodanlong
8996297521 Merge branch 'refs/heads/master' into feature/tax_sync 2024-07-25 11:43:01 +08:00
jinling.yang
0d1cb49cb7 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化表面工艺 2024-07-25 10:35:52 +08:00
马广威
8840e9642d Accept Merge Request #1173: (release/release_2.1 -> master)
Merge Request: 1、货架、货位添加循环货位标签;2、功能刀具拆解时选择的货位添加只能为循环货位的过滤条件

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1173?initial=true
2024-07-24 20:23:31 +08:00
jinling.yang
96c22a5d46 添加表面工艺服务产品验证 2024-07-24 17:30:59 +08:00
jinling.yang
121861863f 优化销售订单确认方法 2024-07-24 16:57:50 +08:00
jinling.yang
c2c8d63848 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化表面工艺 2024-07-24 16:41:19 +08:00
jinling.yang
a5d8e88f1d 注释OCC代码 2024-07-24 16:33:47 +08:00
liaodanlong
ef1c7b6b25 多余字符串信息 2024-07-19 17:23:01 +08:00
liaodanlong
03fe730c50 产品添加税信息 2024-07-19 16:46:53 +08:00
liaodanlong
a0d3b40548 添加工厂订单和产品创建时的错误日志 2024-07-19 16:46:31 +08:00
liaodanlong
dfba055019 添加bfm同步时产品创建填充税值 2024-07-19 16:45:46 +08:00
158 changed files with 7173 additions and 7627 deletions

View File

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

View File

@@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
{
'name': "jikimo_account_process",
'summary': """
Short (1 phrase/line) summary of the module's purpose, used as
subtitle on modules listing or apps.openerp.com""",
'description': """
Long description of module's purpose
""",
'author': "My Company",
'website': "https://www.yourcompany.com",
# Categories can be used to filter modules in modules listing
# Check https://github.com/odoo/odoo/blob/16.0/odoo/addons/base/data/ir_module_category_data.xml
# for the full list
'category': 'Uncategorized',
'version': '0.1',
# any module necessary for this one to work correctly
'depends': ['base', 'account'],
# always loaded
'data': [
# 'security/ir.model.access.csv',
# 'views/views.xml',
# 'views/templates.xml',
],
# only loaded in demonstration mode
'demo': [
# 'demo/demo.xml',
],
}

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,15 @@
from odoo import models, fields, api
from odoo.exceptions import ValidationError
class CustomAccountMoveLine(models.Model):
_inherit = 'account.move'
_description = "account move line"
@api.model_create_multi
def create(self, vals):
for val in vals:
val['name'] = self.env['ir.sequence'].next_by_code('account.move') or '/'
# 因为供应商与客户支付创建流程是先创建move line在修改来填充account_payment与move line的关联
return super(CustomAccountMoveLine, self).create(vals)

View File

@@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
# from odoo import models, fields, api
# class jikimo_account_process(models.Model):
# _name = 'jikimo_account_process.jikimo_account_process'
# _description = 'jikimo_account_process.jikimo_account_process'
# name = fields.Char()
# value = fields.Integer()
# value2 = fields.Float(compute="_value_pc", store=True)
# description = fields.Text()
#
# @api.depends('value')
# def _value_pc(self):
# for record in self:
# record.value2 = float(record.value) / 100

View File

@@ -53,6 +53,23 @@ const tableRequiredList = [
]
patch(FormStatusIndicator.prototype, 'jikimo_frontend.FormStatusIndicator', {
setup() {
owl.onMounted(() => {
try {
const dom = this.__owl__.bdom.el
const buttonsDom = $(dom).find('.o_form_status_indicator_buttons ')
if (buttonsDom) {
const dom1 = buttonsDom.children('.o_form_button_save')
const dom2 = buttonsDom.children('.o_form_button_cancel')
dom1.append('保存')
dom2.append('取消')
}
} catch (e) {
console.log(e)
}
});
},
// 你可以重写或者添加一些方法和属性
async _onDiscardChanges() {
// var self = this;
@@ -183,17 +200,6 @@ patch(ListRenderer.prototype, 'jikimo_frontend.ListRenderer', {
// })
$(function () {
document.addEventListener('click', function () {
const dom = $('.o_form_status_indicator_buttons ')
if (dom) {
const dom1 = dom.children().eq(0)
const dom2 = dom.children().eq(1)
if (!dom1.text()) {
dom1.append('保存')
dom2.append('取消')
}
}
})
function customRequired() {
let timer = null

View File

@@ -324,4 +324,4 @@ def unlink(self):
BaseModel._create = _create
BaseModel.unlink = unlink
# BaseModel.unlink = unlink

View File

@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields, models
from odoo import fields, models, api
class MrpProduction(models.Model):
@@ -12,7 +12,8 @@ class MrpProduction(models.Model):
check_ids = fields.One2many('quality.check', 'production_id', string="Checks")
def _split_productions(self, amounts=False, cancel_remaining_qty=False, set_consumed_qty=False):
productions = super()._split_productions(amounts=amounts, cancel_remaining_qty=cancel_remaining_qty, set_consumed_qty=set_consumed_qty)
productions = super()._split_productions(amounts=amounts, cancel_remaining_qty=cancel_remaining_qty,
set_consumed_qty=set_consumed_qty)
backorders = productions[1:]
if not backorders:
return productions
@@ -20,3 +21,4 @@ class MrpProduction(models.Model):
if wo.current_quality_check_id.component_id:
wo.current_quality_check_id._update_component_quantity()
return productions

View File

@@ -1,41 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Manufacturing Order for Planing view -->
<record id="mrp_production_tree_view_planning" model="ir.ui.view">
<field name="name">mrp.production.tree.inherit.planning</field>
<field name="model">mrp.production</field>
<field name="arch" type="xml">
<tree default_order="date_planned_start asc" decoration-info="state=='confirmed'" decoration-danger="date_planned_start&lt;current_date and state not in ('done','cancel')" decoration-muted="state in ('done','cancel')" string="Manufacturing Orders" name="Production">
<field name="message_needaction" invisible="1"/>
<field name="name"/>
<field name="date_planned_start"/>
<field name="product_id"/>
<field name="product_qty" sum="Total Qty" string="Quantity"/>
<field name="product_uom_id" string="Unit of Measure" options="{'no_open':True,'no_create':True}" groups="uom.group_uom"/>
<field name="reservation_state" string="Availability"/>
<field name="origin"/>
<field name="state"/>
</tree>
</field>
</record>
<!-- Manufacturing Order for Planing view -->
<record id="mrp_production_tree_view_planning" model="ir.ui.view">
<field name="name">mrp.production.tree.inherit.planning</field>
<field name="model">mrp.production</field>
<field name="arch" type="xml">
<tree default_order="date_planned_start asc" decoration-info="state=='confirmed'"
decoration-danger="date_planned_start&lt;current_date and state not in ('done','cancel')"
decoration-muted="state in ('done','cancel')" string="Manufacturing Orders" name="Production">
<field name="message_needaction" invisible="1"/>
<field name="name"/>
<field name="date_planned_start"/>
<field name="product_id"/>
<field name="product_qty" sum="Total Qty" string="Quantity"/>
<field name="product_uom_id" string="Unit of Measure" options="{'no_open':True,'no_create':True}"
groups="uom.group_uom"/>
<field name="reservation_state" string="Availability"/>
<field name="origin"/>
<field name="state"/>
</tree>
</field>
</record>
<!-- <record id="mrp_production_form_inherit_planning" model="ir.ui.view">-->
<!-- <field name="name">mrp.production.form_inherit_planning</field>-->
<!-- <field name="model">mrp.production</field>-->
<!-- <field name="inherit_id" ref="mrp.mrp_production_form_view"/>-->
<!-- <field name="arch" type="xml">-->
<!-- <xpath expr="div[hasclass('oe_chatter')]" position="replace">-->
<!-- &lt;!&ndash; 这里放置替换后的内容 &ndash;&gt;-->
<!-- </xpath>-->
<!-- <xpath expr="//notebook" position="after">-->
<!-- <div class="oe_chatter">-->
<!-- <field name="message_follower_ids"/>-->
<!-- <field name="activity_ids"/>-->
<!-- <field name="message_ids"/>-->
<!-- </div>-->
<!-- </xpath>-->
<!-- </field>-->
<!-- </record>-->
<!-- <record id="mrp_production_form_inherit_planning" model="ir.ui.view">-->
<!-- <field name="name">mrp.production.form_inherit_planning</field>-->
<!-- <field name="model">mrp.production</field>-->
<!-- <field name="inherit_id" ref="mrp.mrp_production_form_view"/>-->
<!-- <field name="arch" type="xml">-->
<!-- <xpath expr="div[hasclass('oe_chatter')]" position="replace">-->
<!-- &lt;!&ndash; 这里放置替换后的内容 &ndash;&gt;-->
<!-- </xpath>-->
<!-- <xpath expr="//notebook" position="after">-->
<!-- <div class="oe_chatter">-->
<!-- <field name="message_follower_ids"/>-->
<!-- <field name="activity_ids"/>-->
<!-- <field name="message_ids"/>-->
<!-- </div>-->
<!-- </xpath>-->
<!-- </field>-->
<!-- </record>-->
<record id="mrp_production_view_search_inherit_planning" model="ir.ui.view">
<field name="name">mrp.production.search.view.inherit.planning</field>
@@ -43,7 +46,9 @@
<field name="inherit_id" ref="mrp.view_mrp_production_filter"/>
<field name="arch" type="xml">
<filter name="filter_planned" position="attributes">
<attribute name="domain">[('is_planned', '=', True), ('date_planned_start', '!=', False), ('date_planned_finished', '!=', False)]</attribute>
<attribute name="domain">[('is_planned', '=', True), ('date_planned_start', '!=', False),
('date_planned_finished', '!=', False)]
</attribute>
</filter>
</field>
</record>
@@ -51,30 +56,33 @@
<record id="production_order_unplan_server_action" model="ir.actions.server">
<field name="name">Unplan orders</field>
<field name="model_id" ref="mrp.model_mrp_production"/>
<field name="binding_model_id" ref="mrp.model_mrp_production" />
<field name="binding_model_id" ref="mrp.model_mrp_production"/>
<field name="binding_view_types">list</field>
<field name="state">code</field>
<field name="code">records.button_unplan()</field>
</record>
<record id="mrp.act_product_mrp_production_workcenter" model="ir.actions.act_window">
<field name="domain">[('bom_id', '!=', False), ('bom_id.operation_ids.workcenter_id', '=', active_id), ('date_planned_start', '!=', False), ('date_planned_finished', '!=', False)]</field>
<field name="domain">[('bom_id', '!=', False), ('bom_id.operation_ids.workcenter_id', '=', active_id),
('date_planned_start', '!=', False), ('date_planned_finished', '!=', False)]
</field>
<field name="view_id" ref="mrp_production_tree_view_planning"/>
</record>
<menuitem id="mrp_workorder_menu_planning"
name="Work Orders"
sequence="2"
parent="mrp.mrp_planning_menu_root"
groups="mrp.group_mrp_routings"/>
name="Work Orders"
sequence="2"
parent="mrp.mrp_planning_menu_root"
groups="mrp.group_mrp_routings"/>
<menuitem id="menu_mrp_workorder_production"
name="Planning by Production"
sequence="1"
action="mrp.action_mrp_workorder_production"
parent="mrp_workorder_menu_planning"/>
name="Planning by Production"
sequence="1"
action="mrp.action_mrp_workorder_production"
parent="mrp_workorder_menu_planning"/>
<menuitem id="menu_mrp_workorder_workcenter"
name="Planning by Workcenter"
sequence="2"
action="mrp_workorder.action_mrp_workorder_dependencies_workcenter"
parent="mrp_workorder_menu_planning"/>
name="Planning by Workcenter"
sequence="2"
action="mrp_workorder.action_mrp_workorder_dependencies_workcenter"
parent="mrp_workorder_menu_planning"/>
</odoo>

View File

@@ -35,6 +35,7 @@
],
'web.assets_backend': [
'sf_base/static/src/scss/*.scss',
'sf_base/static/src/js/*.js',
],
},

View File

@@ -5,3 +5,4 @@ from . import fixture
from . import functional_fixture
from . import tool_other_features
from . import basic_parameters_fixture
from . import ir_sequence

View File

@@ -13,7 +13,7 @@ class BasicParametersFixture(models.Model):
diameter = fields.Float('直径(mm)', digits=(16, 2))
# '零点卡盘' 字段
weight = fields.Float('重量(mm)', digits=(16, 2))
weight = fields.Float('重量(kg)', digits=(16, 2))
orientation_dish_diameter = fields.Float('定位盘直径(mm)', digits=(16, 2))
clamping_diameter = fields.Float('装夹直径(mm)', digits=(16, 2))
clamping_num = fields.Selection([('1', '1'), ('2', '2'), ('4', '4'), ('6', '6'), ('8', '8')], string='装夹单元数')

View File

@@ -84,10 +84,12 @@ class MrsProductionProcessCategory(models.Model):
class MrsProductionProcess(models.Model):
_name = 'sf.production.process'
_description = '表面工艺'
order = 'sequence asc'
code = fields.Char("编码")
name = fields.Char('名称')
remark = fields.Text("备注")
sequence = fields.Integer('排序')
# processing_order_ids = fields.One2many('sf.processing.order', 'production_process_id', string='工序')
partner_process_ids = fields.Many2many('res.partner', 'process_ids', '加工工厂')
active = fields.Boolean('有效', default=True)
@@ -96,7 +98,7 @@ class MrsProductionProcess(models.Model):
# workcenter_ids = fields.Many2many('mrp.workcenter', 'rel_workcenter_process', required=True)
processing_day = fields.Float('加工天数/d')
travel_day = fields.Float('路途天数/d')
sequence = fields.Integer('排序')
# class MrsProcessingTechnology(models.Model):
# _name = 'sf.processing.technology'
@@ -148,6 +150,7 @@ class MrsProductionProcessParameter(models.Model):
processing_day = fields.Float('加工天数/d')
travel_day = fields.Float('路途天数/d')
active = fields.Boolean('有效', default=True)
processing_mm = fields.Char('加工厚度/mm')
def name_get(self):
result = []

View File

@@ -0,0 +1,74 @@
import calendar
from datetime import timedelta
from odoo import models, fields
class IrSequence(models.Model):
_inherit = 'ir.sequence'
date_range_period = fields.Selection(
[('day', '每日'), ('month', '每月'), ('year', '每年')],
string='日期期间',
)
def _next(self, sequence_date=None):
""" Returns the next number in the preferred sequence in all the ones given in self."""
if not self.use_date_range:
return self._next_do()
# date mode
dt = sequence_date or self._context.get('ir_sequence_date', fields.Date.today())
seq_date = self.env['ir.sequence.date_range'].search(
[
('sequence_id', '=', self.id),
('date_from', '<=', dt),
('date_to', '>=', dt),
('date_range_period', '=', self.date_range_period)
], limit=1)
if not seq_date:
if self.date_range_period:
seq_date = self._create_date_range_seq_by_period(dt, self.date_range_period)
else:
seq_date = self._create_date_range_seq(dt)
return seq_date.with_context(ir_sequence_date_range=seq_date.date_from)._next()
def _create_date_range_seq_by_period(self, date, period):
if period == 'year':
year = fields.Date.from_string(date).strftime('%Y')
date_from = '{}-01-01'.format(year)
date_to = '{}-12-31'.format(year)
if period == 'month':
# 计算当前月份的第一天和最后一天
year = fields.Date.from_string(date).strftime('%Y')
month = fields.Date.from_string(date).strftime('%m')
date_from = fields.Date.from_string(date).strftime('%Y-%m-01')
date_to = '{}-{}-{}'.format(year, month, calendar.monthrange(int(year), int(month))[1])
if period == 'day':
date_from = date
date_to = date
date_range = self.env['ir.sequence.date_range'].search(
[
('sequence_id', '=', self.id),
('date_to', '>=', date_from),
('date_to', '<=', date),
('date_range_period', '=', period)
],
order='date_to desc', limit=1)
if date_range:
date_from = date_range.date_to + timedelta(days=1)
seq_date_range = self.env['ir.sequence.date_range'].sudo().create({
'date_from': date_from,
'date_to': date_to,
'sequence_id': self.id,
'date_range_period': period,
})
return seq_date_range
class IrSequenceDateRange(models.Model):
_inherit = 'ir.sequence.date_range'
date_range_period = fields.Selection(
[('day', '每日'), ('month', '每月'), ('year', '每年')],
string='日期期间',
)

View File

@@ -1,10 +0,0 @@
diff a/sf_base/models/tool_base_new.py b/sf_base/models/tool_base_new.py (rejected hunks)
@@ -108,6 +108,4 @@
cutting_speed_ids = fields.One2many('sf.cutting.speed', 'standard_library_id', string='切削速度Vc')
- feed_per_tooth_ids = fields.One2many('sf.feed.per.tooth', 'standard_library_id', '每齿走刀量fz',
- domain=[('cutting_speed', '!=', False)])
- feed_per_tooth_ids_3 = fields.One2many('sf.feed.per.tooth', 'standard_library_id', '每齿走刀量fz',
- domain=[('cutting_speed', '!=', False)])
+ feed_per_tooth_ids = fields.One2many('sf.feed.per.tooth', 'standard_library_id', '每齿走刀量fz')
+ feed_per_tooth_ids_3 = fields.One2many('sf.feed.per.tooth', 'standard_library_id', '每齿走刀量fz')

View File

@@ -0,0 +1,61 @@
/** @odoo-module **/
import { registry } from "@web/core/registry";
import { barcodeGenericHandlers } from '@barcodes/barcode_handlers';
import { patch } from "@web/core/utils/patch";
// 定义新的 clickOnButton 函数
function customClickOnButton(selector) {
console.log("This is the custom clickOnButton function!");
const buttons = document.body.querySelectorAll(selector);
let length = buttons.length;
if (length > 0) {
buttons[length - 1].click();
} else {
console.warn(`Button with selector ${selector} not found`);
}
}
patch(barcodeGenericHandlers, "start", {
start(env, { ui, barcode, notification }) {
// 使用新定义的 clickOnButton 函数
const COMMANDS = {
"O-CMD.EDIT": () => customClickOnButton(".o_form_button_edit"),
"O-CMD.DISCARD": () => customClickOnButton(".o_form_button_cancel"),
"O-CMD.SAVE": () => customClickOnButton(".o_form_button_save"),
"O-CMD.PREV": () => customClickOnButton(".o_pager_previous"),
"O-CMD.NEXT": () => customClickOnButton(".o_pager_next"),
"O-CMD.PAGER-FIRST": () => updatePager("first"),
"O-CMD.PAGER-LAST": () => updatePager("last"),
"O-CMD.CONFIRM": () => customClickOnButton(".jikimo_button_confirm"),
};
barcode.bus.addEventListener("barcode_scanned", (ev) => {
const barcode = ev.detail.barcode;
if (barcode.startsWith("O-BTN.")) {
let targets = [];
try {
targets = getVisibleElements(ui.activeElement, `[barcode_trigger=${barcode.slice(6)}]`);
} catch (_e) {
console.warn(`Barcode '${barcode}' is not valid`);
}
for (let elem of targets) {
elem.click();
}
}
if (barcode.startsWith("O-CMD.")) {
const fn = COMMANDS[barcode];
if (fn) {
fn();
} else {
notification.add(env._t("Barcode: ") + `'${barcode}'`, {
title: env._t("Unknown barcode command"),
type: "danger"
});
}
}
});
}
})

View File

@@ -0,0 +1,42 @@
/** @odoo-module **/
import { registry } from '@web/core/registry';
import { formView } from '@web/views/form/form_view';
import { FormController } from '@web/views/form/form_controller';
import { listView } from '@web/views/list/list_view';
import { ListController } from '@web/views/list/list_controller'
import { onRendered, onMounted } from "@odoo/owl";
export class RemoveFocusFormController extends FormController {
setup() {
super.setup();
onMounted(() => {
this.__owl__.bdom.el.querySelectorAll(':focus').forEach(element => element.blur());
})
}
}
registry.category('views').add('remove_focus_form_view', {
...formView,
Controller: RemoveFocusFormController,
});
export class RemoveFocusListController extends ListController {
setup() {
super.setup();
onMounted(() => {
this.__owl__.bdom.el.querySelectorAll(':focus').forEach(element => element.blur());
})
}
}
registry.category('views').add('remove_focus_list_view', {
...listView,
Controller: RemoveFocusListController,
});

View File

@@ -12,11 +12,10 @@
</tree>
</field>
</record>
<record model="ir.ui.view" id="mrs_production_process_parameter_form">
<field name="model">sf.production.process.parameter</field>
<field name="arch" type="xml">
<form string="表面工艺可选参数" create="0" delete="0">
<form string="表面工艺可选参数" create="0" delete="0" >
<sheet>
<div class="oe_title">
<h1>
@@ -26,18 +25,19 @@
<group>
<group>
<field name="code" readonly="1"/>
<field name="process_id" readonly="1"/>
<field name="process_description" readonly="1"/>
<field name="process_id" attrs="{'readonly': [('code', '!=', False)]}"/>
<field name="process_description" attrs="{'readonly': [('code', '!=', False)]}"/>
<field name="gain_way"/>
</group>
<group>
<field name="processing_day" readonly="1"/>
<field name="travel_day" readonly="1"/>
<field name="processing_day" attrs="{'readonly': [('code', '!=', False)]}"/>
<field name="travel_day" attrs="{'readonly': [('code', '!=', False)]}"/>
<field name="processing_mm" attrs="{'readonly': [('code', '!=', False)]}"/>
</group>
</group>
<notebook>
<page string="适用材料">
<field name="materials_model_ids"></field>
<field name="materials_model_ids" attrs="{'readonly': [('code', '!=', False)]}"></field>
</page>
</notebook>
</sheet>
@@ -52,7 +52,7 @@
<search>
<filter name="filter_active" string="已归档" domain="[('active','=',False)]"/>
<field name="name" string="名称" filter_domain="[('name','ilike',self)]"/>
<field name="code" string="编码" filter_domain="[('codeNum','ilike',self)]"/>
<field name="code" string="编码" filter_domain="[('code','ilike',self)]"/>
<searchpanel class="account_root">
<field name="process_id" icon="fa-filter"/>
</searchpanel>
@@ -140,7 +140,7 @@
<field name="model">sf.production.process.category</field>
<field name="arch" type="xml">
<tree string="表面工艺类别" default_order="sequence, id" create="0" edit="0" delete="1">
<field name="sequence" widget="handle" string="序号"/>
<field name="sequence" widget="handle" string="序号" readonly="1"/>
<field name="code"/>
<field name="name" string="名称"/>
</tree>
@@ -163,7 +163,8 @@
<record model="ir.ui.view" id="sf_production_process_tree">
<field name="model">sf.production.process</field>
<field name="arch" type="xml">
<tree string="表面工艺" create="0" edit="0" delete="1">
<tree string="表面工艺" create="0" edit="0" delete="0">
<field name="sequence" string="加工顺序" readonly="1"/>
<field name="code"/>
<field name="name" string="名称"/>
<field name="remark"/>
@@ -174,7 +175,7 @@
<record model="ir.ui.view" id="sf_production_process_form">
<field name="model">sf.production.process</field>
<field name="arch" type="xml">
<form string="表面工艺" create="0" edit="1" delete="1">
<form string="表面工艺" create="0" delete="0">
<sheet>
<div class="oe_title">
<h1>
@@ -192,11 +193,11 @@
</group>
</group>
<notebook>
<page string="可选参数">
<field name="parameter_ids">
<tree force_save="1">
<page string="可选参数" >
<field name="parameter_ids" >
<tree force_save="1" create="0">
<field name="code" readonly="1" force_save="1"/>
<field name="name"/>
<field name="name" readonly="1"/>
<field name="gain_way"/>
<field name='process_id' default="default"/>
</tree>

View File

@@ -171,7 +171,7 @@
<field name="width"/>
<field name="height"/>
<field name="diameter"/>
<field name="weight"/>
<field name="weight" string="重量(kg)"/>
<field name="orientation_dish_diameter"/>
<field name="clamping_diameter"/>
<field name="clamping_num"/>
@@ -197,7 +197,7 @@
<field name="width"/>
<field name="height"/>
<field name="diameter"/>
<field name="weight"/>
<field name="weight" string="重量(kg)"/>
<field name="clamping_diameter"/>
<field name="connector_diameter"/>
<field name="chucking_power_max"/>
@@ -220,7 +220,7 @@
<field name="length"/>
<field name="width"/>
<field name="height"/>
<field name="weight"/>
<field name="weight" string="重量(kg)"/>
<field name="gripper_length_min"/>
<field name="gripper_width_min"/>
<field name="gripper_height_min"/>
@@ -248,7 +248,7 @@
<field name="length"/>
<field name="width"/>
<field name="height"/>
<field name="weight"/>
<field name="weight" string="重量(kg)"/>
<field name="gripper_length_min"/>
<field name="gripper_width_min"/>
<field name="gripper_height_min"/>
@@ -278,7 +278,7 @@
<field name="width"/>
<field name="height"/>
<field name="height_tolerance_value"/>
<field name="weight"/>
<field name="weight" string="重量(kg)"/>
<field name="gripper_length_min"/>
<field name="gripper_width_min"/>
<field name="gripper_height_min"/>
@@ -307,7 +307,7 @@
<field name="length"/>
<field name="width"/>
<field name="height"/>
<field name="weight"/>
<field name="weight" string="重量(kg)"/>
<field name="gripper_length_min"/>
<field name="gripper_width_min"/>
<field name="gripper_height_min"/>
@@ -335,7 +335,7 @@
<field name="width"/>
<field name="height"/>
<field name="diameter"/>
<field name="weight"/>
<field name="weight" string="重量(kg)"/>
<field name="gripper_length_min"/>
<field name="gripper_width_min"/>
<field name="gripper_height_min"/>

View File

@@ -80,10 +80,10 @@
<field name="name">sf.cutter.function.tree</field>
<field name="model">sf.functional.cutting.tool.model</field>
<field name="arch" type="xml">
<tree string="功能刀具类型" create="0" delete="0" edit="1">
<field name="name" string="名称"/>
<field name="code"/>
<field name="remark"/>
<tree string="功能刀具类型" create="0" delete="0" edit="1" editable="bottom">
<field name="name" string="名称" readonly="1"/>
<field name="code" readonly="1"/>
<field name="remark" readonly="1"/>
</tree>
</field>
</record>

View File

@@ -36,7 +36,7 @@ class Http(models.AbstractModel):
post_time = int(datas['HTTP_TIMESTAMP'])
datetime_post = datetime.fromtimestamp(post_time)
datetime_now = datetime.now().replace(microsecond=0)
datetime_del = datetime_now + timedelta(seconds=5)
datetime_del = datetime_now + timedelta(seconds=30)
if datetime_post > datetime_del:
raise AuthenticationError('请求已过期')
check_str = '%s%s%s' % (datas['HTTP_TOKEN'], post_time, factory_secret.sf_secret_key)

View File

@@ -1,7 +1,9 @@
import traceback
from datetime import datetime
import logging
import requests
from odoo import fields, models
from odoo.exceptions import UserError
from odoo import fields, models, _
_logger = logging.getLogger(__name__)
@@ -14,26 +16,52 @@ class StatusChange(models.Model):
def action_confirm(self):
# 在原有方法执行前记录日志和执行其他操作
logging.info('函数已经执行=============')
server_product_none = []
for order in self.order_line:
gain_way_no = order.product_template_id.model_process_parameters_ids.filtered(lambda a: not a.gain_way)
if gain_way_no:
process_parameters = [item.name for item in gain_way_no]
raise UserError(
_("请先至【制造】-【配置】中【表面工艺可选参数】为【%s】填写获取方式", ", ".join(process_parameters)))
for item in order.product_template_id.model_process_parameters_ids:
if item.gain_way == '外协':
server_product = self.env['product.template'].search(
[('server_product_process_parameters_id', '=', item.id),
('detailed_type', '=', 'service')])
if not server_product:
server_product_none.append(item.name)
if server_product_none:
raise UserError(_("请先至【产品】中创建【表面工艺参数】为【%s】的服务产品", ", ".join(server_product_none)))
# 使用super()来调用原始方法(在本例中为'sale.order'模型的'action_confirm'方法)
res = super(StatusChange, self).action_confirm()
# 原有方法执行后进行额外的操作如调用外部API
process_start_time = str(datetime.now())
config = self.env['res.config.settings'].get_values()
json1 = {
'params': {
'model_name': 'jikimo.process.order',
'field_name': 'name',
'default_code': self.default_code,
'state': '加工中',
'process_start_time': process_start_time,
},
}
url1 = config['bfm_url_new'] + '/api/get/state/get_order'
requests.post(url1, json=json1, data=None)
logging.info('接口已经执行=============')
try:
res = super(StatusChange, self).action_confirm()
# 原有方法执行后进行额外的操作如调用外部API
process_start_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
config = self.env['res.config.settings'].get_values()
json1 = {
'params': {
'model_name': 'jikimo.process.order',
'field_name': 'name',
'default_code': self.default_code,
'state': '加工中',
'process_start_time': process_start_time,
},
}
url1 = config['bfm_url_new'] + '/api/get/state/get_order'
ret = requests.post(url1, json=json1, data=None)
ret = ret.json()
if not ret.get('error'):
logging.info('接口已经执行=============')
else:
traceback_error = traceback.format_exc()
logging.error("bfm订单状态同步失败:%s request info %s" % traceback_error)
logging.error('/api/get/state/get_order 请求失败{}'.format(ret))
raise UserError('工厂加工同步订单状态到bfm失败')
except UserError as e:
traceback_error = traceback.format_exc()
logging.error("工厂加工同步订单状态失败:%s " % traceback_error)
raise UserError(e)
return res
def action_cancel(self):
@@ -202,12 +230,12 @@ class FinishStatusChange(models.Model):
[('id', 'child_of', self.picking_type_id.warehouse_id.view_location_id.id),
('usage', '!=', 'supplier')])
if self.env['stock.move'].search([
('state', 'in', ['confirmed', 'partially_available', 'waiting', 'assigned']),
('product_qty', '>', 0),
('location_id', 'in', wh_location_ids),
('move_orig_ids', '=', False),
('picking_id', 'not in', self.ids),
('product_id', 'in', lines.product_id.ids)], limit=1):
('state', 'in', ['confirmed', 'partially_available', 'waiting', 'assigned']),
('product_qty', '>', 0),
('location_id', 'in', wh_location_ids),
('move_orig_ids', '=', False),
('picking_id', 'not in', self.ids),
('product_id', 'in', lines.product_id.ids)], limit=1):
action = self.action_view_reception_report()
action['context'] = {'default_picking_ids': self.ids}
return action

View File

@@ -122,7 +122,7 @@ class ResMrpBomMo(models.Model):
# 查bom的原材料
def get_raw_bom(self, product):
raw_bom = self.env['product.product'].search(
[('categ_id.type', '=', '原材料'), ('materials_type_id', '=', product.materials_type_id.id)])
[('categ_id.type', '=', '原材料'), ('materials_type_id', '=', product.materials_type_id.id)],limit=1)
return raw_bom

View File

@@ -1,6 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<data>
<record id="mrp.product_template_action" model="ir.actions.act_window">
<field name="context">
{"search_default_categ_id":1,"search_default_consumable": 1, 'default_detailed_type': 'product'}
</field>
</record>
<record model="ir.ui.view" id="view_sale_product_template_form_inherit_sf">
<field name="name">product.template.form.inherit.sf</field>
<field name="model">product.template</field>
@@ -88,7 +93,8 @@
</div>
<field name="model_volume" string="体积[mm³]"/>
<field name="product_model_type_id" string="模型类型"/>
<field name="model_processing_panel" placeholder="例如R,U" string="加工面板" readonly="1"/>
<field name="model_processing_panel" placeholder="例如R,U" string="加工面板"
readonly="1"/>
<field name="model_machining_precision"/>
<field name="model_process_parameters_ids" string="表面工艺参数"
widget="many2many_tags"
@@ -103,11 +109,11 @@
'刀具')], 'required': True}
</attribute>
</xpath>
<!-- <xpath expr="//field[@name='default_code']" position="attributes">-->
<!-- <attribute name="attrs">{'readonly': [('categ_type', '=', '刀具')], 'invisible':-->
<!-- [('product_variant_count', '>' , 1)]}-->
<!-- </attribute>-->
<!-- </xpath>-->
<!-- <xpath expr="//field[@name='default_code']" position="attributes">-->
<!-- <attribute name="attrs">{'readonly': [('categ_type', '=', '刀具')], 'invisible':-->
<!-- [('product_variant_count', '>' , 1)]}-->
<!-- </attribute>-->
<!-- </xpath>-->
</field>
</record>

3
sf_hr/__init__.py Normal file
View File

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

24
sf_hr/__manifest__.py Normal file
View File

@@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name': '机企猫智能工厂 员工管理',
'version': '1.0',
'summary': '智能工厂员工模块',
'sequence': 1,
'category': 'sf',
'website': 'https://www.sf.jikimo.com',
'depends': ['hr'],
'data': [
'views/hr_employee.xml',
'views/res_config_settings_views.xml',
'data/cron_data.xml',
],
'demo': [
],
'qweb': [
],
'license': 'LGPL-3',
'installable': True,
'application': False,
'auto_install': False,
}

15
sf_hr/data/cron_data.xml Normal file
View File

@@ -0,0 +1,15 @@
<odoo>
<data noupdate="1">
<record model="ir.cron" id="ir_cron_employee_info_sync">
<field name="name">员工企微id同步</field>
<field name="model_id" ref="hr.model_hr_employee"/>
<field name="state">code</field>
<field name="code">model._employee_info_sync()</field>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field name="doall" eval="False"/>
</record>
</data>
</odoo>

4
sf_hr/models/__init__.py Normal file
View File

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

View File

@@ -0,0 +1,26 @@
import logging
import requests
from odoo import models, fields, api, _
_logger = logging.getLogger(__name__)
class JkmPracticeEmployee(models.Model):
_inherit = 'hr.employee'
_description = '员工信息'
we_id = fields.Char(string='企微ID', index=True)
def _employee_info_sync(self):
url = '/api/get/organization'
config = self.env['res.config.settings'].get_values()
ret = requests.post((config['ims_url'] + url), json={}, data={})
result = ret.json()['result']
if result['code'] == 200:
if result['employee_list']:
for employee_info in result['employee_list']:
if employee_info['work_email']:
self.sudo().search([('work_email', '=', employee_info['work_email'])]).write(
{'we_id': employee_info['we_id']})
else:
logging.info('_employee_info_sync error:%s' % result['message'])

View File

@@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
import logging
from odoo import api, fields, models
_logger = logging.getLogger(__name__)
class ResIMSConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
ims_url = fields.Char('综合管理系统访问地址')
@api.model
def get_values(self):
"""
重载获取参数的方法,参数都存在系统参数中
:return:
"""
values = super(ResIMSConfigSettings, self).get_values()
config = self.env['ir.config_parameter'].sudo()
ims_url = config.get_param('ims_url', default='')
values.update(
ims_url=ims_url,
)
return values
def set_values(self):
super(ResIMSConfigSettings, self).set_values()
ir_config = self.env['ir.config_parameter'].sudo()
ir_config.set_param("ims_url", self.ims_url or "")

View File

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data>
<record id="view_form_employee_extend" model="ir.ui.view">
<field name="name">employee_form</field>
<field name="model">hr.employee</field>
<field name="inherit_id" ref="hr.view_employee_form"/>
<field name="arch" type="xml">
<xpath expr="//group//field[@name='work_email']" position="attributes">
<attribute name="required">1</attribute>
</xpath>
<xpath expr="//page[@name='public']" position='after'>
<page string="企业微信">
<group col="2">
<group>
<field name="we_id"/>
</group>
</group>
</page>
</xpath>
</field>
</record>
</data>
</odoo>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="res_config_settings_finance_view_form_extend" model="ir.ui.view">
<field name="name">res.config.settings.finance.view.form.extend</field>
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="base.res_config_settings_view_form"/>
<field name="arch" type="xml">
<xpath expr="//div[hasclass('app_settings_block')]/div" position="before">
<div>
<h2>综合管理系统接口配置</h2>
<div class="row mt16 o_settings_container" id="jd_api">
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane"/>
<div class="o_setting_right_pane">
<div class="text-muted">
<label for="ims_url"/>
<field name="ims_url"/>
</div>
</div>
</div>
</div>
</div>
</xpath>
</field>
</record>
</data>
</odoo>

View File

@@ -30,6 +30,7 @@
'views/machine_info_present.xml',
'views/delivery_record.xml',
'views/res_config_settings_views.xml',
'views/maintenance_views.xml',
],
'assets': {

File diff suppressed because it is too large Load Diff

View File

@@ -2,3 +2,4 @@ from . import ftp_client
from . import ftp_operate
from . import py2opcua
from . import res_config_setting
from . import mrp_workorder

View File

@@ -121,6 +121,13 @@ class Machine_ftp(models.Model):
"""
_inherit = 'maintenance.equipment'
# 机床首次上线时间(默认取值2024年08月01日零点)
def _get_default_online_time(self):
return datetime(2024, 1, 1, 0, 0, 0)
first_online_time = fields.Datetime(string='首次上线时间', default=_get_default_online_time)
# workorder_ids = fields.One2many('mrp.workorder', 'machine_tool_id', string='工单')
# # 机床配置项目
@@ -275,7 +282,28 @@ class Machine_ftp(models.Model):
alarm_msg = fields.Char('故障报警信息', readonly=True)
clear_time = fields.Char('故障消除时间(复原时间)', readonly=True)
# 当前程序名, 机床累计运行时间, 机床系统日期, 机床系统时间, 当前刀具号, 机床循环时间
# # 开动率
run_rate = fields.Char('开动率', readonly=True)
# 同步CNC设备到oee
def sync_oee(self):
"""
同步CNC设备到oee
:return:
"""
for record in self:
record.ensure_one()
cnc_oee_dict = {
'equipment_id': record.id,
'type_id': record.type_id.id,
'machine_tool_picture': record.machine_tool_picture,
'equipment_code': record.code,
'function_type': record.function_type,
}
if self.env['maintenance.equipment.oee.logs'].search([('equipment_id', '=', record.id)]):
self.env['maintenance.equipment.oee.logs'].write(cnc_oee_dict)
else:
self.env['maintenance.equipment.oee.logs'].create(cnc_oee_dict)
class WorkCenterBarcode(models.Model):

View File

@@ -0,0 +1,38 @@
import re
from odoo import fields, models, api
class ResMrpWorkOrder(models.Model):
_inherit = 'mrp.workorder'
mixed_search_field = fields.Char(string='坯料产品名称/RFID')
@api.model
def web_read_group(self, domain, fields, groupby, limit=None, offset=0, orderby=False,
lazy=True, expand=False, expand_limit=None, expand_orderby=False):
domain = domain or []
for index, item in enumerate(domain):
if isinstance(item, list):
if item[0] == 'mixed_search_field':
if self._is_rfid_code(item[2]):
domain[index] = ['rfid_code', item[1], item[2]]
else:
domain[index] = ['product_tmpl_name', item[1], item[2]]
return super(ResMrpWorkOrder, self).web_read_group(domain, fields, groupby, limit=limit, offset=offset, orderby=orderby,
lazy=lazy, expand=expand, expand_limit=expand_limit, expand_orderby=expand_orderby)
def _is_rfid_code(self, tag):
"""
判断是否是rfid_code
"""
# 基于长度判断假设RFID标签长度为10到16个字符
if not 10 <= len(tag) <= 16:
return False
# 基于字符集判断(仅包含数字和字母)
if not re.match("^[0-9]*$", tag):
return False
return True

View File

@@ -16,6 +16,7 @@ class ResBFMConfigSettings(models.TransientModel):
# ("https://bfm.jikimo.com", "正式环境(https://bfm.jikimo.com)")], string='bfm环境', store=True)
bfm_url_new = fields.Char('业务平台环境路径', placeholder='请输入当前对应的业务平台环境路径')
get_check_file_path = fields.Char('获取检查文件路径', default='')
@api.model
def get_values(self):
@@ -26,9 +27,11 @@ class ResBFMConfigSettings(models.TransientModel):
values = super(ResBFMConfigSettings, self).get_values()
config = self.env['ir.config_parameter'].sudo()
bfm_url_new = config.get_param('bfm_url_new', default='')
get_check_file_path = config.get_param('get_check_file_path', default='')
values.update(
bfm_url_new=bfm_url_new,
get_check_file_path=get_check_file_path
)
return values
@@ -36,3 +39,4 @@ class ResBFMConfigSettings(models.TransientModel):
super(ResBFMConfigSettings, self).set_values()
ir_config = self.env['ir.config_parameter'].sudo()
ir_config.set_param("bfm_url_new", self.bfm_url_new or "")
ir_config.set_param("get_check_file_path", self.get_check_file_path or "")

View File

@@ -26,6 +26,7 @@
<filter string="自动编程" name="no_manual_quotation" domain="[('manual_quotation', '=', False)]"/>
</xpath>
<xpath expr="//field[@name='production_id']" position="before">
<field name="mixed_search_field"/>
<field name="product_tmpl_name"/>
<field name="rfid_code"/>
</xpath>

View File

@@ -18,6 +18,7 @@
<field name="run_status"/>
<field name="run_time"/>
<field name="system_date"/>
<field name="first_online_time"/>
</group>
<group>
<field name="cut_status"/>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0"?>
<odoo>
<!-- 修改设备列表视图-->
<record id="sf_machine_hr_equipment_view_tree_inherit" model="ir.ui.view">
<field name="name">sf.machine.hr.equipment.view.tree.inherit</field>
<field name="model">maintenance.equipment</field>
<field name="inherit_id" ref="maintenance.hr_equipment_view_tree"/>
<field name="arch" type="xml">
<xpath expr="//tree" position="inside">
<header>
<button name="sync_oee" type="object" string="同步设备至OEE"/>
</header>
</xpath>
</field>
</record>
</odoo>

View File

@@ -22,6 +22,33 @@
</div>
</div>
</div>
<div>
<h2>获取检测报告服务配置</h2>
<div class="row mt16 o_settings_container" id="check_report_config">
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane"/>
<div class="o_setting_right_pane">
<div class="text-muted">
<label for="get_check_file_path" />
<field name="get_check_file_path" string="检测报告服务地址"/>
</div>
</div>
<!-- </div> -->
</div>
</div>
</div>
</xpath>
<xpath expr="//div[@id='check_report_config']/div" position="after">
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="is_get_detection_file"/>
</div>
<div class="o_setting_right_pane">
<div class="text-muted">
<label for="is_get_detection_file"/>
</div>
</div>
</div>
</xpath>
</field>
</record>

View File

@@ -24,6 +24,7 @@ class SfEquipmentSaintenanceStandards(models.Model):
remark = fields.Char('备注')
maintenance_type = fields.Selection([('保养', '保养'), ("检修", "检修")], string='类型', default='保养')
name = fields.Char(string='名称')
active = fields.Boolean(default=True)
@api.model_create_multi
def create(self, vals_list):

View File

@@ -38,8 +38,7 @@ class SfMaintenanceEquipment(models.Model):
crea_url = "/api/machine_tool/create"
#AGV运行日志
# AGV运行日志
agv_logs = fields.One2many('maintenance.equipment.agv.log', 'equipment_id', string='AGV运行日志')
# 1212修改后的字段
number_of_axles = fields.Selection(
@@ -117,7 +116,6 @@ class SfMaintenanceEquipment(models.Model):
# num = "%04d" % m
# return num
equipment_maintenance_standards_ids = fields.Many2many('equipment.maintenance.standards',
'sf_maintenance_equipment_ids', string='设备维保标准')
eq_maintenance_id = fields.Many2one('equipment.maintenance.standards', string='设备保养标准',
@@ -179,7 +177,8 @@ class SfMaintenanceEquipment(models.Model):
type_id = fields.Many2one('sf.machine_tool.type', '型号')
state = fields.Selection(
[("正常", "正常"), ("故障停机", "故障停机"), ("计划维保", "计划维保"), ("空闲", "空闲"), ("封存(报废)", "封存(报废)")],
[("正常", "正常"), ("故障停机", "故障停机"), ("计划维保", "计划维保"), ("空闲", "空闲"),
("封存(报废)", "封存(报废)")],
default='正常', string="机床状态")
run_time = fields.Char('总运行时长')
# 0606新增字段
@@ -328,7 +327,7 @@ class SfMaintenanceEquipment(models.Model):
item.tool_diameter_min = item.type_id.tool_diameter_min
item.machine_tool_category = item.type_id.machine_tool_category.id
item.brand_id = item.type_id.brand_id.id
#新增修改字段
# 新增修改字段
item.taper_type_id = item.type_id.taper_type_id.id
item.function_type = item.type_id.function_type
item.a_axis = item.type_id.a_axis
@@ -370,7 +369,6 @@ class SfMaintenanceEquipment(models.Model):
item.image_id = item.type_id.jg_image_id.ids
item.image_lq_id = item.type_id.lq_image_id.ids
# AGV小车设备参数
AGV_L = fields.Char('AGV尺寸(长)')
AGV_W = fields.Char('AGV尺寸(宽)')
@@ -461,18 +459,6 @@ class SfMaintenanceEquipment(models.Model):
original_value = fields.Char('原值')
incomplete_value = fields.Char('残值')
# 注册同步机床
def enroll_machine_tool(self):
sf_sync_config = self.env['res.config.settings'].get_values()
@@ -763,7 +749,7 @@ class SfMaintenanceEquipment(models.Model):
image_id = fields.Many2many('maintenance.equipment.image', 'equipment_id',
domain="[('type', '=', '加工能力')]")
image_lq_id = fields.Many2many('maintenance.equipment.image', 'equipment_lq_id', string='冷却方式',
domain="[('type', '=', '冷却方式')]")
domain="[('type', '=', '冷却方式')]")
class SfRobotAxisNum(models.Model):
@@ -777,4 +763,5 @@ class SfRobotAxisNum(models.Model):
weight = fields.Char('最大负载(kg)')
permissible_load_torque = fields.Char('允许负载扭矩(N-m)')
permissible_inertial_torque = fields.Char('允许惯性扭矩(kg-m²)')
equipment_id = fields.Many2one('maintenance.equipment', string='机器人', domain="[('equipment_type', '=', '机器人')]")
equipment_id = fields.Many2one('maintenance.equipment', string='机器人',
domain="[('equipment_type', '=', '机器人')]")

View File

@@ -41,29 +41,32 @@ class SfMaintenanceEquipmentOEELog(models.Model):
_name = 'maintenance.equipment.oee.logs'
_description = '设备运行日志'
equipment_id = fields.Many2one('maintenance.equipment', '机台号')
equipment_code = fields.Char('设备编码')
equipment_id = fields.Many2one('maintenance.equipment', '机台号', readonly='True')
equipment_code = fields.Char('设备编码', readonly='True')
name = fields.Char('设备名称', readonly='True')
function_type = fields.Selection(
[("ZXJGZX", "钻铣加工中心"), ("CXJGZX", "车削加工中心"), ("FHJGZX", "复合加工中心")],
default="", string="功能类型")
machine_tool_picture = fields.Binary('设备图片')
type_id = fields.Many2one('sf.machine_tool.type', '品牌型号')
type_id = fields.Many2one('sf.machine_tool.type', '品牌型号', reaonly='True')
state = fields.Selection([("加工", "加工"), ("关机", "关机"), ("待机", "待机"), ("故障", "故障"),
("检修", "检修"), ("保养", "保养")], default="", string="实时状态")
online_time = fields.Char('开机时长')
online_time = fields.Char('开机时长', reaonly='True')
offline_time = fields.Char('关机时长')
offline_nums = fields.Integer('关机次数')
offline_time = fields.Char('关机时长', reaonly='True')
offline_nums = fields.Integer('关机次数', reaonly='True')
# 待机时长
idle_time = fields.Char('待机时长')
idle_time = fields.Char('待机时长', reaonly='True')
# 待机率
idle_rate = fields.Char('待机率')
idle_rate = fields.Char('待机率', reaonly='True')
work_time = fields.Char('加工时长')
work_rate = fields.Char('可用率')
fault_time = fields.Char('故障时长')
fault_rate = fields.Char('故障率')
fault_nums = fields.Integer('故障次数')
work_time = fields.Char('加工时长', reaonly='True')
work_rate = fields.Char('可用率', reaonly='True')
fault_time = fields.Char('故障时长', reaonly='True')
fault_rate = fields.Char('故障率', reaonly='True')
fault_nums = fields.Integer('故障次数', reaonly='True')
detail_ids = fields.One2many('maintenance.equipment.oee.log.detail', 'log_id', string='日志详情')
@@ -81,12 +84,15 @@ class SfMaintenanceEquipmentOEELog(models.Model):
class SfMaintenanceEquipmentOEELogDetail(models.Model):
_name = 'maintenance.equipment.oee.log.detail'
_description = '设备运行日志详情'
_order = 'time desc'
sequence = fields.Integer('序号')
# sequence = fields.Integer('序号', related='id')
time = fields.Datetime('时间')
state = fields.Selection([("加工", "加工"), ("关机", "关机"), ("待机", "待机"), ("故障", "故障"),
("检修", "检修"), ("保养", "保养")], default="", string="事件/状态")
production_id = fields.Many2one('mrp.production', '加工工单')
production_name = fields.Char('加工工单')
log_id = fields.Many2one('maintenance.equipment.oee.logs', '日志')
# equipment_code = fields.Char('设备编码', related='log_id.equipment_code')
equipment_code = fields.Char('设备编码', readonly='True')

View File

@@ -6,15 +6,16 @@
<field name="name">equipment.maintenance.standards.form</field>
<field name="model">equipment.maintenance.standards</field>
<field name="arch" type="xml">
<form string="设备维保标准">
<form string="设备维保标准" delete="false" duplicate="false">
<sheet>
<group>
<group>
<field name="code" readonly="1" force_save="1"/>
<field name="name" readonly="1" force_save="1"/>
<field name="maintenance_equipment_category_id" required="1" />
<field name="eq_maintenance_ids" invisible='1'/>
<field name="overhaul_ids" invisible='1'/>
<group>
<field name="active" invisible="1"/>
<field name="code" readonly="1" force_save="1"/>
<field name="name" readonly="1" force_save="1"/>
<field name="maintenance_equipment_category_id" required="1"/>
<field name="eq_maintenance_ids" invisible='1'/>
<field name="overhaul_ids" invisible='1'/>
</group>
@@ -50,7 +51,8 @@
<field name="name">equipment.maintenance.standards.tree</field>
<field name="model">equipment.maintenance.standards</field>
<field name="arch" type="xml">
<tree string="设备维保标准">
<tree string="设备维保标准" delete="false">
<field name="active" invisible="1"/>
<field name="code" readonly="1" force_save="1"/>
<field name="maintenance_type" required="1"/>
<field name="name" required="1"/>
@@ -77,6 +79,7 @@
<field name="name" string="日常机床保养"/>
<field name="created_user_id" string="创建人"/>
<field name="maintenance_equipment_category_id" string="设备类别"/>
<filter name="filter_active" string="已归档" domain="[('active','=',False)]"/>
</search>
</field>
</record>

View File

@@ -159,6 +159,8 @@
<field name="equipment_id" domain="[('name','ilike','加工中心')]"/>
<field name="type_id"/>
<field name="state"/>
<field name="equipment_code"/>
<field name="function_type"/>
</group>
</group>
<group>
@@ -202,10 +204,10 @@
<!-- <field name="detail_ids" domain="[('time','&lt;',(datetime.datetime.now() - datetime.timedelta(days=1)).strftime('%Y-%m-%d %H:%M:%S'))]"> -->
<field name="detail_ids" domain="[('state','ilike','加工')]">
<tree>
<field name="sequence"/>
<!-- <field name="sequence"/> -->
<field name="time"/>
<field name="state"/>
<field name="production_id"/>
<field name="production_name"/>
</tree>
<!-- <form> -->
<!-- <field name="sequence"/> -->
@@ -219,10 +221,10 @@
<page string="历史日志详情">
<field name="detail_ids">
<tree>
<field name="sequence"/>
<!-- <field name="sequence"/> -->
<field name="time"/>
<field name="state"/>
<field name="production_id"/>
<field name="production_name"/>
</tree>
<!-- <form> -->
<!-- <field name="sequence"/> -->
@@ -263,10 +265,10 @@
<field name="model">maintenance.equipment.oee.log.detail</field>
<field name="arch" type="xml">
<tree>
<field name="sequence"/>
<!-- <field name="sequence"/> -->
<field name="time"/>
<field name="state"/>
<field name="production_id"/>
<field name="production_name"/>
</tree>
</field>
</record>
@@ -280,10 +282,10 @@
<group>
<group>
<field name="state"/>
<field name="production_id"/>
<!-- <field name="production_id"/> -->
</group>
<group>
<field name="sequence"/>
<!-- <field name="sequence"/> -->
<field name="time"/>
</group>
</group>

View File

@@ -15,12 +15,14 @@
'data/stock_data.xml',
'data/empty_racks_data.xml',
'data/panel_data.xml',
'data/agv_scheduling_data.xml',
'security/group_security.xml',
'security/ir.model.access.csv',
'wizard/workpiece_delivery_views.xml',
'wizard/rework_wizard_views.xml',
'wizard/production_wizard_views.xml',
'views/mrp_views_menus.xml',
'views/agv_scheduling_views.xml',
'views/stock_lot_views.xml',
'views/mrp_production_addional_change.xml',
'views/mrp_routing_workcenter_view.xml',
@@ -30,7 +32,7 @@
'views/model_type_view.xml',
'views/agv_setting_views.xml',
'views/sf_maintenance_equipment.xml',
'views/res_config_settings_views.xml',
],
'assets': {
@@ -40,7 +42,9 @@
'web.assets_backend': [
'sf_manufacturing/static/src/xml/kanban_change.xml',
'sf_manufacturing/static/src/js/kanban_change.js',
'sf_manufacturing/static/src/scss/kanban_change.scss'
'sf_manufacturing/static/src/scss/kanban_change.scss',
'sf_manufacturing/static/src/xml/button_show_on_tree.xml',
'sf_manufacturing/static/src/js/workpiece_delivery_wizard_confirm.js',
]
},

View File

@@ -2,6 +2,8 @@
import logging
import json
from datetime import datetime
from odoo.addons.sf_manufacturing.models.agv_scheduling import RepeatTaskException
from odoo import http
from odoo.http import request
@@ -145,7 +147,7 @@ class Manufacturing_Connect(http.Controller):
logging.info('get_qcCheck error:%s' % e)
return json.JSONEncoder().encode(res)
@http.route('/AutoDeviceApi/FeedBackStart', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False,
@http.route('/AutoDeviceApi/FeedBackStart', type='json', auth='none', methods=['GET', 'POST'], csrf=False,
cors="*")
def button_Work_START(self, **kw):
"""
@@ -193,7 +195,7 @@ class Manufacturing_Connect(http.Controller):
logging.info('button_Work_START error:%s' % e)
return json.JSONEncoder().encode(res)
@http.route('/AutoDeviceApi/FeedBackEnd', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False,
@http.route('/AutoDeviceApi/FeedBackEnd', type='json', auth='none', methods=['GET', 'POST'], csrf=False,
cors="*")
def button_Work_End(self, **kw):
"""
@@ -244,7 +246,7 @@ class Manufacturing_Connect(http.Controller):
logging.info('button_Work_End error:%s' % e)
return json.JSONEncoder().encode(res)
@http.route('/AutoDeviceApi/PartQualityInspect', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False,
@http.route('/AutoDeviceApi/PartQualityInspect', type='json', auth='none', methods=['GET', 'POST'], csrf=False,
cors="*")
def PartQualityInspect(self, **kw):
"""
@@ -290,7 +292,7 @@ class Manufacturing_Connect(http.Controller):
logging.info('PartQualityInspect error:%s' % e)
return json.JSONEncoder().encode(res)
@http.route('/AutoDeviceApi/CMMProgDolod', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False,
@http.route('/AutoDeviceApi/CMMProgDolod', type='json', auth='none', methods=['GET', 'POST'], csrf=False,
cors="*")
def CMMProgDolod(self, **kw):
"""
@@ -330,7 +332,7 @@ class Manufacturing_Connect(http.Controller):
logging.info('CMMProgDolod error:%s' % e)
return json.JSONEncoder().encode(res)
@http.route('/AutoDeviceApi/NCProgDolod', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False,
@http.route('/AutoDeviceApi/NCProgDolod', type='json', auth='none', methods=['GET', 'POST'], csrf=False,
cors="*")
def NCProgDolod(self, **kw):
"""
@@ -386,7 +388,7 @@ class Manufacturing_Connect(http.Controller):
ret = json.loads(datas)
request.env['center_control.interface.log'].sudo().create(
{'content': ret, 'name': 'AutoDeviceApi/LocationChange'})
logging.info('LocationChange_ret===========:%s' % ret)
logging.info('库位变更LocationChange_ret:%s' % ret)
RfidCode = ret['RfidCode']
ChangeType = ret['ChangeType']
OldDeciveId = ret['OldDeciveId']
@@ -396,40 +398,86 @@ class Manufacturing_Connect(http.Controller):
OldDeciveStart = ret['OldDeciveStart']
OldDeciveEnd = ret['OldDeciveEnd']
temp_val_sn_id = None
old_localtion = None
# if ChangeType == 'Part' or ChangeType == 'Tool':
stock_lot_obj = request.env['stock.lot'].sudo().search(
[('rfid', '=', RfidCode)], limit=1)
logging.info('stock_lot_obj===========:%s' % stock_lot_obj)
if not stock_lot_obj:
res = {'Succeed': False, 'ErrorCode': 202, 'Error': '未根据RfidCode找到该产品'}
return json.JSONEncoder().encode(res)
if OldPosition:
old_localtion = request.env['sf.shelf.location'].sudo().search(
[('barcode', '=', OldPosition)], limit=1)
logging.info('old_localtion===========:%s' % old_localtion)
new_localtion = request.env['sf.shelf.location'].sudo().search(
[('barcode', '=', NewPosition)], limit=1)
logging.info('new_localtion===========:%s' % new_localtion)
if not new_localtion:
res = {'Succeed': False, 'ErrorCode': 202, 'Error': '没有该目标位置'}
return json.JSONEncoder().encode(res)
if old_localtion:
temp_val_sn_id = old_localtion.product_sn_id
logging.info('temp_val_sn_id===========:%s' % temp_val_sn_id)
old_localtion.product_sn_id = None
new_localtion.product_sn_id = temp_val_sn_id
logging.info('====1======')
else:
new_localtion.product_sn_id = stock_lot_obj.id
logging.info('=====2======')
if ChangeType == 'Part':
temp_val_sn_id = None
old_localtion = None
# if ChangeType == 'Part' or ChangeType == 'Tool':
stock_lot_obj = request.env['stock.lot'].sudo().search(
[('rfid', '=', RfidCode)], limit=1)
logging.info('stock_lot_obj===========:%s' % stock_lot_obj)
if not stock_lot_obj:
res = {'Succeed': False, 'ErrorCode': 202, 'Error': '未根据RfidCode找到该产品'}
return json.JSONEncoder().encode(res)
if OldPosition:
old_localtion = request.env['sf.shelf.location'].sudo().search(
[('barcode', '=', OldPosition)], limit=1)
logging.info('old_localtion===========:%s' % old_localtion)
new_localtion = request.env['sf.shelf.location'].sudo().search(
[('barcode', '=', NewPosition)], limit=1)
logging.info('new_localtion===========:%s' % new_localtion)
if not new_localtion:
res = {'Succeed': False, 'ErrorCode': 202, 'Error': '没有该目标位置'}
return json.JSONEncoder().encode(res)
if old_localtion:
temp_val_sn_id = old_localtion.product_sn_id
logging.info('temp_val_sn_id===========:%s' % temp_val_sn_id)
old_localtion.product_sn_id = None
new_localtion.product_sn_id = temp_val_sn_id
logging.info('====1======')
else:
new_localtion.product_sn_id = stock_lot_obj.id
logging.info('=====2======')
elif ChangeType == 'Tool':
# 对功能刀具库位变更信息进行更改
def write_tool(DeciveId):
if 'Tool' in DeciveId:
shelfinfo = list(filter(lambda x: x.get('DeviceId') == DeciveId,
request.env['sf.shelf.location'].sudo().get_sf_shelf_location_info(
DeciveId)))
total_data = request.env['sf.shelf.location.datasync'].sudo().get_total_data()
for item in shelfinfo:
logging.info('货架已获取信息:%s' % item)
shelf_barcode = request.env['sf.shelf.location.datasync'].sudo().find_our_code(
total_data, item['Postion'])
location_id = request.env['sf.shelf.location'].sudo().search(
[('barcode', '=', shelf_barcode)],
limit=1)
if location_id:
# 如果是线边刀库信息,则对功能刀具移动生成记录
if 'Tool' in item['Postion']:
tool = request.env['sf.functional.cutting.tool.entity'].sudo().search(
[('rfid', '=', item['RfidCode']), ('functional_tool_status', '!=', '已拆除')])
tool.sudo().tool_in_out_stock_location(location_id)
if tool:
location_id.product_sn_id = tool.barcode_id.id
# 修改功能刀具状态
if item.get('State') == '报警':
if tool.functional_tool_status != item.get('State'):
tool.write({
'functional_tool_status': item['State']
})
else:
location_id.product_sn_id = False
if item['RfidCode']:
logging.info('Rfid为【%s】的功能刀具在系统中不存在!' % item['RfidCode'])
else:
equipment_id = request.env['maintenance.equipment'].sudo().search([('name', '=', DeciveId)])
if equipment_id:
equipment_id.sudo().register_equipment_tool()
else:
res_1 = {'Succeed': False, 'ErrorCode': 202, 'Error': f'设备【{DeciveId}】不存在'}
return json.JSONEncoder().encode(res_1)
if OldDeciveId:
write_tool(OldDeciveId)
elif NewDeciveId:
write_tool(NewDeciveId)
except Exception as e:
res = {'Succeed': False, 'ErrorCode': 202, 'Error': e}
logging.info('LocationChange error:%s' % e)
return json.JSONEncoder().encode(res)
@http.route('/AutoDeviceApi/AGVToProduct', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False,
@http.route('/AutoDeviceApi/AGVToProduct', type='json', auth='none', methods=['GET', 'POST'], csrf=False,
cors="*")
def AGVToProduct(self, **kw):
"""
@@ -448,13 +496,16 @@ class Manufacturing_Connect(http.Controller):
if 'DeviceId' in ret:
logging.info('DeviceId:%s' % ret['DeviceId'])
if 'IsComplete' in ret:
rfid_codes = []
workorder_ids = []
if ret['IsComplete'] is True or ret['IsComplete'] is False:
for i in range(1, 5):
logging.info('F-RfidCode:%s' % i)
if f'RfidCode{i}' in ret:
rfid_code = ret[f'RfidCode{i}']
logging.info('RfidCode:%s' % rfid_code)
if rfid_code is not None:
if rfid_code is not None and rfid_code != '':
rfid_codes.append(rfid_code)
domain = [
('rfid_code', '=', rfid_code),
('routing_type', '=', 'CNC加工'), ('state', '!=', 'rework')
@@ -462,6 +513,7 @@ class Manufacturing_Connect(http.Controller):
workorder = request.env['mrp.workorder'].sudo().search(domain, order='id asc')
if workorder:
for order in workorder:
workorder_ids.append(order.id)
if order.production_line_state == '待上产线':
logging.info(
'工单产线状态:%s' % order.production_line_state)
@@ -470,27 +522,34 @@ class Manufacturing_Connect(http.Controller):
('processing_panel', '=', order.processing_panel)])
if panel_workorder:
panel_workorder.write({'production_line_state': '已上产线'})
workpiece_delivery = request.env['sf.workpiece.delivery'].sudo().search(
[
('rfid_code', '=', rfid_code), ('type', '=', '上产线'),
('production_id', '=', order.production_id.id),
('workorder_id', '=', order.id),
('workorder_state', '=', 'done')])
if workpiece_delivery.status == '待下发':
workpiece_delivery.write({'is_manual_work': True})
# workpiece_delivery = request.env['sf.workpiece.delivery'].sudo().search(
# [
# ('rfid_code', '=', rfid_code), ('type', '=', '上产线'),
# ('production_id', '=', order.production_id.id),
# ('workorder_id', '=', order.id),
# ('workorder_state', '=', 'done')])
# if workpiece_delivery.status == '待下发':
# workpiece_delivery.write({'is_manual_work': True})
# 下发
else:
res = {'Succeed': False, 'ErrorCode': 204,
'Error': 'DeviceId为%s没有对应的已配送工件数据' % ret['DeviceId']}
if ret['IsComplete'] is True:
# 向AGV任务调度下发运送空料架任务
workorders = request.env['mrp.workorder'].browse(workorder_ids)
request.env['sf.agv.scheduling'].add_scheduling(ret['DeviceId'], '运送空料架', workorders)
else:
res = {'Succeed': False, 'ErrorCode': 203, 'Error': '未传IsComplete字段'}
else:
res = {'Succeed': False, 'ErrorCode': 201, 'Error': '未传DeviceId字段'}
except RepeatTaskException as e:
logging.info('AGVToProduct error:%s' % e)
except Exception as e:
res = {'Succeed': False, 'ErrorCode': 202, 'Error': e}
res = {'Succeed': False, 'ErrorCode': 202, 'Error': str(e)}
logging.info('AGVToProduct error:%s' % e)
return json.JSONEncoder().encode(res)
@http.route('/AutoDeviceApi/AGVDownProduct', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False,
@http.route('/AutoDeviceApi/AGVDownProduct', type='json', auth='none', methods=['GET', 'POST'], csrf=False,
cors="*")
def AGVDownProduct(self, **kw):
"""
@@ -509,7 +568,8 @@ class Manufacturing_Connect(http.Controller):
logging.info('ret:%s' % ret)
if 'DeviceId' in ret:
logging.info('DeviceId:%s' % ret['DeviceId'])
delivery_Arr = []
# delivery_Arr = []
workorder_ids = []
if 'IsComplete' in ret:
if ret['IsComplete'] is True or ret['IsComplete'] is False:
for i in range(1, 5):
@@ -517,7 +577,7 @@ class Manufacturing_Connect(http.Controller):
if f'RfidCode{i}' in ret:
rfid_code = ret[f'RfidCode{i}']
logging.info('RfidCode:%s' % rfid_code)
if rfid_code is not None:
if rfid_code is not None and rfid_code != '':
domain = [
('rfid_code', '=', rfid_code),
('routing_type', '=', 'CNC加工'), ('state', '!=', 'rework')
@@ -525,6 +585,7 @@ class Manufacturing_Connect(http.Controller):
workorder = request.env['mrp.workorder'].sudo().search(domain, order='id asc')
if workorder:
for order in workorder:
workorder_ids.append(order.id)
if order.production_line_state == '已上产线':
logging.info(
'工单产线状态:%s' % order.production_line_state)
@@ -534,35 +595,41 @@ class Manufacturing_Connect(http.Controller):
if panel_workorder:
panel_workorder.write({'production_line_state': '已下产线'})
workorder.write({'state': 'to be detected'})
workpiece_delivery = request.env['sf.workpiece.delivery'].sudo().search(
[
('rfid_code', '=', rfid_code), ('type', '=', '下产线'),
('production_id', '=', order.production_id.id),
('workorder_id', '=', order.id),
('workorder_state', '=', 'done')])
if workpiece_delivery:
delivery_Arr.append(workpiece_delivery.id)
# workpiece_delivery = request.env['sf.workpiece.delivery'].sudo().search(
# [
# ('rfid_code', '=', rfid_code), ('type', '=', '下产线'),
# ('production_id', '=', order.production_id.id),
# ('workorder_id', '=', order.id),
# ('workorder_state', '=', 'done')])
# if workpiece_delivery:
# delivery_Arr.append(workpiece_delivery.id)
else:
res = {'Succeed': False, 'ErrorCode': 204,
'Error': 'DeviceId为%s没有对应的已配送工件数据' % ret['DeviceId']}
if delivery_Arr:
logging.info('delivery_Arr:%s' % delivery_Arr)
delivery_workpiece = request.env['sf.workpiece.delivery'].sudo().search(
[('id', 'in', delivery_Arr)])
if delivery_workpiece:
logging.info('开始向agv下发下产线任务')
agv_site = request.env['sf.agv.site'].sudo().search([])
if agv_site:
has_site = agv_site.update_site_state()
if has_site is True:
is_free = delivery_workpiece._check_avgsite_state()
if is_free is True:
delivery_workpiece._delivery_avg()
logging.info('agv下发下产线任务下发完成')
# if delivery_Arr:
# logging.info('delivery_Arr:%s' % delivery_Arr)
# delivery_workpiece = request.env['sf.workpiece.delivery'].sudo().search(
# [('id', 'in', delivery_Arr)])
# if delivery_workpiece:
# logging.info('开始向agv下发下产线任务')
# agv_site = request.env['sf.agv.site'].sudo().search([])
# if agv_site:
# has_site = agv_site.update_site_state()
# if has_site is True:
# is_free = delivery_workpiece._check_avgsite_state()
# if is_free is True:
# delivery_workpiece._delivery_avg()
# logging.info('agv下发下产线任务下发完成')
if ret['IsComplete'] is True:
# 向AGV任务调度下发下产线任务
workorders = request.env['mrp.workorder'].browse(workorder_ids)
request.env['sf.agv.scheduling'].add_scheduling(ret['DeviceId'], '下产线', workorders)
else:
res = {'Succeed': False, 'ErrorCode': 203, 'Error': '未传IsComplete字段'}
except RepeatTaskException as e:
logging.info('AGVToProduct error:%s' % e)
except Exception as e:
res = {'Succeed': False, 'ErrorCode': 202, 'Error': e}
res = {'Succeed': False, 'ErrorCode': 202, 'Error': str(e)}
logging.info('AGVDownProduct error:%s' % e)
return json.JSONEncoder().encode(res)
@@ -600,3 +667,32 @@ class Manufacturing_Connect(http.Controller):
res = {'Succeed': False, 'ErrorCode': 202, 'Error': e}
logging.info('AGVDownProduct error:%s' % e)
return json.JSONEncoder().encode(res)
@http.route('/AutoDeviceApi/AgvStationState', type='json', auth='public', methods=['GET', 'POST'], csrf=False,
cors="*")
def AGVStationState(self, **kw):
"""
中控推送接驳站状态
:param kw:
:return:
"""
logging.info('AGVStationState:%s' % kw)
try:
res = {'Succeed': True}
datas = request.httprequest.data
ret = json.loads(datas)
request.env['center_control.interface.log'].sudo().create(
{'content': ret, 'name': 'AutoDeviceApi/AGVStationState'})
logging.info('ret:%s' % ret)
ret = ret['param']
params = {}
for i in range(len(ret)):
if 'DeviceId' in ret[i] and 'AtHome' in ret[i]:
logging.info('DeviceId:%s, AtHome:%s' % (ret[i]['DeviceId'], ret[i]['AtHome']))
params[ret[i]['DeviceId']] = '占用' if ret[i]['AtHome'] else '空闲'
if params:
request.env['sf.agv.site'].update_site_state(params)
except Exception as e:
res = {'Succeed': False, 'ErrorCode': 202, 'Error': str(e)}
logging.info('AGVDownProduct error:%s' % e)
return json.JSONEncoder().encode(res)

View File

@@ -25,15 +25,14 @@ class Workpiece(http.Controller):
if 'reqCode' in ret:
if 'method' in ret:
if ret['method'] == 'end':
req_codes = ret['reqCode'].split(',')
for req_code in req_codes:
workpiece_delivery = request.env['sf.workpiece.delivery'].sudo().search(
[('name', '=', req_code.strip()), ('task_completion_time', '=', False)])
if workpiece_delivery:
workpiece_delivery.write({'status': '已配送', 'task_completion_time': datetime.now()})
else:
res = {'Succeed': False, 'ErrorCode': 203,
'Error': '该reqCode暂未查到对应的工件配送记录'}
# 找到对应的AGV调度任务
agv_scheduling = request.env['sf.agv.scheduling'].sudo().search(
[('name', '=', ret['reqCode']), ('state', '=', '配送中')])
if agv_scheduling:
agv_scheduling.finish_scheduling()
else:
res = {'Succeed': False, 'ErrorCode': 203,
'Error': '该reqCode暂未查到对应的AGV任务记录'}
else:
res = {'Succeed': False, 'ErrorCode': 204, 'Error': '未传method字段'}
else:

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="0">
<record id="sequence_agv_scheduling" model="ir.sequence">
<field name="name">AGV调度</field>
<field name="code">sf.agv.scheduling</field>
<field name="prefix">B%(year)s%(month)s%(day)s</field>
<field name="padding">4</field>
<field name="number_next">1</field>
<field name="implementation">standard</field>
<field name="use_date_range">True</field>
<field name="date_range_period">day</field>
<field name="company_id" eval="False"/>
</record>
</data>
</odoo>

View File

@@ -9,3 +9,5 @@ from . import stock
from . import res_user
from . import production_line_base
from . import agv_setting
from . import agv_scheduling
from . import res_config_setting

View File

@@ -0,0 +1,282 @@
import logging
import requests
from odoo import models, fields, api, _
from odoo.exceptions import UserError
_logger = logging.getLogger(__name__)
class RepeatTaskException(UserError):
pass
class AgvScheduling(models.Model):
_name = 'sf.agv.scheduling'
_description = 'agv调度'
_order = 'id desc'
name = fields.Char('任务单号', index=True, copy=False)
def _get_agv_route_type_selection(self):
return self.env['sf.agv.task.route'].fields_get(['route_type'])['route_type']['selection']
agv_route_type = fields.Selection(selection=_get_agv_route_type_selection, string='任务类型', required=True)
agv_route_id = fields.Many2one('sf.agv.task.route', '任务路线')
start_site_id = fields.Many2one('sf.agv.site', '起点接驳站', required=True)
end_site_id = fields.Many2one('sf.agv.site', '终点接驳站', tracking=True)
site_state = fields.Selection([
('占用', '占用'),
('空闲', '空闲')], string='终点接驳站状态', default='占用')
state = fields.Selection([
('待下发', '待下发'),
('配送中', '配送中'),
('已配送', '已配送'),
('已取消', '已取消')], string='状态', default='待下发', tracking=True)
workorder_ids = fields.Many2many('mrp.workorder', 'sf_agv_scheduling_mrp_workorder_ref', string='关联工单')
task_create_time = fields.Datetime('任务创建时间')
task_delivery_time = fields.Datetime('任务下发时间')
task_completion_time = fields.Datetime('任务完成时间')
task_duration = fields.Char('任务时长', compute='_compute_task_duration')
@api.depends('agv_route_type')
def _compute_delivery_workpieces(self):
for record in self:
if record.agv_route_type == '运送空料架':
record.delivery_workpieces = '/'
else:
record.delivery_workpieces = ''.join(record.workorder_ids.mapped('production_id.name'))
delivery_workpieces = fields.Char('配送工件', compute=_compute_delivery_workpieces)
@api.model
def web_search_read(self, domain=None, fields=None, offset=0, limit=None, order=None, count_limit=None):
domain = domain or []
new_domain = []
for item in domain:
if isinstance(item, list):
if item[0] == 'delivery_workpieces':
new_domain.append('&')
new_domain.append(['workorder_ids.production_id.name', item[1], item[2]])
new_domain.append(['agv_route_type', '!=', '运送空料架'])
continue
new_domain.append(item)
return super(AgvScheduling, self).web_search_read(new_domain, fields, offset, limit, order, count_limit)
@api.depends('task_completion_time', 'task_delivery_time')
def _compute_task_duration(self):
for rec in self:
if rec.task_completion_time and rec.task_delivery_time:
rec.task_duration = str(rec.task_completion_time - rec.task_delivery_time)
else:
rec.task_duration = ''
@api.model_create_multi
def create(self, vals_list):
# We generate a standard reference
for vals in vals_list:
vals['name'] = self.env['ir.sequence'].next_by_code('sf.agv.scheduling') or _('New')
return super().create(vals_list)
def add_scheduling(self, agv_start_site_name, agv_route_type, workorders):
""" add_scheduling(agv_start_site_id, agv_route_type, workorders) -> agv_scheduling
新增AGV调度
params:
agv_start_site_name: AGV起点接驳站名称
agv_route_type: AGV任务类型
workorders: 工单
"""
_logger.info('创建AGV调度任务\r\n起点为【%s】,任务类型为【%s】,工单为【%s' % (agv_start_site_name, agv_route_type, workorders))
if not workorders:
raise UserError(_('工单不能为空'))
agv_start_site = self.env['sf.agv.site'].sudo().search([('name', '=', agv_start_site_name)], limit=1)
if not agv_start_site:
raise UserError(_('不存在名称为【%s】的接驳站,请先创建!' % agv_start_site_name))
# 如果存在相同任务类型工单的AGV调度任务则提示错误
agv_scheduling = self.sudo().search([
('workorder_ids', 'in', workorders.ids),
('agv_route_type', '=', agv_route_type),
('state', 'in', ['待下发', '配送中'])
], limit=1)
if agv_scheduling:
# 计算agv_scheduling.workorder_ids与workorders的交集
repetitive_workorders = agv_scheduling.workorder_ids & workorders
raise RepeatTaskException(
'制造订单号【%s】已存在于【%s】AGV调度任务请勿重复下发' %
(','.join(repetitive_workorders.mapped('production_id.name')), agv_scheduling.name)
)
vals = {
'start_site_id': agv_start_site.id,
'agv_route_type': agv_route_type,
'workorder_ids': workorders.ids,
# 'workpiece_delivery_ids': deliveries.mapped('id') if deliveries else [],
'task_create_time': fields.Datetime.now()
}
# 如果只有唯一任务路线,则自动赋予终点接驳站跟任务名称
agv_routes = self.env['sf.agv.task.route'].sudo().search([
('route_type', '=', agv_route_type),
('start_site_id', '=', agv_start_site.id)
])
if not agv_routes:
raise UserError(_('不存在起点为【%s】的【%s】任务路线,请先创建!' % (agv_start_site_name, agv_route_type)))
idle_route = None
if len(agv_routes) == 1:
idle_route = agv_routes[0]
vals.update({'end_site_id': idle_route.end_site_id.id, 'agv_route_id': idle_route.id})
else:
# 判断终点接驳站是否为空闲
idle_routes = agv_routes.filtered(lambda r: r.end_site_id.state == '空闲')
if idle_routes:
# 将空闲的路线按照终点接驳站名称排序
idle_routes = sorted(idle_routes, key=lambda r: r.end_site_id.name)
idle_route = idle_routes[0]
vals.update({'end_site_id': idle_route.end_site_id.id, 'agv_route_id': idle_route.id})
try:
scheduling = self.env['sf.agv.scheduling'].sudo().create(vals)
# 触发空闲接驳站状态更新,触发新任务下发
if idle_route and idle_route.end_site_id.state == '空闲':
scheduling.dispatch_scheduling(idle_route)
except Exception as e:
_logger.error('添加AGV调度任务失败: %s', e)
raise UserError(_('添加AGV调度任务失败: %s', e))
return scheduling
def on_site_state_change(self, agv_site_id, agv_site_state):
"""
响应AGV接驳站站点状态变化
params:
agv_site_id: 接驳站ID
agv_site_state: 站点状态('空闲', '占用'
"""
if agv_site_state == '空闲':
# 查询终点接驳站为agv_site_id的AGV路线
task_routes = self.env['sf.agv.task.route'].sudo().search([('end_site_id', '=', agv_site_id)])
agv_scheduling = self.env['sf.agv.scheduling'].sudo().search(
[('state', '=', '待下发'), ('agv_route_type', 'in', task_routes.mapped('route_type'))],
order='id asc',
limit=1
)
task_route = task_routes.filtered(
lambda r: r.start_site_id == agv_scheduling.start_site_id and r.start_site_id == agv_scheduling.start_site_id
)
if task_route:
# 下发AGV调度任务并修改接驳站状态为占用
agv_scheduling.dispatch_scheduling(task_route)
def _delivery_avg(self):
config = self.env['res.config.settings'].get_values()
position_code_arr = [{
'positionCode': self.start_site_id.name,
'code': '00'
}, {
'positionCode': self.end_site_id.name,
'code': '00'
}]
res = {'reqCode': self.name, 'reqTime': '', 'clientCode': '', 'tokenCode': '',
'taskTyp': 'F01', 'ctnrTyp': '', 'ctnrCode': '', 'wbCode': config['wbcode'],
'positionCodePath': position_code_arr,
'podCode': '',
'podDir': '', 'materialLot': '', 'priority': '', 'taskCode': '', 'agvCode': '', 'materialLot': '',
'data': ''}
try:
logging.info('AGV请求路径:%s' % config['agv_rcs_url'])
logging.info('AGV-json:%s' % res)
headers = {'Content-Type': 'application/json'}
ret = requests.post((config['agv_rcs_url']), json=res, headers=headers)
ret = ret.json()
logging.info('config-ret:%s' % ret)
if ret['code'] == 0:
return True
else:
raise UserError(ret['message'])
except Exception as e:
logging.info('config-e:%s' % e)
raise UserError("工件配送请求agv失败:%s" % e)
def button_cancel(self):
# 弹出二次确认窗口后执行
for rec in self:
if rec.state != '待下发':
raise UserError('只有待下发状态的AGV调度任务才能取消')
rec.state = '已取消'
def finish_scheduling(self):
"""
完成调度任务
"""
for rec in self:
if rec.state != '配送中':
return False
_logger.info('AGV任务调度完成任务%s' % rec)
rec.state = '已配送'
rec.task_completion_time = fields.Datetime.now()
def dispatch_scheduling(self, agv_task_route):
"""
下发调度任务
params:
agv_route sf.agv.task.route对象
"""
for rec in self:
if rec.state != '待下发':
return False
_logger.info('AGV任务调度下发调度任务路线为%s' % agv_task_route)
rec.state = '配送中'
rec.task_delivery_time = fields.Datetime.now()
rec.site_state = '空闲'
rec.end_site_id = agv_task_route.end_site_id.id
rec.agv_route_id = agv_task_route.id
is_agv_task_dispatch = self.env['ir.config_parameter'].sudo().get_param('is_agv_task_dispatch')
if is_agv_task_dispatch:
rec._delivery_avg()
# 更新接驳站状态
rec.env['sf.agv.site'].update_site_state({rec.end_site_id.name: '占用'}, False)
def write(self, vals):
if vals.get('state', False):
if vals['state'] == '已取消':
self.env['sf.workpiece.delivery'].search([('agv_scheduling_id', '=', self.id)]).write({'status': '待下发'})
elif vals['state'] == '已配送':
self.env['sf.workpiece.delivery'].search([('agv_scheduling_id', '=', self.id)]).write({
'status': '已配送',
'feeder_station_destination_id': self.end_site_id.id,
'route_id': self.agv_route_id.id,
'task_completion_time': fields.Datetime.now()
})
elif vals['state'] == '配送中':
self.env['sf.workpiece.delivery'].search([('agv_scheduling_id', '=', self.id)]).write({
'feeder_station_destination_id': self.end_site_id.id,
'route_id': self.agv_route_id.id,
'task_delivery_time': fields.Datetime.now()
})
return super().write(vals)
class ResMrpWorkOrder(models.Model):
_inherit = 'mrp.workorder'
agv_scheduling_ids = fields.Many2many(
'sf.agv.scheduling',
'sf_agv_scheduling_mrp_workorder_ref',
string='AGV调度',
domain=[('state', '!=', '已取消')])
def get_down_product_agv_scheduling(self):
"""
获取关联的制造订单下产线的agv任务
"""
self.ensure_one()
workorder_ids = self.production_id.workorder_ids
cnc_workorder = workorder_ids.filtered(
lambda w: w.routing_type == 'CNC加工' and w.state == 'done' and w.processing_panel == self.processing_panel
)
if cnc_workorder:
agv_schedulingss = cnc_workorder.agv_scheduling_ids
return agv_schedulingss.filtered(lambda a: a.state == '已配送' and a.agv_route_type == '下产线')
else:
return None

View File

@@ -5,50 +5,77 @@ import time
from odoo import fields, models, api
from odoo.exceptions import UserError
_logger = logging.getLogger(__name__)
class AgvSetting(models.Model):
_name = 'sf.agv.site'
_description = 'agv站点'
name = fields.Char('位置编号')
owning_region = fields.Char('所属区域')
# owning_region = fields.Char('所属区域')
state = fields.Selection([
('占用', '占用'),
('空闲', '空闲')], string='状态')
divide_the_work = fields.Char('主要分工')
active = fields.Boolean('有效', default=True)
workcenter_id = fields.Many2one(string='所属区域', comodel_name='mrp.workcenter', tracking=True,
domain=[('is_agv_scheduling', '=', True)])
def update_site_state(self):
# 调取中控的接驳站接口并修改对应站点的状态
config = self.env['res.config.settings'].get_values()
# token = sf_sync_config['token'Ba F2CF5DCC-1A00-4234-9E95-65603F70CC8A]
headers = {'Authorization': config['center_control_Authorization']}
center_control_url = config['center_control_url'] + "/AutoDeviceApi/GetAgvStationState?date="
timestamp = int(time.time())
center_control_url += str(timestamp)
logging.info('工件配送-请求中控地址:%s' % center_control_url)
try:
center_control_r = requests.get(center_control_url, headers=headers, timeout=10) # 设置超时为60秒
ret = center_control_r.json()
logging.info('工件配送-请求中控站点信息:%s' % ret)
self.env['center_control.interface.log'].sudo().create(
{'content': ret, 'name': 'AutoDeviceApi/GetAgvStationState?date=%s' % str(timestamp)})
if ret['Succeed'] is True:
datas = ret['Datas']
for item in self:
for da in datas:
if da['DeviceId'] == item.name:
if da['AtHome'] is True:
item.state = '占用'
else:
item.state = '空闲'
return True
except requests.exceptions.Timeout:
logging.error('工件配送-请求中控接口超时')
return False
except requests.exceptions.RequestException as e:
logging.error('工件配送-请求中控接口错误: %s', e)
return False
# name必须唯一
_sql_constraints = [
('name_uniq', 'unique (name)', '站点编号必须唯一!'),
]
# def update_site_state(self):
# # 调取中控的接驳站接口并修改对应站点的状态
# config = self.env['res.config.settings'].get_values()
# # token = sf_sync_config['token'Ba F2CF5DCC-1A00-4234-9E95-65603F70CC8A]
# headers = {'Authorization': config['center_control_Authorization']}
# center_control_url = config['center_control_url'] + "/AutoDeviceApi/GetAgvStationState?date="
# timestamp = int(time.time())
# center_control_url += str(timestamp)
# logging.info('工件配送-请求中控地址:%s' % center_control_url)
# try:
# center_control_r = requests.get(center_control_url, headers=headers, timeout=10) # 设置超时为60秒
# ret = center_control_r.json()
# logging.info('工件配送-请求中控站点信息:%s' % ret)
# self.env['center_control.interface.log'].sudo().create(
# {'content': ret, 'name': 'AutoDeviceApi/GetAgvStationState?date=%s' % str(timestamp)})
# if ret['Succeed'] is True:
# datas = ret['Datas']
# for item in self:
# for da in datas:
# if da['DeviceId'] == item.name:
# if da['AtHome'] is True:
# item.state = '占用'
# else:
# item.state = '空闲'
# return True
# except requests.exceptions.Timeout:
# logging.error('工件配送-请求中控接口超时')
# return False
# except requests.exceptions.RequestException as e:
# logging.error('工件配送-请求中控接口错误: %s', e)
# return False
def update_site_state(self, agv_site_state_arr, notify=True):
"""
更新接驳站状态
params:
agv_site_state_arr: {'A01': '空闲', 'B01': '占用'}
notify: 是否通知调度(非中控发起的状态改变不触发调度任务)
"""
if isinstance(agv_site_state_arr, dict):
for agv_site_name, is_occupy in agv_site_state_arr.items():
agv_site = self.env['sf.agv.site'].sudo().search([('name', '=', agv_site_name)])
if agv_site:
agv_site.state = is_occupy
if notify:
self.env['sf.agv.scheduling'].on_site_state_change(agv_site.id, agv_site.state)
else:
_logger.error("更新失败:接驳站站点错误!%s" % agv_site_name)
raise UserError("更新失败:接驳站站点错误!")
class AgvTaskRoute(models.Model):
@@ -71,6 +98,17 @@ class AgvTaskRoute(models.Model):
if self.end_site_id == self.start_site_id:
raise UserError("您选择的终点接驳站与起点接驳站重复,请重新选择")
workcenter_id = fields.Many2one(string='所属区域', comodel_name='mrp.workcenter', domain=[('is_agv_scheduling', '=', True)],
compute="_compute_region")
@api.depends('end_site_id')
def _compute_region(self):
for record in self:
if record.end_site_id:
record.workcenter_id = record.end_site_id.workcenter_id
else:
record.workcenter_id = None
class Center_controlInterfaceLog(models.Model):
_name = 'center_control.interface.log'

View File

@@ -1,12 +1,14 @@
# -*- coding: utf-8 -*-
import base64
import datetime
import logging
import json
import os
import re
import requests
from itertools import groupby
from odoo import api, fields, models, _
from collections import defaultdict, namedtuple
from odoo import api, fields, models, SUPERUSER_ID, _
from odoo.exceptions import UserError, ValidationError
from odoo.addons.sf_base.commons.common import Common
from odoo.tools import float_compare, float_round, float_is_zero, format_datetime
@@ -77,9 +79,10 @@ class MrpProduction(models.Model):
('pending_cam', '待加工'),
('progress', '加工中'),
('rework', '返工'),
('scrap', '报废'),
('to_close', 'To Close'),
('done', 'Done'),
('cancel', '报废')], string='State',
('cancel', '已取消')], string='State',
compute='_compute_state', copy=False, index=True, readonly=True,
store=True, tracking=True,
help=" * Draft: The MO is not confirmed yet.\n"
@@ -120,8 +123,39 @@ class MrpProduction(models.Model):
# 上传零件图纸
part_drawing = fields.Binary('零件图纸')
manual_quotation = fields.Boolean('人工编程', default=False, readonly=True)
@api.depends('product_id.manual_quotation')
def _compute_manual_quotation(self):
for item in self:
item.manual_quotation = item.product_id.manual_quotation
manual_quotation = fields.Boolean('人工编程', default=False, compute=_compute_manual_quotation, store=True)
is_scrap = fields.Boolean('是否报废', default=False)
is_remanufacture = fields.Boolean('是否重新制造', default=False)
remanufacture_count = fields.Integer("重新制造订单数量", compute='_compute_remanufacture_production_ids')
remanufacture_production_id = fields.Many2one('mrp.production', string='')
@api.depends('remanufacture_production_id')
def _compute_remanufacture_production_ids(self):
for production in self:
if production.remanufacture_production_id:
remanufacture_production = self.env['mrp.production'].search(
[('id', '=', production.remanufacture_production_id.id)])
if remanufacture_production:
production.remanufacture_count = len(remanufacture_production)
else:
production.remanufacture_count = 0
def action_view_remanufacture_productions(self):
self.ensure_one()
mrp_production = self.env['mrp.production'].search(
[('id', '=', self.remanufacture_production_id.id)])
action = {
'res_model': 'mrp.production',
'type': 'ir.actions.act_window',
'view_mode': 'form',
'res_id': mrp_production.id,
}
return action
@api.depends(
'move_raw_ids.state', 'move_raw_ids.quantity_done', 'move_finished_ids.state', 'tool_state',
@@ -166,7 +200,7 @@ class MrpProduction(models.Model):
production.state = 'pending_cam'
if production.state == 'progress':
if all(wo_state not in ('progress', 'done', 'rework') for wo_state in
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:
@@ -184,6 +218,11 @@ class MrpProduction(models.Model):
for wo in
production.workorder_ids):
production.state = 'rework'
if any(wo.test_results == '报废' and wo.state == 'done' for wo in production.workorder_ids):
production.state = 'scrap'
if any(dr.test_results == '报废' and dr.handle_result == '已处理' for dr in
production.detection_result_ids):
production.state = 'cancel'
# 如果制造订单的功能刀具为【无效刀】则制造订单状态改为返工
if production.tool_state == '2':
production.state = 'rework'
@@ -279,8 +318,10 @@ class MrpProduction(models.Model):
# cnc程序获取
def fetchCNC(self, production_names):
cnc = self.env['mrp.production'].search([('id', '=', self.id)])
quick_order = self.env['quick.easy.order'].search(
[('name', '=', cnc.product_id.default_code.rsplit('-', 1)[0])])
quick_order = False
if cnc.product_id.default_code:
quick_order = self.env['quick.easy.order'].search(
[('name', '=', cnc.product_id.default_code.rsplit('-', 1)[0])])
programme_way = False
if cnc.manual_quotation is True:
programme_way = 'manual operation'
@@ -437,44 +478,45 @@ class MrpProduction(models.Model):
# self.env['mrp.workorder'].json_workorder_str(k, production, route))
# 表面工艺工序
# 获取表面工艺id
if production.product_id.model_process_parameters_ids:
logging.info('model_process_parameters_ids:%s' % production.product_id.model_process_parameters_ids)
surface_technics_arr = []
# 工序id
route_workcenter_arr = []
for item in production.product_id.product_model_type_id.surface_technics_routing_tmpl_ids:
surface_technics_arr.append(item.route_workcenter_id.surface_technics_id.id)
route_workcenter_arr.append(item.route_workcenter_id.id)
if surface_technics_arr:
production_process_category = self.env['sf.production.process.category'].search(
[('production_process_ids.id', 'in', surface_technics_arr)],
order='sequence asc'
)
# 用filter刷选表面工艺id'是否存在工艺类别对象里
if production_process_category:
for p in production_process_category:
logging.info('production_process_category:%s' % p.name)
production_process = p.production_process_ids.filtered(
lambda pp: pp.id in surface_technics_arr)
if production_process:
process_parameter = production.product_id.model_process_parameters_ids.filtered(
lambda pm: pm.process_id.id == production_process.id)
if process_parameter:
# 产品为表面工艺服务的供应商
product_production_process = self.env['product.template'].search(
[('server_product_process_parameters_id', '=', process_parameter.id)])
if product_production_process:
route_production_process = self.env[
'mrp.routing.workcenter'].search(
[('surface_technics_id', '=', production_process.id),
('id', 'in', route_workcenter_arr)])
if route_production_process:
workorders_values.append(
self.env[
'mrp.workorder']._json_workorder_surface_process_str(
production, route_production_process,
process_parameter,
product_production_process.seller_ids[0].partner_id.id))
# 工序id
surface_technics_arr = []
route_workcenter_arr = []
for item in production.product_id.product_model_type_id.surface_technics_routing_tmpl_ids:
if item.route_workcenter_id.surface_technics_id.id:
for process_param in production.product_id.model_process_parameters_ids:
logging.info('process_param:%s%s' % (process_param.id, process_param.name))
if item.route_workcenter_id.surface_technics_id == process_param.process_id:
logging.info(
'surface_technics_id:%s%s' % (item.route_workcenter_id.surface_technics_id.id,
item.route_workcenter_id.surface_technics_id.name))
surface_technics_arr.append(item.route_workcenter_id.surface_technics_id.id)
route_workcenter_arr.append(item.route_workcenter_id.id)
if surface_technics_arr:
production_process = self.env['sf.production.process'].search(
[('id', 'in', surface_technics_arr)],
order='sequence asc'
)
for p in production_process:
logging.info('production_process:%s' % p.name)
# if production_process:
process_parameter = production.product_id.model_process_parameters_ids.filtered(
lambda pm: pm.process_id.id == p.id)
if process_parameter:
# 产品为表面工艺服务的供应商
product_production_process = self.env['product.template'].search(
[('server_product_process_parameters_id', '=', process_parameter.id)])
if product_production_process:
route_production_process = self.env[
'mrp.routing.workcenter'].search(
[('surface_technics_id', '=', p.id),
('id', 'in', route_workcenter_arr)])
if route_production_process:
workorders_values.append(
self.env[
'mrp.workorder']._json_workorder_surface_process_str(
production, route_production_process,
process_parameter,
product_production_process.seller_ids[0].partner_id.id))
elif production.product_id.categ_id.type == '坯料':
embryo_routing_workcenter = self.env['sf.embryo.model.type.routing.sort'].search(
[('embryo_model_type_id', '=', production.product_id.embryo_model_type_id.id)],
@@ -624,7 +666,7 @@ class MrpProduction(models.Model):
# 表面工艺工序
# 模型类型的表面工艺工序模版
surface_tmpl_ids = model_type_id.surface_technics_routing_tmpl_ids
# 产品选择的表面工艺
# 产品选择的表面工艺参数
model_process_parameters_ids = rec.product_id.model_process_parameters_ids
process_dict = {}
if model_process_parameters_ids:
@@ -633,7 +675,7 @@ class MrpProduction(models.Model):
for surface_tmpl_id in surface_tmpl_ids:
if process_id == surface_tmpl_id.route_workcenter_id.surface_technics_id:
surface_tmpl_name = surface_tmpl_id.route_workcenter_id.name
process_dict.update({int(process_id.category_id.code): '%s-%s' % (
process_dict.update({int(process_id.sequence): '%s-%s' % (
surface_tmpl_name, process_parameters_id.name)})
process_list = sorted(process_dict.keys())
for process_num in process_list:
@@ -650,14 +692,16 @@ class MrpProduction(models.Model):
raise ValidationError('该产品【加工面板】为空!')
else:
raise ValidationError('该产品没有选择【模版类型】!')
logging.info('sequence_list: %s' % sequence_list)
for work in rec.workorder_ids:
if sequence_list.get(work.name):
work.sequence = sequence_list[work.name]
work_name = work.name
logging.info(work_name)
if sequence_list.get(work_name):
work.sequence = sequence_list[work_name]
elif sequence_list.get(work.processing_panel):
processing_panel = sequence_list.get(work.processing_panel)
if processing_panel.get(work.name):
work.sequence = processing_panel[work.name]
if processing_panel.get(work_name):
work.sequence = processing_panel[work_name]
else:
raise ValidationError('工序【%s】在产品选择的模版类型中不存在!' % work.name)
else:
@@ -683,8 +727,9 @@ class MrpProduction(models.Model):
sequence_max += 1
panel_sequence_list.update({tmpl_id.route_workcenter_id.name: sequence_max})
for work_id in work_ids:
if panel_sequence_list.get(work_id.name):
work_id.sequence = panel_sequence_list[work_id.name]
work_name = work_id.name
if panel_sequence_list.get(work_name):
work_id.sequence = panel_sequence_list[work_name]
# 创建工单并进行排序
def _create_workorder(self, item):
@@ -692,6 +737,53 @@ class MrpProduction(models.Model):
self._reset_work_order_sequence()
return True
def process_range_time(self):
for production in self:
works = production.workorder_ids
pro_plan = self.env['sf.production.plan'].search([('production_id', '=', production.id)], limit=1)
if not pro_plan:
continue
type_map = {'装夹预调': False, 'CNC加工': False, '解除装夹': False}
# 最后一次加工结束时间
last_time = pro_plan.date_planned_start
# 预置时间
for work in works:
count = type_map.get(work.routing_type)
date_planned_end = None
date_planned_start = None
duration_expected = datetime.timedelta(minutes=work.duration_expected)
reserve_time = datetime.timedelta(minutes=work.reserved_duration)
if not count:
# 第一轮加工
if work.routing_type == '装夹预调':
date_planned_end = last_time - reserve_time
date_planned_start = date_planned_end - duration_expected
elif work.routing_type == 'CNC加工':
date_planned_start = last_time
date_planned_end = last_time + duration_expected
last_time = date_planned_end
else:
date_planned_start = last_time + reserve_time
date_planned_end = date_planned_start + duration_expected
last_time = date_planned_end
type_map.update({work.routing_type: True})
else:
date_planned_start = last_time + reserve_time
date_planned_end = date_planned_start + duration_expected
last_time = date_planned_end
work.leave_id.write({
'date_from': date_planned_start,
'date_to': date_planned_end,
})
# work.write({'date_planned_start': date_planned_start, 'date_planned_finished': date_planned_end})
work.date_planned_start = date_planned_start
work.date_planned_finished = date_planned_end
routing_workcenter = self.env['mrp.routing.workcenter'].sudo().search(
[('name', '=', work.routing_type)])
work.write({'date_planned_start': date_planned_start, 'date_planned_finished': date_planned_end,
'duration_expected': routing_workcenter.time_cycle})
# 修改标记已完成方法
def button_mark_done1(self):
if not self.workorder_ids.filtered(lambda w: w.routing_type not in ['表面工艺']):
@@ -714,6 +806,10 @@ class MrpProduction(models.Model):
backorders = backorders - productions_to_backorder
productions_not_to_backorder._post_inventory(cancel_backorder=True)
# if self.workorder_ids.filtered(lambda w: w.routing_type in ['表面工艺']):
# move_finish = self.env['stock.move'].search([('created_production_id', '=', self.id)])
# if move_finish:
# move_finish._action_assign()
productions_to_backorder._post_inventory(cancel_backorder=True)
# if completed products make other confirmed/partially_available moves available, assign them
@@ -788,6 +884,23 @@ class MrpProduction(models.Model):
})
return action
# 报废
def button_scrap_new(self):
cloud_programming = self._cron_get_programming_state()
return {
'name': _('报废'),
'type': 'ir.actions.act_window',
'view_mode': 'form',
'res_model': 'sf.production.wizard',
'target': 'new',
'context': {
'default_production_id': self.id,
'default_reprogramming_num': cloud_programming['reprogramming_num'],
'default_programming_states': cloud_programming['programming_state'],
'default_is_reprogramming': True if cloud_programming['programming_state'] in ['已下发'] else False
}
}
# 返工
def button_rework(self):
cloud_programming = None
@@ -905,7 +1018,6 @@ class MrpProduction(models.Model):
# production.write(
# {'state': 'progress', 'programming_state': '已编程', 'is_rework': False})
# logging.info('返工含有已编程未下发的程序更新完成:%s' % production.name)
logging.info('更新程序完成:%s' % production.name)
else:
raise UserError(result['message'])
@@ -913,116 +1025,108 @@ class MrpProduction(models.Model):
logging.info('get_new_program error:%s' % e)
raise UserError("从云平台获取最新程序失败,请联系管理员")
def recreateManufacturing(self):
def recreateManufacturing(self, item):
"""
重新生成制造订单
"""
if self.is_scrap is True:
sale_order = self.env['sale.order'].sudo().search([('name', '=', productions.origin)])
values = self.env['mrp.production'].create_production1_values(self.production_id)
productions = self.env['mrp.production'].with_user(SUPERUSER_ID).sudo().with_company(
self.production_id.company_id).create(
values)
# self.env['stock.move'].sudo().create(productions._get_moves_raw_values())
self.env['stock.move'].sudo().create(productions._get_moves_finished_values())
productions._create_workorder()
productions.filtered(lambda p: (not p.orderpoint_id and p.move_raw_ids) or \
(
p.move_dest_ids.procure_method != 'make_to_order' and
not p.move_raw_ids and not p.workorder_ids)).action_confirm()
for production_item in productions:
process_parameter_workorder = self.env['mrp.workorder'].search(
[('surface_technics_parameters_id', '!=', False), ('production_id', '=', production_item.id),
('is_subcontract', '=', True)])
if process_parameter_workorder:
is_pick = False
consecutive_workorders = []
m = 0
sorted_workorders = sorted(process_parameter_workorder, key=lambda w: w.id)
for i in range(len(sorted_workorders) - 1):
if m == 0:
is_pick = False
if sorted_workorders[i].supplier_id.id == sorted_workorders[i + 1].supplier_id.id and \
sorted_workorders[i].is_subcontract == sorted_workorders[i + 1].is_subcontract and \
sorted_workorders[i].id == sorted_workorders[i + 1].id - 1:
if sorted_workorders[i] not in consecutive_workorders:
consecutive_workorders.append(sorted_workorders[i])
consecutive_workorders.append(sorted_workorders[i + 1])
m += 1
continue
else:
if m == len(consecutive_workorders) - 1 and m != 0:
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders,
production_item)
if sorted_workorders[i] in consecutive_workorders:
is_pick = True
consecutive_workorders = []
m = 0
# 当前面的连续工序生成对应的外协出入库单再生成当前工序的外协出入库单
if is_pick is False:
self.env['stock.picking'].create_outcontract_picking(sorted_workorders[i],
production_item)
if m == len(consecutive_workorders) - 1 and m != 0:
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders,
production_item)
if sorted_workorders[i] in consecutive_workorders:
is_pick = True
consecutive_workorders = []
m = 0
if m == len(consecutive_workorders) - 1 and m != 0:
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production_item)
if is_pick is False and m == 0:
if len(sorted_workorders) == 1:
self.env['stock.picking'].create_outcontract_picking(sorted_workorders, production_item)
else:
self.env['stock.picking'].create_outcontract_picking(sorted_workorders[i], production_item)
for production in productions:
origin_production = production.move_dest_ids and production.move_dest_ids[
0].raw_material_production_id or False
orderpoint = production.orderpoint_id
if orderpoint and orderpoint.create_uid.id == SUPERUSER_ID and orderpoint.trigger == 'manual':
production.message_post(
body=_('This production order has been created from Replenishment Report.'),
message_type='comment',
subtype_xmlid='mail.mt_note')
elif orderpoint:
production.message_post_with_view(
'mail.message_origin_link',
values={'self': production, 'origin': orderpoint},
subtype_id=self.env.ref('mail.mt_note').id)
elif origin_production:
production.message_post_with_view(
'mail.message_origin_link',
values={'self': production, 'origin': origin_production},
subtype_id=self.env.ref('mail.mt_note').id)
'''
创建生产计划
'''
# 工单耗时
workorder_duration = 0
for workorder in productions.workorder_ids:
workorder_duration += workorder.duration_expected
if sale_order:
sale_order.mrp_production_ids |= productions
# sale_order.write({'schedule_status': 'to schedule'})
self.env['sf.production.plan'].sudo().with_company(self.production_id.company_id).create({
'name': productions.name,
'order_deadline': sale_order.deadline_of_delivery,
'production_id': productions.id,
'date_planned_start': productions.date_planned_start,
'origin': productions.origin,
'product_qty': productions.product_qty,
'product_id': productions.product_id.id,
'state': 'draft',
})
procurement_requests = []
sale_order = self.env['sale.order'].sudo().search([('name', '=', self.origin)])
values = self.env['mrp.production'].create_production1_values(self)
# productions = self.env['mrp.production'].with_user(SUPERUSER_ID).sudo().with_company(
# self.company_id).create(
# values)
# 查询出库移动记录
out_picking = self.env['stock.picking'].search(
[('origin', '=', sale_order.name), ('name', 'ilike', 'WH/OUT/')])
move = out_picking.move_ids.filtered(lambda pd: pd.product_id == self.product_id)
move_values = {'product_description_variants': '',
'date_planned': fields.Datetime.now(),
'date_deadline': fields.Datetime.now(),
'move_dest_ids': move,
'group_id': move.group_id,
'route_ids': [],
'warehouse_id': self.warehouse_id,
'priority': 0,
'orderpoint_id': False,
'product_packaging_id': False}
procurement_requests.append(self.env['procurement.group'].Procurement(
move.product_id, 1.0, move.product_uom,
move.location_id, move.rule_id and move.rule_id.name or "/",
sale_order.name, move.company_id, move_values))
self.env['procurement.group'].run(procurement_requests,
raise_user_error=not self.env.context.get('from_orderpoint'))
productions = self.env['mrp.production'].sudo().search(
[('origin', '=', self.origin)], order='id desc', limit=1)
move = self.env['stock.move'].search([('origin', '=', productions.name)], order='id desc')
for mo in move:
if mo.procure_method == 'make_to_order' and mo.name != productions.name:
if mo.name == '/':
domain = [('barcode', '=', 'WH-PC'), ('sequence_code', '=', 'PC')]
elif mo.name == '':
domain = [('barcode', '=', 'WH-INTERNAL'), ('sequence_code', '=', 'INT')]
picking_type = self.env['stock.picking.type'].search(domain)
mo.write({'picking_type_id': picking_type.id})
mo._assign_picking()
else:
if mo.reference != productions.name:
mo.reference = productions.name
if mo.production_id:
if mo.production_id != productions:
mo.production_id = False
mo_move = self.env['stock.move'].search(
[('origin', '=', sale_order.name), ('reference', 'ilike', 'WH/MO/')])
if mo_move:
sfp_move = self.env['stock.move'].search(
[('origin', '=', sale_order.name), ('reference', 'ilike', 'WH/SFP/')], limit=1)
mo_move.write({'reference': sfp_move.reference, 'partner_id': sfp_move.partner_id.id,
'picking_id': sfp_move.picking_id.id, 'picking_type_id': sfp_move.picking_type_id.id,
'production_id': False})
productions.write({'programming_no': self.programming_no, 'is_remanufacture': True})
# productions.procurement_group_id.mrp_production_ids.move_dest_ids.write(
# {'group_id': self.env['procurement.group'].search([('name', '=', sale_order.name)])})
stock_picking_remanufacture = self.env['stock.picking'].search([('origin', '=', productions.name)])
for pick in stock_picking_remanufacture:
if pick.name.startswith('WH/PC/') or pick.name.startswith('WH/INT/'):
if pick.move_ids:
product_type_id = pick.move_ids[0].product_id.categ_id
if product_type_id.name == '坯料':
location_id = self.env['stock.location'].search([('name', '=', '坯料存货区')])
if not location_id:
logging.info(f'没有搜索到【坯料存货区】: {location_id}')
break
if pick.picking_type_id.name == '内部调拨':
if pick.location_dest_id.product_type != product_type_id:
pick.location_dest_id = location_id.id
elif pick.picking_type_id.name == '生产发料':
if pick.location_id.product_type != product_type_id:
pick.location_id = location_id.id
scarp_process_parameter_workorder = self.env['mrp.workorder'].search(
[('surface_technics_parameters_id', '!=', False), ('production_id', '=', self.id),
('is_subcontract', '=', True)])
if scarp_process_parameter_workorder:
production_programming = self.env['mrp.production'].search(
[('programming_no', '=', self.programming_no), ('id', '!=', productions.id)], order='name asc')
production_list = [production.name for production in production_programming]
purchase_orders = self.env['purchase.order'].search([('origin', 'ilike', ','.join(production_list))])
for purchase_item in purchase_orders.order_line:
for process_item in scarp_process_parameter_workorder:
if purchase_item.product_id.categ_type == '表面工艺':
if purchase_item.product_id.server_product_process_parameters_id == process_item.surface_technics_parameters_id:
if purchase_orders.origin.find(productions.name) == -1:
purchase_orders.origin += ',' + productions.name
if item['is_reprogramming'] is False:
productions._create_workorder(item)
productions.programming_state = '已编程'
else:
productions.programming_state = '编程中'
return productions
# 在之前的销售单上重新生成制造订单
def create_production1_values(self, production, sale_order):
def create_production1_values(self, production):
production_values_str = {'origin': production.origin,
'product_id': production.product_id.id,
'programming_state': '已编程',
'product_description_variants': production.product_description_variants,
'product_qty': production.product_qty,
'product_uom_id': production.product_uom_id.id,
@@ -1032,7 +1136,8 @@ class MrpProduction(models.Model):
'date_deadline': production.date_deadline,
'date_planned_start': production.date_planned_start,
'date_planned_finished': production.date_planned_finished,
'procurement_group_id': sale_order.id,
# 'procurement_group_id': self.env["procurement.group"].create(
# {'name': production.name}).id,
'propagate_cancel': production.propagate_cancel,
'orderpoint_id': production.orderpoint_id.id,
'picking_type_id': production.picking_type_id.id,

View File

@@ -21,7 +21,7 @@ class ResMrpRoutingWorkcenter(models.Model):
workcenter_ids = fields.Many2many('mrp.workcenter', 'rel_workcenter_route', required=True)
bom_id = fields.Many2one('mrp.bom', required=False)
surface_technics_id = fields.Many2one('sf.production.process', string="表面工艺")
reserved_duration = fields.Float('预留时长', default=30, tracking=True)
def get_no(self):
international_standards = self.search(
[('code', '!=', ''), ('active', 'in', [True, False])],

View File

@@ -1,7 +1,10 @@
import datetime
from datetime import timedelta, time
from collections import defaultdict
from odoo import fields, models
from odoo import fields, models, api
from odoo.addons.resource.models.resource import Intervals
from odoo.exceptions import UserError, ValidationError
import math
class ResWorkcenter(models.Model):
@@ -41,13 +44,16 @@ class ResWorkcenter(models.Model):
oee_target = fields.Float(
string='OEE Target', help="Overall Effective Efficiency Target in percentage", default=90, tracking=True)
oee = fields.Float(compute='_compute_oee', help='Overall Equipment Effectiveness, based on the last month',
store=True)
time_start = fields.Float('Setup Time', tracking=True)
time_stop = fields.Float('Cleanup Time', tracking=True)
costs_hour = fields.Float(string='Cost per hour', help='Hourly processing cost.', default=0.0, tracking=True)
equipment_status = fields.Selection(
[("正常", "正常"), ("故障停机", "故障停机"), ("计划维保", "计划维保"), ("空闲", "空闲"), ("封存(报废)", "封存(报废)")],
[("正常", "正常"), ("故障停机", "故障停机"), ("计划维保", "计划维保"), ("空闲", "空闲"),
("封存(报废)", "封存(报废)")],
string="设备状态", related='equipment_id.state')
# @api.depends('equipment_id')
@@ -124,6 +130,108 @@ class ResWorkcenter(models.Model):
res[wc_id] = [(datetime.fromtimestamp(s), datetime.fromtimestamp(e)) for s, e, _ in final_intervals_wc]
return res
# AGV是否可配送
is_agv_scheduling = fields.Boolean(string="AGV所属区域", tracking=True)
# 生产线优化
available_machine_number = fields.Integer(string="可用机台数量")
single_machine_capacity = fields.Float(string="单台小时产能")
production_line_hour_capacity = fields.Float(string="生产线小时产能", readonly=True,
compute='_compute_production_line_hour_capacity')
effective_working_hours_day = fields.Float(string="日有效工作时长", default=0, readonly=True,
compute='_compute_effective_working_hours_day')
default_capacity = fields.Float(
string='生产线日产能', compute='_compute_production_line_day_capacity', readonly=True)
# 计算生产线日产能
@api.depends('production_line_hour_capacity', 'effective_working_hours_day')
def _compute_production_line_day_capacity(self):
for record in self:
record.default_capacity = round(
record.production_line_hour_capacity * record.effective_working_hours_day, 2)
# 计算日有效工作时长
@api.depends('resource_calendar_id', 'resource_calendar_id.attendance_ids',
'resource_calendar_id.attendance_ids.hour_to', 'resource_calendar_id.attendance_ids.hour_from')
def _compute_effective_working_hours_day(self):
for record in self:
attendance_ids = [p for p in record.resource_calendar_id.attendance_ids if
p.dayofweek == self.get_current_day_of_week(datetime.datetime.now())]
if attendance_ids:
for attendance_id in attendance_ids:
if attendance_id.hour_from and attendance_id.hour_to:
record.effective_working_hours_day += attendance_id.hour_to - attendance_id.hour_from
else:
record.effective_working_hours_day = 0
# 获取传入时间是星期几
def get_current_day_of_week(self, datetime):
day_num = datetime.weekday()
return str(day_num)
# 计算生产线小时产能
@api.depends('single_machine_capacity', 'available_machine_number')
def _compute_production_line_hour_capacity(self):
for record in self:
record.production_line_hour_capacity = round(
record.single_machine_capacity * record.available_machine_number, 2)
# 判断计划开始时间是否在配置的工作中心的工作日历内
def deal_with_workcenter_calendar(self, start_date):
start_date = start_date + timedelta(hours=8) # 转换为北京时间
for record in self:
attendance_ids = [p for p in record.resource_calendar_id.attendance_ids if
p.dayofweek == record.get_current_day_of_week(start_date) and self.is_between_times(
p.hour_from, p.hour_to, start_date)]
return False if not attendance_ids else True
# 判断传入时间是否在配置的工作中心的工作日历内
def is_between_times(self, hour_from, hour_to, start_date):
integer_part, decimal_part = self.get_integer_and_decimal_parts(hour_from)
start_time = time(integer_part, decimal_part)
integer_part, decimal_part = self.get_integer_and_decimal_parts(hour_to)
end_time = time(integer_part, decimal_part)
return start_time <= start_date.time() <= end_time
# 获取整数部分和小数部分
def get_integer_and_decimal_parts(self, value):
integer_part = int(value)
decimal_part = value - integer_part
if decimal_part > 0:
decimal_part = round(decimal_part, 2) * 60
return int(integer_part), math.ceil(decimal_part)
# 处理排程是否超过日产能
def deal_available_default_capacity(self, date_planned):
date_planned_start = date_planned.strftime('%Y-%m-%d')
date_planned_end = date_planned + timedelta(days=1)
date_planned_end = date_planned_end.strftime('%Y-%m-%d')
plan_ids = self.env['sf.production.plan'].sudo().search([('date_planned_start', '>=', date_planned_start),
('date_planned_start', '<',
date_planned_end),
('state', 'not in', ['draft', 'cancel'])])
if plan_ids:
sum_qty = sum([p.product_qty for p in plan_ids])
if sum_qty >= self.default_capacity:
return False
return True
# 处理排程是否超过小时产能
def deal_available_single_machine_capacity(self, date_planned):
date_planned_start = date_planned.strftime('%Y-%m-%d %H:00:00')
date_planned_end = date_planned + timedelta(hours=1)
date_planned_end = date_planned_end.strftime('%Y-%m-%d %H:00:00')
plan_ids = self.env['sf.production.plan'].sudo().search([('date_planned_start', '>=', date_planned_start),
('date_planned_start', '<',
date_planned_end),
('state', 'not in', ['draft', 'cancel'])])
if plan_ids:
sum_qty = sum([p.product_qty for p in plan_ids])
if sum_qty >= self.production_line_hour_capacity:
return False
return True
class ResWorkcenterProductivity(models.Model):
_inherit = 'mrp.workcenter.productivity'

View File

@@ -58,9 +58,15 @@ class ResMrpWorkOrder(models.Model):
('cancel', '取消')], string='Status',
compute='_compute_state', store=True,
default='pending', copy=False, readonly=True, recursive=True, index=True, tracking=True)
# state = fields.Selection(selection_add=[('to be detected', "待检测"), ('rework', '返工')], tracking=True)
manual_quotation = fields.Boolean('人工编程', default=False, readonly=True)
@api.depends('production_id.manual_quotation')
def _compute_manual_quotation(self):
for item in self:
item.manual_quotation = item.production_id.manual_quotation
manual_quotation = fields.Boolean('人工编程', default=False, compute=_compute_manual_quotation, store=True)
def _compute_working_users(self):
super()._compute_working_users()
@@ -131,13 +137,34 @@ class ResMrpWorkOrder(models.Model):
is_subcontract = fields.Boolean(string='是否外协')
surface_technics_parameters_id = fields.Many2one('sf.production.process.parameter', string="表面工艺可选参数")
picking_ids = fields.Many2many('stock.picking', string='外协出入库单')
# purchase_id = fields.Many2one('purchase.order', string='外协采购单')
surface_technics_picking_count = fields.Integer("外协出入库", compute='_compute_surface_technics_picking_ids')
surface_technics_purchase_count = fields.Integer("外协采购", compute='_compute_surface_technics_purchase_ids')
# 是否绑定托盘
is_trayed = fields.Boolean(string='是否绑定托盘', default=False)
tag_type = fields.Selection([("重新加工", "重新加工")], string="标签", tracking=True)
@api.depends('name', 'production_id.name')
def _compute_surface_technics_picking_ids(self):
for order in self:
picking_ids = self.env['stock.picking'].search([('id', 'in', order.picking_ids.ids)])
order.surface_technics_picking_count = len(picking_ids)
for workorder in self:
if workorder.routing_type == '表面工艺':
domain = [('origin', '=', workorder.production_id.name)]
previous_workorder = self.env['mrp.workorder'].search(
[('sequence', '=', workorder.sequence - 1), ('routing_type', '=', '表面工艺'),
('production_id', '=', workorder.production_id.id)])
if previous_workorder:
process_product = self.env['product.template']._get_process_parameters_product(
previous_workorder.surface_technics_parameters_id)
domain += [('partner_id', '=', process_product.partner_id.id)]
else:
domain += [('surface_technics_parameters_id', '=', workorder.surface_technics_parameters_id.id)]
picking_ids = self.env['stock.picking'].search(domain, order='id asc')
workorder.surface_technics_picking_count = len(picking_ids)
workorder.picking_ids = picking_ids.ids
else:
workorder.surface_technics_picking_count = 0
def action_view_surface_technics_picking(self):
self.ensure_one()
@@ -153,6 +180,38 @@ class ResMrpWorkOrder(models.Model):
action['context'] = dict(self._context, default_origin=self.name)
return action
@api.depends('state', 'production_id.name')
def _compute_surface_technics_purchase_ids(self):
for order in self:
if order.routing_type == '表面工艺':
production_programming = self.env['mrp.production'].search(
[('programming_no', '=', order.production_id.programming_no)], order='name asc')
production_no_remanufacture = production_programming.filtered(lambda a: a.is_remanufacture is False)
production_list = [production.name for production in production_programming]
purchase = self.env['purchase.order'].search([('origin', '=', ','.join(production_list))])
for line in purchase.order_line:
if line.product_id.server_product_process_parameters_id == order.surface_technics_parameters_id and line.product_qty == len(
production_no_remanufacture):
order.surface_technics_purchase_count = len(purchase)
else:
order.surface_technics_purchase_count = 0
def action_view_surface_technics_purchase(self):
self.ensure_one()
production_programming = self.env['mrp.production'].search(
[('programming_no', '=', self.production_id.programming_no)], order='name asc')
production_list = [production.name for production in production_programming]
purchase_orders = self.env['purchase.order'].search([('origin', '=', ','.join(production_list))])
result = {
"type": "ir.actions.act_window",
"res_model": "purchase.order",
"res_id": purchase_orders.id,
# "domain": [['id', 'in', self.purchase_id]],
"name": _("Purchase Orders"),
'view_mode': 'form',
}
return result
supplier_id = fields.Many2one('res.partner', string='外协供应商')
equipment_id = fields.Many2one('maintenance.equipment', string='加工设备', tracking=True)
# 保存名称
@@ -165,7 +224,7 @@ class ResMrpWorkOrder(models.Model):
material_width = fields.Float(string='')
material_height = fields.Float(string='')
# 零件图号
part_number = fields.Char(string='零件图号')
part_number = fields.Char(related='production_id.part_number', string='零件图号')
# 工序状态
process_state = fields.Selection([
('待装夹', '待装夹'),
@@ -181,6 +240,7 @@ class ResMrpWorkOrder(models.Model):
tool_state = fields.Selection([('0', '正常'), ('1', '缺刀'), ('2', '无效刀')], string='功能刀具状态', default='0',
store=True, compute='_compute_tool_state')
tool_state_remark = fields.Text(string='功能刀具状态备注(缺刀)', compute='_compute_tool_state_remark', store=True)
reserved_duration = fields.Float('预留时长', default=30, tracking=True)
@api.depends('cnc_ids.tool_state')
def _compute_tool_state_remark(self):
@@ -318,10 +378,10 @@ class ResMrpWorkOrder(models.Model):
vals['leave_id'] = leave.id
self.write(vals)
@api.onchange('rfid_code')
def _onchange(self):
if self.rfid_code and self.state == 'progress':
self.workpiece_delivery_ids[0].write({'rfid_code': self.rfid_code})
# @api.onchange('rfid_code')
# def _onchange(self):
# if self.rfid_code and self.state == 'progress':
# self.workpiece_delivery_ids[0].write({'rfid_code': self.rfid_code})
def get_plan_workorder(self, production_line):
tomorrow = (date.today() + timedelta(days=+1)).strftime("%Y-%m-%d")
@@ -356,12 +416,10 @@ class ResMrpWorkOrder(models.Model):
# 获取三次元检测点数据
def get_three_check_datas(self):
factory_nick_name = 'XT'
ftp_resconfig = self.env['res.config.settings'].get_values()
ftp = FtpController(str(ftp_resconfig['ftp_host']), int(ftp_resconfig['ftp_port']),
ftp_resconfig['ftp_user'],
ftp_resconfig['ftp_password'])
# ftp.connect()
local_dir_path = '/ftp/before'
os.makedirs(local_dir_path, exist_ok=True)
@@ -370,6 +428,18 @@ class ResMrpWorkOrder(models.Model):
logging.info('local_file_path:%s' % local_file_path)
remote_path = '/home/ftp/ftp_root/ThreeTest/XT/Before/' + local_filename
logging.info('remote_path:%s' % remote_path)
is_get_detection_file = self.env['ir.config_parameter'].sudo().get_param('is_get_detection_file')
if not is_get_detection_file:
paload_data = {
"filename": local_filename
}
if not ftp_resconfig['get_check_file_path']:
raise UserError('请先配置获取检测报告地址')
url = ftp_resconfig['get_check_file_path'] + '/get/check/report'
response = requests.post(url, json=paload_data)
logging.info('response:%s' % response.json())
if response.json().get('detail'):
raise UserError(response.json().get('detail'))
if not ftp.file_exists(remote_path):
raise UserError(f"文件不存在: {remote_path}")
@@ -482,6 +552,7 @@ class ResMrpWorkOrder(models.Model):
raise UserError('PT10点未测或数据错误')
self.data_state = True
self.getcenter()
return True
@@ -535,6 +606,8 @@ class ResMrpWorkOrder(models.Model):
print("(%.2f,%.2f)" % (x, y))
self.material_center_point = ("(%.2f,%.2f,%.2f)" % (x, y, z))
self.X_deviation_angle = jdz
logging.info("坯料中心点坐标:(%.2f,%.2f)" % (x, y))
logging.info("X轴偏差度数:%.2f" % jdz)
# 将补偿值写入CNC加工工单
workorder = self.env['mrp.workorder'].browse(self.ids)
work = workorder.production_id.workorder_ids
@@ -590,29 +663,36 @@ class ResMrpWorkOrder(models.Model):
# 拼接工单对象属性值
def json_workorder_str(self, k, production, route, item):
# 计算预计时长duration_expected
if route.routing_type == '切割':
duration_expected = self.env['mrp.routing.workcenter'].sudo().search(
[('name', '=', '切割')]).time_cycle
# elif route.routing_type == '获取CNC加工程序':
routing_types = ['切割', '装夹预调', 'CNC加工', '解除装夹']
if route.routing_type in routing_types:
routing_workcenter = self.env['mrp.routing.workcenter'].sudo().search(
[('name', '=', route.routing_type)])
duration_expected = routing_workcenter.time_cycle
reserved_duration = routing_workcenter.reserved_duration
# if route.routing_type == '切割':
# duration_expected = self.env['mrp.routing.workcenter'].sudo().search(
# [('name', '=', '获取CNC加工程序')]).time_cycle
elif route.routing_type == '装夹预调':
duration_expected = self.env['mrp.routing.workcenter'].sudo().search(
[('name', '=', '装夹预调')]).time_cycle
# elif route.routing_type == '前置三元定位检测':
# [('name', '=', '切割')]).time_cycle
# # elif route.routing_type == '获取CNC加工程序':
# # duration_expected = self.env['mrp.routing.workcenter'].sudo().search(
# # [('name', '=', '获取CNC加工程序')]).time_cycle
# elif route.routing_type == '装夹预调':
# duration_expected = self.env['mrp.routing.workcenter'].sudo().search(
# [('name', '=', '前置三元定位检测')]).time_cycle
elif route.routing_type == 'CNC加工':
duration_expected = self.env['mrp.routing.workcenter'].sudo().search(
[('name', '=', 'CNC加工')]).time_cycle
# elif route.routing_type == '后置三元质量检测':
# [('name', '=', '装夹预调')]).time_cycle
# # elif route.routing_type == '前置三元定位检测':
# # duration_expected = self.env['mrp.routing.workcenter'].sudo().search(
# # [('name', '=', '前置三元定位检测')]).time_cycle
# elif route.routing_type == 'CNC加工':
# duration_expected = self.env['mrp.routing.workcenter'].sudo().search(
# [('name', '=', '后置三元质量检测')]).time_cycle
elif route.routing_type == '解除装夹':
duration_expected = self.env['mrp.routing.workcenter'].sudo().search(
[('name', '=', '解除装夹')]).time_cycle
# [('name', '=', 'CNC加工')]).time_cycle
# # elif route.routing_type == '后置三元质量检测':
# # duration_expected = self.env['mrp.routing.workcenter'].sudo().search(
# # [('name', '=', '后置三元质量检测')]).time_cycle
# elif route.routing_type == '解除装夹':
# duration_expected = self.env['mrp.routing.workcenter'].sudo().search(
# [('name', '=', '解除装夹')]).time_cycle
else:
duration_expected = 60
reserved_duration = 30
workorders_values_str = [0, '', {
'product_uom_id': production.product_uom_id.id,
'qty_producing': 0,
@@ -630,29 +710,41 @@ class ResMrpWorkOrder(models.Model):
'date_planned_finished': datetime.now() + timedelta(days=1),
'duration_expected': duration_expected,
'duration': 0,
'tag_type': '重新加工' if item is False else False,
'cnc_ids': False if route.routing_type != 'CNC加工' else self.env['sf.cnc.processing']._json_cnc_processing(
k, item),
'cmm_ids': False if route.routing_type != 'CNC加工' else self.env['sf.cmm.program']._json_cmm_program(k,
item),
'workpiece_delivery_ids': False if not route.routing_type == '装夹预调' else self._json_workpiece_delivery_list(
production)
# 'workpiece_delivery_ids': False if not route.routing_type == '装夹预调' else self._json_workpiece_delivery_list(
# production)
'reserved_duration': reserved_duration,
}]
return workorders_values_str
def _json_workpiece_delivery_list(self, production):
up_route = self.env['sf.agv.task.route'].search([('route_type', '=', '上产线')], limit=1, order='id asc')
down_route = self.env['sf.agv.task.route'].search([('route_type', '=', '下产线')], limit=1, order='id asc')
def _json_workpiece_delivery_list(self):
# 修改在装夹工单完成后,生成上产线的工件配送单
# up_route = self.env['sf.agv.task.route'].search([('route_type', '=', '上产线')], limit=1, order='id asc')
# down_route = self.env['sf.agv.task.route'].search([('route_type', '=', '下产线')], limit=1, order='id asc')
return [
[0, '',
{'production_id': production.id, 'production_line_id': production.production_line_id.id, 'type': '上产线',
'route_id': up_route.id,
'feeder_station_start_id': up_route.start_site_id.id,
'feeder_station_destination_id': up_route.end_site_id.id}],
[0, '',
{'production_id': production.id, 'production_line_id': production.production_line_id.id, 'type': '下产线',
'route_id': down_route.id,
'feeder_station_start_id': down_route.start_site_id.id,
'feeder_station_destination_id': down_route.end_site_id.id}]]
{
'production_id': self.production_id.id,
'production_line_id': self.production_id.production_line_id.id,
'type': '上产线',
'is_cnc_program_down': True,
'rfid_code': self.rfid_code
# 'route_id': up_route.id,
# 'feeder_station_start_id': agv_start_site_id,
# 'feeder_station_destination_id': up_route.end_site_id.id
}
],
# [0, '',
# {'production_id': production.id, 'production_line_id': production.production_line_id.id, 'type': '下产线',
# 'route_id': down_route.id,
# 'feeder_station_start_id': down_route.start_site_id.id,
# 'feeder_station_destination_id': down_route.end_site_id.id}]
]
# 拼接工单对象属性值(表面工艺)
def _json_workorder_surface_process_str(self, production, route, process_parameter, supplier_id):
@@ -868,7 +960,7 @@ class ResMrpWorkOrder(models.Model):
workorder.state = 'waiting'
elif workorder.routing_type == '解除装夹' and workorder.state not in ['done', 'rework', 'cancel']:
if cnc_workorder:
if not cnc_workorder_pending:
if not cnc_workorder_pending or unclamp_workorder.test_results == '报废':
workorder.state = 'waiting'
# else:
# if workorder.production_id.is_rework is True:
@@ -885,10 +977,26 @@ class ResMrpWorkOrder(models.Model):
# workorder.state = 'ready'
if workorder.routing_type == '表面工艺' and workorder.state not in ['done', 'progress']:
if unclamp_workorder:
workorder.state = 'ready'
# else:
# if workorder.state not in ['cancel', 'rework']:
# workorder.state = 'rework'
if workorder.is_subcontract is False:
workorder.state = 'ready'
else:
production_programming = self.env['mrp.production'].search(
[('programming_no', '=', self.production_id.programming_no)], order='name asc')
production_no_remanufacture = production_programming.filtered(
lambda a: a.is_remanufacture is False)
production_list = [production.name for production in production_programming]
purchase_orders = self.env['purchase.order'].search(
[('origin', 'ilike', ','.join(production_list))])
for line in purchase_orders.order_line:
if line.product_id.server_product_process_parameters_id == workorder.surface_technics_parameters_id and line.product_qty == len(
production_no_remanufacture):
if purchase_orders.state == 'purchase':
workorder.state = 'ready'
else:
workorder.state = 'waiting'
elif workorder.production_id.state == 'scrap':
if workorder.routing_type == '解除装夹' and unclamp_workorder.test_results == '报废':
workorder.state = 'waiting'
if workorder.routing_type == '装夹预调' and workorder.state in ['waiting', 'ready', 'pending']:
workorder_ids = workorder.production_id.workorder_ids
work_bo = True
@@ -923,16 +1031,20 @@ class ResMrpWorkOrder(models.Model):
# 查询工序最小的非完工、非返工的装夹预调工单
work_id = self.search(
[('production_id', '=', workorder.production_id.id),
('routing_type', '=', '装夹预调'),
('state', 'not in', ['rework', 'done', 'cancel'])],
limit=1,
order="sequence")
if workorder == work_id:
if workorder.production_id.reservation_state == 'assigned':
workorder.state = 'ready'
elif workorder.production_id.reservation_state != 'assigned':
workorder.state = 'waiting'
continue
if work_id.routing_type == '装夹预调':
if workorder == work_id:
if workorder.production_id.reservation_state == 'assigned':
workorder.state = 'ready'
elif workorder.production_id.reservation_state != 'assigned':
workorder.state = 'waiting'
continue
elif (workorder.name == '装夹预调' and
workorder.state not in ['rework', 'done', 'cancel']):
if workorder.state != 'pending':
workorder.state = 'pending'
if workorder.production_id.tool_state in ['1', '2'] and workorder.state == 'ready':
workorder.state = 'waiting'
continue
@@ -1007,8 +1119,8 @@ class ResMrpWorkOrder(models.Model):
('location_dest_id', '=', self.env['stock.location'].search(
[('barcode', 'ilike', 'VL-SPOC')]).id),
('origin', '=', self.production_id.name)])
if move_out:
move_out.write({'state': 'assigned'})
if move_out.state != 'done':
move_out.write({'state': 'assigned', 'production_id': False})
self.env['stock.move.line'].create(move_out.get_move_line(self.production_id, self))
# move_out._action_assign()
@@ -1074,23 +1186,33 @@ class ResMrpWorkOrder(models.Model):
def button_finish(self):
for record in self:
if record.routing_type == '装夹预调':
if not record.material_center_point and record.X_deviation_angle > 0:
raise UserError("请对前置三元检测定位参数进行计算定位")
if not record.rfid_code and record.is_rework is False:
raise UserError("请扫RFID码进行绑定")
if record.is_rework is False:
if not record.material_center_point:
raise UserError("坯料中心点为空,请检查")
if record.X_deviation_angle <= 0:
raise UserError("X偏差角度小于等于0请检查本次计算的X偏差角度为%s" % record.X_deviation_angle)
record.process_state = '待加工'
# record.write({'process_state': '待加工'})
record.production_id.process_state = '待加工'
# 生成工件配送单
record.workpiece_delivery_ids = record._json_workpiece_delivery_list()
if record.routing_type == 'CNC加工':
record.process_state = '待解除装夹'
# record.write({'process_state': '待加工'})
record.production_id.process_state = '待解除装夹'
self.env['sf.production.plan'].sudo().search([('name', '=', record.production_id.name)]).write({
'state': 'finished',
'actual_end_time': datetime.now()
})
record.production_id.write({'detection_result_ids': [(0, 0, {
'rework_reason': record.reason,
'detailed_reason': record.detailed_reason,
'processing_panel': record.processing_panel,
'routing_type': record.routing_type,
'handle_result': '待处理' if record.test_results == '返工' or record.is_rework is True else '',
'handle_result': '待处理' if record.test_results in ['返工',
'报废'] or record.is_rework is True else '',
'test_results': record.test_results,
'test_report': record.detection_report})],
'is_scrap': True if record.test_results == '报废' else False})
@@ -1110,28 +1232,13 @@ class ResMrpWorkOrder(models.Model):
picking_out = record.env['stock.move.line'].search(
[('picking_id', '=', record.picking_ids[0].id)])
logging.info('picking_out:%s' % picking_out.picking_id.name)
if picking_out:
order_line_ids = []
logging.info('surface_technics_parameters_id:%s' % record.surface_technics_parameters_id.name)
server_product = self.env['product.template'].search(
[('server_product_process_parameters_id', '=', record.surface_technics_parameters_id.id),
('detailed_type', '=', 'service')])
logging.info('server_product:%s' % server_product.name)
if server_product:
order_line_ids.append((0, 0, {
'product_id': server_product.product_variant_id.id,
'product_qty': 1,
'product_uom': server_product.uom_id.id
}))
self.env['purchase.order'].sudo().create({
'partner_id': server_product.seller_ids.partner_id.id,
'origin': record.production_id.name,
'state': 'draft',
'order_line': order_line_ids,
})
else:
raise UserError(
'请先在产品中配置表面工艺为%s相关的外协服务产品' % item.surface_technics_parameters_id.name)
# if picking_out:
# order_line_ids = []
# logging.info('surface_technics_parameters_id:%s' % record.surface_technics_parameters_id.name)
#
# else:
# raise UserError(
# '请先在产品中配置表面工艺为%s相关的外协服务产品' % item.surface_technics_parameters_id.name)
tem_date_planned_finished = record.date_planned_finished
tem_date_finished = record.date_finished
logging.info('routing_type:%s' % record.routing_type)
@@ -1183,6 +1290,17 @@ class ResMrpWorkOrder(models.Model):
record.production_id.button_mark_done1()
# record.production_id.state = 'done'
# 解绑托盘
def unbind_tray(self):
self.production_id.workorder_ids.write({
'rfid_code': False,
'tray_serial_number': False,
'tray_product_id': False,
'tray_brand_id': False,
'tray_type_id': False,
'tray_model_id': False,
'is_trayed': False})
# 将FTP的检测报告文件下载到临时目录
def download_reportfile_tmp(self, workorder, reportpath):
logging.info('reportpath/ftp地址:%s' % reportpath)
@@ -1222,6 +1340,73 @@ class ResMrpWorkOrder(models.Model):
else:
raise UserError("无关联制造订单或关联序列号,无法打印。请检查!")
@api.model
def get_views(self, views, options=None):
res = super().get_views(views, options)
if res['views'].get('list', {}) and self.env.context.get('search_default_workcenter_id'):
workcenter = self.env['mrp.workcenter'].browse(self.env.context.get('search_default_workcenter_id'))
tree_view = res['views']['list']
if workcenter.name == '工件拆卸中心':
arch = etree.fromstring(tree_view['arch'])
# 查找 tree 标签
tree_element = arch.xpath("//tree")[0]
tree_element.set('js_class', 'remove_focus_list_view')
# 查找或创建 header 标签
header_element = tree_element.find('header')
if header_element is None:
header_element = etree.Element('header')
tree_element.insert(0, header_element)
# 创建并添加按钮元素
button_element = etree.Element('button', {
'name': 'button_delivery',
'type': 'object',
'string': '解除装夹',
'class': 'btn-primary jikimo_button_confirm',
# 'className': 'btn-primary',
'modifiers': '{"force_show": 1}'
})
header_element.append(button_element)
# 更新 tree_view 的 arch
tree_view['arch'] = etree.tostring(arch, encoding='unicode')
return res
def button_delivery(self):
# production_ids = []
# workorder_ids = []
delivery_type = '运送空料架'
# max_num = 4 # 最大配送数量
# feeder_station_start_id = False
# if len(self) > max_num:
# raise UserError('仅限于拆卸1-4个制造订单请重新选择')
# for item in self:
# if item.state != 'ready':
# raise UserError('请选择状态为【就绪】的工单进行解除装夹')
#
# production_ids.append(item.production_id.id)
# workorder_ids.append(item.id)
# if not feeder_station_start_id:
# down_product_agv_scheduling = item.get_down_product_agv_scheduling()
# if down_product_agv_scheduling:
# feeder_station_start_id = down_product_agv_scheduling.end_site_id.id
return {
'name': _('确认'),
'type': 'ir.actions.act_window',
'view_mode': 'form',
'res_model': 'sf.workpiece.delivery.wizard',
'target': 'new',
'context': {
# 'default_delivery_ids': [(6, 0, delivery_ids)],
# 'default_production_ids': [(6, 0, production_ids)],
'default_delivery_type': delivery_type,
# 'default_workorder_ids': [(6, 0, workorder_ids)],
'default_workcenter_id': self.env.context.get('default_workcenter_id'),
'default_confirm_button': '确认解除',
# 'default_feeder_station_start_id': feeder_station_start_id,
}}
class CNCprocessing(models.Model):
_name = 'sf.cnc.processing'
@@ -1388,6 +1573,8 @@ class SfWorkOrderBarcodes(models.Model):
def on_barcode_scanned(self, barcode):
logging.info('Rfid:%s' % barcode)
if 'O-CMD' in barcode:
return None
workorder = self.env['mrp.workorder'].browse(self.ids)
# workorder_preset = self.env['mrp.workorder'].search(
# [('routing_type', '=', '装夹预调'), ('rfid_code', '=', barcode)])
@@ -1430,6 +1617,7 @@ class SfWorkOrderBarcodes(models.Model):
raise UserError('该Rfid【%s】绑定的是【%s】, 不是托盘!!!' % (barcode, lot.product_id.name))
self.process_state = '待检测'
self.date_start = datetime.now()
self.is_trayed = True
else:
raise UserError('没有找到Rfid为【%s】的托盘信息!!!' % barcode)
# stock_move_line = self.env['stock.move.line'].search([('lot_name', '=', barcode)])
@@ -1501,20 +1689,24 @@ class WorkPieceDelivery(models.Model):
feeder_station_destination_id = fields.Many2one('sf.agv.site', '目的接驳站')
task_delivery_time = fields.Datetime('任务下发时间')
task_completion_time = fields.Datetime('任务完成时间')
type = fields.Selection(
[('上产线', '上产线'), ('下产线', '下产线'), ('运送空料架', '运送空料架')], string='类型')
def _get_agv_route_type_selection(self):
return self.env['sf.agv.task.route'].fields_get(['route_type'])['route_type']['selection']
type = fields.Selection(selection=_get_agv_route_type_selection, string='类型')
delivery_duration = fields.Float('配送时长', compute='_compute_delivery_duration')
status = fields.Selection(
[('待下发', '待下发'), ('待配送', '待配送'), ('已配送', '已配送'), ('已取消', '已取消')], string='状态',
default='待下发',
tracking=True)
[('待下发', '待下发'), ('已下发', '待配送'), ('已配送', '已配送'), ('已取消', '已取消')], string='状态',
default='待下发', tracking=True)
is_cnc_program_down = fields.Boolean('程序是否下发', default=False, tracking=True)
is_manual_work = fields.Boolean('人工操作', default=False)
active = fields.Boolean(string="有效", default=True)
agv_scheduling_id = fields.Many2one('sf.agv.scheduling', 'AGV任务调度')
@api.model
def create(self, vals):
if vals['route_id'] and vals.get('type') is None:
if vals.get('route_id') and vals.get('type') is None:
vals['type'] = '运送空料架'
else:
if vals.get('name', '/') == '/' or vals.get('name', '/') is False:
@@ -1526,14 +1718,14 @@ class WorkPieceDelivery(models.Model):
obj.feeder_station_start_id.name, obj.feeder_station_destination_id.name)
return obj
@api.constrains('route_id')
def _check_route_id(self):
if self.type == '运送空料架':
if self.route_id and self.name is False:
route = self.sudo().search(
[('route_id', '=', self.route_id.id), ('id', '!=', self.id), ('name', 'ilike', '运送空料架路线')])
if route:
raise UserError("该任务路线已存在,请重新选择")
# @api.constrains('route_id')
# def _check_route_id(self):
# if self.type == '运送空料架':
# if self.route_id and self.name is False:
# route = self.sudo().search(
# [('route_id', '=', self.route_id.id), ('id', '!=', self.id), ('name', 'ilike', '运送空料架路线')])
# if route:
# raise UserError("该任务路线已存在,请重新选择")
# @api.constrains('name')
# def _check_name(self):
@@ -1562,84 +1754,44 @@ class WorkPieceDelivery(models.Model):
def button_delivery(self):
delivery_ids = []
production_ids = []
workorder_ids = []
is_cnc_down = 0
is_not_production_line = 0
is_not_route = 0
same_production_line_id = None
same_route_id = None
down_status = '待下发'
production_type = None
num = 0
delivery_type = '上产线'
max_num = 4 # 最大配送数量
if len(self) > max_num:
raise UserError('仅限于配送1-4个制造订单请重新选择')
for item in self:
num += 1
if production_type is None:
production_type = item.type
if item.type == "运送空料架":
if num >= 2:
raise UserError('仅选择一条路线进行配送,请重新选择')
else:
delivery_ids.append(item.id)
else:
if num > 4:
raise UserError('仅限于配送1-4个制造订单请重新选择')
if item.status in ['待配送', '已配送']:
raise UserError('请选择状态为【待下发】的制造订单进行配送')
if item.route_id:
if same_route_id is None:
same_route_id = item.route_id.id
if item.route_id.id != same_route_id:
is_not_route += 1
# else:
# raise UserError('请选择【任务路线】再进行配送')
# if item.production_id.production_line_state == '已下产线' and item.state == '待下发' and item.type == '下产线':
# raise UserError('该制造订单已下产线,无需配送')
if production_type != item.type:
raise UserError('请选择类型为%s的制造订单进行配送' % production_type)
if down_status != item.status:
up_workpiece = self.search([('type', '=', '上产线'), ('production_id', '=', item.production_id),
('status', '=', '待下发')])
if up_workpiece:
raise UserError('您所选择的制造订单暂未上产线,请在上产线后再进行配送')
else:
raise UserError('请选择状态为【待下发】的制造订单进行配送')
if same_production_line_id is None:
same_production_line_id = item.production_line_id.id
if item.production_line_id.id != same_production_line_id:
is_not_production_line += 1
if item.is_cnc_program_down is False:
is_cnc_down += 1
if is_cnc_down == 0 and is_not_production_line == 0 and is_not_route == 0:
delivery_ids.append(item.id)
production_ids.append(item.production_id.id)
if item.status != '待下发':
raise UserError('请选择状态为【待下发】的制造订单进行配送')
if same_production_line_id is None:
same_production_line_id = item.production_line_id.id
if item.production_line_id.id != same_production_line_id:
is_not_production_line += 1
if item.is_cnc_program_down is False:
is_cnc_down += 1
if is_cnc_down == 0 and is_not_production_line == 0:
delivery_ids.append(item.id)
production_ids.append(item.production_id.id)
workorder_ids.append(item.workorder_id.id)
if is_cnc_down >= 1:
raise UserError('您所选择制造订单的【CNC程序】暂未下发请在程序下发后再进行配送')
if is_not_production_line >= 1:
raise UserError('您所选择制造订单的【目的生产线】不一致,请重新确认')
if is_not_route >= 1:
raise UserError('您所选择制造订单的【任务路线】不一致,请重新确认')
is_free = self._check_avgsite_state()
if is_free is True:
if delivery_ids:
return {
'name': _('确认'),
'type': 'ir.actions.act_window',
'view_mode': 'form',
'res_model': 'sf.workpiece.delivery.wizard',
'target': 'new',
'context': {
'default_delivery_ids': [(6, 0, delivery_ids)],
'default_production_ids': [(6, 0, production_ids)],
'default_destination_production_line_id': same_production_line_id,
'default_route_id': same_route_id,
'default_type': production_type,
}}
else:
if production_type == '运送空料架':
raise UserError("您所选择的【任务路线】的【终点接驳站】已占用,请在该接驳站空闲时进行配送")
else:
raise UserError(
"您所选择制造订单的【任务路线】的【终点接驳站】已占用,请在该接驳站空闲时或选择其他路线进行配送")
return {
'name': _('确认'),
'type': 'ir.actions.act_window',
'view_mode': 'form',
'res_model': 'sf.workpiece.delivery.wizard',
'target': 'new',
'context': {
'default_delivery_ids': [(6, 0, delivery_ids)],
'default_production_ids': [(6, 0, production_ids)],
'default_delivery_type': delivery_type,
'default_workorder_ids': [(6, 0, workorder_ids)],
'default_confirm_button': '确认配送'
}}
# 验证agv站点是否可用
def _check_avgsite_state(self):

View File

@@ -5,8 +5,10 @@ import base64
import hashlib
import os
from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
from odoo.exceptions import ValidationError, UserError
from odoo.modules import get_resource_path
from OCC.Extend.DataExchange import read_step_file
from OCC.Extend.DataExchange import write_stl_file
@@ -106,6 +108,15 @@ class ResProductMo(models.Model):
name = fields.Char('产品名称', compute='_compute_tool_name', store=True, required=False)
@api.constrains('seller_ids')
def _check_seller_ids(self):
if self.categ_type == '表面工艺':
if self.seller_ids:
if self.seller_ids[0].price == 0.0:
raise UserError("请在该产品【采购】中的【价格】进行输入")
else:
raise UserError("请在【采购】中输入供应商信息")
@api.depends('cutting_tool_model_id', 'specification_id')
def _compute_tool_name(self):
for item in self:
@@ -113,6 +124,10 @@ class ResProductMo(models.Model):
name = '%s%s' % (item.cutting_tool_model_id.name, item.specification_id.name)
item.name = name
def _get_process_parameters_product(self, production_process):
return self.env['product.template'].search(
[('server_product_process_parameters_id', '=', production_process.id)]).seller_ids[0]
@api.onchange('cutting_tool_model_id')
def _onchange_cutting_tool_model_id(self):
for item in self:
@@ -640,6 +655,10 @@ class ResProductMo(models.Model):
'part_number': item.get('part_number') or '',
'active': True,
}
tax_id = self.env['account.tax'].sudo().search(
[('type_tax_use', '=', 'sale'), ('amount', '=', item.get('tax')), ('price_include', '=', 'True')])
if tax_id:
vals.update({'taxes_id': [(6, 0, [int(tax_id)])]})
copy_product_id.sudo().write(vals)
product_id.product_tmpl_id.active = False
return copy_product_id
@@ -736,7 +755,11 @@ class ResProductMo(models.Model):
# 产品名称唯一性校验
for item in templates:
if len(self.search([('name', '=', item.name)])) > 1:
raise ValidationError('产品名称【%s】已存在' % item.name)
raise UserError('产品名称【%s】已存在' % item.name)
if item.categ_type == '表面工艺':
if len(self.search([('server_product_process_parameters_id', '=',
item.server_product_process_parameters_id.id)])) > 1:
raise UserError('表面工艺参数为【%s】的产品已存在' % item.server_product_process_parameters_id.name)
if "create_product_product" not in self._context:
templates._create_variant_ids()
@@ -800,7 +823,7 @@ class ResProductFixture(models.Model):
diameter = fields.Float('直径(mm)', digits=(16, 2))
# '零点卡盘' 字段
weight = fields.Float('重量(mm)', digits=(16, 2))
weight = fields.Float('重量(kg)', digits=(16, 2))
orientation_dish_diameter = fields.Float('定位盘直径(mm)', digits=(16, 2))
clamping_diameter = fields.Float('装夹直径(mm)', digits=(16, 2))
clamping_num = fields.Selection([('1', '1'), ('2', '2'), ('4', '4'), ('6', '6'), ('8', '8')], string='装夹单元数')
@@ -947,6 +970,7 @@ class SfMaintenanceEquipmentAndProductTemplate(models.Model):
raise ValidationError("机床基坐标获取失败")
class SfMaintenanceEquipmentTool(models.Model):
_name = 'maintenance.equipment.tool'
_description = '机床刀位'

View File

@@ -0,0 +1,42 @@
from odoo import models, fields, api
class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
agv_rcs_url = fields.Char(string='avg_rcs访问地址',
default='http://172.16.10.114:8182/rcms/services/rest/hikRpcService/genAgvSchedulingTask')
wbcode = fields.Char('地码')
agv_code = fields.Char(string='agv编号')
task_type_no = fields.Char('任务单类型编号')
is_agv_task_dispatch = fields.Boolean('是否下发AGV任务', default=False)
# 是否重新获取检测文件
is_get_detection_file = fields.Boolean(string='重新获取检测文件', default=False)
@api.model
def get_values(self):
values = super(ResConfigSettings, self).get_values()
config = self.env['ir.config_parameter'].sudo()
agv_rcs_url = config.get_param('agv_rcs_url', default='')
wbcode = config.get_param('wbcode', default='')
agv_code = config.get_param('agv_code', default='')
is_agv_task_dispatch = config.get_param('is_agv_task_dispatch')
is_get_detection_file = config.get_param('is_get_detection_file')
values.update(
agv_rcs_url=agv_rcs_url,
wbcode=wbcode,
agv_code=agv_code,
is_agv_task_dispatch=is_agv_task_dispatch,
is_get_detection_file=is_get_detection_file
)
return values
def set_values(self):
super(ResConfigSettings, self).set_values()
config = self.env['ir.config_parameter'].sudo()
config.set_param("agv_rcs_url", self.agv_rcs_url or "")
config.set_param("wbcode", self.wbcode or "")
config.set_param("agv_code", self.agv_code or "")
config.set_param("is_agv_task_dispatch", self.is_agv_task_dispatch or False)
config.set_param("is_get_detection_file", self.is_get_detection_file or False)

View File

@@ -68,6 +68,7 @@ class StockRule(models.Model):
@api.model
def _run_pull(self, procurements):
logging.info(procurements)
moves_values_by_company = defaultdict(list)
mtso_products_by_locations = defaultdict(list)
@@ -168,7 +169,6 @@ class StockRule(models.Model):
else:
forecasted_qties_by_loc[rule.location_src_id][procurement.product_id.id] -= qty_needed
procure_method = 'make_to_stock'
move_values = rule._get_stock_move_values(*procurement)
move_values['procure_method'] = procure_method
moves_values_by_company[procurement.company_id.id].append(move_values)
@@ -176,10 +176,10 @@ class StockRule(models.Model):
for company_id, moves_values in moves_values_by_company.items():
# create the move as SUPERUSER because the current user may not have the rights to do it (mto product
# launched by a sale for example)
moves = self.env['stock.move'].with_user(SUPERUSER_ID).sudo().with_company(company_id).create(moves_values)
moves = self.env['stock.move'].with_user(SUPERUSER_ID).sudo().with_company(company_id).create(
moves_values)
# Since action_confirm launch following procurement_group we should activate it.
moves._action_confirm()
return True
@api.model
@@ -217,6 +217,23 @@ class StockRule(models.Model):
(
p.move_dest_ids.procure_method != 'make_to_order' and not
p.move_raw_ids and not p.workorder_ids)).action_confirm()
# 处理 根据制造订单生成的采购单坯料入库时到原材料库,手动将原材料位置该为坯料存货区
for production in productions:
if production.picking_ids:
product_type_id = production.picking_ids[0].move_ids[0].product_id.categ_id
if product_type_id.name == '坯料':
location_id = self.env['stock.location'].search([('name', '=', '坯料存货区')])
if not location_id:
logging.info(f'没有搜索到【坯料存货区】: {location_id}')
break
for picking_id in production.picking_ids:
if picking_id.picking_type_id.name == '内部调拨':
if picking_id.location_dest_id.product_type != product_type_id:
picking_id.location_dest_id = location_id.id
elif picking_id.picking_type_id.name == '生产发料':
if picking_id.location_id.product_type != product_type_id:
picking_id.location_id = location_id.id
for production in productions:
'''
创建制造订单时生成序列号
@@ -250,6 +267,11 @@ class StockRule(models.Model):
workorder_duration += workorder.duration_expected
sale_order = self.env['sale.order'].sudo().search([('name', '=', production.origin)])
# 根据销售订单号查询快速订单
quick_easy_order = self.env['quick.easy.order'].sudo().search([('sale_order_id', '=', sale_order.id)])
if quick_easy_order:
production.write({'part_number': quick_easy_order.part_drawing_number,
'part_drawing': quick_easy_order.machining_drawings})
if sale_order:
# sale_order.write({'schedule_status': 'to schedule'})
self.env['sf.production.plan'].sudo().with_company(company_id).create({
@@ -271,14 +293,71 @@ class StockRule(models.Model):
# 为同一个product_id创建一个生产订单名称列表
product_id_to_production_names[product_id] = [production.name for production in all_production]
for production_item in productions:
production_programming = self.env['mrp.production'].search(
[('product_id.id', '=', production_item.product_id.id),
('origin', '=', production_item.origin)],
limit=1, order='id asc')
if production_item.product_id.id in product_id_to_production_names:
if not production_programming.programming_no:
if production_item.product_id.model_process_parameters_ids:
is_purchase = False
sorted_process_parameters = sorted(production_item.product_id.model_process_parameters_ids,
key=lambda w: w.id)
consecutive_process_parameters = []
m = 0
for i in range(len(sorted_process_parameters) - 1):
if m == 0:
is_purchase = False
if self.env['product.template']._get_process_parameters_product(
sorted_process_parameters[i]).partner_id == self.env[
'product.template']._get_process_parameters_product(sorted_process_parameters[
i + 1]).partner_id and \
sorted_process_parameters[i].gain_way == '外协':
if sorted_process_parameters[i] not in consecutive_process_parameters:
consecutive_process_parameters.append(sorted_process_parameters[i])
consecutive_process_parameters.append(sorted_process_parameters[i + 1])
m += 1
continue
else:
if m == len(consecutive_process_parameters) - 1 and m != 0:
self.env['purchase.order'].get_purchase_order(consecutive_process_parameters,
production_item,
product_id_to_production_names)
if sorted_process_parameters[i] in consecutive_process_parameters:
is_purchase = True
consecutive_process_parameters = []
m = 0
# 当前面的连续外协采购单生成再生成当前外协采购单
if is_purchase is False:
self.env['purchase.order'].get_purchase_order(consecutive_process_parameters,
production_item,
product_id_to_production_names)
if m == len(consecutive_process_parameters) - 1 and m != 0:
self.env['purchase.order'].get_purchase_order(consecutive_process_parameters,
production_item,
product_id_to_production_names)
if sorted_process_parameters[i] in consecutive_process_parameters:
is_purchase = True
consecutive_process_parameters = []
m = 0
if m == len(consecutive_process_parameters) - 1 and m != 0:
self.env['purchase.order'].get_purchase_order(consecutive_process_parameters,
production_item,
product_id_to_production_names)
if is_purchase is False and m == 0:
if len(sorted_process_parameters) == 1:
self.env['purchase.order'].get_purchase_order(sorted_process_parameters,
production_item,
product_id_to_production_names)
else:
self.env['purchase.order'].get_purchase_order(sorted_process_parameters[i],
production_item,
product_id_to_production_names)
# # 同一个产品多个制造订单对应一个编程单和模型库
# # 只调用一次fetchCNC并将所有生产订单的名称作为字符串传递
if not production_item.programming_no:
production_programming = self.env['mrp.production'].search(
[('product_id.id', '=', production_item.product_id.id),
('origin', '=', production_item.origin)],
limit=1, order='id asc')
if not production_programming.programming_no:
production_item.fetchCNC(
', '.join(product_id_to_production_names[production_item.product_id.id]))
@@ -368,7 +447,7 @@ class ProductionLot(models.Model):
if product.tracking == "serial":
last_serial = self.env['stock.lot'].search(
[('company_id', '=', company.id), ('product_id', '=', product.id)],
limit=1, order='id DESC')
limit=1, order='name desc')
if last_serial:
if product.categ_id.name == '刀具':
return self.env['stock.lot'].get_tool_generate_lot_names1(company, product)
@@ -468,12 +547,11 @@ class ProductionLot(models.Model):
class StockPicking(models.Model):
_inherit = 'stock.picking'
# workorder_in_id = fields.One2many('mrp.workorder', 'picking_in_id')
# workorder_out_id = fields.One2many('mrp.workorder', 'picking_out_id')
surface_technics_parameters_id = fields.Many2one('sf.production.process.parameter', string="表面工艺可选参数")
# 设置外协出入单的名称
def _get_name_Res(self, rescode):
last_picking = self.sudo().search([('name', 'like', rescode)], order='create_date desc,id desc', limit=1)
last_picking = self.sudo().search([('name', 'ilike', rescode)], order='create_date desc,id desc', limit=1)
if not last_picking:
num = "%04d" % 1
else:
@@ -499,9 +577,10 @@ class StockPicking(models.Model):
[('barcode', 'ilike', 'WH-PREPRODUCTION')]).id),
('location_id', '=', self.env['stock.location'].search(
[('barcode', 'ilike', 'VL-SPOC')]).id),
('origin', '=', self.origin)])
('origin', '=', self.origin), ('picking_id', '=', self.id)])
if self.location_id == move_in.location_id and self.location_dest_id == move_in.location_dest_id:
if move_out.origin == move_in.origin:
move_in.write({'production_id': False})
if move_out.picking_id.state != 'done':
raise UserError(
_('该入库单对应的单号为%s的出库单还未完成,不能进行验证操作!' % move_out.picking_id.name))
@@ -516,7 +595,7 @@ class StockPicking(models.Model):
[('barcode', 'ilike', 'VL-SPOC')]).id),
('origin', '=', self.origin)])
production = self.env['mrp.production'].search([('name', '=', self.origin)])
if move_in:
if move_in.state != 'done':
move_in.write({'state': 'assigned'})
self.env['stock.move.line'].create(move_in.get_move_line(production, None))
@@ -526,7 +605,7 @@ class StockPicking(models.Model):
def create_outcontract_picking(self, sorted_workorders_arr, item):
m = 0
for sorted_workorders in sorted_workorders_arr:
pick_ids = []
# pick_ids = []
if m == 0:
outcontract_stock_move = self.env['stock.move'].search(
[('workorder_id', '=', sorted_workorders.id), ('production_id', '=', item.id)])
@@ -545,7 +624,7 @@ class StockPicking(models.Model):
outcontract_picking_type_out))
picking_out = self.create(
moves_out._get_new_picking_values_Res(item, sorted_workorders, 'WH/OCOUT/'))
pick_ids.append(picking_out.id)
# pick_ids.append(picking_out.id)
moves_out.write(
{'picking_id': picking_out.id, 'state': 'waiting', 'workorder_id': sorted_workorders.id})
moves_out._assign_picking_post_process(new=new_picking)
@@ -554,12 +633,12 @@ class StockPicking(models.Model):
outcontract_picking_type_in))
picking_in = self.create(
moves_in._get_new_picking_values_Res(item, sorted_workorders, 'WH/OCIN/'))
pick_ids.append(picking_in.id)
# pick_ids.append(picking_in.id)
moves_in.write(
{'picking_id': picking_in.id, 'state': 'waiting', 'workorder_id': sorted_workorders.id})
moves_in._assign_picking_post_process(new=new_picking)
m += 1
sorted_workorders.write({'picking_ids': [(6, 0, pick_ids)]})
# sorted_workorders.write({'picking_ids': [(6, 0, pick_ids)]})
class ReStockMove(models.Model):
@@ -587,14 +666,20 @@ class ReStockMove(models.Model):
return move_values
def _get_new_picking_values_Res(self, item, sorted_workorders, rescode):
picking_type_id = self.mapped('picking_type_id').id
if rescode == 'WH/OCOUT/':
picking_type_id = self.env.ref('sf_manufacturing.outcontract_picking_out').id
elif rescode == 'WH/OCIN/':
picking_type_id = self.env.ref('sf_manufacturing.outcontract_picking_in').id
return {
'name': self.env['stock.picking']._get_name_Res(rescode),
'origin': item.name,
'surface_technics_parameters_id': sorted_workorders.surface_technics_parameters_id.id,
'company_id': self.mapped('company_id').id,
'user_id': False,
'move_type': self.mapped('group_id').move_type or 'direct',
'partner_id': sorted_workorders.supplier_id.id,
'picking_type_id': self.mapped('picking_type_id').id,
'picking_type_id': picking_type_id,
'location_id': self.mapped('location_id').id,
'location_dest_id': self.mapped('location_dest_id').id,
'state': 'confirmed',

View File

@@ -150,5 +150,12 @@ access_sf_processing_panel_group_sf_order_user,sf_processing_panel_group_sf_orde
access_sf_production_wizard_group_sf_order_user,sf_production_wizard_group_sf_order_user,model_sf_production_wizard,sf_base.group_sf_order_user,1,1,1,0
access_sf_processing_panel_group_plan_dispatch,sf_processing_panel_group_plan_dispatch,model_sf_processing_panel,sf_base.group_plan_dispatch,1,1,1,0
access_sf_agv_scheduling_admin,sf_agv_scheduling_admin,model_sf_agv_scheduling,base.group_system,1,1,1,1
access_sf_agv_scheduling_group_sf_order_user,sf_agv_scheduling_group_sf_order_user,model_sf_agv_scheduling,sf_base.group_sf_order_user,1,1,1,0
access_sf_agv_scheduling_group_sf_mrp_manager,sf_agv_scheduling_group_sf_mrp_manager,model_sf_agv_scheduling,sf_base.group_sf_mrp_manager,1,1,1,0
access_sf_agv_scheduling_group_sf_equipment_user,sf_agv_scheduling_group_sf_equipment_user,model_sf_agv_scheduling,sf_base.group_sf_equipment_user,1,1,1,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
150
151
152
153
154
155
156
157
158
159
160
161

View File

@@ -1,16 +1,36 @@
var RFID = ''
$(document).off('keydown')
console.log(2222)
$(document).on('keydown', '.modal.d-block.o_technical_modal,body.o_web_client', function (e) {
const dom = $('.customRFID')
if(!dom.length) return
$(document).on('keydown', 'body.o_web_client', function (e) {
setTimeout(() => {
RFID = ''
}, 200)
if(e.key == 'Enter' && e.keyCode == 13 || e.key == 'Tab' && e.keyCode == 9){
if(!RFID || RFID.length <= 3) return;
dom.children('span').text(RFID)
RFID = ''
let fieldValue1 = $('[name="routing_type"]');
console.log('字段值:', fieldValue1.text());
console.log(RFID)
let fieldValue2 = $('[name="rfid_code"]');
console.log('字段值2:', fieldValue2.text());
// if(!RFID || RFID.length <= 3) return;
// $('[name="button_start"]').trigger('click')
// setTimeout(() => {
// $('.o_dialog .modal-footer .btn-primary').trigger('click')
// }, 50)
// RFID = ''
// return;
// fieldValue2.val() === '')
// 检查字段值是否等于“装夹预调”
if (fieldValue1.text() === '装夹预调') {
if (!RFID || RFID.length <= 3) return;
$('[name="button_start"]').trigger('click');
setTimeout(() => {
$('.o_dialog .modal-footer .btn-primary').trigger('click');
}, 100);
}
RFID = '';
return;
}
RFID += e.key

View File

@@ -0,0 +1,49 @@
odoo.define('sf_manufacturing.action_dispatch_confirm', function (require) {
const core = require('web.core');
const ajax = require('web.ajax');
const Dialog = require('web.Dialog');
var rpc = require('web.rpc');
var _t = core._t;
async function dispatch_confirm(parent, {params}) {
const dialog = new Dialog(parent, {
title: "确认",
$content: $('<div>').append("请确认是否仅配送" + params.workorder_count + "个工件?"),
buttons: [
{ text: "确认", classes: 'btn-primary jikimo_button_confirm', close: true, click: () => dispatchConfirmed(parent, params) },
{ text: "取消", close: true },
],
});
dialog.open();
async function dispatchConfirmed(parent, params) {
console.log(parent, 'parent')
rpc.query({
model: 'sf.workpiece.delivery.wizard',
method: 'confirm',
args: [params.active_id]
,
kwargs: {
context: params.context,
}
}).then(res => {
parent.services.action.doAction({
'type': 'ir.actions.client',
'tag': 'display_notification',
'target': 'new',
'params': {
'message': '任务下发成功AGV任务调度编号为【' + res.name + '】',
'type': 'success',
'sticky': false,
'next': {'type': 'ir.actions.act_window_close'},
}
});
})
}
}
core.action_registry.add('dispatch_confirm', dispatch_confirm);
return dispatch_confirm;
});

View File

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">
<t t-name="sf_manufacturing.button_show" t-inherit="web.ListView.Buttons" t-inherit-mode="extension" owl="1">
<xpath expr="//div/t[@t-if='nbSelected']" position="after">
<t t-elif="!nbSelected">
<t t-foreach="archInfo.headerButtons" t-as="button" t-key="button.id">
<t t-if="button.modifiers.force_show">
<ListViewHeaderButton
list="model.root"
clickParams="button.clickParams"
defaultRank="button.defaultRank"
domain="props.domain"
icon="button.icon"
string="button.string"
title="button.title"
className="button.className+' ms-2'"
/>
</t>
</t>
</t>
</xpath>
<xpath expr="//div/t[@t-if='nbSelected']" position="replace">
<t t-if="nbSelected">
<t t-foreach="archInfo.headerButtons" t-as="button" t-key="button.id">
<t t-if="!button.modifiers.force_show">
<ListViewHeaderButton
list="model.root"
clickParams="button.clickParams"
defaultRank="button.defaultRank"
domain="props.domain"
icon="button.icon"
string="button.string"
title="button.title"
/>
</t>
</t>
<t t-if="!env.isSmall">
<t t-call="web.ListView.Selection"/>
</t>
<t t-foreach="archInfo.headerButtons" t-as="button" t-key="button.id">
<t t-if="button.modifiers.force_show == 1">
<ListViewHeaderButton
list="model.root"
clickParams="button.clickParams"
defaultRank="button.defaultRank"
domain="props.domain"
icon="button.icon"
string="button.string"
title="button.title"
className="button.className+' ms-2'"
/>
</t>
</t>
</t>
</xpath>
</t>
</templates>

View File

@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<!-- agv站点 -->
<record id="view_agv_scheduling_tree" model="ir.ui.view">
<field name="name">agv调度</field>
<field name="model">sf.agv.scheduling</field>
<field name="arch" type="xml">
<tree editable="bottom" delete="0" create="0">
<field name="state" widget="badge"
decoration-success="state == '已配送'"
decoration-warning="state == '待下发'"
decoration-danger="state == '配送中'"
decoration-info="state == '已取消'"
/>
<field name="agv_route_type" invisible="1"/>
<field name="name"/>
<field name="agv_route_id"/>
<field name="start_site_id"/>
<field name="end_site_id"/>
<field name="site_state"/>
<field name="delivery_workpieces"/>
<field name="task_create_time" readonly="1"/>
<field name="task_delivery_time" readonly="1"/>
<field name="task_completion_time" readonly="1"/>
<field name="task_duration" readonly="1"/>
<button
name="button_cancel"
string="取消" type="object"
attrs="{'invisible': ['|', ('state', '!=', '待下发'), ('agv_route_type', '=', '运送空料架')]}"
icon="fa-times"
class="btn-danger"
confirm="你确定要取消这条记录吗?"
/>
</tree>
</field>
</record>
<record id="view_agv_scheduling_search" model="ir.ui.view">
<field name="name">sf.agv.scheduling.search</field>
<field name="model">sf.agv.scheduling</field>
<field name="arch" type="xml">
<search string="AGV调度">
<field name="name"/>
<field name="agv_route_id"/>
<field name="start_site_id"/>
<field name="end_site_id"/>
<field name="delivery_workpieces"/>
<field name="state" string="状态"/>
<filter name="filter_to_be_issued" string="待下发" domain="[('state', 'in', ['待下发'])]"/>
<filter name="filter_delivering" string="配送中" domain="[('state', 'in', ['配送中'])]"/>
<filter name="filter_delivered" string="已配送" domain="[('state', 'in', ['已配送'])]"/>
</search>
</field>
</record>
<record id="action_agv_scheduling_tree" model="ir.actions.act_window">
<field name="name">AGV调度</field>
<field name="res_model">sf.agv.scheduling</field>
<field name="view_mode">tree</field>
<field name="context">
{
"search_default_filter_to_be_issued": 1,
"search_default_filter_delivering": 1,
}
</field>
</record>
<menuitem
id="menu_action_agv_scheduling"
name="AGV调度"
sequence="28"
action="action_agv_scheduling_tree"
parent="mrp.menu_mrp_manufacturing"
groups="sf_base.group_sf_order_user,sf_base.group_sf_mrp_manager,sf_base.group_sf_equipment_user"
/>
</data>
</odoo>

View File

@@ -8,7 +8,7 @@
<field name="arch" type="xml">
<tree editable="bottom">
<field name="name" required="1" attrs="{'readonly': [('id', '!=', False)]}"/>
<field name="owning_region" required="1" attrs="{'readonly': [('id', '!=', False)]}"/>
<field name="workcenter_id" required="1" options="{'no_create': True}"/>
<field name="state" required="1" attrs="{'readonly': [('id', '!=', False)]}"/>
<field name="divide_the_work" required="1"/>
</tree>
@@ -40,8 +40,9 @@
<field name="start_site_id" required="1" options="{'no_create': True}" string="起点接驳站"
attrs="{'readonly': [('id', '!=', False)]}"/>
<field name="end_site_id" required="1" options="{'no_create': True}" string="终点接驳站"/>
<field name="destination_production_line_id" required="1" options="{'no_create': True}"
attrs="{'readonly': [('id', '!=', False)]}"/>
<!-- <field name="destination_production_line_id" required="1" options="{'no_create': True}"-->
<!-- attrs="{'readonly': [('id', '!=', False)]}"/>-->
<field name="workcenter_id"/>
</tree>
</field>
</record>

View File

@@ -7,10 +7,10 @@
<field name="model">mrp.production</field>
<field name="inherit_id" ref="mrp.mrp_production_tree_view"/>
<field name="arch" type="xml">
<!-- <xpath expr="//button[@name='do_unreserve']" position="after">-->
<!-- <button name="do_update_program" type="object" string="更新程序"-->
<!-- groups="sf_base.group_sf_mrp_user"/>-->
<!-- </xpath>-->
<!-- <xpath expr="//button[@name='do_unreserve']" position="after">-->
<!-- <button name="do_update_program" type="object" string="更新程序"-->
<!-- groups="sf_base.group_sf_mrp_user"/>-->
<!-- </xpath>-->
<xpath expr="//field[@name='product_id']" position="replace"/>
<xpath expr="//field[@name='product_qty']" position="replace"/>
<xpath expr="//field[@name='product_uom_id']" position="replace"/>
@@ -70,7 +70,7 @@
<!-- <attribute name="statusbar_visible">draft,confirmed,progress,pending_processing,completed,done -->
<!-- </attribute> -->
<attribute name="statusbar_visible">
confirmed,pending_cam,progress,done
confirmed,pending_cam,progress,rework,scrap,done
</attribute>
</xpath>
<xpath expr="//sheet//group//group[2]//label" position="before">
@@ -127,10 +127,10 @@
confirm="是否确认更新程序"
attrs="{'invisible': ['|',('state', '!=', 'rework'),('programming_state', '!=', '已编程未下发')]}"/>
<button name="button_rework" string="返工" type="object" groups="sf_base.group_sf_mrp_user"
attrs="{'invisible': ['|',('state', '!=', 'rework') ,('programming_state', '!=', '已编程')]}"/>
<!-- <button name="%(sf_manufacturing.action_sf_production_wizard)d" string="报废" type="action"-->
<!-- groups="sf_base.group_sf_mrp_user"-->
<!-- attrs="{'invisible': [('is_scrap', '=', False)]}"/>-->
attrs="{'invisible': ['|','|',('state', '!=', 'rework') ,('programming_state', '!=', '已编程'),('is_rework', '=', True)]}"/>
<button name="button_scrap_new" string="报废" type="object"
groups="sf_base.group_sf_mrp_user"
attrs="{'invisible': ['|',('is_scrap', '=', False),('state','=','cancel')]}"/>
</xpath>
<xpath expr="(//header//button[@name='button_mark_done'])[3]" position="replace">
<button name="button_mark_done" attrs="{'invisible': [
@@ -201,6 +201,19 @@
data-hotkey="l"/>
</xpath>
<xpath expr="//button[@name='action_view_mo_delivery']" position="before">
<button class="oe_stat_button" name="action_view_remanufacture_productions" type="object"
icon="fa-wrench" attrs="{'invisible': [('remanufacture_count', '=', 0)]}"
groups="mrp.group_mrp_user">
<div class="o_field_widget o_stat_info">
<span class="o_stat_value">
<field name="remanufacture_count"/>
</span>
<span class="o_stat_text">新的制造</span>
</div>
</button>
</xpath>
<xpath expr="//header//button[@name='action_toggle_is_locked']" position="replace">
<button name="action_toggle_is_locked"
attrs="{'invisible': ['|', ('show_lock', '=', False), ('is_locked', '=', True)]}"
@@ -285,7 +298,7 @@
<xpath expr="//sheet//notebook//page[@name='operations']" position="after">
<page string="检测结果" attrs="{'invisible': [('detection_result_ids', '=', [])]}">
<field name="detection_result_ids" string="" readonly="1">
<field name="detection_result_ids" string="" readonly="0">
<tree sample="1">
<field name="production_id" invisible="1"/>
<field name="processing_panel"/>
@@ -424,6 +437,12 @@
<xpath expr="//header//button[@name='action_cancel']" position="replace">
<button name="action_cancel" type="object" string="取消" groups="sf_base.group_sf_mrp_user"/>
</xpath>
<xpath expr="//field[@name='state']" position="replace">
<field name="state" decoration-success="state in ('done', 'to_close')"
decoration-warning="state == 'progress'" decoration-info="state == 'confirmed'"
decoration-danger="state in ('cancel','rework','scrap')" decoration-muted="state == 'draft'"
optional="show" widget="badge" class="text-dark"/>
</xpath>
<xpath expr="//field[@name='state']" position="after">
<field name="tool_state" invisible="1"/>
</xpath>
@@ -460,6 +479,7 @@
<field name="arch" type="xml">
<xpath expr="//filter[@name='filter_in_progress']" position="before">
<filter string="返工" name="filter_rework" domain="[('state', '=', 'rework')]"/>
<filter string="报废" name="filter_scrap" domain="[('state', '=', 'scrap')]"/>
</xpath>
<xpath expr="//filter[@name='planning_issues']" position="before">
<separator/>
@@ -568,7 +588,7 @@
<field name="arch" type="xml">
<form>
<group>
<!-- <field name="handle_result"/>-->
<field name="handle_result"/>
<field name="test_report" readonly="1" widget="pdf_viewer"/>
</group>
</form>

View File

@@ -17,6 +17,7 @@
<field name="bom_product_template_attribute_value_ids" position="after">
<field name="routing_type" required="1"/>
<field name="is_repeat"/>
<field name="reserved_duration"/>
</field>
</field>
</record>

View File

@@ -6,9 +6,9 @@
<field name="model">mrp.production</field>
<field name="inherit_id" ref="mrp.mrp_production_form_view"/>
<field name="arch" type="xml">
<!-- <button name="action_cancel" position="before"> -->
<!-- <button name="button_maintenance_req" type="object" string="维修请求"/> -->
<!-- </button> -->
<!-- <button name="action_cancel" position="before"> -->
<!-- <button name="button_maintenance_req" type="object" string="维修请求"/> -->
<!-- </button> -->
<div name="button_box" position="inside">
<button name="open_maintenance_request_mo" type="object" class="oe_stat_button" icon="fa-wrench"
attrs="{'invisible': [('maintenance_count', '=', 0)]}"
@@ -25,38 +25,81 @@
</record>
<record id="custom_model_form_view_inherit" model="ir.ui.view">
<field name="name">custom.model.form.view.inherit</field>
<field name="model">mrp.workcenter</field>
<field name="inherit_id" ref="mrp.mrp_workcenter_view"/>
<field name="arch" type="xml">
<xpath expr='//form//sheet' position="after">
<div class="oe_chatter">
<field name="message_follower_ids"/>
<field name="message_ids"/>
</div>
</xpath>
</field>
</record>
<field name="name">custom.model.form.view.inherit</field>
<field name="model">mrp.workcenter</field>
<field name="inherit_id" ref="mrp.mrp_workcenter_view"/>
<field name="arch" type="xml">
<xpath expr='//form//sheet' position="after">
<div class="oe_chatter">
<field name="message_follower_ids"/>
<field name="message_ids"/>
</div>
</xpath>
<xpath expr="//field[@name='default_capacity'][last()]" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='default_capacity'][last()]" position="after">
<record id="mrp_workcenter_view_kanban_inherit_workorder" model="ir.ui.view">
<field name="name">mrp.workcenter.view.kanban.inherit.mrp.workorder</field>
<field name="model">mrp.workcenter</field>
<field name="inherit_id" ref="mrp.mrp_workcenter_kanban"/>
<field name="arch" type="xml">
<!-- Desktop view -->
<xpath expr='(//field[@name="name"])[1]' position="after">
<field name="equipment_status" />
<field name="equipment_image" />
</xpath>
<xpath expr='(//field[@name="name"])[2]' position="after">
<field name="equipment_status" />
<field name="equipment_image" widget="image" />
</xpath>
<xpath expr='(//a[@name="unblock"])' position="after">
<div class="czyg">绿色:正常,红色:故障,黄色:下线/暂停</div>
</xpath>
</field>
</record>
<label for="default_capacity"/>
<div class="o_row">
<field name="default_capacity" string="产线日产能"/>
</div>
</xpath>
<xpath expr="//field[@name='default_capacity'][last()]" position="before">
<label for="available_machine_number"/>
<div class="o_row">
<field name="available_machine_number"/>
</div>
<label for="single_machine_capacity"/>
<div class="o_row">
<field name="single_machine_capacity"/>
件/小时
</div>
<label for="production_line_hour_capacity"/>
<div class="o_row">
<field name="production_line_hour_capacity"/>
件/小时
</div>
<label for="effective_working_hours_day"/>
<div class="o_row">
<field name="effective_working_hours_day"/>
小时
</div>
</xpath>
<!-- <xpath expr='//group[@name="capacity"]//field[@name="default_capacity"])' position="after">-->
<!-- <group>-->
<!-- <field name="available_machine_number"/>-->
<!-- <field name="single_machine_capacity"/>-->
<!-- <field name="production_line_hour_capacity"/>-->
<!-- <field name="effective_working_hours_day"/>-->
<!-- </group>-->
<!-- </xpath>-->
</field>
</record>
<record id="mrp_workcenter_view_kanban_inherit_workorder" model="ir.ui.view">
<field name="name">mrp.workcenter.view.kanban.inherit.mrp.workorder</field>
<field name="model">mrp.workcenter</field>
<field name="inherit_id" ref="mrp.mrp_workcenter_kanban"/>
<field name="arch" type="xml">
<!-- Desktop view -->
<xpath expr='(//field[@name="name"])[1]' position="after">
<field name="equipment_status"/>
<field name="equipment_image"/>
</xpath>
<xpath expr='(//field[@name="name"])[2]' position="after">
<field name="equipment_status"/>
<field name="equipment_image" widget="image"/>
</xpath>
<xpath expr='(//a[@name="unblock"])' position="after">
<div class="czyg">绿色:正常,红色:故障,黄色:下线/暂停</div>
</xpath>
</field>
</record>
<record id="mrp_workcenter_view_kanban_inherit_workorder" model="ir.ui.view">
<field name="name">mrp.workcenter.view.kanban.inherit.mrp.workorder</field>
@@ -73,11 +116,11 @@
</xpath>
<xpath expr='(//a[@name="unblock"])' position="after">
<!-- <div class="czyg">绿色:正常,红色:故障,黄色:下线/暂停</div>-->
<!-- <div class="czyg">绿色:正常,红色:故障,黄色:下线/暂停</div>-->
</xpath>
</field>
</record>
<!--&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;-->
<!--&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;-->
<record id="mrp_workcenter_kanban_inherit1" model="ir.ui.view">
<field name="name">mrp.workcenter.kanban.inherit</field>
<field name="model">mrp.workcenter</field>
@@ -99,7 +142,7 @@
</field>
</record>
<!-- 继承原有的看板视图 -->
<!-- 继承原有的看板视图 -->
<record id="mrp_workcenter_kanban_inherit1" model="ir.ui.view">
<field name="name">mrp.workcenter.kanban.inherit</field>
<field name="model">mrp.workcenter</field>
@@ -182,6 +225,7 @@
</xpath>
<xpath expr="//field[@name='resource_calendar_id']" position="after">
<field name="is_process_outsourcing"/>
<field name="is_agv_scheduling"/>
</xpath>
</field>
</record>
@@ -390,9 +434,9 @@
<field name="model">mrp.production</field>
<field name="inherit_id" ref="mrp.mrp_production_form_view"/>
<field name="arch" type="xml">
<!-- <button name="action_cancel" position="before"> -->
<!-- <button name="button_maintenance_req" type="object" string="维修请求"/> -->
<!-- </button> -->
<!-- <button name="action_cancel" position="before"> -->
<!-- <button name="button_maintenance_req" type="object" string="维修请求"/> -->
<!-- </button> -->
<div name="button_box" position="inside">
<button name="open_maintenance_request_mo" type="object" class="oe_stat_button" icon="fa-wrench"
attrs="{'invisible': [('maintenance_count', '=', 0)]}"

View File

@@ -10,7 +10,7 @@
<field name="name" decoration-success="is_subcontract" decoration-bf="is_subcontract"/>
</field>
<field name="name" position="before">
<field name="sequence"/>
<field name="sequence" string="序号"/>
<field name='user_permissions' invisible="1"/>
</field>
<field name="name" position="after">
@@ -32,18 +32,28 @@
</field>
<xpath expr="//field[@name='qty_remaining']" position="after">
<field name="manual_quotation" optional="show"/>
<field name='tag_type' widget="badge"
decoration-danger="tag_type == '重新加工'"/>
</xpath>
<xpath expr="//field[@name='date_planned_start']" position="replace">
<field name="date_planned_start" string="计划开始日期" optional="show"/>
</xpath>
<xpath expr="//field[@name='date_planned_start']" position="before">
<field name="reserved_duration" string="计划预留时间" optional="hide"/>
</xpath>
<xpath expr="//field[@name='date_planned_finished']" position="replace">
<field name="date_planned_finished" string="计划结束日期" optional="hide"/>
</xpath>
<xpath expr="//button[@name='button_start']" position="attributes">
<!-- <attribute name="attrs">{'invisible': ['|', '|', '|','|','|', ('production_state','in', ('draft',-->
<!-- 'done',-->
<!-- 'cancel')), ('working_state', '=', 'blocked'), ('state', 'in', ('done', 'cancel')),-->
<!-- ('is_user_working', '!=', False),("user_permissions","=",False),("name","=","CNC加工")]}-->
<!-- </attribute>-->
<attribute name="attrs">{'invisible': ['|', '|', '|','|','|', ('production_state','in', ('draft',
'done',
'cancel')), ('working_state', '=', 'blocked'), ('state', 'in', ('done', 'cancel')),
('is_user_working', '!=', False),("user_permissions","=",False),("name","=","CNC加工")]}
('is_user_working', '!=', False),("user_permissions","=",False),("name","in",("CNC加工","解除装夹"))]}
</attribute>
</xpath>
<xpath expr="//button[@name='%(mrp.act_mrp_block_workcenter_wo)d']" position="attributes">
@@ -113,11 +123,25 @@
<field name="model">mrp.workorder</field>
<field name="inherit_id" ref="mrp.mrp_production_workorder_form_view_inherit"/>
<field name="arch" type="xml">
<xpath expr="//form" position="inside">
<script src="sf_manufacturing/static/src/js/customRFID.js"/>
</xpath>
<xpath expr="//header/field[@name='state']" position="replace">
<field name="state" widget="statusbar"
statusbar_visible="pending,waiting,ready,progress,to be detected,done,rework"/>
</xpath>
<xpath expr="//div[@name='button_box']" position="inside">
<button type="object" name="action_view_surface_technics_purchase" class="oe_stat_button"
icon="fa-credit-card"
groups="base.group_user,sf_base.group_sf_order_user"
attrs="{'invisible': [('surface_technics_purchase_count', '=', 0),('routing_type', '!=', '表面工艺')]}">
<div class="o_field_widget o_stat_info">
<span class="o_stat_value">
<field name="surface_technics_purchase_count"/>
</span>
<span class="o_stat_text">采购</span>
</div>
</button>
<button type="object" name="action_view_surface_technics_picking" class="oe_stat_button" icon="fa-truck"
groups="base.group_user,sf_base.group_sf_order_user"
attrs="{'invisible': [('surface_technics_picking_count', '=', 0)]}">
@@ -130,6 +154,7 @@
<field name='name' invisible="1"/>
<field name='is_rework' invisible="1"/>
<field name='is_delivery' invisible="1"/>
<field name="is_trayed" invisible="1"/>
<!-- <field name='is_send_program_again' invisible="1"/>-->
<!-- 工单form页面的开始停工按钮等 -->
<!-- <button name="button_start" type="object" string="开始" class="btn-success" -->
@@ -142,8 +167,12 @@
<!-- attrs="{'invisible': ['|', '|', ('production_state', 'not in', ('pending_processing', 'pending_cam', 'pending_era_cam')), ('state','!=','progress'), ('routing_type', 'not in', ('装夹预调', 'CNC加工', '解除装夹'))]}" -->
<!-- groups="sf_base.group_sf_mrp_user" 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)]}"/>-->
<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': ['|', '|', '|', '|', '|', ('routing_type', '=', '装夹预调'), ('routing_type', '=', '解除装夹'), ('production_state','in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('state', 'in', ('done', 'cancel','to be detected')), ('is_user_working', '!=', False)]}"/>
<button name="button_start" type="object" string="开始" class="btn-success"
attrs="{'invisible': ['|', '|', '|', '|', ('routing_type', '!=', '装夹预调'), ('production_state','in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('state', 'in', ('done', 'cancel','to be detected')), ('is_user_working', '!=', False)]}"/>
<button name="button_pending" type="object" string="暂停" class="btn-warning"
attrs="{'invisible': ['|', '|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('is_user_working', '=', False)]}"/>
<button name="button_finish" type="object" string="完成" class="btn-success" confirm="是否确认完工"
@@ -164,11 +193,14 @@
<!-- context="{'default_workcenter_id': workcenter_id}" class="btn-danger" -->
<!-- groups="sf_base.group_sf_mrp_user" -->
<!-- attrs="{'invisible': ['|', '|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '!=', 'blocked'),('state','=','done')]}"/> -->
<button name="button_workpiece_delivery" type="object" string="工件配送" class="btn-primary"
attrs="{'invisible': ['|','|','|','|',('routing_type','!=','装夹预调'),('is_delivery','=',True),('state','!=','done'),('is_rework','=',True),'&amp;',('rfid_code','in',['',False]),('state','=','done')]}"/>
<!-- <button name="button_workpiece_delivery" type="object" string="工件配送" class="btn-primary"-->
<!-- attrs="{'invisible': ['|','|','|','|',('routing_type','!=','装夹预调'),('is_delivery','=',True),('state','!=','done'),('is_rework','=',True),'&amp;',('rfid_code','in',['',False]),('state','=','done')]}"/>-->
<button name="button_rework_pre" type="object" string="返工"
class="btn-primary"
attrs="{'invisible': ['|','|',('routing_type','!=','装夹预调'),('state','!=','progress'),('is_rework','=',True)]}"/>
<button name="unbind_tray" type="object" string="解绑托盘"
class="btn-primary"
attrs="{'invisible': ['|', '|', '|', ('routing_type','!=','装夹预调'),('state','!=','progress'), ('is_trayed', '=', False), ('state', 'in', ('done'))]}"/>
<button name="print_method" type="object" string="打印二维码" class="btn-primary"
attrs="{'invisible': ['|',('routing_type','!=','解除装夹'),('state','!=','done')]}"/>
</xpath>
@@ -191,9 +223,12 @@
<xpath expr="//label[1]" position="before">
<field name='routing_type' readonly="1"/>
<field name='process_state' attrs='{"invisible": [("routing_type","!=","装夹预调")]}'/>
<field name='tag_type' readonly="1" attrs='{"invisible": [("tag_type","=",False)]}'
decoration-danger="tag_type == '重新加工'"/>
<field name="rfid_code" force_save="1" readonly="1" cache="True"
attrs="{'invisible': [('rfid_code_old', '!=', False)]}"/>
<field name="rfid_code_old" readonly="1" attrs="{'invisible': [('rfid_code_old', '=', False)]}"/>
</xpath>
<xpath expr="//label[1]" position="attributes">
<attribute name="string">计划加工时间</attribute>
@@ -449,10 +484,10 @@
<div class="col-12 col-lg-6 o_setting_box">
<field name="data_state" invisible="1"/>
<button type="object" class="oe_highlight" name="get_three_check_datas" string="获取数据"
attrs='{"invisible": ["|", "|", "|", ("material_center_point","!=",False),("state","!=","progress"),("user_permissions","=",False), ("data_state", "=", True)]}'/>
<button type="object" class="oe_highlight" name="getcenter" string="计算定位"
attrs='{"invisible": ["|","|", "|",("material_center_point","!=",False),("state","!=","progress"),("user_permissions","=",False), ("data_state", "=", False)]}'/>
<!-- <button type="object" class="oe_highlight" name="get_three_check_datas" string="获取数据" -->
<!-- attrs='{"invisible": ["|", "|", "|", ("material_center_point","!=",False),("state","!=","progress"),("user_permissions","=",False), ("data_state", "=", True)]}'/> -->
<!-- <button type="object" class="oe_highlight" name="getcenter" string="计算定位" -->
<!-- attrs='{"invisible": ["|","|", "|",("material_center_point","!=",False),("state","!=","progress"),("user_permissions","=",False), ("data_state", "=", False)]}'/> -->
</div>
<group>
@@ -483,6 +518,11 @@
</xpath>
<xpath expr="//form//header" position="inside">
<button type="object" class="oe_highlight jikimo_button_confirm" name="get_three_check_datas"
string="获取数据" attrs='{"invisible": [("state","!=","progress")]}'/>
</xpath>
<xpath expr="//page[1]" position="before">
<field name="results" invisible="1"/>
@@ -511,7 +551,7 @@
<xpath expr="//page[1]" position="before">
<page string="CNC程序" attrs='{"invisible": [("routing_type","!=","CNC加工")]}'>
<field name="cnc_ids" widget="one2many" string="工作程序" default_order="sequence_number,id"
readonly="1">
readonly="0">
<tree>
<field name="sequence_number"/>
<field name="program_name"/>
@@ -629,29 +669,30 @@
<field name="name">工件配送</field>
<field name="model">sf.workpiece.delivery</field>
<field name="arch" type="xml">
<tree string="工件配送" class="center" create="0" delete="0">
<tree string="工件配送" class="center" create="0" delete="0" js_class="remove_focus_list_view">
<header>
<button name="button_delivery" type="object" string="配送" class="oe_highlight"/>
<button name="button_delivery" type="object" string="工件配送"
class="btn-primary jikimo_button_confirm" attrs="{'force_show':1}"/>
</header>
<field name="status" widget="badge"
decoration-success="status == '已配送'"
decoration-warning="status == '待下发'"
decoration-danger="status == '待配送'"
decoration-danger="status == '已下发'"
decoration-info="status == '已取消'"
/>
<field name="name"/>
<field name="production_id"/>
<field name="type" readonly="1"/>
<field name="production_line_id" options="{'no_create': True}" readonly="1"/>
<field name="route_id" options="{'no_create': True}"
domain="[('route_type','in',['上产线','下产线'])]"/>
<!-- <field name="route_id" options="{'no_create': True}"-->
<!-- domain="[('route_type','in',['上产线','下产线'])]"/>-->
<field name="feeder_station_start_id" readonly="1" force_save="1"/>
<field name="feeder_station_destination_id" readonly="1" force_save="1"/>
<!-- <field name="feeder_station_destination_id" readonly="1" force_save="1"/>-->
<field name="is_cnc_program_down" readonly="1"/>
<!-- <field name="rfid_code"/>-->
<field name="task_delivery_time" readonly="1"/>
<field name="task_completion_time" readonly="1"/>
<field name="delivery_duration" widget="float_time"/>
<!-- <field name="task_delivery_time" readonly="1"/>-->
<!-- <field name="task_completion_time" readonly="1"/>-->
<!-- <field name="delivery_duration" widget="float_time"/>-->
</tree>
</field>
</record>
@@ -706,7 +747,7 @@
<field name="arch" type="xml">
<search string="工件配送">
<filter name="filter_to_be_issued" string="待下发" domain="[('status', 'in', ['待下发'])]"/>
<filter name="filter_waiting_delivery" string="待配送" domain="[('status', 'in', ['待配送'])]"/>
<filter name="filter_issued" string="已下发" domain="[('status', 'in', ['已下发'])]"/>
<filter name="filter_delivered" string="已配送" domain="[('status', 'in', ['已配送'])]"/>
<field name="rfid_code"/>
<field name="production_id"/>
@@ -730,7 +771,7 @@
<field name="res_model">sf.workpiece.delivery</field>
<field name="search_view_id" ref="sf_workpiece_delivery_search"/>
<field name="context">{'search_default_filter_to_be_issued': 1,
'search_default_filter_waiting_delivery': 1}
'search_default_filter_issued': 1}
</field>
<field name="view_mode">tree,form</field>
<field name="domain">
@@ -817,5 +858,11 @@
<field name="view_mode">tree</field>
<field name="domain">[('type','in',['运送空料架']),('name','not ilike','WDO')]</field>
</record>
<menuitem id="mrp.menu_mrp_manufacturing"
name="Operations"
sequence="10"
parent="mrp.menu_mrp_root"
groups="sf_base.group_sf_order_user,sf_base.group_sf_mrp_manager,sf_base.group_sf_equipment_user"/>
</odoo>

View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="res_config_settings_view_form_sf_sync" model="ir.ui.view">
<field name="name">res.config.settings.view.form.inherit.sf_sync</field>
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="base_setup.res_config_settings_view_form"/>
<field name="arch" type="xml">
<xpath expr="//div[hasclass('app_settings_block')]/div" position="before">
<div>
<h2>AGV参数配置</h2>
<div class="row mt16 o_settings_container" id="agv_config">
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane"/>
<div class="o_setting_right_pane">
<div class="text-muted">
<label for="agv_rcs_url" string="访问地址"/>
<field name="agv_rcs_url"/>
</div>
<div class="text-muted">
<label for="agv_code" string="车辆编号"/>
<field name="agv_code"/>
</div>
<div class="text-muted">
<label for="wbcode"/>
<field name="wbcode"/>
</div>
</div>
</div>
</div>
</div>
</xpath>
<xpath expr="//div[@id='agv_config']/div" position="after">
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="is_agv_task_dispatch"/>
</div>
<div class="o_setting_right_pane">
<div class="text-muted">
<label for="is_agv_task_dispatch"/>
</div>
</div>
</div>
</xpath>
</field>
</record>
</data>
</odoo>

View File

@@ -2,6 +2,8 @@
# Part of YiZuo. See LICENSE file for full copyright and licensing details.
import logging
from odoo.exceptions import UserError, ValidationError
from collections import defaultdict, namedtuple
from odoo.addons.stock.models.stock_rule import ProcurementException
from datetime import datetime
from odoo import models, api, fields, _
@@ -11,11 +13,91 @@ class ProductionWizard(models.TransientModel):
_description = '制造订单向导'
production_id = fields.Many2one('mrp.production', string='制造订单号')
is_reprogramming = fields.Boolean(string='申请重新编程', default=True)
reprogramming_num = fields.Integer('重新编程次数', default=0)
is_reprogramming = fields.Boolean(string='申请重新编程', default=False)
is_remanufacture = fields.Boolean(string='重新生成制造订单', default=True)
programming_states = fields.Selection(
[('待编程', '待编程'), ('编程中', '编程中'), ('已编程', '已编程'), ('已编程未下发', '已编程未下发'),
('已下发', '已下发')],
string='编程状态')
@api.onchange('is_remanufacture')
def _onchange_is_reprogramming(self):
if self.is_remanufacture is False:
self.is_reprogramming = False
def confirm(self):
if self.is_reprogramming is True:
self.production_id.update_programming_state()
self.production_id.action_cancel()
self.production_id.detection_result_ids.write({'handle_result': '已处理'})
self.production_id.write({'state': 'cancel', 'scrap_ids': [(0, 0, {
'name': self.env['ir.sequence'].next_by_code('stock.scrap') or _('New'),
'product_id': self.production_id.product_id.id,
'scrap_qty': 1,
'origin': self.production_id.origin,
'date_done': fields.datetime.now(),
'lot_id': self.env['stock.move.line'].search(
[('move_id', '=', self.production_id.move_raw_ids[0].id)]).lot_id.id,
'location_id': self.production_id.move_raw_ids.filtered(lambda x: x.state not in (
'done',
'cancel')) and self.production_id.location_src_id.id or self.production_id.location_dest_id.id,
'scrap_location_id': self.env['stock.scrap']._get_default_scrap_location_id(),
'state': 'done'})]})
self.production_id.action_cancel()
if self.is_remanufacture is True:
ret = {'programming_list': [], 'is_reprogramming': self.is_reprogramming}
if self.is_reprogramming is True:
self.production_id.update_programming_state()
else:
scrap_cnc = self.production_id.workorder_ids.filtered(lambda crw: crw.routing_type == 'CNC加工').cnc_ids
scrap_cmm = self.production_id.workorder_ids.filtered(lambda cm: cm.routing_type == 'CNC加工').cmm_ids
for item_line in scrap_cnc:
vals = {
'sequence_number': item_line.sequence_number,
'program_name': item_line.program_name,
'cutting_tool_name': item_line.cutting_tool_name,
'cutting_tool_no': item_line.cutting_tool_no,
'processing_type': item_line.processing_type,
'margin_x_y': item_line.margin_x_y,
'margin_z': item_line.margin_z,
'depth_of_processing_z': item_line.depth_of_processing_z,
'cutting_tool_extension_length': item_line.cutting_tool_extension_length,
'estimated_processing_time': item_line.estimated_processing_time,
'cutting_tool_handle_type': item_line.cutting_tool_handle_type,
'ftp_path': item_line.program_path,
'processing_panel': item_line.workorder_id.processing_panel,
'program_create_date': datetime.strftime(item_line.program_create_date,
'%Y-%m-%d %H:%M:%S'),
'remark': item_line.remark
}
ret['programming_list'].append(vals)
for cmm_line in scrap_cmm:
vals = {
'sequence_number': cmm_line.sequence_number,
'program_name': cmm_line.program_name,
'ftp_path': cmm_line.program_path,
'processing_panel': item_line.workorder_id.processing_panel,
'program_create_date': datetime.strftime(
cmm_line.program_create_date,
'%Y-%m-%d %H:%M:%S')
}
ret['programming_list'].append(vals)
new_production = self.production_id.recreateManufacturing(ret)
self.production_id.write({'remanufacture_production_id': new_production.id})
if self.is_reprogramming is False:
for panel in new_production.product_id.model_processing_panel.split(','):
scrap_cnc_workorder = max(
self.production_id.workorder_ids.filtered(
lambda
scn: scn.processing_panel == panel and scn.routing_type == 'CNC加工'),
key=lambda w: w.create_date)
scrap_pre_workorder = max(self.production_id.workorder_ids.filtered(
lambda
pr: pr.processing_panel == panel and pr.routing_type == '装夹预调'),
key=lambda w1: w1.create_date)
new_cnc_workorder = new_production.workorder_ids.filtered(
lambda
nc: nc.processing_panel == panel and nc.routing_type == 'CNC加工')
new_cnc_workorder.write({'cnc_worksheet': scrap_cnc_workorder.cnc_worksheet})
new_pre_workorder = new_production.workorder_ids.filtered(lambda
p: p.routing_type == '装夹预调' and p.processing_panel == panel)
new_pre_workorder.write({'processing_drawing': scrap_pre_workorder.processing_drawing})

View File

@@ -6,14 +6,28 @@
<field name="arch" type="xml">
<form>
<sheet>
<field name="production_id" invisible="True"/>
<field name="production_id" invisible="1"/>
<field name="programming_states" invisible="1"/>
<div>
重新生成制造订单
<field name="is_remanufacture"/>
<field name="is_remanufacture" force_save="1"/>
</div>
<div>
申请重新编程
<field name="is_reprogramming" attrs='{"invisible": [("is_remanufacture","=",False)]}'/>
<div attrs='{"invisible": [("reprogramming_num","=",0)]}'>
注意: 该制造订单产品已申请重新编程次数为<field
name="reprogramming_num" string=""
readonly="1"
style='color:red;'/>,且当前编程状态为
<field name="programming_states" string=""
decoration-info="programming_states == '待编程'"
decoration-success="programming_states == '已下发'"
decoration-warning="programming_states =='编程中'"
decoration-danger="programming_states =='已编程'" readonly="1"/>
</div>
<div attrs='{"invisible": [("is_remanufacture","=",False)]}'>
<span style='font-weight:bold;'>申请重新编程
<field name="is_reprogramming" force_save="1"
attrs='{"readonly": [("programming_states","not in",["已下发"])]}'/>
</span>
</div>
<footer>
<button string="确认" name="confirm" type="object" class="oe_highlight" confirm="是否确认报废"/>
@@ -28,6 +42,9 @@
<field name="name">报废</field>
<field name="res_model">sf.production.wizard</field>
<field name="view_mode">form</field>
<!-- <field name="context">{-->
<!-- 'default_production_id': active_id}-->
<!-- </field>-->
<field name="target">new</field>
</record>

View File

@@ -25,6 +25,7 @@ class ReworkWizard(models.TransientModel):
processing_panel_id = fields.Many2many('sf.processing.panel', string="加工面")
is_reprogramming = fields.Boolean(string='申请重新编程', default=False)
is_reprogramming_readonly = fields.Boolean(string='申请重新编程(只读)', default=False)
is_clamp_measure = fields.Boolean(string='保留装夹测量数据', default=True)
reprogramming_num = fields.Integer('重新编程次数', default=0)
programming_state = fields.Selection(
[('待编程', '待编程'), ('编程中', '编程中'), ('已编程', '已编程'), ('已编程未下发', '已编程未下发'),
@@ -35,6 +36,7 @@ class ReworkWizard(models.TransientModel):
def confirm(self):
if self.routing_type in ['装夹预调', 'CNC加工']:
self.is_clamp_measure = False
self.workorder_id.is_rework = True
self.production_id.write({'detection_result_ids': [(0, 0, {
'rework_reason': self.rework_reason,
@@ -58,22 +60,18 @@ class ReworkWizard(models.TransientModel):
if processing_panels_missing:
processing_panels_str = ','.join(processing_panels_missing)
raise UserError('您还有待处理的检测结果中为%s的加工面未选择' % processing_panels_str)
# processing_panels = set()
# for handle_item in handle_result:
# for dr_panel in self.processing_panel_id:
# if dr_panel.name == handle_item.processing_panel:
# processing_panels.add(dr_panel.name)
# if len(processing_panels) != len(handle_result):
# processing_panels_str = ','.join(processing_panels)
# return UserError(f'您还有待处理的检测结果中为{processing_panels_str}的加工面未选择')
for panel in self.processing_panel_id:
panel_workorder = self.production_id.workorder_ids.filtered(
lambda ap: ap.processing_panel == panel.name and ap.state != 'rework')
if panel_workorder:
panel_workorder.write({'state': 'rework'})
panel_workorder.filtered(
lambda wo: wo.routing_type == '装夹预调').workpiece_delivery_ids.filtered(
lambda wd: wd.status == '待下发').write({'status': '已取消'})
rework_clamp_workorder = max(panel_workorder.filtered(
lambda
rp: rp.processing_panel == panel.name and rp.routing_type == '装夹预调' and rp.state in [
'done', 'rework']))
# panel_workorder.filtered(
# lambda wo: wo.routing_type == '装夹预调').workpiece_delivery_ids.filtered(
# lambda wd: wd.status == '待下发').write({'status': '已取消'})
# workpiece = self.env['sf.workpiece.delivery'].search([('status', '=', '待下发'), (
# 'workorder_id', '=',
# panel_workorder.filtered(lambda wd: wd.routing_type == '装夹预调').id)])
@@ -93,6 +91,43 @@ class ReworkWizard(models.TransientModel):
self.production_id.detection_result_ids.filtered(
lambda ap1: ap1.processing_panel == panel.name and ap1.handle_result == '待处理').write(
{'handle_result': '已处理'})
new_pre_workorder = self.production_id.workorder_ids.filtered(lambda
p: p.routing_type == '装夹预调' and p.processing_panel == panel.name and p.state not in (
'rework', 'done'))
if new_pre_workorder and rework_clamp_workorder and self.is_clamp_measure is True:
new_pre_workorder.write(
{'X1_axis': rework_clamp_workorder.X1_axis, 'Y1_axis': rework_clamp_workorder.Y1_axis
, 'Z1_axis': rework_clamp_workorder.Z1_axis,
'X2_axis': rework_clamp_workorder.X2_axis
, 'Y2_axis': rework_clamp_workorder.Y2_axis,
'Z2_axis': rework_clamp_workorder.Z2_axis
, 'X3_axis': rework_clamp_workorder.X3_axis,
'Y3_axis': rework_clamp_workorder.Y3_axis
, 'Z3_axis': rework_clamp_workorder.Z3_axis,
'X4_axis': rework_clamp_workorder.X4_axis
, 'Y4_axis': rework_clamp_workorder.Y4_axis,
'Z4_axis': rework_clamp_workorder.Z4_axis
, 'X5_axis': rework_clamp_workorder.X5_axis,
'Y5_axis': rework_clamp_workorder.Y5_axis
, 'Z5_axis': rework_clamp_workorder.Z5_axis,
'X6_axis': rework_clamp_workorder.X6_axis
, 'Y6_axis': rework_clamp_workorder.Y6_axis,
'Z6_axis': rework_clamp_workorder.Z6_axis
, 'X7_axis': rework_clamp_workorder.X7_axis,
'Y7_axis': rework_clamp_workorder.Y7_axis
, 'Z7_axis': rework_clamp_workorder.Z7_axis,
'X8_axis': rework_clamp_workorder.X8_axis
, 'Y8_axis': rework_clamp_workorder.Y8_axis,
'Z8_axis': rework_clamp_workorder.Z8_axis
, 'X9_axis': rework_clamp_workorder.X9_axis,
'Y9_axis': rework_clamp_workorder.Y9_axis
, 'Z9_axis': rework_clamp_workorder.Z9_axis,
'X10_axis': rework_clamp_workorder.X10_axis
, 'Y10_axis': rework_clamp_workorder.Y10_axis,
'Z10_axis': rework_clamp_workorder.Z10_axis
, 'X_deviation_angle': rework_clamp_workorder.X_deviation_angle,
'material_center_point': rework_clamp_workorder.material_center_point
})
if self.is_reprogramming is False:
if self.programming_state in ['已编程', '已下发']:
if self.reprogramming_num >= 1 and self.programming_state == '已编程':
@@ -149,9 +184,7 @@ class ReworkWizard(models.TransientModel):
'cmm_ids': new_cnc_workorder.cmm_ids.sudo()._json_cmm_program(panel.name,
ret),
'cnc_worksheet': cnc_rework.cnc_worksheet})
new_pre_workorder = self.production_id.workorder_ids.filtered(lambda
p: p.routing_type == '装夹预调' and p.processing_panel == panel.name and p.state not in (
'rework', 'done'))
if new_pre_workorder:
pre_rework = max(self.production_id.workorder_ids.filtered(
lambda pr: pr.processing_panel == panel.name and pr.state in (

View File

@@ -14,17 +14,25 @@
<group>
<field name="processing_panel_id" options="{'no_create': True}"
attrs='{"invisible": [("routing_type","=","装夹预调")]}' widget="many2many_tags"/>
</group>
<div attrs='{"invisible": [("routing_type","=","装夹预调")]}'>
<span style='font-weight:bold;'>保留装夹测量数据
<field name="is_clamp_measure" force_save="1"/>
</span>
</div>
<div attrs='{"invisible": [("reprogramming_num","=",0)]}'>
注意: 该制造订单的产品已重复编程过<field
name="reprogramming_num" string=""
readonly="1"
style='color:red;'/>次,且当前编程状态为
<field name="programming_state" string=""
decoration-info="programming_state == '待编程'"
decoration-success="programming_state == '已下发'"
decoration-warning="programming_state =='编程中'"
decoration-danger="programming_state =='编程'" readonly="1"/>
<span style='font-weight:bold;'>
注意: 该制造订单产品已申请重新编程次数为<field
name="reprogramming_num" string=""
readonly="1"
style='color:red;'/>,且当前编程状态为
<field name="programming_state" string=""
decoration-info="programming_state == '待编程'"
decoration-success="programming_state == '已下发'"
decoration-warning="programming_state =='编程'"
decoration-danger="programming_state =='已编程'" readonly="1"/>
</span>
</div>
<div attrs='{"invisible": ["|",("routing_type","in",["装夹预调","CNC加工"]),("programming_state","not in",["已下发"])],"readonly": [("tool_state", "=", "2")]}'>
<span style='font-weight:bold;'>申请重新编程

View File

@@ -4,30 +4,22 @@
<field name="name">sf.workpiece.delivery.wizard.form.view</field>
<field name="model">sf.workpiece.delivery.wizard</field>
<field name="arch" type="xml">
<form>
<form js_class="remove_focus_form_view">
<sheet>
<field name="delivery_ids" invisible="True"/>
<field name="workorder_id" invisible="True"/>
<field name="type" invisible="True"/>
<group attrs="{'invisible': [('type', 'in', ['运送空料架'])]}">
<field name="workorder_ids" invisible="True"/>
<field name="delivery_type" invisible="True"/>
<field name="confirm_button" invisible="1"/>
<field name="_barcode_scanned" widget="barcode_handler"/>
<group col="1">
<field name="production_ids" readonly="1" widget="many2many_tags" string="制造订单号"/>
<div class="o_address_format">
<lable for="rfid_code"></lable>
<field name="rfid_code" class="o_address_zip"/>
<button name="recognize_production" string="识别" type="object" class="oe_highlight"/>
</div>
<field name="destination_production_line_id" readonly="1"/>
<field name="route_id"/>
<field name="delivery_type" readonly="1"/>
<field name="feeder_station_start_id" string="当前接驳站" options="{'no_create': True}" required="1"/>
<field name="workcenter_id" options="{'no_create': True}"/>
</group>
<group attrs="{'invisible': [('type', 'in', ['运送空料架'])]}">
<field name="feeder_station_start_id" focesave="1" readonly="1"/>
<field name="feeder_station_destination_id" focesave="1" readonly="1"/>
</group>
<div attrs="{'invisible': [('type', 'in', ['上产线','下产线'])]}">
是否确定配送
</div>
<footer>
<button string="配送" name="confirm" type="object" class="oe_highlight"/>
<button string="确认配送" name="confirm" type="object" class="oe_highlight o_wizard_confirm_button jikimo_button_confirm" attrs="{'invisible': [('confirm_button', '!=', '确认配送')]}"/>
<button string="确认解除" name="confirm" type="object" class="oe_highlight o_wizard_confirm_button jikimo_button_confirm" attrs="{'invisible': [('confirm_button', '!=', '确认解除')]}"/>
<button string="取消" class="btn btn-secondary" special="cancel"/>
</footer>
</sheet>

View File

@@ -1,88 +1,235 @@
# -*- coding: utf-8 -*-
# Part of YiZuo. See LICENSE file for full copyright and licensing details.
import logging
from odoo.exceptions import UserError, ValidationError
from datetime import datetime
from odoo import models, api, fields, _
from datetime import datetime, date
from odoo.exceptions import UserError
from odoo import models, api, fields
def convert_datetime(obj):
if isinstance(obj, (datetime, date)):
return obj.isoformat() # 将 datetime 或 date 对象转换为 ISO 8601 字符串格式
raise TypeError(f"Type {type(obj)} not serializable")
class WorkpieceDeliveryWizard(models.TransientModel):
_name = 'sf.workpiece.delivery.wizard'
_inherit = ["barcodes.barcode_events_mixin"]
_description = '工件配送'
delivery_ids = fields.Many2many('sf.workpiece.delivery', string='配送')
rfid_code = fields.Char('rfid码')
workorder_id = fields.Many2one('mrp.workorder', string='')
delivery_ids = fields.Many2many('sf.workpiece.delivery', string='配送')
workorder_ids = fields.Many2many('mrp.workorder', string='工单')
production_ids = fields.Many2many('mrp.production', string='制造订单号')
destination_production_line_id = fields.Many2one('sf.production.line', '目的生产线')
route_id = fields.Many2one('sf.agv.task.route', '任务路线', domain=[('route_type', 'in', ['上产线', '下产线'])])
feeder_station_start_id = fields.Many2one('sf.agv.site', '起点接驳站')
feeder_station_destination_id = fields.Many2one('sf.agv.site', '目的接驳站')
type = fields.Selection(
[('上产线', '上产线'), ('下产线', '下产线'), ('运送空料架', '运送空料架')], string='类型')
workcenter_id = fields.Many2one(string='所属区域', comodel_name='mrp.workcenter', tracking=True)
confirm_button = fields.Char('按钮名称')
@api.onchange('delivery_type')
def _onchange_type(self):
if self.delivery_type:
routes = self.env['sf.agv.task.route'].search([('route_type', '=', self.delivery_type)])
if self.workcenter_id:
routes = routes.filtered(lambda a: a.start_site_id.workcenter_id.id == self.workcenter_id.id)
start_site_ids = routes.mapped('start_site_id.id')
workcenter_ids = routes.mapped('end_site_id.workcenter_id.id')
if workcenter_ids:
self.workcenter_id = workcenter_ids[0]
return {
'domain':
{
'feeder_station_start_id': [('id', 'in', start_site_ids)],
'workcenter_id': [('id', 'in', workcenter_ids)],
}
}
else:
return {
'domain':
{
'feeder_station_start_id': [],
'workcenter_id': [],
}
}
def _get_agv_route_type_selection(self):
return self.env['sf.agv.task.route'].fields_get(['route_type'])['route_type']['selection']
delivery_type = fields.Selection(selection=_get_agv_route_type_selection, string='类型')
def dispatch_confirm(self):
if len(self.workorder_ids) < 4:
return {
'type': 'ir.actions.client',
'tag': 'dispatch_confirm',
'params': {
'workorder_count': len(self.workorder_ids),
'active_id': self.id,
'context': self.env.context
}
}
else:
scheduling = self.confirm()
# 显示通知
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'target': 'new',
'params': {
'message': f'任务下发成功AGV任务调度编号为【{scheduling["name"]}',
'type': 'success',
'sticky': False,
'next': {'type': 'ir.actions.act_window_close'},
}
}
def confirm(self):
if self.type != '运送空料架':
if not self.route_id:
raise UserError('请选择路线')
if self.workorder_id:
self.workorder_id.workpiece_delivery_ids[0]._delivery_avg()
else:
is_not_production_line = 0
same_production_line_id = None
notsame_production_line_arr = []
for item in self.production_ids:
if same_production_line_id is None:
same_production_line_id = item.production_line_id.id
if item.production_line_id.id != same_production_line_id:
notsame_production_line_arr.append(item.name)
notsame_production_line_str = ','.join(map(str, notsame_production_line_arr))
if is_not_production_line >= 1:
raise UserError('制造订单号为%s的目的生产线不一致' % notsame_production_line_str)
else:
self.delivery_ids._delivery_avg()
try:
if not self.workorder_ids:
raise UserError('制造订单不能为空')
def recognize_production(self):
# production_ids = []
# delivery_ids = []
# aa = self.production_ids.workorder_ids.filtered(
# lambda b: b.routing_type == "装夹预调").workpiece_delivery_ids.filtered(
# lambda c: c.rfid_code == self.rfid_code)
# logging.info('aa:%s' % aa)
if len(self.production_ids) == 4:
raise UserError('只能配送四个制造订单')
else:
if self.rfid_code:
wd = self.env['sf.workpiece.delivery'].search(
[('type', '=', self.delivery_ids[0].type), ('rfid_code', '=', self.rfid_code),
('status', '=', self.delivery_ids[0].status)])
if wd:
if wd.production_line_id.id == self.delivery_ids[0].production_line_id.id:
# production_ids.append(wd.production_id)
# delivery_ids.append(wd.id)
# 将对象添加到对应的同模型且是多对多类型里
self.production_ids |= wd.production_id
self.delivery_ids |= wd
self.rfid_code = False
# self.production_ids = [(6, 0, production_ids)]
# self.delivery_ids = [(6, 0, delivery_ids)]
else:
raise UserError('该rfid对应的制造订单号为%s的目的生产线不一致' % wd.production_id.name)
return {
'name': _('确认'),
'type': 'ir.actions.act_window',
'view_mode': 'form',
'res_model': 'sf.workpiece.delivery.wizard',
'target': 'new',
'context': {
'default_delivery_ids': [(6, 0, self.delivery_ids.ids)],
'default_production_ids': [(6, 0, self.production_ids.ids)],
'default_route_id': self.delivery_ids[0].route_id.id,
'default_type': self.delivery_ids[0].type
}}
scheduling = self.env['sf.agv.scheduling'].add_scheduling(
agv_start_site_name=self.feeder_station_start_id.name,
agv_route_type=self.delivery_type,
workorders=self.workorder_ids,
)
# 如果关联了工件配送单,则修改状态为已下发
if self.delivery_ids:
val = {
'status': '已下发',
'agv_scheduling_id': scheduling.id,
'feeder_station_start_id': scheduling.start_site_id.id,
}
# 如果agv任务已经下发则修改工件配送单信息
if scheduling.state == '配送中':
val.update({
'feeder_station_destination_id': scheduling.end_site_id.id,
'route_id': scheduling.agv_route_id.id,
'task_delivery_time': fields.Datetime.now()
})
self.delivery_ids.write(val)
# 如果是解除装夹工单,则需要处理工单逻辑
for item in self.workorder_ids:
if item.routing_type == '解除装夹' and item.state == 'ready':
item.button_start()
item.button_finish()
# return scheduling.read()[0]
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'target': 'new',
'params': {
'message': f'任务下发成功AGV任务调度编号为【{scheduling.name}',
'type': 'success',
'sticky': False,
'next': {'type': 'ir.actions.act_window_close'},
}
}
except Exception as e:
logging.info('%s任务下发失败:%s', self.delivery_type, e)
raise UserError(f'{self.delivery_type}任务下发失败:{e}') from e
# def recognize_production(self):
# # production_ids = []
# # delivery_ids = []
# # aa = self.production_ids.workorder_ids.filtered(
# # lambda b: b.routing_type == "装夹预调").workpiece_delivery_ids.filtered(
# # lambda c: c.rfid_code == self.rfid_code)
# # logging.info('aa:%s' % aa)
# if len(self.production_ids) == 4:
# raise UserError('只能配送四个制造订单')
# else:
# if self.rfid_code:
# wd = self.env['sf.workpiece.delivery'].search(
# [('type', '=', self.delivery_ids[0].type), ('rfid_code', '=', self.rfid_code),
# ('status', '=', self.delivery_ids[0].status)])
# if wd:
# if wd.production_line_id.id == self.delivery_ids[0].production_line_id.id:
# # production_ids.append(wd.production_id)
# # delivery_ids.append(wd.id)
# # 将对象添加到对应的同模型且是多对多类型里
# self.production_ids |= wd.production_id
# self.delivery_ids |= wd
# self.rfid_code = False
# # self.production_ids = [(6, 0, production_ids)]
# # self.delivery_ids = [(6, 0, delivery_ids)]
# else:
# raise UserError('该rfid对应的制造订单号为%s的目的生产线不一致' % wd.production_id.name)
# return {
# 'name': _('确认'),
# 'type': 'ir.actions.act_window',
# 'view_mode': 'form',
# 'res_model': 'sf.workpiece.delivery.wizard',
# 'target': 'new',
# 'context': {
# 'default_delivery_ids': [(6, 0, self.delivery_ids.ids)],
# 'default_production_ids': [(6, 0, self.production_ids.ids)],
# 'default_route_id': self.delivery_ids[0].route_id.id,
# 'default_type': self.delivery_ids[0].type
# }}
@api.onchange('route_id')
def onchange_route(self):
if self.route_id:
self.feeder_station_start_id = self.route_id.start_site_id.id
self.feeder_station_destination_id = self.route_id.end_site_id.id
def on_barcode_scanned(self, barcode):
delivery_type = self.env.context.get('default_delivery_type')
# 判断barcode是否是数字
if not barcode.isdigit():
# 判断是否是AGV接驳站名称
agv_site = self.env['sf.agv.site'].search([('name', '=', barcode)])
self.feeder_station_start_id = agv_site.id # 修正:移除 .id
return
if delivery_type == '上产线':
workorder = self.env['mrp.workorder'].search(
[('production_line_state', '=', '待上产线'), ('rfid_code', '=', barcode),
('state', '=', 'done')])
# 找到对应的配送单
delivery = self.env['sf.workpiece.delivery'].search(
[('type', '=', '上产线'), ('rfid_code', '=', barcode),
('status', '=', '待下发')])
if delivery:
self.delivery_ids |= delivery
elif delivery_type == '运送空料架':
workorder = self.env['mrp.workorder'].search(
[('routing_type', '=', '解除装夹'), ('rfid_code', '=', barcode),
('state', '=', 'ready')])
if workorder:
if (len(self.production_ids) > 0 and
workorder.production_line_id.id != self.production_ids[0].production_line_id.id):
raise UserError(f'该rfid对应的制造订单号为{workorder.production_id.name}的目的生产线不一致')
# 调用打印成品条码方法
workorder.print_method()
# 将对象添加到对应的同模型且是多对多类型里
self.production_ids |= workorder.production_id
self.workorder_ids |= workorder
down_product_agv_scheduling = workorder.get_down_product_agv_scheduling()
if down_product_agv_scheduling:
if not self.feeder_station_start_id:
self.feeder_station_start_id = down_product_agv_scheduling.end_site_id.id
else:
if self.feeder_station_start_id.id != down_product_agv_scheduling.end_site_id.id:
raise UserError(f'该rfid不在{self.feeder_station_start_id.name}接驳站内')
else:
raise UserError('该rfid码对应的工单不存在')
return
@api.onchange('feeder_station_start_id')
def on_start_id_change(self):
if self.delivery_type == '运送空料架' and len(self.workorder_ids) > 0:
down_product_agv_scheduling = self.workorder_ids[0].get_down_product_agv_scheduling()
if down_product_agv_scheduling and self.feeder_station_start_id \
and down_product_agv_scheduling.end_site_id.id != self.feeder_station_start_id.id:
raise UserError('当前接驳站不匹配!')

File diff suppressed because it is too large Load Diff

1
sf_message/__init__.py Normal file
View File

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

View File

@@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name': '机企猫智能工厂 消息提醒',
'version': '1.0',
'summary': '智能工厂消息提醒模块',
'sequence': 1,
'description': """
""",
'category': 'sf',
'website': 'https://www.sf.jikimo.com',
'depends': ['base', 'sf_plan', 'sf_sale'],
'data': [
'security/ir.model.access.csv',
'views/sf_message_template_view.xml',
],
'test': [
],
'license': 'LGPL-3',
'installable': True,
'auto_install': False,
'application': False,
}

View File

@@ -0,0 +1,8 @@
from . import sf_message_template
from . import sf_message_sale
from . import sf_message_plan
from . import sf_message_stock_picking
from . import sf_message_cam_program
from . import sf_message_functional_tool_assembly
from . import sf_message_purchase
from . import sf_message_workorder

View File

@@ -0,0 +1,6 @@
from odoo import models, fields, api, _
class SFMessageCamProgram(models.Model):
_name = 'sf.cam.work.order.program.knife.plan'
_inherit = ['sf.cam.work.order.program.knife.plan', 'sf.message.template']

View File

@@ -0,0 +1,6 @@
from odoo import models, fields, api, _
class SFMessagefunctionalToolAssembly(models.Model):
_name = 'sf.functional.tool.assembly'
_inherit = ['sf.functional.tool.assembly', 'sf.message.template']

View File

@@ -0,0 +1,6 @@
from odoo import models, fields, api, _
class SFMessagePlan(models.Model):
_name = 'sf.production.plan'
_inherit = ['sf.production.plan', 'sf.message.template']

View File

@@ -0,0 +1,6 @@
from odoo import models, fields, api, _
class SFMessagePurchase(models.Model):
_name = 'purchase.order'
_inherit = ['purchase.order', 'sf.message.template']

View File

@@ -0,0 +1,11 @@
from odoo import models, fields, api, _
class SFMessageSale(models.Model):
_name = 'sale.order'
_inherit = ['sale.order', 'sf.message.template']
# def create(self):
# res = super(SFMessageSale, self).create()
# if res is True:

View File

@@ -0,0 +1,6 @@
from odoo import models, fields, api, _
class SFMessageStockPicking(models.Model):
_name = 'stock.picking'
_inherit = ['stock.picking', 'sf.message.template']

View File

@@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
from odoo import models, fields, api
from abc import ABC, abstractmethod
class SfMessageTemplate(models.Model):
_name = "sf.message.template"
_description = u'消息模板'
name = fields.Char(string=u"名称", required=True)
description = fields.Char(string=u"描述")
content = fields.Html(string=u"内容", render_engine='qweb', translate=True, prefetch=True, sanitize=False)
msgtype = fields.Selection(
[('text', u'文字'), ('markdown', u'Markdown')], u'消息类型',
required=True, default='markdown')
notification_department_id = fields.Many2one('hr.department', u'通知部门', required=True)
notification_employee_ids = fields.Many2many('hr.employee', string=u'员工',
domain="[('department_id', '=',notification_department_id)]",
required=True)
is_send_time = fields.Boolean(string=u"定时发送", default=False)
send_time_1 = fields.Integer('发送时间点1')
send_time_2 = fields.Integer('发送时间点2')
active = fields.Boolean(string=u"是否有效", default=True)
@api.onchange('notification_department_id')
def _clear_employee_ids(self):
if self.notification_department_id:
self.notification_employee_ids = False
@abstractmethod
def dispatch(self, args):
"""
强迫继承该类必走该抽象方法'
"""

View File

@@ -0,0 +1,6 @@
from odoo import models, fields, api, _
class SFMessageWork(models.Model):
_name = 'mrp.workorder'
_inherit = ['mrp.workorder', 'sf.message.template']

View File

@@ -0,0 +1,5 @@
<odoo>
<data>
</data>
</odoo>

View File

@@ -0,0 +1,15 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_sf_message_template_group_sale_salemanager,sf_message_template,model_sf_message_template,sf_base.group_sale_salemanager,1,1,1,0
access_sf_message_template_group_purchase,sf_message_template,model_sf_message_template,sf_base.group_purchase,1,1,1,0
access_sf_message_template_group_sf_stock_user,sf_message_template,model_sf_message_template,sf_base.group_sf_stock_user,1,1,1,0
access_sf_message_template_group_sf_order_user,sf_message_template,model_sf_message_template,sf_base.group_sf_order_user,1,1,1,0
access_sf_message_template_group_sf_tool_user,sf_message_template,model_sf_message_template,sf_base.group_sf_tool_user,1,1,1,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_sf_message_template_group_sale_salemanager sf_message_template model_sf_message_template sf_base.group_sale_salemanager 1 1 1 0
3 access_sf_message_template_group_purchase sf_message_template model_sf_message_template sf_base.group_purchase 1 1 1 0
4 access_sf_message_template_group_sf_stock_user sf_message_template model_sf_message_template sf_base.group_sf_stock_user 1 1 1 0
5 access_sf_message_template_group_sf_order_user sf_message_template model_sf_message_template sf_base.group_sf_order_user 1 1 1 0
6 access_sf_message_template_group_sf_tool_user sf_message_template model_sf_message_template sf_base.group_sf_tool_user 1 1 1 0

View File

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

View File

@@ -10,11 +10,12 @@
""",
'category': 'sf',
'website': 'https://www.sf.cs.jikimo.com',
'depends': ['sf_base', 'base_setup'],
'depends': ['sf_base', 'base_setup','sf_bf_connect'],
'data': [
'data/ir_cron_data.xml',
'security/ir.model.access.csv',
'views/res_config_settings_views.xml'
'views/res_config_settings_views.xml',
'views/order_price.xml',
],
'demo': [
],

View File

@@ -24,11 +24,13 @@ class Sf_Mrs_Connect(http.Controller):
ret = json.loads(datas)
ret = json.loads(ret['result'])
logging.info('下发编程单:%s' % ret)
domain = [('programming_no', '=', ret['programming_no'])]
if ret['manufacturing_type'] == 'scrap':
domain += [('state', 'not in', ['done', 'scrap', 'cancel'])]
productions = request.env['mrp.production'].with_user(
request.env.ref("base.user_admin")).search(
[('programming_no', '=', ret['programming_no'])])
request.env.ref("base.user_admin")).search(domain)
if productions:
# # 拉取所有加工面的程序文件
# 拉取所有加工面的程序文件
for r in ret['processing_panel'].split(','):
program_path_tmp_r = os.path.join('/tmp', ret['folder_name'], 'return', r)
if os.path.exists(program_path_tmp_r):
@@ -48,45 +50,28 @@ class Sf_Mrs_Connect(http.Controller):
if not production.workorder_ids:
production.product_id.model_processing_panel = ret['processing_panel']
production._create_workorder(ret)
# else:
# for panel in ret['processing_panel'].split(','):
# # 查询状态为进行中且工序类型为CNC加工的工单
# cnc_workorder = production.workorder_ids.filtered(
# lambda ac: ac.routing_type == 'CNC加工' and ac.state not in ['progress', 'done',
# 'cancel'] and ac.processing_panel == panel)
# if cnc_workorder:
# if cnc_workorder.cnc_ids:
# cnc_workorder.cmm_ids.sudo().unlink()
# cnc_workorder.cnc_ids.sudo().unlink()
# request.env['sf.cam.work.order.program.knife.plan'].sudo().unlink_cam_plan(
# production)
# # program_path_tmp_panel = os.path.join('C://Users//43484//Desktop//fsdownload//test',
# # panel)
# program_path_tmp_panel = os.path.join('/tmp', ret['folder_name'], 'return', panel)
# logging.info('program_path_tmp_panel:%s' % program_path_tmp_panel)
# files_panel = os.listdir(program_path_tmp_panel)
# if files_panel:
# for file in files_panel:
# file_extension = os.path.splitext(file)[1]
# logging.info('file_extension:%s' % file_extension)
# if file_extension.lower() == '.pdf':
# panel_file_path = os.path.join(program_path_tmp_panel, file)
# logging.info('panel_file_path:%s' % panel_file_path)
# cnc_workorder.write(
# {'cnc_ids': cnc_workorder.cnc_ids.sudo()._json_cnc_processing(panel, ret),
# 'cmm_ids': cnc_workorder.cmm_ids.sudo()._json_cmm_program(panel, ret),
# 'cnc_worksheet': base64.b64encode(open(panel_file_path, 'rb').read())})
# pre_workorder = production.workorder_ids.filtered(
# lambda ap: ap.routing_type == '装夹预调' and ap.state not in ['done',
# 'cancel'] and ap.processing_panel == panel)
# if pre_workorder:
# pre_workorder.write(
# {'processing_drawing': base64.b64encode(open(panel_file_path, 'rb').read())})
productions.process_range_time()
else:
for panel in ret['processing_panel'].split(','):
# 查询状态为进行中且工序类型为CNC加工的工单
cnc_workorder_has = production.workorder_ids.filtered(
lambda ach: ach.routing_type == 'CNC加工' and ach.state not in ['progress', 'done',
'rework',
'cancel'] and ach.processing_panel == panel)
if cnc_workorder_has:
if cnc_workorder_has.cnc_ids:
cnc_workorder_has.cmm_ids.sudo().unlink()
cnc_workorder_has.cnc_ids.sudo().unlink()
request.env['sf.cam.work.order.program.knife.plan'].sudo().unlink_cam_plan(
production)
cnc_workorder_has.write(
{'cnc_ids': cnc_workorder_has.cnc_ids.sudo()._json_cnc_processing(panel, ret),
'cmm_ids': cnc_workorder_has.cmm_ids.sudo()._json_cmm_program(panel, ret)})
for panel in ret['processing_panel'].split(','):
# 查询状态为进行中且工序类型为CNC加工的工单
cnc_workorder = productions.workorder_ids.filtered(
lambda ac: ac.routing_type == 'CNC加工' and ac.state not in ['progress', 'done',
'cancel'] and ac.processing_panel == panel)
lambda ac: ac.routing_type == 'CNC加工' and ac.state not in ['progress', 'done', 'rework'
'cancel'] and ac.processing_panel == panel)
if cnc_workorder:
# program_path_tmp_panel = os.path.join('C://Users//43484//Desktop//fsdownload//test',
# panel)
@@ -102,18 +87,12 @@ class Sf_Mrs_Connect(http.Controller):
logging.info('panel_file_path:%s' % panel_file_path)
cnc_workorder.write({'cnc_worksheet': base64.b64encode(open(panel_file_path, 'rb').read())})
pre_workorder = productions.workorder_ids.filtered(
lambda ap: ap.routing_type == '装夹预调' and ap.state not in ['done',
'cancel'] and ap.processing_panel == panel)
lambda ap: ap.routing_type == '装夹预调' and ap.state not in ['done', 'rework'
'cancel'] and ap.processing_panel == panel)
if pre_workorder:
pre_workorder.write(
{'processing_drawing': base64.b64encode(open(panel_file_path, 'rb').read())})
productions.write({'programming_state': '已编程', 'work_state': '已编程'})
cnc_program_ids = [item.id for item in productions]
workpiece_delivery = request.env['sf.workpiece.delivery'].sudo().search(
[('production_id', 'in', cnc_program_ids)])
if workpiece_delivery:
workpiece_delivery.write(
{'is_cnc_program_down': True, 'production_line_id': productions.production_line_id.id})
return json.JSONEncoder().encode(res)
else:
res = {'status': 0, 'message': '该制造订单暂未开始'}

View File

@@ -1,3 +1,4 @@
from . import ftp_operate
from . import res_config_setting
from . import sync_common
from . import order_price

View File

@@ -0,0 +1,29 @@
from odoo import fields, models, api
class OrderPrice(models.Model):
_name = 'order.price'
_description = '订单价格对比'
sale_order_id = fields.Many2one('sale.order', '销售订单')
bfm_order_name = fields.Char(related="sale_order_id.default_code", string='bfm订单号')
sale_order_name = fields.Char(related="sale_order_id.name", string='销售订单号')
currency_id = fields.Many2one(
related='sale_order_id.currency_id', string='货币', store=True)
sale_order_amount_total = fields.Monetary(related="sale_order_id.amount_total", tracking=4, string='销售订单金额')
bfm_amount_total = fields.Float(string='价格合计', compute='_compute_bfm_amount_total', store=True)
def is_float(self,value):
try:
float(value)
return True
except ValueError:
return False
@api.depends('sale_order_id.remark')
def _compute_bfm_amount_total(self):
for record in self:
amount_total = 0
for line in record.sale_order_id.order_line:
# 判断remark是否存在并且是否是数字
if line.remark and self.is_float(line.remark):
amount_total += float(line.remark)
record.bfm_amount_total = amount_total

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