Compare commits
1306 Commits
fix-get_si
...
pot_develo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee2034410f | ||
|
|
3fa8706f57 | ||
|
|
f92aabd0f3 | ||
|
|
628d7e6458 | ||
|
|
ba60b5911a | ||
|
|
08899d05fb | ||
|
|
754c7f6d1c | ||
|
|
92673d706c | ||
|
|
9c3a105f85 | ||
|
|
272ce24016 | ||
|
|
651e4696fd | ||
|
|
5ed1b6b8fb | ||
|
|
cd5d244d2c | ||
|
|
0887161f2a | ||
|
|
544fc60093 | ||
|
|
c50663c640 | ||
|
|
c41a037174 | ||
|
|
c710ad822c | ||
|
|
ebfbe94aaf | ||
|
|
e51ccecd8a | ||
|
|
bd8382c592 | ||
|
|
6142d07f1a | ||
|
|
ed5344d58b | ||
|
|
44228b754f | ||
|
|
d19ae4ce4c | ||
|
|
58f7039630 | ||
|
|
eac7be2d0f | ||
|
|
42ef95759d | ||
|
|
eb31017058 | ||
|
|
69d68592ad | ||
|
|
eb9f579b8f | ||
|
|
e4db0562ac | ||
|
|
a61148c464 | ||
|
|
7fa22069d8 | ||
|
|
54a12c5186 | ||
|
|
c8e92cb1b2 | ||
|
|
93c6324115 | ||
|
|
f26be2a303 | ||
|
|
61f5ebd2dd | ||
|
|
22c345a24a | ||
|
|
9bf37426c1 | ||
|
|
1cbc200770 | ||
|
|
8289f3c724 | ||
|
|
da3010a41f | ||
|
|
ed9af7d12e | ||
|
|
bf755fab55 | ||
|
|
2402447568 | ||
|
|
f77d5db38e | ||
|
|
fed2d11905 | ||
|
|
8861a76bd0 | ||
|
|
56f0b2628e | ||
|
|
7a6cc84d41 | ||
|
|
a34c99385c | ||
|
|
94339c569e | ||
|
|
1df06efd97 | ||
|
|
52e52e83a9 | ||
|
|
9f092dbe9f | ||
|
|
b324a02fbb | ||
|
|
5fa4cfee04 | ||
|
|
5e48c1ac51 | ||
|
|
e0d12ba4d0 | ||
|
|
f7f3b22786 | ||
|
|
e43697d359 | ||
|
|
2f9a144023 | ||
|
|
9e2ecd67f9 | ||
|
|
b195f519e2 | ||
|
|
9f346e7ba0 | ||
|
|
8e30debc10 | ||
|
|
41695e601d | ||
|
|
066859cca0 | ||
|
|
44f9059338 | ||
|
|
d95d00b7c8 | ||
|
|
880d061164 | ||
|
|
bb5f1dae75 | ||
|
|
1bb1b69dea | ||
|
|
3562c2d1d1 | ||
|
|
46736a737f | ||
|
|
5b1e860489 | ||
|
|
8e095335be | ||
|
|
7fa94843aa | ||
|
|
be7fd6bfb4 | ||
|
|
90d1873ad0 | ||
|
|
341fb6d8f3 | ||
|
|
ca577f7aaa | ||
|
|
2f359e201d | ||
|
|
3c1af2acf0 | ||
|
|
7cb66f7fd3 | ||
|
|
a48966f08c | ||
|
|
ecf07bd128 | ||
|
|
1c613ada6f | ||
|
|
4250ac821f | ||
|
|
aefbe21b46 | ||
|
|
5f6bf4c369 | ||
|
|
cfa3c85f3c | ||
|
|
d0d496a515 | ||
|
|
14bdd5da6e | ||
|
|
b8f7979794 | ||
|
|
3bd598bd1b | ||
|
|
d4fe313de2 | ||
|
|
6d51105082 | ||
|
|
9dbd321133 | ||
|
|
808dbfcade | ||
|
|
3b62237570 | ||
|
|
289495c308 | ||
|
|
de9c8fc9d6 | ||
|
|
6b8f65b7de | ||
|
|
eadd892b03 | ||
|
|
4aef969879 | ||
|
|
4eee3f52a3 | ||
|
|
3e7ccb24a6 | ||
|
|
bbe323fbb4 | ||
|
|
7286df86c5 | ||
|
|
affe304d47 | ||
|
|
b4cbd5fafa | ||
|
|
9a6e762b8b | ||
|
|
41035ccba0 | ||
|
|
29153ed3b4 | ||
|
|
a8f03e8baa | ||
|
|
93e6c6ccab | ||
|
|
f00ae0b92b | ||
|
|
a4b6eda8a9 | ||
|
|
ad8e189c26 | ||
|
|
7ad1bf5840 | ||
|
|
1ad065fc54 | ||
|
|
497f560b4b | ||
|
|
f6f118855b | ||
|
|
e706b4534c | ||
|
|
f8305c2fc0 | ||
|
|
e3fc5990ee | ||
|
|
fb6b98c85d | ||
|
|
9a290fdfc9 | ||
|
|
34fd290edb | ||
|
|
244d62df70 | ||
|
|
8233c392fb | ||
|
|
e36f6453d5 | ||
|
|
732b6e1417 | ||
|
|
7ce6687b68 | ||
|
|
96d96bb500 | ||
|
|
5357b9e727 | ||
|
|
5b1493b56c | ||
|
|
2896e3666c | ||
|
|
24a68a79df | ||
|
|
fe5b88522e | ||
|
|
d69a18b826 | ||
|
|
42a5e61ac3 | ||
|
|
03231e99ef | ||
|
|
85c63f29c0 | ||
|
|
2b32d3644f | ||
|
|
9445bd410c | ||
|
|
8821c98625 | ||
|
|
81b574053f | ||
|
|
67a8f50711 | ||
|
|
071e5ed648 | ||
|
|
b9243569ca | ||
|
|
098b62f0f6 | ||
|
|
760e341cd0 | ||
|
|
9a12376e29 | ||
|
|
59292a09c4 | ||
|
|
2d82631509 | ||
|
|
18ca953d5a | ||
|
|
a6ed77d378 | ||
|
|
8ad0295f1b | ||
|
|
8d94238db8 | ||
|
|
3f8d785f02 | ||
|
|
e93b4a1f2c | ||
|
|
65bddd2930 | ||
|
|
baf0c83cc5 | ||
|
|
bb46f2d8fb | ||
|
|
b04d0dfe70 | ||
|
|
140fdd4a7e | ||
|
|
205fd9888c | ||
|
|
773b63c691 | ||
|
|
fac69d852c | ||
|
|
f9e230e758 | ||
|
|
fa91cda46c | ||
|
|
c3845ac0f1 | ||
|
|
fc835ed6b1 | ||
|
|
65c74fa3c7 | ||
|
|
a70f3ef873 | ||
|
|
6810227be0 | ||
|
|
9aa361fe1f | ||
|
|
51baa95ad2 | ||
|
|
f3ec4f1964 | ||
|
|
b558a4c871 | ||
|
|
eb241d0a86 | ||
|
|
8c0ea11f33 | ||
|
|
165641e495 | ||
|
|
455565412f | ||
|
|
6ab3527987 | ||
|
|
c8ae124436 | ||
|
|
3e216e2f95 | ||
|
|
20f20db179 | ||
|
|
78bef654ed | ||
|
|
71f3883613 | ||
|
|
dd10087db6 | ||
|
|
6b8de22210 | ||
|
|
2a3a35315b | ||
|
|
9905b9e4b0 | ||
|
|
971c867f29 | ||
|
|
c203fafb1b | ||
|
|
5446ed7642 | ||
|
|
3c3009f086 | ||
|
|
429e036e8c | ||
|
|
24d37d22a3 | ||
|
|
549ea8a63c | ||
|
|
b5e017a626 | ||
|
|
3bce4d92f6 | ||
|
|
f331f9b15c | ||
|
|
5f7e06ba6f | ||
|
|
0ade33dd1a | ||
|
|
9f3a1567b5 | ||
|
|
cf806fb2d4 | ||
|
|
680dfbfd2b | ||
|
|
6e2475a266 | ||
|
|
f127c33acc | ||
|
|
f529386b20 | ||
|
|
fd6195f8cd | ||
|
|
433c8c450c | ||
|
|
dc79213bb3 | ||
|
|
4776d660b5 | ||
|
|
d791fa7460 | ||
|
|
10c5ed8a3c | ||
|
|
b02d5a226c | ||
|
|
6a8bd64c40 | ||
|
|
c66dde6318 | ||
|
|
f7c9e1538b | ||
|
|
503687a224 | ||
|
|
39a48a2e2a | ||
|
|
286268567e | ||
|
|
219d5a5e8b | ||
|
|
46a2d3cad9 | ||
|
|
4ded8ca07b | ||
|
|
3f6dcfe0a2 | ||
|
|
a180c502f9 | ||
|
|
c4ffeedffb | ||
|
|
30bbb58ca1 | ||
|
|
6b317b0c0d | ||
|
|
f61faa85a1 | ||
|
|
01888c98bc | ||
|
|
581af4eced | ||
|
|
7ef4dbcaf6 | ||
|
|
550cbbd91c | ||
|
|
64b7f624a5 | ||
|
|
141f462368 | ||
|
|
248cc6105b | ||
|
|
74bc38e0af | ||
|
|
bdd36b0001 | ||
|
|
9fd2dddfde | ||
|
|
a75e095d00 | ||
|
|
8b9079d62e | ||
|
|
9808ae92a4 | ||
|
|
5c9ce575f6 | ||
|
|
fe84558b77 | ||
|
|
c15690e475 | ||
|
|
be0cb5289f | ||
|
|
d868122f12 | ||
|
|
68b076cb61 | ||
|
|
f87be1d96e | ||
|
|
1816f1d5f0 | ||
|
|
fec20decc1 | ||
|
|
8f53bc0096 | ||
|
|
ea1b66931a | ||
|
|
bed1af26e3 | ||
|
|
a3c9fd6567 | ||
|
|
7d22df2af5 | ||
|
|
46e12e0981 | ||
|
|
b4c815b804 | ||
|
|
a8cd850bb6 | ||
|
|
ec675ea3d8 | ||
|
|
c9c6211009 | ||
|
|
198b90eb01 | ||
|
|
f67f163e7d | ||
|
|
c705a393fe | ||
|
|
bcdfbee23e | ||
|
|
3228841e68 | ||
|
|
c3b2ed57f6 | ||
|
|
50dd9fa8a3 | ||
|
|
f3bcdbe5bd | ||
|
|
e8dcbe2625 | ||
|
|
bf88b8eb65 | ||
|
|
1e4b920fd2 | ||
|
|
0b63dbf221 | ||
|
|
7768544226 | ||
|
|
7acbfc06a0 | ||
|
|
f2b96869aa | ||
|
|
5281553b61 | ||
|
|
21a40a2236 | ||
|
|
4c8dfb2e6a | ||
|
|
271fea69b8 | ||
|
|
0a1fab762f | ||
|
|
b0730293e2 | ||
|
|
15c3f09898 | ||
|
|
45d5f6e00a | ||
|
|
edf51c9ab9 | ||
|
|
6416a6ad94 | ||
|
|
4f8990602e | ||
|
|
81cf970883 | ||
|
|
4c79d92faa | ||
|
|
621421bda2 | ||
|
|
2dd07d9292 | ||
|
|
d2b96b415c | ||
|
|
91fa41c9ec | ||
|
|
7ac91deb83 | ||
|
|
b542f21eea | ||
|
|
6283ff5d52 | ||
|
|
9bacf53f04 | ||
|
|
4f91effca9 | ||
|
|
f958e8be06 | ||
|
|
3231ee4d9d | ||
|
|
d73b1f3e6a | ||
|
|
679aea607b | ||
|
|
28c75b8f4d | ||
|
|
2a8a404c69 | ||
|
|
f76da50b7e | ||
|
|
af26ac96e9 | ||
|
|
8e522183bc | ||
|
|
66a06ca1a5 | ||
|
|
a3fbeff333 | ||
|
|
398d3022ef | ||
|
|
d05412f96a | ||
|
|
adee2ba541 | ||
|
|
ce2b9de9be | ||
|
|
29e5c6807e | ||
|
|
10bf6529ef | ||
|
|
2e15b224aa | ||
|
|
e5f87ef8da | ||
|
|
a2961a427d | ||
|
|
fe1290a89a | ||
|
|
e04cad3368 | ||
|
|
139c18f2cc | ||
|
|
59dc4a96e1 | ||
|
|
1f46c1530e | ||
|
|
5a151189ad | ||
|
|
c15a320940 | ||
|
|
87324c7349 | ||
|
|
4d41516abb | ||
|
|
9828d34b19 | ||
|
|
6b2f745afe | ||
|
|
eee86d2e4b | ||
|
|
04c91e263d | ||
|
|
9709a18ef5 | ||
|
|
b156937254 | ||
|
|
ac69513f60 | ||
|
|
5bff434902 | ||
|
|
db1f7fcf63 | ||
|
|
2b8928cae6 | ||
|
|
a4dd1c2bf6 | ||
|
|
bddc1e3974 | ||
|
|
89b5e061af | ||
|
|
54cd492217 | ||
|
|
f63396ef47 | ||
|
|
3effaf21ef | ||
|
|
8afb7790de | ||
|
|
8c7213ad7d | ||
|
|
33fd7b8a1f | ||
|
|
5daf19da40 | ||
|
|
19e054c7a7 | ||
|
|
57f67faba1 | ||
|
|
c2470ccc70 | ||
|
|
dfde490c02 | ||
|
|
95dcb75e93 | ||
|
|
cd36a1051f | ||
|
|
6c1e9fab27 | ||
|
|
0d9d42ae61 | ||
|
|
1b0f95088a | ||
|
|
f96cf111ed | ||
|
|
1a43ed763b | ||
|
|
00eeacd06a | ||
|
|
704925549b | ||
|
|
a42482ce35 | ||
|
|
b2fb7843d1 | ||
|
|
652b4e5dcd | ||
|
|
edced3fd21 | ||
|
|
f189be501b | ||
|
|
8c8d9be810 | ||
|
|
d620b9eae8 | ||
|
|
533627df3b | ||
|
|
016585c248 | ||
|
|
683da71c5e | ||
|
|
c3546cf8e2 | ||
|
|
402ffc6d27 | ||
|
|
9ed74dd8cc | ||
|
|
2e30dda0cd | ||
|
|
662cf21afb | ||
|
|
8b6220efd8 | ||
|
|
b3e163e9d8 | ||
|
|
dcbb54c41f | ||
|
|
064127935b | ||
|
|
5ed13fa913 | ||
|
|
d0e654528b | ||
|
|
1be2df81c9 | ||
|
|
4d4d88ec5f | ||
|
|
b49d64de63 | ||
|
|
8fa5707911 | ||
|
|
34344a062e | ||
|
|
679204ecb8 | ||
|
|
f20c54a6c1 | ||
|
|
f316a29ba6 | ||
|
|
462204fc65 | ||
|
|
e04a3b107a | ||
|
|
441969d7d6 | ||
|
|
7d7d10e422 | ||
|
|
12945341ce | ||
|
|
5ab9656e8f | ||
|
|
e055147849 | ||
|
|
b132892b25 | ||
|
|
e44809bcc9 | ||
|
|
5be3417fdf | ||
|
|
c89b0e37ab | ||
|
|
43fd60a877 | ||
|
|
079cc8bd21 | ||
|
|
d47b87ba71 | ||
|
|
ae31f2c5ad | ||
|
|
24e2672fde | ||
|
|
aaa1df6a1f | ||
|
|
3423334e4f | ||
|
|
b1a9b6d64a | ||
|
|
fdcdc8a56e | ||
|
|
a88bf8419e | ||
|
|
6d603cc35f | ||
|
|
6821baa850 | ||
|
|
844ad405ff | ||
|
|
6940c2b0aa | ||
|
|
f30e5eab11 | ||
|
|
4972f6b66f | ||
|
|
1cd38c860a | ||
|
|
eb45a71997 | ||
|
|
2bd9c5b001 | ||
|
|
d893a465d7 | ||
|
|
ccb51ded95 | ||
|
|
4a49618cd7 | ||
|
|
9fcddc3378 | ||
|
|
58b3ce6a19 | ||
|
|
cbcc47b5c4 | ||
|
|
69824eff80 | ||
|
|
64f686d943 | ||
|
|
4ba67fb3ec | ||
|
|
be9fe7331a | ||
|
|
1714ac6587 | ||
|
|
0a495bf65e | ||
|
|
a1d108c062 | ||
|
|
986357428d | ||
|
|
967540da18 | ||
|
|
e1ce7bfb11 | ||
|
|
1c63983873 | ||
|
|
02c522b7cd | ||
|
|
81309576b0 | ||
|
|
a158b825d7 | ||
|
|
50bfb8eaa9 | ||
|
|
ac92a22914 | ||
|
|
5a3afea8c7 | ||
|
|
5fe0b20be1 | ||
|
|
dfffaddf03 | ||
|
|
1a9ae33110 | ||
|
|
1d91e1788c | ||
|
|
b73f51a9bd | ||
|
|
0725707cb1 | ||
|
|
9996d6b7e6 | ||
|
|
3cec62d4f8 | ||
|
|
0455d0c46c | ||
|
|
4a55240e63 | ||
|
|
815df8e795 | ||
|
|
87e36d290e | ||
|
|
4cfe99d74f | ||
|
|
e9e985aea0 | ||
|
|
775e8db04e | ||
|
|
a8d458b979 | ||
|
|
d238751e6b | ||
|
|
5691cc6323 | ||
|
|
8136954484 | ||
|
|
a64c2ecf39 | ||
|
|
5a8004bc58 | ||
|
|
643cc022fd | ||
|
|
09ea7edb86 | ||
|
|
eea260b9f9 | ||
|
|
0182713dd6 | ||
|
|
12f97e3c63 | ||
|
|
8d1b530070 | ||
|
|
49dd4c1ef3 | ||
|
|
2f3d6cd304 | ||
|
|
e43beac086 | ||
|
|
3dd6686d8a | ||
|
|
e1c2d006ca | ||
|
|
3d5dba6976 | ||
|
|
7695759f3c | ||
|
|
00de529a1e | ||
|
|
08893d1f75 | ||
|
|
11616bec26 | ||
|
|
8b81274769 | ||
|
|
6d47b8a24e | ||
|
|
cefb8f69e5 | ||
|
|
1fc099dacf | ||
|
|
c46c329ed8 | ||
|
|
bb279e368c | ||
|
|
aec630c74f | ||
|
|
3cde81be65 | ||
|
|
3381d0d945 | ||
|
|
daaa00bd4a | ||
|
|
2fadfd7cfc | ||
|
|
60ba25caf2 | ||
|
|
f3f6bc8042 | ||
|
|
b171784d85 | ||
|
|
c80356c7c9 | ||
|
|
c9039d767b | ||
|
|
4f396d3049 | ||
|
|
4d090bd3b8 | ||
|
|
30463657bf | ||
|
|
ec194ef076 | ||
|
|
78c9cc63b1 | ||
|
|
98afb4d468 | ||
|
|
31a2da552b | ||
|
|
55e93b3fe1 | ||
|
|
2dbe68a09d | ||
|
|
1014940953 | ||
|
|
86b5e2e277 | ||
|
|
7c4cff2649 | ||
|
|
b98a5e4edc | ||
|
|
49d3bcbc8d | ||
|
|
b12ca65fcc | ||
|
|
cccb2d5141 | ||
|
|
6a77d86a53 | ||
|
|
8944ab8b6a | ||
|
|
d0dc2c6e77 | ||
|
|
6fbb67b1d2 | ||
|
|
0d65d878de | ||
|
|
1ff8a6f24f | ||
|
|
59222813af | ||
|
|
a84b9434a9 | ||
|
|
a1e8caa5c1 | ||
|
|
ec55831440 | ||
|
|
a06c3e9f9f | ||
|
|
80d3dd2846 | ||
|
|
a3d4aff29c | ||
|
|
3e0c798cca | ||
|
|
f504f2caf3 | ||
|
|
ad42389352 | ||
|
|
2a08072443 | ||
|
|
6d9074d585 | ||
|
|
5f15297f28 | ||
|
|
647bba0f00 | ||
|
|
898affbee9 | ||
|
|
4ed7e3eacd | ||
|
|
12029557fe | ||
|
|
b62a6b6ab0 | ||
|
|
a9a9b1297e | ||
|
|
437bdc2d8c | ||
|
|
62d2fe50d2 | ||
|
|
26202d90cb | ||
|
|
c417e7d800 | ||
|
|
ec83d54826 | ||
|
|
4cda88690f | ||
|
|
d15cdd9190 | ||
|
|
a0247d11bd | ||
|
|
cd79dcccb6 | ||
|
|
f4a945aee4 | ||
|
|
10bb1c31a2 | ||
|
|
65ae9616ba | ||
|
|
560eb174f1 | ||
|
|
9f3a310300 | ||
|
|
8d405684ce | ||
|
|
d7a4c0dfde | ||
|
|
7690a40ebb | ||
|
|
effc9d1492 | ||
|
|
e87b44f758 | ||
|
|
c9623b6fd6 | ||
|
|
83d48ca8d7 | ||
|
|
445d2acf50 | ||
|
|
ce3b1f09f5 | ||
|
|
4d0c2d8e82 | ||
|
|
98a12dd66f | ||
|
|
98c7f44280 | ||
|
|
f24f51b7de | ||
|
|
e786a93c2e | ||
|
|
f3b4237ab6 | ||
|
|
849f478894 | ||
|
|
daf4ae2a6b | ||
|
|
f8a1a7f515 | ||
|
|
948297692e | ||
|
|
79a0473705 | ||
|
|
72614bb8ff | ||
|
|
77aac6f571 | ||
|
|
4a02d1497c | ||
|
|
5ac5b7f258 | ||
|
|
a419812864 | ||
|
|
0ffc5cf012 | ||
|
|
7075c50b85 | ||
|
|
b8da0d9334 | ||
|
|
dedae4fecf | ||
|
|
0da19a40a7 | ||
|
|
7e301f02df | ||
|
|
b9a8dd468b | ||
|
|
655a1797be | ||
|
|
a97a851333 | ||
|
|
c6cf1bec76 | ||
|
|
0344ff2aac | ||
|
|
767f2157e6 | ||
|
|
adf13a19c4 | ||
|
|
2cefe2a20e | ||
|
|
d2b34ea05d | ||
|
|
cde5b934e5 | ||
|
|
c4570ccfad | ||
|
|
58e1548640 | ||
|
|
b660d98f20 | ||
|
|
dee49e6078 | ||
|
|
f4d69f16c0 | ||
|
|
c5b94df188 | ||
|
|
0b100782e2 | ||
|
|
ec74a5e566 | ||
|
|
2c16036ef3 | ||
|
|
1f4c86136f | ||
|
|
b0fcb014c1 | ||
|
|
65c8605b88 | ||
|
|
4c6d28a299 | ||
|
|
962b51d6d5 | ||
|
|
9702a65a0f | ||
|
|
d69c593f93 | ||
|
|
1e09f584d5 | ||
|
|
0d6afda6b8 | ||
|
|
ac1961b687 | ||
|
|
c0a1f298a1 | ||
|
|
55b9664115 | ||
|
|
68baa3612a | ||
|
|
01856a6e9d | ||
|
|
65a2f3d12c | ||
|
|
d0e0b66b2f | ||
|
|
4b38139b44 | ||
|
|
898c6e30eb | ||
|
|
cef6291311 | ||
|
|
a93d14b3f7 | ||
|
|
48da952fd7 | ||
|
|
e178ffc3c1 | ||
|
|
1eaa386657 | ||
|
|
711b72b26c | ||
|
|
171b8af3ee | ||
|
|
031465f5ec | ||
|
|
f44a841af7 | ||
|
|
28ac53a704 | ||
|
|
bdc0175fe3 | ||
|
|
e58c2dd43d | ||
|
|
092999f2a6 | ||
|
|
e52c4c8f22 | ||
|
|
d9a0494fc3 | ||
|
|
cb2529cec8 | ||
|
|
158112896e | ||
|
|
9d9b83362a | ||
|
|
9904a9868c | ||
|
|
34051bc04f | ||
|
|
8e2f9787c1 | ||
|
|
6379238893 | ||
|
|
031b99f373 | ||
|
|
51909077bd | ||
|
|
d0140412cd | ||
|
|
e7d707797a | ||
|
|
f2f5c1a0eb | ||
|
|
ceee93e0e8 | ||
|
|
ed95d41a51 | ||
|
|
eaac02655b | ||
|
|
72ac56b6c4 | ||
|
|
e017421708 | ||
|
|
13b05aa7fb | ||
|
|
a5232d9c10 | ||
|
|
8a5078b826 | ||
|
|
5b67631d40 | ||
|
|
0aa72f841d | ||
|
|
b8dac84a90 | ||
|
|
79c492cc4b | ||
|
|
a8eb5e5c85 | ||
|
|
863abc3ee5 | ||
|
|
93c2762f7b | ||
|
|
c067ac16a7 | ||
|
|
5e736f0d06 | ||
|
|
983f71975a | ||
|
|
b235f48067 | ||
|
|
9d3614597c | ||
|
|
c096133897 | ||
|
|
3c19186654 | ||
|
|
646e9ca0dd | ||
|
|
3327599c9d | ||
|
|
dd70fb5f7e | ||
|
|
ac2b53bf15 | ||
|
|
5c47087f20 | ||
|
|
29f91a7919 | ||
|
|
f6fdfd2c01 | ||
|
|
24dcd64c16 | ||
|
|
9dcdd5b5ef | ||
|
|
fea20db262 | ||
|
|
043d9e3986 | ||
|
|
dde4d9e53c | ||
|
|
36a0569df2 | ||
|
|
f8ba560394 | ||
|
|
93170a56a9 | ||
|
|
6f5815e44f | ||
|
|
0c52eb913b | ||
|
|
519682bb0e | ||
|
|
694c17487d | ||
|
|
5b8b40c13b | ||
|
|
ceeb8fc9e5 | ||
|
|
b193fafe49 | ||
|
|
c310da7b29 | ||
|
|
d6b29d1cd7 | ||
|
|
303433c0ae | ||
|
|
20fa3da950 | ||
|
|
bc9c480246 | ||
|
|
8aa2b7c183 | ||
|
|
08caa7cfa1 | ||
|
|
5885978fc2 | ||
|
|
122373fcd3 | ||
|
|
1f01ff3487 | ||
|
|
c9e2f03a3a | ||
|
|
287eff533a | ||
|
|
1951f71eeb | ||
|
|
924b08e395 | ||
|
|
461fb183fc | ||
|
|
c9ff769d28 | ||
|
|
3658c4754f | ||
|
|
9c8d103d8a | ||
|
|
6d40844894 | ||
|
|
81dbfe189e | ||
|
|
75f8464724 | ||
|
|
e240ccd305 | ||
|
|
3c3c57c674 | ||
|
|
c42444ab3b | ||
|
|
bf6e32a960 | ||
|
|
9f6535472d | ||
|
|
7cb07425b1 | ||
|
|
4c9048fb39 | ||
|
|
f4222be027 | ||
|
|
44ed52c5cf | ||
|
|
8aaddb0f9e | ||
|
|
635174f1ce | ||
|
|
406793a6ff | ||
|
|
7566c1ee78 | ||
|
|
97c3e27c60 | ||
|
|
467c0898e9 | ||
|
|
26ec697a0b | ||
|
|
3294282880 | ||
|
|
a823f16dff | ||
|
|
339698d172 | ||
|
|
dd23ddcd6c | ||
|
|
20eff568b1 | ||
|
|
3634c4c284 | ||
|
|
2e0aaf3521 | ||
|
|
6249965605 | ||
|
|
a9f8af2fd1 | ||
|
|
6d43d46fbc | ||
|
|
4288713abe | ||
|
|
b03c683898 | ||
|
|
c5050c935b | ||
|
|
e2d16955dd | ||
|
|
5a3b133d65 | ||
|
|
146c5b3e16 | ||
|
|
c1e1fd8829 | ||
|
|
da184d709b | ||
|
|
864d7ae04c | ||
|
|
0b04d04da3 | ||
|
|
6707425baa | ||
|
|
6cfb8fe439 | ||
|
|
45b25e09c1 | ||
|
|
38e88db2c9 | ||
|
|
87df7ff717 | ||
|
|
4c061d61fa | ||
|
|
a73ba2c0d2 | ||
|
|
ecd83b12ab | ||
|
|
408ea0432b | ||
|
|
11f4cb914a | ||
|
|
66bf6e4041 | ||
|
|
f37f7ca5c3 | ||
|
|
85471533e9 | ||
|
|
4b24fcd221 | ||
|
|
68a23730f3 | ||
|
|
17f85de6fb | ||
|
|
8e7d47b3a7 | ||
|
|
133f8bd92a | ||
|
|
d4264f7ba1 | ||
|
|
fa1113f912 | ||
|
|
e8ae4ed61d | ||
|
|
a4cbfabe0e | ||
|
|
9cb83d2198 | ||
|
|
e25b4e24df | ||
|
|
4f23d88f62 | ||
|
|
0bbf45cd8b | ||
|
|
2ff06af154 | ||
|
|
9c0755d3de | ||
|
|
701671b2bd | ||
|
|
4d7d7dac01 | ||
|
|
f04676aaed | ||
|
|
0d260faa00 | ||
|
|
44538bd02a | ||
|
|
75230ece9a | ||
|
|
f99f7fd2cf | ||
|
|
cc83af0dd4 | ||
|
|
028d31a6f9 | ||
|
|
3f1d008741 | ||
|
|
0b3ecd24e2 | ||
|
|
506fefa186 | ||
|
|
a995e87567 | ||
|
|
fa4ea7c96d | ||
|
|
dc9115a586 | ||
|
|
f3bd53193d | ||
|
|
8a702a6338 | ||
|
|
8360339119 | ||
|
|
799794cafb | ||
|
|
2fb0499923 | ||
|
|
230a7d8d53 | ||
|
|
b1dfa2537b | ||
|
|
1a8f7f9403 | ||
|
|
d0df5df4a6 | ||
|
|
6239fd704b | ||
|
|
b124081065 | ||
|
|
4bef6707ec | ||
|
|
76023f1fdc | ||
|
|
f1f8f59bdb | ||
|
|
24ba26fef3 | ||
|
|
e6949d71f6 | ||
|
|
e3bd8d10b0 | ||
|
|
d80ca523a4 | ||
|
|
22291d32e6 | ||
|
|
5df5851798 | ||
|
|
1d1cb86c75 | ||
|
|
1c2a7801b7 | ||
|
|
55e66db315 | ||
|
|
094ecc1f62 | ||
|
|
2b1e0d3bd0 | ||
|
|
d97b6d38ef | ||
|
|
b966c06a4f | ||
|
|
2ee642fb2c | ||
|
|
4b1c851da1 | ||
|
|
39067c7614 | ||
|
|
aa1c69dd7a | ||
|
|
e5824fc3f1 | ||
|
|
d59caf08e6 | ||
|
|
186cc3d748 | ||
|
|
a2a8a8f2e0 | ||
|
|
17452b7693 | ||
|
|
8c85404191 | ||
|
|
159a123dc7 | ||
|
|
1568af2a7b | ||
|
|
1745371cd6 | ||
|
|
ecdc4c8e9b | ||
|
|
5cf0759b0c | ||
|
|
61a29eb5fb | ||
|
|
8bb83e267c | ||
|
|
781bdd2ec9 | ||
|
|
2d78dba66f | ||
|
|
2c8e4c1ab3 | ||
|
|
22a187c3be | ||
|
|
2f676ced5c | ||
|
|
e9251c3775 | ||
|
|
294f562fb9 | ||
|
|
81e82b0595 | ||
|
|
a8ebc94a36 | ||
|
|
33efe0d12d | ||
|
|
31a8c3bdc4 | ||
|
|
0549535603 | ||
|
|
50f54d983d | ||
|
|
146147316d | ||
|
|
ab9d6576d0 | ||
|
|
32ccf3524a | ||
|
|
d6d91257b6 | ||
|
|
40ce0c851d | ||
|
|
76b57a4338 | ||
|
|
0e5b4e5f07 | ||
|
|
fb330d1b5a | ||
|
|
9636458ae1 | ||
|
|
4671f65cbd | ||
|
|
9383f5da94 | ||
|
|
01650120d4 | ||
|
|
943dcb6dea | ||
|
|
3a26823c62 | ||
|
|
e55611497b | ||
|
|
798a0510e6 | ||
|
|
e38b46300c | ||
|
|
41f58476e1 | ||
|
|
56e5611337 | ||
|
|
2e509f69d4 | ||
|
|
ee14faaa39 | ||
|
|
ae4ebcd987 | ||
|
|
1bfbbfe393 | ||
|
|
1fa6233377 | ||
|
|
c1e869f040 | ||
|
|
3b671d5875 | ||
|
|
c5770f2ecc | ||
|
|
ff3ca50a4b | ||
|
|
cc96d2b50c | ||
|
|
4d614c1589 | ||
|
|
27d6c8b6d5 | ||
|
|
61ded697a7 | ||
|
|
5ce5c352e4 | ||
|
|
6e6c818084 | ||
|
|
b834ed10d6 | ||
|
|
25c2b79864 | ||
|
|
7a04f0f7ba | ||
|
|
b70f3de16b | ||
|
|
955098c4c0 | ||
|
|
675a0b810f | ||
|
|
d7e4a6be13 | ||
|
|
617d923f0d | ||
|
|
407045a1de | ||
|
|
d73e42fc41 | ||
|
|
9fafc83632 | ||
|
|
c81d597ca5 | ||
|
|
50cff656b4 | ||
|
|
d9a72c1e61 | ||
|
|
322cdbaccf | ||
|
|
a9a2ec81de | ||
|
|
93259cab1d | ||
|
|
7efb5a8cb5 | ||
|
|
c18ff5bd25 | ||
|
|
f7face43cd | ||
|
|
2caa2d677c | ||
|
|
6d87cfeb8d | ||
|
|
2693fcb446 | ||
|
|
7c6a5a0f23 | ||
|
|
1e15a3cc15 | ||
|
|
d78a1e7814 | ||
|
|
12affa70cf | ||
|
|
78483e2ee6 | ||
|
|
e9fe10c6f1 | ||
|
|
518b06c8eb | ||
|
|
27b557bef9 | ||
|
|
beff566c82 | ||
|
|
affca3a519 | ||
|
|
c077eda64e | ||
|
|
772f540bef | ||
|
|
951023f434 | ||
|
|
5e71d6ac4e | ||
|
|
7475233fa6 | ||
|
|
0c9572bb48 | ||
|
|
6b8f046fb4 | ||
|
|
1ff473b615 | ||
|
|
cfd1666181 | ||
|
|
0c6c650c08 | ||
|
|
31f586f716 | ||
|
|
6fea9d6dfe | ||
|
|
212d656d85 | ||
|
|
9a705169fd | ||
|
|
00a915b741 | ||
|
|
ae7be84d87 | ||
|
|
f8a9554bbd | ||
|
|
d86186ec47 | ||
|
|
3fd43cd6bb | ||
|
|
12a4f2761c | ||
|
|
e9dfb45fca | ||
|
|
b14886b227 | ||
|
|
2e49423d3f | ||
|
|
ddecbeba75 | ||
|
|
2e5d716408 | ||
|
|
bdca718103 | ||
|
|
8bdc760733 | ||
|
|
6f2fae1b61 | ||
|
|
91b913b5bb | ||
|
|
5cf47ae5f9 | ||
|
|
a673220feb | ||
|
|
4e182b89ce | ||
|
|
68c997aa06 | ||
|
|
866df9f1c7 | ||
|
|
079cd30b9c | ||
|
|
49cb11c1f3 | ||
|
|
efade9b9ae | ||
|
|
2a46799188 | ||
|
|
50d56db0c2 | ||
|
|
16404110a8 | ||
|
|
6a63a8997d | ||
|
|
88ff945e40 | ||
|
|
8f6c23cb53 | ||
|
|
4c197c8dbd | ||
|
|
f2891229ab | ||
|
|
2486b646a1 | ||
|
|
8fdc244e16 | ||
|
|
5be868c7f6 | ||
|
|
67d828dab3 | ||
|
|
7b37389115 | ||
|
|
0de4197c88 | ||
|
|
92649de5c6 | ||
|
|
3e59c66806 | ||
|
|
fc677811b7 | ||
|
|
19ff10dfeb | ||
|
|
4173203382 | ||
|
|
dbd4dae3d9 | ||
|
|
99b839d2b6 | ||
|
|
30cc65d2b7 | ||
|
|
722ee53fb1 | ||
|
|
6173b34b10 | ||
|
|
f7a3af7473 | ||
|
|
d491036f2d | ||
|
|
d2057588dd | ||
|
|
2bdfdeeb9a | ||
|
|
be074a2972 | ||
|
|
2b3cc5ba2d | ||
|
|
06f48c678b | ||
|
|
53b44ccf29 | ||
|
|
69db569ca5 | ||
|
|
7f8303a493 | ||
|
|
dfda5ad673 | ||
|
|
1e89c1c875 | ||
|
|
d1fb90edff | ||
|
|
4f215f1b70 | ||
|
|
3f383d81bd | ||
|
|
c0a1188067 | ||
|
|
ca02dfa652 | ||
|
|
7d3240ae3a | ||
|
|
93681cfa24 | ||
|
|
4f1e729b7c | ||
|
|
735576ab27 | ||
|
|
23199a3271 | ||
|
|
64cb1153de | ||
|
|
9fcd89d456 | ||
|
|
4a4c4ba21b | ||
|
|
030d35628d | ||
|
|
a552df8a9f | ||
|
|
b127aa308e | ||
|
|
02028becb3 | ||
|
|
764f3422a0 | ||
|
|
236c7e1e95 | ||
|
|
9f1ddeb4e4 | ||
|
|
b046d980ad | ||
|
|
806696a003 | ||
|
|
77b044f1a6 | ||
|
|
7a6a789199 | ||
|
|
252fae68df | ||
|
|
e5a5b6afc8 | ||
|
|
ffd38362d5 | ||
|
|
7a7a213285 | ||
|
|
34ec2f8a2b | ||
|
|
4832175341 | ||
|
|
3c7e7a76f0 | ||
|
|
3815f07c33 | ||
|
|
ebaa5d3add | ||
|
|
0d7dd93284 | ||
|
|
9b4e757b0b | ||
|
|
8de03ef836 | ||
|
|
bd6a4ca1d7 | ||
|
|
7d8aa469d7 | ||
|
|
b1aef01a1f | ||
|
|
c88ce55242 | ||
|
|
1a670ff266 | ||
|
|
1a686cb66d | ||
|
|
31592b8f3a | ||
|
|
f8675817e2 | ||
|
|
236b73565e | ||
|
|
72614fe9e1 | ||
|
|
60809ced85 | ||
|
|
aaf83da3e9 | ||
|
|
4c20a4710b | ||
|
|
52814724eb | ||
|
|
fc0d2aeeff | ||
|
|
7c2cb70387 | ||
|
|
ec0f17ca8b | ||
|
|
f8bbb0619c | ||
|
|
b17e632a85 | ||
|
|
13aae34e9c | ||
|
|
6d8949adea | ||
|
|
faab225126 | ||
|
|
63ffce58cc | ||
|
|
5d94f0bde5 | ||
|
|
b4393bc03d | ||
|
|
da0ad3bc00 | ||
|
|
9fc5c0cc58 | ||
|
|
ebc8230d45 | ||
|
|
e9526b112d | ||
|
|
a6afe50a92 | ||
|
|
273bc1b1e3 | ||
|
|
c40719caa5 | ||
|
|
b2d9380596 | ||
|
|
fcf4687c52 | ||
|
|
cbd443a78a | ||
|
|
6148fb024b | ||
|
|
9678d050a4 | ||
|
|
d468accb02 | ||
|
|
a50808a077 | ||
|
|
125847c69f | ||
|
|
4ca63c07f6 | ||
|
|
35067282cf | ||
|
|
c44eb432a5 | ||
|
|
871a1f4565 | ||
|
|
99b94af49f | ||
|
|
e9bc63aacf | ||
|
|
ba5a7c8cd8 | ||
|
|
527cfcd87f | ||
|
|
ef7aefeb45 | ||
|
|
45aea56198 | ||
|
|
daf954057f | ||
|
|
d7e6b83e64 | ||
|
|
80dc5a7b1c | ||
|
|
0f881bc90a | ||
|
|
6efa92de70 | ||
|
|
2adb710751 | ||
|
|
97f69986ff | ||
|
|
5df40661d2 | ||
|
|
889d67bcee | ||
|
|
8b91287034 | ||
|
|
1148ed1566 | ||
|
|
e3c44231ab | ||
|
|
188ff8cde7 | ||
|
|
3aa17fa0d6 | ||
|
|
4f3aeaefc1 | ||
|
|
120bfdf33d | ||
|
|
73625a2622 | ||
|
|
9f2b62dd1c | ||
|
|
60f52adc90 | ||
|
|
7eefedfb11 | ||
|
|
af80d253db | ||
|
|
ab939cc6e8 | ||
|
|
ca9413bc64 | ||
|
|
bfe42fdccb | ||
|
|
ce2dd28a25 | ||
|
|
96dcfba65a | ||
|
|
6e4d4a55cd | ||
|
|
3349dde5e2 | ||
|
|
4eefb445a7 | ||
|
|
ed927f102e | ||
|
|
82026f780d | ||
|
|
e5aeab7e7e | ||
|
|
32738637ce | ||
|
|
80f5026208 | ||
|
|
00619342e1 | ||
|
|
b719585a2f | ||
|
|
4970b5d5bc | ||
|
|
bdd382bdfd | ||
|
|
92a5cda61a | ||
|
|
60b26ad8b2 | ||
|
|
efe9f6656f | ||
|
|
22bd6a54b2 | ||
|
|
a36b6cb102 | ||
|
|
d91813c277 | ||
|
|
0ec17590ae | ||
|
|
2154502955 | ||
|
|
a4ddf93492 | ||
|
|
9c5a79209e | ||
|
|
5dc22e1811 | ||
|
|
ad8475cb8b | ||
|
|
ff60ec85b8 | ||
|
|
c1fe4bcc64 | ||
|
|
20576e0f47 | ||
|
|
20e0acc20a | ||
|
|
cfb3d87267 | ||
|
|
1cde804c77 | ||
|
|
1387b0ba7f | ||
|
|
2e03af7ac4 | ||
|
|
749c735627 | ||
|
|
aef87cced7 | ||
|
|
6bb2d9195f | ||
|
|
28ebc4cfee | ||
|
|
ad5906916d | ||
|
|
114f2b4326 | ||
|
|
a27a4db3de | ||
|
|
b4354cbc8d | ||
|
|
02fde73545 | ||
|
|
19975dcb7b | ||
|
|
641c3de0ca | ||
|
|
cf6b52e543 | ||
|
|
9500254861 | ||
|
|
13e5578bc6 | ||
|
|
24137ff54f | ||
|
|
9a13842751 | ||
|
|
13b4ddec63 | ||
|
|
39c8507dc2 | ||
|
|
0b1cc7fad1 | ||
|
|
8bc1efcf8b | ||
|
|
1a67d7d95f | ||
|
|
4dad4b50fb | ||
|
|
0f9734ae37 | ||
|
|
a43ee34bd5 | ||
|
|
e6f599b32d | ||
|
|
8cf6ff69c0 | ||
|
|
2249b7c793 | ||
|
|
591de1338b | ||
|
|
2c95cd206b | ||
|
|
8ee6dbc1e2 | ||
|
|
beb169cf75 | ||
|
|
b40d3b0a05 | ||
|
|
93ff84bf56 | ||
|
|
498c9c7955 | ||
|
|
073f2fa302 | ||
|
|
9339a8b57f | ||
|
|
fbeaf2b398 | ||
|
|
7c0e180fd9 | ||
|
|
1710e10b31 | ||
|
|
8ae7ca7f14 | ||
|
|
5fc29ac913 | ||
|
|
41d9225bd1 | ||
|
|
53f6cfb216 | ||
|
|
6827edb2c5 | ||
|
|
0b525f9d87 | ||
|
|
c7509d8ebf | ||
|
|
566876ae7a | ||
|
|
2820a0ac0a | ||
|
|
116ff8241c | ||
|
|
89623aba57 | ||
|
|
f567af49a6 | ||
|
|
1aecb578e6 | ||
|
|
a87bb21246 | ||
|
|
ec5c0deb0e | ||
|
|
3b14c59133 | ||
|
|
98e2b6575d | ||
|
|
9947bae60e | ||
|
|
402a1b91f9 | ||
|
|
3b07700ef6 | ||
|
|
d3aff000d9 | ||
|
|
c648090b5d | ||
|
|
d0687788b5 | ||
|
|
3c46abca6c | ||
|
|
cdd0acc672 | ||
|
|
c20241fcb5 | ||
|
|
ac81323fec | ||
|
|
6b5fa2c673 | ||
|
|
e4755778ae | ||
|
|
6c8f52b26f | ||
|
|
0c47396785 | ||
|
|
935622bde8 | ||
|
|
ea33f902e7 | ||
|
|
ea1624fba5 | ||
|
|
f31c6f52e8 | ||
|
|
3036a6afdc | ||
|
|
e67ed4fb2d | ||
|
|
f32a870a58 | ||
|
|
e69f9ddf8b | ||
|
|
2bcd032a44 | ||
|
|
33bffe8201 | ||
|
|
8039dc5194 | ||
|
|
2a195d457e | ||
|
|
951e8e3a73 | ||
|
|
268731aec4 | ||
|
|
7b3f9386d7 | ||
|
|
d9e2427aa8 | ||
|
|
eb0bc5c6ad | ||
|
|
fde6fadf4d | ||
|
|
432a14c84c | ||
|
|
813b7a96fb | ||
|
|
bbdf98a8f0 | ||
|
|
d96a777edd | ||
|
|
c67b0a3a64 | ||
|
|
7cc324e31e | ||
|
|
f057dc6867 | ||
|
|
e53931e27a | ||
|
|
6f9fe6a792 | ||
|
|
38c5ecf007 | ||
|
|
c1922ea5de | ||
|
|
54bcbd0bc6 | ||
|
|
9f27ac142b | ||
|
|
2ef0596df2 | ||
|
|
3ff562cb8a | ||
|
|
8fdf0ca2d3 | ||
|
|
01f507ebcb | ||
|
|
e1ba5878a3 | ||
|
|
6dceb25fb2 | ||
|
|
5b4c5d59d8 | ||
|
|
28626cd7c0 | ||
|
|
58343e5b7c | ||
|
|
8e1f6c8149 | ||
|
|
53bf44d2b8 | ||
|
|
ce7d05aa1f | ||
|
|
135e19d0aa | ||
|
|
bb421c8b07 | ||
|
|
b5be17c6df | ||
|
|
2b93be1139 | ||
|
|
bd464197c4 | ||
|
|
8d2c78867e | ||
|
|
8548eae368 | ||
|
|
d319caa2ee | ||
|
|
f01f6d50b5 | ||
|
|
e9d36242ce | ||
|
|
b73507abe0 | ||
|
|
5d33bbaff0 | ||
|
|
60329ade9e | ||
|
|
300aaa39fe | ||
|
|
b21da472f6 | ||
|
|
73ecf51a27 | ||
|
|
0d3a77dce9 | ||
|
|
f52d7c7665 | ||
|
|
026824880d | ||
|
|
c86deceaba | ||
|
|
37767738b0 | ||
|
|
517bedeb7e | ||
|
|
0a95b38166 | ||
|
|
43fed29514 | ||
|
|
f73685f4f6 | ||
|
|
c61925598a | ||
|
|
a8949174c8 | ||
|
|
906ac093e3 | ||
|
|
8e0a7a8dbc | ||
|
|
e824cd012b | ||
|
|
083da7d8a4 | ||
|
|
383a4b132e | ||
|
|
bfaa93b0ca | ||
|
|
1662a4c9c3 | ||
|
|
c2f0fadb6e | ||
|
|
c78fdaae90 | ||
|
|
8b21ca2db9 | ||
|
|
fed8cf4196 | ||
|
|
528ed9c986 | ||
|
|
e2cccc4005 | ||
|
|
569d0961f2 | ||
|
|
de46fa8e66 | ||
|
|
bfa0c0981c | ||
|
|
c77c296b8b | ||
|
|
9ab55a5bd8 | ||
|
|
e4d657e6fd | ||
|
|
f4c8d63fe0 | ||
|
|
d94f45531a | ||
|
|
4d38bd8517 | ||
|
|
c99e7ca999 | ||
|
|
aba3065573 | ||
|
|
e95dce6d8d | ||
|
|
e97af14ff4 | ||
|
|
c809e61103 |
@@ -9,6 +9,13 @@ trim_trailing_whitespace = true
|
|||||||
charset = utf-8
|
charset = utf-8
|
||||||
|
|
||||||
# python, js indentation settings
|
# python, js indentation settings
|
||||||
[{*.py,*.js}]
|
[{*.py,*.js,*.vue,*.css,*.scss,*.html}]
|
||||||
indent_style = tab
|
indent_style = tab
|
||||||
indent_size = 4
|
indent_size = 4
|
||||||
|
max_line_length = 110
|
||||||
|
|
||||||
|
# JSON files - mostly doctype schema files
|
||||||
|
[{*.json}]
|
||||||
|
insert_final_newline = false
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|||||||
@@ -124,6 +124,7 @@
|
|||||||
"beforeEach": true,
|
"beforeEach": true,
|
||||||
"onScan": true,
|
"onScan": true,
|
||||||
"extend_cscript": true,
|
"extend_cscript": true,
|
||||||
"localforage": true
|
"localforage": true,
|
||||||
|
"Plaid": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,3 +32,9 @@ baec607ff5905b1c67531096a9cf50ec7ff00a5d
|
|||||||
|
|
||||||
# bulk refactor with sourcery
|
# bulk refactor with sourcery
|
||||||
eb9ee3f79b94e594fc6dfa4f6514580e125eee8c
|
eb9ee3f79b94e594fc6dfa4f6514580e125eee8c
|
||||||
|
|
||||||
|
# js formatting
|
||||||
|
ec74a5e56617bbd76ac402451468fd4668af543d
|
||||||
|
|
||||||
|
# ruff formatting
|
||||||
|
a308792ee7fda18a681e9181f4fd00b36385bc23
|
||||||
|
|||||||
15
.github/helper/documentation.py
vendored
15
.github/helper/documentation.py
vendored
@@ -1,7 +1,7 @@
|
|||||||
import sys
|
import sys
|
||||||
import requests
|
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
WEBSITE_REPOS = [
|
WEBSITE_REPOS = [
|
||||||
"erpnext_com",
|
"erpnext_com",
|
||||||
@@ -36,11 +36,7 @@ def is_documentation_link(word: str) -> bool:
|
|||||||
|
|
||||||
|
|
||||||
def contains_documentation_link(body: str) -> bool:
|
def contains_documentation_link(body: str) -> bool:
|
||||||
return any(
|
return any(is_documentation_link(word) for line in body.splitlines() for word in line.split())
|
||||||
is_documentation_link(word)
|
|
||||||
for line in body.splitlines()
|
|
||||||
for word in line.split()
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def check_pull_request(number: str) -> "tuple[int, str]":
|
def check_pull_request(number: str) -> "tuple[int, str]":
|
||||||
@@ -53,12 +49,7 @@ def check_pull_request(number: str) -> "tuple[int, str]":
|
|||||||
head_sha = (payload.get("head") or {}).get("sha")
|
head_sha = (payload.get("head") or {}).get("sha")
|
||||||
body = (payload.get("body") or "").lower()
|
body = (payload.get("body") or "").lower()
|
||||||
|
|
||||||
if (
|
if not title.startswith("feat") or not head_sha or "no-docs" in body or "backport" in body:
|
||||||
not title.startswith("feat")
|
|
||||||
or not head_sha
|
|
||||||
or "no-docs" in body
|
|
||||||
or "backport" in body
|
|
||||||
):
|
|
||||||
return 0, "Skipping documentation checks... 🏃"
|
return 0, "Skipping documentation checks... 🏃"
|
||||||
|
|
||||||
if contains_documentation_link(body):
|
if contains_documentation_link(body):
|
||||||
|
|||||||
30
.github/helper/translation.py
vendored
30
.github/helper/translation.py
vendored
@@ -2,7 +2,9 @@ import re
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
errors_encounter = 0
|
errors_encounter = 0
|
||||||
pattern = re.compile(r"_\(([\"']{,3})(?P<message>((?!\1).)*)\1(\s*,\s*context\s*=\s*([\"'])(?P<py_context>((?!\5).)*)\5)*(\s*,(\s*?.*?\n*?)*(,\s*([\"'])(?P<js_context>((?!\11).)*)\11)*)*\)")
|
pattern = re.compile(
|
||||||
|
r"_\(([\"']{,3})(?P<message>((?!\1).)*)\1(\s*,\s*context\s*=\s*([\"'])(?P<py_context>((?!\5).)*)\5)*(\s*,(\s*?.*?\n*?)*(,\s*([\"'])(?P<js_context>((?!\11).)*)\11)*)*\)"
|
||||||
|
)
|
||||||
words_pattern = re.compile(r"_{1,2}\([\"'`]{1,3}.*?[a-zA-Z]")
|
words_pattern = re.compile(r"_{1,2}\([\"'`]{1,3}.*?[a-zA-Z]")
|
||||||
start_pattern = re.compile(r"_{1,2}\([f\"'`]{1,3}")
|
start_pattern = re.compile(r"_{1,2}\([f\"'`]{1,3}")
|
||||||
f_string_pattern = re.compile(r"_\(f[\"']")
|
f_string_pattern = re.compile(r"_\(f[\"']")
|
||||||
@@ -10,14 +12,14 @@ starts_with_f_pattern = re.compile(r"_\(f")
|
|||||||
|
|
||||||
# skip first argument
|
# skip first argument
|
||||||
files = sys.argv[1:]
|
files = sys.argv[1:]
|
||||||
files_to_scan = [_file for _file in files if _file.endswith(('.py', '.js'))]
|
files_to_scan = [_file for _file in files if _file.endswith((".py", ".js"))]
|
||||||
|
|
||||||
for _file in files_to_scan:
|
for _file in files_to_scan:
|
||||||
with open(_file, 'r') as f:
|
with open(_file) as f:
|
||||||
print(f'Checking: {_file}')
|
print(f"Checking: {_file}")
|
||||||
file_lines = f.readlines()
|
file_lines = f.readlines()
|
||||||
for line_number, line in enumerate(file_lines, 1):
|
for line_number, line in enumerate(file_lines, 1):
|
||||||
if 'frappe-lint: disable-translate' in line:
|
if "frappe-lint: disable-translate" in line:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
start_matches = start_pattern.search(line)
|
start_matches = start_pattern.search(line)
|
||||||
@@ -28,7 +30,9 @@ for _file in files_to_scan:
|
|||||||
has_f_string = f_string_pattern.search(line)
|
has_f_string = f_string_pattern.search(line)
|
||||||
if has_f_string:
|
if has_f_string:
|
||||||
errors_encounter += 1
|
errors_encounter += 1
|
||||||
print(f'\nF-strings are not supported for translations at line number {line_number}\n{line.strip()[:100]}')
|
print(
|
||||||
|
f"\nF-strings are not supported for translations at line number {line_number}\n{line.strip()[:100]}"
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
@@ -36,7 +40,7 @@ for _file in files_to_scan:
|
|||||||
match = pattern.search(line)
|
match = pattern.search(line)
|
||||||
error_found = False
|
error_found = False
|
||||||
|
|
||||||
if not match and line.endswith((',\n', '[\n')):
|
if not match and line.endswith((",\n", "[\n")):
|
||||||
# concat remaining text to validate multiline pattern
|
# concat remaining text to validate multiline pattern
|
||||||
line = "".join(file_lines[line_number - 1 :])
|
line = "".join(file_lines[line_number - 1 :])
|
||||||
line = line[start_matches.start() + 1 :]
|
line = line[start_matches.start() + 1 :]
|
||||||
@@ -44,17 +48,21 @@ for _file in files_to_scan:
|
|||||||
|
|
||||||
if not match:
|
if not match:
|
||||||
error_found = True
|
error_found = True
|
||||||
print(f'\nTranslation syntax error at line number {line_number}\n{line.strip()[:100]}')
|
print(f"\nTranslation syntax error at line number {line_number}\n{line.strip()[:100]}")
|
||||||
|
|
||||||
if not error_found and not words_pattern.search(line):
|
if not error_found and not words_pattern.search(line):
|
||||||
error_found = True
|
error_found = True
|
||||||
print(f'\nTranslation is useless because it has no words at line number {line_number}\n{line.strip()[:100]}')
|
print(
|
||||||
|
f"\nTranslation is useless because it has no words at line number {line_number}\n{line.strip()[:100]}"
|
||||||
|
)
|
||||||
|
|
||||||
if error_found:
|
if error_found:
|
||||||
errors_encounter += 1
|
errors_encounter += 1
|
||||||
|
|
||||||
if errors_encounter > 0:
|
if errors_encounter > 0:
|
||||||
print('\nVisit "https://frappeframework.com/docs/user/en/translations" to learn about valid translation strings.')
|
print(
|
||||||
|
'\nVisit "https://frappeframework.com/docs/user/en/translations" to learn about valid translation strings.'
|
||||||
|
)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
else:
|
else:
|
||||||
print('\nGood To Go!')
|
print("\nGood To Go!")
|
||||||
|
|||||||
40
.github/helper/update_pot_file.sh
vendored
Normal file
40
.github/helper/update_pot_file.sh
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
cd ~ || exit
|
||||||
|
|
||||||
|
echo "Setting Up Bench..."
|
||||||
|
|
||||||
|
pip install frappe-bench
|
||||||
|
bench -v init frappe-bench --skip-assets --skip-redis-config-generation --python "$(which python)"
|
||||||
|
cd ./frappe-bench || exit
|
||||||
|
|
||||||
|
echo "Get ERPNext..."
|
||||||
|
bench get-app --skip-assets erpnext "${GITHUB_WORKSPACE}"
|
||||||
|
|
||||||
|
echo "Generating POT file..."
|
||||||
|
bench generate-pot-file --app erpnext
|
||||||
|
|
||||||
|
cd ./apps/erpnext || exit
|
||||||
|
|
||||||
|
echo "Configuring git user..."
|
||||||
|
git config user.email "developers@erpnext.com"
|
||||||
|
git config user.name "frappe-pr-bot"
|
||||||
|
|
||||||
|
echo "Setting the correct git remote..."
|
||||||
|
# Here, the git remote is a local file path by default. Let's change it to the upstream repo.
|
||||||
|
git remote set-url upstream https://github.com/frappe/erpnext.git
|
||||||
|
|
||||||
|
echo "Creating a new branch..."
|
||||||
|
isodate=$(date -u +"%Y-%m-%d")
|
||||||
|
branch_name="pot_${BASE_BRANCH}_${isodate}"
|
||||||
|
git checkout -b "${branch_name}"
|
||||||
|
|
||||||
|
echo "Commiting changes..."
|
||||||
|
git add .
|
||||||
|
git commit -m "chore: update POT file"
|
||||||
|
|
||||||
|
gh auth setup-git
|
||||||
|
git push -u upstream "${branch_name}"
|
||||||
|
|
||||||
|
echo "Creating a PR..."
|
||||||
|
gh pr create --fill --base "${BASE_BRANCH}" --head "${branch_name}" -R frappe/erpnext
|
||||||
38
.github/workflows/generate-pot-file.yml
vendored
Normal file
38
.github/workflows/generate-pot-file.yml
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# This workflow is agnostic to branches. Only maintain on develop branch.
|
||||||
|
# To add/remove branches just modify the matrix.
|
||||||
|
|
||||||
|
name: Regenerate POT file (translatable strings)
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
# 9:30 UTC => 3 PM IST Sunday
|
||||||
|
- cron: "30 9 * * 0"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
regeneratee-pot-file:
|
||||||
|
name: Release
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
branch: ["develop"]
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
ref: ${{ matrix.branch }}
|
||||||
|
|
||||||
|
- name: Setup Python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.12"
|
||||||
|
|
||||||
|
- name: Run script to update POT file
|
||||||
|
run: |
|
||||||
|
bash ${GITHUB_WORKSPACE}/.github/helper/update_pot_file.sh
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||||
|
BASE_BRANCH: ${{ matrix.branch }}
|
||||||
12
.github/workflows/linters.yml
vendored
12
.github/workflows/linters.yml
vendored
@@ -20,6 +20,18 @@ jobs:
|
|||||||
- name: Install and Run Pre-commit
|
- name: Install and Run Pre-commit
|
||||||
uses: pre-commit/action@v3.0.0
|
uses: pre-commit/action@v3.0.0
|
||||||
|
|
||||||
|
semgrep:
|
||||||
|
name: semgrep
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set up Python 3.10
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.10'
|
||||||
|
cache: pip
|
||||||
|
|
||||||
- name: Download Semgrep rules
|
- name: Download Semgrep rules
|
||||||
run: git clone --depth 1 https://github.com/frappe/semgrep-rules.git frappe-semgrep-rules
|
run: git clone --depth 1 https://github.com/frappe/semgrep-rules.git frappe-semgrep-rules
|
||||||
|
|
||||||
|
|||||||
14
.github/workflows/patch.yml
vendored
14
.github/workflows/patch.yml
vendored
@@ -32,7 +32,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Clone
|
- name: Clone
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Check for valid Python & Merge Conflicts
|
- name: Check for valid Python & Merge Conflicts
|
||||||
run: |
|
run: |
|
||||||
@@ -43,12 +43,12 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: "actions/setup-python@v4"
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: '3.10'
|
python-version: '3.11'
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
check-latest: true
|
check-latest: true
|
||||||
@@ -57,7 +57,7 @@ jobs:
|
|||||||
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
|
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
|
||||||
|
|
||||||
- name: Cache pip
|
- name: Cache pip
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.cache/pip
|
path: ~/.cache/pip
|
||||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml') }}
|
key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml') }}
|
||||||
@@ -66,7 +66,7 @@ jobs:
|
|||||||
${{ runner.os }}-
|
${{ runner.os }}-
|
||||||
|
|
||||||
- name: Cache node modules
|
- name: Cache node modules
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v4
|
||||||
env:
|
env:
|
||||||
cache-name: cache-node-modules
|
cache-name: cache-node-modules
|
||||||
with:
|
with:
|
||||||
@@ -81,7 +81,7 @@ jobs:
|
|||||||
id: yarn-cache-dir-path
|
id: yarn-cache-dir-path
|
||||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||||
|
|
||||||
- uses: actions/cache@v2
|
- uses: actions/cache@v4
|
||||||
id: yarn-cache
|
id: yarn-cache
|
||||||
with:
|
with:
|
||||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||||
|
|||||||
22
.github/workflows/patch_faux.yml
vendored
Normal file
22
.github/workflows/patch_faux.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# Tests are skipped for these files but github doesn't allow "passing" hence this is required.
|
||||||
|
|
||||||
|
name: Skipped Patch Test
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- "**.js"
|
||||||
|
- "**.css"
|
||||||
|
- "**.md"
|
||||||
|
- "**.html"
|
||||||
|
- "**.csv"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
name: Patch Test
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Pass skipped tests unconditionally
|
||||||
|
run: "echo Skipped"
|
||||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
|||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 20
|
||||||
- name: Setup dependencies
|
- name: Setup dependencies
|
||||||
run: |
|
run: |
|
||||||
npm install @semantic-release/git @semantic-release/exec --no-save
|
npm install @semantic-release/git @semantic-release/exec --no-save
|
||||||
|
|||||||
24
.github/workflows/server-tests-mariadb-faux.yml
vendored
Normal file
24
.github/workflows/server-tests-mariadb-faux.yml
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# Tests are skipped for these files but github doesn't allow "passing" hence this is required.
|
||||||
|
|
||||||
|
name: Skipped Tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- "**.js"
|
||||||
|
- "**.css"
|
||||||
|
- "**.md"
|
||||||
|
- "**.html"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
container: [1, 2, 3, 4]
|
||||||
|
|
||||||
|
name: Python Unit Tests
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Pass skipped tests unconditionally
|
||||||
|
run: "echo Skipped"
|
||||||
30
.github/workflows/server-tests-mariadb.yml
vendored
30
.github/workflows/server-tests-mariadb.yml
vendored
@@ -31,6 +31,9 @@ jobs:
|
|||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 60
|
timeout-minutes: 60
|
||||||
|
env:
|
||||||
|
NODE_ENV: "production"
|
||||||
|
WITH_COVERAGE: ${{ github.event_name != 'pull_request' }}
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
@@ -51,12 +54,12 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Clone
|
- name: Clone
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: '3.11'
|
python-version: '3.12'
|
||||||
|
|
||||||
- name: Check for valid Python & Merge Conflicts
|
- name: Check for valid Python & Merge Conflicts
|
||||||
run: |
|
run: |
|
||||||
@@ -67,7 +70,7 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
check-latest: true
|
check-latest: true
|
||||||
@@ -76,7 +79,7 @@ jobs:
|
|||||||
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
|
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
|
||||||
|
|
||||||
- name: Cache pip
|
- name: Cache pip
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.cache/pip
|
path: ~/.cache/pip
|
||||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml') }}
|
key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml') }}
|
||||||
@@ -85,7 +88,7 @@ jobs:
|
|||||||
${{ runner.os }}-
|
${{ runner.os }}-
|
||||||
|
|
||||||
- name: Cache node modules
|
- name: Cache node modules
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v4
|
||||||
env:
|
env:
|
||||||
cache-name: cache-node-modules
|
cache-name: cache-node-modules
|
||||||
with:
|
with:
|
||||||
@@ -100,7 +103,7 @@ jobs:
|
|||||||
id: yarn-cache-dir-path
|
id: yarn-cache-dir-path
|
||||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||||
|
|
||||||
- uses: actions/cache@v2
|
- uses: actions/cache@v4
|
||||||
id: yarn-cache
|
id: yarn-cache
|
||||||
with:
|
with:
|
||||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||||
@@ -117,11 +120,11 @@ jobs:
|
|||||||
FRAPPE_BRANCH: ${{ github.event.inputs.branch }}
|
FRAPPE_BRANCH: ${{ github.event.inputs.branch }}
|
||||||
|
|
||||||
- name: Run Tests
|
- name: Run Tests
|
||||||
run: 'cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --app erpnext --with-coverage --total-builds 4 --build-number ${{ matrix.container }}'
|
run: 'cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --app erpnext --total-builds 4 --build-number ${{ matrix.container }}'
|
||||||
env:
|
env:
|
||||||
TYPE: server
|
TYPE: server
|
||||||
CI_BUILD_ID: ${{ github.run_id }}
|
CAPTURE_COVERAGE: ${{ github.event_name != 'pull_request' }}
|
||||||
ORCHESTRATOR_URL: http://test-orchestrator.frappe.io
|
|
||||||
|
|
||||||
- name: Show bench output
|
- name: Show bench output
|
||||||
if: ${{ always() }}
|
if: ${{ always() }}
|
||||||
@@ -129,6 +132,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Upload coverage data
|
- name: Upload coverage data
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
with:
|
with:
|
||||||
name: coverage-${{ matrix.container }}
|
name: coverage-${{ matrix.container }}
|
||||||
path: /home/runner/frappe-bench/sites/coverage.xml
|
path: /home/runner/frappe-bench/sites/coverage.xml
|
||||||
@@ -137,16 +141,18 @@ jobs:
|
|||||||
name: Coverage Wrap Up
|
name: Coverage Wrap Up
|
||||||
needs: test
|
needs: test
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ github.event_name != 'pull_request' }}
|
||||||
steps:
|
steps:
|
||||||
- name: Clone
|
- name: Clone
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Download artifacts
|
- name: Download artifacts
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v3
|
||||||
|
|
||||||
- name: Upload coverage data
|
- name: Upload coverage data
|
||||||
uses: codecov/codecov-action@v2
|
uses: codecov/codecov-action@v4
|
||||||
with:
|
with:
|
||||||
name: MariaDB
|
name: MariaDB
|
||||||
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
fail_ci_if_error: true
|
fail_ci_if_error: true
|
||||||
verbose: true
|
verbose: true
|
||||||
|
|||||||
14
.github/workflows/server-tests-postgres.yml
vendored
14
.github/workflows/server-tests-postgres.yml
vendored
@@ -41,12 +41,12 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
|
|
||||||
- name: Clone
|
- name: Clone
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: '3.10'
|
python-version: '3.12'
|
||||||
|
|
||||||
- name: Check for valid Python & Merge Conflicts
|
- name: Check for valid Python & Merge Conflicts
|
||||||
run: |
|
run: |
|
||||||
@@ -57,7 +57,7 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
check-latest: true
|
check-latest: true
|
||||||
@@ -66,7 +66,7 @@ jobs:
|
|||||||
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
|
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
|
||||||
|
|
||||||
- name: Cache pip
|
- name: Cache pip
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.cache/pip
|
path: ~/.cache/pip
|
||||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml') }}
|
key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml') }}
|
||||||
@@ -75,7 +75,7 @@ jobs:
|
|||||||
${{ runner.os }}-
|
${{ runner.os }}-
|
||||||
|
|
||||||
- name: Cache node modules
|
- name: Cache node modules
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v4
|
||||||
env:
|
env:
|
||||||
cache-name: cache-node-modules
|
cache-name: cache-node-modules
|
||||||
with:
|
with:
|
||||||
@@ -90,7 +90,7 @@ jobs:
|
|||||||
id: yarn-cache-dir-path
|
id: yarn-cache-dir-path
|
||||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||||
|
|
||||||
- uses: actions/cache@v2
|
- uses: actions/cache@v4
|
||||||
id: yarn-cache
|
id: yarn-cache
|
||||||
with:
|
with:
|
||||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,7 +2,6 @@
|
|||||||
*.py~
|
*.py~
|
||||||
.DS_Store
|
.DS_Store
|
||||||
conf.py
|
conf.py
|
||||||
locale
|
|
||||||
latest_updates.json
|
latest_updates.json
|
||||||
.wnf-lang-status
|
.wnf-lang-status
|
||||||
*.egg-info
|
*.egg-info
|
||||||
|
|||||||
@@ -20,6 +20,23 @@ repos:
|
|||||||
- id: check-yaml
|
- id: check-yaml
|
||||||
- id: debug-statements
|
- id: debug-statements
|
||||||
|
|
||||||
|
- repo: https://github.com/pre-commit/mirrors-prettier
|
||||||
|
rev: v2.7.1
|
||||||
|
hooks:
|
||||||
|
- id: prettier
|
||||||
|
types_or: [javascript, vue, scss]
|
||||||
|
# Ignore any files that might contain jinja / bundles
|
||||||
|
exclude: |
|
||||||
|
(?x)^(
|
||||||
|
erpnext/public/dist/.*|
|
||||||
|
cypress/.*|
|
||||||
|
.*node_modules.*|
|
||||||
|
.*boilerplate.*|
|
||||||
|
erpnext/public/js/controllers/.*|
|
||||||
|
erpnext/templates/pages/order.js|
|
||||||
|
erpnext/templates/includes/.*
|
||||||
|
)$
|
||||||
|
|
||||||
- repo: https://github.com/pre-commit/mirrors-eslint
|
- repo: https://github.com/pre-commit/mirrors-eslint
|
||||||
rev: v8.44.0
|
rev: v8.44.0
|
||||||
hooks:
|
hooks:
|
||||||
@@ -38,28 +55,15 @@ repos:
|
|||||||
erpnext/templates/includes/.*
|
erpnext/templates/includes/.*
|
||||||
)$
|
)$
|
||||||
|
|
||||||
- repo: https://github.com/PyCQA/flake8
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
rev: 6.0.0
|
rev: v0.2.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: flake8
|
- id: ruff
|
||||||
additional_dependencies: [
|
name: "Run ruff linter and apply fixes"
|
||||||
'flake8-bugbear',
|
args: ["--fix"]
|
||||||
'flake8-tuple',
|
|
||||||
]
|
|
||||||
args: ['--config', '.github/helper/.flake8_strict']
|
|
||||||
exclude: ".*setup.py$"
|
|
||||||
|
|
||||||
- repo: https://github.com/adityahase/black
|
- id: ruff-format
|
||||||
rev: 9cb0a69f4d0030cdf687eddf314468b39ed54119
|
name: "Format Python code"
|
||||||
hooks:
|
|
||||||
- id: black
|
|
||||||
additional_dependencies: ['click==8.0.4']
|
|
||||||
|
|
||||||
- repo: https://github.com/PyCQA/isort
|
|
||||||
rev: 5.12.0
|
|
||||||
hooks:
|
|
||||||
- id: isort
|
|
||||||
exclude: ".*setup.py$"
|
|
||||||
|
|
||||||
|
|
||||||
ci:
|
ci:
|
||||||
|
|||||||
@@ -7,8 +7,7 @@
|
|||||||
<p>ERP made simple</p>
|
<p>ERP made simple</p>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
[](https://github.com/frappe/erpnext/actions/workflows/server-tests.yml)
|
[](https://github.com/frappe/erpnext/actions/workflows/server-tests-mariadb.yml)
|
||||||
[](https://github.com/erpnext/erpnext_ui_tests/actions/workflows/ui-tests.yml)
|
|
||||||
[](https://www.codetriage.com/frappe/erpnext)
|
[](https://www.codetriage.com/frappe/erpnext)
|
||||||
[](https://codecov.io/gh/frappe/erpnext)
|
[](https://codecov.io/gh/frappe/erpnext)
|
||||||
[](https://hub.docker.com/r/frappe/erpnext-worker)
|
[](https://hub.docker.com/r/frappe/erpnext-worker)
|
||||||
|
|||||||
1
babel_extractors.csv
Normal file
1
babel_extractors.csv
Normal file
@@ -0,0 +1 @@
|
|||||||
|
**/setup/setup_wizard/data/uom_data.json,erpnext.gettext.extractors.uom_data.extract
|
||||||
|
@@ -1,25 +1,13 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
parserPreset: 'conventional-changelog-conventionalcommits',
|
parserPreset: "conventional-changelog-conventionalcommits",
|
||||||
rules: {
|
rules: {
|
||||||
'subject-empty': [2, 'never'],
|
"subject-empty": [2, "never"],
|
||||||
'type-case': [2, 'always', 'lower-case'],
|
"type-case": [2, "always", "lower-case"],
|
||||||
'type-empty': [2, 'never'],
|
"type-empty": [2, "never"],
|
||||||
'type-enum': [
|
"type-enum": [
|
||||||
2,
|
2,
|
||||||
'always',
|
"always",
|
||||||
[
|
["build", "chore", "ci", "docs", "feat", "fix", "perf", "refactor", "revert", "style", "test"],
|
||||||
'build',
|
|
||||||
'chore',
|
|
||||||
'ci',
|
|
||||||
'docs',
|
|
||||||
'feat',
|
|
||||||
'fix',
|
|
||||||
'perf',
|
|
||||||
'refactor',
|
|
||||||
'revert',
|
|
||||||
'style',
|
|
||||||
'test',
|
|
||||||
],
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
8
crowdin.yml
Normal file
8
crowdin.yml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
files:
|
||||||
|
- source: /erpnext/locale/main.pot
|
||||||
|
translation: /erpnext/locale/%two_letters_code%.po
|
||||||
|
pull_request_title: "fix: sync translations from crowdin"
|
||||||
|
pull_request_labels:
|
||||||
|
- translation
|
||||||
|
commit_message: "fix: %language% translations"
|
||||||
|
append_commit_message: false
|
||||||
@@ -13,7 +13,7 @@ def get_default_company(user=None):
|
|||||||
if not user:
|
if not user:
|
||||||
user = frappe.session.user
|
user = frappe.session.user
|
||||||
|
|
||||||
companies = get_user_default_as_list(user, "company")
|
companies = get_user_default_as_list("company", user)
|
||||||
if companies:
|
if companies:
|
||||||
default_company = companies[0]
|
default_company = companies[0]
|
||||||
else:
|
else:
|
||||||
@@ -37,9 +37,7 @@ def get_default_cost_center(company):
|
|||||||
if not frappe.flags.company_cost_center:
|
if not frappe.flags.company_cost_center:
|
||||||
frappe.flags.company_cost_center = {}
|
frappe.flags.company_cost_center = {}
|
||||||
if company not in frappe.flags.company_cost_center:
|
if company not in frappe.flags.company_cost_center:
|
||||||
frappe.flags.company_cost_center[company] = frappe.get_cached_value(
|
frappe.flags.company_cost_center[company] = frappe.get_cached_value("Company", company, "cost_center")
|
||||||
"Company", company, "cost_center"
|
|
||||||
)
|
|
||||||
return frappe.flags.company_cost_center[company]
|
return frappe.flags.company_cost_center[company]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,14 +11,14 @@ class ERPNextAddress(Address):
|
|||||||
def validate(self):
|
def validate(self):
|
||||||
self.validate_reference()
|
self.validate_reference()
|
||||||
self.update_compnay_address()
|
self.update_compnay_address()
|
||||||
super(ERPNextAddress, self).validate()
|
super().validate()
|
||||||
|
|
||||||
def link_address(self):
|
def link_address(self):
|
||||||
"""Link address based on owner"""
|
"""Link address based on owner"""
|
||||||
if self.is_your_company_address:
|
if self.is_your_company_address:
|
||||||
return
|
return
|
||||||
|
|
||||||
return super(ERPNextAddress, self).link_address()
|
return super().link_address()
|
||||||
|
|
||||||
def update_compnay_address(self):
|
def update_compnay_address(self):
|
||||||
for link in self.get("links"):
|
for link in self.get("links"):
|
||||||
@@ -26,11 +26,11 @@ class ERPNextAddress(Address):
|
|||||||
self.is_your_company_address = 1
|
self.is_your_company_address = 1
|
||||||
|
|
||||||
def validate_reference(self):
|
def validate_reference(self):
|
||||||
if self.is_your_company_address and not [
|
if self.is_your_company_address and not [row for row in self.links if row.link_doctype == "Company"]:
|
||||||
row for row in self.links if row.link_doctype == "Company"
|
|
||||||
]:
|
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_("Address needs to be linked to a Company. Please add a row for Company in the Links table."),
|
_(
|
||||||
|
"Address needs to be linked to a Company. Please add a row for Company in the Links table."
|
||||||
|
),
|
||||||
title=_("Company Not Linked"),
|
title=_("Company Not Linked"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
frappe.provide('frappe.dashboards.chart_sources');
|
frappe.provide("frappe.dashboards.chart_sources");
|
||||||
|
|
||||||
frappe.dashboards.chart_sources["Account Balance Timeline"] = {
|
frappe.dashboards.chart_sources["Account Balance Timeline"] = {
|
||||||
method: "erpnext.accounts.dashboard_chart_source.account_balance_timeline.account_balance_timeline.get",
|
method: "erpnext.accounts.dashboard_chart_source.account_balance_timeline.account_balance_timeline.get",
|
||||||
@@ -9,14 +9,14 @@ frappe.dashboards.chart_sources["Account Balance Timeline"] = {
|
|||||||
fieldtype: "Link",
|
fieldtype: "Link",
|
||||||
options: "Company",
|
options: "Company",
|
||||||
default: frappe.defaults.get_user_default("Company"),
|
default: frappe.defaults.get_user_default("Company"),
|
||||||
reqd: 1
|
reqd: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fieldname: "account",
|
fieldname: "account",
|
||||||
label: __("Account"),
|
label: __("Account"),
|
||||||
fieldtype: "Link",
|
fieldtype: "Link",
|
||||||
options: "Account",
|
options: "Account",
|
||||||
reqd: 1
|
reqd: 1,
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ def get(
|
|||||||
filters = frappe.parse_json(filters) or frappe.parse_json(chart.filters_json)
|
filters = frappe.parse_json(filters) or frappe.parse_json(chart.filters_json)
|
||||||
|
|
||||||
account = filters.get("account")
|
account = filters.get("account")
|
||||||
company = filters.get("company")
|
filters.get("company")
|
||||||
|
|
||||||
if not account and chart_name:
|
if not account and chart_name:
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
@@ -83,7 +83,6 @@ def build_result(account, dates, gl_entries):
|
|||||||
|
|
||||||
# get balances in debit
|
# get balances in debit
|
||||||
for entry in gl_entries:
|
for entry in gl_entries:
|
||||||
|
|
||||||
# entry date is after the current pointer, so move the pointer forward
|
# entry date is after the current pointer, so move the pointer forward
|
||||||
while getdate(entry.posting_date) > result[date_index][0]:
|
while getdate(entry.posting_date) > result[date_index][0]:
|
||||||
date_index += 1
|
date_index += 1
|
||||||
@@ -133,8 +132,6 @@ def get_dates_from_timegrain(from_date, to_date, timegrain):
|
|||||||
|
|
||||||
dates = [get_period_ending(from_date, timegrain)]
|
dates = [get_period_ending(from_date, timegrain)]
|
||||||
while getdate(dates[-1]) < getdate(to_date):
|
while getdate(dates[-1]) < getdate(to_date):
|
||||||
date = get_period_ending(
|
date = get_period_ending(add_to_date(dates[-1], years=years, months=months, days=days), timegrain)
|
||||||
add_to_date(dates[-1], years=years, months=months, days=days), timegrain
|
|
||||||
)
|
|
||||||
dates.append(date)
|
dates.append(date)
|
||||||
return dates
|
return dates
|
||||||
|
|||||||
@@ -24,14 +24,10 @@ from erpnext.accounts.utils import get_account_currency
|
|||||||
def validate_service_stop_date(doc):
|
def validate_service_stop_date(doc):
|
||||||
"""Validates service_stop_date for Purchase Invoice and Sales Invoice"""
|
"""Validates service_stop_date for Purchase Invoice and Sales Invoice"""
|
||||||
|
|
||||||
enable_check = (
|
enable_check = "enable_deferred_revenue" if doc.doctype == "Sales Invoice" else "enable_deferred_expense"
|
||||||
"enable_deferred_revenue" if doc.doctype == "Sales Invoice" else "enable_deferred_expense"
|
|
||||||
)
|
|
||||||
|
|
||||||
old_stop_dates = {}
|
old_stop_dates = {}
|
||||||
old_doc = frappe.db.get_all(
|
old_doc = frappe.db.get_all(f"{doc.doctype} Item", {"parent": doc.name}, ["name", "service_stop_date"])
|
||||||
"{0} Item".format(doc.doctype), {"parent": doc.name}, ["name", "service_stop_date"]
|
|
||||||
)
|
|
||||||
|
|
||||||
for d in old_doc:
|
for d in old_doc:
|
||||||
old_stop_dates[d.name] = d.service_stop_date or ""
|
old_stop_dates[d.name] = d.service_stop_date or ""
|
||||||
@@ -62,16 +58,14 @@ def build_conditions(process_type, account, company):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if account:
|
if account:
|
||||||
conditions += "AND %s='%s'" % (deferred_account, account)
|
conditions += f"AND {deferred_account}='{account}'"
|
||||||
elif company:
|
elif company:
|
||||||
conditions += f"AND p.company = {frappe.db.escape(company)}"
|
conditions += f"AND p.company = {frappe.db.escape(company)}"
|
||||||
|
|
||||||
return conditions
|
return conditions
|
||||||
|
|
||||||
|
|
||||||
def convert_deferred_expense_to_expense(
|
def convert_deferred_expense_to_expense(deferred_process, start_date=None, end_date=None, conditions=""):
|
||||||
deferred_process, start_date=None, end_date=None, conditions=""
|
|
||||||
):
|
|
||||||
# book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM
|
# book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM
|
||||||
|
|
||||||
if not start_date:
|
if not start_date:
|
||||||
@@ -81,16 +75,14 @@ def convert_deferred_expense_to_expense(
|
|||||||
|
|
||||||
# check for the purchase invoice for which GL entries has to be done
|
# check for the purchase invoice for which GL entries has to be done
|
||||||
invoices = frappe.db.sql_list(
|
invoices = frappe.db.sql_list(
|
||||||
"""
|
f"""
|
||||||
select distinct item.parent
|
select distinct item.parent
|
||||||
from `tabPurchase Invoice Item` item, `tabPurchase Invoice` p
|
from `tabPurchase Invoice Item` item, `tabPurchase Invoice` p
|
||||||
where item.service_start_date<=%s and item.service_end_date>=%s
|
where item.service_start_date<=%s and item.service_end_date>=%s
|
||||||
and item.enable_deferred_expense = 1 and item.parent=p.name
|
and item.enable_deferred_expense = 1 and item.parent=p.name
|
||||||
and item.docstatus = 1 and ifnull(item.amount, 0) > 0
|
and item.docstatus = 1 and ifnull(item.amount, 0) > 0
|
||||||
{0}
|
{conditions}
|
||||||
""".format(
|
""",
|
||||||
conditions
|
|
||||||
),
|
|
||||||
(end_date, start_date),
|
(end_date, start_date),
|
||||||
) # nosec
|
) # nosec
|
||||||
|
|
||||||
@@ -103,9 +95,7 @@ def convert_deferred_expense_to_expense(
|
|||||||
send_mail(deferred_process)
|
send_mail(deferred_process)
|
||||||
|
|
||||||
|
|
||||||
def convert_deferred_revenue_to_income(
|
def convert_deferred_revenue_to_income(deferred_process, start_date=None, end_date=None, conditions=""):
|
||||||
deferred_process, start_date=None, end_date=None, conditions=""
|
|
||||||
):
|
|
||||||
# book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM
|
# book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM
|
||||||
|
|
||||||
if not start_date:
|
if not start_date:
|
||||||
@@ -115,16 +105,14 @@ def convert_deferred_revenue_to_income(
|
|||||||
|
|
||||||
# check for the sales invoice for which GL entries has to be done
|
# check for the sales invoice for which GL entries has to be done
|
||||||
invoices = frappe.db.sql_list(
|
invoices = frappe.db.sql_list(
|
||||||
"""
|
f"""
|
||||||
select distinct item.parent
|
select distinct item.parent
|
||||||
from `tabSales Invoice Item` item, `tabSales Invoice` p
|
from `tabSales Invoice Item` item, `tabSales Invoice` p
|
||||||
where item.service_start_date<=%s and item.service_end_date>=%s
|
where item.service_start_date<=%s and item.service_end_date>=%s
|
||||||
and item.enable_deferred_revenue = 1 and item.parent=p.name
|
and item.enable_deferred_revenue = 1 and item.parent=p.name
|
||||||
and item.docstatus = 1 and ifnull(item.amount, 0) > 0
|
and item.docstatus = 1 and ifnull(item.amount, 0) > 0
|
||||||
{0}
|
{conditions}
|
||||||
""".format(
|
""",
|
||||||
conditions
|
|
||||||
),
|
|
||||||
(end_date, start_date),
|
(end_date, start_date),
|
||||||
) # nosec
|
) # nosec
|
||||||
|
|
||||||
@@ -243,9 +231,7 @@ def calculate_monthly_amount(
|
|||||||
already_booked_amount, already_booked_amount_in_account_currency = get_already_booked_amount(
|
already_booked_amount, already_booked_amount_in_account_currency = get_already_booked_amount(
|
||||||
doc, item
|
doc, item
|
||||||
)
|
)
|
||||||
base_amount = flt(
|
base_amount = flt(item.base_net_amount - already_booked_amount, item.precision("base_net_amount"))
|
||||||
item.base_net_amount - already_booked_amount, item.precision("base_net_amount")
|
|
||||||
)
|
|
||||||
if account_currency == doc.company_currency:
|
if account_currency == doc.company_currency:
|
||||||
amount = base_amount
|
amount = base_amount
|
||||||
else:
|
else:
|
||||||
@@ -265,17 +251,13 @@ def calculate_amount(doc, item, last_gl_entry, total_days, total_booking_days, a
|
|||||||
if account_currency == doc.company_currency:
|
if account_currency == doc.company_currency:
|
||||||
amount = base_amount
|
amount = base_amount
|
||||||
else:
|
else:
|
||||||
amount = flt(
|
amount = flt(item.net_amount * total_booking_days / flt(total_days), item.precision("net_amount"))
|
||||||
item.net_amount * total_booking_days / flt(total_days), item.precision("net_amount")
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
already_booked_amount, already_booked_amount_in_account_currency = get_already_booked_amount(
|
already_booked_amount, already_booked_amount_in_account_currency = get_already_booked_amount(
|
||||||
doc, item
|
doc, item
|
||||||
)
|
)
|
||||||
|
|
||||||
base_amount = flt(
|
base_amount = flt(item.base_net_amount - already_booked_amount, item.precision("base_net_amount"))
|
||||||
item.base_net_amount - already_booked_amount, item.precision("base_net_amount")
|
|
||||||
)
|
|
||||||
if account_currency == doc.company_currency:
|
if account_currency == doc.company_currency:
|
||||||
amount = base_amount
|
amount = base_amount
|
||||||
else:
|
else:
|
||||||
@@ -296,26 +278,22 @@ def get_already_booked_amount(doc, item):
|
|||||||
|
|
||||||
gl_entries_details = frappe.db.sql(
|
gl_entries_details = frappe.db.sql(
|
||||||
"""
|
"""
|
||||||
select sum({0}) as total_credit, sum({1}) as total_credit_in_account_currency, voucher_detail_no
|
select sum({}) as total_credit, sum({}) as total_credit_in_account_currency, voucher_detail_no
|
||||||
from `tabGL Entry` where company=%s and account=%s and voucher_type=%s and voucher_no=%s and voucher_detail_no=%s
|
from `tabGL Entry` where company=%s and account=%s and voucher_type=%s and voucher_no=%s and voucher_detail_no=%s
|
||||||
and is_cancelled = 0
|
and is_cancelled = 0
|
||||||
group by voucher_detail_no
|
group by voucher_detail_no
|
||||||
""".format(
|
""".format(total_credit_debit, total_credit_debit_currency),
|
||||||
total_credit_debit, total_credit_debit_currency
|
|
||||||
),
|
|
||||||
(doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name),
|
(doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name),
|
||||||
as_dict=True,
|
as_dict=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
journal_entry_details = frappe.db.sql(
|
journal_entry_details = frappe.db.sql(
|
||||||
"""
|
"""
|
||||||
SELECT sum(c.{0}) as total_credit, sum(c.{1}) as total_credit_in_account_currency, reference_detail_no
|
SELECT sum(c.{}) as total_credit, sum(c.{}) as total_credit_in_account_currency, reference_detail_no
|
||||||
FROM `tabJournal Entry` p , `tabJournal Entry Account` c WHERE p.name = c.parent and
|
FROM `tabJournal Entry` p , `tabJournal Entry Account` c WHERE p.name = c.parent and
|
||||||
p.company = %s and c.account=%s and c.reference_type=%s and c.reference_name=%s and c.reference_detail_no=%s
|
p.company = %s and c.account=%s and c.reference_type=%s and c.reference_name=%s and c.reference_detail_no=%s
|
||||||
and p.docstatus < 2 group by reference_detail_no
|
and p.docstatus < 2 group by reference_detail_no
|
||||||
""".format(
|
""".format(total_credit_debit, total_credit_debit_currency),
|
||||||
total_credit_debit, total_credit_debit_currency
|
|
||||||
),
|
|
||||||
(doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name),
|
(doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name),
|
||||||
as_dict=True,
|
as_dict=True,
|
||||||
)
|
)
|
||||||
@@ -337,9 +315,7 @@ def get_already_booked_amount(doc, item):
|
|||||||
|
|
||||||
|
|
||||||
def book_deferred_income_or_expense(doc, deferred_process, posting_date=None):
|
def book_deferred_income_or_expense(doc, deferred_process, posting_date=None):
|
||||||
enable_check = (
|
enable_check = "enable_deferred_revenue" if doc.doctype == "Sales Invoice" else "enable_deferred_expense"
|
||||||
"enable_deferred_revenue" if doc.doctype == "Sales Invoice" else "enable_deferred_expense"
|
|
||||||
)
|
|
||||||
|
|
||||||
accounts_frozen_upto = frappe.db.get_single_value("Accounts Settings", "acc_frozen_upto")
|
accounts_frozen_upto = frappe.db.get_single_value("Accounts Settings", "acc_frozen_upto")
|
||||||
|
|
||||||
@@ -358,11 +334,9 @@ def book_deferred_income_or_expense(doc, deferred_process, posting_date=None):
|
|||||||
|
|
||||||
account_currency = get_account_currency(item.expense_account or item.income_account)
|
account_currency = get_account_currency(item.expense_account or item.income_account)
|
||||||
if doc.doctype == "Sales Invoice":
|
if doc.doctype == "Sales Invoice":
|
||||||
against_type = "Customer"
|
|
||||||
against, project = doc.customer, doc.project
|
against, project = doc.customer, doc.project
|
||||||
credit_account, debit_account = item.income_account, item.deferred_revenue_account
|
credit_account, debit_account = item.income_account, item.deferred_revenue_account
|
||||||
else:
|
else:
|
||||||
against_type = "Supplier"
|
|
||||||
against, project = doc.supplier, item.project
|
against, project = doc.supplier, item.project
|
||||||
credit_account, debit_account = item.deferred_expense_account, item.expense_account
|
credit_account, debit_account = item.deferred_expense_account, item.expense_account
|
||||||
|
|
||||||
@@ -386,8 +360,8 @@ def book_deferred_income_or_expense(doc, deferred_process, posting_date=None):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if not amount:
|
if not amount:
|
||||||
return
|
prev_posting_date = end_date
|
||||||
|
else:
|
||||||
gl_posting_date = end_date
|
gl_posting_date = end_date
|
||||||
prev_posting_date = None
|
prev_posting_date = None
|
||||||
# check if books nor frozen till endate:
|
# check if books nor frozen till endate:
|
||||||
@@ -415,7 +389,6 @@ def book_deferred_income_or_expense(doc, deferred_process, posting_date=None):
|
|||||||
doc,
|
doc,
|
||||||
credit_account,
|
credit_account,
|
||||||
debit_account,
|
debit_account,
|
||||||
against_type,
|
|
||||||
against,
|
against,
|
||||||
amount,
|
amount,
|
||||||
base_amount,
|
base_amount,
|
||||||
@@ -443,9 +416,7 @@ def book_deferred_income_or_expense(doc, deferred_process, posting_date=None):
|
|||||||
via_journal_entry = cint(
|
via_journal_entry = cint(
|
||||||
frappe.db.get_singles_value("Accounts Settings", "book_deferred_entries_via_journal_entry")
|
frappe.db.get_singles_value("Accounts Settings", "book_deferred_entries_via_journal_entry")
|
||||||
)
|
)
|
||||||
submit_journal_entry = cint(
|
submit_journal_entry = cint(frappe.db.get_singles_value("Accounts Settings", "submit_journal_entries"))
|
||||||
frappe.db.get_singles_value("Accounts Settings", "submit_journal_entries")
|
|
||||||
)
|
|
||||||
book_deferred_entries_based_on = frappe.db.get_singles_value(
|
book_deferred_entries_based_on = frappe.db.get_singles_value(
|
||||||
"Accounts Settings", "book_deferred_entries_based_on"
|
"Accounts Settings", "book_deferred_entries_based_on"
|
||||||
)
|
)
|
||||||
@@ -465,9 +436,7 @@ def process_deferred_accounting(posting_date=None):
|
|||||||
posting_date = today()
|
posting_date = today()
|
||||||
|
|
||||||
if not cint(
|
if not cint(
|
||||||
frappe.db.get_singles_value(
|
frappe.db.get_singles_value("Accounts Settings", "automatically_process_deferred_accounting_entry")
|
||||||
"Accounts Settings", "automatically_process_deferred_accounting_entry"
|
|
||||||
)
|
|
||||||
):
|
):
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -497,7 +466,6 @@ def make_gl_entries(
|
|||||||
doc,
|
doc,
|
||||||
credit_account,
|
credit_account,
|
||||||
debit_account,
|
debit_account,
|
||||||
against_type,
|
|
||||||
against,
|
against,
|
||||||
amount,
|
amount,
|
||||||
base_amount,
|
base_amount,
|
||||||
@@ -519,9 +487,7 @@ def make_gl_entries(
|
|||||||
doc.get_gl_dict(
|
doc.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": credit_account,
|
"account": credit_account,
|
||||||
"against_type": against_type,
|
|
||||||
"against": against,
|
"against": against,
|
||||||
"against_link": against,
|
|
||||||
"credit": base_amount,
|
"credit": base_amount,
|
||||||
"credit_in_account_currency": amount,
|
"credit_in_account_currency": amount,
|
||||||
"cost_center": cost_center,
|
"cost_center": cost_center,
|
||||||
@@ -540,9 +506,7 @@ def make_gl_entries(
|
|||||||
doc.get_gl_dict(
|
doc.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": debit_account,
|
"account": debit_account,
|
||||||
"against_type": against_type,
|
|
||||||
"against": against,
|
"against": against,
|
||||||
"against_link": against,
|
|
||||||
"debit": base_amount,
|
"debit": base_amount,
|
||||||
"debit_in_account_currency": amount,
|
"debit_in_account_currency": amount,
|
||||||
"cost_center": cost_center,
|
"cost_center": cost_center,
|
||||||
@@ -595,16 +559,13 @@ def book_revenue_via_journal_entry(
|
|||||||
deferred_process=None,
|
deferred_process=None,
|
||||||
submit="No",
|
submit="No",
|
||||||
):
|
):
|
||||||
|
|
||||||
if amount == 0:
|
if amount == 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
journal_entry = frappe.new_doc("Journal Entry")
|
journal_entry = frappe.new_doc("Journal Entry")
|
||||||
journal_entry.posting_date = posting_date
|
journal_entry.posting_date = posting_date
|
||||||
journal_entry.company = doc.company
|
journal_entry.company = doc.company
|
||||||
journal_entry.voucher_type = (
|
journal_entry.voucher_type = "Deferred Revenue" if doc.doctype == "Sales Invoice" else "Deferred Expense"
|
||||||
"Deferred Revenue" if doc.doctype == "Sales Invoice" else "Deferred Expense"
|
|
||||||
)
|
|
||||||
journal_entry.process_deferred_accounting = deferred_process
|
journal_entry.process_deferred_accounting = deferred_process
|
||||||
|
|
||||||
debit_entry = {
|
debit_entry = {
|
||||||
@@ -653,7 +614,6 @@ def book_revenue_via_journal_entry(
|
|||||||
|
|
||||||
|
|
||||||
def get_deferred_booking_accounts(doctype, voucher_detail_no, dr_or_cr):
|
def get_deferred_booking_accounts(doctype, voucher_detail_no, dr_or_cr):
|
||||||
|
|
||||||
if doctype == "Sales Invoice":
|
if doctype == "Sales Invoice":
|
||||||
credit_account, debit_account = frappe.db.get_value(
|
credit_account, debit_account = frappe.db.get_value(
|
||||||
"Sales Invoice Item",
|
"Sales Invoice Item",
|
||||||
|
|||||||
@@ -26,19 +26,14 @@ frappe.ui.form.on("Account", {
|
|||||||
frm.toggle_enable(["is_group", "company"], false);
|
frm.toggle_enable(["is_group", "company"], false);
|
||||||
|
|
||||||
if (cint(frm.doc.is_group) == 0) {
|
if (cint(frm.doc.is_group) == 0) {
|
||||||
frm.toggle_display(
|
frm.toggle_display("freeze_account", frm.doc.__onload && frm.doc.__onload.can_freeze_account);
|
||||||
"freeze_account",
|
|
||||||
frm.doc.__onload && frm.doc.__onload.can_freeze_account
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// read-only for root accounts
|
// read-only for root accounts
|
||||||
if (!frm.is_new()) {
|
if (!frm.is_new()) {
|
||||||
if (!frm.doc.parent_account) {
|
if (!frm.doc.parent_account) {
|
||||||
frm.set_read_only();
|
frm.set_read_only();
|
||||||
frm.set_intro(
|
frm.set_intro(__("This is a root account and cannot be edited."));
|
||||||
__("This is a root account and cannot be edited.")
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
// credit days and type if customer or supplier
|
// credit days and type if customer or supplier
|
||||||
frm.set_intro(null);
|
frm.set_intro(null);
|
||||||
@@ -80,27 +75,33 @@ frappe.ui.form.on("Account", {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (frm.doc.is_group == 1) {
|
if (frm.doc.is_group == 1) {
|
||||||
frm.add_custom_button(__('Convert to Non-Group'), function () {
|
frm.add_custom_button(
|
||||||
|
__("Convert to Non-Group"),
|
||||||
|
function () {
|
||||||
return frappe.call({
|
return frappe.call({
|
||||||
doc: frm.doc,
|
doc: frm.doc,
|
||||||
method: 'convert_group_to_ledger',
|
method: "convert_group_to_ledger",
|
||||||
callback: function () {
|
callback: function () {
|
||||||
frm.refresh();
|
frm.refresh();
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}, __('Actions'));
|
},
|
||||||
|
__("Actions")
|
||||||
} else if (cint(frm.doc.is_group) == 0
|
);
|
||||||
&& frappe.boot.user.can_read.indexOf("GL Entry") !== -1) {
|
} else if (cint(frm.doc.is_group) == 0 && frappe.boot.user.can_read.indexOf("GL Entry") !== -1) {
|
||||||
frm.add_custom_button(__('General Ledger'), function () {
|
frm.add_custom_button(
|
||||||
|
__("General Ledger"),
|
||||||
|
function () {
|
||||||
frappe.route_options = {
|
frappe.route_options = {
|
||||||
"account": frm.doc.name,
|
account: frm.doc.name,
|
||||||
"from_date": erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[1],
|
from_date: erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[1],
|
||||||
"to_date": erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[2],
|
to_date: erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[2],
|
||||||
"company": frm.doc.company
|
company: frm.doc.company,
|
||||||
};
|
};
|
||||||
frappe.set_route("query-report", "General Ledger");
|
frappe.set_route("query-report", "General Ledger");
|
||||||
}, __('View'));
|
},
|
||||||
|
__("View")
|
||||||
|
);
|
||||||
|
|
||||||
frm.add_custom_button(
|
frm.add_custom_button(
|
||||||
__("Convert to Group"),
|
__("Convert to Group"),
|
||||||
@@ -193,14 +194,8 @@ frappe.ui.form.on("Account", {
|
|||||||
if (r.message) {
|
if (r.message) {
|
||||||
frappe.set_route("Form", "Account", r.message);
|
frappe.set_route("Form", "Account", r.message);
|
||||||
} else {
|
} else {
|
||||||
frm.set_value(
|
frm.set_value("account_number", data.account_number);
|
||||||
"account_number",
|
frm.set_value("account_name", data.account_name);
|
||||||
data.account_number
|
|
||||||
);
|
|
||||||
frm.set_value(
|
|
||||||
"account_name",
|
|
||||||
data.account_name
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
d.hide();
|
d.hide();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,6 +65,8 @@
|
|||||||
"label": "Is Group"
|
"label": "Is Group"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"fetch_from": "parent_account.company",
|
||||||
|
"fetch_if_empty": 1,
|
||||||
"fieldname": "company",
|
"fieldname": "company",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"in_standard_filter": 1,
|
"in_standard_filter": 1,
|
||||||
@@ -108,6 +110,7 @@
|
|||||||
"fieldname": "parent_account",
|
"fieldname": "parent_account",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"ignore_user_permissions": 1,
|
"ignore_user_permissions": 1,
|
||||||
|
"in_preview": 1,
|
||||||
"label": "Parent Account",
|
"label": "Parent Account",
|
||||||
"oldfieldname": "parent_account",
|
"oldfieldname": "parent_account",
|
||||||
"oldfieldtype": "Link",
|
"oldfieldtype": "Link",
|
||||||
@@ -192,7 +195,7 @@
|
|||||||
"idx": 1,
|
"idx": 1,
|
||||||
"is_tree": 1,
|
"is_tree": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-07-20 18:18:44.405723",
|
"modified": "2024-03-27 13:05:55.866034",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Account",
|
"name": "Account",
|
||||||
@@ -249,7 +252,8 @@
|
|||||||
],
|
],
|
||||||
"search_fields": "account_number",
|
"search_fields": "account_number",
|
||||||
"show_name_in_global_search": 1,
|
"show_name_in_global_search": 1,
|
||||||
"sort_field": "modified",
|
"show_preview_popup": 1,
|
||||||
|
"sort_field": "creation",
|
||||||
"sort_order": "ASC",
|
"sort_order": "ASC",
|
||||||
"states": [],
|
"states": [],
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
|
|||||||
@@ -88,12 +88,10 @@ class Account(NestedSet):
|
|||||||
if frappe.local.flags.ignore_update_nsm:
|
if frappe.local.flags.ignore_update_nsm:
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
super(Account, self).on_update()
|
super().on_update()
|
||||||
|
|
||||||
def onload(self):
|
def onload(self):
|
||||||
frozen_accounts_modifier = frappe.db.get_single_value(
|
frozen_accounts_modifier = frappe.db.get_single_value("Accounts Settings", "frozen_accounts_modifier")
|
||||||
"Accounts Settings", "frozen_accounts_modifier"
|
|
||||||
)
|
|
||||||
if not frozen_accounts_modifier or frozen_accounts_modifier in frappe.get_roles():
|
if not frozen_accounts_modifier or frozen_accounts_modifier in frappe.get_roles():
|
||||||
self.set_onload("can_freeze_account", True)
|
self.set_onload("can_freeze_account", True)
|
||||||
|
|
||||||
@@ -118,6 +116,7 @@ class Account(NestedSet):
|
|||||||
self.validate_balance_must_be_debit_or_credit()
|
self.validate_balance_must_be_debit_or_credit()
|
||||||
self.validate_account_currency()
|
self.validate_account_currency()
|
||||||
self.validate_root_company_and_sync_account_to_children()
|
self.validate_root_company_and_sync_account_to_children()
|
||||||
|
self.validate_receivable_payable_account_type()
|
||||||
|
|
||||||
def validate_parent_child_account_type(self):
|
def validate_parent_child_account_type(self):
|
||||||
if self.parent_account:
|
if self.parent_account:
|
||||||
@@ -188,6 +187,24 @@ class Account(NestedSet):
|
|||||||
"Balance Sheet" if self.root_type in ("Asset", "Liability", "Equity") else "Profit and Loss"
|
"Balance Sheet" if self.root_type in ("Asset", "Liability", "Equity") else "Profit and Loss"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def validate_receivable_payable_account_type(self):
|
||||||
|
doc_before_save = self.get_doc_before_save()
|
||||||
|
receivable_payable_types = ["Receivable", "Payable"]
|
||||||
|
if (
|
||||||
|
doc_before_save
|
||||||
|
and doc_before_save.account_type in receivable_payable_types
|
||||||
|
and doc_before_save.account_type != self.account_type
|
||||||
|
):
|
||||||
|
# check for ledger entries
|
||||||
|
if frappe.db.get_all("GL Entry", filters={"account": self.name, "is_cancelled": 0}, limit=1):
|
||||||
|
msg = _(
|
||||||
|
"There are ledger entries against this account. Changing {0} to non-{1} in live system will cause incorrect output in 'Accounts {2}' report"
|
||||||
|
).format(
|
||||||
|
frappe.bold("Account Type"), doc_before_save.account_type, doc_before_save.account_type
|
||||||
|
)
|
||||||
|
frappe.msgprint(msg)
|
||||||
|
self.add_comment("Comment", msg)
|
||||||
|
|
||||||
def validate_root_details(self):
|
def validate_root_details(self):
|
||||||
doc_before_save = self.get_doc_before_save()
|
doc_before_save = self.get_doc_before_save()
|
||||||
|
|
||||||
@@ -199,9 +216,7 @@ class Account(NestedSet):
|
|||||||
|
|
||||||
def validate_root_company_and_sync_account_to_children(self):
|
def validate_root_company_and_sync_account_to_children(self):
|
||||||
# ignore validation while creating new compnay or while syncing to child companies
|
# ignore validation while creating new compnay or while syncing to child companies
|
||||||
if (
|
if frappe.local.flags.ignore_root_company_validation or self.flags.ignore_root_company_validation:
|
||||||
frappe.local.flags.ignore_root_company_validation or self.flags.ignore_root_company_validation
|
|
||||||
):
|
|
||||||
return
|
return
|
||||||
ancestors = get_root_company(self.company)
|
ancestors = get_root_company(self.company)
|
||||||
if ancestors:
|
if ancestors:
|
||||||
@@ -399,7 +414,7 @@ class Account(NestedSet):
|
|||||||
if self.check_gle_exists():
|
if self.check_gle_exists():
|
||||||
throw(_("Account with existing transaction can not be deleted"))
|
throw(_("Account with existing transaction can not be deleted"))
|
||||||
|
|
||||||
super(Account, self).on_trash(True)
|
super().on_trash(True)
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
@@ -407,9 +422,8 @@ class Account(NestedSet):
|
|||||||
def get_parent_account(doctype, txt, searchfield, start, page_len, filters):
|
def get_parent_account(doctype, txt, searchfield, start, page_len, filters):
|
||||||
return frappe.db.sql(
|
return frappe.db.sql(
|
||||||
"""select name from tabAccount
|
"""select name from tabAccount
|
||||||
where is_group = 1 and docstatus != 2 and company = %s
|
where is_group = 1 and docstatus != 2 and company = {}
|
||||||
and %s like %s order by name limit %s offset %s"""
|
and {} like {} order by name limit {} offset {}""".format("%s", searchfield, "%s", "%s", "%s"),
|
||||||
% ("%s", searchfield, "%s", "%s", "%s"),
|
|
||||||
(filters["company"], "%%%s%%" % txt, page_len, start),
|
(filters["company"], "%%%s%%" % txt, page_len, start),
|
||||||
as_list=1,
|
as_list=1,
|
||||||
)
|
)
|
||||||
@@ -575,7 +589,5 @@ def sync_update_account_number_in_child(
|
|||||||
if old_acc_number:
|
if old_acc_number:
|
||||||
filters["account_number"] = old_acc_number
|
filters["account_number"] = old_acc_number
|
||||||
|
|
||||||
for d in frappe.db.get_values(
|
for d in frappe.db.get_values("Account", filters=filters, fieldname=["company", "name"], as_dict=True):
|
||||||
"Account", filters=filters, fieldname=["company", "name"], as_dict=True
|
|
||||||
):
|
|
||||||
update_account_number(d["name"], account_name, account_number, from_descendant=True)
|
update_account_number(d["name"], account_name, account_number, from_descendant=True)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
frappe.provide("frappe.treeview_settings")
|
frappe.provide("frappe.treeview_settings");
|
||||||
|
|
||||||
frappe.treeview_settings["Account"] = {
|
frappe.treeview_settings["Account"] = {
|
||||||
breadcrumb: "Accounts",
|
breadcrumb: "Accounts",
|
||||||
@@ -12,7 +12,7 @@ frappe.treeview_settings["Account"] = {
|
|||||||
label: __("Company"),
|
label: __("Company"),
|
||||||
default: erpnext.utils.get_tree_default("company"),
|
default: erpnext.utils.get_tree_default("company"),
|
||||||
on_change: function () {
|
on_change: function () {
|
||||||
var me = frappe.treeview_settings['Account'].treeview;
|
var me = frappe.treeview_settings["Account"].treeview;
|
||||||
var company = me.page.fields_dict.company.get_value();
|
var company = me.page.fields_dict.company.get_value();
|
||||||
if (!company) {
|
if (!company) {
|
||||||
frappe.throw(__("Please set a Company"));
|
frappe.throw(__("Please set a Company"));
|
||||||
@@ -27,24 +27,30 @@ frappe.treeview_settings["Account"] = {
|
|||||||
let root_company = r.message.length ? r.message[0] : "";
|
let root_company = r.message.length ? r.message[0] : "";
|
||||||
me.page.fields_dict.root_company.set_value(root_company);
|
me.page.fields_dict.root_company.set_value(root_company);
|
||||||
|
|
||||||
frappe.db.get_value("Company", {"name": company}, "allow_account_creation_against_child_company", (r) => {
|
frappe.db.get_value(
|
||||||
frappe.flags.ignore_root_company_validation = r.allow_account_creation_against_child_company;
|
"Company",
|
||||||
|
{ name: company },
|
||||||
|
"allow_account_creation_against_child_company",
|
||||||
|
(r) => {
|
||||||
|
frappe.flags.ignore_root_company_validation =
|
||||||
|
r.allow_account_creation_against_child_company;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fieldname: "root_company",
|
fieldname: "root_company",
|
||||||
fieldtype: "Data",
|
fieldtype: "Data",
|
||||||
label: __("Root Company"),
|
label: __("Root Company"),
|
||||||
hidden: true,
|
hidden: true,
|
||||||
disable_onchange: true
|
disable_onchange: true,
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
root_label: "Accounts",
|
root_label: "Accounts",
|
||||||
get_tree_nodes: 'erpnext.accounts.utils.get_children',
|
get_tree_nodes: "erpnext.accounts.utils.get_children",
|
||||||
on_get_node: function (nodes, deep = false) {
|
on_get_node: function (nodes, deep = false) {
|
||||||
if (frappe.boot.user.can_read.indexOf("GL Entry") == -1) return;
|
if (frappe.boot.user.can_read.indexOf("GL Entry") == -1) return;
|
||||||
|
|
||||||
@@ -58,20 +64,18 @@ frappe.treeview_settings["Account"] = {
|
|||||||
|
|
||||||
frappe.db.get_single_value("Accounts Settings", "show_balance_in_coa").then((value) => {
|
frappe.db.get_single_value("Accounts Settings", "show_balance_in_coa").then((value) => {
|
||||||
if (value) {
|
if (value) {
|
||||||
|
|
||||||
const get_balances = frappe.call({
|
const get_balances = frappe.call({
|
||||||
method: 'erpnext.accounts.utils.get_account_balances',
|
method: "erpnext.accounts.utils.get_account_balances",
|
||||||
args: {
|
args: {
|
||||||
accounts: accounts,
|
accounts: accounts,
|
||||||
company: cur_tree.args.company
|
company: cur_tree.args.company,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
get_balances.then(r => {
|
get_balances.then((r) => {
|
||||||
if (!r.message || r.message.length == 0) return;
|
if (!r.message || r.message.length == 0) return;
|
||||||
|
|
||||||
for (let account of r.message) {
|
for (let account of r.message) {
|
||||||
|
|
||||||
const node = cur_tree.nodes && cur_tree.nodes[account.value];
|
const node = cur_tree.nodes && cur_tree.nodes[account.value];
|
||||||
if (!node || node.is_root) continue;
|
if (!node || node.is_root) continue;
|
||||||
|
|
||||||
@@ -81,87 +85,161 @@ frappe.treeview_settings["Account"] = {
|
|||||||
const format = (value, currency) => format_currency(Math.abs(value), currency);
|
const format = (value, currency) => format_currency(Math.abs(value), currency);
|
||||||
|
|
||||||
if (account.balance !== undefined) {
|
if (account.balance !== undefined) {
|
||||||
node.parent && node.parent.find('.balance-area').remove();
|
node.parent && node.parent.find(".balance-area").remove();
|
||||||
$('<span class="balance-area pull-right">'
|
$(
|
||||||
+ (account.balance_in_account_currency ?
|
'<span class="balance-area pull-right">' +
|
||||||
(format(account.balance_in_account_currency, account.account_currency) + " / ") : "")
|
(account.balance_in_account_currency
|
||||||
+ format(account.balance, account.company_currency)
|
? format(
|
||||||
+ " " + dr_or_cr
|
account.balance_in_account_currency,
|
||||||
+ '</span>').insertBefore(node.$ul);
|
account.account_currency
|
||||||
|
) + " / "
|
||||||
|
: "") +
|
||||||
|
format(account.balance, account.company_currency) +
|
||||||
|
" " +
|
||||||
|
dr_or_cr +
|
||||||
|
"</span>"
|
||||||
|
).insertBefore(node.$ul);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
add_tree_node: 'erpnext.accounts.utils.add_ac',
|
add_tree_node: "erpnext.accounts.utils.add_ac",
|
||||||
menu_items: [
|
menu_items: [
|
||||||
{
|
{
|
||||||
label: __('New Company'),
|
label: __("New Company"),
|
||||||
action: function() { frappe.new_doc("Company", true) },
|
action: function () {
|
||||||
condition: 'frappe.boot.user.can_create.indexOf("Company") !== -1'
|
frappe.new_doc("Company", true);
|
||||||
}
|
},
|
||||||
|
condition: 'frappe.boot.user.can_create.indexOf("Company") !== -1',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
fields: [
|
fields: [
|
||||||
{fieldtype:'Data', fieldname:'account_name', label:__('New Account Name'), reqd:true,
|
{
|
||||||
description: __("Name of new Account. Note: Please don't create accounts for Customers and Suppliers")},
|
fieldtype: "Data",
|
||||||
{fieldtype:'Data', fieldname:'account_number', label:__('Account Number'),
|
fieldname: "account_name",
|
||||||
description: __("Number of new Account, it will be included in the account name as a prefix")},
|
label: __("New Account Name"),
|
||||||
{fieldtype:'Check', fieldname:'is_group', label:__('Is Group'),
|
reqd: true,
|
||||||
description: __('Further accounts can be made under Groups, but entries can be made against non-Groups')},
|
description: __(
|
||||||
{fieldtype:'Select', fieldname:'root_type', label:__('Root Type'),
|
"Name of new Account. Note: Please don't create accounts for Customers and Suppliers"
|
||||||
options: ['Asset', 'Liability', 'Equity', 'Income', 'Expense'].join('\n'),
|
),
|
||||||
depends_on: 'eval:doc.is_group && !doc.parent_account'},
|
},
|
||||||
{fieldtype:'Select', fieldname:'account_type', label:__('Account Type'),
|
{
|
||||||
options: frappe.get_meta("Account").fields.filter(d => d.fieldname=='account_type')[0].options,
|
fieldtype: "Data",
|
||||||
description: __("Optional. This setting will be used to filter in various transactions.")
|
fieldname: "account_number",
|
||||||
|
label: __("Account Number"),
|
||||||
|
description: __("Number of new Account, it will be included in the account name as a prefix"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldtype: "Check",
|
||||||
|
fieldname: "is_group",
|
||||||
|
label: __("Is Group"),
|
||||||
|
description: __(
|
||||||
|
"Further accounts can be made under Groups, but entries can be made against non-Groups"
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldtype: "Select",
|
||||||
|
fieldname: "root_type",
|
||||||
|
label: __("Root Type"),
|
||||||
|
options: ["Asset", "Liability", "Equity", "Income", "Expense"].join("\n"),
|
||||||
|
depends_on: "eval:doc.is_group && !doc.parent_account",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldtype: "Select",
|
||||||
|
fieldname: "account_type",
|
||||||
|
label: __("Account Type"),
|
||||||
|
options: frappe.get_meta("Account").fields.filter((d) => d.fieldname == "account_type")[0]
|
||||||
|
.options,
|
||||||
|
description: __("Optional. This setting will be used to filter in various transactions."),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldtype: "Float",
|
||||||
|
fieldname: "tax_rate",
|
||||||
|
label: __("Tax Rate"),
|
||||||
|
depends_on: 'eval:doc.is_group==0&&doc.account_type=="Tax"',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldtype: "Link",
|
||||||
|
fieldname: "account_currency",
|
||||||
|
label: __("Currency"),
|
||||||
|
options: "Currency",
|
||||||
|
description: __("Optional. Sets company's default currency, if not specified."),
|
||||||
},
|
},
|
||||||
{fieldtype:'Float', fieldname:'tax_rate', label:__('Tax Rate'),
|
|
||||||
depends_on: 'eval:doc.is_group==0&&doc.account_type=="Tax"'},
|
|
||||||
{fieldtype:'Link', fieldname:'account_currency', label:__('Currency'), options:"Currency",
|
|
||||||
description: __("Optional. Sets company's default currency, if not specified.")}
|
|
||||||
],
|
],
|
||||||
ignore_fields: ["parent_account"],
|
ignore_fields: ["parent_account"],
|
||||||
onload: function (treeview) {
|
onload: function (treeview) {
|
||||||
frappe.treeview_settings['Account'].treeview = {};
|
frappe.treeview_settings["Account"].treeview = {};
|
||||||
$.extend(frappe.treeview_settings['Account'].treeview, treeview);
|
$.extend(frappe.treeview_settings["Account"].treeview, treeview);
|
||||||
function get_company() {
|
function get_company() {
|
||||||
return treeview.page.fields_dict.company.get_value();
|
return treeview.page.fields_dict.company.get_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
// tools
|
// tools
|
||||||
treeview.page.add_inner_button(__("Chart of Cost Centers"), function() {
|
treeview.page.add_inner_button(
|
||||||
frappe.set_route('Tree', 'Cost Center', {company: get_company()});
|
__("Chart of Cost Centers"),
|
||||||
}, __('View'));
|
function () {
|
||||||
|
frappe.set_route("Tree", "Cost Center", { company: get_company() });
|
||||||
|
},
|
||||||
|
__("View")
|
||||||
|
);
|
||||||
|
|
||||||
treeview.page.add_inner_button(__("Opening Invoice Creation Tool"), function() {
|
treeview.page.add_inner_button(
|
||||||
frappe.set_route('Form', 'Opening Invoice Creation Tool', {company: get_company()});
|
__("Opening Invoice Creation Tool"),
|
||||||
}, __('View'));
|
function () {
|
||||||
|
frappe.set_route("Form", "Opening Invoice Creation Tool", { company: get_company() });
|
||||||
|
},
|
||||||
|
__("View")
|
||||||
|
);
|
||||||
|
|
||||||
treeview.page.add_inner_button(__("Period Closing Voucher"), function() {
|
treeview.page.add_inner_button(
|
||||||
frappe.set_route('List', 'Period Closing Voucher', {company: get_company()});
|
__("Period Closing Voucher"),
|
||||||
}, __('View'));
|
function () {
|
||||||
|
frappe.set_route("List", "Period Closing Voucher", { company: get_company() });
|
||||||
|
},
|
||||||
|
__("View")
|
||||||
|
);
|
||||||
|
|
||||||
|
treeview.page.add_inner_button(
|
||||||
treeview.page.add_inner_button(__("Journal Entry"), function() {
|
__("Journal Entry"),
|
||||||
frappe.new_doc('Journal Entry', {company: get_company()});
|
function () {
|
||||||
}, __('Create'));
|
frappe.new_doc("Journal Entry", { company: get_company() });
|
||||||
treeview.page.add_inner_button(__("Company"), function() {
|
},
|
||||||
frappe.new_doc('Company');
|
__("Create")
|
||||||
}, __('Create'));
|
);
|
||||||
|
treeview.page.add_inner_button(
|
||||||
|
__("Company"),
|
||||||
|
function () {
|
||||||
|
frappe.new_doc("Company");
|
||||||
|
},
|
||||||
|
__("Create")
|
||||||
|
);
|
||||||
|
|
||||||
// financial statements
|
// financial statements
|
||||||
for (let report of ['Trial Balance', 'General Ledger', 'Balance Sheet',
|
for (let report of [
|
||||||
'Profit and Loss Statement', 'Cash Flow Statement', 'Accounts Payable', 'Accounts Receivable']) {
|
"Trial Balance",
|
||||||
treeview.page.add_inner_button(__(report), function() {
|
"General Ledger",
|
||||||
frappe.set_route('query-report', report, {company: get_company()});
|
"Balance Sheet",
|
||||||
}, __('Financial Statements'));
|
"Profit and Loss Statement",
|
||||||
|
"Cash Flow Statement",
|
||||||
|
"Accounts Payable",
|
||||||
|
"Accounts Receivable",
|
||||||
|
]) {
|
||||||
|
treeview.page.add_inner_button(
|
||||||
|
__(report),
|
||||||
|
function () {
|
||||||
|
frappe.set_route("query-report", report, { company: get_company() });
|
||||||
|
},
|
||||||
|
__("Financial Statements")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
post_render: function (treeview) {
|
post_render: function (treeview) {
|
||||||
frappe.treeview_settings['Account'].treeview["tree"] = treeview.tree;
|
frappe.treeview_settings["Account"].treeview["tree"] = treeview.tree;
|
||||||
treeview.page.set_primary_action(__("New"), function() {
|
treeview.page.set_primary_action(
|
||||||
|
__("New"),
|
||||||
|
function () {
|
||||||
let root_company = treeview.page.fields_dict.root_company.get_value();
|
let root_company = treeview.page.fields_dict.root_company.get_value();
|
||||||
|
|
||||||
if (root_company) {
|
if (root_company) {
|
||||||
@@ -169,39 +247,47 @@ frappe.treeview_settings["Account"] = {
|
|||||||
} else {
|
} else {
|
||||||
treeview.new_node();
|
treeview.new_node();
|
||||||
}
|
}
|
||||||
}, "add");
|
},
|
||||||
|
"add"
|
||||||
|
);
|
||||||
},
|
},
|
||||||
toolbar: [
|
toolbar: [
|
||||||
{
|
{
|
||||||
label: __("Add Child"),
|
label: __("Add Child"),
|
||||||
condition: function (node) {
|
condition: function (node) {
|
||||||
return frappe.boot.user.can_create.indexOf("Account") !== -1
|
return (
|
||||||
&& (!frappe.treeview_settings['Account'].treeview.page.fields_dict.root_company.get_value()
|
frappe.boot.user.can_create.indexOf("Account") !== -1 &&
|
||||||
|| frappe.flags.ignore_root_company_validation)
|
(!frappe.treeview_settings[
|
||||||
&& node.expandable && !node.hide_add;
|
"Account"
|
||||||
|
].treeview.page.fields_dict.root_company.get_value() ||
|
||||||
|
frappe.flags.ignore_root_company_validation) &&
|
||||||
|
node.expandable &&
|
||||||
|
!node.hide_add
|
||||||
|
);
|
||||||
},
|
},
|
||||||
click: function () {
|
click: function () {
|
||||||
var me = frappe.views.trees['Account'];
|
var me = frappe.views.trees["Account"];
|
||||||
me.new_node();
|
me.new_node();
|
||||||
},
|
},
|
||||||
btnClass: "hidden-xs"
|
btnClass: "hidden-xs",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
condition: function (node) {
|
condition: function (node) {
|
||||||
return !node.root && frappe.boot.user.can_read.indexOf("GL Entry") !== -1
|
return !node.root && frappe.boot.user.can_read.indexOf("GL Entry") !== -1;
|
||||||
},
|
},
|
||||||
label: __("View Ledger"),
|
label: __("View Ledger"),
|
||||||
click: function (node, btn) {
|
click: function (node, btn) {
|
||||||
frappe.route_options = {
|
frappe.route_options = {
|
||||||
"account": node.label,
|
account: node.label,
|
||||||
"from_date": erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[1],
|
from_date: erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[1],
|
||||||
"to_date": erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[2],
|
to_date: erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[2],
|
||||||
"company": frappe.treeview_settings['Account'].treeview.page.fields_dict.company.get_value()
|
company:
|
||||||
|
frappe.treeview_settings["Account"].treeview.page.fields_dict.company.get_value(),
|
||||||
};
|
};
|
||||||
frappe.set_route("query-report", "General Ledger");
|
frappe.set_route("query-report", "General Ledger");
|
||||||
},
|
},
|
||||||
btnClass: "hidden-xs"
|
btnClass: "hidden-xs",
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
extend_toolbar: true
|
extend_toolbar: true,
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ def create_charts(
|
|||||||
"tax_rate",
|
"tax_rate",
|
||||||
"account_currency",
|
"account_currency",
|
||||||
]:
|
]:
|
||||||
|
|
||||||
account_number = cstr(child.get("account_number")).strip()
|
account_number = cstr(child.get("account_number")).strip()
|
||||||
account_name, account_name_in_db = add_suffix_if_duplicate(
|
account_name, account_name_in_db = add_suffix_if_duplicate(
|
||||||
account_name, account_number, accounts
|
account_name, account_number, accounts
|
||||||
@@ -39,7 +38,9 @@ def create_charts(
|
|||||||
|
|
||||||
is_group = identify_is_group(child)
|
is_group = identify_is_group(child)
|
||||||
report_type = (
|
report_type = (
|
||||||
"Balance Sheet" if root_type in ["Asset", "Liability", "Equity"] else "Profit and Loss"
|
"Balance Sheet"
|
||||||
|
if root_type in ["Asset", "Liability", "Equity"]
|
||||||
|
else "Profit and Loss"
|
||||||
)
|
)
|
||||||
|
|
||||||
account = frappe.get_doc(
|
account = frappe.get_doc(
|
||||||
@@ -141,7 +142,7 @@ def get_chart(chart_template, existing_company=None):
|
|||||||
for fname in os.listdir(path):
|
for fname in os.listdir(path):
|
||||||
fname = frappe.as_unicode(fname)
|
fname = frappe.as_unicode(fname)
|
||||||
if fname.endswith(".json"):
|
if fname.endswith(".json"):
|
||||||
with open(os.path.join(path, fname), "r") as f:
|
with open(os.path.join(path, fname)) as f:
|
||||||
chart = f.read()
|
chart = f.read()
|
||||||
if chart and json.loads(chart).get("name") == chart_template:
|
if chart and json.loads(chart).get("name") == chart_template:
|
||||||
return json.loads(chart).get("tree")
|
return json.loads(chart).get("tree")
|
||||||
@@ -173,7 +174,7 @@ def get_charts_for_country(country, with_standard=False):
|
|||||||
for fname in os.listdir(path):
|
for fname in os.listdir(path):
|
||||||
fname = frappe.as_unicode(fname)
|
fname = frappe.as_unicode(fname)
|
||||||
if (fname.startswith(country_code) or fname.startswith(country)) and fname.endswith(".json"):
|
if (fname.startswith(country_code) or fname.startswith(country)) and fname.endswith(".json"):
|
||||||
with open(os.path.join(path, fname), "r") as f:
|
with open(os.path.join(path, fname)) as f:
|
||||||
_get_chart_name(f.read())
|
_get_chart_name(f.read())
|
||||||
|
|
||||||
# if more than one charts, returned then add the standard
|
# if more than one charts, returned then add the standard
|
||||||
@@ -249,7 +250,13 @@ def validate_bank_account(coa, bank_account):
|
|||||||
|
|
||||||
def _get_account_names(account_master):
|
def _get_account_names(account_master):
|
||||||
for account_name, child in account_master.items():
|
for account_name, child in account_master.items():
|
||||||
if account_name not in ["account_number", "account_type", "root_type", "is_group", "tax_rate"]:
|
if account_name not in [
|
||||||
|
"account_number",
|
||||||
|
"account_type",
|
||||||
|
"root_type",
|
||||||
|
"is_group",
|
||||||
|
"tax_rate",
|
||||||
|
]:
|
||||||
accounts.append(account_name)
|
accounts.append(account_name)
|
||||||
|
|
||||||
_get_account_names(child)
|
_get_account_names(child)
|
||||||
|
|||||||
@@ -56,7 +56,9 @@
|
|||||||
"Constru\u00e7\u00f5es em Andamento de Im\u00f3veis Destinados \u00e0 Venda": {},
|
"Constru\u00e7\u00f5es em Andamento de Im\u00f3veis Destinados \u00e0 Venda": {},
|
||||||
"Estoques Destinados \u00e0 Doa\u00e7\u00e3o": {},
|
"Estoques Destinados \u00e0 Doa\u00e7\u00e3o": {},
|
||||||
"Im\u00f3veis Destinados \u00e0 Venda": {},
|
"Im\u00f3veis Destinados \u00e0 Venda": {},
|
||||||
"Insumos (materiais diretos)": {},
|
"Insumos (materiais diretos)": {
|
||||||
|
"account_type": "Stock"
|
||||||
|
},
|
||||||
"Insumos Agropecu\u00e1rios": {},
|
"Insumos Agropecu\u00e1rios": {},
|
||||||
"Mercadorias para Revenda": {},
|
"Mercadorias para Revenda": {},
|
||||||
"Outras 11": {},
|
"Outras 11": {},
|
||||||
@@ -146,6 +148,65 @@
|
|||||||
"root_type": "Asset"
|
"root_type": "Asset"
|
||||||
},
|
},
|
||||||
"CUSTOS DE PRODU\u00c7\u00c3O": {
|
"CUSTOS DE PRODU\u00c7\u00c3O": {
|
||||||
|
"CUSTO DOS PRODUTOS E SERVI\u00c7OS VENDIDOS": {
|
||||||
|
"CUSTO DOS PRODUTOS VENDIDOS": {
|
||||||
|
"CUSTO DOS PRODUTOS VENDIDOS PARA AS DEMAIS ATIVIDADES": {
|
||||||
|
"Custos dos Produtos Vendidos em Geral": {
|
||||||
|
"account_type": "Cost of Goods Sold"
|
||||||
|
},
|
||||||
|
"Outros Custos 4": {},
|
||||||
|
"account_type": "Cost of Goods Sold"
|
||||||
|
},
|
||||||
|
"CUSTO DOS PRODUTOS VENDIDOS PARA ASSIST\u00caNCIA SOCIAL": {
|
||||||
|
"Custos dos Produtos para Assist\u00eancia Social - Gratuidades": {},
|
||||||
|
"Custos dos Produtos para Assist\u00eancia Social - Vendidos": {},
|
||||||
|
"Outras": {}
|
||||||
|
},
|
||||||
|
"CUSTO DOS PRODUTOS VENDIDOS PARA EDUCA\u00c7\u00c3O": {
|
||||||
|
"Custos dos Produtos para Educa\u00e7\u00e3o - Gratuidades": {},
|
||||||
|
"Custos dos Produtos para Educa\u00e7\u00e3o - Vendidos": {},
|
||||||
|
"Outros Custos 6": {}
|
||||||
|
},
|
||||||
|
"CUSTO DOS PRODUTOS VENDIDOS PARA SA\u00daDE": {
|
||||||
|
"Custos dos Produtos para Sa\u00fade - Gratuidades": {},
|
||||||
|
"Custos dos Produtos para Sa\u00fade \u2013 Vendidos": {},
|
||||||
|
"Outros Custos 5": {}
|
||||||
|
},
|
||||||
|
"account_type": "Cost of Goods Sold"
|
||||||
|
},
|
||||||
|
"CUSTO DOS SERVI\u00c7OS PRESTADOS": {
|
||||||
|
"CUSTO DOS SERVI\u00c7OS PRESTADOS PARA AS DEMAIS ATIVIDADES": {
|
||||||
|
"Custo dos Servi\u00e7os Prestados em Geral": {},
|
||||||
|
"Outros Custos": {}
|
||||||
|
},
|
||||||
|
"CUSTO DOS SERVI\u00c7OS PRESTADOS PARA ASSIST\u00caNCIA SOCIAL": {
|
||||||
|
"Custo dos Servi\u00e7os Prestados a Conv\u00eanios/Contratos/Parcerias": {},
|
||||||
|
"Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es 1": {},
|
||||||
|
"Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es/Subven\u00e7\u00f5es Vinculadas 1": {},
|
||||||
|
"Custo dos Servi\u00e7os Prestados a Gratuidade 1": {},
|
||||||
|
"Custo dos Servi\u00e7os Prestados a Pacientes Particulares": {},
|
||||||
|
"Outros Custos 2": {}
|
||||||
|
},
|
||||||
|
"CUSTO DOS SERVI\u00c7OS PRESTADOS PARA EDUCA\u00c7\u00c3O": {
|
||||||
|
"Custo dos Servi\u00e7os Prestados a Alunos N\u00e3o Bolsistas": {},
|
||||||
|
"Custo dos Servi\u00e7os Prestados a Conv\u00eanios/Contratos/Parcerias (Exceto PROUNI)": {},
|
||||||
|
"Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es": {},
|
||||||
|
"Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es/Subven\u00e7\u00f5es Vinculadas": {},
|
||||||
|
"Custo dos Servi\u00e7os Prestados a Gratuidade": {},
|
||||||
|
"Custo dos Servi\u00e7os Prestados ao PROUNI": {},
|
||||||
|
"Outros Custos 1": {}
|
||||||
|
},
|
||||||
|
"CUSTO DOS SERVI\u00c7OS PRESTADOS PARA SA\u00daDE": {
|
||||||
|
"Custo dos Servi\u00e7os Prestados a Conv\u00eanios SUS": {},
|
||||||
|
"Custo dos Servi\u00e7os Prestados a Conv\u00eanios/Contratos/Parcerias 1": {},
|
||||||
|
"Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es 2": {},
|
||||||
|
"Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es/Subven\u00e7\u00f5es Vinculadas 2": {},
|
||||||
|
"Custo dos Servi\u00e7os Prestados a Gratuidade 2": {},
|
||||||
|
"Custo dos Servi\u00e7os Prestados a Pacientes Particulares 1": {},
|
||||||
|
"Outros Custos 3": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"CUSTO DOS BENS E SERVI\u00c7OS PRODUZIDOS": {
|
"CUSTO DOS BENS E SERVI\u00c7OS PRODUZIDOS": {
|
||||||
"CUSTO DOS PRODUTOS DE FABRICA\u00c7\u00c3O PR\u00d3PRIA PRODUZIDOS": {
|
"CUSTO DOS PRODUTOS DE FABRICA\u00c7\u00c3O PR\u00d3PRIA PRODUZIDOS": {
|
||||||
"Alimenta\u00e7\u00e3o do Trabalhador": {},
|
"Alimenta\u00e7\u00e3o do Trabalhador": {},
|
||||||
@@ -621,7 +682,9 @@
|
|||||||
"Receita das Unidades Imobili\u00e1rias Vendidas": {},
|
"Receita das Unidades Imobili\u00e1rias Vendidas": {},
|
||||||
"Receita de Exporta\u00e7\u00e3o Direta de Mercadorias e Produtos": {},
|
"Receita de Exporta\u00e7\u00e3o Direta de Mercadorias e Produtos": {},
|
||||||
"Receita de Exporta\u00e7\u00e3o de Servi\u00e7os": {},
|
"Receita de Exporta\u00e7\u00e3o de Servi\u00e7os": {},
|
||||||
"Receita de Loca\u00e7\u00e3o de Bens M\u00f3veis e Im\u00f3veis": {},
|
"Receita de Loca\u00e7\u00e3o de Bens M\u00f3veis e Im\u00f3veis": {
|
||||||
|
"account_type": "Income Account"
|
||||||
|
},
|
||||||
"Receita de Vendas de Mercadorias e Produtos a Comercial Exportadora com Fim Espec\u00edfico de Exporta\u00e7\u00e3o": {}
|
"Receita de Vendas de Mercadorias e Produtos a Comercial Exportadora com Fim Espec\u00edfico de Exporta\u00e7\u00e3o": {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -645,65 +708,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"RESULTADO OPERACIONAL": {
|
"RESULTADO OPERACIONAL": {
|
||||||
"CUSTO DOS PRODUTOS E SERVI\u00c7OS VENDIDOS": {
|
|
||||||
"CUSTO DOS PRODUTOS VENDIDOS": {
|
|
||||||
"CUSTO DOS PRODUTOS VENDIDOS PARA AS DEMAIS ATIVIDADES": {
|
|
||||||
"Custos dos Produtos Vendidos em Geral": {
|
|
||||||
"account_type": "Cost of Goods Sold"
|
|
||||||
},
|
|
||||||
"Outros Custos 4": {},
|
|
||||||
"account_type": "Cost of Goods Sold"
|
|
||||||
},
|
|
||||||
"CUSTO DOS PRODUTOS VENDIDOS PARA ASSIST\u00caNCIA SOCIAL": {
|
|
||||||
"Custos dos Produtos para Assist\u00eancia Social - Gratuidades": {},
|
|
||||||
"Custos dos Produtos para Assist\u00eancia Social - Vendidos": {},
|
|
||||||
"Outras": {}
|
|
||||||
},
|
|
||||||
"CUSTO DOS PRODUTOS VENDIDOS PARA EDUCA\u00c7\u00c3O": {
|
|
||||||
"Custos dos Produtos para Educa\u00e7\u00e3o - Gratuidades": {},
|
|
||||||
"Custos dos Produtos para Educa\u00e7\u00e3o - Vendidos": {},
|
|
||||||
"Outros Custos 6": {}
|
|
||||||
},
|
|
||||||
"CUSTO DOS PRODUTOS VENDIDOS PARA SA\u00daDE": {
|
|
||||||
"Custos dos Produtos para Sa\u00fade - Gratuidades": {},
|
|
||||||
"Custos dos Produtos para Sa\u00fade \u2013 Vendidos": {},
|
|
||||||
"Outros Custos 5": {}
|
|
||||||
},
|
|
||||||
"account_type": "Cost of Goods Sold"
|
|
||||||
},
|
|
||||||
"CUSTO DOS SERVI\u00c7OS PRESTADOS": {
|
|
||||||
"CUSTO DOS SERVI\u00c7OS PRESTADOS PARA AS DEMAIS ATIVIDADES": {
|
|
||||||
"Custo dos Servi\u00e7os Prestados em Geral": {},
|
|
||||||
"Outros Custos": {}
|
|
||||||
},
|
|
||||||
"CUSTO DOS SERVI\u00c7OS PRESTADOS PARA ASSIST\u00caNCIA SOCIAL": {
|
|
||||||
"Custo dos Servi\u00e7os Prestados a Conv\u00eanios/Contratos/Parcerias": {},
|
|
||||||
"Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es 1": {},
|
|
||||||
"Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es/Subven\u00e7\u00f5es Vinculadas 1": {},
|
|
||||||
"Custo dos Servi\u00e7os Prestados a Gratuidade 1": {},
|
|
||||||
"Custo dos Servi\u00e7os Prestados a Pacientes Particulares": {},
|
|
||||||
"Outros Custos 2": {}
|
|
||||||
},
|
|
||||||
"CUSTO DOS SERVI\u00c7OS PRESTADOS PARA EDUCA\u00c7\u00c3O": {
|
|
||||||
"Custo dos Servi\u00e7os Prestados a Alunos N\u00e3o Bolsistas": {},
|
|
||||||
"Custo dos Servi\u00e7os Prestados a Conv\u00eanios/Contratos/Parcerias (Exceto PROUNI)": {},
|
|
||||||
"Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es": {},
|
|
||||||
"Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es/Subven\u00e7\u00f5es Vinculadas": {},
|
|
||||||
"Custo dos Servi\u00e7os Prestados a Gratuidade": {},
|
|
||||||
"Custo dos Servi\u00e7os Prestados ao PROUNI": {},
|
|
||||||
"Outros Custos 1": {}
|
|
||||||
},
|
|
||||||
"CUSTO DOS SERVI\u00c7OS PRESTADOS PARA SA\u00daDE": {
|
|
||||||
"Custo dos Servi\u00e7os Prestados a Conv\u00eanios SUS": {},
|
|
||||||
"Custo dos Servi\u00e7os Prestados a Conv\u00eanios/Contratos/Parcerias 1": {},
|
|
||||||
"Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es 2": {},
|
|
||||||
"Custo dos Servi\u00e7os Prestados a Doa\u00e7\u00f5es/Subven\u00e7\u00f5es Vinculadas 2": {},
|
|
||||||
"Custo dos Servi\u00e7os Prestados a Gratuidade 2": {},
|
|
||||||
"Custo dos Servi\u00e7os Prestados a Pacientes Particulares 1": {},
|
|
||||||
"Outros Custos 3": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"DESPESAS OPERACIONAIS": {
|
"DESPESAS OPERACIONAIS": {
|
||||||
"DESPESAS OPERACIONAIS 1": {
|
"DESPESAS OPERACIONAIS 1": {
|
||||||
"DESPESAS OPERACIONAIS 2": {
|
"DESPESAS OPERACIONAIS 2": {
|
||||||
|
|||||||
@@ -36,16 +36,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Fixed Assets": {
|
"Fixed Assets": {
|
||||||
"Capital Equipments": {
|
"Capital Equipment": {
|
||||||
"account_type": "Fixed Asset"
|
"account_type": "Fixed Asset"
|
||||||
},
|
},
|
||||||
"Electronic Equipments": {
|
"Electronic Equipment": {
|
||||||
"account_type": "Fixed Asset"
|
"account_type": "Fixed Asset"
|
||||||
},
|
},
|
||||||
"Furnitures and Fixtures": {
|
"Furniture and Fixtures": {
|
||||||
"account_type": "Fixed Asset"
|
"account_type": "Fixed Asset"
|
||||||
},
|
},
|
||||||
"Office Equipments": {
|
"Office Equipment": {
|
||||||
"account_type": "Fixed Asset"
|
"account_type": "Fixed Asset"
|
||||||
},
|
},
|
||||||
"Plants and Machineries": {
|
"Plants and Machineries": {
|
||||||
|
|||||||
@@ -23,13 +23,13 @@ def get():
|
|||||||
_("Tax Assets"): {"is_group": 1},
|
_("Tax Assets"): {"is_group": 1},
|
||||||
},
|
},
|
||||||
_("Fixed Assets"): {
|
_("Fixed Assets"): {
|
||||||
_("Capital Equipments"): {"account_type": "Fixed Asset"},
|
_("Capital Equipment"): {"account_type": "Fixed Asset"},
|
||||||
_("Electronic Equipments"): {"account_type": "Fixed Asset"},
|
_("Electronic Equipment"): {"account_type": "Fixed Asset"},
|
||||||
_("Furnitures and Fixtures"): {"account_type": "Fixed Asset"},
|
_("Furniture and Fixtures"): {"account_type": "Fixed Asset"},
|
||||||
_("Office Equipments"): {"account_type": "Fixed Asset"},
|
_("Office Equipment"): {"account_type": "Fixed Asset"},
|
||||||
_("Plants and Machineries"): {"account_type": "Fixed Asset"},
|
_("Plants and Machineries"): {"account_type": "Fixed Asset"},
|
||||||
_("Buildings"): {"account_type": "Fixed Asset"},
|
_("Buildings"): {"account_type": "Fixed Asset"},
|
||||||
_("Softwares"): {"account_type": "Fixed Asset"},
|
_("Software"): {"account_type": "Fixed Asset"},
|
||||||
_("Accumulated Depreciation"): {"account_type": "Accumulated Depreciation"},
|
_("Accumulated Depreciation"): {"account_type": "Accumulated Depreciation"},
|
||||||
_("CWIP Account"): {
|
_("CWIP Account"): {
|
||||||
"account_type": "Capital Work in Progress",
|
"account_type": "Capital Work in Progress",
|
||||||
|
|||||||
@@ -36,13 +36,13 @@ def get():
|
|||||||
"account_number": "1100-1600",
|
"account_number": "1100-1600",
|
||||||
},
|
},
|
||||||
_("Fixed Assets"): {
|
_("Fixed Assets"): {
|
||||||
_("Capital Equipments"): {"account_type": "Fixed Asset", "account_number": "1710"},
|
_("Capital Equipment"): {"account_type": "Fixed Asset", "account_number": "1710"},
|
||||||
_("Electronic Equipments"): {"account_type": "Fixed Asset", "account_number": "1720"},
|
_("Electronic Equipment"): {"account_type": "Fixed Asset", "account_number": "1720"},
|
||||||
_("Furnitures and Fixtures"): {"account_type": "Fixed Asset", "account_number": "1730"},
|
_("Furniture and Fixtures"): {"account_type": "Fixed Asset", "account_number": "1730"},
|
||||||
_("Office Equipments"): {"account_type": "Fixed Asset", "account_number": "1740"},
|
_("Office Equipment"): {"account_type": "Fixed Asset", "account_number": "1740"},
|
||||||
_("Plants and Machineries"): {"account_type": "Fixed Asset", "account_number": "1750"},
|
_("Plants and Machineries"): {"account_type": "Fixed Asset", "account_number": "1750"},
|
||||||
_("Buildings"): {"account_type": "Fixed Asset", "account_number": "1760"},
|
_("Buildings"): {"account_type": "Fixed Asset", "account_number": "1760"},
|
||||||
_("Softwares"): {"account_type": "Fixed Asset", "account_number": "1770"},
|
_("Software"): {"account_type": "Fixed Asset", "account_number": "1770"},
|
||||||
_("Accumulated Depreciation"): {
|
_("Accumulated Depreciation"): {
|
||||||
"account_type": "Accumulated Depreciation",
|
"account_type": "Accumulated Depreciation",
|
||||||
"account_number": "1780",
|
"account_number": "1780",
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import unittest
|
|||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe.test_runner import make_test_records
|
from frappe.test_runner import make_test_records
|
||||||
|
from frappe.utils import nowdate
|
||||||
|
|
||||||
from erpnext.accounts.doctype.account.account import (
|
from erpnext.accounts.doctype.account.account import (
|
||||||
InvalidAccountMergeError,
|
InvalidAccountMergeError,
|
||||||
@@ -119,7 +120,7 @@ class TestAccount(unittest.TestCase):
|
|||||||
InvalidAccountMergeError,
|
InvalidAccountMergeError,
|
||||||
merge_account,
|
merge_account,
|
||||||
"Capital Stock - _TC",
|
"Capital Stock - _TC",
|
||||||
"Softwares - _TC",
|
"Software - _TC",
|
||||||
)
|
)
|
||||||
|
|
||||||
# Raise error as currency doesn't match
|
# Raise error as currency doesn't match
|
||||||
@@ -260,28 +261,20 @@ class TestAccount(unittest.TestCase):
|
|||||||
acc.insert()
|
acc.insert()
|
||||||
|
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
frappe.db.exists(
|
frappe.db.exists("Account", {"account_name": "Test Group Account", "company": "_Test Company 4"})
|
||||||
"Account", {"account_name": "Test Group Account", "company": "_Test Company 4"}
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
frappe.db.exists(
|
frappe.db.exists("Account", {"account_name": "Test Group Account", "company": "_Test Company 5"})
|
||||||
"Account", {"account_name": "Test Group Account", "company": "_Test Company 5"}
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Try renaming child company account
|
# Try renaming child company account
|
||||||
acc_tc_5 = frappe.db.get_value(
|
acc_tc_5 = frappe.db.get_value(
|
||||||
"Account", {"account_name": "Test Group Account", "company": "_Test Company 5"}
|
"Account", {"account_name": "Test Group Account", "company": "_Test Company 5"}
|
||||||
)
|
)
|
||||||
self.assertRaises(
|
self.assertRaises(frappe.ValidationError, update_account_number, acc_tc_5, "Test Modified Account")
|
||||||
frappe.ValidationError, update_account_number, acc_tc_5, "Test Modified Account"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Rename child company account with allow_account_creation_against_child_company enabled
|
# Rename child company account with allow_account_creation_against_child_company enabled
|
||||||
frappe.db.set_value(
|
frappe.db.set_value("Company", "_Test Company 5", "allow_account_creation_against_child_company", 1)
|
||||||
"Company", "_Test Company 5", "allow_account_creation_against_child_company", 1
|
|
||||||
)
|
|
||||||
|
|
||||||
update_account_number(acc_tc_5, "Test Modified Account")
|
update_account_number(acc_tc_5, "Test Modified Account")
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
@@ -290,9 +283,7 @@ class TestAccount(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
frappe.db.set_value(
|
frappe.db.set_value("Company", "_Test Company 5", "allow_account_creation_against_child_company", 0)
|
||||||
"Company", "_Test Company 5", "allow_account_creation_against_child_company", 0
|
|
||||||
)
|
|
||||||
|
|
||||||
to_delete = [
|
to_delete = [
|
||||||
"Test Group Account - _TC3",
|
"Test Group Account - _TC3",
|
||||||
@@ -317,13 +308,24 @@ class TestAccount(unittest.TestCase):
|
|||||||
self.assertEqual(acc.account_currency, "INR")
|
self.assertEqual(acc.account_currency, "INR")
|
||||||
|
|
||||||
# Make a JV against this account
|
# Make a JV against this account
|
||||||
make_journal_entry(
|
make_journal_entry("Test Currency Account - _TC", "Miscellaneous Expenses - _TC", 100, submit=True)
|
||||||
"Test Currency Account - _TC", "Miscellaneous Expenses - _TC", 100, submit=True
|
|
||||||
)
|
|
||||||
|
|
||||||
acc.account_currency = "USD"
|
acc.account_currency = "USD"
|
||||||
self.assertRaises(frappe.ValidationError, acc.save)
|
self.assertRaises(frappe.ValidationError, acc.save)
|
||||||
|
|
||||||
|
def test_account_balance(self):
|
||||||
|
from erpnext.accounts.utils import get_balance_on
|
||||||
|
|
||||||
|
if not frappe.db.exists("Account", "Test Percent Account %5 - _TC"):
|
||||||
|
acc = frappe.new_doc("Account")
|
||||||
|
acc.account_name = "Test Percent Account %5"
|
||||||
|
acc.parent_account = "Tax Assets - _TC"
|
||||||
|
acc.company = "_Test Company"
|
||||||
|
acc.insert()
|
||||||
|
|
||||||
|
balance = get_balance_on(account="Test Percent Account %5 - _TC", date=nowdate())
|
||||||
|
self.assertEqual(balance, 0)
|
||||||
|
|
||||||
|
|
||||||
def _make_test_records(verbose=None):
|
def _make_test_records(verbose=None):
|
||||||
from frappe.test_runner import make_test_objects
|
from frappe.test_runner import make_test_objects
|
||||||
|
|||||||
@@ -129,7 +129,7 @@
|
|||||||
"icon": "fa fa-list",
|
"icon": "fa fa-list",
|
||||||
"in_create": 1,
|
"in_create": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-03-06 08:56:36.393237",
|
"modified": "2024-03-27 13:05:56.710541",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Account Closing Balance",
|
"name": "Account Closing Balance",
|
||||||
@@ -158,7 +158,7 @@
|
|||||||
"role": "Auditor"
|
"role": "Auditor"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"sort_field": "modified",
|
"sort_field": "creation",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"states": []
|
"states": []
|
||||||
}
|
}
|
||||||
@@ -40,16 +40,12 @@ class AccountClosingBalance(Document):
|
|||||||
def make_closing_entries(closing_entries, voucher_name, company, closing_date):
|
def make_closing_entries(closing_entries, voucher_name, company, closing_date):
|
||||||
accounting_dimensions = get_accounting_dimensions()
|
accounting_dimensions = get_accounting_dimensions()
|
||||||
|
|
||||||
previous_closing_entries = get_previous_closing_entries(
|
previous_closing_entries = get_previous_closing_entries(company, closing_date, accounting_dimensions)
|
||||||
company, closing_date, accounting_dimensions
|
|
||||||
)
|
|
||||||
combined_entries = closing_entries + previous_closing_entries
|
combined_entries = closing_entries + previous_closing_entries
|
||||||
|
|
||||||
merged_entries = aggregate_with_last_account_closing_balance(
|
merged_entries = aggregate_with_last_account_closing_balance(combined_entries, accounting_dimensions)
|
||||||
combined_entries, accounting_dimensions
|
|
||||||
)
|
|
||||||
|
|
||||||
for key, value in merged_entries.items():
|
for _key, value in merged_entries.items():
|
||||||
cle = frappe.new_doc("Account Closing Balance")
|
cle = frappe.new_doc("Account Closing Balance")
|
||||||
cle.update(value)
|
cle.update(value)
|
||||||
cle.update(value["dimensions"])
|
cle.update(value["dimensions"])
|
||||||
|
|||||||
@@ -1,17 +1,22 @@
|
|||||||
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
|
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
|
|
||||||
frappe.ui.form.on('Accounting Dimension', {
|
frappe.ui.form.on("Accounting Dimension", {
|
||||||
refresh: function (frm) {
|
refresh: function (frm) {
|
||||||
frm.set_query('document_type', () => {
|
frm.set_query("document_type", () => {
|
||||||
let invalid_doctypes = frappe.model.core_doctypes_list;
|
let invalid_doctypes = frappe.model.core_doctypes_list;
|
||||||
invalid_doctypes.push('Accounting Dimension', 'Project',
|
invalid_doctypes.push(
|
||||||
'Cost Center', 'Accounting Dimension Detail', 'Company');
|
"Accounting Dimension",
|
||||||
|
"Project",
|
||||||
|
"Cost Center",
|
||||||
|
"Accounting Dimension Detail",
|
||||||
|
"Company"
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
name: ['not in', invalid_doctypes]
|
name: ["not in", invalid_doctypes],
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -21,54 +26,64 @@ frappe.ui.form.on('Accounting Dimension', {
|
|||||||
filters: {
|
filters: {
|
||||||
company: d.company,
|
company: d.company,
|
||||||
root_type: ["in", ["Asset", "Liability"]],
|
root_type: ["in", ["Asset", "Liability"]],
|
||||||
is_group: 0
|
is_group: 0,
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!frm.is_new()) {
|
if (!frm.is_new()) {
|
||||||
frm.add_custom_button(__('Show {0}', [frm.doc.document_type]), function () {
|
frm.add_custom_button(__("Show {0}", [frm.doc.document_type]), function () {
|
||||||
frappe.set_route("List", frm.doc.document_type);
|
frappe.set_route("List", frm.doc.document_type);
|
||||||
});
|
});
|
||||||
|
|
||||||
let button = frm.doc.disabled ? "Enable" : "Disable";
|
let button = frm.doc.disabled ? "Enable" : "Disable";
|
||||||
|
|
||||||
frm.add_custom_button(__(button), function () {
|
frm.add_custom_button(__(button), function () {
|
||||||
|
frm.set_value("disabled", 1 - frm.doc.disabled);
|
||||||
frm.set_value('disabled', 1 - frm.doc.disabled);
|
|
||||||
|
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: "erpnext.accounts.doctype.accounting_dimension.accounting_dimension.disable_dimension",
|
method: "erpnext.accounts.doctype.accounting_dimension.accounting_dimension.disable_dimension",
|
||||||
args: {
|
args: {
|
||||||
doc: frm.doc
|
doc: frm.doc,
|
||||||
},
|
},
|
||||||
freeze: true,
|
freeze: true,
|
||||||
callback: function (r) {
|
callback: function (r) {
|
||||||
let message = frm.doc.disabled ? "Dimension Disabled" : "Dimension Enabled";
|
let message = frm.doc.disabled ? "Dimension Disabled" : "Dimension Enabled";
|
||||||
frm.save();
|
frm.save();
|
||||||
frappe.show_alert({message:__(message), indicator:'green'});
|
frappe.show_alert({ message: __(message), indicator: "green" });
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
label: function (frm) {
|
||||||
|
frm.set_value("fieldname", frappe.model.scrub(frm.doc.label));
|
||||||
|
},
|
||||||
|
|
||||||
document_type: function (frm) {
|
document_type: function (frm) {
|
||||||
|
frm.set_value("label", frm.doc.document_type);
|
||||||
|
|
||||||
frm.set_value('label', frm.doc.document_type);
|
frappe.db.get_value(
|
||||||
frm.set_value('fieldname', frappe.model.scrub(frm.doc.document_type));
|
"Accounting Dimension",
|
||||||
|
{ document_type: frm.doc.document_type },
|
||||||
frappe.db.get_value('Accounting Dimension', {'document_type': frm.doc.document_type}, 'document_type', (r) => {
|
"document_type",
|
||||||
|
(r) => {
|
||||||
if (r && r.document_type) {
|
if (r && r.document_type) {
|
||||||
frm.set_df_property('document_type', 'description', "Document type is already set as dimension");
|
frm.set_df_property(
|
||||||
|
"document_type",
|
||||||
|
"description",
|
||||||
|
"Document type is already set as dimension"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
frappe.ui.form.on('Accounting Dimension Detail', {
|
frappe.ui.form.on("Accounting Dimension Detail", {
|
||||||
dimension_defaults_add: function (frm, cdt, cdn) {
|
dimension_defaults_add: function (frm, cdt, cdn) {
|
||||||
let row = locals[cdt][cdn];
|
let row = locals[cdt][cdn];
|
||||||
row.reference_document = frm.doc.document_type;
|
row.reference_document = frm.doc.document_type;
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -49,7 +49,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-02-08 16:37:53.936656",
|
"modified": "2024-03-27 13:05:56.890002",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Accounting Dimension",
|
"name": "Accounting Dimension",
|
||||||
@@ -80,7 +80,8 @@
|
|||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"sort_field": "modified",
|
"sort_field": "creation",
|
||||||
"sort_order": "ASC",
|
"sort_order": "ASC",
|
||||||
|
"states": [],
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
||||||
@@ -11,6 +11,10 @@ from frappe.model import core_doctypes_list
|
|||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from frappe.utils import cstr
|
from frappe.utils import cstr
|
||||||
|
|
||||||
|
from erpnext.accounts.doctype.repost_accounting_ledger.repost_accounting_ledger import (
|
||||||
|
get_allowed_types_from_settings,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class AccountingDimension(Document):
|
class AccountingDimension(Document):
|
||||||
# begin: auto-generated types
|
# begin: auto-generated types
|
||||||
@@ -36,7 +40,8 @@ class AccountingDimension(Document):
|
|||||||
self.set_fieldname_and_label()
|
self.set_fieldname_and_label()
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
if self.document_type in core_doctypes_list + (
|
if self.document_type in (
|
||||||
|
*core_doctypes_list,
|
||||||
"Accounting Dimension",
|
"Accounting Dimension",
|
||||||
"Project",
|
"Project",
|
||||||
"Cost Center",
|
"Cost Center",
|
||||||
@@ -44,13 +49,10 @@ class AccountingDimension(Document):
|
|||||||
"Company",
|
"Company",
|
||||||
"Account",
|
"Account",
|
||||||
):
|
):
|
||||||
|
|
||||||
msg = _("Not allowed to create accounting dimension for {0}").format(self.document_type)
|
msg = _("Not allowed to create accounting dimension for {0}").format(self.document_type)
|
||||||
frappe.throw(msg)
|
frappe.throw(msg)
|
||||||
|
|
||||||
exists = frappe.db.get_value(
|
exists = frappe.db.get_value("Accounting Dimension", {"document_type": self.document_type}, ["name"])
|
||||||
"Accounting Dimension", {"document_type": self.document_type}, ["name"]
|
|
||||||
)
|
|
||||||
|
|
||||||
if exists and self.is_new():
|
if exists and self.is_new():
|
||||||
frappe.throw(_("Document Type already used as a dimension"))
|
frappe.throw(_("Document Type already used as a dimension"))
|
||||||
@@ -106,9 +108,9 @@ def make_dimension_in_accounting_doctypes(doc, doclist=None):
|
|||||||
|
|
||||||
doc_count = len(get_accounting_dimensions())
|
doc_count = len(get_accounting_dimensions())
|
||||||
count = 0
|
count = 0
|
||||||
|
repostable_doctypes = get_allowed_types_from_settings()
|
||||||
|
|
||||||
for doctype in doclist:
|
for doctype in doclist:
|
||||||
|
|
||||||
if (doc_count + 1) % 2 == 0:
|
if (doc_count + 1) % 2 == 0:
|
||||||
insert_after_field = "dimension_col_break"
|
insert_after_field = "dimension_col_break"
|
||||||
else:
|
else:
|
||||||
@@ -121,6 +123,7 @@ def make_dimension_in_accounting_doctypes(doc, doclist=None):
|
|||||||
"options": doc.document_type,
|
"options": doc.document_type,
|
||||||
"insert_after": insert_after_field,
|
"insert_after": insert_after_field,
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
|
"allow_on_submit": 1 if doctype in repostable_doctypes else 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
meta = frappe.get_meta(doctype, cached=False)
|
meta = frappe.get_meta(doctype, cached=False)
|
||||||
@@ -142,7 +145,7 @@ def add_dimension_to_budget_doctype(df, doc):
|
|||||||
df.update(
|
df.update(
|
||||||
{
|
{
|
||||||
"insert_after": "cost_center",
|
"insert_after": "cost_center",
|
||||||
"depends_on": "eval:doc.budget_against == '{0}'".format(doc.document_type),
|
"depends_on": f"eval:doc.budget_against == '{doc.document_type}'",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -176,19 +179,17 @@ def delete_accounting_dimension(doc):
|
|||||||
frappe.db.sql(
|
frappe.db.sql(
|
||||||
"""
|
"""
|
||||||
DELETE FROM `tabCustom Field`
|
DELETE FROM `tabCustom Field`
|
||||||
WHERE fieldname = %s
|
WHERE fieldname = {}
|
||||||
AND dt IN (%s)"""
|
AND dt IN ({})""".format("%s", ", ".join(["%s"] * len(doclist))), # nosec
|
||||||
% ("%s", ", ".join(["%s"] * len(doclist))), # nosec
|
tuple([doc.fieldname, *doclist]),
|
||||||
tuple([doc.fieldname] + doclist),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
frappe.db.sql(
|
frappe.db.sql(
|
||||||
"""
|
"""
|
||||||
DELETE FROM `tabProperty Setter`
|
DELETE FROM `tabProperty Setter`
|
||||||
WHERE field_name = %s
|
WHERE field_name = {}
|
||||||
AND doc_type IN (%s)"""
|
AND doc_type IN ({})""".format("%s", ", ".join(["%s"] * len(doclist))), # nosec
|
||||||
% ("%s", ", ".join(["%s"] * len(doclist))), # nosec
|
tuple([doc.fieldname, *doclist]),
|
||||||
tuple([doc.fieldname] + doclist),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
budget_against_property = frappe.get_doc("Property Setter", "Budget-budget_against-options")
|
budget_against_property = frappe.get_doc("Property Setter", "Budget-budget_against-options")
|
||||||
@@ -237,7 +238,6 @@ def get_doctypes_with_dimensions():
|
|||||||
|
|
||||||
|
|
||||||
def get_accounting_dimensions(as_list=True, filters=None):
|
def get_accounting_dimensions(as_list=True, filters=None):
|
||||||
|
|
||||||
if not filters:
|
if not filters:
|
||||||
filters = {"disabled": 0}
|
filters = {"disabled": 0}
|
||||||
|
|
||||||
@@ -255,18 +255,19 @@ def get_accounting_dimensions(as_list=True, filters=None):
|
|||||||
|
|
||||||
|
|
||||||
def get_checks_for_pl_and_bs_accounts():
|
def get_checks_for_pl_and_bs_accounts():
|
||||||
dimensions = frappe.db.sql(
|
if frappe.flags.accounting_dimensions_details is None:
|
||||||
|
# nosemgrep
|
||||||
|
frappe.flags.accounting_dimensions_details = frappe.db.sql(
|
||||||
"""SELECT p.label, p.disabled, p.fieldname, c.default_dimension, c.company, c.mandatory_for_pl, c.mandatory_for_bs
|
"""SELECT p.label, p.disabled, p.fieldname, c.default_dimension, c.company, c.mandatory_for_pl, c.mandatory_for_bs
|
||||||
FROM `tabAccounting Dimension`p ,`tabAccounting Dimension Detail` c
|
FROM `tabAccounting Dimension`p ,`tabAccounting Dimension Detail` c
|
||||||
WHERE p.name = c.parent""",
|
WHERE p.name = c.parent""",
|
||||||
as_dict=1,
|
as_dict=1,
|
||||||
)
|
)
|
||||||
|
|
||||||
return dimensions
|
return frappe.flags.accounting_dimensions_details
|
||||||
|
|
||||||
|
|
||||||
def get_dimension_with_children(doctype, dimensions):
|
def get_dimension_with_children(doctype, dimensions):
|
||||||
|
|
||||||
if isinstance(dimensions, str):
|
if isinstance(dimensions, str):
|
||||||
dimensions = [dimensions]
|
dimensions = [dimensions]
|
||||||
|
|
||||||
@@ -274,9 +275,7 @@ def get_dimension_with_children(doctype, dimensions):
|
|||||||
|
|
||||||
for dimension in dimensions:
|
for dimension in dimensions:
|
||||||
lft, rgt = frappe.db.get_value(doctype, dimension, ["lft", "rgt"])
|
lft, rgt = frappe.db.get_value(doctype, dimension, ["lft", "rgt"])
|
||||||
children = frappe.get_all(
|
children = frappe.get_all(doctype, filters={"lft": [">=", lft], "rgt": ["<=", rgt]}, order_by="lft")
|
||||||
doctype, filters={"lft": [">=", lft], "rgt": ["<=", rgt]}, order_by="lft"
|
|
||||||
)
|
|
||||||
all_dimensions += [c.name for c in children]
|
all_dimensions += [c.name for c in children]
|
||||||
|
|
||||||
return all_dimensions
|
return all_dimensions
|
||||||
@@ -284,14 +283,10 @@ def get_dimension_with_children(doctype, dimensions):
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_dimensions(with_cost_center_and_project=False):
|
def get_dimensions(with_cost_center_and_project=False):
|
||||||
|
|
||||||
c = frappe.qb.DocType("Accounting Dimension Detail")
|
c = frappe.qb.DocType("Accounting Dimension Detail")
|
||||||
p = frappe.qb.DocType("Accounting Dimension")
|
p = frappe.qb.DocType("Accounting Dimension")
|
||||||
dimension_filters = (
|
dimension_filters = (
|
||||||
frappe.qb.from_(p)
|
frappe.qb.from_(p).select(p.label, p.fieldname, p.document_type).where(p.disabled == 0).run(as_dict=1)
|
||||||
.select(p.label, p.fieldname, p.document_type)
|
|
||||||
.where(p.disabled == 0)
|
|
||||||
.run(as_dict=1)
|
|
||||||
)
|
)
|
||||||
default_dimensions = (
|
default_dimensions = (
|
||||||
frappe.qb.from_(c)
|
frappe.qb.from_(c)
|
||||||
|
|||||||
@@ -78,6 +78,8 @@ class TestAccountingDimension(unittest.TestCase):
|
|||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
disable_dimension()
|
disable_dimension()
|
||||||
|
frappe.flags.accounting_dimensions_details = None
|
||||||
|
frappe.flags.dimension_filter_map = None
|
||||||
|
|
||||||
|
|
||||||
def create_dimension():
|
def create_dimension():
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"actions": [],
|
||||||
"creation": "2019-07-16 17:53:18.718831",
|
"creation": "2019-07-16 17:53:18.718831",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
@@ -73,13 +74,15 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"modified": "2019-08-15 11:59:09.389891",
|
"links": [],
|
||||||
|
"modified": "2024-03-27 13:05:57.056874",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Accounting Dimension Detail",
|
"name": "Accounting Dimension Detail",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"sort_field": "modified",
|
"sort_field": "creation",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
|
"states": [],
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
|
|
||||||
frappe.ui.form.on('Accounting Dimension Filter', {
|
frappe.ui.form.on("Accounting Dimension Filter", {
|
||||||
refresh: function (frm, cdt, cdn) {
|
refresh: function (frm, cdt, cdn) {
|
||||||
let help_content =
|
let help_content = `<table class="table table-bordered" style="background-color: var(--scrollbar-track-color);">
|
||||||
`<table class="table table-bordered" style="background-color: var(--scrollbar-track-color);">
|
|
||||||
<tr><td>
|
<tr><td>
|
||||||
<p>
|
<p>
|
||||||
<i class="fa fa-hand-right"></i>
|
<i class="fa fa-hand-right"></i>
|
||||||
@@ -13,29 +12,28 @@ frappe.ui.form.on('Accounting Dimension Filter', {
|
|||||||
</td></tr>
|
</td></tr>
|
||||||
</table>`;
|
</table>`;
|
||||||
|
|
||||||
frm.set_df_property('dimension_filter_help', 'options', help_content);
|
frm.set_df_property("dimension_filter_help", "options", help_content);
|
||||||
},
|
},
|
||||||
onload: function (frm) {
|
onload: function (frm) {
|
||||||
frm.set_query('applicable_on_account', 'accounts', function() {
|
frm.set_query("applicable_on_account", "accounts", function () {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
'company': frm.doc.company
|
company: frm.doc.company,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
frappe.db.get_list('Accounting Dimension',
|
frappe.db.get_list("Accounting Dimension", { fields: ["document_type"] }).then((res) => {
|
||||||
{fields: ['document_type']}).then((res) => {
|
let options = ["Cost Center", "Project"];
|
||||||
let options = ['Cost Center', 'Project'];
|
|
||||||
|
|
||||||
res.forEach((dimension) => {
|
res.forEach((dimension) => {
|
||||||
options.push(dimension.document_type);
|
options.push(dimension.document_type);
|
||||||
});
|
});
|
||||||
|
|
||||||
frm.set_df_property('accounting_dimension', 'options', options);
|
frm.set_df_property("accounting_dimension", "options", options);
|
||||||
});
|
});
|
||||||
|
|
||||||
frm.trigger('setup_filters');
|
frm.trigger("setup_filters");
|
||||||
},
|
},
|
||||||
|
|
||||||
setup_filters: function (frm) {
|
setup_filters: function (frm) {
|
||||||
@@ -44,16 +42,16 @@ frappe.ui.form.on('Accounting Dimension Filter', {
|
|||||||
if (frm.doc.accounting_dimension) {
|
if (frm.doc.accounting_dimension) {
|
||||||
frappe.model.with_doctype(frm.doc.accounting_dimension, function () {
|
frappe.model.with_doctype(frm.doc.accounting_dimension, function () {
|
||||||
if (frappe.model.is_tree(frm.doc.accounting_dimension)) {
|
if (frappe.model.is_tree(frm.doc.accounting_dimension)) {
|
||||||
filters['is_group'] = 0;
|
filters["is_group"] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frappe.meta.has_field(frm.doc.accounting_dimension, 'company')) {
|
if (frappe.meta.has_field(frm.doc.accounting_dimension, "company")) {
|
||||||
filters['company'] = frm.doc.company;
|
filters["company"] = frm.doc.company;
|
||||||
}
|
}
|
||||||
|
|
||||||
frm.set_query('dimension_value', 'dimensions', function() {
|
frm.set_query("dimension_value", "dimensions", function () {
|
||||||
return {
|
return {
|
||||||
filters: filters
|
filters: filters,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -64,9 +62,13 @@ frappe.ui.form.on('Accounting Dimension Filter', {
|
|||||||
frm.clear_table("dimensions");
|
frm.clear_table("dimensions");
|
||||||
let row = frm.add_child("dimensions");
|
let row = frm.add_child("dimensions");
|
||||||
row.accounting_dimension = frm.doc.accounting_dimension;
|
row.accounting_dimension = frm.doc.accounting_dimension;
|
||||||
frm.fields_dict["dimensions"].grid.update_docfield_property("dimension_value", "label", frm.doc.accounting_dimension);
|
frm.fields_dict["dimensions"].grid.update_docfield_property(
|
||||||
|
"dimension_value",
|
||||||
|
"label",
|
||||||
|
frm.doc.accounting_dimension
|
||||||
|
);
|
||||||
frm.refresh_field("dimensions");
|
frm.refresh_field("dimensions");
|
||||||
frm.trigger('setup_filters');
|
frm.trigger("setup_filters");
|
||||||
},
|
},
|
||||||
apply_restriction_on_values: function (frm) {
|
apply_restriction_on_values: function (frm) {
|
||||||
/** If restriction on values is not applied, we should set "allow_or_restrict" to "Restrict" with an empty allowed dimension table.
|
/** If restriction on values is not applied, we should set "allow_or_restrict" to "Restrict" with an empty allowed dimension table.
|
||||||
@@ -77,13 +79,13 @@ frappe.ui.form.on('Accounting Dimension Filter', {
|
|||||||
frm.clear_table("dimensions");
|
frm.clear_table("dimensions");
|
||||||
frm.refresh_field("dimensions");
|
frm.refresh_field("dimensions");
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
frappe.ui.form.on('Allowed Dimension', {
|
frappe.ui.form.on("Allowed Dimension", {
|
||||||
dimensions_add: function (frm, cdt, cdn) {
|
dimensions_add: function (frm, cdt, cdn) {
|
||||||
let row = locals[cdt][cdn];
|
let row = locals[cdt][cdn];
|
||||||
row.accounting_dimension = frm.doc.accounting_dimension;
|
row.accounting_dimension = frm.doc.accounting_dimension;
|
||||||
frm.refresh_field("dimensions");
|
frm.refresh_field("dimensions");
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -94,7 +94,7 @@
|
|||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-06-07 14:59:41.869117",
|
"modified": "2024-03-27 13:05:57.199186",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Accounting Dimension Filter",
|
"name": "Accounting Dimension Filter",
|
||||||
@@ -139,7 +139,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"quick_entry": 1,
|
"quick_entry": 1,
|
||||||
"sort_field": "modified",
|
"sort_field": "creation",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"states": [],
|
"states": [],
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ class AccountingDimensionFilter(Document):
|
|||||||
|
|
||||||
|
|
||||||
def get_dimension_filter_map():
|
def get_dimension_filter_map():
|
||||||
|
if not frappe.flags.get("dimension_filter_map"):
|
||||||
filters = frappe.db.sql(
|
filters = frappe.db.sql(
|
||||||
"""
|
"""
|
||||||
SELECT
|
SELECT
|
||||||
@@ -95,8 +96,9 @@ def get_dimension_filter_map():
|
|||||||
f.allow_or_restrict,
|
f.allow_or_restrict,
|
||||||
f.is_mandatory,
|
f.is_mandatory,
|
||||||
)
|
)
|
||||||
|
frappe.flags.dimension_filter_map = dimension_filter_map
|
||||||
|
|
||||||
return dimension_filter_map
|
return frappe.flags.dimension_filter_map
|
||||||
|
|
||||||
|
|
||||||
def build_map(map_object, dimension, account, filter_value, allow_or_restrict, is_mandatory):
|
def build_map(map_object, dimension, account, filter_value, allow_or_restrict, is_mandatory):
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ class TestAccountingDimensionFilter(unittest.TestCase):
|
|||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
disable_dimension_filter()
|
disable_dimension_filter()
|
||||||
disable_dimension()
|
disable_dimension()
|
||||||
|
frappe.flags.accounting_dimensions_details = None
|
||||||
|
frappe.flags.dimension_filter_map = None
|
||||||
|
|
||||||
for si in self.invoice_list:
|
for si in self.invoice_list:
|
||||||
si.load_from_db()
|
si.load_from_db()
|
||||||
@@ -55,9 +57,7 @@ class TestAccountingDimensionFilter(unittest.TestCase):
|
|||||||
|
|
||||||
|
|
||||||
def create_accounting_dimension_filter():
|
def create_accounting_dimension_filter():
|
||||||
if not frappe.db.get_value(
|
if not frappe.db.get_value("Accounting Dimension Filter", {"accounting_dimension": "Cost Center"}):
|
||||||
"Accounting Dimension Filter", {"accounting_dimension": "Cost Center"}
|
|
||||||
):
|
|
||||||
frappe.get_doc(
|
frappe.get_doc(
|
||||||
{
|
{
|
||||||
"doctype": "Accounting Dimension Filter",
|
"doctype": "Accounting Dimension Filter",
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
|
|
||||||
frappe.ui.form.on('Accounting Period', {
|
frappe.ui.form.on("Accounting Period", {
|
||||||
onload: function (frm) {
|
onload: function (frm) {
|
||||||
if(frm.doc.closed_documents.length === 0 || (frm.doc.closed_documents.length === 1 && frm.doc.closed_documents[0].document_type == undefined)) {
|
if (
|
||||||
|
frm.doc.closed_documents.length === 0 ||
|
||||||
|
(frm.doc.closed_documents.length === 1 && frm.doc.closed_documents[0].document_type == undefined)
|
||||||
|
) {
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: "get_doctypes_for_closing",
|
method: "get_doctypes_for_closing",
|
||||||
doc: frm.doc,
|
doc: frm.doc,
|
||||||
@@ -17,14 +20,14 @@ frappe.ui.form.on('Accounting Period', {
|
|||||||
});
|
});
|
||||||
refresh_field("closed_documents");
|
refresh_field("closed_documents");
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
frm.set_query("document_type", "closed_documents", () => {
|
frm.set_query("document_type", "closed_documents", () => {
|
||||||
return {
|
return {
|
||||||
query: "erpnext.controllers.queries.get_doctypes_for_closing",
|
query: "erpnext.controllers.queries.get_doctypes_for_closing",
|
||||||
}
|
};
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,317 +1,112 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"actions": [],
|
||||||
"allow_guest_to_view": 0,
|
|
||||||
"allow_import": 0,
|
|
||||||
"allow_rename": 0,
|
|
||||||
"autoname": "field:period_name",
|
"autoname": "field:period_name",
|
||||||
"beta": 0,
|
|
||||||
"creation": "2018-04-13 18:50:14.672323",
|
"creation": "2018-04-13 18:50:14.672323",
|
||||||
"custom": 0,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "",
|
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"period_name",
|
||||||
|
"start_date",
|
||||||
|
"end_date",
|
||||||
|
"column_break_4",
|
||||||
|
"company",
|
||||||
|
"section_break_7",
|
||||||
|
"closed_documents"
|
||||||
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "period_name",
|
"fieldname": "period_name",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Period Name",
|
"label": "Period Name",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"unique": 1
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "start_date",
|
"fieldname": "start_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Start Date",
|
"label": "Start Date",
|
||||||
"length": 0,
|
"reqd": 1
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "end_date",
|
"fieldname": "end_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "End Date",
|
"label": "End Date",
|
||||||
"length": 0,
|
"reqd": 1
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "column_break_4",
|
"fieldname": "column_break_4",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break"
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "company",
|
"fieldname": "company",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Company",
|
"label": "Company",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Company",
|
"options": "Company",
|
||||||
"permlevel": 0,
|
"reqd": 1
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "section_break_7",
|
"fieldname": "section_break_7",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break"
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "closed_documents",
|
"fieldname": "closed_documents",
|
||||||
"fieldtype": "Table",
|
"fieldtype": "Table",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Closed Documents",
|
"label": "Closed Documents",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Closed Document",
|
"options": "Closed Document",
|
||||||
"permlevel": 0,
|
"reqd": 1
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 0,
|
"links": [],
|
||||||
"hide_heading": 0,
|
"modified": "2024-03-27 13:05:57.388109",
|
||||||
"hide_toolbar": 0,
|
|
||||||
"idx": 0,
|
|
||||||
"image_view": 0,
|
|
||||||
"in_create": 0,
|
|
||||||
"is_submittable": 0,
|
|
||||||
"issingle": 0,
|
|
||||||
"istable": 0,
|
|
||||||
"max_attachments": 0,
|
|
||||||
"modified": "2019-08-01 19:14:47.593753",
|
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Accounting Period",
|
"name": "Accounting Period",
|
||||||
"name_case": "",
|
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 1,
|
"export": 1,
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "System Manager",
|
"role": "System Manager",
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
"write": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 1,
|
"export": 1,
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "Accounts Manager",
|
"role": "Accounts Manager",
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
"write": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 1,
|
"export": 1,
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "Accounts User",
|
"role": "Accounts User",
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"quick_entry": 0,
|
"sort_field": "creation",
|
||||||
"read_only": 0,
|
|
||||||
"read_only_onload": 0,
|
|
||||||
"show_name_in_global_search": 0,
|
|
||||||
"sort_field": "modified",
|
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"track_changes": 1,
|
"states": [],
|
||||||
"track_seen": 0
|
"track_changes": 1
|
||||||
}
|
}
|
||||||
@@ -84,7 +84,10 @@ class AccountingPeriod(Document):
|
|||||||
for doctype_for_closing in self.get_doctypes_for_closing():
|
for doctype_for_closing in self.get_doctypes_for_closing():
|
||||||
self.append(
|
self.append(
|
||||||
"closed_documents",
|
"closed_documents",
|
||||||
{"document_type": doctype_for_closing.document_type, "closed": doctype_for_closing.closed},
|
{
|
||||||
|
"document_type": doctype_for_closing.document_type,
|
||||||
|
"closed": doctype_for_closing.closed,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -34,9 +34,7 @@ class TestAccountingPeriod(unittest.TestCase):
|
|||||||
ap1 = create_accounting_period(period_name="Test Accounting Period 2")
|
ap1 = create_accounting_period(period_name="Test Accounting Period 2")
|
||||||
ap1.save()
|
ap1.save()
|
||||||
|
|
||||||
doc = create_sales_invoice(
|
doc = create_sales_invoice(do_not_save=1, cost_center="_Test Company - _TC", warehouse="Stores - _TC")
|
||||||
do_not_save=1, cost_center="_Test Company - _TC", warehouse="Stores - _TC"
|
|
||||||
)
|
|
||||||
self.assertRaises(ClosedAccountingPeriod, doc.save)
|
self.assertRaises(ClosedAccountingPeriod, doc.save)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
|
|
||||||
frappe.ui.form.on('Accounts Settings', {
|
frappe.ui.form.on("Accounts Settings", {
|
||||||
refresh: function(frm) {
|
refresh: function (frm) {},
|
||||||
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"actions": [],
|
"actions": [],
|
||||||
"creation": "2013-06-24 15:49:57",
|
"creation": "2013-06-24 15:49:57",
|
||||||
"description": "Settings for Accounts",
|
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "Other",
|
"document_type": "Other",
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
@@ -462,7 +461,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-11-20 09:37:47.650347",
|
"modified": "2024-03-27 13:05:57.568638",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Accounts Settings",
|
"name": "Accounts Settings",
|
||||||
@@ -487,7 +486,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"quick_entry": 1,
|
"quick_entry": 1,
|
||||||
"sort_field": "modified",
|
"sort_field": "creation",
|
||||||
"sort_order": "ASC",
|
"sort_order": "ASC",
|
||||||
"states": [],
|
"states": [],
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
|
frappe.ui.form.on("Accounts Settings", {
|
||||||
frappe.ui.form.on('Accounts Settings', {
|
|
||||||
refresh: function (frm) {
|
refresh: function (frm) {
|
||||||
frm.set_df_property("acc_frozen_upto", "label", "Books Closed Through");
|
frm.set_df_property("acc_frozen_upto", "label", "Books Closed Through");
|
||||||
frm.set_df_property("frozen_accounts_modifier", "label", "Role Allowed to Close Books & Make Changes to Closed Periods");
|
frm.set_df_property(
|
||||||
|
"frozen_accounts_modifier",
|
||||||
|
"label",
|
||||||
|
"Role Allowed to Close Books & Make Changes to Closed Periods"
|
||||||
|
);
|
||||||
frm.set_df_property("credit_controller", "label", "Credit Manager");
|
frm.set_df_property("credit_controller", "label", "Credit Manager");
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -45,12 +45,13 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-11-25 10:27:51.712286",
|
"modified": "2024-03-27 13:05:58.308002",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Advance Tax",
|
"name": "Advance Tax",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"sort_field": "modified",
|
"sort_field": "creation",
|
||||||
"sort_order": "DESC"
|
"sort_order": "DESC",
|
||||||
|
"states": []
|
||||||
}
|
}
|
||||||
@@ -179,12 +179,13 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-11-25 11:10:10.945027",
|
"modified": "2024-03-27 13:05:58.437605",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Advance Taxes and Charges",
|
"name": "Advance Taxes and Charges",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"sort_field": "modified",
|
"sort_field": "creation",
|
||||||
"sort_order": "ASC"
|
"sort_order": "ASC",
|
||||||
|
"states": []
|
||||||
}
|
}
|
||||||
@@ -14,30 +14,27 @@
|
|||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Accounting Dimension",
|
"label": "Accounting Dimension",
|
||||||
"options": "DocType",
|
"options": "DocType",
|
||||||
"read_only": 1,
|
"read_only": 1
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "dimension_value",
|
"fieldname": "dimension_value",
|
||||||
"fieldtype": "Dynamic Link",
|
"fieldtype": "Dynamic Link",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"options": "accounting_dimension",
|
"options": "accounting_dimension"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-11-23 09:56:19.744200",
|
"modified": "2024-03-27 13:05:58.587487",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Allowed Dimension",
|
"name": "Allowed Dimension",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"quick_entry": 1,
|
"quick_entry": 1,
|
||||||
"sort_field": "modified",
|
"sort_field": "creation",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
|
"states": [],
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
||||||
@@ -20,14 +20,14 @@
|
|||||||
],
|
],
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2024-01-03 11:13:02.669632",
|
"modified": "2024-03-27 13:05:58.698893",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Allowed To Transact With",
|
"name": "Allowed To Transact With",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"quick_entry": 1,
|
"quick_entry": 1,
|
||||||
"sort_field": "modified",
|
"sort_field": "creation",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"states": [],
|
"states": [],
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
|
|||||||
@@ -15,9 +15,7 @@
|
|||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Accounts",
|
"label": "Accounts",
|
||||||
"options": "Account",
|
"options": "Account",
|
||||||
"reqd": 1,
|
"reqd": 1
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"columns": 2,
|
"columns": 2,
|
||||||
@@ -25,22 +23,21 @@
|
|||||||
"fieldname": "is_mandatory",
|
"fieldname": "is_mandatory",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Is Mandatory",
|
"label": "Is Mandatory"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-11-22 19:55:13.324136",
|
"modified": "2024-03-27 13:05:59.168897",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Applicable On Account",
|
"name": "Applicable On Account",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"quick_entry": 1,
|
"quick_entry": 1,
|
||||||
"sort_field": "modified",
|
"sort_field": "creation",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
|
"states": [],
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
||||||
@@ -1,38 +1,36 @@
|
|||||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
frappe.provide('erpnext.integrations');
|
frappe.provide("erpnext.integrations");
|
||||||
|
|
||||||
frappe.ui.form.on('Bank', {
|
frappe.ui.form.on("Bank", {
|
||||||
onload: function (frm) {
|
onload: function (frm) {
|
||||||
add_fields_to_mapping_table(frm);
|
add_fields_to_mapping_table(frm);
|
||||||
},
|
},
|
||||||
refresh: function (frm) {
|
refresh: function (frm) {
|
||||||
add_fields_to_mapping_table(frm);
|
add_fields_to_mapping_table(frm);
|
||||||
frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal);
|
frm.toggle_display(["address_html", "contact_html"], !frm.doc.__islocal);
|
||||||
|
|
||||||
if (frm.doc.__islocal) {
|
if (frm.doc.__islocal) {
|
||||||
frm.set_df_property('address_and_contact', 'hidden', 1);
|
frm.set_df_property("address_and_contact", "hidden", 1);
|
||||||
frappe.contacts.clear_address_and_contact(frm);
|
frappe.contacts.clear_address_and_contact(frm);
|
||||||
}
|
} else {
|
||||||
else {
|
frm.set_df_property("address_and_contact", "hidden", 0);
|
||||||
frm.set_df_property('address_and_contact', 'hidden', 0);
|
|
||||||
frappe.contacts.render_address_and_contact(frm);
|
frappe.contacts.render_address_and_contact(frm);
|
||||||
}
|
}
|
||||||
if (frm.doc.plaid_access_token) {
|
if (frm.doc.plaid_access_token) {
|
||||||
frm.add_custom_button(__('Refresh Plaid Link'), () => {
|
frm.add_custom_button(__("Refresh Plaid Link"), () => {
|
||||||
new erpnext.integrations.refreshPlaidLink(frm.doc.plaid_access_token);
|
new erpnext.integrations.refreshPlaidLink(frm.doc.plaid_access_token);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
let add_fields_to_mapping_table = function (frm) {
|
let add_fields_to_mapping_table = function (frm) {
|
||||||
let options = [];
|
let options = [];
|
||||||
|
|
||||||
frappe.model.with_doctype("Bank Transaction", function () {
|
frappe.model.with_doctype("Bank Transaction", function () {
|
||||||
let meta = frappe.get_meta("Bank Transaction");
|
let meta = frappe.get_meta("Bank Transaction");
|
||||||
meta.fields.forEach(value => {
|
meta.fields.forEach((value) => {
|
||||||
if (!["Section Break", "Column Break"].includes(value.fieldtype)) {
|
if (!["Section Break", "Column Break"].includes(value.fieldtype)) {
|
||||||
options.push(value.fieldname);
|
options.push(value.fieldname);
|
||||||
}
|
}
|
||||||
@@ -40,30 +38,32 @@ let add_fields_to_mapping_table = function (frm) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
frm.fields_dict.bank_transaction_mapping.grid.update_docfield_property(
|
frm.fields_dict.bank_transaction_mapping.grid.update_docfield_property(
|
||||||
'bank_transaction_field', 'options', options
|
"bank_transaction_field",
|
||||||
|
"options",
|
||||||
|
options
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
erpnext.integrations.refreshPlaidLink = class refreshPlaidLink {
|
erpnext.integrations.refreshPlaidLink = class refreshPlaidLink {
|
||||||
constructor(access_token) {
|
constructor(access_token) {
|
||||||
this.access_token = access_token;
|
this.access_token = access_token;
|
||||||
this.plaidUrl = 'https://cdn.plaid.com/link/v2/stable/link-initialize.js';
|
this.plaidUrl = "https://cdn.plaid.com/link/v2/stable/link-initialize.js";
|
||||||
this.init_config();
|
this.init_config();
|
||||||
}
|
}
|
||||||
|
|
||||||
async init_config() {
|
async init_config() {
|
||||||
this.plaid_env = await frappe.db.get_single_value('Plaid Settings', 'plaid_env');
|
this.plaid_env = await frappe.db.get_single_value("Plaid Settings", "plaid_env");
|
||||||
this.token = await this.get_link_token_for_update();
|
this.token = await this.get_link_token_for_update();
|
||||||
this.init_plaid();
|
this.init_plaid();
|
||||||
}
|
}
|
||||||
|
|
||||||
async get_link_token_for_update() {
|
async get_link_token_for_update() {
|
||||||
const token = frappe.xcall(
|
const token = frappe.xcall(
|
||||||
'erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.get_link_token_for_update',
|
"erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.get_link_token_for_update",
|
||||||
{ access_token: this.access_token }
|
{ access_token: this.access_token }
|
||||||
)
|
);
|
||||||
if (!token) {
|
if (!token) {
|
||||||
frappe.throw(__('Cannot retrieve link token for update. Check Error Log for more information'));
|
frappe.throw(__("Cannot retrieve link token for update. Check Error Log for more information"));
|
||||||
}
|
}
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
@@ -90,35 +90,45 @@ erpnext.integrations.refreshPlaidLink = class refreshPlaidLink {
|
|||||||
resolve();
|
resolve();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const el = document.createElement('script');
|
const el = document.createElement("script");
|
||||||
el.type = 'text/javascript';
|
el.type = "text/javascript";
|
||||||
el.async = true;
|
el.async = true;
|
||||||
el.src = src;
|
el.src = src;
|
||||||
el.addEventListener('load', resolve);
|
el.addEventListener("load", resolve);
|
||||||
el.addEventListener('error', reject);
|
el.addEventListener("error", reject);
|
||||||
el.addEventListener('abort', reject);
|
el.addEventListener("abort", reject);
|
||||||
document.head.appendChild(el);
|
document.head.appendChild(el);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onScriptLoaded(me) {
|
onScriptLoaded(me) {
|
||||||
me.linkHandler = Plaid.create({ // eslint-disable-line no-undef
|
me.linkHandler = Plaid.create({
|
||||||
|
// eslint-disable-line no-undef
|
||||||
env: me.plaid_env,
|
env: me.plaid_env,
|
||||||
token: me.token,
|
token: me.token,
|
||||||
onSuccess: me.plaid_success
|
onSuccess: me.plaid_success,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onScriptError(error) {
|
onScriptError(error) {
|
||||||
frappe.msgprint(__("There was an issue connecting to Plaid's authentication server. Check browser console for more information"));
|
frappe.msgprint(
|
||||||
|
__(
|
||||||
|
"There was an issue connecting to Plaid's authentication server. Check browser console for more information"
|
||||||
|
)
|
||||||
|
);
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
plaid_success(token, response) {
|
plaid_success(token, response) {
|
||||||
frappe.xcall('erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.update_bank_account_ids', {
|
frappe
|
||||||
|
.xcall(
|
||||||
|
"erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.update_bank_account_ids",
|
||||||
|
{
|
||||||
response: response,
|
response: response,
|
||||||
}).then(() => {
|
}
|
||||||
frappe.show_alert({ message: __('Plaid Link Updated'), indicator: 'green' });
|
)
|
||||||
|
.then(() => {
|
||||||
|
frappe.show_alert({ message: __("Plaid Link Updated"), indicator: "green" });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -101,7 +101,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-07-17 14:00:13.105433",
|
"modified": "2024-03-27 13:06:36.896195",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Bank",
|
"name": "Bank",
|
||||||
@@ -121,7 +121,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"quick_entry": 1,
|
"quick_entry": 1,
|
||||||
"sort_field": "modified",
|
"sort_field": "creation",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
|
"states": [],
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
|
|
||||||
frappe.ui.form.on('Bank Account', {
|
frappe.ui.form.on("Bank Account", {
|
||||||
setup: function (frm) {
|
setup: function (frm) {
|
||||||
frm.set_query("account", function () {
|
frm.set_query("account", function () {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
'account_type': 'Bank',
|
account_type: "Bank",
|
||||||
'company': frm.doc.company,
|
company: frm.doc.company,
|
||||||
'is_group': 0
|
is_group: 0,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
frm.set_query("party_type", function () {
|
frm.set_query("party_type", function () {
|
||||||
@@ -19,27 +19,31 @@ frappe.ui.form.on('Bank Account', {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
refresh: function (frm) {
|
refresh: function (frm) {
|
||||||
frappe.dynamic_link = { doc: frm.doc, fieldname: 'name', doctype: 'Bank Account' }
|
frappe.dynamic_link = { doc: frm.doc, fieldname: "name", doctype: "Bank Account" };
|
||||||
|
|
||||||
frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal);
|
frm.toggle_display(["address_html", "contact_html"], !frm.doc.__islocal);
|
||||||
|
|
||||||
if (frm.doc.__islocal) {
|
if (frm.doc.__islocal) {
|
||||||
frappe.contacts.clear_address_and_contact(frm);
|
frappe.contacts.clear_address_and_contact(frm);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
frappe.contacts.render_address_and_contact(frm);
|
frappe.contacts.render_address_and_contact(frm);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frm.doc.integration_id) {
|
if (frm.doc.integration_id) {
|
||||||
frm.add_custom_button(__("Unlink external integrations"), function () {
|
frm.add_custom_button(__("Unlink external integrations"), function () {
|
||||||
frappe.confirm(__("This action will unlink this account from any external service integrating ERPNext with your bank accounts. It cannot be undone. Are you certain ?"), function() {
|
frappe.confirm(
|
||||||
|
__(
|
||||||
|
"This action will unlink this account from any external service integrating ERPNext with your bank accounts. It cannot be undone. Are you certain ?"
|
||||||
|
),
|
||||||
|
function () {
|
||||||
frm.set_value("integration_id", "");
|
frm.set_value("integration_id", "");
|
||||||
});
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
is_company_account: function (frm) {
|
is_company_account: function (frm) {
|
||||||
frm.set_df_property('account', 'reqd', frm.doc.is_company_account);
|
frm.set_df_property("account", "reqd", frm.doc.is_company_account);
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -209,7 +209,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-09-22 21:31:34.763977",
|
"modified": "2024-03-27 13:06:37.049542",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Bank Account",
|
"name": "Bank Account",
|
||||||
@@ -242,7 +242,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"search_fields": "bank,account",
|
"search_fields": "bank,account",
|
||||||
"sort_field": "modified",
|
"sort_field": "creation",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"states": [],
|
"states": [],
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ from frappe.contacts.address_and_contact import (
|
|||||||
load_address_and_contact,
|
load_address_and_contact,
|
||||||
)
|
)
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
from frappe.utils import comma_and, get_link_to_form
|
||||||
|
|
||||||
|
|
||||||
class BankAccount(Document):
|
class BankAccount(Document):
|
||||||
@@ -52,10 +53,24 @@ class BankAccount(Document):
|
|||||||
def validate(self):
|
def validate(self):
|
||||||
self.validate_company()
|
self.validate_company()
|
||||||
self.validate_iban()
|
self.validate_iban()
|
||||||
|
self.validate_account()
|
||||||
|
self.update_default_bank_account()
|
||||||
|
|
||||||
|
def validate_account(self):
|
||||||
|
if self.account:
|
||||||
|
if accounts := frappe.db.get_all(
|
||||||
|
"Bank Account", filters={"account": self.account, "name": ["!=", self.name]}, as_list=1
|
||||||
|
):
|
||||||
|
frappe.throw(
|
||||||
|
_("'{0}' account is already used by {1}. Use another account.").format(
|
||||||
|
frappe.bold(self.account),
|
||||||
|
frappe.bold(comma_and([get_link_to_form(self.doctype, x[0]) for x in accounts])),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def validate_company(self):
|
def validate_company(self):
|
||||||
if self.is_company_account and not self.company:
|
if self.is_company_account and not self.company:
|
||||||
frappe.throw(_("Company is manadatory for company account"))
|
frappe.throw(_("Company is mandatory for company account"))
|
||||||
|
|
||||||
def validate_iban(self):
|
def validate_iban(self):
|
||||||
"""
|
"""
|
||||||
@@ -86,19 +101,51 @@ class BankAccount(Document):
|
|||||||
if to_check % 97 != 1:
|
if to_check % 97 != 1:
|
||||||
frappe.throw(_("IBAN is not valid"))
|
frappe.throw(_("IBAN is not valid"))
|
||||||
|
|
||||||
|
def update_default_bank_account(self):
|
||||||
|
if self.is_default and not self.disabled:
|
||||||
|
frappe.db.set_value(
|
||||||
|
"Bank Account",
|
||||||
|
{
|
||||||
|
"party_type": self.party_type,
|
||||||
|
"party": self.party,
|
||||||
|
"is_company_account": self.is_company_account,
|
||||||
|
"is_default": 1,
|
||||||
|
"disabled": 0,
|
||||||
|
},
|
||||||
|
"is_default",
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def make_bank_account(doctype, docname):
|
def make_bank_account(doctype, docname):
|
||||||
doc = frappe.new_doc("Bank Account")
|
doc = frappe.new_doc("Bank Account")
|
||||||
doc.party_type = doctype
|
doc.party_type = doctype
|
||||||
doc.party = docname
|
doc.party = docname
|
||||||
doc.is_default = 1
|
|
||||||
|
|
||||||
return doc
|
return doc
|
||||||
|
|
||||||
|
|
||||||
def get_party_bank_account(party_type, party):
|
def get_party_bank_account(party_type, party):
|
||||||
return frappe.db.get_value(party_type, party, "default_bank_account")
|
return frappe.db.get_value(
|
||||||
|
"Bank Account",
|
||||||
|
{"party_type": party_type, "party": party, "is_default": 1, "disabled": 0},
|
||||||
|
"name",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_default_company_bank_account(company, party_type, party):
|
||||||
|
default_company_bank_account = frappe.db.get_value(party_type, party, "default_bank_account")
|
||||||
|
if default_company_bank_account:
|
||||||
|
if company != frappe.get_cached_value("Bank Account", default_company_bank_account, "company"):
|
||||||
|
default_company_bank_account = None
|
||||||
|
|
||||||
|
if not default_company_bank_account:
|
||||||
|
default_company_bank_account = frappe.db.get_value(
|
||||||
|
"Bank Account", {"company": company, "is_company_account": 1, "is_default": 1}
|
||||||
|
)
|
||||||
|
|
||||||
|
return default_company_bank_account
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
|
|||||||
@@ -37,11 +37,11 @@ class TestBankAccount(unittest.TestCase):
|
|||||||
try:
|
try:
|
||||||
bank_account.validate_iban()
|
bank_account.validate_iban()
|
||||||
except ValidationError:
|
except ValidationError:
|
||||||
msg = "BankAccount.validate_iban() failed for valid IBAN {}".format(iban)
|
msg = f"BankAccount.validate_iban() failed for valid IBAN {iban}"
|
||||||
self.fail(msg=msg)
|
self.fail(msg=msg)
|
||||||
|
|
||||||
for not_iban in invalid_ibans:
|
for not_iban in invalid_ibans:
|
||||||
bank_account.iban = not_iban
|
bank_account.iban = not_iban
|
||||||
msg = "BankAccount.validate_iban() accepted invalid IBAN {}".format(not_iban)
|
msg = f"BankAccount.validate_iban() accepted invalid IBAN {not_iban}"
|
||||||
with self.assertRaises(ValidationError, msg=msg):
|
with self.assertRaises(ValidationError, msg=msg):
|
||||||
bank_account.validate_iban()
|
bank_account.validate_iban()
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
|
|
||||||
frappe.ui.form.on('Bank Account Subtype', {
|
frappe.ui.form.on("Bank Account Subtype", {
|
||||||
refresh: function() {
|
refresh: function () {},
|
||||||
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,134 +1,69 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"actions": [],
|
||||||
"allow_events_in_timeline": 0,
|
|
||||||
"allow_guest_to_view": 0,
|
|
||||||
"allow_import": 1,
|
"allow_import": 1,
|
||||||
"allow_rename": 1,
|
"allow_rename": 1,
|
||||||
"autoname": "field:account_subtype",
|
"autoname": "field:account_subtype",
|
||||||
"beta": 0,
|
|
||||||
"creation": "2018-10-25 15:46:08.054586",
|
"creation": "2018-10-25 15:46:08.054586",
|
||||||
"custom": 0,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "",
|
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"account_subtype"
|
||||||
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "account_subtype",
|
"fieldname": "account_subtype",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Account Subtype",
|
"label": "Account Subtype",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 1
|
"unique": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 0,
|
"links": [],
|
||||||
"hide_heading": 0,
|
"modified": "2024-03-27 13:06:37.221876",
|
||||||
"hide_toolbar": 0,
|
|
||||||
"idx": 0,
|
|
||||||
"image_view": 0,
|
|
||||||
"in_create": 0,
|
|
||||||
"is_submittable": 0,
|
|
||||||
"issingle": 0,
|
|
||||||
"istable": 0,
|
|
||||||
"max_attachments": 0,
|
|
||||||
"modified": "2018-10-25 15:47:03.841390",
|
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Bank Account Subtype",
|
"name": "Bank Account Subtype",
|
||||||
"name_case": "",
|
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 1,
|
"export": 1,
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "System Manager",
|
"role": "System Manager",
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
"write": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 1,
|
"export": 1,
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "Accounts Manager",
|
"role": "Accounts Manager",
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
"write": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 1,
|
"export": 1,
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "Accounts User",
|
"role": "Accounts User",
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"quick_entry": 1,
|
"quick_entry": 1,
|
||||||
"read_only": 0,
|
"sort_field": "creation",
|
||||||
"read_only_onload": 0,
|
|
||||||
"show_name_in_global_search": 0,
|
|
||||||
"sort_field": "modified",
|
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"track_changes": 0,
|
"states": []
|
||||||
"track_seen": 0,
|
|
||||||
"track_views": 0
|
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
|
|
||||||
frappe.ui.form.on('Bank Account Type', {
|
frappe.ui.form.on("Bank Account Type", {
|
||||||
// refresh: function(frm) {
|
// refresh: function(frm) {
|
||||||
|
|
||||||
// }
|
// }
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-04-10 21:13:09.137898",
|
"modified": "2024-03-27 13:06:37.347035",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Bank Account Type",
|
"name": "Bank Account Type",
|
||||||
@@ -63,6 +63,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"quick_entry": 1,
|
"quick_entry": 1,
|
||||||
"sort_field": "modified",
|
"sort_field": "creation",
|
||||||
"sort_order": "DESC"
|
"sort_order": "DESC",
|
||||||
|
"states": []
|
||||||
}
|
}
|
||||||
@@ -7,41 +7,37 @@ frappe.ui.form.on("Bank Clearance", {
|
|||||||
|
|
||||||
frm.set_query("account", function () {
|
frm.set_query("account", function () {
|
||||||
return {
|
return {
|
||||||
"filters": {
|
filters: {
|
||||||
"account_type": ["in",["Bank","Cash"]],
|
account_type: ["in", ["Bank", "Cash"]],
|
||||||
"is_group": 0,
|
is_group: 0,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
frm.set_query("bank_account", function () {
|
frm.set_query("bank_account", function () {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
'is_company_account': 1
|
is_company_account: 1,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
onload: function (frm) {
|
onload: function (frm) {
|
||||||
|
let default_bank_account = frappe.defaults.get_user_default("Company")
|
||||||
let default_bank_account = frappe.defaults.get_user_default("Company")?
|
? locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"]
|
||||||
locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"]: "";
|
: "";
|
||||||
frm.set_value("account", default_bank_account);
|
frm.set_value("account", default_bank_account);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
frm.set_value("from_date", frappe.datetime.month_start());
|
frm.set_value("from_date", frappe.datetime.month_start());
|
||||||
frm.set_value("to_date", frappe.datetime.month_end());
|
frm.set_value("to_date", frappe.datetime.month_end());
|
||||||
},
|
},
|
||||||
|
|
||||||
refresh: function (frm) {
|
refresh: function (frm) {
|
||||||
frm.disable_save();
|
frm.disable_save();
|
||||||
frm.add_custom_button(__('Get Payment Entries'), () =>
|
frm.add_custom_button(__("Get Payment Entries"), () => frm.trigger("get_payment_entries"));
|
||||||
frm.trigger("get_payment_entries")
|
|
||||||
);
|
|
||||||
|
|
||||||
frm.change_custom_button_type(__('Get Payment Entries'), null, 'primary');
|
frm.change_custom_button_type(__("Get Payment Entries"), null, "primary");
|
||||||
},
|
},
|
||||||
|
|
||||||
update_clearance_date: function (frm) {
|
update_clearance_date: function (frm) {
|
||||||
@@ -53,10 +49,10 @@ frappe.ui.form.on("Bank Clearance", {
|
|||||||
frm.refresh_fields();
|
frm.refresh_fields();
|
||||||
|
|
||||||
if (!frm.doc.payment_entries.length) {
|
if (!frm.doc.payment_entries.length) {
|
||||||
frm.change_custom_button_type(__('Get Payment Entries'), null, 'primary');
|
frm.change_custom_button_type(__("Get Payment Entries"), null, "primary");
|
||||||
frm.change_custom_button_type(__('Update Clearance Date'), null, 'default');
|
frm.change_custom_button_type(__("Update Clearance Date"), null, "default");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -68,14 +64,14 @@ frappe.ui.form.on("Bank Clearance", {
|
|||||||
frm.refresh_field("payment_entries");
|
frm.refresh_field("payment_entries");
|
||||||
|
|
||||||
if (frm.doc.payment_entries.length) {
|
if (frm.doc.payment_entries.length) {
|
||||||
frm.add_custom_button(__('Update Clearance Date'), () =>
|
frm.add_custom_button(__("Update Clearance Date"), () =>
|
||||||
frm.trigger("update_clearance_date")
|
frm.trigger("update_clearance_date")
|
||||||
);
|
);
|
||||||
|
|
||||||
frm.change_custom_button_type(__('Get Payment Entries'), null, 'default');
|
frm.change_custom_button_type(__("Get Payment Entries"), null, "default");
|
||||||
frm.change_custom_button_type(__('Update Clearance Date'), null, 'primary');
|
frm.change_custom_button_type(__("Update Clearance Date"), null, "primary");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -91,7 +91,7 @@
|
|||||||
"idx": 1,
|
"idx": 1,
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2022-11-28 17:24:13.008692",
|
"modified": "2024-03-27 13:06:37.477927",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Bank Clearance",
|
"name": "Bank Clearance",
|
||||||
@@ -107,7 +107,7 @@
|
|||||||
],
|
],
|
||||||
"quick_entry": 1,
|
"quick_entry": 1,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"sort_field": "modified",
|
"sort_field": "creation",
|
||||||
"sort_order": "ASC",
|
"sort_order": "ASC",
|
||||||
"states": []
|
"states": []
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,9 @@
|
|||||||
import frappe
|
import frappe
|
||||||
from frappe import _, msgprint
|
from frappe import _, msgprint
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
from frappe.query_builder.custom import ConstantColumn
|
||||||
from frappe.utils import flt, fmt_money, getdate
|
from frappe.utils import flt, fmt_money, getdate
|
||||||
|
from pypika import Order
|
||||||
|
|
||||||
import erpnext
|
import erpnext
|
||||||
|
|
||||||
@@ -125,7 +127,7 @@ def get_payment_entries_for_bank_clearance(
|
|||||||
condition = "and (clearance_date IS NULL or clearance_date='0000-00-00')"
|
condition = "and (clearance_date IS NULL or clearance_date='0000-00-00')"
|
||||||
|
|
||||||
journal_entries = frappe.db.sql(
|
journal_entries = frappe.db.sql(
|
||||||
"""
|
f"""
|
||||||
select
|
select
|
||||||
"Journal Entry" as payment_document, t1.name as payment_entry,
|
"Journal Entry" as payment_document, t1.name as payment_entry,
|
||||||
t1.cheque_no as cheque_number, t1.cheque_date,
|
t1.cheque_no as cheque_number, t1.cheque_date,
|
||||||
@@ -139,9 +141,7 @@ def get_payment_entries_for_bank_clearance(
|
|||||||
and ifnull(t1.is_opening, 'No') = 'No' {condition}
|
and ifnull(t1.is_opening, 'No') = 'No' {condition}
|
||||||
group by t2.account, t1.name
|
group by t2.account, t1.name
|
||||||
order by t1.posting_date ASC, t1.name DESC
|
order by t1.posting_date ASC, t1.name DESC
|
||||||
""".format(
|
""",
|
||||||
condition=condition
|
|
||||||
),
|
|
||||||
{"account": account, "from": from_date, "to": to_date},
|
{"account": account, "from": from_date, "to": to_date},
|
||||||
as_dict=1,
|
as_dict=1,
|
||||||
)
|
)
|
||||||
@@ -150,7 +150,7 @@ def get_payment_entries_for_bank_clearance(
|
|||||||
condition += "and bank_account = %(bank_account)s"
|
condition += "and bank_account = %(bank_account)s"
|
||||||
|
|
||||||
payment_entries = frappe.db.sql(
|
payment_entries = frappe.db.sql(
|
||||||
"""
|
f"""
|
||||||
select
|
select
|
||||||
"Payment Entry" as payment_document, name as payment_entry,
|
"Payment Entry" as payment_document, name as payment_entry,
|
||||||
reference_no as cheque_number, reference_date as cheque_date,
|
reference_no as cheque_number, reference_date as cheque_date,
|
||||||
@@ -165,9 +165,7 @@ def get_payment_entries_for_bank_clearance(
|
|||||||
{condition}
|
{condition}
|
||||||
order by
|
order by
|
||||||
posting_date ASC, name DESC
|
posting_date ASC, name DESC
|
||||||
""".format(
|
""",
|
||||||
condition=condition
|
|
||||||
),
|
|
||||||
{
|
{
|
||||||
"account": account,
|
"account": account,
|
||||||
"from": from_date,
|
"from": from_date,
|
||||||
@@ -179,45 +177,65 @@ def get_payment_entries_for_bank_clearance(
|
|||||||
|
|
||||||
pos_sales_invoices, pos_purchase_invoices = [], []
|
pos_sales_invoices, pos_purchase_invoices = [], []
|
||||||
if include_pos_transactions:
|
if include_pos_transactions:
|
||||||
pos_sales_invoices = frappe.db.sql(
|
si_payment = frappe.qb.DocType("Sales Invoice Payment")
|
||||||
"""
|
si = frappe.qb.DocType("Sales Invoice")
|
||||||
select
|
acc = frappe.qb.DocType("Account")
|
||||||
"Sales Invoice Payment" as payment_document, sip.name as payment_entry, sip.amount as debit,
|
|
||||||
si.posting_date, si.customer as against_account, sip.clearance_date,
|
|
||||||
account.account_currency, 0 as credit
|
|
||||||
from `tabSales Invoice Payment` sip, `tabSales Invoice` si, `tabAccount` account
|
|
||||||
where
|
|
||||||
sip.account=%(account)s and si.docstatus=1 and sip.parent = si.name
|
|
||||||
and account.name = sip.account and si.posting_date >= %(from)s and si.posting_date <= %(to)s
|
|
||||||
order by
|
|
||||||
si.posting_date ASC, si.name DESC
|
|
||||||
""",
|
|
||||||
{"account": account, "from": from_date, "to": to_date},
|
|
||||||
as_dict=1,
|
|
||||||
)
|
|
||||||
|
|
||||||
pos_purchase_invoices = frappe.db.sql(
|
pos_sales_invoices = (
|
||||||
"""
|
frappe.qb.from_(si_payment)
|
||||||
select
|
.inner_join(si)
|
||||||
"Purchase Invoice" as payment_document, pi.name as payment_entry, pi.paid_amount as credit,
|
.on(si_payment.parent == si.name)
|
||||||
pi.posting_date, pi.supplier as against_account, pi.clearance_date,
|
.inner_join(acc)
|
||||||
account.account_currency, 0 as debit
|
.on(si_payment.account == acc.name)
|
||||||
from `tabPurchase Invoice` pi, `tabAccount` account
|
.select(
|
||||||
where
|
ConstantColumn("Sales Invoice").as_("payment_document"),
|
||||||
pi.cash_bank_account=%(account)s and pi.docstatus=1 and account.name = pi.cash_bank_account
|
si.name.as_("payment_entry"),
|
||||||
and pi.posting_date >= %(from)s and pi.posting_date <= %(to)s
|
si_payment.reference_no.as_("cheque_number"),
|
||||||
order by
|
si_payment.amount.as_("debit"),
|
||||||
pi.posting_date ASC, pi.name DESC
|
si.posting_date,
|
||||||
""",
|
si.customer.as_("against_account"),
|
||||||
{"account": account, "from": from_date, "to": to_date},
|
si_payment.clearance_date,
|
||||||
as_dict=1,
|
acc.account_currency,
|
||||||
|
ConstantColumn(0).as_("credit"),
|
||||||
)
|
)
|
||||||
|
.where(
|
||||||
|
(si.docstatus == 1)
|
||||||
|
& (si_payment.account == account)
|
||||||
|
& (si.posting_date >= from_date)
|
||||||
|
& (si.posting_date <= to_date)
|
||||||
|
)
|
||||||
|
.orderby(si.posting_date)
|
||||||
|
.orderby(si.name, order=Order.desc)
|
||||||
|
).run(as_dict=True)
|
||||||
|
|
||||||
|
pi = frappe.qb.DocType("Purchase Invoice")
|
||||||
|
|
||||||
|
pos_purchase_invoices = (
|
||||||
|
frappe.qb.from_(pi)
|
||||||
|
.inner_join(acc)
|
||||||
|
.on(pi.cash_bank_account == acc.name)
|
||||||
|
.select(
|
||||||
|
ConstantColumn("Purchase Invoice").as_("payment_document"),
|
||||||
|
pi.name.as_("payment_entry"),
|
||||||
|
pi.paid_amount.as_("credit"),
|
||||||
|
pi.posting_date,
|
||||||
|
pi.supplier.as_("against_account"),
|
||||||
|
pi.clearance_date,
|
||||||
|
acc.account_currency,
|
||||||
|
ConstantColumn(0).as_("debit"),
|
||||||
|
)
|
||||||
|
.where(
|
||||||
|
(pi.docstatus == 1)
|
||||||
|
& (pi.cash_bank_account == account)
|
||||||
|
& (pi.posting_date >= from_date)
|
||||||
|
& (pi.posting_date <= to_date)
|
||||||
|
)
|
||||||
|
.orderby(pi.posting_date)
|
||||||
|
.orderby(pi.name, order=Order.desc)
|
||||||
|
).run(as_dict=True)
|
||||||
|
|
||||||
entries = (
|
entries = (
|
||||||
list(payment_entries)
|
list(payment_entries) + list(journal_entries) + list(pos_sales_invoices) + list(pos_purchase_invoices)
|
||||||
+ list(journal_entries)
|
|
||||||
+ list(pos_sales_invoices)
|
|
||||||
+ list(pos_purchase_invoices)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return entries
|
return entries
|
||||||
|
|||||||
@@ -68,9 +68,7 @@ class TestBankClearance(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
loan.submit()
|
loan.submit()
|
||||||
make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=getdate())
|
make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=getdate())
|
||||||
repayment_entry = create_repayment_entry(
|
repayment_entry = create_repayment_entry(loan.name, "_Test Customer", getdate(), loan.loan_amount)
|
||||||
loan.name, "_Test Customer", getdate(), loan.loan_amount
|
|
||||||
)
|
|
||||||
repayment_entry.save()
|
repayment_entry.save()
|
||||||
repayment_entry.submit()
|
repayment_entry.submit()
|
||||||
|
|
||||||
|
|||||||
@@ -1,340 +1,112 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"actions": [],
|
||||||
"allow_events_in_timeline": 0,
|
|
||||||
"allow_guest_to_view": 0,
|
|
||||||
"allow_import": 0,
|
|
||||||
"allow_rename": 0,
|
|
||||||
"beta": 0,
|
|
||||||
"creation": "2013-02-22 01:27:37",
|
"creation": "2013-02-22 01:27:37",
|
||||||
"custom": 0,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"payment_document",
|
||||||
|
"payment_entry",
|
||||||
|
"against_account",
|
||||||
|
"amount",
|
||||||
|
"column_break_5",
|
||||||
|
"posting_date",
|
||||||
|
"cheque_number",
|
||||||
|
"cheque_date",
|
||||||
|
"clearance_date"
|
||||||
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "payment_document",
|
"fieldname": "payment_document",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Payment Document",
|
"label": "Payment Document",
|
||||||
"length": 0,
|
"options": "DocType"
|
||||||
"no_copy": 0,
|
|
||||||
"options": "DocType",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 2,
|
"columns": 2,
|
||||||
"fieldname": "payment_entry",
|
"fieldname": "payment_entry",
|
||||||
"fieldtype": "Dynamic Link",
|
"fieldtype": "Dynamic Link",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Payment Entry",
|
"label": "Payment Entry",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"oldfieldname": "voucher_id",
|
"oldfieldname": "voucher_id",
|
||||||
"oldfieldtype": "Link",
|
"oldfieldtype": "Link",
|
||||||
"options": "payment_document",
|
"options": "payment_document",
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0,
|
|
||||||
"width": "50"
|
"width": "50"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 2,
|
"columns": 2,
|
||||||
"fieldname": "against_account",
|
"fieldname": "against_account",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Against Account",
|
"label": "Against Account",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"oldfieldname": "against_account",
|
"oldfieldname": "against_account",
|
||||||
"oldfieldtype": "Data",
|
"oldfieldtype": "Data",
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0,
|
|
||||||
"width": "15"
|
"width": "15"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 2,
|
"columns": 2,
|
||||||
"fieldname": "amount",
|
"fieldname": "amount",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Amount",
|
"label": "Amount",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"oldfieldname": "debit",
|
"oldfieldname": "debit",
|
||||||
"oldfieldtype": "Currency",
|
"oldfieldtype": "Currency",
|
||||||
"options": "",
|
"read_only": 1
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 1,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "column_break_5",
|
"fieldname": "column_break_5",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0,
|
|
||||||
"width": "50%"
|
"width": "50%"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 2,
|
"columns": 2,
|
||||||
"fieldname": "posting_date",
|
"fieldname": "posting_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Posting Date",
|
"label": "Posting Date",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"oldfieldname": "posting_date",
|
"oldfieldname": "posting_date",
|
||||||
"oldfieldtype": "Date",
|
"oldfieldtype": "Date",
|
||||||
"permlevel": 0,
|
"read_only": 1
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 1,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 2,
|
"columns": 2,
|
||||||
"fieldname": "cheque_number",
|
"fieldname": "cheque_number",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Cheque Number",
|
"label": "Cheque Number",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"oldfieldname": "cheque_number",
|
"oldfieldname": "cheque_number",
|
||||||
"oldfieldtype": "Data",
|
"oldfieldtype": "Data",
|
||||||
"permlevel": 0,
|
"read_only": 1
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 1,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "cheque_date",
|
"fieldname": "cheque_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Cheque Date",
|
"label": "Cheque Date",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"oldfieldname": "cheque_date",
|
"oldfieldname": "cheque_date",
|
||||||
"oldfieldtype": "Date",
|
"oldfieldtype": "Date",
|
||||||
"permlevel": 0,
|
"read_only": 1
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 1,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 2,
|
"columns": 2,
|
||||||
"fieldname": "clearance_date",
|
"fieldname": "clearance_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Clearance Date",
|
"label": "Clearance Date",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"oldfieldname": "clearance_date",
|
"oldfieldname": "clearance_date",
|
||||||
"oldfieldtype": "Date",
|
"oldfieldtype": "Date"
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 0,
|
|
||||||
"hide_heading": 0,
|
|
||||||
"hide_toolbar": 0,
|
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"image_view": 0,
|
|
||||||
"in_create": 0,
|
|
||||||
"is_submittable": 0,
|
|
||||||
"issingle": 0,
|
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"links": [],
|
||||||
"menu_index": 0,
|
"modified": "2024-03-27 13:06:37.609319",
|
||||||
"modified": "2019-01-07 16:52:07.174687",
|
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Bank Clearance Detail",
|
"name": "Bank Clearance Detail",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"quick_entry": 1,
|
"quick_entry": 1,
|
||||||
"read_only": 0,
|
"sort_field": "creation",
|
||||||
"read_only_onload": 0,
|
|
||||||
"show_name_in_global_search": 0,
|
|
||||||
"sort_order": "ASC",
|
"sort_order": "ASC",
|
||||||
"track_changes": 0,
|
"states": []
|
||||||
"track_seen": 0,
|
|
||||||
"track_views": 0
|
|
||||||
}
|
}
|
||||||
@@ -1,34 +1,34 @@
|
|||||||
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
|
|
||||||
cur_frm.add_fetch('bank_account','account','account');
|
cur_frm.add_fetch("bank_account", "account", "account");
|
||||||
cur_frm.add_fetch('bank_account','bank_account_no','bank_account_no');
|
cur_frm.add_fetch("bank_account", "bank_account_no", "bank_account_no");
|
||||||
cur_frm.add_fetch('bank_account','iban','iban');
|
cur_frm.add_fetch("bank_account", "iban", "iban");
|
||||||
cur_frm.add_fetch('bank_account','branch_code','branch_code');
|
cur_frm.add_fetch("bank_account", "branch_code", "branch_code");
|
||||||
cur_frm.add_fetch('bank','swift_number','swift_number');
|
cur_frm.add_fetch("bank", "swift_number", "swift_number");
|
||||||
|
|
||||||
frappe.ui.form.on('Bank Guarantee', {
|
frappe.ui.form.on("Bank Guarantee", {
|
||||||
setup: function (frm) {
|
setup: function (frm) {
|
||||||
frm.set_query("bank", function () {
|
frm.set_query("bank", function () {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
company: frm.doc.company
|
company: frm.doc.company,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
frm.set_query("bank_account", function () {
|
frm.set_query("bank_account", function () {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
company: frm.doc.company,
|
company: frm.doc.company,
|
||||||
bank: frm.doc.bank
|
bank: frm.doc.bank,
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
});
|
});
|
||||||
frm.set_query("project", function () {
|
frm.set_query("project", function () {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
customer: frm.doc.customer
|
customer: frm.doc.customer,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -48,8 +48,8 @@ frappe.ui.form.on('Bank Guarantee', {
|
|||||||
frappe.call({
|
frappe.call({
|
||||||
method: "erpnext.accounts.doctype.bank_guarantee.bank_guarantee.get_voucher_details",
|
method: "erpnext.accounts.doctype.bank_guarantee.bank_guarantee.get_voucher_details",
|
||||||
args: {
|
args: {
|
||||||
"bank_guarantee_type": frm.doc.bg_type,
|
bank_guarantee_type: frm.doc.bg_type,
|
||||||
"reference_name": frm.doc.reference_docname
|
reference_name: frm.doc.reference_docname,
|
||||||
},
|
},
|
||||||
callback: function (r) {
|
callback: function (r) {
|
||||||
if (r.message) {
|
if (r.message) {
|
||||||
@@ -57,9 +57,8 @@ frappe.ui.form.on('Bank Guarantee', {
|
|||||||
if (r.message.project) frm.set_value("project", r.message.project);
|
if (r.message.project) frm.set_value("project", r.message.project);
|
||||||
if (r.message.grand_total) frm.set_value("amount", r.message.grand_total);
|
if (r.message.grand_total) frm.set_value("amount", r.message.grand_total);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -70,5 +69,5 @@ frappe.ui.form.on('Bank Guarantee', {
|
|||||||
validity: function (frm) {
|
validity: function (frm) {
|
||||||
var end_date = frappe.datetime.add_days(cur_frm.doc.start_date, cur_frm.doc.validity - 1);
|
var end_date = frappe.datetime.add_days(cur_frm.doc.start_date, cur_frm.doc.validity - 1);
|
||||||
cur_frm.set_value("end_date", end_date);
|
cur_frm.set_value("end_date", end_date);
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -48,11 +48,11 @@ class BankGuarantee(Document):
|
|||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
if not self.bank_guarantee_number:
|
if not self.bank_guarantee_number:
|
||||||
frappe.throw(_("Enter the Bank Guarantee Number before submittting."))
|
frappe.throw(_("Enter the Bank Guarantee Number before submitting."))
|
||||||
if not self.name_of_beneficiary:
|
if not self.name_of_beneficiary:
|
||||||
frappe.throw(_("Enter the name of the Beneficiary before submittting."))
|
frappe.throw(_("Enter the name of the Beneficiary before submitting."))
|
||||||
if not self.bank:
|
if not self.bank:
|
||||||
frappe.throw(_("Enter the name of the bank or lending institution before submittting."))
|
frappe.throw(_("Enter the name of the bank or lending institution before submitting."))
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
|
|||||||
@@ -8,21 +8,22 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
|
|||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
company: frm.doc.company,
|
company: frm.doc.company,
|
||||||
'is_company_account': 1
|
is_company_account: 1,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
let no_bank_transactions_text =
|
let no_bank_transactions_text = `<div class="text-muted text-center">${__(
|
||||||
`<div class="text-muted text-center">${__("No Matching Bank Transactions Found")}</div>`
|
"No Matching Bank Transactions Found"
|
||||||
|
)}</div>`;
|
||||||
set_field_options("no_bank_transactions", no_bank_transactions_text);
|
set_field_options("no_bank_transactions", no_bank_transactions_text);
|
||||||
},
|
},
|
||||||
|
|
||||||
onload: function (frm) {
|
onload: function (frm) {
|
||||||
// Set default filter dates
|
// Set default filter dates
|
||||||
let today = frappe.datetime.get_today()
|
let today = frappe.datetime.get_today();
|
||||||
frm.doc.bank_statement_from_date = frappe.datetime.add_months(today, -1);
|
frm.doc.bank_statement_from_date = frappe.datetime.add_months(today, -1);
|
||||||
frm.doc.bank_statement_to_date = today;
|
frm.doc.bank_statement_to_date = today;
|
||||||
frm.trigger('bank_account');
|
frm.trigger("bank_account");
|
||||||
},
|
},
|
||||||
|
|
||||||
filter_by_reference_date: function (frm) {
|
filter_by_reference_date: function (frm) {
|
||||||
@@ -37,14 +38,11 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
|
|||||||
|
|
||||||
refresh: function (frm) {
|
refresh: function (frm) {
|
||||||
frm.disable_save();
|
frm.disable_save();
|
||||||
frappe.require("bank-reconciliation-tool.bundle.js", () =>
|
frappe.require("bank-reconciliation-tool.bundle.js", () => frm.trigger("make_reconciliation_tool"));
|
||||||
frm.trigger("make_reconciliation_tool")
|
|
||||||
);
|
|
||||||
|
|
||||||
frm.add_custom_button(__("Upload Bank Statement"), () =>
|
frm.add_custom_button(__("Upload Bank Statement"), () =>
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method:
|
method: "erpnext.accounts.doctype.bank_statement_import.bank_statement_import.upload_bank_statement",
|
||||||
"erpnext.accounts.doctype.bank_statement_import.bank_statement_import.upload_bank_statement",
|
|
||||||
args: {
|
args: {
|
||||||
dt: frm.doc.doctype,
|
dt: frm.doc.doctype,
|
||||||
dn: frm.doc.name,
|
dn: frm.doc.name,
|
||||||
@@ -54,17 +52,13 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
|
|||||||
callback: function (r) {
|
callback: function (r) {
|
||||||
if (!r.exc) {
|
if (!r.exc) {
|
||||||
var doc = frappe.model.sync(r.message);
|
var doc = frappe.model.sync(r.message);
|
||||||
frappe.set_route(
|
frappe.set_route("Form", doc[0].doctype, doc[0].name);
|
||||||
"Form",
|
|
||||||
doc[0].doctype,
|
|
||||||
doc[0].name
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
frm.add_custom_button(__('Auto Reconcile'), function() {
|
frm.add_custom_button(__("Auto Reconcile"), function () {
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: "erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.auto_reconcile_vouchers",
|
method: "erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.auto_reconcile_vouchers",
|
||||||
args: {
|
args: {
|
||||||
@@ -75,33 +69,22 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
|
|||||||
from_reference_date: frm.doc.from_reference_date,
|
from_reference_date: frm.doc.from_reference_date,
|
||||||
to_reference_date: frm.doc.to_reference_date,
|
to_reference_date: frm.doc.to_reference_date,
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
frm.add_custom_button(__('Get Unreconciled Entries'), function() {
|
frm.add_custom_button(__("Get Unreconciled Entries"), function () {
|
||||||
frm.trigger("make_reconciliation_tool");
|
frm.trigger("make_reconciliation_tool");
|
||||||
});
|
});
|
||||||
frm.change_custom_button_type(__('Get Unreconciled Entries'), null, 'primary');
|
frm.change_custom_button_type(__("Get Unreconciled Entries"), null, "primary");
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
bank_account: function (frm) {
|
bank_account: function (frm) {
|
||||||
frappe.db.get_value(
|
frappe.db.get_value("Bank Account", frm.doc.bank_account, "account", (r) => {
|
||||||
"Bank Account",
|
frappe.db.get_value("Account", r.account, "account_currency", (r) => {
|
||||||
frm.doc.bank_account,
|
|
||||||
"account",
|
|
||||||
(r) => {
|
|
||||||
frappe.db.get_value(
|
|
||||||
"Account",
|
|
||||||
r.account,
|
|
||||||
"account_currency",
|
|
||||||
(r) => {
|
|
||||||
frm.doc.account_currency = r.account_currency;
|
frm.doc.account_currency = r.account_currency;
|
||||||
frm.trigger("render_chart");
|
frm.trigger("render_chart");
|
||||||
}
|
});
|
||||||
);
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
frm.trigger("get_account_opening_balance");
|
frm.trigger("get_account_opening_balance");
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -120,11 +103,7 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
|
|||||||
) {
|
) {
|
||||||
frm.trigger("render_chart");
|
frm.trigger("render_chart");
|
||||||
frm.trigger("render");
|
frm.trigger("render");
|
||||||
frappe.utils.scroll_to(
|
frappe.utils.scroll_to(frm.get_field("reconciliation_tool_cards").$wrapper, true, 30);
|
||||||
frm.get_field("reconciliation_tool_cards").$wrapper,
|
|
||||||
true,
|
|
||||||
30
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -133,11 +112,10 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
|
|||||||
get_account_opening_balance(frm) {
|
get_account_opening_balance(frm) {
|
||||||
if (frm.doc.bank_account && frm.doc.bank_statement_from_date) {
|
if (frm.doc.bank_account && frm.doc.bank_statement_from_date) {
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method:
|
method: "erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.get_account_balance",
|
||||||
"erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.get_account_balance",
|
|
||||||
args: {
|
args: {
|
||||||
bank_account: frm.doc.bank_account,
|
bank_account: frm.doc.bank_account,
|
||||||
till_date: frappe.datetime.add_days(frm.doc.bank_statement_from_date, -1)
|
till_date: frappe.datetime.add_days(frm.doc.bank_statement_from_date, -1),
|
||||||
},
|
},
|
||||||
callback: (response) => {
|
callback: (response) => {
|
||||||
frm.set_value("account_opening_balance", response.message);
|
frm.set_value("account_opening_balance", response.message);
|
||||||
@@ -149,8 +127,7 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
|
|||||||
get_cleared_balance(frm) {
|
get_cleared_balance(frm) {
|
||||||
if (frm.doc.bank_account && frm.doc.bank_statement_to_date) {
|
if (frm.doc.bank_account && frm.doc.bank_statement_to_date) {
|
||||||
return frappe.call({
|
return frappe.call({
|
||||||
method:
|
method: "erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.get_account_balance",
|
||||||
"erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.get_account_balance",
|
|
||||||
args: {
|
args: {
|
||||||
bank_account: frm.doc.bank_account,
|
bank_account: frm.doc.bank_account,
|
||||||
till_date: frm.doc.bank_statement_to_date,
|
till_date: frm.doc.bank_statement_to_date,
|
||||||
@@ -163,41 +140,30 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
|
|||||||
},
|
},
|
||||||
|
|
||||||
render_chart(frm) {
|
render_chart(frm) {
|
||||||
frm.cards_manager = new erpnext.accounts.bank_reconciliation.NumberCardManager(
|
frm.cards_manager = new erpnext.accounts.bank_reconciliation.NumberCardManager({
|
||||||
{
|
$reconciliation_tool_cards: frm.get_field("reconciliation_tool_cards").$wrapper,
|
||||||
$reconciliation_tool_cards: frm.get_field(
|
bank_statement_closing_balance: frm.doc.bank_statement_closing_balance,
|
||||||
"reconciliation_tool_cards"
|
|
||||||
).$wrapper,
|
|
||||||
bank_statement_closing_balance:
|
|
||||||
frm.doc.bank_statement_closing_balance,
|
|
||||||
cleared_balance: frm.cleared_balance,
|
cleared_balance: frm.cleared_balance,
|
||||||
currency: frm.doc.account_currency,
|
currency: frm.doc.account_currency,
|
||||||
}
|
});
|
||||||
);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
render(frm) {
|
render(frm) {
|
||||||
if (frm.doc.bank_account) {
|
if (frm.doc.bank_account) {
|
||||||
frm.bank_reconciliation_data_table_manager = new erpnext.accounts.bank_reconciliation.DataTableManager(
|
frm.bank_reconciliation_data_table_manager =
|
||||||
{
|
new erpnext.accounts.bank_reconciliation.DataTableManager({
|
||||||
company: frm.doc.company,
|
company: frm.doc.company,
|
||||||
bank_account: frm.doc.bank_account,
|
bank_account: frm.doc.bank_account,
|
||||||
$reconciliation_tool_dt: frm.get_field(
|
$reconciliation_tool_dt: frm.get_field("reconciliation_tool_dt").$wrapper,
|
||||||
"reconciliation_tool_dt"
|
$no_bank_transactions: frm.get_field("no_bank_transactions").$wrapper,
|
||||||
).$wrapper,
|
|
||||||
$no_bank_transactions: frm.get_field(
|
|
||||||
"no_bank_transactions"
|
|
||||||
).$wrapper,
|
|
||||||
bank_statement_from_date: frm.doc.bank_statement_from_date,
|
bank_statement_from_date: frm.doc.bank_statement_from_date,
|
||||||
bank_statement_to_date: frm.doc.bank_statement_to_date,
|
bank_statement_to_date: frm.doc.bank_statement_to_date,
|
||||||
filter_by_reference_date: frm.doc.filter_by_reference_date,
|
filter_by_reference_date: frm.doc.filter_by_reference_date,
|
||||||
from_reference_date: frm.doc.from_reference_date,
|
from_reference_date: frm.doc.from_reference_date,
|
||||||
to_reference_date: frm.doc.to_reference_date,
|
to_reference_date: frm.doc.to_reference_date,
|
||||||
bank_statement_closing_balance:
|
bank_statement_closing_balance: frm.doc.bank_statement_closing_balance,
|
||||||
frm.doc.bank_statement_closing_balance,
|
|
||||||
cards_manager: frm.cards_manager,
|
cards_manager: frm.cards_manager,
|
||||||
}
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "company",
|
"fieldname": "company",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
|
"ignore_user_permissions": 1,
|
||||||
"label": "Company",
|
"label": "Company",
|
||||||
"options": "Company"
|
"options": "Company"
|
||||||
},
|
},
|
||||||
@@ -118,7 +119,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-03-07 11:02:24.535714",
|
"modified": "2024-04-28 14:40:50.910884",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Bank Reconciliation Tool",
|
"name": "Bank Reconciliation Tool",
|
||||||
@@ -136,7 +137,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"quick_entry": 1,
|
"quick_entry": 1,
|
||||||
"sort_field": "modified",
|
"sort_field": "creation",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"states": []
|
"states": []
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,6 @@ from frappe import _
|
|||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from frappe.query_builder.custom import ConstantColumn
|
from frappe.query_builder.custom import ConstantColumn
|
||||||
from frappe.utils import cint, flt
|
from frappe.utils import cint, flt
|
||||||
from pypika.terms import Parameter
|
|
||||||
|
|
||||||
from erpnext import get_default_cost_center
|
from erpnext import get_default_cost_center
|
||||||
from erpnext.accounts.doctype.bank_transaction.bank_transaction import get_total_allocated_amount
|
from erpnext.accounts.doctype.bank_transaction.bank_transaction import get_total_allocated_amount
|
||||||
@@ -82,9 +81,7 @@ def get_bank_transactions(bank_account, from_date=None, to_date=None):
|
|||||||
def get_account_balance(bank_account, till_date):
|
def get_account_balance(bank_account, till_date):
|
||||||
# returns account balance till the specified date
|
# returns account balance till the specified date
|
||||||
account = frappe.db.get_value("Bank Account", bank_account, "account")
|
account = frappe.db.get_value("Bank Account", bank_account, "account")
|
||||||
filters = frappe._dict(
|
filters = frappe._dict({"account": account, "report_date": till_date, "include_pos_transactions": 1})
|
||||||
{"account": account, "report_date": till_date, "include_pos_transactions": 1}
|
|
||||||
)
|
|
||||||
data = get_entries(filters)
|
data = get_entries(filters)
|
||||||
|
|
||||||
balance_as_per_system = get_balance_on(filters["account"], filters["report_date"])
|
balance_as_per_system = get_balance_on(filters["account"], filters["report_date"])
|
||||||
@@ -97,10 +94,7 @@ def get_account_balance(bank_account, till_date):
|
|||||||
amounts_not_reflected_in_system = get_amounts_not_reflected_in_system(filters)
|
amounts_not_reflected_in_system = get_amounts_not_reflected_in_system(filters)
|
||||||
|
|
||||||
bank_bal = (
|
bank_bal = (
|
||||||
flt(balance_as_per_system)
|
flt(balance_as_per_system) - flt(total_debit) + flt(total_credit) + amounts_not_reflected_in_system
|
||||||
- flt(total_debit)
|
|
||||||
+ flt(total_credit)
|
|
||||||
+ amounts_not_reflected_in_system
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return bank_bal
|
return bank_bal
|
||||||
@@ -509,6 +503,18 @@ def check_matching(
|
|||||||
to_reference_date,
|
to_reference_date,
|
||||||
):
|
):
|
||||||
exact_match = True if "exact_match" in document_types else False
|
exact_match = True if "exact_match" in document_types else False
|
||||||
|
|
||||||
|
common_filters = frappe._dict(
|
||||||
|
{
|
||||||
|
"amount": transaction.unallocated_amount,
|
||||||
|
"payment_type": "Receive" if transaction.deposit > 0.0 else "Pay",
|
||||||
|
"reference_no": transaction.reference_number,
|
||||||
|
"party_type": transaction.party_type,
|
||||||
|
"party": transaction.party,
|
||||||
|
"bank_account": bank_account,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
queries = get_queries(
|
queries = get_queries(
|
||||||
bank_account,
|
bank_account,
|
||||||
company,
|
company,
|
||||||
@@ -520,24 +526,14 @@ def check_matching(
|
|||||||
from_reference_date,
|
from_reference_date,
|
||||||
to_reference_date,
|
to_reference_date,
|
||||||
exact_match,
|
exact_match,
|
||||||
|
common_filters,
|
||||||
)
|
)
|
||||||
|
|
||||||
filters = {
|
|
||||||
"amount": transaction.unallocated_amount,
|
|
||||||
"payment_type": "Receive" if transaction.deposit > 0.0 else "Pay",
|
|
||||||
"reference_no": transaction.reference_number,
|
|
||||||
"party_type": transaction.party_type,
|
|
||||||
"party": transaction.party,
|
|
||||||
"bank_account": bank_account,
|
|
||||||
}
|
|
||||||
|
|
||||||
matching_vouchers = []
|
matching_vouchers = []
|
||||||
for query in queries:
|
for query in queries:
|
||||||
matching_vouchers.extend(frappe.db.sql(query, filters, as_dict=True))
|
matching_vouchers.extend(query.run(as_dict=True))
|
||||||
|
|
||||||
return (
|
return sorted(matching_vouchers, key=lambda x: x["rank"], reverse=True) if matching_vouchers else []
|
||||||
sorted(matching_vouchers, key=lambda x: x["rank"], reverse=True) if matching_vouchers else []
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def get_queries(
|
def get_queries(
|
||||||
@@ -551,6 +547,7 @@ def get_queries(
|
|||||||
from_reference_date,
|
from_reference_date,
|
||||||
to_reference_date,
|
to_reference_date,
|
||||||
exact_match,
|
exact_match,
|
||||||
|
common_filters,
|
||||||
):
|
):
|
||||||
# get queries to get matching vouchers
|
# get queries to get matching vouchers
|
||||||
account_from_to = "paid_to" if transaction.deposit > 0.0 else "paid_from"
|
account_from_to = "paid_to" if transaction.deposit > 0.0 else "paid_from"
|
||||||
@@ -571,6 +568,7 @@ def get_queries(
|
|||||||
filter_by_reference_date,
|
filter_by_reference_date,
|
||||||
from_reference_date,
|
from_reference_date,
|
||||||
to_reference_date,
|
to_reference_date,
|
||||||
|
common_filters,
|
||||||
)
|
)
|
||||||
or []
|
or []
|
||||||
)
|
)
|
||||||
@@ -590,6 +588,7 @@ def get_matching_queries(
|
|||||||
filter_by_reference_date,
|
filter_by_reference_date,
|
||||||
from_reference_date,
|
from_reference_date,
|
||||||
to_reference_date,
|
to_reference_date,
|
||||||
|
common_filters,
|
||||||
):
|
):
|
||||||
queries = []
|
queries = []
|
||||||
currency = get_account_currency(bank_account)
|
currency = get_account_currency(bank_account)
|
||||||
@@ -604,6 +603,7 @@ def get_matching_queries(
|
|||||||
filter_by_reference_date,
|
filter_by_reference_date,
|
||||||
from_reference_date,
|
from_reference_date,
|
||||||
to_reference_date,
|
to_reference_date,
|
||||||
|
common_filters,
|
||||||
)
|
)
|
||||||
queries.append(query)
|
queries.append(query)
|
||||||
|
|
||||||
@@ -616,16 +616,17 @@ def get_matching_queries(
|
|||||||
filter_by_reference_date,
|
filter_by_reference_date,
|
||||||
from_reference_date,
|
from_reference_date,
|
||||||
to_reference_date,
|
to_reference_date,
|
||||||
|
common_filters,
|
||||||
)
|
)
|
||||||
queries.append(query)
|
queries.append(query)
|
||||||
|
|
||||||
if transaction.deposit > 0.0 and "sales_invoice" in document_types:
|
if transaction.deposit > 0.0 and "sales_invoice" in document_types:
|
||||||
query = get_si_matching_query(exact_match, currency)
|
query = get_si_matching_query(exact_match, currency, common_filters)
|
||||||
queries.append(query)
|
queries.append(query)
|
||||||
|
|
||||||
if transaction.withdrawal > 0.0:
|
if transaction.withdrawal > 0.0:
|
||||||
if "purchase_invoice" in document_types:
|
if "purchase_invoice" in document_types:
|
||||||
query = get_pi_matching_query(exact_match, currency)
|
query = get_pi_matching_query(exact_match, currency, common_filters)
|
||||||
queries.append(query)
|
queries.append(query)
|
||||||
|
|
||||||
if "bank_transaction" in document_types:
|
if "bank_transaction" in document_types:
|
||||||
@@ -646,17 +647,13 @@ def get_bt_matching_query(exact_match, transaction):
|
|||||||
amount_rank = frappe.qb.terms.Case().when(amount_equality, 1).else_(0)
|
amount_rank = frappe.qb.terms.Case().when(amount_equality, 1).else_(0)
|
||||||
amount_condition = amount_equality if exact_match else getattr(bt, field) > 0.0
|
amount_condition = amount_equality if exact_match else getattr(bt, field) > 0.0
|
||||||
|
|
||||||
ref_rank = (
|
ref_rank = frappe.qb.terms.Case().when(bt.reference_number == transaction.reference_number, 1).else_(0)
|
||||||
frappe.qb.terms.Case().when(bt.reference_number == transaction.reference_number, 1).else_(0)
|
|
||||||
)
|
|
||||||
unallocated_rank = (
|
unallocated_rank = (
|
||||||
frappe.qb.terms.Case().when(bt.unallocated_amount == transaction.unallocated_amount, 1).else_(0)
|
frappe.qb.terms.Case().when(bt.unallocated_amount == transaction.unallocated_amount, 1).else_(0)
|
||||||
)
|
)
|
||||||
|
|
||||||
party_condition = (
|
party_condition = (
|
||||||
(bt.party_type == transaction.party_type)
|
(bt.party_type == transaction.party_type) & (bt.party == transaction.party) & bt.party.isnotnull()
|
||||||
& (bt.party == transaction.party)
|
|
||||||
& bt.party.isnotnull()
|
|
||||||
)
|
)
|
||||||
party_rank = frappe.qb.terms.Case().when(party_condition, 1).else_(0)
|
party_rank = frappe.qb.terms.Case().when(party_condition, 1).else_(0)
|
||||||
|
|
||||||
@@ -680,7 +677,7 @@ def get_bt_matching_query(exact_match, transaction):
|
|||||||
.where(amount_condition)
|
.where(amount_condition)
|
||||||
.where(bt.docstatus == 1)
|
.where(bt.docstatus == 1)
|
||||||
)
|
)
|
||||||
return str(query)
|
return query
|
||||||
|
|
||||||
|
|
||||||
def get_pe_matching_query(
|
def get_pe_matching_query(
|
||||||
@@ -692,6 +689,7 @@ def get_pe_matching_query(
|
|||||||
filter_by_reference_date,
|
filter_by_reference_date,
|
||||||
from_reference_date,
|
from_reference_date,
|
||||||
to_reference_date,
|
to_reference_date,
|
||||||
|
common_filters,
|
||||||
):
|
):
|
||||||
# get matching payment entries query
|
# get matching payment entries query
|
||||||
to_from = "to" if transaction.deposit > 0.0 else "from"
|
to_from = "to" if transaction.deposit > 0.0 else "from"
|
||||||
@@ -707,9 +705,7 @@ def get_pe_matching_query(
|
|||||||
amount_condition = amount_equality if exact_match else pe.paid_amount > 0.0
|
amount_condition = amount_equality if exact_match else pe.paid_amount > 0.0
|
||||||
|
|
||||||
party_condition = (
|
party_condition = (
|
||||||
(pe.party_type == transaction.party_type)
|
(pe.party_type == transaction.party_type) & (pe.party == transaction.party) & pe.party.isnotnull()
|
||||||
& (pe.party == transaction.party)
|
|
||||||
& pe.party.isnotnull()
|
|
||||||
)
|
)
|
||||||
party_rank = frappe.qb.terms.Case().when(party_condition, 1).else_(0)
|
party_rank = frappe.qb.terms.Case().when(party_condition, 1).else_(0)
|
||||||
|
|
||||||
@@ -723,7 +719,7 @@ def get_pe_matching_query(
|
|||||||
(ref_rank + amount_rank + party_rank + 1).as_("rank"),
|
(ref_rank + amount_rank + party_rank + 1).as_("rank"),
|
||||||
ConstantColumn("Payment Entry").as_("doctype"),
|
ConstantColumn("Payment Entry").as_("doctype"),
|
||||||
pe.name,
|
pe.name,
|
||||||
pe.paid_amount,
|
pe.paid_amount_after_tax.as_("paid_amount"),
|
||||||
pe.reference_no,
|
pe.reference_no,
|
||||||
pe.reference_date,
|
pe.reference_date,
|
||||||
pe.party,
|
pe.party,
|
||||||
@@ -734,16 +730,16 @@ def get_pe_matching_query(
|
|||||||
.where(pe.docstatus == 1)
|
.where(pe.docstatus == 1)
|
||||||
.where(pe.payment_type.isin([payment_type, "Internal Transfer"]))
|
.where(pe.payment_type.isin([payment_type, "Internal Transfer"]))
|
||||||
.where(pe.clearance_date.isnull())
|
.where(pe.clearance_date.isnull())
|
||||||
.where(getattr(pe, account_from_to) == Parameter("%(bank_account)s"))
|
.where(getattr(pe, account_from_to) == common_filters.bank_account)
|
||||||
.where(amount_condition)
|
.where(amount_condition)
|
||||||
.where(filter_by_date)
|
.where(filter_by_date)
|
||||||
.orderby(pe.reference_date if cint(filter_by_reference_date) else pe.posting_date)
|
.orderby(pe.reference_date if cint(filter_by_reference_date) else pe.posting_date)
|
||||||
)
|
)
|
||||||
|
|
||||||
if frappe.flags.auto_reconcile_vouchers == True:
|
if frappe.flags.auto_reconcile_vouchers is True:
|
||||||
query = query.where(ref_condition)
|
query = query.where(ref_condition)
|
||||||
|
|
||||||
return str(query)
|
return query
|
||||||
|
|
||||||
|
|
||||||
def get_je_matching_query(
|
def get_je_matching_query(
|
||||||
@@ -754,6 +750,7 @@ def get_je_matching_query(
|
|||||||
filter_by_reference_date,
|
filter_by_reference_date,
|
||||||
from_reference_date,
|
from_reference_date,
|
||||||
to_reference_date,
|
to_reference_date,
|
||||||
|
common_filters,
|
||||||
):
|
):
|
||||||
# get matching journal entry query
|
# get matching journal entry query
|
||||||
# We have mapping at the bank level
|
# We have mapping at the bank level
|
||||||
@@ -793,29 +790,29 @@ def get_je_matching_query(
|
|||||||
.where(je.docstatus == 1)
|
.where(je.docstatus == 1)
|
||||||
.where(je.voucher_type != "Opening Entry")
|
.where(je.voucher_type != "Opening Entry")
|
||||||
.where(je.clearance_date.isnull())
|
.where(je.clearance_date.isnull())
|
||||||
.where(jea.account == Parameter("%(bank_account)s"))
|
.where(jea.account == common_filters.bank_account)
|
||||||
.where(amount_equality if exact_match else getattr(jea, amount_field) > 0.0)
|
.where(amount_equality if exact_match else getattr(jea, amount_field) > 0.0)
|
||||||
.where(je.docstatus == 1)
|
.where(je.docstatus == 1)
|
||||||
.where(filter_by_date)
|
.where(filter_by_date)
|
||||||
.orderby(je.cheque_date if cint(filter_by_reference_date) else je.posting_date)
|
.orderby(je.cheque_date if cint(filter_by_reference_date) else je.posting_date)
|
||||||
)
|
)
|
||||||
|
|
||||||
if frappe.flags.auto_reconcile_vouchers == True:
|
if frappe.flags.auto_reconcile_vouchers is True:
|
||||||
query = query.where(ref_condition)
|
query = query.where(ref_condition)
|
||||||
|
|
||||||
return str(query)
|
return query
|
||||||
|
|
||||||
|
|
||||||
def get_si_matching_query(exact_match, currency):
|
def get_si_matching_query(exact_match, currency, common_filters):
|
||||||
# get matching sales invoice query
|
# get matching sales invoice query
|
||||||
si = frappe.qb.DocType("Sales Invoice")
|
si = frappe.qb.DocType("Sales Invoice")
|
||||||
sip = frappe.qb.DocType("Sales Invoice Payment")
|
sip = frappe.qb.DocType("Sales Invoice Payment")
|
||||||
|
|
||||||
amount_equality = sip.amount == Parameter("%(amount)s")
|
amount_equality = sip.amount == common_filters.amount
|
||||||
amount_rank = frappe.qb.terms.Case().when(amount_equality, 1).else_(0)
|
amount_rank = frappe.qb.terms.Case().when(amount_equality, 1).else_(0)
|
||||||
amount_condition = amount_equality if exact_match else sip.amount > 0.0
|
amount_condition = amount_equality if exact_match else sip.amount > 0.0
|
||||||
|
|
||||||
party_condition = si.customer == Parameter("%(party)s")
|
party_condition = si.customer == common_filters.party
|
||||||
party_rank = frappe.qb.terms.Case().when(party_condition, 1).else_(0)
|
party_rank = frappe.qb.terms.Case().when(party_condition, 1).else_(0)
|
||||||
|
|
||||||
query = (
|
query = (
|
||||||
@@ -836,23 +833,23 @@ def get_si_matching_query(exact_match, currency):
|
|||||||
)
|
)
|
||||||
.where(si.docstatus == 1)
|
.where(si.docstatus == 1)
|
||||||
.where(sip.clearance_date.isnull())
|
.where(sip.clearance_date.isnull())
|
||||||
.where(sip.account == Parameter("%(bank_account)s"))
|
.where(sip.account == common_filters.bank_account)
|
||||||
.where(amount_condition)
|
.where(amount_condition)
|
||||||
.where(si.currency == currency)
|
.where(si.currency == currency)
|
||||||
)
|
)
|
||||||
|
|
||||||
return str(query)
|
return query
|
||||||
|
|
||||||
|
|
||||||
def get_pi_matching_query(exact_match, currency):
|
def get_pi_matching_query(exact_match, currency, common_filters):
|
||||||
# get matching purchase invoice query when they are also used as payment entries (is_paid)
|
# get matching purchase invoice query when they are also used as payment entries (is_paid)
|
||||||
purchase_invoice = frappe.qb.DocType("Purchase Invoice")
|
purchase_invoice = frappe.qb.DocType("Purchase Invoice")
|
||||||
|
|
||||||
amount_equality = purchase_invoice.paid_amount == Parameter("%(amount)s")
|
amount_equality = purchase_invoice.paid_amount == common_filters.amount
|
||||||
amount_rank = frappe.qb.terms.Case().when(amount_equality, 1).else_(0)
|
amount_rank = frappe.qb.terms.Case().when(amount_equality, 1).else_(0)
|
||||||
amount_condition = amount_equality if exact_match else purchase_invoice.paid_amount > 0.0
|
amount_condition = amount_equality if exact_match else purchase_invoice.paid_amount > 0.0
|
||||||
|
|
||||||
party_condition = purchase_invoice.supplier == Parameter("%(party)s")
|
party_condition = purchase_invoice.supplier == common_filters.party
|
||||||
party_rank = frappe.qb.terms.Case().when(party_condition, 1).else_(0)
|
party_rank = frappe.qb.terms.Case().when(party_condition, 1).else_(0)
|
||||||
|
|
||||||
query = (
|
query = (
|
||||||
@@ -872,9 +869,9 @@ def get_pi_matching_query(exact_match, currency):
|
|||||||
.where(purchase_invoice.docstatus == 1)
|
.where(purchase_invoice.docstatus == 1)
|
||||||
.where(purchase_invoice.is_paid == 1)
|
.where(purchase_invoice.is_paid == 1)
|
||||||
.where(purchase_invoice.clearance_date.isnull())
|
.where(purchase_invoice.clearance_date.isnull())
|
||||||
.where(purchase_invoice.cash_bank_account == Parameter("%(bank_account)s"))
|
.where(purchase_invoice.cash_bank_account == common_filters.bank_account)
|
||||||
.where(amount_condition)
|
.where(amount_condition)
|
||||||
.where(purchase_invoice.currency == currency)
|
.where(purchase_invoice.currency == currency)
|
||||||
)
|
)
|
||||||
|
|
||||||
return str(query)
|
return query
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
|
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
# See license.txt
|
# See license.txt
|
||||||
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import qb
|
from frappe import qb
|
||||||
from frappe.tests.utils import FrappeTestCase, change_settings
|
from frappe.tests.utils import FrappeTestCase
|
||||||
from frappe.utils import add_days, flt, getdate, today
|
from frappe.utils import add_days, today
|
||||||
|
|
||||||
from erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool import (
|
from erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool import (
|
||||||
auto_reconcile_vouchers,
|
auto_reconcile_vouchers,
|
||||||
@@ -22,7 +21,7 @@ class TestBankReconciliationTool(AccountsTestMixin, FrappeTestCase):
|
|||||||
self.create_customer()
|
self.create_customer()
|
||||||
self.clear_old_entries()
|
self.clear_old_entries()
|
||||||
bank_dt = qb.DocType("Bank")
|
bank_dt = qb.DocType("Bank")
|
||||||
q = qb.from_(bank_dt).delete().where(bank_dt.name == "HDFC").run()
|
qb.from_(bank_dt).delete().where(bank_dt.name == "HDFC").run()
|
||||||
self.create_bank_account()
|
self.create_bank_account()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
@@ -76,6 +75,7 @@ class TestBankReconciliationTool(AccountsTestMixin, FrappeTestCase):
|
|||||||
"deposit": 100,
|
"deposit": 100,
|
||||||
"bank_account": self.bank_account,
|
"bank_account": self.bank_account,
|
||||||
"reference_number": "123",
|
"reference_number": "123",
|
||||||
|
"currency": "INR",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.save()
|
.save()
|
||||||
|
|||||||
@@ -17,9 +17,7 @@ frappe.ui.form.on("Bank Statement Import", {
|
|||||||
frm.import_in_progress = false;
|
frm.import_in_progress = false;
|
||||||
if (data_import !== frm.doc.name) return;
|
if (data_import !== frm.doc.name) return;
|
||||||
frappe.model.clear_doc("Bank Statement Import", frm.doc.name);
|
frappe.model.clear_doc("Bank Statement Import", frm.doc.name);
|
||||||
frappe.model
|
frappe.model.with_doc("Bank Statement Import", frm.doc.name).then(() => {
|
||||||
.with_doc("Bank Statement Import", frm.doc.name)
|
|
||||||
.then(() => {
|
|
||||||
frm.refresh();
|
frm.refresh();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -48,20 +46,9 @@ frappe.ui.form.on("Bank Statement Import", {
|
|||||||
: __("Updating {0} of {1}, {2}", message_args);
|
: __("Updating {0} of {1}, {2}", message_args);
|
||||||
}
|
}
|
||||||
if (data.skipping) {
|
if (data.skipping) {
|
||||||
message = __(
|
message = __("Skipping {0} of {1}, {2}", [data.current, data.total, eta_message]);
|
||||||
"Skipping {0} of {1}, {2}",
|
|
||||||
[
|
|
||||||
data.current,
|
|
||||||
data.total,
|
|
||||||
eta_message,
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
frm.dashboard.show_progress(
|
frm.dashboard.show_progress(__("Import Progress"), percent, message);
|
||||||
__("Import Progress"),
|
|
||||||
percent,
|
|
||||||
message
|
|
||||||
);
|
|
||||||
frm.page.set_indicator(__("In Progress"), "orange");
|
frm.page.set_indicator(__("In Progress"), "orange");
|
||||||
|
|
||||||
// hide progress when complete
|
// hide progress when complete
|
||||||
@@ -103,15 +90,12 @@ frappe.ui.form.on("Bank Statement Import", {
|
|||||||
frm.trigger("show_report_error_button");
|
frm.trigger("show_report_error_button");
|
||||||
|
|
||||||
if (frm.doc.status === "Partial Success") {
|
if (frm.doc.status === "Partial Success") {
|
||||||
frm.add_custom_button(__("Export Errored Rows"), () =>
|
frm.add_custom_button(__("Export Errored Rows"), () => frm.trigger("export_errored_rows"));
|
||||||
frm.trigger("export_errored_rows")
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frm.doc.status.includes("Success")) {
|
if (frm.doc.status.includes("Success")) {
|
||||||
frm.add_custom_button(
|
frm.add_custom_button(__("Go to {0} List", [__(frm.doc.reference_doctype)]), () =>
|
||||||
__("Go to {0} List", [__(frm.doc.reference_doctype)]),
|
frappe.set_route("List", frm.doc.reference_doctype)
|
||||||
() => frappe.set_route("List", frm.doc.reference_doctype)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -128,13 +112,8 @@ frappe.ui.form.on("Bank Statement Import", {
|
|||||||
frm.disable_save();
|
frm.disable_save();
|
||||||
if (frm.doc.status !== "Success") {
|
if (frm.doc.status !== "Success") {
|
||||||
if (!frm.is_new() && frm.has_import_file()) {
|
if (!frm.is_new() && frm.has_import_file()) {
|
||||||
let label =
|
let label = frm.doc.status === "Pending" ? __("Start Import") : __("Retry");
|
||||||
frm.doc.status === "Pending"
|
frm.page.set_primary_action(label, () => frm.events.start_import(frm));
|
||||||
? __("Start Import")
|
|
||||||
: __("Retry");
|
|
||||||
frm.page.set_primary_action(label, () =>
|
|
||||||
frm.events.start_import(frm)
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
frm.page.set_primary_action(__("Save"), () => frm.save());
|
frm.page.set_primary_action(__("Save"), () => frm.save());
|
||||||
}
|
}
|
||||||
@@ -236,8 +215,7 @@ frappe.ui.form.on("Bank Statement Import", {
|
|||||||
},
|
},
|
||||||
|
|
||||||
download_template() {
|
download_template() {
|
||||||
let method =
|
let method = "/api/method/frappe.core.doctype.data_import.data_import.download_template";
|
||||||
"/api/method/frappe.core.doctype.data_import.data_import.download_template";
|
|
||||||
|
|
||||||
open_url_post(method, {
|
open_url_post(method, {
|
||||||
doctype: "Bank Transaction",
|
doctype: "Bank Transaction",
|
||||||
@@ -250,7 +228,7 @@ frappe.ui.form.on("Bank Statement Import", {
|
|||||||
"description",
|
"description",
|
||||||
"reference_number",
|
"reference_number",
|
||||||
"bank_account",
|
"bank_account",
|
||||||
"currency"
|
"currency",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -321,10 +299,7 @@ frappe.ui.form.on("Bank Statement Import", {
|
|||||||
show_import_preview(frm, preview_data) {
|
show_import_preview(frm, preview_data) {
|
||||||
let import_log = JSON.parse(frm.doc.statement_import_log || "[]");
|
let import_log = JSON.parse(frm.doc.statement_import_log || "[]");
|
||||||
|
|
||||||
if (
|
if (frm.import_preview && frm.import_preview.doctype === frm.doc.reference_doctype) {
|
||||||
frm.import_preview &&
|
|
||||||
frm.import_preview.doctype === frm.doc.reference_doctype
|
|
||||||
) {
|
|
||||||
frm.import_preview.preview_data = preview_data;
|
frm.import_preview.preview_data = preview_data;
|
||||||
frm.import_preview.import_log = import_log;
|
frm.import_preview.import_log = import_log;
|
||||||
frm.import_preview.refresh();
|
frm.import_preview.refresh();
|
||||||
@@ -340,19 +315,10 @@ frappe.ui.form.on("Bank Statement Import", {
|
|||||||
frm,
|
frm,
|
||||||
events: {
|
events: {
|
||||||
remap_column(changed_map) {
|
remap_column(changed_map) {
|
||||||
let template_options = JSON.parse(
|
let template_options = JSON.parse(frm.doc.template_options || "{}");
|
||||||
frm.doc.template_options || "{}"
|
template_options.column_to_field_map = template_options.column_to_field_map || {};
|
||||||
);
|
Object.assign(template_options.column_to_field_map, changed_map);
|
||||||
template_options.column_to_field_map =
|
frm.set_value("template_options", JSON.stringify(template_options));
|
||||||
template_options.column_to_field_map || {};
|
|
||||||
Object.assign(
|
|
||||||
template_options.column_to_field_map,
|
|
||||||
changed_map
|
|
||||||
);
|
|
||||||
frm.set_value(
|
|
||||||
"template_options",
|
|
||||||
JSON.stringify(template_options)
|
|
||||||
);
|
|
||||||
frm.save().then(() => frm.trigger("import_file"));
|
frm.save().then(() => frm.trigger("import_file"));
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -386,8 +352,7 @@ frappe.ui.form.on("Bank Statement Import", {
|
|||||||
let other_warnings = [];
|
let other_warnings = [];
|
||||||
for (let warning of warnings) {
|
for (let warning of warnings) {
|
||||||
if (warning.row) {
|
if (warning.row) {
|
||||||
warnings_by_row[warning.row] =
|
warnings_by_row[warning.row] = warnings_by_row[warning.row] || [];
|
||||||
warnings_by_row[warning.row] || [];
|
|
||||||
warnings_by_row[warning.row].push(warning);
|
warnings_by_row[warning.row].push(warning);
|
||||||
} else {
|
} else {
|
||||||
other_warnings.push(warning);
|
other_warnings.push(warning);
|
||||||
@@ -402,9 +367,7 @@ frappe.ui.form.on("Bank Statement Import", {
|
|||||||
if (w.field) {
|
if (w.field) {
|
||||||
let label =
|
let label =
|
||||||
w.field.label +
|
w.field.label +
|
||||||
(w.field.parent !== frm.doc.reference_doctype
|
(w.field.parent !== frm.doc.reference_doctype ? ` (${w.field.parent})` : "");
|
||||||
? ` (${w.field.parent})`
|
|
||||||
: "");
|
|
||||||
return `<li>${label}: ${w.message}</li>`;
|
return `<li>${label}: ${w.message}</li>`;
|
||||||
}
|
}
|
||||||
return `<li>${w.message}</li>`;
|
return `<li>${w.message}</li>`;
|
||||||
@@ -423,10 +386,9 @@ frappe.ui.form.on("Bank Statement Import", {
|
|||||||
.map((warning) => {
|
.map((warning) => {
|
||||||
let header = "";
|
let header = "";
|
||||||
if (warning.col) {
|
if (warning.col) {
|
||||||
let column_number = `<span class="text-uppercase">${__(
|
let column_number = `<span class="text-uppercase">${__("Column {0}", [
|
||||||
"Column {0}",
|
warning.col,
|
||||||
[warning.col]
|
])}</span>`;
|
||||||
)}</span>`;
|
|
||||||
let column_header = columns[warning.col].header_title;
|
let column_header = columns[warning.col].header_title;
|
||||||
header = `${column_number} (${column_header})`;
|
header = `${column_number} (${column_header})`;
|
||||||
}
|
}
|
||||||
@@ -465,36 +427,28 @@ frappe.ui.form.on("Bank Statement Import", {
|
|||||||
let html = "";
|
let html = "";
|
||||||
if (log.success) {
|
if (log.success) {
|
||||||
if (frm.doc.import_type === "Insert New Records") {
|
if (frm.doc.import_type === "Insert New Records") {
|
||||||
html = __(
|
html = __("Successfully imported {0}", [
|
||||||
"Successfully imported {0}", [
|
|
||||||
`<span class="underline">${frappe.utils.get_form_link(
|
`<span class="underline">${frappe.utils.get_form_link(
|
||||||
frm.doc.reference_doctype,
|
frm.doc.reference_doctype,
|
||||||
log.docname,
|
log.docname,
|
||||||
true
|
true
|
||||||
)}<span>`,
|
)}<span>`,
|
||||||
]
|
]);
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
html = __(
|
html = __("Successfully updated {0}", [
|
||||||
"Successfully updated {0}", [
|
|
||||||
`<span class="underline">${frappe.utils.get_form_link(
|
`<span class="underline">${frappe.utils.get_form_link(
|
||||||
frm.doc.reference_doctype,
|
frm.doc.reference_doctype,
|
||||||
log.docname,
|
log.docname,
|
||||||
true
|
true
|
||||||
)}<span>`,
|
)}<span>`,
|
||||||
]
|
]);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let messages = log.messages
|
let messages = log.messages
|
||||||
.map(JSON.parse)
|
.map(JSON.parse)
|
||||||
.map((m) => {
|
.map((m) => {
|
||||||
let title = m.title
|
let title = m.title ? `<strong>${m.title}</strong>` : "";
|
||||||
? `<strong>${m.title}</strong>`
|
let message = m.message ? `<div>${m.message}</div>` : "";
|
||||||
: "";
|
|
||||||
let message = m.message
|
|
||||||
? `<div>${m.message}</div>`
|
|
||||||
: "";
|
|
||||||
return title + message;
|
return title + message;
|
||||||
})
|
})
|
||||||
.join("");
|
.join("");
|
||||||
|
|||||||
@@ -202,7 +202,7 @@
|
|||||||
],
|
],
|
||||||
"hide_toolbar": 1,
|
"hide_toolbar": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2022-09-07 11:11:40.293317",
|
"modified": "2024-03-27 13:06:38.098765",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Bank Statement Import",
|
"name": "Bank Statement Import",
|
||||||
@@ -221,7 +221,8 @@
|
|||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"sort_field": "modified",
|
"sort_field": "creation",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
|
"states": [],
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
||||||
@@ -45,7 +45,7 @@ class BankStatementImport(DataImport):
|
|||||||
# end: auto-generated types
|
# end: auto-generated types
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(BankStatementImport, self).__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
doc_before_save = self.get_doc_before_save()
|
doc_before_save = self.get_doc_before_save()
|
||||||
@@ -54,7 +54,6 @@ class BankStatementImport(DataImport):
|
|||||||
or (doc_before_save and doc_before_save.import_file != self.import_file)
|
or (doc_before_save and doc_before_save.import_file != self.import_file)
|
||||||
or (doc_before_save and doc_before_save.google_sheets_url != self.google_sheets_url)
|
or (doc_before_save and doc_before_save.google_sheets_url != self.google_sheets_url)
|
||||||
):
|
):
|
||||||
|
|
||||||
template_options_dict = {}
|
template_options_dict = {}
|
||||||
column_to_field_map = {}
|
column_to_field_map = {}
|
||||||
bank = frappe.get_doc("Bank", self.bank)
|
bank = frappe.get_doc("Bank", self.bank)
|
||||||
@@ -69,7 +68,6 @@ class BankStatementImport(DataImport):
|
|||||||
self.validate_google_sheets_url()
|
self.validate_google_sheets_url()
|
||||||
|
|
||||||
def start_import(self):
|
def start_import(self):
|
||||||
|
|
||||||
preview = frappe.get_doc("Bank Statement Import", self.name).get_preview_from_template(
|
preview = frappe.get_doc("Bank Statement Import", self.name).get_preview_from_template(
|
||||||
self.import_file, self.google_sheets_url
|
self.import_file, self.google_sheets_url
|
||||||
)
|
)
|
||||||
@@ -80,7 +78,8 @@ class BankStatementImport(DataImport):
|
|||||||
from frappe.utils.background_jobs import is_job_enqueued
|
from frappe.utils.background_jobs import is_job_enqueued
|
||||||
from frappe.utils.scheduler import is_scheduler_inactive
|
from frappe.utils.scheduler import is_scheduler_inactive
|
||||||
|
|
||||||
if is_scheduler_inactive() and not frappe.flags.in_test:
|
run_now = frappe.flags.in_test or frappe.conf.developer_mode
|
||||||
|
if is_scheduler_inactive() and not run_now:
|
||||||
frappe.throw(_("Scheduler is inactive. Cannot import data."), title=_("Scheduler Inactive"))
|
frappe.throw(_("Scheduler is inactive. Cannot import data."), title=_("Scheduler Inactive"))
|
||||||
|
|
||||||
job_id = f"bank_statement_import::{self.name}"
|
job_id = f"bank_statement_import::{self.name}"
|
||||||
@@ -97,7 +96,7 @@ class BankStatementImport(DataImport):
|
|||||||
google_sheets_url=self.google_sheets_url,
|
google_sheets_url=self.google_sheets_url,
|
||||||
bank=self.bank,
|
bank=self.bank,
|
||||||
template_options=self.template_options,
|
template_options=self.template_options,
|
||||||
now=frappe.conf.developer_mode or frappe.flags.in_test,
|
now=run_now,
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -125,7 +124,7 @@ def download_errored_template(data_import_name):
|
|||||||
def parse_data_from_template(raw_data):
|
def parse_data_from_template(raw_data):
|
||||||
data = []
|
data = []
|
||||||
|
|
||||||
for i, row in enumerate(raw_data):
|
for _i, row in enumerate(raw_data):
|
||||||
if all(v in INVALID_VALUES for v in row):
|
if all(v in INVALID_VALUES for v in row):
|
||||||
# empty row
|
# empty row
|
||||||
continue
|
continue
|
||||||
@@ -135,9 +134,7 @@ def parse_data_from_template(raw_data):
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
def start_import(
|
def start_import(data_import, bank_account, import_file_path, google_sheets_url, bank, template_options):
|
||||||
data_import, bank_account, import_file_path, google_sheets_url, bank, template_options
|
|
||||||
):
|
|
||||||
"""This method runs in background job"""
|
"""This method runs in background job"""
|
||||||
|
|
||||||
update_mapping_db(bank, template_options)
|
update_mapping_db(bank, template_options)
|
||||||
@@ -148,6 +145,9 @@ def start_import(
|
|||||||
import_file = ImportFile("Bank Transaction", file=file, import_type="Insert New Records")
|
import_file = ImportFile("Bank Transaction", file=file, import_type="Insert New Records")
|
||||||
|
|
||||||
data = parse_data_from_template(import_file.raw_data)
|
data = parse_data_from_template(import_file.raw_data)
|
||||||
|
# Importer expects 'Data Import' class, which has 'payload_count' attribute
|
||||||
|
if not data_import.get("payload_count"):
|
||||||
|
data_import.payload_count = len(data) - 1
|
||||||
|
|
||||||
if import_file_path:
|
if import_file_path:
|
||||||
add_bank_account(data, bank_account)
|
add_bank_account(data, bank_account)
|
||||||
|
|||||||
@@ -1,36 +1,34 @@
|
|||||||
let imports_in_progress = [];
|
let imports_in_progress = [];
|
||||||
|
|
||||||
frappe.listview_settings['Bank Statement Import'] = {
|
frappe.listview_settings["Bank Statement Import"] = {
|
||||||
onload(listview) {
|
onload(listview) {
|
||||||
frappe.realtime.on('data_import_progress', data => {
|
frappe.realtime.on("data_import_progress", (data) => {
|
||||||
if (!imports_in_progress.includes(data.data_import)) {
|
if (!imports_in_progress.includes(data.data_import)) {
|
||||||
imports_in_progress.push(data.data_import);
|
imports_in_progress.push(data.data_import);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
frappe.realtime.on('data_import_refresh', data => {
|
frappe.realtime.on("data_import_refresh", (data) => {
|
||||||
imports_in_progress = imports_in_progress.filter(
|
imports_in_progress = imports_in_progress.filter((d) => d !== data.data_import);
|
||||||
d => d !== data.data_import
|
|
||||||
);
|
|
||||||
listview.refresh();
|
listview.refresh();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
get_indicator: function (doc) {
|
get_indicator: function (doc) {
|
||||||
var colors = {
|
var colors = {
|
||||||
'Pending': 'orange',
|
Pending: "orange",
|
||||||
'Not Started': 'orange',
|
"Not Started": "orange",
|
||||||
'Partial Success': 'orange',
|
"Partial Success": "orange",
|
||||||
'Success': 'green',
|
Success: "green",
|
||||||
'In Progress': 'orange',
|
"In Progress": "orange",
|
||||||
'Error': 'red'
|
Error: "red",
|
||||||
};
|
};
|
||||||
let status = doc.status;
|
let status = doc.status;
|
||||||
if (imports_in_progress.includes(doc.name)) {
|
if (imports_in_progress.includes(doc.name)) {
|
||||||
status = 'In Progress';
|
status = "In Progress";
|
||||||
}
|
}
|
||||||
if (status == 'Pending') {
|
if (status == "Pending") {
|
||||||
status = 'Not Started';
|
status = "Not Started";
|
||||||
}
|
}
|
||||||
return [__(status), colors[status], 'status,=,' + doc.status];
|
return [__(status), colors[status], "status,=," + doc.status];
|
||||||
},
|
},
|
||||||
hide_name_column: true
|
hide_name_column: true,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
from typing import Tuple, Union
|
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe.utils import flt
|
from frappe.utils import flt
|
||||||
from rapidfuzz import fuzz, process
|
from rapidfuzz import fuzz, process
|
||||||
@@ -19,7 +17,7 @@ class AutoMatchParty:
|
|||||||
def get(self, key):
|
def get(self, key):
|
||||||
return self.__dict__.get(key, None)
|
return self.__dict__.get(key, None)
|
||||||
|
|
||||||
def match(self) -> Union[Tuple, None]:
|
def match(self) -> tuple | None:
|
||||||
result = None
|
result = None
|
||||||
result = AutoMatchbyAccountIBAN(
|
result = AutoMatchbyAccountIBAN(
|
||||||
bank_party_account_number=self.bank_party_account_number,
|
bank_party_account_number=self.bank_party_account_number,
|
||||||
@@ -50,7 +48,7 @@ class AutoMatchbyAccountIBAN:
|
|||||||
result = self.match_account_in_party()
|
result = self.match_account_in_party()
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def match_account_in_party(self) -> Union[Tuple, None]:
|
def match_account_in_party(self) -> tuple | None:
|
||||||
"""Check if there is a IBAN/Account No. match in Customer/Supplier/Employee"""
|
"""Check if there is a IBAN/Account No. match in Customer/Supplier/Employee"""
|
||||||
result = None
|
result = None
|
||||||
parties = get_parties_in_order(self.deposit)
|
parties = get_parties_in_order(self.deposit)
|
||||||
@@ -97,7 +95,7 @@ class AutoMatchbyPartyNameDescription:
|
|||||||
def get(self, key):
|
def get(self, key):
|
||||||
return self.__dict__.get(key, None)
|
return self.__dict__.get(key, None)
|
||||||
|
|
||||||
def match(self) -> Union[Tuple, None]:
|
def match(self) -> tuple | None:
|
||||||
# fuzzy search by customer/supplier & employee
|
# fuzzy search by customer/supplier & employee
|
||||||
if not (self.bank_party_name or self.description):
|
if not (self.bank_party_name or self.description):
|
||||||
return None
|
return None
|
||||||
@@ -105,7 +103,7 @@ class AutoMatchbyPartyNameDescription:
|
|||||||
result = self.match_party_name_desc_in_party()
|
result = self.match_party_name_desc_in_party()
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def match_party_name_desc_in_party(self) -> Union[Tuple, None]:
|
def match_party_name_desc_in_party(self) -> tuple | None:
|
||||||
"""Fuzzy search party name and/or description against parties in the system"""
|
"""Fuzzy search party name and/or description against parties in the system"""
|
||||||
result = None
|
result = None
|
||||||
parties = get_parties_in_order(self.deposit)
|
parties = get_parties_in_order(self.deposit)
|
||||||
@@ -130,7 +128,7 @@ class AutoMatchbyPartyNameDescription:
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def fuzzy_search_and_return_result(self, party, names, field) -> Union[Tuple, None]:
|
def fuzzy_search_and_return_result(self, party, names, field) -> tuple | None:
|
||||||
skip = False
|
skip = False
|
||||||
result = process.extract(
|
result = process.extract(
|
||||||
query=self.get(field),
|
query=self.get(field),
|
||||||
@@ -147,7 +145,7 @@ class AutoMatchbyPartyNameDescription:
|
|||||||
party_name,
|
party_name,
|
||||||
), skip
|
), skip
|
||||||
|
|
||||||
def process_fuzzy_result(self, result: Union[list, None]):
|
def process_fuzzy_result(self, result: list | None):
|
||||||
"""
|
"""
|
||||||
If there are multiple valid close matches return None as result may be faulty.
|
If there are multiple valid close matches return None as result may be faulty.
|
||||||
Return the result only if one accurate match stands out.
|
Return the result only if one accurate match stands out.
|
||||||
|
|||||||
@@ -35,14 +35,8 @@ frappe.ui.form.on("Bank Transaction", {
|
|||||||
|
|
||||||
get_payment_doctypes: function () {
|
get_payment_doctypes: function () {
|
||||||
// get payment doctypes from all the apps
|
// get payment doctypes from all the apps
|
||||||
return [
|
return ["Payment Entry", "Journal Entry", "Sales Invoice", "Purchase Invoice", "Bank Transaction"];
|
||||||
"Payment Entry",
|
},
|
||||||
"Journal Entry",
|
|
||||||
"Sales Invoice",
|
|
||||||
"Purchase Invoice",
|
|
||||||
"Bank Transaction",
|
|
||||||
];
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
frappe.ui.form.on("Bank Transaction Payments", {
|
frappe.ui.form.on("Bank Transaction Payments", {
|
||||||
@@ -54,10 +48,11 @@ frappe.ui.form.on("Bank Transaction Payments", {
|
|||||||
const update_clearance_date = (frm, cdt, cdn) => {
|
const update_clearance_date = (frm, cdt, cdn) => {
|
||||||
if (frm.doc.docstatus === 1) {
|
if (frm.doc.docstatus === 1) {
|
||||||
frappe
|
frappe
|
||||||
.xcall(
|
.xcall("erpnext.accounts.doctype.bank_transaction.bank_transaction.unclear_reference_payment", {
|
||||||
"erpnext.accounts.doctype.bank_transaction.bank_transaction.unclear_reference_payment",
|
doctype: cdt,
|
||||||
{ doctype: cdt, docname: cdn, bt_name: frm.doc.name }
|
docname: cdn,
|
||||||
)
|
bt_name: frm.doc.name,
|
||||||
|
})
|
||||||
.then((e) => {
|
.then((e) => {
|
||||||
if (e == "success") {
|
if (e == "success") {
|
||||||
frappe.show_alert({
|
frappe.show_alert({
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
|
from frappe.model.docstatus import DocStatus
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from frappe.utils import flt
|
from frappe.utils import flt
|
||||||
|
|
||||||
@@ -48,6 +49,26 @@ class BankTransaction(Document):
|
|||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.validate_duplicate_references()
|
self.validate_duplicate_references()
|
||||||
|
self.validate_currency()
|
||||||
|
|
||||||
|
def validate_currency(self):
|
||||||
|
"""
|
||||||
|
Bank Transaction should be on the same currency as the Bank Account.
|
||||||
|
"""
|
||||||
|
if self.currency and self.bank_account:
|
||||||
|
if account := frappe.get_cached_value("Bank Account", self.bank_account, "account"):
|
||||||
|
account_currency = frappe.get_cached_value("Account", account, "account_currency")
|
||||||
|
|
||||||
|
if self.currency != account_currency:
|
||||||
|
frappe.throw(
|
||||||
|
_(
|
||||||
|
"Transaction currency: {0} cannot be different from Bank Account({1}) currency: {2}"
|
||||||
|
).format(
|
||||||
|
frappe.bold(self.currency),
|
||||||
|
frappe.bold(self.bank_account),
|
||||||
|
frappe.bold(account_currency),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def set_status(self):
|
def set_status(self):
|
||||||
if self.docstatus == 2:
|
if self.docstatus == 2:
|
||||||
@@ -75,10 +96,13 @@ class BankTransaction(Document):
|
|||||||
pe.append(reference)
|
pe.append(reference)
|
||||||
|
|
||||||
def update_allocated_amount(self):
|
def update_allocated_amount(self):
|
||||||
self.allocated_amount = (
|
allocated_amount = (
|
||||||
sum(p.allocated_amount for p in self.payment_entries) if self.payment_entries else 0.0
|
sum(p.allocated_amount for p in self.payment_entries) if self.payment_entries else 0.0
|
||||||
)
|
)
|
||||||
self.unallocated_amount = abs(flt(self.withdrawal) - flt(self.deposit)) - self.allocated_amount
|
unallocated_amount = abs(flt(self.withdrawal) - flt(self.deposit)) - allocated_amount
|
||||||
|
|
||||||
|
self.allocated_amount = flt(allocated_amount, self.precision("allocated_amount"))
|
||||||
|
self.unallocated_amount = flt(unallocated_amount, self.precision("unallocated_amount"))
|
||||||
|
|
||||||
def before_submit(self):
|
def before_submit(self):
|
||||||
self.allocate_payment_entries()
|
self.allocate_payment_entries()
|
||||||
@@ -158,7 +182,7 @@ class BankTransaction(Document):
|
|||||||
frappe.throw(_("Voucher {0} is over-allocated by {1}").format(unallocated_amount))
|
frappe.throw(_("Voucher {0} is over-allocated by {1}").format(unallocated_amount))
|
||||||
|
|
||||||
for payment_entry in to_remove:
|
for payment_entry in to_remove:
|
||||||
self.remove(to_remove)
|
self.remove(payment_entry)
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def remove_payment_entries(self):
|
def remove_payment_entries(self):
|
||||||
@@ -213,9 +237,7 @@ def get_clearance_details(transaction, payment_entry):
|
|||||||
"""
|
"""
|
||||||
gl_bank_account = frappe.db.get_value("Bank Account", transaction.bank_account, "account")
|
gl_bank_account = frappe.db.get_value("Bank Account", transaction.bank_account, "account")
|
||||||
gles = get_related_bank_gl_entries(payment_entry.payment_document, payment_entry.payment_entry)
|
gles = get_related_bank_gl_entries(payment_entry.payment_document, payment_entry.payment_entry)
|
||||||
bt_allocations = get_total_allocated_amount(
|
bt_allocations = get_total_allocated_amount(payment_entry.payment_document, payment_entry.payment_entry)
|
||||||
payment_entry.payment_document, payment_entry.payment_entry
|
|
||||||
)
|
|
||||||
|
|
||||||
unallocated_amount = min(
|
unallocated_amount = min(
|
||||||
transaction.unallocated_amount,
|
transaction.unallocated_amount,
|
||||||
@@ -310,7 +332,6 @@ def get_total_allocated_amount(doctype, docname):
|
|||||||
|
|
||||||
def get_paid_amount(payment_entry, currency, gl_bank_account):
|
def get_paid_amount(payment_entry, currency, gl_bank_account):
|
||||||
if payment_entry.payment_document in ["Payment Entry", "Sales Invoice", "Purchase Invoice"]:
|
if payment_entry.payment_document in ["Payment Entry", "Sales Invoice", "Purchase Invoice"]:
|
||||||
|
|
||||||
paid_amount_field = "paid_amount"
|
paid_amount_field = "paid_amount"
|
||||||
if payment_entry.payment_document == "Payment Entry":
|
if payment_entry.payment_document == "Payment Entry":
|
||||||
doc = frappe.get_doc("Payment Entry", payment_entry.payment_entry)
|
doc = frappe.get_doc("Payment Entry", payment_entry.payment_entry)
|
||||||
@@ -349,9 +370,7 @@ def get_paid_amount(payment_entry, currency, gl_bank_account):
|
|||||||
)
|
)
|
||||||
|
|
||||||
elif payment_entry.payment_document == "Loan Repayment":
|
elif payment_entry.payment_document == "Loan Repayment":
|
||||||
return frappe.db.get_value(
|
return frappe.db.get_value(payment_entry.payment_document, payment_entry.payment_entry, "amount_paid")
|
||||||
payment_entry.payment_document, payment_entry.payment_entry, "amount_paid"
|
|
||||||
)
|
|
||||||
|
|
||||||
elif payment_entry.payment_document == "Bank Transaction":
|
elif payment_entry.payment_document == "Bank Transaction":
|
||||||
dep, wth = frappe.db.get_value(
|
dep, wth = frappe.db.get_value(
|
||||||
@@ -361,9 +380,7 @@ def get_paid_amount(payment_entry, currency, gl_bank_account):
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
"Please reconcile {0}: {1} manually".format(
|
f"Please reconcile {payment_entry.payment_document}: {payment_entry.payment_entry} manually"
|
||||||
payment_entry.payment_document, payment_entry.payment_entry
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -415,3 +432,21 @@ def unclear_reference_payment(doctype, docname, bt_name):
|
|||||||
bt = frappe.get_doc("Bank Transaction", bt_name)
|
bt = frappe.get_doc("Bank Transaction", bt_name)
|
||||||
set_voucher_clearance(doctype, docname, None, bt)
|
set_voucher_clearance(doctype, docname, None, bt)
|
||||||
return docname
|
return docname
|
||||||
|
|
||||||
|
|
||||||
|
def remove_from_bank_transaction(doctype, docname):
|
||||||
|
"""Remove a (cancelled) voucher from all Bank Transactions."""
|
||||||
|
for bt_name in get_reconciled_bank_transactions(doctype, docname):
|
||||||
|
bt = frappe.get_doc("Bank Transaction", bt_name)
|
||||||
|
if bt.docstatus == DocStatus.cancelled():
|
||||||
|
continue
|
||||||
|
|
||||||
|
modified = False
|
||||||
|
|
||||||
|
for pe in bt.payment_entries:
|
||||||
|
if pe.payment_document == doctype and pe.payment_entry == docname:
|
||||||
|
bt.remove(pe)
|
||||||
|
modified = True
|
||||||
|
|
||||||
|
if modified:
|
||||||
|
bt.save()
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
// License: GNU General Public License v3. See license.txt
|
// License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
frappe.listview_settings['Bank Transaction'] = {
|
frappe.listview_settings["Bank Transaction"] = {
|
||||||
add_fields: ["unallocated_amount"],
|
add_fields: ["unallocated_amount"],
|
||||||
get_indicator: function (doc) {
|
get_indicator: function (doc) {
|
||||||
if (doc.docstatus == 2) {
|
if (doc.docstatus == 2) {
|
||||||
@@ -11,5 +11,5 @@ frappe.listview_settings['Bank Transaction'] = {
|
|||||||
} else if (flt(doc.unallocated_amount) > 0) {
|
} else if (flt(doc.unallocated_amount) > 0) {
|
||||||
return [__("Unreconciled"), "orange", "unallocated_amount,>,0"];
|
return [__("Unreconciled"), "orange", "unallocated_amount,>,0"];
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -18,12 +18,12 @@ def upload_bank_statement():
|
|||||||
fcontent = frappe.local.uploaded_file
|
fcontent = frappe.local.uploaded_file
|
||||||
fname = frappe.local.uploaded_filename
|
fname = frappe.local.uploaded_filename
|
||||||
|
|
||||||
if frappe.safe_encode(fname).lower().endswith("csv".encode("utf-8")):
|
if frappe.safe_encode(fname).lower().endswith(b"csv"):
|
||||||
from frappe.utils.csvutils import read_csv_content
|
from frappe.utils.csvutils import read_csv_content
|
||||||
|
|
||||||
rows = read_csv_content(fcontent, False)
|
rows = read_csv_content(fcontent, False)
|
||||||
|
|
||||||
elif frappe.safe_encode(fname).lower().endswith("xlsx".encode("utf-8")):
|
elif frappe.safe_encode(fname).lower().endswith(b"xlsx"):
|
||||||
from frappe.utils.xlsxutils import read_xlsx_file_from_attached_file
|
from frappe.utils.xlsxutils import read_xlsx_file_from_attached_file
|
||||||
|
|
||||||
rows = read_xlsx_file_from_attached_file(fcontent=fcontent)
|
rows = read_xlsx_file_from_attached_file(fcontent=fcontent)
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
# See license.txt
|
# See license.txt
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import unittest
|
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import utils
|
from frappe import utils
|
||||||
|
from frappe.model.docstatus import DocStatus
|
||||||
from frappe.tests.utils import FrappeTestCase
|
from frappe.tests.utils import FrappeTestCase
|
||||||
|
|
||||||
from erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool import (
|
from erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool import (
|
||||||
@@ -32,8 +32,16 @@ class TestBankTransaction(FrappeTestCase):
|
|||||||
frappe.db.delete(dt)
|
frappe.db.delete(dt)
|
||||||
clear_loan_transactions()
|
clear_loan_transactions()
|
||||||
make_pos_profile()
|
make_pos_profile()
|
||||||
add_transactions()
|
|
||||||
add_vouchers()
|
# generate and use a uniq hash identifier for 'Bank Account' and it's linked GL 'Account' to avoid validation error
|
||||||
|
uniq_identifier = frappe.generate_hash(length=10)
|
||||||
|
gl_account = create_gl_account("_Test Bank " + uniq_identifier)
|
||||||
|
bank_account = create_bank_account(
|
||||||
|
gl_account=gl_account, bank_account_name="Checking Account " + uniq_identifier
|
||||||
|
)
|
||||||
|
|
||||||
|
add_transactions(bank_account=bank_account)
|
||||||
|
add_vouchers(gl_account=gl_account)
|
||||||
|
|
||||||
# This test checks if ERPNext is able to provide a linked payment for a bank transaction based on the amount of the bank transaction.
|
# This test checks if ERPNext is able to provide a linked payment for a bank transaction based on the amount of the bank transaction.
|
||||||
def test_linked_payments(self):
|
def test_linked_payments(self):
|
||||||
@@ -81,6 +89,29 @@ class TestBankTransaction(FrappeTestCase):
|
|||||||
clearance_date = frappe.db.get_value("Payment Entry", payment.name, "clearance_date")
|
clearance_date = frappe.db.get_value("Payment Entry", payment.name, "clearance_date")
|
||||||
self.assertFalse(clearance_date)
|
self.assertFalse(clearance_date)
|
||||||
|
|
||||||
|
def test_cancel_voucher(self):
|
||||||
|
bank_transaction = frappe.get_doc(
|
||||||
|
"Bank Transaction",
|
||||||
|
dict(description="1512567 BG/000003025 OPSKATTUZWXXX AT776000000098709849 Herr G"),
|
||||||
|
)
|
||||||
|
payment = frappe.get_doc("Payment Entry", dict(party="Mr G", paid_amount=1700))
|
||||||
|
vouchers = json.dumps(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"payment_doctype": "Payment Entry",
|
||||||
|
"payment_name": payment.name,
|
||||||
|
"amount": bank_transaction.unallocated_amount,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
reconcile_vouchers(bank_transaction.name, vouchers)
|
||||||
|
payment.reload()
|
||||||
|
payment.cancel()
|
||||||
|
bank_transaction.reload()
|
||||||
|
self.assertEqual(bank_transaction.docstatus, DocStatus.submitted())
|
||||||
|
self.assertEqual(bank_transaction.unallocated_amount, 1700)
|
||||||
|
self.assertEqual(bank_transaction.payment_entries, [])
|
||||||
|
|
||||||
# Check if ERPNext can correctly filter a linked payments based on the debit/credit amount
|
# Check if ERPNext can correctly filter a linked payments based on the debit/credit amount
|
||||||
def test_debit_credit_output(self):
|
def test_debit_credit_output(self):
|
||||||
bank_transaction = frappe.get_doc(
|
bank_transaction = frappe.get_doc(
|
||||||
@@ -196,7 +227,9 @@ def clear_loan_transactions():
|
|||||||
frappe.db.delete("Loan Repayment")
|
frappe.db.delete("Loan Repayment")
|
||||||
|
|
||||||
|
|
||||||
def create_bank_account(bank_name="Citi Bank", account_name="_Test Bank - _TC"):
|
def create_bank_account(
|
||||||
|
bank_name="Citi Bank", gl_account="_Test Bank - _TC", bank_account_name="Checking Account"
|
||||||
|
):
|
||||||
try:
|
try:
|
||||||
frappe.get_doc(
|
frappe.get_doc(
|
||||||
{
|
{
|
||||||
@@ -208,21 +241,35 @@ def create_bank_account(bank_name="Citi Bank", account_name="_Test Bank - _TC"):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
frappe.get_doc(
|
bank_account = frappe.get_doc(
|
||||||
{
|
{
|
||||||
"doctype": "Bank Account",
|
"doctype": "Bank Account",
|
||||||
"account_name": "Checking Account",
|
"account_name": bank_account_name,
|
||||||
"bank": bank_name,
|
"bank": bank_name,
|
||||||
"account": account_name,
|
"account": gl_account,
|
||||||
}
|
}
|
||||||
).insert(ignore_if_duplicate=True)
|
).insert(ignore_if_duplicate=True)
|
||||||
except frappe.DuplicateEntryError:
|
except frappe.DuplicateEntryError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
return bank_account.name
|
||||||
|
|
||||||
def add_transactions():
|
|
||||||
create_bank_account()
|
|
||||||
|
|
||||||
|
def create_gl_account(gl_account_name="_Test Bank - _TC"):
|
||||||
|
gl_account = frappe.get_doc(
|
||||||
|
{
|
||||||
|
"doctype": "Account",
|
||||||
|
"company": "_Test Company",
|
||||||
|
"parent_account": "Current Assets - _TC",
|
||||||
|
"account_type": "Bank",
|
||||||
|
"is_group": 0,
|
||||||
|
"account_name": gl_account_name,
|
||||||
|
}
|
||||||
|
).insert()
|
||||||
|
return gl_account.name
|
||||||
|
|
||||||
|
|
||||||
|
def add_transactions(bank_account="_Test Bank - _TC"):
|
||||||
doc = frappe.get_doc(
|
doc = frappe.get_doc(
|
||||||
{
|
{
|
||||||
"doctype": "Bank Transaction",
|
"doctype": "Bank Transaction",
|
||||||
@@ -230,7 +277,7 @@ def add_transactions():
|
|||||||
"date": "2018-10-23",
|
"date": "2018-10-23",
|
||||||
"deposit": 1200,
|
"deposit": 1200,
|
||||||
"currency": "INR",
|
"currency": "INR",
|
||||||
"bank_account": "Checking Account - Citi Bank",
|
"bank_account": bank_account,
|
||||||
}
|
}
|
||||||
).insert()
|
).insert()
|
||||||
doc.submit()
|
doc.submit()
|
||||||
@@ -242,7 +289,7 @@ def add_transactions():
|
|||||||
"date": "2018-10-23",
|
"date": "2018-10-23",
|
||||||
"deposit": 1700,
|
"deposit": 1700,
|
||||||
"currency": "INR",
|
"currency": "INR",
|
||||||
"bank_account": "Checking Account - Citi Bank",
|
"bank_account": bank_account,
|
||||||
}
|
}
|
||||||
).insert()
|
).insert()
|
||||||
doc.submit()
|
doc.submit()
|
||||||
@@ -254,7 +301,7 @@ def add_transactions():
|
|||||||
"date": "2018-10-26",
|
"date": "2018-10-26",
|
||||||
"withdrawal": 690,
|
"withdrawal": 690,
|
||||||
"currency": "INR",
|
"currency": "INR",
|
||||||
"bank_account": "Checking Account - Citi Bank",
|
"bank_account": bank_account,
|
||||||
}
|
}
|
||||||
).insert()
|
).insert()
|
||||||
doc.submit()
|
doc.submit()
|
||||||
@@ -266,7 +313,7 @@ def add_transactions():
|
|||||||
"date": "2018-10-27",
|
"date": "2018-10-27",
|
||||||
"deposit": 3900,
|
"deposit": 3900,
|
||||||
"currency": "INR",
|
"currency": "INR",
|
||||||
"bank_account": "Checking Account - Citi Bank",
|
"bank_account": bank_account,
|
||||||
}
|
}
|
||||||
).insert()
|
).insert()
|
||||||
doc.submit()
|
doc.submit()
|
||||||
@@ -278,13 +325,13 @@ def add_transactions():
|
|||||||
"date": "2018-10-27",
|
"date": "2018-10-27",
|
||||||
"withdrawal": 109080,
|
"withdrawal": 109080,
|
||||||
"currency": "INR",
|
"currency": "INR",
|
||||||
"bank_account": "Checking Account - Citi Bank",
|
"bank_account": bank_account,
|
||||||
}
|
}
|
||||||
).insert()
|
).insert()
|
||||||
doc.submit()
|
doc.submit()
|
||||||
|
|
||||||
|
|
||||||
def add_vouchers():
|
def add_vouchers(gl_account="_Test Bank - _TC"):
|
||||||
try:
|
try:
|
||||||
frappe.get_doc(
|
frappe.get_doc(
|
||||||
{
|
{
|
||||||
@@ -300,7 +347,7 @@ def add_vouchers():
|
|||||||
|
|
||||||
pi = make_purchase_invoice(supplier="Conrad Electronic", qty=1, rate=690)
|
pi = make_purchase_invoice(supplier="Conrad Electronic", qty=1, rate=690)
|
||||||
|
|
||||||
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC")
|
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account=gl_account)
|
||||||
pe.reference_no = "Conrad Oct 18"
|
pe.reference_no = "Conrad Oct 18"
|
||||||
pe.reference_date = "2018-10-24"
|
pe.reference_date = "2018-10-24"
|
||||||
pe.insert()
|
pe.insert()
|
||||||
@@ -319,14 +366,14 @@ def add_vouchers():
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
pi = make_purchase_invoice(supplier="Mr G", qty=1, rate=1200)
|
pi = make_purchase_invoice(supplier="Mr G", qty=1, rate=1200)
|
||||||
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC")
|
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account=gl_account)
|
||||||
pe.reference_no = "Herr G Oct 18"
|
pe.reference_no = "Herr G Oct 18"
|
||||||
pe.reference_date = "2018-10-24"
|
pe.reference_date = "2018-10-24"
|
||||||
pe.insert()
|
pe.insert()
|
||||||
pe.submit()
|
pe.submit()
|
||||||
|
|
||||||
pi = make_purchase_invoice(supplier="Mr G", qty=1, rate=1700)
|
pi = make_purchase_invoice(supplier="Mr G", qty=1, rate=1700)
|
||||||
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC")
|
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account=gl_account)
|
||||||
pe.reference_no = "Herr G Nov 18"
|
pe.reference_no = "Herr G Nov 18"
|
||||||
pe.reference_date = "2018-11-01"
|
pe.reference_date = "2018-11-01"
|
||||||
pe.insert()
|
pe.insert()
|
||||||
@@ -357,10 +404,10 @@ def add_vouchers():
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
pi = make_purchase_invoice(supplier="Poore Simon's", qty=1, rate=3900, is_paid=1, do_not_save=1)
|
pi = make_purchase_invoice(supplier="Poore Simon's", qty=1, rate=3900, is_paid=1, do_not_save=1)
|
||||||
pi.cash_bank_account = "_Test Bank - _TC"
|
pi.cash_bank_account = gl_account
|
||||||
pi.insert()
|
pi.insert()
|
||||||
pi.submit()
|
pi.submit()
|
||||||
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC")
|
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account=gl_account)
|
||||||
pe.reference_no = "Poore Simon's Oct 18"
|
pe.reference_no = "Poore Simon's Oct 18"
|
||||||
pe.reference_date = "2018-10-28"
|
pe.reference_date = "2018-10-28"
|
||||||
pe.paid_amount = 690
|
pe.paid_amount = 690
|
||||||
@@ -369,7 +416,7 @@ def add_vouchers():
|
|||||||
pe.submit()
|
pe.submit()
|
||||||
|
|
||||||
si = create_sales_invoice(customer="Poore Simon's", qty=1, rate=3900)
|
si = create_sales_invoice(customer="Poore Simon's", qty=1, rate=3900)
|
||||||
pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank - _TC")
|
pe = get_payment_entry("Sales Invoice", si.name, bank_account=gl_account)
|
||||||
pe.reference_no = "Poore Simon's Oct 18"
|
pe.reference_no = "Poore Simon's Oct 18"
|
||||||
pe.reference_date = "2018-10-28"
|
pe.reference_date = "2018-10-28"
|
||||||
pe.insert()
|
pe.insert()
|
||||||
@@ -389,19 +436,13 @@ def add_vouchers():
|
|||||||
|
|
||||||
mode_of_payment = frappe.get_doc({"doctype": "Mode of Payment", "name": "Cash"})
|
mode_of_payment = frappe.get_doc({"doctype": "Mode of Payment", "name": "Cash"})
|
||||||
|
|
||||||
if not frappe.db.get_value(
|
if not frappe.db.get_value("Mode of Payment Account", {"company": "_Test Company", "parent": "Cash"}):
|
||||||
"Mode of Payment Account", {"company": "_Test Company", "parent": "Cash"}
|
mode_of_payment.append("accounts", {"company": "_Test Company", "default_account": gl_account})
|
||||||
):
|
|
||||||
mode_of_payment.append(
|
|
||||||
"accounts", {"company": "_Test Company", "default_account": "_Test Bank - _TC"}
|
|
||||||
)
|
|
||||||
mode_of_payment.save()
|
mode_of_payment.save()
|
||||||
|
|
||||||
si = create_sales_invoice(customer="Fayva", qty=1, rate=109080, do_not_save=1)
|
si = create_sales_invoice(customer="Fayva", qty=1, rate=109080, do_not_save=1)
|
||||||
si.is_pos = 1
|
si.is_pos = 1
|
||||||
si.append(
|
si.append("payments", {"mode_of_payment": "Cash", "account": gl_account, "amount": 109080})
|
||||||
"payments", {"mode_of_payment": "Cash", "account": "_Test Bank - _TC", "amount": 109080}
|
|
||||||
)
|
|
||||||
si.insert()
|
si.insert()
|
||||||
si.submit()
|
si.submit()
|
||||||
|
|
||||||
|
|||||||
@@ -1,107 +1,38 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"actions": [],
|
||||||
"allow_events_in_timeline": 0,
|
|
||||||
"allow_guest_to_view": 0,
|
|
||||||
"allow_import": 0,
|
|
||||||
"allow_rename": 0,
|
|
||||||
"beta": 0,
|
|
||||||
"creation": "2018-10-24 15:24:56.713277",
|
"creation": "2018-10-24 15:24:56.713277",
|
||||||
"custom": 0,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "",
|
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"bank_transaction_field",
|
||||||
|
"file_field"
|
||||||
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "bank_transaction_field",
|
"fieldname": "bank_transaction_field",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Field in Bank Transaction",
|
"label": "Field in Bank Transaction",
|
||||||
"length": 0,
|
"reqd": 1
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "file_field",
|
"fieldname": "file_field",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Column in Bank File",
|
"label": "Column in Bank File",
|
||||||
"length": 0,
|
"reqd": 1
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 0,
|
|
||||||
"hide_heading": 0,
|
|
||||||
"hide_toolbar": 0,
|
|
||||||
"idx": 0,
|
|
||||||
"image_view": 0,
|
|
||||||
"in_create": 0,
|
|
||||||
"is_submittable": 0,
|
|
||||||
"issingle": 0,
|
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"links": [],
|
||||||
"modified": "2018-10-24 15:24:56.713277",
|
"modified": "2024-03-27 13:06:38.436517",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Bank Transaction Mapping",
|
"name": "Bank Transaction Mapping",
|
||||||
"name_case": "",
|
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"quick_entry": 0,
|
"sort_field": "creation",
|
||||||
"read_only": 0,
|
|
||||||
"read_only_onload": 0,
|
|
||||||
"show_name_in_global_search": 0,
|
|
||||||
"sort_field": "modified",
|
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"track_changes": 0,
|
"states": []
|
||||||
"track_seen": 0,
|
|
||||||
"track_views": 0
|
|
||||||
}
|
}
|
||||||
@@ -1,115 +1,38 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"actions": [],
|
||||||
"allow_events_in_timeline": 0,
|
|
||||||
"allow_guest_to_view": 0,
|
|
||||||
"allow_import": 0,
|
|
||||||
"allow_rename": 0,
|
|
||||||
"beta": 0,
|
|
||||||
"creation": "2018-11-28 08:55:40.815355",
|
"creation": "2018-11-28 08:55:40.815355",
|
||||||
"custom": 0,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "",
|
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"payment_document",
|
||||||
|
"payment_entry",
|
||||||
|
"allocated_amount",
|
||||||
|
"clearance_date"
|
||||||
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "payment_document",
|
"fieldname": "payment_document",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Payment Document",
|
"label": "Payment Document",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "DocType",
|
"options": "DocType",
|
||||||
"permlevel": 0,
|
"reqd": 1
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "payment_entry",
|
"fieldname": "payment_entry",
|
||||||
"fieldtype": "Dynamic Link",
|
"fieldtype": "Dynamic Link",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Payment Entry",
|
"label": "Payment Entry",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "payment_document",
|
"options": "payment_document",
|
||||||
"permlevel": 0,
|
"reqd": 1
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "allocated_amount",
|
"fieldname": "allocated_amount",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Allocated Amount",
|
"label": "Allocated Amount",
|
||||||
"length": 0,
|
"reqd": 1
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval:doc.docstatus==1",
|
"depends_on": "eval:doc.docstatus==1",
|
||||||
@@ -121,30 +44,17 @@
|
|||||||
"read_only": 1
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 0,
|
|
||||||
"hide_heading": 0,
|
|
||||||
"hide_toolbar": 0,
|
|
||||||
"idx": 0,
|
|
||||||
"image_view": 0,
|
|
||||||
"in_create": 0,
|
|
||||||
"is_submittable": 0,
|
|
||||||
"issingle": 0,
|
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"links": [],
|
||||||
"modified": "2020-01-22 00:00:00.000000",
|
"modified": "2024-03-27 13:06:38.549438",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Bank Transaction Payments",
|
"name": "Bank Transaction Payments",
|
||||||
"name_case": "",
|
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"quick_entry": 1,
|
"quick_entry": 1,
|
||||||
"read_only": 0,
|
"sort_field": "creation",
|
||||||
"read_only_onload": 0,
|
|
||||||
"show_name_in_global_search": 0,
|
|
||||||
"sort_field": "modified",
|
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"track_changes": 1,
|
"states": [],
|
||||||
"track_seen": 0,
|
"track_changes": 1
|
||||||
"track_views": 0
|
|
||||||
}
|
}
|
||||||
@@ -6,18 +6,18 @@ frappe.ui.form.on("Bisect Accounting Statements", {
|
|||||||
frm.trigger("render_heatmap");
|
frm.trigger("render_heatmap");
|
||||||
},
|
},
|
||||||
refresh(frm) {
|
refresh(frm) {
|
||||||
frm.add_custom_button(__('Bisect Left'), () => {
|
frm.add_custom_button(__("Bisect Left"), () => {
|
||||||
frm.trigger("bisect_left");
|
frm.trigger("bisect_left");
|
||||||
});
|
});
|
||||||
|
|
||||||
frm.add_custom_button(__('Bisect Right'), () => {
|
frm.add_custom_button(__("Bisect Right"), () => {
|
||||||
frm.trigger("bisect_right");
|
frm.trigger("bisect_right");
|
||||||
});
|
});
|
||||||
|
|
||||||
frm.add_custom_button(__('Up'), () => {
|
frm.add_custom_button(__("Up"), () => {
|
||||||
frm.trigger("move_up");
|
frm.trigger("move_up");
|
||||||
});
|
});
|
||||||
frm.add_custom_button(__('Build Tree'), () => {
|
frm.add_custom_button(__("Build Tree"), () => {
|
||||||
frm.trigger("build_tree");
|
frm.trigger("build_tree");
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -35,7 +35,7 @@ frappe.ui.form.on("Bisect Accounting Statements", {
|
|||||||
|
|
||||||
for (let x = fr_dt; x <= to_dt; x += msiad) {
|
for (let x = fr_dt; x <= to_dt; x += msiad) {
|
||||||
let epoch_in_seconds = x / 1000;
|
let epoch_in_seconds = x / 1000;
|
||||||
if ((bisect_start <= x) && (x <= bisect_end )) {
|
if (bisect_start <= x && x <= bisect_end) {
|
||||||
datapoints[epoch_in_seconds] = 1.0;
|
datapoints[epoch_in_seconds] = 1.0;
|
||||||
} else {
|
} else {
|
||||||
datapoints[epoch_in_seconds] = 0.0;
|
datapoints[epoch_in_seconds] = 0.0;
|
||||||
@@ -49,19 +49,19 @@ frappe.ui.form.on("Bisect Accounting Statements", {
|
|||||||
start: new Date(frm.doc.from_date),
|
start: new Date(frm.doc.from_date),
|
||||||
end: new Date(frm.doc.to_date),
|
end: new Date(frm.doc.to_date),
|
||||||
},
|
},
|
||||||
countLabel: 'Bisecting',
|
countLabel: "Bisecting",
|
||||||
discreteDomains: 1,
|
discreteDomains: 1,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
bisect_left(frm) {
|
bisect_left(frm) {
|
||||||
frm.call({
|
frm.call({
|
||||||
doc: frm.doc,
|
doc: frm.doc,
|
||||||
method: 'bisect_left',
|
method: "bisect_left",
|
||||||
freeze: true,
|
freeze: true,
|
||||||
freeze_message: __("Bisecting Left ..."),
|
freeze_message: __("Bisecting Left ..."),
|
||||||
callback: (r) => {
|
callback: (r) => {
|
||||||
frm.trigger("render_heatmap");
|
frm.trigger("render_heatmap");
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
bisect_right(frm) {
|
bisect_right(frm) {
|
||||||
@@ -69,10 +69,10 @@ frappe.ui.form.on("Bisect Accounting Statements", {
|
|||||||
doc: frm.doc,
|
doc: frm.doc,
|
||||||
freeze: true,
|
freeze: true,
|
||||||
freeze_message: __("Bisecting Right ..."),
|
freeze_message: __("Bisecting Right ..."),
|
||||||
method: 'bisect_right',
|
method: "bisect_right",
|
||||||
callback: (r) => {
|
callback: (r) => {
|
||||||
frm.trigger("render_heatmap");
|
frm.trigger("render_heatmap");
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
move_up(frm) {
|
move_up(frm) {
|
||||||
@@ -80,10 +80,10 @@ frappe.ui.form.on("Bisect Accounting Statements", {
|
|||||||
doc: frm.doc,
|
doc: frm.doc,
|
||||||
freeze: true,
|
freeze: true,
|
||||||
freeze_message: __("Moving up in tree ..."),
|
freeze_message: __("Moving up in tree ..."),
|
||||||
method: 'move_up',
|
method: "move_up",
|
||||||
callback: (r) => {
|
callback: (r) => {
|
||||||
frm.trigger("render_heatmap");
|
frm.trigger("render_heatmap");
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
build_tree(frm) {
|
build_tree(frm) {
|
||||||
@@ -91,10 +91,10 @@ frappe.ui.form.on("Bisect Accounting Statements", {
|
|||||||
doc: frm.doc,
|
doc: frm.doc,
|
||||||
freeze: true,
|
freeze: true,
|
||||||
freeze_message: __("Rebuilding BTree for period ..."),
|
freeze_message: __("Rebuilding BTree for period ..."),
|
||||||
method: 'build_tree',
|
method: "build_tree",
|
||||||
callback: (r) => {
|
callback: (r) => {
|
||||||
frm.trigger("render_heatmap");
|
frm.trigger("render_heatmap");
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -170,7 +170,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-12-01 16:49:54.073890",
|
"modified": "2024-03-27 13:06:39.619458",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Bisect Accounting Statements",
|
"name": "Bisect Accounting Statements",
|
||||||
@@ -188,7 +188,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"sort_field": "modified",
|
"sort_field": "creation",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"states": []
|
"states": []
|
||||||
}
|
}
|
||||||
@@ -138,10 +138,11 @@ class BisectAccountingStatements(Document):
|
|||||||
|
|
||||||
# set root as current node
|
# set root as current node
|
||||||
root = frappe.db.get_all("Bisect Nodes", filters={"root": ["is", "not set"]})[0]
|
root = frappe.db.get_all("Bisect Nodes", filters={"root": ["is", "not set"]})[0]
|
||||||
self.get_report_summary()
|
|
||||||
self.current_node = root.name
|
self.current_node = root.name
|
||||||
self.current_from_date = self.from_date
|
self.current_from_date = self.from_date
|
||||||
self.current_to_date = self.to_date
|
self.current_to_date = self.to_date
|
||||||
|
|
||||||
|
self.get_report_summary()
|
||||||
self.save()
|
self.save()
|
||||||
|
|
||||||
def get_report_summary(self):
|
def get_report_summary(self):
|
||||||
|
|||||||
@@ -70,7 +70,7 @@
|
|||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-12-01 17:46:12.437996",
|
"modified": "2024-03-27 13:06:39.766063",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Bisect Nodes",
|
"name": "Bisect Nodes",
|
||||||
@@ -91,7 +91,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"sort_field": "modified",
|
"sort_field": "creation",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"states": []
|
"states": []
|
||||||
}
|
}
|
||||||
@@ -2,23 +2,23 @@
|
|||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
frappe.provide("erpnext.accounts.dimensions");
|
frappe.provide("erpnext.accounts.dimensions");
|
||||||
|
|
||||||
frappe.ui.form.on('Budget', {
|
frappe.ui.form.on("Budget", {
|
||||||
onload: function (frm) {
|
onload: function (frm) {
|
||||||
frm.set_query("account", "accounts", function () {
|
frm.set_query("account", "accounts", function () {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
company: frm.doc.company,
|
company: frm.doc.company,
|
||||||
report_type: "Profit and Loss",
|
report_type: "Profit and Loss",
|
||||||
is_group: 0
|
is_group: 0,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
frm.set_query("monthly_distribution", function () {
|
frm.set_query("monthly_distribution", function () {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
fiscal_year: frm.doc.fiscal_year
|
fiscal_year: frm.doc.fiscal_year,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -26,24 +26,24 @@ frappe.ui.form.on('Budget', {
|
|||||||
},
|
},
|
||||||
|
|
||||||
refresh: function (frm) {
|
refresh: function (frm) {
|
||||||
frm.trigger("toggle_reqd_fields")
|
frm.trigger("toggle_reqd_fields");
|
||||||
},
|
},
|
||||||
|
|
||||||
budget_against: function (frm) {
|
budget_against: function (frm) {
|
||||||
frm.trigger("set_null_value")
|
frm.trigger("set_null_value");
|
||||||
frm.trigger("toggle_reqd_fields")
|
frm.trigger("toggle_reqd_fields");
|
||||||
},
|
},
|
||||||
|
|
||||||
set_null_value: function (frm) {
|
set_null_value: function (frm) {
|
||||||
if(frm.doc.budget_against == 'Cost Center') {
|
if (frm.doc.budget_against == "Cost Center") {
|
||||||
frm.set_value('project', null)
|
frm.set_value("project", null);
|
||||||
} else {
|
} else {
|
||||||
frm.set_value('cost_center', null)
|
frm.set_value("cost_center", null);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
toggle_reqd_fields: function (frm) {
|
toggle_reqd_fields: function (frm) {
|
||||||
frm.toggle_reqd("cost_center", frm.doc.budget_against == "Cost Center");
|
frm.toggle_reqd("cost_center", frm.doc.budget_against == "Cost Center");
|
||||||
frm.toggle_reqd("project", frm.doc.budget_against == "Project");
|
frm.toggle_reqd("project", frm.doc.budget_against == "Project");
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -207,7 +207,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2022-10-10 22:14:36.361509",
|
"modified": "2024-03-27 13:06:42.675933",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Budget",
|
"name": "Budget",
|
||||||
@@ -231,7 +231,7 @@
|
|||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"sort_field": "modified",
|
"sort_field": "creation",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"states": [],
|
"states": [],
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
|
|||||||
@@ -70,10 +70,11 @@ class Budget(Document):
|
|||||||
select
|
select
|
||||||
b.name, ba.account from `tabBudget` b, `tabBudget Account` ba
|
b.name, ba.account from `tabBudget` b, `tabBudget Account` ba
|
||||||
where
|
where
|
||||||
ba.parent = b.name and b.docstatus < 2 and b.company = %s and %s=%s and
|
ba.parent = b.name and b.docstatus < 2 and b.company = {} and {}={} and
|
||||||
b.fiscal_year=%s and b.name != %s and ba.account in (%s) """
|
b.fiscal_year={} and b.name != {} and ba.account in ({}) """.format(
|
||||||
% ("%s", budget_against_field, "%s", "%s", "%s", ",".join(["%s"] * len(accounts))),
|
"%s", budget_against_field, "%s", "%s", "%s", ",".join(["%s"] * len(accounts))
|
||||||
(self.company, budget_against, self.fiscal_year, self.name) + tuple(accounts),
|
),
|
||||||
|
(self.company, budget_against, self.fiscal_year, self.name, *tuple(accounts)),
|
||||||
as_dict=1,
|
as_dict=1,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -96,12 +97,14 @@ class Budget(Document):
|
|||||||
if account_details.is_group:
|
if account_details.is_group:
|
||||||
frappe.throw(_("Budget cannot be assigned against Group Account {0}").format(d.account))
|
frappe.throw(_("Budget cannot be assigned against Group Account {0}").format(d.account))
|
||||||
elif account_details.company != self.company:
|
elif account_details.company != self.company:
|
||||||
frappe.throw(_("Account {0} does not belongs to company {1}").format(d.account, self.company))
|
frappe.throw(
|
||||||
|
_("Account {0} does not belongs to company {1}").format(d.account, self.company)
|
||||||
|
)
|
||||||
elif account_details.report_type != "Profit and Loss":
|
elif account_details.report_type != "Profit and Loss":
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_("Budget cannot be assigned against {0}, as it's not an Income or Expense account").format(
|
_(
|
||||||
d.account
|
"Budget cannot be assigned against {0}, as it's not an Income or Expense account"
|
||||||
)
|
).format(d.account)
|
||||||
)
|
)
|
||||||
|
|
||||||
if d.account in account_list:
|
if d.account in account_list:
|
||||||
@@ -139,6 +142,8 @@ class Budget(Document):
|
|||||||
|
|
||||||
def validate_expense_against_budget(args, expense_amount=0):
|
def validate_expense_against_budget(args, expense_amount=0):
|
||||||
args = frappe._dict(args)
|
args = frappe._dict(args)
|
||||||
|
if not frappe.get_all("Budget", limit=1):
|
||||||
|
return
|
||||||
|
|
||||||
if args.get("company") and not args.fiscal_year:
|
if args.get("company") and not args.fiscal_year:
|
||||||
args.fiscal_year = get_fiscal_year(args.get("posting_date"), company=args.get("company"))[0]
|
args.fiscal_year = get_fiscal_year(args.get("posting_date"), company=args.get("company"))[0]
|
||||||
@@ -146,6 +151,9 @@ def validate_expense_against_budget(args, expense_amount=0):
|
|||||||
"Company", args.get("company"), "exception_budget_approver_role"
|
"Company", args.get("company"), "exception_budget_approver_role"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if not frappe.get_cached_value("Budget", {"fiscal_year": args.fiscal_year, "company": args.company}): # nosec
|
||||||
|
return
|
||||||
|
|
||||||
if not args.account:
|
if not args.account:
|
||||||
args.account = args.get("expense_account")
|
args.account = args.get("expense_account")
|
||||||
|
|
||||||
@@ -172,32 +180,26 @@ def validate_expense_against_budget(args, expense_amount=0):
|
|||||||
if (
|
if (
|
||||||
args.get(budget_against)
|
args.get(budget_against)
|
||||||
and args.account
|
and args.account
|
||||||
and frappe.db.get_value("Account", {"name": args.account, "root_type": "Expense"})
|
and (frappe.get_cached_value("Account", args.account, "root_type") == "Expense")
|
||||||
):
|
):
|
||||||
|
|
||||||
doctype = dimension.get("document_type")
|
doctype = dimension.get("document_type")
|
||||||
|
|
||||||
if frappe.get_cached_value("DocType", doctype, "is_tree"):
|
if frappe.get_cached_value("DocType", doctype, "is_tree"):
|
||||||
lft, rgt = frappe.db.get_value(doctype, args.get(budget_against), ["lft", "rgt"])
|
lft, rgt = frappe.get_cached_value(doctype, args.get(budget_against), ["lft", "rgt"])
|
||||||
condition = """and exists(select name from `tab%s`
|
condition = f"""and exists(select name from `tab{doctype}`
|
||||||
where lft<=%s and rgt>=%s and name=b.%s)""" % (
|
where lft<={lft} and rgt>={rgt} and name=b.{budget_against})""" # nosec
|
||||||
doctype,
|
|
||||||
lft,
|
|
||||||
rgt,
|
|
||||||
budget_against,
|
|
||||||
) # nosec
|
|
||||||
args.is_tree = True
|
args.is_tree = True
|
||||||
else:
|
else:
|
||||||
condition = "and b.%s=%s" % (budget_against, frappe.db.escape(args.get(budget_against)))
|
condition = f"and b.{budget_against}={frappe.db.escape(args.get(budget_against))}"
|
||||||
args.is_tree = False
|
args.is_tree = False
|
||||||
|
|
||||||
args.budget_against_field = budget_against
|
args.budget_against_field = budget_against
|
||||||
args.budget_against_doctype = doctype
|
args.budget_against_doctype = doctype
|
||||||
|
|
||||||
budget_records = frappe.db.sql(
|
budget_records = frappe.db.sql(
|
||||||
"""
|
f"""
|
||||||
select
|
select
|
||||||
b.{budget_against_field} as budget_against, ba.budget_amount, b.monthly_distribution,
|
b.{budget_against} as budget_against, ba.budget_amount, b.monthly_distribution,
|
||||||
ifnull(b.applicable_on_material_request, 0) as for_material_request,
|
ifnull(b.applicable_on_material_request, 0) as for_material_request,
|
||||||
ifnull(applicable_on_purchase_order, 0) as for_purchase_order,
|
ifnull(applicable_on_purchase_order, 0) as for_purchase_order,
|
||||||
ifnull(applicable_on_booking_actual_expenses,0) as for_actual_expenses,
|
ifnull(applicable_on_booking_actual_expenses,0) as for_actual_expenses,
|
||||||
@@ -210,9 +212,7 @@ def validate_expense_against_budget(args, expense_amount=0):
|
|||||||
b.name=ba.parent and b.fiscal_year=%s
|
b.name=ba.parent and b.fiscal_year=%s
|
||||||
and ba.account=%s and b.docstatus=1
|
and ba.account=%s and b.docstatus=1
|
||||||
{condition}
|
{condition}
|
||||||
""".format(
|
""",
|
||||||
condition=condition, budget_against_field=budget_against
|
|
||||||
),
|
|
||||||
(args.fiscal_year, args.account),
|
(args.fiscal_year, args.account),
|
||||||
as_dict=True,
|
as_dict=True,
|
||||||
) # nosec
|
) # nosec
|
||||||
@@ -224,12 +224,18 @@ def validate_expense_against_budget(args, expense_amount=0):
|
|||||||
def validate_budget_records(args, budget_records, expense_amount):
|
def validate_budget_records(args, budget_records, expense_amount):
|
||||||
for budget in budget_records:
|
for budget in budget_records:
|
||||||
if flt(budget.budget_amount):
|
if flt(budget.budget_amount):
|
||||||
amount = expense_amount or get_amount(args, budget)
|
|
||||||
yearly_action, monthly_action = get_actions(args, budget)
|
yearly_action, monthly_action = get_actions(args, budget)
|
||||||
|
args["for_material_request"] = budget.for_material_request
|
||||||
|
args["for_purchase_order"] = budget.for_purchase_order
|
||||||
|
|
||||||
if yearly_action in ("Stop", "Warn"):
|
if yearly_action in ("Stop", "Warn"):
|
||||||
compare_expense_with_budget(
|
compare_expense_with_budget(
|
||||||
args, flt(budget.budget_amount), _("Annual"), yearly_action, budget.budget_against, amount
|
args,
|
||||||
|
flt(budget.budget_amount),
|
||||||
|
_("Annual"),
|
||||||
|
yearly_action,
|
||||||
|
budget.budget_against,
|
||||||
|
expense_amount,
|
||||||
)
|
)
|
||||||
|
|
||||||
if monthly_action in ["Stop", "Warn"]:
|
if monthly_action in ["Stop", "Warn"]:
|
||||||
@@ -240,18 +246,32 @@ def validate_budget_records(args, budget_records, expense_amount):
|
|||||||
args["month_end_date"] = get_last_day(args.posting_date)
|
args["month_end_date"] = get_last_day(args.posting_date)
|
||||||
|
|
||||||
compare_expense_with_budget(
|
compare_expense_with_budget(
|
||||||
args, budget_amount, _("Accumulated Monthly"), monthly_action, budget.budget_against, amount
|
args,
|
||||||
|
budget_amount,
|
||||||
|
_("Accumulated Monthly"),
|
||||||
|
monthly_action,
|
||||||
|
budget.budget_against,
|
||||||
|
expense_amount,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def compare_expense_with_budget(args, budget_amount, action_for, action, budget_against, amount=0):
|
def compare_expense_with_budget(args, budget_amount, action_for, action, budget_against, amount=0):
|
||||||
actual_expense = get_actual_expense(args)
|
args.actual_expense, args.requested_amount, args.ordered_amount = get_actual_expense(args), 0, 0
|
||||||
total_expense = actual_expense + amount
|
if not amount:
|
||||||
|
args.requested_amount, args.ordered_amount = get_requested_amount(args), get_ordered_amount(args)
|
||||||
|
|
||||||
|
if args.get("doctype") == "Material Request" and args.for_material_request:
|
||||||
|
amount = args.requested_amount + args.ordered_amount
|
||||||
|
|
||||||
|
elif args.get("doctype") == "Purchase Order" and args.for_purchase_order:
|
||||||
|
amount = args.ordered_amount
|
||||||
|
|
||||||
|
total_expense = args.actual_expense + amount
|
||||||
|
|
||||||
if total_expense > budget_amount:
|
if total_expense > budget_amount:
|
||||||
if actual_expense > budget_amount:
|
if args.actual_expense > budget_amount:
|
||||||
error_tense = _("is already")
|
error_tense = _("is already")
|
||||||
diff = actual_expense - budget_amount
|
diff = args.actual_expense - budget_amount
|
||||||
else:
|
else:
|
||||||
error_tense = _("will be")
|
error_tense = _("will be")
|
||||||
diff = total_expense - budget_amount
|
diff = total_expense - budget_amount
|
||||||
@@ -268,9 +288,10 @@ def compare_expense_with_budget(args, budget_amount, action_for, action, budget_
|
|||||||
frappe.bold(fmt_money(diff, currency=currency)),
|
frappe.bold(fmt_money(diff, currency=currency)),
|
||||||
)
|
)
|
||||||
|
|
||||||
if (
|
msg += get_expense_breakup(args, currency, budget_against)
|
||||||
frappe.flags.exception_approver_role
|
|
||||||
and frappe.flags.exception_approver_role in frappe.get_roles(frappe.session.user)
|
if frappe.flags.exception_approver_role and frappe.flags.exception_approver_role in frappe.get_roles(
|
||||||
|
frappe.session.user
|
||||||
):
|
):
|
||||||
action = "Warn"
|
action = "Warn"
|
||||||
|
|
||||||
@@ -280,6 +301,83 @@ def compare_expense_with_budget(args, budget_amount, action_for, action, budget_
|
|||||||
frappe.msgprint(msg, indicator="orange", title=_("Budget Exceeded"))
|
frappe.msgprint(msg, indicator="orange", title=_("Budget Exceeded"))
|
||||||
|
|
||||||
|
|
||||||
|
def get_expense_breakup(args, currency, budget_against):
|
||||||
|
msg = "<hr>Total Expenses booked through - <ul>"
|
||||||
|
|
||||||
|
common_filters = frappe._dict(
|
||||||
|
{
|
||||||
|
args.budget_against_field: budget_against,
|
||||||
|
"account": args.account,
|
||||||
|
"company": args.company,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
msg += (
|
||||||
|
"<li>"
|
||||||
|
+ frappe.utils.get_link_to_report(
|
||||||
|
"General Ledger",
|
||||||
|
label="Actual Expenses",
|
||||||
|
filters=common_filters.copy().update(
|
||||||
|
{
|
||||||
|
"from_date": frappe.get_cached_value("Fiscal Year", args.fiscal_year, "year_start_date"),
|
||||||
|
"to_date": frappe.get_cached_value("Fiscal Year", args.fiscal_year, "year_end_date"),
|
||||||
|
"is_cancelled": 0,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
+ " - "
|
||||||
|
+ frappe.bold(fmt_money(args.actual_expense, currency=currency))
|
||||||
|
+ "</li>"
|
||||||
|
)
|
||||||
|
|
||||||
|
msg += (
|
||||||
|
"<li>"
|
||||||
|
+ frappe.utils.get_link_to_report(
|
||||||
|
"Material Request",
|
||||||
|
label="Material Requests",
|
||||||
|
report_type="Report Builder",
|
||||||
|
doctype="Material Request",
|
||||||
|
filters=common_filters.copy().update(
|
||||||
|
{
|
||||||
|
"status": [["!=", "Stopped"]],
|
||||||
|
"docstatus": 1,
|
||||||
|
"material_request_type": "Purchase",
|
||||||
|
"schedule_date": [["fiscal year", "2023-2024"]],
|
||||||
|
"item_code": args.item_code,
|
||||||
|
"per_ordered": [["<", 100]],
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
+ " - "
|
||||||
|
+ frappe.bold(fmt_money(args.requested_amount, currency=currency))
|
||||||
|
+ "</li>"
|
||||||
|
)
|
||||||
|
|
||||||
|
msg += (
|
||||||
|
"<li>"
|
||||||
|
+ frappe.utils.get_link_to_report(
|
||||||
|
"Purchase Order",
|
||||||
|
label="Unbilled Orders",
|
||||||
|
report_type="Report Builder",
|
||||||
|
doctype="Purchase Order",
|
||||||
|
filters=common_filters.copy().update(
|
||||||
|
{
|
||||||
|
"status": [["!=", "Closed"]],
|
||||||
|
"docstatus": 1,
|
||||||
|
"transaction_date": [["fiscal year", "2023-2024"]],
|
||||||
|
"item_code": args.item_code,
|
||||||
|
"per_billed": [["<", 100]],
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
+ " - "
|
||||||
|
+ frappe.bold(fmt_money(args.ordered_amount, currency=currency))
|
||||||
|
+ "</li></ul>"
|
||||||
|
)
|
||||||
|
|
||||||
|
return msg
|
||||||
|
|
||||||
|
|
||||||
def get_actions(args, budget):
|
def get_actions(args, budget):
|
||||||
yearly_action = budget.action_if_annual_budget_exceeded
|
yearly_action = budget.action_if_annual_budget_exceeded
|
||||||
monthly_action = budget.action_if_accumulated_monthly_budget_exceeded
|
monthly_action = budget.action_if_accumulated_monthly_budget_exceeded
|
||||||
@@ -295,31 +393,15 @@ def get_actions(args, budget):
|
|||||||
return yearly_action, monthly_action
|
return yearly_action, monthly_action
|
||||||
|
|
||||||
|
|
||||||
def get_amount(args, budget):
|
def get_requested_amount(args):
|
||||||
amount = 0
|
|
||||||
|
|
||||||
if args.get("doctype") == "Material Request" and budget.for_material_request:
|
|
||||||
amount = (
|
|
||||||
get_requested_amount(args, budget) + get_ordered_amount(args, budget) + get_actual_expense(args)
|
|
||||||
)
|
|
||||||
|
|
||||||
elif args.get("doctype") == "Purchase Order" and budget.for_purchase_order:
|
|
||||||
amount = get_ordered_amount(args, budget) + get_actual_expense(args)
|
|
||||||
|
|
||||||
return amount
|
|
||||||
|
|
||||||
|
|
||||||
def get_requested_amount(args, budget):
|
|
||||||
item_code = args.get("item_code")
|
item_code = args.get("item_code")
|
||||||
condition = get_other_condition(args, budget, "Material Request")
|
condition = get_other_condition(args, "Material Request")
|
||||||
|
|
||||||
data = frappe.db.sql(
|
data = frappe.db.sql(
|
||||||
""" select ifnull((sum(child.stock_qty - child.ordered_qty) * rate), 0) as amount
|
""" select ifnull((sum(child.stock_qty - child.ordered_qty) * rate), 0) as amount
|
||||||
from `tabMaterial Request Item` child, `tabMaterial Request` parent where parent.name = child.parent and
|
from `tabMaterial Request Item` child, `tabMaterial Request` parent where parent.name = child.parent and
|
||||||
child.item_code = %s and parent.docstatus = 1 and child.stock_qty > child.ordered_qty and {0} and
|
child.item_code = %s and parent.docstatus = 1 and child.stock_qty > child.ordered_qty and {} and
|
||||||
parent.material_request_type = 'Purchase' and parent.status != 'Stopped'""".format(
|
parent.material_request_type = 'Purchase' and parent.status != 'Stopped'""".format(condition),
|
||||||
condition
|
|
||||||
),
|
|
||||||
item_code,
|
item_code,
|
||||||
as_list=1,
|
as_list=1,
|
||||||
)
|
)
|
||||||
@@ -327,17 +409,15 @@ def get_requested_amount(args, budget):
|
|||||||
return data[0][0] if data else 0
|
return data[0][0] if data else 0
|
||||||
|
|
||||||
|
|
||||||
def get_ordered_amount(args, budget):
|
def get_ordered_amount(args):
|
||||||
item_code = args.get("item_code")
|
item_code = args.get("item_code")
|
||||||
condition = get_other_condition(args, budget, "Purchase Order")
|
condition = get_other_condition(args, "Purchase Order")
|
||||||
|
|
||||||
data = frappe.db.sql(
|
data = frappe.db.sql(
|
||||||
""" select ifnull(sum(child.amount - child.billed_amt), 0) as amount
|
f""" select ifnull(sum(child.amount - child.billed_amt), 0) as amount
|
||||||
from `tabPurchase Order Item` child, `tabPurchase Order` parent where
|
from `tabPurchase Order Item` child, `tabPurchase Order` parent where
|
||||||
parent.name = child.parent and child.item_code = %s and parent.docstatus = 1 and child.amount > child.billed_amt
|
parent.name = child.parent and child.item_code = %s and parent.docstatus = 1 and child.amount > child.billed_amt
|
||||||
and parent.status != 'Closed' and {0}""".format(
|
and parent.status != 'Closed' and {condition}""",
|
||||||
condition
|
|
||||||
),
|
|
||||||
item_code,
|
item_code,
|
||||||
as_list=1,
|
as_list=1,
|
||||||
)
|
)
|
||||||
@@ -345,12 +425,12 @@ def get_ordered_amount(args, budget):
|
|||||||
return data[0][0] if data else 0
|
return data[0][0] if data else 0
|
||||||
|
|
||||||
|
|
||||||
def get_other_condition(args, budget, for_doc):
|
def get_other_condition(args, for_doc):
|
||||||
condition = "expense_account = '%s'" % (args.expense_account)
|
condition = "expense_account = '%s'" % (args.expense_account)
|
||||||
budget_against_field = args.get("budget_against_field")
|
budget_against_field = args.get("budget_against_field")
|
||||||
|
|
||||||
if budget_against_field and args.get(budget_against_field):
|
if budget_against_field and args.get(budget_against_field):
|
||||||
condition += " and child.%s = '%s'" % (budget_against_field, args.get(budget_against_field))
|
condition += f" and child.{budget_against_field} = '{args.get(budget_against_field)}'"
|
||||||
|
|
||||||
if args.get("fiscal_year"):
|
if args.get("fiscal_year"):
|
||||||
date_field = "schedule_date" if for_doc == "Material Request" else "transaction_date"
|
date_field = "schedule_date" if for_doc == "Material Request" else "transaction_date"
|
||||||
@@ -358,12 +438,8 @@ def get_other_condition(args, budget, for_doc):
|
|||||||
"Fiscal Year", args.get("fiscal_year"), ["year_start_date", "year_end_date"]
|
"Fiscal Year", args.get("fiscal_year"), ["year_start_date", "year_end_date"]
|
||||||
)
|
)
|
||||||
|
|
||||||
condition += """ and parent.%s
|
condition += f""" and parent.{date_field}
|
||||||
between '%s' and '%s' """ % (
|
between '{start_date}' and '{end_date}' """
|
||||||
date_field,
|
|
||||||
start_date,
|
|
||||||
end_date,
|
|
||||||
)
|
|
||||||
|
|
||||||
return condition
|
return condition
|
||||||
|
|
||||||
@@ -382,21 +458,17 @@ def get_actual_expense(args):
|
|||||||
|
|
||||||
args.update(lft_rgt)
|
args.update(lft_rgt)
|
||||||
|
|
||||||
condition2 = """and exists(select name from `tab{doctype}`
|
condition2 = f"""and exists(select name from `tab{args.budget_against_doctype}`
|
||||||
where lft>=%(lft)s and rgt<=%(rgt)s
|
where lft>=%(lft)s and rgt<=%(rgt)s
|
||||||
and name=gle.{budget_against_field})""".format(
|
and name=gle.{budget_against_field})"""
|
||||||
doctype=args.budget_against_doctype, budget_against_field=budget_against_field # nosec
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
condition2 = """and exists(select name from `tab{doctype}`
|
condition2 = f"""and exists(select name from `tab{args.budget_against_doctype}`
|
||||||
where name=gle.{budget_against} and
|
where name=gle.{budget_against_field} and
|
||||||
gle.{budget_against} = %({budget_against})s)""".format(
|
gle.{budget_against_field} = %({budget_against_field})s)"""
|
||||||
doctype=args.budget_against_doctype, budget_against=budget_against_field
|
|
||||||
)
|
|
||||||
|
|
||||||
amount = flt(
|
amount = flt(
|
||||||
frappe.db.sql(
|
frappe.db.sql(
|
||||||
"""
|
f"""
|
||||||
select sum(gle.debit) - sum(gle.credit)
|
select sum(gle.debit) - sum(gle.credit)
|
||||||
from `tabGL Entry` gle
|
from `tabGL Entry` gle
|
||||||
where
|
where
|
||||||
@@ -407,9 +479,7 @@ def get_actual_expense(args):
|
|||||||
and gle.company=%(company)s
|
and gle.company=%(company)s
|
||||||
and gle.docstatus=1
|
and gle.docstatus=1
|
||||||
{condition2}
|
{condition2}
|
||||||
""".format(
|
""",
|
||||||
condition1=condition1, condition2=condition2
|
|
||||||
),
|
|
||||||
(args),
|
(args),
|
||||||
)[0][0]
|
)[0][0]
|
||||||
) # nosec
|
) # nosec
|
||||||
|
|||||||
@@ -41,9 +41,7 @@ class TestBudget(unittest.TestCase):
|
|||||||
|
|
||||||
budget = make_budget(budget_against="Cost Center")
|
budget = make_budget(budget_against="Cost Center")
|
||||||
|
|
||||||
frappe.db.set_value(
|
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
|
||||||
"Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop"
|
|
||||||
)
|
|
||||||
|
|
||||||
jv = make_journal_entry(
|
jv = make_journal_entry(
|
||||||
"_Test Account Cost for Goods Sold - _TC",
|
"_Test Account Cost for Goods Sold - _TC",
|
||||||
@@ -63,9 +61,7 @@ class TestBudget(unittest.TestCase):
|
|||||||
|
|
||||||
budget = make_budget(budget_against="Cost Center")
|
budget = make_budget(budget_against="Cost Center")
|
||||||
|
|
||||||
frappe.db.set_value(
|
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
|
||||||
"Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop"
|
|
||||||
)
|
|
||||||
|
|
||||||
jv = make_journal_entry(
|
jv = make_journal_entry(
|
||||||
"_Test Account Cost for Goods Sold - _TC",
|
"_Test Account Cost for Goods Sold - _TC",
|
||||||
@@ -97,9 +93,7 @@ class TestBudget(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
fiscal_year = get_fiscal_year(nowdate())[0]
|
fiscal_year = get_fiscal_year(nowdate())[0]
|
||||||
frappe.db.set_value(
|
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
|
||||||
"Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop"
|
|
||||||
)
|
|
||||||
frappe.db.set_value("Budget", budget.name, "fiscal_year", fiscal_year)
|
frappe.db.set_value("Budget", budget.name, "fiscal_year", fiscal_year)
|
||||||
|
|
||||||
mr = frappe.get_doc(
|
mr = frappe.get_doc(
|
||||||
@@ -138,9 +132,7 @@ class TestBudget(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
fiscal_year = get_fiscal_year(nowdate())[0]
|
fiscal_year = get_fiscal_year(nowdate())[0]
|
||||||
frappe.db.set_value(
|
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
|
||||||
"Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop"
|
|
||||||
)
|
|
||||||
frappe.db.set_value("Budget", budget.name, "fiscal_year", fiscal_year)
|
frappe.db.set_value("Budget", budget.name, "fiscal_year", fiscal_year)
|
||||||
|
|
||||||
po = create_purchase_order(transaction_date=nowdate(), do_not_submit=True)
|
po = create_purchase_order(transaction_date=nowdate(), do_not_submit=True)
|
||||||
@@ -158,9 +150,7 @@ class TestBudget(unittest.TestCase):
|
|||||||
|
|
||||||
budget = make_budget(budget_against="Project")
|
budget = make_budget(budget_against="Project")
|
||||||
|
|
||||||
frappe.db.set_value(
|
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
|
||||||
"Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop"
|
|
||||||
)
|
|
||||||
|
|
||||||
project = frappe.get_value("Project", {"project_name": "_Test Project"})
|
project = frappe.get_value("Project", {"project_name": "_Test Project"})
|
||||||
|
|
||||||
@@ -223,7 +213,7 @@ class TestBudget(unittest.TestCase):
|
|||||||
if month > 9:
|
if month > 9:
|
||||||
month = 9
|
month = 9
|
||||||
|
|
||||||
for i in range(month + 1):
|
for _i in range(month + 1):
|
||||||
jv = make_journal_entry(
|
jv = make_journal_entry(
|
||||||
"_Test Account Cost for Goods Sold - _TC",
|
"_Test Account Cost for Goods Sold - _TC",
|
||||||
"_Test Bank - _TC",
|
"_Test Bank - _TC",
|
||||||
@@ -237,9 +227,7 @@ class TestBudget(unittest.TestCase):
|
|||||||
frappe.db.get_value("GL Entry", {"voucher_type": "Journal Entry", "voucher_no": jv.name})
|
frappe.db.get_value("GL Entry", {"voucher_type": "Journal Entry", "voucher_no": jv.name})
|
||||||
)
|
)
|
||||||
|
|
||||||
frappe.db.set_value(
|
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
|
||||||
"Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop"
|
|
||||||
)
|
|
||||||
|
|
||||||
self.assertRaises(BudgetError, jv.cancel)
|
self.assertRaises(BudgetError, jv.cancel)
|
||||||
|
|
||||||
@@ -255,7 +243,7 @@ class TestBudget(unittest.TestCase):
|
|||||||
month = 9
|
month = 9
|
||||||
|
|
||||||
project = frappe.get_value("Project", {"project_name": "_Test Project"})
|
project = frappe.get_value("Project", {"project_name": "_Test Project"})
|
||||||
for i in range(month + 1):
|
for _i in range(month + 1):
|
||||||
jv = make_journal_entry(
|
jv = make_journal_entry(
|
||||||
"_Test Account Cost for Goods Sold - _TC",
|
"_Test Account Cost for Goods Sold - _TC",
|
||||||
"_Test Bank - _TC",
|
"_Test Bank - _TC",
|
||||||
@@ -270,9 +258,7 @@ class TestBudget(unittest.TestCase):
|
|||||||
frappe.db.get_value("GL Entry", {"voucher_type": "Journal Entry", "voucher_no": jv.name})
|
frappe.db.get_value("GL Entry", {"voucher_type": "Journal Entry", "voucher_no": jv.name})
|
||||||
)
|
)
|
||||||
|
|
||||||
frappe.db.set_value(
|
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
|
||||||
"Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop"
|
|
||||||
)
|
|
||||||
|
|
||||||
self.assertRaises(BudgetError, jv.cancel)
|
self.assertRaises(BudgetError, jv.cancel)
|
||||||
|
|
||||||
@@ -284,9 +270,7 @@ class TestBudget(unittest.TestCase):
|
|||||||
set_total_expense_zero(nowdate(), "cost_center", "_Test Cost Center 2 - _TC")
|
set_total_expense_zero(nowdate(), "cost_center", "_Test Cost Center 2 - _TC")
|
||||||
|
|
||||||
budget = make_budget(budget_against="Cost Center", cost_center="_Test Company - _TC")
|
budget = make_budget(budget_against="Cost Center", cost_center="_Test Company - _TC")
|
||||||
frappe.db.set_value(
|
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
|
||||||
"Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop"
|
|
||||||
)
|
|
||||||
|
|
||||||
jv = make_journal_entry(
|
jv = make_journal_entry(
|
||||||
"_Test Account Cost for Goods Sold - _TC",
|
"_Test Account Cost for Goods Sold - _TC",
|
||||||
@@ -316,9 +300,7 @@ class TestBudget(unittest.TestCase):
|
|||||||
).insert(ignore_permissions=True)
|
).insert(ignore_permissions=True)
|
||||||
|
|
||||||
budget = make_budget(budget_against="Cost Center", cost_center=cost_center)
|
budget = make_budget(budget_against="Cost Center", cost_center=cost_center)
|
||||||
frappe.db.set_value(
|
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
|
||||||
"Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop"
|
|
||||||
)
|
|
||||||
|
|
||||||
jv = make_journal_entry(
|
jv = make_journal_entry(
|
||||||
"_Test Account Cost for Goods Sold - _TC",
|
"_Test Account Cost for Goods Sold - _TC",
|
||||||
@@ -423,13 +405,11 @@ def make_budget(**args):
|
|||||||
fiscal_year = get_fiscal_year(nowdate())[0]
|
fiscal_year = get_fiscal_year(nowdate())[0]
|
||||||
|
|
||||||
if budget_against == "Project":
|
if budget_against == "Project":
|
||||||
project_name = "{0}%".format("_Test Project/" + fiscal_year)
|
project_name = "{}%".format("_Test Project/" + fiscal_year)
|
||||||
budget_list = frappe.get_all("Budget", fields=["name"], filters={"name": ("like", project_name)})
|
budget_list = frappe.get_all("Budget", fields=["name"], filters={"name": ("like", project_name)})
|
||||||
else:
|
else:
|
||||||
cost_center_name = "{0}%".format(cost_center or "_Test Cost Center - _TC/" + fiscal_year)
|
cost_center_name = "{}%".format(cost_center or "_Test Cost Center - _TC/" + fiscal_year)
|
||||||
budget_list = frappe.get_all(
|
budget_list = frappe.get_all("Budget", fields=["name"], filters={"name": ("like", cost_center_name)})
|
||||||
"Budget", fields=["name"], filters={"name": ("like", cost_center_name)}
|
|
||||||
)
|
|
||||||
for d in budget_list:
|
for d in budget_list:
|
||||||
frappe.db.sql("delete from `tabBudget` where name = %(name)s", d)
|
frappe.db.sql("delete from `tabBudget` where name = %(name)s", d)
|
||||||
frappe.db.sql("delete from `tabBudget Account` where parent = %(name)s", d)
|
frappe.db.sql("delete from `tabBudget Account` where parent = %(name)s", d)
|
||||||
@@ -451,24 +431,18 @@ def make_budget(**args):
|
|||||||
budget.action_if_annual_budget_exceeded = "Stop"
|
budget.action_if_annual_budget_exceeded = "Stop"
|
||||||
budget.action_if_accumulated_monthly_budget_exceeded = "Ignore"
|
budget.action_if_accumulated_monthly_budget_exceeded = "Ignore"
|
||||||
budget.budget_against = budget_against
|
budget.budget_against = budget_against
|
||||||
budget.append(
|
budget.append("accounts", {"account": "_Test Account Cost for Goods Sold - _TC", "budget_amount": 200000})
|
||||||
"accounts", {"account": "_Test Account Cost for Goods Sold - _TC", "budget_amount": 200000}
|
|
||||||
)
|
|
||||||
|
|
||||||
if args.applicable_on_material_request:
|
if args.applicable_on_material_request:
|
||||||
budget.applicable_on_material_request = 1
|
budget.applicable_on_material_request = 1
|
||||||
budget.action_if_annual_budget_exceeded_on_mr = (
|
budget.action_if_annual_budget_exceeded_on_mr = args.action_if_annual_budget_exceeded_on_mr or "Warn"
|
||||||
args.action_if_annual_budget_exceeded_on_mr or "Warn"
|
|
||||||
)
|
|
||||||
budget.action_if_accumulated_monthly_budget_exceeded_on_mr = (
|
budget.action_if_accumulated_monthly_budget_exceeded_on_mr = (
|
||||||
args.action_if_accumulated_monthly_budget_exceeded_on_mr or "Warn"
|
args.action_if_accumulated_monthly_budget_exceeded_on_mr or "Warn"
|
||||||
)
|
)
|
||||||
|
|
||||||
if args.applicable_on_purchase_order:
|
if args.applicable_on_purchase_order:
|
||||||
budget.applicable_on_purchase_order = 1
|
budget.applicable_on_purchase_order = 1
|
||||||
budget.action_if_annual_budget_exceeded_on_po = (
|
budget.action_if_annual_budget_exceeded_on_po = args.action_if_annual_budget_exceeded_on_po or "Warn"
|
||||||
args.action_if_annual_budget_exceeded_on_po or "Warn"
|
|
||||||
)
|
|
||||||
budget.action_if_accumulated_monthly_budget_exceeded_on_po = (
|
budget.action_if_accumulated_monthly_budget_exceeded_on_po = (
|
||||||
args.action_if_accumulated_monthly_budget_exceeded_on_po or "Warn"
|
args.action_if_accumulated_monthly_budget_exceeded_on_po or "Warn"
|
||||||
)
|
)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user