Compare commits
790 Commits
fix-get_si
...
pot_develo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a79c3d56e0 | ||
|
|
6d47b8a24e | ||
|
|
cefb8f69e5 | ||
|
|
1fc099dacf | ||
|
|
c46c329ed8 | ||
|
|
bb279e368c | ||
|
|
aec630c74f | ||
|
|
3cde81be65 | ||
|
|
2fadfd7cfc | ||
|
|
60ba25caf2 | ||
|
|
f3f6bc8042 | ||
|
|
b171784d85 | ||
|
|
c80356c7c9 | ||
|
|
c9039d767b | ||
|
|
4f396d3049 | ||
|
|
4d090bd3b8 | ||
|
|
1ff8a6f24f | ||
|
|
59222813af | ||
|
|
a84b9434a9 | ||
|
|
a1e8caa5c1 | ||
|
|
ec55831440 | ||
|
|
a06c3e9f9f | ||
|
|
80d3dd2846 | ||
|
|
a3d4aff29c | ||
|
|
3e0c798cca | ||
|
|
f504f2caf3 | ||
|
|
ad42389352 | ||
|
|
2a08072443 | ||
|
|
6d9074d585 | ||
|
|
5f15297f28 | ||
|
|
647bba0f00 | ||
|
|
898affbee9 | ||
|
|
4ed7e3eacd | ||
|
|
12029557fe | ||
|
|
b62a6b6ab0 | ||
|
|
a9a9b1297e | ||
|
|
437bdc2d8c | ||
|
|
62d2fe50d2 | ||
|
|
c417e7d800 | ||
|
|
ec83d54826 | ||
|
|
4cda88690f | ||
|
|
d15cdd9190 | ||
|
|
cd79dcccb6 | ||
|
|
f4a945aee4 | ||
|
|
65ae9616ba | ||
|
|
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 | ||
|
|
dedae4fecf | ||
|
|
0da19a40a7 | ||
|
|
7e301f02df | ||
|
|
b9a8dd468b | ||
|
|
a97a851333 | ||
|
|
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
|
||||
|
||||
# python, js indentation settings
|
||||
[{*.py,*.js}]
|
||||
[{*.py,*.js,*.vue,*.css,*.scss,*.html}]
|
||||
indent_style = tab
|
||||
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,
|
||||
"onScan": true,
|
||||
"extend_cscript": true,
|
||||
"localforage": true
|
||||
"localforage": true,
|
||||
"Plaid": true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,3 +32,6 @@ baec607ff5905b1c67531096a9cf50ec7ff00a5d
|
||||
|
||||
# bulk refactor with sourcery
|
||||
eb9ee3f79b94e594fc6dfa4f6514580e125eee8c
|
||||
|
||||
# js formatting
|
||||
ec74a5e56617bbd76ac402451468fd4668af543d
|
||||
|
||||
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
|
||||
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
|
||||
run: git clone --depth 1 https://github.com/frappe/semgrep-rules.git frappe-semgrep-rules
|
||||
|
||||
|
||||
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
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 18
|
||||
node-version: 20
|
||||
- name: Setup dependencies
|
||||
run: |
|
||||
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"
|
||||
12
.github/workflows/server-tests-mariadb.yml
vendored
12
.github/workflows/server-tests-mariadb.yml
vendored
@@ -31,6 +31,9 @@ jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
NODE_ENV: "production"
|
||||
WITH_COVERAGE: ${{ github.event_name != 'pull_request' }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -117,11 +120,11 @@ jobs:
|
||||
FRAPPE_BRANCH: ${{ github.event.inputs.branch }}
|
||||
|
||||
- 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:
|
||||
TYPE: server
|
||||
CI_BUILD_ID: ${{ github.run_id }}
|
||||
ORCHESTRATOR_URL: http://test-orchestrator.frappe.io
|
||||
CAPTURE_COVERAGE: ${{ github.event_name != 'pull_request' }}
|
||||
|
||||
|
||||
- name: Show bench output
|
||||
if: ${{ always() }}
|
||||
@@ -129,6 +132,7 @@ jobs:
|
||||
|
||||
- name: Upload coverage data
|
||||
uses: actions/upload-artifact@v3
|
||||
if: github.event_name != 'pull_request'
|
||||
with:
|
||||
name: coverage-${{ matrix.container }}
|
||||
path: /home/runner/frappe-bench/sites/coverage.xml
|
||||
@@ -137,6 +141,7 @@ jobs:
|
||||
name: Coverage Wrap Up
|
||||
needs: test
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
steps:
|
||||
- name: Clone
|
||||
uses: actions/checkout@v2
|
||||
@@ -148,5 +153,6 @@ jobs:
|
||||
uses: codecov/codecov-action@v2
|
||||
with:
|
||||
name: MariaDB
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
fail_ci_if_error: true
|
||||
verbose: true
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,7 +2,6 @@
|
||||
*.py~
|
||||
.DS_Store
|
||||
conf.py
|
||||
locale
|
||||
latest_updates.json
|
||||
.wnf-lang-status
|
||||
*.egg-info
|
||||
|
||||
@@ -20,6 +20,23 @@ repos:
|
||||
- id: check-yaml
|
||||
- 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
|
||||
rev: v8.44.0
|
||||
hooks:
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
<p>ERP made simple</p>
|
||||
</p>
|
||||
|
||||
[](https://github.com/frappe/erpnext/actions/workflows/server-tests.yml)
|
||||
[](https://github.com/erpnext/erpnext_ui_tests/actions/workflows/ui-tests.yml)
|
||||
[](https://github.com/frappe/erpnext/actions/workflows/server-tests-mariadb.yml)
|
||||
[](https://www.codetriage.com/frappe/erpnext)
|
||||
[](https://codecov.io/gh/frappe/erpnext)
|
||||
[](https://hub.docker.com/r/frappe/erpnext-worker)
|
||||
|
||||
@@ -1,25 +1,13 @@
|
||||
module.exports = {
|
||||
parserPreset: 'conventional-changelog-conventionalcommits',
|
||||
parserPreset: "conventional-changelog-conventionalcommits",
|
||||
rules: {
|
||||
'subject-empty': [2, 'never'],
|
||||
'type-case': [2, 'always', 'lower-case'],
|
||||
'type-empty': [2, 'never'],
|
||||
'type-enum': [
|
||||
"subject-empty": [2, "never"],
|
||||
"type-case": [2, "always", "lower-case"],
|
||||
"type-empty": [2, "never"],
|
||||
"type-enum": [
|
||||
2,
|
||||
'always',
|
||||
[
|
||||
'build',
|
||||
'chore',
|
||||
'ci',
|
||||
'docs',
|
||||
'feat',
|
||||
'fix',
|
||||
'perf',
|
||||
'refactor',
|
||||
'revert',
|
||||
'style',
|
||||
'test',
|
||||
],
|
||||
"always",
|
||||
["build", "chore", "ci", "docs", "feat", "fix", "perf", "refactor", "revert", "style", "test"],
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
4
crowdin.yml
Normal file
4
crowdin.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
files:
|
||||
- source: /erpnext/locale/main.pot
|
||||
translation: /erpnext/locale/%two_letters_code%.po
|
||||
pull_request_title: "chore: sync translations from crowdin"
|
||||
@@ -13,7 +13,7 @@ def get_default_company(user=None):
|
||||
if not user:
|
||||
user = frappe.session.user
|
||||
|
||||
companies = get_user_default_as_list(user, "company")
|
||||
companies = get_user_default_as_list("company", user)
|
||||
if companies:
|
||||
default_company = companies[0]
|
||||
else:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
frappe.provide('frappe.dashboards.chart_sources');
|
||||
frappe.provide("frappe.dashboards.chart_sources");
|
||||
|
||||
frappe.dashboards.chart_sources["Account Balance Timeline"] = {
|
||||
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",
|
||||
options: "Company",
|
||||
default: frappe.defaults.get_user_default("Company"),
|
||||
reqd: 1
|
||||
reqd: 1,
|
||||
},
|
||||
{
|
||||
fieldname: "account",
|
||||
label: __("Account"),
|
||||
fieldtype: "Link",
|
||||
options: "Account",
|
||||
reqd: 1
|
||||
reqd: 1,
|
||||
},
|
||||
]
|
||||
],
|
||||
};
|
||||
|
||||
@@ -358,11 +358,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)
|
||||
if doc.doctype == "Sales Invoice":
|
||||
against_type = "Customer"
|
||||
against, project = doc.customer, doc.project
|
||||
credit_account, debit_account = item.income_account, item.deferred_revenue_account
|
||||
else:
|
||||
against_type = "Supplier"
|
||||
against, project = doc.supplier, item.project
|
||||
credit_account, debit_account = item.deferred_expense_account, item.expense_account
|
||||
|
||||
@@ -415,7 +413,6 @@ def book_deferred_income_or_expense(doc, deferred_process, posting_date=None):
|
||||
doc,
|
||||
credit_account,
|
||||
debit_account,
|
||||
against_type,
|
||||
against,
|
||||
amount,
|
||||
base_amount,
|
||||
@@ -497,7 +494,6 @@ def make_gl_entries(
|
||||
doc,
|
||||
credit_account,
|
||||
debit_account,
|
||||
against_type,
|
||||
against,
|
||||
amount,
|
||||
base_amount,
|
||||
@@ -519,9 +515,7 @@ def make_gl_entries(
|
||||
doc.get_gl_dict(
|
||||
{
|
||||
"account": credit_account,
|
||||
"against_type": against_type,
|
||||
"against": against,
|
||||
"against_link": against,
|
||||
"credit": base_amount,
|
||||
"credit_in_account_currency": amount,
|
||||
"cost_center": cost_center,
|
||||
@@ -540,9 +534,7 @@ def make_gl_entries(
|
||||
doc.get_gl_dict(
|
||||
{
|
||||
"account": debit_account,
|
||||
"against_type": against_type,
|
||||
"against": against,
|
||||
"against_link": against,
|
||||
"debit": base_amount,
|
||||
"debit_in_account_currency": amount,
|
||||
"cost_center": cost_center,
|
||||
|
||||
@@ -26,19 +26,14 @@ frappe.ui.form.on("Account", {
|
||||
frm.toggle_enable(["is_group", "company"], false);
|
||||
|
||||
if (cint(frm.doc.is_group) == 0) {
|
||||
frm.toggle_display(
|
||||
"freeze_account",
|
||||
frm.doc.__onload && frm.doc.__onload.can_freeze_account
|
||||
);
|
||||
frm.toggle_display("freeze_account", frm.doc.__onload && frm.doc.__onload.can_freeze_account);
|
||||
}
|
||||
|
||||
// read-only for root accounts
|
||||
if (!frm.is_new()) {
|
||||
if (!frm.doc.parent_account) {
|
||||
frm.set_read_only();
|
||||
frm.set_intro(
|
||||
__("This is a root account and cannot be edited.")
|
||||
);
|
||||
frm.set_intro(__("This is a root account and cannot be edited."));
|
||||
} else {
|
||||
// credit days and type if customer or supplier
|
||||
frm.set_intro(null);
|
||||
@@ -80,27 +75,33 @@ frappe.ui.form.on("Account", {
|
||||
);
|
||||
|
||||
if (frm.doc.is_group == 1) {
|
||||
frm.add_custom_button(__('Convert to Non-Group'), function () {
|
||||
return frappe.call({
|
||||
doc: frm.doc,
|
||||
method: 'convert_group_to_ledger',
|
||||
callback: function() {
|
||||
frm.refresh();
|
||||
}
|
||||
});
|
||||
}, __('Actions'));
|
||||
|
||||
} else if (cint(frm.doc.is_group) == 0
|
||||
&& frappe.boot.user.can_read.indexOf("GL Entry") !== -1) {
|
||||
frm.add_custom_button(__('General Ledger'), function () {
|
||||
frappe.route_options = {
|
||||
"account": frm.doc.name,
|
||||
"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],
|
||||
"company": frm.doc.company
|
||||
};
|
||||
frappe.set_route("query-report", "General Ledger");
|
||||
}, __('View'));
|
||||
frm.add_custom_button(
|
||||
__("Convert to Non-Group"),
|
||||
function () {
|
||||
return frappe.call({
|
||||
doc: frm.doc,
|
||||
method: "convert_group_to_ledger",
|
||||
callback: function () {
|
||||
frm.refresh();
|
||||
},
|
||||
});
|
||||
},
|
||||
__("Actions")
|
||||
);
|
||||
} else if (cint(frm.doc.is_group) == 0 && frappe.boot.user.can_read.indexOf("GL Entry") !== -1) {
|
||||
frm.add_custom_button(
|
||||
__("General Ledger"),
|
||||
function () {
|
||||
frappe.route_options = {
|
||||
account: frm.doc.name,
|
||||
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],
|
||||
company: frm.doc.company,
|
||||
};
|
||||
frappe.set_route("query-report", "General Ledger");
|
||||
},
|
||||
__("View")
|
||||
);
|
||||
|
||||
frm.add_custom_button(
|
||||
__("Convert to Group"),
|
||||
@@ -193,14 +194,8 @@ frappe.ui.form.on("Account", {
|
||||
if (r.message) {
|
||||
frappe.set_route("Form", "Account", r.message);
|
||||
} else {
|
||||
frm.set_value(
|
||||
"account_number",
|
||||
data.account_number
|
||||
);
|
||||
frm.set_value(
|
||||
"account_name",
|
||||
data.account_name
|
||||
);
|
||||
frm.set_value("account_number", data.account_number);
|
||||
frm.set_value("account_name", data.account_name);
|
||||
}
|
||||
d.hide();
|
||||
}
|
||||
|
||||
@@ -108,6 +108,7 @@
|
||||
"fieldname": "parent_account",
|
||||
"fieldtype": "Link",
|
||||
"ignore_user_permissions": 1,
|
||||
"in_preview": 1,
|
||||
"label": "Parent Account",
|
||||
"oldfieldname": "parent_account",
|
||||
"oldfieldtype": "Link",
|
||||
@@ -192,7 +193,7 @@
|
||||
"idx": 1,
|
||||
"is_tree": 1,
|
||||
"links": [],
|
||||
"modified": "2023-07-20 18:18:44.405723",
|
||||
"modified": "2024-01-10 04:57:33.681676",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Account",
|
||||
@@ -249,8 +250,9 @@
|
||||
],
|
||||
"search_fields": "account_number",
|
||||
"show_name_in_global_search": 1,
|
||||
"show_preview_popup": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "ASC",
|
||||
"states": [],
|
||||
"track_changes": 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,6 +118,7 @@ class Account(NestedSet):
|
||||
self.validate_balance_must_be_debit_or_credit()
|
||||
self.validate_account_currency()
|
||||
self.validate_root_company_and_sync_account_to_children()
|
||||
self.validate_receivable_payable_account_type()
|
||||
|
||||
def validate_parent_child_account_type(self):
|
||||
if self.parent_account:
|
||||
@@ -188,6 +189,24 @@ class Account(NestedSet):
|
||||
"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):
|
||||
doc_before_save = self.get_doc_before_save()
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
frappe.provide("frappe.treeview_settings")
|
||||
frappe.provide("frappe.treeview_settings");
|
||||
|
||||
frappe.treeview_settings["Account"] = {
|
||||
breadcrumb: "Accounts",
|
||||
@@ -7,12 +7,12 @@ frappe.treeview_settings["Account"] = {
|
||||
filters: [
|
||||
{
|
||||
fieldname: "company",
|
||||
fieldtype:"Select",
|
||||
fieldtype: "Select",
|
||||
options: erpnext.utils.get_tree_options("company"),
|
||||
label: __("Company"),
|
||||
default: erpnext.utils.get_tree_default("company"),
|
||||
on_change: function() {
|
||||
var me = frappe.treeview_settings['Account'].treeview;
|
||||
on_change: function () {
|
||||
var me = frappe.treeview_settings["Account"].treeview;
|
||||
var company = me.page.fields_dict.company.get_value();
|
||||
if (!company) {
|
||||
frappe.throw(__("Please set a Company"));
|
||||
@@ -22,30 +22,36 @@ frappe.treeview_settings["Account"] = {
|
||||
args: {
|
||||
company: company,
|
||||
},
|
||||
callback: function(r) {
|
||||
if(r.message) {
|
||||
callback: function (r) {
|
||||
if (r.message) {
|
||||
let root_company = r.message.length ? r.message[0] : "";
|
||||
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.flags.ignore_root_company_validation = r.allow_account_creation_against_child_company;
|
||||
});
|
||||
frappe.db.get_value(
|
||||
"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",
|
||||
fieldtype:"Data",
|
||||
fieldtype: "Data",
|
||||
label: __("Root Company"),
|
||||
hidden: true,
|
||||
disable_onchange: true
|
||||
}
|
||||
disable_onchange: true,
|
||||
},
|
||||
],
|
||||
root_label: "Accounts",
|
||||
get_tree_nodes: 'erpnext.accounts.utils.get_children',
|
||||
on_get_node: function(nodes, deep=false) {
|
||||
get_tree_nodes: "erpnext.accounts.utils.get_children",
|
||||
on_get_node: function (nodes, deep = false) {
|
||||
if (frappe.boot.user.can_read.indexOf("GL Entry") == -1) return;
|
||||
|
||||
let accounts = [];
|
||||
@@ -57,151 +63,231 @@ frappe.treeview_settings["Account"] = {
|
||||
}
|
||||
|
||||
frappe.db.get_single_value("Accounts Settings", "show_balance_in_coa").then((value) => {
|
||||
if(value) {
|
||||
|
||||
if (value) {
|
||||
const get_balances = frappe.call({
|
||||
method: 'erpnext.accounts.utils.get_account_balances',
|
||||
method: "erpnext.accounts.utils.get_account_balances",
|
||||
args: {
|
||||
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;
|
||||
|
||||
for (let account of r.message) {
|
||||
|
||||
const node = cur_tree.nodes && cur_tree.nodes[account.value];
|
||||
if (!node || node.is_root) continue;
|
||||
|
||||
// show Dr if positive since balance is calculated as debit - credit else show Cr
|
||||
const balance = account.balance_in_account_currency || account.balance;
|
||||
const dr_or_cr = balance > 0 ? __("Dr"): __("Cr");
|
||||
const dr_or_cr = balance > 0 ? __("Dr") : __("Cr");
|
||||
const format = (value, currency) => format_currency(Math.abs(value), currency);
|
||||
|
||||
if (account.balance!==undefined) {
|
||||
node.parent && node.parent.find('.balance-area').remove();
|
||||
$('<span class="balance-area pull-right">'
|
||||
+ (account.balance_in_account_currency ?
|
||||
(format(account.balance_in_account_currency, account.account_currency) + " / ") : "")
|
||||
+ format(account.balance, account.company_currency)
|
||||
+ " " + dr_or_cr
|
||||
+ '</span>').insertBefore(node.$ul);
|
||||
if (account.balance !== undefined) {
|
||||
node.parent && node.parent.find(".balance-area").remove();
|
||||
$(
|
||||
'<span class="balance-area pull-right">' +
|
||||
(account.balance_in_account_currency
|
||||
? format(
|
||||
account.balance_in_account_currency,
|
||||
account.account_currency
|
||||
) + " / "
|
||||
: "") +
|
||||
format(account.balance, account.company_currency) +
|
||||
" " +
|
||||
dr_or_cr +
|
||||
"</span>"
|
||||
).insertBefore(node.$ul);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
add_tree_node: 'erpnext.accounts.utils.add_ac',
|
||||
menu_items:[
|
||||
add_tree_node: "erpnext.accounts.utils.add_ac",
|
||||
menu_items: [
|
||||
{
|
||||
label: __('New Company'),
|
||||
action: function() { frappe.new_doc("Company", true) },
|
||||
condition: 'frappe.boot.user.can_create.indexOf("Company") !== -1'
|
||||
}
|
||||
label: __("New Company"),
|
||||
action: function () {
|
||||
frappe.new_doc("Company", true);
|
||||
},
|
||||
condition: 'frappe.boot.user.can_create.indexOf("Company") !== -1',
|
||||
},
|
||||
],
|
||||
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', 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: "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",
|
||||
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"],
|
||||
onload: function(treeview) {
|
||||
frappe.treeview_settings['Account'].treeview = {};
|
||||
$.extend(frappe.treeview_settings['Account'].treeview, treeview);
|
||||
ignore_fields: ["parent_account"],
|
||||
onload: function (treeview) {
|
||||
frappe.treeview_settings["Account"].treeview = {};
|
||||
$.extend(frappe.treeview_settings["Account"].treeview, treeview);
|
||||
function get_company() {
|
||||
return treeview.page.fields_dict.company.get_value();
|
||||
}
|
||||
|
||||
// tools
|
||||
treeview.page.add_inner_button(__("Chart of Cost Centers"), function() {
|
||||
frappe.set_route('Tree', 'Cost Center', {company: get_company()});
|
||||
}, __('View'));
|
||||
treeview.page.add_inner_button(
|
||||
__("Chart of Cost Centers"),
|
||||
function () {
|
||||
frappe.set_route("Tree", "Cost Center", { company: get_company() });
|
||||
},
|
||||
__("View")
|
||||
);
|
||||
|
||||
treeview.page.add_inner_button(__("Opening Invoice Creation Tool"), function() {
|
||||
frappe.set_route('Form', 'Opening Invoice Creation Tool', {company: get_company()});
|
||||
}, __('View'));
|
||||
treeview.page.add_inner_button(
|
||||
__("Opening Invoice Creation Tool"),
|
||||
function () {
|
||||
frappe.set_route("Form", "Opening Invoice Creation Tool", { company: get_company() });
|
||||
},
|
||||
__("View")
|
||||
);
|
||||
|
||||
treeview.page.add_inner_button(__("Period Closing Voucher"), function() {
|
||||
frappe.set_route('List', 'Period Closing Voucher', {company: get_company()});
|
||||
}, __('View'));
|
||||
treeview.page.add_inner_button(
|
||||
__("Period Closing Voucher"),
|
||||
function () {
|
||||
frappe.set_route("List", "Period Closing Voucher", { company: get_company() });
|
||||
},
|
||||
__("View")
|
||||
);
|
||||
|
||||
|
||||
treeview.page.add_inner_button(__("Journal Entry"), function() {
|
||||
frappe.new_doc('Journal Entry', {company: get_company()});
|
||||
}, __('Create'));
|
||||
treeview.page.add_inner_button(__("Company"), function() {
|
||||
frappe.new_doc('Company');
|
||||
}, __('Create'));
|
||||
treeview.page.add_inner_button(
|
||||
__("Journal Entry"),
|
||||
function () {
|
||||
frappe.new_doc("Journal Entry", { company: get_company() });
|
||||
},
|
||||
__("Create")
|
||||
);
|
||||
treeview.page.add_inner_button(
|
||||
__("Company"),
|
||||
function () {
|
||||
frappe.new_doc("Company");
|
||||
},
|
||||
__("Create")
|
||||
);
|
||||
|
||||
// financial statements
|
||||
for (let report of ['Trial Balance', 'General Ledger', 'Balance Sheet',
|
||||
'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'));
|
||||
for (let report of [
|
||||
"Trial Balance",
|
||||
"General Ledger",
|
||||
"Balance Sheet",
|
||||
"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) {
|
||||
frappe.treeview_settings['Account'].treeview["tree"] = treeview.tree;
|
||||
treeview.page.set_primary_action(__("New"), function() {
|
||||
let root_company = treeview.page.fields_dict.root_company.get_value();
|
||||
post_render: function (treeview) {
|
||||
frappe.treeview_settings["Account"].treeview["tree"] = treeview.tree;
|
||||
treeview.page.set_primary_action(
|
||||
__("New"),
|
||||
function () {
|
||||
let root_company = treeview.page.fields_dict.root_company.get_value();
|
||||
|
||||
if(root_company) {
|
||||
frappe.throw(__("Please add the account to root level Company - {0}"), [root_company]);
|
||||
} else {
|
||||
treeview.new_node();
|
||||
}
|
||||
}, "add");
|
||||
if (root_company) {
|
||||
frappe.throw(__("Please add the account to root level Company - {0}"), [root_company]);
|
||||
} else {
|
||||
treeview.new_node();
|
||||
}
|
||||
},
|
||||
"add"
|
||||
);
|
||||
},
|
||||
toolbar: [
|
||||
{
|
||||
label:__("Add Child"),
|
||||
condition: function(node) {
|
||||
return frappe.boot.user.can_create.indexOf("Account") !== -1
|
||||
&& (!frappe.treeview_settings['Account'].treeview.page.fields_dict.root_company.get_value()
|
||||
|| frappe.flags.ignore_root_company_validation)
|
||||
&& node.expandable && !node.hide_add;
|
||||
label: __("Add Child"),
|
||||
condition: function (node) {
|
||||
return (
|
||||
frappe.boot.user.can_create.indexOf("Account") !== -1 &&
|
||||
(!frappe.treeview_settings[
|
||||
"Account"
|
||||
].treeview.page.fields_dict.root_company.get_value() ||
|
||||
frappe.flags.ignore_root_company_validation) &&
|
||||
node.expandable &&
|
||||
!node.hide_add
|
||||
);
|
||||
},
|
||||
click: function() {
|
||||
var me = frappe.views.trees['Account'];
|
||||
click: function () {
|
||||
var me = frappe.views.trees["Account"];
|
||||
me.new_node();
|
||||
},
|
||||
btnClass: "hidden-xs"
|
||||
btnClass: "hidden-xs",
|
||||
},
|
||||
{
|
||||
condition: function(node) {
|
||||
return !node.root && frappe.boot.user.can_read.indexOf("GL Entry") !== -1
|
||||
condition: function (node) {
|
||||
return !node.root && frappe.boot.user.can_read.indexOf("GL Entry") !== -1;
|
||||
},
|
||||
label: __("View Ledger"),
|
||||
click: function(node, btn) {
|
||||
click: function (node, btn) {
|
||||
frappe.route_options = {
|
||||
"account": node.label,
|
||||
"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],
|
||||
"company": frappe.treeview_settings['Account'].treeview.page.fields_dict.company.get_value()
|
||||
account: node.label,
|
||||
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],
|
||||
company:
|
||||
frappe.treeview_settings["Account"].treeview.page.fields_dict.company.get_value(),
|
||||
};
|
||||
frappe.set_route("query-report", "General Ledger");
|
||||
},
|
||||
btnClass: "hidden-xs"
|
||||
}
|
||||
btnClass: "hidden-xs",
|
||||
},
|
||||
],
|
||||
extend_toolbar: true
|
||||
}
|
||||
extend_toolbar: true,
|
||||
};
|
||||
|
||||
@@ -56,7 +56,9 @@
|
||||
"Constru\u00e7\u00f5es em Andamento de Im\u00f3veis Destinados \u00e0 Venda": {},
|
||||
"Estoques Destinados \u00e0 Doa\u00e7\u00e3o": {},
|
||||
"Im\u00f3veis Destinados \u00e0 Venda": {},
|
||||
"Insumos (materiais diretos)": {},
|
||||
"Insumos (materiais diretos)": {
|
||||
"account_type": "Stock"
|
||||
},
|
||||
"Insumos Agropecu\u00e1rios": {},
|
||||
"Mercadorias para Revenda": {},
|
||||
"Outras 11": {},
|
||||
@@ -146,6 +148,65 @@
|
||||
"root_type": "Asset"
|
||||
},
|
||||
"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 PRODUTOS DE FABRICA\u00c7\u00c3O PR\u00d3PRIA PRODUZIDOS": {
|
||||
"Alimenta\u00e7\u00e3o do Trabalhador": {},
|
||||
@@ -621,7 +682,9 @@
|
||||
"Receita das Unidades Imobili\u00e1rias Vendidas": {},
|
||||
"Receita de Exporta\u00e7\u00e3o Direta de Mercadorias e Produtos": {},
|
||||
"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": {}
|
||||
}
|
||||
}
|
||||
@@ -645,65 +708,6 @@
|
||||
}
|
||||
},
|
||||
"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 1": {
|
||||
"DESPESAS OPERACIONAIS 2": {
|
||||
|
||||
@@ -36,16 +36,16 @@
|
||||
}
|
||||
},
|
||||
"Fixed Assets": {
|
||||
"Capital Equipments": {
|
||||
"Capital Equipment": {
|
||||
"account_type": "Fixed Asset"
|
||||
},
|
||||
"Electronic Equipments": {
|
||||
"Electronic Equipment": {
|
||||
"account_type": "Fixed Asset"
|
||||
},
|
||||
"Furnitures and Fixtures": {
|
||||
"Furniture and Fixtures": {
|
||||
"account_type": "Fixed Asset"
|
||||
},
|
||||
"Office Equipments": {
|
||||
"Office Equipment": {
|
||||
"account_type": "Fixed Asset"
|
||||
},
|
||||
"Plants and Machineries": {
|
||||
|
||||
@@ -23,13 +23,13 @@ def get():
|
||||
_("Tax Assets"): {"is_group": 1},
|
||||
},
|
||||
_("Fixed Assets"): {
|
||||
_("Capital Equipments"): {"account_type": "Fixed Asset"},
|
||||
_("Electronic Equipments"): {"account_type": "Fixed Asset"},
|
||||
_("Furnitures and Fixtures"): {"account_type": "Fixed Asset"},
|
||||
_("Office Equipments"): {"account_type": "Fixed Asset"},
|
||||
_("Capital Equipment"): {"account_type": "Fixed Asset"},
|
||||
_("Electronic Equipment"): {"account_type": "Fixed Asset"},
|
||||
_("Furniture and Fixtures"): {"account_type": "Fixed Asset"},
|
||||
_("Office Equipment"): {"account_type": "Fixed Asset"},
|
||||
_("Plants and Machineries"): {"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"},
|
||||
_("CWIP Account"): {
|
||||
"account_type": "Capital Work in Progress",
|
||||
|
||||
@@ -36,13 +36,13 @@ def get():
|
||||
"account_number": "1100-1600",
|
||||
},
|
||||
_("Fixed Assets"): {
|
||||
_("Capital Equipments"): {"account_type": "Fixed Asset", "account_number": "1710"},
|
||||
_("Electronic Equipments"): {"account_type": "Fixed Asset", "account_number": "1720"},
|
||||
_("Furnitures and Fixtures"): {"account_type": "Fixed Asset", "account_number": "1730"},
|
||||
_("Office Equipments"): {"account_type": "Fixed Asset", "account_number": "1740"},
|
||||
_("Capital Equipment"): {"account_type": "Fixed Asset", "account_number": "1710"},
|
||||
_("Electronic Equipment"): {"account_type": "Fixed Asset", "account_number": "1720"},
|
||||
_("Furniture and Fixtures"): {"account_type": "Fixed Asset", "account_number": "1730"},
|
||||
_("Office Equipment"): {"account_type": "Fixed Asset", "account_number": "1740"},
|
||||
_("Plants and Machineries"): {"account_type": "Fixed Asset", "account_number": "1750"},
|
||||
_("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"): {
|
||||
"account_type": "Accumulated Depreciation",
|
||||
"account_number": "1780",
|
||||
|
||||
@@ -6,6 +6,7 @@ import unittest
|
||||
|
||||
import frappe
|
||||
from frappe.test_runner import make_test_records
|
||||
from frappe.utils import nowdate
|
||||
|
||||
from erpnext.accounts.doctype.account.account import (
|
||||
InvalidAccountMergeError,
|
||||
@@ -119,7 +120,7 @@ class TestAccount(unittest.TestCase):
|
||||
InvalidAccountMergeError,
|
||||
merge_account,
|
||||
"Capital Stock - _TC",
|
||||
"Softwares - _TC",
|
||||
"Software - _TC",
|
||||
)
|
||||
|
||||
# Raise error as currency doesn't match
|
||||
@@ -324,6 +325,19 @@ class TestAccount(unittest.TestCase):
|
||||
acc.account_currency = "USD"
|
||||
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):
|
||||
from frappe.test_runner import make_test_objects
|
||||
|
||||
@@ -1,74 +1,86 @@
|
||||
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Accounting Dimension', {
|
||||
refresh: function(frm) {
|
||||
frm.set_query('document_type', () => {
|
||||
frappe.ui.form.on("Accounting Dimension", {
|
||||
refresh: function (frm) {
|
||||
frm.set_query("document_type", () => {
|
||||
let invalid_doctypes = frappe.model.core_doctypes_list;
|
||||
invalid_doctypes.push('Accounting Dimension', 'Project',
|
||||
'Cost Center', 'Accounting Dimension Detail', 'Company');
|
||||
invalid_doctypes.push(
|
||||
"Accounting Dimension",
|
||||
"Project",
|
||||
"Cost Center",
|
||||
"Accounting Dimension Detail",
|
||||
"Company"
|
||||
);
|
||||
|
||||
return {
|
||||
filters: {
|
||||
name: ['not in', invalid_doctypes]
|
||||
}
|
||||
name: ["not in", invalid_doctypes],
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query("offsetting_account", "dimension_defaults", function(doc, cdt, cdn) {
|
||||
frm.set_query("offsetting_account", "dimension_defaults", function (doc, cdt, cdn) {
|
||||
let d = locals[cdt][cdn];
|
||||
return {
|
||||
filters: {
|
||||
company: d.company,
|
||||
root_type: ["in", ["Asset", "Liability"]],
|
||||
is_group: 0
|
||||
}
|
||||
}
|
||||
is_group: 0,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
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);
|
||||
});
|
||||
|
||||
let button = frm.doc.disabled ? "Enable" : "Disable";
|
||||
|
||||
frm.add_custom_button(__(button), function() {
|
||||
|
||||
frm.set_value('disabled', 1 - frm.doc.disabled);
|
||||
frm.add_custom_button(__(button), function () {
|
||||
frm.set_value("disabled", 1 - frm.doc.disabled);
|
||||
|
||||
frappe.call({
|
||||
method: "erpnext.accounts.doctype.accounting_dimension.accounting_dimension.disable_dimension",
|
||||
args: {
|
||||
doc: frm.doc
|
||||
doc: frm.doc,
|
||||
},
|
||||
freeze: true,
|
||||
callback: function(r) {
|
||||
callback: function (r) {
|
||||
let message = frm.doc.disabled ? "Dimension Disabled" : "Dimension Enabled";
|
||||
frm.save();
|
||||
frappe.show_alert({message:__(message), indicator:'green'});
|
||||
}
|
||||
frappe.show_alert({ message: __(message), indicator: "green" });
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
document_type: function(frm) {
|
||||
document_type: function (frm) {
|
||||
frm.set_value("label", frm.doc.document_type);
|
||||
frm.set_value("fieldname", frappe.model.scrub(frm.doc.document_type));
|
||||
|
||||
frm.set_value('label', frm.doc.document_type);
|
||||
frm.set_value('fieldname', frappe.model.scrub(frm.doc.document_type));
|
||||
|
||||
frappe.db.get_value('Accounting Dimension', {'document_type': frm.doc.document_type}, 'document_type', (r) => {
|
||||
if (r && r.document_type) {
|
||||
frm.set_df_property('document_type', 'description', "Document type is already set as dimension");
|
||||
frappe.db.get_value(
|
||||
"Accounting Dimension",
|
||||
{ document_type: frm.doc.document_type },
|
||||
"document_type",
|
||||
(r) => {
|
||||
if (r && r.document_type) {
|
||||
frm.set_df_property(
|
||||
"document_type",
|
||||
"description",
|
||||
"Document type is already set as dimension"
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
frappe.ui.form.on('Accounting Dimension Detail', {
|
||||
dimension_defaults_add: function(frm, cdt, cdn) {
|
||||
frappe.ui.form.on("Accounting Dimension Detail", {
|
||||
dimension_defaults_add: function (frm, cdt, cdn) {
|
||||
let row = locals[cdt][cdn];
|
||||
row.reference_document = frm.doc.document_type;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -11,6 +11,10 @@ from frappe.model import core_doctypes_list
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import cstr
|
||||
|
||||
from erpnext.accounts.doctype.repost_accounting_ledger.repost_accounting_ledger import (
|
||||
get_allowed_types_from_settings,
|
||||
)
|
||||
|
||||
|
||||
class AccountingDimension(Document):
|
||||
# begin: auto-generated types
|
||||
@@ -106,6 +110,7 @@ def make_dimension_in_accounting_doctypes(doc, doclist=None):
|
||||
|
||||
doc_count = len(get_accounting_dimensions())
|
||||
count = 0
|
||||
repostable_doctypes = get_allowed_types_from_settings()
|
||||
|
||||
for doctype in doclist:
|
||||
|
||||
@@ -121,6 +126,7 @@ def make_dimension_in_accounting_doctypes(doc, doclist=None):
|
||||
"options": doc.document_type,
|
||||
"insert_after": insert_after_field,
|
||||
"owner": "Administrator",
|
||||
"allow_on_submit": 1 if doctype in repostable_doctypes else 0,
|
||||
}
|
||||
|
||||
meta = frappe.get_meta(doctype, cached=False)
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Accounting Dimension Filter', {
|
||||
refresh: function(frm, cdt, cdn) {
|
||||
let help_content =
|
||||
`<table class="table table-bordered" style="background-color: var(--scrollbar-track-color);">
|
||||
frappe.ui.form.on("Accounting Dimension Filter", {
|
||||
refresh: function (frm, cdt, cdn) {
|
||||
let help_content = `<table class="table table-bordered" style="background-color: var(--scrollbar-track-color);">
|
||||
<tr><td>
|
||||
<p>
|
||||
<i class="fa fa-hand-right"></i>
|
||||
@@ -13,77 +12,80 @@ frappe.ui.form.on('Accounting Dimension Filter', {
|
||||
</td></tr>
|
||||
</table>`;
|
||||
|
||||
frm.set_df_property('dimension_filter_help', 'options', help_content);
|
||||
frm.set_df_property("dimension_filter_help", "options", help_content);
|
||||
},
|
||||
onload: function(frm) {
|
||||
frm.set_query('applicable_on_account', 'accounts', function() {
|
||||
onload: function (frm) {
|
||||
frm.set_query("applicable_on_account", "accounts", function () {
|
||||
return {
|
||||
filters: {
|
||||
'company': frm.doc.company
|
||||
}
|
||||
company: frm.doc.company,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
frappe.db.get_list('Accounting Dimension',
|
||||
{fields: ['document_type']}).then((res) => {
|
||||
let options = ['Cost Center', 'Project'];
|
||||
frappe.db.get_list("Accounting Dimension", { fields: ["document_type"] }).then((res) => {
|
||||
let options = ["Cost Center", "Project"];
|
||||
|
||||
res.forEach((dimension) => {
|
||||
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) {
|
||||
let filters = {};
|
||||
|
||||
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)) {
|
||||
filters['is_group'] = 0;
|
||||
filters["is_group"] = 0;
|
||||
}
|
||||
|
||||
if (frappe.meta.has_field(frm.doc.accounting_dimension, 'company')) {
|
||||
filters['company'] = frm.doc.company;
|
||||
if (frappe.meta.has_field(frm.doc.accounting_dimension, "company")) {
|
||||
filters["company"] = frm.doc.company;
|
||||
}
|
||||
|
||||
frm.set_query('dimension_value', 'dimensions', function() {
|
||||
frm.set_query("dimension_value", "dimensions", function () {
|
||||
return {
|
||||
filters: filters
|
||||
filters: filters,
|
||||
};
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
accounting_dimension: function(frm) {
|
||||
accounting_dimension: function (frm) {
|
||||
frm.clear_table("dimensions");
|
||||
let row = frm.add_child("dimensions");
|
||||
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.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.
|
||||
* Hence it's not "restricted" on any value.
|
||||
*/
|
||||
*/
|
||||
if (!frm.doc.apply_restriction_on_values) {
|
||||
frm.set_value("allow_or_restrict", "Restrict");
|
||||
frm.clear_table("dimensions");
|
||||
frm.refresh_field("dimensions");
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
frappe.ui.form.on('Allowed Dimension', {
|
||||
dimensions_add: function(frm, cdt, cdn) {
|
||||
frappe.ui.form.on("Allowed Dimension", {
|
||||
dimensions_add: function (frm, cdt, cdn) {
|
||||
let row = locals[cdt][cdn];
|
||||
row.accounting_dimension = frm.doc.accounting_dimension;
|
||||
frm.refresh_field("dimensions");
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,30 +1,33 @@
|
||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Accounting Period', {
|
||||
onload: function(frm) {
|
||||
if(frm.doc.closed_documents.length === 0 || (frm.doc.closed_documents.length === 1 && frm.doc.closed_documents[0].document_type == undefined)) {
|
||||
frappe.ui.form.on("Accounting Period", {
|
||||
onload: function (frm) {
|
||||
if (
|
||||
frm.doc.closed_documents.length === 0 ||
|
||||
(frm.doc.closed_documents.length === 1 && frm.doc.closed_documents[0].document_type == undefined)
|
||||
) {
|
||||
frappe.call({
|
||||
method: "get_doctypes_for_closing",
|
||||
doc:frm.doc,
|
||||
callback: function(r) {
|
||||
if(r.message) {
|
||||
doc: frm.doc,
|
||||
callback: function (r) {
|
||||
if (r.message) {
|
||||
cur_frm.clear_table("closed_documents");
|
||||
r.message.forEach(function(element) {
|
||||
r.message.forEach(function (element) {
|
||||
var c = frm.add_child("closed_documents");
|
||||
c.document_type = element.document_type;
|
||||
c.closed = element.closed;
|
||||
});
|
||||
refresh_field("closed_documents");
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
frm.set_query("document_type", "closed_documents", () => {
|
||||
return {
|
||||
query: "erpnext.controllers.queries.get_doctypes_for_closing",
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Accounts Settings', {
|
||||
refresh: function(frm) {
|
||||
|
||||
}
|
||||
frappe.ui.form.on("Accounts Settings", {
|
||||
refresh: function (frm) {},
|
||||
});
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
{
|
||||
"actions": [],
|
||||
"creation": "2013-06-24 15:49:57",
|
||||
"description": "Settings for Accounts",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Other",
|
||||
"editable_grid": 1,
|
||||
@@ -462,7 +461,7 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2023-11-20 09:37:47.650347",
|
||||
"modified": "2024-01-30 14:04:26.553554",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Accounts Settings",
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
|
||||
frappe.ui.form.on('Accounts Settings', {
|
||||
refresh: function(frm) {
|
||||
frappe.ui.form.on("Accounts Settings", {
|
||||
refresh: function (frm) {
|
||||
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");
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,38 +1,36 @@
|
||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
frappe.provide('erpnext.integrations');
|
||||
frappe.provide("erpnext.integrations");
|
||||
|
||||
frappe.ui.form.on('Bank', {
|
||||
onload: function(frm) {
|
||||
frappe.ui.form.on("Bank", {
|
||||
onload: function (frm) {
|
||||
add_fields_to_mapping_table(frm);
|
||||
},
|
||||
refresh: function(frm) {
|
||||
refresh: function (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) {
|
||||
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);
|
||||
}
|
||||
else {
|
||||
frm.set_df_property('address_and_contact', 'hidden', 0);
|
||||
} else {
|
||||
frm.set_df_property("address_and_contact", "hidden", 0);
|
||||
frappe.contacts.render_address_and_contact(frm);
|
||||
}
|
||||
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);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
let add_fields_to_mapping_table = function (frm) {
|
||||
let options = [];
|
||||
|
||||
frappe.model.with_doctype("Bank Transaction", function() {
|
||||
frappe.model.with_doctype("Bank Transaction", function () {
|
||||
let meta = frappe.get_meta("Bank Transaction");
|
||||
meta.fields.forEach(value => {
|
||||
meta.fields.forEach((value) => {
|
||||
if (!["Section Break", "Column Break"].includes(value.fieldtype)) {
|
||||
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(
|
||||
'bank_transaction_field', 'options', options
|
||||
"bank_transaction_field",
|
||||
"options",
|
||||
options
|
||||
);
|
||||
};
|
||||
|
||||
erpnext.integrations.refreshPlaidLink = class refreshPlaidLink {
|
||||
constructor(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();
|
||||
}
|
||||
|
||||
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.init_plaid();
|
||||
}
|
||||
|
||||
async get_link_token_for_update() {
|
||||
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 }
|
||||
)
|
||||
);
|
||||
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;
|
||||
}
|
||||
@@ -90,35 +90,45 @@ erpnext.integrations.refreshPlaidLink = class refreshPlaidLink {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
const el = document.createElement('script');
|
||||
el.type = 'text/javascript';
|
||||
const el = document.createElement("script");
|
||||
el.type = "text/javascript";
|
||||
el.async = true;
|
||||
el.src = src;
|
||||
el.addEventListener('load', resolve);
|
||||
el.addEventListener('error', reject);
|
||||
el.addEventListener('abort', reject);
|
||||
el.addEventListener("load", resolve);
|
||||
el.addEventListener("error", reject);
|
||||
el.addEventListener("abort", reject);
|
||||
document.head.appendChild(el);
|
||||
});
|
||||
}
|
||||
|
||||
onScriptLoaded(me) {
|
||||
me.linkHandler = Plaid.create({ // eslint-disable-line no-undef
|
||||
me.linkHandler = Plaid.create({
|
||||
// eslint-disable-line no-undef
|
||||
env: me.plaid_env,
|
||||
token: me.token,
|
||||
onSuccess: me.plaid_success
|
||||
onSuccess: me.plaid_success,
|
||||
});
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
plaid_success(token, response) {
|
||||
frappe.xcall('erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.update_bank_account_ids', {
|
||||
response: response,
|
||||
}).then(() => {
|
||||
frappe.show_alert({ message: __('Plaid Link Updated'), indicator: 'green' });
|
||||
});
|
||||
frappe
|
||||
.xcall(
|
||||
"erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.update_bank_account_ids",
|
||||
{
|
||||
response: response,
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
frappe.show_alert({ message: __("Plaid Link Updated"), indicator: "green" });
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,45 +1,49 @@
|
||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Bank Account', {
|
||||
setup: function(frm) {
|
||||
frm.set_query("account", function() {
|
||||
frappe.ui.form.on("Bank Account", {
|
||||
setup: function (frm) {
|
||||
frm.set_query("account", function () {
|
||||
return {
|
||||
filters: {
|
||||
'account_type': 'Bank',
|
||||
'company': frm.doc.company,
|
||||
'is_group': 0
|
||||
}
|
||||
account_type: "Bank",
|
||||
company: frm.doc.company,
|
||||
is_group: 0,
|
||||
},
|
||||
};
|
||||
});
|
||||
frm.set_query("party_type", function() {
|
||||
frm.set_query("party_type", function () {
|
||||
return {
|
||||
query: "erpnext.setup.doctype.party_type.party_type.get_party_type",
|
||||
};
|
||||
});
|
||||
},
|
||||
refresh: function(frm) {
|
||||
frappe.dynamic_link = { doc: frm.doc, fieldname: 'name', doctype: 'Bank Account' }
|
||||
refresh: function (frm) {
|
||||
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) {
|
||||
frappe.contacts.clear_address_and_contact(frm);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
frappe.contacts.render_address_and_contact(frm);
|
||||
}
|
||||
|
||||
if (frm.doc.integration_id) {
|
||||
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() {
|
||||
frm.set_value("integration_id", "");
|
||||
});
|
||||
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 () {
|
||||
frm.set_value("integration_id", "");
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
is_company_account: function(frm) {
|
||||
frm.set_df_property('account', 'reqd', frm.doc.is_company_account);
|
||||
}
|
||||
is_company_account: function (frm) {
|
||||
frm.set_df_property("account", "reqd", frm.doc.is_company_account);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -9,6 +9,7 @@ from frappe.contacts.address_and_contact import (
|
||||
load_address_and_contact,
|
||||
)
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import comma_and, get_link_to_form
|
||||
|
||||
|
||||
class BankAccount(Document):
|
||||
@@ -52,10 +53,23 @@ class BankAccount(Document):
|
||||
def validate(self):
|
||||
self.validate_company()
|
||||
self.validate_iban()
|
||||
self.validate_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):
|
||||
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):
|
||||
"""
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Bank Account Subtype', {
|
||||
refresh: function() {
|
||||
|
||||
}
|
||||
frappe.ui.form.on("Bank Account Subtype", {
|
||||
refresh: function () {},
|
||||
});
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Bank Account Type', {
|
||||
frappe.ui.form.on("Bank Account Type", {
|
||||
// refresh: function(frm) {
|
||||
|
||||
// }
|
||||
});
|
||||
|
||||
@@ -2,80 +2,76 @@
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
frappe.ui.form.on("Bank Clearance", {
|
||||
setup: function(frm) {
|
||||
setup: function (frm) {
|
||||
frm.add_fetch("account", "account_currency", "account_currency");
|
||||
|
||||
frm.set_query("account", function() {
|
||||
frm.set_query("account", function () {
|
||||
return {
|
||||
"filters": {
|
||||
"account_type": ["in",["Bank","Cash"]],
|
||||
"is_group": 0,
|
||||
}
|
||||
filters: {
|
||||
account_type: ["in", ["Bank", "Cash"]],
|
||||
is_group: 0,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query("bank_account", function () {
|
||||
return {
|
||||
filters: {
|
||||
'is_company_account': 1
|
||||
is_company_account: 1,
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
onload: function(frm) {
|
||||
|
||||
let default_bank_account = frappe.defaults.get_user_default("Company")?
|
||||
locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"]: "";
|
||||
onload: function (frm) {
|
||||
let default_bank_account = frappe.defaults.get_user_default("Company")
|
||||
? locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"]
|
||||
: "";
|
||||
frm.set_value("account", default_bank_account);
|
||||
|
||||
|
||||
|
||||
frm.set_value("from_date", frappe.datetime.month_start());
|
||||
frm.set_value("to_date", frappe.datetime.month_end());
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
refresh: function (frm) {
|
||||
frm.disable_save();
|
||||
frm.add_custom_button(__('Get Payment Entries'), () =>
|
||||
frm.trigger("get_payment_entries")
|
||||
);
|
||||
frm.add_custom_button(__("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) {
|
||||
return frappe.call({
|
||||
method: "update_clearance_date",
|
||||
doc: frm.doc,
|
||||
callback: function(r, rt) {
|
||||
callback: function (r, rt) {
|
||||
frm.refresh_field("payment_entries");
|
||||
frm.refresh_fields();
|
||||
|
||||
if (!frm.doc.payment_entries.length) {
|
||||
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(__("Get Payment Entries"), null, "primary");
|
||||
frm.change_custom_button_type(__("Update Clearance Date"), null, "default");
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
get_payment_entries: function(frm) {
|
||||
get_payment_entries: function (frm) {
|
||||
return frappe.call({
|
||||
method: "get_payment_entries",
|
||||
doc: frm.doc,
|
||||
callback: function(r, rt) {
|
||||
callback: function (r, rt) {
|
||||
frm.refresh_field("payment_entries");
|
||||
|
||||
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.change_custom_button_type(__('Get Payment Entries'), null, 'default');
|
||||
frm.change_custom_button_type(__('Update Clearance Date'), null, 'primary');
|
||||
frm.change_custom_button_type(__("Get Payment Entries"), null, "default");
|
||||
frm.change_custom_button_type(__("Update Clearance Date"), null, "primary");
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
import frappe
|
||||
from frappe import _, msgprint
|
||||
from frappe.model.document import Document
|
||||
from frappe.query_builder.custom import ConstantColumn
|
||||
from frappe.utils import flt, fmt_money, getdate
|
||||
from pypika import Order
|
||||
|
||||
import erpnext
|
||||
|
||||
@@ -179,39 +181,62 @@ def get_payment_entries_for_bank_clearance(
|
||||
|
||||
pos_sales_invoices, pos_purchase_invoices = [], []
|
||||
if include_pos_transactions:
|
||||
pos_sales_invoices = frappe.db.sql(
|
||||
"""
|
||||
select
|
||||
"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,
|
||||
)
|
||||
si_payment = frappe.qb.DocType("Sales Invoice Payment")
|
||||
si = frappe.qb.DocType("Sales Invoice")
|
||||
acc = frappe.qb.DocType("Account")
|
||||
|
||||
pos_purchase_invoices = frappe.db.sql(
|
||||
"""
|
||||
select
|
||||
"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,
|
||||
account.account_currency, 0 as debit
|
||||
from `tabPurchase Invoice` pi, `tabAccount` account
|
||||
where
|
||||
pi.cash_bank_account=%(account)s and pi.docstatus=1 and account.name = pi.cash_bank_account
|
||||
and pi.posting_date >= %(from)s and pi.posting_date <= %(to)s
|
||||
order by
|
||||
pi.posting_date ASC, pi.name DESC
|
||||
""",
|
||||
{"account": account, "from": from_date, "to": to_date},
|
||||
as_dict=1,
|
||||
)
|
||||
pos_sales_invoices = (
|
||||
frappe.qb.from_(si_payment)
|
||||
.inner_join(si)
|
||||
.on(si_payment.parent == si.name)
|
||||
.inner_join(acc)
|
||||
.on(si_payment.account == acc.name)
|
||||
.select(
|
||||
ConstantColumn("Sales Invoice").as_("payment_document"),
|
||||
si.name.as_("payment_entry"),
|
||||
si_payment.reference_no.as_("cheque_number"),
|
||||
si_payment.amount.as_("debit"),
|
||||
si.posting_date,
|
||||
si.customer.as_("against_account"),
|
||||
si_payment.clearance_date,
|
||||
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 = (
|
||||
list(payment_entries)
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
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','iban','iban');
|
||||
cur_frm.add_fetch('bank_account','branch_code','branch_code');
|
||||
cur_frm.add_fetch('bank','swift_number','swift_number');
|
||||
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", "iban", "iban");
|
||||
cur_frm.add_fetch("bank_account", "branch_code", "branch_code");
|
||||
cur_frm.add_fetch("bank", "swift_number", "swift_number");
|
||||
|
||||
frappe.ui.form.on('Bank Guarantee', {
|
||||
setup: function(frm) {
|
||||
frm.set_query("bank", function() {
|
||||
return {
|
||||
filters: {
|
||||
company: frm.doc.company
|
||||
}
|
||||
};
|
||||
});
|
||||
frm.set_query("bank_account", function() {
|
||||
frappe.ui.form.on("Bank Guarantee", {
|
||||
setup: function (frm) {
|
||||
frm.set_query("bank", function () {
|
||||
return {
|
||||
filters: {
|
||||
company: frm.doc.company,
|
||||
bank: frm.doc.bank
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
});
|
||||
frm.set_query("project", function() {
|
||||
frm.set_query("bank_account", function () {
|
||||
return {
|
||||
filters: {
|
||||
customer: frm.doc.customer
|
||||
}
|
||||
company: frm.doc.company,
|
||||
bank: frm.doc.bank,
|
||||
},
|
||||
};
|
||||
});
|
||||
frm.set_query("project", function () {
|
||||
return {
|
||||
filters: {
|
||||
customer: frm.doc.customer,
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
bg_type: function(frm) {
|
||||
bg_type: function (frm) {
|
||||
if (frm.doc.bg_type == "Receiving") {
|
||||
frm.set_value("reference_doctype", "Sales Order");
|
||||
} else if (frm.doc.bg_type == "Providing") {
|
||||
@@ -41,34 +41,33 @@ frappe.ui.form.on('Bank Guarantee', {
|
||||
}
|
||||
},
|
||||
|
||||
reference_docname: function(frm) {
|
||||
reference_docname: function (frm) {
|
||||
if (frm.doc.reference_docname && frm.doc.reference_doctype) {
|
||||
let party_field = frm.doc.reference_doctype == "Sales Order" ? "customer" : "supplier";
|
||||
|
||||
frappe.call({
|
||||
method: "erpnext.accounts.doctype.bank_guarantee.bank_guarantee.get_voucher_details",
|
||||
args: {
|
||||
"bank_guarantee_type": frm.doc.bg_type,
|
||||
"reference_name": frm.doc.reference_docname
|
||||
bank_guarantee_type: frm.doc.bg_type,
|
||||
reference_name: frm.doc.reference_docname,
|
||||
},
|
||||
callback: function(r) {
|
||||
callback: function (r) {
|
||||
if (r.message) {
|
||||
if (r.message[party_field]) frm.set_value(party_field, r.message[party_field]);
|
||||
if (r.message.project) frm.set_value("project", r.message.project);
|
||||
if (r.message.grand_total) frm.set_value("amount", r.message.grand_total);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
start_date: function(frm) {
|
||||
start_date: function (frm) {
|
||||
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);
|
||||
},
|
||||
validity: function(frm) {
|
||||
validity: function (frm) {
|
||||
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);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -48,11 +48,11 @@ class BankGuarantee(Document):
|
||||
|
||||
def on_submit(self):
|
||||
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:
|
||||
frappe.throw(_("Enter the name of the Beneficiary before submittting."))
|
||||
frappe.throw(_("Enter the name of the Beneficiary before submitting."))
|
||||
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()
|
||||
|
||||
@@ -8,21 +8,22 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
|
||||
return {
|
||||
filters: {
|
||||
company: frm.doc.company,
|
||||
'is_company_account': 1
|
||||
is_company_account: 1,
|
||||
},
|
||||
};
|
||||
});
|
||||
let no_bank_transactions_text =
|
||||
`<div class="text-muted text-center">${__("No Matching Bank Transactions Found")}</div>`
|
||||
let no_bank_transactions_text = `<div class="text-muted text-center">${__(
|
||||
"No Matching Bank Transactions Found"
|
||||
)}</div>`;
|
||||
set_field_options("no_bank_transactions", no_bank_transactions_text);
|
||||
},
|
||||
|
||||
onload: function (frm) {
|
||||
// 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_to_date = today;
|
||||
frm.trigger('bank_account');
|
||||
frm.trigger("bank_account");
|
||||
},
|
||||
|
||||
filter_by_reference_date: function (frm) {
|
||||
@@ -37,34 +38,27 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
|
||||
|
||||
refresh: function (frm) {
|
||||
frm.disable_save();
|
||||
frappe.require("bank-reconciliation-tool.bundle.js", () =>
|
||||
frm.trigger("make_reconciliation_tool")
|
||||
);
|
||||
frappe.require("bank-reconciliation-tool.bundle.js", () => frm.trigger("make_reconciliation_tool"));
|
||||
|
||||
frm.add_custom_button(__("Upload Bank Statement"), () =>
|
||||
frappe.call({
|
||||
method:
|
||||
"erpnext.accounts.doctype.bank_statement_import.bank_statement_import.upload_bank_statement",
|
||||
args: {
|
||||
dt: frm.doc.doctype,
|
||||
dn: frm.doc.name,
|
||||
company: frm.doc.company,
|
||||
bank_account: frm.doc.bank_account,
|
||||
},
|
||||
callback: function (r) {
|
||||
if (!r.exc) {
|
||||
var doc = frappe.model.sync(r.message);
|
||||
frappe.set_route(
|
||||
"Form",
|
||||
doc[0].doctype,
|
||||
doc[0].name
|
||||
);
|
||||
}
|
||||
},
|
||||
})
|
||||
frappe.call({
|
||||
method: "erpnext.accounts.doctype.bank_statement_import.bank_statement_import.upload_bank_statement",
|
||||
args: {
|
||||
dt: frm.doc.doctype,
|
||||
dn: frm.doc.name,
|
||||
company: frm.doc.company,
|
||||
bank_account: frm.doc.bank_account,
|
||||
},
|
||||
callback: function (r) {
|
||||
if (!r.exc) {
|
||||
var doc = frappe.model.sync(r.message);
|
||||
frappe.set_route("Form", doc[0].doctype, doc[0].name);
|
||||
}
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
frm.add_custom_button(__('Auto Reconcile'), function() {
|
||||
frm.add_custom_button(__("Auto Reconcile"), function () {
|
||||
frappe.call({
|
||||
method: "erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.auto_reconcile_vouchers",
|
||||
args: {
|
||||
@@ -75,33 +69,22 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
|
||||
from_reference_date: frm.doc.from_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.change_custom_button_type(__('Get Unreconciled Entries'), null, 'primary');
|
||||
|
||||
frm.change_custom_button_type(__("Get Unreconciled Entries"), null, "primary");
|
||||
},
|
||||
|
||||
bank_account: function (frm) {
|
||||
frappe.db.get_value(
|
||||
"Bank Account",
|
||||
frm.doc.bank_account,
|
||||
"account",
|
||||
(r) => {
|
||||
frappe.db.get_value(
|
||||
"Account",
|
||||
r.account,
|
||||
"account_currency",
|
||||
(r) => {
|
||||
frm.doc.account_currency = r.account_currency;
|
||||
frm.trigger("render_chart");
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
frappe.db.get_value("Bank Account", frm.doc.bank_account, "account", (r) => {
|
||||
frappe.db.get_value("Account", r.account, "account_currency", (r) => {
|
||||
frm.doc.account_currency = r.account_currency;
|
||||
frm.trigger("render_chart");
|
||||
});
|
||||
});
|
||||
frm.trigger("get_account_opening_balance");
|
||||
},
|
||||
|
||||
@@ -120,11 +103,7 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
|
||||
) {
|
||||
frm.trigger("render_chart");
|
||||
frm.trigger("render");
|
||||
frappe.utils.scroll_to(
|
||||
frm.get_field("reconciliation_tool_cards").$wrapper,
|
||||
true,
|
||||
30
|
||||
);
|
||||
frappe.utils.scroll_to(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) {
|
||||
if (frm.doc.bank_account && frm.doc.bank_statement_from_date) {
|
||||
frappe.call({
|
||||
method:
|
||||
"erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.get_account_balance",
|
||||
method: "erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.get_account_balance",
|
||||
args: {
|
||||
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) => {
|
||||
frm.set_value("account_opening_balance", response.message);
|
||||
@@ -149,8 +127,7 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
|
||||
get_cleared_balance(frm) {
|
||||
if (frm.doc.bank_account && frm.doc.bank_statement_to_date) {
|
||||
return frappe.call({
|
||||
method:
|
||||
"erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.get_account_balance",
|
||||
method: "erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.get_account_balance",
|
||||
args: {
|
||||
bank_account: frm.doc.bank_account,
|
||||
till_date: frm.doc.bank_statement_to_date,
|
||||
@@ -163,41 +140,30 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
|
||||
},
|
||||
|
||||
render_chart(frm) {
|
||||
frm.cards_manager = new erpnext.accounts.bank_reconciliation.NumberCardManager(
|
||||
{
|
||||
$reconciliation_tool_cards: frm.get_field(
|
||||
"reconciliation_tool_cards"
|
||||
).$wrapper,
|
||||
bank_statement_closing_balance:
|
||||
frm.doc.bank_statement_closing_balance,
|
||||
cleared_balance: frm.cleared_balance,
|
||||
currency: frm.doc.account_currency,
|
||||
}
|
||||
);
|
||||
frm.cards_manager = new erpnext.accounts.bank_reconciliation.NumberCardManager({
|
||||
$reconciliation_tool_cards: frm.get_field("reconciliation_tool_cards").$wrapper,
|
||||
bank_statement_closing_balance: frm.doc.bank_statement_closing_balance,
|
||||
cleared_balance: frm.cleared_balance,
|
||||
currency: frm.doc.account_currency,
|
||||
});
|
||||
},
|
||||
|
||||
render(frm) {
|
||||
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,
|
||||
bank_account: frm.doc.bank_account,
|
||||
$reconciliation_tool_dt: frm.get_field(
|
||||
"reconciliation_tool_dt"
|
||||
).$wrapper,
|
||||
$no_bank_transactions: frm.get_field(
|
||||
"no_bank_transactions"
|
||||
).$wrapper,
|
||||
$reconciliation_tool_dt: frm.get_field("reconciliation_tool_dt").$wrapper,
|
||||
$no_bank_transactions: frm.get_field("no_bank_transactions").$wrapper,
|
||||
bank_statement_from_date: frm.doc.bank_statement_from_date,
|
||||
bank_statement_to_date: frm.doc.bank_statement_to_date,
|
||||
filter_by_reference_date: frm.doc.filter_by_reference_date,
|
||||
from_reference_date: frm.doc.from_reference_date,
|
||||
to_reference_date: frm.doc.to_reference_date,
|
||||
bank_statement_closing_balance:
|
||||
frm.doc.bank_statement_closing_balance,
|
||||
bank_statement_closing_balance: frm.doc.bank_statement_closing_balance,
|
||||
cards_manager: frm.cards_manager,
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -9,7 +9,6 @@ from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.query_builder.custom import ConstantColumn
|
||||
from frappe.utils import cint, flt
|
||||
from pypika.terms import Parameter
|
||||
|
||||
from erpnext import get_default_cost_center
|
||||
from erpnext.accounts.doctype.bank_transaction.bank_transaction import get_total_allocated_amount
|
||||
@@ -509,6 +508,18 @@ def check_matching(
|
||||
to_reference_date,
|
||||
):
|
||||
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(
|
||||
bank_account,
|
||||
company,
|
||||
@@ -520,20 +531,12 @@ def check_matching(
|
||||
from_reference_date,
|
||||
to_reference_date,
|
||||
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 = []
|
||||
for query in queries:
|
||||
matching_vouchers.extend(frappe.db.sql(query, filters, as_dict=True))
|
||||
matching_vouchers.extend(query.run(as_dict=True))
|
||||
|
||||
return (
|
||||
sorted(matching_vouchers, key=lambda x: x["rank"], reverse=True) if matching_vouchers else []
|
||||
@@ -551,6 +554,7 @@ def get_queries(
|
||||
from_reference_date,
|
||||
to_reference_date,
|
||||
exact_match,
|
||||
common_filters,
|
||||
):
|
||||
# get queries to get matching vouchers
|
||||
account_from_to = "paid_to" if transaction.deposit > 0.0 else "paid_from"
|
||||
@@ -571,6 +575,7 @@ def get_queries(
|
||||
filter_by_reference_date,
|
||||
from_reference_date,
|
||||
to_reference_date,
|
||||
common_filters,
|
||||
)
|
||||
or []
|
||||
)
|
||||
@@ -590,6 +595,7 @@ def get_matching_queries(
|
||||
filter_by_reference_date,
|
||||
from_reference_date,
|
||||
to_reference_date,
|
||||
common_filters,
|
||||
):
|
||||
queries = []
|
||||
currency = get_account_currency(bank_account)
|
||||
@@ -604,6 +610,7 @@ def get_matching_queries(
|
||||
filter_by_reference_date,
|
||||
from_reference_date,
|
||||
to_reference_date,
|
||||
common_filters,
|
||||
)
|
||||
queries.append(query)
|
||||
|
||||
@@ -616,16 +623,17 @@ def get_matching_queries(
|
||||
filter_by_reference_date,
|
||||
from_reference_date,
|
||||
to_reference_date,
|
||||
common_filters,
|
||||
)
|
||||
queries.append(query)
|
||||
|
||||
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)
|
||||
|
||||
if transaction.withdrawal > 0.0:
|
||||
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)
|
||||
|
||||
if "bank_transaction" in document_types:
|
||||
@@ -680,7 +688,7 @@ def get_bt_matching_query(exact_match, transaction):
|
||||
.where(amount_condition)
|
||||
.where(bt.docstatus == 1)
|
||||
)
|
||||
return str(query)
|
||||
return query
|
||||
|
||||
|
||||
def get_pe_matching_query(
|
||||
@@ -692,6 +700,7 @@ def get_pe_matching_query(
|
||||
filter_by_reference_date,
|
||||
from_reference_date,
|
||||
to_reference_date,
|
||||
common_filters,
|
||||
):
|
||||
# get matching payment entries query
|
||||
to_from = "to" if transaction.deposit > 0.0 else "from"
|
||||
@@ -734,7 +743,7 @@ def get_pe_matching_query(
|
||||
.where(pe.docstatus == 1)
|
||||
.where(pe.payment_type.isin([payment_type, "Internal Transfer"]))
|
||||
.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(filter_by_date)
|
||||
.orderby(pe.reference_date if cint(filter_by_reference_date) else pe.posting_date)
|
||||
@@ -743,7 +752,7 @@ def get_pe_matching_query(
|
||||
if frappe.flags.auto_reconcile_vouchers == True:
|
||||
query = query.where(ref_condition)
|
||||
|
||||
return str(query)
|
||||
return query
|
||||
|
||||
|
||||
def get_je_matching_query(
|
||||
@@ -754,6 +763,7 @@ def get_je_matching_query(
|
||||
filter_by_reference_date,
|
||||
from_reference_date,
|
||||
to_reference_date,
|
||||
common_filters,
|
||||
):
|
||||
# get matching journal entry query
|
||||
# We have mapping at the bank level
|
||||
@@ -793,7 +803,7 @@ def get_je_matching_query(
|
||||
.where(je.docstatus == 1)
|
||||
.where(je.voucher_type != "Opening Entry")
|
||||
.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(je.docstatus == 1)
|
||||
.where(filter_by_date)
|
||||
@@ -803,19 +813,19 @@ def get_je_matching_query(
|
||||
if frappe.flags.auto_reconcile_vouchers == True:
|
||||
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
|
||||
si = frappe.qb.DocType("Sales Invoice")
|
||||
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_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)
|
||||
|
||||
query = (
|
||||
@@ -836,23 +846,23 @@ def get_si_matching_query(exact_match, currency):
|
||||
)
|
||||
.where(si.docstatus == 1)
|
||||
.where(sip.clearance_date.isnull())
|
||||
.where(sip.account == Parameter("%(bank_account)s"))
|
||||
.where(sip.account == common_filters.bank_account)
|
||||
.where(amount_condition)
|
||||
.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)
|
||||
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_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)
|
||||
|
||||
query = (
|
||||
@@ -872,9 +882,9 @@ def get_pi_matching_query(exact_match, currency):
|
||||
.where(purchase_invoice.docstatus == 1)
|
||||
.where(purchase_invoice.is_paid == 1)
|
||||
.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(purchase_invoice.currency == currency)
|
||||
)
|
||||
|
||||
return str(query)
|
||||
return query
|
||||
|
||||
@@ -76,6 +76,7 @@ class TestBankReconciliationTool(AccountsTestMixin, FrappeTestCase):
|
||||
"deposit": 100,
|
||||
"bank_account": self.bank_account,
|
||||
"reference_number": "123",
|
||||
"currency": "INR",
|
||||
}
|
||||
)
|
||||
.save()
|
||||
|
||||
@@ -17,11 +17,9 @@ frappe.ui.form.on("Bank Statement Import", {
|
||||
frm.import_in_progress = false;
|
||||
if (data_import !== frm.doc.name) return;
|
||||
frappe.model.clear_doc("Bank Statement Import", frm.doc.name);
|
||||
frappe.model
|
||||
.with_doc("Bank Statement Import", frm.doc.name)
|
||||
.then(() => {
|
||||
frm.refresh();
|
||||
});
|
||||
frappe.model.with_doc("Bank Statement Import", frm.doc.name).then(() => {
|
||||
frm.refresh();
|
||||
});
|
||||
});
|
||||
frappe.realtime.on("data_import_progress", (data) => {
|
||||
frm.import_in_progress = true;
|
||||
@@ -48,20 +46,9 @@ frappe.ui.form.on("Bank Statement Import", {
|
||||
: __("Updating {0} of {1}, {2}", message_args);
|
||||
}
|
||||
if (data.skipping) {
|
||||
message = __(
|
||||
"Skipping {0} of {1}, {2}",
|
||||
[
|
||||
data.current,
|
||||
data.total,
|
||||
eta_message,
|
||||
]
|
||||
);
|
||||
message = __("Skipping {0} of {1}, {2}", [data.current, data.total, eta_message]);
|
||||
}
|
||||
frm.dashboard.show_progress(
|
||||
__("Import Progress"),
|
||||
percent,
|
||||
message
|
||||
);
|
||||
frm.dashboard.show_progress(__("Import Progress"), percent, message);
|
||||
frm.page.set_indicator(__("In Progress"), "orange");
|
||||
|
||||
// hide progress when complete
|
||||
@@ -103,15 +90,12 @@ frappe.ui.form.on("Bank Statement Import", {
|
||||
frm.trigger("show_report_error_button");
|
||||
|
||||
if (frm.doc.status === "Partial Success") {
|
||||
frm.add_custom_button(__("Export Errored Rows"), () =>
|
||||
frm.trigger("export_errored_rows")
|
||||
);
|
||||
frm.add_custom_button(__("Export Errored Rows"), () => frm.trigger("export_errored_rows"));
|
||||
}
|
||||
|
||||
if (frm.doc.status.includes("Success")) {
|
||||
frm.add_custom_button(
|
||||
__("Go to {0} List", [__(frm.doc.reference_doctype)]),
|
||||
() => frappe.set_route("List", frm.doc.reference_doctype)
|
||||
frm.add_custom_button(__("Go to {0} 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();
|
||||
if (frm.doc.status !== "Success") {
|
||||
if (!frm.is_new() && frm.has_import_file()) {
|
||||
let label =
|
||||
frm.doc.status === "Pending"
|
||||
? __("Start Import")
|
||||
: __("Retry");
|
||||
frm.page.set_primary_action(label, () =>
|
||||
frm.events.start_import(frm)
|
||||
);
|
||||
let label = frm.doc.status === "Pending" ? __("Start Import") : __("Retry");
|
||||
frm.page.set_primary_action(label, () => frm.events.start_import(frm));
|
||||
} else {
|
||||
frm.page.set_primary_action(__("Save"), () => frm.save());
|
||||
}
|
||||
@@ -176,24 +155,24 @@ frappe.ui.form.on("Bank Statement Import", {
|
||||
message =
|
||||
successful_records.length > 1
|
||||
? __(
|
||||
"Successfully imported {0} records out of {1}. Click on Export Errored Rows, fix the errors and import again.",
|
||||
message_args
|
||||
)
|
||||
"Successfully imported {0} records out of {1}. Click on Export Errored Rows, fix the errors and import again.",
|
||||
message_args
|
||||
)
|
||||
: __(
|
||||
"Successfully imported {0} record out of {1}. Click on Export Errored Rows, fix the errors and import again.",
|
||||
message_args
|
||||
);
|
||||
"Successfully imported {0} record out of {1}. Click on Export Errored Rows, fix the errors and import again.",
|
||||
message_args
|
||||
);
|
||||
} else {
|
||||
message =
|
||||
successful_records.length > 1
|
||||
? __(
|
||||
"Successfully updated {0} records out of {1}. Click on Export Errored Rows, fix the errors and import again.",
|
||||
message_args
|
||||
)
|
||||
"Successfully updated {0} records out of {1}. Click on Export Errored Rows, fix the errors and import again.",
|
||||
message_args
|
||||
)
|
||||
: __(
|
||||
"Successfully updated {0} record out of {1}. Click on Export Errored Rows, fix the errors and import again.",
|
||||
message_args
|
||||
);
|
||||
"Successfully updated {0} record out of {1}. Click on Export Errored Rows, fix the errors and import again.",
|
||||
message_args
|
||||
);
|
||||
}
|
||||
}
|
||||
frm.dashboard.set_headline(message);
|
||||
@@ -236,8 +215,7 @@ frappe.ui.form.on("Bank Statement Import", {
|
||||
},
|
||||
|
||||
download_template() {
|
||||
let method =
|
||||
"/api/method/frappe.core.doctype.data_import.data_import.download_template";
|
||||
let method = "/api/method/frappe.core.doctype.data_import.data_import.download_template";
|
||||
|
||||
open_url_post(method, {
|
||||
doctype: "Bank Transaction",
|
||||
@@ -250,7 +228,7 @@ frappe.ui.form.on("Bank Statement Import", {
|
||||
"description",
|
||||
"reference_number",
|
||||
"bank_account",
|
||||
"currency"
|
||||
"currency",
|
||||
],
|
||||
},
|
||||
});
|
||||
@@ -321,10 +299,7 @@ frappe.ui.form.on("Bank Statement Import", {
|
||||
show_import_preview(frm, preview_data) {
|
||||
let import_log = JSON.parse(frm.doc.statement_import_log || "[]");
|
||||
|
||||
if (
|
||||
frm.import_preview &&
|
||||
frm.import_preview.doctype === frm.doc.reference_doctype
|
||||
) {
|
||||
if (frm.import_preview && frm.import_preview.doctype === frm.doc.reference_doctype) {
|
||||
frm.import_preview.preview_data = preview_data;
|
||||
frm.import_preview.import_log = import_log;
|
||||
frm.import_preview.refresh();
|
||||
@@ -340,19 +315,10 @@ frappe.ui.form.on("Bank Statement Import", {
|
||||
frm,
|
||||
events: {
|
||||
remap_column(changed_map) {
|
||||
let template_options = JSON.parse(
|
||||
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
|
||||
);
|
||||
frm.set_value(
|
||||
"template_options",
|
||||
JSON.stringify(template_options)
|
||||
);
|
||||
let template_options = JSON.parse(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);
|
||||
frm.set_value("template_options", JSON.stringify(template_options));
|
||||
frm.save().then(() => frm.trigger("import_file"));
|
||||
},
|
||||
},
|
||||
@@ -386,8 +352,7 @@ frappe.ui.form.on("Bank Statement Import", {
|
||||
let other_warnings = [];
|
||||
for (let warning of warnings) {
|
||||
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);
|
||||
} else {
|
||||
other_warnings.push(warning);
|
||||
@@ -402,9 +367,7 @@ frappe.ui.form.on("Bank Statement Import", {
|
||||
if (w.field) {
|
||||
let label =
|
||||
w.field.label +
|
||||
(w.field.parent !== frm.doc.reference_doctype
|
||||
? ` (${w.field.parent})`
|
||||
: "");
|
||||
(w.field.parent !== frm.doc.reference_doctype ? ` (${w.field.parent})` : "");
|
||||
return `<li>${label}: ${w.message}</li>`;
|
||||
}
|
||||
return `<li>${w.message}</li>`;
|
||||
@@ -423,10 +386,9 @@ frappe.ui.form.on("Bank Statement Import", {
|
||||
.map((warning) => {
|
||||
let header = "";
|
||||
if (warning.col) {
|
||||
let column_number = `<span class="text-uppercase">${__(
|
||||
"Column {0}",
|
||||
[warning.col]
|
||||
)}</span>`;
|
||||
let column_number = `<span class="text-uppercase">${__("Column {0}", [
|
||||
warning.col,
|
||||
])}</span>`;
|
||||
let column_header = columns[warning.col].header_title;
|
||||
header = `${column_number} (${column_header})`;
|
||||
}
|
||||
@@ -465,36 +427,28 @@ frappe.ui.form.on("Bank Statement Import", {
|
||||
let html = "";
|
||||
if (log.success) {
|
||||
if (frm.doc.import_type === "Insert New Records") {
|
||||
html = __(
|
||||
"Successfully imported {0}", [
|
||||
`<span class="underline">${frappe.utils.get_form_link(
|
||||
frm.doc.reference_doctype,
|
||||
log.docname,
|
||||
true
|
||||
)}<span>`,
|
||||
]
|
||||
);
|
||||
html = __("Successfully imported {0}", [
|
||||
`<span class="underline">${frappe.utils.get_form_link(
|
||||
frm.doc.reference_doctype,
|
||||
log.docname,
|
||||
true
|
||||
)}<span>`,
|
||||
]);
|
||||
} else {
|
||||
html = __(
|
||||
"Successfully updated {0}", [
|
||||
`<span class="underline">${frappe.utils.get_form_link(
|
||||
frm.doc.reference_doctype,
|
||||
log.docname,
|
||||
true
|
||||
)}<span>`,
|
||||
]
|
||||
);
|
||||
html = __("Successfully updated {0}", [
|
||||
`<span class="underline">${frappe.utils.get_form_link(
|
||||
frm.doc.reference_doctype,
|
||||
log.docname,
|
||||
true
|
||||
)}<span>`,
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
let messages = log.messages
|
||||
.map(JSON.parse)
|
||||
.map((m) => {
|
||||
let title = m.title
|
||||
? `<strong>${m.title}</strong>`
|
||||
: "";
|
||||
let message = m.message
|
||||
? `<div>${m.message}</div>`
|
||||
: "";
|
||||
let title = m.title ? `<strong>${m.title}</strong>` : "";
|
||||
let message = m.message ? `<div>${m.message}</div>` : "";
|
||||
return title + message;
|
||||
})
|
||||
.join("");
|
||||
|
||||
@@ -80,7 +80,8 @@ class BankStatementImport(DataImport):
|
||||
from frappe.utils.background_jobs import is_job_enqueued
|
||||
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"))
|
||||
|
||||
job_id = f"bank_statement_import::{self.name}"
|
||||
@@ -97,7 +98,7 @@ class BankStatementImport(DataImport):
|
||||
google_sheets_url=self.google_sheets_url,
|
||||
bank=self.bank,
|
||||
template_options=self.template_options,
|
||||
now=frappe.conf.developer_mode or frappe.flags.in_test,
|
||||
now=run_now,
|
||||
)
|
||||
return True
|
||||
|
||||
@@ -148,6 +149,9 @@ def start_import(
|
||||
import_file = ImportFile("Bank Transaction", file=file, import_type="Insert New Records")
|
||||
|
||||
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:
|
||||
add_bank_account(data, bank_account)
|
||||
|
||||
@@ -1,36 +1,34 @@
|
||||
let imports_in_progress = [];
|
||||
|
||||
frappe.listview_settings['Bank Statement Import'] = {
|
||||
frappe.listview_settings["Bank Statement Import"] = {
|
||||
onload(listview) {
|
||||
frappe.realtime.on('data_import_progress', data => {
|
||||
frappe.realtime.on("data_import_progress", (data) => {
|
||||
if (!imports_in_progress.includes(data.data_import)) {
|
||||
imports_in_progress.push(data.data_import);
|
||||
}
|
||||
});
|
||||
frappe.realtime.on('data_import_refresh', data => {
|
||||
imports_in_progress = imports_in_progress.filter(
|
||||
d => d !== data.data_import
|
||||
);
|
||||
frappe.realtime.on("data_import_refresh", (data) => {
|
||||
imports_in_progress = imports_in_progress.filter((d) => d !== data.data_import);
|
||||
listview.refresh();
|
||||
});
|
||||
},
|
||||
get_indicator: function(doc) {
|
||||
get_indicator: function (doc) {
|
||||
var colors = {
|
||||
'Pending': 'orange',
|
||||
'Not Started': 'orange',
|
||||
'Partial Success': 'orange',
|
||||
'Success': 'green',
|
||||
'In Progress': 'orange',
|
||||
'Error': 'red'
|
||||
Pending: "orange",
|
||||
"Not Started": "orange",
|
||||
"Partial Success": "orange",
|
||||
Success: "green",
|
||||
"In Progress": "orange",
|
||||
Error: "red",
|
||||
};
|
||||
let status = doc.status;
|
||||
if (imports_in_progress.includes(doc.name)) {
|
||||
status = 'In Progress';
|
||||
status = "In Progress";
|
||||
}
|
||||
if (status == 'Pending') {
|
||||
status = 'Not Started';
|
||||
if (status == "Pending") {
|
||||
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,
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
frappe.ui.form.on("Bank Transaction", {
|
||||
onload(frm) {
|
||||
frm.set_query("payment_document", "payment_entries", function() {
|
||||
frm.set_query("payment_document", "payment_entries", function () {
|
||||
const payment_doctypes = frm.events.get_payment_doctypes(frm);
|
||||
return {
|
||||
filters: {
|
||||
@@ -23,7 +23,7 @@ frappe.ui.form.on("Bank Transaction", {
|
||||
set_bank_statement_filter(frm);
|
||||
},
|
||||
|
||||
setup: function(frm) {
|
||||
setup: function (frm) {
|
||||
frm.set_query("party_type", function () {
|
||||
return {
|
||||
filters: {
|
||||
@@ -33,16 +33,10 @@ frappe.ui.form.on("Bank Transaction", {
|
||||
});
|
||||
},
|
||||
|
||||
get_payment_doctypes: function() {
|
||||
get_payment_doctypes: function () {
|
||||
// get payment doctypes from all the apps
|
||||
return [
|
||||
"Payment Entry",
|
||||
"Journal Entry",
|
||||
"Sales Invoice",
|
||||
"Purchase Invoice",
|
||||
"Bank Transaction",
|
||||
];
|
||||
}
|
||||
return ["Payment Entry", "Journal Entry", "Sales Invoice", "Purchase Invoice", "Bank Transaction"];
|
||||
},
|
||||
});
|
||||
|
||||
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) => {
|
||||
if (frm.doc.docstatus === 1) {
|
||||
frappe
|
||||
.xcall(
|
||||
"erpnext.accounts.doctype.bank_transaction.bank_transaction.unclear_reference_payment",
|
||||
{ doctype: cdt, docname: cdn, bt_name: frm.doc.name }
|
||||
)
|
||||
.xcall("erpnext.accounts.doctype.bank_transaction.bank_transaction.unclear_reference_payment", {
|
||||
doctype: cdt,
|
||||
docname: cdn,
|
||||
bt_name: frm.doc.name,
|
||||
})
|
||||
.then((e) => {
|
||||
if (e == "success") {
|
||||
frappe.show_alert({
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.docstatus import DocStatus
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import flt
|
||||
|
||||
@@ -48,6 +49,24 @@ class BankTransaction(Document):
|
||||
|
||||
def validate(self):
|
||||
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):
|
||||
if self.docstatus == 2:
|
||||
@@ -75,10 +94,13 @@ class BankTransaction(Document):
|
||||
pe.append(reference)
|
||||
|
||||
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
|
||||
)
|
||||
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):
|
||||
self.allocate_payment_entries()
|
||||
@@ -415,3 +437,21 @@ def unclear_reference_payment(doctype, docname, bt_name):
|
||||
bt = frappe.get_doc("Bank Transaction", bt_name)
|
||||
set_voucher_clearance(doctype, docname, None, bt)
|
||||
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,15 +1,15 @@
|
||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
frappe.listview_settings['Bank Transaction'] = {
|
||||
frappe.listview_settings["Bank Transaction"] = {
|
||||
add_fields: ["unallocated_amount"],
|
||||
get_indicator: function(doc) {
|
||||
if(doc.docstatus == 2) {
|
||||
get_indicator: function (doc) {
|
||||
if (doc.docstatus == 2) {
|
||||
return [__("Cancelled"), "red", "docstatus,=,2"];
|
||||
} else if(flt(doc.unallocated_amount)<=0) {
|
||||
} else if (flt(doc.unallocated_amount) <= 0) {
|
||||
return [__("Reconciled"), "green", "unallocated_amount,=,0"];
|
||||
} else if(flt(doc.unallocated_amount)>0) {
|
||||
} else if (flt(doc.unallocated_amount) > 0) {
|
||||
return [__("Unreconciled"), "orange", "unallocated_amount,>,0"];
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
# See license.txt
|
||||
|
||||
import json
|
||||
import unittest
|
||||
|
||||
import frappe
|
||||
from frappe import utils
|
||||
from frappe.model.docstatus import DocStatus
|
||||
from frappe.tests.utils import FrappeTestCase
|
||||
|
||||
from erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool import (
|
||||
@@ -32,8 +32,16 @@ class TestBankTransaction(FrappeTestCase):
|
||||
frappe.db.delete(dt)
|
||||
clear_loan_transactions()
|
||||
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.
|
||||
def test_linked_payments(self):
|
||||
@@ -81,6 +89,29 @@ class TestBankTransaction(FrappeTestCase):
|
||||
clearance_date = frappe.db.get_value("Payment Entry", payment.name, "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
|
||||
def test_debit_credit_output(self):
|
||||
bank_transaction = frappe.get_doc(
|
||||
@@ -196,7 +227,9 @@ def clear_loan_transactions():
|
||||
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:
|
||||
frappe.get_doc(
|
||||
{
|
||||
@@ -208,21 +241,35 @@ def create_bank_account(bank_name="Citi Bank", account_name="_Test Bank - _TC"):
|
||||
pass
|
||||
|
||||
try:
|
||||
frappe.get_doc(
|
||||
bank_account = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Bank Account",
|
||||
"account_name": "Checking Account",
|
||||
"account_name": bank_account_name,
|
||||
"bank": bank_name,
|
||||
"account": account_name,
|
||||
"account": gl_account,
|
||||
}
|
||||
).insert(ignore_if_duplicate=True)
|
||||
except frappe.DuplicateEntryError:
|
||||
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(
|
||||
{
|
||||
"doctype": "Bank Transaction",
|
||||
@@ -230,7 +277,7 @@ def add_transactions():
|
||||
"date": "2018-10-23",
|
||||
"deposit": 1200,
|
||||
"currency": "INR",
|
||||
"bank_account": "Checking Account - Citi Bank",
|
||||
"bank_account": bank_account,
|
||||
}
|
||||
).insert()
|
||||
doc.submit()
|
||||
@@ -242,7 +289,7 @@ def add_transactions():
|
||||
"date": "2018-10-23",
|
||||
"deposit": 1700,
|
||||
"currency": "INR",
|
||||
"bank_account": "Checking Account - Citi Bank",
|
||||
"bank_account": bank_account,
|
||||
}
|
||||
).insert()
|
||||
doc.submit()
|
||||
@@ -254,7 +301,7 @@ def add_transactions():
|
||||
"date": "2018-10-26",
|
||||
"withdrawal": 690,
|
||||
"currency": "INR",
|
||||
"bank_account": "Checking Account - Citi Bank",
|
||||
"bank_account": bank_account,
|
||||
}
|
||||
).insert()
|
||||
doc.submit()
|
||||
@@ -266,7 +313,7 @@ def add_transactions():
|
||||
"date": "2018-10-27",
|
||||
"deposit": 3900,
|
||||
"currency": "INR",
|
||||
"bank_account": "Checking Account - Citi Bank",
|
||||
"bank_account": bank_account,
|
||||
}
|
||||
).insert()
|
||||
doc.submit()
|
||||
@@ -278,13 +325,13 @@ def add_transactions():
|
||||
"date": "2018-10-27",
|
||||
"withdrawal": 109080,
|
||||
"currency": "INR",
|
||||
"bank_account": "Checking Account - Citi Bank",
|
||||
"bank_account": bank_account,
|
||||
}
|
||||
).insert()
|
||||
doc.submit()
|
||||
|
||||
|
||||
def add_vouchers():
|
||||
def add_vouchers(gl_account="_Test Bank - _TC"):
|
||||
try:
|
||||
frappe.get_doc(
|
||||
{
|
||||
@@ -300,7 +347,7 @@ def add_vouchers():
|
||||
|
||||
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_date = "2018-10-24"
|
||||
pe.insert()
|
||||
@@ -319,14 +366,14 @@ def add_vouchers():
|
||||
pass
|
||||
|
||||
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_date = "2018-10-24"
|
||||
pe.insert()
|
||||
pe.submit()
|
||||
|
||||
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_date = "2018-11-01"
|
||||
pe.insert()
|
||||
@@ -357,10 +404,10 @@ def add_vouchers():
|
||||
pass
|
||||
|
||||
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.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_date = "2018-10-28"
|
||||
pe.paid_amount = 690
|
||||
@@ -369,7 +416,7 @@ def add_vouchers():
|
||||
pe.submit()
|
||||
|
||||
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_date = "2018-10-28"
|
||||
pe.insert()
|
||||
@@ -392,16 +439,12 @@ def add_vouchers():
|
||||
if not frappe.db.get_value(
|
||||
"Mode of Payment Account", {"company": "_Test Company", "parent": "Cash"}
|
||||
):
|
||||
mode_of_payment.append(
|
||||
"accounts", {"company": "_Test Company", "default_account": "_Test Bank - _TC"}
|
||||
)
|
||||
mode_of_payment.append("accounts", {"company": "_Test Company", "default_account": gl_account})
|
||||
mode_of_payment.save()
|
||||
|
||||
si = create_sales_invoice(customer="Fayva", qty=1, rate=109080, do_not_save=1)
|
||||
si.is_pos = 1
|
||||
si.append(
|
||||
"payments", {"mode_of_payment": "Cash", "account": "_Test Bank - _TC", "amount": 109080}
|
||||
)
|
||||
si.append("payments", {"mode_of_payment": "Cash", "account": gl_account, "amount": 109080})
|
||||
si.insert()
|
||||
si.submit()
|
||||
|
||||
|
||||
@@ -6,18 +6,18 @@ frappe.ui.form.on("Bisect Accounting Statements", {
|
||||
frm.trigger("render_heatmap");
|
||||
},
|
||||
refresh(frm) {
|
||||
frm.add_custom_button(__('Bisect Left'), () => {
|
||||
frm.add_custom_button(__("Bisect Left"), () => {
|
||||
frm.trigger("bisect_left");
|
||||
});
|
||||
|
||||
frm.add_custom_button(__('Bisect Right'), () => {
|
||||
frm.add_custom_button(__("Bisect Right"), () => {
|
||||
frm.trigger("bisect_right");
|
||||
});
|
||||
|
||||
frm.add_custom_button(__('Up'), () => {
|
||||
frm.add_custom_button(__("Up"), () => {
|
||||
frm.trigger("move_up");
|
||||
});
|
||||
frm.add_custom_button(__('Build Tree'), () => {
|
||||
frm.add_custom_button(__("Build Tree"), () => {
|
||||
frm.trigger("build_tree");
|
||||
});
|
||||
},
|
||||
@@ -26,16 +26,16 @@ frappe.ui.form.on("Bisect Accounting Statements", {
|
||||
bisect_heatmap.addClass("bisect_heatmap_location");
|
||||
|
||||
// milliseconds in a day
|
||||
let msiad=24*60*60*1000;
|
||||
let msiad = 24 * 60 * 60 * 1000;
|
||||
let datapoints = {};
|
||||
let fr_dt = new Date(frm.doc.from_date).getTime();
|
||||
let to_dt = new Date(frm.doc.to_date).getTime();
|
||||
let bisect_start = new Date(frm.doc.current_from_date).getTime();
|
||||
let bisect_end = new Date(frm.doc.current_to_date).getTime();
|
||||
|
||||
for(let x=fr_dt; x <= to_dt; x+=msiad){
|
||||
let epoch_in_seconds = x/1000;
|
||||
if ((bisect_start <= x) && (x <= bisect_end )) {
|
||||
for (let x = fr_dt; x <= to_dt; x += msiad) {
|
||||
let epoch_in_seconds = x / 1000;
|
||||
if (bisect_start <= x && x <= bisect_end) {
|
||||
datapoints[epoch_in_seconds] = 1.0;
|
||||
} else {
|
||||
datapoints[epoch_in_seconds] = 0.0;
|
||||
@@ -49,19 +49,19 @@ frappe.ui.form.on("Bisect Accounting Statements", {
|
||||
start: new Date(frm.doc.from_date),
|
||||
end: new Date(frm.doc.to_date),
|
||||
},
|
||||
countLabel: 'Bisecting',
|
||||
countLabel: "Bisecting",
|
||||
discreteDomains: 1,
|
||||
});
|
||||
},
|
||||
bisect_left(frm) {
|
||||
frm.call({
|
||||
doc: frm.doc,
|
||||
method: 'bisect_left',
|
||||
method: "bisect_left",
|
||||
freeze: true,
|
||||
freeze_message: __("Bisecting Left ..."),
|
||||
callback: (r) => {
|
||||
frm.trigger("render_heatmap");
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
bisect_right(frm) {
|
||||
@@ -69,10 +69,10 @@ frappe.ui.form.on("Bisect Accounting Statements", {
|
||||
doc: frm.doc,
|
||||
freeze: true,
|
||||
freeze_message: __("Bisecting Right ..."),
|
||||
method: 'bisect_right',
|
||||
method: "bisect_right",
|
||||
callback: (r) => {
|
||||
frm.trigger("render_heatmap");
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
move_up(frm) {
|
||||
@@ -80,10 +80,10 @@ frappe.ui.form.on("Bisect Accounting Statements", {
|
||||
doc: frm.doc,
|
||||
freeze: true,
|
||||
freeze_message: __("Moving up in tree ..."),
|
||||
method: 'move_up',
|
||||
method: "move_up",
|
||||
callback: (r) => {
|
||||
frm.trigger("render_heatmap");
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
build_tree(frm) {
|
||||
@@ -91,10 +91,10 @@ frappe.ui.form.on("Bisect Accounting Statements", {
|
||||
doc: frm.doc,
|
||||
freeze: true,
|
||||
freeze_message: __("Rebuilding BTree for period ..."),
|
||||
method: 'build_tree',
|
||||
method: "build_tree",
|
||||
callback: (r) => {
|
||||
frm.trigger("render_heatmap");
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@@ -138,10 +138,11 @@ class BisectAccountingStatements(Document):
|
||||
|
||||
# set root as current node
|
||||
root = frappe.db.get_all("Bisect Nodes", filters={"root": ["is", "not set"]})[0]
|
||||
self.get_report_summary()
|
||||
self.current_node = root.name
|
||||
self.current_from_date = self.from_date
|
||||
self.current_to_date = self.to_date
|
||||
|
||||
self.get_report_summary()
|
||||
self.save()
|
||||
|
||||
def get_report_summary(self):
|
||||
|
||||
@@ -2,48 +2,48 @@
|
||||
// For license information, please see license.txt
|
||||
frappe.provide("erpnext.accounts.dimensions");
|
||||
|
||||
frappe.ui.form.on('Budget', {
|
||||
onload: function(frm) {
|
||||
frm.set_query("account", "accounts", function() {
|
||||
frappe.ui.form.on("Budget", {
|
||||
onload: function (frm) {
|
||||
frm.set_query("account", "accounts", function () {
|
||||
return {
|
||||
filters: {
|
||||
company: frm.doc.company,
|
||||
report_type: "Profit and Loss",
|
||||
is_group: 0
|
||||
}
|
||||
is_group: 0,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query("monthly_distribution", function() {
|
||||
frm.set_query("monthly_distribution", function () {
|
||||
return {
|
||||
filters: {
|
||||
fiscal_year: frm.doc.fiscal_year
|
||||
}
|
||||
fiscal_year: frm.doc.fiscal_year,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
erpnext.accounts.dimensions.setup_dimension_filters(frm, frm.doctype);
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
frm.trigger("toggle_reqd_fields")
|
||||
refresh: function (frm) {
|
||||
frm.trigger("toggle_reqd_fields");
|
||||
},
|
||||
|
||||
budget_against: function(frm) {
|
||||
frm.trigger("set_null_value")
|
||||
frm.trigger("toggle_reqd_fields")
|
||||
budget_against: function (frm) {
|
||||
frm.trigger("set_null_value");
|
||||
frm.trigger("toggle_reqd_fields");
|
||||
},
|
||||
|
||||
set_null_value: function(frm) {
|
||||
if(frm.doc.budget_against == 'Cost Center') {
|
||||
frm.set_value('project', null)
|
||||
set_null_value: function (frm) {
|
||||
if (frm.doc.budget_against == "Cost Center") {
|
||||
frm.set_value("project", null);
|
||||
} else {
|
||||
frm.set_value('cost_center', null)
|
||||
frm.set_value("cost_center", null);
|
||||
}
|
||||
},
|
||||
|
||||
toggle_reqd_fields: function(frm) {
|
||||
frm.toggle_reqd("cost_center", frm.doc.budget_against=="Cost Center");
|
||||
frm.toggle_reqd("project", frm.doc.budget_against=="Project");
|
||||
}
|
||||
toggle_reqd_fields: function (frm) {
|
||||
frm.toggle_reqd("cost_center", frm.doc.budget_against == "Cost Center");
|
||||
frm.toggle_reqd("project", frm.doc.budget_against == "Project");
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
frappe.ui.form.on('Cashier Closing', {
|
||||
|
||||
setup: function(frm){
|
||||
frappe.ui.form.on("Cashier Closing", {
|
||||
setup: function (frm) {
|
||||
if (frm.doc.user == "" || frm.doc.user == null) {
|
||||
frm.doc.user = frappe.session.user;
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
frappe.ui.form.on('Chart of Accounts Importer', {
|
||||
frappe.ui.form.on("Chart of Accounts Importer", {
|
||||
onload: function (frm) {
|
||||
frm.set_value("company", "");
|
||||
frm.set_value("import_file", "");
|
||||
@@ -8,31 +8,34 @@ frappe.ui.form.on('Chart of Accounts Importer', {
|
||||
frm.disable_save();
|
||||
|
||||
// make company mandatory
|
||||
frm.set_df_property('company', 'reqd', frm.doc.company ? 0 : 1);
|
||||
frm.set_df_property('import_file_section', 'hidden', frm.doc.company ? 0 : 1);
|
||||
frm.set_df_property("company", "reqd", frm.doc.company ? 0 : 1);
|
||||
frm.set_df_property("import_file_section", "hidden", frm.doc.company ? 0 : 1);
|
||||
|
||||
if (frm.doc.import_file) {
|
||||
frappe.run_serially([
|
||||
() => generate_tree_preview(frm),
|
||||
() => create_import_button(frm),
|
||||
() => frm.set_df_property('chart_preview', 'hidden', 0)
|
||||
() => frm.set_df_property("chart_preview", "hidden", 0),
|
||||
]);
|
||||
}
|
||||
|
||||
frm.set_df_property('chart_preview', 'hidden',
|
||||
$(frm.fields_dict['chart_tree'].wrapper).html()!="" ? 0 : 1);
|
||||
frm.set_df_property(
|
||||
"chart_preview",
|
||||
"hidden",
|
||||
$(frm.fields_dict["chart_tree"].wrapper).html() != "" ? 0 : 1
|
||||
);
|
||||
},
|
||||
|
||||
download_template: function(frm) {
|
||||
download_template: function (frm) {
|
||||
var d = new frappe.ui.Dialog({
|
||||
title: __("Download Template"),
|
||||
fields: [
|
||||
{
|
||||
label : "File Type",
|
||||
label: "File Type",
|
||||
fieldname: "file_type",
|
||||
fieldtype: "Select",
|
||||
reqd: 1,
|
||||
options: ["Excel", "CSV"]
|
||||
options: ["Excel", "CSV"],
|
||||
},
|
||||
{
|
||||
label: "Template Type",
|
||||
@@ -41,21 +44,27 @@ frappe.ui.form.on('Chart of Accounts Importer', {
|
||||
reqd: 1,
|
||||
options: ["Sample Template", "Blank Template"],
|
||||
change: () => {
|
||||
let template_type = d.get_value('template_type');
|
||||
let template_type = d.get_value("template_type");
|
||||
|
||||
if (template_type === "Sample Template") {
|
||||
d.set_df_property('template_type', 'description',
|
||||
d.set_df_property(
|
||||
"template_type",
|
||||
"description",
|
||||
`The Sample Template contains all the required accounts pre filled in the template.
|
||||
You can add more accounts or change existing accounts in the template as per your choice.`);
|
||||
You can add more accounts or change existing accounts in the template as per your choice.`
|
||||
);
|
||||
} else {
|
||||
d.set_df_property('template_type', 'description',
|
||||
d.set_df_property(
|
||||
"template_type",
|
||||
"description",
|
||||
`The Blank Template contains just the account type and root type required to build the Chart
|
||||
of Accounts. Please enter the account names and add more rows as per your requirement.`);
|
||||
of Accounts. Please enter the account names and add more rows as per your requirement.`
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
label : "Company",
|
||||
label: "Company",
|
||||
fieldname: "company",
|
||||
fieldtype: "Link",
|
||||
reqd: 1,
|
||||
@@ -63,25 +72,25 @@ frappe.ui.form.on('Chart of Accounts Importer', {
|
||||
default: frm.doc.company,
|
||||
},
|
||||
],
|
||||
primary_action: function() {
|
||||
primary_action: function () {
|
||||
let data = d.get_values();
|
||||
|
||||
if (!data.template_type) {
|
||||
frappe.throw(__('Please select <b>Template Type</b> to download template'));
|
||||
frappe.throw(__("Please select <b>Template Type</b> to download template"));
|
||||
}
|
||||
|
||||
open_url_post(
|
||||
'/api/method/erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.download_template',
|
||||
"/api/method/erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.download_template",
|
||||
{
|
||||
file_type: data.file_type,
|
||||
template_type: data.template_type,
|
||||
company: data.company
|
||||
company: data.company,
|
||||
}
|
||||
);
|
||||
|
||||
d.hide();
|
||||
},
|
||||
primary_action_label: __('Download')
|
||||
primary_action_label: __("Download"),
|
||||
});
|
||||
d.show();
|
||||
},
|
||||
@@ -89,7 +98,7 @@ frappe.ui.form.on('Chart of Accounts Importer', {
|
||||
import_file: function (frm) {
|
||||
if (!frm.doc.import_file) {
|
||||
frm.page.set_indicator("");
|
||||
$(frm.fields_dict['chart_tree'].wrapper).empty(); // empty wrapper on removing file
|
||||
$(frm.fields_dict["chart_tree"].wrapper).empty(); // empty wrapper on removing file
|
||||
}
|
||||
},
|
||||
|
||||
@@ -99,89 +108,97 @@ frappe.ui.form.on('Chart of Accounts Importer', {
|
||||
frappe.call({
|
||||
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.validate_company",
|
||||
args: {
|
||||
company: frm.doc.company
|
||||
company: frm.doc.company,
|
||||
},
|
||||
callback: function(r) {
|
||||
if(r.message===false) {
|
||||
callback: function (r) {
|
||||
if (r.message === false) {
|
||||
frm.set_value("company", "");
|
||||
frappe.throw(__("Transactions against the Company already exist! Chart of Accounts can only be imported for a Company with no transactions."));
|
||||
frappe.throw(
|
||||
__(
|
||||
"Transactions against the Company already exist! Chart of Accounts can only be imported for a Company with no transactions."
|
||||
)
|
||||
);
|
||||
} else {
|
||||
frm.trigger("refresh");
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
var create_import_button = function(frm) {
|
||||
frm.page.set_primary_action(__("Import"), function () {
|
||||
var create_import_button = function (frm) {
|
||||
frm.page
|
||||
.set_primary_action(__("Import"), function () {
|
||||
return frappe.call({
|
||||
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.import_coa",
|
||||
args: {
|
||||
file_name: frm.doc.import_file,
|
||||
company: frm.doc.company,
|
||||
},
|
||||
freeze: true,
|
||||
freeze_message: __("Creating Accounts..."),
|
||||
callback: function (r) {
|
||||
if (!r.exc) {
|
||||
clearInterval(frm.page["interval"]);
|
||||
frm.page.set_indicator(__("Import Successful"), "blue");
|
||||
create_reset_button(frm);
|
||||
}
|
||||
},
|
||||
});
|
||||
})
|
||||
.addClass("btn btn-primary");
|
||||
};
|
||||
|
||||
var create_reset_button = function (frm) {
|
||||
frm.page
|
||||
.set_primary_action(__("Reset"), function () {
|
||||
frm.page.clear_primary_action();
|
||||
delete frm.page["show_import_button"];
|
||||
frm.reload_doc();
|
||||
})
|
||||
.addClass("btn btn-primary");
|
||||
};
|
||||
|
||||
var validate_coa = function (frm) {
|
||||
if (frm.doc.import_file) {
|
||||
let parent = __("All Accounts");
|
||||
return frappe.call({
|
||||
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.import_coa",
|
||||
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.get_coa",
|
||||
args: {
|
||||
file_name: frm.doc.import_file,
|
||||
company: frm.doc.company
|
||||
},
|
||||
freeze: true,
|
||||
freeze_message: __("Creating Accounts..."),
|
||||
callback: function(r) {
|
||||
if (!r.exc) {
|
||||
clearInterval(frm.page["interval"]);
|
||||
frm.page.set_indicator(__('Import Successful'), 'blue');
|
||||
create_reset_button(frm);
|
||||
}
|
||||
}
|
||||
});
|
||||
}).addClass('btn btn-primary');
|
||||
};
|
||||
|
||||
var create_reset_button = function(frm) {
|
||||
frm.page.set_primary_action(__("Reset"), function () {
|
||||
frm.page.clear_primary_action();
|
||||
delete frm.page["show_import_button"];
|
||||
frm.reload_doc();
|
||||
}).addClass('btn btn-primary');
|
||||
};
|
||||
|
||||
var validate_coa = function(frm) {
|
||||
if (frm.doc.import_file) {
|
||||
let parent = __('All Accounts');
|
||||
return frappe.call({
|
||||
'method': 'erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.get_coa',
|
||||
'args': {
|
||||
file_name: frm.doc.import_file,
|
||||
parent: parent,
|
||||
doctype: 'Chart of Accounts Importer',
|
||||
doctype: "Chart of Accounts Importer",
|
||||
file_type: frm.doc.file_type,
|
||||
for_validate: 1
|
||||
for_validate: 1,
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message['show_import_button']) {
|
||||
frm.page['show_import_button'] = Boolean(r.message['show_import_button']);
|
||||
callback: function (r) {
|
||||
if (r.message["show_import_button"]) {
|
||||
frm.page["show_import_button"] = Boolean(r.message["show_import_button"]);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var generate_tree_preview = function(frm) {
|
||||
let parent = __('All Accounts');
|
||||
$(frm.fields_dict['chart_tree'].wrapper).empty(); // empty wrapper to load new data
|
||||
var generate_tree_preview = function (frm) {
|
||||
let parent = __("All Accounts");
|
||||
$(frm.fields_dict["chart_tree"].wrapper).empty(); // empty wrapper to load new data
|
||||
|
||||
// generate tree structure based on the csv data
|
||||
return new frappe.ui.Tree({
|
||||
parent: $(frm.fields_dict['chart_tree'].wrapper),
|
||||
parent: $(frm.fields_dict["chart_tree"].wrapper),
|
||||
label: parent,
|
||||
expandable: true,
|
||||
method: 'erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.get_coa',
|
||||
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.get_coa",
|
||||
args: {
|
||||
file_name: frm.doc.import_file,
|
||||
parent: parent,
|
||||
doctype: 'Chart of Accounts Importer',
|
||||
file_type: frm.doc.file_type
|
||||
doctype: "Chart of Accounts Importer",
|
||||
file_type: frm.doc.file_type,
|
||||
},
|
||||
onclick: function(node) {
|
||||
onclick: function (node) {
|
||||
parent = node.value;
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -3,18 +3,20 @@
|
||||
|
||||
frappe.provide("erpnext.cheque_print");
|
||||
|
||||
frappe.ui.form.on('Cheque Print Template', {
|
||||
refresh: function(frm) {
|
||||
if(!frm.doc.__islocal) {
|
||||
frm.add_custom_button(frm.doc.has_print_format?__("Update Print Format"):__("Create Print Format"),
|
||||
function() {
|
||||
frappe.ui.form.on("Cheque Print Template", {
|
||||
refresh: function (frm) {
|
||||
if (!frm.doc.__islocal) {
|
||||
frm.add_custom_button(
|
||||
frm.doc.has_print_format ? __("Update Print Format") : __("Create Print Format"),
|
||||
function () {
|
||||
erpnext.cheque_print.view_cheque_print(frm);
|
||||
}).addClass("btn-primary");
|
||||
}
|
||||
).addClass("btn-primary");
|
||||
|
||||
$(frm.fields_dict.cheque_print_preview.wrapper).empty()
|
||||
$(frm.fields_dict.cheque_print_preview.wrapper).empty();
|
||||
|
||||
|
||||
var template = '<div style="position: relative; overflow-x: scroll;">\
|
||||
var template =
|
||||
'<div style="position: relative; overflow-x: scroll;">\
|
||||
<div id="cheque_preview" style="width: {{ cheque_width }}cm; \
|
||||
height: {{ cheque_height }}cm;\
|
||||
background-repeat: no-repeat;\
|
||||
@@ -48,30 +50,30 @@ frappe.ui.form.on('Cheque Print Template', {
|
||||
</div>\
|
||||
</div>';
|
||||
|
||||
$(frappe.render(template, frm.doc)).appendTo(frm.fields_dict.cheque_print_preview.wrapper)
|
||||
$(frappe.render(template, frm.doc)).appendTo(frm.fields_dict.cheque_print_preview.wrapper);
|
||||
|
||||
if (frm.doc.scanned_cheque) {
|
||||
$(frm.fields_dict.cheque_print_preview.wrapper).find("#cheque_preview").css('background-image', 'url(' + frm.doc.scanned_cheque + ')');
|
||||
$(frm.fields_dict.cheque_print_preview.wrapper)
|
||||
.find("#cheque_preview")
|
||||
.css("background-image", "url(" + frm.doc.scanned_cheque + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
erpnext.cheque_print.view_cheque_print = function(frm) {
|
||||
erpnext.cheque_print.view_cheque_print = function (frm) {
|
||||
frappe.call({
|
||||
method: "erpnext.accounts.doctype.cheque_print_template.cheque_print_template.create_or_update_cheque_print_format",
|
||||
args:{
|
||||
"template_name": frm.doc.name
|
||||
args: {
|
||||
template_name: frm.doc.name,
|
||||
},
|
||||
callback: function(r) {
|
||||
callback: function (r) {
|
||||
if (!r.exe && !frm.doc.has_print_format) {
|
||||
var doc = frappe.model.sync(r.message);
|
||||
frappe.set_route("Form", r.message.doctype, r.message.name);
|
||||
} else {
|
||||
frappe.msgprint(__("Print settings updated in respective print format"));
|
||||
}
|
||||
else {
|
||||
frappe.msgprint(__("Print settings updated in respective print format"))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -3,75 +3,80 @@
|
||||
|
||||
frappe.provide("erpnext.accounts");
|
||||
|
||||
|
||||
|
||||
frappe.ui.form.on('Cost Center', {
|
||||
onload: function(frm) {
|
||||
frm.set_query("parent_cost_center", function() {
|
||||
frappe.ui.form.on("Cost Center", {
|
||||
onload: function (frm) {
|
||||
frm.set_query("parent_cost_center", function () {
|
||||
return {
|
||||
filters: {
|
||||
company: frm.doc.company,
|
||||
is_group: 1
|
||||
}
|
||||
}
|
||||
is_group: 1,
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
refresh: function(frm) {
|
||||
refresh: function (frm) {
|
||||
if (!frm.is_new()) {
|
||||
frm.add_custom_button(__('Update Cost Center Name / Number'), function () {
|
||||
frm.add_custom_button(__("Update Cost Center Name / Number"), function () {
|
||||
frm.trigger("update_cost_center_number");
|
||||
});
|
||||
}
|
||||
|
||||
let intro_txt = '';
|
||||
let intro_txt = "";
|
||||
let doc = frm.doc;
|
||||
frm.toggle_display('cost_center_name', doc.__islocal);
|
||||
frm.toggle_enable(['is_group', 'company'], doc.__islocal);
|
||||
frm.toggle_display("cost_center_name", doc.__islocal);
|
||||
frm.toggle_enable(["is_group", "company"], doc.__islocal);
|
||||
|
||||
if(!doc.__islocal && doc.is_group==1) {
|
||||
intro_txt += __('Note: This Cost Center is a Group. Cannot make accounting entries against groups.');
|
||||
if (!doc.__islocal && doc.is_group == 1) {
|
||||
intro_txt += __(
|
||||
"Note: This Cost Center is a Group. Cannot make accounting entries against groups."
|
||||
);
|
||||
}
|
||||
|
||||
frm.events.hide_unhide_group_ledger(frm);
|
||||
|
||||
frm.toggle_display('sb1', doc.is_group==0);
|
||||
frm.toggle_display("sb1", doc.is_group == 0);
|
||||
frm.set_intro(intro_txt);
|
||||
|
||||
if(!frm.doc.__islocal) {
|
||||
frm.add_custom_button(__('Chart of Cost Centers'),
|
||||
function() { frappe.set_route("Tree", "Cost Center"); });
|
||||
if (!frm.doc.__islocal) {
|
||||
frm.add_custom_button(__("Chart of Cost Centers"), function () {
|
||||
frappe.set_route("Tree", "Cost Center");
|
||||
});
|
||||
|
||||
frm.add_custom_button(__('Budget'),
|
||||
function() { frappe.set_route("List", "Budget", {'cost_center': frm.doc.name}); });
|
||||
frm.add_custom_button(__("Budget"), function () {
|
||||
frappe.set_route("List", "Budget", { cost_center: frm.doc.name });
|
||||
});
|
||||
}
|
||||
},
|
||||
update_cost_center_number: function(frm) {
|
||||
update_cost_center_number: function (frm) {
|
||||
var d = new frappe.ui.Dialog({
|
||||
title: __('Update Cost Center Name / Number'),
|
||||
title: __("Update Cost Center Name / Number"),
|
||||
fields: [
|
||||
{
|
||||
"label": "Cost Center Name",
|
||||
"fieldname": "cost_center_name",
|
||||
"fieldtype": "Data",
|
||||
"reqd": 1,
|
||||
"default": frm.doc.cost_center_name
|
||||
label: "Cost Center Name",
|
||||
fieldname: "cost_center_name",
|
||||
fieldtype: "Data",
|
||||
reqd: 1,
|
||||
default: frm.doc.cost_center_name,
|
||||
},
|
||||
{
|
||||
"label": "Cost Center Number",
|
||||
"fieldname": "cost_center_number",
|
||||
"fieldtype": "Data",
|
||||
"default": frm.doc.cost_center_number
|
||||
label: "Cost Center Number",
|
||||
fieldname: "cost_center_number",
|
||||
fieldtype: "Data",
|
||||
default: frm.doc.cost_center_number,
|
||||
},
|
||||
{
|
||||
"label": __("Merge with existing"),
|
||||
"fieldname": "merge",
|
||||
"fieldtype": "Check",
|
||||
"default": 0
|
||||
}
|
||||
label: __("Merge with existing"),
|
||||
fieldname: "merge",
|
||||
fieldtype: "Check",
|
||||
default: 0,
|
||||
},
|
||||
],
|
||||
primary_action: function() {
|
||||
primary_action: function () {
|
||||
let data = d.get_values();
|
||||
if(data.cost_center_name === frm.doc.cost_center_name && data.cost_center_number === frm.doc.cost_center_number) {
|
||||
if (
|
||||
data.cost_center_name === frm.doc.cost_center_name &&
|
||||
data.cost_center_number === frm.doc.cost_center_number
|
||||
) {
|
||||
d.hide();
|
||||
return;
|
||||
}
|
||||
@@ -83,12 +88,12 @@ frappe.ui.form.on('Cost Center', {
|
||||
cost_center_name: data.cost_center_name,
|
||||
cost_center_number: cstr(data.cost_center_number),
|
||||
company: frm.doc.company,
|
||||
merge: data.merge
|
||||
merge: data.merge,
|
||||
},
|
||||
callback: function(r) {
|
||||
callback: function (r) {
|
||||
frappe.dom.unfreeze();
|
||||
if(!r.exc) {
|
||||
if(r.message) {
|
||||
if (!r.exc) {
|
||||
if (r.message) {
|
||||
frappe.set_route("Form", "Cost Center", r.message);
|
||||
} else {
|
||||
frm.set_value("cost_center_name", data.cost_center_name);
|
||||
@@ -96,44 +101,42 @@ frappe.ui.form.on('Cost Center', {
|
||||
}
|
||||
d.hide();
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
primary_action_label: __('Update')
|
||||
primary_action_label: __("Update"),
|
||||
});
|
||||
d.show();
|
||||
},
|
||||
|
||||
parent_cost_center(frm) {
|
||||
if(!frm.doc.company) {
|
||||
frappe.msgprint(__('Please enter company name first'));
|
||||
if (!frm.doc.company) {
|
||||
frappe.msgprint(__("Please enter company name first"));
|
||||
}
|
||||
},
|
||||
|
||||
hide_unhide_group_ledger(frm) {
|
||||
let doc = frm.doc;
|
||||
if (doc.is_group == 1) {
|
||||
frm.add_custom_button(__('Convert to Non-Group'),
|
||||
() => frm.events.convert_to_ledger(frm));
|
||||
frm.add_custom_button(__("Convert to Non-Group"), () => frm.events.convert_to_ledger(frm));
|
||||
} else if (doc.is_group == 0) {
|
||||
frm.add_custom_button(__('Convert to Group'),
|
||||
() => frm.events.convert_to_group(frm));
|
||||
frm.add_custom_button(__("Convert to Group"), () => frm.events.convert_to_group(frm));
|
||||
}
|
||||
},
|
||||
|
||||
convert_to_group(frm) {
|
||||
frm.call('convert_ledger_to_group').then(r => {
|
||||
if(r.message === 1) {
|
||||
frm.call("convert_ledger_to_group").then((r) => {
|
||||
if (r.message === 1) {
|
||||
frm.refresh();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
convert_to_ledger(frm) {
|
||||
frm.call('convert_group_to_ledger').then(r => {
|
||||
if(r.message === 1) {
|
||||
frm.call("convert_group_to_ledger").then((r) => {
|
||||
if (r.message === 1) {
|
||||
frm.refresh();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Cost Center Number",
|
||||
"read_only": 1
|
||||
"read_only_depends_on": "eval:!doc.__islocal"
|
||||
},
|
||||
{
|
||||
"fieldname": "parent_cost_center",
|
||||
@@ -170,4 +170,4 @@
|
||||
"sort_field": "modified",
|
||||
"sort_order": "ASC",
|
||||
"states": []
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,54 +1,84 @@
|
||||
frappe.treeview_settings["Cost Center"] = {
|
||||
breadcrumb: "Accounts",
|
||||
get_tree_root: false,
|
||||
filters: [{
|
||||
fieldname: "company",
|
||||
fieldtype:"Select",
|
||||
options: erpnext.utils.get_tree_options("company"),
|
||||
label: __("Company"),
|
||||
default: erpnext.utils.get_tree_default("company")
|
||||
}],
|
||||
root_label: "Cost Centers",
|
||||
get_tree_nodes: 'erpnext.accounts.utils.get_children',
|
||||
add_tree_node: 'erpnext.accounts.utils.add_cc',
|
||||
menu_items:[
|
||||
filters: [
|
||||
{
|
||||
label: __('New Company'),
|
||||
action: function() { frappe.new_doc("Company", true) },
|
||||
condition: 'frappe.boot.user.can_create.indexOf("Company") !== -1'
|
||||
}
|
||||
fieldname: "company",
|
||||
fieldtype: "Select",
|
||||
options: erpnext.utils.get_tree_options("company"),
|
||||
label: __("Company"),
|
||||
default: erpnext.utils.get_tree_default("company"),
|
||||
},
|
||||
],
|
||||
fields:[
|
||||
{fieldtype:'Data', fieldname:'cost_center_name', label:__('New Cost Center Name'), reqd:true},
|
||||
{fieldtype:'Check', fieldname:'is_group', label:__('Is Group'),
|
||||
description:__('Further cost centers can be made under Groups but entries can be made against non-Groups')},
|
||||
{fieldtype:'Data', fieldname:'cost_center_number', label:__('Cost Center Number'),
|
||||
description: __("Number of new Cost Center, it will be included in the cost center name as a prefix")}
|
||||
root_label: "Cost Centers",
|
||||
get_tree_nodes: "erpnext.accounts.utils.get_children",
|
||||
add_tree_node: "erpnext.accounts.utils.add_cc",
|
||||
menu_items: [
|
||||
{
|
||||
label: __("New Company"),
|
||||
action: function () {
|
||||
frappe.new_doc("Company", true);
|
||||
},
|
||||
condition: 'frappe.boot.user.can_create.indexOf("Company") !== -1',
|
||||
},
|
||||
],
|
||||
ignore_fields:["parent_cost_center"],
|
||||
onload: function(treeview) {
|
||||
fields: [
|
||||
{ fieldtype: "Data", fieldname: "cost_center_name", label: __("New Cost Center Name"), reqd: true },
|
||||
{
|
||||
fieldtype: "Check",
|
||||
fieldname: "is_group",
|
||||
label: __("Is Group"),
|
||||
description: __(
|
||||
"Further cost centers can be made under Groups but entries can be made against non-Groups"
|
||||
),
|
||||
},
|
||||
{
|
||||
fieldtype: "Data",
|
||||
fieldname: "cost_center_number",
|
||||
label: __("Cost Center Number"),
|
||||
description: __(
|
||||
"Number of new Cost Center, it will be included in the cost center name as a prefix"
|
||||
),
|
||||
},
|
||||
],
|
||||
ignore_fields: ["parent_cost_center"],
|
||||
onload: function (treeview) {
|
||||
function get_company() {
|
||||
return treeview.page.fields_dict.company.get_value();
|
||||
}
|
||||
|
||||
// tools
|
||||
treeview.page.add_inner_button(__("Chart of Accounts"), function() {
|
||||
frappe.set_route('Tree', 'Account', {company: get_company()});
|
||||
}, __('View'));
|
||||
treeview.page.add_inner_button(
|
||||
__("Chart of Accounts"),
|
||||
function () {
|
||||
frappe.set_route("Tree", "Account", { company: get_company() });
|
||||
},
|
||||
__("View")
|
||||
);
|
||||
|
||||
// make
|
||||
treeview.page.add_inner_button(__("Budget List"), function() {
|
||||
frappe.set_route('List', 'Budget', {company: get_company()});
|
||||
}, __('Budget'));
|
||||
treeview.page.add_inner_button(
|
||||
__("Budget List"),
|
||||
function () {
|
||||
frappe.set_route("List", "Budget", { company: get_company() });
|
||||
},
|
||||
__("Budget")
|
||||
);
|
||||
|
||||
treeview.page.add_inner_button(__("Monthly Distribution"), function() {
|
||||
frappe.set_route('List', 'Monthly Distribution', {company: get_company()});
|
||||
}, __('Budget'));
|
||||
treeview.page.add_inner_button(
|
||||
__("Monthly Distribution"),
|
||||
function () {
|
||||
frappe.set_route("List", "Monthly Distribution", { company: get_company() });
|
||||
},
|
||||
__("Budget")
|
||||
);
|
||||
|
||||
treeview.page.add_inner_button(__("Budget Variance Report"), function() {
|
||||
frappe.set_route('query-report', 'Budget Variance Report', {company: get_company()});
|
||||
}, __('Budget'));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
treeview.page.add_inner_button(
|
||||
__("Budget Variance Report"),
|
||||
function () {
|
||||
frappe.set_route("query-report", "Budget Variance Report", { company: get_company() });
|
||||
},
|
||||
__("Budget")
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,19 +1,24 @@
|
||||
// Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Cost Center Allocation', {
|
||||
setup: function(frm) {
|
||||
let filters = {"is_group": 0};
|
||||
if (frm.doc.company) {
|
||||
$.extend(filters, {
|
||||
"company": frm.doc.company
|
||||
});
|
||||
}
|
||||
|
||||
frm.set_query('main_cost_center', function() {
|
||||
frappe.ui.form.on("Cost Center Allocation", {
|
||||
setup: function (frm) {
|
||||
frm.set_query("main_cost_center", function () {
|
||||
return {
|
||||
filters: filters
|
||||
filters: {
|
||||
company: frm.doc.company,
|
||||
is_group: 0,
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
frm.set_query("cost_center", "allocation_percentages", function () {
|
||||
return {
|
||||
filters: {
|
||||
company: frm.doc.company,
|
||||
is_group: 0,
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,44 +1,41 @@
|
||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Coupon Code', {
|
||||
setup: function(frm) {
|
||||
frm.set_query("pricing_rule", function() {
|
||||
frappe.ui.form.on("Coupon Code", {
|
||||
setup: function (frm) {
|
||||
frm.set_query("pricing_rule", function () {
|
||||
return {
|
||||
filters: [
|
||||
["Pricing Rule","coupon_code_based", "=", "1"]
|
||||
]
|
||||
filters: [["Pricing Rule", "coupon_code_based", "=", "1"]],
|
||||
};
|
||||
});
|
||||
},
|
||||
coupon_name:function(frm){
|
||||
if (frm.doc.__islocal===1) {
|
||||
coupon_name: function (frm) {
|
||||
if (frm.doc.__islocal === 1) {
|
||||
frm.trigger("make_coupon_code");
|
||||
}
|
||||
},
|
||||
coupon_type:function(frm){
|
||||
if (frm.doc.__islocal===1) {
|
||||
coupon_type: function (frm) {
|
||||
if (frm.doc.__islocal === 1) {
|
||||
frm.trigger("make_coupon_code");
|
||||
}
|
||||
},
|
||||
make_coupon_code: function(frm) {
|
||||
var coupon_name=frm.doc.coupon_name;
|
||||
make_coupon_code: function (frm) {
|
||||
var coupon_name = frm.doc.coupon_name;
|
||||
var coupon_code;
|
||||
if (frm.doc.coupon_type=='Gift Card') {
|
||||
coupon_code=Math.random().toString(12).substring(2, 12).toUpperCase();
|
||||
if (frm.doc.coupon_type == "Gift Card") {
|
||||
coupon_code = Math.random().toString(12).substring(2, 12).toUpperCase();
|
||||
} else if (frm.doc.coupon_type == "Promotional") {
|
||||
coupon_name = coupon_name.replace(/\s/g, "");
|
||||
coupon_code = coupon_name.toUpperCase().slice(0, 8);
|
||||
}
|
||||
else if(frm.doc.coupon_type=='Promotional'){
|
||||
coupon_name=coupon_name.replace(/\s/g,'');
|
||||
coupon_code=coupon_name.toUpperCase().slice(0,8);
|
||||
}
|
||||
frm.doc.coupon_code=coupon_code;
|
||||
frm.refresh_field('coupon_code');
|
||||
frm.doc.coupon_code = coupon_code;
|
||||
frm.refresh_field("coupon_code");
|
||||
},
|
||||
refresh: function(frm) {
|
||||
refresh: function (frm) {
|
||||
if (frm.doc.pricing_rule) {
|
||||
frm.add_custom_button(__("Add/Edit Coupon Conditions"), function(){
|
||||
frm.add_custom_button(__("Add/Edit Coupon Conditions"), function () {
|
||||
frappe.set_route("Form", "Pricing Rule", frm.doc.pricing_rule);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
{
|
||||
"fieldname": "valid_upto",
|
||||
"fieldtype": "Date",
|
||||
"label": "Valid Upto"
|
||||
"label": "Valid Up To"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval: doc.coupon_type == \"Promotional\"",
|
||||
@@ -115,7 +115,7 @@
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"modified": "2019-10-19 14:48:14.602481",
|
||||
"modified": "2024-01-24 02:20:26.145996",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Coupon Code",
|
||||
|
||||
@@ -1,28 +1,27 @@
|
||||
// Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Currency Exchange Settings', {
|
||||
service_provider: function(frm) {
|
||||
frappe.ui.form.on("Currency Exchange Settings", {
|
||||
service_provider: function (frm) {
|
||||
if (frm.doc.service_provider == "exchangerate.host") {
|
||||
let result = ['result'];
|
||||
let result = ["result"];
|
||||
let params = {
|
||||
date: '{transaction_date}',
|
||||
from: '{from_currency}',
|
||||
to: '{to_currency}'
|
||||
date: "{transaction_date}",
|
||||
from: "{from_currency}",
|
||||
to: "{to_currency}",
|
||||
};
|
||||
add_param(frm, "https://api.exchangerate.host/convert", params, result);
|
||||
} else if (frm.doc.service_provider == "frankfurter.app") {
|
||||
let result = ['rates', '{to_currency}'];
|
||||
let result = ["rates", "{to_currency}"];
|
||||
let params = {
|
||||
base: '{from_currency}',
|
||||
symbols: '{to_currency}'
|
||||
base: "{from_currency}",
|
||||
symbols: "{to_currency}",
|
||||
};
|
||||
add_param(frm, "https://frankfurter.app/{transaction_date}", params, result);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
function add_param(frm, api, params, result) {
|
||||
var row;
|
||||
frm.clear_table("req_params");
|
||||
@@ -30,13 +29,13 @@ function add_param(frm, api, params, result) {
|
||||
|
||||
frm.doc.api_endpoint = api;
|
||||
|
||||
$.each(params, function(key, value) {
|
||||
$.each(params, function (key, value) {
|
||||
row = frm.add_child("req_params");
|
||||
row.key = key;
|
||||
row.value = value;
|
||||
});
|
||||
|
||||
$.each(result, function(key, value) {
|
||||
$.each(result, function (key, value) {
|
||||
row = frm.add_child("result_key");
|
||||
row.key = value;
|
||||
});
|
||||
|
||||
@@ -10,7 +10,7 @@ frappe.ui.form.on("Dunning", {
|
||||
company: frm.doc.company,
|
||||
customer: frm.doc.customer,
|
||||
outstanding_amount: [">", 0],
|
||||
status: "Overdue"
|
||||
status: "Overdue",
|
||||
},
|
||||
};
|
||||
});
|
||||
@@ -19,16 +19,16 @@ frappe.ui.form.on("Dunning", {
|
||||
filters: {
|
||||
company: frm.doc.company,
|
||||
root_type: "Income",
|
||||
is_group: 0
|
||||
}
|
||||
is_group: 0,
|
||||
},
|
||||
};
|
||||
});
|
||||
frm.set_query("cost_center", () => {
|
||||
return {
|
||||
filters: {
|
||||
company: frm.doc.company,
|
||||
is_group: 0
|
||||
}
|
||||
is_group: 0,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
@@ -51,7 +51,8 @@ frappe.ui.form.on("Dunning", {
|
||||
__("Payment"),
|
||||
function () {
|
||||
frm.events.make_payment_entry(frm);
|
||||
}, __("Create")
|
||||
},
|
||||
__("Create")
|
||||
);
|
||||
frm.page.set_inner_btn_group_as_primary(__("Create"));
|
||||
}
|
||||
@@ -69,7 +70,7 @@ frappe.ui.form.on("Dunning", {
|
||||
get_query_filters: {
|
||||
docstatus: 1,
|
||||
status: "Overdue",
|
||||
company: frm.doc.company
|
||||
company: frm.doc.company,
|
||||
},
|
||||
allow_child_item_selection: true,
|
||||
child_fieldname: "payment_schedule",
|
||||
@@ -78,9 +79,12 @@ frappe.ui.form.on("Dunning", {
|
||||
});
|
||||
}
|
||||
|
||||
frappe.dynamic_link = { doc: frm.doc, fieldname: 'customer', doctype: 'Customer' };
|
||||
frappe.dynamic_link = { doc: frm.doc, fieldname: "customer", doctype: "Customer" };
|
||||
|
||||
frm.toggle_display("customer_name", (frm.doc.customer_name && frm.doc.customer_name !== frm.doc.customer));
|
||||
frm.toggle_display(
|
||||
"customer_name",
|
||||
frm.doc.customer_name && frm.doc.customer_name !== frm.doc.customer
|
||||
);
|
||||
},
|
||||
// When multiple companies are set up. in case company name is changed set default company address
|
||||
company: function (frm) {
|
||||
@@ -90,8 +94,8 @@ frappe.ui.form.on("Dunning", {
|
||||
args: { name: frm.doc.company, existing_address: frm.doc.company_address || "" },
|
||||
debounce: 2000,
|
||||
callback: function (r) {
|
||||
frm.set_value("company_address", r && r.message || "");
|
||||
}
|
||||
frm.set_value("company_address", (r && r.message) || "");
|
||||
},
|
||||
});
|
||||
|
||||
if (frm.fields_dict.currency) {
|
||||
@@ -125,16 +129,16 @@ frappe.ui.form.on("Dunning", {
|
||||
transaction_date: frm.doc.posting_date,
|
||||
from_currency: frm.doc.currency,
|
||||
to_currency: company_currency,
|
||||
args: "for_selling"
|
||||
args: "for_selling",
|
||||
},
|
||||
freeze: true,
|
||||
freeze_message: __("Fetching exchange rates ..."),
|
||||
callback: function(r) {
|
||||
callback: function (r) {
|
||||
const exchange_rate = flt(r.message);
|
||||
if (exchange_rate != frm.doc.conversion_rate) {
|
||||
frm.set_value("conversion_rate", exchange_rate);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
} else {
|
||||
frm.trigger("conversion_rate");
|
||||
@@ -166,8 +170,7 @@ frappe.ui.form.on("Dunning", {
|
||||
get_dunning_letter_text: function (frm) {
|
||||
if (frm.doc.dunning_type) {
|
||||
frappe.call({
|
||||
method:
|
||||
"erpnext.accounts.doctype.dunning.dunning.get_dunning_letter_text",
|
||||
method: "erpnext.accounts.doctype.dunning.dunning.get_dunning_letter_text",
|
||||
args: {
|
||||
dunning_type: frm.doc.dunning_type,
|
||||
language: frm.doc.language,
|
||||
@@ -204,10 +207,7 @@ frappe.ui.form.on("Dunning", {
|
||||
calculate_overdue_days: function (frm) {
|
||||
frm.doc.overdue_payments.forEach((row) => {
|
||||
if (frm.doc.posting_date && row.due_date) {
|
||||
const overdue_days = moment(frm.doc.posting_date).diff(
|
||||
row.due_date,
|
||||
"days"
|
||||
);
|
||||
const overdue_days = moment(frm.doc.posting_date).diff(row.due_date, "days");
|
||||
frappe.model.set_value(row.doctype, row.name, "overdue_days", overdue_days);
|
||||
}
|
||||
});
|
||||
@@ -215,15 +215,16 @@ frappe.ui.form.on("Dunning", {
|
||||
calculate_interest: function (frm) {
|
||||
frm.doc.overdue_payments.forEach((row) => {
|
||||
const interest_per_day = frm.doc.rate_of_interest / 100 / 365;
|
||||
const interest = flt((interest_per_day * row.overdue_days * row.outstanding), precision("interest", row));
|
||||
const interest = flt(
|
||||
interest_per_day * row.overdue_days * row.outstanding,
|
||||
precision("interest", row)
|
||||
);
|
||||
frappe.model.set_value(row.doctype, row.name, "interest", interest);
|
||||
});
|
||||
},
|
||||
calculate_totals: function (frm) {
|
||||
const total_interest = frm.doc.overdue_payments
|
||||
.reduce((prev, cur) => prev + cur.interest, 0);
|
||||
const total_outstanding = frm.doc.overdue_payments
|
||||
.reduce((prev, cur) => prev + cur.outstanding, 0);
|
||||
const total_interest = frm.doc.overdue_payments.reduce((prev, cur) => prev + cur.interest, 0);
|
||||
const total_outstanding = frm.doc.overdue_payments.reduce((prev, cur) => prev + cur.outstanding, 0);
|
||||
const dunning_amount = total_interest + frm.doc.dunning_fee;
|
||||
const base_dunning_amount = dunning_amount * frm.doc.conversion_rate;
|
||||
const grand_total = total_outstanding + dunning_amount;
|
||||
@@ -240,8 +241,7 @@ frappe.ui.form.on("Dunning", {
|
||||
},
|
||||
make_payment_entry: function (frm) {
|
||||
return frappe.call({
|
||||
method:
|
||||
"erpnext.accounts.doctype.payment_entry.payment_entry.get_payment_entry",
|
||||
method: "erpnext.accounts.doctype.payment_entry.payment_entry.get_payment_entry",
|
||||
args: {
|
||||
dt: frm.doc.doctype,
|
||||
dn: frm.doc.name,
|
||||
@@ -257,5 +257,5 @@ frappe.ui.form.on("Dunning", {
|
||||
frappe.ui.form.on("Overdue Payment", {
|
||||
interest: function (frm) {
|
||||
frm.trigger("calculate_totals");
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@@ -85,7 +85,14 @@ class Dunning(AccountsController):
|
||||
frappe.throw(
|
||||
_(
|
||||
"The currency of invoice {} ({}) is different from the currency of this dunning ({})."
|
||||
).format(row.sales_invoice, invoice_currency, self.currency)
|
||||
).format(
|
||||
frappe.get_desk_link(
|
||||
"Sales Invoice",
|
||||
row.sales_invoice,
|
||||
),
|
||||
invoice_currency,
|
||||
self.currency,
|
||||
)
|
||||
)
|
||||
|
||||
def validate_overdue_payments(self):
|
||||
|
||||
@@ -1,75 +1,79 @@
|
||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Exchange Rate Revaluation', {
|
||||
setup: function(frm) {
|
||||
frm.set_query("party_type", "accounts", function() {
|
||||
frappe.ui.form.on("Exchange Rate Revaluation", {
|
||||
setup: function (frm) {
|
||||
frm.set_query("party_type", "accounts", function () {
|
||||
return {
|
||||
"filters": {
|
||||
"name": ["in", Object.keys(frappe.boot.party_account_types)],
|
||||
}
|
||||
filters: {
|
||||
name: ["in", Object.keys(frappe.boot.party_account_types)],
|
||||
},
|
||||
};
|
||||
});
|
||||
frm.set_query("account", "accounts", function(doc) {
|
||||
frm.set_query("account", "accounts", function (doc) {
|
||||
return {
|
||||
"filters": {
|
||||
"company": doc.company
|
||||
}
|
||||
filters: {
|
||||
company: doc.company,
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
if(frm.doc.docstatus==1) {
|
||||
refresh: function (frm) {
|
||||
if (frm.doc.docstatus == 1) {
|
||||
frappe.call({
|
||||
method: 'check_journal_entry_condition',
|
||||
method: "check_journal_entry_condition",
|
||||
doc: frm.doc,
|
||||
callback: function(r) {
|
||||
callback: function (r) {
|
||||
if (r.message) {
|
||||
frm.add_custom_button(__('Journal Entries'), function() {
|
||||
return frm.events.make_jv(frm);
|
||||
}, __('Create'));
|
||||
frm.add_custom_button(
|
||||
__("Journal Entries"),
|
||||
function () {
|
||||
return frm.events.make_jv(frm);
|
||||
},
|
||||
__("Create")
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
validate_rounding_loss: function(frm) {
|
||||
validate_rounding_loss: function (frm) {
|
||||
let allowance = frm.doc.rounding_loss_allowance;
|
||||
if (!(allowance >= 0 && allowance < 1)) {
|
||||
frappe.throw(__("Rounding Loss Allowance should be between 0 and 1"));
|
||||
}
|
||||
},
|
||||
|
||||
rounding_loss_allowance: function(frm) {
|
||||
rounding_loss_allowance: function (frm) {
|
||||
frm.events.validate_rounding_loss(frm);
|
||||
},
|
||||
|
||||
validate: function(frm) {
|
||||
validate: function (frm) {
|
||||
frm.events.validate_rounding_loss(frm);
|
||||
},
|
||||
|
||||
get_entries: function(frm, account) {
|
||||
get_entries: function (frm, account) {
|
||||
frappe.call({
|
||||
method: "get_accounts_data",
|
||||
doc: cur_frm.doc,
|
||||
account: account,
|
||||
callback: function(r){
|
||||
callback: function (r) {
|
||||
frappe.model.clear_table(frm.doc, "accounts");
|
||||
if(r.message) {
|
||||
if (r.message) {
|
||||
r.message.forEach((d) => {
|
||||
cur_frm.add_child("accounts",d);
|
||||
cur_frm.add_child("accounts", d);
|
||||
});
|
||||
frm.events.get_total_gain_loss(frm);
|
||||
refresh_field("accounts");
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
get_total_gain_loss: function(frm) {
|
||||
if(!(frm.doc.accounts && frm.doc.accounts.length)) return;
|
||||
get_total_gain_loss: function (frm) {
|
||||
if (!(frm.doc.accounts && frm.doc.accounts.length)) return;
|
||||
|
||||
let total_gain_loss = 0;
|
||||
frm.doc.accounts.forEach((d) => {
|
||||
@@ -80,7 +84,7 @@ frappe.ui.form.on('Exchange Rate Revaluation', {
|
||||
frm.refresh_fields();
|
||||
},
|
||||
|
||||
make_jv : function(frm) {
|
||||
make_jv: function (frm) {
|
||||
let revaluation_journal = null;
|
||||
let zero_balance_journal = null;
|
||||
frappe.call({
|
||||
@@ -88,66 +92,68 @@ frappe.ui.form.on('Exchange Rate Revaluation', {
|
||||
doc: frm.doc,
|
||||
freeze: true,
|
||||
freeze_message: "Making Journal Entries...",
|
||||
callback: function(r){
|
||||
callback: function (r) {
|
||||
if (r.message) {
|
||||
let response = r.message;
|
||||
if(response['revaluation_jv'] || response['zero_balance_jv']) {
|
||||
if (response["revaluation_jv"] || response["zero_balance_jv"]) {
|
||||
frappe.msgprint(__("Journals have been created"));
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
frappe.ui.form.on("Exchange Rate Revaluation Account", {
|
||||
new_exchange_rate: function(frm, cdt, cdn) {
|
||||
new_exchange_rate: function (frm, cdt, cdn) {
|
||||
var row = frappe.get_doc(cdt, cdn);
|
||||
row.new_balance_in_base_currency = flt(row.new_exchange_rate * flt(row.balance_in_account_currency),
|
||||
precision("new_balance_in_base_currency", row));
|
||||
row.new_balance_in_base_currency = flt(
|
||||
row.new_exchange_rate * flt(row.balance_in_account_currency),
|
||||
precision("new_balance_in_base_currency", row)
|
||||
);
|
||||
row.gain_loss = row.new_balance_in_base_currency - flt(row.balance_in_base_currency);
|
||||
refresh_field("accounts");
|
||||
frm.events.get_total_gain_loss(frm);
|
||||
},
|
||||
|
||||
account: function(frm, cdt, cdn) {
|
||||
account: function (frm, cdt, cdn) {
|
||||
var row = locals[cdt][cdn];
|
||||
if (row.account) {
|
||||
get_account_details(frm, cdt, cdn);
|
||||
}
|
||||
},
|
||||
|
||||
party: function(frm, cdt, cdn) {
|
||||
party: function (frm, cdt, cdn) {
|
||||
var row = locals[cdt][cdn];
|
||||
if (row.party && row.account) {
|
||||
get_account_details(frm, cdt, cdn);
|
||||
}
|
||||
},
|
||||
|
||||
accounts_remove: function(frm) {
|
||||
accounts_remove: function (frm) {
|
||||
frm.events.get_total_gain_loss(frm);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
var get_account_details = function(frm, cdt, cdn) {
|
||||
var get_account_details = function (frm, cdt, cdn) {
|
||||
var row = frappe.get_doc(cdt, cdn);
|
||||
if(!frm.doc.company || !frm.doc.posting_date) {
|
||||
if (!frm.doc.company || !frm.doc.posting_date) {
|
||||
frappe.throw(__("Please select Company and Posting Date to getting entries"));
|
||||
}
|
||||
frappe.call({
|
||||
method: "erpnext.accounts.doctype.exchange_rate_revaluation.exchange_rate_revaluation.get_account_details",
|
||||
args:{
|
||||
args: {
|
||||
account: row.account,
|
||||
company: frm.doc.company,
|
||||
posting_date: frm.doc.posting_date,
|
||||
party_type: row.party_type,
|
||||
party: row.party,
|
||||
rounding_loss_allowance: frm.doc.rounding_loss_allowance
|
||||
rounding_loss_allowance: frm.doc.rounding_loss_allowance,
|
||||
},
|
||||
callback: function(r){
|
||||
callback: function (r) {
|
||||
$.extend(row, r.message);
|
||||
refresh_field("accounts");
|
||||
frm.events.get_total_gain_loss(frm);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -628,21 +628,21 @@ def get_account_details(
|
||||
if account_balance and (
|
||||
account_balance[0].balance or account_balance[0].balance_in_account_currency
|
||||
):
|
||||
account_with_new_balance = ExchangeRateRevaluation.calculate_new_account_balance(
|
||||
if account_with_new_balance := ExchangeRateRevaluation.calculate_new_account_balance(
|
||||
company, posting_date, account_balance
|
||||
)
|
||||
row = account_with_new_balance[0]
|
||||
account_details.update(
|
||||
{
|
||||
"balance_in_base_currency": row["balance_in_base_currency"],
|
||||
"balance_in_account_currency": row["balance_in_account_currency"],
|
||||
"current_exchange_rate": row["current_exchange_rate"],
|
||||
"new_exchange_rate": row["new_exchange_rate"],
|
||||
"new_balance_in_base_currency": row["new_balance_in_base_currency"],
|
||||
"new_balance_in_account_currency": row["new_balance_in_account_currency"],
|
||||
"zero_balance": row["zero_balance"],
|
||||
"gain_loss": row["gain_loss"],
|
||||
}
|
||||
)
|
||||
):
|
||||
row = account_with_new_balance[0]
|
||||
account_details.update(
|
||||
{
|
||||
"balance_in_base_currency": row["balance_in_base_currency"],
|
||||
"balance_in_account_currency": row["balance_in_account_currency"],
|
||||
"current_exchange_rate": row["current_exchange_rate"],
|
||||
"new_exchange_rate": row["new_exchange_rate"],
|
||||
"new_balance_in_base_currency": row["new_balance_in_base_currency"],
|
||||
"new_balance_in_account_currency": row["new_balance_in_account_currency"],
|
||||
"zero_balance": row["zero_balance"],
|
||||
"gain_loss": row["gain_loss"],
|
||||
}
|
||||
)
|
||||
|
||||
return account_details
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Finance Book', {
|
||||
refresh: function(frm) {
|
||||
|
||||
}
|
||||
frappe.ui.form.on("Finance Book", {
|
||||
refresh: function (frm) {},
|
||||
});
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
frappe.ui.form.on('Fiscal Year', {
|
||||
onload: function(frm) {
|
||||
if(frm.doc.__islocal) {
|
||||
frm.set_value("year_start_date",
|
||||
frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1));
|
||||
frappe.ui.form.on("Fiscal Year", {
|
||||
onload: function (frm) {
|
||||
if (frm.doc.__islocal) {
|
||||
frm.set_value(
|
||||
"year_start_date",
|
||||
frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)
|
||||
);
|
||||
}
|
||||
},
|
||||
year_start_date: function(frm) {
|
||||
year_start_date: function (frm) {
|
||||
if (!frm.doc.is_short_year) {
|
||||
let year_end_date =
|
||||
frappe.datetime.add_days(frappe.datetime.add_months(frm.doc.year_start_date, 12), -1);
|
||||
let year_end_date = frappe.datetime.add_days(
|
||||
frappe.datetime.add_months(frm.doc.year_start_date, 12),
|
||||
-1
|
||||
);
|
||||
frm.set_value("year_end_date", year_end_date);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"allow_import": 1,
|
||||
"autoname": "field:year",
|
||||
"creation": "2013-01-22 16:50:25",
|
||||
"description": "**Fiscal Year** represents a Financial Year. All accounting entries and other major transactions are tracked against **Fiscal Year**.",
|
||||
"description": "Represents a Financial Year. All accounting entries and other major transactions are tracked against the Fiscal Year.",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"engine": "InnoDB",
|
||||
@@ -82,10 +82,11 @@
|
||||
"icon": "fa fa-calendar",
|
||||
"idx": 1,
|
||||
"links": [],
|
||||
"modified": "2020-11-05 12:16:53.081573",
|
||||
"modified": "2024-01-30 12:35:38.645968",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Fiscal Year",
|
||||
"naming_rule": "By fieldname",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
@@ -118,9 +119,18 @@
|
||||
{
|
||||
"read": 1,
|
||||
"role": "Employee"
|
||||
},
|
||||
{
|
||||
"read": 1,
|
||||
"role": "Accounts Manager"
|
||||
},
|
||||
{
|
||||
"read": 1,
|
||||
"role": "Stock Manager"
|
||||
}
|
||||
],
|
||||
"show_name_in_global_search": 1,
|
||||
"sort_field": "name",
|
||||
"sort_order": "DESC"
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
||||
@@ -39,7 +39,7 @@ def test_record_generator():
|
||||
]
|
||||
|
||||
start = 2012
|
||||
end = now_datetime().year + 5
|
||||
end = now_datetime().year + 25
|
||||
for year in range(start, end):
|
||||
test_records.append(
|
||||
{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('GL Entry', {
|
||||
refresh: function(frm) {
|
||||
frm.page.btn_secondary.hide()
|
||||
}
|
||||
frappe.ui.form.on("GL Entry", {
|
||||
refresh: function (frm) {
|
||||
frm.page.btn_secondary.hide();
|
||||
},
|
||||
});
|
||||
|
||||
@@ -17,9 +17,7 @@
|
||||
"account_currency",
|
||||
"debit_in_account_currency",
|
||||
"credit_in_account_currency",
|
||||
"against_type",
|
||||
"against",
|
||||
"against_link",
|
||||
"against_voucher_type",
|
||||
"against_voucher",
|
||||
"voucher_type",
|
||||
@@ -131,13 +129,6 @@
|
||||
"label": "Credit Amount in Account Currency",
|
||||
"options": "account_currency"
|
||||
},
|
||||
{
|
||||
"fieldname": "against_type",
|
||||
"fieldtype": "Link",
|
||||
"in_filter": 1,
|
||||
"label": "Against Type",
|
||||
"options": "DocType"
|
||||
},
|
||||
{
|
||||
"fieldname": "against",
|
||||
"fieldtype": "Text",
|
||||
@@ -146,13 +137,6 @@
|
||||
"oldfieldname": "against",
|
||||
"oldfieldtype": "Text"
|
||||
},
|
||||
{
|
||||
"fieldname": "against_link",
|
||||
"fieldtype": "Dynamic Link",
|
||||
"in_filter": 1,
|
||||
"label": "Against",
|
||||
"options": "against_type"
|
||||
},
|
||||
{
|
||||
"fieldname": "against_voucher_type",
|
||||
"fieldtype": "Link",
|
||||
@@ -306,7 +290,7 @@
|
||||
"idx": 1,
|
||||
"in_create": 1,
|
||||
"links": [],
|
||||
"modified": "2023-12-18 15:38:14.006208",
|
||||
"modified": "2023-09-26 12:03:23.031733",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "GL Entry",
|
||||
|
||||
@@ -13,16 +13,9 @@ import erpnext
|
||||
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
|
||||
get_checks_for_pl_and_bs_accounts,
|
||||
)
|
||||
from erpnext.accounts.doctype.accounting_dimension_filter.accounting_dimension_filter import (
|
||||
get_dimension_filter_map,
|
||||
)
|
||||
from erpnext.accounts.party import validate_party_frozen_disabled, validate_party_gle_currency
|
||||
from erpnext.accounts.utils import get_account_currency, get_fiscal_year
|
||||
from erpnext.exceptions import (
|
||||
InvalidAccountCurrency,
|
||||
InvalidAccountDimensionError,
|
||||
MandatoryAccountDimensionError,
|
||||
)
|
||||
from erpnext.exceptions import InvalidAccountCurrency
|
||||
|
||||
exclude_from_linked_with = True
|
||||
|
||||
@@ -98,7 +91,6 @@ class GLEntry(Document):
|
||||
if not self.flags.from_repost and self.voucher_type != "Period Closing Voucher":
|
||||
self.validate_account_details(adv_adj)
|
||||
self.validate_dimensions_for_pl_and_bs()
|
||||
self.validate_allowed_dimensions()
|
||||
validate_balance_type(self.account, adv_adj)
|
||||
validate_frozen_account(self.account, adv_adj)
|
||||
|
||||
@@ -208,42 +200,6 @@ class GLEntry(Document):
|
||||
)
|
||||
)
|
||||
|
||||
def validate_allowed_dimensions(self):
|
||||
dimension_filter_map = get_dimension_filter_map()
|
||||
for key, value in dimension_filter_map.items():
|
||||
dimension = key[0]
|
||||
account = key[1]
|
||||
|
||||
if self.account == account:
|
||||
if value["is_mandatory"] and not self.get(dimension):
|
||||
frappe.throw(
|
||||
_("{0} is mandatory for account {1}").format(
|
||||
frappe.bold(frappe.unscrub(dimension)), frappe.bold(self.account)
|
||||
),
|
||||
MandatoryAccountDimensionError,
|
||||
)
|
||||
|
||||
if value["allow_or_restrict"] == "Allow":
|
||||
if self.get(dimension) and self.get(dimension) not in value["allowed_dimensions"]:
|
||||
frappe.throw(
|
||||
_("Invalid value {0} for {1} against account {2}").format(
|
||||
frappe.bold(self.get(dimension)),
|
||||
frappe.bold(frappe.unscrub(dimension)),
|
||||
frappe.bold(self.account),
|
||||
),
|
||||
InvalidAccountDimensionError,
|
||||
)
|
||||
else:
|
||||
if self.get(dimension) and self.get(dimension) in value["allowed_dimensions"]:
|
||||
frappe.throw(
|
||||
_("Invalid value {0} for {1} against account {2}").format(
|
||||
frappe.bold(self.get(dimension)),
|
||||
frappe.bold(frappe.unscrub(dimension)),
|
||||
frappe.bold(self.account),
|
||||
),
|
||||
InvalidAccountDimensionError,
|
||||
)
|
||||
|
||||
def check_pl_account(self):
|
||||
if (
|
||||
self.is_opening == "Yes"
|
||||
|
||||
@@ -1,47 +1,49 @@
|
||||
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Invoice Discounting', {
|
||||
frappe.ui.form.on("Invoice Discounting", {
|
||||
setup: (frm) => {
|
||||
frm.set_query("sales_invoice", "invoices", (doc) => {
|
||||
return {
|
||||
"filters": {
|
||||
"docstatus": 1,
|
||||
"company": doc.company,
|
||||
"outstanding_amount": [">", 0]
|
||||
filters: {
|
||||
docstatus: 1,
|
||||
company: doc.company,
|
||||
outstanding_amount: [">", 0],
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
frm.events.filter_accounts("bank_account", frm, [["account_type", "=", "Bank"]]);
|
||||
frm.events.filter_accounts("bank_charges_account", frm, [["root_type", "=", "Expense"]]);
|
||||
frm.events.filter_accounts("short_term_loan", frm, [["root_type", "=", "Liability"]]);
|
||||
frm.events.filter_accounts("accounts_receivable_discounted", frm, [["account_type", "=", "Receivable"]]);
|
||||
frm.events.filter_accounts("accounts_receivable_discounted", frm, [
|
||||
["account_type", "=", "Receivable"],
|
||||
]);
|
||||
frm.events.filter_accounts("accounts_receivable_credit", frm, [["account_type", "=", "Receivable"]]);
|
||||
frm.events.filter_accounts("accounts_receivable_unpaid", frm, [["account_type", "=", "Receivable"]]);
|
||||
|
||||
},
|
||||
|
||||
filter_accounts: (fieldname, frm, addl_filters) => {
|
||||
let filters = [
|
||||
["company", "=", frm.doc.company],
|
||||
["is_group", "=", 0]
|
||||
["is_group", "=", 0],
|
||||
];
|
||||
if(addl_filters){
|
||||
filters = $.merge(filters , addl_filters);
|
||||
if (addl_filters) {
|
||||
filters = $.merge(filters, addl_filters);
|
||||
}
|
||||
|
||||
frm.set_query(fieldname, () => { return { "filters": filters }; });
|
||||
frm.set_query(fieldname, () => {
|
||||
return { filters: filters };
|
||||
});
|
||||
},
|
||||
|
||||
refresh_filters: (frm) =>{
|
||||
let invoice_accounts = Object.keys(frm.doc.invoices).map(function(key) {
|
||||
refresh_filters: (frm) => {
|
||||
let invoice_accounts = Object.keys(frm.doc.invoices).map(function (key) {
|
||||
return frm.doc.invoices[key].debit_to;
|
||||
});
|
||||
let filters = [
|
||||
["account_type", "=", "Receivable"],
|
||||
["name", "not in", invoice_accounts]
|
||||
["name", "not in", invoice_accounts],
|
||||
];
|
||||
frm.events.filter_accounts("accounts_receivable_credit", frm, filters);
|
||||
frm.events.filter_accounts("accounts_receivable_discounted", frm, filters);
|
||||
@@ -52,19 +54,19 @@ frappe.ui.form.on('Invoice Discounting', {
|
||||
frm.events.show_general_ledger(frm);
|
||||
|
||||
if (frm.doc.docstatus === 0) {
|
||||
frm.add_custom_button(__('Get Invoices'), function() {
|
||||
frm.add_custom_button(__("Get Invoices"), function () {
|
||||
frm.events.get_invoices(frm);
|
||||
});
|
||||
}
|
||||
|
||||
if (frm.doc.docstatus === 1 && frm.doc.status !== "Settled") {
|
||||
if (frm.doc.status == "Sanctioned") {
|
||||
frm.add_custom_button(__('Disburse Loan'), function() {
|
||||
frm.add_custom_button(__("Disburse Loan"), function () {
|
||||
frm.events.create_disbursement_entry(frm);
|
||||
}).addClass("btn-primary");
|
||||
}
|
||||
if (frm.doc.status == "Disbursed") {
|
||||
frm.add_custom_button(__('Close Loan'), function() {
|
||||
frm.add_custom_button(__("Close Loan"), function () {
|
||||
frm.events.close_loan(frm);
|
||||
}).addClass("btn-primary");
|
||||
}
|
||||
@@ -92,119 +94,121 @@ frappe.ui.form.on('Invoice Discounting', {
|
||||
|
||||
calculate_total_amount: (frm) => {
|
||||
let total_amount = 0.0;
|
||||
for (let row of (frm.doc.invoices || [])) {
|
||||
for (let row of frm.doc.invoices || []) {
|
||||
total_amount += flt(row.outstanding_amount);
|
||||
}
|
||||
frm.set_value("total_amount", total_amount);
|
||||
},
|
||||
get_invoices: (frm) => {
|
||||
var d = new frappe.ui.Dialog({
|
||||
title: __('Get Invoices based on Filters'),
|
||||
title: __("Get Invoices based on Filters"),
|
||||
fields: [
|
||||
{
|
||||
"label": "Customer",
|
||||
"fieldname": "customer",
|
||||
"fieldtype": "Link",
|
||||
"options": "Customer"
|
||||
label: "Customer",
|
||||
fieldname: "customer",
|
||||
fieldtype: "Link",
|
||||
options: "Customer",
|
||||
},
|
||||
{
|
||||
"label": "From Date",
|
||||
"fieldname": "from_date",
|
||||
"fieldtype": "Date"
|
||||
label: "From Date",
|
||||
fieldname: "from_date",
|
||||
fieldtype: "Date",
|
||||
},
|
||||
{
|
||||
"label": "To Date",
|
||||
"fieldname": "to_date",
|
||||
"fieldtype": "Date"
|
||||
label: "To Date",
|
||||
fieldname: "to_date",
|
||||
fieldtype: "Date",
|
||||
},
|
||||
{
|
||||
"fieldname": "col_break",
|
||||
"fieldtype": "Column Break",
|
||||
fieldname: "col_break",
|
||||
fieldtype: "Column Break",
|
||||
},
|
||||
{
|
||||
"label": "Min Amount",
|
||||
"fieldname": "min_amount",
|
||||
"fieldtype": "Currency"
|
||||
label: "Min Amount",
|
||||
fieldname: "min_amount",
|
||||
fieldtype: "Currency",
|
||||
},
|
||||
{
|
||||
"label": "Max Amount",
|
||||
"fieldname": "max_amount",
|
||||
"fieldtype": "Currency"
|
||||
}
|
||||
label: "Max Amount",
|
||||
fieldname: "max_amount",
|
||||
fieldtype: "Currency",
|
||||
},
|
||||
],
|
||||
primary_action: function() {
|
||||
primary_action: function () {
|
||||
var data = d.get_values();
|
||||
|
||||
frappe.call({
|
||||
method: "erpnext.accounts.doctype.invoice_discounting.invoice_discounting.get_invoices",
|
||||
args: {
|
||||
filters: data
|
||||
filters: data,
|
||||
},
|
||||
callback: function(r) {
|
||||
if(!r.exc) {
|
||||
callback: function (r) {
|
||||
if (!r.exc) {
|
||||
d.hide();
|
||||
$.each(r.message, function(i, v) {
|
||||
frm.doc.invoices = frm.doc.invoices.filter(row => row.sales_invoice);
|
||||
$.each(r.message, function (i, v) {
|
||||
frm.doc.invoices = frm.doc.invoices.filter((row) => row.sales_invoice);
|
||||
let row = frm.add_child("invoices");
|
||||
$.extend(row, v);
|
||||
frm.events.refresh_filters(frm);
|
||||
});
|
||||
refresh_field("invoices");
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
primary_action_label: __('Get Invocies')
|
||||
primary_action_label: __("Get Invoices"),
|
||||
});
|
||||
d.show();
|
||||
},
|
||||
|
||||
create_disbursement_entry: (frm) => {
|
||||
frappe.call({
|
||||
method:"create_disbursement_entry",
|
||||
method: "create_disbursement_entry",
|
||||
doc: frm.doc,
|
||||
callback: function(r) {
|
||||
if(!r.exc){
|
||||
callback: function (r) {
|
||||
if (!r.exc) {
|
||||
var doclist = frappe.model.sync(r.message);
|
||||
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
close_loan: (frm) => {
|
||||
frappe.call({
|
||||
method:"close_loan",
|
||||
method: "close_loan",
|
||||
doc: frm.doc,
|
||||
callback: function(r) {
|
||||
if(!r.exc){
|
||||
callback: function (r) {
|
||||
if (!r.exc) {
|
||||
var doclist = frappe.model.sync(r.message);
|
||||
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
show_general_ledger: (frm) => {
|
||||
if(frm.doc.docstatus > 0) {
|
||||
cur_frm.add_custom_button(__('Accounting Ledger'), function() {
|
||||
frappe.route_options = {
|
||||
voucher_no: frm.doc.name,
|
||||
from_date: frm.doc.posting_date,
|
||||
to_date: moment(frm.doc.modified).format('YYYY-MM-DD'),
|
||||
company: frm.doc.company,
|
||||
group_by: "Group by Voucher (Consolidated)",
|
||||
show_cancelled_entries: frm.doc.docstatus === 2
|
||||
};
|
||||
frappe.set_route("query-report", "General Ledger");
|
||||
}, __("View"));
|
||||
if (frm.doc.docstatus > 0) {
|
||||
cur_frm.add_custom_button(
|
||||
__("Accounting Ledger"),
|
||||
function () {
|
||||
frappe.route_options = {
|
||||
voucher_no: frm.doc.name,
|
||||
from_date: frm.doc.posting_date,
|
||||
to_date: moment(frm.doc.modified).format("YYYY-MM-DD"),
|
||||
company: frm.doc.company,
|
||||
group_by: "Group by Voucher (Consolidated)",
|
||||
show_cancelled_entries: frm.doc.docstatus === 2,
|
||||
};
|
||||
frappe.set_route("query-report", "General Ledger");
|
||||
},
|
||||
__("View")
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
frappe.ui.form.on('Discounted Invoice', {
|
||||
frappe.ui.form.on("Discounted Invoice", {
|
||||
sales_invoice: (frm) => {
|
||||
frm.events.calculate_total_amount(frm);
|
||||
frm.events.refresh_filters(frm);
|
||||
@@ -212,5 +216,5 @@ frappe.ui.form.on('Discounted Invoice', {
|
||||
invoices_remove: (frm) => {
|
||||
frm.events.calculate_total_amount(frm);
|
||||
frm.events.refresh_filters(frm);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -153,9 +153,7 @@ class InvoiceDiscounting(AccountsController):
|
||||
"account": inv.debit_to,
|
||||
"party_type": "Customer",
|
||||
"party": d.customer,
|
||||
"against_type": "Account",
|
||||
"against": self.accounts_receivable_credit,
|
||||
"against_link": self.accounts_receivable_credit,
|
||||
"credit": outstanding_in_company_currency,
|
||||
"credit_in_account_currency": outstanding_in_company_currency
|
||||
if inv.party_account_currency == company_currency
|
||||
@@ -175,9 +173,7 @@ class InvoiceDiscounting(AccountsController):
|
||||
"account": self.accounts_receivable_credit,
|
||||
"party_type": "Customer",
|
||||
"party": d.customer,
|
||||
"against_type": "Account",
|
||||
"against": inv.debit_to,
|
||||
"against_link": inv.debit_to,
|
||||
"debit": outstanding_in_company_currency,
|
||||
"debit_in_account_currency": outstanding_in_company_currency
|
||||
if ar_credit_account_currency == company_currency
|
||||
|
||||
@@ -1,21 +1,16 @@
|
||||
frappe.listview_settings['Invoice Discounting'] = {
|
||||
frappe.listview_settings["Invoice Discounting"] = {
|
||||
add_fields: ["status"],
|
||||
get_indicator: function(doc)
|
||||
{
|
||||
if(doc.status == "Draft") {
|
||||
get_indicator: function (doc) {
|
||||
if (doc.status == "Draft") {
|
||||
return [__("Draft"), "red", "status,=,Draft"];
|
||||
}
|
||||
else if(doc.status == "Sanctioned") {
|
||||
} else if (doc.status == "Sanctioned") {
|
||||
return [__("Sanctioned"), "green", "status,=,Sanctioned"];
|
||||
}
|
||||
else if(doc.status == "Disbursed") {
|
||||
} else if (doc.status == "Disbursed") {
|
||||
return [__("Disbursed"), "blue", "status,=,Disbursed"];
|
||||
}
|
||||
else if(doc.status == "Settled") {
|
||||
} else if (doc.status == "Settled") {
|
||||
return [__("Settled"), "orange", "status,=,Settled"];
|
||||
}
|
||||
else if(doc.status == "Canceled") {
|
||||
} else if (doc.status == "Canceled") {
|
||||
return [__("Canceled"), "red", "status,=,Canceled"];
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,27 +1,49 @@
|
||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Item Tax Template', {
|
||||
setup: function(frm) {
|
||||
frm.set_query("tax_type", "taxes", function(doc) {
|
||||
frappe.ui.form.on("Item Tax Template", {
|
||||
setup: function (frm) {
|
||||
frm.set_query("tax_type", "taxes", function (doc) {
|
||||
return {
|
||||
filters: [
|
||||
['Account', 'company', '=', frm.doc.company],
|
||||
['Account', 'is_group', '=', 0],
|
||||
['Account', 'account_type', 'in', ['Tax', 'Chargeable', 'Income Account', 'Expense Account', 'Expenses Included In Valuation']]
|
||||
]
|
||||
}
|
||||
["Account", "company", "=", frm.doc.company],
|
||||
["Account", "is_group", "=", 0],
|
||||
[
|
||||
"Account",
|
||||
"account_type",
|
||||
"in",
|
||||
[
|
||||
"Tax",
|
||||
"Chargeable",
|
||||
"Income Account",
|
||||
"Expense Account",
|
||||
"Expenses Included In Valuation",
|
||||
],
|
||||
],
|
||||
],
|
||||
};
|
||||
});
|
||||
},
|
||||
company: function (frm) {
|
||||
frm.set_query("tax_type", "taxes", function(doc) {
|
||||
frm.set_query("tax_type", "taxes", function (doc) {
|
||||
return {
|
||||
filters: [
|
||||
['Account', 'company', '=', frm.doc.company],
|
||||
['Account', 'is_group', '=', 0],
|
||||
['Account', 'account_type', 'in', ['Tax', 'Chargeable', 'Income Account', 'Expense Account', 'Expenses Included In Valuation']]
|
||||
]
|
||||
}
|
||||
["Account", "company", "=", frm.doc.company],
|
||||
["Account", "is_group", "=", 0],
|
||||
[
|
||||
"Account",
|
||||
"account_type",
|
||||
"in",
|
||||
[
|
||||
"Tax",
|
||||
"Chargeable",
|
||||
"Income Account",
|
||||
"Expense Account",
|
||||
"Expenses Included In Valuation",
|
||||
],
|
||||
],
|
||||
],
|
||||
};
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -4,39 +4,82 @@
|
||||
frappe.provide("erpnext.accounts");
|
||||
frappe.provide("erpnext.journal_entry");
|
||||
|
||||
|
||||
frappe.ui.form.on("Journal Entry", {
|
||||
setup: function(frm) {
|
||||
setup: function (frm) {
|
||||
frm.add_fetch("bank_account", "account", "account");
|
||||
frm.ignore_doctypes_on_cancel_all = ['Sales Invoice', 'Purchase Invoice', 'Journal Entry', "Repost Payment Ledger", 'Asset', 'Asset Movement', 'Asset Depreciation Schedule', "Repost Accounting Ledger", "Unreconcile Payment", "Unreconcile Payment Entries"];
|
||||
frm.ignore_doctypes_on_cancel_all = [
|
||||
"Sales Invoice",
|
||||
"Purchase Invoice",
|
||||
"Journal Entry",
|
||||
"Repost Payment Ledger",
|
||||
"Asset",
|
||||
"Asset Movement",
|
||||
"Asset Depreciation Schedule",
|
||||
"Repost Accounting Ledger",
|
||||
"Unreconcile Payment",
|
||||
"Unreconcile Payment Entries",
|
||||
"Bank Transaction",
|
||||
];
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
refresh: function (frm) {
|
||||
erpnext.toggle_naming_series();
|
||||
|
||||
if(frm.doc.docstatus > 0) {
|
||||
frm.add_custom_button(__('Ledger'), function() {
|
||||
frappe.route_options = {
|
||||
"voucher_no": frm.doc.name,
|
||||
"from_date": frm.doc.posting_date,
|
||||
"to_date": moment(frm.doc.modified).format('YYYY-MM-DD'),
|
||||
"company": frm.doc.company,
|
||||
"finance_book": frm.doc.finance_book,
|
||||
"group_by": '',
|
||||
"show_cancelled_entries": frm.doc.docstatus === 2
|
||||
};
|
||||
frappe.set_route("query-report", "General Ledger");
|
||||
}, __('View'));
|
||||
if (frm.doc.repost_required && frm.doc.docstatus === 1) {
|
||||
frm.set_intro(
|
||||
__(
|
||||
"Accounting entries for this Journal Entry need to be reposted. Please click on 'Repost' button to update."
|
||||
)
|
||||
);
|
||||
frm.add_custom_button(__("Repost Accounting Entries"), () => {
|
||||
frm.call({
|
||||
doc: frm.doc,
|
||||
method: "repost_accounting_entries",
|
||||
freeze: true,
|
||||
freeze_message: __("Reposting..."),
|
||||
callback: (r) => {
|
||||
if (!r.exc) {
|
||||
frappe.msgprint(__("Accounting Entries are reposted."));
|
||||
frm.refresh();
|
||||
}
|
||||
},
|
||||
});
|
||||
})
|
||||
.removeClass("btn-default")
|
||||
.addClass("btn-warning");
|
||||
}
|
||||
|
||||
if(frm.doc.docstatus==1) {
|
||||
frm.add_custom_button(__('Reverse Journal Entry'), function() {
|
||||
return erpnext.journal_entry.reverse_journal_entry(frm);
|
||||
}, __('Actions'));
|
||||
if (frm.doc.docstatus > 0) {
|
||||
frm.add_custom_button(
|
||||
__("Ledger"),
|
||||
function () {
|
||||
frappe.route_options = {
|
||||
voucher_no: frm.doc.name,
|
||||
from_date: frm.doc.posting_date,
|
||||
to_date: moment(frm.doc.modified).format("YYYY-MM-DD"),
|
||||
company: frm.doc.company,
|
||||
finance_book: frm.doc.finance_book,
|
||||
group_by: "",
|
||||
show_cancelled_entries: frm.doc.docstatus === 2,
|
||||
};
|
||||
frappe.set_route("query-report", "General Ledger");
|
||||
},
|
||||
__("View")
|
||||
);
|
||||
}
|
||||
|
||||
if (frm.doc.docstatus == 1) {
|
||||
frm.add_custom_button(
|
||||
__("Reverse Journal Entry"),
|
||||
function () {
|
||||
return erpnext.journal_entry.reverse_journal_entry(frm);
|
||||
},
|
||||
__("Actions")
|
||||
);
|
||||
}
|
||||
|
||||
if (frm.doc.__islocal) {
|
||||
frm.add_custom_button(__('Quick Entry'), function() {
|
||||
frm.add_custom_button(__("Quick Entry"), function () {
|
||||
return erpnext.journal_entry.quick_entry(frm);
|
||||
});
|
||||
}
|
||||
@@ -44,52 +87,63 @@ frappe.ui.form.on("Journal Entry", {
|
||||
// hide /unhide fields based on currency
|
||||
erpnext.journal_entry.toggle_fields_based_on_currency(frm);
|
||||
|
||||
if ((frm.doc.voucher_type == "Inter Company Journal Entry") && (frm.doc.docstatus == 1) && (!frm.doc.inter_company_journal_entry_reference)) {
|
||||
frm.add_custom_button(__("Create Inter Company Journal Entry"),
|
||||
function() {
|
||||
if (
|
||||
frm.doc.voucher_type == "Inter Company Journal Entry" &&
|
||||
frm.doc.docstatus == 1 &&
|
||||
!frm.doc.inter_company_journal_entry_reference
|
||||
) {
|
||||
frm.add_custom_button(
|
||||
__("Create Inter Company Journal Entry"),
|
||||
function () {
|
||||
frm.trigger("make_inter_company_journal_entry");
|
||||
}, __('Make'));
|
||||
},
|
||||
__("Make")
|
||||
);
|
||||
}
|
||||
|
||||
erpnext.accounts.unreconcile_payment.add_unreconcile_btn(frm);
|
||||
},
|
||||
before_save: function(frm) {
|
||||
if ((frm.doc.docstatus == 0) && (!frm.doc.is_system_generated)) {
|
||||
let payment_entry_references = frm.doc.accounts.filter(elem => (elem.reference_type == "Payment Entry"));
|
||||
before_save: function (frm) {
|
||||
if (frm.doc.docstatus == 0 && !frm.doc.is_system_generated) {
|
||||
let payment_entry_references = frm.doc.accounts.filter(
|
||||
(elem) => elem.reference_type == "Payment Entry"
|
||||
);
|
||||
if (payment_entry_references.length > 0) {
|
||||
let rows = payment_entry_references.map(x => "#"+x.idx);
|
||||
frappe.throw(__("Rows: {0} have 'Payment Entry' as reference_type. This should not be set manually.", [frappe.utils.comma_and(rows)]));
|
||||
let rows = payment_entry_references.map((x) => "#" + x.idx);
|
||||
frappe.throw(
|
||||
__("Rows: {0} have 'Payment Entry' as reference_type. This should not be set manually.", [
|
||||
frappe.utils.comma_and(rows),
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
make_inter_company_journal_entry: function(frm) {
|
||||
make_inter_company_journal_entry: function (frm) {
|
||||
var d = new frappe.ui.Dialog({
|
||||
title: __("Select Company"),
|
||||
fields: [
|
||||
{
|
||||
'fieldname': 'company',
|
||||
'fieldtype': 'Link',
|
||||
'label': __('Company'),
|
||||
'options': 'Company',
|
||||
"get_query": function () {
|
||||
fieldname: "company",
|
||||
fieldtype: "Link",
|
||||
label: __("Company"),
|
||||
options: "Company",
|
||||
get_query: function () {
|
||||
return {
|
||||
filters: [
|
||||
["Company", "name", "!=", frm.doc.company]
|
||||
]
|
||||
filters: [["Company", "name", "!=", frm.doc.company]],
|
||||
};
|
||||
},
|
||||
'reqd': 1
|
||||
}
|
||||
reqd: 1,
|
||||
},
|
||||
],
|
||||
});
|
||||
d.set_primary_action(__('Create'), function() {
|
||||
d.set_primary_action(__("Create"), function () {
|
||||
d.hide();
|
||||
var args = d.get_values();
|
||||
frappe.call({
|
||||
args: {
|
||||
"name": frm.doc.name,
|
||||
"voucher_type": frm.doc.voucher_type,
|
||||
"company": args.company
|
||||
name: frm.doc.name,
|
||||
voucher_type: frm.doc.voucher_type,
|
||||
company: args.company,
|
||||
},
|
||||
method: "erpnext.accounts.doctype.journal_entry.journal_entry.make_inter_company_journal_entry",
|
||||
callback: function (r) {
|
||||
@@ -97,103 +151,106 @@ frappe.ui.form.on("Journal Entry", {
|
||||
var doc = frappe.model.sync(r.message)[0];
|
||||
frappe.set_route("Form", doc.doctype, doc.name);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
d.show();
|
||||
},
|
||||
|
||||
multi_currency: function(frm) {
|
||||
multi_currency: function (frm) {
|
||||
erpnext.journal_entry.toggle_fields_based_on_currency(frm);
|
||||
},
|
||||
|
||||
posting_date: function(frm) {
|
||||
if(!frm.doc.multi_currency || !frm.doc.posting_date) return;
|
||||
posting_date: function (frm) {
|
||||
if (!frm.doc.multi_currency || !frm.doc.posting_date) return;
|
||||
|
||||
$.each(frm.doc.accounts || [], function(i, row) {
|
||||
$.each(frm.doc.accounts || [], function (i, row) {
|
||||
erpnext.journal_entry.set_exchange_rate(frm, row.doctype, row.name);
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
company: function(frm) {
|
||||
company: function (frm) {
|
||||
frappe.call({
|
||||
method: "frappe.client.get_value",
|
||||
args: {
|
||||
doctype: "Company",
|
||||
filters: {"name": frm.doc.company},
|
||||
fieldname: "cost_center"
|
||||
filters: { name: frm.doc.company },
|
||||
fieldname: "cost_center",
|
||||
},
|
||||
callback: function(r){
|
||||
if(r.message){
|
||||
$.each(frm.doc.accounts || [], function(i, jvd) {
|
||||
callback: function (r) {
|
||||
if (r.message) {
|
||||
$.each(frm.doc.accounts || [], function (i, jvd) {
|
||||
frappe.model.set_value(jvd.doctype, jvd.name, "cost_center", r.message.cost_center);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
erpnext.accounts.dimensions.update_dimension(frm, frm.doctype);
|
||||
},
|
||||
|
||||
voucher_type: function(frm){
|
||||
voucher_type: function (frm) {
|
||||
if (!frm.doc.company) return null;
|
||||
|
||||
if(!frm.doc.company) return null;
|
||||
|
||||
if((!(frm.doc.accounts || []).length) || ((frm.doc.accounts || []).length === 1 && !frm.doc.accounts[0].account)) {
|
||||
if(in_list(["Bank Entry", "Cash Entry"], frm.doc.voucher_type)) {
|
||||
if (
|
||||
!(frm.doc.accounts || []).length ||
|
||||
((frm.doc.accounts || []).length === 1 && !frm.doc.accounts[0].account)
|
||||
) {
|
||||
if (in_list(["Bank Entry", "Cash Entry"], frm.doc.voucher_type)) {
|
||||
return frappe.call({
|
||||
type: "GET",
|
||||
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_default_bank_cash_account",
|
||||
args: {
|
||||
"account_type": (frm.doc.voucher_type=="Bank Entry" ?
|
||||
"Bank" : (frm.doc.voucher_type=="Cash Entry" ? "Cash" : null)),
|
||||
"company": frm.doc.company
|
||||
account_type:
|
||||
frm.doc.voucher_type == "Bank Entry"
|
||||
? "Bank"
|
||||
: frm.doc.voucher_type == "Cash Entry"
|
||||
? "Cash"
|
||||
: null,
|
||||
company: frm.doc.company,
|
||||
},
|
||||
callback: function(r) {
|
||||
if(r.message) {
|
||||
callback: function (r) {
|
||||
if (r.message) {
|
||||
// If default company bank account not set
|
||||
if(!$.isEmptyObject(r.message)){
|
||||
if (!$.isEmptyObject(r.message)) {
|
||||
update_jv_details(frm.doc, [r.message]);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
from_template: function(frm){
|
||||
if (frm.doc.from_template){
|
||||
frappe.db.get_doc("Journal Entry Template", frm.doc.from_template)
|
||||
.then((doc) => {
|
||||
frappe.model.clear_table(frm.doc, "accounts");
|
||||
frm.set_value({
|
||||
"company": doc.company,
|
||||
"voucher_type": doc.voucher_type,
|
||||
"naming_series": doc.naming_series,
|
||||
"is_opening": doc.is_opening,
|
||||
"multi_currency": doc.multi_currency
|
||||
})
|
||||
update_jv_details(frm.doc, doc.accounts);
|
||||
from_template: function (frm) {
|
||||
if (frm.doc.from_template) {
|
||||
frappe.db.get_doc("Journal Entry Template", frm.doc.from_template).then((doc) => {
|
||||
frappe.model.clear_table(frm.doc, "accounts");
|
||||
frm.set_value({
|
||||
company: doc.company,
|
||||
voucher_type: doc.voucher_type,
|
||||
naming_series: doc.naming_series,
|
||||
is_opening: doc.is_opening,
|
||||
multi_currency: doc.multi_currency,
|
||||
});
|
||||
update_jv_details(frm.doc, doc.accounts);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
var update_jv_details = function(doc, r) {
|
||||
$.each(r, function(i, d) {
|
||||
var update_jv_details = function (doc, r) {
|
||||
$.each(r, function (i, d) {
|
||||
var row = frappe.model.add_child(doc, "Journal Entry Account", "accounts");
|
||||
frappe.model.set_value(row.doctype, row.name, "account", d.account)
|
||||
frappe.model.set_value(row.doctype, row.name, "balance", d.balance)
|
||||
frappe.model.set_value(row.doctype, row.name, "account", d.account);
|
||||
});
|
||||
refresh_field("accounts");
|
||||
}
|
||||
};
|
||||
|
||||
erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Controller {
|
||||
onload() {
|
||||
this.load_defaults();
|
||||
this.setup_queries();
|
||||
this.setup_balance_formatter();
|
||||
erpnext.accounts.dimensions.setup_dimension_filters(this.frm, this.frm.doctype);
|
||||
}
|
||||
|
||||
@@ -203,79 +260,67 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
|
||||
|
||||
load_defaults() {
|
||||
//this.frm.show_print_first = true;
|
||||
if(this.frm.doc.__islocal && this.frm.doc.company) {
|
||||
if (this.frm.doc.__islocal && this.frm.doc.company) {
|
||||
frappe.model.set_default_values(this.frm.doc);
|
||||
$.each(this.frm.doc.accounts || [], function(i, jvd) {
|
||||
$.each(this.frm.doc.accounts || [], function (i, jvd) {
|
||||
frappe.model.set_default_values(jvd);
|
||||
});
|
||||
var posting_date = this.frm.doc.posting_date;
|
||||
if(!this.frm.doc.amended_from) this.frm.set_value('posting_date', posting_date || frappe.datetime.get_today());
|
||||
if (!this.frm.doc.amended_from)
|
||||
this.frm.set_value("posting_date", posting_date || frappe.datetime.get_today());
|
||||
}
|
||||
}
|
||||
|
||||
setup_queries() {
|
||||
var me = this;
|
||||
|
||||
me.frm.set_query("account", "accounts", function(doc, cdt, cdn) {
|
||||
me.frm.set_query("account", "accounts", function (doc, cdt, cdn) {
|
||||
return erpnext.journal_entry.account_query(me.frm);
|
||||
});
|
||||
|
||||
me.frm.set_query("against_account_link", "accounts", function(doc, cdt, cdn) {
|
||||
return erpnext.journal_entry.against_account_query(me.frm);
|
||||
});
|
||||
|
||||
me.frm.set_query("against_type", "accounts", function(){
|
||||
return {
|
||||
query: "erpnext.accounts.doctype.journal_entry.journal_entry.get_against_type",
|
||||
}
|
||||
})
|
||||
|
||||
me.frm.set_query("party_type", "accounts", function(doc, cdt, cdn) {
|
||||
me.frm.set_query("party_type", "accounts", function (doc, cdt, cdn) {
|
||||
const row = locals[cdt][cdn];
|
||||
|
||||
return {
|
||||
query: "erpnext.setup.doctype.party_type.party_type.get_party_type",
|
||||
filters: {
|
||||
'account': row.account
|
||||
}
|
||||
}
|
||||
account: row.account,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
me.frm.set_query("reference_name", "accounts", function(doc, cdt, cdn) {
|
||||
me.frm.set_query("reference_name", "accounts", function (doc, cdt, cdn) {
|
||||
var jvd = frappe.get_doc(cdt, cdn);
|
||||
|
||||
// journal entry
|
||||
if(jvd.reference_type==="Journal Entry") {
|
||||
if (jvd.reference_type === "Journal Entry") {
|
||||
frappe.model.validate_missing(jvd, "account");
|
||||
return {
|
||||
query: "erpnext.accounts.doctype.journal_entry.journal_entry.get_against_jv",
|
||||
filters: {
|
||||
account: jvd.account,
|
||||
party: jvd.party
|
||||
}
|
||||
party: jvd.party,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
var out = {
|
||||
filters: [
|
||||
[jvd.reference_type, "docstatus", "=", 1]
|
||||
]
|
||||
filters: [[jvd.reference_type, "docstatus", "=", 1]],
|
||||
};
|
||||
|
||||
if(in_list(["Sales Invoice", "Purchase Invoice"], jvd.reference_type)) {
|
||||
if (in_list(["Sales Invoice", "Purchase Invoice"], jvd.reference_type)) {
|
||||
out.filters.push([jvd.reference_type, "outstanding_amount", "!=", 0]);
|
||||
// Filter by cost center
|
||||
if(jvd.cost_center) {
|
||||
if (jvd.cost_center) {
|
||||
out.filters.push([jvd.reference_type, "cost_center", "in", ["", jvd.cost_center]]);
|
||||
}
|
||||
// account filter
|
||||
frappe.model.validate_missing(jvd, "account");
|
||||
var party_account_field = jvd.reference_type==="Sales Invoice" ? "debit_to": "credit_to";
|
||||
var party_account_field = jvd.reference_type === "Sales Invoice" ? "debit_to" : "credit_to";
|
||||
out.filters.push([jvd.reference_type, party_account_field, "=", jvd.account]);
|
||||
|
||||
}
|
||||
|
||||
if(in_list(["Sales Order", "Purchase Order"], jvd.reference_type)) {
|
||||
if (in_list(["Sales Order", "Purchase Order"], jvd.reference_type)) {
|
||||
// party_type and party mandatory
|
||||
frappe.model.validate_missing(jvd, "party_type");
|
||||
frappe.model.validate_missing(jvd, "party");
|
||||
@@ -283,11 +328,11 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
|
||||
out.filters.push([jvd.reference_type, "per_billed", "<", 100]);
|
||||
}
|
||||
|
||||
if(jvd.party_type && jvd.party) {
|
||||
if (jvd.party_type && jvd.party) {
|
||||
let party_field = "";
|
||||
if(jvd.reference_type.indexOf("Sales")===0) {
|
||||
if (jvd.reference_type.indexOf("Sales") === 0) {
|
||||
party_field = "customer";
|
||||
} else if (jvd.reference_type.indexOf("Purchase")===0) {
|
||||
} else if (jvd.reference_type.indexOf("Purchase") === 0) {
|
||||
party_field = "supplier";
|
||||
}
|
||||
|
||||
@@ -298,64 +343,49 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
|
||||
|
||||
return out;
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
setup_balance_formatter() {
|
||||
const formatter = function(value, df, options, doc) {
|
||||
var currency = frappe.meta.get_field_currency(df, doc);
|
||||
var dr_or_cr = value ? ('<label>' + (value > 0.0 ? __("Dr") : __("Cr")) + '</label>') : "";
|
||||
return "<div style='text-align: right'>"
|
||||
+ ((value==null || value==="") ? "" : format_currency(Math.abs(value), currency))
|
||||
+ " " + dr_or_cr
|
||||
+ "</div>";
|
||||
};
|
||||
this.frm.fields_dict.accounts.grid.update_docfield_property('balance', 'formatter', formatter);
|
||||
this.frm.fields_dict.accounts.grid.update_docfield_property('party_balance', 'formatter', formatter);
|
||||
}
|
||||
|
||||
reference_name(doc, cdt, cdn) {
|
||||
var d = frappe.get_doc(cdt, cdn);
|
||||
|
||||
if(d.reference_name) {
|
||||
if (d.reference_type==="Purchase Invoice" && !flt(d.debit)) {
|
||||
this.get_outstanding('Purchase Invoice', d.reference_name, doc.company, d);
|
||||
} else if (d.reference_type==="Sales Invoice" && !flt(d.credit)) {
|
||||
this.get_outstanding('Sales Invoice', d.reference_name, doc.company, d);
|
||||
} else if (d.reference_type==="Journal Entry" && !flt(d.credit) && !flt(d.debit)) {
|
||||
this.get_outstanding('Journal Entry', d.reference_name, doc.company, d);
|
||||
if (d.reference_name) {
|
||||
if (d.reference_type === "Purchase Invoice" && !flt(d.debit)) {
|
||||
this.get_outstanding("Purchase Invoice", d.reference_name, doc.company, d);
|
||||
} else if (d.reference_type === "Sales Invoice" && !flt(d.credit)) {
|
||||
this.get_outstanding("Sales Invoice", d.reference_name, doc.company, d);
|
||||
} else if (d.reference_type === "Journal Entry" && !flt(d.credit) && !flt(d.debit)) {
|
||||
this.get_outstanding("Journal Entry", d.reference_name, doc.company, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get_outstanding(doctype, docname, company, child) {
|
||||
var args = {
|
||||
"doctype": doctype,
|
||||
"docname": docname,
|
||||
"party": child.party,
|
||||
"account": child.account,
|
||||
"account_currency": child.account_currency,
|
||||
"company": company
|
||||
}
|
||||
doctype: doctype,
|
||||
docname: docname,
|
||||
party: child.party,
|
||||
account: child.account,
|
||||
account_currency: child.account_currency,
|
||||
company: company,
|
||||
};
|
||||
|
||||
return frappe.call({
|
||||
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_outstanding",
|
||||
args: { args: args},
|
||||
callback: function(r) {
|
||||
if(r.message) {
|
||||
$.each(r.message, function(field, value) {
|
||||
args: { args: args },
|
||||
callback: function (r) {
|
||||
if (r.message) {
|
||||
$.each(r.message, function (field, value) {
|
||||
frappe.model.set_value(child.doctype, child.name, field, value);
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
accounts_add(doc, cdt, cdn) {
|
||||
var row = frappe.get_doc(cdt, cdn);
|
||||
$.each(doc.accounts, function(i, d) {
|
||||
if(d.account && d.party && d.party_type) {
|
||||
$.each(doc.accounts, function (i, d) {
|
||||
if (d.account && d.party && d.party_type) {
|
||||
row.account = d.account;
|
||||
row.party = d.party;
|
||||
row.party_type = d.party_type;
|
||||
@@ -363,8 +393,8 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
|
||||
});
|
||||
|
||||
// set difference
|
||||
if(doc.difference) {
|
||||
if(doc.difference > 0) {
|
||||
if (doc.difference) {
|
||||
if (doc.difference > 0) {
|
||||
row.credit_in_account_currency = doc.difference;
|
||||
row.credit = doc.difference;
|
||||
} else {
|
||||
@@ -374,132 +404,141 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
|
||||
}
|
||||
cur_frm.cscript.update_totals(doc);
|
||||
|
||||
erpnext.accounts.dimensions.copy_dimension_from_first_row(this.frm, cdt, cdn, 'accounts');
|
||||
erpnext.accounts.dimensions.copy_dimension_from_first_row(this.frm, cdt, cdn, "accounts");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
cur_frm.script_manager.make(erpnext.accounts.JournalEntry);
|
||||
|
||||
cur_frm.cscript.update_totals = function(doc) {
|
||||
var td=0.0; var tc =0.0;
|
||||
cur_frm.cscript.update_totals = function (doc) {
|
||||
var td = 0.0;
|
||||
var tc = 0.0;
|
||||
var accounts = doc.accounts || [];
|
||||
for(var i in accounts) {
|
||||
for (var i in accounts) {
|
||||
td += flt(accounts[i].debit, precision("debit", accounts[i]));
|
||||
tc += flt(accounts[i].credit, precision("credit", accounts[i]));
|
||||
}
|
||||
doc = locals[doc.doctype][doc.name];
|
||||
doc.total_debit = td;
|
||||
doc.total_credit = tc;
|
||||
doc.difference = flt((td - tc), precision("difference"));
|
||||
refresh_many(['total_debit','total_credit','difference']);
|
||||
}
|
||||
doc.difference = flt(td - tc, precision("difference"));
|
||||
refresh_many(["total_debit", "total_credit", "difference"]);
|
||||
};
|
||||
|
||||
cur_frm.cscript.get_balance = function(doc,dt,dn) {
|
||||
cur_frm.cscript.get_balance = function (doc, dt, dn) {
|
||||
cur_frm.cscript.update_totals(doc);
|
||||
cur_frm.call('get_balance', null, () => { cur_frm.refresh(); });
|
||||
}
|
||||
cur_frm.call("get_balance", null, () => {
|
||||
cur_frm.refresh();
|
||||
});
|
||||
};
|
||||
|
||||
cur_frm.cscript.validate = function(doc,cdt,cdn) {
|
||||
cur_frm.cscript.validate = function (doc, cdt, cdn) {
|
||||
cur_frm.cscript.update_totals(doc);
|
||||
}
|
||||
};
|
||||
|
||||
frappe.ui.form.on("Journal Entry Account", {
|
||||
party: function(frm, cdt, cdn) {
|
||||
party: function (frm, cdt, cdn) {
|
||||
var d = frappe.get_doc(cdt, cdn);
|
||||
if(!d.account && d.party_type && d.party) {
|
||||
if(!frm.doc.company) frappe.throw(__("Please select Company"));
|
||||
if (!d.account && d.party_type && d.party) {
|
||||
if (!frm.doc.company) frappe.throw(__("Please select Company"));
|
||||
return frm.call({
|
||||
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_party_account_and_balance",
|
||||
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_party_account_and_currency",
|
||||
child: d,
|
||||
args: {
|
||||
company: frm.doc.company,
|
||||
party_type: d.party_type,
|
||||
party: d.party,
|
||||
cost_center: d.cost_center
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
cost_center: function(frm, dt, dn) {
|
||||
erpnext.journal_entry.set_account_balance(frm, dt, dn);
|
||||
cost_center: function (frm, dt, dn) {
|
||||
erpnext.journal_entry.set_account_details(frm, dt, dn);
|
||||
},
|
||||
|
||||
account: function(frm, dt, dn) {
|
||||
erpnext.journal_entry.set_account_balance(frm, dt, dn);
|
||||
account: function (frm, dt, dn) {
|
||||
erpnext.journal_entry.set_account_details(frm, dt, dn);
|
||||
},
|
||||
|
||||
debit_in_account_currency: function(frm, cdt, cdn) {
|
||||
debit_in_account_currency: function (frm, cdt, cdn) {
|
||||
erpnext.journal_entry.set_exchange_rate(frm, cdt, cdn);
|
||||
},
|
||||
|
||||
credit_in_account_currency: function(frm, cdt, cdn) {
|
||||
credit_in_account_currency: function (frm, cdt, cdn) {
|
||||
erpnext.journal_entry.set_exchange_rate(frm, cdt, cdn);
|
||||
},
|
||||
|
||||
debit: function(frm, dt, dn) {
|
||||
debit: function (frm, dt, dn) {
|
||||
cur_frm.cscript.update_totals(frm.doc);
|
||||
},
|
||||
|
||||
credit: function(frm, dt, dn) {
|
||||
credit: function (frm, dt, dn) {
|
||||
cur_frm.cscript.update_totals(frm.doc);
|
||||
},
|
||||
|
||||
exchange_rate: function(frm, cdt, cdn) {
|
||||
exchange_rate: function (frm, cdt, cdn) {
|
||||
var company_currency = frappe.get_doc(":Company", frm.doc.company).default_currency;
|
||||
var row = locals[cdt][cdn];
|
||||
|
||||
if(row.account_currency == company_currency || !frm.doc.multi_currency) {
|
||||
if (row.account_currency == company_currency || !frm.doc.multi_currency) {
|
||||
frappe.model.set_value(cdt, cdn, "exchange_rate", 1);
|
||||
}
|
||||
|
||||
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn);
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
frappe.ui.form.on("Journal Entry Account", "accounts_remove", function(frm) {
|
||||
frappe.ui.form.on("Journal Entry Account", "accounts_remove", function (frm) {
|
||||
cur_frm.cscript.update_totals(frm.doc);
|
||||
});
|
||||
|
||||
$.extend(erpnext.journal_entry, {
|
||||
toggle_fields_based_on_currency: function(frm) {
|
||||
toggle_fields_based_on_currency: function (frm) {
|
||||
var fields = ["currency_section", "account_currency", "exchange_rate", "debit", "credit"];
|
||||
|
||||
var grid = frm.get_field("accounts").grid;
|
||||
if(grid) grid.set_column_disp(fields, frm.doc.multi_currency);
|
||||
if (grid) grid.set_column_disp(fields, frm.doc.multi_currency);
|
||||
|
||||
// dynamic label
|
||||
var field_label_map = {
|
||||
"debit_in_account_currency": "Debit",
|
||||
"credit_in_account_currency": "Credit"
|
||||
debit_in_account_currency: "Debit",
|
||||
credit_in_account_currency: "Credit",
|
||||
};
|
||||
|
||||
$.each(field_label_map, function (fieldname, label) {
|
||||
frm.fields_dict.accounts.grid.update_docfield_property(
|
||||
fieldname,
|
||||
'label',
|
||||
frm.doc.multi_currency ? (label + " in Account Currency") : label
|
||||
"label",
|
||||
frm.doc.multi_currency ? label + " in Account Currency" : label
|
||||
);
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
set_debit_credit_in_company_currency: function(frm, cdt, cdn) {
|
||||
set_debit_credit_in_company_currency: function (frm, cdt, cdn) {
|
||||
var row = locals[cdt][cdn];
|
||||
|
||||
frappe.model.set_value(cdt, cdn, "debit",
|
||||
flt(flt(row.debit_in_account_currency)*row.exchange_rate, precision("debit", row)));
|
||||
frappe.model.set_value(
|
||||
cdt,
|
||||
cdn,
|
||||
"debit",
|
||||
flt(flt(row.debit_in_account_currency) * row.exchange_rate, precision("debit", row))
|
||||
);
|
||||
|
||||
frappe.model.set_value(cdt, cdn, "credit",
|
||||
flt(flt(row.credit_in_account_currency)*row.exchange_rate, precision("credit", row)));
|
||||
frappe.model.set_value(
|
||||
cdt,
|
||||
cdn,
|
||||
"credit",
|
||||
flt(flt(row.credit_in_account_currency) * row.exchange_rate, precision("credit", row))
|
||||
);
|
||||
|
||||
cur_frm.cscript.update_totals(frm.doc);
|
||||
},
|
||||
|
||||
set_exchange_rate: function(frm, cdt, cdn) {
|
||||
set_exchange_rate: function (frm, cdt, cdn) {
|
||||
var company_currency = frappe.get_doc(":Company", frm.doc.company).default_currency;
|
||||
var row = locals[cdt][cdn];
|
||||
|
||||
if(row.account_currency == company_currency || !frm.doc.multi_currency) {
|
||||
if (row.account_currency == company_currency || !frm.doc.multi_currency) {
|
||||
row.exchange_rate = 1;
|
||||
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn);
|
||||
} else if (!row.exchange_rate || row.exchange_rate == 1 || row.account_type == "Bank") {
|
||||
@@ -514,50 +553,70 @@ $.extend(erpnext.journal_entry, {
|
||||
reference_name: cstr(row.reference_name),
|
||||
debit: flt(row.debit_in_account_currency),
|
||||
credit: flt(row.credit_in_account_currency),
|
||||
exchange_rate: row.exchange_rate
|
||||
exchange_rate: row.exchange_rate,
|
||||
},
|
||||
callback: function(r) {
|
||||
if(r.message) {
|
||||
callback: function (r) {
|
||||
if (r.message) {
|
||||
row.exchange_rate = r.message;
|
||||
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn);
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
} else {
|
||||
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn);
|
||||
}
|
||||
refresh_field("exchange_rate", cdn, "accounts");
|
||||
},
|
||||
|
||||
quick_entry: function(frm) {
|
||||
quick_entry: function (frm) {
|
||||
var naming_series_options = frm.fields_dict.naming_series.df.options;
|
||||
var naming_series_default = frm.fields_dict.naming_series.df.default || naming_series_options.split("\n")[0];
|
||||
var naming_series_default =
|
||||
frm.fields_dict.naming_series.df.default || naming_series_options.split("\n")[0];
|
||||
|
||||
var dialog = new frappe.ui.Dialog({
|
||||
title: __("Quick Journal Entry"),
|
||||
fields: [
|
||||
{fieldtype: "Currency", fieldname: "debit", label: __("Amount"), reqd: 1},
|
||||
{fieldtype: "Link", fieldname: "debit_account", label: __("Debit Account"), reqd: 1,
|
||||
{ fieldtype: "Currency", fieldname: "debit", label: __("Amount"), reqd: 1 },
|
||||
{
|
||||
fieldtype: "Link",
|
||||
fieldname: "debit_account",
|
||||
label: __("Debit Account"),
|
||||
reqd: 1,
|
||||
options: "Account",
|
||||
get_query: function() {
|
||||
get_query: function () {
|
||||
return erpnext.journal_entry.account_query(frm);
|
||||
}
|
||||
},
|
||||
},
|
||||
{fieldtype: "Link", fieldname: "credit_account", label: __("Credit Account"), reqd: 1,
|
||||
{
|
||||
fieldtype: "Link",
|
||||
fieldname: "credit_account",
|
||||
label: __("Credit Account"),
|
||||
reqd: 1,
|
||||
options: "Account",
|
||||
get_query: function() {
|
||||
get_query: function () {
|
||||
return erpnext.journal_entry.account_query(frm);
|
||||
}
|
||||
},
|
||||
},
|
||||
{fieldtype: "Date", fieldname: "posting_date", label: __("Date"), reqd: 1,
|
||||
default: frm.doc.posting_date},
|
||||
{fieldtype: "Small Text", fieldname: "user_remark", label: __("User Remark")},
|
||||
{fieldtype: "Select", fieldname: "naming_series", label: __("Series"), reqd: 1,
|
||||
options: naming_series_options, default: naming_series_default},
|
||||
]
|
||||
{
|
||||
fieldtype: "Date",
|
||||
fieldname: "posting_date",
|
||||
label: __("Date"),
|
||||
reqd: 1,
|
||||
default: frm.doc.posting_date,
|
||||
},
|
||||
{ fieldtype: "Small Text", fieldname: "user_remark", label: __("User Remark") },
|
||||
{
|
||||
fieldtype: "Select",
|
||||
fieldname: "naming_series",
|
||||
label: __("Series"),
|
||||
reqd: 1,
|
||||
options: naming_series_options,
|
||||
default: naming_series_default,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
dialog.set_primary_action(__("Save"), function() {
|
||||
dialog.set_primary_action(__("Save"), function () {
|
||||
var btn = this;
|
||||
var values = dialog.get_values();
|
||||
|
||||
@@ -574,11 +633,21 @@ $.extend(erpnext.journal_entry, {
|
||||
|
||||
var debit_row = frm.fields_dict.accounts.grid.add_new_row();
|
||||
frappe.model.set_value(debit_row.doctype, debit_row.name, "account", values.debit_account);
|
||||
frappe.model.set_value(debit_row.doctype, debit_row.name, "debit_in_account_currency", values.debit);
|
||||
frappe.model.set_value(
|
||||
debit_row.doctype,
|
||||
debit_row.name,
|
||||
"debit_in_account_currency",
|
||||
values.debit
|
||||
);
|
||||
|
||||
var credit_row = frm.fields_dict.accounts.grid.add_new_row();
|
||||
frappe.model.set_value(credit_row.doctype, credit_row.name, "account", values.credit_account);
|
||||
frappe.model.set_value(credit_row.doctype, credit_row.name, "credit_in_account_currency", values.debit);
|
||||
frappe.model.set_value(
|
||||
credit_row.doctype,
|
||||
credit_row.name,
|
||||
"credit_in_account_currency",
|
||||
values.debit
|
||||
);
|
||||
|
||||
frm.save();
|
||||
|
||||
@@ -588,51 +657,39 @@ $.extend(erpnext.journal_entry, {
|
||||
dialog.show();
|
||||
},
|
||||
|
||||
account_query: function(frm) {
|
||||
account_query: function (frm) {
|
||||
var filters = {
|
||||
company: frm.doc.company,
|
||||
is_group: 0
|
||||
is_group: 0,
|
||||
};
|
||||
if(!frm.doc.multi_currency) {
|
||||
if (!frm.doc.multi_currency) {
|
||||
$.extend(filters, {
|
||||
account_currency: ['in', [frappe.get_doc(":Company", frm.doc.company).default_currency, null]]
|
||||
account_currency: [
|
||||
"in",
|
||||
[frappe.get_doc(":Company", frm.doc.company).default_currency, null],
|
||||
],
|
||||
});
|
||||
}
|
||||
return { filters: filters };
|
||||
},
|
||||
|
||||
against_account_query: function(frm) {
|
||||
if (frm.doc.against_type != "Account"){
|
||||
return { filters: {} };
|
||||
}
|
||||
else {
|
||||
let filters = { company: frm.doc.company, is_group: 0 };
|
||||
if(!frm.doc.multi_currency) {
|
||||
$.extend(filters, {
|
||||
account_currency: ['in', [frappe.get_doc(":Company", frm.doc.company).default_currency, null]]
|
||||
});
|
||||
}
|
||||
return { filters: filters };
|
||||
}
|
||||
},
|
||||
|
||||
reverse_journal_entry: function() {
|
||||
reverse_journal_entry: function () {
|
||||
frappe.model.open_mapped_doc({
|
||||
method: "erpnext.accounts.doctype.journal_entry.journal_entry.make_reverse_journal_entry",
|
||||
frm: cur_frm
|
||||
})
|
||||
frm: cur_frm,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
$.extend(erpnext.journal_entry, {
|
||||
set_account_balance: function(frm, dt, dn) {
|
||||
set_account_details: function (frm, dt, dn) {
|
||||
var d = locals[dt][dn];
|
||||
if(d.account) {
|
||||
if(!frm.doc.company) frappe.throw(__("Please select Company first"));
|
||||
if(!frm.doc.posting_date) frappe.throw(__("Please select Posting Date first"));
|
||||
if (d.account) {
|
||||
if (!frm.doc.company) frappe.throw(__("Please select Company first"));
|
||||
if (!frm.doc.posting_date) frappe.throw(__("Please select Posting Date first"));
|
||||
|
||||
return frappe.call({
|
||||
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_account_balance_and_party_type",
|
||||
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_account_details_and_party_type",
|
||||
args: {
|
||||
account: d.account,
|
||||
date: frm.doc.posting_date,
|
||||
@@ -640,15 +697,14 @@ $.extend(erpnext.journal_entry, {
|
||||
debit: flt(d.debit_in_account_currency),
|
||||
credit: flt(d.credit_in_account_currency),
|
||||
exchange_rate: d.exchange_rate,
|
||||
cost_center: d.cost_center
|
||||
},
|
||||
callback: function(r) {
|
||||
if(r.message) {
|
||||
callback: function (r) {
|
||||
if (r.message) {
|
||||
$.extend(d, r.message);
|
||||
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, dt, dn);
|
||||
refresh_field('accounts');
|
||||
refresh_field("accounts");
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -64,7 +64,8 @@
|
||||
"stock_entry",
|
||||
"subscription_section",
|
||||
"auto_repeat",
|
||||
"amended_from"
|
||||
"amended_from",
|
||||
"repost_required"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
@@ -543,6 +544,15 @@
|
||||
"label": "Is System Generated",
|
||||
"no_copy": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "repost_required",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"label": "Repost Required",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-file-text",
|
||||
@@ -558,6 +568,7 @@
|
||||
}
|
||||
],
|
||||
"modified": "2023-11-23 12:11:04.128015",
|
||||
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Journal Entry",
|
||||
|
||||
@@ -13,6 +13,10 @@ from erpnext.accounts.deferred_revenue import get_deferred_booking_accounts
|
||||
from erpnext.accounts.doctype.invoice_discounting.invoice_discounting import (
|
||||
get_party_account_based_on_invoice_discounting,
|
||||
)
|
||||
from erpnext.accounts.doctype.repost_accounting_ledger.repost_accounting_ledger import (
|
||||
validate_docs_for_deferred_accounting,
|
||||
validate_docs_for_voucher_types,
|
||||
)
|
||||
from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import (
|
||||
get_party_tax_withholding_details,
|
||||
)
|
||||
@@ -140,7 +144,6 @@ class JournalEntry(AccountsController):
|
||||
self.set_print_format_fields()
|
||||
self.validate_credit_debit_note()
|
||||
self.validate_empty_accounts_table()
|
||||
self.set_account_and_party_balance()
|
||||
self.validate_inter_company_accounts()
|
||||
self.validate_depr_entry_voucher_type()
|
||||
|
||||
@@ -150,6 +153,24 @@ class JournalEntry(AccountsController):
|
||||
if not self.title:
|
||||
self.title = self.get_title()
|
||||
|
||||
def validate_for_repost(self):
|
||||
validate_docs_for_voucher_types(["Journal Entry"])
|
||||
validate_docs_for_deferred_accounting([self.name], [])
|
||||
|
||||
def submit(self):
|
||||
if len(self.accounts) > 100:
|
||||
msgprint(_("The task has been enqueued as a background job."), alert=True)
|
||||
self.queue_action("submit", timeout=4600)
|
||||
else:
|
||||
return self._submit()
|
||||
|
||||
def cancel(self):
|
||||
if len(self.accounts) > 100:
|
||||
msgprint(_("The task has been enqueued as a background job."), alert=True)
|
||||
self.queue_action("cancel", timeout=4600)
|
||||
else:
|
||||
return self._cancel()
|
||||
|
||||
def on_submit(self):
|
||||
self.validate_cheque_info()
|
||||
self.check_credit_limit()
|
||||
@@ -159,6 +180,15 @@ class JournalEntry(AccountsController):
|
||||
self.update_inter_company_jv()
|
||||
self.update_invoice_discounting()
|
||||
|
||||
def on_update_after_submit(self):
|
||||
if hasattr(self, "repost_required"):
|
||||
self.needs_repost = self.check_if_fields_updated(
|
||||
fields_to_check=[], child_tables={"accounts": []}
|
||||
)
|
||||
if self.needs_repost:
|
||||
self.validate_for_repost()
|
||||
self.db_set("repost_required", self.needs_repost)
|
||||
|
||||
def on_cancel(self):
|
||||
# References for this Journal are removed on the `on_cancel` event in accounts_controller
|
||||
super(JournalEntry, self).on_cancel()
|
||||
@@ -186,9 +216,12 @@ class JournalEntry(AccountsController):
|
||||
|
||||
def update_advance_paid(self):
|
||||
advance_paid = frappe._dict()
|
||||
advance_payment_doctypes = frappe.get_hooks(
|
||||
"advance_payment_receivable_doctypes"
|
||||
) + frappe.get_hooks("advance_payment_payable_doctypes")
|
||||
for d in self.get("accounts"):
|
||||
if d.is_advance:
|
||||
if d.reference_type in frappe.get_hooks("advance_payment_doctypes"):
|
||||
if d.reference_type in advance_payment_doctypes:
|
||||
advance_paid.setdefault(d.reference_type, []).append(d.reference_name)
|
||||
|
||||
for voucher_type, order_list in advance_paid.items():
|
||||
@@ -304,7 +337,6 @@ class JournalEntry(AccountsController):
|
||||
"account": tax_withholding_details.get("account_head"),
|
||||
rev_debit_or_credit: tax_withholding_details.get("tax_amount"),
|
||||
"against_account": parties[0],
|
||||
"against_account_link": parties[0],
|
||||
},
|
||||
)
|
||||
|
||||
@@ -546,17 +578,28 @@ class JournalEntry(AccountsController):
|
||||
elif d.party_type == "Supplier" and flt(d.credit) > 0:
|
||||
frappe.throw(_("Row {0}: Advance against Supplier must be debit").format(d.idx))
|
||||
|
||||
def system_generated_gain_loss(self):
|
||||
return (
|
||||
self.voucher_type == "Exchange Gain Or Loss"
|
||||
and self.multi_currency
|
||||
and self.is_system_generated
|
||||
)
|
||||
|
||||
def validate_against_jv(self):
|
||||
for d in self.get("accounts"):
|
||||
if d.reference_type == "Journal Entry":
|
||||
account_root_type = frappe.get_cached_value("Account", d.account, "root_type")
|
||||
if account_root_type == "Asset" and flt(d.debit) > 0:
|
||||
if account_root_type == "Asset" and flt(d.debit) > 0 and not self.system_generated_gain_loss():
|
||||
frappe.throw(
|
||||
_(
|
||||
"Row #{0}: For {1}, you can select reference document only if account gets credited"
|
||||
).format(d.idx, d.account)
|
||||
)
|
||||
elif account_root_type == "Liability" and flt(d.credit) > 0:
|
||||
elif (
|
||||
account_root_type == "Liability"
|
||||
and flt(d.credit) > 0
|
||||
and not self.system_generated_gain_loss()
|
||||
):
|
||||
frappe.throw(
|
||||
_(
|
||||
"Row #{0}: For {1}, you can select reference document only if account gets debited"
|
||||
@@ -588,7 +631,7 @@ class JournalEntry(AccountsController):
|
||||
for jvd in against_entries:
|
||||
if flt(jvd[dr_or_cr]) > 0:
|
||||
valid = True
|
||||
if not valid:
|
||||
if not valid and not self.system_generated_gain_loss():
|
||||
frappe.throw(
|
||||
_("Against Journal Entry {0} does not have any unmatched {1} entry").format(
|
||||
d.reference_name, dr_or_cr
|
||||
@@ -751,90 +794,27 @@ class JournalEntry(AccountsController):
|
||||
)
|
||||
|
||||
def set_against_account(self):
|
||||
accounts_debited, accounts_credited = [], []
|
||||
if self.voucher_type in ("Deferred Revenue", "Deferred Expense"):
|
||||
for d in self.get("accounts"):
|
||||
if d.reference_type == "Sales Invoice":
|
||||
against_type = "Customer"
|
||||
field = "customer"
|
||||
else:
|
||||
against_type = "Supplier"
|
||||
field = "supplier"
|
||||
|
||||
against_account = frappe.db.get_value(d.reference_type, d.reference_name, against_type.lower())
|
||||
d.against_type = against_type
|
||||
d.against_account_link = against_account
|
||||
d.against_account = frappe.db.get_value(d.reference_type, d.reference_name, field)
|
||||
else:
|
||||
self.get_debited_credited_accounts()
|
||||
if len(self.accounts_credited) > 1 and len(self.accounts_debited) > 1:
|
||||
self.auto_set_against_accounts()
|
||||
return
|
||||
self.get_against_accounts()
|
||||
for d in self.get("accounts"):
|
||||
if flt(d.debit) > 0:
|
||||
accounts_debited.append(d.party or d.account)
|
||||
if flt(d.credit) > 0:
|
||||
accounts_credited.append(d.party or d.account)
|
||||
|
||||
def auto_set_against_accounts(self):
|
||||
for i in range(0, len(self.accounts), 2):
|
||||
acc = self.accounts[i]
|
||||
against_acc = self.accounts[i + 1]
|
||||
if acc.debit_in_account_currency > 0:
|
||||
current_val = acc.debit_in_account_currency * flt(acc.exchange_rate)
|
||||
against_val = against_acc.credit_in_account_currency * flt(against_acc.exchange_rate)
|
||||
else:
|
||||
current_val = acc.credit_in_account_currency * flt(acc.exchange_rate)
|
||||
against_val = against_acc.debit_in_account_currency * flt(against_acc.exchange_rate)
|
||||
|
||||
if current_val == against_val:
|
||||
acc.against_type = against_acc.party_type or "Account"
|
||||
against_acc.against_type = acc.party_type or "Account"
|
||||
|
||||
acc.against_account_link = against_acc.party or against_acc.account
|
||||
against_acc.against_account_link = acc.party or acc.account
|
||||
else:
|
||||
frappe.msgprint(
|
||||
_(
|
||||
"Unable to automatically determine {0} accounts. Set them up in the {1} table if needed."
|
||||
).format(frappe.bold("against"), frappe.bold("Accounting Entries")),
|
||||
alert=True,
|
||||
)
|
||||
break
|
||||
|
||||
def get_against_accounts(self):
|
||||
self.against_accounts = []
|
||||
self.split_account = {}
|
||||
self.get_debited_credited_accounts()
|
||||
|
||||
if self.separate_against_account_entries:
|
||||
no_of_credited_acc, no_of_debited_acc = len(self.accounts_credited), len(self.accounts_debited)
|
||||
if no_of_credited_acc <= 1 and no_of_debited_acc <= 1:
|
||||
self.set_against_accounts_for_single_dr_cr()
|
||||
self.separate_against_account_entries = 0
|
||||
elif no_of_credited_acc == 1:
|
||||
self.against_accounts = self.accounts_debited
|
||||
self.split_account = self.accounts_credited[0]
|
||||
elif no_of_debited_acc == 1:
|
||||
self.against_accounts = self.accounts_credited
|
||||
self.split_account = self.accounts_debited[0]
|
||||
|
||||
def get_debited_credited_accounts(self):
|
||||
self.accounts_debited, self.accounts_credited = [], []
|
||||
self.separate_against_account_entries = 1
|
||||
for d in self.get("accounts"):
|
||||
if flt(d.debit) > 0:
|
||||
self.accounts_debited.append(d)
|
||||
elif flt(d.credit) > 0:
|
||||
self.accounts_credited.append(d)
|
||||
|
||||
if d.against_account_link:
|
||||
self.separate_against_account_entries = 0
|
||||
break
|
||||
|
||||
def set_against_accounts_for_single_dr_cr(self):
|
||||
against_account = None
|
||||
for d in self.accounts:
|
||||
if flt(d.debit) > 0:
|
||||
against_account = self.accounts_credited[0]
|
||||
elif flt(d.credit) > 0:
|
||||
against_account = self.accounts_debited[0]
|
||||
if against_account:
|
||||
d.against_type = against_account.party_type or "Account"
|
||||
d.against_account = against_account.party or against_account.account
|
||||
d.against_account_link = against_account.party or against_account.account
|
||||
for d in self.get("accounts"):
|
||||
if flt(d.debit) > 0:
|
||||
d.against_account = ", ".join(list(set(accounts_credited)))
|
||||
if flt(d.credit) > 0:
|
||||
d.against_account = ", ".join(list(set(accounts_debited)))
|
||||
|
||||
def validate_debit_credit_amount(self):
|
||||
if not (self.voucher_type == "Exchange Gain Or Loss" and self.multi_currency):
|
||||
@@ -1031,108 +1011,42 @@ class JournalEntry(AccountsController):
|
||||
|
||||
def build_gl_map(self):
|
||||
gl_map = []
|
||||
conversion_rate_map = self.get_conversion_rate_map()
|
||||
transaction_currency_map = self.get_transaction_currency_map()
|
||||
company_currency = erpnext.get_company_currency(self.company)
|
||||
|
||||
self.get_against_accounts()
|
||||
for d in self.get("accounts"):
|
||||
if d.debit or d.credit or (self.voucher_type == "Exchange Gain Or Loss"):
|
||||
r = [d.user_remark, self.remark]
|
||||
r = [x for x in r if x]
|
||||
remarks = "\n".join(r)
|
||||
|
||||
gl_dict = self.get_gl_dict(
|
||||
{
|
||||
"account": d.account,
|
||||
"party_type": d.party_type,
|
||||
"due_date": self.due_date,
|
||||
"party": d.party,
|
||||
"debit": flt(d.debit, d.precision("debit")),
|
||||
"credit": flt(d.credit, d.precision("credit")),
|
||||
"account_currency": d.account_currency,
|
||||
"debit_in_account_currency": flt(
|
||||
d.debit_in_account_currency, d.precision("debit_in_account_currency")
|
||||
),
|
||||
"credit_in_account_currency": flt(
|
||||
d.credit_in_account_currency, d.precision("credit_in_account_currency")
|
||||
),
|
||||
"against_voucher_type": d.reference_type,
|
||||
"against_voucher": d.reference_name,
|
||||
"remarks": remarks,
|
||||
"voucher_detail_no": d.reference_detail_no,
|
||||
"cost_center": d.cost_center,
|
||||
"project": d.project,
|
||||
"finance_book": self.finance_book,
|
||||
"conversion_rate": conversion_rate_map.get(d.against_account_link, 1)
|
||||
if d.account_currency == company_currency
|
||||
else 1,
|
||||
"currency": transaction_currency_map.get(d.against_account_link, d.account_currency)
|
||||
if d.account_currency == company_currency
|
||||
else d.account_currency,
|
||||
},
|
||||
item=d,
|
||||
gl_map.append(
|
||||
self.get_gl_dict(
|
||||
{
|
||||
"account": d.account,
|
||||
"party_type": d.party_type,
|
||||
"due_date": self.due_date,
|
||||
"party": d.party,
|
||||
"against": d.against_account,
|
||||
"debit": flt(d.debit, d.precision("debit")),
|
||||
"credit": flt(d.credit, d.precision("credit")),
|
||||
"account_currency": d.account_currency,
|
||||
"debit_in_account_currency": flt(
|
||||
d.debit_in_account_currency, d.precision("debit_in_account_currency")
|
||||
),
|
||||
"credit_in_account_currency": flt(
|
||||
d.credit_in_account_currency, d.precision("credit_in_account_currency")
|
||||
),
|
||||
"against_voucher_type": d.reference_type,
|
||||
"against_voucher": d.reference_name,
|
||||
"remarks": remarks,
|
||||
"voucher_detail_no": d.reference_detail_no,
|
||||
"cost_center": d.cost_center,
|
||||
"project": d.project,
|
||||
"finance_book": self.finance_book,
|
||||
},
|
||||
item=d,
|
||||
)
|
||||
)
|
||||
|
||||
if not self.separate_against_account_entries:
|
||||
gl_dict.update(
|
||||
{
|
||||
"against_type": d.against_type,
|
||||
"against_link": d.against_account_link,
|
||||
}
|
||||
)
|
||||
gl_map.append(gl_dict)
|
||||
|
||||
elif d in self.against_accounts:
|
||||
gl_dict.update(
|
||||
{
|
||||
"against_type": self.split_account.get("party_type") or "Account",
|
||||
"against": self.split_account.get("party") or self.split_account.get("account"),
|
||||
"against_link": self.split_account.get("party") or self.split_account.get("account"),
|
||||
}
|
||||
)
|
||||
gl_map.append(gl_dict)
|
||||
|
||||
else:
|
||||
for against_account in self.against_accounts:
|
||||
against_account = against_account.as_dict()
|
||||
debit = against_account.credit or against_account.credit_in_account_currency
|
||||
credit = against_account.debit or against_account.debit_in_account_currency
|
||||
gl_dict = gl_dict.copy()
|
||||
gl_dict.update(
|
||||
{
|
||||
"against_type": against_account.party_type or "Account",
|
||||
"against": against_account.party or against_account.account,
|
||||
"against_link": against_account.party or against_account.account,
|
||||
"debit": flt(debit, d.precision("debit")),
|
||||
"credit": flt(credit, d.precision("credit")),
|
||||
"account_currency": d.account_currency,
|
||||
"debit_in_account_currency": flt(
|
||||
debit / d.exchange_rate, d.precision("debit_in_account_currency")
|
||||
),
|
||||
"credit_in_account_currency": flt(
|
||||
credit / d.exchange_rate, d.precision("credit_in_account_currency")
|
||||
),
|
||||
}
|
||||
)
|
||||
gl_map.append(gl_dict)
|
||||
|
||||
return gl_map
|
||||
|
||||
def get_transaction_currency_map(self):
|
||||
transaction_currency_map = {}
|
||||
for account in self.get("accounts"):
|
||||
transaction_currency_map.setdefault(account.party or account.account, account.account_currency)
|
||||
|
||||
return transaction_currency_map
|
||||
|
||||
def get_conversion_rate_map(self):
|
||||
conversion_rate_map = {}
|
||||
for account in self.get("accounts"):
|
||||
conversion_rate_map.setdefault(account.party or account.account, account.exchange_rate)
|
||||
|
||||
return conversion_rate_map
|
||||
|
||||
def make_gl_entries(self, cancel=0, adv_adj=0):
|
||||
from erpnext.accounts.general_ledger import make_gl_entries
|
||||
|
||||
@@ -1265,24 +1179,11 @@ class JournalEntry(AccountsController):
|
||||
if not self.get("accounts"):
|
||||
frappe.throw(_("Accounts table cannot be blank."))
|
||||
|
||||
def set_account_and_party_balance(self):
|
||||
account_balance = {}
|
||||
party_balance = {}
|
||||
for d in self.get("accounts"):
|
||||
if d.account not in account_balance:
|
||||
account_balance[d.account] = get_balance_on(account=d.account, date=self.posting_date)
|
||||
|
||||
if (d.party_type, d.party) not in party_balance:
|
||||
party_balance[(d.party_type, d.party)] = get_balance_on(
|
||||
party_type=d.party_type, party=d.party, date=self.posting_date, company=self.company
|
||||
)
|
||||
|
||||
d.account_balance = account_balance[d.account]
|
||||
d.party_balance = party_balance[(d.party_type, d.party)]
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_default_bank_cash_account(company, account_type=None, mode_of_payment=None, account=None):
|
||||
def get_default_bank_cash_account(
|
||||
company, account_type=None, mode_of_payment=None, account=None, ignore_permissions=False
|
||||
):
|
||||
from erpnext.accounts.doctype.sales_invoice.sales_invoice import get_bank_cash_account
|
||||
|
||||
if mode_of_payment:
|
||||
@@ -1320,7 +1221,7 @@ def get_default_bank_cash_account(company, account_type=None, mode_of_payment=No
|
||||
return frappe._dict(
|
||||
{
|
||||
"account": account,
|
||||
"balance": get_balance_on(account),
|
||||
"balance": get_balance_on(account, ignore_account_permission=ignore_permissions),
|
||||
"account_currency": account_details.account_currency,
|
||||
"account_type": account_details.account_type,
|
||||
}
|
||||
@@ -1445,8 +1346,6 @@ def get_payment_entry(ref_doc, args):
|
||||
"account_type": frappe.get_cached_value("Account", args.get("party_account"), "account_type"),
|
||||
"account_currency": args.get("party_account_currency")
|
||||
or get_account_currency(args.get("party_account")),
|
||||
"balance": get_balance_on(args.get("party_account")),
|
||||
"party_balance": get_balance_on(party=args.get("party"), party_type=args.get("party_type")),
|
||||
"exchange_rate": exchange_rate,
|
||||
args.get("amount_field_party"): args.get("amount"),
|
||||
"is_advance": args.get("is_advance"),
|
||||
@@ -1594,30 +1493,23 @@ def get_outstanding(args):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_party_account_and_balance(company, party_type, party, cost_center=None):
|
||||
def get_party_account_and_currency(company, party_type, party):
|
||||
if not frappe.has_permission("Account"):
|
||||
frappe.msgprint(_("No Permission"), raise_exception=1)
|
||||
|
||||
account = get_party_account(party_type, party, company)
|
||||
|
||||
account_balance = get_balance_on(account=account, cost_center=cost_center)
|
||||
party_balance = get_balance_on(
|
||||
party_type=party_type, party=party, company=company, cost_center=cost_center
|
||||
)
|
||||
|
||||
return {
|
||||
"account": account,
|
||||
"balance": account_balance,
|
||||
"party_balance": party_balance,
|
||||
"account_currency": frappe.get_cached_value("Account", account, "account_currency"),
|
||||
}
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_account_balance_and_party_type(
|
||||
account, date, company, debit=None, credit=None, exchange_rate=None, cost_center=None
|
||||
def get_account_details_and_party_type(
|
||||
account, date, company, debit=None, credit=None, exchange_rate=None
|
||||
):
|
||||
"""Returns dict of account balance and party type to be set in Journal Entry on selection of account."""
|
||||
"""Returns dict of account details and party type to be set in Journal Entry on selection of account."""
|
||||
if not frappe.has_permission("Account"):
|
||||
frappe.msgprint(_("No Permission"), raise_exception=1)
|
||||
|
||||
@@ -1637,7 +1529,6 @@ def get_account_balance_and_party_type(
|
||||
party_type = ""
|
||||
|
||||
grid_values = {
|
||||
"balance": get_balance_on(account, date, cost_center=cost_center),
|
||||
"party_type": party_type,
|
||||
"account_type": account_details.account_type,
|
||||
"account_currency": account_details.account_currency or company_currency,
|
||||
@@ -1755,10 +1646,3 @@ def make_reverse_journal_entry(source_name, target_doc=None):
|
||||
)
|
||||
|
||||
return doclist
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_against_type(doctype, txt, searchfield, start, page_len, filters):
|
||||
against_types = frappe.db.get_list("Party Type", pluck="name") + ["Account"]
|
||||
doctype = frappe.qb.DocType("DocType")
|
||||
return frappe.qb.from_(doctype).select(doctype.name).where(doctype.name.isin(against_types)).run()
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
frappe.listview_settings['Journal Entry'] = {
|
||||
frappe.listview_settings["Journal Entry"] = {
|
||||
add_fields: ["voucher_type", "posting_date", "total_debit", "company", "user_remark"],
|
||||
get_indicator: function(doc) {
|
||||
if(doc.docstatus==0) {
|
||||
return [__("Draft", "red", "docstatus,=,0")]
|
||||
} else if(doc.docstatus==2) {
|
||||
return [__("Cancelled", "grey", "docstatus,=,2")]
|
||||
} else {
|
||||
return [__(doc.voucher_type), "blue", "voucher_type,=," + doc.voucher_type]
|
||||
get_indicator: function (doc) {
|
||||
if (doc.docstatus === 1) {
|
||||
return [__(doc.voucher_type), "blue", `voucher_type,=,${doc.voucher_type}`];
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -166,43 +166,37 @@ class TestJournalEntry(unittest.TestCase):
|
||||
jv.get("accounts")[1].credit_in_account_currency = 5000
|
||||
jv.submit()
|
||||
|
||||
gl_entries = frappe.db.sql(
|
||||
"""select account, account_currency, debit, credit,
|
||||
debit_in_account_currency, credit_in_account_currency
|
||||
from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s
|
||||
order by account asc""",
|
||||
jv.name,
|
||||
as_dict=1,
|
||||
)
|
||||
self.voucher_no = jv.name
|
||||
|
||||
self.assertTrue(gl_entries)
|
||||
self.fields = [
|
||||
"account",
|
||||
"account_currency",
|
||||
"debit",
|
||||
"debit_in_account_currency",
|
||||
"credit",
|
||||
"credit_in_account_currency",
|
||||
]
|
||||
|
||||
expected_values = {
|
||||
"_Test Bank USD - _TC": {
|
||||
"account_currency": "USD",
|
||||
"debit": 5000,
|
||||
"debit_in_account_currency": 100,
|
||||
"credit": 0,
|
||||
"credit_in_account_currency": 0,
|
||||
},
|
||||
"_Test Bank - _TC": {
|
||||
self.expected_gle = [
|
||||
{
|
||||
"account": "_Test Bank - _TC",
|
||||
"account_currency": "INR",
|
||||
"debit": 0,
|
||||
"debit_in_account_currency": 0,
|
||||
"credit": 5000,
|
||||
"credit_in_account_currency": 5000,
|
||||
},
|
||||
}
|
||||
{
|
||||
"account": "_Test Bank USD - _TC",
|
||||
"account_currency": "USD",
|
||||
"debit": 5000,
|
||||
"debit_in_account_currency": 100,
|
||||
"credit": 0,
|
||||
"credit_in_account_currency": 0,
|
||||
},
|
||||
]
|
||||
|
||||
for field in (
|
||||
"account_currency",
|
||||
"debit",
|
||||
"debit_in_account_currency",
|
||||
"credit",
|
||||
"credit_in_account_currency",
|
||||
):
|
||||
for i, gle in enumerate(gl_entries):
|
||||
self.assertEqual(expected_values[gle.account][field], gle[field])
|
||||
self.check_gl_entries()
|
||||
|
||||
# cancel
|
||||
jv.cancel()
|
||||
@@ -228,43 +222,37 @@ class TestJournalEntry(unittest.TestCase):
|
||||
rjv.posting_date = nowdate()
|
||||
rjv.submit()
|
||||
|
||||
gl_entries = frappe.db.sql(
|
||||
"""select account, account_currency, debit, credit,
|
||||
debit_in_account_currency, credit_in_account_currency
|
||||
from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s
|
||||
order by account asc""",
|
||||
rjv.name,
|
||||
as_dict=1,
|
||||
)
|
||||
self.voucher_no = rjv.name
|
||||
|
||||
self.assertTrue(gl_entries)
|
||||
self.fields = [
|
||||
"account",
|
||||
"account_currency",
|
||||
"debit",
|
||||
"credit",
|
||||
"debit_in_account_currency",
|
||||
"credit_in_account_currency",
|
||||
]
|
||||
|
||||
expected_values = {
|
||||
"_Test Bank USD - _TC": {
|
||||
self.expected_gle = [
|
||||
{
|
||||
"account": "_Test Bank USD - _TC",
|
||||
"account_currency": "USD",
|
||||
"debit": 0,
|
||||
"debit_in_account_currency": 0,
|
||||
"credit": 5000,
|
||||
"credit_in_account_currency": 100,
|
||||
},
|
||||
"Sales - _TC": {
|
||||
{
|
||||
"account": "Sales - _TC",
|
||||
"account_currency": "INR",
|
||||
"debit": 5000,
|
||||
"debit_in_account_currency": 5000,
|
||||
"credit": 0,
|
||||
"credit_in_account_currency": 0,
|
||||
},
|
||||
}
|
||||
]
|
||||
|
||||
for field in (
|
||||
"account_currency",
|
||||
"debit",
|
||||
"debit_in_account_currency",
|
||||
"credit",
|
||||
"credit_in_account_currency",
|
||||
):
|
||||
for i, gle in enumerate(gl_entries):
|
||||
self.assertEqual(expected_values[gle.account][field], gle[field])
|
||||
self.check_gl_entries()
|
||||
|
||||
def test_disallow_change_in_account_currency_for_a_party(self):
|
||||
# create jv in USD
|
||||
@@ -344,23 +332,25 @@ class TestJournalEntry(unittest.TestCase):
|
||||
jv.insert()
|
||||
jv.submit()
|
||||
|
||||
expected_values = {
|
||||
"_Test Cash - _TC": {"cost_center": cost_center},
|
||||
"_Test Bank - _TC": {"cost_center": cost_center},
|
||||
}
|
||||
self.voucher_no = jv.name
|
||||
|
||||
gl_entries = frappe.db.sql(
|
||||
"""select account, cost_center, debit, credit
|
||||
from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s
|
||||
order by account asc""",
|
||||
jv.name,
|
||||
as_dict=1,
|
||||
)
|
||||
self.fields = [
|
||||
"account",
|
||||
"cost_center",
|
||||
]
|
||||
|
||||
self.assertTrue(gl_entries)
|
||||
self.expected_gle = [
|
||||
{
|
||||
"account": "_Test Bank - _TC",
|
||||
"cost_center": cost_center,
|
||||
},
|
||||
{
|
||||
"account": "_Test Cash - _TC",
|
||||
"cost_center": cost_center,
|
||||
},
|
||||
]
|
||||
|
||||
for gle in gl_entries:
|
||||
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
|
||||
self.check_gl_entries()
|
||||
|
||||
def test_jv_with_project(self):
|
||||
from erpnext.projects.doctype.project.test_project import make_project
|
||||
@@ -387,23 +377,22 @@ class TestJournalEntry(unittest.TestCase):
|
||||
jv.insert()
|
||||
jv.submit()
|
||||
|
||||
expected_values = {
|
||||
"_Test Cash - _TC": {"project": project_name},
|
||||
"_Test Bank - _TC": {"project": project_name},
|
||||
}
|
||||
self.voucher_no = jv.name
|
||||
|
||||
gl_entries = frappe.db.sql(
|
||||
"""select account, project, debit, credit
|
||||
from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s
|
||||
order by account asc""",
|
||||
jv.name,
|
||||
as_dict=1,
|
||||
)
|
||||
self.fields = ["account", "project"]
|
||||
|
||||
self.assertTrue(gl_entries)
|
||||
self.expected_gle = [
|
||||
{
|
||||
"account": "_Test Bank - _TC",
|
||||
"project": project_name,
|
||||
},
|
||||
{
|
||||
"account": "_Test Cash - _TC",
|
||||
"project": project_name,
|
||||
},
|
||||
]
|
||||
|
||||
for gle in gl_entries:
|
||||
self.assertEqual(expected_values[gle.account]["project"], gle.project)
|
||||
self.check_gl_entries()
|
||||
|
||||
def test_jv_account_and_party_balance_with_cost_centre(self):
|
||||
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
|
||||
@@ -426,6 +415,79 @@ class TestJournalEntry(unittest.TestCase):
|
||||
account_balance = get_balance_on(account="_Test Bank - _TC", cost_center=cost_center)
|
||||
self.assertEqual(expected_account_balance, account_balance)
|
||||
|
||||
def test_repost_accounting_entries(self):
|
||||
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
|
||||
|
||||
# Configure Repost Accounting Ledger for JVs
|
||||
settings = frappe.get_doc("Repost Accounting Ledger Settings")
|
||||
if not [x for x in settings.allowed_types if x.document_type == "Journal Entry"]:
|
||||
settings.append("allowed_types", {"document_type": "Journal Entry", "allowed": True})
|
||||
settings.save()
|
||||
|
||||
# Create JV with defaut cost center - _Test Cost Center
|
||||
jv = make_journal_entry("_Test Cash - _TC", "_Test Bank - _TC", 100, save=False)
|
||||
jv.multi_currency = 0
|
||||
jv.submit()
|
||||
|
||||
# Check GL entries before reposting
|
||||
self.voucher_no = jv.name
|
||||
|
||||
self.fields = [
|
||||
"account",
|
||||
"debit_in_account_currency",
|
||||
"credit_in_account_currency",
|
||||
"cost_center",
|
||||
]
|
||||
|
||||
self.expected_gle = [
|
||||
{
|
||||
"account": "_Test Bank - _TC",
|
||||
"debit_in_account_currency": 0,
|
||||
"credit_in_account_currency": 100,
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
},
|
||||
{
|
||||
"account": "_Test Cash - _TC",
|
||||
"debit_in_account_currency": 100,
|
||||
"credit_in_account_currency": 0,
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
},
|
||||
]
|
||||
|
||||
self.check_gl_entries()
|
||||
|
||||
# Change cost center for bank account - _Test Cost Center for BS Account
|
||||
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
|
||||
jv.accounts[1].cost_center = "_Test Cost Center for BS Account - _TC"
|
||||
jv.save()
|
||||
|
||||
# Check if repost flag gets set on update after submit
|
||||
self.assertTrue(jv.repost_required)
|
||||
jv.repost_accounting_entries()
|
||||
|
||||
# Check GL entries after reposting
|
||||
jv.load_from_db()
|
||||
self.expected_gle[0]["cost_center"] = "_Test Cost Center for BS Account - _TC"
|
||||
self.check_gl_entries()
|
||||
|
||||
def check_gl_entries(self):
|
||||
gl = frappe.qb.DocType("GL Entry")
|
||||
query = frappe.qb.from_(gl)
|
||||
for field in self.fields:
|
||||
query = query.select(gl[field])
|
||||
|
||||
query = query.where(
|
||||
(gl.voucher_type == "Journal Entry")
|
||||
& (gl.voucher_no == self.voucher_no)
|
||||
& (gl.is_cancelled == 0)
|
||||
).orderby(gl.account)
|
||||
|
||||
gl_entries = query.run(as_dict=True)
|
||||
|
||||
for i in range(len(self.expected_gle)):
|
||||
for field in self.fields:
|
||||
self.assertEqual(self.expected_gle[i][field], gl_entries[i][field])
|
||||
|
||||
|
||||
def make_journal_entry(
|
||||
account1,
|
||||
|
||||
@@ -9,12 +9,10 @@
|
||||
"field_order": [
|
||||
"account",
|
||||
"account_type",
|
||||
"balance",
|
||||
"col_break1",
|
||||
"bank_account",
|
||||
"party_type",
|
||||
"party",
|
||||
"party_balance",
|
||||
"accounting_dimensions_section",
|
||||
"cost_center",
|
||||
"dimension_col_break",
|
||||
@@ -37,9 +35,7 @@
|
||||
"col_break3",
|
||||
"is_advance",
|
||||
"user_remark",
|
||||
"against_type",
|
||||
"against_account",
|
||||
"against_account_link"
|
||||
"against_account"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
@@ -66,17 +62,7 @@
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "balance",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Account Balance",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "balance",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "account_currency",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"default": ":Company",
|
||||
"description": "If Income or Expense",
|
||||
"fieldname": "cost_center",
|
||||
@@ -109,14 +95,6 @@
|
||||
"label": "Party",
|
||||
"options": "party_type"
|
||||
},
|
||||
{
|
||||
"fieldname": "party_balance",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Party Balance",
|
||||
"options": "account_currency",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "currency_section",
|
||||
"fieldtype": "Section Break",
|
||||
@@ -225,6 +203,7 @@
|
||||
"no_copy": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"fieldname": "project",
|
||||
"fieldtype": "Link",
|
||||
"label": "Project",
|
||||
@@ -252,21 +231,14 @@
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "against_account",
|
||||
"fieldtype": "Text",
|
||||
"hidden": 1,
|
||||
"label": "Against Account",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "against_account",
|
||||
"oldfieldtype": "Text",
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "against_account_link",
|
||||
"fieldtype": "Dynamic Link",
|
||||
"fieldname": "against_account",
|
||||
"fieldtype": "Text",
|
||||
"hidden": 1,
|
||||
"label": "Against Account",
|
||||
"no_copy": 1,
|
||||
"options": "against_type"
|
||||
"oldfieldname": "against_account",
|
||||
"oldfieldtype": "Text",
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
@@ -290,18 +262,12 @@
|
||||
"hidden": 1,
|
||||
"label": "Reference Detail No",
|
||||
"no_copy": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "against_type",
|
||||
"fieldtype": "Link",
|
||||
"label": "Against Type",
|
||||
"options": "DocType"
|
||||
}
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2023-12-02 23:21:22.205409",
|
||||
"modified": "2024-02-05 01:10:50.224840",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Journal Entry Account",
|
||||
|
||||
@@ -2,78 +2,85 @@
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on("Journal Entry Template", {
|
||||
onload: function(frm) {
|
||||
if(frm.is_new()) {
|
||||
onload: function (frm) {
|
||||
if (frm.is_new()) {
|
||||
frappe.call({
|
||||
type: "GET",
|
||||
method: "erpnext.accounts.doctype.journal_entry_template.journal_entry_template.get_naming_series",
|
||||
callback: function(r){
|
||||
if(r.message) {
|
||||
callback: function (r) {
|
||||
if (r.message) {
|
||||
frm.set_df_property("naming_series", "options", r.message.split("\n"));
|
||||
frm.set_value("naming_series", r.message.split("\n")[0]);
|
||||
frm.refresh_field("naming_series");
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
refresh: function(frm) {
|
||||
refresh: function (frm) {
|
||||
frappe.model.set_default_values(frm.doc);
|
||||
|
||||
frm.set_query("account" ,"accounts", function(){
|
||||
frm.set_query("account", "accounts", function () {
|
||||
var filters = {
|
||||
company: frm.doc.company,
|
||||
is_group: 0
|
||||
is_group: 0,
|
||||
};
|
||||
|
||||
if(!frm.doc.multi_currency) {
|
||||
if (!frm.doc.multi_currency) {
|
||||
$.extend(filters, {
|
||||
account_currency: ['in', [frappe.get_doc(":Company", frm.doc.company).default_currency, null]]
|
||||
account_currency: [
|
||||
"in",
|
||||
[frappe.get_doc(":Company", frm.doc.company).default_currency, null],
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
return { filters: filters };
|
||||
});
|
||||
},
|
||||
voucher_type: function(frm) {
|
||||
var add_accounts = function(doc, r) {
|
||||
$.each(r, function(i, d) {
|
||||
voucher_type: function (frm) {
|
||||
var add_accounts = function (doc, r) {
|
||||
$.each(r, function (i, d) {
|
||||
var row = frappe.model.add_child(doc, "Journal Entry Template Account", "accounts");
|
||||
row.account = d.account;
|
||||
});
|
||||
refresh_field("accounts");
|
||||
};
|
||||
|
||||
if(!frm.doc.company) return;
|
||||
if (!frm.doc.company) return;
|
||||
|
||||
frm.trigger("clear_child");
|
||||
switch(frm.doc.voucher_type){
|
||||
switch (frm.doc.voucher_type) {
|
||||
case "Bank Entry":
|
||||
case "Cash Entry":
|
||||
frappe.call({
|
||||
type: "GET",
|
||||
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_default_bank_cash_account",
|
||||
args: {
|
||||
"account_type": (frm.doc.voucher_type=="Bank Entry" ?
|
||||
"Bank" : (frm.doc.voucher_type=="Cash Entry" ? "Cash" : null)),
|
||||
"company": frm.doc.company
|
||||
account_type:
|
||||
frm.doc.voucher_type == "Bank Entry"
|
||||
? "Bank"
|
||||
: frm.doc.voucher_type == "Cash Entry"
|
||||
? "Cash"
|
||||
: null,
|
||||
company: frm.doc.company,
|
||||
},
|
||||
callback: function(r) {
|
||||
if(r.message) {
|
||||
callback: function (r) {
|
||||
if (r.message) {
|
||||
// If default company bank account not set
|
||||
if(!$.isEmptyObject(r.message)){
|
||||
if (!$.isEmptyObject(r.message)) {
|
||||
add_accounts(frm.doc, [r.message]);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
break;
|
||||
default:
|
||||
frm.trigger("clear_child");
|
||||
}
|
||||
},
|
||||
clear_child: function(frm){
|
||||
clear_child: function (frm) {
|
||||
frappe.model.clear_table(frm.doc, "accounts");
|
||||
frm.refresh_field("accounts");
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// Copyright (c) 2021, Wahni Green Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Ledger Merge', {
|
||||
setup: function(frm) {
|
||||
frappe.realtime.on('ledger_merge_refresh', ({ ledger_merge }) => {
|
||||
frappe.ui.form.on("Ledger Merge", {
|
||||
setup: function (frm) {
|
||||
frappe.realtime.on("ledger_merge_refresh", ({ ledger_merge }) => {
|
||||
if (ledger_merge !== frm.doc.name) return;
|
||||
frappe.model.clear_doc(frm.doc.doctype, frm.doc.name);
|
||||
frappe.model.with_doc(frm.doc.doctype, frm.doc.name).then(() => {
|
||||
@@ -11,29 +11,29 @@ frappe.ui.form.on('Ledger Merge', {
|
||||
});
|
||||
});
|
||||
|
||||
frappe.realtime.on('ledger_merge_progress', data => {
|
||||
frappe.realtime.on("ledger_merge_progress", (data) => {
|
||||
if (data.ledger_merge !== frm.doc.name) return;
|
||||
let message = __('Merging {0} of {1}', [data.current, data.total]);
|
||||
let message = __("Merging {0} of {1}", [data.current, data.total]);
|
||||
let percent = Math.floor((data.current * 100) / data.total);
|
||||
frm.dashboard.show_progress(__('Merge Progress'), percent, message);
|
||||
frm.page.set_indicator(__('In Progress'), 'orange');
|
||||
frm.dashboard.show_progress(__("Merge Progress"), percent, message);
|
||||
frm.page.set_indicator(__("In Progress"), "orange");
|
||||
});
|
||||
|
||||
frm.set_query("account", function(doc) {
|
||||
if (!doc.company) frappe.throw(__('Please set Company'));
|
||||
if (!doc.root_type) frappe.throw(__('Please set Root Type'));
|
||||
frm.set_query("account", function (doc) {
|
||||
if (!doc.company) frappe.throw(__("Please set Company"));
|
||||
if (!doc.root_type) frappe.throw(__("Please set Root Type"));
|
||||
return {
|
||||
filters: {
|
||||
root_type: doc.root_type,
|
||||
company: doc.company
|
||||
}
|
||||
company: doc.company,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query('account', 'merge_accounts', function(doc) {
|
||||
if (!doc.company) frappe.throw(__('Please set Company'));
|
||||
if (!doc.root_type) frappe.throw(__('Please set Root Type'));
|
||||
if (!doc.account) frappe.throw(__('Please set Account'));
|
||||
frm.set_query("account", "merge_accounts", function (doc) {
|
||||
if (!doc.company) frappe.throw(__("Please set Company"));
|
||||
if (!doc.root_type) frappe.throw(__("Please set Root Type"));
|
||||
if (!doc.account) frappe.throw(__("Please set Account"));
|
||||
let acc = [doc.account];
|
||||
frm.doc.merge_accounts.forEach((row) => {
|
||||
acc.push(row.account);
|
||||
@@ -43,86 +43,86 @@ frappe.ui.form.on('Ledger Merge', {
|
||||
is_group: doc.is_group,
|
||||
root_type: doc.root_type,
|
||||
name: ["not in", acc],
|
||||
company: doc.company
|
||||
}
|
||||
company: doc.company,
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
refresh: function (frm) {
|
||||
frm.page.hide_icon_group();
|
||||
frm.trigger('set_merge_status');
|
||||
frm.trigger('update_primary_action');
|
||||
frm.trigger("set_merge_status");
|
||||
frm.trigger("update_primary_action");
|
||||
},
|
||||
|
||||
after_save: function(frm) {
|
||||
after_save: function (frm) {
|
||||
setTimeout(() => {
|
||||
frm.trigger('update_primary_action');
|
||||
frm.trigger("update_primary_action");
|
||||
}, 500);
|
||||
},
|
||||
|
||||
update_primary_action: function(frm) {
|
||||
update_primary_action: function (frm) {
|
||||
if (frm.is_dirty()) {
|
||||
frm.enable_save();
|
||||
return;
|
||||
}
|
||||
frm.disable_save();
|
||||
if (frm.doc.status !== 'Success') {
|
||||
if (frm.doc.status !== "Success") {
|
||||
if (!frm.is_new()) {
|
||||
let label = frm.doc.status === 'Pending' ? __('Start Merge') : __('Retry');
|
||||
let label = frm.doc.status === "Pending" ? __("Start Merge") : __("Retry");
|
||||
frm.page.set_primary_action(label, () => frm.events.start_merge(frm));
|
||||
} else {
|
||||
frm.page.set_primary_action(__('Save'), () => frm.save());
|
||||
frm.page.set_primary_action(__("Save"), () => frm.save());
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
start_merge: function(frm) {
|
||||
start_merge: function (frm) {
|
||||
frm.call({
|
||||
method: 'form_start_merge',
|
||||
method: "form_start_merge",
|
||||
args: { docname: frm.doc.name },
|
||||
btn: frm.page.btn_primary
|
||||
}).then(r => {
|
||||
btn: frm.page.btn_primary,
|
||||
}).then((r) => {
|
||||
if (r.message === true) {
|
||||
frm.disable_save();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
set_merge_status: function(frm) {
|
||||
set_merge_status: function (frm) {
|
||||
if (frm.doc.status == "Pending") return;
|
||||
let successful_records = 0;
|
||||
frm.doc.merge_accounts.forEach((row) => {
|
||||
if (row.merged) successful_records += 1;
|
||||
});
|
||||
let message_args = [successful_records, frm.doc.merge_accounts.length];
|
||||
frm.dashboard.set_headline(__('Successfully merged {0} out of {1}.', message_args));
|
||||
frm.dashboard.set_headline(__("Successfully merged {0} out of {1}.", message_args));
|
||||
},
|
||||
|
||||
root_type: function(frm) {
|
||||
frm.set_value('account', '');
|
||||
frm.set_value('merge_accounts', []);
|
||||
root_type: function (frm) {
|
||||
frm.set_value("account", "");
|
||||
frm.set_value("merge_accounts", []);
|
||||
},
|
||||
|
||||
company: function(frm) {
|
||||
frm.set_value('account', '');
|
||||
frm.set_value('merge_accounts', []);
|
||||
}
|
||||
company: function (frm) {
|
||||
frm.set_value("account", "");
|
||||
frm.set_value("merge_accounts", []);
|
||||
},
|
||||
});
|
||||
|
||||
frappe.ui.form.on('Ledger Merge Accounts', {
|
||||
merge_accounts_add: function(frm) {
|
||||
frm.trigger('update_primary_action');
|
||||
frappe.ui.form.on("Ledger Merge Accounts", {
|
||||
merge_accounts_add: function (frm) {
|
||||
frm.trigger("update_primary_action");
|
||||
},
|
||||
|
||||
merge_accounts_remove: function(frm) {
|
||||
frm.trigger('update_primary_action');
|
||||
merge_accounts_remove: function (frm) {
|
||||
frm.trigger("update_primary_action");
|
||||
},
|
||||
|
||||
account: function(frm, cdt, cdn) {
|
||||
account: function (frm, cdt, cdn) {
|
||||
let row = frappe.get_doc(cdt, cdn);
|
||||
row.account_name = row.account;
|
||||
frm.refresh_field('merge_accounts');
|
||||
frm.trigger('update_primary_action');
|
||||
}
|
||||
frm.refresh_field("merge_accounts");
|
||||
frm.trigger("update_primary_action");
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Loyalty Point Entry', {
|
||||
refresh: function(frm) {
|
||||
|
||||
}
|
||||
frappe.ui.form.on("Loyalty Point Entry", {
|
||||
refresh: function (frm) {},
|
||||
});
|
||||
|
||||
@@ -3,30 +3,37 @@
|
||||
|
||||
frappe.provide("erpnext.accounts.dimensions");
|
||||
|
||||
frappe.ui.form.on('Loyalty Program', {
|
||||
setup: function(frm) {
|
||||
var help_content =
|
||||
`<table class="table table-bordered" style="background-color: var(--scrollbar-track-color);">
|
||||
frappe.ui.form.on("Loyalty Program", {
|
||||
setup: function (frm) {
|
||||
var help_content = `<table class="table table-bordered" style="background-color: var(--scrollbar-track-color);">
|
||||
<tr><td>
|
||||
<h4>
|
||||
<i class="fa fa-hand-right"></i>
|
||||
${__('Notes')}
|
||||
${__("Notes")}
|
||||
</h4>
|
||||
<ul>
|
||||
<li>
|
||||
${__("Loyalty Points will be calculated from the spent done (via the Sales Invoice), based on collection factor mentioned.")}
|
||||
${__(
|
||||
"Loyalty Points will be calculated from the spent done (via the Sales Invoice), based on collection factor mentioned."
|
||||
)}
|
||||
</li>
|
||||
<li>
|
||||
${__("There can be multiple tiered collection factor based on the total spent. But the conversion factor for redemption will always be same for all the tier.")}
|
||||
${__(
|
||||
"There can be multiple tiered collection factor based on the total spent. But the conversion factor for redemption will always be same for all the tier."
|
||||
)}
|
||||
</li>
|
||||
<li>
|
||||
${__("In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent")}
|
||||
${__(
|
||||
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent"
|
||||
)}
|
||||
</li>
|
||||
<li>
|
||||
${__("If unlimited expiry for the Loyalty Points, keep the Expiry Duration empty or 0.")}
|
||||
</li>
|
||||
<li>
|
||||
${__("If Auto Opt In is checked, then the customers will be automatically linked with the concerned Loyalty Program (on save)")}
|
||||
${__(
|
||||
"If Auto Opt In is checked, then the customers will be automatically linked with the concerned Loyalty Program (on save)"
|
||||
)}
|
||||
</li>
|
||||
<li>
|
||||
${__("One customer can be part of only single Loyalty Program.")}
|
||||
@@ -37,14 +44,14 @@ frappe.ui.form.on('Loyalty Program', {
|
||||
set_field_options("loyalty_program_help", help_content);
|
||||
},
|
||||
|
||||
onload: function(frm) {
|
||||
frm.set_query("expense_account", function(doc) {
|
||||
onload: function (frm) {
|
||||
frm.set_query("expense_account", function (doc) {
|
||||
return {
|
||||
filters: {
|
||||
"root_type": "Expense",
|
||||
'is_group': 0,
|
||||
'company': doc.company
|
||||
}
|
||||
root_type: "Expense",
|
||||
is_group: 0,
|
||||
company: doc.company,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
@@ -52,13 +59,15 @@ frappe.ui.form.on('Loyalty Program', {
|
||||
erpnext.accounts.dimensions.setup_dimension_filters(frm, frm.doctype);
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
refresh: function (frm) {
|
||||
if (frm.doc.loyalty_program_type === "Single Tier Program" && frm.doc.collection_rules.length > 1) {
|
||||
frappe.throw(__("Please select the Multiple Tier Program type for more than one collection rules."));
|
||||
frappe.throw(
|
||||
__("Please select the Multiple Tier Program type for more than one collection rules.")
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
company: function(frm) {
|
||||
company: function (frm) {
|
||||
erpnext.accounts.dimensions.update_dimension(frm, frm.doctype);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
frappe.ui.form.on('Mode of Payment', {
|
||||
setup: function(frm) {
|
||||
frm.set_query("default_account", "accounts", function(doc, cdt, cdn) {
|
||||
frappe.ui.form.on("Mode of Payment", {
|
||||
setup: function (frm) {
|
||||
frm.set_query("default_account", "accounts", function (doc, cdt, cdn) {
|
||||
let d = locals[cdt][cdn];
|
||||
return {
|
||||
filters: [
|
||||
['Account', 'account_type', 'in', 'Bank, Cash, Receivable'],
|
||||
['Account', 'is_group', '=', 0],
|
||||
['Account', 'company', '=', d.company]
|
||||
]
|
||||
["Account", "account_type", "in", "Bank, Cash, Receivable"],
|
||||
["Account", "is_group", "=", 0],
|
||||
["Account", "company", "=", d.company],
|
||||
],
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
frappe.ui.form.on('Monthly Distribution', {
|
||||
frappe.ui.form.on("Monthly Distribution", {
|
||||
onload(frm) {
|
||||
if(frm.doc.__islocal) {
|
||||
return frm.call('get_months').then(() => {
|
||||
frm.refresh_field('percentages');
|
||||
if (frm.doc.__islocal) {
|
||||
return frm.call("get_months").then(() => {
|
||||
frm.refresh_field("percentages");
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
refresh(frm) {
|
||||
frm.toggle_display('distribution_id', frm.doc.__islocal);
|
||||
}
|
||||
frm.toggle_display("distribution_id", frm.doc.__islocal);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,173 +1,77 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"autoname": "field:distribution_id",
|
||||
"beta": 0,
|
||||
"creation": "2013-01-10 16:34:05",
|
||||
"custom": 0,
|
||||
"description": "**Monthly Distribution** helps you distribute the Budget/Target across months if you have seasonality in your business.",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 0,
|
||||
"engine": "InnoDB",
|
||||
"actions": [],
|
||||
"autoname": "field:distribution_id",
|
||||
"creation": "2013-01-10 16:34:05",
|
||||
"description": "Helps you distribute the Budget/Target across months if you have seasonality in your business.",
|
||||
"doctype": "DocType",
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"distribution_id",
|
||||
"fiscal_year",
|
||||
"percentages"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Name of the Monthly Distribution",
|
||||
"fieldname": "distribution_id",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Distribution Name",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "distribution_id",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
"description": "Name of the Monthly Distribution",
|
||||
"fieldname": "distribution_id",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Distribution Name",
|
||||
"oldfieldname": "distribution_id",
|
||||
"oldfieldtype": "Data",
|
||||
"reqd": 1,
|
||||
"unique": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "fiscal_year",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Fiscal Year",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "fiscal_year",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "Fiscal Year",
|
||||
"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": 1,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "fiscal_year",
|
||||
"fieldtype": "Link",
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Fiscal Year",
|
||||
"oldfieldname": "fiscal_year",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "Fiscal Year",
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "percentages",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Monthly Distribution Percentages",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "budget_distribution_details",
|
||||
"oldfieldtype": "Table",
|
||||
"options": "Monthly Distribution Percentage",
|
||||
"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,
|
||||
"unique": 0
|
||||
"fieldname": "percentages",
|
||||
"fieldtype": "Table",
|
||||
"label": "Monthly Distribution Percentages",
|
||||
"oldfieldname": "budget_distribution_details",
|
||||
"oldfieldtype": "Table",
|
||||
"options": "Monthly Distribution Percentage"
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"icon": "fa fa-bar-chart",
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-11-21 14:54:35.998761",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Monthly Distribution",
|
||||
"name_case": "Title Case",
|
||||
"owner": "Administrator",
|
||||
],
|
||||
"icon": "fa fa-bar-chart",
|
||||
"idx": 1,
|
||||
"links": [],
|
||||
"modified": "2024-01-30 13:57:55.802744",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Monthly Distribution",
|
||||
"naming_rule": "By fieldname",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"is_custom": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
"email": 0,
|
||||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"is_custom": 0,
|
||||
"permlevel": 2,
|
||||
"print": 0,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 0,
|
||||
"submit": 0,
|
||||
"write": 0
|
||||
"permlevel": 2,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts Manager"
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_seen": 0
|
||||
],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
||||
@@ -1,48 +1,52 @@
|
||||
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Opening Invoice Creation Tool', {
|
||||
setup: function(frm) {
|
||||
frm.set_query('party_type', 'invoices', function(doc, cdt, cdn) {
|
||||
frappe.ui.form.on("Opening Invoice Creation Tool", {
|
||||
setup: function (frm) {
|
||||
frm.set_query("party_type", "invoices", function (doc, cdt, cdn) {
|
||||
return {
|
||||
filters: {
|
||||
'name': ['in', 'Customer, Supplier']
|
||||
}
|
||||
name: ["in", "Customer, Supplier"],
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
if (frm.doc.company) {
|
||||
frm.trigger('setup_company_filters');
|
||||
frm.trigger("setup_company_filters");
|
||||
}
|
||||
|
||||
frappe.realtime.on('opening_invoice_creation_progress', data => {
|
||||
frappe.realtime.on("opening_invoice_creation_progress", (data) => {
|
||||
if (!frm.doc.import_in_progress) {
|
||||
frm.dashboard.reset();
|
||||
frm.doc.import_in_progress = true;
|
||||
}
|
||||
if (data.count == data.total) {
|
||||
setTimeout(() => {
|
||||
frm.doc.import_in_progress = false;
|
||||
frm.clear_table("invoices");
|
||||
frm.refresh_fields();
|
||||
frm.page.clear_indicator();
|
||||
frm.dashboard.hide_progress();
|
||||
frappe.msgprint(__("Opening {0} Invoices created", [frm.doc.invoice_type]));
|
||||
}, 1500, data.title);
|
||||
setTimeout(
|
||||
() => {
|
||||
frm.doc.import_in_progress = false;
|
||||
frm.clear_table("invoices");
|
||||
frm.refresh_fields();
|
||||
frm.page.clear_indicator();
|
||||
frm.dashboard.hide_progress();
|
||||
frappe.msgprint(__("Opening {0} Invoices created", [frm.doc.invoice_type]));
|
||||
},
|
||||
1500,
|
||||
data.title
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
frm.dashboard.show_progress(data.title, (data.count / data.total) * 100, data.message);
|
||||
frm.page.set_indicator(__('In Progress'), 'orange');
|
||||
frm.page.set_indicator(__("In Progress"), "orange");
|
||||
});
|
||||
|
||||
erpnext.accounts.dimensions.setup_dimension_filters(frm, frm.doctype);
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
refresh: function (frm) {
|
||||
frm.disable_save();
|
||||
!frm.doc.import_in_progress && frm.trigger("make_dashboard");
|
||||
frm.page.set_primary_action(__('Create Invoices'), () => {
|
||||
frm.page.set_primary_action(__("Create Invoices"), () => {
|
||||
let btn_primary = frm.page.btn_primary.get(0);
|
||||
return frm.call({
|
||||
doc: frm.doc,
|
||||
@@ -58,100 +62,98 @@ frappe.ui.form.on('Opening Invoice Creation Tool', {
|
||||
}
|
||||
},
|
||||
|
||||
setup_company_filters: function(frm) {
|
||||
frm.set_query('cost_center', 'invoices', function(doc, cdt, cdn) {
|
||||
setup_company_filters: function (frm) {
|
||||
frm.set_query("cost_center", "invoices", function (doc, cdt, cdn) {
|
||||
return {
|
||||
filters: {
|
||||
'company': doc.company
|
||||
}
|
||||
company: doc.company,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query('cost_center', function(doc) {
|
||||
frm.set_query("cost_center", function (doc) {
|
||||
return {
|
||||
filters: {
|
||||
'company': doc.company
|
||||
}
|
||||
company: doc.company,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query('temporary_opening_account', 'invoices', function(doc, cdt, cdn) {
|
||||
frm.set_query("temporary_opening_account", "invoices", function (doc, cdt, cdn) {
|
||||
return {
|
||||
filters: {
|
||||
'company': doc.company
|
||||
}
|
||||
}
|
||||
company: doc.company,
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
company: function(frm) {
|
||||
company: function (frm) {
|
||||
if (frm.doc.company) {
|
||||
|
||||
frm.trigger('setup_company_filters');
|
||||
frm.trigger("setup_company_filters");
|
||||
|
||||
frappe.call({
|
||||
method: 'erpnext.accounts.doctype.opening_invoice_creation_tool.opening_invoice_creation_tool.get_temporary_opening_account',
|
||||
method: "erpnext.accounts.doctype.opening_invoice_creation_tool.opening_invoice_creation_tool.get_temporary_opening_account",
|
||||
args: {
|
||||
company: frm.doc.company
|
||||
company: frm.doc.company,
|
||||
},
|
||||
callback: (r) => {
|
||||
if (r.message) {
|
||||
frm.doc.__onload.temporary_opening_account = r.message;
|
||||
frm.trigger('update_invoice_table');
|
||||
frm.trigger("update_invoice_table");
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
}
|
||||
erpnext.accounts.dimensions.update_dimension(frm, frm.doctype);
|
||||
},
|
||||
|
||||
invoice_type: function(frm) {
|
||||
invoice_type: function (frm) {
|
||||
$.each(frm.doc.invoices, (idx, row) => {
|
||||
row.party_type = frm.doc.invoice_type == "Sales"? "Customer": "Supplier";
|
||||
row.party_type = frm.doc.invoice_type == "Sales" ? "Customer" : "Supplier";
|
||||
row.party = "";
|
||||
});
|
||||
frm.refresh_fields();
|
||||
},
|
||||
|
||||
make_dashboard: function(frm) {
|
||||
make_dashboard: function (frm) {
|
||||
let max_count = frm.doc.__onload.max_count;
|
||||
let opening_invoices_summary = frm.doc.__onload.opening_invoices_summary;
|
||||
if(!$.isEmptyObject(opening_invoices_summary)) {
|
||||
if (!$.isEmptyObject(opening_invoices_summary)) {
|
||||
let section = frm.dashboard.add_section(
|
||||
frappe.render_template('opening_invoice_creation_tool_dashboard', {
|
||||
frappe.render_template("opening_invoice_creation_tool_dashboard", {
|
||||
data: opening_invoices_summary,
|
||||
max_count: max_count
|
||||
max_count: max_count,
|
||||
}),
|
||||
__("Opening Invoices Summary")
|
||||
);
|
||||
|
||||
section.on('click', '.invoice-link', function() {
|
||||
let doctype = $(this).attr('data-type');
|
||||
let company = $(this).attr('data-company');
|
||||
frappe.set_route('List', doctype,
|
||||
{'is_opening': 'Yes', 'company': company, 'docstatus': 1});
|
||||
section.on("click", ".invoice-link", function () {
|
||||
let doctype = $(this).attr("data-type");
|
||||
let company = $(this).attr("data-company");
|
||||
frappe.set_route("List", doctype, { is_opening: "Yes", company: company, docstatus: 1 });
|
||||
});
|
||||
frm.dashboard.show();
|
||||
}
|
||||
},
|
||||
|
||||
update_invoice_table: function(frm) {
|
||||
update_invoice_table: function (frm) {
|
||||
$.each(frm.doc.invoices, (idx, row) => {
|
||||
if (!row.temporary_opening_account) {
|
||||
row.temporary_opening_account = frm.doc.__onload.temporary_opening_account;
|
||||
}
|
||||
|
||||
if(!row.cost_center) {
|
||||
if (!row.cost_center) {
|
||||
row.cost_center = frm.doc.cost_center;
|
||||
}
|
||||
|
||||
row.party_type = frm.doc.invoice_type == "Sales"? "Customer": "Supplier";
|
||||
row.party_type = frm.doc.invoice_type == "Sales" ? "Customer" : "Supplier";
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
frappe.ui.form.on('Opening Invoice Creation Tool Item', {
|
||||
frappe.ui.form.on("Opening Invoice Creation Tool Item", {
|
||||
invoices_add: (frm) => {
|
||||
frm.trigger('update_invoice_table');
|
||||
}
|
||||
frm.trigger("update_invoice_table");
|
||||
},
|
||||
});
|
||||
|
||||
@@ -270,7 +270,7 @@ def start_import(invoices):
|
||||
errors, "<a href='/app/List/Error Log' class='variant-click'>Error Log</a>"
|
||||
),
|
||||
indicator="red",
|
||||
title=_("Error Occured"),
|
||||
title=_("Error Occurred"),
|
||||
)
|
||||
return names
|
||||
|
||||
|
||||
@@ -1,33 +1,34 @@
|
||||
// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Party Link', {
|
||||
refresh: function(frm) {
|
||||
frm.set_query('primary_role', () => {
|
||||
frappe.ui.form.on("Party Link", {
|
||||
refresh: function (frm) {
|
||||
frm.set_query("primary_role", () => {
|
||||
return {
|
||||
filters: {
|
||||
name: ['in', ['Customer', 'Supplier']]
|
||||
}
|
||||
name: ["in", ["Customer", "Supplier"]],
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query('secondary_role', () => {
|
||||
let party_types = Object.keys(frappe.boot.party_account_types)
|
||||
.filter(p => p != frm.doc.primary_role);
|
||||
frm.set_query("secondary_role", () => {
|
||||
let party_types = Object.keys(frappe.boot.party_account_types).filter(
|
||||
(p) => p != frm.doc.primary_role
|
||||
);
|
||||
return {
|
||||
filters: {
|
||||
name: ['in', party_types]
|
||||
}
|
||||
name: ["in", party_types],
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
primary_role(frm) {
|
||||
frm.set_value('primary_party', '');
|
||||
frm.set_value('secondary_role', '');
|
||||
frm.set_value("primary_party", "");
|
||||
frm.set_value("secondary_role", "");
|
||||
},
|
||||
|
||||
secondary_role(frm) {
|
||||
frm.set_value('secondary_party', '');
|
||||
}
|
||||
frm.set_value("secondary_party", "");
|
||||
},
|
||||
});
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -87,12 +87,14 @@
|
||||
"status",
|
||||
"custom_remarks",
|
||||
"remarks",
|
||||
"base_in_words",
|
||||
"column_break_16",
|
||||
"letter_head",
|
||||
"print_heading",
|
||||
"bank",
|
||||
"bank_account_no",
|
||||
"payment_order",
|
||||
"in_words",
|
||||
"subscription_section",
|
||||
"auto_repeat",
|
||||
"amended_from",
|
||||
@@ -747,6 +749,20 @@
|
||||
"hidden": 1,
|
||||
"label": "Book Advance Payments in Separate Party Account",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "base_in_words",
|
||||
"fieldtype": "Small Text",
|
||||
"label": "In Words (Company Currency)",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "in_words",
|
||||
"fieldtype": "Small Text",
|
||||
"label": "In Words",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
|
||||
@@ -13,6 +13,7 @@ from pypika import Case
|
||||
from pypika.functions import Coalesce, Sum
|
||||
|
||||
import erpnext
|
||||
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_dimensions
|
||||
from erpnext.accounts.doctype.bank_account.bank_account import (
|
||||
get_bank_account_details,
|
||||
get_party_bank_account,
|
||||
@@ -29,7 +30,7 @@ from erpnext.accounts.general_ledger import (
|
||||
make_reverse_gl_entries,
|
||||
process_gl_map,
|
||||
)
|
||||
from erpnext.accounts.party import get_party_account
|
||||
from erpnext.accounts.party import get_party_account, set_contact_details
|
||||
from erpnext.accounts.utils import (
|
||||
cancel_exchange_gain_loss_journal,
|
||||
get_account_currency,
|
||||
@@ -177,6 +178,7 @@ class PaymentEntry(AccountsController):
|
||||
self.validate_paid_invoices()
|
||||
self.ensure_supplier_is_not_blocked()
|
||||
self.set_status()
|
||||
self.set_total_in_words()
|
||||
|
||||
def on_submit(self):
|
||||
if self.difference_amount:
|
||||
@@ -189,7 +191,7 @@ class PaymentEntry(AccountsController):
|
||||
|
||||
def set_liability_account(self):
|
||||
# Auto setting liability account should only be done during 'draft' status
|
||||
if self.docstatus > 0:
|
||||
if self.docstatus > 0 or self.payment_type == "Internal Transfer":
|
||||
return
|
||||
|
||||
if not frappe.db.get_value(
|
||||
@@ -442,6 +444,8 @@ class PaymentEntry(AccountsController):
|
||||
self.party_name = frappe.db.get_value(self.party_type, self.party, "name")
|
||||
|
||||
if self.party:
|
||||
if not self.contact_person:
|
||||
set_contact_details(self, party=frappe._dict({"name": self.party}), party_type=self.party_type)
|
||||
if not self.party_balance:
|
||||
self.party_balance = get_balance_on(
|
||||
party_type=self.party_type, party=self.party, date=self.posting_date, company=self.company
|
||||
@@ -469,7 +473,10 @@ class PaymentEntry(AccountsController):
|
||||
)
|
||||
|
||||
def set_missing_ref_details(
|
||||
self, force: bool = False, update_ref_details_only_for: list | None = None
|
||||
self,
|
||||
force: bool = False,
|
||||
update_ref_details_only_for: list | None = None,
|
||||
ref_exchange_rate: float | None = None,
|
||||
) -> None:
|
||||
for d in self.get("references"):
|
||||
if d.allocated_amount:
|
||||
@@ -482,6 +489,8 @@ class PaymentEntry(AccountsController):
|
||||
ref_details = get_reference_details(
|
||||
d.reference_doctype, d.reference_name, self.party_account_currency
|
||||
)
|
||||
if ref_exchange_rate:
|
||||
ref_details.update({"exchange_rate": ref_exchange_rate})
|
||||
|
||||
for field, value in ref_details.items():
|
||||
if d.exchange_gain_loss:
|
||||
@@ -602,9 +611,9 @@ class PaymentEntry(AccountsController):
|
||||
|
||||
def get_valid_reference_doctypes(self):
|
||||
if self.party_type == "Customer":
|
||||
return ("Sales Order", "Sales Invoice", "Journal Entry", "Dunning")
|
||||
return ("Sales Order", "Sales Invoice", "Journal Entry", "Dunning", "Payment Entry")
|
||||
elif self.party_type == "Supplier":
|
||||
return ("Purchase Order", "Purchase Invoice", "Journal Entry")
|
||||
return ("Purchase Order", "Purchase Invoice", "Journal Entry", "Payment Entry")
|
||||
elif self.party_type == "Shareholder":
|
||||
return ("Journal Entry",)
|
||||
elif self.party_type == "Employee":
|
||||
@@ -785,6 +794,21 @@ class PaymentEntry(AccountsController):
|
||||
|
||||
self.db_set("status", self.status, update_modified=True)
|
||||
|
||||
def set_total_in_words(self):
|
||||
from frappe.utils import money_in_words
|
||||
|
||||
if self.payment_type in ("Pay", "Internal Transfer"):
|
||||
base_amount = abs(self.base_paid_amount)
|
||||
amount = abs(self.paid_amount)
|
||||
currency = self.paid_from_account_currency
|
||||
elif self.payment_type == "Receive":
|
||||
base_amount = abs(self.base_received_amount)
|
||||
amount = abs(self.received_amount)
|
||||
currency = self.paid_to_account_currency
|
||||
|
||||
self.base_in_words = money_in_words(base_amount, self.company_currency)
|
||||
self.in_words = money_in_words(amount, currency)
|
||||
|
||||
def set_tax_withholding(self):
|
||||
if self.party_type != "Supplier":
|
||||
return
|
||||
@@ -925,7 +949,10 @@ class PaymentEntry(AccountsController):
|
||||
|
||||
def calculate_base_allocated_amount_for_reference(self, d) -> float:
|
||||
base_allocated_amount = 0
|
||||
if d.reference_doctype in frappe.get_hooks("advance_payment_doctypes"):
|
||||
advance_payment_doctypes = frappe.get_hooks(
|
||||
"advance_payment_receivable_doctypes"
|
||||
) + frappe.get_hooks("advance_payment_payable_doctypes")
|
||||
if d.reference_doctype in advance_payment_doctypes:
|
||||
# When referencing Sales/Purchase Order, use the source/target exchange rate depending on payment type.
|
||||
# This is so there are no Exchange Gain/Loss generated for such doctypes
|
||||
|
||||
@@ -1012,19 +1039,19 @@ class PaymentEntry(AccountsController):
|
||||
)
|
||||
|
||||
base_party_amount = flt(self.base_total_allocated_amount) + flt(base_unallocated_amount)
|
||||
|
||||
if self.payment_type == "Receive":
|
||||
self.difference_amount = base_party_amount - self.base_received_amount
|
||||
elif self.payment_type == "Pay":
|
||||
self.difference_amount = self.base_paid_amount - base_party_amount
|
||||
else:
|
||||
self.difference_amount = self.base_paid_amount - flt(self.base_received_amount)
|
||||
|
||||
total_deductions = sum(flt(d.amount) for d in self.get("deductions"))
|
||||
included_taxes = self.get_included_taxes()
|
||||
|
||||
if self.payment_type == "Receive":
|
||||
self.difference_amount = base_party_amount - self.base_received_amount + included_taxes
|
||||
elif self.payment_type == "Pay":
|
||||
self.difference_amount = self.base_paid_amount - base_party_amount - included_taxes
|
||||
else:
|
||||
self.difference_amount = self.base_paid_amount - flt(self.base_received_amount) - included_taxes
|
||||
|
||||
total_deductions = sum(flt(d.amount) for d in self.get("deductions"))
|
||||
|
||||
self.difference_amount = flt(
|
||||
self.difference_amount - total_deductions - included_taxes, self.precision("difference_amount")
|
||||
self.difference_amount - total_deductions, self.precision("difference_amount")
|
||||
)
|
||||
|
||||
def get_included_taxes(self):
|
||||
@@ -1144,9 +1171,7 @@ class PaymentEntry(AccountsController):
|
||||
"account": self.party_account,
|
||||
"party_type": self.party_type,
|
||||
"party": self.party,
|
||||
"against_type": "Account",
|
||||
"against": against_account,
|
||||
"against_link": against_account,
|
||||
"account_currency": self.party_account_currency,
|
||||
"cost_center": self.cost_center,
|
||||
},
|
||||
@@ -1248,7 +1273,14 @@ class PaymentEntry(AccountsController):
|
||||
references = [x for x in self.get("references") if x.name == entry.name]
|
||||
|
||||
for ref in references:
|
||||
if ref.reference_doctype in ("Sales Invoice", "Purchase Invoice", "Journal Entry"):
|
||||
if ref.reference_doctype in (
|
||||
"Sales Invoice",
|
||||
"Purchase Invoice",
|
||||
"Journal Entry",
|
||||
"Sales Order",
|
||||
"Purchase Order",
|
||||
"Payment Entry",
|
||||
):
|
||||
self.add_advance_gl_for_reference(gl_entries, ref)
|
||||
|
||||
def add_advance_gl_for_reference(self, gl_entries, invoice):
|
||||
@@ -1262,14 +1294,17 @@ class PaymentEntry(AccountsController):
|
||||
"voucher_detail_no": invoice.name,
|
||||
}
|
||||
|
||||
posting_date = frappe.db.get_value(
|
||||
invoice.reference_doctype, invoice.reference_name, "posting_date"
|
||||
)
|
||||
date_field = "posting_date"
|
||||
if invoice.reference_doctype in ["Sales Order", "Purchase Order"]:
|
||||
date_field = "transaction_date"
|
||||
posting_date = frappe.db.get_value(invoice.reference_doctype, invoice.reference_name, date_field)
|
||||
|
||||
if getdate(posting_date) < getdate(self.posting_date):
|
||||
posting_date = self.posting_date
|
||||
|
||||
dr_or_cr = "credit" if invoice.reference_doctype == "Sales Invoice" else "debit"
|
||||
dr_or_cr = (
|
||||
"credit" if invoice.reference_doctype in ["Sales Invoice", "Payment Entry"] else "debit"
|
||||
)
|
||||
args_dict["account"] = invoice.account
|
||||
args_dict[dr_or_cr] = invoice.allocated_amount
|
||||
args_dict[dr_or_cr + "_in_account_currency"] = invoice.allocated_amount
|
||||
@@ -1311,9 +1346,7 @@ class PaymentEntry(AccountsController):
|
||||
{
|
||||
"account": self.paid_from,
|
||||
"account_currency": self.paid_from_account_currency,
|
||||
"against_type": self.party_type if self.payment_type == "Pay" else "Account",
|
||||
"against": self.party if self.payment_type == "Pay" else self.paid_to,
|
||||
"against_link": self.party if self.payment_type == "Pay" else self.paid_to,
|
||||
"credit_in_account_currency": self.paid_amount,
|
||||
"credit": self.base_paid_amount,
|
||||
"cost_center": self.cost_center,
|
||||
@@ -1328,9 +1361,7 @@ class PaymentEntry(AccountsController):
|
||||
{
|
||||
"account": self.paid_to,
|
||||
"account_currency": self.paid_to_account_currency,
|
||||
"against_type": self.party_type if self.payment_type == "Receive" else "Account",
|
||||
"against": self.party if self.payment_type == "Receive" else self.paid_from,
|
||||
"against_link": self.party if self.payment_type == "Receive" else self.paid_from,
|
||||
"debit_in_account_currency": self.received_amount,
|
||||
"debit": self.base_received_amount,
|
||||
"cost_center": self.cost_center,
|
||||
@@ -1354,7 +1385,6 @@ class PaymentEntry(AccountsController):
|
||||
rev_dr_or_cr = "credit" if dr_or_cr == "debit" else "debit"
|
||||
against = self.party or self.paid_to
|
||||
|
||||
against_type = self.party_type or "Account"
|
||||
payment_account = self.get_party_account_for_taxes()
|
||||
tax_amount = d.tax_amount
|
||||
base_tax_amount = d.base_tax_amount
|
||||
@@ -1363,9 +1393,7 @@ class PaymentEntry(AccountsController):
|
||||
self.get_gl_dict(
|
||||
{
|
||||
"account": d.account_head,
|
||||
"against_type": against_type,
|
||||
"against": against,
|
||||
"against_link": against,
|
||||
dr_or_cr: tax_amount,
|
||||
dr_or_cr + "_in_account_currency": base_tax_amount
|
||||
if account_currency == self.company_currency
|
||||
@@ -1390,9 +1418,7 @@ class PaymentEntry(AccountsController):
|
||||
self.get_gl_dict(
|
||||
{
|
||||
"account": payment_account,
|
||||
"against_type": against_type,
|
||||
"against": against,
|
||||
"against_link": against,
|
||||
rev_dr_or_cr: tax_amount,
|
||||
rev_dr_or_cr + "_in_account_currency": base_tax_amount
|
||||
if account_currency == self.company_currency
|
||||
@@ -1417,9 +1443,7 @@ class PaymentEntry(AccountsController):
|
||||
{
|
||||
"account": d.account,
|
||||
"account_currency": account_currency,
|
||||
"against_type": self.party_type or "Account",
|
||||
"against": self.party or self.paid_from,
|
||||
"against_link": self.party or self.paid_from,
|
||||
"debit_in_account_currency": d.amount,
|
||||
"debit": d.amount,
|
||||
"cost_center": d.cost_center,
|
||||
@@ -1436,8 +1460,11 @@ class PaymentEntry(AccountsController):
|
||||
|
||||
def update_advance_paid(self):
|
||||
if self.payment_type in ("Receive", "Pay") and self.party:
|
||||
advance_payment_doctypes = frappe.get_hooks(
|
||||
"advance_payment_receivable_doctypes"
|
||||
) + frappe.get_hooks("advance_payment_payable_doctypes")
|
||||
for d in self.get("references"):
|
||||
if d.allocated_amount and d.reference_doctype in frappe.get_hooks("advance_payment_doctypes"):
|
||||
if d.allocated_amount and d.reference_doctype in advance_payment_doctypes:
|
||||
frappe.get_doc(
|
||||
d.reference_doctype, d.reference_name, for_update=True
|
||||
).set_total_advance_paid()
|
||||
@@ -1684,6 +1711,13 @@ def get_outstanding_reference_documents(args, validate=False):
|
||||
condition += " and cost_center='%s'" % args.get("cost_center")
|
||||
accounting_dimensions_filter.append(ple.cost_center == args.get("cost_center"))
|
||||
|
||||
# dynamic dimension filters
|
||||
active_dimensions = get_dimensions()[0]
|
||||
for dim in active_dimensions:
|
||||
if args.get(dim.fieldname):
|
||||
condition += " and {0}='{1}'".format(dim.fieldname, args.get(dim.fieldname))
|
||||
accounting_dimensions_filter.append(ple[dim.fieldname] == args.get(dim.fieldname))
|
||||
|
||||
date_fields_dict = {
|
||||
"posting_date": ["from_posting_date", "to_posting_date"],
|
||||
"due_date": ["from_due_date", "to_due_date"],
|
||||
@@ -1720,7 +1754,7 @@ def get_outstanding_reference_documents(args, validate=False):
|
||||
outstanding_invoices = get_outstanding_invoices(
|
||||
args.get("party_type"),
|
||||
args.get("party"),
|
||||
party_account,
|
||||
[party_account],
|
||||
common_filter=common_filter,
|
||||
posting_date=posting_and_due_date,
|
||||
min_outstanding=args.get("outstanding_amt_greater_than"),
|
||||
@@ -1917,6 +1951,12 @@ def get_orders_to_be_billed(
|
||||
if doc and hasattr(doc, "cost_center") and doc.cost_center:
|
||||
condition = " and cost_center='%s'" % cost_center
|
||||
|
||||
# dynamic dimension filters
|
||||
active_dimensions = get_dimensions()[0]
|
||||
for dim in active_dimensions:
|
||||
if filters.get(dim.fieldname):
|
||||
condition += " and {0}='{1}'".format(dim.fieldname, filters.get(dim.fieldname))
|
||||
|
||||
if party_account_currency == company_currency:
|
||||
grand_total_field = "base_grand_total"
|
||||
rounded_total_field = "base_rounded_total"
|
||||
@@ -2169,6 +2209,11 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre
|
||||
else:
|
||||
outstanding_amount = flt(total_amount) - flt(ref_doc.get("advance_paid"))
|
||||
|
||||
if reference_doctype in ["Sales Order", "Purchase Order"]:
|
||||
party_type = "Customer" if reference_doctype == "Sales Order" else "Supplier"
|
||||
party_field = "customer" if reference_doctype == "Sales Order" else "supplier"
|
||||
party = ref_doc.get(party_field)
|
||||
account = get_party_account(party_type, party, ref_doc.company)
|
||||
else:
|
||||
# Get the exchange rate based on the posting date of the ref doc.
|
||||
exchange_rate = get_exchange_rate(party_account_currency, company_currency, ref_doc.posting_date)
|
||||
@@ -2197,6 +2242,7 @@ def get_payment_entry(
|
||||
party_type=None,
|
||||
payment_type=None,
|
||||
reference_date=None,
|
||||
ignore_permissions=False,
|
||||
):
|
||||
doc = frappe.get_doc(dt, dn)
|
||||
over_billing_allowance = frappe.db.get_single_value("Accounts Settings", "over_billing_allowance")
|
||||
@@ -2219,14 +2265,14 @@ def get_payment_entry(
|
||||
)
|
||||
|
||||
# bank or cash
|
||||
bank = get_bank_cash_account(doc, bank_account)
|
||||
bank = get_bank_cash_account(doc, bank_account, ignore_permissions=ignore_permissions)
|
||||
|
||||
# if default bank or cash account is not set in company master and party has default company bank account, fetch it
|
||||
if party_type in ["Customer", "Supplier"] and not bank:
|
||||
party_bank_account = get_party_bank_account(party_type, doc.get(scrub(party_type)))
|
||||
if party_bank_account:
|
||||
account = frappe.db.get_value("Bank Account", party_bank_account, "account")
|
||||
bank = get_bank_cash_account(doc, account)
|
||||
bank = get_bank_cash_account(doc, account, ignore_permissions=ignore_permissions)
|
||||
|
||||
paid_amount, received_amount = set_paid_amount_and_received_amount(
|
||||
dt, party_account_currency, bank, outstanding_amount, payment_type, bank_amount, doc
|
||||
@@ -2366,9 +2412,13 @@ def update_accounting_dimensions(pe, doc):
|
||||
pe.set(dimension, doc.get(dimension))
|
||||
|
||||
|
||||
def get_bank_cash_account(doc, bank_account):
|
||||
def get_bank_cash_account(doc, bank_account, ignore_permissions=False):
|
||||
bank = get_default_bank_cash_account(
|
||||
doc.company, "Bank", mode_of_payment=doc.get("mode_of_payment"), account=bank_account
|
||||
doc.company,
|
||||
"Bank",
|
||||
mode_of_payment=doc.get("mode_of_payment"),
|
||||
account=bank_account,
|
||||
ignore_permissions=ignore_permissions,
|
||||
)
|
||||
|
||||
if not bank:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user