Compare commits
589 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a5007db902 | ||
|
|
0d58501229 | ||
|
|
7c654cd1bb | ||
|
|
54fc260a42 | ||
|
|
7a39d51366 | ||
|
|
79c94426f7 | ||
|
|
c3ced9a0b5 | ||
|
|
c825575940 | ||
|
|
afd3209017 | ||
|
|
c541b87bb9 | ||
|
|
b42f3e34ef | ||
|
|
6a7edd32aa | ||
|
|
fc307970aa | ||
|
|
b9e7cb02f4 | ||
|
|
a20a419cb8 | ||
|
|
d805bd7daf | ||
|
|
ac53f2dbb1 | ||
|
|
20a7d820ab | ||
|
|
d48c2394e8 | ||
|
|
58101e9e6c | ||
|
|
666131d2fe | ||
|
|
118f043335 | ||
|
|
b4a51ec80b | ||
|
|
6197860643 | ||
|
|
95fbfa4928 | ||
|
|
b7f0a4961e | ||
|
|
9c044eefff | ||
|
|
5951692db0 | ||
|
|
bd4814fbb7 | ||
|
|
7d23e4286e | ||
|
|
15ea751f3c | ||
|
|
c40148e0da | ||
|
|
a9dda232b2 | ||
|
|
1f25c45ad7 | ||
|
|
12ffd914ee | ||
|
|
b1d8979a59 | ||
|
|
ec2d0030b7 | ||
|
|
55d0506155 | ||
|
|
5e9b52c273 | ||
|
|
00b4663e12 | ||
|
|
e54a4004ec | ||
|
|
d0b086ca54 | ||
|
|
8d1191ac8f | ||
|
|
a938b81e1c | ||
|
|
7cd0ba70d9 | ||
|
|
66340f9894 | ||
|
|
41f7f7442b | ||
|
|
126fb31f9a | ||
|
|
a8a91cca16 | ||
|
|
381385d19a | ||
|
|
aba8fdd18d | ||
|
|
bacc679df5 | ||
|
|
b0388d971a | ||
|
|
61c9ea938d | ||
|
|
6956eee790 | ||
|
|
2e65aadb1e | ||
|
|
653cffec1e | ||
|
|
cc8f1afa56 | ||
|
|
2f702dcb32 | ||
|
|
f857d81f35 | ||
|
|
6d64fe378d | ||
|
|
b0ab93f779 | ||
|
|
df1c1a573f | ||
|
|
a1f2aec918 | ||
|
|
d8930a776d | ||
|
|
8a8ef85174 | ||
|
|
edba048c14 | ||
|
|
b705798ccb | ||
|
|
5e0b0b4b97 | ||
|
|
a4efbf0db7 | ||
|
|
e930f0f74e | ||
|
|
99543f72d8 | ||
|
|
1a9646739a | ||
|
|
bd65cb8817 | ||
|
|
98b287565a | ||
|
|
c6dbe70256 | ||
|
|
556536615e | ||
|
|
8bd96f1c08 | ||
|
|
5b7e9a1c94 | ||
|
|
c306b21415 | ||
|
|
c39cef363c | ||
|
|
baefec4498 | ||
|
|
02a56b4e1a | ||
|
|
9a6df0341f | ||
|
|
5a90e3b2e9 | ||
|
|
7dab3c1f85 | ||
|
|
f9a974385a | ||
|
|
20a653e829 | ||
|
|
a2c668cb77 | ||
|
|
d0b0a80be3 | ||
|
|
532b9e8bfb | ||
|
|
32e48bb568 | ||
|
|
21e09a2bd8 | ||
|
|
1aa6e98136 | ||
|
|
023c036afa | ||
|
|
8372c44262 | ||
|
|
6d69ca6bac | ||
|
|
283b55f88c | ||
|
|
4757d0634a | ||
|
|
dc8ce7f7e9 | ||
|
|
d02375e89d | ||
|
|
a90a0528aa | ||
|
|
350f9592d3 | ||
|
|
43e50de6ef | ||
|
|
a530f410e3 | ||
|
|
bdfb070ed6 | ||
|
|
caa9fc033f | ||
|
|
15bf4e5599 | ||
|
|
6d490e530a | ||
|
|
9b363fe5f1 | ||
|
|
3c5df9f64c | ||
|
|
fd53991dfa | ||
|
|
c794ca53fb | ||
|
|
fa0adafa82 | ||
|
|
99f4b43641 | ||
|
|
fdeab29e94 | ||
|
|
31755b485f | ||
|
|
3f3696d1eb | ||
|
|
e1a478779c | ||
|
|
6c6f3789d0 | ||
|
|
044c43a5cb | ||
|
|
9ce9c052e4 | ||
|
|
83e68bb837 | ||
|
|
415df04834 | ||
|
|
6d2d6862d6 | ||
|
|
13a65d52dd | ||
|
|
6485d4a749 | ||
|
|
2e63c80523 | ||
|
|
23bd21778e | ||
|
|
a3f490890d | ||
|
|
8e3ea32d6d | ||
|
|
c4a1a943ef | ||
|
|
abc0b64b68 | ||
|
|
00818bfa90 | ||
|
|
b9bfe6117e | ||
|
|
7a9f46d9d1 | ||
|
|
a10b52c6e6 | ||
|
|
5033e7b431 | ||
|
|
e6791ee78e | ||
|
|
b84ba868e6 | ||
|
|
1c501b6aac | ||
|
|
9a2a6d8fcb | ||
|
|
0b59d1c78b | ||
|
|
0fbf10797c | ||
|
|
58344cbb81 | ||
|
|
c6e2c8f79e | ||
|
|
b64b461d53 | ||
|
|
0b93bdcf40 | ||
|
|
e3910d02a5 | ||
|
|
0af146cea6 | ||
|
|
683f756d0f | ||
|
|
d905204e49 | ||
|
|
d8bc40d7f0 | ||
|
|
54059b77a0 | ||
|
|
f9f0e2591f | ||
|
|
5810bf70c7 | ||
|
|
97d8db775e | ||
|
|
fbe08ec7d0 | ||
|
|
0045c305ac | ||
|
|
5dd0fb6e2a | ||
|
|
e99fff8d08 | ||
|
|
b61fed9106 | ||
|
|
398c83afa5 | ||
|
|
c346484ca4 | ||
|
|
70b7f7f036 | ||
|
|
31c51ef914 | ||
|
|
be464696cc | ||
|
|
191b2970e9 | ||
|
|
c50f033722 | ||
|
|
e1e1414894 | ||
|
|
d1441245fb | ||
|
|
87da662703 | ||
|
|
99ba924303 | ||
|
|
066ff9599a | ||
|
|
33ebaf479d | ||
|
|
3a573d1a6d | ||
|
|
7f66983309 | ||
|
|
2c867fdd73 | ||
|
|
95dfc2730b | ||
|
|
558646c6b8 | ||
|
|
ea0d98891f | ||
|
|
1b4c5ad1e1 | ||
|
|
2678135f5e | ||
|
|
25ef4ff373 | ||
|
|
c85a37fe00 | ||
|
|
3c3d69f905 | ||
|
|
aed8da40ae | ||
|
|
3bc43682f1 | ||
|
|
725816e616 | ||
|
|
7c0eadb451 | ||
|
|
d4357e80d7 | ||
|
|
c0f88e4caf | ||
|
|
73286dd9f5 | ||
|
|
1f259ba73d | ||
|
|
7b2b0cd73c | ||
|
|
2c749db2a9 | ||
|
|
17c633d00f | ||
|
|
4ee5b75687 | ||
|
|
a4fad72a65 | ||
|
|
e65ac00f36 | ||
|
|
75bd0f7cfe | ||
|
|
4d20f3029b | ||
|
|
c35b35abca | ||
|
|
17dc249841 | ||
|
|
12af47918d | ||
|
|
84ca0197e4 | ||
|
|
3395e7a2e4 | ||
|
|
25956d6282 | ||
|
|
ba2133cba2 | ||
|
|
28e3d63280 | ||
|
|
414660313a | ||
|
|
c52a601e87 | ||
|
|
7a869b0dca | ||
|
|
6f64a78ecf | ||
|
|
608bbc7850 | ||
|
|
639826e888 | ||
|
|
16b2c51988 | ||
|
|
76e9ba1e76 | ||
|
|
9dad86c189 | ||
|
|
5302b46955 | ||
|
|
afd14f6f0e | ||
|
|
05584d6d8b | ||
|
|
aa015902d5 | ||
|
|
2873f2e7de | ||
|
|
64fd970a8a | ||
|
|
b4e9c1da64 | ||
|
|
1d093a4039 | ||
|
|
fe9717cb9c | ||
|
|
d665a07621 | ||
|
|
2a1ba886f1 | ||
|
|
55f1ea05da | ||
|
|
2e7f9d2b8f | ||
|
|
3a519f269d | ||
|
|
4c0d0793a3 | ||
|
|
d3b8a74508 | ||
|
|
77760db89c | ||
|
|
1d23ebb51d | ||
|
|
ba5b0e8458 | ||
|
|
14a908bdec | ||
|
|
9f436a7c71 | ||
|
|
746fd90625 | ||
|
|
f861856ed9 | ||
|
|
f94f153078 | ||
|
|
c9bacedbfe | ||
|
|
c0cee82727 | ||
|
|
4c53931363 | ||
|
|
53f7e6281c | ||
|
|
9f235b891f | ||
|
|
c4d4c7feb0 | ||
|
|
ee6862b277 | ||
|
|
53f77ad5e8 | ||
|
|
fb73151da6 | ||
|
|
6e322d0a02 | ||
|
|
73e73795f1 | ||
|
|
80d2a55342 | ||
|
|
9cbf6b1b22 | ||
|
|
41dd2c458b | ||
|
|
71ebad5668 | ||
|
|
b4c0e94e99 | ||
|
|
73f1dc4edf | ||
|
|
174299124f | ||
|
|
c27748b2b3 | ||
|
|
626ba1bb81 | ||
|
|
591f047974 | ||
|
|
38e4c6f2af | ||
|
|
58e9590850 | ||
|
|
03afb45e34 | ||
|
|
d91382dbf3 | ||
|
|
e07958bbda | ||
|
|
b445be3552 | ||
|
|
c865f229fb | ||
|
|
ec5deb6e48 | ||
|
|
486bf2e113 | ||
|
|
f49b085625 | ||
|
|
adcaf75bb0 | ||
|
|
4f4fc45ae6 | ||
|
|
079d0b7108 | ||
|
|
86125b2b9f | ||
|
|
22d0d586ab | ||
|
|
eb62aed8c7 | ||
|
|
60f1739ca5 | ||
|
|
5f349a67c9 | ||
|
|
fd294eb981 | ||
|
|
d256055a8c | ||
|
|
cefa106a06 | ||
|
|
67ecfcf52c | ||
|
|
b7e46c4ed9 | ||
|
|
bc5ecfff06 | ||
|
|
8fa4845d00 | ||
|
|
d4882653c3 | ||
|
|
9a4d165ba2 | ||
|
|
a7099eaa8d | ||
|
|
4b72d05793 | ||
|
|
a30f3ea1f9 | ||
|
|
3b6a8af0da | ||
|
|
4fa69780a8 | ||
|
|
2dc619ae1f | ||
|
|
fc9031924e | ||
|
|
e14124198d | ||
|
|
51e980dd2c | ||
|
|
95781919fb | ||
|
|
c03cba9d17 | ||
|
|
72cd206286 | ||
|
|
9801745090 | ||
|
|
7866c6e6db | ||
|
|
5812fdb574 | ||
|
|
4c502bcd26 | ||
|
|
714948c867 | ||
|
|
8f3b360f83 | ||
|
|
314086d6c0 | ||
|
|
bcd655a985 | ||
|
|
b0dbdc1439 | ||
|
|
37b0bf257d | ||
|
|
c5a25f44e1 | ||
|
|
8dafa376ab | ||
|
|
74eb8e34da | ||
|
|
5c66fb7631 | ||
|
|
be3b3b2107 | ||
|
|
9ab09fd1d6 | ||
|
|
8a7bdd5a92 | ||
|
|
1d753c92b1 | ||
|
|
54ecc8ebba | ||
|
|
f4edaef481 | ||
|
|
ebbd163903 | ||
|
|
8954b24b22 | ||
|
|
ae92fc7f35 | ||
|
|
0bc3ca02f3 | ||
|
|
d10ba853e6 | ||
|
|
5bcf8315de | ||
|
|
789a798e36 | ||
|
|
ee1169dac7 | ||
|
|
fbef1fdf3a | ||
|
|
4358e1cd46 | ||
|
|
7a287a9153 | ||
|
|
5a49ded5d9 | ||
|
|
71f23acc2b | ||
|
|
1a1f790150 | ||
|
|
3c54e9779b | ||
|
|
db48b7d764 | ||
|
|
83c0899c83 | ||
|
|
e5047ec90a | ||
|
|
d9ab725be4 | ||
|
|
7afaeb0820 | ||
|
|
da2d8b958d | ||
|
|
ba48f82e03 | ||
|
|
8e7e128e81 | ||
|
|
0353569e8b | ||
|
|
665e2f5418 | ||
|
|
dace2b6796 | ||
|
|
712b02593a | ||
|
|
d2a60fd727 | ||
|
|
f924e08b93 | ||
|
|
5c623dae4d | ||
|
|
e2c3d40b57 | ||
|
|
673887455f | ||
|
|
63199e486b | ||
|
|
bf7294cf5c | ||
|
|
8aa06a809a | ||
|
|
72d2d682ae | ||
|
|
21f6ea6f7e | ||
|
|
185f488c51 | ||
|
|
f3006972d5 | ||
|
|
dccc6bc11d | ||
|
|
15d2c89939 | ||
|
|
ca4c8a2a46 | ||
|
|
c320fe541d | ||
|
|
f40a87511e | ||
|
|
4945b94950 | ||
|
|
cb96b61449 | ||
|
|
248c867a2c | ||
|
|
da98ab6f3c | ||
|
|
cd0989e051 | ||
|
|
b20baf894f | ||
|
|
d3cf4f1264 | ||
|
|
2dbe2b63b2 | ||
|
|
edba8f5582 | ||
|
|
89b8d11f9c | ||
|
|
19a33994da | ||
|
|
89349d3ae3 | ||
|
|
f6a31a568a | ||
|
|
4bcbcd29f7 | ||
|
|
740a11263f | ||
|
|
142859f36e | ||
|
|
6534ad082d | ||
|
|
6361ae3495 | ||
|
|
7f75dbf061 | ||
|
|
199d8a44fc | ||
|
|
72b1128467 | ||
|
|
d6cb55ad1a | ||
|
|
c76e34d7de | ||
|
|
33b10faf94 | ||
|
|
d970b001a4 | ||
|
|
d767fb6134 | ||
|
|
6239923340 | ||
|
|
e5a31462fe | ||
|
|
6f39300d43 | ||
|
|
0ca587e018 | ||
|
|
8ffe12ebe4 | ||
|
|
8579af371c | ||
|
|
b5ff9421e1 | ||
|
|
ba8ec17f0b | ||
|
|
44bd3b2601 | ||
|
|
9d40eca428 | ||
|
|
1b6c00e2c7 | ||
|
|
52efde31e7 | ||
|
|
f723032fd7 | ||
|
|
3297c43bdf | ||
|
|
aea250bc5a | ||
|
|
d37d4dfdec | ||
|
|
0ea68b33ed | ||
|
|
7f96c20f5b | ||
|
|
e75d947867 | ||
|
|
bba0a5d38f | ||
|
|
953e97536a | ||
|
|
e74d7ca33e | ||
|
|
8f2b8afcb7 | ||
|
|
b3f12c3109 | ||
|
|
f66e6aacd4 | ||
|
|
1d621be1f7 | ||
|
|
ab57e52cbd | ||
|
|
e63da9813c | ||
|
|
c020e42d20 | ||
|
|
b126ba0132 | ||
|
|
20ae349ebd | ||
|
|
c6e4b5978d | ||
|
|
361eca4cae | ||
|
|
9fc03b6c10 | ||
|
|
e2d46d0474 | ||
|
|
dd2f2f5321 | ||
|
|
6e4f5a214a | ||
|
|
b07b0a9e54 | ||
|
|
307978fea9 | ||
|
|
06ad308ca1 | ||
|
|
52dfc32eca | ||
|
|
72fbf902d7 | ||
|
|
8ffd483e24 | ||
|
|
3d76686b82 | ||
|
|
156ce607e2 | ||
|
|
65b6762247 | ||
|
|
abdfb4d3db | ||
|
|
3bcb13b1b8 | ||
|
|
b6ec680c46 | ||
|
|
53a0de7607 | ||
|
|
0a1d037f01 | ||
|
|
ce3e15d30c | ||
|
|
5b649521d1 | ||
|
|
798e75832c | ||
|
|
aa95a1b1ef | ||
|
|
c0c94aef44 | ||
|
|
e4dfeb651f | ||
|
|
f7e6eb4fd7 | ||
|
|
97c858a5e3 | ||
|
|
974892bf87 | ||
|
|
361df8993f | ||
|
|
b8b8de7a49 | ||
|
|
be6cfddc4d | ||
|
|
bf8c8df9ce | ||
|
|
40759c284c | ||
|
|
a48d754158 | ||
|
|
26bcd89d10 | ||
|
|
20fd360a63 | ||
|
|
df8efce36f | ||
|
|
9acd6a2629 | ||
|
|
779ae439cd | ||
|
|
a8ef4c9220 | ||
|
|
ce6b61b41e | ||
|
|
0332f83bc2 | ||
|
|
926ae17e5a | ||
|
|
8adb5f3e32 | ||
|
|
5532a14938 | ||
|
|
a69682c4e0 | ||
|
|
d20120e649 | ||
|
|
e9b14e497b | ||
|
|
ba0bf9e13d | ||
|
|
cba5a684cb | ||
|
|
c439b87ccc | ||
|
|
340709b2da | ||
|
|
a8de61e24b | ||
|
|
28386f551b | ||
|
|
9ff52cd57e | ||
|
|
e3401182c8 | ||
|
|
7523429ded | ||
|
|
0401e418be | ||
|
|
ff6fd7fa9d | ||
|
|
7620393b9b | ||
|
|
6489e97726 | ||
|
|
8c1a4c0c48 | ||
|
|
77ca80217c | ||
|
|
8247ad4028 | ||
|
|
1194c6ef4b | ||
|
|
70fed64cd5 | ||
|
|
87c2d1d634 | ||
|
|
d4aa27cbb8 | ||
|
|
59f4fa9a8c | ||
|
|
3b0c0a76b4 | ||
|
|
262ac09305 | ||
|
|
2a04d98c16 | ||
|
|
fec9f75707 | ||
|
|
12106725fb | ||
|
|
c5f919eb68 | ||
|
|
5fe0086d9a | ||
|
|
0b031cdd6c | ||
|
|
c19afa140d | ||
|
|
0bd145a608 | ||
|
|
c663f5c2bd | ||
|
|
adde1cff48 | ||
|
|
bb9427d1ef | ||
|
|
052babc6b6 | ||
|
|
24fa06bc53 | ||
|
|
7c867ae9ad | ||
|
|
8f7317175d | ||
|
|
957e7a37be | ||
|
|
def71d4d5d | ||
|
|
ef511b160e | ||
|
|
09f9c96c53 | ||
|
|
1a2d121073 | ||
|
|
810bd35609 | ||
|
|
949d7dbaba | ||
|
|
72e6aa160c | ||
|
|
0870b185de | ||
|
|
69f2cc8d24 | ||
|
|
86102064a5 | ||
|
|
0fd3347148 | ||
|
|
b74265c842 | ||
|
|
1fef2fad2d | ||
|
|
9345240ff1 | ||
|
|
9ab23231e6 | ||
|
|
dbe623b167 | ||
|
|
71e51c179c | ||
|
|
4b8dbbdf98 | ||
|
|
aaf1895a12 | ||
|
|
979326b0b1 | ||
|
|
5d9cfc76cd | ||
|
|
8db7bd2d8f | ||
|
|
d461d462aa | ||
|
|
e67fa424b2 | ||
|
|
121176f0e9 | ||
|
|
1c2636e7b3 | ||
|
|
840cad0ff7 | ||
|
|
f76d63b92a | ||
|
|
71ef6675ce | ||
|
|
793b87948c | ||
|
|
a1b0ff09a8 | ||
|
|
5a803d76ad | ||
|
|
9513025130 | ||
|
|
a13c60bf9f | ||
|
|
bc23e5ac5c | ||
|
|
2377cdfa4e | ||
|
|
e3ae05aabd | ||
|
|
6c3ff3e2ed | ||
|
|
2249eea59f | ||
|
|
d608363d7b | ||
|
|
b2739cbb79 | ||
|
|
3607737b5e | ||
|
|
bf9691ed39 | ||
|
|
216aaaf1d6 | ||
|
|
3a53d49b7e | ||
|
|
4d62d7867e | ||
|
|
c0e3b1a0c7 | ||
|
|
34fe81f7eb | ||
|
|
11a746d363 | ||
|
|
1609933748 | ||
|
|
98096771c2 | ||
|
|
deb38f7a68 | ||
|
|
bac9b8eef6 | ||
|
|
76bb927337 | ||
|
|
699751c531 | ||
|
|
06b15bfd63 | ||
|
|
c68f68d6cc | ||
|
|
6e439a5e53 | ||
|
|
78be566428 | ||
|
|
f6f38f2f2d | ||
|
|
9a9a4293b3 | ||
|
|
09c68c9ad0 | ||
|
|
13d8835b75 | ||
|
|
2091f0c97e | ||
|
|
54fe26dcfb | ||
|
|
4ffd7f3d05 | ||
|
|
a12d959729 | ||
|
|
895029dc15 | ||
|
|
c561a499d7 | ||
|
|
69c1401764 | ||
|
|
50ba6faaf6 | ||
|
|
46bcbaf97b | ||
|
|
0e46a9b86e | ||
|
|
e459cb4d09 | ||
|
|
7dbd395781 | ||
|
|
6aea1c0da5 | ||
|
|
aeab6c559c |
@@ -1,12 +1,12 @@
|
||||
# ERPNext - Open source ERP for small and medium-size business [](https://travis-ci.org/frappe/erpnext)
|
||||
# ERPNext - ERP made simple
|
||||
|
||||
[](https://gitter.im/frappe/erpnext?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://travis-ci.org/frappe/erpnext) [](https://gitter.im/frappe/erpnext?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
[https://erpnext.com](https://erpnext.com)
|
||||
|
||||
Includes: Accounting, Inventory, CRM, Sales, Purchase, Projects, HRMS. Requires MariaDB.
|
||||
|
||||
ERPNext is built on the [Frappe](https://github.com/frappe/frappe) Framework, a full-stack web app framework in Python & Javascript.
|
||||
ERPNext is built on the [Frappe](https://github.com/frappe/frappe) Framework, a full-stack web app framework in Python & JavaScript.
|
||||
|
||||
- [User Guide](https://manual.erpnext.com)
|
||||
- [Getting Help](http://erpnext.org/getting-help.html)
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
from __future__ import unicode_literals
|
||||
__version__ = '6.1.1'
|
||||
__version__ = '6.7.2'
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"description": "Heads (or groups) against which Accounting Entries are made and balances are maintained.",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Master",
|
||||
"document_type": "Setup",
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
@@ -132,7 +132,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Root Type",
|
||||
"label": "Root Type",
|
||||
"no_copy": 0,
|
||||
"options": "\nAsset\nLiability\nIncome\nExpense\nEquity",
|
||||
"permlevel": 0,
|
||||
@@ -154,7 +154,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Report Type",
|
||||
"label": "Report Type",
|
||||
"no_copy": 0,
|
||||
"options": "\nBalance Sheet\nProfit and Loss",
|
||||
"permlevel": 0,
|
||||
@@ -166,6 +166,30 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "eval:doc.is_group==0",
|
||||
"fieldname": "account_currency",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Currency",
|
||||
"no_copy": 0,
|
||||
"options": "Currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -222,7 +246,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 1,
|
||||
"in_list_view": 0,
|
||||
"label": "Account Type",
|
||||
"label": "Account Type",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "account_type",
|
||||
"oldfieldtype": "Select",
|
||||
@@ -271,7 +295,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Frozen",
|
||||
"label": "Frozen",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "freeze_account",
|
||||
"oldfieldtype": "Select",
|
||||
@@ -317,7 +341,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Balance must be",
|
||||
"label": "Balance must be",
|
||||
"no_copy": 0,
|
||||
"options": "\nDebit\nCredit",
|
||||
"permlevel": 0,
|
||||
@@ -402,7 +426,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-09-07 15:51:26",
|
||||
"modified": "2015-10-02 07:38:37.436071",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Account",
|
||||
|
||||
@@ -7,6 +7,8 @@ from frappe.utils import cstr, cint
|
||||
from frappe import throw, _
|
||||
from frappe.model.document import Document
|
||||
|
||||
class RootNotEditable(frappe.ValidationError): pass
|
||||
|
||||
class Account(Document):
|
||||
nsm_parent_field = 'parent_account'
|
||||
|
||||
@@ -28,6 +30,7 @@ class Account(Document):
|
||||
self.validate_warehouse_account()
|
||||
self.validate_frozen_accounts_modifier()
|
||||
self.validate_balance_must_be_debit_or_credit()
|
||||
self.validate_account_currency()
|
||||
|
||||
def validate_parent(self):
|
||||
"""Fetch Parent Details and validate parent account"""
|
||||
@@ -47,27 +50,27 @@ class Account(Document):
|
||||
def set_root_and_report_type(self):
|
||||
if self.parent_account:
|
||||
par = frappe.db.get_value("Account", self.parent_account, ["report_type", "root_type"], as_dict=1)
|
||||
|
||||
|
||||
if par.report_type:
|
||||
self.report_type = par.report_type
|
||||
if par.root_type:
|
||||
self.root_type = par.root_type
|
||||
|
||||
|
||||
if self.is_group:
|
||||
db_value = frappe.db.get_value("Account", self.name, ["report_type", "root_type"], as_dict=1)
|
||||
if db_value:
|
||||
if self.report_type != db_value.report_type:
|
||||
frappe.db.sql("update `tabAccount` set report_type=%s where lft > %s and rgt < %s",
|
||||
frappe.db.sql("update `tabAccount` set report_type=%s where lft > %s and rgt < %s",
|
||||
(self.report_type, self.lft, self.rgt))
|
||||
if self.root_type != db_value.root_type:
|
||||
frappe.db.sql("update `tabAccount` set root_type=%s where lft > %s and rgt < %s",
|
||||
frappe.db.sql("update `tabAccount` set root_type=%s where lft > %s and rgt < %s",
|
||||
(self.root_type, self.lft, self.rgt))
|
||||
|
||||
def validate_root_details(self):
|
||||
# does not exists parent
|
||||
if frappe.db.exists("Account", self.name):
|
||||
if not frappe.db.get_value("Account", self.name, "parent_account"):
|
||||
throw(_("Root cannot be edited."))
|
||||
throw(_("Root cannot be edited."), RootNotEditable)
|
||||
|
||||
def validate_frozen_accounts_modifier(self):
|
||||
old_value = frappe.db.get_value("Account", self.name, "freeze_account")
|
||||
@@ -87,6 +90,14 @@ class Account(Document):
|
||||
elif account_balance < 0 and self.balance_must_be == "Debit":
|
||||
frappe.throw(_("Account balance already in Credit, you are not allowed to set 'Balance Must Be' as 'Debit'"))
|
||||
|
||||
def validate_account_currency(self):
|
||||
if not self.account_currency:
|
||||
self.account_currency = frappe.db.get_value("Company", self.company, "default_currency")
|
||||
|
||||
elif self.account_currency != frappe.db.get_value("Account", self.name, "account_currency"):
|
||||
if frappe.db.get_value("GL Entry", {"account": self.name}):
|
||||
frappe.throw(_("Currency can not be changed after making entries using some other currency"))
|
||||
|
||||
def convert_group_to_ledger(self):
|
||||
if self.check_if_child_exists():
|
||||
throw(_("Account with child nodes cannot be converted to ledger"))
|
||||
@@ -136,6 +147,8 @@ class Account(Document):
|
||||
self.validate_warehouse(old_warehouse)
|
||||
if self.warehouse:
|
||||
self.validate_warehouse(self.warehouse)
|
||||
elif self.warehouse:
|
||||
self.warehouse = None
|
||||
|
||||
def validate_warehouse(self, warehouse):
|
||||
if frappe.db.get_value("Stock Ledger Entry", {"warehouse": warehouse}):
|
||||
@@ -196,3 +209,16 @@ def get_parent_account(doctype, txt, searchfield, start, page_len, filters):
|
||||
and %s like %s order by name limit %s, %s""" %
|
||||
("%s", searchfield, "%s", "%s", "%s"),
|
||||
(filters["company"], "%%%s%%" % txt, start, page_len), as_list=1)
|
||||
|
||||
def get_account_currency(account):
|
||||
"""Helper function to get account currency"""
|
||||
if not account:
|
||||
return
|
||||
def generator():
|
||||
account_currency, company = frappe.db.get_value("Account", account, ["account_currency", "company"])
|
||||
if not account_currency:
|
||||
account_currency = frappe.db.get_value("Company", company, "default_currency")
|
||||
|
||||
return account_currency
|
||||
|
||||
return frappe.local_cache("account_currency", account, generator)
|
||||
|
||||
@@ -36,7 +36,8 @@ def create_charts(chart_name, company):
|
||||
"is_group": is_group,
|
||||
"root_type": root_type,
|
||||
"report_type": report_type,
|
||||
"account_type": child.get("account_type")
|
||||
"account_type": child.get("account_type"),
|
||||
"account_currency": frappe.db.get_value("Company", company, "default_currency")
|
||||
})
|
||||
|
||||
if root_account:
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
{
|
||||
"country_code": "gt",
|
||||
"name": "Cuentas de Guatemala",
|
||||
"is_active": "Yes",
|
||||
"tree": {
|
||||
"Activos": {
|
||||
"Activo Corriente": {
|
||||
"Caja y Bancos": {},
|
||||
"Cuentas por Cobrar": {},
|
||||
"Impuestos por Cobrar": {
|
||||
"IVA por Cobrar": {},
|
||||
"Retenciones de IVA recibidas": {}
|
||||
},
|
||||
"Inventario": {}
|
||||
},
|
||||
"No Corriente": {
|
||||
"Activos Fijos": {},
|
||||
"Cargos Diferidos": {}
|
||||
},
|
||||
"root_type": "Asset"
|
||||
},
|
||||
"Pasivos": {
|
||||
"Pasivo Corriente": {
|
||||
"Proveedores": {
|
||||
"Inventario Recibido pero No Cobrado": {
|
||||
"account_type": "Stock Received But Not Billed"
|
||||
}
|
||||
},
|
||||
"Impuestos por Pagar": {},
|
||||
"Sueldos por Liquidar": {},
|
||||
"Prestaciones": {},
|
||||
"Cuentas por Pagar": {},
|
||||
"Otras Cuentas por Pagar": {},
|
||||
"Acreedores": {}
|
||||
},
|
||||
"Pasivo No Corriente": {
|
||||
"Provisión para Indemnizaciones": {},
|
||||
"Acreedores": {}
|
||||
},
|
||||
"root_type": "Liability"
|
||||
},
|
||||
"Patrimonio": {
|
||||
"Capital": {},
|
||||
"Utilidades Retenidas": {},
|
||||
"Resultados del Ejercicio": {},
|
||||
"root_type": "Asset"
|
||||
},
|
||||
"Costos": {
|
||||
"Costo de Ventas": {},
|
||||
"Costos Incluidos en la Valuación": {
|
||||
"account_type": "Expenses Included In Valuation"
|
||||
},
|
||||
"Stock Adjustment": {
|
||||
"account_type": "Stock Adjustment"
|
||||
},
|
||||
"root_type": "Expense"
|
||||
},
|
||||
"Gastos": {
|
||||
"Gastos de Personal": {},
|
||||
"Honorarios Profesionales": {},
|
||||
"Servicios Básicos": {},
|
||||
"Alquileres": {},
|
||||
"Seguros": {},
|
||||
"Mantenimiento": {},
|
||||
"Depreciaciones": {},
|
||||
"Gastos Diversos": {},
|
||||
"root_type": "Expense"
|
||||
},
|
||||
"Ingresos": {
|
||||
"Productos": {},
|
||||
"Servicios": {},
|
||||
"root_type": "Income"
|
||||
},
|
||||
"Otros Gastos y Productos Financieros": {
|
||||
"Otros Ingresos": {
|
||||
"Otros Gastos y Productos Financieros": {
|
||||
"Intereses": {},
|
||||
"Otros Gastos Financieros": {}
|
||||
}
|
||||
},
|
||||
"Otros Gastos": {
|
||||
"Otros Gastos y Productos Financieros": {
|
||||
"Intereses": {},
|
||||
"Otros Gastos Financieros": {}
|
||||
}
|
||||
},
|
||||
"root_type": "Expense"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,36 +9,39 @@ def _make_test_records(verbose):
|
||||
|
||||
accounts = [
|
||||
# [account_name, parent_account, is_group]
|
||||
["_Test Account Bank Account", "Bank Accounts", 0, "Bank"],
|
||||
["_Test Bank", "Bank Accounts", 0, "Bank", None],
|
||||
["_Test Bank USD", "Bank Accounts", 0, "Bank", "USD"],
|
||||
["_Test Bank EUR", "Bank Accounts", 0, "Bank", "EUR"],
|
||||
|
||||
["_Test Account Stock Expenses", "Direct Expenses", 1, None],
|
||||
["_Test Account Shipping Charges", "_Test Account Stock Expenses", 0, "Chargeable"],
|
||||
["_Test Account Customs Duty", "_Test Account Stock Expenses", 0, "Tax"],
|
||||
["_Test Account Insurance Charges", "_Test Account Stock Expenses", 0, "Chargeable"],
|
||||
["_Test Account Stock Adjustment", "_Test Account Stock Expenses", 0, "Stock Adjustment"],
|
||||
["_Test Account Stock Expenses", "Direct Expenses", 1, None, None],
|
||||
["_Test Account Shipping Charges", "_Test Account Stock Expenses", 0, "Chargeable", None],
|
||||
["_Test Account Customs Duty", "_Test Account Stock Expenses", 0, "Tax", None],
|
||||
["_Test Account Insurance Charges", "_Test Account Stock Expenses", 0, "Chargeable", None],
|
||||
["_Test Account Stock Adjustment", "_Test Account Stock Expenses", 0, "Stock Adjustment", None],
|
||||
|
||||
["_Test Account Tax Assets", "Current Assets", 1, None, None],
|
||||
["_Test Account VAT", "_Test Account Tax Assets", 0, "Tax", None],
|
||||
["_Test Account Service Tax", "_Test Account Tax Assets", 0, "Tax", None],
|
||||
|
||||
["_Test Account Tax Assets", "Current Assets", 1, None],
|
||||
["_Test Account VAT", "_Test Account Tax Assets", 0, "Tax"],
|
||||
["_Test Account Service Tax", "_Test Account Tax Assets", 0, "Tax"],
|
||||
["_Test Account Reserves and Surplus", "Current Liabilities", 0, None, None],
|
||||
|
||||
["_Test Account Reserves and Surplus", "Current Liabilities", 0, None],
|
||||
|
||||
["_Test Account Cost for Goods Sold", "Expenses", 0, None],
|
||||
["_Test Account Excise Duty", "_Test Account Tax Assets", 0, "Tax"],
|
||||
["_Test Account Education Cess", "_Test Account Tax Assets", 0, "Tax"],
|
||||
["_Test Account S&H Education Cess", "_Test Account Tax Assets", 0, "Tax"],
|
||||
["_Test Account CST", "Direct Expenses", 0, "Tax"],
|
||||
["_Test Account Discount", "Direct Expenses", 0, None],
|
||||
["_Test Write Off", "Indirect Expenses", 0, None],
|
||||
["_Test Account Cost for Goods Sold", "Expenses", 0, None, None],
|
||||
["_Test Account Excise Duty", "_Test Account Tax Assets", 0, "Tax", None],
|
||||
["_Test Account Education Cess", "_Test Account Tax Assets", 0, "Tax", None],
|
||||
["_Test Account S&H Education Cess", "_Test Account Tax Assets", 0, "Tax", None],
|
||||
["_Test Account CST", "Direct Expenses", 0, "Tax", None],
|
||||
["_Test Account Discount", "Direct Expenses", 0, None, None],
|
||||
["_Test Write Off", "Indirect Expenses", 0, None, None],
|
||||
|
||||
# related to Account Inventory Integration
|
||||
["_Test Account Stock In Hand", "Current Assets", 0, None],
|
||||
["_Test Account Fixed Assets", "Current Assets", 0, None],
|
||||
["_Test Account Stock In Hand", "Current Assets", 0, None, None],
|
||||
["_Test Account Fixed Assets", "Current Assets", 0, None, None],
|
||||
|
||||
# Receivable / Payable Account
|
||||
["_Test Receivable", "Current Assets", 0, "Receivable"],
|
||||
["_Test Payable", "Current Liabilities", 0, "Payable"],
|
||||
["_Test Receivable", "Current Assets", 0, "Receivable", None],
|
||||
["_Test Payable", "Current Liabilities", 0, "Payable", None],
|
||||
["_Test Receivable USD", "Current Assets", 0, "Receivable", "USD"],
|
||||
["_Test Payable USD", "Current Liabilities", 0, "Payable", "USD"]
|
||||
]
|
||||
|
||||
for company, abbr in [["_Test Company", "_TC"], ["_Test Company 1", "_TC1"]]:
|
||||
@@ -48,7 +51,8 @@ def _make_test_records(verbose):
|
||||
"parent_account": parent_account + " - " + abbr,
|
||||
"company": company,
|
||||
"is_group": is_group,
|
||||
"account_type": account_type
|
||||
} for account_name, parent_account, is_group, account_type in accounts])
|
||||
"account_type": account_type,
|
||||
"account_currency": currency
|
||||
} for account_name, parent_account, is_group, account_type, currency in accounts])
|
||||
|
||||
return test_objects
|
||||
|
||||
@@ -16,7 +16,9 @@ class AccountsSettings(Document):
|
||||
if cint(self.auto_accounting_for_stock):
|
||||
# set default perpetual account in company
|
||||
for company in frappe.db.sql("select name from tabCompany"):
|
||||
frappe.get_doc("Company", company[0]).save()
|
||||
company = frappe.get_doc("Company", company[0])
|
||||
company.flags.ignore_permissions = True
|
||||
company.save()
|
||||
|
||||
# Create account head for warehouses
|
||||
warehouse_list = frappe.db.sql("select name, company from tabWarehouse", as_dict=1)
|
||||
@@ -25,4 +27,5 @@ class AccountsSettings(Document):
|
||||
frappe.throw(_("Company is missing in warehouses {0}").format(comma_and(warehouse_with_no_company)))
|
||||
for wh in warehouse_list:
|
||||
wh_doc = frappe.get_doc("Warehouse", wh.name)
|
||||
wh_doc.flags.ignore_permissions = True
|
||||
wh_doc.save()
|
||||
|
||||
@@ -249,7 +249,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2015-08-10 16:59:43.974705",
|
||||
"modified": "2015-10-02 07:38:39.149782",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Bank Reconciliation Detail",
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2015-02-19 01:06:59.471417",
|
||||
"modified": "2015-10-02 07:38:40.727468",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Budget Detail",
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Series",
|
||||
"label": "Series",
|
||||
"no_copy": 0,
|
||||
"options": "C-FORM-",
|
||||
"permlevel": 0,
|
||||
@@ -192,7 +192,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Quarter",
|
||||
"label": "Quarter",
|
||||
"no_copy": 0,
|
||||
"options": "\nI\nII\nIII\nIV",
|
||||
"permlevel": 0,
|
||||
@@ -344,7 +344,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 3,
|
||||
"modified": "2015-09-07 15:51:26",
|
||||
"modified": "2015-10-02 07:38:40.926061",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "C-Form",
|
||||
|
||||
@@ -136,7 +136,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2015-01-01 14:29:58.597428",
|
||||
"modified": "2015-10-02 07:38:41.105885",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "C-Form Invoice Detail",
|
||||
|
||||
@@ -17,8 +17,7 @@ erpnext.accounts.CostCenterController = frappe.ui.form.Controller.extend({
|
||||
return {
|
||||
filters:[
|
||||
['Account', 'company', '=', me.frm.doc.company],
|
||||
['Account', 'root_type', '=', 'Expense'],
|
||||
['Account', 'is_group', '=', '0'],
|
||||
['Account', 'is_group', '=', '0']
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"description": "Track separate Income and Expense for product verticals or divisions.",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Master",
|
||||
"document_type": "Setup",
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
@@ -298,7 +298,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-09-07 15:51:26",
|
||||
"modified": "2015-10-02 07:38:42.617993",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Cost Center",
|
||||
|
||||
@@ -32,13 +32,13 @@ class CostCenter(NestedSet):
|
||||
for d in self.get('budgets'):
|
||||
if d.account:
|
||||
account_details = frappe.db.get_value("Account", d.account,
|
||||
["is_group", "company", "root_type"], as_dict=1)
|
||||
["is_group", "company", "report_type"], as_dict=1)
|
||||
if account_details.is_group:
|
||||
frappe.throw(_("Budget cannot be assigned against Group Account {0}").format(d.account))
|
||||
elif account_details.company != self.company:
|
||||
frappe.throw(_("Account {0} does not belongs to company {1}").format(d.account, self.company))
|
||||
elif account_details.root_type != "Expense":
|
||||
frappe.throw(_("Budget cannot be assigned against {0}, as it's not an Expense account")
|
||||
elif account_details.report_type != "Profit and Loss":
|
||||
frappe.throw(_("Budget cannot be assigned against {0}, as it's not an Income or Expense account")
|
||||
.format(d.account))
|
||||
|
||||
if [d.account, d.fiscal_year] in check_acc_list:
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"description": "**Fiscal Year** represents a Financial Year. All accounting entries and other major transactions are tracked against **Fiscal Year**.",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Master",
|
||||
"document_type": "Setup",
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
@@ -133,7 +133,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-09-07 15:51:26",
|
||||
"modified": "2015-10-02 07:38:50.942038",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Fiscal Year",
|
||||
|
||||
@@ -1,32 +1,38 @@
|
||||
[
|
||||
{
|
||||
"doctype": "Fiscal Year",
|
||||
"year": "_Test Fiscal Year 2012",
|
||||
"year_end_date": "2012-12-31",
|
||||
"doctype": "Fiscal Year",
|
||||
"year": "_Test Fiscal Year 2012",
|
||||
"year_end_date": "2012-12-31",
|
||||
"year_start_date": "2012-01-01"
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "Fiscal Year",
|
||||
"year": "_Test Fiscal Year 2013",
|
||||
"year_end_date": "2013-12-31",
|
||||
"doctype": "Fiscal Year",
|
||||
"year": "_Test Fiscal Year 2013",
|
||||
"year_end_date": "2013-12-31",
|
||||
"year_start_date": "2013-01-01"
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "Fiscal Year",
|
||||
"year": "_Test Fiscal Year 2014",
|
||||
"year_end_date": "2014-12-31",
|
||||
"doctype": "Fiscal Year",
|
||||
"year": "_Test Fiscal Year 2014",
|
||||
"year_end_date": "2014-12-31",
|
||||
"year_start_date": "2014-01-01"
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "Fiscal Year",
|
||||
"year": "_Test Fiscal Year 2015",
|
||||
"year_end_date": "2015-12-31",
|
||||
"doctype": "Fiscal Year",
|
||||
"year": "_Test Fiscal Year 2015",
|
||||
"year_end_date": "2015-12-31",
|
||||
"year_start_date": "2015-01-01"
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "Fiscal Year",
|
||||
"year": "_Test Fiscal Year 2016",
|
||||
"year_end_date": "2016-12-31",
|
||||
"doctype": "Fiscal Year",
|
||||
"year": "_Test Fiscal Year 2016",
|
||||
"year_end_date": "2016-12-31",
|
||||
"year_start_date": "2016-01-01"
|
||||
},
|
||||
{
|
||||
"doctype": "Fiscal Year",
|
||||
"year": "_Test Fiscal Year 2017",
|
||||
"year_end_date": "2017-12-31",
|
||||
"year_start_date": "2017-01-01"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Master",
|
||||
"document_type": "Setup",
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
@@ -39,7 +39,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2014-10-02 13:35:44.155278",
|
||||
"modified": "2015-10-02 07:38:51.045350",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Fiscal Year Company",
|
||||
|
||||
@@ -156,12 +156,13 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Debit Amt",
|
||||
"label": "Debit Amount",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "debit",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
@@ -180,12 +181,82 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Credit Amt",
|
||||
"label": "Credit Amount",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "credit",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "account_currency",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Account Currency",
|
||||
"no_copy": 0,
|
||||
"options": "Currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "debit_in_account_currency",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Debit Amount in Account Currency",
|
||||
"no_copy": 0,
|
||||
"options": "currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "credit_in_account_currency",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Credit Amount in Account Currency",
|
||||
"no_copy": 0,
|
||||
"options": "currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
@@ -261,7 +332,7 @@
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
@@ -442,7 +513,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-09-07 15:51:26",
|
||||
"modified": "2015-10-20 12:10:59.771050",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "GL Entry",
|
||||
|
||||
@@ -3,13 +3,15 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
from frappe.utils import flt, fmt_money, getdate, formatdate
|
||||
from frappe import _
|
||||
|
||||
from frappe.utils import flt, fmt_money, getdate, formatdate
|
||||
from frappe.model.document import Document
|
||||
from erpnext.accounts.party import validate_party_gle_currency
|
||||
from erpnext.accounts.utils import get_account_currency
|
||||
from erpnext.setup.doctype.company.company import get_company_currency
|
||||
from erpnext.exceptions import InvalidAccountCurrency, CustomerFrozen
|
||||
|
||||
class CustomerFrozen(frappe.ValidationError): pass
|
||||
exclude_from_linked_with = True
|
||||
|
||||
class GLEntry(Document):
|
||||
def validate(self):
|
||||
@@ -20,6 +22,7 @@ class GLEntry(Document):
|
||||
self.check_pl_account()
|
||||
self.validate_cost_center()
|
||||
self.validate_party()
|
||||
self.validate_currency()
|
||||
|
||||
def on_update_with_args(self, adv_adj, update_outstanding = 'Yes'):
|
||||
self.validate_account_details(adv_adj)
|
||||
@@ -99,6 +102,20 @@ class GLEntry(Document):
|
||||
if frappe.db.get_value(self.party_type, self.party, "is_frozen"):
|
||||
frappe.throw("{0} {1} is frozen".format(self.party_type, self.party), CustomerFrozen)
|
||||
|
||||
def validate_currency(self):
|
||||
company_currency = get_company_currency(self.company)
|
||||
account_currency = get_account_currency(self.account)
|
||||
|
||||
if not self.account_currency:
|
||||
self.account_currency = company_currency
|
||||
|
||||
if account_currency != self.account_currency:
|
||||
frappe.throw(_("Accounting Entry for {0} can only be made in currency: {1}")
|
||||
.format(self.account, (account_currency or company_currency)), InvalidAccountCurrency)
|
||||
|
||||
if self.party_type and self.party:
|
||||
validate_party_gle_currency(self.party_type, self.party, self.company, self.account_currency)
|
||||
|
||||
def validate_balance_type(account, adv_adj=False):
|
||||
if not adv_adj and account:
|
||||
balance_must_be = frappe.db.get_value("Account", account, "balance_must_be")
|
||||
@@ -131,7 +148,8 @@ def update_outstanding_amt(account, party_type, party, against_voucher_type, aga
|
||||
party_condition = ""
|
||||
|
||||
# get final outstanding amt
|
||||
bal = flt(frappe.db.sql("""select sum(ifnull(debit, 0)) - sum(ifnull(credit, 0))
|
||||
bal = flt(frappe.db.sql("""
|
||||
select sum(ifnull(debit_in_account_currency, 0)) - sum(ifnull(credit_in_account_currency, 0))
|
||||
from `tabGL Entry`
|
||||
where against_voucher_type=%s and against_voucher=%s
|
||||
and account = %s {0}""".format(party_condition),
|
||||
@@ -141,7 +159,7 @@ def update_outstanding_amt(account, party_type, party, against_voucher_type, aga
|
||||
bal = -bal
|
||||
elif against_voucher_type == "Journal Entry":
|
||||
against_voucher_amount = flt(frappe.db.sql("""
|
||||
select sum(ifnull(debit, 0)) - sum(ifnull(credit, 0))
|
||||
select sum(ifnull(debit_in_account_currency, 0)) - sum(ifnull(credit_in_account_currency, 0))
|
||||
from `tabGL Entry` where voucher_type = 'Journal Entry' and voucher_no = %s
|
||||
and account = %s and ifnull(against_voucher, '') = '' {0}"""
|
||||
.format(party_condition), (against_voucher, account))[0][0])
|
||||
|
||||
@@ -11,7 +11,7 @@ class TestGLEntry(unittest.TestCase):
|
||||
frappe.db.set_value("Company", "_Test Company", "round_off_cost_center", "_Test Cost Center - _TC")
|
||||
|
||||
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
||||
"_Test Account Bank Account - _TC", 100, "_Test Cost Center - _TC", submit=False)
|
||||
"_Test Bank - _TC", 100, "_Test Cost Center - _TC", submit=False)
|
||||
|
||||
jv.get("accounts")[0].debit = 100.01
|
||||
jv.flags.ignore_validate = True
|
||||
|
||||
@@ -2,8 +2,42 @@
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
frappe.provide("erpnext.accounts");
|
||||
frappe.provide("erpnext.journal_entry");
|
||||
frappe.require("assets/erpnext/js/utils.js");
|
||||
|
||||
frappe.ui.form.on("Journal Entry", {
|
||||
refresh: function(frm) {
|
||||
erpnext.toggle_naming_series();
|
||||
frm.cscript.voucher_type(frm.doc);
|
||||
|
||||
if(frm.doc.docstatus==1) {
|
||||
frm.add_custom_button(__('View Ledger'), function() {
|
||||
frappe.route_options = {
|
||||
"voucher_no": frm.doc.name,
|
||||
"from_date": frm.doc.posting_date,
|
||||
"to_date": frm.doc.posting_date,
|
||||
"company": frm.doc.company,
|
||||
group_by_voucher: 0
|
||||
};
|
||||
frappe.set_route("query-report", "General Ledger");
|
||||
}, "icon-table");
|
||||
}
|
||||
|
||||
if (frm.doc.__islocal) {
|
||||
frm.add_custom_button(__('Quick Entry'), function() {
|
||||
return erpnext.journal_entry.quick_entry(frm);
|
||||
});
|
||||
}
|
||||
|
||||
// hide /unhide fields based on currency
|
||||
erpnext.journal_entry.toggle_fields_based_on_currency(frm);
|
||||
},
|
||||
|
||||
multi_currency: function(frm) {
|
||||
erpnext.journal_entry.toggle_fields_based_on_currency(frm);
|
||||
}
|
||||
})
|
||||
|
||||
erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
|
||||
onload: function() {
|
||||
this.load_defaults();
|
||||
@@ -23,23 +57,24 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
|
||||
}
|
||||
);
|
||||
|
||||
if(!this.frm.doc.amended_from) this.frm.doc.posting_date = get_today();
|
||||
if(!this.frm.doc.amended_from) this.frm.doc.posting_date = this.frm.posting_date || get_today();
|
||||
}
|
||||
},
|
||||
|
||||
setup_queries: function() {
|
||||
var me = this;
|
||||
|
||||
$.each(["account", "cost_center"], function(i, fieldname) {
|
||||
me.frm.set_query(fieldname, "accounts", function() {
|
||||
frappe.model.validate_missing(me.frm.doc, "company");
|
||||
return {
|
||||
filters: {
|
||||
company: me.frm.doc.company,
|
||||
is_group: 0
|
||||
}
|
||||
};
|
||||
});
|
||||
me.frm.set_query("account", "accounts", function(doc, cdt, cdn) {
|
||||
return erpnext.journal_entry.account_query(me.frm);
|
||||
});
|
||||
|
||||
me.frm.set_query("cost_center", "accounts", function(doc, cdt, cdn) {
|
||||
return {
|
||||
filters: {
|
||||
company: me.frm.doc.company,
|
||||
is_group: 0
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
me.frm.set_query("party_type", "accounts", function(doc, cdt, cdn) {
|
||||
@@ -76,22 +111,22 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
|
||||
|
||||
if(in_list(["Sales Invoice", "Purchase Invoice"], jvd.reference_type)) {
|
||||
out.filters.push([jvd.reference_type, "outstanding_amount", "!=", 0]);
|
||||
|
||||
|
||||
// account filter
|
||||
frappe.model.validate_missing(jvd, "account");
|
||||
|
||||
|
||||
party_account_field = jvd.reference_type==="Sales Invoice" ? "debit_to": "credit_to";
|
||||
out.filters.push([jvd.reference_type, party_account_field, "=", jvd.account]);
|
||||
} else {
|
||||
// party_type and party mandatory
|
||||
frappe.model.validate_missing(jvd, "party_type");
|
||||
frappe.model.validate_missing(jvd, "party");
|
||||
|
||||
|
||||
out.filters.push([jvd.reference_type, "per_billed", "<", 100]);
|
||||
}
|
||||
|
||||
|
||||
if(jvd.party_type && jvd.party) {
|
||||
out.filters.push([jvd.reference_type,
|
||||
out.filters.push([jvd.reference_type,
|
||||
(jvd.reference_type.indexOf("Sales")===0 ? "customer" : "supplier"), "=", jvd.party]);
|
||||
}
|
||||
|
||||
@@ -118,32 +153,39 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
|
||||
|
||||
reference_name: function(doc, cdt, cdn) {
|
||||
var d = frappe.get_doc(cdt, cdn);
|
||||
if (d.reference_type==="Purchase Invoice" && !flt(d.debit)) {
|
||||
this.get_outstanding('Purchase Invoice', d.reference_name, d);
|
||||
}
|
||||
if (d.reference_type==="Sales Invoice" && !flt(d.credit)) {
|
||||
this.get_outstanding('Sales Invoice', d.reference_name, d);
|
||||
}
|
||||
if (d.reference_type==="Journal Entry" && !flt(d.credit) && !flt(d.debit)) {
|
||||
this.get_outstanding('Journal Entry', d.reference_name, 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);
|
||||
}
|
||||
if (d.reference_type==="Sales Invoice" && !flt(d.credit)) {
|
||||
this.get_outstanding('Sales Invoice', d.reference_name, doc.company, d);
|
||||
}
|
||||
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: function(doctype, docname, child) {
|
||||
get_outstanding: function(doctype, docname, company, child) {
|
||||
var me = this;
|
||||
var args = {
|
||||
"doctype": doctype,
|
||||
"docname": docname,
|
||||
"party": child.party,
|
||||
"account": child.account
|
||||
"account": child.account,
|
||||
"account_currency": child.account_currency,
|
||||
"company": company
|
||||
}
|
||||
|
||||
return this.frm.call({
|
||||
child: child,
|
||||
method: "get_outstanding",
|
||||
return frappe.call({
|
||||
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_outstanding",
|
||||
args: { args: args},
|
||||
callback: function(r) {
|
||||
cur_frm.cscript.update_totals(me.frm.doc);
|
||||
if(r.message) {
|
||||
$.each(r.message, function(field, value) {
|
||||
frappe.model.set_value(child.doctype, child.name, field, value);
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
@@ -161,50 +203,36 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
|
||||
// set difference
|
||||
if(doc.difference) {
|
||||
if(doc.difference > 0) {
|
||||
row.credit_in_account_currency = doc.difference;
|
||||
row.credit = doc.difference;
|
||||
} else {
|
||||
row.debit_in_account_currency = -doc.difference;
|
||||
row.debit = -doc.difference;
|
||||
}
|
||||
}
|
||||
cur_frm.cscript.update_totals(doc);
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
cur_frm.script_manager.make(erpnext.accounts.JournalEntry);
|
||||
|
||||
cur_frm.cscript.refresh = function(doc) {
|
||||
erpnext.toggle_naming_series();
|
||||
cur_frm.cscript.voucher_type(doc);
|
||||
|
||||
if(doc.docstatus==1) {
|
||||
cur_frm.add_custom_button(__('View Ledger'), function() {
|
||||
frappe.route_options = {
|
||||
"voucher_no": doc.name,
|
||||
"from_date": doc.posting_date,
|
||||
"to_date": doc.posting_date,
|
||||
"company": doc.company,
|
||||
group_by_voucher: 0
|
||||
};
|
||||
frappe.set_route("query-report", "General Ledger");
|
||||
}, "icon-table");
|
||||
}
|
||||
}
|
||||
|
||||
cur_frm.cscript.company = function(doc, cdt, cdn) {
|
||||
cur_frm.refresh_fields();
|
||||
erpnext.get_fiscal_year(doc.company, doc.posting_date);
|
||||
}
|
||||
|
||||
cur_frm.cscript.posting_date = function(doc, cdt, cdn){
|
||||
cur_frm.posting_date = cur_frm.doc.posting_date;
|
||||
erpnext.get_fiscal_year(doc.company, doc.posting_date);
|
||||
}
|
||||
|
||||
cur_frm.cscript.update_totals = function(doc) {
|
||||
var td=0.0; var tc =0.0;
|
||||
var el = doc.accounts || [];
|
||||
for(var i in el) {
|
||||
td += flt(el[i].debit, precision("debit", el[i]));
|
||||
tc += flt(el[i].credit, precision("credit", el[i]));
|
||||
var accounts = doc.accounts || [];
|
||||
for(var i in accounts) {
|
||||
td += flt(accounts[i].debit, precision("debit", accounts[i]));
|
||||
tc += flt(accounts[i].credit, precision("credit", accounts[i]));
|
||||
}
|
||||
var doc = locals[doc.doctype][doc.name];
|
||||
doc.total_debit = td;
|
||||
@@ -213,32 +241,12 @@ cur_frm.cscript.update_totals = function(doc) {
|
||||
refresh_many(['total_debit','total_credit','difference']);
|
||||
}
|
||||
|
||||
cur_frm.cscript.debit = function(doc,dt,dn) { cur_frm.cscript.update_totals(doc); }
|
||||
cur_frm.cscript.credit = function(doc,dt,dn) { cur_frm.cscript.update_totals(doc); }
|
||||
|
||||
cur_frm.cscript.get_balance = function(doc,dt,dn) {
|
||||
cur_frm.cscript.update_totals(doc);
|
||||
return $c_obj(cur_frm.doc, 'get_balance', '', function(r, rt){
|
||||
cur_frm.refresh();
|
||||
});
|
||||
}
|
||||
// Get balance
|
||||
// -----------
|
||||
|
||||
cur_frm.cscript.account = function(doc,dt,dn) {
|
||||
var d = locals[dt][dn];
|
||||
if(d.account) {
|
||||
return frappe.call({
|
||||
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_account_balance_and_party_type",
|
||||
args: {account: d.account, date: doc.posting_date},
|
||||
callback: function(r) {
|
||||
$.extend(d, r.message);
|
||||
refresh_field('balance', d.name, 'accounts');
|
||||
refresh_field('party_type', d.name, 'accounts');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
cur_frm.cscript.validate = function(doc,cdt,cdn) {
|
||||
cur_frm.cscript.update_totals(doc);
|
||||
@@ -303,18 +311,67 @@ cur_frm.cscript.voucher_type = function(doc, cdt, cdn) {
|
||||
}
|
||||
}
|
||||
|
||||
frappe.ui.form.on("Journal Entry Account", "party", function(frm, cdt, cdn) {
|
||||
var d = frappe.get_doc(cdt, cdn);
|
||||
if(!d.account && d.party_type && d.party) {
|
||||
return frm.call({
|
||||
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_party_account_and_balance",
|
||||
child: d,
|
||||
args: {
|
||||
company: frm.doc.company,
|
||||
party_type: d.party_type,
|
||||
party: d.party
|
||||
}
|
||||
});
|
||||
frappe.ui.form.on("Journal Entry Account", {
|
||||
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"));
|
||||
return frm.call({
|
||||
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_party_account_and_balance",
|
||||
child: d,
|
||||
args: {
|
||||
company: frm.doc.company,
|
||||
party_type: d.party_type,
|
||||
party: d.party
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
account: 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"));
|
||||
|
||||
return frappe.call({
|
||||
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_account_balance_and_party_type",
|
||||
args: {
|
||||
account: d.account,
|
||||
date: frm.doc.posting_date,
|
||||
company: frm.doc.company,
|
||||
debit: flt(d.debit_in_account_currency),
|
||||
credit: flt(d.credit_in_account_currency),
|
||||
exchange_rate: d.exchange_rate
|
||||
},
|
||||
callback: function(r) {
|
||||
if(r.message) {
|
||||
$.extend(d, r.message);
|
||||
refresh_field('accounts');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
debit_in_account_currency: function(frm, cdt, cdn) {
|
||||
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn);
|
||||
},
|
||||
|
||||
credit_in_account_currency: function(frm, cdt, cdn) {
|
||||
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn);
|
||||
},
|
||||
|
||||
debit: function(frm, dt, dn) {
|
||||
cur_frm.cscript.update_totals(frm.doc);
|
||||
},
|
||||
|
||||
credit: function(frm, dt, dn) {
|
||||
cur_frm.cscript.update_totals(frm.doc);
|
||||
},
|
||||
|
||||
exchange_rate: function(frm, cdt, cdn) {
|
||||
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn);
|
||||
}
|
||||
})
|
||||
|
||||
@@ -322,3 +379,134 @@ 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) {
|
||||
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);
|
||||
|
||||
// dynamic label
|
||||
var field_label_map = {
|
||||
"debit_in_account_currency": "Debit",
|
||||
"credit_in_account_currency": "Credit"
|
||||
};
|
||||
|
||||
$.each(field_label_map, function (fieldname, label) {
|
||||
var df = frappe.meta.get_docfield("Journal Entry Account", fieldname, frm.doc.name);
|
||||
df.label = frm.doc.multi_currency ? (label + " in Account Currency") : label;
|
||||
})
|
||||
},
|
||||
|
||||
set_debit_credit_in_company_currency: function(frm, cdt, cdn) {
|
||||
erpnext.journal_entry.set_exchange_rate(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, "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) {
|
||||
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) {
|
||||
frappe.model.set_value(cdt, cdn, "exchange_rate", 1);
|
||||
} else if (!row.exchange_rate || row.account_type == "Bank") {
|
||||
frappe.call({
|
||||
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_exchange_rate",
|
||||
args: {
|
||||
account: row.account,
|
||||
account_currency: row.account_currency,
|
||||
company: frm.doc.company,
|
||||
reference_type: cstr(row.reference_type),
|
||||
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
|
||||
},
|
||||
callback: function(r) {
|
||||
if(r.message) {
|
||||
frappe.model.set_value(cdt, cdn, "exchange_rate", r.message);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
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 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,
|
||||
options: "Account",
|
||||
get_query: function() {
|
||||
return erpnext.journal_entry.account_query(frm);
|
||||
}
|
||||
},
|
||||
{fieldtype: "Link", fieldname: "credit_account", label: __("Credit Account"), reqd: 1,
|
||||
options: "Account",
|
||||
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: "Select", fieldname: "naming_series", label: __("Series"), reqd: 1,
|
||||
options: naming_series_options, default: naming_series_default},
|
||||
]
|
||||
});
|
||||
|
||||
dialog.set_primary_action(__("Save"), function() {
|
||||
var btn = this;
|
||||
var values = dialog.get_values();
|
||||
|
||||
frm.set_value("posting_date", values.posting_date);
|
||||
frm.set_value("naming_series", values.naming_series);
|
||||
|
||||
// clear table is used because there might've been an error while adding child
|
||||
// and cleanup didn't happen
|
||||
frm.clear_table("accounts");
|
||||
|
||||
// using grid.add_new_row() to add a row in UI as well as locals
|
||||
// this is required because triggers try to refresh the grid
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
frm.save();
|
||||
|
||||
dialog.hide();
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
},
|
||||
|
||||
account_query: function(frm) {
|
||||
var filters = {
|
||||
company: frm.doc.company,
|
||||
is_group: 0
|
||||
};
|
||||
if(!frm.doc.multi_currency) {
|
||||
$.extend(filters, {
|
||||
account_currency: frappe.get_doc(":Company", frm.doc.company).default_currency
|
||||
});
|
||||
}
|
||||
return { filters: filters };
|
||||
}
|
||||
});
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Title",
|
||||
"no_copy": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
@@ -64,7 +64,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 1,
|
||||
"in_list_view": 0,
|
||||
"label": "Entry Type",
|
||||
"label": "Entry Type",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "voucher_type",
|
||||
"oldfieldtype": "Select",
|
||||
@@ -88,7 +88,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Series",
|
||||
"label": "Series",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "naming_series",
|
||||
"oldfieldtype": "Select",
|
||||
@@ -171,7 +171,7 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "accounts",
|
||||
@@ -400,6 +400,28 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "multi_currency",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Multi Currency",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -636,7 +658,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Write Off Based On",
|
||||
"label": "Write Off Based On",
|
||||
"no_copy": 0,
|
||||
"options": "Accounts Receivable\nAccounts Payable",
|
||||
"permlevel": 0,
|
||||
@@ -930,7 +952,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 1,
|
||||
"in_list_view": 0,
|
||||
"label": "Is Opening",
|
||||
"label": "Is Opening",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "is_opening",
|
||||
"oldfieldtype": "Select",
|
||||
@@ -1002,7 +1024,7 @@
|
||||
"is_submittable": 1,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-09-07 15:51:26",
|
||||
"modified": "2015-10-02 07:38:54.074343",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Journal Entry",
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.utils import cstr, flt, fmt_money, formatdate, getdate, date_diff
|
||||
from frappe.utils import cstr, flt, fmt_money, formatdate
|
||||
from frappe import msgprint, _, scrub
|
||||
from erpnext.setup.utils import get_company_currency
|
||||
from erpnext.controllers.accounts_controller import AccountsController
|
||||
from erpnext.accounts.utils import get_balance_on
|
||||
|
||||
from erpnext.accounts.utils import get_balance_on, get_account_currency
|
||||
from erpnext.setup.utils import get_company_currency
|
||||
from erpnext.accounts.party import get_party_account
|
||||
|
||||
class JournalEntry(AccountsController):
|
||||
def __init__(self, arg1, arg2=None):
|
||||
@@ -26,6 +26,8 @@ class JournalEntry(AccountsController):
|
||||
self.validate_party()
|
||||
self.validate_cheque_info()
|
||||
self.validate_entries_for_advance()
|
||||
self.validate_multi_currency()
|
||||
self.set_amounts_in_company_currency()
|
||||
self.validate_debit_and_credit()
|
||||
self.validate_against_jv()
|
||||
self.validate_reference_doc()
|
||||
@@ -35,7 +37,9 @@ class JournalEntry(AccountsController):
|
||||
self.validate_expense_claim()
|
||||
self.validate_credit_debit_note()
|
||||
self.validate_empty_accounts_table()
|
||||
self.set_title()
|
||||
self.set_account_and_party_balance()
|
||||
if not self.title:
|
||||
self.title = self.get_title()
|
||||
|
||||
def on_submit(self):
|
||||
self.check_credit_limit()
|
||||
@@ -43,8 +47,8 @@ class JournalEntry(AccountsController):
|
||||
self.update_advance_paid()
|
||||
self.update_expense_claim()
|
||||
|
||||
def set_title(self):
|
||||
self.title = self.pay_to_recd_from or self.accounts[0].account
|
||||
def get_title(self):
|
||||
return self.pay_to_recd_from or self.accounts[0].account
|
||||
|
||||
def update_advance_paid(self):
|
||||
advance_paid = frappe._dict()
|
||||
@@ -144,6 +148,7 @@ class JournalEntry(AccountsController):
|
||||
|
||||
self.reference_totals = {}
|
||||
self.reference_types = {}
|
||||
self.reference_accounts = {}
|
||||
|
||||
for d in self.get("accounts"):
|
||||
if not d.reference_type:
|
||||
@@ -151,8 +156,8 @@ class JournalEntry(AccountsController):
|
||||
if not d.reference_name:
|
||||
d.reference_type = None
|
||||
if d.reference_type and d.reference_name and (d.reference_type in field_dict.keys()):
|
||||
dr_or_cr = "credit" if d.reference_type in ("Sales Order", "Sales Invoice") \
|
||||
else "debit"
|
||||
dr_or_cr = "credit_in_account_currency" \
|
||||
if d.reference_type in ("Sales Order", "Sales Invoice") else "debit_in_account_currency"
|
||||
|
||||
# check debit or credit type Sales / Purchase Order
|
||||
if d.reference_type=="Sales Order" and flt(d.debit) > 0:
|
||||
@@ -166,10 +171,14 @@ class JournalEntry(AccountsController):
|
||||
self.reference_totals[d.reference_name] = 0.0
|
||||
self.reference_totals[d.reference_name] += flt(d.get(dr_or_cr))
|
||||
self.reference_types[d.reference_name] = d.reference_type
|
||||
self.reference_accounts[d.reference_name] = d.account
|
||||
|
||||
against_voucher = frappe.db.get_value(d.reference_type, d.reference_name,
|
||||
[scrub(dt) for dt in field_dict.get(d.reference_type)])
|
||||
|
||||
if not against_voucher:
|
||||
frappe.throw(_("Row {0}: Invalid reference {1}").format(d.idx, d.reference_name))
|
||||
|
||||
# check if party and account match
|
||||
if d.reference_type in ("Sales Invoice", "Purchase Invoice"):
|
||||
if (against_voucher[0] != d.party or against_voucher[1] != d.account):
|
||||
@@ -191,23 +200,31 @@ class JournalEntry(AccountsController):
|
||||
"""Validate totals, stopped and docstatus for orders"""
|
||||
for reference_name, total in self.reference_totals.iteritems():
|
||||
reference_type = self.reference_types[reference_name]
|
||||
account = self.reference_accounts[reference_name]
|
||||
|
||||
if reference_type in ("Sales Order", "Purchase Order"):
|
||||
voucher_properties = frappe.db.get_value(reference_type, reference_name,
|
||||
["docstatus", "per_billed", "status", "advance_paid", "base_grand_total"])
|
||||
order = frappe.db.get_value(reference_type, reference_name,
|
||||
["docstatus", "per_billed", "status", "advance_paid",
|
||||
"base_grand_total", "grand_total", "currency"], as_dict=1)
|
||||
|
||||
if voucher_properties[0] != 1:
|
||||
if order.docstatus != 1:
|
||||
frappe.throw(_("{0} {1} is not submitted").format(reference_type, reference_name))
|
||||
|
||||
if flt(voucher_properties[1]) >= 100:
|
||||
if flt(order.per_billed) >= 100:
|
||||
frappe.throw(_("{0} {1} is fully billed").format(reference_type, reference_name))
|
||||
|
||||
if cstr(voucher_properties[2]) == "Stopped":
|
||||
if cstr(order.status) == "Stopped":
|
||||
frappe.throw(_("{0} {1} is stopped").format(reference_type, reference_name))
|
||||
|
||||
if flt(voucher_properties[4]) < (flt(voucher_properties[3]) + total):
|
||||
account_currency = get_account_currency(account)
|
||||
if account_currency == self.company_currency:
|
||||
voucher_total = order.base_grand_total
|
||||
else:
|
||||
voucher_total = order.grand_total
|
||||
|
||||
if flt(voucher_total) < (flt(order.advance_paid) + total):
|
||||
frappe.throw(_("Advance paid against {0} {1} cannot be greater \
|
||||
than Grand Total {2}").format(reference_type, reference_name, voucher_properties[4]))
|
||||
than Grand Total {2}").format(reference_type, reference_name, voucher_total))
|
||||
|
||||
def validate_invoices(self):
|
||||
"""Validate totals and docstatus for invoices"""
|
||||
@@ -215,15 +232,15 @@ class JournalEntry(AccountsController):
|
||||
reference_type = self.reference_types[reference_name]
|
||||
|
||||
if reference_type in ("Sales Invoice", "Purchase Invoice"):
|
||||
voucher_properties = frappe.db.get_value(reference_type, reference_name,
|
||||
["docstatus", "outstanding_amount"])
|
||||
invoice = frappe.db.get_value(reference_type, reference_name,
|
||||
["docstatus", "outstanding_amount"], as_dict=1)
|
||||
|
||||
if voucher_properties[0] != 1:
|
||||
if invoice.docstatus != 1:
|
||||
frappe.throw(_("{0} {1} is not submitted").format(reference_type, reference_name))
|
||||
|
||||
if total and flt(voucher_properties[1]) < total:
|
||||
frappe.throw(_("Payment against {0} {1} cannot be greater \
|
||||
than Outstanding Amount {2}").format(reference_type, reference_name, voucher_properties[1]))
|
||||
if total and flt(invoice.outstanding_amount) < total:
|
||||
frappe.throw(_("Payment against {0} {1} cannot be greater than Outstanding Amount {2}")
|
||||
.format(reference_type, reference_name, invoice.outstanding_amount))
|
||||
|
||||
def set_against_account(self):
|
||||
accounts_debited, accounts_credited = [], []
|
||||
@@ -237,13 +254,12 @@ class JournalEntry(AccountsController):
|
||||
|
||||
def validate_debit_and_credit(self):
|
||||
self.total_debit, self.total_credit, self.difference = 0, 0, 0
|
||||
|
||||
for d in self.get("accounts"):
|
||||
if d.debit and d.credit:
|
||||
frappe.throw(_("You cannot credit and debit same account at the same time"))
|
||||
|
||||
self.total_debit = flt(self.total_debit) + flt(d.debit, self.precision("debit", "accounts"))
|
||||
self.total_credit = flt(self.total_credit) + flt(d.credit, self.precision("credit", "accounts"))
|
||||
self.total_debit = flt(self.total_debit) + flt(d.debit, d.precision("debit"))
|
||||
self.total_credit = flt(self.total_credit) + flt(d.credit, d.precision("credit"))
|
||||
|
||||
self.difference = flt(self.total_debit, self.precision("total_debit")) - \
|
||||
flt(self.total_credit, self.precision("total_credit"))
|
||||
@@ -252,6 +268,39 @@ class JournalEntry(AccountsController):
|
||||
frappe.throw(_("Total Debit must be equal to Total Credit. The difference is {0}")
|
||||
.format(self.difference))
|
||||
|
||||
def validate_multi_currency(self):
|
||||
alternate_currency = []
|
||||
for d in self.get("accounts"):
|
||||
account = frappe.db.get_value("Account", d.account, ["account_currency", "account_type"], as_dict=1)
|
||||
d.account_currency = account.account_currency or self.company_currency
|
||||
d.account_type = account.account_type
|
||||
|
||||
if d.account_currency!=self.company_currency and d.account_currency not in alternate_currency:
|
||||
alternate_currency.append(d.account_currency)
|
||||
|
||||
if alternate_currency:
|
||||
if not self.multi_currency:
|
||||
frappe.throw(_("Please check Multi Currency option to allow accounts with other currency"))
|
||||
|
||||
self.set_exchange_rate()
|
||||
|
||||
def set_amounts_in_company_currency(self):
|
||||
for d in self.get("accounts"):
|
||||
d.debit = flt(flt(d.debit_in_account_currency)*flt(d.exchange_rate), d.precision("debit"))
|
||||
d.credit = flt(flt(d.credit_in_account_currency)*flt(d.exchange_rate), d.precision("credit"))
|
||||
|
||||
def set_exchange_rate(self):
|
||||
for d in self.get("accounts"):
|
||||
if d.account_currency == self.company_currency:
|
||||
d.exchange_rate = 1
|
||||
elif not d.exchange_rate or d.account_type=="Bank" or \
|
||||
(d.reference_type in ("Sales Invoice", "Purchase Invoice") and d.reference_name):
|
||||
d.exchange_rate = get_exchange_rate(d.account, d.account_currency, self.company,
|
||||
d.reference_type, d.reference_name, d.debit, d.credit, d.exchange_rate)
|
||||
|
||||
if not d.exchange_rate:
|
||||
frappe.throw(_("Row {0}: Exchange Rate is mandatory").format(d.idx))
|
||||
|
||||
def create_remarks(self):
|
||||
r = []
|
||||
if self.cheque_no:
|
||||
@@ -260,15 +309,13 @@ class JournalEntry(AccountsController):
|
||||
else:
|
||||
msgprint(_("Please enter Reference date"), raise_exception=frappe.MandatoryError)
|
||||
|
||||
company_currency = get_company_currency(self.company)
|
||||
|
||||
for d in self.get('accounts'):
|
||||
if d.reference_type=="Sales Invoice" and d.credit:
|
||||
r.append(_("{0} against Sales Invoice {1}").format(fmt_money(flt(d.credit), currency = company_currency), \
|
||||
r.append(_("{0} against Sales Invoice {1}").format(fmt_money(flt(d.credit), currency = self.company_currency), \
|
||||
d.reference_name))
|
||||
|
||||
if d.reference_type=="Sales Order" and d.credit:
|
||||
r.append(_("{0} against Sales Order {1}").format(fmt_money(flt(d.credit), currency = company_currency), \
|
||||
r.append(_("{0} against Sales Order {1}").format(fmt_money(flt(d.credit), currency = self.company_currency), \
|
||||
d.reference_name))
|
||||
|
||||
if d.reference_type == "Purchase Invoice" and d.debit:
|
||||
@@ -276,11 +323,11 @@ class JournalEntry(AccountsController):
|
||||
from `tabPurchase Invoice` where name=%s""", d.reference_name)
|
||||
if bill_no and bill_no[0][0] and bill_no[0][0].lower().strip() \
|
||||
not in ['na', 'not applicable', 'none']:
|
||||
r.append(_('{0} against Bill {1} dated {2}').format(fmt_money(flt(d.debit), currency=company_currency), bill_no[0][0],
|
||||
r.append(_('{0} against Bill {1} dated {2}').format(fmt_money(flt(d.debit), currency=self.company_currency), bill_no[0][0],
|
||||
bill_no[0][1] and formatdate(bill_no[0][1].strftime('%Y-%m-%d'))))
|
||||
|
||||
if d.reference_type == "Purchase Order" and d.debit:
|
||||
r.append(_("{0} against Purchase Order {1}").format(fmt_money(flt(d.credit), currency = company_currency), \
|
||||
r.append(_("{0} against Purchase Order {1}").format(fmt_money(flt(d.credit), currency = self.company_currency), \
|
||||
d.reference_name))
|
||||
|
||||
if self.user_remark:
|
||||
@@ -301,10 +348,9 @@ class JournalEntry(AccountsController):
|
||||
self.set_total_amount(d.debit or d.credit)
|
||||
|
||||
def set_total_amount(self, amt):
|
||||
company_currency = get_company_currency(self.company)
|
||||
self.total_amount = amt
|
||||
from frappe.utils import money_in_words
|
||||
self.total_amount_in_words = money_in_words(amt, company_currency)
|
||||
self.total_amount_in_words = money_in_words(amt, self.company_currency)
|
||||
|
||||
def make_gl_entries(self, cancel=0, adv_adj=0):
|
||||
from erpnext.accounts.general_ledger import make_gl_entries
|
||||
@@ -318,8 +364,11 @@ class JournalEntry(AccountsController):
|
||||
"party_type": d.party_type,
|
||||
"party": d.party,
|
||||
"against": d.against_account,
|
||||
"debit": flt(d.debit, self.precision("debit", "accounts")),
|
||||
"credit": flt(d.credit, self.precision("credit", "accounts")),
|
||||
"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": self.remark,
|
||||
@@ -338,21 +387,22 @@ class JournalEntry(AccountsController):
|
||||
diff = flt(self.difference, self.precision("difference"))
|
||||
|
||||
# If any row without amount, set the diff on that row
|
||||
for d in self.get('accounts'):
|
||||
if not d.credit and not d.debit and diff != 0:
|
||||
if diff>0:
|
||||
d.credit = diff
|
||||
elif diff<0:
|
||||
d.debit = diff
|
||||
flag = 1
|
||||
if diff:
|
||||
blank_row = None
|
||||
for d in self.get('accounts'):
|
||||
if not d.credit_in_account_currency and not d.debit_in_account_currency and diff != 0:
|
||||
blank_row = d
|
||||
|
||||
# Set the diff in a new row
|
||||
if flag == 0 and diff != 0:
|
||||
jd = self.append('accounts', {})
|
||||
if not blank_row:
|
||||
blank_row = self.append('accounts', {})
|
||||
|
||||
blank_row.exchange_rate = 1
|
||||
if diff>0:
|
||||
jd.credit = abs(diff)
|
||||
blank_row.credit_in_account_currency = diff
|
||||
blank_row.credit = diff
|
||||
elif diff<0:
|
||||
jd.debit = abs(diff)
|
||||
blank_row.debit_in_account_currency = abs(diff)
|
||||
blank_row.debit = abs(diff)
|
||||
|
||||
self.validate_debit_and_credit()
|
||||
|
||||
@@ -427,6 +477,20 @@ 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)
|
||||
|
||||
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, voucher_type, mode_of_payment=None):
|
||||
from erpnext.accounts.doctype.sales_invoice.sales_invoice import get_bank_cash_account
|
||||
@@ -439,143 +503,135 @@ def get_default_bank_cash_account(company, voucher_type, mode_of_payment=None):
|
||||
if voucher_type=="Bank Entry":
|
||||
account = frappe.db.get_value("Company", company, "default_bank_account")
|
||||
if not account:
|
||||
account = frappe.db.get_value("Account", {"company": company, "account_type": "Bank", "is_group": 0})
|
||||
account = frappe.db.get_value("Account",
|
||||
{"company": company, "account_type": "Bank", "is_group": 0})
|
||||
elif voucher_type=="Cash Entry":
|
||||
account = frappe.db.get_value("Company", company, "default_cash_account")
|
||||
if not account:
|
||||
account = frappe.db.get_value("Account", {"company": company, "account_type": "Cash", "is_group": 0})
|
||||
account = frappe.db.get_value("Account",
|
||||
{"company": company, "account_type": "Cash", "is_group": 0})
|
||||
|
||||
if account:
|
||||
account_details = frappe.db.get_value("Account", account,
|
||||
["account_currency", "account_type"], as_dict=1)
|
||||
return {
|
||||
"account": account,
|
||||
"balance": get_balance_on(account)
|
||||
"balance": get_balance_on(account),
|
||||
"account_currency": account_details.account_currency,
|
||||
"account_type": account_details.account_type
|
||||
}
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_payment_entry_from_sales_invoice(sales_invoice):
|
||||
"""Returns new Journal Entry document as dict for given Sales Invoice"""
|
||||
from erpnext.accounts.utils import get_balance_on
|
||||
si = frappe.get_doc("Sales Invoice", sales_invoice)
|
||||
jv = get_payment_entry(si)
|
||||
jv.remark = 'Payment received against Sales Invoice {0}. {1}'.format(si.name, si.remarks)
|
||||
|
||||
# credit customer
|
||||
jv.get("accounts")[0].account = si.debit_to
|
||||
jv.get("accounts")[0].party_type = "Customer"
|
||||
jv.get("accounts")[0].party = si.customer
|
||||
jv.get("accounts")[0].balance = get_balance_on(si.debit_to)
|
||||
jv.get("accounts")[0].party_balance = get_balance_on(party=si.customer, party_type="Customer")
|
||||
jv.get("accounts")[0].credit = si.outstanding_amount
|
||||
jv.get("accounts")[0].reference_type = si.doctype
|
||||
jv.get("accounts")[0].reference_name = si.name
|
||||
|
||||
# debit bank
|
||||
jv.get("accounts")[1].debit = si.outstanding_amount
|
||||
|
||||
return jv.as_dict()
|
||||
|
||||
def get_payment_entry_against_order(dt, dn):
|
||||
ref_doc = frappe.get_doc(dt, dn)
|
||||
|
||||
if flt(ref_doc.per_billed, 2) > 0:
|
||||
frappe.throw(_("Can only make payment against unbilled {0}").format(dt))
|
||||
|
||||
if dt == "Sales Order":
|
||||
party_type = "Customer"
|
||||
amount_field_party = "credit_in_account_currency"
|
||||
amount_field_bank = "debit_in_account_currency"
|
||||
else:
|
||||
party_type = "Supplier"
|
||||
amount_field_party = "debit_in_account_currency"
|
||||
amount_field_bank = "credit_in_account_currency"
|
||||
|
||||
party_account = get_party_account(party_type, ref_doc.get(party_type.lower()), ref_doc.company)
|
||||
party_account_currency = get_account_currency(party_account)
|
||||
|
||||
if party_account_currency == ref_doc.company_currency:
|
||||
amount = flt(ref_doc.base_grand_total) - flt(ref_doc.advance_paid)
|
||||
else:
|
||||
amount = flt(ref_doc.grand_total) - flt(ref_doc.advance_paid)
|
||||
|
||||
return get_payment_entry(ref_doc, {
|
||||
"party_type": party_type,
|
||||
"party_account": party_account,
|
||||
"party_account_currency": party_account_currency,
|
||||
"amount_field_party": amount_field_party,
|
||||
"amount_field_bank": amount_field_bank,
|
||||
"amount": amount,
|
||||
"remarks": 'Advance Payment received against {0} {1}'.format(dt, dn),
|
||||
"is_advance": "Yes"
|
||||
})
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_payment_entry_from_purchase_invoice(purchase_invoice):
|
||||
"""Returns new Journal Entry document as dict for given Purchase Invoice"""
|
||||
pi = frappe.get_doc("Purchase Invoice", purchase_invoice)
|
||||
jv = get_payment_entry(pi)
|
||||
jv.remark = 'Payment against Purchase Invoice {0}. {1}'.format(pi.name, pi.remarks)
|
||||
def get_payment_entry_against_invoice(dt, dn):
|
||||
ref_doc = frappe.get_doc(dt, dn)
|
||||
if dt == "Sales Invoice":
|
||||
party_type = "Customer"
|
||||
party_account = ref_doc.debit_to
|
||||
amount_field_party = "credit_in_account_currency"
|
||||
amount_field_bank = "debit_in_account_currency"
|
||||
else:
|
||||
party_type = "Supplier"
|
||||
party_account = ref_doc.credit_to
|
||||
amount_field_party = "debit_in_account_currency"
|
||||
amount_field_bank = "credit_in_account_currency"
|
||||
|
||||
return get_payment_entry(ref_doc, {
|
||||
"party_type": party_type,
|
||||
"party_account": party_account,
|
||||
"party_account_currency": ref_doc.party_account_currency,
|
||||
"amount_field_party": amount_field_party,
|
||||
"amount_field_bank": amount_field_bank,
|
||||
"amount": ref_doc.outstanding_amount,
|
||||
"remarks": 'Payment received against {0} {1}. {2}'.format(dt, dn, ref_doc.remarks),
|
||||
"is_advance": "No"
|
||||
})
|
||||
|
||||
def get_payment_entry(ref_doc, args):
|
||||
cost_center = frappe.db.get_value("Company", ref_doc.company, "cost_center")
|
||||
exchange_rate = get_exchange_rate(args.get("party_account"), args.get("party_account_currency"),
|
||||
ref_doc.company, ref_doc.doctype, ref_doc.name)
|
||||
|
||||
# credit supplier
|
||||
jv.get("accounts")[0].account = pi.credit_to
|
||||
jv.get("accounts")[0].party_type = "Supplier"
|
||||
jv.get("accounts")[0].party = pi.supplier
|
||||
jv.get("accounts")[0].balance = get_balance_on(pi.credit_to)
|
||||
jv.get("accounts")[0].party_balance = get_balance_on(party=pi.supplier, party_type="Supplier")
|
||||
jv.get("accounts")[0].debit = pi.outstanding_amount
|
||||
jv.get("accounts")[0].reference_type = pi.doctype
|
||||
jv.get("accounts")[0].reference_name = pi.name
|
||||
|
||||
# credit bank
|
||||
jv.get("accounts")[1].credit = pi.outstanding_amount
|
||||
|
||||
return jv.as_dict()
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_payment_entry_from_sales_order(sales_order):
|
||||
"""Returns new Journal Entry document as dict for given Sales Order"""
|
||||
from erpnext.accounts.utils import get_balance_on
|
||||
from erpnext.accounts.party import get_party_account
|
||||
so = frappe.get_doc("Sales Order", sales_order)
|
||||
|
||||
if flt(so.per_billed, 2) != 0.0:
|
||||
frappe.throw(_("Can only make payment against unbilled Sales Order"))
|
||||
|
||||
jv = get_payment_entry(so)
|
||||
jv.remark = 'Advance payment received against Sales Order {0}.'.format(so.name)
|
||||
party_account = get_party_account(so.company, so.customer, "Customer")
|
||||
|
||||
amount = flt(so.base_grand_total) - flt(so.advance_paid)
|
||||
|
||||
# credit customer
|
||||
jv.get("accounts")[0].account = party_account
|
||||
jv.get("accounts")[0].party_type = "Customer"
|
||||
jv.get("accounts")[0].party = so.customer
|
||||
jv.get("accounts")[0].balance = get_balance_on(party_account)
|
||||
jv.get("accounts")[0].party_balance = get_balance_on(party=so.customer, party_type="Customer")
|
||||
jv.get("accounts")[0].credit = amount
|
||||
jv.get("accounts")[0].reference_type = so.doctype
|
||||
jv.get("accounts")[0].reference_name = so.name
|
||||
jv.get("accounts")[0].is_advance = "Yes"
|
||||
|
||||
# debit bank
|
||||
jv.get("accounts")[1].debit = amount
|
||||
|
||||
return jv.as_dict()
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_payment_entry_from_purchase_order(purchase_order):
|
||||
"""Returns new Journal Entry document as dict for given Sales Order"""
|
||||
from erpnext.accounts.utils import get_balance_on
|
||||
from erpnext.accounts.party import get_party_account
|
||||
po = frappe.get_doc("Purchase Order", purchase_order)
|
||||
|
||||
if flt(po.per_billed, 2) != 0.0:
|
||||
frappe.throw(_("Can only make payment against unbilled Sales Order"))
|
||||
|
||||
jv = get_payment_entry(po)
|
||||
jv.remark = 'Advance payment made against Purchase Order {0}.'.format(po.name)
|
||||
party_account = get_party_account(po.company, po.supplier, "Supplier")
|
||||
|
||||
amount = flt(po.base_grand_total) - flt(po.advance_paid)
|
||||
|
||||
# credit customer
|
||||
jv.get("accounts")[0].account = party_account
|
||||
jv.get("accounts")[0].party_type = "Supplier"
|
||||
jv.get("accounts")[0].party = po.supplier
|
||||
jv.get("accounts")[0].balance = get_balance_on(party_account)
|
||||
jv.get("accounts")[0].party_balance = get_balance_on(party=po.supplier, party_type="Supplier")
|
||||
jv.get("accounts")[0].debit = amount
|
||||
jv.get("accounts")[0].reference_type = po.doctype
|
||||
jv.get("accounts")[0].reference_name = po.name
|
||||
jv.get("accounts")[0].is_advance = "Yes"
|
||||
|
||||
# debit bank
|
||||
jv.get("accounts")[1].credit = amount
|
||||
|
||||
return jv.as_dict()
|
||||
|
||||
def get_payment_entry(doc):
|
||||
bank_account = get_default_bank_cash_account(doc.company, "Bank Entry")
|
||||
|
||||
jv = frappe.new_doc('Journal Entry')
|
||||
jv.voucher_type = 'Bank Entry'
|
||||
jv.company = doc.company
|
||||
jv.fiscal_year = doc.fiscal_year
|
||||
|
||||
jv.append("accounts")
|
||||
d2 = jv.append("accounts")
|
||||
jv = frappe.new_doc("Journal Entry")
|
||||
jv.update({
|
||||
"voucher_type": "Bank Entry",
|
||||
"company": ref_doc.company,
|
||||
"remark": args.get("remarks")
|
||||
})
|
||||
|
||||
party_row = jv.append("accounts", {
|
||||
"account": args.get("party_account"),
|
||||
"party_type": args.get("party_type"),
|
||||
"party": ref_doc.get(args.get("party_type").lower()),
|
||||
"cost_center": cost_center,
|
||||
"account_type": frappe.db.get_value("Account", args.get("party_account"), "account_type"),
|
||||
"account_currency": args.get("party_account_currency") or \
|
||||
get_account_currency(args.get("party_account")),
|
||||
"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"),
|
||||
"reference_type": ref_doc.doctype,
|
||||
"reference_name": ref_doc.name
|
||||
})
|
||||
|
||||
bank_row = jv.append("accounts")
|
||||
bank_account = get_default_bank_cash_account(ref_doc.company, "Bank Entry")
|
||||
if bank_account:
|
||||
d2.account = bank_account["account"]
|
||||
d2.balance = bank_account["balance"]
|
||||
bank_row.update(bank_account)
|
||||
bank_row.exchange_rate = get_exchange_rate(bank_account["account"],
|
||||
bank_account["account_currency"], ref_doc.company)
|
||||
|
||||
bank_row.cost_center = cost_center
|
||||
|
||||
if bank_row.account_currency == args.get("party_account_currency"):
|
||||
bank_row.set(args.get("amount_field_bank"), args.get("amount"))
|
||||
else:
|
||||
bank_row.set(args.get("amount_field_bank"), args.get("amount") * exchange_rate)
|
||||
|
||||
return jv
|
||||
# set multi currency check
|
||||
if party_row.account_currency != ref_doc.company_currency \
|
||||
or (bank_row.account_currency and bank_row.account_currency != ref_doc.company_currency):
|
||||
jv.multi_currency = 1
|
||||
|
||||
jv.set_amounts_in_company_currency()
|
||||
|
||||
return jv.as_dict()
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_opening_accounts(company):
|
||||
@@ -599,27 +655,37 @@ def get_outstanding(args):
|
||||
if not frappe.has_permission("Account"):
|
||||
frappe.msgprint(_("No Permission"), raise_exception=1)
|
||||
args = eval(args)
|
||||
company_currency = get_company_currency(args.get("company"))
|
||||
|
||||
if args.get("doctype") == "Journal Entry":
|
||||
condition = " and party=%(party)s" if args.get("party") else ""
|
||||
|
||||
against_jv_amount = frappe.db.sql("""
|
||||
select sum(ifnull(debit, 0)) - sum(ifnull(credit, 0))
|
||||
select sum(ifnull(debit_in_account_currency, 0)) - sum(ifnull(credit_in_account_currency, 0))
|
||||
from `tabJournal Entry Account` where parent=%(docname)s and account=%(account)s {0}
|
||||
and ifnull(reference_type, '')=''""".format(condition), args)
|
||||
|
||||
against_jv_amount = flt(against_jv_amount[0][0]) if against_jv_amount else 0
|
||||
amount_field = "credit_in_account_currency" if against_jv_amount > 0 else "debit_in_account_currency"
|
||||
return {
|
||||
("credit" if against_jv_amount > 0 else "debit"): abs(against_jv_amount)
|
||||
amount_field: abs(against_jv_amount)
|
||||
}
|
||||
elif args.get("doctype") == "Sales Invoice":
|
||||
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", args["docname"], "outstanding_amount"))
|
||||
elif args.get("doctype") in ("Sales Invoice", "Purchase Invoice"):
|
||||
invoice = frappe.db.get_value(args["doctype"], args["docname"],
|
||||
["outstanding_amount", "conversion_rate"], as_dict=1)
|
||||
|
||||
exchange_rate = invoice.conversion_rate if (args.get("account_currency") != company_currency) else 1
|
||||
|
||||
if args["doctype"] == "Sales Invoice":
|
||||
amount_field = "credit_in_account_currency" \
|
||||
if flt(invoice.outstanding_amount) > 0 else "debit_in_account_currency"
|
||||
else:
|
||||
amount_field = "debit_in_account_currency" \
|
||||
if flt(invoice.outstanding_amount) > 0 else "credit_in_account_currency"
|
||||
|
||||
return {
|
||||
("credit" if outstanding_amount > 0 else "debit"): abs(outstanding_amount)
|
||||
}
|
||||
elif args.get("doctype") == "Purchase Invoice":
|
||||
outstanding_amount = flt(frappe.db.get_value("Purchase Invoice", args["docname"], "outstanding_amount"))
|
||||
return {
|
||||
("debit" if outstanding_amount > 0 else "credit"): abs(outstanding_amount)
|
||||
amount_field: abs(flt(invoice.outstanding_amount)),
|
||||
"exchange_rate": exchange_rate
|
||||
}
|
||||
|
||||
@frappe.whitelist()
|
||||
@@ -627,8 +693,7 @@ def get_party_account_and_balance(company, party_type, party):
|
||||
if not frappe.has_permission("Account"):
|
||||
frappe.msgprint(_("No Permission"), raise_exception=1)
|
||||
|
||||
from erpnext.accounts.party import get_party_account
|
||||
account = get_party_account(company, party, party_type)
|
||||
account = get_party_account(party_type, party, company)
|
||||
|
||||
account_balance = get_balance_on(account=account)
|
||||
party_balance = get_balance_on(party_type=party_type, party=party)
|
||||
@@ -640,14 +705,69 @@ def get_party_account_and_balance(company, party_type, party):
|
||||
}
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_account_balance_and_party_type(account, date):
|
||||
def get_account_balance_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."""
|
||||
if not frappe.has_permission("Account"):
|
||||
frappe.msgprint(_("No Permission"), raise_exception=1)
|
||||
|
||||
account_type = frappe.db.get_value("Account", account, "account_type")
|
||||
return {
|
||||
"balance": get_balance_on(account, date),
|
||||
"party_type": {"Receivable":"Customer", "Payable":"Supplier"}.get(account_type, "")
|
||||
}
|
||||
company_currency = get_company_currency(company)
|
||||
account_details = frappe.db.get_value("Account", account, ["account_type", "account_currency"], as_dict=1)
|
||||
|
||||
if account_details.account_type == "Receivable":
|
||||
party_type = "Customer"
|
||||
elif account_details.account_type == "Payable":
|
||||
party_type = "Supplier"
|
||||
else:
|
||||
party_type = ""
|
||||
|
||||
grid_values = {
|
||||
"balance": get_balance_on(account, date),
|
||||
"party_type": party_type,
|
||||
"account_type": account_details.account_type,
|
||||
"account_currency": account_details.account_currency or company_currency,
|
||||
"exchange_rate": get_exchange_rate(account, account_details.account_currency,
|
||||
company, debit=debit, credit=credit, exchange_rate=exchange_rate)
|
||||
}
|
||||
return grid_values
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_exchange_rate(account, account_currency=None, company=None,
|
||||
reference_type=None, reference_name=None, debit=None, credit=None, exchange_rate=None):
|
||||
from erpnext.setup.utils import get_exchange_rate
|
||||
account_details = frappe.db.get_value("Account", account,
|
||||
["account_type", "root_type", "account_currency", "company"], as_dict=1)
|
||||
|
||||
if not company:
|
||||
company = account_details.company
|
||||
|
||||
if not account_currency:
|
||||
account_currency = account_details.account_currency
|
||||
|
||||
company_currency = get_company_currency(company)
|
||||
|
||||
if account_currency != company_currency:
|
||||
if reference_type in ("Sales Invoice", "Purchase Invoice") and reference_name:
|
||||
exchange_rate = frappe.db.get_value(reference_type, reference_name, "conversion_rate")
|
||||
|
||||
elif account_details and account_details.account_type == "Bank" and \
|
||||
((account_details.root_type == "Asset" and flt(credit) > 0) or
|
||||
(account_details.root_type == "Liability" and debit)):
|
||||
exchange_rate = get_average_exchange_rate(account)
|
||||
|
||||
if not exchange_rate and account_currency:
|
||||
exchange_rate = get_exchange_rate(account_currency, company_currency)
|
||||
|
||||
else:
|
||||
exchange_rate = 1
|
||||
|
||||
# don't return None or 0 as it is multipled with a value and that value could be lost
|
||||
return exchange_rate or 1
|
||||
|
||||
def get_average_exchange_rate(account):
|
||||
exchange_rate = 0
|
||||
bank_balance_in_account_currency = get_balance_on(account)
|
||||
if bank_balance_in_account_currency:
|
||||
bank_balance_in_company_currency = get_balance_on(account, in_account_currency=False)
|
||||
exchange_rate = bank_balance_in_company_currency / bank_balance_in_account_currency
|
||||
|
||||
return exchange_rate
|
||||
|
||||
@@ -5,6 +5,7 @@ from __future__ import unicode_literals
|
||||
import unittest, frappe
|
||||
from frappe.utils import flt
|
||||
from erpnext.accounts.utils import get_actual_expense, BudgetError, get_fiscal_year
|
||||
from erpnext.exceptions import InvalidAccountCurrency
|
||||
|
||||
|
||||
class TestJournalEntry(unittest.TestCase):
|
||||
@@ -101,7 +102,7 @@ class TestJournalEntry(unittest.TestCase):
|
||||
self.set_total_expense_zero("2013-02-28")
|
||||
|
||||
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
||||
"_Test Account Bank Account - _TC", 40000, "_Test Cost Center - _TC", submit=True)
|
||||
"_Test Bank - _TC", 40000, "_Test Cost Center - _TC", submit=True)
|
||||
|
||||
self.assertTrue(frappe.db.get_value("GL Entry",
|
||||
{"voucher_type": "Journal Entry", "voucher_no": jv.name}))
|
||||
@@ -112,7 +113,7 @@ class TestJournalEntry(unittest.TestCase):
|
||||
self.set_total_expense_zero("2013-02-28")
|
||||
|
||||
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
||||
"_Test Account Bank Account - _TC", 40000, "_Test Cost Center - _TC")
|
||||
"_Test Bank - _TC", 40000, "_Test Cost Center - _TC")
|
||||
|
||||
self.assertRaises(BudgetError, jv.submit)
|
||||
|
||||
@@ -126,7 +127,7 @@ class TestJournalEntry(unittest.TestCase):
|
||||
self.set_total_expense_zero("2013-02-28")
|
||||
|
||||
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
||||
"_Test Account Bank Account - _TC", 150000, "_Test Cost Center - _TC")
|
||||
"_Test Bank - _TC", 150000, "_Test Cost Center - _TC")
|
||||
|
||||
self.assertRaises(BudgetError, jv.submit)
|
||||
|
||||
@@ -136,13 +137,13 @@ class TestJournalEntry(unittest.TestCase):
|
||||
self.set_total_expense_zero("2013-02-28")
|
||||
|
||||
jv1 = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
||||
"_Test Account Bank Account - _TC", 20000, "_Test Cost Center - _TC", submit=True)
|
||||
"_Test Bank - _TC", 20000, "_Test Cost Center - _TC", submit=True)
|
||||
|
||||
self.assertTrue(frappe.db.get_value("GL Entry",
|
||||
{"voucher_type": "Journal Entry", "voucher_no": jv1.name}))
|
||||
|
||||
jv2 = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
||||
"_Test Account Bank Account - _TC", 20000, "_Test Cost Center - _TC", submit=True)
|
||||
"_Test Bank - _TC", 20000, "_Test Cost Center - _TC", submit=True)
|
||||
|
||||
self.assertTrue(frappe.db.get_value("GL Entry",
|
||||
{"voucher_type": "Journal Entry", "voucher_no": jv2.name}))
|
||||
@@ -165,32 +166,112 @@ class TestJournalEntry(unittest.TestCase):
|
||||
def set_total_expense_zero(self, posting_date):
|
||||
existing_expense = self.get_actual_expense(posting_date)
|
||||
make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
||||
"_Test Account Bank Account - _TC", -existing_expense, "_Test Cost Center - _TC", submit=True)
|
||||
"_Test Bank - _TC", -existing_expense, "_Test Cost Center - _TC", submit=True)
|
||||
|
||||
def make_journal_entry(account1, account2, amount, cost_center=None, submit=False):
|
||||
def test_multi_currency(self):
|
||||
jv = make_journal_entry("_Test Bank USD - _TC",
|
||||
"_Test Bank - _TC", 100, exchange_rate=50, save=False)
|
||||
|
||||
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.assertTrue(gl_entries)
|
||||
|
||||
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": {
|
||||
"account_currency": "INR",
|
||||
"debit": 0,
|
||||
"debit_in_account_currency": 0,
|
||||
"credit": 5000,
|
||||
"credit_in_account_currency": 5000
|
||||
}
|
||||
}
|
||||
|
||||
for field in ("account_currency", "debit", "debit_in_account_currency", "credit", "credit_in_account_currency"):
|
||||
for i, gle in enumerate(gl_entries):
|
||||
self.assertEquals(expected_values[gle.account][field], gle[field])
|
||||
|
||||
# cancel
|
||||
jv.cancel()
|
||||
|
||||
gle = frappe.db.sql("""select name from `tabGL Entry`
|
||||
where voucher_type='Sales Invoice' and voucher_no=%s""", jv.name)
|
||||
|
||||
self.assertFalse(gle)
|
||||
|
||||
def test_disallow_change_in_account_currency_for_a_party(self):
|
||||
# create jv in USD
|
||||
jv = make_journal_entry("_Test Bank USD - _TC",
|
||||
"_Test Receivable USD - _TC", 100, save=False)
|
||||
|
||||
jv.accounts[1].update({
|
||||
"party_type": "Customer",
|
||||
"party": "_Test Customer USD"
|
||||
})
|
||||
|
||||
jv.submit()
|
||||
|
||||
# create jv in USD, but account currency in INR
|
||||
jv = make_journal_entry("_Test Bank - _TC",
|
||||
"_Test Receivable - _TC", 100, save=False)
|
||||
|
||||
jv.accounts[1].update({
|
||||
"party_type": "Customer",
|
||||
"party": "_Test Customer USD"
|
||||
})
|
||||
|
||||
self.assertRaises(InvalidAccountCurrency, jv.submit)
|
||||
|
||||
# back in USD
|
||||
jv = make_journal_entry("_Test Bank USD - _TC",
|
||||
"_Test Receivable USD - _TC", 100, save=False)
|
||||
|
||||
jv.accounts[1].update({
|
||||
"party_type": "Customer",
|
||||
"party": "_Test Customer USD"
|
||||
})
|
||||
|
||||
jv.submit()
|
||||
|
||||
def make_journal_entry(account1, account2, amount, cost_center=None, exchange_rate=1, save=True, submit=False):
|
||||
jv = frappe.new_doc("Journal Entry")
|
||||
jv.posting_date = "2013-02-14"
|
||||
jv.company = "_Test Company"
|
||||
jv.fiscal_year = "_Test Fiscal Year 2013"
|
||||
jv.user_remark = "test"
|
||||
|
||||
jv.multi_currency = 1
|
||||
jv.set("accounts", [
|
||||
{
|
||||
"account": account1,
|
||||
"cost_center": cost_center,
|
||||
"debit": amount if amount > 0 else 0,
|
||||
"credit": abs(amount) if amount < 0 else 0,
|
||||
"debit_in_account_currency": amount if amount > 0 else 0,
|
||||
"credit_in_account_currency": abs(amount) if amount < 0 else 0,
|
||||
"exchange_rate": exchange_rate
|
||||
}, {
|
||||
"account": account2,
|
||||
"cost_center": cost_center,
|
||||
"credit": amount if amount > 0 else 0,
|
||||
"debit": abs(amount) if amount < 0 else 0,
|
||||
"credit_in_account_currency": amount if amount > 0 else 0,
|
||||
"debit_in_account_currency": abs(amount) if amount < 0 else 0,
|
||||
"exchange_rate": exchange_rate
|
||||
}
|
||||
])
|
||||
jv.insert()
|
||||
if save or submit:
|
||||
jv.insert()
|
||||
|
||||
if submit:
|
||||
jv.submit()
|
||||
if submit:
|
||||
jv.submit()
|
||||
|
||||
return jv
|
||||
|
||||
|
||||
@@ -9,15 +9,15 @@
|
||||
"account": "_Test Receivable - _TC",
|
||||
"party_type": "Customer",
|
||||
"party": "_Test Customer",
|
||||
"credit": 400.0,
|
||||
"debit": 0.0,
|
||||
"credit_in_account_currency": 400.0,
|
||||
"debit_in_account_currency": 0.0,
|
||||
"doctype": "Journal Entry Account",
|
||||
"parentfield": "accounts"
|
||||
},
|
||||
{
|
||||
"account": "_Test Account Bank Account - _TC",
|
||||
"credit": 0.0,
|
||||
"debit": 400.0,
|
||||
"account": "_Test Bank - _TC",
|
||||
"credit_in_account_currency": 0.0,
|
||||
"debit_in_account_currency": 400.0,
|
||||
"doctype": "Journal Entry Account",
|
||||
"parentfield": "accounts"
|
||||
}
|
||||
@@ -40,15 +40,15 @@
|
||||
"account": "_Test Payable - _TC",
|
||||
"party_type": "Supplier",
|
||||
"party": "_Test Supplier",
|
||||
"credit": 0.0,
|
||||
"debit": 400.0,
|
||||
"credit_in_account_currency": 0.0,
|
||||
"debit_in_account_currency": 400.0,
|
||||
"doctype": "Journal Entry Account",
|
||||
"parentfield": "accounts"
|
||||
},
|
||||
{
|
||||
"account": "_Test Account Bank Account - _TC",
|
||||
"credit": 400.0,
|
||||
"debit": 0.0,
|
||||
"account": "_Test Bank - _TC",
|
||||
"credit_in_account_currency": 400.0,
|
||||
"debit_in_account_currency": 0.0,
|
||||
"doctype": "Journal Entry Account",
|
||||
"parentfield": "accounts"
|
||||
}
|
||||
@@ -71,16 +71,16 @@
|
||||
"account": "_Test Receivable - _TC",
|
||||
"party_type": "Customer",
|
||||
"party": "_Test Customer",
|
||||
"credit": 0.0,
|
||||
"debit": 400.0,
|
||||
"credit_in_account_currency": 0.0,
|
||||
"debit_in_account_currency": 400.0,
|
||||
"doctype": "Journal Entry Account",
|
||||
"parentfield": "accounts"
|
||||
},
|
||||
{
|
||||
"account": "Sales - _TC",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"credit": 400.0,
|
||||
"debit": 0.0,
|
||||
"credit_in_account_currency": 400.0,
|
||||
"debit_in_account_currency": 0.0,
|
||||
"doctype": "Journal Entry Account",
|
||||
"parentfield": "accounts"
|
||||
}
|
||||
|
||||
@@ -34,6 +34,28 @@
|
||||
"unique": 0,
|
||||
"width": "250px"
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "account_type",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Account Type",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -48,7 +70,7 @@
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "balance",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "Company:company:default_currency",
|
||||
"options": "account_currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
@@ -162,7 +184,7 @@
|
||||
"in_list_view": 0,
|
||||
"label": "Party Balance",
|
||||
"no_copy": 0,
|
||||
"options": "Company:company:default_currency",
|
||||
"options": "account_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
@@ -173,6 +195,96 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"collapsible_depends_on": "",
|
||||
"depends_on": "",
|
||||
"fieldname": "currency_section",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Currency",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "account_currency",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Account Currency",
|
||||
"no_copy": 1,
|
||||
"options": "Currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "column_break_10",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "exchange_rate",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Exchange Rate",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "6",
|
||||
"print_hide": 1,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -198,20 +310,44 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "debit",
|
||||
"fieldname": "debit_in_account_currency",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Debit",
|
||||
"label": "Debit in Account Currency",
|
||||
"no_copy": 0,
|
||||
"options": "account_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "debit",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Debit in Company Currency",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "debit",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@@ -242,20 +378,44 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "credit",
|
||||
"fieldname": "credit_in_account_currency",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Credit",
|
||||
"label": "Credit in Account Currency",
|
||||
"no_copy": 0,
|
||||
"options": "account_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "credit",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Credit in Company Currency",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "credit",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@@ -405,7 +565,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2015-08-17 02:11:33.991361",
|
||||
"modified": "2015-10-20 12:10:22.203395",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Journal Entry Account",
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Master",
|
||||
"document_type": "Setup",
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
@@ -65,7 +65,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-09-07 15:51:26",
|
||||
"modified": "2015-10-02 07:38:57.318104",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Mode of Payment",
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
# test_records = frappe.get_test_records('Mode of Payment')
|
||||
|
||||
class TestModeofPayment(unittest.TestCase):
|
||||
pass
|
||||
@@ -63,7 +63,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2015-01-06 17:26:57.053474",
|
||||
"modified": "2015-10-02 07:38:57.388194",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Mode of Payment Account",
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-02-05 05:11:41.429491",
|
||||
"modified": "2015-10-02 07:38:57.594541",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Monthly Distribution",
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2015-02-19 01:07:00.800015",
|
||||
"modified": "2015-10-02 07:38:57.670950",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Monthly Distribution Percentage",
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2015-08-26 11:23:22.917738",
|
||||
"modified": "2015-10-02 07:38:59.582533",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Party Account",
|
||||
|
||||
@@ -44,7 +44,7 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
refresh: function() {
|
||||
this.frm.disable_save();
|
||||
},
|
||||
@@ -74,21 +74,7 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext
|
||||
doc: me.frm.doc,
|
||||
method: 'get_unreconciled_entries',
|
||||
callback: function(r, rt) {
|
||||
var invoices = [];
|
||||
|
||||
$.each(me.frm.doc.invoices || [], function(i, row) {
|
||||
if (row.invoice_number && !inList(invoices, row.invoice_number))
|
||||
invoices.push(row.invoice_number);
|
||||
});
|
||||
|
||||
frappe.meta.get_docfield("Payment Reconciliation Payment", "invoice_number",
|
||||
me.frm.doc.name).options = invoices.join("\n");
|
||||
|
||||
$.each(me.frm.doc.payments || [], function(i, p) {
|
||||
if(!inList(invoices, cstr(p.invoice_number))) p.invoice_number = null;
|
||||
});
|
||||
|
||||
refresh_field("payments");
|
||||
me.set_invoice_options();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -98,8 +84,29 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext
|
||||
var me = this;
|
||||
return this.frm.call({
|
||||
doc: me.frm.doc,
|
||||
method: 'reconcile'
|
||||
method: 'reconcile',
|
||||
callback: function(r, rt) {
|
||||
me.set_invoice_options();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
set_invoice_options: function() {
|
||||
var invoices = [];
|
||||
|
||||
$.each(me.frm.doc.invoices || [], function(i, row) {
|
||||
if (row.invoice_number && !inList(invoices, row.invoice_number))
|
||||
invoices.push(row.invoice_type + " | " + row.invoice_number);
|
||||
});
|
||||
|
||||
frappe.meta.get_docfield("Payment Reconciliation Payment", "invoice_number",
|
||||
me.frm.doc.name).options = invoices.join("\n");
|
||||
|
||||
$.each(me.frm.doc.payments || [], function(i, p) {
|
||||
if(!inList(invoices, cstr(p.invoice_number))) p.invoice_number = null;
|
||||
});
|
||||
|
||||
refresh_field("payments");
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@@ -130,7 +130,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Column Break",
|
||||
"label": "",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
@@ -362,7 +362,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 1,
|
||||
"istable": 0,
|
||||
"modified": "2015-02-05 05:11:42.105088",
|
||||
"modified": "2015-09-21 03:41:24.672227",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Reconciliation",
|
||||
|
||||
@@ -3,11 +3,8 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
from frappe.utils import flt
|
||||
|
||||
from frappe import msgprint, _
|
||||
|
||||
from frappe.model.document import Document
|
||||
|
||||
class PaymentReconciliation(Document):
|
||||
@@ -17,7 +14,8 @@ class PaymentReconciliation(Document):
|
||||
|
||||
def get_jv_entries(self):
|
||||
self.check_mandatory_to_fetch()
|
||||
dr_or_cr = "credit" if self.party_type == "Customer" else "debit"
|
||||
dr_or_cr = "credit_in_account_currency" if self.party_type == "Customer" \
|
||||
else "debit_in_account_currency"
|
||||
|
||||
cond = self.check_condition(dr_or_cr)
|
||||
|
||||
@@ -68,7 +66,7 @@ class PaymentReconciliation(Document):
|
||||
def get_invoice_entries(self):
|
||||
#Fetch JVs, Sales and Purchase Invoices for 'invoices' to reconcile against
|
||||
non_reconciled_invoices = []
|
||||
dr_or_cr = "debit" if self.party_type == "Customer" else "credit"
|
||||
dr_or_cr = "debit_in_account_currency" if self.party_type == "Customer" else "credit_in_account_currency"
|
||||
cond = self.check_condition(dr_or_cr)
|
||||
|
||||
invoice_list = frappe.db.sql("""
|
||||
@@ -80,6 +78,11 @@ class PaymentReconciliation(Document):
|
||||
where
|
||||
party_type = %(party_type)s and party = %(party)s
|
||||
and account = %(account)s and {dr_or_cr} > 0 {cond}
|
||||
and (CASE
|
||||
WHEN voucher_type = 'Journal Entry'
|
||||
THEN ifnull(against_voucher, '') = ''
|
||||
ELSE 1=1
|
||||
END)
|
||||
group by voucher_type, voucher_no
|
||||
""".format(**{
|
||||
"cond": cond,
|
||||
@@ -101,13 +104,15 @@ class PaymentReconciliation(Document):
|
||||
and account = %(account)s and {0} > 0
|
||||
and against_voucher_type = %(against_voucher_type)s
|
||||
and ifnull(against_voucher, '') = %(against_voucher)s
|
||||
""".format("credit" if self.party_type == "Customer" else "debit"), {
|
||||
"party_type": self.party_type,
|
||||
"party": self.party,
|
||||
"account": self.receivable_payable_account,
|
||||
"against_voucher_type": d.voucher_type,
|
||||
"against_voucher": d.voucher_no
|
||||
})
|
||||
""".format("credit_in_account_currency" if self.party_type == "Customer"
|
||||
else "debit_in_account_currency"), {
|
||||
"party_type": self.party_type,
|
||||
"party": self.party,
|
||||
"account": self.receivable_payable_account,
|
||||
"against_voucher_type": d.voucher_type,
|
||||
"against_voucher": d.voucher_no
|
||||
}
|
||||
)
|
||||
|
||||
payment_amount = payment_amount[0][0] if payment_amount else 0
|
||||
|
||||
@@ -135,12 +140,18 @@ class PaymentReconciliation(Document):
|
||||
ent.outstanding_amount = e.get('outstanding_amount')
|
||||
|
||||
def reconcile(self, args):
|
||||
for e in self.get('payments'):
|
||||
e.invoice_type = None
|
||||
if e.invoice_number and " | " in e.invoice_number:
|
||||
e.invoice_type, e.invoice_number = e.invoice_number.split(" | ")
|
||||
|
||||
self.get_invoice_entries()
|
||||
self.validate_invoice()
|
||||
dr_or_cr = "credit" if self.party_type == "Customer" else "debit"
|
||||
dr_or_cr = "credit_in_account_currency" if self.party_type == "Customer" \
|
||||
else "debit_in_account_currency"
|
||||
lst = []
|
||||
for e in self.get('payments'):
|
||||
if e.invoice_type and e.invoice_number and e.allocated_amount:
|
||||
if e.invoice_number and e.allocated_amount:
|
||||
lst.append({
|
||||
'voucher_no' : e.journal_entry,
|
||||
'voucher_detail_no' : e.voucher_detail_number,
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Column Break",
|
||||
"label": "",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
@@ -144,7 +144,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2014-07-18 12:20:51.269974",
|
||||
"modified": "2015-10-16 06:14:07.460813",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Reconciliation Invoice",
|
||||
|
||||
@@ -124,7 +124,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Column Break",
|
||||
"label": "",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
@@ -135,51 +135,6 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "allocated_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Allocated amount",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"default": "Sales Invoice",
|
||||
"fieldname": "invoice_type",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Invoice Type",
|
||||
"no_copy": 0,
|
||||
"options": "\nSales Invoice\nPurchase Invoice\nJournal Entry",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -202,6 +157,28 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "allocated_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Allocated amount",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -243,27 +220,6 @@
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "col_break2",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Column Break",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
@@ -273,7 +229,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2014-12-25 16:26:48.345281",
|
||||
"modified": "2015-10-02 07:38:59.835936",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Reconciliation Payment",
|
||||
|
||||
@@ -25,8 +25,14 @@ frappe.ui.form.on("Payment Tool", "onload", function(frm) {
|
||||
});
|
||||
|
||||
frm.set_query("against_voucher_type", "vouchers", function() {
|
||||
if (frm.doc.party_type=="Customer") {
|
||||
var doctypes = ["Sales Order", "Sales Invoice", "Journal Entry"];
|
||||
} else {
|
||||
var doctypes = ["Purchase Order", "Purchase Invoice", "Journal Entry"];
|
||||
}
|
||||
|
||||
return {
|
||||
filters: {"name": ["in", ["Sales Invoice", "Purchase Invoice", "Journal Entry", "Sales Order", "Purchase Order"]]}
|
||||
filters: { "name": ["in", doctypes] }
|
||||
};
|
||||
});
|
||||
});
|
||||
@@ -55,6 +61,25 @@ frappe.ui.form.on("Payment Tool", "party", function(frm) {
|
||||
}
|
||||
})
|
||||
|
||||
frappe.ui.form.on("Payment Tool", "party_account", function(frm) {
|
||||
if(frm.doc.party_account) {
|
||||
frm.call({
|
||||
method: "frappe.client.get_value",
|
||||
args: {
|
||||
doctype: "Account",
|
||||
fieldname: "account_currency",
|
||||
filters: { name: frm.doc.party_account },
|
||||
},
|
||||
callback: function(r, rt) {
|
||||
if(r.message) {
|
||||
frm.set_value("party_account_currency", r.message.account_currency);
|
||||
erpnext.payment_tool.check_mandatory_to_set_button(frm);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
frappe.ui.form.on("Payment Tool", "company", function(frm) {
|
||||
erpnext.payment_tool.check_mandatory_to_set_button(frm);
|
||||
});
|
||||
@@ -63,10 +88,6 @@ frappe.ui.form.on("Payment Tool", "received_or_paid", function(frm) {
|
||||
erpnext.payment_tool.check_mandatory_to_set_button(frm);
|
||||
});
|
||||
|
||||
frappe.ui.form.on("Payment Tool", "party", function(frm) {
|
||||
erpnext.payment_tool.check_mandatory_to_set_button(frm);
|
||||
});
|
||||
|
||||
// Fetch bank/cash account based on payment mode
|
||||
frappe.ui.form.on("Payment Tool", "payment_mode", function(frm) {
|
||||
return frappe.call({
|
||||
@@ -75,7 +96,7 @@ frappe.ui.form.on("Payment Tool", "payment_mode", function(frm) {
|
||||
"mode_of_payment": frm.doc.payment_mode,
|
||||
"company": frm.doc.company
|
||||
},
|
||||
callback: function(r, rt) {
|
||||
callback: function(r, rt) {
|
||||
if(r.message) {
|
||||
cur_frm.set_value("payment_account", r.message['account']);
|
||||
}
|
||||
@@ -120,6 +141,10 @@ frappe.ui.form.on("Payment Tool", "get_outstanding_vouchers", function(frm) {
|
||||
c.against_voucher_no = d.voucher_no;
|
||||
c.total_amount = d.invoice_amount;
|
||||
c.outstanding_amount = d.outstanding_amount;
|
||||
|
||||
if (frm.doc.set_payment_amount) {
|
||||
c.payment_amount = d.outstanding_amount;
|
||||
}
|
||||
});
|
||||
}
|
||||
refresh_field("vouchers");
|
||||
@@ -130,41 +155,63 @@ frappe.ui.form.on("Payment Tool", "get_outstanding_vouchers", function(frm) {
|
||||
});
|
||||
|
||||
// validate against_voucher_type
|
||||
frappe.ui.form.on("Payment Tool Detail", "against_voucher_type", function(frm) {
|
||||
erpnext.payment_tool.validate_against_voucher(frm);
|
||||
frappe.ui.form.on("Payment Tool Detail", "against_voucher_type", function(frm, cdt, cdn) {
|
||||
var row = frappe.model.get_doc(cdt, cdn);
|
||||
erpnext.payment_tool.validate_against_voucher(frm, row);
|
||||
});
|
||||
|
||||
erpnext.payment_tool.validate_against_voucher = function(frm) {
|
||||
$.each(frm.doc.vouchers || [], function(i, row) {
|
||||
erpnext.payment_tool.validate_against_voucher = function(frm, row) {
|
||||
var _validate = function(i, row) {
|
||||
if (!row.against_voucher_type) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(frm.doc.party_type=="Customer"
|
||||
&& !in_list(["Sales Order", "Sales Invoice", "Journal Entry"], row.against_voucher_type)) {
|
||||
frappe.model.set_value(row.doctype, row.name, "against_voucher_type", "");
|
||||
frappe.throw(__("Against Voucher Type must be one of Sales Order, Sales Invoice or Journal Entry"))
|
||||
frappe.msgprint(__("Against Voucher Type must be one of Sales Order, Sales Invoice or Journal Entry"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if(frm.doc.party_type=="Supplier"
|
||||
&& !in_list(["Purchase Order", "Purchase Invoice", "Journal Entry"], row.against_voucher_type)) {
|
||||
frappe.model.set_value(row.doctype, row.name, "against_voucher_type", "");
|
||||
frappe.throw(__("Against Voucher Type must be one of Purchase Order, Purchase Invoice or Journal Entry"))
|
||||
frappe.msgprint(__("Against Voucher Type must be one of Purchase Order, Purchase Invoice or Journal Entry"));
|
||||
return false;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
if (row) {
|
||||
_validate(0, row);
|
||||
} else {
|
||||
$.each(frm.doc.vouchers || [], _validate);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// validate against_voucher_type
|
||||
frappe.ui.form.on("Payment Tool Detail", "against_voucher_no", function(frm, cdt, cdn) {
|
||||
var row = locals[cdt][cdn];
|
||||
if (!row.against_voucher_no) {
|
||||
return;
|
||||
}
|
||||
|
||||
frappe.call({
|
||||
method: 'erpnext.accounts.doctype.payment_tool.payment_tool.get_against_voucher_amount',
|
||||
args: {
|
||||
"against_voucher_type": row.against_voucher_type,
|
||||
"against_voucher_no": row.against_voucher_no
|
||||
"against_voucher_no": row.against_voucher_no,
|
||||
"party_account": frm.doc.party_account,
|
||||
"company": frm.doc.company
|
||||
},
|
||||
callback: function(r) {
|
||||
if(!r.exc) {
|
||||
$.each(r.message, function(k, v) {
|
||||
frappe.model.set_value(cdt, cdn, k, v);
|
||||
});
|
||||
|
||||
frappe.model.set_value(cdt, cdn, "payment_amount", r.message.outstanding_amount);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -187,7 +234,7 @@ erpnext.payment_tool.set_total_payment_amount = function(frm) {
|
||||
} else {
|
||||
if(row.payment_amount < 0)
|
||||
msgprint(__("Row {0}: Payment amount can not be negative", [row.idx]));
|
||||
else if(row.payment_amount >= row.outstanding_amount)
|
||||
else if(row.payment_amount > row.outstanding_amount)
|
||||
msgprint(__("Row {0}: Payment Amount cannot be greater than Outstanding Amount", [__(row.idx)]));
|
||||
|
||||
frappe.model.set_value(row.doctype, row.name, "payment_amount", 0.0);
|
||||
|
||||
@@ -106,7 +106,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Column Break 1",
|
||||
"label": "",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
@@ -162,6 +162,51 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "party_account_currency",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Party Account Currency",
|
||||
"no_copy": 1,
|
||||
"options": "Currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "set_payment_amount",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Set Payment Amount = Outstanding Amount",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -306,6 +351,7 @@
|
||||
"in_list_view": 0,
|
||||
"label": "Total Payment Amount",
|
||||
"no_copy": 0,
|
||||
"options": "party_account_currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
@@ -450,7 +496,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 1,
|
||||
"istable": 0,
|
||||
"modified": "2015-06-05 11:17:33.843334",
|
||||
"modified": "2015-10-01 09:43:24.199025",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Tool",
|
||||
|
||||
@@ -3,10 +3,11 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe import _, scrub
|
||||
from frappe.utils import flt
|
||||
from frappe.model.document import Document
|
||||
import json
|
||||
from erpnext.accounts.utils import get_account_currency
|
||||
|
||||
class PaymentTool(Document):
|
||||
def make_journal_entry(self):
|
||||
@@ -33,15 +34,18 @@ class PaymentTool(Document):
|
||||
d1.party_type = self.party_type
|
||||
d1.party = self.party
|
||||
d1.balance = get_balance_on(self.party_account)
|
||||
d1.set("debit" if self.received_or_paid=="Paid" else "credit", flt(v.payment_amount))
|
||||
d1.set("debit_in_account_currency" if self.received_or_paid=="Paid" \
|
||||
else "credit_in_account_currency", flt(v.payment_amount))
|
||||
d1.set("reference_type", v.against_voucher_type)
|
||||
d1.set("reference_name", v.against_voucher_no)
|
||||
d1.set('is_advance', 'Yes' if v.against_voucher_type in ['Sales Order', 'Purchase Order'] else 'No')
|
||||
total_payment_amount = flt(total_payment_amount) + flt(d1.debit) - flt(d1.credit)
|
||||
total_payment_amount = flt(total_payment_amount) + \
|
||||
flt(d1.debit_in_account_currency) - flt(d1.credit_in_account_currency)
|
||||
|
||||
d2 = jv.append("accounts")
|
||||
d2.account = self.payment_account
|
||||
d2.set('debit' if total_payment_amount < 0 else 'credit', abs(total_payment_amount))
|
||||
d2.set('debit_in_account_currency' if total_payment_amount < 0 \
|
||||
else 'credit_in_account_currency', abs(total_payment_amount))
|
||||
if self.payment_account:
|
||||
d2.balance = get_balance_on(self.payment_account)
|
||||
|
||||
@@ -56,10 +60,13 @@ def get_outstanding_vouchers(args):
|
||||
|
||||
args = json.loads(args)
|
||||
|
||||
party_account_currency = get_account_currency(args.get("party_account"))
|
||||
company_currency = frappe.db.get_value("Company", args.get("company"), "default_currency")
|
||||
|
||||
if args.get("party_type") == "Customer" and args.get("received_or_paid") == "Received":
|
||||
amount_query = "ifnull(debit, 0) - ifnull(credit, 0)"
|
||||
amount_query = "ifnull(debit_in_account_currency, 0) - ifnull(credit_in_account_currency, 0)"
|
||||
elif args.get("party_type") == "Supplier" and args.get("received_or_paid") == "Paid":
|
||||
amount_query = "ifnull(credit, 0) - ifnull(debit, 0)"
|
||||
amount_query = "ifnull(credit_in_account_currency, 0) - ifnull(debit_in_account_currency, 0)"
|
||||
else:
|
||||
frappe.throw(_("Please enter the Against Vouchers manually"))
|
||||
|
||||
@@ -68,27 +75,34 @@ def get_outstanding_vouchers(args):
|
||||
args.get("party_type"), args.get("party"))
|
||||
|
||||
# Get all SO / PO which are not fully billed or aginst which full advance not paid
|
||||
orders_to_be_billed = get_orders_to_be_billed(args.get("party_type"), args.get("party"))
|
||||
orders_to_be_billed = get_orders_to_be_billed(args.get("party_type"), args.get("party"),
|
||||
party_account_currency, company_currency)
|
||||
return outstanding_invoices + orders_to_be_billed
|
||||
|
||||
def get_orders_to_be_billed(party_type, party):
|
||||
def get_orders_to_be_billed(party_type, party, party_account_currency, company_currency):
|
||||
voucher_type = 'Sales Order' if party_type == "Customer" else 'Purchase Order'
|
||||
|
||||
ref_field = "base_grand_total" if party_account_currency == company_currency else "grand_total"
|
||||
|
||||
orders = frappe.db.sql("""
|
||||
select
|
||||
name as voucher_no,
|
||||
ifnull(base_grand_total, 0) as invoice_amount,
|
||||
(ifnull(base_grand_total, 0) - ifnull(advance_paid, 0)) as outstanding_amount,
|
||||
ifnull({ref_field}, 0) as invoice_amount,
|
||||
(ifnull({ref_field}, 0) - ifnull(advance_paid, 0)) as outstanding_amount,
|
||||
transaction_date as posting_date
|
||||
from
|
||||
`tab%s`
|
||||
`tab{voucher_type}`
|
||||
where
|
||||
%s = %s
|
||||
{party_type} = %s
|
||||
and docstatus = 1
|
||||
and ifnull(status, "") != "Stopped"
|
||||
and ifnull(base_grand_total, 0) > ifnull(advance_paid, 0)
|
||||
and ifnull({ref_field}, 0) > ifnull(advance_paid, 0)
|
||||
and abs(100 - ifnull(per_billed, 0)) > 0.01
|
||||
""" % (voucher_type, 'customer' if party_type == "Customer" else 'supplier', '%s'),
|
||||
party, as_dict = True)
|
||||
""".format(**{
|
||||
"ref_field": ref_field,
|
||||
"voucher_type": voucher_type,
|
||||
"party_type": scrub(party_type)
|
||||
}), party, as_dict = True)
|
||||
|
||||
order_list = []
|
||||
for d in orders:
|
||||
@@ -98,13 +112,19 @@ def get_orders_to_be_billed(party_type, party):
|
||||
return order_list
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_against_voucher_amount(against_voucher_type, against_voucher_no):
|
||||
def get_against_voucher_amount(against_voucher_type, against_voucher_no, party_account, company):
|
||||
party_account_currency = get_account_currency(party_account)
|
||||
company_currency = frappe.db.get_value("Company", company, "default_currency")
|
||||
ref_field = "base_grand_total" if party_account_currency == company_currency else "grand_total"
|
||||
|
||||
if against_voucher_type in ["Sales Order", "Purchase Order"]:
|
||||
select_cond = "base_grand_total as total_amount, ifnull(base_grand_total, 0) - ifnull(advance_paid, 0) as outstanding_amount"
|
||||
select_cond = "{0} as total_amount, ifnull({0}, 0) - ifnull(advance_paid, 0) as outstanding_amount"\
|
||||
.format(ref_field)
|
||||
elif against_voucher_type in ["Sales Invoice", "Purchase Invoice"]:
|
||||
select_cond = "base_grand_total as total_amount, outstanding_amount"
|
||||
select_cond = "{0} as total_amount, outstanding_amount".format(ref_field)
|
||||
elif against_voucher_type == "Journal Entry":
|
||||
select_cond = "total_debit as total_amount"
|
||||
ref_field = "total_debit" if party_account_currency == company_currency else "total_debit/exchange_rate"
|
||||
select_cond = "{0} as total_amount".format(ref_field)
|
||||
|
||||
details = frappe.db.sql("""select {0} from `tab{1}` where name = %s"""
|
||||
.format(select_cond, against_voucher_type), against_voucher_no, as_dict=1)
|
||||
|
||||
@@ -39,7 +39,7 @@ class TestPaymentTool(unittest.TestCase):
|
||||
"party": "_Test Customer 3",
|
||||
"reference_type": "Sales Order",
|
||||
"reference_name": so2.name,
|
||||
"credit": 1000,
|
||||
"credit_in_account_currency": 1000,
|
||||
"is_advance": "Yes"
|
||||
})
|
||||
|
||||
@@ -67,7 +67,7 @@ class TestPaymentTool(unittest.TestCase):
|
||||
"party": "_Test Customer 3",
|
||||
"reference_type": si2.doctype,
|
||||
"reference_name": si2.name,
|
||||
"credit": 561.80
|
||||
"credit_in_account_currency": 561.80
|
||||
})
|
||||
|
||||
pi = self.create_voucher(pi_test_records[0], {
|
||||
@@ -91,7 +91,7 @@ class TestPaymentTool(unittest.TestCase):
|
||||
"party": "_Test Customer 3",
|
||||
"party_account": "_Test Receivable - _TC",
|
||||
"payment_mode": "Cheque",
|
||||
"payment_account": "_Test Account Bank Account - _TC",
|
||||
"payment_account": "_Test Bank - _TC",
|
||||
"reference_no": "123456",
|
||||
"reference_date": "2013-02-14"
|
||||
}
|
||||
@@ -117,10 +117,10 @@ class TestPaymentTool(unittest.TestCase):
|
||||
def create_against_jv(self, test_record, args):
|
||||
jv = frappe.copy_doc(test_record)
|
||||
jv.get("accounts")[0].update(args)
|
||||
if args.get("debit"):
|
||||
jv.get("accounts")[1].credit = args["debit"]
|
||||
elif args.get("credit"):
|
||||
jv.get("accounts")[1].debit = args["credit"]
|
||||
if args.get("debit_in_account_currency"):
|
||||
jv.get("accounts")[1].credit_in_account_currency = args["debit_in_account_currency"]
|
||||
elif args.get("credit_in_account_currency"):
|
||||
jv.get("accounts")[1].debit_in_account_currency = args["credit_in_account_currency"]
|
||||
|
||||
jv.insert()
|
||||
jv.submit()
|
||||
@@ -141,7 +141,8 @@ class TestPaymentTool(unittest.TestCase):
|
||||
outstanding_entries = get_outstanding_vouchers(json.dumps(args))
|
||||
|
||||
for d in outstanding_entries:
|
||||
self.assertEquals(flt(d.get("outstanding_amount"), 2), expected_outstanding.get(d.get("voucher_type"))[1])
|
||||
self.assertEquals(flt(d.get("outstanding_amount"), 2),
|
||||
expected_outstanding.get(d.get("voucher_type"))[1])
|
||||
|
||||
self.check_jv_entries(doc, outstanding_entries, expected_outstanding)
|
||||
|
||||
@@ -156,11 +157,10 @@ class TestPaymentTool(unittest.TestCase):
|
||||
paytool.total_payment_amount = 300
|
||||
|
||||
new_jv = paytool.make_journal_entry()
|
||||
|
||||
for jv_entry in new_jv.get("accounts"):
|
||||
if paytool.party_account == jv_entry.get("account") and paytool.party == jv_entry.get("party"):
|
||||
self.assertEquals(100.00,
|
||||
jv_entry.get("debit" if paytool.party_type=="Supplier" else "credit"))
|
||||
self.assertEquals(100.00, jv_entry.get("debit_in_account_currency"
|
||||
if paytool.party_type=="Supplier" else "credit_in_account_currency"))
|
||||
self.assertEquals(jv_entry.reference_name,
|
||||
expected_outstanding[jv_entry.reference_type][0])
|
||||
|
||||
@@ -170,4 +170,6 @@ class TestPaymentTool(unittest.TestCase):
|
||||
def clear_table_entries(self):
|
||||
frappe.db.sql("""delete from `tabGL Entry` where party in ("_Test Customer 3", "_Test Supplier 1")""")
|
||||
frappe.db.sql("""delete from `tabSales Order` where customer = "_Test Customer 3" """)
|
||||
frappe.db.sql("""delete from `tabSales Invoice` where customer = "_Test Customer 3" """)
|
||||
frappe.db.sql("""delete from `tabPurchase Order` where supplier = "_Test Supplier 1" """)
|
||||
frappe.db.sql("""delete from `tabPurchase Invoice` where supplier = "_Test Supplier 1" """)
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
"in_list_view": 1,
|
||||
"label": "Total Amount",
|
||||
"no_copy": 0,
|
||||
"options": "party_account_currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
@@ -108,6 +109,7 @@
|
||||
"in_list_view": 1,
|
||||
"label": "Outstanding Amount",
|
||||
"no_copy": 0,
|
||||
"options": "party_account_currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
@@ -129,6 +131,7 @@
|
||||
"in_list_view": 1,
|
||||
"label": "Payment Amount",
|
||||
"no_copy": 0,
|
||||
"options": "party_account_currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
@@ -146,7 +149,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2014-09-11 08:55:34.384017",
|
||||
"modified": "2015-10-02 07:38:59.950506",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Tool Detail",
|
||||
|
||||
@@ -13,7 +13,7 @@ cur_frm.fields_dict['closing_account_head'].get_query = function(doc, cdt, cdn)
|
||||
return{
|
||||
filters:{
|
||||
"company": doc.company,
|
||||
"report_type": "Balance Sheet",
|
||||
"root_type": "Liability",
|
||||
"freeze_account": "No",
|
||||
"is_group": 0
|
||||
}
|
||||
|
||||
@@ -194,29 +194,6 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "coa_help",
|
||||
"fieldtype": "HTML",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "CoA Help",
|
||||
"no_copy": 0,
|
||||
"oldfieldtype": "HTML",
|
||||
"options": "<a href=\"#!Accounts Browser/Account\">To manage Account Head, click here</a>",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -250,7 +227,7 @@
|
||||
"is_submittable": 1,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-02-05 05:11:42.268561",
|
||||
"modified": "2015-10-21 12:40:58.278256",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Period Closing Voucher",
|
||||
|
||||
@@ -5,6 +5,7 @@ from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.utils import flt
|
||||
from frappe import _
|
||||
from erpnext.accounts.utils import get_account_currency
|
||||
from erpnext.controllers.accounts_controller import AccountsController
|
||||
|
||||
class PeriodClosingVoucher(AccountsController):
|
||||
@@ -20,51 +21,75 @@ class PeriodClosingVoucher(AccountsController):
|
||||
where voucher_type = 'Period Closing Voucher' and voucher_no=%s""", self.name)
|
||||
|
||||
def validate_account_head(self):
|
||||
if frappe.db.get_value("Account", self.closing_account_head, "report_type") \
|
||||
!= "Balance Sheet":
|
||||
frappe.throw(_("Closing Account {0} must be of type 'Liability'").format(self.closing_account_head))
|
||||
closing_account_type = frappe.db.get_value("Account", self.closing_account_head, "root_type")
|
||||
|
||||
if closing_account_type != "Liability":
|
||||
frappe.throw(_("Closing Account {0} must be of type 'Liability'")
|
||||
.format(self.closing_account_head))
|
||||
|
||||
account_currency = get_account_currency(self.closing_account_head)
|
||||
company_currency = frappe.db.get_value("Company", self.company, "default_currency")
|
||||
if account_currency != company_currency:
|
||||
frappe.throw(_("Currency of the Closing Account must be {0}").format(company_currency))
|
||||
|
||||
def validate_posting_date(self):
|
||||
from erpnext.accounts.utils import get_fiscal_year
|
||||
from erpnext.accounts.utils import get_fiscal_year, validate_fiscal_year
|
||||
|
||||
validate_fiscal_year(self.posting_date, self.fiscal_year, label=_("Posting Date"), doc=self)
|
||||
|
||||
self.year_start_date = get_fiscal_year(self.posting_date, self.fiscal_year)[1]
|
||||
|
||||
pce = frappe.db.sql("""select name from `tabPeriod Closing Voucher`
|
||||
where posting_date > %s and fiscal_year = %s and docstatus = 1""",
|
||||
(self.posting_date, self.fiscal_year))
|
||||
if pce and pce[0][0]:
|
||||
frappe.throw(_("Another Period Closing Entry {0} has been made after {1}").format(pce[0][0], self.posting_date))
|
||||
|
||||
def get_pl_balances(self):
|
||||
"""Get balance for pl accounts"""
|
||||
return frappe.db.sql("""
|
||||
select t1.account, sum(ifnull(t1.debit,0))-sum(ifnull(t1.credit,0)) as balance
|
||||
from `tabGL Entry` t1, `tabAccount` t2
|
||||
where t1.account = t2.name and ifnull(t2.report_type, '') = 'Profit and Loss'
|
||||
and t2.docstatus < 2 and t2.company = %s
|
||||
and t1.posting_date between %s and %s
|
||||
group by t1.account
|
||||
""", (self.company, self.get("year_start_date"), self.posting_date), as_dict=1)
|
||||
frappe.throw(_("Another Period Closing Entry {0} has been made after {1}")
|
||||
.format(pce[0][0], self.posting_date))
|
||||
|
||||
def make_gl_entries(self):
|
||||
gl_entries = []
|
||||
net_pl_balance = 0
|
||||
pl_accounts = self.get_pl_balances()
|
||||
|
||||
for acc in pl_accounts:
|
||||
if flt(acc.balance):
|
||||
if flt(acc.balance_in_company_currency):
|
||||
gl_entries.append(self.get_gl_dict({
|
||||
"account": acc.account,
|
||||
"debit": abs(flt(acc.balance)) if flt(acc.balance) < 0 else 0,
|
||||
"credit": abs(flt(acc.balance)) if flt(acc.balance) > 0 else 0,
|
||||
"account_currency": acc.account_currency,
|
||||
"debit_in_account_currency": abs(flt(acc.balance_in_account_currency)) \
|
||||
if flt(acc.balance_in_account_currency) < 0 else 0,
|
||||
"debit": abs(flt(acc.balance_in_company_currency)) \
|
||||
if flt(acc.balance_in_company_currency) < 0 else 0,
|
||||
"credit_in_account_currency": abs(flt(acc.balance_in_account_currency)) \
|
||||
if flt(acc.balance_in_account_currency) > 0 else 0,
|
||||
"credit": abs(flt(acc.balance_in_company_currency)) \
|
||||
if flt(acc.balance_in_company_currency) > 0 else 0
|
||||
}))
|
||||
|
||||
net_pl_balance += flt(acc.balance)
|
||||
|
||||
net_pl_balance += flt(acc.balance_in_company_currency)
|
||||
|
||||
if net_pl_balance:
|
||||
gl_entries.append(self.get_gl_dict({
|
||||
"account": self.closing_account_head,
|
||||
"debit_in_account_currency": abs(net_pl_balance) if net_pl_balance > 0 else 0,
|
||||
"debit": abs(net_pl_balance) if net_pl_balance > 0 else 0,
|
||||
"credit_in_account_currency": abs(net_pl_balance) if net_pl_balance < 0 else 0,
|
||||
"credit": abs(net_pl_balance) if net_pl_balance < 0 else 0
|
||||
}))
|
||||
|
||||
|
||||
from erpnext.accounts.general_ledger import make_gl_entries
|
||||
make_gl_entries(gl_entries)
|
||||
|
||||
def get_pl_balances(self):
|
||||
"""Get balance for pl accounts"""
|
||||
return frappe.db.sql("""
|
||||
select
|
||||
t1.account, t2.account_currency, sum(ifnull(t1.debit_in_account_currency,0))-sum(ifnull(t1.credit_in_account_currency,0))
|
||||
as balance_in_account_currency,
|
||||
sum(ifnull(t1.debit,0))-sum(ifnull(t1.credit,0)) as balance_in_company_currency
|
||||
from `tabGL Entry` t1, `tabAccount` t2
|
||||
where t1.account = t2.name and ifnull(t2.report_type, '') = 'Profit and Loss'
|
||||
and t2.docstatus < 2 and t2.company = %s
|
||||
and t1.posting_date between %s and %s
|
||||
group by t1.account
|
||||
""", (self.company, self.get("year_start_date"), self.posting_date), as_dict=1)
|
||||
@@ -5,42 +5,74 @@
|
||||
from __future__ import unicode_literals
|
||||
import unittest
|
||||
import frappe
|
||||
from frappe.utils import flt
|
||||
from frappe.utils import flt, today
|
||||
from erpnext.accounts.utils import get_fiscal_year
|
||||
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
|
||||
|
||||
class TestPeriodClosingVoucher(unittest.TestCase):
|
||||
def test_closing_entry(self):
|
||||
make_journal_entry("_Test Account Bank Account - _TC", "Sales - _TC", 400,
|
||||
year_start_date = get_fiscal_year(today())[1]
|
||||
|
||||
make_journal_entry("_Test Bank - _TC", "Sales - _TC", 400,
|
||||
"_Test Cost Center - _TC", submit=True)
|
||||
|
||||
make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
||||
"_Test Account Bank Account - _TC", 600, "_Test Cost Center - _TC", submit=True)
|
||||
"_Test Bank - _TC", 600, "_Test Cost Center - _TC", submit=True)
|
||||
|
||||
random_expense_account = frappe.db.sql("""
|
||||
select t1.account,
|
||||
sum(ifnull(t1.debit,0))-sum(ifnull(t1.credit,0)) as balance,
|
||||
sum(ifnull(t1.debit_in_account_currency,0))-sum(ifnull(t1.credit_in_account_currency,0)) \
|
||||
as balance_in_account_currency
|
||||
from `tabGL Entry` t1, `tabAccount` t2
|
||||
where t1.account = t2.name and ifnull(t2.root_type, '') = 'Expense'
|
||||
and t2.docstatus < 2 and t2.company = '_Test Company'
|
||||
and t1.posting_date between %s and %s
|
||||
group by t1.account
|
||||
having sum(ifnull(t1.debit,0)) > sum(ifnull(t1.credit,0))
|
||||
limit 1""", (year_start_date, today()), as_dict=True)
|
||||
|
||||
profit_or_loss = frappe.db.sql("""select sum(ifnull(t1.debit,0))-sum(ifnull(t1.credit,0)) as balance
|
||||
from `tabGL Entry` t1, `tabAccount` t2
|
||||
where t1.account = t2.name and ifnull(t2.report_type, '') = 'Profit and Loss'
|
||||
and t2.docstatus < 2 and t2.company = '_Test Company'
|
||||
and t1.posting_date between '2013-01-01' and '2013-12-31'""")
|
||||
and t1.posting_date between %s and %s""", (year_start_date, today()))
|
||||
|
||||
profit_or_loss = flt(profit_or_loss[0][0]) if profit_or_loss else 0
|
||||
|
||||
pcv = self.make_period_closing_voucher()
|
||||
|
||||
gle_value = frappe.db.sql("""select ifnull(debit, 0) - ifnull(credit, 0)
|
||||
# Check value for closing account
|
||||
gle_amount_for_closing_account = frappe.db.sql("""select ifnull(debit, 0) - ifnull(credit, 0)
|
||||
from `tabGL Entry` where voucher_type='Period Closing Voucher' and voucher_no=%s
|
||||
and account = '_Test Account Reserves and Surplus - _TC'""", pcv.name)
|
||||
|
||||
gle_value = flt(gle_value[0][0]) if gle_value else 0
|
||||
gle_amount_for_closing_account = flt(gle_amount_for_closing_account[0][0]) \
|
||||
if gle_amount_for_closing_account else 0
|
||||
|
||||
self.assertEqual(gle_value, profit_or_loss)
|
||||
self.assertEqual(gle_amount_for_closing_account, profit_or_loss)
|
||||
|
||||
if random_expense_account:
|
||||
# Check posted value for teh above random_expense_account
|
||||
gle_for_random_expense_account = frappe.db.sql("""
|
||||
select ifnull(debit, 0) - ifnull(credit, 0) as amount,
|
||||
ifnull(debit_in_account_currency, 0) - ifnull(credit_in_account_currency, 0)
|
||||
as amount_in_account_currency
|
||||
from `tabGL Entry`
|
||||
where voucher_type='Period Closing Voucher' and voucher_no=%s and account =%s""",
|
||||
(pcv.name, random_expense_account[0].account), as_dict=True)
|
||||
|
||||
self.assertEqual(gle_for_random_expense_account[0].amount, -1*random_expense_account[0].balance)
|
||||
self.assertEqual(gle_for_random_expense_account[0].amount_in_account_currency,
|
||||
-1*random_expense_account[0].balance_in_account_currency)
|
||||
|
||||
def make_period_closing_voucher(self):
|
||||
pcv = frappe.get_doc({
|
||||
"doctype": "Period Closing Voucher",
|
||||
"closing_account_head": "_Test Account Reserves and Surplus - _TC",
|
||||
"company": "_Test Company",
|
||||
"fiscal_year": "_Test Fiscal Year 2013",
|
||||
"posting_date": "2013-12-31",
|
||||
"fiscal_year": get_fiscal_year(today())[0],
|
||||
"posting_date": today(),
|
||||
"remarks": "test"
|
||||
})
|
||||
pcv.insert()
|
||||
|
||||
@@ -622,7 +622,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-09-07 15:51:26",
|
||||
"modified": "2015-10-02 07:39:00.196535",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "POS Profile",
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Title",
|
||||
"no_copy": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
@@ -63,7 +63,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Apply On",
|
||||
"label": "Apply On",
|
||||
"no_copy": 0,
|
||||
"options": "\nItem Code\nItem Group\nBrand",
|
||||
"permlevel": 0,
|
||||
@@ -176,7 +176,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Priority",
|
||||
"label": "Priority",
|
||||
"no_copy": 0,
|
||||
"options": "\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20",
|
||||
"permlevel": 0,
|
||||
@@ -304,7 +304,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Applicable For",
|
||||
"label": "Applicable For",
|
||||
"no_copy": 0,
|
||||
"options": "\nCustomer\nCustomer Group\nTerritory\nSales Partner\nCampaign\nSupplier\nSupplier Type",
|
||||
"permlevel": 0,
|
||||
@@ -699,7 +699,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Price or Discount",
|
||||
"label": "Price or Discount",
|
||||
"no_copy": 0,
|
||||
"options": "\nPrice\nDiscount Percentage",
|
||||
"permlevel": 0,
|
||||
@@ -851,7 +851,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-08-13 14:58:29.194326",
|
||||
"modified": "2015-10-02 07:39:00.632196",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Pricing Rule",
|
||||
|
||||
@@ -175,7 +175,7 @@ def get_pricing_rules(args):
|
||||
if parent_groups:
|
||||
if allow_blank: parent_groups.append('')
|
||||
condition = " ifnull("+field+", '') in ('" + \
|
||||
"', '".join([d.replace("'", "\\'").replace('"', '\\"') for d in parent_groups])+"')"
|
||||
"', '".join([d.replace("'", "\\'").replace('"', '\\"').replace("%", "%%") for d in parent_groups])+"')"
|
||||
return condition
|
||||
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
|
||||
get_query_filters: {
|
||||
supplier: cur_frm.doc.supplier || undefined,
|
||||
docstatus: 1,
|
||||
status: ["!=", "Stopped"],
|
||||
status: ["not in", ["Stopped", "Closed"]],
|
||||
per_billed: ["<", 99.99],
|
||||
company: cur_frm.doc.company
|
||||
}
|
||||
@@ -52,6 +52,7 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
|
||||
get_query_filters: {
|
||||
supplier: cur_frm.doc.supplier || undefined,
|
||||
docstatus: 1,
|
||||
status: ["!=", "Closed"],
|
||||
company: cur_frm.doc.company
|
||||
}
|
||||
})
|
||||
@@ -75,8 +76,29 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
|
||||
me.apply_pricing_rule();
|
||||
})
|
||||
},
|
||||
|
||||
credit_to: function() {
|
||||
var me = this;
|
||||
if(this.frm.doc.credit_to) {
|
||||
me.frm.call({
|
||||
method: "frappe.client.get_value",
|
||||
args: {
|
||||
doctype: "Account",
|
||||
fieldname: "account_currency",
|
||||
filters: { name: me.frm.doc.credit_to },
|
||||
},
|
||||
callback: function(r, rt) {
|
||||
if(r.message) {
|
||||
me.frm.set_value("party_account_currency", r.message.account_currency);
|
||||
me.set_dynamic_labels();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
write_off_amount: function() {
|
||||
this.set_in_company_currency(this.frm.doc, ["write_off_amount"]);
|
||||
this.calculate_outstanding_amount();
|
||||
this.frm.refresh_fields();
|
||||
},
|
||||
@@ -114,9 +136,10 @@ cur_frm.script_manager.make(erpnext.accounts.PurchaseInvoice);
|
||||
|
||||
cur_frm.cscript.make_bank_entry = function() {
|
||||
return frappe.call({
|
||||
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_payment_entry_from_purchase_invoice",
|
||||
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_payment_entry_against_invoice",
|
||||
args: {
|
||||
"purchase_invoice": cur_frm.doc.name,
|
||||
"dt": "Purchase Invoice",
|
||||
"dn": cur_frm.doc.name
|
||||
},
|
||||
callback: function(r) {
|
||||
var doclist = frappe.model.sync(r.message);
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Title",
|
||||
"no_copy": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
@@ -41,7 +41,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Series",
|
||||
"label": "Series",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "naming_series",
|
||||
"oldfieldtype": "Select",
|
||||
@@ -576,7 +576,7 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "items",
|
||||
@@ -1048,7 +1048,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Apply Additional Discount On",
|
||||
"label": "Apply Additional Discount On",
|
||||
"no_copy": 0,
|
||||
"options": "\nGrand Total\nNet Total",
|
||||
"permlevel": 0,
|
||||
@@ -1266,30 +1266,6 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "total_amount_to_pay",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Total Amount To Pay",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "total_amount_to_pay",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -1304,7 +1280,7 @@
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "total_advance",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"options": "party_account_currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
@@ -1328,7 +1304,7 @@
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "outstanding_amount",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"options": "party_account_currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
@@ -1338,6 +1314,30 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"collapsible_depends_on": "write_off_amount",
|
||||
"depends_on": "grand_total",
|
||||
"fieldname": "write_off",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Write Off",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -1350,7 +1350,7 @@
|
||||
"in_list_view": 0,
|
||||
"label": "Write Off Amount",
|
||||
"no_copy": 1,
|
||||
"options": "Company:company:default_currency",
|
||||
"options": "currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 0,
|
||||
@@ -1360,6 +1360,50 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "base_write_off_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Write Off Amount (Company Currency)",
|
||||
"no_copy": 1,
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "column_break_61",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -1406,29 +1450,6 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "against_expense_account",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Against Expense Account",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "against_expense_account",
|
||||
"oldfieldtype": "Small Text",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -1676,6 +1697,29 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "letter_head",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Letter Head",
|
||||
"no_copy": 0,
|
||||
"options": "Letter Head",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"bold": 0,
|
||||
@@ -1748,6 +1792,29 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "party_account_currency",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Party Account Currency",
|
||||
"no_copy": 1,
|
||||
"options": "Currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -1760,7 +1827,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 1,
|
||||
"in_list_view": 0,
|
||||
"label": "Is Opening",
|
||||
"label": "Is Opening",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "is_opening",
|
||||
"oldfieldtype": "Select",
|
||||
@@ -1797,6 +1864,29 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "against_expense_account",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Against Expense Account",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "against_expense_account",
|
||||
"oldfieldtype": "Small Text",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -1947,7 +2037,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Recurring Type",
|
||||
"label": "Recurring Type",
|
||||
"no_copy": 1,
|
||||
"options": "Monthly\nQuarterly\nHalf-yearly\nYearly",
|
||||
"permlevel": 0,
|
||||
@@ -2175,7 +2265,7 @@
|
||||
"is_submittable": 1,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-09-07 15:51:26",
|
||||
"modified": "2015-10-12 16:23:32.141069",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Purchase Invoice",
|
||||
|
||||
@@ -10,6 +10,7 @@ import frappe.defaults
|
||||
|
||||
from erpnext.controllers.buying_controller import BuyingController
|
||||
from erpnext.accounts.party import get_party_account, get_due_date
|
||||
from erpnext.accounts.utils import get_account_currency
|
||||
|
||||
form_grid_templates = {
|
||||
"items": "templates/form_grid/item_grid.html"
|
||||
@@ -47,7 +48,7 @@ class PurchaseInvoice(BuyingController):
|
||||
self.check_conversion_rate()
|
||||
self.validate_credit_to_acc()
|
||||
self.clear_unallocated_advances("Purchase Invoice Advance", "advances")
|
||||
self.check_for_stopped_status()
|
||||
self.check_for_stopped_or_closed_status()
|
||||
self.validate_with_previous_doc()
|
||||
self.validate_uom_is_integer("uom", "qty")
|
||||
self.set_against_expense_account()
|
||||
@@ -66,7 +67,7 @@ class PurchaseInvoice(BuyingController):
|
||||
|
||||
def set_missing_values(self, for_validate=False):
|
||||
if not self.credit_to:
|
||||
self.credit_to = get_party_account(self.company, self.supplier, "Supplier")
|
||||
self.credit_to = get_party_account("Supplier", self.supplier, self.company)
|
||||
if not self.due_date:
|
||||
self.due_date = get_due_date(self.posting_date, "Supplier", self.supplier, self.company)
|
||||
|
||||
@@ -75,7 +76,7 @@ class PurchaseInvoice(BuyingController):
|
||||
def get_advances(self):
|
||||
if not self.is_return:
|
||||
super(PurchaseInvoice, self).get_advances(self.credit_to, "Supplier", self.supplier,
|
||||
"Purchase Invoice Advance", "advances", "debit", "purchase_order")
|
||||
"Purchase Invoice Advance", "advances", "debit_in_account_currency", "purchase_order")
|
||||
|
||||
def check_active_purchase_items(self):
|
||||
for d in self.get('items'):
|
||||
@@ -91,7 +92,8 @@ class PurchaseInvoice(BuyingController):
|
||||
throw(_("Conversion rate cannot be 0 or 1"))
|
||||
|
||||
def validate_credit_to_acc(self):
|
||||
account = frappe.db.get_value("Account", self.credit_to, ["account_type", "report_type"], as_dict=True)
|
||||
account = frappe.db.get_value("Account", self.credit_to,
|
||||
["account_type", "report_type", "account_currency"], as_dict=True)
|
||||
|
||||
if account.report_type != "Balance Sheet":
|
||||
frappe.throw(_("Credit To account must be a Balance Sheet account"))
|
||||
@@ -99,14 +101,16 @@ class PurchaseInvoice(BuyingController):
|
||||
if self.supplier and account.account_type != "Payable":
|
||||
frappe.throw(_("Credit To account must be a Payable account"))
|
||||
|
||||
def check_for_stopped_status(self):
|
||||
self.party_account_currency = account.account_currency
|
||||
|
||||
def check_for_stopped_or_closed_status(self):
|
||||
check_list = []
|
||||
pc_obj = frappe.get_doc('Purchase Common')
|
||||
|
||||
for d in self.get('items'):
|
||||
if d.purchase_order and not d.purchase_order in check_list and not d.purchase_receipt:
|
||||
check_list.append(d.purchase_order)
|
||||
stopped = frappe.db.sql("select name from `tabPurchase Order` where status = 'Stopped' and name = %s", d.purchase_order)
|
||||
if stopped:
|
||||
throw(_("Purchase Order {0} is 'Stopped'").format(d.purchase_order))
|
||||
pc_obj.check_for_stopped_or_closed_status('Purchase Order', d.purchase_order)
|
||||
|
||||
def validate_with_previous_doc(self):
|
||||
super(PurchaseInvoice, self).validate_with_previous_doc({
|
||||
@@ -213,7 +217,7 @@ class PurchaseInvoice(BuyingController):
|
||||
'party_type': 'Supplier',
|
||||
'party': self.supplier,
|
||||
'is_advance' : 'Yes',
|
||||
'dr_or_cr' : 'debit',
|
||||
'dr_or_cr' : 'debit_in_account_currency',
|
||||
'unadjusted_amt' : flt(d.advance_amount),
|
||||
'allocated_amt' : flt(d.allocated_amount)
|
||||
}
|
||||
@@ -257,26 +261,32 @@ class PurchaseInvoice(BuyingController):
|
||||
"party_type": "Supplier",
|
||||
"party": self.supplier,
|
||||
"against": self.against_expense_account,
|
||||
"credit": self.total_amount_to_pay,
|
||||
"remarks": self.remarks,
|
||||
"credit": self.base_grand_total,
|
||||
"credit_in_account_currency": self.base_grand_total \
|
||||
if self.party_account_currency==self.company_currency else self.grand_total,
|
||||
"against_voucher": self.return_against if cint(self.is_return) else self.name,
|
||||
"against_voucher_type": self.doctype,
|
||||
})
|
||||
}, self.party_account_currency)
|
||||
)
|
||||
|
||||
# tax table gl entries
|
||||
valuation_tax = {}
|
||||
for tax in self.get("taxes"):
|
||||
if tax.category in ("Total", "Valuation and Total") and flt(tax.base_tax_amount_after_discount_amount):
|
||||
account_currency = get_account_currency(tax.account_head)
|
||||
|
||||
dr_or_cr = "debit" if tax.add_deduct_tax == "Add" else "credit"
|
||||
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": tax.account_head,
|
||||
"against": self.supplier,
|
||||
"debit": tax.add_deduct_tax == "Add" and tax.base_tax_amount_after_discount_amount or 0,
|
||||
"credit": tax.add_deduct_tax == "Deduct" and tax.base_tax_amount_after_discount_amount or 0,
|
||||
"remarks": self.remarks,
|
||||
dr_or_cr: tax.base_tax_amount_after_discount_amount,
|
||||
dr_or_cr + "_in_account_currency": tax.base_tax_amount_after_discount_amount \
|
||||
if account_currency==self.company_currency \
|
||||
else tax.tax_amount_after_discount_amount,
|
||||
"cost_center": tax.cost_center
|
||||
})
|
||||
}, account_currency)
|
||||
)
|
||||
|
||||
# accumulate valuation tax
|
||||
@@ -292,36 +302,37 @@ class PurchaseInvoice(BuyingController):
|
||||
stock_items = self.get_stock_items()
|
||||
for item in self.get("items"):
|
||||
if flt(item.base_net_amount):
|
||||
account_currency = get_account_currency(item.expense_account)
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": item.expense_account,
|
||||
"against": self.supplier,
|
||||
"debit": item.base_net_amount,
|
||||
"remarks": self.remarks,
|
||||
"debit_in_account_currency": item.base_net_amount \
|
||||
if account_currency==self.company_currency else item.net_amount,
|
||||
"cost_center": item.cost_center
|
||||
})
|
||||
}, account_currency)
|
||||
)
|
||||
|
||||
if auto_accounting_for_stock and self.is_opening == "No" and \
|
||||
item.item_code in stock_items and item.item_tax_amount:
|
||||
# Post reverse entry for Stock-Received-But-Not-Billed if it is booked in Purchase Receipt
|
||||
negative_expense_booked_in_pi = None
|
||||
if item.purchase_receipt:
|
||||
negative_expense_booked_in_pi = frappe.db.sql("""select name from `tabGL Entry`
|
||||
negative_expense_booked_in_pr = frappe.db.sql("""select name from `tabGL Entry`
|
||||
where voucher_type='Purchase Receipt' and voucher_no=%s and account=%s""",
|
||||
(item.purchase_receipt, expenses_included_in_valuation))
|
||||
|
||||
if not negative_expense_booked_in_pi:
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": stock_received_but_not_billed,
|
||||
"against": self.supplier,
|
||||
"debit": flt(item.item_tax_amount, self.precision("item_tax_amount", item)),
|
||||
"remarks": self.remarks or "Accounting Entry for Stock"
|
||||
})
|
||||
)
|
||||
if not negative_expense_booked_in_pr:
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": stock_received_but_not_billed,
|
||||
"against": self.supplier,
|
||||
"debit": flt(item.item_tax_amount, self.precision("item_tax_amount", item)),
|
||||
"remarks": self.remarks or "Accounting Entry for Stock"
|
||||
})
|
||||
)
|
||||
|
||||
negative_expense_to_be_booked += flt(item.item_tax_amount, self.precision("item_tax_amount", item))
|
||||
negative_expense_to_be_booked += flt(item.item_tax_amount, self.precision("item_tax_amount", item))
|
||||
|
||||
if self.is_opening == "No" and negative_expense_to_be_booked and valuation_tax:
|
||||
# credit valuation tax amount in "Expenses Included In Valuation"
|
||||
@@ -352,12 +363,28 @@ class PurchaseInvoice(BuyingController):
|
||||
# writeoff account includes petty difference in the invoice amount
|
||||
# and the amount that is paid
|
||||
if self.write_off_account and flt(self.write_off_amount):
|
||||
write_off_account_currency = get_account_currency(self.write_off_account)
|
||||
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": self.credit_to,
|
||||
"party_type": "Supplier",
|
||||
"party": self.supplier,
|
||||
"against": self.write_off_account,
|
||||
"debit": self.base_write_off_amount,
|
||||
"debit_in_account_currency": self.base_write_off_amount \
|
||||
if self.party_account_currency==self.company_currency else self.write_off_amount,
|
||||
"against_voucher": self.return_against if cint(self.is_return) else self.name,
|
||||
"against_voucher_type": self.doctype,
|
||||
}, self.party_account_currency)
|
||||
)
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": self.write_off_account,
|
||||
"against": self.supplier,
|
||||
"credit": flt(self.write_off_amount),
|
||||
"remarks": self.remarks,
|
||||
"credit": flt(self.base_write_off_amount),
|
||||
"credit_in_account_currency": self.base_write_off_amount \
|
||||
if write_off_account_currency==self.company_currency else self.write_off_amount,
|
||||
"cost_center": self.write_off_cost_center
|
||||
})
|
||||
)
|
||||
@@ -367,6 +394,8 @@ class PurchaseInvoice(BuyingController):
|
||||
make_gl_entries(gl_entries, cancel=(self.docstatus == 2))
|
||||
|
||||
def on_cancel(self):
|
||||
self.check_for_stopped_or_closed_status()
|
||||
|
||||
if not self.is_return:
|
||||
from erpnext.accounts.utils import remove_against_link_from_jv
|
||||
remove_against_link_from_jv(self.doctype, self.name)
|
||||
@@ -393,7 +422,7 @@ class PurchaseInvoice(BuyingController):
|
||||
if self.bill_no:
|
||||
if cint(frappe.db.get_single_value("Accounts Settings", "check_supplier_invoice_uniqueness")):
|
||||
pi = frappe.db.exists("Purchase Invoice", {"bill_no": self.bill_no,
|
||||
"fiscal_year": self.fiscal_year, "name": ("!=", self.name)})
|
||||
"fiscal_year": self.fiscal_year, "name": ("!=", self.name), "docstatus": ("<", 2)})
|
||||
if pi:
|
||||
frappe.throw("Supplier Invoice No exists in Purchase Invoice {0}".format(pi))
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ from frappe.utils import cint
|
||||
import frappe.defaults
|
||||
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory, \
|
||||
test_records as pr_test_records
|
||||
from erpnext.exceptions import InvalidCurrency
|
||||
|
||||
test_dependencies = ["Item", "Cost Center"]
|
||||
test_ignore = ["Serial No"]
|
||||
@@ -48,25 +49,9 @@ class TestPurchaseInvoice(unittest.TestCase):
|
||||
pi = frappe.copy_doc(test_records[1])
|
||||
pi.insert()
|
||||
pi.submit()
|
||||
|
||||
gl_entries = frappe.db.sql("""select account, debit, credit
|
||||
from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s
|
||||
order by account asc""", pi.name, as_dict=1)
|
||||
self.assertTrue(gl_entries)
|
||||
|
||||
expected_values = dict((d[0], d) for d in [
|
||||
["_Test Payable - _TC", 0, 720],
|
||||
["Stock Received But Not Billed - _TC", 750.0, 0],
|
||||
["Expenses Included In Valuation - _TC", 0.0, 250.0],
|
||||
["_Test Account Shipping Charges - _TC", 100.0, 0],
|
||||
["_Test Account VAT - _TC", 120.0, 0],
|
||||
])
|
||||
|
||||
for i, gle in enumerate(gl_entries):
|
||||
self.assertEquals(expected_values[gle.account][0], gle.account)
|
||||
self.assertEquals(expected_values[gle.account][1], gle.debit)
|
||||
self.assertEquals(expected_values[gle.account][2], gle.credit)
|
||||
|
||||
|
||||
self.check_gle_for_pi(pi.name)
|
||||
|
||||
set_perpetual_inventory(0)
|
||||
|
||||
def test_gl_entries_with_auto_accounting_for_stock_against_pr(self):
|
||||
@@ -82,9 +67,14 @@ class TestPurchaseInvoice(unittest.TestCase):
|
||||
pi.insert()
|
||||
pi.submit()
|
||||
|
||||
self.check_gle_for_pi(pi.name)
|
||||
|
||||
set_perpetual_inventory(0)
|
||||
|
||||
def check_gle_for_pi(self, pi):
|
||||
gl_entries = frappe.db.sql("""select account, debit, credit
|
||||
from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s
|
||||
order by account asc""", pi.name, as_dict=1)
|
||||
order by account asc""", pi, as_dict=1)
|
||||
self.assertTrue(gl_entries)
|
||||
|
||||
expected_values = dict((d[0], d) for d in [
|
||||
@@ -99,8 +89,6 @@ class TestPurchaseInvoice(unittest.TestCase):
|
||||
self.assertEquals(expected_values[gle.account][1], gle.debit)
|
||||
self.assertEquals(expected_values[gle.account][2], gle.credit)
|
||||
|
||||
set_perpetual_inventory(0)
|
||||
|
||||
def test_gl_entries_with_aia_for_non_stock_items(self):
|
||||
set_perpetual_inventory()
|
||||
self.assertEqual(cint(frappe.defaults.get_global_default("auto_accounting_for_stock")), 1)
|
||||
@@ -218,7 +206,8 @@ class TestPurchaseInvoice(unittest.TestCase):
|
||||
pi.load_from_db()
|
||||
|
||||
self.assertTrue(frappe.db.sql("""select name from `tabJournal Entry Account`
|
||||
where reference_type='Purchase Invoice' and reference_name=%s and debit=300""", pi.name))
|
||||
where reference_type='Purchase Invoice'
|
||||
and reference_name=%s and debit_in_account_currency=300""", pi.name))
|
||||
|
||||
self.assertEqual(pi.outstanding_amount, 1212.30)
|
||||
|
||||
@@ -235,17 +224,17 @@ class TestPurchaseInvoice(unittest.TestCase):
|
||||
existing_purchase_cost = frappe.db.sql("""select sum(ifnull(base_net_amount, 0))
|
||||
from `tabPurchase Invoice Item` where project_name = '_Test Project' and docstatus=1""")
|
||||
existing_purchase_cost = existing_purchase_cost and existing_purchase_cost[0][0] or 0
|
||||
|
||||
|
||||
pi = make_purchase_invoice(currency="USD", conversion_rate=60, project_name="_Test Project")
|
||||
self.assertEqual(frappe.db.get_value("Project", "_Test Project", "total_purchase_cost"),
|
||||
self.assertEqual(frappe.db.get_value("Project", "_Test Project", "total_purchase_cost"),
|
||||
existing_purchase_cost + 15000)
|
||||
|
||||
pi1 = make_purchase_invoice(qty=10, project_name="_Test Project")
|
||||
self.assertEqual(frappe.db.get_value("Project", "_Test Project", "total_purchase_cost"),
|
||||
self.assertEqual(frappe.db.get_value("Project", "_Test Project", "total_purchase_cost"),
|
||||
existing_purchase_cost + 15500)
|
||||
|
||||
pi1.cancel()
|
||||
self.assertEqual(frappe.db.get_value("Project", "_Test Project", "total_purchase_cost"),
|
||||
self.assertEqual(frappe.db.get_value("Project", "_Test Project", "total_purchase_cost"),
|
||||
existing_purchase_cost + 15000)
|
||||
|
||||
pi.cancel()
|
||||
@@ -277,6 +266,55 @@ class TestPurchaseInvoice(unittest.TestCase):
|
||||
|
||||
set_perpetual_inventory(0)
|
||||
|
||||
def test_multi_currency_gle(self):
|
||||
set_perpetual_inventory(0)
|
||||
|
||||
pi = make_purchase_invoice(supplier="_Test Supplier USD", credit_to="_Test Payable USD - _TC",
|
||||
currency="USD", conversion_rate=50)
|
||||
|
||||
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='Purchase Invoice' and voucher_no=%s
|
||||
order by account asc""", pi.name, as_dict=1)
|
||||
|
||||
self.assertTrue(gl_entries)
|
||||
|
||||
expected_values = {
|
||||
"_Test Payable USD - _TC": {
|
||||
"account_currency": "USD",
|
||||
"debit": 0,
|
||||
"debit_in_account_currency": 0,
|
||||
"credit": 12500,
|
||||
"credit_in_account_currency": 250
|
||||
},
|
||||
"_Test Account Cost for Goods Sold - _TC": {
|
||||
"account_currency": "INR",
|
||||
"debit": 12500,
|
||||
"debit_in_account_currency": 12500,
|
||||
"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.assertEquals(expected_values[gle.account][field], gle[field])
|
||||
|
||||
|
||||
# Check for valid currency
|
||||
pi1 = make_purchase_invoice(supplier="_Test Supplier USD", credit_to="_Test Payable USD - _TC",
|
||||
do_not_save=True)
|
||||
|
||||
self.assertRaises(InvalidCurrency, pi1.save)
|
||||
|
||||
# cancel
|
||||
pi.cancel()
|
||||
|
||||
gle = frappe.db.sql("""select name from `tabGL Entry`
|
||||
where voucher_type='Sales Invoice' and voucher_no=%s""", pi.name)
|
||||
|
||||
self.assertFalse(gle)
|
||||
|
||||
def make_purchase_invoice(**args):
|
||||
pi = frappe.new_doc("Purchase Invoice")
|
||||
args = frappe._dict(args)
|
||||
|
||||
@@ -141,6 +141,9 @@
|
||||
"supplier": "_Test Supplier",
|
||||
"supplier_name": "_Test Supplier"
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
"bill_no": "NA",
|
||||
"buying_price_list": "_Test Price List",
|
||||
|
||||
@@ -117,7 +117,7 @@
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "advance_amount",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"options": "party_account_currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_width": "100px",
|
||||
@@ -143,7 +143,7 @@
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "allocated_amount",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"options": "party_account_currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_width": "100px",
|
||||
@@ -164,7 +164,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2014-12-25 16:29:15.176476",
|
||||
"modified": "2015-10-02 07:39:03.538046",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Purchase Invoice Advance",
|
||||
|
||||
@@ -1093,7 +1093,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2015-08-26 12:28:16.728059",
|
||||
"modified": "2015-10-19 03:04:52.304768",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Purchase Invoice Item",
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Consider Tax or Charge for",
|
||||
"label": "Consider Tax or Charge for",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "category",
|
||||
"oldfieldtype": "Select",
|
||||
@@ -44,7 +44,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Add or Deduct",
|
||||
"label": "Add or Deduct",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "add_deduct_tax",
|
||||
"oldfieldtype": "Select",
|
||||
@@ -68,7 +68,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Type",
|
||||
"label": "Type",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "charge_type",
|
||||
"oldfieldtype": "Select",
|
||||
@@ -504,7 +504,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2015-08-19 12:46:32.687299",
|
||||
"modified": "2015-10-02 07:39:06.372275",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Purchase Taxes and Charges",
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"description": "Standard tax template that can be applied to all Purchase Transactions. This template can contain list of tax heads and also other expense heads like \"Shipping\", \"Insurance\", \"Handling\" etc.\n\n#### Note\n\nThe tax rate you define here will be the standard tax rate for all **Items**. If there are **Items** that have different rates, they must be added in the **Item Tax** table in the **Item** master.\n\n#### Description of Columns\n\n1. Calculation Type: \n - This can be on **Net Total** (that is the sum of basic amount).\n - **On Previous Row Total / Amount** (for cumulative taxes or charges). If you select this option, the tax will be applied as a percentage of the previous row (in the tax table) amount or total.\n - **Actual** (as mentioned).\n2. Account Head: The Account ledger under which this tax will be booked\n3. Cost Center: If the tax / charge is an income (like shipping) or expense it needs to be booked against a Cost Center.\n4. Description: Description of the tax (that will be printed in invoices / quotes).\n5. Rate: Tax rate.\n6. Amount: Tax amount.\n7. Total: Cumulative total to this point.\n8. Enter Row: If based on \"Previous Row Total\" you can select the row number which will be taken as a base for this calculation (default is the previous row).\n9. Consider Tax or Charge for: In this section you can specify if the tax / charge is only for valuation (not a part of total) or only for total (does not add value to the item) or for both.\n10. Add or Deduct: Whether you want to add or deduct the tax.",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Master",
|
||||
"document_type": "Setup",
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
@@ -21,7 +21,7 @@
|
||||
"in_filter": 1,
|
||||
"in_list_view": 0,
|
||||
"label": "Title",
|
||||
"no_copy": 0,
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "title",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
@@ -176,7 +176,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-05-06 08:52:01.499434",
|
||||
"modified": "2015-10-02 07:39:06.563868",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Purchase Taxes and Charges Template",
|
||||
|
||||
@@ -36,6 +36,11 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
||||
refresh: function(doc, dt, dn) {
|
||||
this._super();
|
||||
|
||||
if(cur_frm.msgbox && cur_frm.msgbox.$wrapper.is(":visible")) {
|
||||
// hide new msgbox
|
||||
cur_frm.msgbox.hide();
|
||||
}
|
||||
|
||||
cur_frm.dashboard.reset();
|
||||
|
||||
this.frm.toggle_reqd("due_date", !this.frm.doc.is_return);
|
||||
@@ -45,6 +50,13 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
||||
if(doc.update_stock) this.show_stock_ledger();
|
||||
|
||||
if(doc.docstatus==1 && !doc.is_return) {
|
||||
|
||||
var is_delivered_by_supplier = false;
|
||||
|
||||
is_delivered_by_supplier = cur_frm.doc.items.some(function(item){
|
||||
return item.is_delivered_by_supplier ? true : false;
|
||||
})
|
||||
|
||||
cur_frm.add_custom_button(doc.update_stock ? __('Sales Return') : __('Credit Note'),
|
||||
this.make_sales_return);
|
||||
|
||||
@@ -56,7 +68,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
||||
return item.delivery_note ? true : false;
|
||||
});
|
||||
|
||||
if(!from_delivery_note) {
|
||||
if(!from_delivery_note && !is_delivered_by_supplier) {
|
||||
cur_frm.add_custom_button(__('Delivery'), cur_frm.cscript['Make Delivery Note']).addClass("btn-primary");
|
||||
}
|
||||
}
|
||||
@@ -99,7 +111,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
||||
source_doctype: "Sales Order",
|
||||
get_query_filters: {
|
||||
docstatus: 1,
|
||||
status: ["!=", "Stopped"],
|
||||
status: ["not in", ["Stopped", "Closed"]],
|
||||
per_billed: ["<", 99.99],
|
||||
customer: cur_frm.doc.customer || undefined,
|
||||
company: cur_frm.doc.company
|
||||
@@ -146,13 +158,18 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
||||
method: "set_missing_values",
|
||||
callback: function(r) {
|
||||
if(!r.exc) {
|
||||
cur_frm.pos_print_format = r.message.print_format;
|
||||
if(r.message && r.message.print_format) {
|
||||
cur_frm.pos_print_format = r.message.print_format;
|
||||
}
|
||||
cur_frm.doc.__missing_values_set = true;
|
||||
me.frm.script_manager.trigger("update_stock");
|
||||
frappe.model.set_default_values(me.frm.doc);
|
||||
me.set_dynamic_labels();
|
||||
me.calculate_taxes_and_totals();
|
||||
if(callback_fn) callback_fn();
|
||||
frappe.after_ajax(function() {
|
||||
cur_frm.doc.__missing_values_set = false;
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -176,6 +193,26 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
||||
})
|
||||
},
|
||||
|
||||
debit_to: function() {
|
||||
var me = this;
|
||||
if(this.frm.doc.debit_to) {
|
||||
me.frm.call({
|
||||
method: "frappe.client.get_value",
|
||||
args: {
|
||||
doctype: "Account",
|
||||
fieldname: "account_currency",
|
||||
filters: { name: me.frm.doc.debit_to },
|
||||
},
|
||||
callback: function(r, rt) {
|
||||
if(r.message) {
|
||||
me.frm.set_value("party_account_currency", r.message.account_currency);
|
||||
me.set_dynamic_labels();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
allocated_amount: function() {
|
||||
this.calculate_total_advance();
|
||||
this.frm.refresh_fields();
|
||||
@@ -183,10 +220,10 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
||||
|
||||
write_off_outstanding_amount_automatically: function() {
|
||||
if(cint(this.frm.doc.write_off_outstanding_amount_automatically)) {
|
||||
frappe.model.round_floats_in(this.frm.doc, ["base_grand_total", "paid_amount"]);
|
||||
frappe.model.round_floats_in(this.frm.doc, ["grand_total", "paid_amount"]);
|
||||
// this will make outstanding amount 0
|
||||
this.frm.set_value("write_off_amount",
|
||||
flt(this.frm.doc.base_grand_total - this.frm.doc.paid_amount - this.frm.doc.total_advance, precision("write_off_amount"))
|
||||
flt(this.frm.doc.grand_total - this.frm.doc.paid_amount - this.frm.doc.total_advance, precision("write_off_amount"))
|
||||
);
|
||||
this.frm.toggle_enable("write_off_amount", false);
|
||||
|
||||
@@ -199,10 +236,12 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
||||
},
|
||||
|
||||
write_off_amount: function() {
|
||||
this.set_in_company_currency(this.frm.doc, ["write_off_amount"]);
|
||||
this.write_off_outstanding_amount_automatically();
|
||||
},
|
||||
|
||||
paid_amount: function() {
|
||||
this.set_in_company_currency(this.frm.doc, ["paid_amount"]);
|
||||
this.write_off_outstanding_amount_automatically();
|
||||
},
|
||||
|
||||
@@ -291,9 +330,10 @@ cur_frm.cscript['Make Delivery Note'] = function() {
|
||||
|
||||
cur_frm.cscript.make_bank_entry = function() {
|
||||
return frappe.call({
|
||||
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_payment_entry_from_sales_invoice",
|
||||
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_payment_entry_against_invoice",
|
||||
args: {
|
||||
"sales_invoice": cur_frm.doc.name
|
||||
"dt": "Sales Invoice",
|
||||
"dn": cur_frm.doc.name
|
||||
},
|
||||
callback: function(r) {
|
||||
var doclist = frappe.model.sync(r.message);
|
||||
@@ -347,7 +387,7 @@ cur_frm.fields_dict['project_name'].get_query = function(doc, cdt, cdn) {
|
||||
// --------------------------------
|
||||
cur_frm.set_query("income_account", "items", function(doc) {
|
||||
return{
|
||||
query: "erpnext.accounts.doctype.sales_invoice.sales_invoice.get_income_account",
|
||||
query: "erpnext.controllers.queries.get_income_account",
|
||||
filters: {'company': doc.company}
|
||||
}
|
||||
});
|
||||
@@ -395,9 +435,9 @@ cur_frm.cscript.on_submit = function(doc, cdt, cdn) {
|
||||
})
|
||||
|
||||
if(cur_frm.doc.is_pos) {
|
||||
frappe.msgprint('<a class="btn btn-primary" \
|
||||
cur_frm.msgbox = frappe.msgprint('<a class="btn btn-primary" \
|
||||
onclick="cur_frm.print_preview.printit(true)" style="margin-right: 5px;">Print</a>\
|
||||
<a class="btn btn-default" href="#Form/Sales Invoice/New">New</a>');
|
||||
<a class="btn btn-default" href="#Form/Sales Invoice/New Sales Invoice">New</a>');
|
||||
|
||||
} else if(cint(frappe.boot.notification_settings.sales_invoice)) {
|
||||
cur_frm.email_doc(frappe.boot.notification_settings.sales_invoice_message);
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Title",
|
||||
"no_copy": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
@@ -671,7 +671,7 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "items",
|
||||
@@ -1002,7 +1002,7 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "taxes",
|
||||
@@ -1145,7 +1145,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Discount",
|
||||
"label": "Additional Discount",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
@@ -1448,7 +1448,7 @@
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "total_advance",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"options": "party_account_currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
@@ -1472,7 +1472,7 @@
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "outstanding_amount",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"options": "party_account_currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
@@ -1663,7 +1663,7 @@
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "paid_amount",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"options": "currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 0,
|
||||
@@ -1673,6 +1673,29 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "base_paid_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Paid Amount (Company Currency)",
|
||||
"no_copy": 1,
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -1710,7 +1733,7 @@
|
||||
"in_list_view": 0,
|
||||
"label": "Write Off Amount",
|
||||
"no_copy": 1,
|
||||
"options": "Company:company:default_currency",
|
||||
"options": "currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 0,
|
||||
@@ -1720,6 +1743,29 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "base_write_off_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Write Off Amount (Company Currency)",
|
||||
"no_copy": 1,
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -2227,6 +2273,29 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "party_account_currency",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Party Account Currency",
|
||||
"no_copy": 1,
|
||||
"options": "Currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -2528,7 +2597,7 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"allow_on_submit": 1,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "sales_team",
|
||||
@@ -2882,7 +2951,7 @@
|
||||
"is_submittable": 1,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-09-07 15:51:26",
|
||||
"modified": "2015-10-26 12:12:40.616546",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice",
|
||||
|
||||
@@ -11,6 +11,7 @@ from erpnext.controllers.stock_controller import update_gl_entries_after
|
||||
from frappe.model.mapper import get_mapped_doc
|
||||
|
||||
from erpnext.controllers.selling_controller import SellingController
|
||||
from erpnext.accounts.utils import get_account_currency
|
||||
|
||||
form_grid_templates = {
|
||||
"items": "templates/form_grid/item_grid.html"
|
||||
@@ -35,6 +36,15 @@ class SalesInvoice(SellingController):
|
||||
'overflow_type': 'billing'
|
||||
}]
|
||||
|
||||
def set_indicator(self):
|
||||
"""Set indicator for portal"""
|
||||
if self.outstanding_amount > 0:
|
||||
self.indicator_color = "orange"
|
||||
self.indicator_title = _("Unpaid")
|
||||
else:
|
||||
self.indicator_color = "green"
|
||||
self.indicator_title = _("Paid")
|
||||
|
||||
def validate(self):
|
||||
super(SalesInvoice, self).validate()
|
||||
self.validate_posting_time()
|
||||
@@ -42,7 +52,7 @@ class SalesInvoice(SellingController):
|
||||
self.validate_proj_cust()
|
||||
self.validate_with_previous_doc()
|
||||
self.validate_uom_is_integer("stock_uom", "qty")
|
||||
self.check_stop_sales_order("sales_order")
|
||||
self.check_stop_or_close_sales_order("sales_order")
|
||||
self.validate_debit_to_acc()
|
||||
self.validate_fixed_asset_account()
|
||||
self.clear_unallocated_advances("Sales Invoice Advance", "advances")
|
||||
@@ -90,7 +100,7 @@ class SalesInvoice(SellingController):
|
||||
|
||||
# this sequence because outstanding may get -ve
|
||||
self.make_gl_entries()
|
||||
|
||||
|
||||
if not self.is_return:
|
||||
self.update_billing_status_for_zero_amount_refdoc("Sales Order")
|
||||
self.check_credit_limit()
|
||||
@@ -107,7 +117,7 @@ class SalesInvoice(SellingController):
|
||||
if cint(self.update_stock) == 1:
|
||||
self.update_stock_ledger()
|
||||
|
||||
self.check_stop_sales_order("sales_order")
|
||||
self.check_stop_or_close_sales_order("sales_order")
|
||||
|
||||
from erpnext.accounts.utils import remove_against_link_from_jv
|
||||
remove_against_link_from_jv(self.doctype, self.name)
|
||||
@@ -161,10 +171,10 @@ class SalesInvoice(SellingController):
|
||||
'extra_cond': """ and exists (select name from `tabSales Invoice` where name=`tabSales Invoice Item`.parent and update_stock=1 and is_return=1)"""
|
||||
}
|
||||
])
|
||||
|
||||
|
||||
def check_credit_limit(self):
|
||||
from erpnext.selling.doctype.customer.customer import check_credit_limit
|
||||
|
||||
|
||||
validate_against_credit_limit = False
|
||||
for d in self.get("items"):
|
||||
if not (d.sales_order or d.delivery_note):
|
||||
@@ -177,7 +187,7 @@ class SalesInvoice(SellingController):
|
||||
pos = self.set_pos_fields(for_validate)
|
||||
|
||||
if not self.debit_to:
|
||||
self.debit_to = get_party_account(self.company, self.customer, "Customer")
|
||||
self.debit_to = get_party_account("Customer", self.customer, self.company)
|
||||
if not self.due_date and self.customer:
|
||||
self.due_date = get_due_date(self.posting_date, "Customer", self.customer, self.company)
|
||||
|
||||
@@ -197,8 +207,8 @@ class SalesInvoice(SellingController):
|
||||
def validate_time_logs_are_submitted(self):
|
||||
for d in self.get("items"):
|
||||
if d.time_log_batch:
|
||||
status = frappe.db.get_value("Time Log Batch", d.time_log_batch, "status")
|
||||
if status!="Submitted":
|
||||
docstatus = frappe.db.get_value("Time Log Batch", d.time_log_batch, "docstatus")
|
||||
if docstatus!=1:
|
||||
frappe.throw(_("Time Log Batch {0} must be 'Submitted'").format(d.time_log_batch))
|
||||
|
||||
def set_pos_fields(self, for_validate=False):
|
||||
@@ -246,7 +256,7 @@ class SalesInvoice(SellingController):
|
||||
def get_advances(self):
|
||||
if not self.is_return:
|
||||
super(SalesInvoice, self).get_advances(self.debit_to, "Customer", self.customer,
|
||||
"Sales Invoice Advance", "advances", "credit", "sales_order")
|
||||
"Sales Invoice Advance", "advances", "credit_in_account_currency", "sales_order")
|
||||
|
||||
def get_company_abbr(self):
|
||||
return frappe.db.sql("select abbr from tabCompany where name=%s", self.company)[0][0]
|
||||
@@ -271,7 +281,7 @@ class SalesInvoice(SellingController):
|
||||
'party_type': 'Customer',
|
||||
'party': self.customer,
|
||||
'is_advance' : 'Yes',
|
||||
'dr_or_cr' : 'credit',
|
||||
'dr_or_cr' : 'credit_in_account_currency',
|
||||
'unadjusted_amt' : flt(d.advance_amount),
|
||||
'allocated_amt' : flt(d.allocated_amount)
|
||||
}
|
||||
@@ -282,7 +292,8 @@ class SalesInvoice(SellingController):
|
||||
reconcile_against_document(lst)
|
||||
|
||||
def validate_debit_to_acc(self):
|
||||
account = frappe.db.get_value("Account", self.debit_to, ["account_type", "report_type"], as_dict=True)
|
||||
account = frappe.db.get_value("Account", self.debit_to,
|
||||
["account_type", "report_type", "account_currency"], as_dict=True)
|
||||
|
||||
if account.report_type != "Balance Sheet":
|
||||
frappe.throw(_("Debit To account must be a Balance Sheet account"))
|
||||
@@ -290,6 +301,8 @@ class SalesInvoice(SellingController):
|
||||
if self.customer and account.account_type != "Receivable":
|
||||
frappe.throw(_("Debit To account must be a Receivable account"))
|
||||
|
||||
self.party_account_currency = account.account_currency
|
||||
|
||||
def validate_fixed_asset_account(self):
|
||||
"""Validate Fixed Asset and whether Income Account Entered Exists"""
|
||||
for d in self.get('items'):
|
||||
@@ -409,7 +422,7 @@ class SalesInvoice(SellingController):
|
||||
def update_packing_list(self):
|
||||
if cint(self.update_stock) == 1:
|
||||
from erpnext.stock.doctype.packed_item.packed_item import make_packing_list
|
||||
make_packing_list(self, 'items')
|
||||
make_packing_list(self)
|
||||
else:
|
||||
self.set('packed_items', [])
|
||||
|
||||
@@ -435,7 +448,7 @@ class SalesInvoice(SellingController):
|
||||
if flt(self.paid_amount) == 0:
|
||||
if self.cash_bank_account:
|
||||
frappe.db.set(self, 'paid_amount',
|
||||
(flt(self.base_grand_total) - flt(self.write_off_amount)))
|
||||
flt(flt(self.grand_total) - flt(self.write_off_amount), self.precision("paid_amount")))
|
||||
else:
|
||||
# show message that the amount is not paid
|
||||
frappe.db.set(self,'paid_amount',0)
|
||||
@@ -443,6 +456,9 @@ class SalesInvoice(SellingController):
|
||||
else:
|
||||
frappe.db.set(self,'paid_amount',0)
|
||||
|
||||
frappe.db.set(self, 'base_paid_amount',
|
||||
flt(self.paid_amount*self.conversion_rate, self.precision("base_paid_amount")))
|
||||
|
||||
def check_prev_docstatus(self):
|
||||
for d in self.get('items'):
|
||||
if d.sales_order and frappe.db.get_value("Sales Order", d.sales_order, "docstatus") != 1:
|
||||
@@ -498,7 +514,7 @@ class SalesInvoice(SellingController):
|
||||
return gl_entries
|
||||
|
||||
def make_customer_gl_entry(self, gl_entries):
|
||||
if self.base_grand_total:
|
||||
if self.grand_total:
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": self.debit_to,
|
||||
@@ -506,37 +522,42 @@ class SalesInvoice(SellingController):
|
||||
"party": self.customer,
|
||||
"against": self.against_income_account,
|
||||
"debit": self.base_grand_total,
|
||||
"remarks": self.remarks,
|
||||
"debit_in_account_currency": self.base_grand_total \
|
||||
if self.party_account_currency==self.company_currency else self.grand_total,
|
||||
"against_voucher": self.return_against if cint(self.is_return) else self.name,
|
||||
"against_voucher_type": self.doctype
|
||||
})
|
||||
}, self.party_account_currency)
|
||||
)
|
||||
|
||||
def make_tax_gl_entries(self, gl_entries):
|
||||
for tax in self.get("taxes"):
|
||||
if flt(tax.base_tax_amount_after_discount_amount):
|
||||
account_currency = get_account_currency(tax.account_head)
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": tax.account_head,
|
||||
"against": self.customer,
|
||||
"credit": flt(tax.base_tax_amount_after_discount_amount),
|
||||
"remarks": self.remarks,
|
||||
"credit_in_account_currency": flt(tax.base_tax_amount_after_discount_amount) \
|
||||
if account_currency==self.company_currency else flt(tax.tax_amount_after_discount_amount),
|
||||
"cost_center": tax.cost_center
|
||||
})
|
||||
}, account_currency)
|
||||
)
|
||||
|
||||
def make_item_gl_entries(self, gl_entries):
|
||||
# income account gl entries
|
||||
for item in self.get("items"):
|
||||
if flt(item.base_net_amount):
|
||||
account_currency = get_account_currency(item.income_account)
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": item.income_account,
|
||||
"against": self.customer,
|
||||
"credit": item.base_net_amount,
|
||||
"remarks": self.remarks,
|
||||
"credit_in_account_currency": item.base_net_amount \
|
||||
if account_currency==self.company_currency else item.net_amount,
|
||||
"cost_center": item.cost_center
|
||||
})
|
||||
}, account_currency)
|
||||
)
|
||||
|
||||
# expense account gl entries
|
||||
@@ -546,6 +567,7 @@ class SalesInvoice(SellingController):
|
||||
|
||||
def make_pos_gl_entries(self, gl_entries):
|
||||
if cint(self.is_pos) and self.cash_bank_account and self.paid_amount:
|
||||
bank_account_currency = get_account_currency(self.cash_bank_account)
|
||||
# POS, make payment entries
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
@@ -553,44 +575,50 @@ class SalesInvoice(SellingController):
|
||||
"party_type": "Customer",
|
||||
"party": self.customer,
|
||||
"against": self.cash_bank_account,
|
||||
"credit": self.paid_amount,
|
||||
"remarks": self.remarks,
|
||||
"credit": self.base_paid_amount,
|
||||
"credit_in_account_currency": self.base_paid_amount \
|
||||
if self.party_account_currency==self.company_currency else self.paid_amount,
|
||||
"against_voucher": self.return_against if cint(self.is_return) else self.name,
|
||||
"against_voucher_type": self.doctype,
|
||||
})
|
||||
}, self.party_account_currency)
|
||||
)
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": self.cash_bank_account,
|
||||
"against": self.customer,
|
||||
"debit": self.paid_amount,
|
||||
"remarks": self.remarks,
|
||||
})
|
||||
"debit": self.base_paid_amount,
|
||||
"debit_in_account_currency": self.base_paid_amount \
|
||||
if bank_account_currency==self.company_currency else self.paid_amount
|
||||
}, bank_account_currency)
|
||||
)
|
||||
|
||||
def make_write_off_gl_entry(self, gl_entries):
|
||||
# write off entries, applicable if only pos
|
||||
if self.write_off_account and self.write_off_amount:
|
||||
write_off_account_currency = get_account_currency(self.write_off_account)
|
||||
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": self.debit_to,
|
||||
"party_type": "Customer",
|
||||
"party": self.customer,
|
||||
"against": self.write_off_account,
|
||||
"credit": self.write_off_amount,
|
||||
"remarks": self.remarks,
|
||||
"credit": self.base_write_off_amount,
|
||||
"credit_in_account_currency": self.base_write_off_amount \
|
||||
if self.party_account_currency==self.company_currency else self.write_off_amount,
|
||||
"against_voucher": self.return_against if cint(self.is_return) else self.name,
|
||||
"against_voucher_type": self.doctype,
|
||||
})
|
||||
"against_voucher_type": self.doctype
|
||||
}, self.party_account_currency)
|
||||
)
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": self.write_off_account,
|
||||
"against": self.customer,
|
||||
"debit": self.write_off_amount,
|
||||
"remarks": self.remarks,
|
||||
"debit": self.base_write_off_amount,
|
||||
"debit_in_account_currency": self.base_write_off_amount \
|
||||
if write_off_account_currency==self.company_currency else self.write_off_amount,
|
||||
"cost_center": self.write_off_cost_center
|
||||
})
|
||||
}, write_off_account_currency)
|
||||
)
|
||||
|
||||
def get_list_context(context=None):
|
||||
@@ -609,24 +637,6 @@ def get_bank_cash_account(mode_of_payment, company):
|
||||
"account": account
|
||||
}
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_income_account(doctype, txt, searchfield, start, page_len, filters):
|
||||
from erpnext.controllers.queries import get_match_cond
|
||||
|
||||
# income account can be any Credit account,
|
||||
# but can also be a Asset account with account_type='Income Account' in special circumstances.
|
||||
# Hence the first condition is an "OR"
|
||||
return frappe.db.sql("""select tabAccount.name from `tabAccount`
|
||||
where (tabAccount.report_type = "Profit and Loss"
|
||||
or tabAccount.account_type in ("Income Account", "Temporary"))
|
||||
and tabAccount.is_group=0
|
||||
and tabAccount.docstatus!=2
|
||||
and tabAccount.company = '%(company)s'
|
||||
and tabAccount.%(key)s LIKE '%(txt)s'
|
||||
%(mcond)s""" % {'company': filters['company'], 'key': searchfield,
|
||||
'txt': "%%%s%%" % frappe.db.escape(txt), 'mcond':get_match_cond(doctype)})
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_delivery_note(source_name, target_doc=None):
|
||||
def set_missing_values(source, target):
|
||||
@@ -657,7 +667,8 @@ def make_delivery_note(source_name, target_doc=None):
|
||||
"sales_order": "against_sales_order",
|
||||
"so_detail": "so_detail"
|
||||
},
|
||||
"postprocess": update_item
|
||||
"postprocess": update_item,
|
||||
"condition": lambda doc: doc.delivered_by_supplier!=1
|
||||
},
|
||||
"Sales Taxes and Charges": {
|
||||
"doctype": "Sales Taxes and Charges",
|
||||
|
||||
@@ -7,6 +7,9 @@ import unittest, copy
|
||||
from frappe.utils import nowdate, add_days, flt
|
||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry, get_qty_after_transaction
|
||||
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
|
||||
from erpnext.exceptions import InvalidAccountCurrency, InvalidCurrency
|
||||
from erpnext.stock.doctype.serial_no.serial_no import SerialNoWarehouseError
|
||||
from frappe.model.naming import make_autoname
|
||||
|
||||
class TestSalesInvoice(unittest.TestCase):
|
||||
def make(self):
|
||||
@@ -401,7 +404,7 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
jv.cancel()
|
||||
self.assertEquals(frappe.db.get_value("Sales Invoice", w.name, "outstanding_amount"), 561.8)
|
||||
|
||||
def test_sales_invoice_gl_entry_without_aii(self):
|
||||
def test_sales_invoice_gl_entry_without_perpetual_inventory(self):
|
||||
set_perpetual_inventory(0)
|
||||
si = frappe.copy_doc(test_records[1])
|
||||
si.insert()
|
||||
@@ -433,7 +436,7 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
|
||||
self.assertFalse(gle)
|
||||
|
||||
def test_pos_gl_entry_with_aii(self):
|
||||
def test_pos_gl_entry_with_perpetual_inventory(self):
|
||||
set_perpetual_inventory()
|
||||
self.make_pos_profile()
|
||||
|
||||
@@ -442,8 +445,7 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
pos = copy.deepcopy(test_records[1])
|
||||
pos["is_pos"] = 1
|
||||
pos["update_stock"] = 1
|
||||
# pos["posting_time"] = "12:05"
|
||||
pos["cash_bank_account"] = "_Test Account Bank Account - _TC"
|
||||
pos["cash_bank_account"] = "_Test Bank - _TC"
|
||||
pos["paid_amount"] = 600.0
|
||||
|
||||
si = frappe.copy_doc(pos)
|
||||
@@ -474,7 +476,7 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
[stock_in_hand, 0.0, abs(sle.stock_value_difference)],
|
||||
[pos["items"][0]["expense_account"], abs(sle.stock_value_difference), 0.0],
|
||||
[si.debit_to, 0.0, 600.0],
|
||||
["_Test Account Bank Account - _TC", 600.0, 0.0]
|
||||
["_Test Bank - _TC", 600.0, 0.0]
|
||||
])
|
||||
|
||||
for i, gle in enumerate(sorted(gl_entries, key=lambda gle: gle.account)):
|
||||
@@ -494,7 +496,7 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
|
||||
def make_pos_profile(self):
|
||||
pos_profile = frappe.get_doc({
|
||||
"cash_bank_account": "_Test Account Bank Account - _TC",
|
||||
"cash_bank_account": "_Test Bank - _TC",
|
||||
"company": "_Test Company",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"currency": "INR",
|
||||
@@ -513,7 +515,7 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
if not frappe.db.exists("POS Profile", "_Test POS Profile"):
|
||||
pos_profile.insert()
|
||||
|
||||
def test_si_gl_entry_with_aii_and_update_stock_with_warehouse_but_no_account(self):
|
||||
def test_si_gl_entry_with_perpetual_inventory_and_update_stock_with_warehouse_but_no_account(self):
|
||||
set_perpetual_inventory()
|
||||
frappe.delete_doc("Account", "_Test Warehouse No Account - _TC")
|
||||
|
||||
@@ -567,7 +569,7 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
self.assertFalse(gle)
|
||||
set_perpetual_inventory(0)
|
||||
|
||||
def test_sales_invoice_gl_entry_with_aii_no_item_code(self):
|
||||
def test_sales_invoice_gl_entry_with_perpetual_inventory_no_item_code(self):
|
||||
set_perpetual_inventory()
|
||||
|
||||
si = frappe.get_doc(test_records[1])
|
||||
@@ -593,7 +595,7 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
|
||||
set_perpetual_inventory(0)
|
||||
|
||||
def test_sales_invoice_gl_entry_with_aii_non_stock_item(self):
|
||||
def test_sales_invoice_gl_entry_with_perpetual_inventory_non_stock_item(self):
|
||||
set_perpetual_inventory()
|
||||
si = frappe.get_doc(test_records[1])
|
||||
si.get("items")[0].item_code = "_Test Non Stock Item"
|
||||
@@ -660,7 +662,7 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
where reference_name=%s""", si.name))
|
||||
|
||||
self.assertTrue(frappe.db.sql("""select name from `tabJournal Entry Account`
|
||||
where reference_name=%s and credit=300""", si.name))
|
||||
where reference_name=%s and credit_in_account_currency=300""", si.name))
|
||||
|
||||
self.assertEqual(si.outstanding_amount, 261.8)
|
||||
|
||||
@@ -688,7 +690,6 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
si.insert()
|
||||
si.submit()
|
||||
|
||||
self.assertEquals(frappe.db.get_value("Serial No", serial_nos[0], "status"), "Delivered")
|
||||
self.assertFalse(frappe.db.get_value("Serial No", serial_nos[0], "warehouse"))
|
||||
self.assertEquals(frappe.db.get_value("Serial No", serial_nos[0],
|
||||
"delivery_document_no"), si.name)
|
||||
@@ -702,33 +703,26 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
|
||||
serial_nos = get_serial_nos(si.get("items")[0].serial_no)
|
||||
|
||||
self.assertEquals(frappe.db.get_value("Serial No", serial_nos[0], "status"), "Available")
|
||||
self.assertEquals(frappe.db.get_value("Serial No", serial_nos[0], "warehouse"), "_Test Warehouse - _TC")
|
||||
self.assertFalse(frappe.db.get_value("Serial No", serial_nos[0],
|
||||
"delivery_document_no"))
|
||||
|
||||
def test_serialize_status(self):
|
||||
from erpnext.stock.doctype.serial_no.serial_no import SerialNoStatusError, get_serial_nos, SerialNoDuplicateError
|
||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item
|
||||
|
||||
se = make_serialized_item()
|
||||
serial_nos = get_serial_nos(se.get("items")[0].serial_no)
|
||||
|
||||
sr = frappe.get_doc("Serial No", serial_nos[0])
|
||||
sr.status = "Not Available"
|
||||
sr.save()
|
||||
serial_no = frappe.get_doc({
|
||||
"doctype": "Serial No",
|
||||
"item_code": "_Test Serialized Item With Series",
|
||||
"serial_no": make_autoname("SR", "Serial No")
|
||||
})
|
||||
serial_no.save()
|
||||
|
||||
si = frappe.copy_doc(test_records[0])
|
||||
si.update_stock = 1
|
||||
si.get("items")[0].item_code = "_Test Serialized Item With Series"
|
||||
si.get("items")[0].qty = 1
|
||||
si.get("items")[0].serial_no = serial_nos[0]
|
||||
si.get("items")[0].serial_no = serial_no.name
|
||||
si.insert()
|
||||
|
||||
self.assertRaises(SerialNoStatusError, si.submit)
|
||||
|
||||
# hack! because stock ledger entires are already inserted and are not rolled back!
|
||||
self.assertRaises(SerialNoDuplicateError, si.cancel)
|
||||
self.assertRaises(SerialNoWarehouseError, si.submit)
|
||||
|
||||
def test_invoice_due_date_against_customers_credit_days(self):
|
||||
# set customer's credit days
|
||||
@@ -842,6 +836,79 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
self.assertEquals(si.base_grand_total, 859.44)
|
||||
self.assertEquals(si.grand_total, 859.44)
|
||||
|
||||
def test_multi_currency_gle(self):
|
||||
set_perpetual_inventory(0)
|
||||
si = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC",
|
||||
currency="USD", conversion_rate=50)
|
||||
|
||||
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='Sales Invoice' and voucher_no=%s
|
||||
order by account asc""", si.name, as_dict=1)
|
||||
|
||||
self.assertTrue(gl_entries)
|
||||
|
||||
expected_values = {
|
||||
"_Test Receivable USD - _TC": {
|
||||
"account_currency": "USD",
|
||||
"debit": 5000,
|
||||
"debit_in_account_currency": 100,
|
||||
"credit": 0,
|
||||
"credit_in_account_currency": 0
|
||||
},
|
||||
"Sales - _TC": {
|
||||
"account_currency": "INR",
|
||||
"debit": 0,
|
||||
"debit_in_account_currency": 0,
|
||||
"credit": 5000,
|
||||
"credit_in_account_currency": 5000
|
||||
}
|
||||
}
|
||||
|
||||
for field in ("account_currency", "debit", "debit_in_account_currency", "credit", "credit_in_account_currency"):
|
||||
for i, gle in enumerate(gl_entries):
|
||||
self.assertEquals(expected_values[gle.account][field], gle[field])
|
||||
|
||||
# cancel
|
||||
si.cancel()
|
||||
|
||||
gle = frappe.db.sql("""select name from `tabGL Entry`
|
||||
where voucher_type='Sales Invoice' and voucher_no=%s""", si.name)
|
||||
|
||||
self.assertFalse(gle)
|
||||
|
||||
def test_invalid_currency(self):
|
||||
# Customer currency = USD
|
||||
|
||||
# Transaction currency cannot be INR
|
||||
si1 = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC",
|
||||
do_not_save=True)
|
||||
|
||||
self.assertRaises(InvalidCurrency, si1.save)
|
||||
|
||||
# Transaction currency cannot be EUR
|
||||
si2 = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC",
|
||||
currency="EUR", conversion_rate=80, do_not_save=True)
|
||||
|
||||
self.assertRaises(InvalidCurrency, si2.save)
|
||||
|
||||
# Transaction currency only allowed in USD
|
||||
si3 = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC",
|
||||
currency="USD", conversion_rate=50)
|
||||
|
||||
# Party Account currency must be in USD, as there is existing GLE with USD
|
||||
si4 = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable - _TC",
|
||||
currency="USD", conversion_rate=50, do_not_submit=True)
|
||||
|
||||
self.assertRaises(InvalidAccountCurrency, si4.submit)
|
||||
|
||||
# Party Account currency must be in USD, force customer currency as there is no GLE
|
||||
|
||||
si3.cancel()
|
||||
si5 = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable - _TC",
|
||||
currency="USD", conversion_rate=50, do_not_submit=True)
|
||||
|
||||
self.assertRaises(InvalidAccountCurrency, si5.submit)
|
||||
|
||||
def create_sales_invoice(**args):
|
||||
si = frappe.new_doc("Sales Invoice")
|
||||
@@ -856,14 +923,15 @@ def create_sales_invoice(**args):
|
||||
si.is_pos = args.is_pos
|
||||
si.is_return = args.is_return
|
||||
si.return_against = args.return_against
|
||||
si.currency="INR"
|
||||
si.conversion_rate = 1
|
||||
si.currency=args.currency or "INR"
|
||||
si.conversion_rate = args.conversion_rate or 1
|
||||
|
||||
si.append("items", {
|
||||
"item_code": args.item or args.item_code or "_Test Item",
|
||||
"warehouse": args.warehouse or "_Test Warehouse - _TC",
|
||||
"qty": args.qty or 1,
|
||||
"rate": args.rate or 100,
|
||||
"income_account": "Sales - _TC",
|
||||
"expense_account": "Cost of Goods Sold - _TC",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"serial_no": args.serial_no
|
||||
|
||||
@@ -117,7 +117,7 @@
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "advance_amount",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"options": "party_account_currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_width": "120px",
|
||||
@@ -143,7 +143,7 @@
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "allocated_amount",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"options": "party_account_currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_width": "120px",
|
||||
@@ -164,7 +164,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2014-12-25 16:30:19.446500",
|
||||
"modified": "2015-10-02 07:39:09.979547",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice Advance",
|
||||
|
||||
@@ -680,6 +680,51 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"collapsible_depends_on": "eval:doc.delivered_by_supplier==1",
|
||||
"fieldname": "drop_ship",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Drop Ship",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "delivered_by_supplier",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Delivered By Supplier",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -843,6 +888,29 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "target_warehouse",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Target Warehouse",
|
||||
"no_copy": 0,
|
||||
"options": "Warehouse",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -1259,7 +1327,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2015-08-20 17:18:52.752064",
|
||||
"modified": "2015-11-02 15:14:02.306067",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice Item",
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Type",
|
||||
"label": "Type",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "charge_type",
|
||||
"oldfieldtype": "Select",
|
||||
@@ -456,7 +456,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2015-08-19 12:46:33.165519",
|
||||
"modified": "2015-10-02 07:39:11.977789",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Taxes and Charges",
|
||||
|
||||
@@ -5,6 +5,3 @@ cur_frm.cscript.tax_table = "Sales Taxes and Charges";
|
||||
|
||||
{% include "public/js/controllers/accounts.js" %}
|
||||
|
||||
frappe.ui.form.on("Sales Taxes and Charges Template", "onload", function(frm) {
|
||||
erpnext.add_applicable_territory();
|
||||
});
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"description": "Standard tax template that can be applied to all Sales Transactions. This template can contain list of tax heads and also other expense / income heads like \"Shipping\", \"Insurance\", \"Handling\" etc.\n\n#### Note\n\nThe tax rate you define here will be the standard tax rate for all **Items**. If there are **Items** that have different rates, they must be added in the **Item Tax** table in the **Item** master.\n\n#### Description of Columns\n\n1. Calculation Type: \n - This can be on **Net Total** (that is the sum of basic amount).\n - **On Previous Row Total / Amount** (for cumulative taxes or charges). If you select this option, the tax will be applied as a percentage of the previous row (in the tax table) amount or total.\n - **Actual** (as mentioned).\n2. Account Head: The Account ledger under which this tax will be booked\n3. Cost Center: If the tax / charge is an income (like shipping) or expense it needs to be booked against a Cost Center.\n4. Description: Description of the tax (that will be printed in invoices / quotes).\n5. Rate: Tax rate.\n6. Amount: Tax amount.\n7. Total: Cumulative total to this point.\n8. Enter Row: If based on \"Previous Row Total\" you can select the row number which will be taken as a base for this calculation (default is the previous row).\n9. Is this Tax included in Basic Rate?: If you check this, it means that this tax will not be shown below the item table, but will be included in the Basic Rate in your main item table. This is useful where you want give a flat price (inclusive of all taxes) price to customers.",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Master",
|
||||
"document_type": "Setup",
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
@@ -21,7 +21,7 @@
|
||||
"in_filter": 1,
|
||||
"in_list_view": 0,
|
||||
"label": "Title",
|
||||
"no_copy": 0,
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "title",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
@@ -164,29 +164,6 @@
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"description": "Specify a list of Territories, for which, this Taxes Master is valid",
|
||||
"fieldname": "territories",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Valid for Territories",
|
||||
"no_copy": 0,
|
||||
"options": "Applicable Territory",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
@@ -198,7 +175,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-09-07 15:51:26",
|
||||
"modified": "2015-10-02 07:39:12.157257",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Taxes and Charges Template",
|
||||
@@ -206,7 +183,7 @@
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
|
||||
@@ -5,7 +5,6 @@ from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
from erpnext.controllers.accounts_controller import validate_taxes_and_charges, validate_inclusive_tax
|
||||
from frappe.utils.nestedset import get_root_of
|
||||
|
||||
class SalesTaxesandChargesTemplate(Document):
|
||||
def validate(self):
|
||||
@@ -20,10 +19,6 @@ def valdiate_taxes_and_charges_template(doc):
|
||||
where ifnull(is_default,0) = 1 and name != %s and company = %s""".format(doc.doctype),
|
||||
(doc.name, doc.company))
|
||||
|
||||
if doc.meta.get_field("territories"):
|
||||
if not doc.territories:
|
||||
doc.append("territories", {"territory": get_root_of("Territory") })
|
||||
|
||||
for tax in doc.get("taxes"):
|
||||
validate_taxes_and_charges(tax)
|
||||
validate_inclusive_tax(tax, doc)
|
||||
|
||||
@@ -20,19 +20,7 @@
|
||||
"rate": 6.36
|
||||
}
|
||||
],
|
||||
"title": "_Test Sales Taxes and Charges Template",
|
||||
"territories": [
|
||||
{
|
||||
"doctype": "Applicable Territory",
|
||||
"parentfield": "territories",
|
||||
"territory": "All Territories"
|
||||
},
|
||||
{
|
||||
"doctype": "Applicable Territory",
|
||||
"parentfield": "territories",
|
||||
"territory": "_Test Territory Rest Of The World"
|
||||
}
|
||||
]
|
||||
"title": "_Test Sales Taxes and Charges Template"
|
||||
},
|
||||
{
|
||||
"company": "_Test Company",
|
||||
@@ -115,14 +103,7 @@
|
||||
"row_id": 7
|
||||
}
|
||||
],
|
||||
"title": "_Test India Tax Master",
|
||||
"territories": [
|
||||
{
|
||||
"doctype": "Applicable Territory",
|
||||
"parentfield": "territories",
|
||||
"territory": "_Test Territory India"
|
||||
}
|
||||
]
|
||||
"title": "_Test India Tax Master"
|
||||
},
|
||||
{
|
||||
"company": "_Test Company",
|
||||
@@ -145,13 +126,76 @@
|
||||
"rate": 4
|
||||
}
|
||||
],
|
||||
"title": "_Test Sales Taxes and Charges Template - Rest of the World",
|
||||
"territories": [
|
||||
"title": "_Test Sales Taxes and Charges Template - Rest of the World"
|
||||
},
|
||||
{
|
||||
"company": "_Test Company",
|
||||
"doctype": "Sales Taxes and Charges Template",
|
||||
"taxes": [
|
||||
{
|
||||
"doctype": "Applicable Territory",
|
||||
"parentfield": "territories",
|
||||
"territory": "_Test Territory Rest Of The World"
|
||||
"account_head": "_Test Account VAT - _TC",
|
||||
"charge_type": "On Net Total",
|
||||
"description": "VAT",
|
||||
"doctype": "Sales Taxes and Charges",
|
||||
"parentfield": "taxes",
|
||||
"rate": 12
|
||||
},
|
||||
{
|
||||
"account_head": "_Test Account Service Tax - _TC",
|
||||
"charge_type": "On Net Total",
|
||||
"description": "Service Tax",
|
||||
"doctype": "Sales Taxes and Charges",
|
||||
"parentfield": "taxes",
|
||||
"rate": 4
|
||||
}
|
||||
]
|
||||
],
|
||||
"title": "_Test Sales Taxes and Charges Template 1"
|
||||
},
|
||||
{
|
||||
"company": "_Test Company",
|
||||
"doctype": "Sales Taxes and Charges Template",
|
||||
"taxes": [
|
||||
{
|
||||
"account_head": "_Test Account VAT - _TC",
|
||||
"charge_type": "On Net Total",
|
||||
"description": "VAT",
|
||||
"doctype": "Sales Taxes and Charges",
|
||||
"parentfield": "taxes",
|
||||
"rate": 12
|
||||
},
|
||||
{
|
||||
"account_head": "_Test Account Service Tax - _TC",
|
||||
"charge_type": "On Net Total",
|
||||
"description": "Service Tax",
|
||||
"doctype": "Sales Taxes and Charges",
|
||||
"parentfield": "taxes",
|
||||
"rate": 4
|
||||
}
|
||||
],
|
||||
"title": "_Test Sales Taxes and Charges Template 2"
|
||||
},
|
||||
{
|
||||
"doctype" : "Sales Taxes and Charges Template",
|
||||
"title": "_Test Tax 1",
|
||||
"company": "_Test Company",
|
||||
"taxes":[{
|
||||
"charge_type": "Actual",
|
||||
"account_head": "Sales Expenses - _TC",
|
||||
"cost_center": "Main - _TC",
|
||||
"description": "Test Shopping cart taxes with Tax Rule",
|
||||
"tax_amount": 1000
|
||||
}]
|
||||
},
|
||||
{
|
||||
"doctype" : "Sales Taxes and Charges Template",
|
||||
"title": "_Test Tax 2",
|
||||
"company": "_Test Company",
|
||||
"taxes":[{
|
||||
"charge_type": "Actual",
|
||||
"account_head": "Sales Expenses - _TC",
|
||||
"cost_center": "Main - _TC",
|
||||
"description": "Test Shopping cart taxes with Tax Rule",
|
||||
"tax_amount": 200
|
||||
}]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
$.extend(cur_frm.cscript, {
|
||||
onload: function() {
|
||||
erpnext.add_applicable_territory();
|
||||
}
|
||||
});
|
||||
@@ -35,14 +35,16 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "column_break_2",
|
||||
"fieldtype": "Column Break",
|
||||
"fieldname": "disabled",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Disabled",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
@@ -62,7 +64,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Calculate Based On",
|
||||
"label": "Calculate Based On",
|
||||
"no_copy": 0,
|
||||
"options": "Net Total\nNet Weight",
|
||||
"permlevel": 0,
|
||||
@@ -78,6 +80,7 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "eval:!doc.disabled",
|
||||
"fieldname": "rule_conditions_section",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -121,12 +124,14 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "eval:!doc.disabled",
|
||||
"fieldname": "section_break_6",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Valid for Countries",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
@@ -141,21 +146,20 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"description": "Specify a list of Territories, for which, this Shipping Rule is valid",
|
||||
"fieldname": "territories",
|
||||
"fieldtype": "Table",
|
||||
"fieldname": "worldwide_shipping",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Valid For Territories",
|
||||
"label": "Worldwide Shipping",
|
||||
"no_copy": 0,
|
||||
"options": "Applicable Territory",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
@@ -164,8 +168,33 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "column_break_8",
|
||||
"fieldtype": "Column Break",
|
||||
"depends_on": "eval:!doc.worldwide_shipping",
|
||||
"fieldname": "countries",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Valid for Countries",
|
||||
"no_copy": 0,
|
||||
"options": "Shipping Rule Country",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "eval:!doc.disabled",
|
||||
"fieldname": "section_break_10",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
@@ -206,8 +235,8 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "section_break_10",
|
||||
"fieldtype": "Section Break",
|
||||
"fieldname": "column_break_12",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
@@ -244,26 +273,6 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "column_break_12",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -296,7 +305,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-09-07 15:51:26",
|
||||
"modified": "2015-10-02 07:39:12.778062",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Shipping Rule",
|
||||
@@ -304,7 +313,7 @@
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
@@ -324,7 +333,7 @@
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
|
||||
@@ -22,6 +22,12 @@ class ShippingRule(Document):
|
||||
self.sort_shipping_rule_conditions()
|
||||
self.validate_overlapping_shipping_rule_conditions()
|
||||
|
||||
if self.worldwide_shipping:
|
||||
self.countries = []
|
||||
|
||||
elif not len([d.country for d in self.countries if d.country]):
|
||||
frappe.throw(_("Please specify a country for this Shipping Rule or check Worldwide Shipping"))
|
||||
|
||||
def validate_from_to_values(self):
|
||||
zero_to_values = []
|
||||
|
||||
|
||||
@@ -1,116 +1,100 @@
|
||||
[
|
||||
{
|
||||
"account": "_Test Account Shipping Charges - _TC",
|
||||
"calculate_based_on": "Net Total",
|
||||
"company": "_Test Company",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"doctype": "Shipping Rule",
|
||||
"label": "_Test Shipping Rule",
|
||||
"name": "_Test Shipping Rule",
|
||||
"account": "_Test Account Shipping Charges - _TC",
|
||||
"calculate_based_on": "Net Total",
|
||||
"company": "_Test Company",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"doctype": "Shipping Rule",
|
||||
"label": "_Test Shipping Rule",
|
||||
"name": "_Test Shipping Rule",
|
||||
"conditions": [
|
||||
{
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 0,
|
||||
"parentfield": "conditions",
|
||||
"shipping_amount": 50.0,
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 0,
|
||||
"parentfield": "conditions",
|
||||
"shipping_amount": 50.0,
|
||||
"to_value": 100
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 101,
|
||||
"parentfield": "conditions",
|
||||
"shipping_amount": 100.0,
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 101,
|
||||
"parentfield": "conditions",
|
||||
"shipping_amount": 100.0,
|
||||
"to_value": 200
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 201,
|
||||
"parentfield": "conditions",
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 201,
|
||||
"parentfield": "conditions",
|
||||
"shipping_amount": 0.0
|
||||
}
|
||||
],
|
||||
"territories": [
|
||||
{
|
||||
"doctype": "Applicable Territory",
|
||||
"parentfield": "territories",
|
||||
"territory": "_Test Territory"
|
||||
}
|
||||
]
|
||||
},
|
||||
],
|
||||
"worldwide_shipping": 1
|
||||
},
|
||||
{
|
||||
"account": "_Test Account Shipping Charges - _TC",
|
||||
"calculate_based_on": "Net Total",
|
||||
"company": "_Test Company",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"doctype": "Shipping Rule",
|
||||
"label": "_Test Shipping Rule - India",
|
||||
"name": "_Test Shipping Rule - India",
|
||||
"account": "_Test Account Shipping Charges - _TC",
|
||||
"calculate_based_on": "Net Total",
|
||||
"company": "_Test Company",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"doctype": "Shipping Rule",
|
||||
"label": "_Test Shipping Rule - India",
|
||||
"name": "_Test Shipping Rule - India",
|
||||
"conditions": [
|
||||
{
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 0,
|
||||
"parentfield": "conditions",
|
||||
"shipping_amount": 50.0,
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 0,
|
||||
"parentfield": "conditions",
|
||||
"shipping_amount": 50.0,
|
||||
"to_value": 100
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 101,
|
||||
"parentfield": "conditions",
|
||||
"shipping_amount": 100.0,
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 101,
|
||||
"parentfield": "conditions",
|
||||
"shipping_amount": 100.0,
|
||||
"to_value": 200
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 201,
|
||||
"parentfield": "conditions",
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 201,
|
||||
"parentfield": "conditions",
|
||||
"shipping_amount": 0.0
|
||||
}
|
||||
],
|
||||
"territories": [
|
||||
{
|
||||
"doctype": "Applicable Territory",
|
||||
"parentfield": "territories",
|
||||
"territory": "_Test Territory India"
|
||||
}
|
||||
],
|
||||
"countries": [
|
||||
{"country": "India"}
|
||||
]
|
||||
},
|
||||
},
|
||||
{
|
||||
"account": "_Test Account Shipping Charges - _TC",
|
||||
"calculate_based_on": "Net Total",
|
||||
"company": "_Test Company",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"doctype": "Shipping Rule",
|
||||
"label": "_Test Shipping Rule - Rest of the World",
|
||||
"name": "_Test Shipping Rule - Rest of the World",
|
||||
"account": "_Test Account Shipping Charges - _TC",
|
||||
"calculate_based_on": "Net Total",
|
||||
"company": "_Test Company",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"doctype": "Shipping Rule",
|
||||
"label": "_Test Shipping Rule - Rest of the World",
|
||||
"name": "_Test Shipping Rule - Rest of the World",
|
||||
"conditions": [
|
||||
{
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 0,
|
||||
"parentfield": "conditions",
|
||||
"shipping_amount": 500.0,
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 0,
|
||||
"parentfield": "conditions",
|
||||
"shipping_amount": 500.0,
|
||||
"to_value": 1000
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 1001,
|
||||
"parentfield": "conditions",
|
||||
"shipping_amount": 1000.0,
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 1001,
|
||||
"parentfield": "conditions",
|
||||
"shipping_amount": 1000.0,
|
||||
"to_value": 2000
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 2001,
|
||||
"parentfield": "conditions",
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 2001,
|
||||
"parentfield": "conditions",
|
||||
"shipping_amount": 1500.0
|
||||
}
|
||||
],
|
||||
"territories": [
|
||||
{
|
||||
"doctype": "Applicable Territory",
|
||||
"parentfield": "territories",
|
||||
"territory": "_Test Territory Rest Of The World"
|
||||
}
|
||||
]
|
||||
],
|
||||
"worldwide_shipping": 1
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2013-12-20 19:21:46",
|
||||
"modified": "2015-10-02 07:39:12.974539",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Shipping Rule Condition",
|
||||
|
||||
@@ -2,26 +2,27 @@
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"creation": "2013-06-20 12:48:38",
|
||||
"creation": "2015-09-17 06:43:22.767534",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Other",
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"description": "",
|
||||
"fieldname": "territory",
|
||||
"fieldname": "country",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Territory",
|
||||
"label": "Country",
|
||||
"no_copy": 0,
|
||||
"options": "Territory",
|
||||
"options": "Country",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
@@ -33,18 +34,20 @@
|
||||
],
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 1,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2015-01-01 14:29:58.724652",
|
||||
"modified": "2015-10-02 07:39:13.035775",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Setup",
|
||||
"name": "Applicable Territory",
|
||||
"module": "Accounts",
|
||||
"name": "Shipping Rule Country",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0
|
||||
"read_only_onload": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
||||
@@ -1,12 +1,10 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
from frappe.model.document import Document
|
||||
|
||||
class ApplicableTerritory(Document):
|
||||
pass
|
||||
class ShippingRuleCountry(Document):
|
||||
pass
|
||||
60
erpnext/accounts/doctype/tax_rule/tax_rule.js
Normal file
60
erpnext/accounts/doctype/tax_rule/tax_rule.js
Normal file
@@ -0,0 +1,60 @@
|
||||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
cur_frm.add_fetch("customer", "customer_group", "customer_group" );
|
||||
cur_frm.add_fetch("supplier", "supplier_type", "supplier_type" );
|
||||
|
||||
cur_frm.toggle_reqd("sales_tax_template", cur_frm.doc.tax_type=="Sales");
|
||||
cur_frm.toggle_reqd("purchase_tax_template", cur_frm.doc.tax_type=="Purchase");
|
||||
|
||||
|
||||
frappe.ui.form.on("Tax Rule", "onload", function(frm) {
|
||||
if(frm.doc.__islocal){
|
||||
frm.set_value("use_for_shopping_cart", 1);
|
||||
}
|
||||
})
|
||||
|
||||
frappe.ui.form.on("Tax Rule", "use_for_shopping_cart", function(frm) {
|
||||
if(!frm.doc.use_for_shopping_cart && (frappe.get_list("Tax Rule", {"use_for_shopping_cart":1}).length == 0)){
|
||||
frappe.model.get_value("Shopping Cart Settings", "Shopping Cart Settings", "enabled", function(docfield) {
|
||||
if(docfield.enabled){
|
||||
frm.set_value("use_for_shopping_cart", 1);
|
||||
frappe.throw(__("Shopping Cart is enabled"));
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
frappe.ui.form.on("Tax Rule", "customer", function(frm) {
|
||||
frappe.call({
|
||||
method:"erpnext.accounts.doctype.tax_rule.tax_rule.get_party_details",
|
||||
args: {
|
||||
"party": frm.doc.customer,
|
||||
"party_type": "customer"
|
||||
},
|
||||
callback: function(r) {
|
||||
if(!r.exc) {
|
||||
$.each(r.message, function(k, v) {
|
||||
frm.set_value(k, v);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
frappe.ui.form.on("Tax Rule", "supplier", function(frm) {
|
||||
frappe.call({
|
||||
method:"erpnext.accounts.doctype.tax_rule.tax_rule.get_party_details",
|
||||
args: {
|
||||
"party": frm.doc.supplier,
|
||||
"party_type": "supplier"
|
||||
},
|
||||
callback: function(r) {
|
||||
if(!r.exc) {
|
||||
$.each(r.message, function(k, v) {
|
||||
frm.set_value(k, v);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,27 +1,30 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 0,
|
||||
"creation": "2013-04-30 12:58:38",
|
||||
"autoname": "TR.####",
|
||||
"creation": "2015-08-07 02:33:52.670866",
|
||||
"custom": 0,
|
||||
"description": "System for managing Backups",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "System",
|
||||
"document_type": "Setup",
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "setup",
|
||||
"fieldtype": "Section Break",
|
||||
"default": "Sales",
|
||||
"fieldname": "tax_type",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Download Backups",
|
||||
"in_list_view": 1,
|
||||
"label": "Tax Type",
|
||||
"no_copy": 0,
|
||||
"options": "Sales\nPurchase",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
@@ -34,13 +37,13 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "current_backups",
|
||||
"fieldtype": "HTML",
|
||||
"fieldname": "use_for_shopping_cart",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Current Backups",
|
||||
"label": "Use for Shopping Cart",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
@@ -56,56 +59,12 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"description": "",
|
||||
"fieldname": "sync_with_dropbox",
|
||||
"fieldtype": "Section Break",
|
||||
"fieldname": "column_break_1",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Sync with Dropbox",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "backup_right_now",
|
||||
"fieldtype": "Button",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Backup Right Now",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "send_backups_to_dropbox",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Send Backups to Dropbox",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
@@ -121,18 +80,18 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "send_backups_to_dropbox",
|
||||
"description": "Note: Backups and files are not deleted from Dropbox, you will have to delete them manually.",
|
||||
"fieldname": "upload_backups_to_dropbox",
|
||||
"fieldtype": "Select",
|
||||
"depends_on": "eval:doc.tax_type==\"Sales\"",
|
||||
"fieldname": "sales_tax_template",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Upload Backups to Dropbox",
|
||||
"label": "Sales Tax Template",
|
||||
"no_copy": 0,
|
||||
"options": "Never\nWeekly\nDaily",
|
||||
"options": "Sales Taxes and Charges Template",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
@@ -145,17 +104,18 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "send_backups_to_dropbox",
|
||||
"description": "Email ids separated by commas.",
|
||||
"fieldname": "send_notifications_to",
|
||||
"fieldtype": "Data",
|
||||
"depends_on": "eval:doc.tax_type==\"Purchase\"",
|
||||
"fieldname": "purchase_tax_template",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Send Notifications To",
|
||||
"label": "Purchase Tax Template",
|
||||
"no_copy": 0,
|
||||
"options": "Purchase Taxes and Charges Template",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
@@ -168,123 +128,16 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "dropbox_access_key",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Dropbox Access Key",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "dropbox_access_secret",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Dropbox Access Secret",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "dropbox_access_allowed",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Dropbox Access Allowed",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "send_backups_to_dropbox",
|
||||
"fieldname": "allow_dropbox_access",
|
||||
"fieldtype": "Button",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Allow Dropbox Access",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"description": "Note: Backups and files are not deleted from Google Drive, you will have to delete them manually.",
|
||||
"fieldname": "sync_with_gdrive",
|
||||
"fieldname": "filters",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Sync with Google Drive",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "upload_backups_to_gdrive",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Upload Backups to Google Drive",
|
||||
"label": "Filters",
|
||||
"no_copy": 0,
|
||||
"options": "Never\nDaily\nWeekly",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
@@ -297,15 +150,18 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "allow_gdrive_access",
|
||||
"fieldtype": "Button",
|
||||
"depends_on": "eval:doc.tax_type==\"Sales\"",
|
||||
"fieldname": "customer",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Allow Google Drive Access",
|
||||
"label": "Customer",
|
||||
"no_copy": 0,
|
||||
"options": "Customer",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
@@ -318,15 +174,40 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "verification_code",
|
||||
"depends_on": "eval:doc.tax_type==\"Purchase\"",
|
||||
"fieldname": "supplier",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Supplier",
|
||||
"no_copy": 0,
|
||||
"options": "Supplier",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "billing_city",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Enter Verification Code",
|
||||
"label": "Billing City",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
@@ -339,15 +220,16 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "validate_gdrive",
|
||||
"fieldtype": "Button",
|
||||
"fieldname": "billing_state",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Validate",
|
||||
"label": "Billing State",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
@@ -360,17 +242,19 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "gdrive_access_allowed",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"fieldname": "billing_country",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Google Drive Access Allowed",
|
||||
"label": "Billing Country",
|
||||
"no_copy": 0,
|
||||
"options": "Country",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@@ -381,17 +265,17 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "gdrive_credentials",
|
||||
"fieldtype": "Text",
|
||||
"hidden": 1,
|
||||
"fieldname": "column_break_2",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Credentials",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@@ -402,17 +286,66 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "database_folder_id",
|
||||
"depends_on": "eval:doc.tax_type==\"Sales\"",
|
||||
"fieldname": "customer_group",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Customer Group",
|
||||
"no_copy": 0,
|
||||
"options": "Customer Group",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "eval:doc.tax_type==\"Purchase\"",
|
||||
"fieldname": "supplier_type",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Supplier Type",
|
||||
"no_copy": 0,
|
||||
"options": "Supplier Type",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "shipping_city",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Database Folder ID",
|
||||
"label": "Shipping City",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@@ -423,17 +356,216 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "files_folder_id",
|
||||
"fieldname": "shipping_state",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Files Folder ID",
|
||||
"label": "Shipping State",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "shipping_country",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Shipping Country",
|
||||
"no_copy": 0,
|
||||
"options": "Country",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "section_break_4",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Validity",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "from_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "From Date",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "column_break_7",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "to_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "To Date",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "section_break_6",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"default": "1",
|
||||
"fieldname": "priority",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Priority",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "column_break_20",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Company",
|
||||
"no_copy": 0,
|
||||
"options": "Company",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@@ -443,17 +575,16 @@
|
||||
],
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"icon": "icon-cloud-upload",
|
||||
"idx": 1,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 1,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-05-26 04:54:10.193573",
|
||||
"modified": "2015-10-02 07:39:16.298546",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Setup",
|
||||
"name": "Backup Manager",
|
||||
"module": "Accounts",
|
||||
"name": "Tax Rule",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
@@ -461,16 +592,16 @@
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 0,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 0,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 0,
|
||||
"role": "System Manager",
|
||||
"report": 1,
|
||||
"role": "Accounts Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
@@ -478,5 +609,7 @@
|
||||
}
|
||||
],
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0
|
||||
"read_only_onload": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
||||
133
erpnext/accounts/doctype/tax_rule/tax_rule.py
Normal file
133
erpnext/accounts/doctype/tax_rule/tax_rule.py
Normal file
@@ -0,0 +1,133 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import cstr
|
||||
|
||||
class IncorrectCustomerGroup(frappe.ValidationError): pass
|
||||
class IncorrectSupplierType(frappe.ValidationError): pass
|
||||
class ConflictingTaxRule(frappe.ValidationError): pass
|
||||
|
||||
class TaxRule(Document):
|
||||
def __setup__(self):
|
||||
self.flags.ignore_these_exceptions_in_test = [ConflictingTaxRule]
|
||||
|
||||
def validate(self):
|
||||
self.validate_tax_template()
|
||||
self.validate_date()
|
||||
self.validate_filters()
|
||||
|
||||
def validate_tax_template(self):
|
||||
if self.tax_type== "Sales":
|
||||
self.purchase_tax_template = self.supplier = self.supplier_type= None
|
||||
if self.customer:
|
||||
self.customer_group = None
|
||||
|
||||
else:
|
||||
self.sales_tax_template= self.customer = self.customer_group= None
|
||||
|
||||
if self.supplier:
|
||||
self.supplier_type = None
|
||||
|
||||
if not (self.sales_tax_template or self.purchase_tax_template):
|
||||
frappe.throw(_("Tax Template is mandatory."))
|
||||
|
||||
def validate_date(self):
|
||||
if self.from_date and self.to_date and self.from_date > self.to_date:
|
||||
frappe.throw(_("From Date cannot be greater than To Date"))
|
||||
|
||||
def validate_filters(self):
|
||||
filters = {
|
||||
"tax_type": self.tax_type,
|
||||
"customer": self.customer,
|
||||
"customer_group": self.customer_group,
|
||||
"supplier": self.supplier,
|
||||
"supplier_type": self.supplier_type,
|
||||
"billing_city": self.billing_city,
|
||||
"billing_state": self.billing_state,
|
||||
"billing_country": self.billing_country,
|
||||
"shipping_city": self.shipping_city,
|
||||
"shipping_state": self.shipping_state,
|
||||
"shipping_country": self.shipping_country,
|
||||
"company": self.company
|
||||
}
|
||||
|
||||
conds=""
|
||||
for d in filters:
|
||||
if conds:
|
||||
conds += " and "
|
||||
conds += """ifnull({0}, '') = '{1}'""".format(d, frappe.db.escape(cstr(filters[d])))
|
||||
|
||||
if self.from_date and self.to_date:
|
||||
conds += """ and ((from_date > '{from_date}' and from_date < '{to_date}') or
|
||||
(to_date > '{from_date}' and to_date < '{to_date}') or
|
||||
('{from_date}' > from_date and '{from_date}' < to_date) or
|
||||
('{from_date}' = from_date and '{to_date}' = to_date))""".format(from_date=self.from_date, to_date=self.to_date)
|
||||
|
||||
elif self.from_date and not self.to_date:
|
||||
conds += """ and to_date > '{from_date}'""".format(from_date = self.from_date)
|
||||
|
||||
elif self.to_date and not self.from_date:
|
||||
conds += """ and from_date < '{to_date}'""".format(to_date = self.to_date)
|
||||
|
||||
tax_rule = frappe.db.sql("select name, priority \
|
||||
from `tabTax Rule` where {0} and name != '{1}'".format(conds, self.name), as_dict=1)
|
||||
|
||||
if tax_rule:
|
||||
if tax_rule[0].priority == self.priority:
|
||||
frappe.throw(_("Tax Rule Conflicts with {0}".format(tax_rule[0].name)), ConflictingTaxRule)
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_party_details(party, party_type, args=None):
|
||||
out = {}
|
||||
if args:
|
||||
billing_filters= {"name": args.get("billing_address")}
|
||||
shipping_filters= {"name": args.get("shipping_address")}
|
||||
else:
|
||||
billing_filters= {party_type: party, "is_primary_address": 1}
|
||||
shipping_filters= {party_type:party, "is_shipping_address": 1}
|
||||
|
||||
billing_address= frappe.get_all("Address", fields=["city", "state", "country"], filters= billing_filters)
|
||||
shipping_address= frappe.get_all("Address", fields=["city", "state", "country"], filters= shipping_filters)
|
||||
|
||||
if billing_address:
|
||||
out["billing_city"]= billing_address[0].city
|
||||
out["billing_state"]= billing_address[0].state
|
||||
out["billing_country"]= billing_address[0].country
|
||||
|
||||
if shipping_address:
|
||||
out["shipping_city"]= shipping_address[0].city
|
||||
out["shipping_state"]= shipping_address[0].state
|
||||
out["shipping_country"]= shipping_address[0].country
|
||||
|
||||
return out
|
||||
|
||||
def get_tax_template(posting_date, args):
|
||||
"""Get matching tax rule"""
|
||||
args = frappe._dict(args)
|
||||
conditions = ["""(from_date is null or from_date = '' or from_date <= '{0}')
|
||||
and (to_date is null or to_date = '' or to_date >= '{0}')""".format(posting_date)]
|
||||
|
||||
for key, value in args.iteritems():
|
||||
if key in "use_for_shopping_cart":
|
||||
conditions.append("use_for_shopping_cart = {0}".format(1 if value else 0))
|
||||
else:
|
||||
conditions.append("ifnull({0}, '') in ('', '{1}')".format(key, frappe.db.escape(cstr(value))))
|
||||
|
||||
tax_rule = frappe.db.sql("""select * from `tabTax Rule`
|
||||
where {0}""".format(" and ".join(conditions)), as_dict = True)
|
||||
|
||||
if not tax_rule:
|
||||
return None
|
||||
|
||||
for rule in tax_rule:
|
||||
rule.no_of_keys_matched = 0
|
||||
for key in args:
|
||||
if rule.get(key): rule.no_of_keys_matched += 1
|
||||
|
||||
rule = sorted(tax_rule, lambda b, a: cmp(a.no_of_keys_matched, b.no_of_keys_matched) or cmp(a.priority, b.priority))[0]
|
||||
return rule.sales_tax_template or rule.purchase_tax_template
|
||||
28
erpnext/accounts/doctype/tax_rule/test_records.json
Normal file
28
erpnext/accounts/doctype/tax_rule/test_records.json
Normal file
@@ -0,0 +1,28 @@
|
||||
[
|
||||
{
|
||||
"doctype": "Tax Rule",
|
||||
"tax_type" : "Sales",
|
||||
"sales_tax_template": "_Test Tax 1",
|
||||
"use_for_shopping_cart": 1,
|
||||
"billing_city": "_Test City",
|
||||
"billing_state": "Test State",
|
||||
"billing_country": "India",
|
||||
"shipping_city": "_Test City",
|
||||
"shipping_country": "India",
|
||||
"priority": 1,
|
||||
"company": "_Test Company"
|
||||
},
|
||||
{
|
||||
"doctype": "Tax Rule",
|
||||
"tax_type" : "Sales",
|
||||
"sales_tax_template": "_Test Tax 2",
|
||||
"use_for_shopping_cart": 0,
|
||||
"billing_city": "_Test City",
|
||||
"billing_country": "India",
|
||||
"shipping_city": "_Test City",
|
||||
"shipping_state": "Test State",
|
||||
"shipping_country": "India",
|
||||
"priority": 2,
|
||||
"company": "_Test Company"
|
||||
}
|
||||
]
|
||||
130
erpnext/accounts/doctype/tax_rule/test_tax_rule.py
Normal file
130
erpnext/accounts/doctype/tax_rule/test_tax_rule.py
Normal file
@@ -0,0 +1,130 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
from erpnext.accounts.doctype.tax_rule.tax_rule import IncorrectCustomerGroup, IncorrectSupplierType, ConflictingTaxRule, get_tax_template
|
||||
|
||||
test_records = frappe.get_test_records('Tax Rule')
|
||||
|
||||
class TestTaxRule(unittest.TestCase):
|
||||
def setUp(self):
|
||||
frappe.db.sql("delete from `tabTax Rule` where use_for_shopping_cart <> 1")
|
||||
|
||||
def test_conflict(self):
|
||||
tax_rule1 = make_tax_rule(customer= "_Test Customer",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1)
|
||||
tax_rule1.save()
|
||||
|
||||
tax_rule2 = make_tax_rule(customer= "_Test Customer",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1)
|
||||
|
||||
self.assertRaises(ConflictingTaxRule, tax_rule2.save)
|
||||
|
||||
def test_conflict_with_non_overlapping_dates(self):
|
||||
tax_rule1 = make_tax_rule(customer= "_Test Customer",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, from_date = "2015-01-01")
|
||||
tax_rule1.save()
|
||||
|
||||
tax_rule2 = make_tax_rule(customer= "_Test Customer",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, to_date = "2013-01-01")
|
||||
|
||||
tax_rule2.save()
|
||||
self.assertTrue(tax_rule2.name)
|
||||
|
||||
def test_conflict_with_overlapping_dates(self):
|
||||
tax_rule1 = make_tax_rule(customer= "_Test Customer",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, from_date = "2015-01-01", to_date = "2015-01-05")
|
||||
tax_rule1.save()
|
||||
|
||||
tax_rule2 = make_tax_rule(customer= "_Test Customer",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, from_date = "2015-01-03", to_date = "2015-01-09")
|
||||
|
||||
self.assertRaises(ConflictingTaxRule, tax_rule2.save)
|
||||
|
||||
def test_tax_template(self):
|
||||
tax_rule = make_tax_rule()
|
||||
self.assertEquals(tax_rule.purchase_tax_template, None)
|
||||
|
||||
|
||||
def test_select_tax_rule_based_on_customer(self):
|
||||
make_tax_rule(customer= "_Test Customer",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template", save=1)
|
||||
|
||||
make_tax_rule(customer= "_Test Customer 1",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template 1", save=1)
|
||||
|
||||
make_tax_rule(customer= "_Test Customer 2",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template 2", save=1)
|
||||
|
||||
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer 2"}),
|
||||
"_Test Sales Taxes and Charges Template 2")
|
||||
|
||||
def test_select_tax_rule_based_on_better_match(self):
|
||||
make_tax_rule(customer= "_Test Customer", billing_city = "Test City", billing_state = "Test State",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template", save=1)
|
||||
|
||||
make_tax_rule(customer= "_Test Customer", billing_city = "Test City1", billing_state = "Test State",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template 1", save=1)
|
||||
|
||||
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City", "billing_state": "Test State"}),
|
||||
"_Test Sales Taxes and Charges Template")
|
||||
|
||||
def test_select_tax_rule_based_on_state_match(self):
|
||||
make_tax_rule(customer= "_Test Customer", shipping_state = "Test State",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template", save=1)
|
||||
|
||||
make_tax_rule(customer= "_Test Customer", shipping_state = "Test State12",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template 1", priority=2, save=1)
|
||||
|
||||
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "shipping_state": "Test State"}),
|
||||
"_Test Sales Taxes and Charges Template")
|
||||
|
||||
def test_select_tax_rule_based_on_better_priority(self):
|
||||
make_tax_rule(customer= "_Test Customer", billing_city = "Test City",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template", priority=1, save=1)
|
||||
|
||||
make_tax_rule(customer= "_Test Customer", billing_city = "Test City",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template 1", priority=2, save=1)
|
||||
|
||||
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City"}),
|
||||
"_Test Sales Taxes and Charges Template 1")
|
||||
|
||||
def test_select_tax_rule_based_cross_matching_keys(self):
|
||||
make_tax_rule(customer= "_Test Customer", billing_city = "Test City",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template", save=1)
|
||||
|
||||
make_tax_rule(customer= "_Test Customer 1", billing_city = "Test City 1",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template 1", save=1)
|
||||
|
||||
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City 1"}),
|
||||
None)
|
||||
|
||||
def test_select_tax_rule_based_cross_partially_keys(self):
|
||||
make_tax_rule(customer= "_Test Customer", billing_city = "Test City",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template", save=1)
|
||||
|
||||
make_tax_rule(billing_city = "Test City 1",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template 1", save=1)
|
||||
|
||||
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City 1"}),
|
||||
"_Test Sales Taxes and Charges Template 1")
|
||||
|
||||
|
||||
def make_tax_rule(**args):
|
||||
args = frappe._dict(args)
|
||||
|
||||
tax_rule = frappe.new_doc("Tax Rule")
|
||||
|
||||
for key, val in args.iteritems():
|
||||
if key != "save":
|
||||
tax_rule.set(key, val)
|
||||
|
||||
tax_rule.company = args.company or "_Test Company"
|
||||
|
||||
if args.save:
|
||||
tax_rule.insert()
|
||||
|
||||
return tax_rule
|
||||
@@ -27,14 +27,25 @@ def process_gl_map(gl_map, merge_entries=True):
|
||||
gl_map = merge_similar_entries(gl_map)
|
||||
|
||||
for entry in gl_map:
|
||||
# toggle debit, credit if negative entry
|
||||
# toggle debit, credit if negative entry
|
||||
if flt(entry.debit) < 0:
|
||||
entry.credit = flt(entry.credit) - flt(entry.debit)
|
||||
entry.debit = 0.0
|
||||
|
||||
if flt(entry.debit_in_account_currency) < 0:
|
||||
entry.credit_in_account_currency = \
|
||||
flt(entry.credit_in_account_currency) - flt(entry.debit_in_account_currency)
|
||||
entry.debit_in_account_currency = 0.0
|
||||
|
||||
if flt(entry.credit) < 0:
|
||||
entry.debit = flt(entry.debit) - flt(entry.credit)
|
||||
entry.credit = 0.0
|
||||
|
||||
|
||||
if flt(entry.credit_in_account_currency) < 0:
|
||||
entry.debit_in_account_currency = \
|
||||
flt(entry.debit_in_account_currency) - flt(entry.credit_in_account_currency)
|
||||
entry.credit_in_account_currency = 0.0
|
||||
|
||||
return gl_map
|
||||
|
||||
def merge_similar_entries(gl_map):
|
||||
@@ -45,7 +56,11 @@ def merge_similar_entries(gl_map):
|
||||
same_head = check_if_in_list(entry, merged_gl_map)
|
||||
if same_head:
|
||||
same_head.debit = flt(same_head.debit) + flt(entry.debit)
|
||||
same_head.debit_in_account_currency = \
|
||||
flt(same_head.debit_in_account_currency) + flt(entry.debit_in_account_currency)
|
||||
same_head.credit = flt(same_head.credit) + flt(entry.credit)
|
||||
same_head.credit_in_account_currency = \
|
||||
flt(same_head.credit_in_account_currency) + flt(entry.credit_in_account_currency)
|
||||
else:
|
||||
merged_gl_map.append(entry)
|
||||
|
||||
|
||||
@@ -166,7 +166,7 @@ erpnext.AccountsChart = Class.extend({
|
||||
var dr_or_cr = node.data.balance < 0 ? "Cr" : "Dr";
|
||||
if (me.ctype == 'Account' && node.data && node.data.balance!==undefined) {
|
||||
$('<span class="balance-area pull-right text-muted small">'
|
||||
+ format_currency(Math.abs(node.data.balance), node.data.currency)
|
||||
+ format_currency(Math.abs(node.data.balance), node.data.account_currency)
|
||||
+ " " + dr_or_cr
|
||||
+ '</span>').insertBefore(node.$ul);
|
||||
}
|
||||
@@ -209,12 +209,12 @@ erpnext.AccountsChart = Class.extend({
|
||||
{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:'account_type', label:__('Account Type'),
|
||||
options: ['', 'Bank', 'Cash', 'Warehouse', 'Receivable', 'Payable',
|
||||
'Equity', 'Cost of Goods Sold', 'Fixed Asset', 'Expense Account',
|
||||
'Income Account', 'Tax', 'Chargeable', 'Temporary'].join('\n'),
|
||||
options: ['', 'Bank', 'Cash', 'Warehouse', 'Tax', 'Chargeable'].join('\n'),
|
||||
description: __("Optional. This setting will be used to filter in various transactions.") },
|
||||
{fieldtype:'Float', fieldname:'tax_rate', label:__('Tax Rate')},
|
||||
{fieldtype:'Link', fieldname:'warehouse', label:__('Warehouse'), options:"Warehouse"}
|
||||
{fieldtype:'Link', fieldname:'warehouse', label:__('Warehouse'), options:"Warehouse"},
|
||||
{fieldtype:'Link', fieldname:'account_currency', label:__('Currency'), options:"Currency",
|
||||
description: __("Optional. Sets company's default currency, if not specified.")}
|
||||
]
|
||||
})
|
||||
|
||||
|
||||
@@ -21,8 +21,7 @@ def get_children():
|
||||
|
||||
# root
|
||||
if args['parent'] in ("Accounts", "Cost Centers"):
|
||||
select_cond = ", root_type, report_type" if args["parent"]=="Accounts" else ""
|
||||
|
||||
select_cond = ", root_type, report_type, account_currency" if ctype=="Account" else ""
|
||||
acc = frappe.db.sql(""" select
|
||||
name as value, is_group as expandable %s
|
||||
from `tab%s`
|
||||
@@ -35,19 +34,17 @@ def get_children():
|
||||
sort_root_accounts(acc)
|
||||
else:
|
||||
# other
|
||||
select_cond = ", account_currency" if ctype=="Account" else ""
|
||||
acc = frappe.db.sql("""select
|
||||
name as value, is_group as expandable
|
||||
name as value, is_group as expandable %s
|
||||
from `tab%s`
|
||||
where ifnull(parent_%s,'') = %s
|
||||
and docstatus<2
|
||||
order by name""" % (ctype, ctype.lower().replace(' ','_'), '%s'),
|
||||
order by name""" % (select_cond, ctype, ctype.lower().replace(' ','_'), '%s'),
|
||||
args['parent'], as_dict=1)
|
||||
|
||||
if ctype == 'Account':
|
||||
currency = frappe.db.sql("select default_currency from `tabCompany` where name = %s", company)[0][0]
|
||||
for each in acc:
|
||||
bal = get_balance_on(each.get("value"))
|
||||
each["currency"] = currency
|
||||
each["balance"] = flt(bal)
|
||||
each["balance"] = flt(get_balance_on(each.get("value")))
|
||||
|
||||
return acc
|
||||
|
||||
@@ -7,9 +7,12 @@ import frappe
|
||||
import datetime
|
||||
from frappe import _, msgprint, scrub
|
||||
from frappe.defaults import get_user_permissions
|
||||
from frappe.utils import add_days, getdate, formatdate, flt, get_first_day, date_diff, nowdate
|
||||
from frappe.utils import add_days, getdate, formatdate, get_first_day, date_diff
|
||||
from erpnext.utilities.doctype.address.address import get_address_display
|
||||
from erpnext.utilities.doctype.contact.contact import get_contact_details
|
||||
from erpnext.exceptions import InvalidAccountCurrency
|
||||
|
||||
class DuplicatePartyAccountError(frappe.ValidationError): pass
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_party_details(party=None, account=None, party_type="Customer", company=None,
|
||||
@@ -17,7 +20,7 @@ def get_party_details(party=None, account=None, party_type="Customer", company=N
|
||||
|
||||
if not party:
|
||||
return {}
|
||||
|
||||
|
||||
if not frappe.db.exists(party_type, party):
|
||||
frappe.throw(_("{0}: {1} does not exists").format(party_type, party))
|
||||
|
||||
@@ -26,7 +29,7 @@ def get_party_details(party=None, account=None, party_type="Customer", company=N
|
||||
|
||||
def _get_party_details(party=None, account=None, party_type="Customer", company=None,
|
||||
posting_date=None, price_list=None, currency=None, doctype=None, ignore_permissions=False):
|
||||
|
||||
|
||||
out = frappe._dict(set_account_and_due_date(party, account, party_type, company, posting_date, doctype))
|
||||
|
||||
party = out[party_type.lower()]
|
||||
@@ -40,6 +43,7 @@ def _get_party_details(party=None, account=None, party_type="Customer", company=
|
||||
set_contact_details(out, party, party_type)
|
||||
set_other_values(out, party, party_type)
|
||||
set_price_list(out, party, party_type, price_list)
|
||||
out["taxes_and_charges"] = set_taxes(party.name, party_type, posting_date, company, out.customer_group, out.supplier_type)
|
||||
|
||||
if not out.get("currency"):
|
||||
out["currency"] = currency
|
||||
@@ -48,8 +52,7 @@ def _get_party_details(party=None, account=None, party_type="Customer", company=
|
||||
if party_type=="Customer":
|
||||
out["sales_team"] = [{
|
||||
"sales_person": d.sales_person,
|
||||
"sales_designation": d.sales_designation,
|
||||
"allocated_percentage": d.allocated_percentage
|
||||
"allocated_percentage": d.allocated_percentage or None
|
||||
} for d in party.get("sales_team")]
|
||||
|
||||
return out
|
||||
@@ -96,11 +99,24 @@ def set_other_values(out, party, party_type):
|
||||
out[f] = party.get(f)
|
||||
|
||||
# fields prepended with default in Customer doctype
|
||||
for f in ['currency', 'taxes_and_charges'] \
|
||||
for f in ['currency'] \
|
||||
+ (['sales_partner', 'commission_rate'] if party_type=="Customer" else []):
|
||||
if party.get("default_" + f):
|
||||
out[f] = party.get("default_" + f)
|
||||
|
||||
def get_default_price_list(party):
|
||||
"""Return default price list for party (Document object)"""
|
||||
if party.default_price_list:
|
||||
return party.default_price_list
|
||||
|
||||
if party.doctype == "Customer":
|
||||
price_list = frappe.db.get_value("Customer Group",
|
||||
party.customer_group, "default_price_list")
|
||||
if price_list:
|
||||
return price_list
|
||||
|
||||
return None
|
||||
|
||||
def set_price_list(out, party, party_type, given_price_list):
|
||||
# price list
|
||||
price_list = filter(None, get_user_permissions().get("Price List", []))
|
||||
@@ -108,11 +124,7 @@ def set_price_list(out, party, party_type, given_price_list):
|
||||
price_list = price_list[0] if len(price_list)==1 else None
|
||||
|
||||
if not price_list:
|
||||
price_list = party.default_price_list
|
||||
|
||||
if not price_list and party_type=="Customer":
|
||||
price_list = frappe.db.get_value("Customer Group",
|
||||
party.customer_group, "default_price_list")
|
||||
price_list = get_default_price_list(party)
|
||||
|
||||
if not price_list:
|
||||
price_list = given_price_list
|
||||
@@ -131,7 +143,7 @@ def set_account_and_due_date(party, account, party_type, company, posting_date,
|
||||
}
|
||||
|
||||
if party:
|
||||
account = get_party_account(company, party, party_type)
|
||||
account = get_party_account(party_type, party, company)
|
||||
|
||||
account_fieldname = "debit_to" if party_type=="Customer" else "credit_to"
|
||||
|
||||
@@ -142,14 +154,21 @@ def set_account_and_due_date(party, account, party_type, company, posting_date,
|
||||
}
|
||||
return out
|
||||
|
||||
def get_company_currency():
|
||||
company_currency = frappe._dict()
|
||||
for d in frappe.get_all("Company", fields=["name", "default_currency"]):
|
||||
company_currency.setdefault(d.name, d.default_currency)
|
||||
|
||||
return company_currency
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_party_account(company, party, party_type):
|
||||
def get_party_account(party_type, party, company):
|
||||
"""Returns the account for the given `party`.
|
||||
Will first search in party (Customer / Supplier) record, if not found,
|
||||
will search in group (Customer Group / Supplier Type),
|
||||
finally will return default."""
|
||||
if not company:
|
||||
frappe.throw(_("Please select company first."))
|
||||
frappe.throw(_("Please select a Company"))
|
||||
|
||||
if party:
|
||||
account = frappe.db.get_value("Party Account",
|
||||
@@ -167,6 +186,51 @@ def get_party_account(company, party, party_type):
|
||||
|
||||
return account
|
||||
|
||||
def get_party_account_currency(party_type, party, company):
|
||||
def generator():
|
||||
party_account = get_party_account(party_type, party, company)
|
||||
return frappe.db.get_value("Account", party_account, "account_currency")
|
||||
|
||||
return frappe.local_cache("party_account_currency", (party_type, party, company), generator)
|
||||
|
||||
def get_party_gle_currency(party_type, party, company):
|
||||
def generator():
|
||||
existing_gle_currency = frappe.db.sql("""select account_currency from `tabGL Entry`
|
||||
where docstatus=1 and company=%(company)s and party_type=%(party_type)s and party=%(party)s
|
||||
limit 1""", { "company": company, "party_type": party_type, "party": party })
|
||||
|
||||
return existing_gle_currency[0][0] if existing_gle_currency else None
|
||||
|
||||
return frappe.local_cache("party_gle_currency", (party_type, party, company), generator,
|
||||
regenerate_if_none=True)
|
||||
|
||||
def validate_party_gle_currency(party_type, party, company, party_account_currency=None):
|
||||
"""Validate party account currency with existing GL Entry's currency"""
|
||||
if not party_account_currency:
|
||||
party_account_currency = get_party_account_currency(party_type, party, company)
|
||||
|
||||
existing_gle_currency = get_party_gle_currency(party_type, party, company)
|
||||
|
||||
if existing_gle_currency and party_account_currency != existing_gle_currency:
|
||||
frappe.throw(_("Accounting Entry for {0}: {1} can only be made in currency: {2}")
|
||||
.format(party_type, party, existing_gle_currency), InvalidAccountCurrency)
|
||||
|
||||
def validate_party_accounts(doc):
|
||||
companies = []
|
||||
|
||||
for account in doc.get("accounts"):
|
||||
if account.company in companies:
|
||||
frappe.throw(_("There can only be 1 Account per Company in {0} {1}")
|
||||
.format(doc.doctype, doc.name), DuplicatePartyAccountError)
|
||||
else:
|
||||
companies.append(account.company)
|
||||
|
||||
party_account_currency = frappe.db.get_value("Account", account.account, "account_currency")
|
||||
existing_gle_currency = get_party_gle_currency(doc.doctype, doc.name, account.company)
|
||||
|
||||
if existing_gle_currency and party_account_currency != existing_gle_currency:
|
||||
frappe.throw(_("Accounting entries have already been made in currency {0} for company {1}. Please select a receivable or payable account with currency {0}.").format(existing_gle_currency, account.company))
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_due_date(posting_date, party_type, party, company):
|
||||
"""Set Due Date = Posting Date + Credit Days"""
|
||||
@@ -183,7 +247,7 @@ def get_due_date(posting_date, party_type, party, company):
|
||||
credit_days = get_credit_days(party_type, party, company)
|
||||
if credit_days:
|
||||
due_date = add_days(posting_date, credit_days)
|
||||
|
||||
|
||||
return due_date
|
||||
|
||||
def get_credit_days(party_type, party, company):
|
||||
@@ -191,30 +255,60 @@ def get_credit_days(party_type, party, company):
|
||||
if party_type == "Customer":
|
||||
credit_days_based_on, credit_days, customer_group = \
|
||||
frappe.db.get_value(party_type, party, ["credit_days_based_on", "credit_days", "customer_group"])
|
||||
|
||||
|
||||
if not credit_days_based_on:
|
||||
credit_days_based_on, credit_days = \
|
||||
frappe.db.get_value("Customer Group", customer_group, ["credit_days_based_on", "credit_days"]) \
|
||||
or frappe.db.get_value("Company", company, ["credit_days_based_on", "credit_days"])
|
||||
|
||||
|
||||
return credit_days_based_on, credit_days
|
||||
else:
|
||||
credit_days, supplier_type = frappe.db.get_value(party_type, party, ["credit_days", "supplier_type"])
|
||||
if not credit_days:
|
||||
credit_days = frappe.db.get_value("Supplier Type", supplier_type, "credit_days") \
|
||||
or frappe.db.get_value("Company", company, "credit_days")
|
||||
|
||||
|
||||
return credit_days
|
||||
|
||||
|
||||
def validate_due_date(posting_date, due_date, party_type, party, company):
|
||||
if getdate(due_date) < getdate(posting_date):
|
||||
frappe.throw(_("Due Date cannot be before Posting Date"))
|
||||
else:
|
||||
default_due_date = get_due_date(posting_date, party_type, party, company)
|
||||
if not default_due_date:
|
||||
return
|
||||
|
||||
if default_due_date != posting_date and getdate(due_date) > getdate(default_due_date):
|
||||
is_credit_controller = frappe.db.get_single_value("Accounts Settings", "credit_controller") in frappe.get_roles()
|
||||
if is_credit_controller:
|
||||
msgprint(_("Note: Due / Reference Date exceeds allowed customer credit days by {0} day(s)")
|
||||
.format(date_diff(due_date, default_due_date)))
|
||||
else:
|
||||
frappe.throw(_("Due / Reference Date cannot be after {0}").format(formatdate(default_due_date)))
|
||||
frappe.throw(_("Due / Reference Date cannot be after {0}").format(formatdate(default_due_date)))
|
||||
|
||||
@frappe.whitelist()
|
||||
def set_taxes(party, party_type, posting_date, company, customer_group=None, supplier_type=None,
|
||||
billing_address=None, shipping_address=None, use_for_shopping_cart=None):
|
||||
from erpnext.accounts.doctype.tax_rule.tax_rule import get_tax_template, get_party_details
|
||||
args = {
|
||||
party_type.lower(): party,
|
||||
"customer_group": customer_group,
|
||||
"supplier_type": supplier_type,
|
||||
"company": company
|
||||
}
|
||||
|
||||
if billing_address or shipping_address:
|
||||
args.update(get_party_details(party, party_type, {"billing_address": billing_address, \
|
||||
"shipping_address": shipping_address }))
|
||||
else:
|
||||
args.update(get_party_details(party, party_type))
|
||||
|
||||
if party_type=="Customer":
|
||||
args.update({"tax_type": "Sales"})
|
||||
else:
|
||||
args.update({"tax_type": "Purchase"})
|
||||
|
||||
if use_for_shopping_cart:
|
||||
args.update({"use_for_shopping_cart": use_for_shopping_cart})
|
||||
|
||||
return get_tax_template(posting_date, args)
|
||||
|
||||
@@ -30,19 +30,47 @@ class ReceivablePayableReport(object):
|
||||
if args.get("party_type") == "Supplier":
|
||||
columns += [_("Bill No") + "::80", _("Bill Date") + ":Date:80"]
|
||||
|
||||
columns += [_("Invoiced Amount") + ":Currency:100", _("Paid Amount") + ":Currency:100",
|
||||
_("Outstanding Amount") + ":Currency:100", _("Age") + ":Int:50",
|
||||
"0-" + str(self.filters.range1) + ":Currency:100",
|
||||
str(self.filters.range1) + "-" + str(self.filters.range2) + ":Currency:100",
|
||||
str(self.filters.range2) + "-" + str(self.filters.range3) + ":Currency:100",
|
||||
str(self.filters.range3) + _("-Above") + ":Currency:100"
|
||||
]
|
||||
for label in ("Invoiced Amount", "Paid Amount", "Outstanding Amount"):
|
||||
columns.append({
|
||||
"label": label,
|
||||
"fieldtype": "Currency",
|
||||
"options": "currency",
|
||||
"width": 120
|
||||
})
|
||||
|
||||
columns += [_("Age (Days)") + ":Int:80"]
|
||||
|
||||
if not "range1" in self.filters:
|
||||
self.filters["range1"] = "30"
|
||||
if not "range2" in self.filters:
|
||||
self.filters["range2"] = "60"
|
||||
if not "range3" in self.filters:
|
||||
self.filters["range3"] = "90"
|
||||
|
||||
for label in ("0-{range1}".format(**self.filters),
|
||||
"{range1}-{range2}".format(**self.filters),
|
||||
"{range2}-{range3}".format(**self.filters),
|
||||
"{range3}-{above}".format(range3=self.filters.range3, above=_("Above"))):
|
||||
columns.append({
|
||||
"label": label,
|
||||
"fieldtype": "Currency",
|
||||
"options": "currency",
|
||||
"width": 120
|
||||
})
|
||||
|
||||
if args.get("party_type") == "Customer":
|
||||
columns += [_("Territory") + ":Link/Territory:80"]
|
||||
if args.get("party_type") == "Supplier":
|
||||
columns += [_("Supplier Type") + ":Link/Supplier Type:80"]
|
||||
columns += [_("Remarks") + "::200"]
|
||||
columns += [
|
||||
{
|
||||
"fieldname": "currency",
|
||||
"label": _("Currency"),
|
||||
"fieldtype": "Data",
|
||||
"width": 100,
|
||||
},
|
||||
_("Remarks") + "::200"
|
||||
]
|
||||
|
||||
return columns
|
||||
|
||||
@@ -55,6 +83,8 @@ class ReceivablePayableReport(object):
|
||||
|
||||
future_vouchers = self.get_entries_after(self.filters.report_date, args.get("party_type"))
|
||||
|
||||
company_currency = frappe.db.get_value("Company", self.filters.get("company"), "default_currency")
|
||||
|
||||
data = []
|
||||
for gle in self.get_entries_till(self.filters.report_date, args.get("party_type")):
|
||||
if self.is_receivable_or_payable(gle, dr_or_cr, future_vouchers):
|
||||
@@ -91,10 +121,16 @@ class ReceivablePayableReport(object):
|
||||
|
||||
# customer territory / supplier type
|
||||
if args.get("party_type") == "Customer":
|
||||
row += [self.get_territory(gle.party), gle.remarks]
|
||||
row += [self.get_territory(gle.party)]
|
||||
if args.get("party_type") == "Supplier":
|
||||
row += [self.get_supplier_type(gle.party), gle.remarks]
|
||||
row += [self.get_supplier_type(gle.party)]
|
||||
|
||||
if self.filters.get(scrub(args.get("party_type"))):
|
||||
row.append(gle.account_currency)
|
||||
else:
|
||||
row.append(company_currency)
|
||||
|
||||
row.append(gle.remarks)
|
||||
data.append(row)
|
||||
|
||||
return data
|
||||
@@ -155,7 +191,7 @@ class ReceivablePayableReport(object):
|
||||
|
||||
def get_voucher_details(self, party_type):
|
||||
voucher_details = frappe._dict()
|
||||
|
||||
|
||||
if party_type == "Customer":
|
||||
for si in frappe.db.sql("""select name, due_date
|
||||
from `tabSales Invoice` where docstatus=1""", as_dict=1):
|
||||
@@ -171,17 +207,25 @@ class ReceivablePayableReport(object):
|
||||
def get_gl_entries(self, party_type):
|
||||
if not hasattr(self, "gl_entries"):
|
||||
conditions, values = self.prepare_conditions(party_type)
|
||||
self.gl_entries = frappe.db.sql("""select name, posting_date, account, party_type, party, debit, credit,
|
||||
voucher_type, voucher_no, against_voucher_type, against_voucher from `tabGL Entry`
|
||||
where docstatus < 2 and party_type=%s {0} order by posting_date, party"""
|
||||
.format(conditions), values, as_dict=True)
|
||||
|
||||
if self.filters.get(scrub(party_type)):
|
||||
select_fields = "debit_in_account_currency as debit, credit_in_account_currency as credit"
|
||||
else:
|
||||
select_fields = "debit, credit"
|
||||
|
||||
self.gl_entries = frappe.db.sql("""select name, posting_date, account, party_type, party,
|
||||
voucher_type, voucher_no, against_voucher_type, against_voucher, account_currency, remarks, {0}
|
||||
from `tabGL Entry`
|
||||
where docstatus < 2 and party_type=%s and ifnull(party, '') != '' {1}
|
||||
order by posting_date, party"""
|
||||
.format(select_fields, conditions), values, as_dict=True)
|
||||
|
||||
return self.gl_entries
|
||||
|
||||
def prepare_conditions(self, party_type):
|
||||
conditions = [""]
|
||||
values = [party_type]
|
||||
|
||||
|
||||
party_type_field = scrub(party_type)
|
||||
|
||||
if self.filters.company:
|
||||
@@ -190,7 +234,7 @@ class ReceivablePayableReport(object):
|
||||
|
||||
if self.filters.get(party_type_field):
|
||||
conditions.append("party=%s")
|
||||
values.append(self.filters.get(party_type_field))
|
||||
values.append(self.filters.get(party_type_field))
|
||||
|
||||
return " and ".join(conditions), values
|
||||
|
||||
|
||||
@@ -23,7 +23,8 @@ def execute(filters=None):
|
||||
total_debit += flt(d[2])
|
||||
total_credit += flt(d[3])
|
||||
|
||||
amounts_not_reflected_in_system = frappe.db.sql("""select sum(ifnull(jvd.debit, 0) - ifnull(jvd.credit, 0))
|
||||
amounts_not_reflected_in_system = frappe.db.sql("""
|
||||
select sum(ifnull(jvd.debit_in_account_currency, 0) - ifnull(jvd.credit_in_account_currency, 0))
|
||||
from `tabJournal Entry Account` jvd, `tabJournal Entry` jv
|
||||
where jvd.parent = jv.name and jv.docstatus=1 and jvd.account=%s
|
||||
and jv.posting_date > %s and jv.clearance_date <= %s and ifnull(jv.is_opening, 'No') = 'No'
|
||||
@@ -38,7 +39,7 @@ def execute(filters=None):
|
||||
data += [
|
||||
get_balance_row(_("System Balance"), balance_as_per_system),
|
||||
[""]*len(columns),
|
||||
["", '"' + _("Amounts not reflected in bank") + '"', total_debit, total_credit, "", "", "", ""],
|
||||
["", '"' + _("Amounts not reflected in bank") + '"', total_debit, total_credit, "", "", "", "", ""],
|
||||
get_balance_row(_("Amounts not reflected in system"), amounts_not_reflected_in_system),
|
||||
[""]*len(columns),
|
||||
get_balance_row(_("Expected balance as per bank"), bank_bal)
|
||||
@@ -49,13 +50,14 @@ def execute(filters=None):
|
||||
def get_columns():
|
||||
return [_("Posting Date") + ":Date:100", _("Journal Entry") + ":Link/Journal Entry:220",
|
||||
_("Debit") + ":Currency:120", _("Credit") + ":Currency:120",
|
||||
_("Against Account") + ":Link/Account:200", _("Reference") + "::100", _("Ref Date") + ":Date:110", _("Clearance Date") + ":Date:110"
|
||||
_("Against Account") + ":Link/Account:200", _("Reference") + "::100",
|
||||
_("Ref Date") + ":Date:110", _("Clearance Date") + ":Date:110", _("Currency") + ":Link/Currency:70"
|
||||
]
|
||||
|
||||
def get_entries(filters):
|
||||
entries = frappe.db.sql("""select
|
||||
jv.posting_date, jv.name, jvd.debit, jvd.credit,
|
||||
jvd.against_account, jv.cheque_no, jv.cheque_date, jv.clearance_date
|
||||
jv.posting_date, jv.name, jvd.debit_in_account_currency, jvd.credit_in_account_currency,
|
||||
jvd.against_account, jv.cheque_no, jv.cheque_date, jv.clearance_date, jvd.account_currency
|
||||
from
|
||||
`tabJournal Entry Account` jvd, `tabJournal Entry` jv
|
||||
where jvd.parent = jv.name and jv.docstatus=1
|
||||
@@ -68,6 +70,6 @@ def get_entries(filters):
|
||||
|
||||
def get_balance_row(label, amount):
|
||||
if amount > 0:
|
||||
return ["", '"' + label + '"', amount, 0, "", "", "", ""]
|
||||
return ["", '"' + label + '"', amount, 0, "", "", "", "", ""]
|
||||
else:
|
||||
return ["", '"' + label + '"', 0, abs(amount), "", "", "", ""]
|
||||
return ["", '"' + label + '"', 0, abs(amount), "", "", "", "", ""]
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
{
|
||||
"add_total_row": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"creation": "2013-07-30 17:28:49",
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"idx": 1,
|
||||
"is_standard": "Yes",
|
||||
"modified": "2015-03-30 05:33:45.353064",
|
||||
"modified": "2015-11-02 12:32:02.048551",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Delivered Items To Be Billed",
|
||||
"owner": "Administrator",
|
||||
"query": "select\n `tabDelivery Note`.`name` as \"Delivery Note:Link/Delivery Note:120\",\n\t`tabDelivery Note`.`customer` as \"Customer:Link/Customer:120\",\n\t`tabDelivery Note`.`posting_date` as \"Date:Date\",\n\t`tabDelivery Note`.`project_name` as \"Project\",\n\t`tabDelivery Note Item`.`item_code` as \"Item:Link/Item:120\",\n\t(`tabDelivery Note Item`.`qty` - ifnull((select sum(qty) from `tabSales Invoice Item` \n\t where `tabSales Invoice Item`.docstatus=1 and \n `tabSales Invoice Item`.delivery_note = `tabDelivery Note`.name and\n\t `tabSales Invoice Item`.dn_detail = `tabDelivery Note Item`.name), 0))\n\t\tas \"Qty:Float:110\",\n\t(`tabDelivery Note Item`.`base_amount` - ifnull((select sum(base_amount) from `tabSales Invoice Item` \n where `tabSales Invoice Item`.docstatus=1 and \n `tabSales Invoice Item`.delivery_note = `tabDelivery Note`.name and\n `tabSales Invoice Item`.dn_detail = `tabDelivery Note Item`.name), 0))\n\t\tas \"Amount:Currency:110\",\n\t`tabDelivery Note Item`.`item_name` as \"Item Name::150\",\n\t`tabDelivery Note Item`.`description` as \"Description::200\",\n\t`tabDelivery Note`.`company` as \"Company:Link/Company:\"\nfrom `tabDelivery Note`, `tabDelivery Note Item`\nwhere\n `tabDelivery Note`.docstatus = 1 and\n\t`tabDelivery Note`.`status` != \"Stopped\" and\n `tabDelivery Note`.name = `tabDelivery Note Item`.parent and\n (`tabDelivery Note Item`.qty > ifnull((select sum(qty) from `tabSales Invoice Item` \n where `tabSales Invoice Item`.docstatus=1 and \n `tabSales Invoice Item`.delivery_note = `tabDelivery Note`.name and\n `tabSales Invoice Item`.dn_detail = `tabDelivery Note Item`.name), 0))\norder by `tabDelivery Note`.`name` desc",
|
||||
"query": "select\n `tabDelivery Note`.`name` as \"Delivery Note:Link/Delivery Note:120\",\n\t`tabDelivery Note`.`customer` as \"Customer:Link/Customer:120\",\n\t`tabDelivery Note`.`posting_date` as \"Date:Date\",\n\t`tabDelivery Note`.`project_name` as \"Project\",\n\t`tabDelivery Note Item`.`item_code` as \"Item:Link/Item:120\",\n\t(`tabDelivery Note Item`.`qty` - ifnull((select sum(qty) from `tabSales Invoice Item` \n\t where `tabSales Invoice Item`.docstatus=1 and \n `tabSales Invoice Item`.delivery_note = `tabDelivery Note`.name and\n\t `tabSales Invoice Item`.dn_detail = `tabDelivery Note Item`.name), 0))\n\t\tas \"Qty:Float:110\",\n\t(`tabDelivery Note Item`.`base_amount` - ifnull((select sum(base_amount) from `tabSales Invoice Item` \n where `tabSales Invoice Item`.docstatus=1 and \n `tabSales Invoice Item`.delivery_note = `tabDelivery Note`.name and\n `tabSales Invoice Item`.dn_detail = `tabDelivery Note Item`.name), 0))\n\t\tas \"Amount:Currency:110\",\n\t`tabDelivery Note Item`.`item_name` as \"Item Name::150\",\n\t`tabDelivery Note Item`.`description` as \"Description::200\",\n\t`tabDelivery Note`.`company` as \"Company:Link/Company:\"\nfrom `tabDelivery Note`, `tabDelivery Note Item`\nwhere\n `tabDelivery Note`.docstatus = 1 and\n\t`tabDelivery Note`.`status` not in (\"Stopped\", \"Closed\") and\n `tabDelivery Note`.name = `tabDelivery Note Item`.parent and\n (`tabDelivery Note Item`.qty > ifnull((select sum(qty) from `tabSales Invoice Item` \n where `tabSales Invoice Item`.docstatus=1 and \n `tabSales Invoice Item`.delivery_note = `tabDelivery Note`.name and\n `tabSales Invoice Item`.dn_detail = `tabDelivery Note Item`.name), 0))\norder by `tabDelivery Note`.`name` desc",
|
||||
"ref_doctype": "Sales Invoice",
|
||||
"report_name": "Delivered Items To Be Billed",
|
||||
"report_type": "Query Report"
|
||||
|
||||
@@ -5,6 +5,7 @@ from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.utils import flt, getdate, cstr
|
||||
from frappe import _
|
||||
from erpnext.accounts.utils import get_account_currency
|
||||
|
||||
def execute(filters=None):
|
||||
account_details = {}
|
||||
@@ -12,9 +13,12 @@ def execute(filters=None):
|
||||
account_details.setdefault(acc.name, acc)
|
||||
|
||||
validate_filters(filters, account_details)
|
||||
|
||||
validate_party(filters)
|
||||
|
||||
columns = get_columns()
|
||||
filters = set_account_currency(filters)
|
||||
|
||||
columns = get_columns(filters)
|
||||
|
||||
res = get_result(filters, account_details)
|
||||
|
||||
@@ -44,35 +48,76 @@ def validate_party(filters):
|
||||
elif not frappe.db.exists(party_type, party):
|
||||
frappe.throw(_("Invalid {0}: {1}").format(party_type, party))
|
||||
|
||||
def get_columns():
|
||||
return [_("Posting Date") + ":Date:90", _("Account") + ":Link/Account:200",
|
||||
_("Debit") + ":Float:100", _("Credit") + ":Float:100",
|
||||
def set_account_currency(filters):
|
||||
if not (filters.get("account") or filters.get("party")):
|
||||
return filters
|
||||
else:
|
||||
filters["company_currency"] = frappe.db.get_value("Company", filters.company, "default_currency")
|
||||
account_currency = None
|
||||
|
||||
if filters.get("account"):
|
||||
account_currency = get_account_currency(filters.account)
|
||||
elif filters.get("party"):
|
||||
gle_currency = frappe.db.get_value("GL Entry", {"party_type": filters.party_type,
|
||||
"party": filters.party, "company": filters.company}, "account_currency")
|
||||
if gle_currency:
|
||||
account_currency = gle_currency
|
||||
else:
|
||||
account_currency = frappe.db.get_value(filters.party_type, filters.party, "default_currency")
|
||||
|
||||
filters["account_currency"] = account_currency or filters.company_currency
|
||||
|
||||
if filters.account_currency != filters.company_currency:
|
||||
filters["show_in_account_currency"] = 1
|
||||
|
||||
return filters
|
||||
|
||||
def get_columns(filters):
|
||||
columns = [
|
||||
_("Posting Date") + ":Date:90", _("Account") + ":Link/Account:200",
|
||||
_("Debit") + ":Float:100", _("Credit") + ":Float:100"
|
||||
]
|
||||
|
||||
if filters.get("show_in_account_currency"):
|
||||
columns += [
|
||||
_("Debit") + " (" + filters.account_currency + ")" + ":Float:100",
|
||||
_("Credit") + " (" + filters.account_currency + ")" + ":Float:100"
|
||||
]
|
||||
|
||||
columns += [
|
||||
_("Voucher Type") + "::120", _("Voucher No") + ":Dynamic Link/Voucher Type:160",
|
||||
_("Against Account") + "::120", _("Party Type") + "::80", _("Party") + "::150",
|
||||
_("Cost Center") + ":Link/Cost Center:100", _("Remarks") + "::400"]
|
||||
_("Cost Center") + ":Link/Cost Center:100", _("Remarks") + "::400"
|
||||
]
|
||||
|
||||
return columns
|
||||
|
||||
def get_result(filters, account_details):
|
||||
gl_entries = get_gl_entries(filters)
|
||||
|
||||
data = get_data_with_opening_closing(filters, account_details, gl_entries)
|
||||
|
||||
result = get_result_as_list(data)
|
||||
result = get_result_as_list(data, filters)
|
||||
|
||||
return result
|
||||
|
||||
def get_gl_entries(filters):
|
||||
select_fields = """, sum(ifnull(debit_in_account_currency, 0)) as debit_in_account_currency,
|
||||
sum(ifnull(credit_in_account_currency, 0)) as credit_in_account_currency""" \
|
||||
if filters.get("show_in_account_currency") else ""
|
||||
|
||||
group_by_condition = "group by voucher_type, voucher_no, account, cost_center" \
|
||||
if filters.get("group_by_voucher") else "group by name"
|
||||
|
||||
gl_entries = frappe.db.sql("""select posting_date, account, party_type, party,
|
||||
sum(ifnull(debit, 0)) as debit, sum(ifnull(credit, 0)) as credit,
|
||||
voucher_type, voucher_no, cost_center, remarks, against, is_opening
|
||||
voucher_type, voucher_no, cost_center, remarks, against, is_opening {select_fields}
|
||||
from `tabGL Entry`
|
||||
where company=%(company)s {conditions}
|
||||
{group_by_condition}
|
||||
order by posting_date, account"""\
|
||||
.format(conditions=get_conditions(filters), group_by_condition=group_by_condition),
|
||||
filters, as_dict=1)
|
||||
.format(select_fields=select_fields, conditions=get_conditions(filters),
|
||||
group_by_condition=group_by_condition), filters, as_dict=1)
|
||||
|
||||
return gl_entries
|
||||
|
||||
@@ -91,7 +136,7 @@ def get_conditions(filters):
|
||||
|
||||
if filters.get("party"):
|
||||
conditions.append("party=%(party)s")
|
||||
|
||||
|
||||
if not (filters.get("account") or filters.get("party") or filters.get("group_by_account")):
|
||||
conditions.append("posting_date >=%(from_date)s")
|
||||
|
||||
@@ -105,35 +150,56 @@ def get_data_with_opening_closing(filters, account_details, gl_entries):
|
||||
data = []
|
||||
gle_map = initialize_gle_map(gl_entries)
|
||||
|
||||
opening, total_debit, total_credit, gle_map = get_accountwise_gle(filters, gl_entries, gle_map)
|
||||
opening, total_debit, total_credit, opening_in_account_currency, total_debit_in_account_currency, \
|
||||
total_credit_in_account_currency, gle_map = get_accountwise_gle(filters, gl_entries, gle_map)
|
||||
|
||||
# Opening for filtered account
|
||||
if filters.get("account") or filters.get("party"):
|
||||
data += [get_balance_row(_("Opening"), opening), {}]
|
||||
data += [get_balance_row(_("Opening"), opening, opening_in_account_currency), {}]
|
||||
|
||||
for acc, acc_dict in gle_map.items():
|
||||
if acc_dict.entries:
|
||||
# Opening for individual ledger, if grouped by account
|
||||
if filters.get("group_by_account"):
|
||||
data.append(get_balance_row(_("Opening"), acc_dict.opening))
|
||||
if filters.get("group_by_account"):
|
||||
for acc, acc_dict in gle_map.items():
|
||||
if acc_dict.entries:
|
||||
# Opening for individual ledger, if grouped by account
|
||||
data.append(get_balance_row(_("Opening"), acc_dict.opening,
|
||||
acc_dict.opening_in_account_currency))
|
||||
|
||||
data += acc_dict.entries
|
||||
data += acc_dict.entries
|
||||
|
||||
# Totals and closing for individual ledger, if grouped by account
|
||||
account_closing = acc_dict.opening + acc_dict.total_debit - acc_dict.total_credit
|
||||
account_closing_in_account_currency = acc_dict.opening_in_account_currency \
|
||||
+ acc_dict.total_debit_in_account_currency - acc_dict.total_credit_in_account_currency
|
||||
|
||||
# Totals and closing for individual ledger, if grouped by account
|
||||
if filters.get("group_by_account"):
|
||||
data += [{"account": "'" + _("Totals") + "'", "debit": acc_dict.total_debit,
|
||||
"credit": acc_dict.total_credit},
|
||||
get_balance_row(_("Closing (Opening + Totals)"),
|
||||
(acc_dict.opening + acc_dict.total_debit - acc_dict.total_credit)), {}]
|
||||
account_closing, account_closing_in_account_currency), {}]
|
||||
|
||||
else:
|
||||
for gl in gl_entries:
|
||||
if gl.posting_date >= getdate(filters.from_date) and gl.posting_date <= getdate(filters.to_date):
|
||||
data.append(gl)
|
||||
|
||||
|
||||
# Total debit and credit between from and to date
|
||||
if total_debit or total_credit:
|
||||
data.append({"account": "'" + _("Totals") + "'", "debit": total_debit, "credit": total_credit})
|
||||
data.append({
|
||||
"account": "'" + _("Totals") + "'",
|
||||
"debit": total_debit,
|
||||
"credit": total_credit,
|
||||
"debit_in_account_currency": total_debit_in_account_currency,
|
||||
"credit_in_account_currency": total_credit_in_account_currency
|
||||
})
|
||||
|
||||
# Closing for filtered account
|
||||
if filters.get("account") or filters.get("party"):
|
||||
closing = opening + total_debit - total_credit
|
||||
closing_in_account_currency = opening_in_account_currency + \
|
||||
total_debit_in_account_currency - total_credit_in_account_currency
|
||||
|
||||
data.append(get_balance_row(_("Closing (Opening + Totals)"),
|
||||
(opening + total_debit - total_credit)))
|
||||
closing, closing_in_account_currency))
|
||||
|
||||
return data
|
||||
|
||||
@@ -142,23 +208,38 @@ def initialize_gle_map(gl_entries):
|
||||
for gle in gl_entries:
|
||||
gle_map.setdefault(gle.account, frappe._dict({
|
||||
"opening": 0,
|
||||
"opening_in_account_currency": 0,
|
||||
"entries": [],
|
||||
"total_debit": 0,
|
||||
"total_debit_in_account_currency": 0,
|
||||
"total_credit": 0,
|
||||
"closing": 0
|
||||
"total_credit_in_account_currency": 0,
|
||||
"closing": 0,
|
||||
"closing_in_account_currency": 0
|
||||
}))
|
||||
return gle_map
|
||||
|
||||
def get_accountwise_gle(filters, gl_entries, gle_map):
|
||||
opening, total_debit, total_credit = 0, 0, 0
|
||||
opening_in_account_currency, total_debit_in_account_currency, total_credit_in_account_currency = 0, 0, 0
|
||||
|
||||
from_date, to_date = getdate(filters.from_date), getdate(filters.to_date)
|
||||
for gle in gl_entries:
|
||||
amount = flt(gle.debit, 3) - flt(gle.credit, 3)
|
||||
amount_in_account_currency = flt(gle.debit_in_account_currency, 3) - flt(gle.credit_in_account_currency, 3)
|
||||
|
||||
if (filters.get("account") or filters.get("party") or filters.get("group_by_account")) \
|
||||
and (gle.posting_date < from_date or cstr(gle.is_opening) == "Yes"):
|
||||
|
||||
gle_map[gle.account].opening += amount
|
||||
if filters.get("show_in_account_currency"):
|
||||
gle_map[gle.account].opening_in_account_currency += amount_in_account_currency
|
||||
|
||||
if filters.get("account") or filters.get("party"):
|
||||
opening += amount
|
||||
if filters.get("show_in_account_currency"):
|
||||
opening_in_account_currency += amount_in_account_currency
|
||||
|
||||
elif gle.posting_date <= to_date:
|
||||
gle_map[gle.account].entries.append(gle)
|
||||
gle_map[gle.account].total_debit += flt(gle.debit, 3)
|
||||
@@ -167,21 +248,43 @@ def get_accountwise_gle(filters, gl_entries, gle_map):
|
||||
total_debit += flt(gle.debit, 3)
|
||||
total_credit += flt(gle.credit, 3)
|
||||
|
||||
return opening, total_debit, total_credit, gle_map
|
||||
if filters.get("show_in_account_currency"):
|
||||
gle_map[gle.account].total_debit_in_account_currency += flt(gle.debit_in_account_currency, 3)
|
||||
gle_map[gle.account].total_credit_in_account_currency += flt(gle.credit_in_account_currency, 3)
|
||||
|
||||
def get_balance_row(label, balance):
|
||||
return {
|
||||
total_debit_in_account_currency += flt(gle.debit_in_account_currency, 3)
|
||||
total_credit_in_account_currency += flt(gle.credit_in_account_currency, 3)
|
||||
|
||||
return opening, total_debit, total_credit, opening_in_account_currency, \
|
||||
total_debit_in_account_currency, total_credit_in_account_currency, gle_map
|
||||
|
||||
def get_balance_row(label, balance, balance_in_account_currency=None):
|
||||
balance_row = {
|
||||
"account": "'" + label + "'",
|
||||
"debit": balance if balance > 0 else 0,
|
||||
"credit": -1*balance if balance < 0 else 0,
|
||||
"credit": -1*balance if balance < 0 else 0
|
||||
}
|
||||
|
||||
def get_result_as_list(data):
|
||||
if balance_in_account_currency != None:
|
||||
balance_row.update({
|
||||
"debit_in_account_currency": balance_in_account_currency if balance_in_account_currency > 0 else 0,
|
||||
"credit_in_account_currency": -1*balance_in_account_currency if balance_in_account_currency < 0 else 0
|
||||
})
|
||||
|
||||
return balance_row
|
||||
|
||||
def get_result_as_list(data, filters):
|
||||
result = []
|
||||
for d in data:
|
||||
result.append([d.get("posting_date"), d.get("account"), d.get("debit"),
|
||||
d.get("credit"), d.get("voucher_type"), d.get("voucher_no"),
|
||||
d.get("against"), d.get("party_type"), d.get("party"),
|
||||
d.get("cost_center"), d.get("remarks")])
|
||||
row = [d.get("posting_date"), d.get("account"), d.get("debit"), d.get("credit")]
|
||||
|
||||
if filters.get("show_in_account_currency"):
|
||||
row += [d.get("debit_in_account_currency"), d.get("credit_in_account_currency")]
|
||||
|
||||
row += [d.get("voucher_type"), d.get("voucher_no"), d.get("against"),
|
||||
d.get("party_type"), d.get("party"), d.get("cost_center"), d.get("remarks")
|
||||
]
|
||||
|
||||
result.append(row)
|
||||
|
||||
return result
|
||||
|
||||
@@ -98,11 +98,17 @@ class GrossProfitGenerator(object):
|
||||
|
||||
row.base_amount = flt(row.base_net_amount)
|
||||
|
||||
product_bundles = self.product_bundles.get(row.parenttype, {}).get(row.parent, frappe._dict())
|
||||
|
||||
if row.update_stock:
|
||||
product_bundles = self.product_bundles.get(row.parenttype, {}).get(row.parent, frappe._dict())
|
||||
elif row.dn_detail:
|
||||
product_bundles = self.product_bundles.get("Delivery Note", {})\
|
||||
.get(row.delivery_note, frappe._dict())
|
||||
row.item_row = row.dn_detail
|
||||
|
||||
# get buying amount
|
||||
if row.item_code in product_bundles:
|
||||
row.buying_amount = self.get_buying_amount_from_product_bundle(row, product_bundles[row.item_code])
|
||||
row.buying_amount = self.get_buying_amount_from_product_bundle(row,
|
||||
product_bundles[row.item_code])
|
||||
else:
|
||||
row.buying_amount = self.get_buying_amount(row, row.item_code)
|
||||
|
||||
@@ -142,7 +148,6 @@ class GrossProfitGenerator(object):
|
||||
new_row.qty += row.qty
|
||||
new_row.buying_amount += row.buying_amount
|
||||
new_row.base_amount += row.base_amount
|
||||
# new_row.allocated_amount += (row.allocated_amount or 0) if new_row.allocated_amount else 0
|
||||
|
||||
new_row.gross_profit = new_row.base_amount - new_row.buying_amount
|
||||
new_row.gross_profit_percent = ((new_row.gross_profit / new_row.base_amount) * 100.0) \
|
||||
@@ -158,9 +163,9 @@ class GrossProfitGenerator(object):
|
||||
|
||||
def get_buying_amount_from_product_bundle(self, row, product_bundle):
|
||||
buying_amount = 0.0
|
||||
for bom_item in product_bundle:
|
||||
if bom_item.get("parent_detail_docname")==row.item_row:
|
||||
buying_amount += self.get_buying_amount(row, bom_item.item_code)
|
||||
for packed_item in product_bundle:
|
||||
if packed_item.get("parent_detail_docname")==row.item_row:
|
||||
buying_amount += self.get_buying_amount(row, packed_item.item_code)
|
||||
|
||||
return buying_amount
|
||||
|
||||
@@ -176,14 +181,14 @@ class GrossProfitGenerator(object):
|
||||
else:
|
||||
my_sle = self.sle.get((item_code, row.warehouse))
|
||||
if (row.update_stock or row.dn_detail) and my_sle:
|
||||
parenttype, parent, item_row = row.parenttype, row.parent, row.item_row
|
||||
parenttype, parent = row.parenttype, row.parent
|
||||
if row.dn_detail:
|
||||
parenttype, parent, item_row = "Delivery Note", row.delivery_note, row.dn_detail
|
||||
parenttype, parent = "Delivery Note", row.delivery_note
|
||||
|
||||
for i, sle in enumerate(my_sle):
|
||||
# find the stock valution rate from stock ledger entry
|
||||
if sle.voucher_type == parenttype and parent == sle.voucher_no and \
|
||||
sle.voucher_detail_no == item_row:
|
||||
sle.voucher_detail_no == row.item_row:
|
||||
previous_stock_value = len(my_sle) > i+1 and \
|
||||
flt(my_sle[i+1].stock_value) or 0.0
|
||||
return previous_stock_value - flt(sle.stock_value)
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
{
|
||||
"add_total_row": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"creation": "2013-02-21 14:26:44",
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"idx": 1,
|
||||
"is_standard": "Yes",
|
||||
"modified": "2015-03-30 05:33:29.382709",
|
||||
"modified": "2015-11-04 11:56:32.699103",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Ordered Items To Be Billed",
|
||||
"owner": "Administrator",
|
||||
"query": "select \n `tabSales Order`.`name` as \"Sales Order:Link/Sales Order:120\",\n `tabSales Order`.`customer` as \"Customer:Link/Customer:120\",\n `tabSales Order`.`status` as \"Status\",\n `tabSales Order`.`transaction_date` as \"Date:Date\",\n `tabSales Order`.`project_name` as \"Project\",\n `tabSales Order Item`.item_code as \"Item:Link/Item:120\",\n `tabSales Order Item`.base_amount as \"Amount:Currency:110\",\n (`tabSales Order Item`.billed_amt * ifnull(`tabSales Order`.conversion_rate, 1)) as \"Billed Amount:Currency:110\",\n (ifnull(`tabSales Order Item`.base_amount, 0) - (ifnull(`tabSales Order Item`.billed_amt, 0) * ifnull(`tabSales Order`.conversion_rate, 1))) as \"Pending Amount:Currency:120\",\n `tabSales Order Item`.item_name as \"Item Name::150\",\n `tabSales Order Item`.description as \"Description::200\",\n `tabSales Order`.`company` as \"Company:Link/Company:\"\nfrom\n `tabSales Order`, `tabSales Order Item`\nwhere\n `tabSales Order Item`.`parent` = `tabSales Order`.`name`\n and `tabSales Order`.docstatus = 1\n and `tabSales Order`.status != \"Stopped\"\n and ifnull(`tabSales Order Item`.billed_amt,0) < ifnull(`tabSales Order Item`.amount,0)\norder by `tabSales Order`.transaction_date asc",
|
||||
"query": "select \n `tabSales Order`.`name` as \"Sales Order:Link/Sales Order:120\",\n `tabSales Order`.`customer` as \"Customer:Link/Customer:120\",\n `tabSales Order`.`status` as \"Status\",\n `tabSales Order`.`transaction_date` as \"Date:Date\",\n `tabSales Order`.`project_name` as \"Project\",\n `tabSales Order Item`.item_code as \"Item:Link/Item:120\",\n `tabSales Order Item`.base_amount as \"Amount:Currency:110\",\n (`tabSales Order Item`.billed_amt * ifnull(`tabSales Order`.conversion_rate, 1)) as \"Billed Amount:Currency:110\",\n (ifnull(`tabSales Order Item`.base_amount, 0) - (ifnull(`tabSales Order Item`.billed_amt, 0) * ifnull(`tabSales Order`.conversion_rate, 1))) as \"Pending Amount:Currency:120\",\n `tabSales Order Item`.item_name as \"Item Name::150\",\n `tabSales Order Item`.description as \"Description::200\",\n `tabSales Order`.`company` as \"Company:Link/Company:\"\nfrom\n `tabSales Order`, `tabSales Order Item`\nwhere\n `tabSales Order Item`.`parent` = `tabSales Order`.`name`\n and `tabSales Order`.docstatus = 1\n and `tabSales Order`.status not in (\"Stopped\", \"Closed\")\n and ifnull(`tabSales Order Item`.billed_amt,0) < ifnull(`tabSales Order Item`.amount,0)\norder by `tabSales Order`.transaction_date asc",
|
||||
"ref_doctype": "Sales Invoice",
|
||||
"report_name": "Ordered Items To Be Billed",
|
||||
"report_type": "Query Report"
|
||||
|
||||
@@ -5,7 +5,7 @@ from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from erpnext.accounts.report.accounts_receivable.accounts_receivable import get_ageing_data
|
||||
from frappe.utils import flt
|
||||
from frappe.utils import flt, getdate
|
||||
|
||||
def execute(filters=None):
|
||||
if not filters: filters = {}
|
||||
@@ -13,25 +13,27 @@ def execute(filters=None):
|
||||
|
||||
columns = get_columns(filters)
|
||||
entries = get_entries(filters)
|
||||
invoice_posting_date_map = get_invoice_posting_date_map(filters)
|
||||
invoice_details = get_invoice_posting_date_map(filters)
|
||||
against_date = ""
|
||||
|
||||
data = []
|
||||
for d in entries:
|
||||
against_date = invoice_posting_date_map.get(d.reference_name) or ""
|
||||
invoice = invoice_details.get(d.reference_name) or frappe._dict()
|
||||
if d.reference_type=="Purchase Invoice":
|
||||
payment_amount = flt(d.debit) or -1 * flt(d.credit)
|
||||
else:
|
||||
payment_amount = flt(d.credit) or -1 * flt(d.debit)
|
||||
|
||||
row = [d.name, d.party_type, d.party, d.posting_date, d.reference_name,
|
||||
against_date, d.debit, d.credit, d.cheque_no, d.cheque_date, d.remark]
|
||||
row = [d.name, d.party_type, d.party, d.posting_date, d.reference_name, invoice.posting_date,
|
||||
invoice.due_date, d.debit, d.credit, d.cheque_no, d.cheque_date, d.remark]
|
||||
|
||||
if d.reference_name:
|
||||
row += get_ageing_data(30, 60, 90, d.posting_date, against_date, payment_amount)
|
||||
else:
|
||||
row += ["", "", "", "", ""]
|
||||
|
||||
if invoice.due_date:
|
||||
row.append((getdate(d.posting_date) - getdate(invoice.due_date)).days or 0)
|
||||
|
||||
data.append(row)
|
||||
|
||||
return columns, data
|
||||
@@ -43,13 +45,25 @@ def validate_filters(filters):
|
||||
.format(filters.payment_type, filters.party_type))
|
||||
|
||||
def get_columns(filters):
|
||||
return [_("Journal Entry") + ":Link/Journal Entry:140",
|
||||
_("Party Type") + "::100", _("Party") + ":Dynamic Link/Party Type:140",
|
||||
return [
|
||||
_("Journal Entry") + ":Link/Journal Entry:140",
|
||||
_("Party Type") + "::100",
|
||||
_("Party") + ":Dynamic Link/Party Type:140",
|
||||
_("Posting Date") + ":Date:100",
|
||||
_("Against Invoice") + (":Link/Purchase Invoice:130" if filters.get("payment_type") == "Outgoing" else ":Link/Sales Invoice:130"),
|
||||
_("Against Invoice Posting Date") + ":Date:130", _("Debit") + ":Currency:120", _("Credit") + ":Currency:120",
|
||||
_("Reference No") + "::100", _("Reference Date") + ":Date:100", _("Remarks") + "::150", _("Age") +":Int:40",
|
||||
"0-30:Currency:100", "30-60:Currency:100", "60-90:Currency:100", _("90-Above") + ":Currency:100"
|
||||
_("Invoice") + (":Link/Purchase Invoice:130" if filters.get("payment_type") == "Outgoing" else ":Link/Sales Invoice:130"),
|
||||
_("Invoice Posting Date") + ":Date:130",
|
||||
_("Payment Due Date") + ":Date:130",
|
||||
_("Debit") + ":Currency:120",
|
||||
_("Credit") + ":Currency:120",
|
||||
_("Reference No") + "::100",
|
||||
_("Reference Date") + ":Date:100",
|
||||
_("Remarks") + "::150",
|
||||
_("Age") +":Int:40",
|
||||
"0-30:Currency:100",
|
||||
"30-60:Currency:100",
|
||||
"60-90:Currency:100",
|
||||
_("90-Above") + ":Currency:100",
|
||||
_("Delay in payment (Days)") + "::150"
|
||||
]
|
||||
|
||||
def get_conditions(filters):
|
||||
@@ -66,7 +80,14 @@ def get_conditions(filters):
|
||||
|
||||
if filters.get("party"):
|
||||
conditions.append("jvd.party=%(party)s")
|
||||
|
||||
|
||||
if filters.get("party_type"):
|
||||
conditions.append("jvd.reference_type=%(reference_type)s")
|
||||
if filters.get("party_type") == "Customer":
|
||||
filters["reference_type"] = "Sales Invoice"
|
||||
else:
|
||||
filters["reference_type"] = "Purchase Invoice"
|
||||
|
||||
if filters.get("company"):
|
||||
conditions.append("jv.company=%(company)s")
|
||||
|
||||
@@ -89,12 +110,9 @@ def get_entries(filters):
|
||||
return entries
|
||||
|
||||
def get_invoice_posting_date_map(filters):
|
||||
invoice_posting_date_map = {}
|
||||
if filters.get("payment_type") == "Incoming":
|
||||
for t in frappe.db.sql("""select name, posting_date from `tabSales Invoice`"""):
|
||||
invoice_posting_date_map[t[0]] = t[1]
|
||||
else:
|
||||
for t in frappe.db.sql("""select name, posting_date from `tabPurchase Invoice`"""):
|
||||
invoice_posting_date_map[t[0]] = t[1]
|
||||
invoice_details = {}
|
||||
dt = "Sales Invoice" if filters.get("payment_type") == "Incoming" else "Purchase Invoice"
|
||||
for t in frappe.db.sql("select name, posting_date, due_date from `tab{0}`".format(dt), as_dict=1):
|
||||
invoice_details[t.name] = t
|
||||
|
||||
return invoice_posting_date_map
|
||||
return invoice_details
|
||||
|
||||
@@ -2,16 +2,17 @@
|
||||
"add_total_row": 1,
|
||||
"apply_user_permissions": 1,
|
||||
"creation": "2013-05-28 15:54:16",
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"idx": 1,
|
||||
"is_standard": "Yes",
|
||||
"modified": "2015-03-30 05:37:23.626083",
|
||||
"modified": "2015-11-04 11:56:14.321664",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Purchase Order Items To Be Billed",
|
||||
"owner": "Administrator",
|
||||
"query": "select \n `tabPurchase Order`.`name` as \"Purchase Order:Link/Purchase Order:120\",\n `tabPurchase Order`.`transaction_date` as \"Date:Date:100\",\n\t`tabPurchase Order`.`supplier` as \"Supplier:Link/Supplier:120\",\n\t`tabPurchase Order Item`.`project_name` as \"Project\",\n\t`tabPurchase Order Item`.item_code as \"Item Code:Link/Item:120\",\n\t`tabPurchase Order Item`.base_amount as \"Amount:Currency:100\",\n\t(`tabPurchase Order Item`.billed_amt * ifnull(`tabPurchase Order`.conversion_rate, 1)) as \"Billed Amount:Currency:100\", \n\t(`tabPurchase Order Item`.base_amount - (ifnull(`tabPurchase Order Item`.billed_amt, 0) * ifnull(`tabPurchase Order`.conversion_rate, 1))) as \"Amount to Bill:Currency:100\",\n\t`tabPurchase Order Item`.item_name as \"Item Name::150\",\n\t`tabPurchase Order Item`.description as \"Description::200\",\n\t`tabPurchase Order`.company as \"Company:Link/Company:\"\nfrom\n\t`tabPurchase Order`, `tabPurchase Order Item`\nwhere\n\t`tabPurchase Order Item`.`parent` = `tabPurchase Order`.`name`\n\tand `tabPurchase Order`.docstatus = 1\n\tand `tabPurchase Order`.status != \"Stopped\"\n\tand (ifnull(`tabPurchase Order Item`.billed_amt, 0) * ifnull(`tabPurchase Order`.conversion_rate, 1)) < ifnull(`tabPurchase Order Item`.base_amount, 0)\norder by `tabPurchase Order`.transaction_date asc",
|
||||
"query": "select \n `tabPurchase Order`.`name` as \"Purchase Order:Link/Purchase Order:120\",\n `tabPurchase Order`.`transaction_date` as \"Date:Date:100\",\n\t`tabPurchase Order`.`supplier` as \"Supplier:Link/Supplier:120\",\n\t`tabPurchase Order Item`.`project_name` as \"Project\",\n\t`tabPurchase Order Item`.item_code as \"Item Code:Link/Item:120\",\n\t`tabPurchase Order Item`.base_amount as \"Amount:Currency:100\",\n\t(`tabPurchase Order Item`.billed_amt * ifnull(`tabPurchase Order`.conversion_rate, 1)) as \"Billed Amount:Currency:100\", \n\t(`tabPurchase Order Item`.base_amount - (ifnull(`tabPurchase Order Item`.billed_amt, 0) * ifnull(`tabPurchase Order`.conversion_rate, 1))) as \"Amount to Bill:Currency:100\",\n\t`tabPurchase Order Item`.item_name as \"Item Name::150\",\n\t`tabPurchase Order Item`.description as \"Description::200\",\n\t`tabPurchase Order`.company as \"Company:Link/Company:\"\nfrom\n\t`tabPurchase Order`, `tabPurchase Order Item`\nwhere\n\t`tabPurchase Order Item`.`parent` = `tabPurchase Order`.`name`\n\tand `tabPurchase Order`.docstatus = 1\n\tand `tabPurchase Order`.status not in (\"Stopped\", \"Closed\")\n\tand (ifnull(`tabPurchase Order Item`.billed_amt, 0) * ifnull(`tabPurchase Order`.conversion_rate, 1)) < ifnull(`tabPurchase Order Item`.base_amount, 0)\norder by `tabPurchase Order`.transaction_date asc",
|
||||
"ref_doctype": "Purchase Invoice",
|
||||
"report_name": "Purchase Order Items To Be Billed",
|
||||
"report_type": "Query Report"
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
{
|
||||
"add_total_row": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"creation": "2013-07-30 18:35:10",
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"idx": 1,
|
||||
"is_standard": "Yes",
|
||||
"modified": "2015-04-14 11:56:02.323769",
|
||||
"modified": "2015-11-02 12:33:11.681513",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Received Items To Be Billed",
|
||||
"owner": "Administrator",
|
||||
"query": "select\n `tabPurchase Receipt`.`name` as \"Purchase Receipt:Link/Purchase Receipt:120\",\n `tabPurchase Receipt`.`supplier` as \"Supplier:Link/Supplier:120\",\n\t`tabPurchase Receipt`.`posting_date` as \"Date:Date\",\n\t`tabPurchase Receipt Item`.`project_name` as \"Project\",\n\t`tabPurchase Receipt Item`.`item_code` as \"Item:Link/Item:120\",\n\t(`tabPurchase Receipt Item`.`qty` - ifnull((select sum(qty) from `tabPurchase Invoice Item` \n\t where `tabPurchase Invoice Item`.purchase_receipt = `tabPurchase Receipt`.name and\n `tabPurchase Invoice Item`.docstatus = 1 and\n\t `tabPurchase Invoice Item`.pr_detail = `tabPurchase Receipt Item`.name), 0))\n\t as \"Qty:Float:110\",\n\t(`tabPurchase Receipt Item`.`base_amount` - ifnull((select sum(base_amount) \n from `tabPurchase Invoice Item` \n where `tabPurchase Invoice Item`.purchase_receipt = `tabPurchase Receipt`.name and\n `tabPurchase Invoice Item`.docstatus = 1 and\n `tabPurchase Invoice Item`.pr_detail = `tabPurchase Receipt Item`.name), 0))\n\t as \"Amount:Currency:110\",\n\t`tabPurchase Receipt Item`.`item_name` as \"Item Name::150\",\n\t`tabPurchase Receipt Item`.`description` as \"Description::200\",\n\t`tabPurchase Receipt`.`company` as \"Company:Link/Company:\"\nfrom `tabPurchase Receipt`, `tabPurchase Receipt Item`\nwhere\n `tabPurchase Receipt`.docstatus = 1 and\n `tabPurchase Receipt`.name = `tabPurchase Receipt Item`.parent and\n (`tabPurchase Receipt Item`.qty > ifnull((select sum(qty) from `tabPurchase Invoice Item` \n where `tabPurchase Invoice Item`.purchase_receipt = `tabPurchase Receipt`.name and\n `tabPurchase Invoice Item`.docstatus=1 and \n `tabPurchase Invoice Item`.pr_detail = `tabPurchase Receipt Item`.name), 0))\norder by `tabPurchase Receipt`.`name` desc",
|
||||
"query": "select\n `tabPurchase Receipt`.`name` as \"Purchase Receipt:Link/Purchase Receipt:120\",\n `tabPurchase Receipt`.`supplier` as \"Supplier:Link/Supplier:120\",\n\t`tabPurchase Receipt`.`posting_date` as \"Date:Date\",\n\t`tabPurchase Receipt Item`.`project_name` as \"Project\",\n\t`tabPurchase Receipt Item`.`item_code` as \"Item:Link/Item:120\",\n\t(`tabPurchase Receipt Item`.`qty` - ifnull((select sum(qty) from `tabPurchase Invoice Item` \n\t where `tabPurchase Invoice Item`.purchase_receipt = `tabPurchase Receipt`.name and\n `tabPurchase Invoice Item`.docstatus = 1 and\n\t `tabPurchase Invoice Item`.pr_detail = `tabPurchase Receipt Item`.name), 0))\n\t as \"Qty:Float:110\",\n\t(`tabPurchase Receipt Item`.`base_amount` - ifnull((select sum(base_amount) \n from `tabPurchase Invoice Item` \n where `tabPurchase Invoice Item`.purchase_receipt = `tabPurchase Receipt`.name and\n `tabPurchase Invoice Item`.docstatus = 1 and\n `tabPurchase Invoice Item`.pr_detail = `tabPurchase Receipt Item`.name), 0))\n\t as \"Amount:Currency:110\",\n\t`tabPurchase Receipt Item`.`item_name` as \"Item Name::150\",\n\t`tabPurchase Receipt Item`.`description` as \"Description::200\",\n\t`tabPurchase Receipt`.`company` as \"Company:Link/Company:\"\nfrom `tabPurchase Receipt`, `tabPurchase Receipt Item`\nwhere\n `tabPurchase Receipt`.docstatus = 1 and `tabPurchase Receipt`.status != \"Closed\" and \n `tabPurchase Receipt`.name = `tabPurchase Receipt Item`.parent and\n (`tabPurchase Receipt Item`.qty > ifnull((select sum(qty) from `tabPurchase Invoice Item` \n where `tabPurchase Invoice Item`.purchase_receipt = `tabPurchase Receipt`.name and\n `tabPurchase Invoice Item`.docstatus=1 and \n `tabPurchase Invoice Item`.pr_detail = `tabPurchase Receipt Item`.name), 0))\norder by `tabPurchase Receipt`.`name` desc",
|
||||
"ref_doctype": "Purchase Invoice",
|
||||
"report_name": "Received Items To Be Billed",
|
||||
"report_type": "Query Report"
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.query_reports["Trial Balance for Party"] = {
|
||||
"filters": [
|
||||
{
|
||||
"fieldname": "company",
|
||||
"label": __("Company"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Company",
|
||||
"default": frappe.defaults.get_user_default("company"),
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "fiscal_year",
|
||||
"label": __("Fiscal Year"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Fiscal Year",
|
||||
"default": frappe.defaults.get_user_default("fiscal_year"),
|
||||
"reqd": 1,
|
||||
"on_change": function(query_report) {
|
||||
var fiscal_year = query_report.get_values().fiscal_year;
|
||||
if (!fiscal_year) {
|
||||
return;
|
||||
}
|
||||
frappe.model.with_doc("Fiscal Year", fiscal_year, function(r) {
|
||||
var fy = frappe.model.get_doc("Fiscal Year", fiscal_year);
|
||||
query_report.filters_by_name.from_date.set_input(fy.year_start_date);
|
||||
query_report.filters_by_name.to_date.set_input(fy.year_end_date);
|
||||
query_report.trigger_refresh();
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
"fieldname": "from_date",
|
||||
"label": __("From Date"),
|
||||
"fieldtype": "Date",
|
||||
"default": frappe.defaults.get_user_default("year_start_date"),
|
||||
},
|
||||
{
|
||||
"fieldname": "to_date",
|
||||
"label": __("To Date"),
|
||||
"fieldtype": "Date",
|
||||
"default": frappe.defaults.get_user_default("year_end_date"),
|
||||
},
|
||||
{
|
||||
"fieldname":"party_type",
|
||||
"label": __("Party Type"),
|
||||
"fieldtype": "Select",
|
||||
"options": ["Customer", "Supplier"],
|
||||
"default": "Customer"
|
||||
},
|
||||
{
|
||||
"fieldname": "show_zero_values",
|
||||
"label": __("Show zero values"),
|
||||
"fieldtype": "Check"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"add_total_row": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"creation": "2015-09-22 10:28:45.762272",
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"is_standard": "Yes",
|
||||
"modified": "2015-09-22 10:28:45.762272",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Trial Balance for Party",
|
||||
"owner": "Administrator",
|
||||
"ref_doctype": "GL Entry",
|
||||
"report_name": "Trial Balance for Party",
|
||||
"report_type": "Script Report"
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user