Compare commits
759 Commits
2b7f4c3f06
...
feature/产品
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f7e6be7925 | ||
|
|
8695a66e3d | ||
|
|
410b384fd6 | ||
|
|
51b7bcac8a | ||
|
|
36ce43cf8a | ||
|
|
b4538a3f9d | ||
|
|
7d3a320893 | ||
|
|
0354f6b136 | ||
|
|
1e006b0bd7 | ||
|
|
50b0204cc6 | ||
|
|
72df0aa640 | ||
|
|
02bf6a6764 | ||
|
|
64581abeb1 | ||
|
|
82f80f1d15 | ||
|
|
f324a9d471 | ||
|
|
6103bca698 | ||
|
|
9a4477de8b | ||
|
|
5646cc492e | ||
|
|
d5c748db78 | ||
|
|
9c08021773 | ||
|
|
cf3ec1b6ae | ||
|
|
df89f40a24 | ||
|
|
5c24cec4f6 | ||
|
|
4379854b89 | ||
|
|
3a076bbdd1 | ||
|
|
bb519b8ab8 | ||
|
|
de26109ccc | ||
|
|
53e5aa2017 | ||
|
|
0183a5ab2b | ||
|
|
54c5259ed9 | ||
|
|
efdde5aef0 | ||
|
|
584dd11c61 | ||
|
|
635583826f | ||
|
|
cbd7b561de | ||
|
|
9c080e0cb4 | ||
|
|
1c61a8ef1c | ||
|
|
07ed60e8a7 | ||
|
|
7207d7eb36 | ||
|
|
9ede024710 | ||
|
|
cb8285d0ca | ||
|
|
3e3f49f8aa | ||
|
|
35cc1ce6dc | ||
|
|
b4b70e3cf0 | ||
|
|
39a2b1035a | ||
|
|
b370e34dca | ||
|
|
a6b5a823b8 | ||
|
|
24bcec8646 | ||
|
|
5a74c346a7 | ||
|
|
1c64ee9b90 | ||
|
|
c867b3c7bc | ||
|
|
a4413af2f3 | ||
|
|
f726bbaef6 | ||
|
|
53ce27d623 | ||
|
|
b88e4af4e2 | ||
|
|
a12c81e60d | ||
|
|
13415dd771 | ||
|
|
7ea6a78fbd | ||
|
|
d5aaa70013 | ||
|
|
f05d0461c3 | ||
|
|
b525a45107 | ||
|
|
6ab0bf7b5d | ||
|
|
f1335e8252 | ||
|
|
f0c8a82b43 | ||
|
|
f435fe3577 | ||
|
|
9bae3a4e5f | ||
|
|
e7808216ca | ||
|
|
e48c5e39ac | ||
|
|
0d2e043449 | ||
|
|
f2a822aeda | ||
|
|
6cdc547da5 | ||
|
|
c11dc4f9c4 | ||
|
|
f6c121771f | ||
|
|
db77b0b3ac | ||
|
|
9565927ba6 | ||
|
|
18d8212c3f | ||
|
|
1ca5817379 | ||
|
|
0185a3bc2b | ||
|
|
0c4407ce8e | ||
|
|
f11c88cf1b | ||
|
|
7e025e7ca1 | ||
|
|
4da7114655 | ||
|
|
e3bac55346 | ||
|
|
8c52c42074 | ||
|
|
ab9fcf97e0 | ||
|
|
f270f683de | ||
|
|
8e806225d0 | ||
|
|
56847c7a22 | ||
|
|
9973370fd6 | ||
|
|
3cb71a8017 | ||
|
|
cc72ddfad7 | ||
|
|
527ab396ee | ||
|
|
1c90c97b92 | ||
|
|
d70d3a9254 | ||
|
|
2d4ae18e64 | ||
|
|
92850fe34f | ||
|
|
17bbe1414b | ||
|
|
7f56a75722 | ||
|
|
51a9b55782 | ||
|
|
addc68ed5a | ||
|
|
5e9d541239 | ||
|
|
642a93c449 | ||
|
|
ff7151399f | ||
|
|
a67f45f9d5 | ||
|
|
98ef86866a | ||
|
|
f2c70fa167 | ||
|
|
1c0187d55b | ||
|
|
04244dd17a | ||
|
|
da63b0b7ff | ||
|
|
a088ee9ed5 | ||
|
|
ee78dda3a9 | ||
|
|
e13bd0dc61 | ||
|
|
9f57ad6aaf | ||
|
|
8c4996b7c2 | ||
|
|
cf2aaa38fe | ||
|
|
ac900dd3f0 | ||
|
|
0e762f9cbc | ||
|
|
4ee4b28389 | ||
|
|
d36acedaa3 | ||
|
|
1311d5be1e | ||
|
|
207cd83d3c | ||
|
|
37161e2e20 | ||
|
|
6461e3a423 | ||
|
|
76393d438b | ||
|
|
50ced99785 | ||
|
|
8e3a316200 | ||
|
|
fc7c66c615 | ||
|
|
2daeb01c4d | ||
|
|
1818e97289 | ||
|
|
e661297b5d | ||
|
|
926caeca97 | ||
|
|
403ba64e50 | ||
|
|
cdc3c52784 | ||
|
|
7000b66683 | ||
|
|
82f54b5d83 | ||
|
|
1af08763ea | ||
|
|
8f379a2635 | ||
|
|
96b0773c00 | ||
|
|
79f8cd21a9 | ||
|
|
5c129331e0 | ||
|
|
cddb025e98 | ||
|
|
1e2272c13a | ||
|
|
d955832bd8 | ||
|
|
4a52327acd | ||
|
|
136d0f5156 | ||
|
|
0254387c03 | ||
|
|
90f8c4143e | ||
|
|
0ef13504e7 | ||
|
|
40bf41c93d | ||
|
|
3f8aded61c | ||
|
|
f5c555ec86 | ||
|
|
3e7f145255 | ||
|
|
2a5a9de3e3 | ||
|
|
d2bca2ff51 | ||
|
|
f9d6a13d33 | ||
|
|
adcd2c39fc | ||
|
|
b37d547359 | ||
|
|
72f5496905 | ||
|
|
daa7c467f9 | ||
|
|
12c6959ba4 | ||
|
|
81fe1cf486 | ||
|
|
b5a8379d52 | ||
|
|
92fc988951 | ||
|
|
d03813db40 | ||
|
|
1b3b80f735 | ||
|
|
4efb6dc6d0 | ||
|
|
f58420ac46 | ||
|
|
7b2b15d601 | ||
|
|
b9ba29d276 | ||
|
|
e0baa2574a | ||
|
|
fced85f530 | ||
|
|
e80056938f | ||
|
|
b5c7be8de0 | ||
|
|
b0104e7b93 | ||
|
|
bd9b52e6ce | ||
|
|
af348c4d8f | ||
|
|
9e65f947f9 | ||
|
|
3226942ed3 | ||
|
|
2dfd3c9128 | ||
|
|
eb117aef86 | ||
|
|
3575f0c5c9 | ||
|
|
aa810bbda2 | ||
|
|
2c12f5b9b6 | ||
|
|
72b89288f2 | ||
|
|
cffda26ed0 | ||
|
|
eefabbd5b3 | ||
|
|
6bb46186b1 | ||
|
|
4ab1409b13 | ||
|
|
bba2c1d839 | ||
|
|
d9115333bf | ||
|
|
2b7243f69c | ||
|
|
a3c8082906 | ||
|
|
9bab450af1 | ||
|
|
7520d71adb | ||
|
|
4f0c7ad274 | ||
|
|
d6e36eea99 | ||
|
|
0ea69f41e2 | ||
|
|
de142bd371 | ||
|
|
cb14bb4ea8 | ||
|
|
22176eda69 | ||
|
|
bb75b73247 | ||
|
|
1b490951b1 | ||
|
|
f19af2a33f | ||
|
|
d0e92a649a | ||
|
|
687af76372 | ||
|
|
3acb32a5c2 | ||
|
|
8d7dcda582 | ||
|
|
fc2c1e06d9 | ||
|
|
6c57df8270 | ||
|
|
d042de9e84 | ||
|
|
bc6303d1af | ||
|
|
077ce6d37f | ||
|
|
0cf3e6e7d6 | ||
|
|
027537080d | ||
|
|
95d29bb20d | ||
|
|
461bc1f86e | ||
|
|
1bc09a4424 | ||
|
|
e6866552bc | ||
|
|
fd7b0630fe | ||
|
|
6e6575eadb | ||
|
|
cc6ec38bfa | ||
|
|
8eefbeba54 | ||
|
|
94a24bb469 | ||
|
|
82c0269761 | ||
|
|
631f72bfe9 | ||
|
|
b5147678b1 | ||
|
|
9047e54afa | ||
|
|
8a15ce12d9 | ||
|
|
4c3e7e40cb | ||
|
|
128dd60a89 | ||
|
|
f82cb462cf | ||
|
|
7f6025afc0 | ||
|
|
9bbe3f28a5 | ||
|
|
3f2a13448d | ||
|
|
e11976bb61 | ||
|
|
00541c1c8f | ||
|
|
cac7815369 | ||
|
|
c336230287 | ||
|
|
1a896a730e | ||
|
|
eaad8337d4 | ||
|
|
b4ee93bc5a | ||
|
|
3919290985 | ||
|
|
ec3f00f4a3 | ||
|
|
f15ac2c7fd | ||
|
|
cc9e6fa3d1 | ||
|
|
3c3ffa1ebc | ||
|
|
776515a861 | ||
|
|
8332c5d141 | ||
|
|
e6c77e7b35 | ||
|
|
1fab9ad253 | ||
|
|
e4de4f2af0 | ||
|
|
afdfde245a | ||
|
|
86366cc6cb | ||
|
|
4e6a66c681 | ||
|
|
f5805ce6ae | ||
|
|
8239e53a76 | ||
|
|
bbaede2166 | ||
|
|
6e68611f6e | ||
|
|
31dd710f6a | ||
|
|
8b2b58dfa1 | ||
|
|
84f62ebe1c | ||
|
|
ce2f8714d0 | ||
|
|
931b78ee03 | ||
|
|
61554bf3e5 | ||
|
|
0b070de19c | ||
|
|
7077b8a297 | ||
|
|
e8995acc87 | ||
|
|
fbaa81fe7a | ||
|
|
3742a3b163 | ||
|
|
498e1c12af | ||
|
|
317b5d4ced | ||
|
|
3c65b3e3df | ||
|
|
4dde30f9f9 | ||
|
|
631d59f95e | ||
|
|
8928d497ff | ||
|
|
99b1d5f534 | ||
|
|
61d13b90dc | ||
|
|
31bb7f0c97 | ||
|
|
d980a036cd | ||
|
|
f8c6c766cb | ||
|
|
41fe63d948 | ||
|
|
ce53afe1b0 | ||
|
|
bc4a4df53e | ||
|
|
3f448bc6da | ||
|
|
d1c10f56d1 | ||
|
|
edf4699e9e | ||
|
|
ad025eb6da | ||
|
|
e5bf0d8205 | ||
|
|
831a91c925 | ||
|
|
bc3325bd3b | ||
|
|
e29883d0de | ||
|
|
5b9b700372 | ||
|
|
c81dc99aef | ||
|
|
c0a3a550d7 | ||
|
|
0c67b2b659 | ||
|
|
974b112b3a | ||
|
|
57f5d138e8 | ||
|
|
2b117e9192 | ||
|
|
688a39363b | ||
|
|
9443a07eb4 | ||
|
|
ce58e989dd | ||
|
|
b9bb528db0 | ||
|
|
da8cbe4cce | ||
|
|
ce69127250 | ||
|
|
583f6503ec | ||
|
|
7f050b62f9 | ||
|
|
5d09d1585b | ||
|
|
f373003d2c | ||
|
|
45e8e380db | ||
|
|
c2263c9318 | ||
|
|
f09a6cde3e | ||
|
|
ccdbfda019 | ||
|
|
ec9435bb82 | ||
|
|
77db3d57c9 | ||
|
|
73c3e06900 | ||
|
|
56d8190fc6 | ||
|
|
7fe7de46c6 | ||
|
|
2339f75517 | ||
|
|
8ec038847a | ||
|
|
e1118bd579 | ||
|
|
c9af7a8cc4 | ||
|
|
4ab7e4db0f | ||
|
|
939a255c2e | ||
|
|
fbf86a69e3 | ||
|
|
1cf5cd41b4 | ||
|
|
860e16659c | ||
|
|
e9987fdcfa | ||
|
|
98847a2c42 | ||
|
|
f81bf760d4 | ||
|
|
b2bb2e33de | ||
|
|
8be6373b77 | ||
|
|
f3ec784383 | ||
|
|
a9c2d1aa5c | ||
|
|
8e61d5f87c | ||
|
|
032b13b2ad | ||
|
|
e33ca7cd33 | ||
|
|
3a7a6e480a | ||
|
|
51b67c0dcd | ||
|
|
8124818bad | ||
|
|
3a62d4406f | ||
|
|
8b8b30602b | ||
|
|
7a5fcd79d8 | ||
|
|
93fe4d8c62 | ||
|
|
cdeec93e76 | ||
|
|
1a2d9592d1 | ||
|
|
71a64c36ca | ||
|
|
5f026e3b1e | ||
|
|
d50f8716b5 | ||
|
|
6cd2637983 | ||
|
|
ab91ce01d4 | ||
|
|
8f1897c4ff | ||
|
|
1e2c80c38f | ||
|
|
db8ad0f425 | ||
|
|
eedce8338b | ||
|
|
b132cb8713 | ||
|
|
66d6fe8f0a | ||
|
|
97e57f9b3c | ||
|
|
57cfa56081 | ||
|
|
1d464dd00e | ||
|
|
fdc38afcbd | ||
|
|
2e9dc3d006 | ||
|
|
c54a8308c6 | ||
|
|
1934708d78 | ||
|
|
e7bfff491b | ||
|
|
97e36c249b | ||
|
|
6d93d5ef87 | ||
|
|
e8a0b3da93 | ||
|
|
e9acd98ccc | ||
|
|
535d69f4d9 | ||
|
|
603a59b6d7 | ||
|
|
ca2f30fdbd | ||
|
|
4c92c08f84 | ||
|
|
2fd8483a52 | ||
|
|
71bdd6334f | ||
|
|
194f6f52dc | ||
|
|
93ce482d40 | ||
|
|
96c5c3dcf5 | ||
|
|
6bcf7ec53a | ||
|
|
a7d760bc5e | ||
|
|
e196b6b1e3 | ||
|
|
9cb9872a5e | ||
|
|
58d4b3813b | ||
|
|
34d0e989d6 | ||
|
|
c52af21477 | ||
|
|
149d6778f5 | ||
|
|
98c9f3098b | ||
|
|
ff904ad68c | ||
|
|
932f82ac6c | ||
|
|
bbb5ddb177 | ||
|
|
7cbbf58309 | ||
|
|
8edee62d3a | ||
|
|
ce67b7985b | ||
|
|
ef47597cf9 | ||
|
|
9e8d5aaf6a | ||
|
|
363463e31d | ||
|
|
8ff635e901 | ||
|
|
c65e13a83e | ||
|
|
8721bc2de1 | ||
|
|
ec344cc918 | ||
|
|
905df2b79e | ||
|
|
e73fb5791a | ||
|
|
6738a855bb | ||
|
|
3c82020e5e | ||
|
|
422074fcec | ||
|
|
897f5b76f0 | ||
|
|
ee565d3796 | ||
|
|
912b50246a | ||
|
|
df2ba048f4 | ||
|
|
ef2f7d3ecb | ||
|
|
2391c08485 | ||
|
|
85ac3d7a3e | ||
|
|
b96723d9a5 | ||
|
|
19b9db66d3 | ||
|
|
8371875d62 | ||
|
|
a3f6fdda2a | ||
|
|
4a10335379 | ||
|
|
1132acfa40 | ||
|
|
7138dab1b5 | ||
|
|
6bf3df0ef4 | ||
|
|
55594c119f | ||
|
|
0a3bd37224 | ||
|
|
60abdfb372 | ||
|
|
facdf5712a | ||
|
|
94df139110 | ||
|
|
e4f6bc4632 | ||
|
|
6f0dbe3625 | ||
|
|
c00cd5a00a | ||
|
|
b487b6fc40 | ||
|
|
8489a67e64 | ||
|
|
f8426ae4c3 | ||
|
|
c4021d02ce | ||
|
|
bd01ad7bbf | ||
|
|
9650f45ba2 | ||
|
|
cfed77d1a5 | ||
|
|
94c795a68f | ||
|
|
2fba2ad488 | ||
|
|
31260e8921 | ||
|
|
4d04b37582 | ||
|
|
eec27b26f7 | ||
|
|
e300ca1822 | ||
|
|
c8a3bee099 | ||
|
|
35c051e730 | ||
|
|
950ec3a1e1 | ||
|
|
1c1a038156 | ||
|
|
640bf79dc8 | ||
|
|
1ccc32cbcb | ||
|
|
f8d8d885bb | ||
|
|
7c8c869172 | ||
|
|
8d5a4ed4c8 | ||
|
|
981872b0b1 | ||
|
|
d8a74c17f0 | ||
|
|
fe6d207099 | ||
|
|
206043a1a0 | ||
|
|
6a2a465569 | ||
|
|
1767ada489 | ||
|
|
d7f85967c9 | ||
|
|
1a95f5e4ac | ||
|
|
abd7364658 | ||
|
|
26ec1c9f6e | ||
|
|
490aa3fe04 | ||
|
|
924a28e957 | ||
|
|
e58ceb3ac8 | ||
|
|
61c3b16a69 | ||
|
|
70109c0965 | ||
|
|
74b4fd1367 | ||
|
|
c206dc3097 | ||
|
|
4c1c8e7683 | ||
|
|
0d8d54c05b | ||
|
|
71147eb7f9 | ||
|
|
c753df768d | ||
|
|
45df8f5bc2 | ||
|
|
29a55f3ff8 | ||
|
|
94c0b00c2d | ||
|
|
32473d302f | ||
|
|
2cf4958f46 | ||
|
|
893aa2111c | ||
|
|
6cf26e8029 | ||
|
|
e796bbe990 | ||
|
|
c2d2d16948 | ||
|
|
c3ba11bed4 | ||
|
|
37815d603a | ||
|
|
ca0b59e95b | ||
|
|
7c478ec4fd | ||
|
|
5b1d347fd4 | ||
|
|
e738d40b75 | ||
|
|
685eced709 | ||
|
|
ffc40c70d2 | ||
|
|
cc3ee289d3 | ||
|
|
487b452519 | ||
|
|
4a62af7545 | ||
|
|
07be7c3074 | ||
|
|
ddad1e9114 | ||
|
|
2c1a101c24 | ||
|
|
ab1af72727 | ||
|
|
bc186a9723 | ||
|
|
de04d452b3 | ||
|
|
66b808dfc9 | ||
|
|
ad36b37f27 | ||
|
|
e403f2f8e6 | ||
|
|
24b850a508 | ||
|
|
4d8b463cb3 | ||
|
|
9fef877d12 | ||
|
|
c323d9995e | ||
|
|
4f83c5f29a | ||
|
|
ed5f47cc31 | ||
|
|
66bb55a823 | ||
|
|
5926d71d27 | ||
|
|
c78ea6fbe5 | ||
|
|
96df8f971c | ||
|
|
35511effae | ||
|
|
54912f15b9 | ||
|
|
e8a13f1721 | ||
|
|
1532293918 | ||
|
|
030ef14633 | ||
|
|
bf8b45609c | ||
|
|
964618d365 | ||
|
|
06eeb1ed1f | ||
|
|
deb732dc5e | ||
|
|
5737d7b0bc | ||
|
|
5fd0beab95 | ||
|
|
858c163cbe | ||
|
|
fee3572f38 | ||
|
|
f2862af565 | ||
|
|
c1c3639611 | ||
|
|
41017412cd | ||
|
|
e552502fd1 | ||
|
|
61da25a031 | ||
|
|
aafafd682d | ||
|
|
98ed831a85 | ||
|
|
e9be2e9c43 | ||
|
|
b73a449b01 | ||
|
|
45d04e1a05 | ||
|
|
fc17063507 | ||
|
|
b3fbbeb85c | ||
|
|
97d760cd56 | ||
|
|
9d911a5c2b | ||
|
|
9bb3b88fd6 | ||
|
|
baaeac10eb | ||
|
|
2510f5fbf3 | ||
|
|
f77691251e | ||
|
|
5292826c72 | ||
|
|
6fed64ba2a | ||
|
|
8e5f5cf0d1 | ||
|
|
b4b5207aea | ||
|
|
ca61537e21 | ||
|
|
83da8f58e2 | ||
|
|
a36c30b5c1 | ||
|
|
ae6ec7183e | ||
|
|
cc58425f50 | ||
|
|
dda3aad95d | ||
|
|
d6dcb6bf55 | ||
|
|
4b672f3c23 | ||
|
|
423d5cec8e | ||
|
|
e6bb5db0e1 | ||
|
|
f0e66c6d90 | ||
|
|
8a1dfe14e6 | ||
|
|
5113de7e97 | ||
|
|
e06002e05a | ||
|
|
8b7b52ee2c | ||
|
|
6738f38131 | ||
|
|
ab115ab71c | ||
|
|
6ec6094c5e | ||
|
|
321c40d31d | ||
|
|
890b73e108 | ||
|
|
247b3e4444 | ||
|
|
7391b1324d | ||
|
|
d53e664881 | ||
|
|
b49b5890a0 | ||
|
|
690543e2d4 | ||
|
|
f296e1ba1a | ||
|
|
31f07c5156 | ||
|
|
63d6ce6da8 | ||
|
|
580f95f338 | ||
|
|
326181fa81 | ||
|
|
6fc735063a | ||
|
|
499261f62e | ||
|
|
6912160232 | ||
|
|
04e63dcc59 | ||
|
|
7ceaadb9c4 | ||
|
|
fdf1b786fe | ||
|
|
1da7a0195d | ||
|
|
b093b11ec2 | ||
|
|
718b1f9edf | ||
|
|
5bdd3982ae | ||
|
|
a606cbfc6d | ||
|
|
1a5fcf09e1 | ||
|
|
d2899fe38e | ||
|
|
24e75f8895 | ||
|
|
5bc5766507 | ||
|
|
49f021ed7a | ||
|
|
94031e68ad | ||
|
|
182348f427 | ||
|
|
c885f3ce8c | ||
|
|
e5b0960e3a | ||
|
|
dd5d4e7748 | ||
|
|
369980d655 | ||
|
|
2096d05cdb | ||
|
|
fbab054324 | ||
|
|
e3ff9e9fde | ||
|
|
c3ee544ca6 | ||
|
|
08581c8bc4 | ||
|
|
49cbf2fde2 | ||
|
|
2f2522c99e | ||
|
|
fefa14a47b | ||
|
|
329d7b6464 | ||
|
|
f36c2ac096 | ||
|
|
9c6367c053 | ||
|
|
076866e9b7 | ||
|
|
3a64a2106a | ||
|
|
ead39c9649 | ||
|
|
25d1a99239 | ||
|
|
9a318d45f3 | ||
|
|
41a9aa86a7 | ||
|
|
2322758e50 | ||
|
|
d216478679 | ||
|
|
b487ee127a | ||
|
|
2a964bc30e | ||
|
|
d0132dbc3a | ||
|
|
acccb4b6f9 | ||
|
|
48f75ad600 | ||
|
|
daeae46820 | ||
|
|
77535fa70e | ||
|
|
913780bc2b | ||
|
|
f566fc1c08 | ||
|
|
a97ce9b0a7 | ||
|
|
d0e18fbd44 | ||
|
|
3845041f7f | ||
|
|
f313a171cb | ||
|
|
93731a4777 | ||
|
|
dba17d5c7a | ||
|
|
2a984ba2c0 | ||
|
|
dbfd75b139 | ||
|
|
db1dc18c28 | ||
|
|
523f7a0942 | ||
|
|
16b3df87c9 | ||
|
|
8d952aa046 | ||
|
|
e3e253fab8 | ||
|
|
fe96004111 | ||
|
|
8483be5d2d | ||
|
|
b6964e29bc | ||
|
|
56d1a98c53 | ||
|
|
01f0902937 | ||
|
|
6335c03cef | ||
|
|
4f898dd8ce | ||
|
|
d012066428 | ||
|
|
4c57bbe791 | ||
|
|
b8d590de6d | ||
|
|
82a31c6f31 | ||
|
|
30a7f762c2 | ||
|
|
3a1acb0f5a | ||
|
|
c0b759aa9d | ||
|
|
7f5ac4ef90 | ||
|
|
f1c835800e | ||
|
|
77852900a3 | ||
|
|
b2a9088354 | ||
|
|
3be0d1ffad | ||
|
|
686c049e52 | ||
|
|
780dbd5dda | ||
|
|
53ad002f3b | ||
|
|
36270477d5 | ||
|
|
a45ee59a76 | ||
|
|
d2782446b0 | ||
|
|
eb835ae5c8 | ||
|
|
401103f17b | ||
|
|
e592d49983 | ||
|
|
de0cb1ebbc | ||
|
|
8e91aec7f1 | ||
|
|
0b7dc6d09a | ||
|
|
108cb96ca5 | ||
|
|
03efa01a85 | ||
|
|
ba19175472 | ||
|
|
aa9464face | ||
|
|
0c788df2f2 | ||
|
|
cbc9264b2c | ||
|
|
82ce347ca4 | ||
|
|
d13071272a | ||
|
|
74523c710f | ||
|
|
fc35ef687b | ||
|
|
a71d960e2d | ||
|
|
0cbf01b9ec | ||
|
|
869b389420 | ||
|
|
d429a8b4b8 | ||
|
|
deccb6e3cd | ||
|
|
2a9c5276ab | ||
|
|
db0c83bd2b | ||
|
|
f81ee155e7 | ||
|
|
76368398ba | ||
|
|
8e5fc5eb61 | ||
|
|
a0804758f5 | ||
|
|
4634393f6c | ||
|
|
5ffe2ce0e2 | ||
|
|
911f464aca | ||
|
|
9f30a029c5 | ||
|
|
5b9fcb2e53 | ||
|
|
46807003e1 | ||
|
|
593944cac2 | ||
|
|
018b51e1e5 | ||
|
|
a29dbca0e4 | ||
|
|
47a408d034 | ||
|
|
d14120dfa2 | ||
|
|
b88c6a53ab | ||
|
|
e3d58c2a9e | ||
|
|
04261036a5 | ||
|
|
0eaed68b82 | ||
|
|
ccb53a61de | ||
|
|
4a01132b91 | ||
|
|
9fffcd4f04 | ||
|
|
ce86a66e92 | ||
|
|
65dd8372dd | ||
|
|
39f97131a2 | ||
|
|
7b471be4cf | ||
|
|
802bd4285c | ||
|
|
e7de773f28 | ||
|
|
4098dda5b8 | ||
|
|
2c67f7a286 | ||
|
|
a953ca189e | ||
|
|
0a09c54690 | ||
|
|
076c4a2bcb | ||
|
|
0e2cbf06ca | ||
|
|
575c856f27 | ||
|
|
103b00a635 | ||
|
|
38c77e7fbb | ||
|
|
272ab8daa0 | ||
|
|
acff814e9b | ||
|
|
1bc3f756fe | ||
|
|
99ea796f2e | ||
|
|
4ef82ee7cf | ||
|
|
4bed65d1df | ||
|
|
2b9e768793 | ||
|
|
f4a878ced9 | ||
|
|
093724a277 | ||
|
|
8346f40b79 | ||
|
|
a9ba65ec17 | ||
|
|
8f29696b64 | ||
|
|
2d32419a7d | ||
|
|
2c636c5e64 | ||
|
|
270338868b | ||
|
|
845d606b36 | ||
|
|
919a200750 | ||
|
|
ad11f2ea63 | ||
|
|
a414f7cd25 | ||
|
|
2a8558f5a2 | ||
|
|
13555d91e2 | ||
|
|
5ccc186bd1 | ||
|
|
27259fb8f7 | ||
|
|
b733c4168f | ||
|
|
1e243e4500 | ||
|
|
ef2e84e411 | ||
|
|
4f644b1e25 | ||
|
|
a5cb2dc93b | ||
|
|
749473f9dc | ||
|
|
dc8aecba93 | ||
|
|
587e2a4e3e | ||
|
|
d83255cc67 | ||
|
|
14edbd85f4 | ||
|
|
e7df6c14b1 | ||
|
|
e2c13a8194 | ||
|
|
9acdcc0429 | ||
|
|
c04e138d6b | ||
|
|
296efcc395 |
@@ -10,7 +10,7 @@
|
||||
""",
|
||||
'category': 'sf',
|
||||
'website': 'https://www.sf.jikimo.com',
|
||||
'depends': ['web'],
|
||||
'depends': ['web', 'purchase'],
|
||||
'data': [
|
||||
|
||||
],
|
||||
@@ -22,11 +22,22 @@
|
||||
],
|
||||
'web.assets_backend': [
|
||||
'jikimo_frontend/static/src/fields/custom_many2many_checkboxes/*',
|
||||
'jikimo_frontend/static/src/fields/Many2OneRadioField/*',
|
||||
'jikimo_frontend/static/src/scss/custom_style.scss',
|
||||
# 'jikimo_frontend/static/src/views/list_nums/list_nbCols.js',
|
||||
'jikimo_frontend/static/src/views/list_nums/list_nums.xml',
|
||||
'jikimo_frontend/static/src/views/list_nums/list_nums2.xml',
|
||||
'jikimo_frontend/static/src/views/list_nums/list_nums3.xml',
|
||||
'jikimo_frontend/static/src/js/custom_form_status_indicator.js',
|
||||
'jikimo_frontend/static/src/js/custom_image_temp.js',
|
||||
'jikimo_frontend/static/src/scss/rowno_in_tree.scss',
|
||||
# 'jikimo_frontend/static/src/views/list_nums/list_render.xml',
|
||||
# 'jikimo_frontend/static/src/list/list_up_down_button.xml',
|
||||
# 'jikimo_frontend/static/src/list/custom_import.js',
|
||||
# 'jikimo_frontend/static/src/list/custom_width.js',
|
||||
'jikimo_frontend/static/src/views/list_nums/extent_purchase.xml',
|
||||
# 'jikimo_frontend/static/src/css/list_border_styles.css',
|
||||
|
||||
],
|
||||
|
||||
},
|
||||
|
||||
3
jikimo_frontend/static/src/css/list_border_styles.css
Normal file
@@ -0,0 +1,3 @@
|
||||
.o_list_renderer .o_list_table tbody > tr > td:not(.o_list_record_selector):not(.o_handle_cell):not(.o_list_button):not(.o_list_record_remove){
|
||||
border:1px solid #dee2e6 !important;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
.many2one_radio_field {
|
||||
display: inline-block;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { RadioField } from "@web/views/fields/radio/radio_field"; // 导入单选按钮组件
|
||||
import { registry } from "@web/core/registry";
|
||||
|
||||
export class Many2OneRadioField extends RadioField {
|
||||
// 你可以重写或者添加一些方法和属性
|
||||
// 例如,你可以重写setup方法来添加一些事件监听器或者初始化一些变量
|
||||
setup() {
|
||||
super.setup(); // 调用父类的setup方法
|
||||
// 你自己的代码
|
||||
}
|
||||
|
||||
onImageClick(event) {
|
||||
// 放大图片逻辑
|
||||
// 获取图片元素
|
||||
const img = event.target;
|
||||
const close = img.nextSibling;
|
||||
// 实现放大图片逻辑
|
||||
// 比如使用 CSS 放大
|
||||
img.parentElement.classList.add('zoomed');
|
||||
close.classList.add('img_close');
|
||||
}
|
||||
|
||||
onCloseClick(event) {
|
||||
const close = event.target;
|
||||
const img = close.previousSibling;
|
||||
img.parentElement.classList.remove('zoomed');
|
||||
close.classList.remove('img_close');
|
||||
}
|
||||
|
||||
get items() {
|
||||
return Many2OneRadioField.getItems(this.props.name, this.props.record);
|
||||
}
|
||||
|
||||
static getItems(fieldName, record) {
|
||||
switch (record.fields[fieldName].type) {
|
||||
case "selection":
|
||||
return record.fields[fieldName].selection;
|
||||
case "many2one": {
|
||||
const value = record.preloadedData[fieldName] || [];
|
||||
return value.map((item) => [item.id, item.display_name, item.image]);
|
||||
}
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Many2OneRadioField.template = "jikimo_frontend.Many2OneRadioField";
|
||||
// MyCustomWidget.supportedTypes = ['many2many'];
|
||||
|
||||
registry.category("fields").add("many2one_radio", Many2OneRadioField);
|
||||
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="jikimo_frontend.Many2OneRadioField" owl="1">
|
||||
<div
|
||||
role="radiogroup"
|
||||
t-attf-class="o_{{ props.orientation }}"
|
||||
t-att-aria-label="string"
|
||||
>
|
||||
<t t-foreach="items" t-as="item" t-key="item[0]">
|
||||
<div class="form-check o_radio_item many2one_radio_field" aria-atomic="true">
|
||||
<input
|
||||
type="radio"
|
||||
class="form-check-input o_radio_input"
|
||||
t-att-checked="item[0] === value"
|
||||
t-att-disabled="props.readonly"
|
||||
t-att-name="id"
|
||||
t-att-data-value="item[0]"
|
||||
t-att-data-index="item_index"
|
||||
t-att-id="`${id}_${item[0]}`"
|
||||
t-on-change="() => this.onChange(item)"
|
||||
/>
|
||||
<label class="form-check-label o_form_label" t-att-for="`${id}_${item[0]}`" t-esc="item[1]" />
|
||||
<div t-on-dblclick="onImageClick">
|
||||
<t>
|
||||
<img t-att-src="item[2]" width="50" height="50"/>
|
||||
<div class="close" t-on-click="onCloseClick">×</div>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
@@ -15,23 +15,24 @@ export class MyCustomWidget extends Many2ManyCheckboxesField {
|
||||
// 放大图片逻辑
|
||||
// 获取图片元素
|
||||
const img = event.target;
|
||||
const close = img.nextSibling
|
||||
const close = img.nextSibling;
|
||||
|
||||
// 实现放大图片逻辑
|
||||
// 比如使用 CSS 放大
|
||||
img.parentElement.classList.add('zoomed');
|
||||
close.classList.add('img_close')
|
||||
close.classList.add('img_close');
|
||||
}
|
||||
|
||||
onCloseClick(event) {
|
||||
const close = event.target;
|
||||
const img = close.previousSibling
|
||||
img.parentElement.classList.remove('zoomed')
|
||||
close.classList.remove('img_close')
|
||||
const img = close.previousSibling;
|
||||
img.parentElement.classList.remove('zoomed');
|
||||
close.classList.remove('img_close');
|
||||
}
|
||||
}
|
||||
|
||||
MyCustomWidget.template = "jikimo_frontend.MyCustomWidget"
|
||||
MyCustomWidget.template = "jikimo_frontend.MyCustomWidget";
|
||||
// MyCustomWidget.supportedTypes = ['many2many'];
|
||||
|
||||
registry.category("fields").add("custom_many2many_checkboxes", MyCustomWidget);
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import {patch} from '@web/core/utils/patch';
|
||||
// import { Dialog } from "@web/core/dialog/dialog";
|
||||
import {_t} from "@web/core/l10n/translation";
|
||||
import {FormStatusIndicator} from "@web/views/form/form_status_indicator/form_status_indicator";
|
||||
|
||||
var Dialog = require('web.Dialog');
|
||||
// var {patch} = require("web.utils") 这句话也行
|
||||
|
||||
patch(FormStatusIndicator.prototype, 'jikimo_frontend.FormStatusIndicator', {
|
||||
// 你可以重写或者添加一些方法和属性
|
||||
async _onDiscardChanges() {
|
||||
// var self = this;
|
||||
Dialog.confirm(this, _t("Are you sure you want to discard changes?"), {
|
||||
title: _t("Discard Changes"),
|
||||
|
||||
// confirm_callback: function () {
|
||||
// self.model.discardChanges(self.handle);
|
||||
// },
|
||||
});
|
||||
},
|
||||
|
||||
async discard() {
|
||||
// if (window.confirm("Are you sure you want to discard changes?")) {
|
||||
// await this.props.discard();
|
||||
// }
|
||||
// const result = await this._confirmDiscardChange();
|
||||
await this._confirmDiscardChange();
|
||||
await this.props.discard();
|
||||
},
|
||||
|
||||
_confirmDiscardChange(){
|
||||
var self = this;
|
||||
var def = new Promise(function (resolve, reject) {
|
||||
var message = _t("请确认是否要舍弃之前的更改?");
|
||||
var dialog = Dialog.confirm(self, message, {
|
||||
title: _t("Warning"),
|
||||
confirm_callback: resolve.bind(self, true),
|
||||
cancel_callback: reject,
|
||||
});
|
||||
dialog.on('closed', self, reject);
|
||||
});
|
||||
return def;
|
||||
},
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
$(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('取消')
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
32
jikimo_frontend/static/src/js/custom_image.js
Normal file
@@ -0,0 +1,32 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
|
||||
import {patch} from '@web/core/utils/patch';
|
||||
import { url } from "@web/core/utils/urls";
|
||||
import { ImageField, imageCacheKey } from '@web/views/fields/image/image_field';
|
||||
|
||||
patch(ImageField.prototype, 'jikimo_frontend/static/src/js/custom_image.js', {
|
||||
// 你可以重写或者添加一些方法和属性
|
||||
getUrl(previewFieldName) {
|
||||
console.log('666666666666666666666666666666666')
|
||||
if (this.state.isValid && this.props.value) {
|
||||
if (1) {
|
||||
if (!this.rawCacheKey) {
|
||||
this.rawCacheKey = this.props.record.data.__last_update;
|
||||
}
|
||||
return url("/web/image", {
|
||||
model: this.props.record.resModel,
|
||||
id: this.props.record.resId,
|
||||
field: previewFieldName,
|
||||
unique: imageCacheKey(this.rawCacheKey),
|
||||
});
|
||||
} else {
|
||||
// Use magic-word technique for detecting image type
|
||||
const magic = fileTypeMagicWordMap[this.props.value[0]] || "png";
|
||||
return `data:image/${magic};base64,${this.props.value}`;
|
||||
}
|
||||
}
|
||||
return placeholder;
|
||||
}
|
||||
}
|
||||
);
|
||||
36
jikimo_frontend/static/src/js/custom_image_temp.js
Normal file
@@ -0,0 +1,36 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { registry } from "@web/core/registry";
|
||||
import { url } from "@web/core/utils/urls";
|
||||
import { ImageField, imageCacheKey } from '@web/views/fields/image/image_field';
|
||||
|
||||
export class CustomImageField extends ImageField {
|
||||
setup() {
|
||||
super.setup();
|
||||
// this.dialog = useService("dialog");
|
||||
}
|
||||
|
||||
getUrl(previewFieldName) {
|
||||
console.log('8888888888886666666666666666666')
|
||||
if (this.state.isValid && this.props.value) {
|
||||
if (1) {
|
||||
if (!this.rawCacheKey) {
|
||||
this.rawCacheKey = this.props.record.data.__last_update;
|
||||
}
|
||||
return url("/web/image", {
|
||||
model: this.props.record.resModel,
|
||||
id: this.props.record.resId,
|
||||
field: previewFieldName,
|
||||
unique: imageCacheKey(this.rawCacheKey),
|
||||
});
|
||||
} else {
|
||||
// Use magic-word technique for detecting image type
|
||||
const magic = fileTypeMagicWordMap[this.props.value[0]] || "png";
|
||||
return `data:image/${magic};base64,${this.props.value}`;
|
||||
}
|
||||
}
|
||||
return placeholder;
|
||||
}
|
||||
}
|
||||
|
||||
registry.category("fields").add("custom_image", CustomImageField);
|
||||
95
jikimo_frontend/static/src/list/custom_width.js
Normal file
@@ -0,0 +1,95 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import {patch} from '@web/core/utils/patch';
|
||||
import {ListRenderer} from "@web/views/list/list_renderer";
|
||||
|
||||
// var {patch} = require("web.utils") 这句话也行
|
||||
|
||||
patch(ListRenderer.prototype, 'jikimo_frontend.ListRenderer', {
|
||||
// 你可以重写或者添加一些方法和属性
|
||||
// The following code manipulates the DOM directly to avoid having to wait for a
|
||||
// render + patch which would occur on the next frame and cause flickering.
|
||||
freezeColumnWidths() {
|
||||
// console.log('ccccccccccccccccccccccccccc')
|
||||
if (!this.keepColumnWidths) {
|
||||
this.columnWidths = null;
|
||||
}
|
||||
|
||||
const table = this.tableRef.el;
|
||||
const headers = [...table.querySelectorAll("thead th:not(.o_list_actions_header)")];
|
||||
const column_num = headers.length;
|
||||
|
||||
if (!this.columnWidths || !this.columnWidths.length) {
|
||||
// no column widths to restore
|
||||
// Set table layout auto and remove inline style to make sure that css
|
||||
// rules apply (e.g. fixed width of record selector)
|
||||
table.style.tableLayout = "auto";
|
||||
headers.forEach((th) => {
|
||||
th.style.width = null;
|
||||
th.style.maxWidth = null;
|
||||
});
|
||||
|
||||
this.setDefaultColumnWidths(column_num);
|
||||
|
||||
// Squeeze the table by applying a max-width on largest columns to
|
||||
// ensure that it doesn't overflow
|
||||
this.columnWidths = this.computeColumnWidthsFromContent();
|
||||
table.style.tableLayout = "fixed";
|
||||
}
|
||||
headers.forEach((th, index) => {
|
||||
if (!th.style.width) {
|
||||
th.style.width = `${Math.floor(this.columnWidths[index])}px`;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
setDefaultColumnWidths(column_num) {
|
||||
// const bbb = this.state.columns[0].name
|
||||
const widths = this.state.columns.map((col) =>
|
||||
this.calculateColumnWidth(col));
|
||||
// const sumOfRelativeWidths = (widths
|
||||
// .filter(({ type }) => type === "relative")
|
||||
// .reduce((sum, { value }) => sum + value, 0));
|
||||
|
||||
// 获取数组的最后一项
|
||||
const lastItem = widths[widths.length - 1];
|
||||
|
||||
// 复制最后一项
|
||||
const newItem = { ...lastItem };
|
||||
|
||||
// 将新的对象添加到数组的末尾
|
||||
widths.push(newItem);
|
||||
|
||||
// 判断销售的sequence
|
||||
// if (this.state.columns[0].name === "sequence") {
|
||||
// widths[1] = { type: "relative", value: 0.1 };
|
||||
// }
|
||||
|
||||
// 判断 this.state.columns 是否存在且长度大于零
|
||||
if (this.state.columns && this.state.columns.length > 0
|
||||
&& this.state.columns[0].name === "sequence") {
|
||||
widths[1] = { type: "relative", value: 0.1 };
|
||||
}
|
||||
|
||||
|
||||
// 1 because nth-child selectors are 1-indexed,
|
||||
// 2 when the first column contains
|
||||
// the checkboxes to select records.
|
||||
const columnOffset = this.hasSelectors ? 2 : 1;
|
||||
widths.forEach(({ type, value }, width) => {
|
||||
const headerEl = this.tableRef.el.querySelector(
|
||||
`th:nth-child(${width + columnOffset})`);
|
||||
if (type === "absolute") {
|
||||
if (this.isEmpty) {
|
||||
headerEl.style.width = value;
|
||||
} else {
|
||||
headerEl.style.minWidth = value;
|
||||
}
|
||||
} else if (type === "relative" && this.isEmpty) {
|
||||
headerEl.style.width = `${((value / column_num) * 100
|
||||
).toFixed(2)}%`;
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
);
|
||||
20
jikimo_frontend/static/src/list/list_up_down_button.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates>
|
||||
<t t-name="list_up_down_button" t-inherit="web.ListView.Buttons" t-inherit-mode="extension" owl="1">
|
||||
<xpath expr="//t[@t-if='nbTotal and !nbSelected and activeActions.exportXlsx and isExportEnable and !env.isSmall']" position="before">
|
||||
<!-- 新增的导入文件按钮 -->
|
||||
<!-- <button type="button" class="btn btn-secondary fa fa-upload o_list_import_file" data-tooltip="导入文件" aria-label="Import File" title="" t-on-click="onDirectImportData"/> -->
|
||||
<!-- <button type="button" class="btn btn-secondary fa fa-upload o_list_import_file" data-tooltip="导入文件" aria-label="Import File" title="" t-on-click="onDirectImportData"/> -->
|
||||
<!-- <button type="button" class="btn btn-secondary fa fa-download o_list_export_xlsx" data-tooltip="导出全部" aria-label="导出全部" t-on-click="onDirectExportData"/> -->
|
||||
<button type="button" class="btn btn-secondary o_list_export_xlsx" data-tooltip="导出全部" aria-label="导出全部" t-on-click="onDirectExportData">导出全部</button>
|
||||
<!-- <button type="button" t-component="base_import.ImportRecords" class="btn btn-secondary o_list_export_xlsx" data-tooltip="导入数据" aria-label="导入数据" t-on-click="importRecords">导入数据</button> -->
|
||||
<!-- <button type="button" class="btn btn-secondary o_list_export_xlsx" data-tooltip="导入数据" aria-label="导入数据" t-on-click="importRecords">导入数据</button> -->
|
||||
<!-- <t t-component="base_import.ImportRecords"> -->
|
||||
<!-- <button t-on-click="importRecords" type="button" class="btn btn-secondary o_list_export_xlsx" data-tooltip="导入数据" aria-label="导入数据">导入数据</button> -->
|
||||
<!-- </t> -->
|
||||
|
||||
</xpath>
|
||||
<xpath expr="//t[@t-if='nbTotal and !nbSelected and activeActions.exportXlsx and isExportEnable and !env.isSmall']" position="replace">
|
||||
</xpath>
|
||||
</t>
|
||||
</templates>
|
||||
@@ -17,6 +17,7 @@ div:has(.o_required_modifier) > label::before {
|
||||
}
|
||||
|
||||
.my-image div {
|
||||
|
||||
width: 110px !important;
|
||||
height: 110px !important;
|
||||
}
|
||||
@@ -78,9 +79,9 @@ td.o_required_modifier {
|
||||
}
|
||||
|
||||
.oe_kanban_card.kanban_color_1 {
|
||||
background-color: #27FEA9 !important;
|
||||
background-color: #fff !important;
|
||||
opacity: 0.7;
|
||||
color: #fff;
|
||||
color: #777;
|
||||
}
|
||||
|
||||
.oe_kanban_card.kanban_color_3 {
|
||||
@@ -134,7 +135,7 @@ td.o_required_modifier {
|
||||
.text-truncate {
|
||||
overflow: unset !important;
|
||||
text-overflow: unset !important;
|
||||
white-space: unset !important;
|
||||
//white-space: nowrap!important;
|
||||
}
|
||||
|
||||
.o_list_renderer .o_list_table tbody > tr > td:not(.o_list_record_selector):not(.o_handle_cell):not(.o_list_button):not(.o_list_record_remove) {
|
||||
@@ -204,8 +205,8 @@ div[class="o_content o_component_with_search_panel"] img[name="equipment_image"]
|
||||
|
||||
div[class="o_content o_component_with_search_panel"] .o_kanban_card_content button {
|
||||
position: absolute;
|
||||
top: -52px;
|
||||
left: -55px;
|
||||
//top: -52px;
|
||||
//left: -55px;
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
@@ -252,16 +253,16 @@ div[class="o_content o_component_with_search_panel"] .show_state span {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
div[class="o_content o_component_with_search_panel"] .o_kanban_primary_right > .row {
|
||||
position: absolute;
|
||||
top: 55px;
|
||||
right: 43.5%;
|
||||
}
|
||||
//div[class="o_content o_component_with_search_panel"] .o_kanban_primary_right > .row {
|
||||
// position: absolute;
|
||||
// top: 55px;
|
||||
// right: 43.5%;
|
||||
//}
|
||||
//------------------------------------------
|
||||
|
||||
.test_model > .o_form_label {
|
||||
margin-left: 4px !important;
|
||||
line-height: 0 !important;
|
||||
//line-height: 0 !important;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1200px) {
|
||||
@@ -269,10 +270,10 @@ div[class="o_content o_component_with_search_panel"] .o_kanban_primary_right > .
|
||||
right: 52%;
|
||||
}
|
||||
|
||||
div[class="o_content o_component_with_search_panel"] .o_kanban_card_content button {
|
||||
|
||||
left: -95px;
|
||||
}
|
||||
//div[class="o_content o_component_with_search_panel"] .o_kanban_card_content button {
|
||||
//
|
||||
// left: -95px;
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
@@ -317,27 +318,135 @@ div[class="o_content o_component_with_search_panel"] .o_kanban_primary_right > .
|
||||
.o_horizontal_separator {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.o_field_widget input[class='o_input'] {
|
||||
text-align: center
|
||||
}
|
||||
//
|
||||
//.o_field_widget input[class='o_input'] {
|
||||
//text-align: center
|
||||
//}
|
||||
|
||||
div:has(.o_required_modifier) > label::before {
|
||||
position: absolute;
|
||||
left: -3px;
|
||||
}
|
||||
|
||||
.o_form_view .o_form_label {
|
||||
position: relative;
|
||||
width: 9rem;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
padding-left: 1rem;
|
||||
//.o_form_view .o_form_label {
|
||||
// position: relative;
|
||||
// width: 9rem;
|
||||
// overflow: hidden;
|
||||
// text-overflow: ellipsis;
|
||||
// white-space: nowrap;
|
||||
// padding-left: 1rem;
|
||||
//}
|
||||
//
|
||||
//.o_form_view .o_form_label:hover {
|
||||
// white-space: normal;
|
||||
// overflow: visible;
|
||||
//}
|
||||
|
||||
.o_form_view {
|
||||
.o_form_sheet_bg .o_form_sheet {
|
||||
//max-width: none !important;
|
||||
width: auto !important;
|
||||
max-width: 98% !important;
|
||||
}
|
||||
.o_FormRenderer_chatterContainer {
|
||||
max-width: none;
|
||||
}
|
||||
}
|
||||
|
||||
.o_form_view .o_form_label:hover {
|
||||
white-space: normal;
|
||||
overflow: visible;
|
||||
|
||||
// 2023-11-16 hy 新增
|
||||
.o_kanban_card_content .btn-group {
|
||||
position: unset;
|
||||
}
|
||||
|
||||
.o_kanban_card_content .btn-group button{
|
||||
top: 100px;
|
||||
left: 168px;
|
||||
}
|
||||
|
||||
|
||||
.o_kanban_primary_right {
|
||||
position: absolute;
|
||||
top: 40px;
|
||||
left: 168px;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
box-sizing: border-box;
|
||||
.row {
|
||||
width: 50%;
|
||||
margin: 0;
|
||||
>div {
|
||||
padding: 0;
|
||||
width: unset;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.oe_kanban_details li.o_text_overflow {
|
||||
display: block;
|
||||
}
|
||||
.o_stock_kanban .o_kanban_card_content {
|
||||
.row {
|
||||
align-items: center;
|
||||
|
||||
.o_kanban_primary_left, .o_kanban_primary_right {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.o_kanban_primary_right {
|
||||
position: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 机床换刀申请表格宽度设置
|
||||
.o_list_table_ungrouped {
|
||||
min-width: 1089px;
|
||||
}
|
||||
// 加工能力\冷却方式 竖列展示改为横列展示
|
||||
.processingMethod {
|
||||
.o_cell.flex-grow-1.flex-sm-grow-0 {
|
||||
width: 100%!important;
|
||||
}
|
||||
}
|
||||
@media (min-width: 576px) {
|
||||
.o_inner_group.processingMethod {
|
||||
grid-template-columns: auto;
|
||||
}
|
||||
}
|
||||
|
||||
// 设置所有表格序号列padding为0
|
||||
.o_form_view .o_notebook > .tab-content > .tab-pane > :first-child:not(.o_group) .o_field_x2many.o_field_x2many_list tr > :first-child, .o_form_view .o_notebook > .tab-content > .tab-pane > :first-child.o_invisible_modifier + .o_field_widget .o_field_x2many.o_field_x2many_list tr > :first-child {
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
// 设置剩余number类型数据表格列 left
|
||||
.o_list_renderer .o_list_table thead .o_list_number_th {
|
||||
text-align:left;
|
||||
}
|
||||
.o_list_renderer .o_list_table tbody > tr > td:not(.o_list_record_selector).o_list_number {
|
||||
text-align: left;
|
||||
}
|
||||
.o_list_renderer .flex-row-reverse {
|
||||
flex-direction: unset!important;
|
||||
}
|
||||
|
||||
.o_list_renderer .flex-row-reverse > .text-end {
|
||||
text-align: left!important;
|
||||
}
|
||||
|
||||
// 设置modal弹窗样式
|
||||
.modal.o_technical_modal {
|
||||
.modal-lg {
|
||||
@media (min-width: 992px) {
|
||||
max-width: 1200px;
|
||||
}
|
||||
@media (min-width: 576px) {
|
||||
.o_form_view .o_inner_group {
|
||||
grid-template-columns: auto;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
4
jikimo_frontend/static/src/scss/rowno_in_tree.scss
Normal file
@@ -0,0 +1,4 @@
|
||||
.row_no {
|
||||
width: 35px !important;
|
||||
vertical-align: middle;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<templates>
|
||||
<t t-name="purchase.PurchaseListView" t-inherit="web.ListRenderer" t-inherit-mode="primary" owl="1">
|
||||
<xpath expr="//div[hasclass('o_list_renderer')]" position="before">
|
||||
<PurchaseDashBoard />
|
||||
</xpath>
|
||||
</t>
|
||||
</templates>
|
||||
@@ -8,4 +8,4 @@ patch(ListRenderer.prototype, '/jikimo_frontend/static/src/views/list_nums/list_
|
||||
const nbCols = this._super(...arguments);
|
||||
return nbCols + 1;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
<t t-name="og.web.ListRenderer" t-inherit="web.ListRenderer" t-inherit-mode="extension">
|
||||
<xpath expr="//table/thead/tr/th[@t-if='hasSelectors']" position="before">
|
||||
<th><i class="fa fa-list-ol"/></th>
|
||||
<th class="row_no"><i class="fa fa-list-ol"/></th>
|
||||
</xpath>
|
||||
</t>
|
||||
|
||||
|
||||
47
jikimo_frontend/static/src/views/list_nums/list_render.xml
Normal file
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<template>
|
||||
<t
|
||||
t-name="rowno_in_tree.ListRenderer"
|
||||
t-inherit="web.ListRenderer"
|
||||
t-inherit-mode="extension"
|
||||
owl="1"
|
||||
|
||||
>
|
||||
<xpath expr="//table/thead/tr/th[@t-if='hasSelectors']" position="before">
|
||||
<th class="row_no"><i class="fa fa-list-ol"/></th>
|
||||
</xpath>
|
||||
<xpath expr="//div/table/tfoot/tr/td" position="before">
|
||||
<td />
|
||||
</xpath>
|
||||
</t>
|
||||
|
||||
<t
|
||||
t-name="rowno_in_tree.add_number"
|
||||
t-inherit="web.ListRenderer.Rows"
|
||||
t-inherit-mode="extension"
|
||||
owl="1"
|
||||
>
|
||||
<xpath expr="//t[@t-foreach='list.records']" position="before">
|
||||
<t t-set="RowNumber" t-value="1" />
|
||||
</xpath>
|
||||
<xpath
|
||||
expr="//t[@t-call='{{ constructor.recordRowTemplate }}']"
|
||||
position="after"
|
||||
>
|
||||
<t t-set="RowNumber" t-value="RowNumber+1" />
|
||||
</xpath>
|
||||
</t>
|
||||
|
||||
<t
|
||||
t-name="rowno_in_tree.ListRenderer.RecordRowNumber"
|
||||
t-inherit="web.ListRenderer.RecordRow"
|
||||
t-inherit-mode="extension"
|
||||
owl="1"
|
||||
>
|
||||
<xpath expr="//td[@class='o_list_record_selector']" position="before">
|
||||
<td tabindex="-1">
|
||||
<span t-esc="RowNumber" />
|
||||
</td>
|
||||
</xpath>
|
||||
</t>
|
||||
</template>
|
||||
14
jikimo_hide_options/__init__.py
Normal file
@@ -0,0 +1,14 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from . import models
|
||||
from odoo import api, SUPERUSER_ID
|
||||
|
||||
|
||||
def uninstall_hook(cr, registry):
|
||||
# 使用cr来执行数据库操作
|
||||
with api.Environment.manage():
|
||||
env = api.Environment(cr, SUPERUSER_ID, {})
|
||||
# 执行数据清理操作
|
||||
access_rights = env['access.right'].search([])
|
||||
access_rights.unlink()
|
||||
followers = env['mail.followers'].search([('res_model', '=', 'access.right')])
|
||||
followers.unlink()
|
||||
32
jikimo_hide_options/__manifest__.py
Normal file
@@ -0,0 +1,32 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
{
|
||||
'name': '机企猫 隐藏项目',
|
||||
'version': '16.0.1.0.0',
|
||||
'category': 'Extra Tools, Productivity',
|
||||
'summary': """ Can hide options from user """,
|
||||
'description': """ By using this module we can hide the options like create,
|
||||
delete,export,and archive/un archive in the model which we want. Here we
|
||||
are also able to select the user groups except Administrator which we want
|
||||
to apply the above hiding functionality """,
|
||||
'author': '机企猫-MGW',
|
||||
'company': '机企猫',
|
||||
'depends': ['base_setup', 'mail'],
|
||||
'data': [
|
||||
'security/security.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'views/model_access_rights_views.xml',
|
||||
],
|
||||
'assets': {
|
||||
'web.assets_backend': [
|
||||
'jikimo_hide_options/static/src/js/form_controller.js',
|
||||
'jikimo_hide_options/static/src/js/list_controller.js',
|
||||
'jikimo_hide_options/static/src/js/kanban_controller.js'
|
||||
]
|
||||
},
|
||||
'images': ['static/description/banner.jpg'],
|
||||
'license': 'LGPL-3',
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'application': False,
|
||||
'uninstall_hook': 'uninstall_hook',
|
||||
}
|
||||
4
jikimo_hide_options/models/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from . import model_access_rights
|
||||
from . import models
|
||||
|
||||
107
jikimo_hide_options/models/model_access_rights.py
Normal file
@@ -0,0 +1,107 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from odoo import api, fields, models, _
|
||||
|
||||
|
||||
class ModelAccessRights(models.Model):
|
||||
"""This class is used to detect, which all options want to hide from the
|
||||
specified group and model"""
|
||||
_name = 'access.right'
|
||||
_inherit = 'mail.thread'
|
||||
_description = 'Manage Modules Access Control'
|
||||
_rec_name = 'model_id'
|
||||
|
||||
model_id = fields.Many2one('ir.model', ondelete='cascade', required=True,
|
||||
help="select the model")
|
||||
groups_id = fields.Many2one('res.groups', required=True,
|
||||
help="select the group")
|
||||
is_delete = fields.Boolean(string="Delete", help="hide the delete option")
|
||||
is_export = fields.Boolean(string="Export",
|
||||
help="hide the 'Export All'"
|
||||
" option from list view")
|
||||
is_create_or_update = fields.Boolean(string="Create/Update",
|
||||
help="hide the create option from list"
|
||||
" as well as form view")
|
||||
is_archive = fields.Boolean(string="Archive/UnArchive",
|
||||
help="hide the archive option")
|
||||
|
||||
@api.model
|
||||
def hide_buttons(self):
|
||||
"""This function contains a query that detects which all options want
|
||||
to hide, in which model,and to which user groups"""
|
||||
access_right_rec = self.sudo().search_read([], ['model_id', 'is_delete',
|
||||
'is_export',
|
||||
'is_create_or_update',
|
||||
'is_archive',
|
||||
'groups_id'])
|
||||
for dic in access_right_rec:
|
||||
model = self.env['ir.model'].sudo().browse(dic['model_id'][0]).model
|
||||
group_name = self.env['ir.model.data'].sudo().search([
|
||||
('model', '=', 'res.groups'),
|
||||
('res_id', '=', dic['groups_id'][0])
|
||||
]).name
|
||||
|
||||
module_name = self.env['ir.model.data'].sudo().search([
|
||||
('model', '=', 'res.groups'),
|
||||
('res_id', '=', dic['groups_id'][0])
|
||||
]).module
|
||||
dic.update({
|
||||
'model': model,
|
||||
'group_name': group_name,
|
||||
'module': module_name
|
||||
})
|
||||
return access_right_rec
|
||||
# @api.model
|
||||
# def hide_buttons(self):
|
||||
# """This function contains a query that detects which all options want
|
||||
# to hide, in which model,and to which user groups"""
|
||||
# access_right_rec = self.sudo().search_read([], ['model_id', 'is_delete',
|
||||
# 'is_export',
|
||||
# 'is_create_or_update',
|
||||
# 'is_archive',
|
||||
# 'groups_id'])
|
||||
# for dic in access_right_rec:
|
||||
# model = self.env['ir.model'].sudo().browse(dic['model_id']).model
|
||||
# group_name = self.env['ir.model.data'].sudo().search([
|
||||
# ('model', '=', 'res.groups'),
|
||||
# ('res_id', '=', dic['groups_id'])
|
||||
# ]).name
|
||||
# module_name = self.env['ir.model.data'].sudo().search([
|
||||
# ('model', '=', 'res.groups'),
|
||||
# ('res_id', '=', dic['groups_id'])
|
||||
# ]).module
|
||||
# dic.update({
|
||||
# 'model': model,
|
||||
# 'group_name': group_name,
|
||||
# 'module': module_name
|
||||
# })
|
||||
# return access_right_rec
|
||||
|
||||
|
||||
# class AccessRightCleanup(models.Model):
|
||||
# _name = 'access.right.cleanup' # 定义一个新的模型名
|
||||
# _description = 'Access Right Cleanup'
|
||||
|
||||
|
||||
|
||||
# @api.model
|
||||
# def _module_uninstall(self):
|
||||
# """在模块卸载时执行清理操作"""
|
||||
# super(AccessRightCleanup, self)._module_uninstall()
|
||||
# # 这里执行你的清理逻辑
|
||||
#
|
||||
# # 获取access.right模型的所有记录
|
||||
# access_rights = self.env['access.right'].search([])
|
||||
# for access_right in access_rights:
|
||||
# # 删除access.right模型的所有记录
|
||||
# access_right.unlink()
|
||||
#
|
||||
# # 查找所有关联到access.right模型的关注者记录
|
||||
# followers = self.env['mail.followers'].search([('res_model', '=', 'access.right')])
|
||||
# for follower in followers:
|
||||
# # 删除关注者记录
|
||||
# follower.unlink()
|
||||
#
|
||||
# # # 示例:删除自定义数据表(确保先检查外键约束等)
|
||||
# # self.env.cr.execute('DROP TABLE IF EXISTS access_right CASCADE;')
|
||||
#
|
||||
# # 其他清理工作...
|
||||
353
jikimo_hide_options/models/models.py
Normal file
@@ -0,0 +1,353 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from collections import defaultdict
|
||||
from operator import attrgetter
|
||||
from odoo import api, _
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.models import BaseModel, _unlink, LOG_ACCESS_COLUMNS, \
|
||||
INSERT_BATCH_SIZE, SQL_DEFAULT
|
||||
# from odoo.tools import OrderedSet, split_every, attrgetter, clean_context
|
||||
from odoo.tools import OrderedSet, split_every, clean_context
|
||||
|
||||
|
||||
@api.model
|
||||
def _create(self, data_list):
|
||||
""" Create records from the stored field values in ``data_list``. """
|
||||
assert data_list
|
||||
cr = self.env.cr
|
||||
|
||||
# insert rows in batches of maximum INSERT_BATCH_SIZE
|
||||
ids = [] # ids of created records
|
||||
other_fields = OrderedSet() # non-column fields
|
||||
|
||||
for data_sublist in split_every(INSERT_BATCH_SIZE, data_list):
|
||||
stored_list = [data['stored'] for data in data_sublist]
|
||||
fnames = sorted({name for stored in stored_list for name in stored})
|
||||
|
||||
columns = []
|
||||
rows = [[] for _ in stored_list]
|
||||
for fname in fnames:
|
||||
field = self._fields[fname]
|
||||
if field.column_type:
|
||||
columns.append(fname)
|
||||
for stored, row in zip(stored_list, rows):
|
||||
if fname in stored:
|
||||
colval = field.convert_to_column(stored[fname], self,
|
||||
stored)
|
||||
if field.translate is True and colval:
|
||||
if 'en_US' not in colval.adapted:
|
||||
colval.adapted['en_US'] = next(
|
||||
iter(colval.adapted.values()))
|
||||
row.append(colval)
|
||||
else:
|
||||
row.append(SQL_DEFAULT)
|
||||
else:
|
||||
other_fields.add(field)
|
||||
|
||||
if field.type == 'properties':
|
||||
# force calling fields.create for properties field because
|
||||
# we might want to update the parent definition
|
||||
other_fields.add(field)
|
||||
|
||||
if not columns:
|
||||
# manage the case where we create empty records
|
||||
columns = ['id']
|
||||
for row in rows:
|
||||
row.append(SQL_DEFAULT)
|
||||
|
||||
header = ", ".join(f'"{column}"' for column in columns)
|
||||
template = ", ".join("%s" for _ in rows)
|
||||
cr.execute(
|
||||
f'INSERT INTO "{self._table}" ({header}) VALUES {template} RETURNING "id"',
|
||||
[tuple(row) for row in rows],
|
||||
)
|
||||
ids.extend(id_ for id_, in cr.fetchall())
|
||||
|
||||
# put the new records in cache, and update inverse fields, for many2one
|
||||
#
|
||||
# cachetoclear is an optimization to avoid modified()'s cost until other_fields are processed
|
||||
cachetoclear = []
|
||||
records = self.browse(ids)
|
||||
inverses_update = defaultdict(list) # {(field, value): ids}
|
||||
common_set_vals = set(
|
||||
LOG_ACCESS_COLUMNS + [self.CONCURRENCY_CHECK_FIELD, 'id',
|
||||
'parent_path'])
|
||||
for data, record in zip(data_list, records):
|
||||
data['record'] = record
|
||||
# DLE P104: test_inherit.py, test_50_search_one2many
|
||||
vals = dict(
|
||||
{k: v for d in data['inherited'].values() for k, v in d.items()},
|
||||
**data['stored'])
|
||||
set_vals = common_set_vals.union(vals)
|
||||
for field in self._fields.values():
|
||||
if field.type in ('one2many', 'many2many'):
|
||||
self.env.cache.set(record, field, ())
|
||||
elif field.related and not field.column_type:
|
||||
self.env.cache.set(record, field,
|
||||
field.convert_to_cache(None, record))
|
||||
# DLE P123: `test_adv_activity`, `test_message_assignation_inbox`, `test_message_log`, `test_create_mail_simple`, ...
|
||||
# Set `mail.message.parent_id` to False in cache so it doesn't do the useless SELECT when computing the modified of `child_ids`
|
||||
# in other words, if `parent_id` is not set, no other message `child_ids` are impacted.
|
||||
# + avoid the fetch of fields which are False. e.g. if a boolean field is not passed in vals and as no default set in the field attributes,
|
||||
# then we know it can be set to False in the cache in the case of a create.
|
||||
elif field.name not in set_vals and not field.compute:
|
||||
self.env.cache.set(record, field,
|
||||
field.convert_to_cache(None, record))
|
||||
for fname, value in vals.items():
|
||||
field = self._fields[fname]
|
||||
if field.type in ('one2many', 'many2many'):
|
||||
cachetoclear.append((record, field))
|
||||
else:
|
||||
cache_value = field.convert_to_cache(value, record)
|
||||
self.env.cache.set(record, field, cache_value)
|
||||
if field.type in ('many2one', 'many2one_reference') and \
|
||||
self.pool.field_inverses[field]:
|
||||
inverses_update[(field, cache_value)].append(record.id)
|
||||
|
||||
for (field, value), record_ids in inverses_update.items():
|
||||
field._update_inverses(self.browse(record_ids), value)
|
||||
|
||||
# update parent_path
|
||||
records._parent_store_create()
|
||||
|
||||
# protect fields being written against recomputation
|
||||
protected = [(data['protected'], data['record']) for data in data_list]
|
||||
with self.env.protecting(protected):
|
||||
# mark computed fields as todo
|
||||
records.modified(self._fields, create=True)
|
||||
|
||||
if other_fields:
|
||||
# discard default values from context for other fields
|
||||
others = records.with_context(clean_context(self._context))
|
||||
for field in sorted(other_fields, key=attrgetter('_sequence')):
|
||||
field.create([
|
||||
(other, data['stored'][field.name])
|
||||
for other, data in zip(others, data_list)
|
||||
if field.name in data['stored']
|
||||
])
|
||||
|
||||
# mark fields to recompute
|
||||
records.modified([field.name for field in other_fields],
|
||||
create=True)
|
||||
|
||||
# if value in cache has not been updated by other_fields, remove it
|
||||
for record, field in cachetoclear:
|
||||
if self.env.cache.contains(record,
|
||||
field) and not self.env.cache.get(
|
||||
record, field):
|
||||
self.env.cache.remove(record, field)
|
||||
|
||||
# check Python constraints for stored fields
|
||||
records._validate_fields(
|
||||
name for data in data_list for name in data['stored'])
|
||||
records.check_access_rule('create')
|
||||
# This is used to restrict the access right to create a record
|
||||
current_model_id = self.env['ir.model'].sudo().search(
|
||||
[('model', '=', self._name)]).id
|
||||
# access_right_rec = self.env['access.right'].sudo().search_read(
|
||||
# [('model_id', '=', current_model_id)],
|
||||
# ['model_id', 'is_create_or_update',
|
||||
# 'groups_id'])
|
||||
# if access_right_rec and not self.env.is_admin():
|
||||
# for rec in access_right_rec:
|
||||
# group_name = self.env['ir.model.data'].sudo().search([
|
||||
# ('model', '=', 'res.groups'),
|
||||
# ('res_id', '=', rec['groups_id'][0])
|
||||
# ]).name
|
||||
# module_name = self.env['ir.model.data'].sudo().search([
|
||||
# ('model', '=', 'res.groups'),
|
||||
# ('res_id', '=', rec['groups_id'][0])
|
||||
# ]).module
|
||||
# group = module_name + "." + group_name
|
||||
# if self.env.user.has_group(group):
|
||||
# if rec['is_create_or_update']:
|
||||
# raise UserError('You are restricted from performing this'
|
||||
# ' operation. Please contact the'
|
||||
# ' administrator.')
|
||||
# 检查 'access.right' 模型是否存在于环境中
|
||||
if 'access.right' in self.env:
|
||||
access_right_rec = self.env['access.right'].sudo().search_read(
|
||||
[('model_id', '=', current_model_id)],
|
||||
['model_id', 'is_create_or_update', 'groups_id']
|
||||
)
|
||||
|
||||
# 如果找到相关记录,并且当前用户不是管理员
|
||||
if access_right_rec and not self.env.is_admin():
|
||||
for rec in access_right_rec:
|
||||
# 获取与权限相关的用户组信息
|
||||
group_data = self.env['ir.model.data'].sudo().search_read(
|
||||
[('model', '=', 'res.groups'), ('res_id', '=', rec['groups_id'][0])],
|
||||
['name', 'module']
|
||||
)
|
||||
|
||||
# 如果找到了用户组数据
|
||||
if group_data:
|
||||
group_name = group_data[0]['name']
|
||||
module_name = group_data[0]['module']
|
||||
group_xml_id = f"{module_name}.{group_name}"
|
||||
|
||||
# 检查当前用户是否属于该组
|
||||
if self.env.user.has_group(group_xml_id):
|
||||
# 如果该用户组被限制创建或更新操作
|
||||
if rec['is_create_or_update']:
|
||||
raise UserError(
|
||||
_("You are restricted from performing this operation. Please contact the administrator."))
|
||||
else:
|
||||
# 如果 'access.right' 模型不存在,可以在这里定义备选逻辑
|
||||
# 例如,记录日志、发送通知或者简单地跳过这部分逻辑
|
||||
pass
|
||||
|
||||
return records
|
||||
|
||||
|
||||
@api.model
|
||||
def unlink(self):
|
||||
""" unlink()
|
||||
|
||||
Deletes the records in ``self``.
|
||||
|
||||
:raise AccessError: if the user is not allowed to delete all the given records
|
||||
:raise UserError: if the record is default property for other records
|
||||
"""
|
||||
if not self:
|
||||
return True
|
||||
|
||||
self.check_access_rights('unlink')
|
||||
self.check_access_rule('unlink')
|
||||
|
||||
from odoo.addons.base.models.ir_model import MODULE_UNINSTALL_FLAG
|
||||
for func in self._ondelete_methods:
|
||||
# func._ondelete is True if it should be called during uninstallation
|
||||
if func._ondelete or not self._context.get(MODULE_UNINSTALL_FLAG):
|
||||
func(self)
|
||||
|
||||
# TOFIX: this avoids an infinite loop when trying to recompute a
|
||||
# field, which triggers the recomputation of another field using the
|
||||
# same compute function, which then triggers again the computation
|
||||
# of those two fields
|
||||
for field in self._fields.values():
|
||||
self.env.remove_to_compute(field, self)
|
||||
|
||||
self.env.flush_all()
|
||||
|
||||
cr = self._cr
|
||||
Data = self.env['ir.model.data'].sudo().with_context({})
|
||||
Defaults = self.env['ir.default'].sudo()
|
||||
Property = self.env['ir.property'].sudo()
|
||||
Attachment = self.env['ir.attachment'].sudo()
|
||||
ir_property_unlink = Property
|
||||
ir_model_data_unlink = Data
|
||||
ir_attachment_unlink = Attachment
|
||||
|
||||
# mark fields that depend on 'self' to recompute them after 'self' has
|
||||
# been deleted (like updating a sum of lines after deleting one line)
|
||||
with self.env.protecting(self._fields.values(), self):
|
||||
self.modified(self._fields, before=True)
|
||||
for sub_ids in cr.split_for_in_conditions(self.ids):
|
||||
records = self.browse(sub_ids)
|
||||
|
||||
# Check if the records are used as default properties.
|
||||
refs = [f'{self._name},{id_}' for id_ in sub_ids]
|
||||
if Property.search(
|
||||
[('res_id', '=', False), ('value_reference', 'in', refs)],
|
||||
limit=1):
|
||||
raise UserError(
|
||||
_('Unable to delete this document because it is used as a default property'))
|
||||
|
||||
# Delete the records' properties.
|
||||
ir_property_unlink |= Property.search([('res_id', 'in', refs)])
|
||||
|
||||
query = f'DELETE FROM "{self._table}" WHERE id IN %s'
|
||||
cr.execute(query, (sub_ids,))
|
||||
|
||||
# Removing the ir_model_data reference if the record being deleted
|
||||
# is a record created by xml/csv file, as these are not connected
|
||||
# with real database foreign keys, and would be dangling references.
|
||||
#
|
||||
# Note: the following steps are performed as superuser to avoid
|
||||
# access rights restrictions, and with no context to avoid possible
|
||||
# side-effects during admin calls.
|
||||
data = Data.search(
|
||||
[('model', '=', self._name), ('res_id', 'in', sub_ids)])
|
||||
ir_model_data_unlink |= data
|
||||
|
||||
# For the same reason, remove the defaults having some of the
|
||||
# records as value
|
||||
Defaults.discard_records(records)
|
||||
|
||||
# For the same reason, remove the relevant records in ir_attachment
|
||||
# (the search is performed with sql as the search method of
|
||||
# ir_attachment is overridden to hide attachments of deleted
|
||||
# records)
|
||||
query = 'SELECT id FROM ir_attachment WHERE res_model=%s AND res_id IN %s'
|
||||
cr.execute(query, (self._name, sub_ids))
|
||||
ir_attachment_unlink |= Attachment.browse(
|
||||
row[0] for row in cr.fetchall())
|
||||
|
||||
# invalidate the *whole* cache, since the orm does not handle all
|
||||
# changes made in the database, like cascading delete!
|
||||
self.env.invalidate_all(flush=False)
|
||||
if ir_property_unlink:
|
||||
ir_property_unlink.unlink()
|
||||
if ir_model_data_unlink:
|
||||
ir_model_data_unlink.unlink()
|
||||
if ir_attachment_unlink:
|
||||
ir_attachment_unlink.unlink()
|
||||
# DLE P93: flush after the unlink, for recompute fields depending on
|
||||
# the modified of the unlink
|
||||
self.env.flush_all()
|
||||
# auditing: deletions are infrequent and leave no trace in the database
|
||||
_unlink.info('User #%s deleted %s records with IDs: %r', self._uid,
|
||||
self._name, self.ids)
|
||||
# This is used to restrict the access right to unlink a record
|
||||
current_model_id = self.env['ir.model'].sudo().search(
|
||||
[('model', '=', self._name)]).id
|
||||
# access_right_rec = self.env['access.right'].sudo().search_read(
|
||||
# [('model_id', '=', current_model_id)], ['model_id', 'is_delete',
|
||||
# 'groups_id'])
|
||||
# if access_right_rec and not self.env.is_admin():
|
||||
# for rec in access_right_rec:
|
||||
# group_name = self.env['ir.model.data'].sudo().search([
|
||||
# ('model', '=', 'res.groups'),
|
||||
# ('res_id', '=', rec['groups_id'][0])
|
||||
# ]).name
|
||||
# module_name = self.env['ir.model.data'].sudo().search([
|
||||
# ('model', '=', 'res.groups'),
|
||||
# ('res_id', '=', rec['groups_id'][0])
|
||||
# ]).module
|
||||
# group = module_name + "." + group_name
|
||||
# if self.env.user.has_group(group):
|
||||
# if rec['is_delete']:
|
||||
# raise UserError(_('You are restricted from performing this'
|
||||
# ' operation. Please contact the'
|
||||
# ' administrator.'))
|
||||
# 检查 'access.right' 模型是否存在于环境中
|
||||
if 'access.right' in self.env:
|
||||
# current_model_id = self.env['ir.model'].sudo().search([('model', '=', self._name)]).id
|
||||
access_right_rec = self.env['access.right'].sudo().search_read(
|
||||
[('model_id', '=', current_model_id)], ['model_id', 'is_delete', 'groups_id']
|
||||
)
|
||||
|
||||
if access_right_rec and not self.env.is_admin():
|
||||
for rec in access_right_rec:
|
||||
group_data = self.env['ir.model.data'].sudo().search_read(
|
||||
[('model', '=', 'res.groups'), ('res_id', '=', rec['groups_id'][0])],
|
||||
['name', 'module']
|
||||
)
|
||||
|
||||
if group_data:
|
||||
group_name = group_data[0]['name']
|
||||
module_name = group_data[0]['module']
|
||||
group_xml_id = f"{module_name}.{group_name}"
|
||||
|
||||
if self.env.user.has_group(group_xml_id) and rec['is_delete']:
|
||||
raise UserError(
|
||||
_('You are restricted from performing this operation. Please contact the administrator.'))
|
||||
else:
|
||||
# 如果 'access.right' 模型不存在,可以在这里定义备选逻辑
|
||||
pass
|
||||
|
||||
return True
|
||||
|
||||
|
||||
BaseModel._create = _create
|
||||
BaseModel.unlink = unlink
|
||||
2
jikimo_hide_options/security/ir.model.access.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_access_right,access.access.right,model_access_right,jikimo_hide_options.model_access_rights_groups_configure_model_access,1,1,1,1
|
||||
|
9
jikimo_hide_options/security/security.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--Add a group named Configure Model Access in res.groups-->
|
||||
<odoo>
|
||||
<record id="model_access_rights_groups_configure_model_access" model="res.groups">
|
||||
<field name="name">配置隐藏项目</field>
|
||||
<field name="category_id" ref="base.module_category_usability"/>
|
||||
<field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
|
||||
</record>
|
||||
</odoo>
|
||||
BIN
jikimo_hide_options/static/description/assets/icons/check.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
jikimo_hide_options/static/description/assets/icons/chevron.png
Normal file
|
After Width: | Height: | Size: 310 B |
BIN
jikimo_hide_options/static/description/assets/icons/cogs.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 576 B |
|
After Width: | Height: | Size: 733 B |
|
After Width: | Height: | Size: 911 B |
BIN
jikimo_hide_options/static/description/assets/icons/license.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
jikimo_hide_options/static/description/assets/icons/lifebuoy.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 673 B |
|
After Width: | Height: | Size: 878 B |
BIN
jikimo_hide_options/static/description/assets/icons/puzzle.png
Normal file
|
After Width: | Height: | Size: 653 B |
|
After Width: | Height: | Size: 905 B |
|
After Width: | Height: | Size: 839 B |
|
After Width: | Height: | Size: 427 B |
BIN
jikimo_hide_options/static/description/assets/icons/training.png
Normal file
|
After Width: | Height: | Size: 627 B |
BIN
jikimo_hide_options/static/description/assets/icons/update.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
jikimo_hide_options/static/description/assets/icons/user.png
Normal file
|
After Width: | Height: | Size: 988 B |
BIN
jikimo_hide_options/static/description/assets/icons/wrench.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
BIN
jikimo_hide_options/static/description/assets/misc/check-box.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
jikimo_hide_options/static/description/assets/misc/compass.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
jikimo_hide_options/static/description/assets/misc/corporate.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 4.4 KiB |
BIN
jikimo_hide_options/static/description/assets/misc/features.png
Normal file
|
After Width: | Height: | Size: 589 B |
BIN
jikimo_hide_options/static/description/assets/misc/logo.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
jikimo_hide_options/static/description/assets/misc/pictures.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
jikimo_hide_options/static/description/assets/misc/pie-chart.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 967 B |
BIN
jikimo_hide_options/static/description/assets/misc/star.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
jikimo_hide_options/static/description/assets/misc/support.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
jikimo_hide_options/static/description/assets/misc/whatsapp.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
jikimo_hide_options/static/description/assets/modules/1.png
Normal file
|
After Width: | Height: | Size: 228 KiB |
BIN
jikimo_hide_options/static/description/assets/modules/l2.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
jikimo_hide_options/static/description/assets/modules/l3.png
Normal file
|
After Width: | Height: | Size: 82 KiB |
BIN
jikimo_hide_options/static/description/assets/modules/l4.png
Normal file
|
After Width: | Height: | Size: 83 KiB |
BIN
jikimo_hide_options/static/description/assets/modules/l5.png
Normal file
|
After Width: | Height: | Size: 88 KiB |
BIN
jikimo_hide_options/static/description/assets/modules/l6.png
Normal file
|
After Width: | Height: | Size: 237 KiB |
|
After Width: | Height: | Size: 138 KiB |
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 95 KiB |
|
After Width: | Height: | Size: 87 KiB |
|
After Width: | Height: | Size: 219 KiB |
|
After Width: | Height: | Size: 127 KiB |
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 83 KiB |
|
After Width: | Height: | Size: 94 KiB |
BIN
jikimo_hide_options/static/description/banner.jpg
Normal file
|
After Width: | Height: | Size: 124 KiB |
BIN
jikimo_hide_options/static/description/icon.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
596
jikimo_hide_options/static/description/index.html
Normal file
@@ -0,0 +1,596 @@
|
||||
<div style="background-color: #714B67; height: 810px; width: 100%; padding: 15px; position: relative;">
|
||||
<!-- TITLE BAR -->
|
||||
<div class="d-flex align-items-center justify-content-between"
|
||||
style="border-bottom: 1px solid #875A7B; padding: 15px; display: flex; justify-content: space-between; align-items: center;">
|
||||
<img src="assets/misc/cybrosys-logo.png" width="42" height="42" style="width: 42px; height: 42px;" />
|
||||
<div>
|
||||
<div
|
||||
style="color: #7C7BAD; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;"
|
||||
class="mr-2">
|
||||
<i class="fa fa-check mr-1"></i>Community
|
||||
</div>
|
||||
<div
|
||||
style="color: #875A7B; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;"
|
||||
class="mr-2">
|
||||
<i class="fa fa-check mr-1"></i>Enterprise
|
||||
</div>
|
||||
<div
|
||||
style="color: #017E84; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;"
|
||||
class="mr-2">
|
||||
<i class="fa fa-check mr-1"></i>Odoo.sh
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END OF TITLE BAR -->
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-12 col-lg-12">
|
||||
<!-- APP HERO -->
|
||||
<h1 style="color: #FFFFFF; font-weight: bolder; font-size: 50px; text-align: center; margin-top: 50px;">
|
||||
Hide Create|Delete|Archive|Export Options - Model Wise</h1>
|
||||
<p style="color:#FFFFFF; padding: 8px 15px; text-align: center; font-size: 24px;">Hide Create, Delete, Archive, Export Options in Models</p>
|
||||
<!-- END OF APP HERO -->
|
||||
<img src="assets/screenshots/hero.gif" class="img-responsive"
|
||||
style="width: 100%; margin-left: auto; margin-right: auto;" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<!-- NAVIGATION SECTION -->
|
||||
<div class="d-flex align-items-center" style="border-bottom: 2px solid #714B67; padding: 15px 0px; margin-top: 300px;">
|
||||
<div class="d-flex justify-content-center align-items-center mr-2"
|
||||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
|
||||
<img src="assets/misc/compass.png" />
|
||||
</div>
|
||||
<h2 class="mt-2" style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">Explore This
|
||||
Module</h2>
|
||||
</div>
|
||||
<div class="row my-4" style="font-family: 'Montserrat', sans-serif;">
|
||||
<div class="col-sm-12 col-md-6 my-3">
|
||||
<a href="#overview">
|
||||
<div class="d-flex justify-content-between align-items-center"
|
||||
style="background-color: #f5f5f5; padding: 30px; width: 100%;">
|
||||
<div>
|
||||
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Overview</span>
|
||||
<span
|
||||
style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">Learn
|
||||
more about this
|
||||
module</span>
|
||||
</div>
|
||||
<img src="assets/misc/right-arrow.png" width="36" height="36" />
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6 my-3">
|
||||
<a href="#features">
|
||||
<div class="d-flex justify-content-between align-items-center"
|
||||
style="background-color: #f5f5f5; padding: 30px; width: 100%;">
|
||||
<div>
|
||||
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Features</span>
|
||||
<span
|
||||
style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">View
|
||||
features of this
|
||||
module</span>
|
||||
</div>
|
||||
<img src="assets/misc/right-arrow.png" width="36" height="36" />
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6 my-3">
|
||||
<a href="#screenshots">
|
||||
<div class="d-flex justify-content-between align-items-center"
|
||||
style="background-color: #f5f5f5; padding: 30px; width: 100%;">
|
||||
<div>
|
||||
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Screenshots</span>
|
||||
<span
|
||||
style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">View
|
||||
screenshots of this
|
||||
module</span>
|
||||
</div>
|
||||
<img src="assets/misc/right-arrow.png" width="36" height="36" />
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END OF NAVIGATION SECTION -->
|
||||
|
||||
<!-- OVERVIEW SECTION -->
|
||||
<div class="d-flex align-items-center" style="border-bottom: 2px solid #714B67; padding: 15px 0px;" id="overview">
|
||||
<div class="d-flex justify-content-center align-items-center mr-2"
|
||||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
|
||||
<img src="assets/misc/pie-chart.png" />
|
||||
</div>
|
||||
<h2 class="mt-2" style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">Overview
|
||||
</h2>
|
||||
</div>
|
||||
<div class="row" style="font-family: 'Montserrat', sans-serif; font-weight: 400; font-size: 14px; line-height: 200%;">
|
||||
<div class="col-sm-12 py-4">
|
||||
By using this module we can hide the options like create,delete,export,and archive/un archive in the model
|
||||
which we want. Here we are also able to select the user groups except Administrator which we want to apply the
|
||||
above hiding functionality </div>
|
||||
</div>
|
||||
<!-- END OF OVERVIEW SECTION -->
|
||||
|
||||
<!-- FEATURES SECTION -->
|
||||
<div class="d-flex align-items-center" style="border-bottom: 2px solid #714B67; padding: 15px 0px;" id="features">
|
||||
<div class="d-flex justify-content-center align-items-center mr-2"
|
||||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
|
||||
<img src="assets/misc/features.png" />
|
||||
</div>
|
||||
<h2 class="mt-2" style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">Features
|
||||
</h2>
|
||||
</div>
|
||||
<div class="row" style="font-family: 'Montserrat', sans-serif; font-weight: 400; font-size: 14px; line-height: 200%;">
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<div class="d-flex align-items-center" style="margin-top: 40px; margin-bottom: 40px">
|
||||
<img src="assets/misc/check-box.png" class="mr-2" />
|
||||
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> Easily hide the options like Create,Delete,Export and Archive/UnArchive</span>
|
||||
</div>
|
||||
<div class="d-flex align-items-center" style="margin-top: 30px; margin-bottom: 30px">
|
||||
<img src="assets/misc/check-box.png" class="mr-2" />
|
||||
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Can hide the options for specific model</span>
|
||||
</div>
|
||||
<div class="d-flex align-items-center" style="margin-top: 30px; margin-bottom: 30px">
|
||||
<img src="assets/misc/check-box.png" class="mr-2" />
|
||||
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Can hide the options for specific user group</span>
|
||||
</div>
|
||||
<div class="d-flex align-items-center" style="margin-top: 30px; margin-bottom: 30px">
|
||||
<img src="assets/misc/check-box.png" class="mr-2" />
|
||||
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">No additional configuration needed</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END OF FEATURES SECTION -->
|
||||
|
||||
<!-- SCREENSHOTS SECTION -->
|
||||
<div class="d-flex align-items-center" style="border-bottom: 2px solid #714B67; padding: 15px 0px;" id="screenshots">
|
||||
<div class="d-flex justify-content-center align-items-center mr-2"
|
||||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
|
||||
<img src="assets/misc/pictures.png" />
|
||||
</div>
|
||||
<h2 class="mt-2" style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">Screenshots
|
||||
</h2>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
|
||||
<div style="display: block; margin: 30px auto;">
|
||||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> Go to Settings > Users and there you can see the Configure Model Access, by enabling that
|
||||
option and refresh the page, you can see a new menu named 'Restrict Access Rights'</h3>
|
||||
<img src="assets/screenshots/model_access_right_01.png" class="img-thumbnail">
|
||||
</div>
|
||||
|
||||
<div style="display: block; margin: 30px auto;">
|
||||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> User in the Purchase module</h3>
|
||||
<img src="assets/screenshots/model_access_right_02.png" class="img-thumbnail">
|
||||
</div>
|
||||
|
||||
<div style="display: block; margin: 30px auto;">
|
||||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Select the Model, Groups and the options which we want to hide</h3>
|
||||
<img src="assets/screenshots/model_access_right_03.png" class="img-thumbnail">
|
||||
</div>
|
||||
<div style="display: block; margin: 30px auto;">
|
||||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> We can see Create option is hidden in purchase.order to those who are User
|
||||
in purchase module</h3>
|
||||
<img src="assets/screenshots/model_access_right_04.png" class="img-thumbnail">
|
||||
</div>
|
||||
|
||||
<div style="display: block; margin: 30px auto;">
|
||||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">User in Project module</h3>
|
||||
<img src="assets/screenshots/model_access_right_05.png" class="img-thumbnail">
|
||||
</div>
|
||||
<div style="display: block; margin: 30px auto;">
|
||||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> By default, we can see Export and Archive/UnArchive options</h3>
|
||||
<img src="assets/screenshots/model_access_right_06.png" class="img-thumbnail">
|
||||
</div>
|
||||
<div style="display: block; margin: 30px auto;">
|
||||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> Select the options which we want to hide</h3>
|
||||
<img src="assets/screenshots/model_access_right_07.png" class="img-thumbnail">
|
||||
</div>
|
||||
<div style="display: block; margin: 30px auto;">
|
||||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> Export and Archive/UnArchive functionality are hidden</h3>
|
||||
<img src="assets/screenshots/model_access_right_08.png" class="img-thumbnail">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END OF SCREENSHOTS SECTION -->
|
||||
<!-- RELATED PRODUCTS -->
|
||||
<div class="d-flex align-items-center"
|
||||
style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
|
||||
<div class="d-flex justify-content-center align-items-center mr-2"
|
||||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
|
||||
<img src="assets/misc/categories.png"/>
|
||||
</div>
|
||||
<h2 class="mt-2"
|
||||
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
|
||||
Related
|
||||
Products
|
||||
</h2>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div id="demo1" class="row carousel slide" data-ride="carousel">
|
||||
<!-- The slideshow -->
|
||||
<div class="carousel-inner" style="padding: 30px;">
|
||||
<div class="carousel-item" style="min-height: 198.656px;">
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
|
||||
style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/16.0/openai_odoo_base/"
|
||||
target="_blank">
|
||||
<div style="border-radius:10px">
|
||||
<img class="img img-responsive center-block"
|
||||
style="border-radius: 0px;"
|
||||
src="assets/modules/1.png">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
|
||||
style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/16.0/woo_commerce/"
|
||||
target="_blank">
|
||||
<div style="border-radius:10px">
|
||||
<img class="img img-responsive center-block"
|
||||
style="border-radius: 0px;"
|
||||
src="assets/modules/l2.png">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
|
||||
style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/16.0/shopify_odoo_connector/"
|
||||
target="_blank">
|
||||
<div style="border-radius:10px">
|
||||
<img class="img img-responsive center-block"
|
||||
style="border-radius: 0px;"
|
||||
src="assets/modules/l3.png">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="carousel-item active"
|
||||
style="min-height: 198.656px;">
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
|
||||
style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/16.0/hr_zk_attendance/"
|
||||
target="_blank">
|
||||
<div style="border-radius:10px">
|
||||
<img class="img img-responsive center-block"
|
||||
style="border-radius: 0px;"
|
||||
src="assets/modules/l4.png">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
|
||||
style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/16.0/whatsapp_redirect/"
|
||||
target="_blank">
|
||||
<div style="border-radius:10px">
|
||||
<img class="img img-responsive center-block"
|
||||
style="border-radius: 0px;"
|
||||
src="assets/modules/l5.png">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
|
||||
style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/16.0/openai_website_product_media/"
|
||||
target="_blank">
|
||||
<div style="border-radius:10px">
|
||||
<img class="img img-responsive center-block"
|
||||
style="border-radius: 0px;"
|
||||
src="assets/modules/l6.png">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Left and right controls -->
|
||||
<a class="carousel-control-prev" href="#demo1" data-slide="prev"
|
||||
style="width:35px; color:#000"> <span
|
||||
class="carousel-control-prev-icon"><i
|
||||
class="fa fa-chevron-left"
|
||||
style="font-size:24px"></i></span>
|
||||
</a> <a class="carousel-control-next" href="#demo1"
|
||||
data-slide="next" style="width:35px; color:#000">
|
||||
<span class="carousel-control-next-icon"><i
|
||||
class="fa fa-chevron-right"
|
||||
style="font-size:24px"></i></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END OF RELATED PRODUCTS -->
|
||||
|
||||
<!-- OUR SERVICES -->
|
||||
|
||||
<div class="d-flex align-items-center" style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
|
||||
<div class="d-flex justify-content-center align-items-center mr-2"
|
||||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
|
||||
<img src="assets/misc/star.png" />
|
||||
</div>
|
||||
<h2 class="mt-2" style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">Our Services
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="container my-5">
|
||||
<div class="row">
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #1dd1a1 !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/cogs.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Customization</h6>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #ff6b6b !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/wrench.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Implementation</h6>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #6462CD !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/lifebuoy.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Support</h6>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #ffa801 !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/user.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Hire
|
||||
Odoo
|
||||
Developer</h6>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #54a0ff !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/puzzle.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Integration</h6>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #6d7680 !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/update.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Migration</h6>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #786fa6 !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/consultation.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Consultancy</h6>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #f8a5c2 !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/training.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Implementation</h6>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #e6be26 !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/license.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Licensing Consultancy</h6>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- END OF OUR SERVICES -->
|
||||
|
||||
<!-- OUR INDUSTRIES -->
|
||||
|
||||
<div class="d-flex align-items-center" style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
|
||||
<div class="d-flex justify-content-center align-items-center mr-2"
|
||||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
|
||||
<img src="assets/misc/corporate.png" />
|
||||
</div>
|
||||
<h2 class="mt-2" style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">Our
|
||||
Industries
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="container my-5">
|
||||
<div class="row">
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="assets/icons/trading-black.png" class="img-responsive mb-3" height="48px" width="48px">
|
||||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
Trading
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
Easily procure
|
||||
and
|
||||
sell your products</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="assets/icons/pos-black.png" class="img-responsive mb-3" height="48px" width="48px">
|
||||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
POS
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
Easy
|
||||
configuration
|
||||
and convivial experience</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="assets/icons/education-black.png" class="img-responsive mb-3" height="48px" width="48px">
|
||||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
Education
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
A platform for
|
||||
educational management</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="assets/icons/manufacturing-black.png" class="img-responsive mb-3" height="48px"
|
||||
width="48px">
|
||||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
Manufacturing
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
Plan, track and
|
||||
schedule your operations</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="assets/icons/ecom-black.png" class="img-responsive mb-3" height="48px" width="48px">
|
||||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
E-commerce & Website
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
Mobile
|
||||
friendly,
|
||||
awe-inspiring product pages</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="assets/icons/service-black.png" class="img-responsive mb-3" height="48px" width="48px">
|
||||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
Service Management
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
Keep track of
|
||||
services and invoice</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="assets/icons/restaurant-black.png" class="img-responsive mb-3" height="48px" width="48px">
|
||||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
Restaurant
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
Run your bar or
|
||||
restaurant methodically</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="assets/icons/hotel-black.png" class="img-responsive mb-3" height="48px" width="48px">
|
||||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
Hotel Management
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
An
|
||||
all-inclusive
|
||||
hotel management application</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- END OF OUR INDUSTRIES -->
|
||||
|
||||
<!-- SUPPORT -->
|
||||
<div class="d-flex align-items-center" style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
|
||||
<div class="d-flex justify-content-center align-items-center mr-2"
|
||||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
|
||||
<img src="assets/misc/customer-support.png" />
|
||||
</div>
|
||||
<h2 class="mt-2" style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">Support
|
||||
</h2>
|
||||
</div>
|
||||
<div class="container mt-5">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<div style="background-color: #F6F8F9; padding: 30px; display: flex; align-items: center;">
|
||||
<div class="mr-4"
|
||||
style="background-color: #714B67; display: inline-block; height: 70px; width: 70px; display: flex; align-items: center; justify-content: center;">
|
||||
<img src="assets/misc/support.png" height="48" width="48" style="width: 42px; height: 42px;" />
|
||||
</div>
|
||||
<div>
|
||||
<h4>Need Help?</h4>
|
||||
<p style="line-height: 100%;">Got questions or need help? Get in touch.</p>
|
||||
<a href="mailto:odoo@cybrosys.com">
|
||||
<p style="font-weight: 400; font-size: 28px; line-height: 80%; color: #714B67;">
|
||||
odoo@cybrosys.com</p>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<div style="background-color: #F6F8F9; padding: 30px; display: flex; align-items: center;">
|
||||
<div class="mr-4"
|
||||
style="background-color: #2AC44D; display: inline-block; height: 70px; width: 70px; display: flex; align-items: center; justify-content: center;">
|
||||
<img src="assets/misc/whatsapp.png" height="52" width="52" style="width: 52px; height: 52px;" />
|
||||
</div>
|
||||
<div>
|
||||
<h4>WhatsApp</h4>
|
||||
<p style="line-height: 100%;">Say hi to us on WhatsApp!</p>
|
||||
<a href="https://api.whatsapp.com/send?phone=918606827707">
|
||||
<p style="font-weight: 400; font-size: 28px; line-height: 80%; color: #714B67;">+91 86068
|
||||
27707</p>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12 my-5 d-flex justify-content-center align-items-center">
|
||||
<img src="assets/misc/logo.png" width="144" height="31"
|
||||
style="width:144px; height: 31px; margin-top: 40px;" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END OF SUPPORT -->
|
||||
46
jikimo_hide_options/static/src/js/form_controller.js
Normal file
@@ -0,0 +1,46 @@
|
||||
/** @odoo-module */
|
||||
/**
|
||||
* This file will used to hide the selected options from the form view
|
||||
*/
|
||||
import { FormController} from "@web/views/form/form_controller";
|
||||
import { patch} from "@web/core/utils/patch";
|
||||
var rpc = require('web.rpc');
|
||||
const { onWillStart} = owl;
|
||||
patch(FormController.prototype, 'jikimo_hide_options/static/src/js/form_controller.js.FormController', {
|
||||
/**
|
||||
* This function will used to hide the selected options from the form view
|
||||
*/
|
||||
setup() {
|
||||
this._super();
|
||||
onWillStart(async () => {
|
||||
var self = this
|
||||
var result;
|
||||
await rpc.query({
|
||||
model: 'access.right',
|
||||
method: 'hide_buttons',
|
||||
}).then(function(data) {
|
||||
result = data;
|
||||
});
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
var group = result[i].module + "." + result[i].group_name
|
||||
if (self.props.resModel == result[i].model) {
|
||||
if (await self.user.hasGroup(group)) {
|
||||
if (!this.user.isAdmin) {
|
||||
if (result[i].is_create_or_update) {
|
||||
self.canCreate = false
|
||||
}
|
||||
if (result[i].is_delete) {
|
||||
this.archInfo.activeActions.delete = false
|
||||
}
|
||||
if (result[i].is_archive) {
|
||||
self.archiveEnabled = false
|
||||
} else {
|
||||
self.archiveEnabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
42
jikimo_hide_options/static/src/js/kanban_controller.js
Normal file
@@ -0,0 +1,42 @@
|
||||
/** @odoo-module */
|
||||
/**
|
||||
* This file will used to hide the selected options from the list view
|
||||
*/
|
||||
import { KanbanController } from '@web/views/kanban/kanban_controller';
|
||||
import { patch} from "@web/core/utils/patch";
|
||||
var rpc = require('web.rpc');
|
||||
const {onWillStart} = owl;
|
||||
patch(KanbanController.prototype, 'jikimo_hide_options/static/src/js/list_controller.js.KanbanController', {
|
||||
/**
|
||||
* This function will used to hide the selected options from the Kanban view
|
||||
*/
|
||||
setup() {
|
||||
this._super();
|
||||
onWillStart(async () => {
|
||||
var self = this
|
||||
var result;
|
||||
await rpc.query({
|
||||
model: 'access.right',
|
||||
method: 'hide_buttons',
|
||||
}).then(function(data) {
|
||||
result = data;
|
||||
});
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
var group = result[i].module + "." + result[i].group_name
|
||||
if (self.props.resModel == result[i].model) {
|
||||
if (await self.model.user.hasGroup(group)) {
|
||||
if (!self.model.user.isAdmin) {
|
||||
if (result[i].is_create_or_update) {
|
||||
self.props.archInfo.activeActions.create=false
|
||||
self.props.archInfo.activeActions.edit=false
|
||||
}
|
||||
if (result[i].is_delete) {
|
||||
self.props.archInfo.activeActions.delete=false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
50
jikimo_hide_options/static/src/js/list_controller.js
Normal file
@@ -0,0 +1,50 @@
|
||||
/** @odoo-module */
|
||||
/**
|
||||
* This file will used to hide the selected options from the list view
|
||||
*/
|
||||
import { ListController} from '@web/views/list/list_controller';
|
||||
import { patch} from "@web/core/utils/patch";
|
||||
var rpc = require('web.rpc');
|
||||
const {onWillStart} = owl;
|
||||
patch(ListController.prototype, 'jikimo_hide_options/static/src/js/list_controller.js.ListController', {
|
||||
/**
|
||||
* This function will used to hide the selected options from the list view
|
||||
*/
|
||||
setup() {
|
||||
this._super();
|
||||
onWillStart(async () => {
|
||||
var self = this
|
||||
var result;
|
||||
await rpc.query({
|
||||
model: 'access.right',
|
||||
method: 'hide_buttons',
|
||||
}).then(function(data) {
|
||||
result = data;
|
||||
});
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
var group = result[i].module + "." + result[i].group_name
|
||||
if (self.props.resModel == result[i].model) {
|
||||
if (await self.userService.hasGroup(group)) {
|
||||
if (!this.userService.isAdmin) {
|
||||
if (result[i].is_create_or_update) {
|
||||
self.activeActions.create = false;
|
||||
}
|
||||
if (result[i].is_export) {
|
||||
self.isExportEnable = false
|
||||
self.isExportEnable = false
|
||||
}
|
||||
if (result[i].is_delete) {
|
||||
self.activeActions.delete = false;
|
||||
}
|
||||
if (result[i].is_archive) {
|
||||
self.archiveEnabled = false;
|
||||
} else {
|
||||
self.archiveEnabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
58
jikimo_hide_options/views/model_access_rights_views.xml
Normal file
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<!-- Action for the menu Restrict Model Access-->
|
||||
<record id="access_right_action" model="ir.actions.act_window">
|
||||
<field name="name">隐藏项目</field>
|
||||
<field name="res_model">access.right</field>
|
||||
<field name='view_mode'>tree,form</field>
|
||||
</record>
|
||||
<!-- Tree view for the model access.right-->
|
||||
<record id="access_right_view_tree" model="ir.ui.view">
|
||||
<field name="name">access.right.view.tree</field>
|
||||
<field name="model">access.right</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree>
|
||||
<field name="model_id" string="模型"/>
|
||||
<field name="groups_id" string="用户组"/>
|
||||
<field name="is_delete" string="删除"/>
|
||||
<field name="is_export" string="导出"/>
|
||||
<field name="is_create_or_update" string="创建或更新"/>
|
||||
<field name="is_archive" string="归档"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<!-- Form view for the model access.right-->
|
||||
<record id="access_right_view_form" model="ir.ui.view">
|
||||
<field name="name">access.right.view.form</field>
|
||||
<field name="model">access.right</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<sheet>
|
||||
<group>
|
||||
<group>
|
||||
<field name="model_id" string="模型"/>
|
||||
<field name="groups_id" string="用户组"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="is_delete" string="删除"/>
|
||||
<field name="is_export" string="导出"/>
|
||||
<field name="is_create_or_update" string="创建或更新"/>
|
||||
<field name="is_archive" string="归档"/>
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids"/>
|
||||
<field name="message_ids"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<!-- Creating a menu named Restrict Model Access-->
|
||||
<menuitem id="access_right_menu"
|
||||
name="隐藏项目"
|
||||
parent="base.menu_administration"
|
||||
action="access_right_action"
|
||||
sequence="6"
|
||||
groups="jikimo_hide_options.model_access_rights_groups_configure_model_access"/>
|
||||
</odoo>
|
||||
@@ -23,7 +23,7 @@ html .o_web_client > .o_action_manager > .o_action {
|
||||
}
|
||||
|
||||
.o_form_view {
|
||||
background-color: unset !important;
|
||||
//background-color: unset !important;
|
||||
min-height: unset !important;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,9 +38,9 @@
|
||||
<xpath expr="//field[@name='state']" position="after">
|
||||
<field name="production_state" invisible="1"/>
|
||||
</xpath>
|
||||
<xpath expr="//button[@name='action_open_wizard']" position="after">
|
||||
<button name="open_tablet_view" type="object" icon="fa-tablet" title="Open Tablet View" context="{'from_production_order': True}" attrs="{'invisible': ['|', ('production_state', 'in', ('draft', 'cancel', 'done')), ('state', '=', 'done')]}"/>
|
||||
</xpath>
|
||||
<!-- <xpath expr="//button[@name='action_open_wizard']" position="after">-->
|
||||
<!-- <button name="open_tablet_view" type="object" icon="fa-tablet" title="Open Tablet View" context="{'from_production_order': True}" attrs="{'invisible': ['|', ('production_state', 'in', ('draft', 'cancel', 'done')), ('state', '=', 'done')]}"/>-->
|
||||
<!-- </xpath>-->
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -4,14 +4,14 @@ csv_internal_sep = ,
|
||||
data_dir = /var/lib/odoo
|
||||
db_host = 172.17.0.2
|
||||
db_maxconn = 64
|
||||
db_name = sf_cs_dev937
|
||||
db_name = sf_t2cs_003
|
||||
db_password = sf
|
||||
db_port = 5432
|
||||
db_sslmode = prefer
|
||||
db_template = template0
|
||||
db_user = sf
|
||||
dbfilter =
|
||||
demo = {}
|
||||
without_demo = all
|
||||
email_from = False
|
||||
from_filter = False
|
||||
geoip_database = /usr/share/GeoIP/GeoLite2-City.mmdb
|
||||
@@ -56,7 +56,6 @@ test_tags = None
|
||||
;transient_age_limit = 1.0
|
||||
;translate_modules = ['all']
|
||||
unaccent = False
|
||||
upgrade_path =
|
||||
without_demo = False
|
||||
upgrade_path =
|
||||
workers = 0
|
||||
|
||||
|
||||
@@ -7,10 +7,15 @@
|
||||
<field name="model">quality.point</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<header>
|
||||
</header>
|
||||
<sheet>
|
||||
<div class="oe_button_box" name="button_box"/>
|
||||
<widget name="web_ribbon" title="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
|
||||
<h2><field name="name" readonly="1"/></h2>
|
||||
<widget name="web_ribbon" title="Archived" bg_color="bg-danger"
|
||||
attrs="{'invisible': [('active', '=', True)]}"/>
|
||||
<h2>
|
||||
<field name="name" readonly="1"/>
|
||||
</h2>
|
||||
<group>
|
||||
<group>
|
||||
<field name="active" invisible="1"/>
|
||||
@@ -33,13 +38,14 @@
|
||||
<field name="note" placeholder="Describe the quality check to do..."/>
|
||||
</page>
|
||||
<page string="Notes" name="Notes">
|
||||
<field name="reason" string="Note" placeholder="Describe why you need to perform this quality check..."/>
|
||||
<field name="reason" string="Note"
|
||||
placeholder="Describe why you need to perform this quality check..."/>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids"/>
|
||||
<field name="message_ids"/>
|
||||
<field name="message_follower_ids"/>
|
||||
<field name="message_ids"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
@@ -85,17 +91,18 @@
|
||||
<filter name="filter_date_close" date="date_close"/>
|
||||
<separator/>
|
||||
<filter string="Late Activities" name="activities_overdue"
|
||||
domain="[('my_activity_date_deadline', '<', context_today().strftime('%Y-%m-%d'))]"
|
||||
help="Show all records which has next action date is before today"/>
|
||||
domain="[('my_activity_date_deadline', '<', context_today().strftime('%Y-%m-%d'))]"
|
||||
help="Show all records which has next action date is before today"/>
|
||||
<filter string="Today Activities" name="activities_today"
|
||||
domain="[('my_activity_date_deadline', '=', context_today().strftime('%Y-%m-%d'))]"/>
|
||||
domain="[('my_activity_date_deadline', '=', context_today().strftime('%Y-%m-%d'))]"/>
|
||||
<filter string="Future Activities" name="activities_upcoming_all"
|
||||
domain="[('my_activity_date_deadline', '>', context_today().strftime('%Y-%m-%d'))]"/>
|
||||
domain="[('my_activity_date_deadline', '>', context_today().strftime('%Y-%m-%d'))]"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter string="Stage" name="groupby_stage" domain="[]" context="{'group_by': 'stage_id'}"/>
|
||||
<filter string="Responsible" name="groupby_user" domain="[]" context="{'group_by': 'user_id'}"/>
|
||||
<filter string="Root Cause" name="groupby_reason" domain="[]" context="{'group_by': 'reason_id'}"/>
|
||||
<filter string="Creation Date" name="groupby_createmonth" domain="[]" context="{'group_by': 'create_date'}"/>
|
||||
<filter string="Creation Date" name="groupby_createmonth" domain="[]"
|
||||
context="{'group_by': 'create_date'}"/>
|
||||
<filter string="Quality Team" name="groupby_team_id" domain="[]" context="{'group_by': 'team_id'}"/>
|
||||
</group>
|
||||
</search>
|
||||
@@ -122,4 +129,4 @@
|
||||
</record>
|
||||
|
||||
<!-- js stuff -->
|
||||
</odoo>
|
||||
</odoo>
|
||||
|
||||
@@ -602,6 +602,7 @@
|
||||
<field name="model">quality.alert.team</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<header></header>
|
||||
<sheet>
|
||||
<div class="oe_title">
|
||||
<label for="name" string="Team Name"/>
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
from . import models
|
||||
from . import commons
|
||||
from . import controllers
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
""",
|
||||
'category': 'sf',
|
||||
'website': 'https://www.sf.jikimo.com',
|
||||
'depends': ['account', 'base', 'mrp_workorder', 'sale'],
|
||||
'depends': ['base', 'mrp_workorder', 'sale', 'purchase', 'sales_team'],
|
||||
'data': [
|
||||
'security/group_security.xml',
|
||||
'security/ir.model.access.csv',
|
||||
@@ -19,9 +19,11 @@
|
||||
'views/fixture_view.xml',
|
||||
'views/functional_fixture_view.xml',
|
||||
'views/menu_view.xml',
|
||||
"views/tool_views.xml",
|
||||
"views/tool_menu.xml",
|
||||
'views/tool_views.xml',
|
||||
'views/tool_basic_param.xml',
|
||||
'views/tool_menu.xml',
|
||||
'views/menu_fixture_view.xml',
|
||||
'views/change_base_view.xml',
|
||||
|
||||
],
|
||||
'demo': [
|
||||
|
||||
@@ -1 +1 @@
|
||||
from. import common
|
||||
from . import common
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from odoo import models
|
||||
import time
|
||||
import hashlib
|
||||
from odoo import models
|
||||
|
||||
|
||||
class Common(models.Model):
|
||||
_name = 'sf.sync.common'
|
||||
_description = u'公用类'
|
||||
|
||||
def get_headers(self,token, secret_key):
|
||||
def get_headers(self, token, secret_key):
|
||||
'''
|
||||
获取requests中的heardes参数
|
||||
'''
|
||||
@@ -20,4 +20,12 @@ class Common(models.Model):
|
||||
'checkstr': check_sf_str}
|
||||
return headers
|
||||
|
||||
|
||||
def get_add_time(self, parse_time):
|
||||
"""
|
||||
把时间增加8小时
|
||||
:return:
|
||||
"""
|
||||
dt = datetime.datetime.strptime(parse_time, "%Y-%m-%d %H:%M:%S")
|
||||
d = dt + datetime.timedelta(hours=8)
|
||||
nTime = d.strftime("%Y-%m-%d %H:%M:%S")
|
||||
return nTime
|
||||
|
||||
1
sf_base/controllers/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import controllers
|
||||
40
sf_base/controllers/controllers.py
Normal file
@@ -0,0 +1,40 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import logging
|
||||
import json
|
||||
import base64
|
||||
from odoo import http
|
||||
from odoo.http import request
|
||||
|
||||
|
||||
class Manufacturing_Connect(http.Controller):
|
||||
|
||||
@http.route('/AutoDeviceApi/MaintenanceToolGroups', type='json', auth='none', methods=['GET', 'POST'], csrf=False,
|
||||
cors="*")
|
||||
def get_maintenance_tool_groups_Info(self, **kw):
|
||||
"""
|
||||
机床刀具组接口
|
||||
:param kw:
|
||||
:return:
|
||||
"""
|
||||
logging.info('get_maintenance_tool_groups_Info:%s' % kw)
|
||||
try:
|
||||
datas = request.httprequest.data
|
||||
ret = json.loads(datas)
|
||||
ret = json.loads(ret['result'])
|
||||
logging.info('DeviceId:%s' % ret)
|
||||
tool_groups = request.env['sf.tool.groups'].sudo().search([])
|
||||
|
||||
res = {'Succeed': True, 'Datas': []}
|
||||
if tool_groups:
|
||||
for item in tool_groups:
|
||||
device_id = ''
|
||||
for equipment_id in item.equipment_ids:
|
||||
device_id = '%s,%s' % (device_id, equipment_id.name)
|
||||
res['Datas'].append({
|
||||
'GroupName': item.name,
|
||||
'DeviceId': device_id
|
||||
})
|
||||
except Exception as e:
|
||||
res = {'Succeed': False, 'ErrorCode': 202, 'Error': e}
|
||||
logging.info('get_maintenance_tool_groups_Info error:%s' % e)
|
||||
return json.JSONEncoder().encode(res)
|
||||
@@ -3,9 +3,5 @@ from . import common
|
||||
from . import tool_base_new
|
||||
from . import fixture
|
||||
from . import functional_fixture
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
from . import tool_other_features
|
||||
from . import basic_parameters_fixture
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import logging
|
||||
import requests
|
||||
import json
|
||||
import requests
|
||||
from odoo import fields, models, api
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo.addons.sf_base.commons.common import Common
|
||||
@@ -9,6 +9,14 @@ from odoo.addons.sf_base.commons.common import Common
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SpindleTaperType(models.Model):
|
||||
_name = 'spindle.taper.type'
|
||||
_description = '主轴锥孔型号'
|
||||
|
||||
name = fields.Char('名称')
|
||||
active = fields.Boolean('有效', default=True)
|
||||
|
||||
|
||||
class MachineBrandTags(models.Model):
|
||||
_name = 'sf.machine.brand.tags'
|
||||
_description = '标签'
|
||||
@@ -39,7 +47,7 @@ class MachineBrand(models.Model):
|
||||
remark = fields.Text('备注')
|
||||
active = fields.Boolean('有效', default=True)
|
||||
|
||||
|
||||
|
||||
# 机床
|
||||
class MachineTool(models.Model):
|
||||
_name = 'sf.machine_tool'
|
||||
@@ -84,9 +92,10 @@ class MachineTool(models.Model):
|
||||
type_id = fields.Many2one('sf.machine_tool.type', '型号')
|
||||
brand_id = fields.Many2one('sf.machine.brand', string='品牌')
|
||||
state = fields.Selection(
|
||||
[("正常", "正常"), ("故障", "故障"), ("不可用", "不可用")],
|
||||
[("正常", "正常"), ("故障停机", "故障停机"), ("计划维保", "计划维保"), ("空闲", "空闲"),
|
||||
("封存(报废)", "封存(报废)")],
|
||||
default='正常', string="机床状态")
|
||||
#0606新增字段
|
||||
# 0606新增字段
|
||||
machine_tool_picture = fields.Binary('图片')
|
||||
heightened_way = fields.Selection([
|
||||
('sifudianji', '伺服电机驱动'),
|
||||
@@ -260,7 +269,7 @@ class MachineToolType(models.Model):
|
||||
default="", string="刀把类型")
|
||||
number_of_knife_library = fields.Integer('刀库数量')
|
||||
rotate_speed = fields.Integer('转速')
|
||||
#0606新增字段
|
||||
# 0606新增字段
|
||||
created_user = fields.Many2one('res.users', string='创建人', default=lambda self: self.env.user)
|
||||
machine_tool_picture = fields.Binary('图片')
|
||||
heightened_way = fields.Selection([
|
||||
@@ -269,31 +278,19 @@ class MachineToolType(models.Model):
|
||||
('chilunjia', '齿轮架驱动')
|
||||
], string="主轴加高方式", default='sifudianji')
|
||||
workpiece_load = fields.Char('工件最大负载(kg)')
|
||||
lead_screw = fields.Char('丝杆')
|
||||
workbench_L = fields.Char('工作台长度(mm)')
|
||||
workbench_W = fields.Char('工作台宽度(mm)')
|
||||
guide_rail = fields.Char('导轨')
|
||||
machine_tool_L = fields.Char('机床长度(mm)')
|
||||
machine_tool_W = fields.Char('机床宽度(mm)')
|
||||
machine_tool_H = fields.Char('机床高度(mm)')
|
||||
feed_speed = fields.Char('进给速度(mm/min)')
|
||||
tool_speed = fields.Char('刀具速度(m/min)')
|
||||
distance_min = fields.Char('主轴端面至工作台面距离MIN(mm)')
|
||||
distance_max = fields.Char('主轴端面至工作台面距离MAX(mm)')
|
||||
taper = fields.Char('主轴锥度(°)')
|
||||
torque = fields.Char('主轴电机扭矩(n/m)')
|
||||
motor_power = fields.Char('主轴电机功率(kw)')
|
||||
tool_quality_max = fields.Char('刀具最大质量(kg)')
|
||||
tool_long_max = fields.Char('刀具最大长度(mm)')
|
||||
tool_diameter_max = fields.Char('刀具刀径max(mm)')
|
||||
tool_diameter_min = fields.Char('刀具刀径min(mm)')
|
||||
machine_tool_category = fields.Many2one('sf.machine_tool.category', string='机床类型')
|
||||
|
||||
# 多个型号对应一个机床
|
||||
machine_tool_id = fields.Many2one('sf.machine_tool', '机床')
|
||||
number_of_axles = fields.Selection(
|
||||
[("三轴", "三轴"), ("四轴", "四轴"), ("五轴", "五轴")],
|
||||
default="", string="轴数")
|
||||
# 加工进程
|
||||
x_axis = fields.Integer('X轴')
|
||||
y_axis = fields.Integer('Y轴')
|
||||
@@ -301,13 +298,79 @@ class MachineToolType(models.Model):
|
||||
b_axis = fields.Integer('B轴')
|
||||
c_axis = fields.Integer('C轴')
|
||||
remark = fields.Char('备注')
|
||||
precision_min = fields.Float('X轴定位精度min(mm)', digits=(12, 3))
|
||||
precision_max = fields.Float('X轴定位精度max(mm)', digits=(12, 3))
|
||||
control_system_id = fields.Many2one('sf.machine.control_system',
|
||||
string="控制系统")
|
||||
active = fields.Boolean('有效', default=True)
|
||||
code = fields.Char('编码')
|
||||
|
||||
# 1212修改后的字段
|
||||
number_of_axles = fields.Selection(
|
||||
[("三轴", "三轴"), ("四轴", "四轴"), ("五轴", "五轴"), ("六轴", "六轴")],
|
||||
default="", string="轴数")
|
||||
|
||||
# 1212新增字段
|
||||
a_axis = fields.Integer('a轴')
|
||||
function_type = fields.Selection(
|
||||
[("ZXJGZX", "钻铣加工中心"), ("CXJGZX", "车削加工中心"), ("FHJGZX", "复合加工中心")],
|
||||
default="", string="功能类型")
|
||||
T_trough_num = fields.Integer('槽数')
|
||||
T_trough_wide = fields.Float('槽宽(mm)')
|
||||
T_trough_distance = fields.Float('槽距(mm)')
|
||||
|
||||
taper_type_id = fields.Many2one('spindle.taper.type', string='主轴锥孔型号')
|
||||
spindle_center_distance = fields.Float('主轴中心至立柱滑轨面距离(mm)')
|
||||
spindle_continuous_power = fields.Float('主轴持续功率(kw)')
|
||||
spindle_peak_power = fields.Float('主轴峰值功率(kw)')
|
||||
spindle_sustained_torque = fields.Float('主轴持续扭矩(n/m)')
|
||||
spindle_peak_torque = fields.Float('主轴峰值扭矩(n/m)')
|
||||
linear_axis_guides_type = fields.Char('直线轴导轨类型')
|
||||
axis_driven_type = fields.Char('坐标轴驱动类型')
|
||||
|
||||
X_axis_rapid_traverse_speed = fields.Char('X轴快速进给速度(mm/min)')
|
||||
Y_axis_rapid_traverse_speed = fields.Char('Y轴快速进给速度(mm/min)')
|
||||
Z_axis_rapid_traverse_speed = fields.Char('Z轴快速进给速度(mm/min)')
|
||||
a_axis_rapid_traverse_speed = fields.Char('a轴快速进给速度(mm/min)')
|
||||
b_axis_rapid_traverse_speed = fields.Char('b轴快速进给速度(mm/min)')
|
||||
c_axis_rapid_traverse_speed = fields.Char('c轴快速进给速度(mm/min)')
|
||||
straight_cutting_feed_rate = fields.Char('直线切削进给速度(mm/min)')
|
||||
rotary_cutting_feed_rate = fields.Char('回转切削进给速度(mm/min)')
|
||||
|
||||
X_precision = fields.Float('X轴定位精度(mm)', digits=(12, 3))
|
||||
X_precision_repeat = fields.Float('X轴重复定位精度(mm)', digits=(12, 3))
|
||||
Y_precision = fields.Float('Y轴定位精度(mm)', digits=(12, 3))
|
||||
Y_precision_repeat = fields.Float('Y轴重复定位精度(mm)', digits=(12, 3))
|
||||
Z_precision = fields.Float('Z轴定位精度(mm)', digits=(12, 3))
|
||||
Z_precision_repeat = fields.Float('Z轴重复定位精度(mm)', digits=(12, 3))
|
||||
a_precision = fields.Float('a轴定位精度(mm)', digits=(12, 3))
|
||||
a_precision_repeat = fields.Float('a轴重复定位精度(mm)', digits=(12, 3))
|
||||
b_precision = fields.Float('b轴定位精度(mm)', digits=(12, 3))
|
||||
b_precision_repeat = fields.Float('b轴重复定位精度(mm)', digits=(12, 3))
|
||||
c_precision = fields.Float('c轴定位精度(mm)', digits=(12, 3))
|
||||
c_precision_repeat = fields.Float('c轴重复定位精度(mm)', digits=(12, 3))
|
||||
|
||||
tool_full_diameter_max = fields.Float('刀具满刀最大直径(mm)')
|
||||
tool_perimeter_diameter_max = fields.Float('刀具邻空刀最大直径(mm)')
|
||||
T_tool_time = fields.Integer('T-T换刀时间(s)')
|
||||
C_tool_time = fields.Integer('C-C换刀时间(s)')
|
||||
|
||||
jg_image_id = fields.Many2many('maintenance.equipment.image', 'jg_equipment_id', string='加工能力',
|
||||
domain="[('type', '=', '加工能力')]")
|
||||
lq_image_id = fields.Many2many('maintenance.equipment.image', 'lq_equipment_id', string='冷却方式',
|
||||
domain="[('type', '=', '冷却方式')]")
|
||||
|
||||
# 待删除字段
|
||||
precision_min = fields.Float('X轴定位精度min(mm)', digits=(12, 3))
|
||||
precision_max = fields.Float('X轴定位精度max(mm)', digits=(12, 3))
|
||||
lead_screw = fields.Char('丝杆')
|
||||
guide_rail = fields.Char('导轨')
|
||||
feed_speed = fields.Char('进给速度(mm/min)')
|
||||
tool_speed = fields.Char('刀具速度(m/min)')
|
||||
torque = fields.Char('主轴点击扭矩(n/m)')
|
||||
motor_power = fields.Char('主轴电机功率(kw)')
|
||||
taper = fields.Char('主轴锥度(°)')
|
||||
tool_diameter_max = fields.Char('刀具刀径max(mm)')
|
||||
tool_diameter_min = fields.Char('刀具刀径min(mm)')
|
||||
|
||||
def _get_ids(self, machine_tool_type_code):
|
||||
machine_tool_type_ids = []
|
||||
for item in machine_tool_type_code:
|
||||
@@ -326,5 +389,4 @@ class MachineToolCategory(models.Model):
|
||||
remark = fields.Text('备注')
|
||||
active = fields.Boolean('有效', default=True)
|
||||
category = fields.Selection([('shukong', u'数控'), ('putong', u'普通')], string=u'机床类别',
|
||||
default='shukong')
|
||||
|
||||
default='shukong')
|
||||
|
||||
252
sf_base/models/basic_parameters_fixture.py
Normal file
@@ -0,0 +1,252 @@
|
||||
from odoo import models, fields
|
||||
|
||||
|
||||
class BasicParametersFixture(models.Model):
|
||||
_name = 'sf.fixture.materials.basic.parameters'
|
||||
_description = '夹具物料基本参数'
|
||||
|
||||
fixture_model_id = fields.Many2one('sf.fixture.model', '夹具型号')
|
||||
name = fields.Char('物料号', size=20)
|
||||
length = fields.Float('长度(mm)', digits=(16, 2))
|
||||
width = fields.Float('宽度(mm)', digits=(16, 2))
|
||||
height = fields.Float('高度(mm)', digits=(16, 2))
|
||||
diameter = fields.Float('直径(mm)', digits=(16, 2))
|
||||
|
||||
# '零点卡盘' 字段
|
||||
weight = fields.Float('重量(mm)', 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='装夹单元数')
|
||||
chucking_power_max = fields.Float('最大夹持力(KN)', digits=(16, 2))
|
||||
repeated_positioning_accuracy = fields.Char('重复定位精度(mm)', size=20)
|
||||
boolean_transposing_hole = fields.Boolean('是否有转位孔')
|
||||
unlocking_method = fields.Selection(
|
||||
[('手动', '手动'), ('气动', '气动'), ('液压', '液压'), ('电动', '电动'), ('其他', '其他')], string='解锁方式')
|
||||
boolean_chip_blowing_function = fields.Boolean('是否有吹屑功能')
|
||||
carrying_capacity_max = fields.Float('最大承载重量(kg)', digits=(16, 2))
|
||||
rigidity = fields.Integer('硬度HRC')
|
||||
materials_model_id = fields.Many2one('sf.materials.model', '夹具材质')
|
||||
machine_tool_type_id = fields.Many2one('sf.machine_tool.type', '适用机床型号')
|
||||
|
||||
# ’零点托盘‘ 字段
|
||||
connector_diameter = fields.Selection([('2', '2'), ('3', '3'), ('4', '4'), ('5', '5'), ('6', '6'), ('8', '8')],
|
||||
string='连接头直径(mm)')
|
||||
way_to_install = fields.Selection(
|
||||
[('接口式', '接口式'), ('螺栓固定', '螺栓固定'), ('磁吸式', '磁吸式'), ('其他', '其他')], string='安装方式')
|
||||
type_of_drive = fields.Selection(
|
||||
[('气动式', '气动式'), ('液压式', '液压式'), ('机械式', '机械式'), ('电动式', '电动式'), ('其他', '其他')],
|
||||
string='驱动方式')
|
||||
|
||||
# ’气动夹具‘ 字段
|
||||
gripper_length_min = fields.Float('夹持工件最小长度(mm)', digits=(16, 2))
|
||||
gripper_width_min = fields.Float('夹持工件最小宽度(mm)', digits=(16, 2))
|
||||
gripper_height_min = fields.Float('夹持工件最小高度(mm)', digits=(16, 2))
|
||||
gripper_diameter_min = fields.Float('夹持工件最小直径(mm)', digits=(16, 2))
|
||||
gripper_length_max = fields.Float('夹持工件最大长度(mm)', digits=(16, 2))
|
||||
gripper_width_max = fields.Float('夹持工件最大宽度(mm)', digits=(16, 2))
|
||||
gripper_height_max = fields.Float('夹持工件最大高度(mm)', digits=(16, 2))
|
||||
gripper_diameter_max = fields.Float('夹持工件最大直径(mm)', digits=(16, 2))
|
||||
rated_air_pressure = fields.Float('额定气压(Mpa)', digits=(16, 2))
|
||||
interface_materials_model_id = fields.Many2one('sf.materials.model', '接口类型')
|
||||
|
||||
# ‘虎钳夹具' 字段
|
||||
transverse_groove = fields.Float('横向配合槽n(mm)', digits=(16, 2))
|
||||
longitudinal_fitting_groove = fields.Float('纵向配合槽l(mm)', digits=(16, 2))
|
||||
|
||||
# '磁吸夹具' 字段
|
||||
height_tolerance_value = fields.Char('高度公差(mm)')
|
||||
rated_adsorption_force = fields.Float('额定吸附力(N/cm²)', digits=(16, 2))
|
||||
magnetic_field_height = fields.Float('磁场高度(mm)', digits=(16, 2))
|
||||
magnetic_pole_plate_grinding_allowance = fields.Float('磁极板磨削余量(mm)', digits=(16, 2))
|
||||
|
||||
# '转接板(锁板)夹具' 字段
|
||||
screw_size = fields.Float('螺牙大小(mm)', digits=(16, 2))
|
||||
via_hole_diameter = fields.Float('过孔直径(mm)', digits=(16, 2))
|
||||
|
||||
# '三爪卡盘' 字段
|
||||
mounting_hole_depth = fields.Float('安装孔深度(mm)', digits=(16, 2))
|
||||
centering_diameter = fields.Float('定心直径(mm)', digits=(16, 2))
|
||||
|
||||
def _json_zero_chuck_param(self, obj):
|
||||
zero_chuck_param_str = (0, '', {
|
||||
'name': obj['name'],
|
||||
'length': obj['length'],
|
||||
'width': obj['width'],
|
||||
'height': obj['height'],
|
||||
'diameter': obj['diameter'],
|
||||
'weight': obj['weight'],
|
||||
'orientation_dish_diameter': obj['orientation_dish_diameter'],
|
||||
'clamping_diameter': obj['clamping_diameter'],
|
||||
'clamping_num': obj['clamping_num'],
|
||||
'chucking_power_max': obj['chucking_power_max'],
|
||||
'repeated_positioning_accuracy': obj['repeated_positioning_accuracy'],
|
||||
'boolean_transposing_hole': obj['boolean_transposing_hole'],
|
||||
'unlocking_method': obj['unlocking_method'],
|
||||
'boolean_chip_blowing_function': obj['boolean_chip_blowing_function'],
|
||||
'carrying_capacity_max': obj['carrying_capacity_max'],
|
||||
'rigidity': obj['rigidity'],
|
||||
'materials_model_id': self.env['sf.materials.model'].sudo().search(
|
||||
[('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id,
|
||||
'machine_tool_type_id': self.env['sf.machine_tool.type'].sudo().search(
|
||||
[('code', '=', obj['machine_tool_type_id']), ('active', '=', True)]).id,
|
||||
})
|
||||
return zero_chuck_param_str
|
||||
|
||||
def _json_zero_tray_param(self, obj):
|
||||
zero_tray_param_str = (0, '', {
|
||||
'name': obj['name'],
|
||||
'length': obj['length'],
|
||||
'width': obj['width'],
|
||||
'height': obj['height'],
|
||||
'diameter': obj['diameter'],
|
||||
'weight': obj['weight'],
|
||||
'clamping_diameter': obj['clamping_diameter'],
|
||||
'connector_diameter': obj['connector_diameter'],
|
||||
'chucking_power_max': obj['chucking_power_max'],
|
||||
'repeated_positioning_accuracy': obj['repeated_positioning_accuracy'],
|
||||
'boolean_chip_blowing_function': obj['boolean_chip_blowing_function'],
|
||||
'way_to_install': obj['way_to_install'],
|
||||
'type_of_drive': obj['type_of_drive'],
|
||||
'carrying_capacity_max': obj['carrying_capacity_max'],
|
||||
'materials_model_id': self.env['sf.materials.model'].sudo().search(
|
||||
[('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id,
|
||||
'rigidity': obj['rigidity'],
|
||||
})
|
||||
return zero_tray_param_str
|
||||
|
||||
def _json_pneumatic_fixture_param(self, obj):
|
||||
pneumatic_fixture_param_str = (0, '', {
|
||||
'name': obj['name'],
|
||||
'length': obj['length'],
|
||||
'width': obj['width'],
|
||||
'height': obj['height'],
|
||||
'weight': obj['weight'],
|
||||
'gripper_length_min': obj['gripper_length_min'],
|
||||
'gripper_width_min': obj['gripper_width_min'],
|
||||
'gripper_height_min': obj['gripper_height_min'],
|
||||
'gripper_diameter_min': obj['gripper_diameter_min'],
|
||||
'gripper_length_max': obj['gripper_length_max'],
|
||||
'gripper_width_max': obj['gripper_width_max'],
|
||||
'gripper_height_max': obj['gripper_height_max'],
|
||||
'gripper_diameter_max': obj['gripper_diameter_max'],
|
||||
'chucking_power_max': obj['chucking_power_max'],
|
||||
'carrying_capacity_max': obj['carrying_capacity_max'],
|
||||
'rated_air_pressure': obj['rated_air_pressure'],
|
||||
'materials_model_id': self.env['sf.materials.model'].sudo().search(
|
||||
[('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id,
|
||||
'rigidity': obj['rigidity'],
|
||||
'interface_materials_model_id': self.env['sf.materials.model'].sudo().search(
|
||||
[('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id,
|
||||
'type_of_drive': obj['type_of_drive'],
|
||||
})
|
||||
return pneumatic_fixture_param_str
|
||||
|
||||
def _json_jaw_vice_fixture_param(self, obj):
|
||||
jaw_vice_fixture_param_str = (0, '', {
|
||||
'name': obj['name'],
|
||||
'length': obj['length'],
|
||||
'width': obj['width'],
|
||||
'height': obj['height'],
|
||||
'weight': obj['weight'],
|
||||
'gripper_length_min': obj['gripper_length_min'],
|
||||
'gripper_width_min': obj['gripper_width_min'],
|
||||
'gripper_height_min': obj['gripper_height_min'],
|
||||
'gripper_diameter_min': obj['gripper_diameter_min'],
|
||||
'gripper_length_max': obj['gripper_length_max'],
|
||||
'gripper_width_max': obj['gripper_width_max'],
|
||||
'gripper_height_max': obj['gripper_height_max'],
|
||||
'gripper_diameter_max': obj['gripper_diameter_max'],
|
||||
'chucking_power_max': obj['chucking_power_max'],
|
||||
'carrying_capacity_max': obj['carrying_capacity_max'],
|
||||
'transverse_groove': obj['transverse_groove'],
|
||||
'longitudinal_fitting_groove': obj['longitudinal_fitting_groove'],
|
||||
'materials_model_id': self.env['sf.materials.model'].sudo().search(
|
||||
[('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id,
|
||||
'rigidity': obj['rigidity'],
|
||||
'interface_materials_model_id': self.env['sf.materials.model'].sudo().search(
|
||||
[('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id,
|
||||
'type_of_drive': obj['type_of_drive'],
|
||||
})
|
||||
return jaw_vice_fixture_param_str
|
||||
|
||||
def _json_magnet_fixture_param(self, obj):
|
||||
magnet_fixture_param_str = (0, '', {
|
||||
'name': obj['name'],
|
||||
'length': obj['length'],
|
||||
'width': obj['width'],
|
||||
'height': obj['height'],
|
||||
'height_tolerance_value': obj['height_tolerance_value'],
|
||||
'weight': obj['weight'],
|
||||
'gripper_length_min': obj['gripper_length_min'],
|
||||
'gripper_width_min': obj['gripper_width_min'],
|
||||
'gripper_height_min': obj['gripper_height_min'],
|
||||
'gripper_diameter_min': obj['gripper_diameter_min'],
|
||||
'gripper_length_max': obj['gripper_length_max'],
|
||||
'gripper_width_max': obj['gripper_width_max'],
|
||||
'gripper_height_max': obj['gripper_height_max'],
|
||||
'gripper_diameter_max': obj['gripper_diameter_max'],
|
||||
'rated_adsorption_force': obj['rated_adsorption_force'],
|
||||
'magnetic_field_height': obj['magnetic_field_height'],
|
||||
'magnetic_pole_plate_grinding_allowance': obj['magnetic_pole_plate_grinding_allowance'],
|
||||
'carrying_capacity_max': obj['carrying_capacity_max'],
|
||||
'materials_model_id': self.env['sf.materials.model'].sudo().search(
|
||||
[('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id,
|
||||
'rigidity': obj['rigidity'],
|
||||
'interface_materials_model_id': self.env['sf.materials.model'].sudo().search(
|
||||
[('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id,
|
||||
'type_of_drive': obj['type_of_drive'],
|
||||
})
|
||||
return magnet_fixture_param_str
|
||||
|
||||
def _json_adapter_board_fixture_param(self, obj):
|
||||
adapter_board_fixture_param_str = (0, '', {
|
||||
'name': obj['name'],
|
||||
'length': obj['length'],
|
||||
'width': obj['width'],
|
||||
'height': obj['height'],
|
||||
'weight': obj['weight'],
|
||||
'gripper_length_min': obj['gripper_length_min'],
|
||||
'gripper_width_min': obj['gripper_width_min'],
|
||||
'gripper_height_min': obj['gripper_height_min'],
|
||||
'gripper_diameter_min': obj['gripper_diameter_min'],
|
||||
'gripper_length_max': obj['gripper_length_max'],
|
||||
'gripper_width_max': obj['gripper_width_max'],
|
||||
'gripper_height_max': obj['gripper_height_max'],
|
||||
'gripper_diameter_max': obj['gripper_diameter_max'],
|
||||
'chucking_power_max': obj['chucking_power_max'],
|
||||
'carrying_capacity_max': obj['carrying_capacity_max'],
|
||||
'materials_model_id': self.env['sf.materials.model'].sudo().search(
|
||||
[('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id,
|
||||
'rigidity': obj['rigidity'],
|
||||
'screw_size': obj['screw_size'],
|
||||
'via_hole_diameter': obj['via_hole_diameter'],
|
||||
'type_of_drive': obj['type_of_drive'],
|
||||
})
|
||||
return adapter_board_fixture_param_str
|
||||
|
||||
def _json_scroll_chuck_param(self, obj):
|
||||
scroll_chuck_param_str = (0, '', {
|
||||
'name': obj['name'],
|
||||
'length': obj['length'],
|
||||
'width': obj['width'],
|
||||
'height': obj['height'],
|
||||
'diameter': obj['diameter'],
|
||||
'weight': obj['weight'],
|
||||
'gripper_length_min': obj['gripper_length_min'],
|
||||
'gripper_width_min': obj['gripper_width_min'],
|
||||
'gripper_height_min': obj['gripper_height_min'],
|
||||
'gripper_diameter_min': obj['gripper_diameter_min'],
|
||||
'gripper_length_max': obj['gripper_length_max'],
|
||||
'gripper_width_max': obj['gripper_width_max'],
|
||||
'gripper_height_max': obj['gripper_height_max'],
|
||||
'gripper_diameter_max': obj['gripper_diameter_max'],
|
||||
'chucking_power_max': obj['chucking_power_max'],
|
||||
'carrying_capacity_max': obj['carrying_capacity_max'],
|
||||
'materials_model_id': self.env['sf.materials.model'].sudo().search(
|
||||
[('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id,
|
||||
'rigidity': obj['rigidity'],
|
||||
'mounting_hole_depth': obj['mounting_hole_depth'],
|
||||
'centering_diameter': obj['centering_diameter'],
|
||||
'type_of_drive': obj['type_of_drive'],
|
||||
})
|
||||
return scroll_chuck_param_str
|
||||
@@ -1,9 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import logging
|
||||
from odoo import fields, models
|
||||
import requests
|
||||
from odoo.addons.sf_base.commons.common import Common
|
||||
from urllib.parse import urlencode
|
||||
from odoo import fields, models, api
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -19,29 +19,7 @@ class MrsProductionMaterials(models.Model):
|
||||
remark = fields.Text("备注")
|
||||
active = fields.Boolean('有效', default=True)
|
||||
|
||||
# def open_url_action(self):
|
||||
# base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
|
||||
# # url = 'http://192.168.50.202:8080/api'
|
||||
# url = 'https://bfw.jikimo.com/'
|
||||
# # data = {
|
||||
# # 'key' : 'value'
|
||||
# # }
|
||||
#
|
||||
# response = requests.get(url)
|
||||
# response.raise_for_status()
|
||||
# return {
|
||||
# 'type': 'ir.actions.act_url',
|
||||
# 'url': response.url,
|
||||
# 'target': 'new'
|
||||
# }
|
||||
|
||||
|
||||
|
||||
def open_url_action(self):
|
||||
# sf_sync_config = self.env['res.config.settings'].get_values()
|
||||
# token = sf_sync_config['token']
|
||||
# sf_secret_key = sf_sync_config['sf_secret_key']
|
||||
# headers = Common.get_headers(self, token, sf_secret_key)
|
||||
url = 'http://192.168.50.127:8081'
|
||||
params = {
|
||||
'user_id': self._uid
|
||||
@@ -68,12 +46,12 @@ class MrsMaterialModel(models.Model):
|
||||
density = fields.Float("密度(kg/m³)")
|
||||
materials_id = fields.Many2one('sf.production.materials', "材料名")
|
||||
tensile_strength = fields.Char("拉伸强度(n/mm²)")
|
||||
standards_id = fields.Many2one('sf.international.standards', '制造标准')
|
||||
standards_id = fields.Many2one('sf.international.standards', '执行标准')
|
||||
alloy_code = fields.Char('合金牌号')
|
||||
price = fields.Float('单价/kg')
|
||||
apply = fields.Many2many('material.apply', string='材料应用')
|
||||
materials_code = fields.Char('材料代号')
|
||||
hardness = fields.Float("硬度(hrc)")
|
||||
hardness = fields.Integer("硬度(hrc)")
|
||||
rough_machining = fields.Float("粗加工Vc(m/min)")
|
||||
finish_machining = fields.Float("精加工Vc(m/min)")
|
||||
remark = fields.Text("备注")
|
||||
@@ -83,6 +61,14 @@ class MrsMaterialModel(models.Model):
|
||||
supplier_ids = fields.One2many('sf.supplier.sort', 'materials_model_id', string='供应商')
|
||||
active = fields.Boolean('有效', default=True)
|
||||
|
||||
@api.constrains('supplier_ids')
|
||||
def _check_gain_way(self):
|
||||
if not self.gain_way:
|
||||
raise UserError("请输入获取方式")
|
||||
if self.gain_way in ['外协', '采购']:
|
||||
if not self.supplier_ids:
|
||||
raise UserError("请添加供应商")
|
||||
|
||||
|
||||
class MrsProductionProcessCategory(models.Model):
|
||||
_name = 'sf.production.process.category'
|
||||
@@ -132,6 +118,7 @@ class MrsProcessingOrder(models.Model):
|
||||
index=True, string='加工工艺')
|
||||
production_process_id = fields.Many2one('sf.production.process', string="表面工艺")
|
||||
|
||||
|
||||
class SupplierSort(models.Model):
|
||||
_name = 'sf.supplier.sort'
|
||||
_description = '供应商排序'
|
||||
|
||||
@@ -26,66 +26,65 @@ class FixtureModel(models.Model):
|
||||
_name = 'sf.fixture.model'
|
||||
_description = "夹具型号"
|
||||
|
||||
name = fields.Char(string="名称", size=15)
|
||||
fixture_material_id = fields.Many2one('sf.fixture.material', string="夹具物料", )
|
||||
fixture_material_type = fields.Char(string="夹具物料类型", related='fixture_material_id.name', store=True)
|
||||
multi_mounting_type_id = fields.Many2one('sf.multi_mounting.type', string="联装类型")
|
||||
brand_id = fields.Many2one('sf.machine.brand', string="品牌", domain="[('tag_ids.name', 'ilike', '夹具')]")
|
||||
clamping_way = fields.Char(string="装夹方式")
|
||||
port_type = fields.Char(string="接口类型")
|
||||
model_file = fields.Binary(string="3D模型图")
|
||||
|
||||
length = fields.Char(string="长度(mm)")
|
||||
width = fields.Char(string="宽度(mm)")
|
||||
height = fields.Char(string="高度(mm)")
|
||||
weight = fields.Char(string="重量(kg)")
|
||||
clamp_workpiece_length_max = fields.Integer(string="夹持工件长度max(mm)")
|
||||
clamp_workpiece_width_max = fields.Integer(string="夹持工件宽度max(mm)")
|
||||
clamp_workpiece_height_max = fields.Integer(string="夹持工件高度max(mm)")
|
||||
clamp_workpiece_diameter_max = fields.Float(string="夹持工件直径max(mm)")
|
||||
maximum_carrying_weight = fields.Float(string="最大承载重量(kg)")
|
||||
maximum_clamping_force = fields.Integer(string="最大夹持力(n)")
|
||||
|
||||
materials_model_id = fields.Many2one('sf.materials.model', string="材料型号")
|
||||
driving_way = fields.Selection([('气动', '气动'), ('液压', '液压'), ('机械', '机械')], string="驱动方式")
|
||||
apply_machine_tool_type_ids = fields.Many2many('sf.machine_tool.type', 'rel_fixture_model_machine_tool_type',
|
||||
string="适用机床型号")
|
||||
through_hole_size = fields.Integer(string="过孔大小[mm]")
|
||||
screw_size = fields.Integer(string="螺牙大小[mm]")
|
||||
active = fields.Boolean('有效', default=True)
|
||||
|
||||
def _get_code(self, fixture_model_type_code):
|
||||
fixture_model = self.env['sf.fixture.model'].sudo().search(
|
||||
[('code', 'ilike', fixture_model_type_code)],
|
||||
limit=1,
|
||||
order="id desc")
|
||||
if not fixture_model:
|
||||
num = "%03d" % 1
|
||||
else:
|
||||
m = int(fixture_model.code[-3:]) + 1
|
||||
num = "%03d" % m
|
||||
return "%s%s" % (fixture_model_type_code, num)
|
||||
name = fields.Char(string="名称", size=50, required=True)
|
||||
fixture_material_id = fields.Many2one('sf.fixture.material', string="夹具物料", required=True)
|
||||
fixture_material_type = fields.Char(string="夹具物料类型", related='fixture_material_id.name')
|
||||
multi_mounting_type_id = fields.Many2one('sf.multi_mounting.type', string="联装类型", required=True)
|
||||
brand_id = fields.Many2one('sf.machine.brand', string="品牌")
|
||||
model_file = fields.Binary(string="图片")
|
||||
status = fields.Boolean('状态')
|
||||
active = fields.Boolean('有效', default=False)
|
||||
|
||||
zero_chuck_ids = fields.One2many('sf.fixture.materials.basic.parameters', 'fixture_model_id',
|
||||
string='零点卡盘基本参数')
|
||||
zero_tray_ids = fields.One2many('sf.fixture.materials.basic.parameters', 'fixture_model_id',
|
||||
string='零点托盘基本参数')
|
||||
pneumatic_fixture_ids = fields.One2many('sf.fixture.materials.basic.parameters', 'fixture_model_id',
|
||||
string='气动夹具基本参数')
|
||||
jaw_vice_fixture_ids = fields.One2many('sf.fixture.materials.basic.parameters', 'fixture_model_id',
|
||||
string='虎钳夹具基本参数')
|
||||
magnet_fixture_ids = fields.One2many('sf.fixture.materials.basic.parameters', 'fixture_model_id',
|
||||
string='磁吸夹具基本参数')
|
||||
adapter_board_fixture_ids = fields.One2many('sf.fixture.materials.basic.parameters', 'fixture_model_id',
|
||||
string='转接板(锁板)夹具基本参数')
|
||||
scroll_chuck_ids = fields.One2many('sf.fixture.materials.basic.parameters', 'fixture_model_id',
|
||||
string='三爪卡盘基本参数')
|
||||
code = fields.Char(string='编码', readonly=True)
|
||||
|
||||
def _onchange_fixture_material_id(self, fixture_material_id):
|
||||
if fixture_material_id:
|
||||
if fixture_material_id.name == "气动夹具":
|
||||
code = self._get_code("JKM-C-JJWL-QDJJ-")
|
||||
elif fixture_material_id.name == "转接板(锁板)夹具":
|
||||
code = self._get_code("JKM-C-JJWL-ZJBJJ-")
|
||||
elif fixture_material_id.name == "磁吸夹具":
|
||||
code = self._get_code("JKM-C-JJWL-CXJJ-")
|
||||
elif fixture_material_id.name == "虎钳夹具":
|
||||
code = self._get_code("JKM-C-JJWL-HQJJ-")
|
||||
else:
|
||||
code = self._get_code("JKM-C-JJWL-LDKP-")
|
||||
return code
|
||||
|
||||
@api.model_create_multi
|
||||
def create(self, vals):
|
||||
obj = super(FixtureModel, self).create(vals)
|
||||
if obj.fixture_material_id:
|
||||
code = self._onchange_fixture_material_id(obj.fixture_material_id)
|
||||
obj.code = code
|
||||
return obj
|
||||
# def _get_code(self, fixture_model_type_code):
|
||||
# fixture_model = self.env['sf.fixture.model'].sudo().search(
|
||||
# [('code', 'ilike', fixture_model_type_code)],
|
||||
# limit=1,
|
||||
# order="id desc")
|
||||
# if not fixture_model:
|
||||
# num = "%03d" % 1
|
||||
# else:
|
||||
# m = int(fixture_model.code[-3:]) + 1
|
||||
# num = "%03d" % m
|
||||
# return "%s%s" % (fixture_model_type_code, num)
|
||||
#
|
||||
# def _onchange_fixture_material_id(self, fixture_material_id):
|
||||
# if fixture_material_id:
|
||||
# if self.fixture_material_id.name == "气动夹具":
|
||||
# code = self._get_code("JKM-C-JJWL-QDJJ-")
|
||||
# elif self.fixture_material_id.name == "转接板(锁板)夹具":
|
||||
# code = self._get_code("JKM-C-JJWL-ZJJJ-")
|
||||
# elif self.fixture_material_id.name == "磁吸夹具":
|
||||
# code = self._get_code("JKM-C-JJWL-CXJJ-")
|
||||
# elif self.fixture_material_id.name == "虎钳夹具":
|
||||
# code = self._get_code("JKM-C-JJWL-HQJJ-")
|
||||
# elif self.fixture_material_id.name == "零点托盘":
|
||||
# code = self._get_code("JKM-C-JJWL-LDTP-")
|
||||
# elif self.fixture_material_id.name == "三爪卡盘":
|
||||
# code = self._get_code("JKM-C-JJWL-SZKP-")
|
||||
# else:
|
||||
# code = self._get_code("JKM-C-JJWL-LDKP-")
|
||||
# return code
|
||||
#
|
||||
# @api.model_create_multi
|
||||
# def create(self, vals):
|
||||
# obj = super(FixtureModel, self).create(vals)
|
||||
# if obj.fixture_material_id:
|
||||
# code = self._onchange_fixture_material_id(obj.fixture_material_id)
|
||||
# obj.code = code
|
||||
# return obj
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import json
|
||||
import requests
|
||||
from odoo import models, fields, api
|
||||
from odoo.addons.sf_base.commons.common import Common
|
||||
from odoo.exceptions import ValidationError
|
||||
import requests
|
||||
import json
|
||||
|
||||
|
||||
class FunctionalFixtureType(models.Model):
|
||||
@@ -62,7 +62,8 @@ class FunctionalFixture(models.Model):
|
||||
def _get_name(self):
|
||||
for record in self:
|
||||
if record.type:
|
||||
if not record.transfer_tray_model_ids and not record.pneumatic_tray_model_ids and not record.magnetic_tray_model_ids and not record.vice_tray_model_ids:
|
||||
if not record.transfer_tray_model_ids and not record.pneumatic_tray_model_ids and \
|
||||
not record.magnetic_tray_model_ids and not record.vice_tray_model_ids:
|
||||
record.name = ''
|
||||
if record.transfer_tray_model_ids:
|
||||
for i in record.transfer_tray_model_ids:
|
||||
|
||||
@@ -1,304 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import logging
|
||||
|
||||
from odoo import fields, models, api
|
||||
# from odoo.exceptions import UserError
|
||||
# # from odoo.addons import sf_base, sf_common
|
||||
# from datetime import datetime
|
||||
|
||||
|
||||
# 功能刀具物料
|
||||
class CuttingToolMaterial(models.Model):
|
||||
_name = 'sf.cutting.tool.material'
|
||||
_description = '刀具物料'
|
||||
|
||||
code = fields.Char('编码')
|
||||
name = fields.Char('名称')
|
||||
remark = fields.Char('备注')
|
||||
active = fields.Boolean('有效', default=True)
|
||||
|
||||
|
||||
# 功能刀具
|
||||
class FunctionalCuttingTool(models.Model):
|
||||
_name = 'sf.functional.cutting.tool'
|
||||
_description = '功能刀具'
|
||||
|
||||
code = fields.Char('编码')
|
||||
name = fields.Char('名称')
|
||||
functional_model_number = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型')
|
||||
integral_model_number = fields.Many2one('sf.integral.cutting.tool', string='整体式刀具型号')
|
||||
blade_model_number = fields.Many2one('sf.blade', string='刀片型号')
|
||||
cutterbar_model_number = fields.Many2one('sf.cutter.bar', string='刀杆型号')
|
||||
cutterpad_model_number = fields.Many2one('sf.cutter.pad', string='刀盘型号')
|
||||
handle_model_number = fields.Many2one('sf.handle', string='刀柄型号')
|
||||
chuck_model_number = fields.Many2one('sf.chuck', string='夹头型号')
|
||||
diameter = fields.Float('直径(mm)')
|
||||
tool_grade = fields.Selection([('1', 'P1'), ('2', 'P2'), ('3', 'P3'), ('4', 'P4'), ('5', 'P5'), ('6', 'P6')],
|
||||
string='刀具等级')
|
||||
machining_accuracy = fields.Float('加工精度(mm)')
|
||||
tool_length = fields.Float('装刀长')
|
||||
blade_number = fields.Integer('刃数')
|
||||
integral_blade_length = fields.Float('整体刃长(mm)')
|
||||
effective_blade_length = fields.Float('有效刃长(mm)')
|
||||
max_life = fields.Float('最大寿命值')
|
||||
is_standard = fields.Boolean('是否标准刀')
|
||||
applicable_range = fields.Char('适用范围')
|
||||
image = fields.Binary('图片')
|
||||
active = fields.Boolean('有效', default=True)
|
||||
|
||||
|
||||
# 功能刀具类型
|
||||
class FunctionalCuttingToolModel(models.Model):
|
||||
_name = 'sf.functional.cutting.tool.model'
|
||||
_description = '功能刀具类型'
|
||||
|
||||
name = fields.Char('名称')
|
||||
code = fields.Char('编码')
|
||||
remark = fields.Char('备注')
|
||||
active = fields.Boolean('有效', default=True)
|
||||
|
||||
|
||||
# 整体式刀具
|
||||
class IntegralCuttingTool(models.Model):
|
||||
_name = 'sf.integral.cutting.tool'
|
||||
_description = '整体式刀具'
|
||||
|
||||
code = fields.Char('编码')
|
||||
name = fields.Char('型号名称')
|
||||
# 关联刀具物料
|
||||
cutting_tool_material = fields.Many2one('sf.cutting.tool.material', '刀具物料')
|
||||
# 整体式刀具类型字段,关联整体式刀具类型对象
|
||||
integral_model_number = fields.Many2one('sf.integral.cutting.tool.model', '整体式刀具类型')
|
||||
# 增加品牌、总长度(mm)、柄部长度(mm)、刃部长度(mm)、直径(mm)、刃数、前角(°)、后角(°)、主偏角(°)、材料型号、配对螺母(mm)、适用夹头型号、适用范围、图片、创建人、创建时间等字段
|
||||
brand = fields.Many2one('sf.machine.brand', '品牌', domain="[('tag_ids.name', 'ilike', '刀具')]")
|
||||
total_length = fields.Float('总长度(mm)')
|
||||
shank_length = fields.Float('柄部长度(mm)')
|
||||
blade_length = fields.Float('刃部长度(mm)')
|
||||
diameter = fields.Float('直径(mm)')
|
||||
blade_number = fields.Integer('刃数')
|
||||
front_angle = fields.Float('前角(°)')
|
||||
rear_angle = fields.Float('后角(°)')
|
||||
main_included_angle = fields.Float('主偏角(°)')
|
||||
material_model = fields.Many2one('sf.materials.model', '材料型号')
|
||||
nut = fields.Float('配对螺母(mm)')
|
||||
# 适用夹头型号可以多选
|
||||
chuck_model = fields.Many2many('sf.chuck', string='适用夹头型号')
|
||||
scope = fields.Char('适用范围')
|
||||
image = fields.Binary('图片')
|
||||
active = fields.Boolean('有效', default=True)
|
||||
|
||||
|
||||
# 整体式刀具类型
|
||||
class IntegralCuttingToolModel(models.Model):
|
||||
_name = 'sf.integral.cutting.tool.model'
|
||||
_description = '整体式刀具类型'
|
||||
|
||||
code = fields.Char('编码')
|
||||
name = fields.Char('名称')
|
||||
# 关联刀具物料
|
||||
cutting_tool_material = fields.Many2one('sf.cutting.tool.material', '刀具物料')
|
||||
remark = fields.Char('备注')
|
||||
|
||||
|
||||
# 刀片
|
||||
class Blade(models.Model):
|
||||
_name = 'sf.blade'
|
||||
_description = '刀片'
|
||||
|
||||
code = fields.Char('编码')
|
||||
name = fields.Char('型号名称')
|
||||
# 关联刀具物料
|
||||
cutting_tool_material = fields.Many2one('sf.cutting.tool.material', '刀具物料')
|
||||
# 刀片类型字段,关联刀片类型对象
|
||||
blade_model_number = fields.Many2one('sf.blade.model', '刀片类型')
|
||||
# 编码、型号名称、刀片类型、品牌、长度L(mm)、宽度D(mm)、高度T(mm)、顶角(°)、前角(°)、后角(°)、主偏角(°)、R角(°)、材料型号、加工硬度、配对螺母(mm)、适用刀杆/刀盘型号、刀尖半径(mm)、图片、创建人、创建时间字段
|
||||
brand = fields.Many2one('sf.machine.brand', '品牌', )
|
||||
length = fields.Float('长度L(mm)')
|
||||
width = fields.Float('宽度D(mm)')
|
||||
height = fields.Float('高度T(mm)')
|
||||
top_angle = fields.Float('顶角(°)')
|
||||
front_angle = fields.Float('前角(°)')
|
||||
rear_angle = fields.Float('后角(°)')
|
||||
main_included_angle = fields.Float('主偏角(°)')
|
||||
r_angle = fields.Float('R角(°)')
|
||||
material_model = fields.Many2one('sf.materials.model', '材料型号')
|
||||
hardness = fields.Char('加工硬度')
|
||||
nut = fields.Float('配对螺母(mm)')
|
||||
# 适用刀杆型号可以多选
|
||||
cutter_bar = fields.Many2many('sf.cutter.bar', string='适用刀杆型号')
|
||||
# 适用刀盘型号可以多选
|
||||
cutter_pad = fields.Many2many('sf.cutter.pad', string='适用刀盘型号')
|
||||
radius = fields.Float('刀尖半径(mm)')
|
||||
image = fields.Binary('图片')
|
||||
|
||||
|
||||
# 刀片类型
|
||||
class BladeModel(models.Model):
|
||||
_name = 'sf.blade.model'
|
||||
_description = '刀片类型'
|
||||
|
||||
code = fields.Char('编码')
|
||||
name = fields.Char('名称')
|
||||
# 关联刀具物料
|
||||
cutting_tool_material = fields.Many2one('sf.cutting.tool.material', '刀具物料')
|
||||
# 刀片类型字段,关联刀片对象
|
||||
blade_ids = fields.One2many('sf.blade', 'blade_model_number', '刀片类型')
|
||||
remark = fields.Char('备注')
|
||||
|
||||
|
||||
# 刀杆
|
||||
class CutterBar(models.Model):
|
||||
_name = 'sf.cutter.bar'
|
||||
_description = '刀杆'
|
||||
|
||||
code = fields.Char('编码')
|
||||
name = fields.Char('型号名称')
|
||||
# 关联刀具物料
|
||||
cutting_tool_material = fields.Many2one('sf.cutting.tool.material', '刀具物料')
|
||||
# 刀杆类型字段,关联刀杆类型对象
|
||||
cutter_bar_model_number = fields.Many2one('sf.cutter.bar.model', '刀杆类型')
|
||||
# 品牌、C柄径(mm)、L总长(mm)、材料型号、刃数、D刃径(mm)、适用刀片型号、配对扳手(mm)、配备螺丝(mm)、刀尖圆角半径、精度等级、硬度(°)、适用范围、图片、创建人、创建时间
|
||||
brand = fields.Many2one('sf.machine.brand', '品牌')
|
||||
c_diameter = fields.Float('C柄径(mm)')
|
||||
total_length = fields.Float('L总长(mm)')
|
||||
material_model = fields.Many2one('sf.materials.model', '材料型号')
|
||||
blade_number = fields.Integer('刃数')
|
||||
d_diameter = fields.Float('D刃径(mm)')
|
||||
blade = fields.Many2many('sf.blade', string='适用刀片型号')
|
||||
wrench = fields.Float('配对扳手(mm)')
|
||||
screw = fields.Float('配备螺丝(mm)')
|
||||
radius = fields.Float('刀尖圆角半径')
|
||||
accuracy = fields.Char('精度等级')
|
||||
hardness = fields.Char('硬度(°)')
|
||||
scope = fields.Char('适用范围')
|
||||
image = fields.Binary('图片')
|
||||
|
||||
|
||||
# 刀杆类型
|
||||
class CutterBarModel(models.Model):
|
||||
_name = 'sf.cutter.bar.model'
|
||||
_description = '刀杆类型'
|
||||
|
||||
code = fields.Char('编码')
|
||||
name = fields.Char('名称')
|
||||
# 关联刀具物料
|
||||
cutting_tool_material = fields.Many2one('sf.cutting.tool.material', '刀具物料')
|
||||
remark = fields.Char('备注')
|
||||
|
||||
|
||||
# 刀盘
|
||||
class CutterPad(models.Model):
|
||||
_name = 'sf.cutter.pad'
|
||||
_description = '刀盘'
|
||||
|
||||
code = fields.Char('编码')
|
||||
name = fields.Char('型号名称')
|
||||
# 关联刀具物料
|
||||
cutting_tool_material = fields.Many2one('sf.cutting.tool.material', '刀具物料')
|
||||
# 刀盘类型字段,关联刀盘类型对象
|
||||
cutter_pad_model_number = fields.Many2one('sf.cutter.pad.model', '刀盘类型')
|
||||
# 增加品牌、C柄径(mm)、L总长(mm)、材料型号、刃数、D刃径(mm)、适用刀片型号、配对扳手(mm)、配备螺丝(mm)、刀尖圆角半径、精度等级、硬度(°)、适用范围、图片、创建人、创建时间
|
||||
brand = fields.Many2one('sf.machine.brand', '品牌')
|
||||
c_diameter = fields.Float('C柄径(mm)')
|
||||
total_length = fields.Float('L总长(mm)')
|
||||
material_model = fields.Many2one('sf.materials.model', '材料型号')
|
||||
blade_number = fields.Integer('刃数')
|
||||
d_diameter = fields.Float('D刃径(mm)')
|
||||
blade = fields.Many2many('sf.blade', string='适用刀片型号')
|
||||
wrench = fields.Float('配对扳手(mm)')
|
||||
screw = fields.Float('配备螺丝(mm)')
|
||||
radius = fields.Float('刀尖圆角半径')
|
||||
accuracy = fields.Char('精度等级')
|
||||
hardness = fields.Char('硬度(°)')
|
||||
scope = fields.Char('适用范围')
|
||||
image = fields.Binary('图片')
|
||||
|
||||
|
||||
# 刀盘类型
|
||||
class CutterPadModel(models.Model):
|
||||
_name = 'sf.cutter.pad.model'
|
||||
_description = '刀盘类型'
|
||||
|
||||
code = fields.Char('编码')
|
||||
name = fields.Char('名称')
|
||||
# 关联刀具物料
|
||||
cutting_tool_material = fields.Many2one('sf.cutting.tool.material', '刀具物料')
|
||||
remark = fields.Char('备注')
|
||||
|
||||
|
||||
# 刀柄
|
||||
class Handle(models.Model):
|
||||
_name = 'sf.handle'
|
||||
_description = '刀柄'
|
||||
|
||||
code = fields.Char('编码')
|
||||
name = fields.Char('型号名称')
|
||||
# 关联刀具物料
|
||||
cutting_tool_material = fields.Many2one('sf.cutting.tool.material', '刀具物料')
|
||||
# 刀柄类型字段,关联刀柄类型对象
|
||||
handle_model_number = fields.Many2one('sf.handle.model', '刀柄类型')
|
||||
# 增加、刀柄类型、品牌、L(mm)、L1(mm)、D1(mm)、重量(kg)、材料型号、本体精度(mm)、配对螺母(mm)、适用夹头型号、夹持范围(mm)、检测精度、检测硬度、标准转速、图片、创建人、创建时间
|
||||
brand = fields.Many2one('sf.machine.brand', '品牌')
|
||||
length = fields.Float('L(mm)')
|
||||
length1 = fields.Float('L1(mm)')
|
||||
diameter1 = fields.Float('D1(mm)')
|
||||
weight = fields.Float('重量(kg)')
|
||||
material_model = fields.Many2one('sf.materials.model', '材料型号')
|
||||
body_accuracy = fields.Float('本体精度(mm)')
|
||||
nut = fields.Float('配对螺母(mm)')
|
||||
chuck_model = fields.Many2many('sf.chuck.model', string='适用夹头型号')
|
||||
clamping_range = fields.Float('夹持范围(mm)')
|
||||
detection_accuracy = fields.Float('检测精度')
|
||||
detection_hardness = fields.Char('检测硬度')
|
||||
standard_speed = fields.Float('标准转速')
|
||||
image = fields.Binary('图片')
|
||||
|
||||
|
||||
# 刀柄类型
|
||||
class HandleModel(models.Model):
|
||||
_name = 'sf.handle.model'
|
||||
_description = '刀柄类型'
|
||||
|
||||
code = fields.Char('编码')
|
||||
name = fields.Char('名称')
|
||||
# 关联刀具物料
|
||||
cutting_tool_material = fields.Many2one('sf.cutting.tool.material', '刀具物料')
|
||||
remark = fields.Char('备注')
|
||||
|
||||
|
||||
# 夹头对象(夹头型号对象)
|
||||
class Chuck(models.Model):
|
||||
_name = 'sf.chuck'
|
||||
_description = '夹头'
|
||||
_rec_name = 'code'
|
||||
|
||||
code = fields.Char('编码')
|
||||
name = fields.Char('型号名称')
|
||||
# 关联刀具物料
|
||||
cutting_tool_material = fields.Many2one('sf.cutting.tool.material', '刀具物料')
|
||||
# 夹头类型字段,关联夹头类型对象
|
||||
chuck_model_number = fields.Many2one('sf.chuck.model', '夹头类型')
|
||||
# 增加品牌、精度(mm)、外径(mm)、内径(mm)、高度(mm)、材料型号、配对螺母(mm)、适用刀柄型号、夹持范围(mm)、特性、图片、创建人、创建时间
|
||||
brand = fields.Many2one('sf.machine.brand', '品牌')
|
||||
accuracy = fields.Float('精度(mm)')
|
||||
diameter = fields.Float('外径(mm)')
|
||||
inner_diameter = fields.Float('内径(mm)')
|
||||
height = fields.Float('高度(mm)')
|
||||
material_model = fields.Many2one('sf.materials.model', '材料型号')
|
||||
nut = fields.Float('配对螺母(mm)')
|
||||
handle_model = fields.Many2many('sf.handle.model', string='适用刀柄型号')
|
||||
clamping_range = fields.Float('夹持范围(mm)')
|
||||
feature = fields.Char('特性')
|
||||
image = fields.Binary('图片')
|
||||
|
||||
|
||||
# 夹头类型
|
||||
class ChuckModel(models.Model):
|
||||
_name = 'sf.chuck.model'
|
||||
_description = '夹头类型'
|
||||
|
||||
code = fields.Char('编码')
|
||||
name = fields.Char('名称')
|
||||
# 关联刀具物料
|
||||
cutting_tool_material = fields.Many2one('sf.cutting.tool.material', '刀具物料')
|
||||
remark = fields.Char('备注')
|
||||
@@ -1,12 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import json
|
||||
import requests
|
||||
from odoo import fields, models, api
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo.addons.sf_base.commons.common import Common
|
||||
|
||||
|
||||
# from datetime import datetime
|
||||
# from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
# 刀具物料
|
||||
class CuttingToolMaterial(models.Model):
|
||||
_name = 'sf.cutting.tool.material'
|
||||
_description = '刀具物料'
|
||||
@@ -26,58 +25,7 @@ class FunctionalCuttingTool(models.Model):
|
||||
name = fields.Char('名称')
|
||||
active = fields.Boolean('有效', default=True)
|
||||
mrs_cutting_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型')
|
||||
mrs_cutting_tool_model_id = fields.Many2one('sf.cutting.tool.model', string='刀具型号')
|
||||
|
||||
# # 整体式刀具型号
|
||||
# mrs_cutting_tool_integral_model_ids = fields.Many2many('sf.cutting.tool.model', 'rel_integral_model_functional_sf',
|
||||
# string='整体式刀具型号', domain=
|
||||
# [('cutting_tool_type', '=', '整体式刀具')])
|
||||
# # 刀片型号
|
||||
# mrs_cutting_tool_blade_model_ids = fields.Many2many('sf.cutting.tool.model', 'rel_blade_model_functional_sf',
|
||||
# string='刀片型号', domain=
|
||||
# [('cutting_tool_type', '=', '刀片')])
|
||||
# # 刀杆型号
|
||||
# mrs_cutting_tool_cutterbar_model_ids = fields.Many2many('sf.cutting.tool.model',
|
||||
# 'rel_cutterbar_model_functional_sf',
|
||||
# string='刀杆型号', domain=
|
||||
# [('cutting_tool_type', '=', '刀杆')])
|
||||
# # 刀盘型号
|
||||
# mrs_cutting_tool_cutterpad_model_ids = fields.Many2many('sf.cutting.tool.model',
|
||||
# 'rel_cutterpad_model_functional_sf',
|
||||
# string='刀盘型号', domain=
|
||||
# [('cutting_tool_type', '=', '刀盘')])
|
||||
# # 刀柄型号
|
||||
# mrs_cutting_tool_cutterhandle_model_ids = fields.Many2many('sf.cutting.tool.model',
|
||||
# 'rel_cutterhandle_model_functional_sf',
|
||||
# string='刀柄型号',
|
||||
# domain=
|
||||
# [('cutting_tool_type', '=', '刀柄')])
|
||||
# # 夹头型号
|
||||
# mrs_cutting_tool_cutterhead_model_ids = fields.Many2many('sf.cutting.tool.model',
|
||||
# 'rel_cutterhead_model_functional_sf',
|
||||
# string='夹头型号', domain=
|
||||
# [('cutting_tool_type', '=', '夹头')])
|
||||
#
|
||||
# diameter = fields.Float('直径(mm)')
|
||||
# tool_grade = fields.Selection([('1', 'P1'), ('2', 'P2'), ('3', 'P3'), ('4', 'P4'), ('5', 'P5'), ('6', 'P6')],
|
||||
# string='刀具等级')
|
||||
# machining_accuracy = fields.Float('加工精度(mm)')
|
||||
# tool_length = fields.Float('装刀长')
|
||||
# blade_number = fields.Integer('刃数')
|
||||
# integral_blade_length = fields.Float('整体刃长(mm)')
|
||||
# effective_blade_length = fields.Float('有效刃长(mm)')
|
||||
# max_life = fields.Float('最大寿命值')
|
||||
# is_standard = fields.Boolean('是否标准刀')
|
||||
# applicable_range = fields.Char('适用范围')
|
||||
# image = fields.Binary('图片')
|
||||
# active = fields.Boolean('有效', default=True)
|
||||
#
|
||||
# def _get_functional_tool_model_ids(self, functional_tool_model_code):
|
||||
# functional_tool_model_ids = []
|
||||
# for item in functional_tool_model_code:
|
||||
# functional_tool_model = self.env['sf.cutting.tool.model'].search([('code', '=', item)])
|
||||
# functional_tool_model_ids.append(functional_tool_model.id)
|
||||
# return [(6, 0, functional_tool_model_ids)]
|
||||
mrs_cutting_tool_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀具型号')
|
||||
|
||||
|
||||
# 功能刀具类型
|
||||
@@ -91,133 +39,6 @@ class FunctionalCuttingToolModel(models.Model):
|
||||
active = fields.Boolean('有效', default=True)
|
||||
|
||||
|
||||
# 刀具型号
|
||||
class CuttingToolModel(models.Model):
|
||||
_name = 'sf.cutting.tool.model'
|
||||
_description = '刀具型号'
|
||||
|
||||
name = fields.Char('名称')
|
||||
cutting_tool_material_id = fields.Many2one('sf.cutting.tool.material', string='刀具物料')
|
||||
cutting_tool_type = fields.Char(string="刀具物料类型", related='cutting_tool_material_id.name', store=True)
|
||||
cutting_tool_type_id = fields.Many2one('sf.cutting.tool.type', string='刀具类型',
|
||||
)
|
||||
brand_id = fields.Many2one('sf.machine.brand', '品牌', domain="[('tag_ids.name', 'ilike', '刀具')]")
|
||||
tool_length = fields.Integer('长度(mm)')
|
||||
tool_width = fields.Integer('宽度(mm)')
|
||||
tool_height = fields.Integer('高度(mm)')
|
||||
tool_thickness = fields.Integer('厚度(mm)')
|
||||
tool_weight = fields.Float('重量(kg)')
|
||||
coating_material = fields.Char('涂层材质')
|
||||
|
||||
# 整体式刀具参数
|
||||
total_length = fields.Float('总长度(mm)')
|
||||
shank_length = fields.Float('柄部长度(mm)')
|
||||
blade_length = fields.Float('刃部长度(mm)')
|
||||
diameter = fields.Float('直径(mm)')
|
||||
blade_number = fields.Integer('刃数')
|
||||
front_angle = fields.Float('前角(°)')
|
||||
rear_angle = fields.Float('后角(°)')
|
||||
main_included_angle = fields.Float('主偏角(°)')
|
||||
material_model_id = fields.Many2one('sf.materials.model', '材料型号')
|
||||
nut = fields.Float('配对螺母(mm)')
|
||||
# 适用夹头型号可以多选
|
||||
chuck_ids = fields.Many2many(
|
||||
'sf.cutting.tool.model',
|
||||
relation='cutting_tool_model_handle_chuck_rel',
|
||||
column1='model_id_1',
|
||||
column2='model_id_2',
|
||||
domain="[('cutting_tool_type', '=', '夹头')]",
|
||||
string='适用夹头型号')
|
||||
# 刀片参数
|
||||
top_angle = fields.Float('顶角(°)')
|
||||
jump_accuracy = fields.Float('径跳精度(um)')
|
||||
working_hardness = fields.Char('加工硬度(hrc)')
|
||||
cutter_bar_ids = fields.Many2many(
|
||||
'sf.cutting.tool.model',
|
||||
relation='cutting_tool_model_blade_cutter_bar_rel',
|
||||
column1='model_id_1',
|
||||
column2='model_id_2',
|
||||
domain="[('cutting_tool_type', '=', '刀杆')]",
|
||||
string='适用刀杆型号'
|
||||
)
|
||||
cutter_pad_ids = fields.Many2many(
|
||||
'sf.cutting.tool.model',
|
||||
relation='cutting_tool_model_blade_cutter_pad_rel',
|
||||
column1='model_id_1',
|
||||
column2='model_id_2',
|
||||
domain="[('cutting_tool_type', '=', '刀盘')]",
|
||||
string='适用刀盘型号' # 使用空列表作为默认值
|
||||
)
|
||||
# 刀杆/参数
|
||||
blade_diameter = fields.Float('刃径(mm)')
|
||||
blade_ids = fields.Many2many(
|
||||
'sf.cutting.tool.model',
|
||||
relation='cutting_tool_model_pad_blade_rel',
|
||||
column1='model_id_1',
|
||||
column2='model_id_2',
|
||||
domain="[('cutting_tool_type', '=', '刀片')]",
|
||||
string='适用刀片型号' # 使用空列表作为默认值
|
||||
)
|
||||
wrench = fields.Float('配对扳手(mm)')
|
||||
screw = fields.Float('配备螺丝(mm)')
|
||||
accuracy_level = fields.Char('精度等级')
|
||||
# 刀柄参数
|
||||
diameter_max = fields.Float('最大直径(mm)')
|
||||
clamping_diameter = fields.Float('夹持直径(mm)')
|
||||
flange_length = fields.Float('法兰柄长度(mm)')
|
||||
flange_diameter = fields.Float('法兰直径(mm)')
|
||||
# 夹头参数
|
||||
outer_diameter = fields.Float('外径(mm)')
|
||||
inner_diameter = fields.Float('内径(mm)')
|
||||
handle_ids = fields.Many2many(
|
||||
'sf.cutting.tool.model',
|
||||
relation='cutting_tool_model_chuck_handle_rel',
|
||||
column1='model_id_1',
|
||||
column2='model_id_2',
|
||||
domain="[('cutting_tool_type', '=', '刀柄')]",
|
||||
string='适用刀柄型号'
|
||||
)
|
||||
active = fields.Boolean('有效', default=True)
|
||||
|
||||
def _get_code(self, cutting_tool_type_code):
|
||||
cutting_tool_model = self.search(
|
||||
[('code', 'ilike', cutting_tool_type_code)],
|
||||
limit=1,
|
||||
order="id desc")
|
||||
if not cutting_tool_model:
|
||||
num = "%03d" % 1
|
||||
else:
|
||||
m = int(cutting_tool_model.code[-3:]) + 1
|
||||
num = "%03d" % m
|
||||
return "%s%s" % (cutting_tool_type_code, num)
|
||||
|
||||
code = fields.Char(string='编码', readonly=True)
|
||||
|
||||
def _onchange_cutting_tool_material_id(self, cutting_tool_material_id):
|
||||
if cutting_tool_material_id:
|
||||
if cutting_tool_material_id.name == "整体式刀具":
|
||||
code = self._get_code("JKM-T-DJWL-ZTDJ-")
|
||||
elif cutting_tool_material_id.name == "刀片":
|
||||
code = self._get_code("JKM-T-DJWL-DPIA-")
|
||||
elif cutting_tool_material_id.name == "刀杆":
|
||||
code = self._get_code("JKM-T-DJWL-DGAN-")
|
||||
elif cutting_tool_material_id.name == "刀盘":
|
||||
code = self._get_code("JKM-T-DJWL-DPAN-")
|
||||
elif cutting_tool_material_id.name == "夹头":
|
||||
code = self._get_code("JKM-T-DJWL-DJIA-")
|
||||
else:
|
||||
code = self._get_code("JKM-T-DJWL-DBIN-")
|
||||
return code
|
||||
|
||||
@api.model_create_multi
|
||||
def create(self, vals):
|
||||
obj = super(CuttingToolModel, self).create(vals)
|
||||
if obj.cutting_tool_material_id:
|
||||
code = self._onchange_cutting_tool_material_id(obj.cutting_tool_material_id)
|
||||
obj.code = code
|
||||
return obj
|
||||
|
||||
|
||||
# 刀具类型
|
||||
class CuttingToolType(models.Model):
|
||||
_name = 'sf.cutting.tool.type'
|
||||
@@ -229,3 +50,243 @@ class CuttingToolType(models.Model):
|
||||
cutting_tool_material_id = fields.Many2one('sf.cutting.tool.material', '刀具物料')
|
||||
remark = fields.Char('备注')
|
||||
active = fields.Boolean('有效', default=True)
|
||||
|
||||
|
||||
# 刀具标准库
|
||||
class CuttingToolModel(models.Model):
|
||||
_name = 'sf.cutting_tool.standard.library'
|
||||
_description = '刀具标准库'
|
||||
|
||||
code = fields.Char(string='编码')
|
||||
name = fields.Char('名称')
|
||||
# 关联刀具物料
|
||||
cutting_tool_material_id = fields.Many2one('sf.cutting.tool.material', '刀具物料', required=True)
|
||||
# 刀具物料类型
|
||||
cutting_tool_type = fields.Char(related='cutting_tool_material_id.name', string='刀具物料类型',
|
||||
store=True)
|
||||
# 关联刀具类型
|
||||
cutting_tool_type_id = fields.Many2one('sf.cutting.tool.type', '类型',
|
||||
domain="[('cutting_tool_material_id.name', '=', cutting_tool_type)]")
|
||||
brand_id = fields.Many2one('sf.machine.brand', '品牌')
|
||||
status = fields.Boolean(string='状态', default=False)
|
||||
image = fields.Binary('图片')
|
||||
|
||||
# 整体式刀具参数
|
||||
material_model_id = fields.Many2one('mrs.materials.model', '刀具材质')
|
||||
tool_hardness = fields.Integer('刀具硬度(hrc)')
|
||||
coating_material = fields.Char('涂层材质')
|
||||
blade_type = fields.Char('刃部类型')
|
||||
integral_coarse_medium_fine = fields.Selection([('粗', '粗'), ('中', '中'), ('精', '精')], '粗/中/精')
|
||||
integral_run_out_accuracy_max = fields.Char('整体式刀具端跳精度max')
|
||||
integral_run_out_accuracy_min = fields.Char('整体式刀具端跳精度min')
|
||||
ramping_angle_ids = fields.One2many('sf.ramping.angle', 'standard_library_id', '坡铣角度',
|
||||
domain=lambda self: [('standard_library_id', '=', self.id)])
|
||||
|
||||
fit_blade_shape_id = fields.Many2one('maintenance.equipment.image',
|
||||
'适配刀片形状', domain=[('type', '=', '刀片形状')])
|
||||
suitable_machining_method_ids = fields.Many2many('maintenance.equipment.image',
|
||||
'suitable_machining_method_library_rel',
|
||||
'适合加工方式', domain=[('type', '=', '加工能力')])
|
||||
blade_tip_characteristics_id = fields.Many2one('maintenance.equipment.image',
|
||||
'刀尖特征', domain=[('type', '=', '刀尖特征')])
|
||||
handle_type_id = fields.Many2one('maintenance.equipment.image',
|
||||
'柄部类型', domain=[('type', '=', '柄部类型')])
|
||||
cutting_direction_ids = fields.Many2many('maintenance.equipment.image', 'cutting_direction_library_rel',
|
||||
'走刀方向', domain=[('type', '=', '走刀方向')])
|
||||
suitable_coolant_ids = fields.Many2many('maintenance.equipment.image', 'suitable_coolants_library_rel',
|
||||
'适合冷却方式', domain=[('type', '=', '冷却方式')])
|
||||
compaction_way_id = fields.Many2one('maintenance.equipment.image',
|
||||
'压紧方式', domain=[('type', '=', '压紧方式')])
|
||||
integral_tool_basic_parameters_ids = fields.One2many('sf.tool.materials.basic.parameters',
|
||||
'standard_library_id', string='整体式刀具基本参数')
|
||||
blade_basic_parameters_ids = fields.One2many('sf.tool.materials.basic.parameters',
|
||||
'standard_library_id', string='刀片基本参数')
|
||||
cutter_bar_basic_parameters_ids = fields.One2many('sf.tool.materials.basic.parameters',
|
||||
'standard_library_id', string='刀杆基本参数')
|
||||
cutter_head_basic_parameters_ids = fields.One2many('sf.tool.materials.basic.parameters',
|
||||
'standard_library_id', string='刀盘基本参数')
|
||||
knife_handle_basic_parameters_ids = fields.One2many('sf.tool.materials.basic.parameters',
|
||||
'standard_library_id', string='刀柄基本参数')
|
||||
chuck_basic_parameters_ids = fields.One2many('sf.tool.materials.basic.parameters',
|
||||
'standard_library_id', string='夹头基本参数')
|
||||
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(整体式刀具)')
|
||||
feed_per_tooth_ids_3 = fields.One2many('sf.feed.per.tooth', 'standard_library_id', '每齿走刀量fz(刀片)')
|
||||
material_model_id = fields.Many2one('sf.materials.model', '材料型号')
|
||||
# 适用夹头型号可以多选
|
||||
# chuck_ids = fields.Many2many(
|
||||
# 'sf.cutting_tool.standard.library',
|
||||
# relation='cutting_tool_type_library_handle_chuck_rel',
|
||||
# column1='model_id_1',
|
||||
# column2='model_id_2',
|
||||
# domain="[('cutting_tool_material_id.name', '=', '夹头')]",
|
||||
# string='适用夹头型号')
|
||||
|
||||
chuck_id = fields.Many2one(
|
||||
'sf.cutting_tool.standard.library',
|
||||
domain="[('cutting_tool_material_id.name', '=', '夹头')]",
|
||||
string='适用夹头型号')
|
||||
cutter_bar_ids = fields.Many2many(
|
||||
'sf.cutting_tool.standard.library',
|
||||
relation='cutting_tool_type_library_cutter_bar_rel',
|
||||
column1='model_id_1',
|
||||
column2='model_id_2',
|
||||
domain="[('cutting_tool_material_id.name', '=', '刀杆')]",
|
||||
string='适用刀杆型号'
|
||||
)
|
||||
cutter_pad_ids = fields.Many2many(
|
||||
'sf.cutting_tool.standard.library',
|
||||
relation='cutting_tool_type_library_cutter_pad_rel',
|
||||
column1='model_id_1',
|
||||
column2='model_id_2',
|
||||
domain="[('cutting_tool_material_id.name', '=', '刀盘')]",
|
||||
string='适用刀盘型号' # 使用空列表作为默认值
|
||||
)
|
||||
# 刀杆/参数
|
||||
# blade_ids = fields.Many2many(
|
||||
# 'sf.cutting_tool.standard.library',
|
||||
# relation='cutting_tool_type_library_pad_blade_rel',
|
||||
# column1='model_id_1',
|
||||
# column2='model_id_2',
|
||||
# domain="[('cutting_tool_material_id.name', '=', '刀片')]",
|
||||
# string='适用刀片型号' # 使用空列表作为默认值
|
||||
# )
|
||||
|
||||
handle_id = fields.Many2one(
|
||||
'sf.cutting_tool.standard.library',
|
||||
domain="[('cutting_tool_material_id.name', '=', '刀柄')]",
|
||||
string='适用刀柄型号'
|
||||
)
|
||||
# handle_ids = fields.Many2many(
|
||||
# 'sf.cutting_tool.standard.library',
|
||||
# relation='cutting_tool_type_library_chuck_handle_rel',
|
||||
# column1='model_id_1',
|
||||
# column2='model_id_2',
|
||||
# domain="[('cutting_tool_material_id.name', '=', '刀柄')]",
|
||||
# string='适用刀柄型号'
|
||||
# )
|
||||
active = fields.Boolean('有效', default=True)
|
||||
is_cloud = fields.Boolean('云端数据', default=False)
|
||||
|
||||
def _get_ids(self, cutting_tool_type_code, factory_short_name):
|
||||
cutting_tool_type_ids = []
|
||||
for item in cutting_tool_type_code:
|
||||
cutting_tool_type = self.search([('code', '=', item.replace("JKM", factory_short_name))])
|
||||
if cutting_tool_type:
|
||||
cutting_tool_type_ids.append(cutting_tool_type.id)
|
||||
return [(6, 0, cutting_tool_type_ids)]
|
||||
|
||||
|
||||
class MaintenanceStandardImage(models.Model):
|
||||
_name = 'maintenance.equipment.image'
|
||||
_description = '能力特征库'
|
||||
|
||||
active = fields.Boolean('有效', default=True)
|
||||
name = fields.Char('名称')
|
||||
image = fields.Binary(string='图文')
|
||||
type = fields.Selection(
|
||||
[('加工能力', '加工能力'), ('刀尖特征', '刀尖特征'), ('柄部类型', '柄部类型'), ('走刀方向', '走刀方向'),
|
||||
('压紧方式', '压紧方式'), ('刀片形状', '刀片形状'), ('冷却方式', '冷却方式')],
|
||||
string='特征')
|
||||
equipment_id = fields.Many2many('maintenance.equipment', 'image_id', string='设备')
|
||||
equipment_lq_id = fields.Many2many('maintenance.equipment', 'image_lq_id', string='设备')
|
||||
jg_equipment_id = fields.Many2many('sf.machine_tool.type', 'jg_image_id', string='机床型号')
|
||||
lq_equipment_id = fields.Many2many('sf.machine_tool.type', 'lq_image_id', string='机床型号')
|
||||
|
||||
def _get_ids(self, name_arr):
|
||||
ability_feature_ids = []
|
||||
for item in name_arr:
|
||||
ability_feature = self.search([('name', '=', item)])
|
||||
if ability_feature:
|
||||
ability_feature_ids.append(ability_feature.id)
|
||||
return [(6, 0, ability_feature_ids)]
|
||||
|
||||
@api.model
|
||||
def name_search(self, name='', args=None, operator='ilike', limit=100):
|
||||
# 调用父类的name_search方法,获取原始的结果列表
|
||||
res = super().name_search(name, args, operator, limit)
|
||||
# 定义一个空字典用来存储id和name的映射关系
|
||||
name_dict = {}
|
||||
# 遍历结果列表,将id和name存入字典中
|
||||
for item in res:
|
||||
id = item[0]
|
||||
name = item[1]
|
||||
name_dict[id] = name
|
||||
# 根据id列表搜索符合条件的记录
|
||||
records = self.browse(name_dict.keys())
|
||||
# 定义一个新的结果列表用来存储修改后的结果
|
||||
new_res = []
|
||||
# 遍历每条记录
|
||||
for record in records:
|
||||
# 获取记录的id,name和image属性
|
||||
id = record.id
|
||||
name = name_dict[id]
|
||||
image = record.image
|
||||
# 如果image不为空,将其转换为data URI scheme
|
||||
if image:
|
||||
data_uri = f"data:image/png;base64,{image.decode('utf-8')}"
|
||||
else:
|
||||
data_uri = ""
|
||||
# 将这三个属性组成一个数组,并添加到结果列表中 result.append([id, name, data_uri]) # 返回结果列表 return result
|
||||
new_res.append([id, name, data_uri])
|
||||
# 返回新的结果列表
|
||||
return new_res
|
||||
|
||||
@api.model
|
||||
def search_read(self, domain=None, fields=None, offset=0, limit=None, order=None):
|
||||
# 调用原生的search_read方法获取记录
|
||||
records = super(MaintenanceStandardImage, self).search_read(domain, fields, offset, limit, order)
|
||||
# 遍历每条记录,添加image数据
|
||||
for record in records:
|
||||
image_field = self.browse(record['id']).image
|
||||
if image_field:
|
||||
record['image'] = f"data:image/png;base64,{image_field.decode('utf-8')}"
|
||||
else:
|
||||
record['image'] = ""
|
||||
return records
|
||||
|
||||
|
||||
class ToolGroups(models.Model):
|
||||
_name = 'sf.tool.groups'
|
||||
_description = '刀具组'
|
||||
|
||||
name = fields.Char('名称')
|
||||
equipment_ids = fields.Many2many('maintenance.equipment', 'ref_maintenance_equipment', string='机台号')
|
||||
remark = fields.Char('备注', size=50)
|
||||
|
||||
# ==========机床刀具组接口==========
|
||||
def _register_tool_groups(self, obj):
|
||||
create_url = '/AutoDeviceApi/MaintenanceToolGroups'
|
||||
sf_sync_config = self.env['res.config.settings'].get_values()
|
||||
token = sf_sync_config['token']
|
||||
sf_secret_key = sf_sync_config['sf_secret_key']
|
||||
headers = Common.get_headers(obj, token, sf_secret_key)
|
||||
strurl = sf_sync_config['sf_url'] + create_url
|
||||
device_id = ''
|
||||
name = None
|
||||
if obj:
|
||||
for equipment_id in obj.equipment_ids:
|
||||
device_id = '%s,%s' % (device_id, equipment_id.name)
|
||||
name = obj.name
|
||||
val = {
|
||||
'DeviceId': device_id,
|
||||
'GroupName': name,
|
||||
}
|
||||
kw = json.dumps(val, ensure_ascii=False)
|
||||
r = requests.post(strurl, json={}, data={'kw': kw, 'token': token}, headers=headers)
|
||||
ret = r.json()
|
||||
if r == 200:
|
||||
return "机床刀具组发送成功"
|
||||
else:
|
||||
raise ValidationError("机床刀具组发送失败")
|
||||
|
||||
# def write(self, vals):
|
||||
# obj = super().write(vals)
|
||||
# self._register_tool_groups(self)
|
||||
# return obj
|
||||
#
|
||||
# @api.model_create_multi
|
||||
# def create(self, vals_list):
|
||||
# records = super(ToolGroups, self).create(vals_list)
|
||||
# self._register_tool_groups(records)
|
||||
# return records
|
||||
|
||||
10
sf_base/models/tool_base_new.py.rej
Normal file
@@ -0,0 +1,10 @@
|
||||
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')
|
||||
|
||||
194
sf_base/models/tool_other_features.py
Normal file
@@ -0,0 +1,194 @@
|
||||
from odoo import fields, models, api
|
||||
|
||||
|
||||
class ToolMaterialsBasicParameters(models.Model):
|
||||
_name = 'sf.tool.materials.basic.parameters'
|
||||
_description = '刀具物料基本参数'
|
||||
|
||||
name = fields.Char('物料号', size=50)
|
||||
code = fields.Char('编码', size=50)
|
||||
standard_library_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀具标准库')
|
||||
cutting_tool_type = fields.Char(related='standard_library_id.cutting_tool_type', string='刀具物料类型',
|
||||
store=True)
|
||||
|
||||
# 整体式刀具参数
|
||||
total_length = fields.Float('总长度(mm)')
|
||||
blade_number = fields.Selection(
|
||||
[('0', '0'), ('2', '2'), ('3', '3'), ('4', '4'), ('5', '5'), ('6', '6'), ('7', '7'), ('8', '8')],
|
||||
string='刃数(个)', default='0')
|
||||
neck_diameter = fields.Float('颈部直径(mm)')
|
||||
neck_length = fields.Float('颈部长度(mm)')
|
||||
handle_diameter = fields.Float('柄部直径(mm)')
|
||||
handle_length = fields.Float('柄部长度(mm)')
|
||||
blade_tip_diameter = fields.Integer('刀尖直径(mm)')
|
||||
blade_tip_working_size = fields.Char('刀尖处理尺寸(R半径mm/倒角)', size=20)
|
||||
blade_tip_taper = fields.Integer('刀尖锥度(°)')
|
||||
blade_diameter = fields.Float('刃部直径(mm)')
|
||||
blade_length = fields.Float('刃部长度(mm)')
|
||||
blade_helix_angle = fields.Integer('刃部螺旋角(°)')
|
||||
blade_width = fields.Float('刃部宽度(mm)')
|
||||
blade_depth = fields.Float('刃部深度(mm)')
|
||||
pitch = fields.Float('牙距(mm)')
|
||||
cutting_depth = fields.Float('切削深度(mm)')
|
||||
# 刀片参数
|
||||
length = fields.Float('长度(mm)')
|
||||
thickness = fields.Float('厚度(mm)')
|
||||
width = fields.Float('宽度(mm)')
|
||||
cutting_blade_length = fields.Float('切削刃长(mm)')
|
||||
relief_angle = fields.Integer('后角(°)')
|
||||
blade_tip_circular_arc_radius = fields.Char('刀尖圆弧半径(mm)', size=20)
|
||||
inscribed_circle_diameter = fields.Float('内接圆直径(mm)')
|
||||
install_aperture_diameter = fields.Float('安装孔直径(mm)')
|
||||
chip_breaker_groove = fields.Selection([('无', '无'), ('单面', '单面'), ('双面', '双面')],
|
||||
string='有无断屑槽')
|
||||
chip_breaker_type_code = fields.Char('断屑槽型代号')
|
||||
blade_teeth_model = fields.Selection(
|
||||
[('无', '无'), ('V牙型', 'V牙型'), ('米制全牙型', '米制全牙型'), ('美制全牙型', '美制全牙型'),
|
||||
('惠氏全牙型', '惠氏全牙型'), ('BSPT全牙型', 'BSPT全牙型'), ('NPT全牙型', 'NPT全牙型'),
|
||||
('UNJ全牙型', 'UNJ全牙型'), ('DIN405圆牙型', 'DIN405圆牙型'), ('ACME梯形', 'ACME梯形'),
|
||||
('石油管螺纹刀片', '石油管螺纹刀片'), ('矮牙ACME梯形', '矮牙ACME梯形'),
|
||||
('Trapeze30° 103', 'Trapeze30° 103')], string='刀片牙型', default='无')
|
||||
blade_blade_number = fields.Selection(
|
||||
[('0', '0'), ('1', '1'), ('2', '2'), ('3', '3'), ('4', '4'), ('5', '5'), ('6', '6'), ('7', '7'), ('8', '8'),
|
||||
('9', '9'), ('10', '10')],
|
||||
string='刀片的刃数(个)', default='0')
|
||||
main_included_angle = fields.Integer('主偏角(°)')
|
||||
top_angle = fields.Integer('顶角(°)')
|
||||
thread_model = fields.Selection([('无', '无'), ('外螺纹', '外螺纹'), ('内螺纹', '内螺纹')], string='螺纹类型',
|
||||
default='无')
|
||||
thread_num = fields.Float('每英寸螺纹数(tpi)')
|
||||
blade_tip_height_tolerance = fields.Char('刀尖高度公差(mm)', size=20)
|
||||
inscribed_circle_tolerance = fields.Char('内接圆公差(mm)', size=20)
|
||||
thickness_tolerance = fields.Char('厚度公差(mm)', size=20)
|
||||
# 刀杆参数
|
||||
height = fields.Float('高度(mm)')
|
||||
blade_height = fields.Float('刃部高度(mm)')
|
||||
knife_head_height = fields.Float('刀头高度(mm)')
|
||||
knife_head_width = fields.Float('刀头宽度(mm)')
|
||||
knife_head_length = fields.Float('刀头长度(mm)')
|
||||
cut_depth_max = fields.Float('最大切削深度(mm)')
|
||||
cutter_arbor_diameter = fields.Float('刀杆直径(mm)')
|
||||
min_machining_aperture = fields.Integer('最小加工孔径(mm)')
|
||||
install_blade_tip_num = fields.Integer('可装刀片数/齿数(个)')
|
||||
cutting_blade_model = fields.Char('切削类型', size=20)
|
||||
is_cooling_hole = fields.Boolean('有无冷却孔')
|
||||
locating_slot_code = fields.Char('定位槽代号', size=20)
|
||||
installing_structure = fields.Char('安装结构', size=20)
|
||||
blade_id = fields.Many2one(
|
||||
'sf.cutting_tool.standard.library',
|
||||
domain="[('cutting_tool_material_id.name', '=', '刀片')]",
|
||||
string='适配刀片型号' # 使用空列表作为默认值
|
||||
)
|
||||
tool_shim = fields.Char('适配刀垫型号', size=50)
|
||||
cotter_pin = fields.Char('适配销钉型号', size=50)
|
||||
pressing_plate = fields.Char('适配压板型号', size=50)
|
||||
screw = fields.Char('适配螺钉型号', size=50)
|
||||
spanner = fields.Char('适配扳手型号', size=50)
|
||||
# 刀盘参数
|
||||
cutter_head_diameter = fields.Float('刀盘直径(mm)')
|
||||
interface_diameter = fields.Float('接口直径(mm)')
|
||||
# 刀柄参数
|
||||
flange_shank_length = fields.Float('法兰长(mm)')
|
||||
flange_diameter = fields.Float('法兰直径(mm)')
|
||||
fit_chuck_size = fields.Char('适配夹头尺寸')
|
||||
handle_external_diameter = fields.Float('柄部外径(mm)')
|
||||
handle_inside_diameter = fields.Float('柄部内径(mm)')
|
||||
dynamic_balance_class = fields.Char('动平衡等级')
|
||||
min_clamping_diameter = fields.Float('最小夹持直径(mm)')
|
||||
max_clamping_diameter = fields.Float('最大夹持直径(mm)')
|
||||
clamping_mode = fields.Char('夹持方式', size=20)
|
||||
max_load_capacity = fields.Float('最大负载能力(kg)')
|
||||
taper = fields.Integer('锥度(°)')
|
||||
shank_length = fields.Float('刀柄长度(mm)', digits=(3, 2))
|
||||
shank_diameter = fields.Float('刀柄直径(mm)')
|
||||
tool_changing_time = fields.Integer('换刀时间(s)')
|
||||
standard_rotate_speed = fields.Integer('标准转速(n/min)')
|
||||
max_rotate_speed = fields.Integer('最大转速(n/min)')
|
||||
diameter_slip_accuracy = fields.Char('径跳精度(mm)', size=20)
|
||||
cooling_model = fields.Char('冷却类型', size=20)
|
||||
taper_shank_model = fields.Char('锥柄型号')
|
||||
is_quick_cutting = fields.Boolean('可高速切削', default=False)
|
||||
is_safe_lock = fields.Boolean('有无安全锁', default=False)
|
||||
chuck_id = fields.Many2one(
|
||||
'sf.cutting_tool.standard.library',
|
||||
domain="[('cutting_tool_material_id.name', '=', '夹头')]",
|
||||
string='适配夹头型号' # 使用空列表作为默认值
|
||||
)
|
||||
nut = fields.Char('适配锁紧螺母型号')
|
||||
|
||||
# 夹头参数
|
||||
er_size_model = fields.Char('ER尺寸型号', size=20)
|
||||
outer_diameter = fields.Float('外径(mm)')
|
||||
inner_diameter = fields.Float('内径(mm)')
|
||||
run_out_accuracy = fields.Char('跳动精度(mm)', size=20)
|
||||
top_diameter = fields.Float('顶部直径(mm)')
|
||||
weight = fields.Float('重量(kg)')
|
||||
clamping_length = fields.Float('夹持长度(mm)')
|
||||
clamping_tolerance = fields.Char('夹持公差(mm)', size=20)
|
||||
cooling_jacket = fields.Char('适用冷却套型号', size=50)
|
||||
active = fields.Boolean(string='有效', default=True)
|
||||
|
||||
|
||||
class CuttingSpeed(models.Model):
|
||||
_name = 'sf.cutting.speed'
|
||||
_description = '切削速度Vc'
|
||||
|
||||
name = fields.Char('名称')
|
||||
product_template_id = fields.Many2one('product.template')
|
||||
standard_library_id = fields.Many2one('sf.cutting_tool.standard.library', string='标准库')
|
||||
|
||||
execution_standard_id = fields.Many2one('sf.international.standards', string='执行标准', store=True)
|
||||
material_code = fields.Char('材料代号')
|
||||
material_name_id = fields.Many2one('sf.materials.model', '材料名称',
|
||||
domain="[('standards_id', '=', execution_standard_id)]")
|
||||
material_grade = fields.Char('材料牌号')
|
||||
tensile_strength = fields.Char('拉伸强度 (N/mm²)')
|
||||
hardness = fields.Integer('硬度(hrc)')
|
||||
ability_feature_library = fields.Many2one('maintenance.equipment.image', '加工方式',
|
||||
domain="[('type', '=', '加工能力')]")
|
||||
cutting_width_depth_id = fields.Many2one('sf.cutting.width.depth', '切削宽度和深度')
|
||||
process_capability = fields.Selection([('粗加工', '粗加工'), ('精加工', '精加工')], string='粗/精加工')
|
||||
cutting_speed = fields.Char('切削速度', required=True)
|
||||
cutting_speed_max = fields.Float('最大值')
|
||||
cutting_speed_min = fields.Float('最小值')
|
||||
|
||||
application = fields.Selection([('主应用', '主应用'), ('次应用', '次应用')], '主/次应用')
|
||||
active = fields.Boolean(string='有效', default=True)
|
||||
|
||||
|
||||
class FeedPerTooth(models.Model):
|
||||
_name = 'sf.feed.per.tooth'
|
||||
_description = '每齿走刀量fz'
|
||||
_order = 'blade_diameter,cutting_width_depth_id,materials_type_id'
|
||||
|
||||
name = fields.Char('名称')
|
||||
product_template_id = fields.Many2one('product.template')
|
||||
standard_library_id = fields.Many2one('sf.cutting_tool.standard.library', string='标准库')
|
||||
blade_diameter = fields.Integer('刃部直径(mm)', readonly=True)
|
||||
materials_type_id = fields.Many2one('sf.materials.model', string='材料名称', readonly=True)
|
||||
cutting_width_depth_id = fields.Many2one('sf.cutting.width.depth', '切削宽度和深度', readonly=True)
|
||||
feed_per_tooth = fields.Char('每齿走刀量 (mm/z)', size=20)
|
||||
active = fields.Boolean(string='有效', default=True)
|
||||
|
||||
|
||||
|
||||
# @api.depends('product_template_id')
|
||||
# def _compute_product_template_id(self):
|
||||
# if self.product_template_id is not None:
|
||||
# self.blade_diameter = self.product_template_id.cutting_tool_blade_diameter
|
||||
|
||||
|
||||
class CuttingWidthDepth(models.Model):
|
||||
_name = 'sf.cutting.width.depth'
|
||||
_description = '切削宽度和深度'
|
||||
|
||||
name = fields.Char('名称')
|
||||
|
||||
|
||||
class RampingAngle(models.Model):
|
||||
_name = 'sf.ramping.angle'
|
||||
_description = '坡铣角度'
|
||||
|
||||
standard_library_id = fields.Many2one('sf.cutting_tool.standard.library', '刀具标准库')
|
||||
|
||||
name = fields.Char('坡铣角度')
|
||||