Compare commits
761 Commits
14-formatL
...
10-account
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
29481d91b7 | ||
|
|
fc45c44280 | ||
|
|
a370c9100c | ||
|
|
e5d6ef4bad | ||
|
|
c3f1d30bdd | ||
|
|
6405be3fcf | ||
|
|
7a65c63f99 | ||
|
|
13d8100d98 | ||
|
|
0151c6a6e3 | ||
|
|
ea5fdcf4df | ||
|
|
4ff06be1a6 | ||
|
|
6c3c6cd43b | ||
|
|
3fef559aac | ||
|
|
75d7b7eac4 | ||
|
|
4a2fff177c | ||
|
|
e83238becd | ||
|
|
8bebd1e2ef | ||
|
|
b23f03f79d | ||
|
|
dc8363d6d1 | ||
|
|
ad850024ec | ||
|
|
03564a20b2 | ||
|
|
c1618166fb | ||
|
|
cf2464dfa4 | ||
|
|
80191002b8 | ||
|
|
694c800df3 | ||
|
|
bdf51029c7 | ||
|
|
478ab1fc2b | ||
|
|
362dba5f90 | ||
|
|
ac2b70b66e | ||
|
|
b75a2e47a2 | ||
|
|
3f73f15e4a | ||
|
|
c196343ec0 | ||
|
|
7d359d6730 | ||
|
|
904bf6c4f4 | ||
|
|
e13a2aba3d | ||
|
|
8cb880771e | ||
|
|
087bb1fde2 | ||
|
|
806b1b4a86 | ||
|
|
23519f4027 | ||
|
|
08cb6f2e86 | ||
|
|
b54ec10f10 | ||
|
|
118dd2a5c0 | ||
|
|
0afe9a39a6 | ||
|
|
159f163da5 | ||
|
|
d0620a4c83 | ||
|
|
5d2d5b1e63 | ||
|
|
ab1144850b | ||
|
|
4995403bf5 | ||
|
|
a415744f11 | ||
|
|
c943b4cd33 | ||
|
|
8800b94e5b | ||
|
|
ca5238a03c | ||
|
|
5f15d83c3c | ||
|
|
6370dc0ec8 | ||
|
|
0d27c0a830 | ||
|
|
d01820cd39 | ||
|
|
5f6107f2e8 | ||
|
|
ebb8f1ad86 | ||
|
|
04118bbf46 | ||
|
|
9cba31b68a | ||
|
|
21d1454ab9 | ||
|
|
d4e673103e | ||
|
|
9ebf7cdb4c | ||
|
|
f34a731d95 | ||
|
|
6ef322be4c | ||
|
|
dd15e3d194 | ||
|
|
71ecc03001 | ||
|
|
913be476dd | ||
|
|
de9871fd17 | ||
|
|
90a2e26e79 | ||
|
|
21f3b14d7a | ||
|
|
a7a8271a38 | ||
|
|
4cfd326398 | ||
|
|
295bb4edb5 | ||
|
|
8c73a84c46 | ||
|
|
8f555c88ce | ||
|
|
b5af2e54b0 | ||
|
|
b298039af4 | ||
|
|
8fbac5c221 | ||
|
|
96680c893f | ||
|
|
cc3b9d73ae | ||
|
|
8416216a77 | ||
|
|
1a9126d9a1 | ||
|
|
4e8c6f47f6 | ||
|
|
1cabf721f4 | ||
|
|
929f79cd98 | ||
|
|
0fabc8c4c1 | ||
|
|
c25747b474 | ||
|
|
6fa8464ab7 | ||
|
|
c02f539f8f | ||
|
|
27f96b8af2 | ||
|
|
8b3205cc35 | ||
|
|
7908943645 | ||
|
|
ffd6a409cc | ||
|
|
6446e087be | ||
|
|
a4a9be78bc | ||
|
|
567e7f1f6e | ||
|
|
a29384b817 | ||
|
|
23bd22a009 | ||
|
|
020ca72188 | ||
|
|
e3fc2764fb | ||
|
|
2d9b133cf6 | ||
|
|
4e9ca8fc5c | ||
|
|
3fdc3b4256 | ||
|
|
4d7102d699 | ||
|
|
bfb0f5380a | ||
|
|
e02727e6ee | ||
|
|
7cb35a031d | ||
|
|
f0bb02edf1 | ||
|
|
4f10be1bfe | ||
|
|
d547fd6916 | ||
|
|
357ad8d707 | ||
|
|
03bbe001ae | ||
|
|
b199228e1d | ||
|
|
7f0ea7fd0c | ||
|
|
0c94dde977 | ||
|
|
da92731607 | ||
|
|
2950f86219 | ||
|
|
744c0f487a | ||
|
|
d9fe676cae | ||
|
|
65d0d61c13 | ||
|
|
d61e48635b | ||
|
|
a7b2bde9e9 | ||
|
|
74966a7f15 | ||
|
|
3f47f7bf9f | ||
|
|
4d833d1c97 | ||
|
|
a577c4bbbd | ||
|
|
dc05ed3b5d | ||
|
|
2c1b8fe657 | ||
|
|
a2ea2534f0 | ||
|
|
1cae9ca021 | ||
|
|
953929cc4b | ||
|
|
068d57030a | ||
|
|
054bee90c0 | ||
|
|
782f1fdb92 | ||
|
|
72f7235c18 | ||
|
|
0a5c14b7f9 | ||
|
|
a4c382a546 | ||
|
|
5c9b6dd702 | ||
|
|
da6ba9b75e | ||
|
|
1ed7034ee4 | ||
|
|
9a8d9616b7 | ||
|
|
b9014e937d | ||
|
|
fc2dcbc359 | ||
|
|
b95837fa86 | ||
|
|
22a0d2b41b | ||
|
|
f9e554a312 | ||
|
|
559c301f2c | ||
|
|
295bf50cea | ||
|
|
8ed8c2bc70 | ||
|
|
b8a015a01e | ||
|
|
3024889c41 | ||
|
|
8a538c4e74 | ||
|
|
03ebc09eb0 | ||
|
|
81a4328531 | ||
|
|
1faecd98f7 | ||
|
|
0f4193e7c4 | ||
|
|
ecd05222a9 | ||
|
|
690a9196dd | ||
|
|
ab03ebe2cb | ||
|
|
074f4e517a | ||
|
|
26b27c398d | ||
|
|
e7afaa2c78 | ||
|
|
72116a7374 | ||
|
|
5d1df0b654 | ||
|
|
522d3d5aa0 | ||
|
|
bfd0c6f8cd | ||
|
|
a05263be77 | ||
|
|
f9951890b5 | ||
|
|
06a1d182e5 | ||
|
|
c4256b3005 | ||
|
|
c5776557cc | ||
|
|
361eb380e4 | ||
|
|
1034cc2347 | ||
|
|
f74dc15d4b | ||
|
|
c52412295f | ||
|
|
0d8e3a9066 | ||
|
|
238344b964 | ||
|
|
6ff67694ab | ||
|
|
662c37670c | ||
|
|
2b0c64b69e | ||
|
|
b40e4eca05 | ||
|
|
cc5291ba52 | ||
|
|
2f63e4e7a6 | ||
|
|
9ec29082b8 | ||
|
|
a11f9574ee | ||
|
|
ac05ca27a4 | ||
|
|
746d23fb3a | ||
|
|
aba8e33d48 | ||
|
|
d384b626e5 | ||
|
|
fcecfcc4e1 | ||
|
|
e6076c3f76 | ||
|
|
987e753a54 | ||
|
|
080e3decbc | ||
|
|
7d7424ad8a | ||
|
|
a32d091d83 | ||
|
|
bb849c0228 | ||
|
|
338d0d445d | ||
|
|
f0adce0034 | ||
|
|
2ebdc8e329 | ||
|
|
748614ba34 | ||
|
|
d0cdc96fbf | ||
|
|
61d576451e | ||
|
|
d56acb4a86 | ||
|
|
f3ad97de73 | ||
|
|
03cec78dc7 | ||
|
|
d4a936deaa | ||
|
|
9cfdaa88a3 | ||
|
|
e0732689b8 | ||
|
|
55d977914e | ||
|
|
0da06febfc | ||
|
|
a9d8137d1f | ||
|
|
19d2614feb | ||
|
|
dd05dfab28 | ||
|
|
a6e9568454 | ||
|
|
5a39df7423 | ||
|
|
2f9584e04e | ||
|
|
a3245985e5 | ||
|
|
19909b6761 | ||
|
|
aca7911d81 | ||
|
|
1d765aa4f7 | ||
|
|
16094358c7 | ||
|
|
2469c1f79d | ||
|
|
94926d188a | ||
|
|
e5221d6a96 | ||
|
|
d55b01ca7b | ||
|
|
5fda678474 | ||
|
|
390363d7e1 | ||
|
|
15a12feafd | ||
|
|
479e1a2710 | ||
|
|
735495656c | ||
|
|
b8255a5287 | ||
|
|
08445ad370 | ||
|
|
9267fca881 | ||
|
|
b8b307154a | ||
|
|
8b06320204 | ||
|
|
181ffab457 | ||
|
|
4d2f7a47ff | ||
|
|
216369f66c | ||
|
|
348e0205a0 | ||
|
|
ffda316d34 | ||
|
|
37281620af | ||
|
|
933bf336aa | ||
|
|
09b94dd01d | ||
|
|
0af5c20727 | ||
|
|
e3b305f117 | ||
|
|
1a191c9444 | ||
|
|
e30285caf7 | ||
|
|
fe7fec797f | ||
|
|
5304bde100 | ||
|
|
db7ea5681f | ||
|
|
0b12805495 | ||
|
|
f91b5267fe | ||
|
|
3396814a09 | ||
|
|
83c4e095f6 | ||
|
|
84bf228d92 | ||
|
|
7f8c461122 | ||
|
|
80b3d08ba5 | ||
|
|
7750ed1834 | ||
|
|
3b6973c4a2 | ||
|
|
b518594136 | ||
|
|
e353cdcad1 | ||
|
|
ea20effa7e | ||
|
|
c9bfc8bef2 | ||
|
|
6361e2e453 | ||
|
|
217afc8af0 | ||
|
|
2d74753bea | ||
|
|
d507311091 | ||
|
|
84c1caaf16 | ||
|
|
895a92393c | ||
|
|
fcba3e4129 | ||
|
|
a22148329f | ||
|
|
b2a96f4db2 | ||
|
|
a325a3a828 | ||
|
|
1c1855ec11 | ||
|
|
5bcfe45251 | ||
|
|
ddbdecd64e | ||
|
|
9e44400acd | ||
|
|
67e3c9a199 | ||
|
|
da5d35b8cb | ||
|
|
9fdbebc591 | ||
|
|
7f3d465a24 | ||
|
|
ad7a8d5e40 | ||
|
|
9617aedcb3 | ||
|
|
d8f0d061b7 | ||
|
|
5d7f512335 | ||
|
|
a7dc7a51ce | ||
|
|
da7ac67933 | ||
|
|
4d9659dee3 | ||
|
|
1f5887eb87 | ||
|
|
84ee109bdf | ||
|
|
80c90c7d35 | ||
|
|
bf4d613ed2 | ||
|
|
889fb28fd6 | ||
|
|
265210b4f1 | ||
|
|
ec6975ce6a | ||
|
|
b0f6832541 | ||
|
|
49f928199e | ||
|
|
94fd30c4b3 | ||
|
|
e51d19941b | ||
|
|
3284953528 | ||
|
|
52350ba5a7 | ||
|
|
95fb0d6f43 | ||
|
|
e7191d3ee1 | ||
|
|
8fc54fd37a | ||
|
|
85f505bd2d | ||
|
|
777fc14908 | ||
|
|
115c0b36de | ||
|
|
256c603796 | ||
|
|
985a894866 | ||
|
|
23cadc403c | ||
|
|
23139916b2 | ||
|
|
42b3505966 | ||
|
|
a9139b9430 | ||
|
|
3eab0c9d7a | ||
|
|
07f646dca3 | ||
|
|
4350679c22 | ||
|
|
5fb19a4a5e | ||
|
|
346de9be4b | ||
|
|
e4dc38b963 | ||
|
|
67e6860ec1 | ||
|
|
bdeb1a4101 | ||
|
|
e1f8e95bce | ||
|
|
f16095e343 | ||
|
|
c92ce72fd9 | ||
|
|
f90aa12a9f | ||
|
|
35163d8613 | ||
|
|
4e4d02aa14 | ||
|
|
9e3d62b4ba | ||
|
|
0bc2d19747 | ||
|
|
ed1937d501 | ||
|
|
acfd2f18a7 | ||
|
|
83140872ef | ||
|
|
6abb743736 | ||
|
|
5549139e5c | ||
|
|
e878021e63 | ||
|
|
6d7dc61dee | ||
|
|
cebc0e3b84 | ||
|
|
ef85216271 | ||
|
|
7c5ac7144c | ||
|
|
a35f1a3a32 | ||
|
|
022d7a719d | ||
|
|
e505ce2ad4 | ||
|
|
8bcbb83a91 | ||
|
|
07781aa724 | ||
|
|
42233bc0ce | ||
|
|
10eacdf226 | ||
|
|
1a46f39705 | ||
|
|
9e37c6e1ae | ||
|
|
96a7e6e443 | ||
|
|
c2f4e2066a | ||
|
|
b861521571 | ||
|
|
245c605ef5 | ||
|
|
aa278b3a0c | ||
|
|
a1ef881201 | ||
|
|
56095375d1 | ||
|
|
746a6926ea | ||
|
|
13e6facec5 | ||
|
|
6c53b3c1ae | ||
|
|
a379b59597 | ||
|
|
2f179995bf | ||
|
|
7c5f04a39e | ||
|
|
b814ec11bf | ||
|
|
7d39e50ba3 | ||
|
|
77995aa125 | ||
|
|
314350efee | ||
|
|
40ef119999 | ||
|
|
6583ea0cd9 | ||
|
|
7def6a85e4 | ||
|
|
618ad6d6d6 | ||
|
|
05c0f74420 | ||
|
|
78ff16436d | ||
|
|
b4dc9da272 | ||
|
|
3aa16cdacf | ||
|
|
d823e3ae75 | ||
|
|
a1f57e1ab5 | ||
|
|
c2d2e93f07 | ||
|
|
56bdeb3ee9 | ||
|
|
b811ae890a | ||
|
|
07a444367b | ||
|
|
8a7a3c670f | ||
|
|
7f2589c9bf | ||
|
|
93e63b74b6 | ||
|
|
c2accec411 | ||
|
|
62b01c781f | ||
|
|
33b99de09e | ||
|
|
e134153a40 | ||
|
|
6812d2e68b | ||
|
|
25d8a50d3a | ||
|
|
54b74f01c0 | ||
|
|
5ac6b777b2 | ||
|
|
fd05834ffe | ||
|
|
34a763d894 | ||
|
|
30089555c5 | ||
|
|
7f62369a06 | ||
|
|
005063e8c6 | ||
|
|
08ad828da7 | ||
|
|
31c6246e2c | ||
|
|
b7dd2a6a07 | ||
|
|
ef97656b42 | ||
|
|
16627ba6f0 | ||
|
|
7cf98a1001 | ||
|
|
6e8e9fa1aa | ||
|
|
02940c08cd | ||
|
|
2dd4a7d577 | ||
|
|
e1c660d90c | ||
|
|
aa3568e986 | ||
|
|
9c67a6df5d | ||
|
|
5be71f05b3 | ||
|
|
0498f6e24e | ||
|
|
80763de94b | ||
|
|
18753eadf9 | ||
|
|
932de847b6 | ||
|
|
b7ab16477a | ||
|
|
72bd441617 | ||
|
|
c7908c38ed | ||
|
|
ad786e892f | ||
|
|
744c721950 | ||
|
|
7c2f10423f | ||
|
|
9c666ba4d9 | ||
|
|
c62a163f93 | ||
|
|
9ad2d0f7e1 | ||
|
|
907022b31d | ||
|
|
2cbb4dcfb6 | ||
|
|
8cdf8c68e8 | ||
|
|
10ebf47612 | ||
|
|
3a69e7bf69 | ||
|
|
69c975bfc5 | ||
|
|
9d8d2cf8cc | ||
|
|
9356ccc497 | ||
|
|
3e702f0186 | ||
|
|
b0110ca542 | ||
|
|
ecf5f6f843 | ||
|
|
d90bd9dd8e | ||
|
|
d794e3fcd2 | ||
|
|
e519cf89cd | ||
|
|
15ebf4a756 | ||
|
|
7a6a38aa1d | ||
|
|
0971fb48e4 | ||
|
|
41f012e0b4 | ||
|
|
dba79c83c4 | ||
|
|
f2e48cb977 | ||
|
|
8b3dd37c33 | ||
|
|
549ab31e82 | ||
|
|
3bedaa076c | ||
|
|
518628ec8c | ||
|
|
14518c7f9f | ||
|
|
354137d101 | ||
|
|
cb2ec53062 | ||
|
|
d806d1cf81 | ||
|
|
b640290962 | ||
|
|
447e5a7d82 | ||
|
|
3bc6bb2900 | ||
|
|
9a55c50563 | ||
|
|
a88c3e7f6d | ||
|
|
9c63ea19d3 | ||
|
|
38f0f5eb78 | ||
|
|
53f85a6b8e | ||
|
|
5b7cdcff37 | ||
|
|
30bc6ff801 | ||
|
|
f4574647dd | ||
|
|
1b2fada686 | ||
|
|
db55e148c3 | ||
|
|
2ceb626723 | ||
|
|
90a2f719ef | ||
|
|
4883570131 | ||
|
|
110d8b6982 | ||
|
|
6d29f236fd | ||
|
|
dd784fa245 | ||
|
|
7d0ea7967c | ||
|
|
111a42c2da | ||
|
|
f66d74499f | ||
|
|
ea195e6c75 | ||
|
|
f74828e3ea | ||
|
|
3ef6312f65 | ||
|
|
9701eb1986 | ||
|
|
dbb427e70e | ||
|
|
91ad3f0f05 | ||
|
|
2c760935af | ||
|
|
607968983b | ||
|
|
e1f8611ef3 | ||
|
|
0a154e4314 | ||
|
|
25d593710e | ||
|
|
9f2ce9dd14 | ||
|
|
7fdf51be31 | ||
|
|
ccc0684312 | ||
|
|
140349e4d8 | ||
|
|
540d7cf82c | ||
|
|
f745388f37 | ||
|
|
ad0e2f43c4 | ||
|
|
12d9934889 | ||
|
|
32553d0042 | ||
|
|
823e9ad208 | ||
|
|
f5c54ce9d0 | ||
|
|
b24182c5b6 | ||
|
|
91f400be09 | ||
|
|
4c7dc09979 | ||
|
|
15c0400805 | ||
|
|
b3bc3c923d | ||
|
|
623dca3cbf | ||
|
|
490b203943 | ||
|
|
a41d5bc3ce | ||
|
|
55d1f66d0e | ||
|
|
2617170314 | ||
|
|
f436a651cf | ||
|
|
0eedae22c6 | ||
|
|
26930e6a84 | ||
|
|
b26164e05c | ||
|
|
fcaf342d2a | ||
|
|
b5d814860e | ||
|
|
ad6a8f28eb | ||
|
|
5252ed95cd | ||
|
|
a068c534bb | ||
|
|
c67d51b303 | ||
|
|
91886211ae | ||
|
|
473b97fd7e | ||
|
|
92c89b0756 | ||
|
|
abe79d1c48 | ||
|
|
81e923def2 | ||
|
|
fb9e05b5b9 | ||
|
|
96796ebe05 | ||
|
|
72eef666eb | ||
|
|
03f4a1438c | ||
|
|
8d64f799d1 | ||
|
|
725314e497 | ||
|
|
45f3294249 | ||
|
|
7ed3a38cb2 | ||
|
|
ab464db930 | ||
|
|
704667e71e | ||
|
|
badaa404a4 | ||
|
|
0fb70e97aa | ||
|
|
1a38600aeb | ||
|
|
c3a55088ed | ||
|
|
5c3716dfe1 | ||
|
|
fec06bbb59 | ||
|
|
9b4c770382 | ||
|
|
2d7f151543 | ||
|
|
8c9c30b604 | ||
|
|
cfc24eeeee | ||
|
|
fdbc003ac7 | ||
|
|
44fcf386ee | ||
|
|
a1e4829455 | ||
|
|
0bac95c085 | ||
|
|
9f331306af | ||
|
|
613d6d688d | ||
|
|
152e94b116 | ||
|
|
60e9caf2e7 | ||
|
|
214aafd243 | ||
|
|
b140aa2abf | ||
|
|
da2c22329c | ||
|
|
83bca9318d | ||
|
|
32e2ecea37 | ||
|
|
27fc5070ec | ||
|
|
d3080b90a7 | ||
|
|
dddc24dc02 | ||
|
|
6c073b7d4d | ||
|
|
2114ce5da5 | ||
|
|
27abfa0880 | ||
|
|
340bd0857d | ||
|
|
13f9a51bff | ||
|
|
d4b979979a | ||
|
|
6aadd49592 | ||
|
|
b2ce56755f | ||
|
|
7070f7f1ec | ||
|
|
6d50815196 | ||
|
|
99f3bc3778 | ||
|
|
e081876473 | ||
|
|
1fbd4281ba | ||
|
|
45593e94fc | ||
|
|
f967e0007b | ||
|
|
3e5af98552 | ||
|
|
d365286bdf | ||
|
|
63d06b285a | ||
|
|
d67e82926a | ||
|
|
e11a62dd90 | ||
|
|
9a787e88b3 | ||
|
|
f086cb9d29 | ||
|
|
0b3c1ff510 | ||
|
|
8cd265cae3 | ||
|
|
a5507fadfc | ||
|
|
7713a1178f | ||
|
|
ea41ed7663 | ||
|
|
1f04ef8b92 | ||
|
|
165d042a6b | ||
|
|
44b3e74398 | ||
|
|
215cb70cea | ||
|
|
d9f8da2b9e | ||
|
|
58203941df | ||
|
|
f717761aa2 | ||
|
|
2ea24123da | ||
|
|
e67d9a6a3a | ||
|
|
9fdfaf9d49 | ||
|
|
154104e5a8 | ||
|
|
9f1c82aeca | ||
|
|
8eb87d249b | ||
|
|
9a3fa8dbe0 | ||
|
|
cdfbc427d1 | ||
|
|
beed014aca | ||
|
|
6347327b58 | ||
|
|
c52a8e901f | ||
|
|
db8f78e5cf | ||
|
|
54efe13723 | ||
|
|
2a5f3c460e | ||
|
|
9a678154c9 | ||
|
|
4e8f9bbf97 | ||
|
|
4e40393b14 | ||
|
|
5c95d9bd88 | ||
|
|
a6480df8c5 | ||
|
|
db690e77ea | ||
|
|
b2a7741fd3 | ||
|
|
053911edca | ||
|
|
1ff2416435 | ||
|
|
219ec0e671 | ||
|
|
fe46134a43 | ||
|
|
43ce9daf2e | ||
|
|
4842386aac | ||
|
|
f20145d06a | ||
|
|
f986bf05fd | ||
|
|
21f657616b | ||
|
|
ac91927ea1 | ||
|
|
74d8f0c23d | ||
|
|
ddb802b31a | ||
|
|
979c33a457 | ||
|
|
681be2ec9e | ||
|
|
b217a504e6 | ||
|
|
2f8e57ae28 | ||
|
|
4373d5ff4b | ||
|
|
3526e98a00 | ||
|
|
6bd38857d1 | ||
|
|
2abab0caaa | ||
|
|
de76a64f7e | ||
|
|
604dab1bb9 | ||
|
|
1bfa265278 | ||
|
|
7e868f3faa | ||
|
|
7e19809cff | ||
|
|
f5d86f7bc8 | ||
|
|
db89d01739 | ||
|
|
0bae792e79 | ||
|
|
2a311b8cb8 | ||
|
|
ae0bd93403 | ||
|
|
36929e5f48 | ||
|
|
413f8ca0fd | ||
|
|
0d1f1961af | ||
|
|
749dd367fa | ||
|
|
5849a2fecd | ||
|
|
343e92439c | ||
|
|
82c8243978 | ||
|
|
35d13bfc53 | ||
|
|
af975d3055 | ||
|
|
aeb64790d0 | ||
|
|
8d23f49c05 | ||
|
|
496a2ad710 | ||
|
|
7af3778761 | ||
|
|
0035b197c2 | ||
|
|
522e5299f1 | ||
|
|
13d28af70d | ||
|
|
7e8cad4fcc | ||
|
|
4c04109ba4 | ||
|
|
5341c120cc | ||
|
|
215e5a7b90 | ||
|
|
9e6c8b28ba | ||
|
|
e6761de367 | ||
|
|
18d24ebfdd | ||
|
|
c7d66ac1ab | ||
|
|
9039f26eab | ||
|
|
a91d3f79c3 | ||
|
|
587403d009 | ||
|
|
30585ec690 | ||
|
|
1b591a83ca | ||
|
|
189c3062f0 | ||
|
|
37b8bb1ce4 | ||
|
|
de89795eed | ||
|
|
a8b122e1c4 | ||
|
|
eba9a4bce5 | ||
|
|
14e6acad4d | ||
|
|
b2b073a2d7 | ||
|
|
59a5181e80 | ||
|
|
b800a639a2 | ||
|
|
4852a84ab8 | ||
|
|
2a9882e7af | ||
|
|
6c3b3749b1 | ||
|
|
eae6766995 | ||
|
|
67b49d9917 | ||
|
|
b8f0db3e69 | ||
|
|
55fe513c50 | ||
|
|
1653ac5453 | ||
|
|
6889fdf8a1 | ||
|
|
5f1fc280bb | ||
|
|
76b510fabc | ||
|
|
706c29231c | ||
|
|
4048a8cdc4 | ||
|
|
703757dc1f | ||
|
|
924e4011ee | ||
|
|
cbfebd6fdb | ||
|
|
6c8f51b311 | ||
|
|
484baa832d | ||
|
|
c89ca60777 | ||
|
|
aeb0c2f5e7 | ||
|
|
6a0d9043a2 | ||
|
|
b54b69d48f | ||
|
|
5052b233dd | ||
|
|
7f1c5a9b7e | ||
|
|
f17ca54c77 | ||
|
|
a33c3a1a21 | ||
|
|
7c515b6273 | ||
|
|
e7dbeaea52 | ||
|
|
46b08d22ac | ||
|
|
eef739806e | ||
|
|
4eb3bdbb5c | ||
|
|
ee6915dd47 | ||
|
|
45c23df381 | ||
|
|
79a700f9b3 | ||
|
|
0074a23631 | ||
|
|
7cd8d59fba | ||
|
|
188730318e | ||
|
|
044f2addbe | ||
|
|
f0715c53c4 | ||
|
|
46e3a86c81 | ||
|
|
06808dde92 | ||
|
|
cffd57797b | ||
|
|
1b918f3655 | ||
|
|
9f4e25be09 | ||
|
|
d552909adf | ||
|
|
81ae120a11 | ||
|
|
28d820e5ad | ||
|
|
d32796ce8f | ||
|
|
527424db79 | ||
|
|
762419f037 | ||
|
|
7c09ab2ea2 | ||
|
|
14bacaeba5 | ||
|
|
fe08942e39 | ||
|
|
bc4dd21316 | ||
|
|
0c5a496ba2 | ||
|
|
0a626f39ae | ||
|
|
e9806b73c6 | ||
|
|
2b522f5702 | ||
|
|
082c133128 | ||
|
|
c33ef19086 | ||
|
|
6f07d50d90 | ||
|
|
037e4d4214 | ||
|
|
53b1ff6ed4 | ||
|
|
2847f14dc7 | ||
|
|
4fb4ed9ca4 | ||
|
|
98bc291b54 | ||
|
|
532b9cb53c | ||
|
|
5075221428 | ||
|
|
3ee3edb8ce | ||
|
|
f3085a163f | ||
|
|
7b04e578af | ||
|
|
9daeeca997 | ||
|
|
0c5366420f | ||
|
|
f388d0d10f | ||
|
|
e588686d5f | ||
|
|
2e6e1c07bf | ||
|
|
a98dbc0b1c | ||
|
|
529b585d07 | ||
|
|
46d177fb9f | ||
|
|
24abaec406 | ||
|
|
673afbac0f | ||
|
|
5dc05f3c81 | ||
|
|
dce0604e7d |
3
account_aged_balance_from_partner/__init__.py
Normal file
3
account_aged_balance_from_partner/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import partner
|
||||
25
account_aged_balance_from_partner/__manifest__.py
Normal file
25
account_aged_balance_from_partner/__manifest__.py
Normal file
@@ -0,0 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2015-2018 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
'name': 'Aged Partner Balance from Partner',
|
||||
'version': '10.0.0.1.0',
|
||||
'category': 'Accounting',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Direct access to the aged partner balance report from the partner form',
|
||||
'description': """
|
||||
Aged Partner Balance from Partner
|
||||
=================================
|
||||
|
||||
This module adds a button on the partner form view (the icon on the button is a banknote) to easily open the detailed aged partner balance of the partner in PDF format.
|
||||
|
||||
This module has been written by Alexis de Lattre from Akretion <alexis.delattre@akretion.com>.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['account_financial_report_qweb'],
|
||||
'data': ['partner_view.xml'],
|
||||
'installable': True,
|
||||
}
|
||||
30
account_aged_balance_from_partner/partner.py
Normal file
30
account_aged_balance_from_partner/partner.py
Normal file
@@ -0,0 +1,30 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2015-2018 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
|
||||
from odoo import models, fields, api
|
||||
|
||||
|
||||
class ResPartner(models.Model):
|
||||
_inherit = 'res.partner'
|
||||
|
||||
@api.depends('credit', 'debit')
|
||||
def _compute_balance(self):
|
||||
for partner in self:
|
||||
partner.balance = partner.credit - partner.debit
|
||||
|
||||
# The field 'currency_id' defined in the account module
|
||||
# is a computed field that gets the company currency
|
||||
balance = fields.Monetary(
|
||||
compute='_compute_balance', readonly=True,
|
||||
string="Account Balance")
|
||||
|
||||
def open_aged_open_invoices_report(self):
|
||||
wiz = self.env['aged.partner.balance.wizard'].create({
|
||||
'show_move_line_details': True,
|
||||
'partner_ids': [(6, 0, self.ids)],
|
||||
})
|
||||
action = wiz.button_export_pdf()
|
||||
return action
|
||||
31
account_aged_balance_from_partner/partner_view.xml
Normal file
31
account_aged_balance_from_partner/partner_view.xml
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2015-2018 Akretion (http://www.akretion.com/)
|
||||
@author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
|
||||
<record id="view_partner_form" model="ir.ui.view">
|
||||
<field name="name">account.balance.button.partner.form</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="inherit_id" ref="account.partner_view_buttons"/>
|
||||
<field name="arch" type="xml">
|
||||
<button name="open_partner_history" type="object" position="after">
|
||||
<button class="oe_stat_button" type="object"
|
||||
name="open_aged_open_invoices_report"
|
||||
attrs="{'invisible': [('parent_id', '!=', False)]}"
|
||||
icon="fa-money">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<span class="o_stat_value"><field name="balance"/></span>
|
||||
<span class="o_stat_text">Account Balance</span>
|
||||
</div>
|
||||
</button>
|
||||
</button>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</odoo>
|
||||
@@ -1,27 +0,0 @@
|
||||
===============================
|
||||
Bank Reconciliation Report XLSX
|
||||
===============================
|
||||
|
||||
In Odoo v13+, a bank reconciliation report is not really needed because all the payments executed that are not debited/credited on the bank account are in separate waiting accounts. But accountants want a bank reconciliation report, so this module adds one, even if it is quite different from a classic bank reconciliation report.
|
||||
|
||||
Configuration
|
||||
=============
|
||||
|
||||
This module doesn't require any configuration.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
You can launch the Bank Reconciliation Report wizard from:
|
||||
|
||||
* the menu *Accounting > Reports > Bank > Bank Reconciliation*,
|
||||
* the invoicing dashboard: on a bank journal, click on the options, then select *Bank Reconciliation*.
|
||||
* the form view of a bank statement: click on the button *Bank Reconciliation Report*.
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
||||
* Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
@@ -1,2 +0,0 @@
|
||||
from . import report
|
||||
from . import wizard
|
||||
@@ -1,21 +0,0 @@
|
||||
# Copyright 2017-2024 Akretion France (http://www.akretion.com/)
|
||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
"name": "Bank Reconciliation Report",
|
||||
"version": "14.0.2.0.0",
|
||||
"license": "AGPL-3",
|
||||
"author": "Akretion",
|
||||
"website": "https://github.com/akretion/odoo-usability",
|
||||
"summary": "Bank reconciliation XLSX report",
|
||||
"depends": ["account", "report_xlsx"],
|
||||
"data": [
|
||||
"report/report.xml",
|
||||
"wizard/bank_reconciliation_report_wizard_view.xml",
|
||||
"views/account_bank_statement.xml",
|
||||
"views/account_journal.xml",
|
||||
"security/ir.model.access.csv",
|
||||
],
|
||||
"installable": True,
|
||||
}
|
||||
@@ -1,268 +0,0 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * account_bank_reconciliation_summary_xlsx
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 14.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-10-23 10:04+0000\n"
|
||||
"PO-Revision-Date: 2024-10-23 10:04+0000\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: \n"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||
#, python-format
|
||||
msgid "Amount"
|
||||
msgstr "Montant"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||
#, python-format
|
||||
msgid "Balance %s:"
|
||||
msgstr "Solde %s :"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||
#, python-format
|
||||
msgid "Bank Balance:"
|
||||
msgstr "Solde bancaire :"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: model:ir.model.fields,field_description:account_bank_reconciliation_summary_xlsx.field_bank_reconciliation_report_wizard__journal_ids
|
||||
msgid "Bank Journals"
|
||||
msgstr "Journaux de banque"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: model:ir.actions.act_window,name:account_bank_reconciliation_summary_xlsx.bank_reconciliation_report_wizard_action
|
||||
#: model:ir.ui.menu,name:account_bank_reconciliation_summary_xlsx.bank_reconciliation_report_wizard_menu
|
||||
#: model_terms:ir.ui.view,arch_db:account_bank_reconciliation_summary_xlsx.account_journal_dashboard_kanban_view
|
||||
msgid "Bank Reconciliation"
|
||||
msgstr "Rapprochement bancaire"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||
#: model_terms:ir.ui.view,arch_db:account_bank_reconciliation_summary_xlsx.view_bank_statement_form
|
||||
#, python-format
|
||||
msgid "Bank Reconciliation Report"
|
||||
msgstr "Rapport de rapprochement bancaire"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: model:ir.model,name:account_bank_reconciliation_summary_xlsx.model_bank_reconciliation_report_wizard
|
||||
msgid "Bank Reconciliation Report Wizard"
|
||||
msgstr "Assistant de rapport de rapprochement bancaire"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: model:ir.actions.report,name:account_bank_reconciliation_summary_xlsx.bank_reconciliation_xlsx
|
||||
msgid "Bank Reconciliation XLSX"
|
||||
msgstr "Rapprochement bancaire XLSX"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: model:ir.model,name:account_bank_reconciliation_summary_xlsx.model_report_bank_reconciliation_xlsx
|
||||
msgid "Bank Reconciliation XLSX Report"
|
||||
msgstr "Rapport de rapprochement bancaire XLSX"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: model:ir.ui.menu,name:account_bank_reconciliation_summary_xlsx.menu_report_bank_root
|
||||
msgid "Bank Reports"
|
||||
msgstr "Rapports bancaires"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: model_terms:ir.ui.view,arch_db:account_bank_reconciliation_summary_xlsx.bank_reconciliation_report_wizard_form
|
||||
msgid "Cancel"
|
||||
msgstr "Annuler"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||
#: model:ir.model.fields,field_description:account_bank_reconciliation_summary_xlsx.field_bank_reconciliation_report_wizard__company_id
|
||||
#, python-format
|
||||
msgid "Company"
|
||||
msgstr "Société"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||
#, python-format
|
||||
msgid "Counter-part"
|
||||
msgstr "Contre partie"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: model:ir.model.fields,field_description:account_bank_reconciliation_summary_xlsx.field_bank_reconciliation_report_wizard__create_uid
|
||||
msgid "Created by"
|
||||
msgstr "Créé par"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: model:ir.model.fields,field_description:account_bank_reconciliation_summary_xlsx.field_bank_reconciliation_report_wizard__create_date
|
||||
msgid "Created on"
|
||||
msgstr "Créé le"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||
#, python-format
|
||||
msgid "Currency"
|
||||
msgstr "Devise"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||
#: model:ir.model.fields,field_description:account_bank_reconciliation_summary_xlsx.field_bank_reconciliation_report_wizard__date
|
||||
#, python-format
|
||||
msgid "Date"
|
||||
msgstr "Date"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||
#, python-format
|
||||
msgid "Description"
|
||||
msgstr "Description"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||
#, python-format
|
||||
msgid "Difference:"
|
||||
msgstr "Écart :"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: model:ir.model.fields,field_description:account_bank_reconciliation_summary_xlsx.field_bank_reconciliation_report_wizard__display_name
|
||||
#: model:ir.model.fields,field_description:account_bank_reconciliation_summary_xlsx.field_report_bank_reconciliation_xlsx__display_name
|
||||
msgid "Display Name"
|
||||
msgstr "Nom affiché"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: model:ir.model.fields.selection,name:account_bank_reconciliation_summary_xlsx.selection__bank_reconciliation_report_wizard__move_state__draft_posted
|
||||
msgid "Draft and Posted Entries"
|
||||
msgstr "Écritures brouillon et comptabilisées"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||
#: model:ir.model.fields,field_description:account_bank_reconciliation_summary_xlsx.field_bank_reconciliation_report_wizard__move_state
|
||||
#, python-format
|
||||
msgid "Entries"
|
||||
msgstr "Écritures"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: model_terms:ir.ui.view,arch_db:account_bank_reconciliation_summary_xlsx.bank_reconciliation_report_wizard_form
|
||||
msgid "Export XLSX"
|
||||
msgstr "Exporter en XLSX"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||
#, python-format
|
||||
msgid "Generated from Odoo on %s by %s"
|
||||
msgstr "Généré par Odoo le %s par %s"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: model:ir.model.fields,field_description:account_bank_reconciliation_summary_xlsx.field_bank_reconciliation_report_wizard__id
|
||||
#: model:ir.model.fields,field_description:account_bank_reconciliation_summary_xlsx.field_report_bank_reconciliation_xlsx__id
|
||||
msgid "ID"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||
#, python-format
|
||||
msgid "Journal"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||
#, python-format
|
||||
msgid "Journal Entry"
|
||||
msgstr "Pièce"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||
#, python-format
|
||||
msgid "Justification:"
|
||||
msgstr "Justification :"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||
#, python-format
|
||||
msgid "Label"
|
||||
msgstr "Libellé"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: model:ir.model.fields,field_description:account_bank_reconciliation_summary_xlsx.field_bank_reconciliation_report_wizard____last_update
|
||||
#: model:ir.model.fields,field_description:account_bank_reconciliation_summary_xlsx.field_report_bank_reconciliation_xlsx____last_update
|
||||
msgid "Last Modified on"
|
||||
msgstr "Dernière modification le"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: model:ir.model.fields,field_description:account_bank_reconciliation_summary_xlsx.field_bank_reconciliation_report_wizard__write_uid
|
||||
msgid "Last Updated by"
|
||||
msgstr "Dernière mise à jour par"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: model:ir.model.fields,field_description:account_bank_reconciliation_summary_xlsx.field_bank_reconciliation_report_wizard__write_date
|
||||
msgid "Last Updated on"
|
||||
msgstr "Dernière mise à jour le"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||
#, python-format
|
||||
msgid "No bank journal selected."
|
||||
msgstr "Aucun journal de banque sélectionné."
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||
#, python-format
|
||||
msgid "None"
|
||||
msgstr "Aucun"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"On bank journal %(journal)s which is configured with currency "
|
||||
"%(journal_currency)s, the account %(account)s must be configured with the "
|
||||
"same currency (current account currency: %(account_currency)s)."
|
||||
msgstr ""
|
||||
"Sur le journal de banque %(journal)s qui est configuré avec la devise "
|
||||
"%(journal_currency)s, le compte %(account)s doit être configuré avec la même"
|
||||
" devise (devise actuelle du compte : %(account_currency)s)."
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||
#, python-format
|
||||
msgid "Partner"
|
||||
msgstr "Partenaire"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: model:ir.model.fields.selection,name:account_bank_reconciliation_summary_xlsx.selection__bank_reconciliation_report_wizard__move_state__posted
|
||||
msgid "Posted Entries"
|
||||
msgstr "Écritures comptabilisées"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||
#, python-format
|
||||
msgid "Ref."
|
||||
msgstr "Réf."
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||
#, python-format
|
||||
msgid "Sub-total:"
|
||||
msgstr "Sous-total :"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||
#, python-format
|
||||
msgid "TOTAL:"
|
||||
msgstr "TOTAL :"
|
||||
|
||||
#. module: account_bank_reconciliation_summary_xlsx
|
||||
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The are %(count)s journal items in account %(account)s that have a currency "
|
||||
"other than %(currency)s or where currency is not set."
|
||||
msgstr ""
|
||||
"Il y a %(count)s écritures comptables dans le compte %(account)s qui ont une"
|
||||
" devise autre que %(currency)s ou dont la devise n'est pas définie."
|
||||
@@ -1 +0,0 @@
|
||||
from . import bank_reconciliation_xlsx
|
||||
@@ -1,375 +0,0 @@
|
||||
# Copyright 2017-2024 Akretion France (http://www.akretion.com/)
|
||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import _, models
|
||||
from odoo.exceptions import UserError
|
||||
from datetime import datetime
|
||||
from odoo.tools.misc import format_datetime
|
||||
import pytz
|
||||
|
||||
|
||||
class BankReconciliationXlsx(models.AbstractModel):
|
||||
_name = "report.bank.reconciliation.xlsx"
|
||||
_description = "Bank Reconciliation XLSX Report"
|
||||
_inherit = "report.report_xlsx.abstract"
|
||||
|
||||
def _prepare_payment_move_lines(self, jdi, account, unreconciled_only=True):
|
||||
domain = [
|
||||
("company_id", "=", jdi['company'].id),
|
||||
("account_id", "=", account.id),
|
||||
("journal_id", "=", jdi['journal'].id),
|
||||
("date", "<=", jdi['wizard'].date),
|
||||
]
|
||||
if jdi['wizard'].move_state == 'posted':
|
||||
domain.append(('parent_state', '=', 'posted'))
|
||||
elif jdi['wizard'].move_state == 'draft_posted':
|
||||
domain.append(('parent_state', 'in', ('draft', 'posted')))
|
||||
if unreconciled_only:
|
||||
limit_datetime_naive = datetime.combine(jdi['wizard'].date, datetime.max.time())
|
||||
tz = pytz.timezone(self.env.user.tz)
|
||||
limit_datetime_aware = tz.localize(limit_datetime_naive)
|
||||
limit_datetime_utc = limit_datetime_aware.astimezone(pytz.utc)
|
||||
limit_datetime = limit_datetime_utc.replace(tzinfo=None)
|
||||
domain += [
|
||||
'|', ('full_reconcile_id', '=', False),
|
||||
('full_reconcile_id.create_date', '>', limit_datetime)]
|
||||
mlines = self.env["account.move.line"].search(domain)
|
||||
res = []
|
||||
for mline in mlines:
|
||||
move = mline.move_id
|
||||
cpart = []
|
||||
for line in move.line_ids:
|
||||
if (
|
||||
line.account_id != account
|
||||
and line.account_id.code not in cpart
|
||||
):
|
||||
cpart.append(line.account_id.code)
|
||||
counterpart = " ,".join(cpart)
|
||||
if jdi['currency'] == mline.currency_id:
|
||||
amount = mline.amount_currency
|
||||
else:
|
||||
amount = mline.currency_id._convert(
|
||||
mline.amount_currency, jdi['currency'], jdi['company'], mline.date)
|
||||
res.append(
|
||||
{
|
||||
"date": mline.date,
|
||||
"ref": move.ref or "",
|
||||
"label": mline.name,
|
||||
"partner": mline.partner_id.display_name or "",
|
||||
"amount": amount,
|
||||
"move_name": move.name,
|
||||
"counterpart": counterpart,
|
||||
}
|
||||
)
|
||||
return res
|
||||
|
||||
def _write_move_lines_block(self, jdi, row, account, add2total=True):
|
||||
# Returns row
|
||||
# For suspense lines, it may not add any cells if there are no suspense lines
|
||||
# => in this case, it doesn't increment row
|
||||
# If it adds cells, it returns row + 2 to add 2 empty rows at the end
|
||||
sheet = jdi['sheet']
|
||||
style = jdi['style']
|
||||
style_suffix = not add2total and '_warn' or ''
|
||||
subtotal = 0.0
|
||||
mlines = self._prepare_payment_move_lines(jdi, account)
|
||||
if mlines or add2total:
|
||||
sheet.write(row, 0, '%s %s' % (account.name, account.code), style[f"title{style_suffix}"])
|
||||
sheet.write(row, 1, "", style[f"title{style_suffix}"])
|
||||
|
||||
if not mlines:
|
||||
if add2total:
|
||||
sheet.write(row, 2, _("None"), style['none'])
|
||||
else:
|
||||
return row
|
||||
else:
|
||||
row += 1
|
||||
col_labels = [
|
||||
_("Date"),
|
||||
_("Partner"),
|
||||
_("Amount"),
|
||||
_("Journal Entry"),
|
||||
_("Counter-part"),
|
||||
_("Ref."),
|
||||
_("Label"),
|
||||
]
|
||||
col = 0
|
||||
for col_label in col_labels:
|
||||
sheet.write(row, col, col_label, style['col_header'])
|
||||
col += 1
|
||||
row += 1
|
||||
start_line = row + 1
|
||||
for mline in mlines:
|
||||
sheet.write(row, 0, mline["date"], style['regular_date'])
|
||||
sheet.write(row, 1, mline["partner"], style['regular'])
|
||||
sheet.write(row, 2, mline["amount"], style[jdi['currency']])
|
||||
sheet.write(row, 3, mline["move_name"], style['regular'])
|
||||
sheet.write(row, 4, mline["counterpart"], style['regular'])
|
||||
sheet.write(row, 5, mline["ref"], style['regular'])
|
||||
sheet.write(row, 6, mline["label"], style['regular'])
|
||||
subtotal += mline["amount"]
|
||||
row += 1
|
||||
end_line = row
|
||||
|
||||
for col in range(1):
|
||||
sheet.write(row, col, "", style[f"title{style_suffix}"])
|
||||
sheet.write(row, 1, _("Sub-total:") + ' ', style[f"title_right{style_suffix}"])
|
||||
|
||||
formula = f"=SUM({jdi['total_col']}{start_line}:{jdi['total_col']}{end_line})"
|
||||
sheet.write_formula(row, 2, formula, style[f"{jdi['currency']}_bg{style_suffix}"], subtotal)
|
||||
if add2total:
|
||||
jdi['total'] += subtotal
|
||||
jdi['total_formula'] += f"+{jdi['total_col']}{row + 1}"
|
||||
return row + 2
|
||||
|
||||
def generate_xlsx_report(self, workbook, data, wizard):
|
||||
lang = self.env.user.lang
|
||||
self = self.with_context(lang=lang)
|
||||
wizard = wizard.with_context(lang=lang)
|
||||
if not wizard.journal_ids:
|
||||
raise UserError(_("No bank journal selected."))
|
||||
date_dt = wizard.date
|
||||
company = wizard.company_id
|
||||
style = self._get_style(workbook, company)
|
||||
move_state_label = dict(
|
||||
wizard.fields_get('move_state', 'selection')['move_state']['selection'])
|
||||
generated_on_label = _('Generated from Odoo on %s by %s') % (
|
||||
format_datetime(self.env, datetime.utcnow()),
|
||||
self.env.user.name)
|
||||
for journal in wizard.journal_ids:
|
||||
row = 0
|
||||
sheet = workbook.add_worksheet(journal.code or journal.name)
|
||||
bank_account = journal.default_account_id
|
||||
jdi = {
|
||||
'wizard': wizard,
|
||||
'company': company,
|
||||
'journal': journal,
|
||||
'currency': journal.currency_id or company.currency_id,
|
||||
'bank_account': bank_account,
|
||||
'style': style,
|
||||
'workbook': workbook,
|
||||
'sheet': sheet,
|
||||
'total': 0.0,
|
||||
'total_formula': '=',
|
||||
'total_col': 'C',
|
||||
}
|
||||
sheet.write(
|
||||
row,
|
||||
0,
|
||||
_("Bank Reconciliation Report"),
|
||||
style['doc_title'],
|
||||
)
|
||||
row += 1
|
||||
sheet.write(row, 0, generated_on_label, style['small'])
|
||||
sheet.set_row(0, 26)
|
||||
sheet.set_column(0, 0, 10)
|
||||
sheet.set_column(1, 1, 35)
|
||||
sheet.set_column(2, 2, 15)
|
||||
sheet.set_column(3, 3, 15)
|
||||
sheet.set_column(4, 4, 25)
|
||||
sheet.set_column(5, 5, 30)
|
||||
sheet.set_column(6, 6, 60)
|
||||
row += 3
|
||||
sheet.write(row, 0, _("Company"), style['wizard_field'])
|
||||
sheet.write(row, 1, company.display_name, style['wizard_value'])
|
||||
row += 1
|
||||
sheet.write(row, 0, _("Date"), style['wizard_field'])
|
||||
sheet.write(row, 1, date_dt, style['wizard_value_date'])
|
||||
row += 1
|
||||
sheet.write(row, 0, _("Journal"), style['wizard_field'])
|
||||
sheet.write(row, 1, journal.display_name, style['wizard_value'])
|
||||
row += 1
|
||||
sheet.write(row, 0, _("Currency"), style['wizard_field'])
|
||||
sheet.write(row, 1, jdi['currency'].name, style['wizard_value'])
|
||||
row += 1
|
||||
sheet.write(row, 0, _("Entries"), style['wizard_field'])
|
||||
sheet.write(row, 1, move_state_label[wizard.move_state], style['wizard_value'])
|
||||
|
||||
# Setup check
|
||||
if journal.currency_id and journal.currency_id != company.currency_id:
|
||||
if journal.currency_id != bank_account.currency_id:
|
||||
raise UserError(_(
|
||||
"On bank journal %(journal)s which is configured with currency "
|
||||
"%(journal_currency)s, the account %(account)s must be configured "
|
||||
"with the same currency (current account currency: %(account_currency)s).",
|
||||
journal=journal.display_name,
|
||||
journal_currency=journal.currency_id.name,
|
||||
account=bank_account.display_name,
|
||||
account_currency=bank_account.currency_id.name or _('None')))
|
||||
bad_line_count = self.env['account.move.line'].search_count([
|
||||
('company_id', '=', company.id),
|
||||
('journal_id', '=', journal.id),
|
||||
('account_id', '=', bank_account.id),
|
||||
('currency_id', '!=', jdi['currency'].id),
|
||||
])
|
||||
if bad_line_count:
|
||||
raise UserError(_(
|
||||
"The are %(count)s journal items in account %(account)s "
|
||||
"that have a currency other than %(currency)s or where "
|
||||
"currency is not set.",
|
||||
count=bad_line_count,
|
||||
account=bank_account.display_name,
|
||||
currency=jdi['currency'].name))
|
||||
|
||||
# 1) Show balance of bank account
|
||||
row += 3
|
||||
for col in range(1):
|
||||
sheet.write(row, col, "", style['title'])
|
||||
sheet.write(row, 1, _("Balance %s:") % bank_account.code + ' ', style['title_right'])
|
||||
if wizard.move_state == 'posted':
|
||||
domain = [('parent_state', '=', 'posted')]
|
||||
else:
|
||||
# by default, the native method _get_journal_bank_account_balance()
|
||||
# has ('parent_state', '!=', 'cancel')
|
||||
domain = None
|
||||
account_bal, nb_lines = journal._get_journal_bank_account_balance(domain=domain)
|
||||
|
||||
sheet.write(row, 2, account_bal, style[f"{jdi['currency']}_bg"])
|
||||
jdi['total'] += account_bal
|
||||
jdi['total_formula'] += f"{jdi['total_col']}{row + 1}"
|
||||
|
||||
row += 2
|
||||
# 2) Show payment lines IN (debit)
|
||||
debit_account = journal.payment_debit_account_id
|
||||
row = self._write_move_lines_block(jdi, row, debit_account)
|
||||
# 3) Show payment lines OUT (credit)
|
||||
credit_account = journal.payment_credit_account_id
|
||||
row = self._write_move_lines_block(jdi, row, credit_account)
|
||||
|
||||
for col in range(1):
|
||||
sheet.write(row, col, "", style['title'])
|
||||
sheet.write(row, 1, _("TOTAL:") + ' ', style['title_right'])
|
||||
sheet.write_formula(
|
||||
row, 2, jdi['total_formula'], style[f"{jdi['currency']}_bg"], jdi['total'])
|
||||
total_row = row
|
||||
row += 2
|
||||
|
||||
# 4) Show suspense account lines
|
||||
row = self._write_move_lines_block(
|
||||
jdi, row, journal.suspense_account_id, add2total=False)
|
||||
|
||||
# Static cells
|
||||
for col in range(1):
|
||||
sheet.write(row, col, "", style['title'])
|
||||
sheet.write(row, 1, _("Bank Balance:") + ' ', style['title_right'])
|
||||
sheet.write(row, 2, 0, style[f"{jdi['currency']}_bg_manual"])
|
||||
bank_bal_row = row
|
||||
row += 2
|
||||
for col in range(1):
|
||||
sheet.write(row, col, "", style['title'])
|
||||
sheet.write(row, 1, _("Difference:") + ' ', style['title_right'])
|
||||
sheet.write_formula(
|
||||
row, 2, f"={jdi['total_col']}{total_row + 1}-{jdi['total_col']}{bank_bal_row + 1}",
|
||||
style[f"{jdi['currency']}_bg"], jdi['total'])
|
||||
row += 2
|
||||
for col in range(1):
|
||||
sheet.write(row, col, "", style['title'])
|
||||
sheet.write(row, 1, _("Justification:") + ' ', style['title_right'])
|
||||
justif_lines = 6
|
||||
sheet.write_formula(
|
||||
row, 2, f"=SUM({jdi['total_col']}{row+3}:{jdi['total_col']}{row+3+justif_lines-1})",
|
||||
style[f"{jdi['currency']}_bg"], 0)
|
||||
row += 1
|
||||
col_labels = [
|
||||
_("Date"),
|
||||
_("Description"),
|
||||
_("Amount"),
|
||||
]
|
||||
col = 0
|
||||
for col_label in col_labels:
|
||||
sheet.write(row, col, col_label, style['col_header'])
|
||||
col += 1
|
||||
for x in range(justif_lines):
|
||||
row += 1
|
||||
sheet.write(row, 0, "", style['regular_date'])
|
||||
sheet.write(row, 1, "", style['regular'])
|
||||
sheet.write(row, 2, "", style[jdi['currency']])
|
||||
|
||||
def _get_style(self, workbook, company):
|
||||
style = {}
|
||||
font_size = 10
|
||||
light_grey = "#eeeeee"
|
||||
light_blue = "#e0edff"
|
||||
subtotal_orange = "#ffcc00"
|
||||
subtotal_warn = "#ffff99"
|
||||
amount_manual = "#ffeeab"
|
||||
title_warn = "#ff9999"
|
||||
lang_code = self.env.user.lang
|
||||
lang = False
|
||||
if lang_code:
|
||||
lang = self.env["res.lang"].search([("code", "=", lang_code)])
|
||||
if not lang:
|
||||
lang = self.env["res.lang"].search([], limit=1)
|
||||
xls_date_format = (
|
||||
lang.date_format.replace("%Y", "yyyy")
|
||||
.replace("%m", "mm")
|
||||
.replace("%d", "dd")
|
||||
.replace("%y", "yy")
|
||||
)
|
||||
|
||||
style['doc_title'] = workbook.add_format(
|
||||
{"bold": True, "font_size": font_size + 4})
|
||||
style['small'] = workbook.add_format({"font_size": font_size - 3})
|
||||
style['col_header'] = workbook.add_format(
|
||||
{
|
||||
"bold": True,
|
||||
"bg_color": light_grey,
|
||||
"text_wrap": True,
|
||||
"font_size": font_size,
|
||||
"align": "center",
|
||||
}
|
||||
)
|
||||
title_style = {
|
||||
"bold": True,
|
||||
"bg_color": light_blue,
|
||||
"font_size": font_size,
|
||||
"align": "left",
|
||||
}
|
||||
style['title_right'] = workbook.add_format(dict(title_style, align="right"))
|
||||
style['title'] = workbook.add_format(dict(title_style))
|
||||
style['wizard_field'] = workbook.add_format(dict(title_style, bg_color=light_grey))
|
||||
wizard_value_style = {
|
||||
"bg_color": light_blue,
|
||||
"bold": True,
|
||||
"font_size": font_size,
|
||||
"align": "left",
|
||||
}
|
||||
|
||||
style['wizard_value'] = workbook.add_format(wizard_value_style)
|
||||
style['wizard_value_date'] = workbook.add_format(
|
||||
dict(wizard_value_style, num_format=xls_date_format))
|
||||
style['none'] = workbook.add_format(
|
||||
{"bold": True, "font_size": font_size, "align": "right", "bg_color": subtotal_orange}
|
||||
)
|
||||
# WARN for suspense account
|
||||
style['title_warn'] = workbook.add_format(
|
||||
dict(title_style, align="left", bg_color=title_warn))
|
||||
style['title_right_warn'] = workbook.add_format(
|
||||
dict(title_style, align="right", bg_color=title_warn))
|
||||
style['regular'] = workbook.add_format({"font_size": font_size, "border": 1})
|
||||
if "%" in xls_date_format:
|
||||
# fallback
|
||||
xls_date_format = "yyyy-mm-dd"
|
||||
style['regular_date'] = workbook.add_format(
|
||||
{"num_format": xls_date_format, "font_size": font_size, "align": "left", "border": 1}
|
||||
)
|
||||
for currency in self.env['res.currency'].search([]):
|
||||
symbol = currency.symbol or currency.name
|
||||
decimals = '0' * currency.decimal_places
|
||||
if currency.position == 'before':
|
||||
cur_format = f"{symbol} #,##0.{decimals}"
|
||||
else:
|
||||
cur_format = f"#,##0.{decimals} {symbol}"
|
||||
# It seems that Excel replaces automatically the decimal
|
||||
# and thousand separator by those of the language under which
|
||||
# Excel runs
|
||||
currency_style = {"num_format": cur_format, "font_size": font_size}
|
||||
style[currency] = workbook.add_format(dict(currency_style, border=1))
|
||||
style[f'{currency}_bg'] = workbook.add_format(
|
||||
dict(currency_style, bg_color=subtotal_orange))
|
||||
style[f'{currency}_bg_warn'] = workbook.add_format(
|
||||
dict(currency_style, bg_color=subtotal_warn))
|
||||
style[f'{currency}_bg_manual'] = workbook.add_format(
|
||||
dict(currency_style, bg_color=amount_manual))
|
||||
return style
|
||||
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!--
|
||||
Copyright 2017-2024 Akretion France (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
<odoo>
|
||||
|
||||
<record id="bank_reconciliation_xlsx" model="ir.actions.report">
|
||||
<field name="name">Bank Reconciliation XLSX</field>
|
||||
<field name="model">bank.reconciliation.report.wizard</field>
|
||||
<field name="report_type">xlsx</field>
|
||||
<field name="report_name">bank.reconciliation.xlsx</field>
|
||||
<field name="report_file">bank.reconciliation.xlsx</field>
|
||||
<field name="print_report_name">'bank_reconciliation-%s' % (object.date)</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -1,3 +0,0 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_bank_reconciliation_report_wizard_user,Full access on bank.reconciliation.report.wizard,model_bank_reconciliation_report_wizard,account.group_account_user,1,1,1,1
|
||||
access_bank_reconciliation_report_wizard_readonly,Full access on bank.reconciliation.report.wizard,model_bank_reconciliation_report_wizard,account.group_account_readonly,1,1,1,1
|
||||
|
Binary file not shown.
|
Before Width: | Height: | Size: 9.2 KiB |
@@ -1,23 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!--
|
||||
Copyright 2017-2024 Akretion France (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
<odoo>
|
||||
<record id="view_bank_statement_form" model="ir.ui.view">
|
||||
<field name="name">bank_rec_summary.account.bank.statement.form</field>
|
||||
<field name="model">account.bank.statement</field>
|
||||
<field name="inherit_id" ref="account.view_bank_statement_form" />
|
||||
<field name="arch" type="xml">
|
||||
<button name="button_reprocess" position="after">
|
||||
<button
|
||||
name="%(bank_reconciliation_report_wizard_action)d"
|
||||
type="action"
|
||||
string="Bank Reconciliation Report"
|
||||
context="{'default_journal_ids': [journal_id]}"
|
||||
/>
|
||||
</button>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -1,28 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!--
|
||||
Copyright 2018-2024 Akretion France (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
<odoo>
|
||||
<!-- Accounting Dashboard -->
|
||||
<record id="account_journal_dashboard_kanban_view" model="ir.ui.view">
|
||||
<field
|
||||
name="name"
|
||||
>bank_reconciliation_summary.account_journal_dashboard</field>
|
||||
<field name="model">account.journal</field>
|
||||
<field name="inherit_id" ref="account.account_journal_dashboard_kanban_view" />
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//a[@name='open_collect_money']/.." position="before">
|
||||
<div name="bank_reconciliation_report">
|
||||
<a
|
||||
role="menuitem"
|
||||
type="action"
|
||||
name="%(bank_reconciliation_report_wizard_action)d"
|
||||
context="{'default_journal_ids': [active_id]}"
|
||||
>Bank Reconciliation</a>
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -1 +0,0 @@
|
||||
from . import bank_reconciliation_report_wizard
|
||||
@@ -1,42 +0,0 @@
|
||||
# Copyright 2017-2024 Akretion France (http://www.akretion.com/)
|
||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class BankReconciliationReportWizard(models.TransientModel):
|
||||
_name = "bank.reconciliation.report.wizard"
|
||||
_description = "Bank Reconciliation Report Wizard"
|
||||
_check_company_auto = True
|
||||
|
||||
company_id = fields.Many2one(
|
||||
'res.company', string='Company',
|
||||
ondelete='cascade', required=True,
|
||||
default=lambda self: self.env.company)
|
||||
date = fields.Date(required=True, default=fields.Date.context_today)
|
||||
move_state = fields.Selection(
|
||||
[("posted", "Posted Entries"), ("draft_posted", "Draft and Posted Entries")],
|
||||
string="Entries",
|
||||
required=True,
|
||||
default="posted",
|
||||
)
|
||||
journal_ids = fields.Many2many(
|
||||
"account.journal",
|
||||
string="Bank Journals",
|
||||
domain="[('type', '=', 'bank'), ('company_id', '=', company_id)]",
|
||||
required=True,
|
||||
check_company=True,
|
||||
default=lambda self: self._default_journal_ids(),
|
||||
)
|
||||
|
||||
@api.model
|
||||
def _default_journal_ids(self):
|
||||
journals = self.env["account.journal"].search(
|
||||
[
|
||||
("type", "=", "bank"),
|
||||
("bank_account_id", "!=", False),
|
||||
("company_id", "=", self.env.company.id),
|
||||
]
|
||||
)
|
||||
return journals
|
||||
@@ -1,49 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!--
|
||||
Copyright 2017-2024 Akretion France (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
<odoo>
|
||||
<record id="bank_reconciliation_report_wizard_form" model="ir.ui.view">
|
||||
<field name="name">bank.reconciliation.report.wizard.form</field>
|
||||
<field name="model">bank.reconciliation.report.wizard</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<group name="main">
|
||||
<field name="company_id" invisible="1" />
|
||||
<field name="date" />
|
||||
<field name="journal_ids" widget="many2many_tags" options="{'no_open': True, 'no_create': True}"/>
|
||||
<field name="move_state" widget="radio"/>
|
||||
</group>
|
||||
<footer>
|
||||
<button
|
||||
name="%(account_bank_reconciliation_summary_xlsx.bank_reconciliation_xlsx)d"
|
||||
string="Export XLSX"
|
||||
type="action"
|
||||
class="btn-primary"
|
||||
/>
|
||||
<button special="cancel" string="Cancel" />
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<record id="bank_reconciliation_report_wizard_action" model="ir.actions.act_window">
|
||||
<field name="name">Bank Reconciliation</field>
|
||||
<field name="res_model">bank.reconciliation.report.wizard</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
<menuitem
|
||||
id="menu_report_bank_root"
|
||||
parent="account.menu_finance_reports"
|
||||
name="Bank Reports"
|
||||
sequence="12"
|
||||
/>
|
||||
<menuitem
|
||||
id="bank_reconciliation_report_wizard_menu"
|
||||
action="bank_reconciliation_report_wizard_action"
|
||||
parent="menu_report_bank_root"
|
||||
sequence="10"
|
||||
/>
|
||||
</odoo>
|
||||
35
account_bank_statement_import_fr_hsbc_card/README.rst
Normal file
35
account_bank_statement_import_fr_hsbc_card/README.rst
Normal file
@@ -0,0 +1,35 @@
|
||||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
|
||||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
|
||||
:alt: License: AGPL-3
|
||||
|
||||
=======================================
|
||||
Import French HSBC Card Bank Statements
|
||||
=======================================
|
||||
|
||||
This module allows you to import French HSBC credit cards bank statements (CSV version).
|
||||
|
||||
Configuration
|
||||
=============
|
||||
|
||||
Create a bank journal dedicated to HSBC credit cards. Associate it with a new bank account on which you will set the account number to *HSBC_CARD_EUR*.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
In the dashboard of the *Accounting* menu, click on the button *Import Statement* located on the journal corresponding to the bank account of the statement file you are importing.
|
||||
|
||||
Bug Tracker
|
||||
===========
|
||||
|
||||
Bugs are tracked on `GitHub Issues
|
||||
<https://github.com/akretion/odoo-usability/issues>`_. In case of trouble, please
|
||||
check there if your issue has already been reported. If you spotted it first,
|
||||
help us smashing it by providing a detailed and welcomed feedback.
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
||||
* Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
3
account_bank_statement_import_fr_hsbc_card/__init__.py
Normal file
3
account_bank_statement_import_fr_hsbc_card/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import wizard
|
||||
16
account_bank_statement_import_fr_hsbc_card/__manifest__.py
Normal file
16
account_bank_statement_import_fr_hsbc_card/__manifest__.py
Normal file
@@ -0,0 +1,16 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
'name': 'Import French HSBC Card Bank Statements',
|
||||
'version': '10.0.1.0.0',
|
||||
'license': 'AGPL-3',
|
||||
'author': "Akretion",
|
||||
'website': 'http://www.akretion.com',
|
||||
'summary': 'Import French HSBC Card Bank Statements in Odoo (CSV version)',
|
||||
'depends': ['account_bank_statement_import'],
|
||||
'data': ['views/account_bank_statement_import.xml'],
|
||||
'installable': True,
|
||||
}
|
||||
69
account_bank_statement_import_fr_hsbc_card/i18n/nb_NO.po
Normal file
69
account_bank_statement_import_fr_hsbc_card/i18n/nb_NO.po
Normal file
@@ -0,0 +1,69 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * account_bank_statement_import_fr_cfonb
|
||||
#
|
||||
# Translators:
|
||||
# OCA Transbot <transbot@odoo-community.org>, 2017
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 10.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-01-13 03:36+0000\n"
|
||||
"PO-Revision-Date: 2017-01-13 03:36+0000\n"
|
||||
"Last-Translator: OCA Transbot <transbot@odoo-community.org>, 2017\n"
|
||||
"Language-Team: Norwegian Bokmål (Norway) (https://www.transifex.com/oca/teams/23907/nb_NO/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Language: nb_NO\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#. module: account_bank_statement_import_fr_cfonb
|
||||
#: code:addons/account_bank_statement_import_fr_cfonb/models/account_bank_statement_import.py:146
|
||||
#, python-format
|
||||
msgid "Account %s"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_bank_statement_import_fr_cfonb
|
||||
#: model:ir.ui.view,arch_db:account_bank_statement_import_fr_cfonb.account_bank_statement_import_view
|
||||
msgid "CFONB (French format, fixed-length text lines of 120 caracters)"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_bank_statement_import_fr_cfonb
|
||||
#: model:ir.model,name:account_bank_statement_import_fr_cfonb.model_account_bank_statement_import
|
||||
msgid "Import Bank Statement"
|
||||
msgstr "Importer bankutsagn"
|
||||
|
||||
#. module: account_bank_statement_import_fr_cfonb
|
||||
#: code:addons/account_bank_statement_import_fr_cfonb/models/account_bank_statement_import.py:70
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Line %d is %d caracters long. All lines of a CFONB bank statement file must "
|
||||
"be 120 caracters long."
|
||||
msgstr ""
|
||||
"Linje %d er %d tegn langt. Alle linjer i en CFONB-bankutsagnsfil må være 120"
|
||||
" tegn langt."
|
||||
|
||||
#. module: account_bank_statement_import_fr_cfonb
|
||||
#: code:addons/account_bank_statement_import_fr_cfonb/models/account_bank_statement_import.py:110
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Only single-account files and single-currency files are supported for the "
|
||||
"moment. It is not the case starting from line %d."
|
||||
msgstr ""
|
||||
"Kun enkeltkontofiler og enkeltmyntenhetsfiler støttes for øyeblikket. Dette "
|
||||
"er ikke tilfellet fra og med linje %d og utover."
|
||||
|
||||
#. module: account_bank_statement_import_fr_cfonb
|
||||
#: code:addons/account_bank_statement_import_fr_cfonb/models/account_bank_statement_import.py:99
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The 2 first letters of the first line are '%s'. A CFONB file should start "
|
||||
"with '01'"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_bank_statement_import_fr_cfonb
|
||||
#: code:addons/account_bank_statement_import_fr_cfonb/models/account_bank_statement_import.py:52
|
||||
#, python-format
|
||||
msgid "The file is empty."
|
||||
msgstr "Filen er tom."
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" ?>
|
||||
<!--
|
||||
© 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
|
||||
<record id="account_bank_statement_import_view" model="ir.ui.view">
|
||||
<field name="name">hsbc.fr.csv.account.bank.statement.import.form</field>
|
||||
<field name="model">account.bank.statement.import</field>
|
||||
<field name="inherit_id" ref="account_bank_statement_import.account_bank_statement_import_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//ul[@id='statement_format']" position="inside">
|
||||
<li>French HSBC Credit Cards (CSV format)</li>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</odoo>
|
||||
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import account_bank_statement_import
|
||||
@@ -0,0 +1,105 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
import logging
|
||||
import unicodecsv
|
||||
from tempfile import TemporaryFile
|
||||
from datetime import datetime
|
||||
from odoo import models, fields, api, _
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AccountBankStatementImport(models.TransientModel):
|
||||
_inherit = 'account.bank.statement.import'
|
||||
|
||||
@api.model
|
||||
def _check_hsbc_card_csv(self, data_file):
|
||||
return data_file.strip().startswith(
|
||||
'Titulaire;Division;;Cpt Affaires;Num carte;')
|
||||
|
||||
@api.model
|
||||
def _parse_file(self, data_file):
|
||||
""" Import a file in French HSBC CSV Credit card format"""
|
||||
hsbc_csv = self._check_hsbc_card_csv(data_file)
|
||||
if not hsbc_csv:
|
||||
return super(AccountBankStatementImport, self)._parse_file(
|
||||
data_file)
|
||||
transactions = []
|
||||
fileobj = TemporaryFile('w+')
|
||||
fileobj.write(data_file)
|
||||
fileobj.seek(0)
|
||||
reader = unicodecsv.DictReader(
|
||||
fileobj,
|
||||
fieldnames=[
|
||||
'company', 'division', 'empty', 'account',
|
||||
'card_num', 'title', 'lastname', 'firstname',
|
||||
'op_code', 'seller_type', 'seller', 'date', 'acc_date',
|
||||
'hour', 'city', 'code', 'label', 'local_amount',
|
||||
'local_currency', 'acc_amount', 'acc_currency'],
|
||||
delimiter=';',
|
||||
quoting=unicodecsv.QUOTE_MINIMAL,
|
||||
encoding='latin1')
|
||||
i = 0
|
||||
start_balance = end_balance = 0.0
|
||||
currency_code = 'EUR'
|
||||
account_number = 'HSBC_CARD_EUR'
|
||||
for line in reader:
|
||||
i += 1
|
||||
if i == 1:
|
||||
continue # skip title line
|
||||
_logger.debug("Line %d: %s" % (i, line))
|
||||
if not line:
|
||||
continue
|
||||
# cleanup
|
||||
for key, value in line.iteritems():
|
||||
line[key] = value and value.strip() or False
|
||||
if not line['date'] or not line['acc_amount']:
|
||||
continue
|
||||
labels = [
|
||||
'%s %s' % (line['firstname'], line['lastname']),
|
||||
'%s (%s)' % (line['seller'], line['seller_type']),
|
||||
line['city']]
|
||||
if line['local_currency'] != currency_code:
|
||||
labels.append(
|
||||
'%s %s' % (line['local_amount'], line['local_currency']))
|
||||
name = ', '.join(labels)
|
||||
amount = float(
|
||||
line['acc_amount'].replace(',', '.').replace(' ', '')) * -1
|
||||
end_balance += amount
|
||||
date_dt = datetime.strptime(line['date'], '%d/%m/%Y')
|
||||
date_str = fields.Date.to_string(date_dt)
|
||||
if line['acc_currency'] != currency_code:
|
||||
raise UserError(_(
|
||||
"On line %d of the HSBC CSV file, the column "
|
||||
"'Dev Cpt Affaires' contains '%s' instead of 'EUR'")
|
||||
% (line['acc_currency'], i))
|
||||
vals_line = {
|
||||
'date': date_str,
|
||||
'name': name,
|
||||
'ref': False,
|
||||
# unfortunately, I'm obliged to include i in
|
||||
# the unique_import_id, which will disable the auto-delete
|
||||
# of already imported lines. But experice has proven that
|
||||
# Internet payment often have hour=00:00, and it's possible
|
||||
# to have 2 internet payments for the same supplier the same
|
||||
# day with the same amount (e.g. purchase a return ticket)
|
||||
'unique_import_id': '%s-%s-%.2f-%s-%d' % (
|
||||
date_str, line['hour'], amount, name, i),
|
||||
'amount': amount,
|
||||
'partner_id': False,
|
||||
}
|
||||
transactions.append(vals_line)
|
||||
vals_bank_statement = {
|
||||
'name': _('HSBC Cards'),
|
||||
'balance_start': start_balance,
|
||||
'balance_end_real': end_balance,
|
||||
'transactions': transactions,
|
||||
}
|
||||
fileobj.close()
|
||||
# from pprint import pprint
|
||||
# pprint(vals_bank_statement)
|
||||
return currency_code, account_number, [vals_bank_statement]
|
||||
3
account_bank_statement_import_usability/__init__.py
Normal file
3
account_bank_statement_import_usability/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import account_bank_statement_import
|
||||
29
account_bank_statement_import_usability/__manifest__.py
Normal file
29
account_bank_statement_import_usability/__manifest__.py
Normal file
@@ -0,0 +1,29 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2015-2016 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
'name': 'Account Bank Statement Import Usability',
|
||||
'version': '10.0.0.1.0',
|
||||
'category': 'Accounting & Finance',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Small usability enhancements in account_bank_statement_import module',
|
||||
'description': """
|
||||
Account Bank Statement Import Usability
|
||||
=======================================
|
||||
|
||||
This module adds the following changes:
|
||||
|
||||
* Works if the bank statement file only contain the account number and not the full IBAN
|
||||
|
||||
* remove start balance and end balance (doesn't work with OFX, which is one of the most used file format !)
|
||||
|
||||
This module has been written by Alexis de Lattre from Akretion <alexis.delattre@akretion.com>.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['account_bank_statement_import'],
|
||||
'data': ['account_view.xml'],
|
||||
'installable': True,
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2015-2016 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import models, api
|
||||
|
||||
|
||||
class AccountBankStatementImport(models.TransientModel):
|
||||
_inherit = 'account.bank.statement.import'
|
||||
|
||||
def _check_journal_bank_account(self, journal, account_number):
|
||||
if account_number in journal.bank_account_id.sanitized_acc_number:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class AccountBankStatement(models.Model):
|
||||
_inherit = 'account.bank.statement'
|
||||
|
||||
# When we use the import of bank statement via files,
|
||||
# the start/end_balance is usually computed from the lines itself
|
||||
# because we don't have the 'real' information in the file
|
||||
# But, in the module account_bank_statement_import, in the method
|
||||
# _create_bank_statement(), the bank statement lines already present in
|
||||
# Odoo are filtered out, but the start/end balance is not adjusted,
|
||||
# so the user has to manually modifiy it the close the bank statement
|
||||
# I think the solution is just to remove the start/end balance system
|
||||
# on the bank statement when we use the file import
|
||||
# This code is present in the 'account' module, but I override it here
|
||||
# and not in account_usability because the users who don't have
|
||||
# account_bank_statement_import may want to keep start/end balance
|
||||
@api.multi
|
||||
def _balance_check(self):
|
||||
return True
|
||||
48
account_bank_statement_import_usability/account_view.xml
Normal file
48
account_bank_statement_import_usability/account_view.xml
Normal file
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
© 2016 Akretion (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
<!--
|
||||
Let's try again to work with balance_start and balance_end_real
|
||||
in v10 to see if we can work with it in v10 or not...
|
||||
If we really can't, I'll re-activate this view inheritance again
|
||||
|
||||
<record id="view_bank_statement_form" model="ir.ui.view">
|
||||
<field name="name">bank_statement_import_usability.account.bank.statement.form</field>
|
||||
<field name="model">account.bank.statement</field>
|
||||
<field name="inherit_id" ref="account.view_bank_statement_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="balance_start" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</field>
|
||||
<field name="balance_end_real" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
-->
|
||||
|
||||
<record id="view_bank_statement_tree" model="ir.ui.view">
|
||||
<field name="name">bank_statement_import_usability.account.bank.statement.tree</field>
|
||||
<field name="model">account.bank.statement</field>
|
||||
<field name="inherit_id" ref="account.view_bank_statement_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="balance_start" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</field>
|
||||
<field name="balance_end_real" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</field>
|
||||
<tree position="attributes">
|
||||
<attribute name="colors">blue:state=='draft';black:state=='confirm'</attribute>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</odoo>
|
||||
3
account_bank_statement_no_reconcile_guess/__init__.py
Normal file
3
account_bank_statement_no_reconcile_guess/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import account
|
||||
33
account_bank_statement_no_reconcile_guess/__manifest__.py
Normal file
33
account_bank_statement_no_reconcile_guess/__manifest__.py
Normal file
@@ -0,0 +1,33 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
'name': 'Account Bank Statement No Reconcile Guess',
|
||||
'version': '10.0.1.0.0',
|
||||
'category': 'Accounting & Finance',
|
||||
'license': 'AGPL-3',
|
||||
'summary': "Don't pre-select lines to reconcile in bank statements",
|
||||
'description': """
|
||||
Account Bank Statement No Reconcile Guess
|
||||
=========================================
|
||||
|
||||
Here is a scenario where the "reconcile guess" feature is a problem for the accountant:
|
||||
|
||||
1) The accountant imports a large bank statement with 40 bank statement lines.
|
||||
2) The "reconcile guess" feature will pre-select reconcile of line X with line 39 of the bank statement. But this guess is a mistake and line X should be reconciled with line 2 of the bank statement.
|
||||
=> The accountant will not understand why he can't select line X to be reconciled with line 2 of the bank statement. To be able to reconcile line 2 correctif, he has to:
|
||||
3) click several times on the "next page" button to reach line 39 of the bank statement and unselect line X.
|
||||
4) Go back to line 2 of the bank statement and now he will be able to select line X.
|
||||
|
||||
This module disables the "reconcile guess" feature to avoid this problem.
|
||||
|
||||
This module has been written by Alexis de Lattre from Akretion <alexis.delattre@akretion.com>.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['account'],
|
||||
'data': [],
|
||||
'installable': True,
|
||||
}
|
||||
14
account_bank_statement_no_reconcile_guess/account.py
Normal file
14
account_bank_statement_no_reconcile_guess/account.py
Normal file
@@ -0,0 +1,14 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import models
|
||||
|
||||
|
||||
class AccountBankStatementLine(models.Model):
|
||||
_inherit = 'account.bank.statement.line'
|
||||
|
||||
def get_reconciliation_proposition(self, excluded_ids=None):
|
||||
self.ensure_one()
|
||||
return self.env['account.move.line']
|
||||
3
account_credit_control_usability/__init__.py
Normal file
3
account_credit_control_usability/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import account_credit_control
|
||||
46
account_credit_control_usability/__manifest__.py
Normal file
46
account_credit_control_usability/__manifest__.py
Normal file
@@ -0,0 +1,46 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Account Credit Control Usability module for Odoo
|
||||
# Copyright (C) 2016 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
{
|
||||
'name': 'Account Credit Control Usability',
|
||||
'version': '0.1',
|
||||
'category': 'Accounting & Finance',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Small usability enhancements in account_credit_control module',
|
||||
'description': """
|
||||
Account Credit Control Usability
|
||||
================================
|
||||
|
||||
The usability enhancements include:
|
||||
|
||||
* add phone call in the list of channels
|
||||
* hide some fields
|
||||
|
||||
This module has been written by Alexis de Lattre from Akretion <alexis.delattre@akretion.com>.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['account_credit_control', 'partner_aged_open_invoices'],
|
||||
'data': ['account_credit_control_view.xml'],
|
||||
'installable': False,
|
||||
}
|
||||
82
account_credit_control_usability/account_credit_control.py
Normal file
82
account_credit_control_usability/account_credit_control.py
Normal file
@@ -0,0 +1,82 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Account Credit Control Usability module for Odoo
|
||||
# Copyright (C) 2016 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp import models, fields, api
|
||||
|
||||
|
||||
class CreditControlPolicyLevel(models.Model):
|
||||
_inherit = "credit.control.policy.level"
|
||||
_rec_name = 'internal_name'
|
||||
|
||||
channel = fields.Selection(selection_add=[('phone', 'Phone Call')])
|
||||
name = fields.Char(
|
||||
string='Subject',
|
||||
help="Will be displayed in the subject of the emails and in "
|
||||
"the letters")
|
||||
internal_name = fields.Char(string='Internal Name', required=True)
|
||||
|
||||
|
||||
class CreditControlLine(models.Model):
|
||||
_inherit = "credit.control.line"
|
||||
|
||||
channel = fields.Selection(selection_add=[('phone', 'Phone Call')])
|
||||
note = fields.Text(string='Notes')
|
||||
|
||||
@api.multi
|
||||
def open_aged_open_invoices_report(self):
|
||||
self.ensure_one()
|
||||
return self.partner_id.open_aged_open_invoices_report()
|
||||
|
||||
@api.multi
|
||||
def go_to_partner_form(self):
|
||||
self.ensure_one()
|
||||
action = self.env['ir.actions.act_window'].for_xml_id(
|
||||
'base', 'action_partner_customer_form')
|
||||
action.update({
|
||||
'view_mode': 'form,kanban,tree',
|
||||
'views': False,
|
||||
'res_id': self.partner_id.id,
|
||||
'context': {},
|
||||
})
|
||||
return action
|
||||
|
||||
|
||||
class CreditControlRun(models.Model):
|
||||
_inherit = "credit.control.run"
|
||||
|
||||
date = fields.Date(default=fields.Date.context_today)
|
||||
|
||||
|
||||
class ResPartner(models.Model):
|
||||
_inherit = 'res.partner'
|
||||
|
||||
@api.one
|
||||
@api.depends('credit_control_line_ids')
|
||||
def _credit_control_line_count(self):
|
||||
try:
|
||||
self.credit_control_line_count = len(self.credit_control_line_ids)
|
||||
except:
|
||||
self.credit_control_line_count = 0
|
||||
|
||||
credit_control_line_count = fields.Integer(
|
||||
compute='_credit_control_line_count',
|
||||
string="# of Credit Control Lines", readonly=True)
|
||||
127
account_credit_control_usability/account_credit_control_view.xml
Normal file
127
account_credit_control_usability/account_credit_control_view.xml
Normal file
@@ -0,0 +1,127 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="credit_control_line_tree" model="ir.ui.view">
|
||||
<field name="name">credit_control_usability.credit_control_line_tree</field>
|
||||
<field name="model">credit.control.line</field>
|
||||
<field name="inherit_id" ref="account_credit_control.credit_control_line_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="account_id" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</field>
|
||||
<field name="move_line_id" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</field>
|
||||
<field name="mail_message_id" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</field>
|
||||
<field name="partner_id" position="after">
|
||||
<button name="go_to_partner_form" type="object"
|
||||
string="Go to Partner" icon="terp-gtk-jump-to-ltr"/>
|
||||
<button name="open_aged_open_invoices_report" type="object"
|
||||
string="Open Aged Open Invoices Report" icon="STOCK_ZOOM_IN"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="credit_control_line_form" model="ir.ui.view">
|
||||
<field name="name">credit_control_usability.credit_control_line_form</field>
|
||||
<field name="model">credit.control.line</field>
|
||||
<field name="inherit_id" ref="account_credit_control.credit_control_line_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='currency_id']/.." position="after">
|
||||
<group name="note">
|
||||
<field name="note"/>
|
||||
</group>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="credit_control_policy_form" model="ir.ui.view">
|
||||
<field name="name">credit_control_usability.credit.control.policy.form</field>
|
||||
<field name="model">credit.control.policy</field>
|
||||
<field name="inherit_id" ref="account_credit_control.credit_control_policy_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='level_ids']/tree/field[@name='name']" position="before">
|
||||
<field name="internal_name"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='level_ids']/form//field[@name='name']" position="replace">
|
||||
<group name="level-main">
|
||||
|
||||
<field name="internal_name"/>
|
||||
<field name="name"/>
|
||||
</group>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="credit_mangement_policy_level_form" model="ir.ui.view">
|
||||
<field name="name">credit_control_usability.credit.control.policy.level.form</field>
|
||||
<field name="model">credit.control.policy.level</field>
|
||||
<field name="inherit_id" ref="account_credit_control.credit_mangement_policy_level_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="name" position="before">
|
||||
<field name="internal_name"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="credit_control_policy_level_tree" model="ir.ui.view">
|
||||
<field name="name">credit_control_usability.credit.control.policy.level.tree</field>
|
||||
<field name="model">credit.control.policy.level</field>
|
||||
<field name="inherit_id" ref="account_credit_control.credit_control_policy_level_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="name" position="before">
|
||||
<field name="internal_name"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="credit_control_line_search" model="ir.ui.view">
|
||||
<field name="name">credit_control_usability.credit_control_line_search</field>
|
||||
<field name="model">credit.control.line</field>
|
||||
<field name="inherit_id" ref="account_credit_control.credit_control_line_search"/>
|
||||
<field name="arch" type="xml">
|
||||
<filter name="filter_manual" position="after">
|
||||
<filter name="phone" string="Phone Call" domain="[('channel', '=', 'phone')]"/>
|
||||
<filter name="letter" string="Letter" domain="[('channel', '=', 'letter')]"/>
|
||||
<filter name="email" string="Email" domain="[('channel', '=', 'email')]"/>
|
||||
</filter>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="partner_credit_control_line_action" model="ir.actions.act_window">
|
||||
<field name="name">Credit Control Lines</field>
|
||||
<field name="res_model">credit.control.line</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="context">{'search_default_partner_id': active_id}</field>
|
||||
</record>
|
||||
|
||||
<record id="view_partner_form" model="ir.ui.view">
|
||||
<field name="name">account_credit_control_usability.button.res.partner.form</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="inherit_id" ref="base.view_partner_form" />
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[@name='buttons']" position="inside">
|
||||
<button class="oe_inline oe_stat_button" type="action"
|
||||
name="%(partner_credit_control_line_action)d"
|
||||
attrs="{'invisible': [('customer', '=', False)]}"
|
||||
icon="fa-gavel">
|
||||
<field string="Credit Control"
|
||||
name="credit_control_line_count" widget="statinfo"/>
|
||||
</button>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- rapport -->
|
||||
<template id="report_credit_control_summary_document" inherit_id="account_credit_control.report_credit_control_summary_document">
|
||||
<xpath expr="//span[@t-field='l.amount_due']" position="attributes">
|
||||
<attribute name="t-field-options">{"widget": "monetary", "display_currency": "l.currency_id or l.company_id.currency_id"}</attribute>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
1
account_cutoff_accrual_picking_ods/__init__.py
Normal file
1
account_cutoff_accrual_picking_ods/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
24
account_cutoff_accrual_picking_ods/__manifest__.py
Normal file
24
account_cutoff_accrual_picking_ods/__manifest__.py
Normal file
@@ -0,0 +1,24 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2016 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
'name': 'Account Cutoff Accrual Picking ODS',
|
||||
'version': '8.0.0.1.0',
|
||||
'category': 'Tools',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Adds an Aeroo ODS report on cutoff accrual',
|
||||
'description': """
|
||||
Account Cutoff Accrual Picking ODS
|
||||
==================================
|
||||
|
||||
This module will add an Aeroo ODS report on Accrued Revenue and Accrued Expense.
|
||||
|
||||
This module has been written by Alexis de Lattre from Akretion <alexis.delattre@akretion.com>.
|
||||
""",
|
||||
'author': "Akretion",
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['account_cutoff_accrual_picking', 'report_aeroo'],
|
||||
'data': ['report.xml'],
|
||||
'installable': False,
|
||||
}
|
||||
BIN
account_cutoff_accrual_picking_ods/cutoff_accrual.ods
Normal file
BIN
account_cutoff_accrual_picking_ods/cutoff_accrual.ods
Normal file
Binary file not shown.
27
account_cutoff_accrual_picking_ods/report.xml
Normal file
27
account_cutoff_accrual_picking_ods/report.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
|
||||
<record id="account_cutoff_accrual_picking_ods" model="ir.actions.report.xml">
|
||||
<field name="name">Cutoff Accrual ODS</field>
|
||||
<field name="model">account.cutoff</field>
|
||||
<field name="report_name">account.cutoff.accrual.picking.ods</field>
|
||||
<field name="report_type">aeroo</field>
|
||||
<field name="in_format">oo-ods</field>
|
||||
<field name="report_rml">account_cutoff_accrual_picking_ods/cutoff_accrual.ods</field>
|
||||
<field name="parser_state">default</field>
|
||||
<field name="tml_source">file</field>
|
||||
<field name="out_format" ref="report_aeroo.report_mimetypes_ods_ods"/>
|
||||
</record>
|
||||
|
||||
<record id="account_cutoff_accrual_picking_ods_button" model="ir.values">
|
||||
<field name="name">Cutoff Accrual ODS</field>
|
||||
<field name="model">account.cutoff</field>
|
||||
<field name="key2">client_print_multi</field>
|
||||
<field name="value" eval="'ir.actions.report.xml,%d'%account_cutoff_accrual_picking_ods"/>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
1
account_cutoff_prepaid_ods/__init__.py
Normal file
1
account_cutoff_prepaid_ods/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
43
account_cutoff_prepaid_ods/__manifest__.py
Normal file
43
account_cutoff_prepaid_ods/__manifest__.py
Normal file
@@ -0,0 +1,43 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Account Cutoff Prepaid ODS module for Odoo
|
||||
# Copyright (C) 2016 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
{
|
||||
'name': 'Account Cutoff Prepaid ODS',
|
||||
'version': '8.0.0.1.0',
|
||||
'category': 'Tools',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Adds an Aeroo ODS report on cutoff prepaid',
|
||||
'description': """
|
||||
Account Cutoff Prepaid ODS
|
||||
===========================
|
||||
|
||||
This module will add an Aeroo ODS report on Prepaid Revenue and Prepaid Expense.
|
||||
|
||||
This module has been written by Alexis de Lattre from Akretion <alexis.delattre@akretion.com>.
|
||||
""",
|
||||
'author': "Akretion",
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['account_cutoff_prepaid', 'report_aeroo'],
|
||||
'data': ['report.xml'],
|
||||
'installable': False,
|
||||
}
|
||||
BIN
account_cutoff_prepaid_ods/cutoff_prepaid.ods
Normal file
BIN
account_cutoff_prepaid_ods/cutoff_prepaid.ods
Normal file
Binary file not shown.
27
account_cutoff_prepaid_ods/report.xml
Normal file
27
account_cutoff_prepaid_ods/report.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
|
||||
<record id="account_cutoff_prepaid_ods" model="ir.actions.report.xml">
|
||||
<field name="name">Cutoff Prepaid ODS</field>
|
||||
<field name="model">account.cutoff</field>
|
||||
<field name="report_name">account.cutoff.prepaid.ods</field>
|
||||
<field name="report_type">aeroo</field>
|
||||
<field name="in_format">oo-ods</field>
|
||||
<field name="report_rml">account_cutoff_prepaid_ods/cutoff_prepaid.ods</field>
|
||||
<field name="parser_state">default</field>
|
||||
<field name="tml_source">file</field>
|
||||
<field name="out_format" ref="report_aeroo.report_mimetypes_ods_ods"/>
|
||||
</record>
|
||||
|
||||
<record id="account_cutoff_prepaid_ods_button" model="ir.values">
|
||||
<field name="name">Cutoff Prepaid ODS</field>
|
||||
<field name="model">account.cutoff</field>
|
||||
<field name="key2">client_print_multi</field>
|
||||
<field name="value" eval="'ir.actions.report.xml,%d'%account_cutoff_prepaid_ods"/>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -1,68 +0,0 @@
|
||||
=======================================
|
||||
Account Default Report Without Paiement
|
||||
=======================================
|
||||
|
||||
..
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! source digest: sha256:2035514c3af2d372479b91ca5314fe2f5ff90523f11fb8cc874b4fac8b375f50
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
|
||||
:target: https://odoo-community.org/page/development-status
|
||||
:alt: Beta
|
||||
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
|
||||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
|
||||
:alt: License: AGPL-3
|
||||
.. |badge3| image:: https://img.shields.io/badge/github-akretion%2Fodoo--usability-lightgray.png?logo=github
|
||||
:target: https://github.com/akretion/odoo-usability/tree/14.0/account_default_report_without_paiement
|
||||
:alt: akretion/odoo-usability
|
||||
|
||||
|badge1| |badge2| |badge3|
|
||||
|
||||
This module switch the default account report to the one without paiement
|
||||
|
||||
**Table of contents**
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
Bug Tracker
|
||||
===========
|
||||
|
||||
Bugs are tracked on `GitHub Issues <https://github.com/akretion/odoo-usability/issues>`_.
|
||||
In case of trouble, please check there if your issue has already been reported.
|
||||
If you spotted it first, help us to smash it by providing a detailed and welcomed
|
||||
`feedback <https://github.com/akretion/odoo-usability/issues/new?body=module:%20account_default_report_without_paiement%0Aversion:%2014.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
|
||||
|
||||
Do not contact contributors directly about support or help with technical issues.
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
Authors
|
||||
~~~~~~~
|
||||
|
||||
* Akretion
|
||||
|
||||
Contributors
|
||||
~~~~~~~~~~~~
|
||||
|
||||
* Kévin Roche <kevin.roche@akretion.com>
|
||||
|
||||
Maintainers
|
||||
~~~~~~~~~~~
|
||||
|
||||
.. |maintainer-Kev-Roche| image:: https://github.com/Kev-Roche.png?size=40px
|
||||
:target: https://github.com/Kev-Roche
|
||||
:alt: Kev-Roche
|
||||
|
||||
Current maintainer:
|
||||
|
||||
|maintainer-Kev-Roche|
|
||||
|
||||
This module is part of the `akretion/odoo-usability <https://github.com/akretion/odoo-usability/tree/14.0/account_default_report_without_paiement>`_ project on GitHub.
|
||||
|
||||
You are welcome to contribute.
|
||||
@@ -1,22 +0,0 @@
|
||||
# Copyright 2024 Akretion (https://www.akretion.com).
|
||||
# @author Kévin Roche <kevin.roche@akretion.com>
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
"name": "Account Default Report Without Paiement",
|
||||
"summary": "Account Default Report Without Paiement",
|
||||
"version": "14.0.1.0.0",
|
||||
"category": "reports",
|
||||
"website": "https://github.com/OCA/account",
|
||||
"author": "Akretion, Odoo Community Association (OCA)",
|
||||
"license": "AGPL-3",
|
||||
"maintainers":["Kev-Roche"],
|
||||
"application": False,
|
||||
"installable": True,
|
||||
"depends": [
|
||||
"account",
|
||||
],
|
||||
"data": [
|
||||
"data/data.xml",
|
||||
],
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!-- Copyright (C) 2024 Akretion (<http://www.akretion.com>).
|
||||
@author Kévin Roche <kevin.roche@akretion.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
|
||||
<odoo>
|
||||
<record id="account.account_invoices" model="ir.actions.report">
|
||||
<field name="report_name">account.report_invoice</field>
|
||||
<field name="report_file">account.report_invoice</field>
|
||||
</record>
|
||||
|
||||
<record id="account.account_invoices_without_payment" model="ir.actions.report">
|
||||
<field name="name">Factures avec paiement</field>
|
||||
<field name="report_name">account.report_invoice_with_payments</field>
|
||||
<field name="report_file">account.report_invoice_with_payments</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -1 +0,0 @@
|
||||
* Kévin Roche <kevin.roche@akretion.com>
|
||||
@@ -1 +0,0 @@
|
||||
This module switch the default account report to the one without paiement
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 9.2 KiB |
@@ -1,418 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
|
||||
<title>Account Default Report Without Paiement</title>
|
||||
<style type="text/css">
|
||||
|
||||
/*
|
||||
:Author: David Goodger (goodger@python.org)
|
||||
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
|
||||
:Copyright: This stylesheet has been placed in the public domain.
|
||||
|
||||
Default cascading style sheet for the HTML output of Docutils.
|
||||
Despite the name, some widely supported CSS2 features are used.
|
||||
|
||||
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
|
||||
customize this style sheet.
|
||||
*/
|
||||
|
||||
/* used to remove borders from tables and images */
|
||||
.borderless, table.borderless td, table.borderless th {
|
||||
border: 0 }
|
||||
|
||||
table.borderless td, table.borderless th {
|
||||
/* Override padding for "table.docutils td" with "! important".
|
||||
The right padding separates the table cells. */
|
||||
padding: 0 0.5em 0 0 ! important }
|
||||
|
||||
.first {
|
||||
/* Override more specific margin styles with "! important". */
|
||||
margin-top: 0 ! important }
|
||||
|
||||
.last, .with-subtitle {
|
||||
margin-bottom: 0 ! important }
|
||||
|
||||
.hidden {
|
||||
display: none }
|
||||
|
||||
.subscript {
|
||||
vertical-align: sub;
|
||||
font-size: smaller }
|
||||
|
||||
.superscript {
|
||||
vertical-align: super;
|
||||
font-size: smaller }
|
||||
|
||||
a.toc-backref {
|
||||
text-decoration: none ;
|
||||
color: black }
|
||||
|
||||
blockquote.epigraph {
|
||||
margin: 2em 5em ; }
|
||||
|
||||
dl.docutils dd {
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Uncomment (and remove this text!) to get bold-faced definition list terms
|
||||
dl.docutils dt {
|
||||
font-weight: bold }
|
||||
*/
|
||||
|
||||
div.abstract {
|
||||
margin: 2em 5em }
|
||||
|
||||
div.abstract p.topic-title {
|
||||
font-weight: bold ;
|
||||
text-align: center }
|
||||
|
||||
div.admonition, div.attention, div.caution, div.danger, div.error,
|
||||
div.hint, div.important, div.note, div.tip, div.warning {
|
||||
margin: 2em ;
|
||||
border: medium outset ;
|
||||
padding: 1em }
|
||||
|
||||
div.admonition p.admonition-title, div.hint p.admonition-title,
|
||||
div.important p.admonition-title, div.note p.admonition-title,
|
||||
div.tip p.admonition-title {
|
||||
font-weight: bold ;
|
||||
font-family: sans-serif }
|
||||
|
||||
div.attention p.admonition-title, div.caution p.admonition-title,
|
||||
div.danger p.admonition-title, div.error p.admonition-title,
|
||||
div.warning p.admonition-title, .code .error {
|
||||
color: red ;
|
||||
font-weight: bold ;
|
||||
font-family: sans-serif }
|
||||
|
||||
/* Uncomment (and remove this text!) to get reduced vertical space in
|
||||
compound paragraphs.
|
||||
div.compound .compound-first, div.compound .compound-middle {
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
div.compound .compound-last, div.compound .compound-middle {
|
||||
margin-top: 0.5em }
|
||||
*/
|
||||
|
||||
div.dedication {
|
||||
margin: 2em 5em ;
|
||||
text-align: center ;
|
||||
font-style: italic }
|
||||
|
||||
div.dedication p.topic-title {
|
||||
font-weight: bold ;
|
||||
font-style: normal }
|
||||
|
||||
div.figure {
|
||||
margin-left: 2em ;
|
||||
margin-right: 2em }
|
||||
|
||||
div.footer, div.header {
|
||||
clear: both;
|
||||
font-size: smaller }
|
||||
|
||||
div.line-block {
|
||||
display: block ;
|
||||
margin-top: 1em ;
|
||||
margin-bottom: 1em }
|
||||
|
||||
div.line-block div.line-block {
|
||||
margin-top: 0 ;
|
||||
margin-bottom: 0 ;
|
||||
margin-left: 1.5em }
|
||||
|
||||
div.sidebar {
|
||||
margin: 0 0 0.5em 1em ;
|
||||
border: medium outset ;
|
||||
padding: 1em ;
|
||||
background-color: #ffffee ;
|
||||
width: 40% ;
|
||||
float: right ;
|
||||
clear: right }
|
||||
|
||||
div.sidebar p.rubric {
|
||||
font-family: sans-serif ;
|
||||
font-size: medium }
|
||||
|
||||
div.system-messages {
|
||||
margin: 5em }
|
||||
|
||||
div.system-messages h1 {
|
||||
color: red }
|
||||
|
||||
div.system-message {
|
||||
border: medium outset ;
|
||||
padding: 1em }
|
||||
|
||||
div.system-message p.system-message-title {
|
||||
color: red ;
|
||||
font-weight: bold }
|
||||
|
||||
div.topic {
|
||||
margin: 2em }
|
||||
|
||||
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
|
||||
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
|
||||
margin-top: 0.4em }
|
||||
|
||||
h1.title {
|
||||
text-align: center }
|
||||
|
||||
h2.subtitle {
|
||||
text-align: center }
|
||||
|
||||
hr.docutils {
|
||||
width: 75% }
|
||||
|
||||
img.align-left, .figure.align-left, object.align-left, table.align-left {
|
||||
clear: left ;
|
||||
float: left ;
|
||||
margin-right: 1em }
|
||||
|
||||
img.align-right, .figure.align-right, object.align-right, table.align-right {
|
||||
clear: right ;
|
||||
float: right ;
|
||||
margin-left: 1em }
|
||||
|
||||
img.align-center, .figure.align-center, object.align-center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
table.align-center {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.align-left {
|
||||
text-align: left }
|
||||
|
||||
.align-center {
|
||||
clear: both ;
|
||||
text-align: center }
|
||||
|
||||
.align-right {
|
||||
text-align: right }
|
||||
|
||||
/* reset inner alignment in figures */
|
||||
div.align-right {
|
||||
text-align: inherit }
|
||||
|
||||
/* div.align-center * { */
|
||||
/* text-align: left } */
|
||||
|
||||
.align-top {
|
||||
vertical-align: top }
|
||||
|
||||
.align-middle {
|
||||
vertical-align: middle }
|
||||
|
||||
.align-bottom {
|
||||
vertical-align: bottom }
|
||||
|
||||
ol.simple, ul.simple {
|
||||
margin-bottom: 1em }
|
||||
|
||||
ol.arabic {
|
||||
list-style: decimal }
|
||||
|
||||
ol.loweralpha {
|
||||
list-style: lower-alpha }
|
||||
|
||||
ol.upperalpha {
|
||||
list-style: upper-alpha }
|
||||
|
||||
ol.lowerroman {
|
||||
list-style: lower-roman }
|
||||
|
||||
ol.upperroman {
|
||||
list-style: upper-roman }
|
||||
|
||||
p.attribution {
|
||||
text-align: right ;
|
||||
margin-left: 50% }
|
||||
|
||||
p.caption {
|
||||
font-style: italic }
|
||||
|
||||
p.credits {
|
||||
font-style: italic ;
|
||||
font-size: smaller }
|
||||
|
||||
p.label {
|
||||
white-space: nowrap }
|
||||
|
||||
p.rubric {
|
||||
font-weight: bold ;
|
||||
font-size: larger ;
|
||||
color: maroon ;
|
||||
text-align: center }
|
||||
|
||||
p.sidebar-title {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold ;
|
||||
font-size: larger }
|
||||
|
||||
p.sidebar-subtitle {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold }
|
||||
|
||||
p.topic-title {
|
||||
font-weight: bold }
|
||||
|
||||
pre.address {
|
||||
margin-bottom: 0 ;
|
||||
margin-top: 0 ;
|
||||
font: inherit }
|
||||
|
||||
pre.literal-block, pre.doctest-block, pre.math, pre.code {
|
||||
margin-left: 2em ;
|
||||
margin-right: 2em }
|
||||
|
||||
pre.code .ln { color: gray; } /* line numbers */
|
||||
pre.code, code { background-color: #eeeeee }
|
||||
pre.code .comment, code .comment { color: #5C6576 }
|
||||
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
|
||||
pre.code .literal.string, code .literal.string { color: #0C5404 }
|
||||
pre.code .name.builtin, code .name.builtin { color: #352B84 }
|
||||
pre.code .deleted, code .deleted { background-color: #DEB0A1}
|
||||
pre.code .inserted, code .inserted { background-color: #A3D289}
|
||||
|
||||
span.classifier {
|
||||
font-family: sans-serif ;
|
||||
font-style: oblique }
|
||||
|
||||
span.classifier-delimiter {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold }
|
||||
|
||||
span.interpreted {
|
||||
font-family: sans-serif }
|
||||
|
||||
span.option {
|
||||
white-space: nowrap }
|
||||
|
||||
span.pre {
|
||||
white-space: pre }
|
||||
|
||||
span.problematic, pre.problematic {
|
||||
color: red }
|
||||
|
||||
span.section-subtitle {
|
||||
/* font-size relative to parent (h1..h6 element) */
|
||||
font-size: 80% }
|
||||
|
||||
table.citation {
|
||||
border-left: solid 1px gray;
|
||||
margin-left: 1px }
|
||||
|
||||
table.docinfo {
|
||||
margin: 2em 4em }
|
||||
|
||||
table.docutils {
|
||||
margin-top: 0.5em ;
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
table.footnote {
|
||||
border-left: solid 1px black;
|
||||
margin-left: 1px }
|
||||
|
||||
table.docutils td, table.docutils th,
|
||||
table.docinfo td, table.docinfo th {
|
||||
padding-left: 0.5em ;
|
||||
padding-right: 0.5em ;
|
||||
vertical-align: top }
|
||||
|
||||
table.docutils th.field-name, table.docinfo th.docinfo-name {
|
||||
font-weight: bold ;
|
||||
text-align: left ;
|
||||
white-space: nowrap ;
|
||||
padding-left: 0 }
|
||||
|
||||
/* "booktabs" style (no vertical lines) */
|
||||
table.docutils.booktabs {
|
||||
border: 0px;
|
||||
border-top: 2px solid;
|
||||
border-bottom: 2px solid;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table.docutils.booktabs * {
|
||||
border: 0px;
|
||||
}
|
||||
table.docutils.booktabs th {
|
||||
border-bottom: thin solid;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
|
||||
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
|
||||
font-size: 100% }
|
||||
|
||||
ul.auto-toc {
|
||||
list-style-type: none }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document" id="account-default-report-without-paiement">
|
||||
<h1 class="title">Account Default Report Without Paiement</h1>
|
||||
|
||||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! source digest: sha256:2035514c3af2d372479b91ca5314fe2f5ff90523f11fb8cc874b4fac8b375f50
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/akretion/odoo-usability/tree/14.0/account_default_report_without_paiement"><img alt="akretion/odoo-usability" src="https://img.shields.io/badge/github-akretion%2Fodoo--usability-lightgray.png?logo=github" /></a></p>
|
||||
<p>This module switch the default account report to the one without paiement</p>
|
||||
<p><strong>Table of contents</strong></p>
|
||||
<div class="contents local topic" id="contents">
|
||||
<ul class="simple">
|
||||
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-1">Bug Tracker</a></li>
|
||||
<li><a class="reference internal" href="#credits" id="toc-entry-2">Credits</a><ul>
|
||||
<li><a class="reference internal" href="#authors" id="toc-entry-3">Authors</a></li>
|
||||
<li><a class="reference internal" href="#contributors" id="toc-entry-4">Contributors</a></li>
|
||||
<li><a class="reference internal" href="#maintainers" id="toc-entry-5">Maintainers</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="bug-tracker">
|
||||
<h1><a class="toc-backref" href="#toc-entry-1">Bug Tracker</a></h1>
|
||||
<p>Bugs are tracked on <a class="reference external" href="https://github.com/akretion/odoo-usability/issues">GitHub Issues</a>.
|
||||
In case of trouble, please check there if your issue has already been reported.
|
||||
If you spotted it first, help us to smash it by providing a detailed and welcomed
|
||||
<a class="reference external" href="https://github.com/akretion/odoo-usability/issues/new?body=module:%20account_default_report_without_paiement%0Aversion:%2014.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
|
||||
<p>Do not contact contributors directly about support or help with technical issues.</p>
|
||||
</div>
|
||||
<div class="section" id="credits">
|
||||
<h1><a class="toc-backref" href="#toc-entry-2">Credits</a></h1>
|
||||
<div class="section" id="authors">
|
||||
<h2><a class="toc-backref" href="#toc-entry-3">Authors</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Akretion</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="contributors">
|
||||
<h2><a class="toc-backref" href="#toc-entry-4">Contributors</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Kévin Roche <<a class="reference external" href="mailto:kevin.roche@akretion.com">kevin.roche@akretion.com</a>></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="maintainers">
|
||||
<h2><a class="toc-backref" href="#toc-entry-5">Maintainers</a></h2>
|
||||
<p>Current maintainer:</p>
|
||||
<p><a class="reference external image-reference" href="https://github.com/Kev-Roche"><img alt="Kev-Roche" src="https://github.com/Kev-Roche.png?size=40px" /></a></p>
|
||||
<p>This module is part of the <a class="reference external" href="https://github.com/akretion/odoo-usability/tree/14.0/account_default_report_without_paiement">akretion/odoo-usability</a> project on GitHub.</p>
|
||||
<p>You are welcome to contribute.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
24
account_direct_debit_autogenerate/__init__.py
Normal file
24
account_direct_debit_autogenerate/__init__.py
Normal file
@@ -0,0 +1,24 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Account Direct Debit Autogenerate module for Odoo
|
||||
# Copyright (C) 2015 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
from . import account_invoice
|
||||
47
account_direct_debit_autogenerate/__manifest__.py
Normal file
47
account_direct_debit_autogenerate/__manifest__.py
Normal file
@@ -0,0 +1,47 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Account Direct Debit Autogenerate module for Odoo
|
||||
# Copyright (C) 2015 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
{
|
||||
'name': 'Account Direct Debit Autogenerate',
|
||||
'version': '0.1',
|
||||
'category': 'Accounting & Finance',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Auto-generate direct debit order on invoice validation',
|
||||
'description': """
|
||||
Account Direct Debit Autogenerate
|
||||
=================================
|
||||
|
||||
With this module, when you validate a customer invoice whose payment mode is SEPA Direct Debit :
|
||||
|
||||
* if a draft Direct Debit order for SEPA Direct Debit already exists, a new payment line is added to it for the invoice,
|
||||
|
||||
* otherwise, a new SEPA Direct Debit order is created for this invoice.
|
||||
|
||||
This module has been written by Alexis de Lattre from Akretion <alexis.delattre@akretion.com>.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['account_banking_sepa_direct_debit', 'account_payment_partner'],
|
||||
'data': [],
|
||||
'installable': False,
|
||||
}
|
||||
107
account_direct_debit_autogenerate/account_invoice.py
Normal file
107
account_direct_debit_autogenerate/account_invoice.py
Normal file
@@ -0,0 +1,107 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Account Direct Debit Autogenerate module for Odoo
|
||||
# Copyright (C) 2015 Akretion (www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp import models, api, _
|
||||
from openerp.exceptions import Warning
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AccountInvoice(models.Model):
|
||||
_inherit = 'account.invoice'
|
||||
|
||||
@api.model
|
||||
def _prepare_payment_order(self, invoice):
|
||||
vals = {
|
||||
'mode': invoice.payment_mode_id.id,
|
||||
'payment_order_type': 'debit',
|
||||
}
|
||||
return vals
|
||||
|
||||
@api.model
|
||||
def _prepare_payment_line(self, move_line, payment_order):
|
||||
assert move_line.invoice, 'The move line must be linked to an invoice'
|
||||
if not move_line.invoice.mandate_id:
|
||||
raise Warning(
|
||||
_('Missing Mandate on Invoice %s') % move_line.invoice.number)
|
||||
vals = {
|
||||
'order_id': payment_order.id,
|
||||
'move_line_id': move_line.id,
|
||||
'partner_id': move_line.partner_id.id,
|
||||
'amount_currency': move_line.debit,
|
||||
'communication': move_line.invoice.number.replace('/', ''),
|
||||
'state': 'structured',
|
||||
'date': move_line.date_maturity,
|
||||
'currency': move_line.invoice.currency_id.id,
|
||||
'mandate_id': move_line.invoice.mandate_id.id,
|
||||
'bank_id': move_line.invoice.mandate_id.partner_bank_id.id,
|
||||
}
|
||||
return vals
|
||||
|
||||
@api.multi
|
||||
def invoice_validate(self):
|
||||
'''Create Direct debit payment order on invoice validation or update
|
||||
an existing draft Direct Debit pay order'''
|
||||
res = super(AccountInvoice, self).invoice_validate()
|
||||
poo = self.env['payment.order']
|
||||
plo = self.env['payment.line']
|
||||
for invoice in self:
|
||||
if (
|
||||
invoice.type == 'out_invoice'
|
||||
and invoice.payment_mode_id
|
||||
and invoice.payment_mode_id.type
|
||||
and invoice.payment_mode_id.type.code
|
||||
and invoice.payment_mode_id.type.code.
|
||||
startswith('pain.008.001.')):
|
||||
payorders = poo.search([
|
||||
('state', '=', 'draft'),
|
||||
('payment_order_type', '=', 'debit'),
|
||||
('mode', '=', invoice.payment_mode_id.id),
|
||||
# mode is attached to company
|
||||
])
|
||||
if payorders:
|
||||
payorder = payorders[0]
|
||||
payorder_type = _('existing')
|
||||
else:
|
||||
payorder_vals = self._prepare_payment_order(invoice)
|
||||
payorder = poo.create(payorder_vals)
|
||||
payorder_type = _('new')
|
||||
logger.info(
|
||||
'New Direct Debit Order created %s'
|
||||
% payorder.reference)
|
||||
move_lines = [
|
||||
line for line in invoice.move_id.line_id
|
||||
if line.account_id == invoice.account_id]
|
||||
for move_line in move_lines:
|
||||
if not invoice.mandate_id:
|
||||
raise Warning(
|
||||
_("Missing Mandate on invoice %s")
|
||||
% invoice.number)
|
||||
# add payment line
|
||||
pl_vals = self._prepare_payment_line(move_line, payorder)
|
||||
pl = plo.create(pl_vals)
|
||||
invoice.message_post(
|
||||
_("A new payment line %s has been automatically "
|
||||
"created on the %s direct debit order %s")
|
||||
% (pl.name, payorder_type, payorder.reference))
|
||||
return res
|
||||
@@ -1 +1,3 @@
|
||||
from . import models
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import account_fiscal_position
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2016-2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
"name": "Account Fiscal Position Payable Receivable",
|
||||
"version": "12.0.1.0.0",
|
||||
"category": "Accounting & Finance",
|
||||
"license": "AGPL-3",
|
||||
"summary": "Configure payable/receivable accounts on fiscal positions",
|
||||
"description": """
|
||||
'name': 'Account Fiscal Position Payable Receivable',
|
||||
'version': '10.0.1.0.0',
|
||||
'category': 'Accounting & Finance',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Configure payable/receivable accounts on fiscal positions',
|
||||
'description': """
|
||||
Account Fiscal Position Payable Receivable
|
||||
==========================================
|
||||
|
||||
@@ -15,9 +16,11 @@ This module allows to configure a special *Partner Receivable Account* and a spe
|
||||
|
||||
This module has been written by Alexis de Lattre from Akretion <alexis.delattre@akretion.com>.
|
||||
""",
|
||||
"author": "Akretion",
|
||||
"website": "http://www.akretion.com",
|
||||
"depends": ["account"],
|
||||
"data": ["views/account_fiscal_position_view.xml"],
|
||||
"installable": False,
|
||||
'author': "Akretion",
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['account'],
|
||||
'data': [
|
||||
'account_fiscal_position_view.xml',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2016-2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import models, fields, api
|
||||
|
||||
|
||||
class AccountFiscalPosition(models.Model):
|
||||
_inherit = 'account.fiscal.position'
|
||||
|
||||
receivable_account_id = fields.Many2one(
|
||||
'account.account', string='Partner Receivable Account',
|
||||
company_dependent=True, domain=[('internal_type', '=', 'receivable')])
|
||||
payable_account_id = fields.Many2one(
|
||||
'account.account', string='Partner Payable Account',
|
||||
company_dependent=True, domain=[('internal_type', '=', 'payable')])
|
||||
|
||||
|
||||
class ResPartner(models.Model):
|
||||
_inherit = 'res.partner'
|
||||
|
||||
@api.onchange('property_account_position_id')
|
||||
def fiscal_position_receivable_payable_change(self):
|
||||
fp = self.property_account_position_id
|
||||
ipo = self.env['ir.property']
|
||||
if fp.receivable_account_id:
|
||||
self.property_account_receivable_id = fp.receivable_account_id
|
||||
else:
|
||||
self.property_account_receivable_id = ipo.get(
|
||||
'property_account_receivable_id', 'res.partner')
|
||||
if fp.payable_account_id:
|
||||
self.property_account_payable_id = fp.payable_account_id
|
||||
else:
|
||||
self.property_account_payable_id = ipo.get(
|
||||
'property_account_payable_id', 'res.partner')
|
||||
@@ -1,2 +0,0 @@
|
||||
from . import account_fiscal_position
|
||||
from . import res_partner
|
||||
@@ -1,21 +0,0 @@
|
||||
# © 2016-2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import models, fields
|
||||
|
||||
|
||||
class AccountFiscalPosition(models.Model):
|
||||
_inherit = "account.fiscal.position"
|
||||
|
||||
receivable_account_id = fields.Many2one(
|
||||
"account.account",
|
||||
string="Partner Receivable Account",
|
||||
company_dependent=True,
|
||||
domain=[("internal_type", "=", "receivable")],
|
||||
)
|
||||
payable_account_id = fields.Many2one(
|
||||
"account.account",
|
||||
string="Partner Payable Account",
|
||||
company_dependent=True,
|
||||
domain=[("internal_type", "=", "payable")],
|
||||
)
|
||||
@@ -1,25 +0,0 @@
|
||||
# © 2016-2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import models, api
|
||||
|
||||
|
||||
class ResPartner(models.Model):
|
||||
_inherit = "res.partner"
|
||||
|
||||
@api.onchange("property_account_position_id")
|
||||
def fiscal_position_receivable_payable_change(self):
|
||||
fp = self.property_account_position_id
|
||||
ipo = self.env["ir.property"]
|
||||
if fp.receivable_account_id:
|
||||
self.property_account_receivable_id = fp.receivable_account_id
|
||||
else:
|
||||
self.property_account_receivable_id = ipo.get(
|
||||
"property_account_receivable_id", "res.partner"
|
||||
)
|
||||
if fp.payable_account_id:
|
||||
self.property_account_payable_id = fp.payable_account_id
|
||||
else:
|
||||
self.property_account_payable_id = ipo.get(
|
||||
"property_account_payable_id", "res.partner"
|
||||
)
|
||||
@@ -1 +1,4 @@
|
||||
from . import models
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import account_invoice
|
||||
from . import account_invoice_report
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Copyright 2015-2019 Akretion France (http://www.akretion.com)
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2015-2017 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
'name': 'Account Invoice Margin',
|
||||
'version': '14.0.1.0.0',
|
||||
'category': 'Invoicing Management',
|
||||
'version': '10.0.1.0.0',
|
||||
'category': 'Accounting & Finance',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Copy standard price on invoice line and compute margins',
|
||||
'description': """
|
||||
@@ -15,10 +15,10 @@ This module has been written by Alexis de Lattre from Akretion
|
||||
<alexis.delattre@akretion.com>.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'https://github.com/akretion/odoo-usability',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['account'],
|
||||
'data': [
|
||||
'views/account_move.xml',
|
||||
'account_invoice_view.xml',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
|
||||
149
account_invoice_margin/account_invoice.py
Normal file
149
account_invoice_margin/account_invoice.py
Normal file
@@ -0,0 +1,149 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2015-2017 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import models, fields, api
|
||||
import odoo.addons.decimal_precision as dp
|
||||
|
||||
|
||||
class AccountInvoiceLine(models.Model):
|
||||
_inherit = 'account.invoice.line'
|
||||
|
||||
standard_price_company_currency = fields.Float(
|
||||
string='Cost Price in Company Currency', readonly=True,
|
||||
digits=dp.get_precision('Product Price'),
|
||||
help="Cost price in company currency in the unit of measure "
|
||||
"of the invoice line (which may be different from the unit "
|
||||
"of measure of the product).")
|
||||
standard_price_invoice_currency = fields.Float(
|
||||
string='Cost Price in Invoice Currency', readonly=True,
|
||||
compute='_compute_margin', store=True,
|
||||
digits=dp.get_precision('Product Price'),
|
||||
help="Cost price in invoice currency in the unit of measure "
|
||||
"of the invoice line")
|
||||
margin_invoice_currency = fields.Monetary(
|
||||
string='Margin in Invoice Currency', readonly=True, store=True,
|
||||
compute='_compute_margin', currency_field='currency_id')
|
||||
margin_company_currency = fields.Monetary(
|
||||
string='Margin in Company Currency', readonly=True, store=True,
|
||||
compute='_compute_margin', currency_field='company_currency_id')
|
||||
margin_rate = fields.Float(
|
||||
string="Margin Rate", readonly=True, store=True,
|
||||
compute='_compute_margin',
|
||||
digits=(16, 2), help="Margin rate in percentage of the sale price")
|
||||
|
||||
@api.depends(
|
||||
'standard_price_company_currency', 'invoice_id.currency_id',
|
||||
'invoice_id.type', 'invoice_id.company_id',
|
||||
'invoice_id.date_invoice', 'quantity', 'price_subtotal')
|
||||
def _compute_margin(self):
|
||||
for il in self:
|
||||
standard_price_inv_cur = 0.0
|
||||
margin_inv_cur = 0.0
|
||||
margin_comp_cur = 0.0
|
||||
margin_rate = 0.0
|
||||
inv = il.invoice_id
|
||||
if inv and inv.type in ('out_invoice', 'out_refund'):
|
||||
# it works in _get_current_rate
|
||||
# even if we set date = False in context
|
||||
# standard_price_inv_cur is in the UoM of the invoice line
|
||||
standard_price_inv_cur =\
|
||||
inv.company_id.currency_id.with_context(
|
||||
date=inv.date_invoice).compute(
|
||||
il.standard_price_company_currency,
|
||||
inv.currency_id)
|
||||
margin_inv_cur =\
|
||||
il.price_subtotal - il.quantity * standard_price_inv_cur
|
||||
margin_comp_cur = inv.currency_id.with_context(
|
||||
date=inv.date_invoice).compute(
|
||||
margin_inv_cur, inv.company_id.currency_id)
|
||||
if il.price_subtotal:
|
||||
margin_rate = 100 * margin_inv_cur / il.price_subtotal
|
||||
# for a refund, margin should be negative
|
||||
# but margin rate should stay positive
|
||||
if inv.type == 'out_refund':
|
||||
margin_inv_cur *= -1
|
||||
margin_comp_cur *= -1
|
||||
il.standard_price_invoice_currency = standard_price_inv_cur
|
||||
il.margin_invoice_currency = margin_inv_cur
|
||||
il.margin_company_currency = margin_comp_cur
|
||||
il.margin_rate = margin_rate
|
||||
|
||||
# We want to copy standard_price on invoice line for customer
|
||||
# invoice/refunds. We can't do that via on_change of product_id,
|
||||
# because it is not always played when invoice is created from code
|
||||
# => we inherit write/create
|
||||
# We write standard_price_company_currency even on supplier invoice/refunds
|
||||
# because we don't have access to the 'type' of the invoice
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
if vals.get('product_id'):
|
||||
pp = self.env['product.product'].browse(vals['product_id'])
|
||||
std_price = pp.standard_price
|
||||
inv_uom_id = vals.get('uom_id')
|
||||
if inv_uom_id and inv_uom_id != pp.uom_id.id:
|
||||
std_price = self.env['product.uom']._compute_price(
|
||||
pp.uom_id.id, std_price, inv_uom_id)
|
||||
vals['standard_price_company_currency'] = std_price
|
||||
return super(AccountInvoiceLine, self).create(vals)
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
if not vals:
|
||||
vals = {}
|
||||
if 'product_id' in vals or 'uom_id' in vals:
|
||||
for il in self:
|
||||
if 'product_id' in vals:
|
||||
if vals.get('product_id'):
|
||||
pp = self.env['product.product'].browse(
|
||||
vals['product_id'])
|
||||
else:
|
||||
pp = False
|
||||
else:
|
||||
pp = il.product_id or False
|
||||
# uom_id is NOT a required field
|
||||
if 'uom_id' in vals:
|
||||
if vals.get('uom_id'):
|
||||
inv_uom = self.env['product.uom'].browse(
|
||||
vals['uom_id'])
|
||||
else:
|
||||
inv_uom = False
|
||||
else:
|
||||
inv_uom = il.uom_id or False
|
||||
std_price = 0.0
|
||||
if pp:
|
||||
std_price = pp.standard_price
|
||||
if inv_uom and inv_uom != pp.uom_id:
|
||||
std_price = pp.uom_id._compute_price(
|
||||
std_price, inv_uom)
|
||||
il.write({'standard_price_company_currency': std_price})
|
||||
return super(AccountInvoiceLine, self).write(vals)
|
||||
|
||||
|
||||
class AccountInvoice(models.Model):
|
||||
_inherit = 'account.invoice'
|
||||
|
||||
margin_invoice_currency = fields.Monetary(
|
||||
string='Margin in Invoice Currency',
|
||||
readonly=True, compute='_compute_margin', store=True,
|
||||
currency_field='currency_id')
|
||||
margin_company_currency = fields.Monetary(
|
||||
string='Margin in Company Currency',
|
||||
readonly=True, compute='_compute_margin', store=True,
|
||||
currency_field='company_currency_id')
|
||||
|
||||
@api.depends(
|
||||
'type',
|
||||
'invoice_line_ids.margin_invoice_currency',
|
||||
'invoice_line_ids.margin_company_currency')
|
||||
def _compute_margin(self):
|
||||
for inv in self:
|
||||
margin_inv_cur = 0.0
|
||||
margin_comp_cur = 0.0
|
||||
if inv.type in ('out_invoice', 'out_refund'):
|
||||
for il in inv.invoice_line_ids:
|
||||
margin_inv_cur += il.margin_invoice_currency
|
||||
margin_comp_cur += il.margin_company_currency
|
||||
inv.margin_invoice_currency = margin_inv_cur
|
||||
inv.margin_company_currency = margin_comp_cur
|
||||
62
account_invoice_margin/account_invoice_report.py
Normal file
62
account_invoice_margin/account_invoice_report.py
Normal file
@@ -0,0 +1,62 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2018 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import models, fields, api
|
||||
|
||||
|
||||
class AccountInvoiceReport(models.Model):
|
||||
_inherit = 'account.invoice.report'
|
||||
|
||||
margin = fields.Float(string='Margin', readonly=True)
|
||||
# why digits=0 ??? Why is it like that in the native "account" module
|
||||
user_currency_margin = fields.Float(
|
||||
string="Margin", compute='_compute_user_currency_margin', digits=0)
|
||||
|
||||
_depends = {
|
||||
'account.invoice': [
|
||||
'account_id', 'amount_total_company_signed',
|
||||
'commercial_partner_id', 'company_id',
|
||||
'currency_id', 'date_due', 'date_invoice', 'fiscal_position_id',
|
||||
'journal_id', 'partner_bank_id', 'partner_id', 'payment_term_id',
|
||||
'residual', 'state', 'type', 'user_id',
|
||||
],
|
||||
'account.invoice.line': [
|
||||
'account_id', 'invoice_id', 'price_subtotal', 'product_id',
|
||||
'quantity', 'uom_id', 'account_analytic_id',
|
||||
'margin_company_currency',
|
||||
],
|
||||
'product.product': ['product_tmpl_id'],
|
||||
'product.template': ['categ_id'],
|
||||
'product.uom': ['category_id', 'factor', 'name', 'uom_type'],
|
||||
'res.currency.rate': ['currency_id', 'name'],
|
||||
'res.partner': ['country_id'],
|
||||
}
|
||||
|
||||
@api.depends('currency_id', 'date', 'margin')
|
||||
def _compute_user_currency_margin(self):
|
||||
context = dict(self._context or {})
|
||||
user_currency_id = self.env.user.company_id.currency_id
|
||||
currency_rate_id = self.env['res.currency.rate'].search([
|
||||
('rate', '=', 1),
|
||||
'|',
|
||||
('company_id', '=', self.env.user.company_id.id),
|
||||
('company_id', '=', False)], limit=1)
|
||||
base_currency_id = currency_rate_id.currency_id
|
||||
ctx = context.copy()
|
||||
for record in self:
|
||||
ctx['date'] = record.date
|
||||
record.user_currency_margin = base_currency_id.with_context(
|
||||
ctx).compute(record.margin, user_currency_id)
|
||||
|
||||
# TODO check for refunds
|
||||
def _sub_select(self):
|
||||
select_str = super(AccountInvoiceReport, self)._sub_select()
|
||||
select_str += ", SUM(ail.margin_company_currency) AS margin"
|
||||
return select_str
|
||||
|
||||
def _select(self):
|
||||
select_str = super(AccountInvoiceReport, self)._select()
|
||||
select_str += ", sub.margin AS margin"
|
||||
return select_str
|
||||
49
account_invoice_margin/account_invoice_view.xml
Normal file
49
account_invoice_margin/account_invoice_view.xml
Normal file
@@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
© 2015-2017 Akretion (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
<record id="view_invoice_line_form" model="ir.ui.view">
|
||||
<field name="name">margin.account.invoice.line.form</field>
|
||||
<field name="model">account.invoice.line</field>
|
||||
<field name="inherit_id" ref="account.view_invoice_line_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="company_id" position="after">
|
||||
<field name="standard_price_company_currency"
|
||||
groups="base.group_no_one"/>
|
||||
<field name="standard_price_invoice_currency"
|
||||
widget="monetary"
|
||||
options="{'currency_field': 'currency_id'}"
|
||||
groups="base.group_no_one"/>
|
||||
<field name="margin_invoice_currency"
|
||||
groups="base.group_no_one"/>
|
||||
<field name="margin_company_currency"
|
||||
groups="base.group_no_one"/>
|
||||
<label for="margin_rate" groups="base.group_no_one"/>
|
||||
<div name="margin_rate" groups="base.group_no_one">
|
||||
<field name="margin_rate" class="oe_inline"/> %
|
||||
</div>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="invoice_form" model="ir.ui.view">
|
||||
<field name="name">margin.account.invoice.form</field>
|
||||
<field name="model">account.invoice</field>
|
||||
<field name="inherit_id" ref="account.invoice_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="move_id" position="after">
|
||||
<field name="margin_invoice_currency"
|
||||
string="Margin" groups="base.group_no_one"/>
|
||||
<field name="margin_company_currency"
|
||||
groups="base.group_no_one"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</odoo>
|
||||
@@ -1,2 +0,0 @@
|
||||
from . import account_move
|
||||
from . import account_invoice_report
|
||||
@@ -1,36 +0,0 @@
|
||||
# Copyright 2018-2019 Akretion France (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class AccountInvoiceReport(models.Model):
|
||||
_inherit = 'account.invoice.report'
|
||||
|
||||
margin = fields.Float(string='Margin', readonly=True)
|
||||
|
||||
# added margin_company_currency on account.move.line
|
||||
_depends = {
|
||||
'account.move': [
|
||||
'name', 'state', 'move_type', 'partner_id', 'invoice_user_id', 'fiscal_position_id',
|
||||
'invoice_date', 'invoice_date_due', 'invoice_payment_term_id', 'partner_bank_id',
|
||||
],
|
||||
'account.move.line': [
|
||||
'quantity', 'price_subtotal', 'amount_residual', 'balance', 'amount_currency',
|
||||
'move_id', 'product_id', 'product_uom_id', 'account_id', 'analytic_account_id',
|
||||
'journal_id', 'company_id', 'currency_id', 'partner_id',
|
||||
'margin_company_currency',
|
||||
],
|
||||
'product.product': ['product_tmpl_id'],
|
||||
'product.template': ['categ_id'],
|
||||
'uom.uom': ['category_id', 'factor', 'name', 'uom_type'],
|
||||
'res.currency.rate': ['currency_id', 'name'],
|
||||
'res.partner': ['country_id'],
|
||||
}
|
||||
|
||||
@api.model
|
||||
def _select(self):
|
||||
select_str = super()._select()
|
||||
select_str += ", line.margin_company_currency * currency_table.rate AS margin"
|
||||
return select_str
|
||||
@@ -1,155 +0,0 @@
|
||||
# Copyright 2015-2021 Akretion France (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class AccountMoveLine(models.Model):
|
||||
_inherit = 'account.move.line'
|
||||
|
||||
standard_price_company_currency = fields.Float(
|
||||
string='Unit Cost Price in Company Currency', readonly=True,
|
||||
digits='Product Price',
|
||||
help="Unit Cost price in company currency in the unit of measure "
|
||||
"of the invoice line (which may be different from the unit "
|
||||
"of measure of the product).")
|
||||
standard_price_invoice_currency = fields.Float(
|
||||
string='Unit Cost Price in Invoice Currency',
|
||||
compute='_compute_margin', store=True, digits='Product Price',
|
||||
help="Unit Cost price in invoice currency in the unit of measure "
|
||||
"of the invoice line.")
|
||||
margin_invoice_currency = fields.Monetary(
|
||||
string='Margin in Invoice Currency', store=True,
|
||||
compute='_compute_margin', currency_field='currency_id')
|
||||
margin_company_currency = fields.Monetary(
|
||||
string='Margin in Company Currency', store=True,
|
||||
compute='_compute_margin', currency_field='company_currency_id')
|
||||
margin_rate = fields.Float(
|
||||
string="Margin Rate", readonly=True, store=True,
|
||||
compute='_compute_margin',
|
||||
digits=(16, 2), help="Margin rate in percentage of the sale price")
|
||||
|
||||
@api.depends(
|
||||
'standard_price_company_currency', 'move_id.currency_id',
|
||||
'move_id.move_type', 'move_id.company_id',
|
||||
'move_id.invoice_date', 'quantity', 'price_subtotal')
|
||||
def _compute_margin(self):
|
||||
for ml in self:
|
||||
standard_price_inv_cur = 0.0
|
||||
margin_inv_cur = 0.0
|
||||
margin_comp_cur = 0.0
|
||||
margin_rate = 0.0
|
||||
move = ml.move_id
|
||||
if move.move_type and move.move_type in ('out_invoice', 'out_refund'):
|
||||
# it works in _get_current_rate
|
||||
# even if we set date = False in context
|
||||
# standard_price_inv_cur is in the UoM of the invoice line
|
||||
date = move.date or fields.Date.context_today(self)
|
||||
company = move.company_id
|
||||
company_currency = company.currency_id
|
||||
standard_price_inv_cur =\
|
||||
company_currency._convert(
|
||||
ml.standard_price_company_currency,
|
||||
ml.currency_id, company, date)
|
||||
margin_inv_cur =\
|
||||
ml.price_subtotal - ml.quantity * standard_price_inv_cur
|
||||
margin_comp_cur = move.currency_id._convert(
|
||||
margin_inv_cur, company_currency, company, date)
|
||||
if ml.price_subtotal:
|
||||
margin_rate = 100 * margin_inv_cur / ml.price_subtotal
|
||||
# for a refund, margin should be negative
|
||||
# but margin rate should stay positive
|
||||
if move.move_type == 'out_refund':
|
||||
margin_inv_cur *= -1
|
||||
margin_comp_cur *= -1
|
||||
ml.standard_price_invoice_currency = standard_price_inv_cur
|
||||
ml.margin_invoice_currency = margin_inv_cur
|
||||
ml.margin_company_currency = margin_comp_cur
|
||||
ml.margin_rate = margin_rate
|
||||
|
||||
# We want to copy standard_price on invoice line for customer
|
||||
# invoice/refunds. We can't do that via on_change of product_id,
|
||||
# because it is not always played when invoice is created from code
|
||||
# => we inherit write/create
|
||||
# We write standard_price_company_currency even on supplier invoice/refunds
|
||||
# because we don't have access to the 'type' of the invoice
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
if vals.get('product_id') and not vals.get('display_type'):
|
||||
pp = self.env['product.product'].browse(vals['product_id'])
|
||||
std_price = pp.standard_price
|
||||
inv_uom_id = vals.get('product_uom_id')
|
||||
if inv_uom_id and inv_uom_id != pp.uom_id.id:
|
||||
inv_uom = self.env['uom.uom'].browse(inv_uom_id)
|
||||
std_price = pp.uom_id._compute_price(
|
||||
std_price, inv_uom)
|
||||
vals['standard_price_company_currency'] = std_price
|
||||
return super().create(vals_list)
|
||||
|
||||
def write(self, vals):
|
||||
if not vals:
|
||||
vals = {}
|
||||
if 'product_id' in vals or 'product_uom_id' in vals:
|
||||
for il in self:
|
||||
if 'product_id' in vals:
|
||||
if vals.get('product_id'):
|
||||
pp = self.env['product.product'].browse(
|
||||
vals['product_id'])
|
||||
else:
|
||||
pp = False
|
||||
else:
|
||||
pp = il.product_id or False
|
||||
# uom_id is NOT a required field
|
||||
if 'product_uom_id' in vals:
|
||||
if vals.get('product_uom_id'):
|
||||
inv_uom = self.env['uom.uom'].browse(
|
||||
vals['product_uom_id'])
|
||||
else:
|
||||
inv_uom = False
|
||||
else:
|
||||
inv_uom = il.uom_id or False
|
||||
std_price = 0.0
|
||||
if pp:
|
||||
std_price = pp.standard_price
|
||||
if inv_uom and inv_uom != pp.uom_id:
|
||||
std_price = pp.uom_id._compute_price(
|
||||
std_price, inv_uom)
|
||||
il.write({'standard_price_company_currency': std_price})
|
||||
return super().write(vals)
|
||||
|
||||
|
||||
class AccountMove(models.Model):
|
||||
_inherit = 'account.move'
|
||||
|
||||
margin_invoice_currency = fields.Monetary(
|
||||
string='Margin in Invoice Currency',
|
||||
compute='_compute_margin', store=True,
|
||||
currency_field='currency_id')
|
||||
margin_company_currency = fields.Monetary(
|
||||
string='Margin in Company Currency',
|
||||
compute='_compute_margin', store=True,
|
||||
currency_field='company_currency_id')
|
||||
|
||||
@api.depends(
|
||||
'move_type',
|
||||
'invoice_line_ids.margin_invoice_currency',
|
||||
'invoice_line_ids.margin_company_currency')
|
||||
def _compute_margin(self):
|
||||
rg_res = self.env['account.move.line'].read_group(
|
||||
[
|
||||
('move_id', 'in', self.ids),
|
||||
('display_type', '=', False),
|
||||
('exclude_from_invoice_tab', '=', False),
|
||||
('move_id.move_type', 'in', ('out_invoice', 'out_refund')),
|
||||
],
|
||||
['move_id', 'margin_invoice_currency:sum', 'margin_company_currency:sum'],
|
||||
['move_id'])
|
||||
mapped_data = dict([(x['move_id'][0], {
|
||||
'margin_invoice_currency': x['margin_invoice_currency'],
|
||||
'margin_company_currency': x['margin_company_currency'],
|
||||
}) for x in rg_res])
|
||||
for move in self:
|
||||
move.margin_invoice_currency = mapped_data.get(move.id, {}).get('margin_invoice_currency')
|
||||
move.margin_company_currency = mapped_data.get(move.id, {}).get('margin_company_currency')
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 9.2 KiB |
@@ -1,55 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2015-2024 Akretion (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
<record id="view_move_form" model="ir.ui.view">
|
||||
<field name="name">margin.account.move.form</field>
|
||||
<field name="model">account.move</field>
|
||||
<field name="inherit_id" ref="account.view_move_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<group name="sale_info_group" position="inside">
|
||||
<field name="margin_invoice_currency"
|
||||
groups="base.group_no_one"
|
||||
attrs="{'invisible': [('move_type', 'not in', ('out_invoice', 'out_refund'))]}"/>
|
||||
<field name="margin_company_currency"
|
||||
groups="base.group_no_one"
|
||||
attrs="{'invisible': [('move_type', 'not in', ('out_invoice', 'out_refund'))]}"/>
|
||||
</group>
|
||||
<xpath expr="//field[@name='invoice_line_ids']/tree/field[@name='price_total']" position="after">
|
||||
<field name="standard_price_invoice_currency" optional="hide" attrs="{'column_invisible': [('parent.move_type', 'not in', ('out_invoice', 'out_refund'))]}"/>
|
||||
<field name="margin_invoice_currency" optional="hide" attrs="{'column_invisible': [('parent.move_type', 'not in', ('out_invoice', 'out_refund'))]}"/>
|
||||
<field name="margin_rate" optional="hide" string="Margin Rate (%)" attrs="{'column_invisible': [('parent.move_type', 'not in', ('out_invoice', 'out_refund'))]}"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='invoice_line_ids']/form//field[@name='price_total']/.." position="inside">
|
||||
<field name="standard_price_company_currency"
|
||||
groups="base.group_no_one" attrs="{'invisible': [('parent.move_type', 'not in', ('out_invoice', 'out_refund'))]}"/>
|
||||
<field name="standard_price_invoice_currency"
|
||||
groups="base.group_no_one" attrs="{'invisible': [('parent.move_type', 'not in', ('out_invoice', 'out_refund'))]}"/>
|
||||
<field name="margin_invoice_currency"
|
||||
groups="base.group_no_one" attrs="{'invisible': [('parent.move_type', 'not in', ('out_invoice', 'out_refund'))]}"/>
|
||||
<field name="margin_company_currency"
|
||||
groups="base.group_no_one" attrs="{'invisible': [('parent.move_type', 'not in', ('out_invoice', 'out_refund'))]}"/>
|
||||
<label for="margin_rate" groups="base.group_no_one" attrs="{'invisible': [('parent.move_type', 'not in', ('out_invoice', 'out_refund'))]}"/>
|
||||
<div name="margin_rate" groups="base.group_no_one" attrs="{'invisible': [('parent.move_type', 'not in', ('out_invoice', 'out_refund'))]}">
|
||||
<field name="margin_rate" class="oe_inline"/> %
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_invoice_tree" model="ir.ui.view">
|
||||
<field name="model">account.move</field>
|
||||
<field name="inherit_id" ref="account.view_invoice_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="amount_residual_signed" position="after">
|
||||
<field name="margin_company_currency" optional="hide" sum="1" invisible="context.get('default_move_type') not in ('out_invoice', 'out_refund')" string="Margin"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
1
account_invoice_transmit_method_street3/__init__.py
Normal file
1
account_invoice_transmit_method_street3/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
26
account_invoice_transmit_method_street3/__manifest__.py
Normal file
26
account_invoice_transmit_method_street3/__manifest__.py
Normal file
@@ -0,0 +1,26 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2018 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
'name': 'partner_address_street3 / account_invoice_transmit_method compat.',
|
||||
'version': '10.0.0.1.0',
|
||||
'category': 'Partner',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Compatibility between partner_address_street3 and account_invoice_transmit_method',
|
||||
'description': """
|
||||
Glue module between partner_address_street3 and account_invoice_transmit_method
|
||||
===============================================================================
|
||||
|
||||
Stupid technical module to workaround an Odoo framework limitation about the inherit of the context attribute in a view.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['partner_address_street3', 'account_invoice_transmit_method'],
|
||||
'data': [
|
||||
'partner_view.xml',
|
||||
],
|
||||
'installable': True,
|
||||
'auto_install': True,
|
||||
}
|
||||
23
account_invoice_transmit_method_street3/partner_view.xml
Normal file
23
account_invoice_transmit_method_street3/partner_view.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2018 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
|
||||
<record id="view_partner_form" model="ir.ui.view">
|
||||
<field name="name">Compatibility partner_address_street3 / account_invoice_transmit_method</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="inherit_id" ref="base.view_partner_form"/>
|
||||
<field name="priority">1000</field>
|
||||
<field name="arch" type="xml">
|
||||
<field name="child_ids" position="attributes">
|
||||
<attribute name="context">{'default_parent_id': active_id, 'default_street': street, 'default_street2': street2, 'default_city': city, 'default_state_id': state_id, 'default_zip': zip, 'default_country_id': country_id, 'default_supplier': supplier, 'default_customer': customer, 'default_lang': lang, 'default_customer_invoice_transmit_method_code': customer_invoice_transmit_method_code, 'default_supplier_invoice_transmit_method_code': supplier_invoice_transmit_method_code, 'default_street3': street3}</attribute>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</odoo>
|
||||
@@ -1,39 +0,0 @@
|
||||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
|
||||
:target: https://www.gnu.org/licenses/agpl-3.0-standalone.html
|
||||
:alt: License: AGPL-3
|
||||
|
||||
Account Invoice Update Wizard
|
||||
=============================
|
||||
|
||||
This module adds a button *Update Invoice* on Customer and Supplier invoices in
|
||||
Open or Paid state. This button starts a wizard which allows the user to update
|
||||
non-legal fields of the invoice:
|
||||
|
||||
* Source Document
|
||||
* Reference/Description
|
||||
* Payment terms (update allowed only to a payment term with same number of terms
|
||||
of the same amount and on invoices without any payment)
|
||||
* Bank Account
|
||||
* Salesman
|
||||
* Notes
|
||||
* Description of invoice lines
|
||||
* Analytic account
|
||||
* Analytic tags
|
||||
|
||||
Bug Tracker
|
||||
===========
|
||||
|
||||
Bugs are tracked on `GitHub Issues
|
||||
<https://github.com/akretion/odoo-usability/issues>`_. In case of trouble, please
|
||||
check there if your issue has already been reported. If you spotted it first,
|
||||
help us smash it by providing detailed and welcomed feedback.
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
||||
* Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
* Florian da Costa <florian.dacosta@akretion.com>
|
||||
* Matthieu Dietrich <matthieu.dietrich@camptocamp.com>
|
||||
* Yannick Vaucher <yannick.vaucher@camptocamp.com>
|
||||
* Mykhailo Panarin <m.panarin@mobilunity.com>
|
||||
* Artem Kostyuk <a.kostyuk@mobilunity.com>
|
||||
@@ -1,2 +1 @@
|
||||
from . import models
|
||||
from . import wizard
|
||||
|
||||
@@ -1,22 +1,37 @@
|
||||
# Copyright 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
# Copyright 2018-2019 Camptocamp
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
# Copyright 2018 Camptocamp
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
'name': 'Account Invoice Update Wizard',
|
||||
'version': '14.0.1.0.0',
|
||||
'version': '8.0.1.0.0',
|
||||
'category': 'Accounting & Finance',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Wizard to update non-legal fields of an open/paid invoice',
|
||||
'description': """
|
||||
Account Invoice Update Wizard
|
||||
=============================
|
||||
|
||||
This module adds a button *Update Invoice* on Customer and Supplier invoices in Open or Paid state. This button starts a wizard which allows the user to update non-legal fields of the invoice:
|
||||
|
||||
* Source Document
|
||||
* Reference/Description
|
||||
* Payment terms (update allowed only to a payment term with same number of terms of the same amount and on invoices without any payment)
|
||||
* Bank Account
|
||||
* Salesman
|
||||
* Notes
|
||||
* Description of invoice lines
|
||||
* Analytic account
|
||||
* Analytic tags
|
||||
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'https://github.com/akretion/odoo-usability',
|
||||
'depends': [
|
||||
'account',
|
||||
],
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['account'],
|
||||
'data': [
|
||||
'security/ir.model.access.csv',
|
||||
'wizard/account_move_update_view.xml',
|
||||
'views/account_move.xml',
|
||||
],
|
||||
'wizard/account_invoice_update_view.xml',
|
||||
'views/account_invoice.xml',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
|
||||
@@ -1,243 +0,0 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * account_invoice_update_wizard
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 14.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: \n"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__price_subtotal
|
||||
msgid "Amount"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__analytic_account_id
|
||||
msgid "Analytic Account"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__analytic_tag_ids
|
||||
msgid "Analytic Tags"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__partner_bank_id
|
||||
msgid "Bank Account"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model_terms:ir.ui.view,arch_db:account_invoice_update_wizard.account_invoice_update_form
|
||||
msgid "Bill Reference"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model_terms:ir.ui.view,arch_db:account_invoice_update_wizard.account_invoice_update_form
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__company_id
|
||||
msgid "Company"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__create_uid
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__create_uid
|
||||
msgid "Created by"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__create_date
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__create_date
|
||||
msgid "Created on"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__currency_id
|
||||
msgid "Currency"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model_terms:ir.ui.view,arch_db:account_invoice_update_wizard.account_invoice_update_form
|
||||
msgid "Customer Reference"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__name
|
||||
msgid "Description"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move__display_name
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__display_name
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__display_name
|
||||
msgid "Display Name"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__display_type
|
||||
msgid "Display Type"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move__id
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__id
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__id
|
||||
msgid "ID"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__invoice_id
|
||||
msgid "Invoice"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__invoice_line_id
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__line_ids
|
||||
msgid "Invoice Lines"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.actions.act_window,name:account_invoice_update_wizard.account_invoice_update_action
|
||||
msgid "Invoice Update Wizard"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model,name:account_invoice_update_wizard.model_account_move
|
||||
msgid "Journal Entry"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move____last_update
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update____last_update
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update____last_update
|
||||
msgid "Last Modified on"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__write_uid
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__write_uid
|
||||
msgid "Last Updated by"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__write_date
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__write_date
|
||||
msgid "Last Updated on"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: code:addons/account_invoice_update_wizard/wizard/account_move_update.py:0
|
||||
#, python-format
|
||||
msgid "Non-legal fields of invoice updated via the Invoice Update wizard."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields.selection,name:account_invoice_update_wizard.selection__account_move_line_update__display_type__line_note
|
||||
msgid "Note"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__partner_id
|
||||
msgid "Partner"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__invoice_payment_term_id
|
||||
msgid "Payment Term"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__quantity
|
||||
msgid "Quantity"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__ref
|
||||
msgid "Reference"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__user_id
|
||||
msgid "Salesperson"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields.selection,name:account_invoice_update_wizard.selection__account_move_line_update__display_type__line_section
|
||||
msgid "Section"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__sequence
|
||||
msgid "Sequence"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__invoice_origin
|
||||
msgid "Source Document"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,help:account_invoice_update_wizard.field_account_move_line_update__display_type
|
||||
msgid "Technical field for UX purpose."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: code:addons/account_invoice_update_wizard/wizard/account_move_update.py:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The original payment term '%s' doesn't have the same terms (number of terms "
|
||||
"and/or amount) as the new payment term '%s'. You can only switch to a "
|
||||
"payment term that has the same number of terms with the same amount."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: code:addons/account_invoice_update_wizard/wizard/account_move_update.py:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"This wizard doesn't support the update of payment terms on an invoice which "
|
||||
"is partially or fully paid."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__move_type
|
||||
msgid "Type"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model_terms:ir.ui.view,arch_db:account_invoice_update_wizard.account_invoice_update_form
|
||||
msgid "Update"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model_terms:ir.ui.view,arch_db:account_invoice_update_wizard.view_move_form_inherit
|
||||
msgid "Update Invoice"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model_terms:ir.ui.view,arch_db:account_invoice_update_wizard.account_invoice_update_form
|
||||
msgid "Update Invoice Wizard"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model,name:account_invoice_update_wizard.model_account_move_line_update
|
||||
msgid "Update non-legal fields of invoice lines"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__parent_id
|
||||
msgid "Wizard"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model,name:account_invoice_update_wizard.model_account_move_update
|
||||
msgid "Wizard to update non-legal fields of invoice"
|
||||
msgstr ""
|
||||
@@ -1,250 +0,0 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * account_invoice_update_wizard
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 14.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: \n"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__price_subtotal
|
||||
msgid "Amount"
|
||||
msgstr "Montant"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__analytic_account_id
|
||||
msgid "Analytic Account"
|
||||
msgstr "Compte Analytique"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__analytic_tag_ids
|
||||
msgid "Analytic Tags"
|
||||
msgstr "Tag Analytique"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__partner_bank_id
|
||||
msgid "Bank Account"
|
||||
msgstr "Compte Bancaire"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model_terms:ir.ui.view,arch_db:account_invoice_update_wizard.account_invoice_update_form
|
||||
#, fuzzy
|
||||
msgid "Bill Reference"
|
||||
msgstr "Reference Client"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model_terms:ir.ui.view,arch_db:account_invoice_update_wizard.account_invoice_update_form
|
||||
msgid "Cancel"
|
||||
msgstr "Annuler"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__company_id
|
||||
msgid "Company"
|
||||
msgstr "Société"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__create_uid
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__create_uid
|
||||
msgid "Created by"
|
||||
msgstr "Créé par"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__create_date
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__create_date
|
||||
msgid "Created on"
|
||||
msgstr "Créé le"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__currency_id
|
||||
msgid "Currency"
|
||||
msgstr "Devise"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model_terms:ir.ui.view,arch_db:account_invoice_update_wizard.account_invoice_update_form
|
||||
#, fuzzy
|
||||
msgid "Customer Reference"
|
||||
msgstr "Reference Client"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__name
|
||||
msgid "Description"
|
||||
msgstr "Description"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move__display_name
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__display_name
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__display_name
|
||||
msgid "Display Name"
|
||||
msgstr "Nom"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__display_type
|
||||
msgid "Display Type"
|
||||
msgstr "Type Affichage"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move__id
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__id
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__id
|
||||
msgid "ID"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__invoice_id
|
||||
msgid "Invoice"
|
||||
msgstr "Facture"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__invoice_line_id
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__line_ids
|
||||
msgid "Invoice Lines"
|
||||
msgstr "Ligne de factures"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.actions.act_window,name:account_invoice_update_wizard.account_invoice_update_action
|
||||
msgid "Invoice Update Wizard"
|
||||
msgstr "Assistance de mise à jour de la facture"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model,name:account_invoice_update_wizard.model_account_move
|
||||
msgid "Journal Entry"
|
||||
msgstr "Entrée comptable"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move____last_update
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update____last_update
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update____last_update
|
||||
msgid "Last Modified on"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__write_uid
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__write_uid
|
||||
msgid "Last Updated by"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__write_date
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__write_date
|
||||
msgid "Last Updated on"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: code:addons/account_invoice_update_wizard/wizard/account_move_update.py:0
|
||||
#, python-format
|
||||
msgid "Non-legal fields of invoice updated via the Invoice Update wizard."
|
||||
msgstr "Champs non légaux mis à jour via l'assistant"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields.selection,name:account_invoice_update_wizard.selection__account_move_line_update__display_type__line_note
|
||||
msgid "Note"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__partner_id
|
||||
msgid "Partner"
|
||||
msgstr "Client"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__invoice_payment_term_id
|
||||
msgid "Payment Term"
|
||||
msgstr "Condition de paiement"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__quantity
|
||||
msgid "Quantity"
|
||||
msgstr "Quantité"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__ref
|
||||
#, fuzzy
|
||||
msgid "Reference"
|
||||
msgstr "Reference Client"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__user_id
|
||||
msgid "Salesperson"
|
||||
msgstr "Vendeur"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields.selection,name:account_invoice_update_wizard.selection__account_move_line_update__display_type__line_section
|
||||
msgid "Section"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__sequence
|
||||
msgid "Sequence"
|
||||
msgstr "Sequence"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__invoice_origin
|
||||
msgid "Source Document"
|
||||
msgstr "Origine du document"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,help:account_invoice_update_wizard.field_account_move_line_update__display_type
|
||||
msgid "Technical field for UX purpose."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: code:addons/account_invoice_update_wizard/wizard/account_move_update.py:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The original payment term '%s' doesn't have the same terms (number of terms "
|
||||
"and/or amount) as the new payment term '%s'. You can only switch to a "
|
||||
"payment term that has the same number of terms with the same amount."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: code:addons/account_invoice_update_wizard/wizard/account_move_update.py:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"This wizard doesn't support the update of payment terms on an invoice which "
|
||||
"is partially or fully paid."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_update__move_type
|
||||
msgid "Type"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model_terms:ir.ui.view,arch_db:account_invoice_update_wizard.account_invoice_update_form
|
||||
msgid "Update"
|
||||
msgstr "Mettre à jour"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model_terms:ir.ui.view,arch_db:account_invoice_update_wizard.view_move_form_inherit
|
||||
msgid "Update Invoice"
|
||||
msgstr "Mettre à jour"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model_terms:ir.ui.view,arch_db:account_invoice_update_wizard.account_invoice_update_form
|
||||
msgid "Update Invoice Wizard"
|
||||
msgstr "Assistant de mise à jour"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model,name:account_invoice_update_wizard.model_account_move_line_update
|
||||
msgid "Update non-legal fields of invoice lines"
|
||||
msgstr "Mettre à jour les champs non légaux des lignes de facture"
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model.fields,field_description:account_invoice_update_wizard.field_account_move_line_update__parent_id
|
||||
msgid "Wizard"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_invoice_update_wizard
|
||||
#: model:ir.model,name:account_invoice_update_wizard.model_account_move_update
|
||||
msgid "Wizard to update non-legal fields of invoice"
|
||||
msgstr "Assistant pour mettre à jours les champs non légaux"
|
||||
|
||||
#~ msgid "Account"
|
||||
#~ msgstr "Compte"
|
||||
@@ -1 +0,0 @@
|
||||
from . import account_move
|
||||
@@ -1,18 +0,0 @@
|
||||
# Copyright 2019-2022 Camptocamp
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import models
|
||||
|
||||
|
||||
class AccountMove(models.Model):
|
||||
_inherit = 'account.move'
|
||||
|
||||
def prepare_update_wizard(self):
|
||||
self.ensure_one()
|
||||
wizard = self.env['account.move.update']
|
||||
res = wizard._prepare_default_get(self)
|
||||
action = self.env["ir.actions.actions"]._for_xml_id(
|
||||
'account_invoice_update_wizard.account_invoice_update_action')
|
||||
action['name'] = "Update Wizard"
|
||||
action['res_id'] = wizard.create(res).id
|
||||
return action
|
||||
@@ -1,3 +0,0 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_account_move_update,account.move.update.user,model_account_move_update,account.group_account_invoice,1,1,1,1
|
||||
access_account_move_line_update,account.move.line.update.user,model_account_move_line_update,account.group_account_invoice,1,1,1,1
|
||||
|
Binary file not shown.
|
Before Width: | Height: | Size: 9.2 KiB |
@@ -1 +1 @@
|
||||
from . import test_account_move_update_wizard
|
||||
from . import test_account_invoice_update_wizard
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2018 Camptocamp
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo.tests.common import TransactionCase
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class TestAccountInvoiceUpdateWizard(TransactionCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestAccountInvoiceUpdateWizard, self).setUp()
|
||||
self.customer12 = self.env.ref('base.res_partner_12')
|
||||
self.product16 = self.env.ref('product.product_product_16')
|
||||
self.product24 = self.env.ref('product.product_product_24')
|
||||
uom_unit = self.env.ref('product.product_uom_categ_unit')
|
||||
|
||||
self.invoice1 = self.env['account.invoice'].create({
|
||||
'name': 'Test invoice',
|
||||
'partner_id': self.customer12.id,
|
||||
})
|
||||
self.inv_line1 = self.env['account.invoice.line'].create({
|
||||
'invoice_id': self.invoice1.id,
|
||||
'name': "Line1",
|
||||
'product_id': self.product16.id,
|
||||
'product_uom_id': uom_unit.id,
|
||||
'account_id': self.invoice1.account_id.id,
|
||||
'price_unit': 42.0,
|
||||
})
|
||||
self.inv_line2 = self.env['account.invoice.line'].create({
|
||||
'invoice_id': self.invoice1.id,
|
||||
'name': "Line2",
|
||||
'product_id': self.product24.id,
|
||||
'product_uom_id': uom_unit.id,
|
||||
'account_id': self.invoice1.account_id.id,
|
||||
'price_unit': 1111.1,
|
||||
})
|
||||
|
||||
self.aa1 = self.env.ref('analytic.analytic_partners_camp_to_camp')
|
||||
self.aa2 = self.env.ref('analytic.analytic_nebula')
|
||||
self.atag1 = self.env.ref('analytic.tag_contract')
|
||||
self.atag2 = self.env['account.analytic.tag'].create({
|
||||
'name': u'の',
|
||||
})
|
||||
|
||||
def create_wizard(self):
|
||||
UpdateWizard = self.env['account.invoice.update'].with_context(
|
||||
active_model='account.invoice',
|
||||
active_id=self.invoice1.id)
|
||||
self.wiz = UpdateWizard.create({})
|
||||
|
||||
def test_add_analytic_account_line1(self):
|
||||
""" Add analytic account on an invoice line
|
||||
after the invoice has been approved.
|
||||
|
||||
This will:
|
||||
- update the move line
|
||||
- create a new analytic line.
|
||||
"""
|
||||
self.invoice1.action_invoice_open()
|
||||
self.create_wizard()
|
||||
|
||||
wiz_line = self.wiz.line_ids.filtered(
|
||||
lambda rec: rec.invoice_line_id == self.inv_line1)
|
||||
wiz_line.account_analytic_id = self.aa1
|
||||
self.wiz.run()
|
||||
|
||||
related_ml = self.invoice1.move_id.line_ids.filtered(
|
||||
lambda rec: rec.product_id == self.product16)
|
||||
self.assertEqual(related_ml.analytic_account_id, self.aa1)
|
||||
self.assertEqual(related_ml.analytic_line_ids.account_id, self.aa1)
|
||||
|
||||
def test_change_analytic_account_line1(self):
|
||||
""" Change analytic account on an invoice line
|
||||
after the invoice has been approved.
|
||||
|
||||
This will:
|
||||
- update the move line
|
||||
- update the existing analytic line."""
|
||||
self.inv_line1.account_analytic_id = self.aa2
|
||||
|
||||
self.invoice1.action_invoice_open()
|
||||
self.create_wizard()
|
||||
|
||||
wiz_line = self.wiz.line_ids.filtered(
|
||||
lambda rec: rec.invoice_line_id == self.inv_line1)
|
||||
wiz_line.account_analytic_id = self.aa1
|
||||
self.wiz.run()
|
||||
|
||||
related_ml = self.invoice1.move_id.line_ids.filtered(
|
||||
lambda rec: rec.product_id == self.product16)
|
||||
self.assertEqual(related_ml.analytic_account_id, self.aa1)
|
||||
self.assertEqual(related_ml.analytic_line_ids.account_id, self.aa1)
|
||||
|
||||
def test_error_grouped_move_lines(self):
|
||||
""" Change analytic account on an invoice line
|
||||
after the invoice has been approved where both
|
||||
lines were grouped in the same move line.
|
||||
|
||||
This will raise an error.
|
||||
"""
|
||||
self.invoice1.journal_id.group_invoice_lines = True
|
||||
|
||||
self.inv_line2.product_id = self.product16
|
||||
self.inv_line2.unit_price = 42.0
|
||||
|
||||
self.invoice1.action_invoice_open()
|
||||
self.create_wizard()
|
||||
|
||||
line1 = self.wiz.line_ids[0]
|
||||
line1.account_analytic_id = self.aa1
|
||||
with self.assertRaises(UserError):
|
||||
self.wiz.run()
|
||||
|
||||
def test_add_analytic_tags_line1(self):
|
||||
""" Add analytic tags on an invoice line
|
||||
after the invoice has been approved.
|
||||
|
||||
This will update move line.
|
||||
"""
|
||||
self.invoice1.action_invoice_open()
|
||||
self.create_wizard()
|
||||
|
||||
wiz_line = self.wiz.line_ids.filtered(
|
||||
lambda rec: rec.invoice_line_id == self.inv_line1)
|
||||
wiz_line.analytic_tag_ids = self.atag2
|
||||
self.wiz.run()
|
||||
|
||||
related_ml = self.invoice1.move_id.line_ids.filtered(
|
||||
lambda rec: rec.product_id == self.product16)
|
||||
self.assertEqual(related_ml.analytic_tag_ids, self.atag2)
|
||||
self.assertFalse(related_ml.analytic_line_ids)
|
||||
|
||||
def test_change_analytic_tags_line1(self):
|
||||
""" Change analytic tags on an invoice line
|
||||
after the invoice has been approved.
|
||||
|
||||
It will update move line and analytic line
|
||||
"""
|
||||
self.inv_line1.account_analytic_id = self.aa2
|
||||
self.inv_line1.analytic_tag_ids = self.atag1
|
||||
|
||||
self.invoice1.action_invoice_open()
|
||||
self.create_wizard()
|
||||
|
||||
wiz_line = self.wiz.line_ids.filtered(
|
||||
lambda rec: rec.invoice_line_id == self.inv_line1)
|
||||
wiz_line.analytic_tag_ids = self.atag2
|
||||
self.wiz.run()
|
||||
|
||||
related_ml = self.invoice1.move_id.line_ids.filtered(
|
||||
lambda rec: rec.product_id == self.product16)
|
||||
self.assertEqual(related_ml.analytic_tag_ids, self.atag2)
|
||||
self.assertEqual(related_ml.analytic_line_ids.tag_ids, self.atag2)
|
||||
|
||||
def test_add_analytic_info_line1(self):
|
||||
""" Add analytic account and tags on an invoice line
|
||||
after the invoice has been approved.
|
||||
|
||||
This will:
|
||||
- update move line
|
||||
- create an analytic line
|
||||
"""
|
||||
self.invoice1.action_invoice_open()
|
||||
self.create_wizard()
|
||||
|
||||
wiz_line = self.wiz.line_ids.filtered(
|
||||
lambda rec: rec.invoice_line_id == self.inv_line1)
|
||||
wiz_line.account_analytic_id = self.aa1
|
||||
wiz_line.analytic_tag_ids = self.atag2
|
||||
self.wiz.run()
|
||||
|
||||
related_ml = self.invoice1.move_id.line_ids.filtered(
|
||||
lambda rec: rec.product_id == self.product16)
|
||||
self.assertEqual(related_ml.analytic_account_id, self.aa1)
|
||||
self.assertEqual(related_ml.analytic_tag_ids, self.atag2)
|
||||
self.assertEqual(related_ml.analytic_line_ids.account_id, self.aa1)
|
||||
self.assertEqual(related_ml.analytic_line_ids.tag_ids, self.atag2)
|
||||
|
||||
def test_empty_analytic_account_line1(self):
|
||||
""" Remove analytic account
|
||||
after the invoice has been approved.
|
||||
|
||||
This will raise an error as it is not implemented.
|
||||
"""
|
||||
self.inv_line1.account_analytic_id = self.aa2
|
||||
|
||||
self.invoice1.action_invoice_open()
|
||||
self.create_wizard()
|
||||
|
||||
wiz_line = self.wiz.line_ids.filtered(
|
||||
lambda rec: rec.invoice_line_id == self.inv_line1)
|
||||
wiz_line.account_analytic_id = False
|
||||
self.wiz.run()
|
||||
related_ml = self.invoice1.move_id.line_ids.filtered(
|
||||
lambda rec: rec.product_id == self.product16)
|
||||
self.assertFalse(related_ml.analytic_account_id)
|
||||
self.assertFalse(related_ml.analytic_line_ids)
|
||||
@@ -1,173 +0,0 @@
|
||||
# Copyright 2018-2022 Camptocamp
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo.tests.common import SavepointCase
|
||||
|
||||
|
||||
class TestAccountInvoiceUpdateWizard(SavepointCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.customer12 = cls.env.ref('base.res_partner_12')
|
||||
cls.product16 = cls.env.ref('product.product_product_16')
|
||||
uom_unit = cls.env.ref('uom.product_uom_categ_unit')
|
||||
|
||||
cls.move1 = cls.env['account.move'].create({
|
||||
'name': 'Test invoice',
|
||||
'partner_id': cls.customer12.id,
|
||||
'move_type': 'out_invoice',
|
||||
'invoice_line_ids': [
|
||||
[0, None, {
|
||||
'name': 'Line1',
|
||||
'product_id': cls.product16.id,
|
||||
'product_uom_id': uom_unit.id,
|
||||
'quantity': 1,
|
||||
'price_unit': 42.0,
|
||||
'credit': 42.0,
|
||||
'debit': 0
|
||||
}],
|
||||
],
|
||||
})
|
||||
|
||||
cls.aa1 = cls.env.ref('analytic.analytic_partners_camp_to_camp')
|
||||
cls.aa2 = cls.env.ref('analytic.analytic_nebula')
|
||||
cls.atag1 = cls.env.ref('analytic.tag_contract')
|
||||
cls.atag2 = cls.env['account.analytic.tag'].create({
|
||||
'name': 'の',
|
||||
})
|
||||
|
||||
def create_wizard(self, move):
|
||||
res = move.prepare_update_wizard()
|
||||
self.wiz = self.env['account.move.update'].browse(res['res_id'])
|
||||
|
||||
def test_add_analytic_account_line1(self):
|
||||
""" Add analytic account on a move line
|
||||
after the move has been approved.
|
||||
|
||||
This will:
|
||||
- update the move line
|
||||
- create a new analytic line.
|
||||
"""
|
||||
self.move1._post()
|
||||
self.create_wizard(self.move1)
|
||||
|
||||
wiz_line = self.wiz.line_ids.filtered(
|
||||
lambda rec: rec.invoice_line_id.product_id.id == self.product16.id)
|
||||
wiz_line.analytic_account_id = self.aa1
|
||||
self.wiz.run()
|
||||
|
||||
related_ml = self.move1.invoice_line_ids.filtered(
|
||||
lambda rec: rec.product_id == self.product16)
|
||||
self.assertEqual(related_ml.analytic_account_id, self.aa1)
|
||||
self.assertEqual(related_ml.analytic_line_ids.account_id, self.aa1)
|
||||
|
||||
def test_change_analytic_account_line1(self):
|
||||
""" Change analytic account on a move line
|
||||
after the move has been approved.
|
||||
|
||||
This will:
|
||||
- update the move line
|
||||
- update the existing analytic line."""
|
||||
move_line1 = self.move1.invoice_line_ids.filtered(lambda rec: rec.product_id == self.product16)
|
||||
move_line1.analytic_account_id = self.aa2
|
||||
|
||||
self.move1._post()
|
||||
self.create_wizard(self.move1)
|
||||
|
||||
wiz_line = self.wiz.line_ids.filtered(
|
||||
lambda rec: rec.invoice_line_id.product_id.id == self.product16.id)
|
||||
wiz_line.analytic_account_id = self.aa1
|
||||
self.wiz.run()
|
||||
|
||||
related_ml = self.move1.invoice_line_ids.filtered(
|
||||
lambda rec: rec.product_id == self.product16)
|
||||
self.assertEqual(related_ml.analytic_account_id, self.aa1)
|
||||
self.assertEqual(related_ml.analytic_line_ids.account_id, self.aa1)
|
||||
|
||||
def test_add_analytic_tags_line1(self):
|
||||
""" Add analytic tags on a move line
|
||||
after the move has been approved.
|
||||
|
||||
This will update move line.
|
||||
"""
|
||||
self.move1._post()
|
||||
self.create_wizard(self.move1)
|
||||
|
||||
wiz_line = self.wiz.line_ids.filtered(
|
||||
lambda rec: rec.invoice_line_id.product_id.id == self.product16.id)
|
||||
wiz_line.analytic_tag_ids = self.atag2
|
||||
self.wiz.run()
|
||||
|
||||
related_ml = self.move1.invoice_line_ids.filtered(
|
||||
lambda rec: rec.product_id == self.product16)
|
||||
self.assertEqual(related_ml.analytic_tag_ids, self.atag2)
|
||||
self.assertFalse(related_ml.analytic_line_ids)
|
||||
|
||||
def test_change_analytic_tags_line1(self):
|
||||
""" Change analytic tags on a move line
|
||||
after the move has been approved.
|
||||
|
||||
It will update move line and analytic line
|
||||
"""
|
||||
move_line1 = self.move1.invoice_line_ids.filtered(lambda rec: rec.product_id == self.product16)
|
||||
move_line1.analytic_account_id = self.aa2
|
||||
move_line1.analytic_tag_ids = self.atag1
|
||||
|
||||
self.move1._post()
|
||||
self.create_wizard(self.move1)
|
||||
|
||||
wiz_line = self.wiz.line_ids.filtered(
|
||||
lambda rec: rec.invoice_line_id.product_id.id == self.product16.id)
|
||||
wiz_line.analytic_tag_ids = self.atag2
|
||||
self.wiz.run()
|
||||
|
||||
related_ml = self.move1.invoice_line_ids.filtered(
|
||||
lambda rec: rec.product_id == self.product16)
|
||||
self.assertEqual(related_ml.analytic_tag_ids, self.atag2)
|
||||
self.assertEqual(related_ml.analytic_line_ids.tag_ids, self.atag2)
|
||||
|
||||
def test_add_analytic_info_line1(self):
|
||||
""" Add analytic account and tags on a move line
|
||||
after the move has been approved.
|
||||
|
||||
This will:
|
||||
- update move line
|
||||
- create an analytic line
|
||||
"""
|
||||
self.move1._post()
|
||||
self.create_wizard(self.move1)
|
||||
|
||||
wiz_line = self.wiz.line_ids.filtered(
|
||||
lambda rec: rec.invoice_line_id.product_id.id == self.product16.id)
|
||||
wiz_line.analytic_account_id = self.aa1
|
||||
wiz_line.analytic_tag_ids = self.atag2
|
||||
self.wiz.run()
|
||||
|
||||
related_ml = self.move1.invoice_line_ids.filtered(
|
||||
lambda rec: rec.product_id == self.product16)
|
||||
self.assertEqual(related_ml.analytic_account_id, self.aa1)
|
||||
self.assertEqual(related_ml.analytic_tag_ids, self.atag2)
|
||||
self.assertEqual(related_ml.analytic_line_ids.account_id, self.aa1)
|
||||
self.assertEqual(related_ml.analytic_line_ids.tag_ids, self.atag2)
|
||||
|
||||
def test_empty_analytic_account_line1(self):
|
||||
""" Remove analytic account
|
||||
after the move has been approved.
|
||||
|
||||
This will raise an error as it is not implemented.
|
||||
"""
|
||||
move_line1 = self.move1.invoice_line_ids.filtered(lambda rec: rec.product_id == self.product16)
|
||||
move_line1.analytic_account_id = self.aa2
|
||||
|
||||
self.move1._post()
|
||||
self.create_wizard(self.move1)
|
||||
|
||||
wiz_line = self.wiz.line_ids.filtered(
|
||||
lambda rec: rec.invoice_line_id.product_id.id == self.product16.id)
|
||||
wiz_line.analytic_account_id = False
|
||||
self.wiz.run()
|
||||
related_ml = self.move1.invoice_line_ids.filtered(
|
||||
lambda rec: rec.product_id == self.product16)
|
||||
self.assertFalse(related_ml.analytic_account_id)
|
||||
self.assertFalse(related_ml.analytic_line_ids)
|
||||
29
account_invoice_update_wizard/views/account_invoice.xml
Normal file
29
account_invoice_update_wizard/views/account_invoice.xml
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
© 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
<record id="invoice_supplier_form" model="ir.ui.view">
|
||||
<field name="model">account.invoice</field>
|
||||
<field name="inherit_id" ref="account.invoice_supplier_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<button name="action_invoice_cancel" position="before">
|
||||
<button name="%(account_invoice_update_action)d" type="action" string="Update Invoice" states="open,paid" groups="account.group_account_invoice"/>
|
||||
</button>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="invoice_form" model="ir.ui.view">
|
||||
<field name="model">account.invoice</field>
|
||||
<field name="inherit_id" ref="account.invoice_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<button name="action_invoice_cancel" position="before">
|
||||
<button name="%(account_invoice_update_action)d" type="action" string="Update Invoice" states="open,paid" groups="account.group_account_invoice"/>
|
||||
</button>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,20 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
<record id="view_move_form_inherit" model="ir.ui.view">
|
||||
<field name="model">account.move</field>
|
||||
<field name="inherit_id" ref="account.view_move_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<button name="button_draft" position="before">
|
||||
<button name="prepare_update_wizard" type="object" string="Update Invoice" groups="account.group_account_invoice" attrs="{'invisible': ['|', ('state', '!=', 'posted'), ('move_type', '=', 'entry')]}"/>
|
||||
<button name="prepare_update_wizard" type="object" string="Update Entry" groups="account.group_account_invoice" attrs="{'invisible': ['|', ('state', '!=', 'posted'), ('move_type', '!=', 'entry')]}"/>
|
||||
</button>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1 +1 @@
|
||||
from . import account_move_update
|
||||
from . import account_invoice_update
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# Copyright 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
# Copyright 2018-2022 Camptocamp
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
# Copyright 2018 Camptocamp
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import models, fields, api, _
|
||||
@@ -7,35 +8,38 @@ from odoo.exceptions import UserError
|
||||
import odoo.addons.decimal_precision as dp
|
||||
|
||||
|
||||
class AccountMoveUpdate(models.TransientModel):
|
||||
_name = 'account.move.update'
|
||||
class AccountInvoiceUpdate(models.TransientModel):
|
||||
_name = 'account.invoice.update'
|
||||
_description = 'Wizard to update non-legal fields of invoice'
|
||||
|
||||
invoice_id = fields.Many2one(
|
||||
'account.move', string='Invoice', required=True,
|
||||
'account.invoice', string='Invoice', required=True,
|
||||
readonly=True)
|
||||
move_type = fields.Selection(related='invoice_id.move_type')
|
||||
company_id = fields.Many2one(related='invoice_id.company_id')
|
||||
partner_id = fields.Many2one(related='invoice_id.partner_id')
|
||||
type = fields.Selection(related='invoice_id.type', readonly=True)
|
||||
company_id = fields.Many2one(
|
||||
related='invoice_id.company_id', readonly=True)
|
||||
partner_id = fields.Many2one(
|
||||
related='invoice_id.partner_id', readonly=True)
|
||||
user_id = fields.Many2one('res.users', string='Salesperson')
|
||||
invoice_payment_term_id = fields.Many2one(
|
||||
payment_term_id = fields.Many2one(
|
||||
'account.payment.term', string='Payment Term')
|
||||
ref = fields.Char(string='Reference') # field label is customized in the view
|
||||
invoice_date = fields.Date()
|
||||
invoice_origin = fields.Char(string='Source Document')
|
||||
reference = fields.Char(string='Invoice Reference')
|
||||
name = fields.Char(string='Reference/Description')
|
||||
origin = fields.Char(string='Source Document')
|
||||
comment = fields.Text('Additional Information')
|
||||
partner_bank_id = fields.Many2one(
|
||||
'res.partner.bank', string='Bank Account')
|
||||
line_ids = fields.One2many(
|
||||
'account.move.line.update', 'parent_id', string='Invoice Lines')
|
||||
'account.invoice.line.update', 'parent_id', string='Invoice Lines')
|
||||
|
||||
@api.model
|
||||
def _simple_fields2update(self):
|
||||
'''List boolean, date, datetime, char, text fields'''
|
||||
return ['ref', 'invoice_origin', 'invoice_date']
|
||||
return ['reference', 'name', 'origin', 'comment']
|
||||
|
||||
@api.model
|
||||
def _m2o_fields2update(self):
|
||||
return ['invoice_payment_term_id', 'user_id', 'partner_bank_id']
|
||||
return ['payment_term_id', 'user_id', 'partner_bank_id']
|
||||
|
||||
@api.model
|
||||
def _prepare_default_get(self, invoice):
|
||||
@@ -49,21 +53,27 @@ class AccountMoveUpdate(models.TransientModel):
|
||||
aa_tags = [(6, 0, aa_tags.ids)] if aa_tags else False
|
||||
res['line_ids'].append([0, 0, {
|
||||
'invoice_line_id': line.id,
|
||||
'sequence': line.sequence,
|
||||
'name': line.name,
|
||||
'quantity': line.quantity,
|
||||
'price_subtotal': line.price_subtotal,
|
||||
'analytic_account_id': line.analytic_account_id.id,
|
||||
'currency_id': line.currency_id.id,
|
||||
'account_analytic_id': line.account_analytic_id.id,
|
||||
'analytic_tag_ids': aa_tags,
|
||||
'display_type': line.display_type,
|
||||
}])
|
||||
}])
|
||||
return res
|
||||
|
||||
@api.onchange('move_type')
|
||||
def move_type_on_change(self):
|
||||
@api.model
|
||||
def default_get(self, fields_list):
|
||||
res = super(AccountInvoiceUpdate, self).default_get(fields_list)
|
||||
assert self._context.get('active_model') == 'account.invoice',\
|
||||
'active_model should be account.invoice'
|
||||
inv = self.env['account.invoice'].browse(self._context['active_id'])
|
||||
res = self._prepare_default_get(inv)
|
||||
return res
|
||||
|
||||
@api.onchange('type')
|
||||
def type_on_change(self):
|
||||
res = {'domain': {}}
|
||||
if self.move_type in ('out_invoice', 'out_refund'):
|
||||
if self.type in ('out_invoice', 'out_refund'):
|
||||
res['domain']['partner_bank_id'] =\
|
||||
"[('partner_id.ref_company_ids', 'in', [company_id])]"
|
||||
else:
|
||||
@@ -71,6 +81,7 @@ class AccountMoveUpdate(models.TransientModel):
|
||||
"[('partner_id', '=', partner_id)]"
|
||||
return res
|
||||
|
||||
@api.multi
|
||||
def _prepare_invoice(self):
|
||||
vals = {}
|
||||
inv = self.invoice_id
|
||||
@@ -80,8 +91,8 @@ class AccountMoveUpdate(models.TransientModel):
|
||||
for m2ofield in self._m2o_fields2update():
|
||||
if self[m2ofield] != inv[m2ofield]:
|
||||
vals[m2ofield] = self[m2ofield].id or False
|
||||
if 'invoice_payment_term_id' in vals:
|
||||
pterm_list = self.invoice_payment_term_id.compute(
|
||||
if 'payment_term_id' in vals:
|
||||
pterm_list = self.payment_term_id.compute(
|
||||
value=1, date_ref=inv.date_invoice)[0]
|
||||
if pterm_list:
|
||||
vals['date_due'] = max(line[0] for line in pterm_list)
|
||||
@@ -89,15 +100,15 @@ class AccountMoveUpdate(models.TransientModel):
|
||||
|
||||
@api.model
|
||||
def _line_simple_fields2update(self):
|
||||
return ["name"]
|
||||
return ["name",]
|
||||
|
||||
@api.model
|
||||
def _line_m2o_fields2update(self):
|
||||
return ["analytic_account_id"]
|
||||
return ["account_analytic_id",]
|
||||
|
||||
@api.model
|
||||
def _line_m2m_fields2update(self):
|
||||
return ["analytic_tag_ids"]
|
||||
return ["analytic_tag_ids",]
|
||||
|
||||
@api.model
|
||||
def _prepare_invoice_line(self, line):
|
||||
@@ -113,45 +124,87 @@ class AccountMoveUpdate(models.TransientModel):
|
||||
vals[field] = [(6, 0, line[field].ids)]
|
||||
return vals
|
||||
|
||||
def _prepare_move_line_and_analytic_line(self, inv_line):
|
||||
@api.multi
|
||||
def _prepare_move(self):
|
||||
mvals = {}
|
||||
inv = self.invoice_id
|
||||
ini_ref = inv.move_id.ref
|
||||
ref = inv.reference or inv.name
|
||||
if ini_ref != ref:
|
||||
mvals['ref'] = ref
|
||||
return mvals
|
||||
|
||||
@api.multi
|
||||
def _get_matching_inv_line(self, move_line):
|
||||
""" Find matching invoice line by product """
|
||||
# TODO make it accept more case as lines won't
|
||||
# be grouped unless journal.group_invoice_line is True
|
||||
inv_line = self.invoice_id.invoice_line_ids.filtered(
|
||||
lambda rec: rec.product_id == move_line.product_id)
|
||||
if len(inv_line) <> 1:
|
||||
raise UserError(
|
||||
"Cannot match a single invoice line to move line %s" %
|
||||
move_line.name)
|
||||
return inv_line
|
||||
|
||||
@api.multi
|
||||
def _prepare_move_line(self, inv_line):
|
||||
mlvals = {}
|
||||
alvals = {}
|
||||
inv_line_upd = self.line_ids.filtered(
|
||||
lambda rec: rec.invoice_line_id == inv_line)
|
||||
|
||||
ini_aa = inv_line.analytic_account_id
|
||||
new_aa = inv_line_upd.analytic_account_id
|
||||
ini_aa = inv_line.account_analytic_id
|
||||
new_aa = inv_line_upd.account_analytic_id
|
||||
|
||||
if ini_aa != new_aa:
|
||||
mlvals['analytic_account_id'] = new_aa.id
|
||||
alvals['account_id'] = new_aa.id
|
||||
|
||||
ini_aa_tags = inv_line.analytic_tag_ids
|
||||
new_aa_tags = inv_line_upd.analytic_tag_ids
|
||||
|
||||
if ini_aa_tags != new_aa_tags:
|
||||
mlvals['analytic_tag_ids'] = [(6, None, new_aa_tags.ids)]
|
||||
alvals['tag_ids'] = [(6, None, new_aa_tags.ids)]
|
||||
return mlvals, alvals
|
||||
return mlvals
|
||||
|
||||
@api.multi
|
||||
def _prepare_analytic_line(self, inv_line):
|
||||
alvals = {}
|
||||
inv_line_upd = self.line_ids.filtered(
|
||||
lambda rec: rec.invoice_line_id == inv_line)
|
||||
|
||||
ini_aa = inv_line.account_analytic_id
|
||||
new_aa = inv_line_upd.account_analytic_id
|
||||
|
||||
if ini_aa != new_aa:
|
||||
alvals['account_id'] = new_aa.id
|
||||
|
||||
ini_aa_tags = inv_line.analytic_tag_ids
|
||||
new_aa_tags = inv_line_upd.analytic_tag_ids
|
||||
|
||||
if ini_aa_tags != new_aa_tags:
|
||||
alvals['tag_ids'] = [(6, None, new_aa_tags.ids)]
|
||||
return alvals
|
||||
|
||||
@api.multi
|
||||
def _update_payment_term_move(self):
|
||||
self.ensure_one()
|
||||
inv = self.invoice_id
|
||||
if (
|
||||
self.invoice_payment_term_id and
|
||||
self.invoice_payment_term_id != inv.invoice_payment_term_id):
|
||||
self.payment_term_id and
|
||||
self.payment_term_id != inv.payment_term_id and
|
||||
inv.move_id):
|
||||
# I don't update pay term when the invoice is partially (or fully)
|
||||
# paid because if you have a payment term with several lines
|
||||
# of the same amount, you would also have to take into account
|
||||
# the reconcile marks to put the new maturity date on the right
|
||||
# lines
|
||||
if inv.payment_id:
|
||||
if inv.payment_ids:
|
||||
raise UserError(_(
|
||||
"This wizard doesn't support the update of payment "
|
||||
"terms on an invoice which is partially or fully "
|
||||
"paid."))
|
||||
prec = self.env['decimal.precision'].precision_get('Account')
|
||||
term_res = self.invoice_payment_term_id.compute(
|
||||
term_res = self.payment_term_id.compute(
|
||||
inv.amount_total, inv.date_invoice)[0]
|
||||
new_pterm = {} # key = int(amount * 100), value = [date1, date2]
|
||||
for entry in term_res:
|
||||
@@ -168,7 +221,7 @@ class AccountMoveUpdate(models.TransientModel):
|
||||
mlines[amount].append(line)
|
||||
else:
|
||||
mlines[amount] = [line]
|
||||
for iamount, lines in mlines.items():
|
||||
for iamount, lines in mlines.iteritems():
|
||||
if len(lines) != len(new_pterm.get(iamount, [])):
|
||||
raise UserError(_(
|
||||
"The original payment term '%s' doesn't have the "
|
||||
@@ -176,10 +229,11 @@ class AccountMoveUpdate(models.TransientModel):
|
||||
"new payment term '%s'. You can only switch to a "
|
||||
"payment term that has the same number of terms "
|
||||
"with the same amount.") % (
|
||||
inv.invoice_payment_term_id.name, self.invoice_payment_term_id.name))
|
||||
inv.payment_term_id.name, self.payment_term_id.name))
|
||||
for line in lines:
|
||||
line.date_maturity = new_pterm[iamount].pop()
|
||||
|
||||
@api.multi
|
||||
def run(self):
|
||||
self.ensure_one()
|
||||
inv = self.invoice_id
|
||||
@@ -190,24 +244,28 @@ class AccountMoveUpdate(models.TransientModel):
|
||||
if ivals:
|
||||
updated = True
|
||||
inv.write(ivals)
|
||||
if inv:
|
||||
for ml in inv.line_ids.filtered(
|
||||
if inv.move_id:
|
||||
mvals = self._prepare_move()
|
||||
if mvals:
|
||||
inv.move_id.write(mvals)
|
||||
for ml in inv.move_id.line_ids.filtered(
|
||||
# we are only interested in invoice lines, not tax lines
|
||||
lambda rec: bool(rec.product_id)
|
||||
):
|
||||
if ml.credit == 0.0:
|
||||
continue
|
||||
analytic_account = ml.analytic_account_id
|
||||
mlvals, alvals = self._prepare_move_line_and_analytic_line(ml)
|
||||
inv_line = self._get_matching_inv_line(ml)
|
||||
mlvals = self._prepare_move_line(inv_line)
|
||||
if mlvals:
|
||||
updated = True
|
||||
ml.write(mlvals)
|
||||
aalines = ml.analytic_line_ids
|
||||
alvals = self._prepare_analytic_line(inv_line)
|
||||
if aalines and alvals:
|
||||
updated = True
|
||||
if ('account_id' in alvals and
|
||||
alvals['account_id'] is False):
|
||||
former_aa = analytic_account
|
||||
former_aa = inv_line.account_analytic_id
|
||||
to_remove_aalines = aalines.filtered(
|
||||
lambda rec: rec.account_id == former_aa)
|
||||
# remove existing analytic line
|
||||
@@ -224,38 +282,27 @@ class AccountMoveUpdate(models.TransientModel):
|
||||
updated = True
|
||||
line.invoice_line_id.write(ilvals)
|
||||
if updated:
|
||||
inv.message_post(body=_(
|
||||
inv.message_post(_(
|
||||
'Non-legal fields of invoice updated via the Invoice Update '
|
||||
'wizard.'))
|
||||
# Purge existing PDF
|
||||
report = self.env.ref("account.account_invoices")
|
||||
attachment = report.retrieve_attachment(inv)
|
||||
# attachment may be None
|
||||
if attachment:
|
||||
attachment.unlink()
|
||||
return True
|
||||
|
||||
|
||||
class AccountMoveLineUpdate(models.TransientModel):
|
||||
_name = 'account.move.line.update'
|
||||
class AccountInvoiceLineUpdate(models.TransientModel):
|
||||
_name = 'account.invoice.line.update'
|
||||
_description = 'Update non-legal fields of invoice lines'
|
||||
_order = "sequence, name"
|
||||
|
||||
sequence = fields.Integer()
|
||||
parent_id = fields.Many2one(
|
||||
'account.move.update', string='Wizard', ondelete='cascade')
|
||||
'account.invoice.update', string='Wizard', ondelete='cascade')
|
||||
invoice_line_id = fields.Many2one(
|
||||
'account.move.line', string='Invoice Line', readonly=True)
|
||||
'account.invoice.line', string='Invoice Line', readonly=True)
|
||||
name = fields.Text(string='Description', required=True)
|
||||
display_type = fields.Selection([
|
||||
('line_section', "Section"),
|
||||
('line_note', "Note")], default=False, help="Technical field for UX purpose.")
|
||||
quantity = fields.Float(
|
||||
string='Quantity', digits='Product Unit of Measure', readonly=True)
|
||||
price_subtotal = fields.Monetary(
|
||||
string='Amount', readonly=True)
|
||||
analytic_account_id = fields.Many2one(
|
||||
string='Quantity', digits=dp.get_precision('Product Unit of Measure'),
|
||||
readonly=True)
|
||||
price_subtotal = fields.Float(
|
||||
string='Amount', readonly=True, digits=dp.get_precision('Account'))
|
||||
account_analytic_id = fields.Many2one(
|
||||
'account.analytic.account', string='Analytic Account')
|
||||
analytic_tag_ids = fields.Many2many(
|
||||
'account.analytic.tag', string='Analytic Tags')
|
||||
currency_id = fields.Many2one('res.currency', readonly=True)
|
||||
@@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
© 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
<record id="account_invoice_update_form" model="ir.ui.view">
|
||||
<field name="model">account.invoice.update</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Update Invoice Wizard">
|
||||
<group name="main">
|
||||
<field name="invoice_id" invisible="1"/>
|
||||
<field name="type" invisible="1"/>
|
||||
<field name="company_id" invisible="1"/>
|
||||
<field name="partner_id" invisible="1"/>
|
||||
<field name="reference" attrs="{'invisible': [('type', 'not in', ('in_invoice', 'in_refund'))]}"/>
|
||||
<field name="origin"/>
|
||||
<field name="name"/>
|
||||
<field name="payment_term_id" widget="selection"/>
|
||||
<field name="partner_bank_id"/>
|
||||
<field name="user_id"/>
|
||||
<field name="comment"/>
|
||||
</group>
|
||||
<group name="lines">
|
||||
<field name="line_ids" nolabel="1">
|
||||
<tree editable="bottom">
|
||||
<field name="invoice_line_id" invisible="1"/>
|
||||
<field name="name"/>
|
||||
<field name="quantity"/>
|
||||
<field name="price_subtotal"/>
|
||||
<field name="account_analytic_id" groups="analytic.group_analytic_accounting"/>
|
||||
<field name="analytic_tag_ids" groups="analytic.group_analytic_accounting" widget="many2many_tags"/>
|
||||
</tree>
|
||||
</field>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="run" type="object" class="oe_highlight" string="Update"/>
|
||||
<button special="cancel" string="Cancel" class="oe_link"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="account_invoice_update_action" model="ir.actions.act_window">
|
||||
<field name="name">Invoice Update Wizard</field>
|
||||
<field name="res_model">account.invoice.update</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,57 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
© 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
<record id="account_invoice_update_form" model="ir.ui.view">
|
||||
<field name="model">account.move.update</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Update Invoice Wizard">
|
||||
<group name="main">
|
||||
<field name="invoice_id" invisible="1"/>
|
||||
<field name="move_type" invisible="1"/>
|
||||
<field name="company_id" invisible="1"/>
|
||||
<field name="partner_id" invisible="1"/>
|
||||
<field string="Bill Date" attrs="{'invisible': [('move_type', 'not in', ('in_invoice', 'in_refund'))]}" name="invoice_date"/>
|
||||
<field string="Supplier Bill Reference" attrs="{'invisible': [('move_type', 'not in', ('in_invoice', 'in_refund'))]}" name="ref"/>
|
||||
<field string="Customer Reference" attrs="{'invisible': [('move_type', 'not in', ('out_invoice', 'out_refund'))]}" name="ref"/>
|
||||
<field string="Ref" attrs="{'invisible': [('move_type', '!=', 'entry')]}" name="ref"/>
|
||||
<field name="invoice_origin" attrs="{'invisible': [('move_type', '=', 'entry')]}"/>
|
||||
<!-- update of payment term is broken -->
|
||||
<!-- <field name="invoice_payment_term_id" widget="selection"/>-->
|
||||
<field name="partner_bank_id" attrs="{'invisible': [('move_type', '=', 'entry')]}"/>
|
||||
<field name="user_id" options="{'no_open': True, 'no_create': True, 'no_create_edit': True}" attrs="{'invisible': [('move_type', '=', 'entry')]}"/>
|
||||
</group>
|
||||
<group name="lines">
|
||||
<field name="line_ids" nolabel="1" widget="section_and_note_one2many">
|
||||
<tree editable="bottom" create="false" delete="false" edit="true">
|
||||
<field name="invoice_line_id" invisible="1"/>
|
||||
<field name="display_type" invisible="1"/>
|
||||
<field name="currency_id" invisible="1"/>
|
||||
<field name="name"/>
|
||||
<field name="quantity" attrs="{'invisible': [('display_type', '!=', False)], 'column_invisible': [('parent.move_type', '=', 'entry')]}"/>
|
||||
<field name="price_subtotal" attrs="{'invisible': [('display_type', '!=', False)], 'column_invisible': [('parent.move_type', '=', 'entry')]}"/>
|
||||
<field name="analytic_account_id" attrs="{'invisible': [('display_type', '!=', False)]}" groups="analytic.group_analytic_accounting"/>
|
||||
<field name="analytic_tag_ids" attrs="{'invisible': [('display_type', '!=', False)]}" groups="analytic.group_analytic_tags" widget="many2many_tags"/>
|
||||
</tree>
|
||||
</field>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="run" type="object" class="oe_highlight" string="Update"/>
|
||||
<button special="cancel" string="Cancel" class="oe_link"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="account_invoice_update_action" model="ir.actions.act_window">
|
||||
<field name="name">Invoice Update Wizard</field>
|
||||
<field name="res_model">account.move.update</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,39 +0,0 @@
|
||||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
|
||||
:target: https://www.gnu.org/licenses/agpl-3.0-standalone.html
|
||||
:alt: License: AGPL-3
|
||||
|
||||
Account Invoice Update Wizard
|
||||
=============================
|
||||
|
||||
This module adds a button *Update Invoice* on Customer and Supplier invoices in
|
||||
Open or Paid state. This button starts a wizard which allows the user to update
|
||||
non-legal fields of the invoice:
|
||||
|
||||
* Source Document
|
||||
* Reference/Description
|
||||
* Payment terms (update allowed only to a payment term with same number of terms
|
||||
of the same amount and on invoices without any payment)
|
||||
* Bank Account
|
||||
* Salesman
|
||||
* Notes
|
||||
* Description of invoice lines
|
||||
* Analytic account
|
||||
* Analytic tags
|
||||
|
||||
Bug Tracker
|
||||
===========
|
||||
|
||||
Bugs are tracked on `GitHub Issues
|
||||
<https://github.com/akretion/odoo-usability/issues>`_. In case of trouble, please
|
||||
check there if your issue has already been reported. If you spotted it first,
|
||||
help us smash it by providing detailed and welcomed feedback.
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
||||
* Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
* Florian da Costa <florian.dacosta@akretion.com>
|
||||
* Matthieu Dietrich <matthieu.dietrich@camptocamp.com>
|
||||
* Yannick Vaucher <yannick.vaucher@camptocamp.com>
|
||||
* Mykhailo Panarin <m.panarin@mobilunity.com>
|
||||
* Artem Kostyuk <a.kostyuk@mobilunity.com>
|
||||
@@ -1 +0,0 @@
|
||||
from . import wizard
|
||||
@@ -1,17 +0,0 @@
|
||||
# Copyright 2022 Akretion France (http://www.akretion.com/)
|
||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
'name': 'Account Invoice Update Wizard Payment Mode',
|
||||
'version': '14.0.1.0.0',
|
||||
'category': 'Accounting & Finance',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Add Payment Mode to Invoice Update Wizard',
|
||||
'author': 'Akretion',
|
||||
'website': 'https://github.com/akretion/odoo-usability',
|
||||
'depends': ['account_invoice_update_wizard', 'account_payment_partner'],
|
||||
'data': ['wizard/account_move_update_view.xml'],
|
||||
'installable': True,
|
||||
'auto_install': True,
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 9.2 KiB |
@@ -1,19 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
<record id="view_move_form_inherit" model="ir.ui.view">
|
||||
<field name="model">account.move</field>
|
||||
<field name="inherit_id" ref="account.view_move_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<button name="button_draft" position="before">
|
||||
<button name="prepare_update_wizard" type="object" string="Update Invoice" states="posted" groups="account.group_account_invoice"/>
|
||||
</button>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1 +0,0 @@
|
||||
from . import account_move_update
|
||||
@@ -1,24 +0,0 @@
|
||||
# Copyright 2022 Akretion France (http://www.akretion.com/)
|
||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
|
||||
|
||||
from odoo import models, fields, api, _
|
||||
|
||||
|
||||
class AccountMoveUpdate(models.TransientModel):
|
||||
_inherit = 'account.move.update'
|
||||
|
||||
payment_mode_filter_type_domain = fields.Char(
|
||||
related='invoice_id.payment_mode_filter_type_domain')
|
||||
partner_bank_filter_type_domain = fields.Many2one(
|
||||
related='invoice_id.partner_bank_filter_type_domain')
|
||||
bank_account_required = fields.Boolean(
|
||||
related='invoice_id.bank_account_required')
|
||||
payment_mode_id = fields.Many2one("account.payment.mode")
|
||||
|
||||
@api.model
|
||||
def _m2o_fields2update(self):
|
||||
m2o_list = super()._m2o_fields2update()
|
||||
m2o_list.append('payment_mode_id')
|
||||
return m2o_list
|
||||
@@ -1,32 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2022 Akretion France (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
|
||||
<record id="account_invoice_update_form" model="ir.ui.view">
|
||||
<field name="model">account.move.update</field>
|
||||
<field name="inherit_id" ref="account_invoice_update_wizard.account_invoice_update_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="partner_bank_id" position="before">
|
||||
<field name="payment_mode_filter_type_domain" invisible="1"/>
|
||||
<field name="partner_bank_filter_type_domain" invisible="1"/>
|
||||
<field name="bank_account_required" invisible="1"/>
|
||||
<field name="payment_mode_id" domain="[('payment_type', '=', payment_mode_filter_type_domain), ('company_id', '=', company_id)]"/>
|
||||
</field>
|
||||
<field name="partner_bank_id" position="attributes">
|
||||
<attribute name="domain">
|
||||
[('partner_id', '=', partner_bank_filter_type_domain),
|
||||
'|',('company_id', '=', company_id),('company_id', '=', False)]
|
||||
</attribute>
|
||||
<attribute name="attrs">{'required': [('bank_account_required', '=', True),('move_type', 'in', ('in_invoice', 'in_refund'))]}</attribute>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</odoo>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user