Compare commits
429 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
a2fda1c779 | ||
|
|
a29577ca71 | ||
|
|
b1454cdf9f | ||
|
|
f668a4d03c | ||
|
|
c2b4ae6667 | ||
|
|
1857bb8b0b | ||
|
|
888a70c2d4 | ||
|
|
9d5b84e78a | ||
|
|
bdc125ad0f | ||
|
|
f0b3014a23 | ||
|
|
0b17a91aba | ||
|
|
83dd3e14e5 | ||
|
|
38f64ea3ab | ||
|
|
cd103c05d6 | ||
|
|
bc1e8b4408 | ||
|
|
6c3ff3e2ed | ||
|
|
4fb7f881c8 | ||
|
|
83a358afc1 | ||
|
|
96bb070781 | ||
|
|
d387dd3bc6 | ||
|
|
9f25575e0c | ||
|
|
e1af7f1a0f | ||
|
|
c35df5ce80 | ||
|
|
2c2868db11 | ||
|
|
17f28c13ed | ||
|
|
3f1f2dd307 | ||
|
|
ab05dcd9f9 | ||
|
|
f21edba97f | ||
|
|
91b0e2348c | ||
|
|
4de91887db | ||
|
|
9b1288605f | ||
|
|
43888546f6 | ||
|
|
68d2e317d2 | ||
|
|
2249eea59f | ||
|
|
d608363d7b | ||
|
|
b2739cbb79 | ||
|
|
f5940907ae | ||
|
|
90162078d5 | ||
|
|
cba99743a4 | ||
|
|
f44128f81c | ||
|
|
3607737b5e | ||
|
|
bf9691ed39 | ||
|
|
bbca95fd1b | ||
|
|
4df98d52c1 | ||
|
|
28f8664b93 | ||
|
|
216aaaf1d6 | ||
|
|
be9edae961 | ||
|
|
4223d7c044 | ||
|
|
3a53d49b7e | ||
|
|
4d62d7867e | ||
|
|
c0e3b1a0c7 | ||
|
|
34fe81f7eb | ||
|
|
11a746d363 | ||
|
|
1609933748 | ||
|
|
5f90f7096d | ||
|
|
59c4ae5a46 | ||
|
|
85abdc4fad | ||
|
|
98096771c2 | ||
|
|
ba51ebd1b7 | ||
|
|
be090fa512 | ||
|
|
c2283ca304 | ||
|
|
deb38f7a68 | ||
|
|
283850ce47 | ||
|
|
099bbbded0 | ||
|
|
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,6 +1,6 @@
|
||||
# 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)
|
||||
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
from __future__ import unicode_literals
|
||||
__version__ = '6.0.0'
|
||||
__version__ = '6.5.1'
|
||||
|
||||
@@ -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-07-20 03:54:14.297995",
|
||||
"modified": "2015-10-02 07:38:37.436071",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Account",
|
||||
@@ -410,7 +434,7 @@
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
@@ -430,7 +454,7 @@
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
@@ -450,7 +474,7 @@
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
@@ -470,7 +494,7 @@
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
|
||||
@@ -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"))
|
||||
@@ -196,3 +207,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-02-05 05:11:35.427357",
|
||||
"modified": "2015-10-02 07:38:40.926061",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "C-Form",
|
||||
@@ -352,7 +352,7 @@
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 0,
|
||||
|
||||
@@ -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-07-13 05:28:25.504801",
|
||||
"modified": "2015-10-02 07:38:42.617993",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Cost Center",
|
||||
@@ -326,7 +326,7 @@
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
@@ -346,7 +346,7 @@
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
@@ -366,7 +366,7 @@
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
@@ -386,7 +386,7 @@
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
|
||||
@@ -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-07-13 05:28:27.745408",
|
||||
"modified": "2015-10-02 07:38:50.942038",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Fiscal Year",
|
||||
@@ -161,7 +161,7 @@
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
|
||||
@@ -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,7 +156,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Debit Amt",
|
||||
"label": "Debit Amount",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "debit",
|
||||
"oldfieldtype": "Currency",
|
||||
@@ -180,7 +180,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Credit Amt",
|
||||
"label": "Credit Amount",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "credit",
|
||||
"oldfieldtype": "Currency",
|
||||
@@ -194,6 +194,75 @@
|
||||
"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,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -261,7 +330,7 @@
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
@@ -346,7 +415,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",
|
||||
@@ -370,7 +439,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Is Advance",
|
||||
"label": "Is Advance",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "is_advance",
|
||||
"oldfieldtype": "Select",
|
||||
@@ -442,7 +511,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-07-09 15:51:04.986518",
|
||||
"modified": "2015-10-02 07:38:51.117114",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "GL Entry",
|
||||
@@ -450,7 +519,7 @@
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
|
||||
@@ -3,13 +3,15 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
from frappe.utils import flt, fmt_money, getdate, formatdate, cstr
|
||||
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, get_party_account_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)
|
||||
@@ -91,7 +94,7 @@ class GLEntry(Document):
|
||||
|
||||
if self.cost_center and _get_cost_center_company() != self.company:
|
||||
frappe.throw(_("Cost Center {0} does not belong to Company {1}").format(self.cost_center, self.company))
|
||||
|
||||
|
||||
def validate_party(self):
|
||||
if self.party_type and self.party:
|
||||
frozen_accounts_modifier = frappe.db.get_value( 'Accounts Settings', None,'frozen_accounts_modifier')
|
||||
@@ -99,6 +102,26 @@ 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:
|
||||
party_account_currency = get_party_account_currency(self.party_type, self.party, self.company)
|
||||
|
||||
if party_account_currency != self.account_currency:
|
||||
frappe.throw(_("Accounting Entry for {0}: {1} can only be made in currency: {2}")
|
||||
.format(self.party_type, self.party, party_account_currency), InvalidAccountCurrency)
|
||||
|
||||
validate_party_gle_currency(self.party_type, self.party, self.company)
|
||||
|
||||
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")
|
||||
@@ -124,22 +147,28 @@ def check_freezing_date(posting_date, adv_adj=False):
|
||||
frappe.throw(_("You are not authorized to add or update entries before {0}").format(formatdate(acc_frozen_upto)))
|
||||
|
||||
def update_outstanding_amt(account, party_type, party, against_voucher_type, against_voucher, on_cancel=False):
|
||||
if party_type and party:
|
||||
party_condition = " and ifnull(party_type, '')='{0}' and ifnull(party, '')='{1}'"\
|
||||
.format(frappe.db.escape(party_type), frappe.db.escape(party))
|
||||
else:
|
||||
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 and ifnull(party_type, '')=%s and ifnull(party, '')=%s""",
|
||||
(against_voucher_type, against_voucher, account, party_type, party))[0][0] or 0.0)
|
||||
and account = %s {0}""".format(party_condition),
|
||||
(against_voucher_type, against_voucher, account))[0][0] or 0.0)
|
||||
|
||||
if against_voucher_type == 'Purchase Invoice':
|
||||
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(party_type, '')=%s and ifnull(party, '')=%s
|
||||
and ifnull(against_voucher, '') = ''""",
|
||||
(against_voucher, account, cstr(party_type), cstr(party)))[0][0])
|
||||
and account = %s and ifnull(against_voucher, '') = '' {0}"""
|
||||
.format(party_condition), (against_voucher, account))[0][0])
|
||||
|
||||
if not against_voucher_amount:
|
||||
frappe.throw(_("Against Journal Entry {0} is already adjusted against some other voucher")
|
||||
|
||||
@@ -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,54 @@
|
||||
// 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();
|
||||
cur_frm.cscript.voucher_type(frm.doc);
|
||||
|
||||
if(frm.doc.docstatus==1) {
|
||||
cur_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");
|
||||
}
|
||||
|
||||
// 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.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;
|
||||
})
|
||||
}
|
||||
|
||||
erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
|
||||
onload: function() {
|
||||
this.load_defaults();
|
||||
@@ -29,17 +75,27 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
|
||||
|
||||
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) {
|
||||
var filters = {
|
||||
company: me.frm.doc.company,
|
||||
is_group: 0
|
||||
};
|
||||
if(!doc.multi_currency) {
|
||||
$.extend(filters, {
|
||||
account_currency: frappe.get_doc(":Company", me.frm.doc.company).default_currency
|
||||
});
|
||||
}
|
||||
return { filters: filters };
|
||||
});
|
||||
|
||||
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) {
|
||||
@@ -59,7 +115,6 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
|
||||
// journal entry
|
||||
if(jvd.reference_type==="Journal Entry") {
|
||||
frappe.model.validate_missing(jvd, "account");
|
||||
|
||||
return {
|
||||
query: "erpnext.accounts.doctype.journal_entry.journal_entry.get_against_jv",
|
||||
filters: {
|
||||
@@ -69,23 +124,32 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
|
||||
};
|
||||
}
|
||||
|
||||
// against party
|
||||
|
||||
frappe.model.validate_missing(jvd, "party_type");
|
||||
frappe.model.validate_missing(jvd, "party");
|
||||
|
||||
var out = {
|
||||
filters: [
|
||||
[jvd.reference_type, jvd.reference_type.indexOf("Sales")===0 ? "customer" : "supplier", "=", jvd.party],
|
||||
[jvd.reference_type, "docstatus", "=", 1],
|
||||
[jvd.reference_type, "docstatus", "=", 1]
|
||||
]
|
||||
};
|
||||
|
||||
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,
|
||||
(jvd.reference_type.indexOf("Sales")===0 ? "customer" : "supplier"), "=", jvd.party]);
|
||||
}
|
||||
|
||||
return out;
|
||||
});
|
||||
@@ -110,32 +174,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);
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
@@ -153,35 +224,20 @@ 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);
|
||||
@@ -193,10 +249,10 @@ cur_frm.cscript.posting_date = function(doc, cdt, cdn){
|
||||
|
||||
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;
|
||||
@@ -205,32 +261,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);
|
||||
@@ -295,18 +331,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);
|
||||
}
|
||||
})
|
||||
|
||||
@@ -314,3 +399,41 @@ frappe.ui.form.on("Journal Entry Account", "accounts_remove", function(frm) {
|
||||
cur_frm.cscript.update_totals(frm.doc);
|
||||
});
|
||||
|
||||
erpnext.journal_entry.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));
|
||||
}
|
||||
|
||||
erpnext.journal_entry.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);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -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-08-27 03:19:18.634225",
|
||||
"modified": "2015-10-02 07:38:54.074343",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Journal Entry",
|
||||
@@ -1010,7 +1032,7 @@
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 1,
|
||||
"apply_user_permissions": 1,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
@@ -1050,7 +1072,7 @@
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
|
||||
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
|
||||
|
||||
|
||||
class JournalEntry(AccountsController):
|
||||
@@ -26,6 +26,7 @@ class JournalEntry(AccountsController):
|
||||
self.validate_party()
|
||||
self.validate_cheque_info()
|
||||
self.validate_entries_for_advance()
|
||||
self.validate_multi_currency()
|
||||
self.validate_debit_and_credit()
|
||||
self.validate_against_jv()
|
||||
self.validate_reference_doc()
|
||||
@@ -35,7 +36,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 +46,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 +147,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 +155,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,6 +170,7 @@ 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)])
|
||||
@@ -191,23 +196,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 +228,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 +250,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 +264,38 @@ 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()
|
||||
|
||||
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 +304,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 +318,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 +343,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 +359,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 +382,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 +472,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
|
||||
@@ -446,9 +505,12 @@ def get_default_bank_cash_account(company, voucher_type, mode_of_payment=None):
|
||||
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()
|
||||
@@ -456,21 +518,38 @@ 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)
|
||||
|
||||
# exchange rate
|
||||
exchange_rate = get_exchange_rate(si.debit_to, si.party_account_currency, si.company,
|
||||
si.doctype, si.name)
|
||||
|
||||
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
|
||||
row1 = jv.get("accounts")[0]
|
||||
row1.account = si.debit_to
|
||||
row1.account_currency = si.party_account_currency
|
||||
row1.party_type = "Customer"
|
||||
row1.party = si.customer
|
||||
row1.balance = get_balance_on(si.debit_to)
|
||||
row1.party_balance = get_balance_on(party=si.customer, party_type="Customer")
|
||||
row1.credit_in_account_currency = si.outstanding_amount
|
||||
row1.reference_type = si.doctype
|
||||
row1.reference_name = si.name
|
||||
row1.exchange_rate = exchange_rate
|
||||
row1.account_type = "Receivable" if si.customer else ""
|
||||
|
||||
# debit bank
|
||||
jv.get("accounts")[1].debit = si.outstanding_amount
|
||||
row2 = jv.get("accounts")[1]
|
||||
if row2.account_currency == si.party_account_currency:
|
||||
row2.debit_in_account_currency = si.outstanding_amount
|
||||
else:
|
||||
row2.debit_in_account_currency = si.outstanding_amount * exchange_rate
|
||||
|
||||
# set multi currency check
|
||||
if row1.account_currency != si.company_currency or row2.account_currency != si.company_currency:
|
||||
jv.multi_currency = 1
|
||||
|
||||
return jv.as_dict()
|
||||
|
||||
@@ -478,21 +557,38 @@ def get_payment_entry_from_sales_invoice(sales_invoice):
|
||||
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)
|
||||
|
||||
exchange_rate = get_exchange_rate(pi.credit_to, pi.party_account_currency, pi.company,
|
||||
pi.doctype, pi.name)
|
||||
|
||||
jv = get_payment_entry(pi)
|
||||
jv.remark = 'Payment against Purchase Invoice {0}. {1}'.format(pi.name, pi.remarks)
|
||||
jv.exchange_rate = exchange_rate
|
||||
|
||||
# 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
|
||||
row1 = jv.get("accounts")[0]
|
||||
row1.account = pi.credit_to
|
||||
row1.account_currency = pi.party_account_currency
|
||||
row1.party_type = "Supplier"
|
||||
row1.party = pi.supplier
|
||||
row1.balance = get_balance_on(pi.credit_to)
|
||||
row1.party_balance = get_balance_on(party=pi.supplier, party_type="Supplier")
|
||||
row1.debit_in_account_currency = pi.outstanding_amount
|
||||
row1.reference_type = pi.doctype
|
||||
row1.reference_name = pi.name
|
||||
row1.exchange_rate = exchange_rate
|
||||
row1.account_type = "Payable" if pi.supplier else ""
|
||||
|
||||
# credit bank
|
||||
jv.get("accounts")[1].credit = pi.outstanding_amount
|
||||
row2 = jv.get("accounts")[1]
|
||||
if row2.account_currency == pi.party_account_currency:
|
||||
row2.credit_in_account_currency = pi.outstanding_amount
|
||||
else:
|
||||
row2.credit_in_account_currency = pi.outstanding_amount * exchange_rate
|
||||
|
||||
# set multi currency check
|
||||
if row1.account_currency != pi.company_currency or row2.account_currency != pi.company_currency:
|
||||
jv.multi_currency = 1
|
||||
|
||||
return jv.as_dict()
|
||||
|
||||
@@ -501,6 +597,7 @@ 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:
|
||||
@@ -508,23 +605,42 @@ def get_payment_entry_from_sales_order(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)
|
||||
party_account = get_party_account("Customer", so.customer, so.company)
|
||||
party_account_currency = get_account_currency(party_account)
|
||||
|
||||
exchange_rate = get_exchange_rate(party_account, party_account_currency, so.company)
|
||||
|
||||
if party_account_currency == so.company_currency:
|
||||
amount = flt(so.base_grand_total) - flt(so.advance_paid)
|
||||
else:
|
||||
amount = flt(so.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"
|
||||
row1 = jv.get("accounts")[0]
|
||||
row1.account = party_account
|
||||
row1.account_currency = party_account_currency
|
||||
row1.party_type = "Customer"
|
||||
row1.party = so.customer
|
||||
row1.balance = get_balance_on(party_account)
|
||||
row1.party_balance = get_balance_on(party=so.customer, party_type="Customer")
|
||||
row1.credit_in_account_currency = amount
|
||||
row1.reference_type = so.doctype
|
||||
row1.reference_name = so.name
|
||||
row1.is_advance = "Yes"
|
||||
row1.exchange_rate = exchange_rate
|
||||
row1.account_type = "Receivable"
|
||||
|
||||
# debit bank
|
||||
jv.get("accounts")[1].debit = amount
|
||||
row2 = jv.get("accounts")[1]
|
||||
if row2.account_currency == party_account_currency:
|
||||
row2.debit_in_account_currency = amount
|
||||
else:
|
||||
row2.debit_in_account_currency = amount * exchange_rate
|
||||
|
||||
# set multi currency check
|
||||
if row1.account_currency != so.company_currency or row2.account_currency != so.company_currency:
|
||||
jv.multi_currency = 1
|
||||
|
||||
return jv.as_dict()
|
||||
|
||||
@@ -540,23 +656,41 @@ def get_payment_entry_from_purchase_order(purchase_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)
|
||||
party_account = get_party_account("Supplier", po.supplier, po.company)
|
||||
party_account_currency = get_account_currency(party_account)
|
||||
|
||||
exchange_rate = get_exchange_rate(party_account, party_account_currency, po.company)
|
||||
|
||||
if party_account_currency == po.company_currency:
|
||||
amount = flt(po.base_grand_total) - flt(po.advance_paid)
|
||||
else:
|
||||
amount = flt(po.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"
|
||||
row1 = jv.get("accounts")[0]
|
||||
row1.account = party_account
|
||||
row1.party_type = "Supplier"
|
||||
row1.party = po.supplier
|
||||
row1.balance = get_balance_on(party_account)
|
||||
row1.party_balance = get_balance_on(party=po.supplier, party_type="Supplier")
|
||||
row1.debit_in_account_currency = amount
|
||||
row1.reference_type = po.doctype
|
||||
row1.reference_name = po.name
|
||||
row1.is_advance = "Yes"
|
||||
row1.exchange_rate = exchange_rate
|
||||
row1.account_type = "Payable"
|
||||
|
||||
# debit bank
|
||||
jv.get("accounts")[1].credit = amount
|
||||
row2 = jv.get("accounts")[1]
|
||||
if row2.account_currency == party_account_currency:
|
||||
row2.credit_in_account_currency = amount
|
||||
else:
|
||||
row2.credit_in_account_currency = amount * exchange_rate
|
||||
|
||||
# set multi currency check
|
||||
if row1.account_currency != po.company_currency or row2.account_currency != po.company_currency:
|
||||
jv.multi_currency = 1
|
||||
|
||||
return jv.as_dict()
|
||||
|
||||
@@ -574,6 +708,10 @@ def get_payment_entry(doc):
|
||||
if bank_account:
|
||||
d2.account = bank_account["account"]
|
||||
d2.balance = bank_account["balance"]
|
||||
d2.account_currency = bank_account["account_currency"]
|
||||
d2.account_type = bank_account["account_type"]
|
||||
d2.exchange_rate = get_exchange_rate(bank_account["account"],
|
||||
bank_account["account_currency"], doc.company)
|
||||
|
||||
return jv
|
||||
|
||||
@@ -599,27 +737,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()
|
||||
@@ -628,7 +776,7 @@ def get_party_account_and_balance(company, party_type, party):
|
||||
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 +788,61 @@ 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, company,
|
||||
reference_type=None, reference_name=None, debit=None, credit=None, exchange_rate=None):
|
||||
from erpnext.setup.utils import get_exchange_rate
|
||||
company_currency = get_company_currency(company)
|
||||
account_details = frappe.db.get_value("Account", account, ["account_type", "root_type"], as_dict=1)
|
||||
|
||||
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": "",
|
||||
"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,43 @@
|
||||
"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,
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@@ -242,20 +377,43 @@
|
||||
"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,
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@@ -293,7 +451,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Reference Type",
|
||||
"label": "Reference Type",
|
||||
"no_copy": 0,
|
||||
"options": "\nSales Invoice\nPurchase Invoice\nJournal Entry\nSales Order\nPurchase Order\nExpense Claim",
|
||||
"permlevel": 0,
|
||||
@@ -359,7 +517,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Is Advance",
|
||||
"label": "Is Advance",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "is_advance",
|
||||
"oldfieldtype": "Select",
|
||||
@@ -405,7 +563,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2015-08-17 02:11:33.991361",
|
||||
"modified": "2015-10-02 07:38:54.406370",
|
||||
"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-02-05 05:11:41.346436",
|
||||
"modified": "2015-10-02 07:38:57.318104",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Mode of Payment",
|
||||
@@ -93,7 +93,7 @@
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -250,7 +250,7 @@
|
||||
"is_submittable": 1,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-02-05 05:11:42.268561",
|
||||
"modified": "2015-10-02 07:39:00.056337",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Period Closing Voucher",
|
||||
|
||||
@@ -10,11 +10,11 @@ from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journ
|
||||
|
||||
class TestPeriodClosingVoucher(unittest.TestCase):
|
||||
def test_closing_entry(self):
|
||||
make_journal_entry("_Test Account Bank Account - _TC", "Sales - _TC", 400,
|
||||
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)
|
||||
|
||||
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
|
||||
|
||||
@@ -622,7 +622,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-08-18 17:49:09.098876",
|
||||
"modified": "2015-10-02 07:39:00.196535",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "POS Profile",
|
||||
@@ -650,7 +650,7 @@
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -75,8 +75,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();
|
||||
},
|
||||
|
||||
@@ -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-08-27 03:21:24.432106",
|
||||
"modified": "2015-10-12 16:23:32.141069",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Purchase Invoice",
|
||||
@@ -2183,7 +2273,7 @@
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 1,
|
||||
"apply_user_permissions": 1,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 0,
|
||||
@@ -2203,7 +2293,7 @@
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
@@ -2223,7 +2313,7 @@
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
@@ -2263,7 +2353,7 @@
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
|
||||
@@ -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"
|
||||
@@ -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,6 +101,8 @@ class PurchaseInvoice(BuyingController):
|
||||
if self.supplier and account.account_type != "Payable":
|
||||
frappe.throw(_("Credit To account must be a Payable account"))
|
||||
|
||||
self.party_account_currency = account.account_currency
|
||||
|
||||
def check_for_stopped_status(self):
|
||||
check_list = []
|
||||
for d in self.get('items'):
|
||||
@@ -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,14 +302,16 @@ 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 \
|
||||
@@ -352,12 +364,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
|
||||
})
|
||||
)
|
||||
@@ -393,7 +421,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"]
|
||||
@@ -218,7 +219,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 +237,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 +279,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);
|
||||
@@ -146,7 +151,9 @@ 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);
|
||||
@@ -176,6 +183,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 +210,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 +226,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();
|
||||
},
|
||||
|
||||
@@ -347,7 +376,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 +424,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,
|
||||
@@ -65,7 +65,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Series",
|
||||
"label": "Series",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "naming_series",
|
||||
"oldfieldtype": "Select",
|
||||
@@ -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": "",
|
||||
@@ -1168,7 +1168,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,
|
||||
@@ -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,
|
||||
@@ -2165,7 +2211,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Source",
|
||||
"label": "Source",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "source",
|
||||
"oldfieldtype": "Select",
|
||||
@@ -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,
|
||||
@@ -2239,7 +2308,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 1,
|
||||
"in_list_view": 0,
|
||||
"label": "Is Opening Entry",
|
||||
"label": "Is Opening Entry",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "is_opening",
|
||||
"oldfieldtype": "Select",
|
||||
@@ -2263,7 +2332,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "C-Form Applicable",
|
||||
"label": "C-Form Applicable",
|
||||
"no_copy": 1,
|
||||
"options": "No\nYes",
|
||||
"permlevel": 0,
|
||||
@@ -2528,7 +2597,7 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"allow_on_submit": 1,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "sales_team",
|
||||
@@ -2631,7 +2700,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Recurring Type",
|
||||
"label": "Recurring Type",
|
||||
"no_copy": 1,
|
||||
"options": "\nMonthly\nQuarterly\nHalf-yearly\nYearly",
|
||||
"permlevel": 0,
|
||||
@@ -2882,7 +2951,7 @@
|
||||
"is_submittable": 1,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-08-27 03:29:14.270731",
|
||||
"modified": "2015-10-02 07:39:09.123982",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice",
|
||||
@@ -2910,7 +2979,7 @@
|
||||
},
|
||||
{
|
||||
"amend": 1,
|
||||
"apply_user_permissions": 1,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 0,
|
||||
@@ -2930,7 +2999,7 @@
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
|
||||
@@ -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()
|
||||
@@ -88,13 +98,13 @@ class SalesInvoice(SellingController):
|
||||
self.update_status_updater_args()
|
||||
self.update_prevdoc_status()
|
||||
|
||||
# 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()
|
||||
|
||||
# this sequence because outstanding may get -ve
|
||||
self.make_gl_entries()
|
||||
|
||||
if not cint(self.is_pos) == 1 and not self.is_return:
|
||||
self.update_against_document_in_jv()
|
||||
|
||||
@@ -162,11 +172,22 @@ class SalesInvoice(SellingController):
|
||||
}
|
||||
])
|
||||
|
||||
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):
|
||||
validate_against_credit_limit = True
|
||||
break
|
||||
if validate_against_credit_limit:
|
||||
check_credit_limit(self.customer, self.company)
|
||||
|
||||
def set_missing_values(self, for_validate=False):
|
||||
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)
|
||||
|
||||
@@ -186,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):
|
||||
@@ -235,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]
|
||||
@@ -260,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)
|
||||
}
|
||||
@@ -271,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"))
|
||||
@@ -279,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'):
|
||||
@@ -398,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', [])
|
||||
|
||||
@@ -424,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)
|
||||
@@ -432,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:
|
||||
@@ -487,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,
|
||||
@@ -495,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
|
||||
@@ -535,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({
|
||||
@@ -542,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):
|
||||
@@ -598,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):
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -843,6 +843,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 +1282,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2015-08-20 17:18:52.752064",
|
||||
"modified": "2015-10-19 03:04:52.093181",
|
||||
"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-05-06 08:51:54.662853",
|
||||
"modified": "2015-10-02 07:39:12.157257",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Taxes and Charges Template",
|
||||
|
||||
@@ -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-02-05 05:11:46.634371",
|
||||
"modified": "2015-10-02 07:39:12.778062",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Shipping Rule",
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
132
erpnext/accounts/doctype/tax_rule/tax_rule.py
Normal file
132
erpnext/accounts/doctype/tax_rule/tax_rule.py
Normal file
@@ -0,0 +1,132 @@
|
||||
# -*- 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 = []
|
||||
|
||||
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))))
|
||||
|
||||
matching = frappe.db.sql("""select * from `tabTax Rule`
|
||||
where {0}""".format(" and ".join(conditions)), as_dict = True)
|
||||
|
||||
if not matching:
|
||||
return None
|
||||
|
||||
for rule in matching:
|
||||
rule.no_of_keys_matched = 0
|
||||
for key in args:
|
||||
if rule.get(key): rule.no_of_keys_matched += 1
|
||||
|
||||
rule = sorted(matching, 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)
|
||||
|
||||
|
||||
@@ -42,13 +42,13 @@ frappe.pages["Accounts Browser"].on_page_load = function(wrapper){
|
||||
wrapper.page.add_menu_item(__('New Company'), function() { newdoc('Company'); }, true);
|
||||
}
|
||||
|
||||
wrapper.page.set_secondary_action(__('Refresh'), function() {
|
||||
wrapper.page.add_menu_item(__('Refresh'), function() {
|
||||
wrapper.$company_select.change();
|
||||
});
|
||||
|
||||
wrapper.page.set_primary_action(__('New'), function() {
|
||||
erpnext.account_chart && erpnext.account_chart.make_new();
|
||||
});
|
||||
}, "octicon octicon-plus");
|
||||
|
||||
// company-select
|
||||
wrapper.$company_select = wrapper.page.add_select("Company", [])
|
||||
@@ -121,7 +121,8 @@ erpnext.AccountsChart = Class.extend({
|
||||
label: __("Add Child"),
|
||||
click: function() {
|
||||
me.make_new()
|
||||
}
|
||||
},
|
||||
btnClass: "hidden-xs"
|
||||
},
|
||||
{
|
||||
condition: function(node) {
|
||||
@@ -137,8 +138,8 @@ erpnext.AccountsChart = Class.extend({
|
||||
"company": me.company
|
||||
};
|
||||
frappe.set_route("query-report", "General Ledger");
|
||||
}
|
||||
|
||||
},
|
||||
btnClass: "hidden-xs"
|
||||
},
|
||||
{
|
||||
condition: function(node) { return !node.root && me.can_write },
|
||||
@@ -147,7 +148,8 @@ erpnext.AccountsChart = Class.extend({
|
||||
frappe.model.rename_doc(me.ctype, node.label, function(new_name) {
|
||||
node.reload();
|
||||
});
|
||||
}
|
||||
},
|
||||
btnClass: "hidden-xs"
|
||||
},
|
||||
{
|
||||
condition: function(node) { return !node.root && me.can_delete },
|
||||
@@ -156,14 +158,15 @@ erpnext.AccountsChart = Class.extend({
|
||||
frappe.model.delete_doc(me.ctype, node.label, function() {
|
||||
node.parent.remove();
|
||||
});
|
||||
}
|
||||
},
|
||||
btnClass: "hidden-xs"
|
||||
}
|
||||
],
|
||||
onrender: function(node) {
|
||||
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);
|
||||
}
|
||||
@@ -211,7 +214,8 @@ erpnext.AccountsChart = Class.extend({
|
||||
'Income Account', 'Tax', 'Chargeable', 'Temporary'].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"}
|
||||
]
|
||||
})
|
||||
|
||||
|
||||
@@ -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,48 @@ 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)
|
||||
|
||||
def validate_party_gle_currency(party_type, party, company):
|
||||
"""Validate party account currency with existing GL Entry's 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 +244,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 +252,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), "", "", "", "", ""]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -226,7 +226,7 @@ class GrossProfitGenerator(object):
|
||||
inner join `tabSales Invoice Item` item on item.parent = si.name
|
||||
left join `tabSales Team` sales on sales.parent = si.name
|
||||
where
|
||||
si.docstatus = 1 %s
|
||||
si.docstatus = 1 and si.is_return != 1 %s
|
||||
order by
|
||||
si.posting_date desc, si.posting_time desc""" % (conditions,), self.filters, as_dict=1)
|
||||
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
# Copyright (c) 2013, 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.utils import flt, cint
|
||||
from erpnext.accounts.report.trial_balance.trial_balance import validate_filters
|
||||
|
||||
|
||||
def execute(filters=None):
|
||||
validate_filters(filters)
|
||||
|
||||
show_party_name = is_party_name_visible(filters)
|
||||
|
||||
columns = get_columns(filters, show_party_name)
|
||||
data = get_data(filters, show_party_name)
|
||||
|
||||
return columns, data
|
||||
|
||||
def get_data(filters, show_party_name):
|
||||
party_name_field = "customer_name" if filters.get("party_type")=="Customer" else "supplier_name"
|
||||
parties = frappe.get_all(filters.get("party_type"), fields = ["name", party_name_field], order_by="name")
|
||||
|
||||
opening_balances = get_opening_balances(filters)
|
||||
balances_within_period = get_balances_within_period(filters)
|
||||
|
||||
data = []
|
||||
total_debit, total_credit = 0, 0
|
||||
for party in parties:
|
||||
row = { "party": party.name }
|
||||
if show_party_name:
|
||||
row["party_name"] = party.get(party_name_field)
|
||||
|
||||
# opening
|
||||
opening_debit, opening_credit = opening_balances.get(party.name, [0, 0])
|
||||
row.update({
|
||||
"opening_debit": opening_debit,
|
||||
"opening_credit": opening_credit
|
||||
})
|
||||
|
||||
# within period
|
||||
debit, credit = balances_within_period.get(party.name, [0, 0])
|
||||
row.update({
|
||||
"debit": debit,
|
||||
"credit": credit
|
||||
})
|
||||
|
||||
# totals
|
||||
total_debit += debit
|
||||
total_credit += credit
|
||||
|
||||
# closing
|
||||
closing_debit, closing_credit = toggle_debit_credit(opening_debit + debit, opening_credit + credit)
|
||||
row.update({
|
||||
"closing_debit": closing_debit,
|
||||
"closing_credit": closing_credit
|
||||
})
|
||||
|
||||
has_value = False
|
||||
if (opening_debit or opening_credit or debit or credit or closing_debit or closing_credit):
|
||||
has_value =True
|
||||
|
||||
if cint(filters.show_zero_values) or has_value:
|
||||
data.append(row)
|
||||
|
||||
# Add total row
|
||||
if total_debit or total_credit:
|
||||
data.append({
|
||||
"party": "'" + _("Totals") + "'",
|
||||
"debit": total_debit,
|
||||
"credit": total_credit
|
||||
})
|
||||
|
||||
return data
|
||||
|
||||
def get_opening_balances(filters):
|
||||
gle = frappe.db.sql("""
|
||||
select party, sum(ifnull(debit, 0)) as opening_debit, sum(ifnull(credit, 0)) as opening_credit
|
||||
from `tabGL Entry`
|
||||
where company=%(company)s
|
||||
and ifnull(party_type, '') = %(party_type)s and ifnull(party, '') != ''
|
||||
and (posting_date < %(from_date)s or ifnull(is_opening, 'No') = 'Yes')
|
||||
group by party""", {
|
||||
"company": filters.company,
|
||||
"from_date": filters.from_date,
|
||||
"party_type": filters.party_type
|
||||
}, as_dict=True)
|
||||
|
||||
opening = frappe._dict()
|
||||
for d in gle:
|
||||
opening_debit, opening_credit = toggle_debit_credit(d.opening_debit, d.opening_credit)
|
||||
opening.setdefault(d.party, [opening_debit, opening_credit])
|
||||
|
||||
return opening
|
||||
|
||||
def get_balances_within_period(filters):
|
||||
gle = frappe.db.sql("""
|
||||
select party, sum(ifnull(debit, 0)) as debit, sum(ifnull(credit, 0)) as credit
|
||||
from `tabGL Entry`
|
||||
where company=%(company)s
|
||||
and ifnull(party_type, '') = %(party_type)s and ifnull(party, '') != ''
|
||||
and posting_date >= %(from_date)s and posting_date <= %(to_date)s
|
||||
and ifnull(is_opening, 'No') = 'No'
|
||||
group by party""", {
|
||||
"company": filters.company,
|
||||
"from_date": filters.from_date,
|
||||
"to_date": filters.to_date,
|
||||
"party_type": filters.party_type
|
||||
}, as_dict=True)
|
||||
|
||||
balances_within_period = frappe._dict()
|
||||
for d in gle:
|
||||
balances_within_period.setdefault(d.party, [d.debit, d.credit])
|
||||
|
||||
return balances_within_period
|
||||
|
||||
def toggle_debit_credit(debit, credit):
|
||||
if flt(debit) > flt(credit):
|
||||
debit = flt(debit) - flt(credit)
|
||||
credit = 0.0
|
||||
else:
|
||||
credit = flt(credit) - flt(debit)
|
||||
debit = 0.0
|
||||
|
||||
return debit, credit
|
||||
|
||||
def get_columns(filters, show_party_name):
|
||||
columns = [
|
||||
{
|
||||
"fieldname": "party",
|
||||
"label": _(filters.party_type),
|
||||
"fieldtype": "Link",
|
||||
"options": filters.party_type,
|
||||
"width": 200
|
||||
},
|
||||
{
|
||||
"fieldname": "opening_debit",
|
||||
"label": _("Opening (Dr)"),
|
||||
"fieldtype": "Currency",
|
||||
"width": 120
|
||||
},
|
||||
{
|
||||
"fieldname": "opening_credit",
|
||||
"label": _("Opening (Cr)"),
|
||||
"fieldtype": "Currency",
|
||||
"width": 120
|
||||
},
|
||||
{
|
||||
"fieldname": "debit",
|
||||
"label": _("Debit"),
|
||||
"fieldtype": "Currency",
|
||||
"width": 120
|
||||
},
|
||||
{
|
||||
"fieldname": "credit",
|
||||
"label": _("Credit"),
|
||||
"fieldtype": "Currency",
|
||||
"width": 120
|
||||
},
|
||||
{
|
||||
"fieldname": "closing_debit",
|
||||
"label": _("Closing (Dr)"),
|
||||
"fieldtype": "Currency",
|
||||
"width": 120
|
||||
},
|
||||
{
|
||||
"fieldname": "closing_credit",
|
||||
"label": _("Closing (Cr)"),
|
||||
"fieldtype": "Currency",
|
||||
"width": 120
|
||||
}
|
||||
]
|
||||
|
||||
if show_party_name:
|
||||
columns.insert(1, {
|
||||
"fieldname": "party_name",
|
||||
"label": _(filters.party_type) + " Name",
|
||||
"fieldtype": "Data",
|
||||
"width": 200
|
||||
})
|
||||
|
||||
return columns
|
||||
|
||||
def is_party_name_visible(filters):
|
||||
show_party_name = False
|
||||
if filters.get("party_type") == "Customer":
|
||||
party_naming_by = frappe.db.get_single_value("Selling Settings", "cust_master_name")
|
||||
else:
|
||||
party_naming_by = frappe.db.get_single_value("Buying Settings", "supp_master_name")
|
||||
|
||||
if party_naming_by == "Naming Series":
|
||||
show_party_name = True
|
||||
|
||||
return show_party_name
|
||||
@@ -9,6 +9,9 @@ from frappe import throw, _
|
||||
from frappe.utils import formatdate
|
||||
import frappe.desk.reportview
|
||||
|
||||
# imported to enable erpnext.accounts.utils.get_account_currency
|
||||
from erpnext.accounts.doctype.account.account import get_account_currency
|
||||
|
||||
class FiscalYearError(frappe.ValidationError): pass
|
||||
class BudgetError(frappe.ValidationError): pass
|
||||
|
||||
@@ -50,7 +53,7 @@ def validate_fiscal_year(date, fiscal_year, label=_("Date"), doc=None):
|
||||
throw(_("{0} '{1}' not in Fiscal Year {2}").format(label, formatdate(date), fiscal_year))
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_balance_on(account=None, date=None, party_type=None, party=None):
|
||||
def get_balance_on(account=None, date=None, party_type=None, party=None, in_account_currency=True):
|
||||
if not account and frappe.form_dict.get("account"):
|
||||
account = frappe.form_dict.get("account")
|
||||
if not date and frappe.form_dict.get("date"):
|
||||
@@ -81,7 +84,9 @@ def get_balance_on(account=None, date=None, party_type=None, party=None):
|
||||
|
||||
if account:
|
||||
acc = frappe.get_doc("Account", account)
|
||||
acc.check_permission("read")
|
||||
|
||||
if not frappe.flags.ignore_account_permission:
|
||||
acc.check_permission("read")
|
||||
|
||||
# for pl accounts, get balance within a fiscal year
|
||||
if acc.report_type == 'Profit and Loss':
|
||||
@@ -94,18 +99,27 @@ def get_balance_on(account=None, date=None, party_type=None, party=None):
|
||||
select name from `tabAccount` ac where ac.name = gle.account
|
||||
and ac.lft >= %s and ac.rgt <= %s
|
||||
)""" % (acc.lft, acc.rgt))
|
||||
|
||||
# If group and currency same as company,
|
||||
# always return balance based on debit and credit in company currency
|
||||
if acc.account_currency == frappe.db.get_value("Company", acc.company, "default_currency"):
|
||||
in_account_currency = False
|
||||
else:
|
||||
cond.append("""gle.account = "%s" """ % (account.replace('"', '\\"'), ))
|
||||
|
||||
if party_type and party:
|
||||
cond.append("""gle.party_type = "%s" and gle.party = "%s" """ %
|
||||
(party_type.replace('"', '\\"'), party.replace('"', '\\"')))
|
||||
|
||||
|
||||
if account or (party_type and party):
|
||||
if in_account_currency:
|
||||
select_field = "sum(ifnull(debit_in_account_currency, 0)) - sum(ifnull(credit_in_account_currency, 0))"
|
||||
else:
|
||||
select_field = "sum(ifnull(debit, 0)) - sum(ifnull(credit, 0))"
|
||||
bal = frappe.db.sql("""
|
||||
SELECT sum(ifnull(debit, 0)) - sum(ifnull(credit, 0))
|
||||
SELECT {0}
|
||||
FROM `tabGL Entry` gle
|
||||
WHERE %s""" % " and ".join(cond))[0][0]
|
||||
WHERE {1}""".format(select_field, " and ".join(cond)))[0][0]
|
||||
|
||||
# if bal is None, return 0
|
||||
return flt(bal)
|
||||
@@ -186,6 +200,8 @@ def update_against_doc(d, jv_obj):
|
||||
"""
|
||||
jv_detail = jv_obj.get("accounts", {"name": d["voucher_detail_no"]})[0]
|
||||
jv_detail.set(d["dr_or_cr"], d["allocated_amt"])
|
||||
jv_detail.set('debit' if d['dr_or_cr']=='debit_in_account_currency' else 'credit',
|
||||
d["allocated_amt"]*flt(jv_detail.exchange_rate))
|
||||
|
||||
original_reference_type = jv_detail.reference_type
|
||||
original_reference_name = jv_detail.reference_name
|
||||
@@ -194,21 +210,37 @@ def update_against_doc(d, jv_obj):
|
||||
jv_detail.set("reference_name", d["against_voucher"])
|
||||
|
||||
if d['allocated_amt'] < d['unadjusted_amt']:
|
||||
jvd = frappe.db.sql("""select cost_center, balance, against_account, is_advance
|
||||
from `tabJournal Entry Account` where name = %s""", d['voucher_detail_no'])
|
||||
jvd = frappe.db.sql("""
|
||||
select cost_center, balance, against_account, is_advance,
|
||||
account_type, exchange_rate, account_currency
|
||||
from `tabJournal Entry Account` where name = %s
|
||||
""", d['voucher_detail_no'], as_dict=True)
|
||||
|
||||
amount_in_account_currency = flt(d['unadjusted_amt']) - flt(d['allocated_amt'])
|
||||
amount_in_company_currency = amount_in_account_currency * flt(jvd[0]['exchange_rate'])
|
||||
|
||||
# new entry with balance amount
|
||||
ch = jv_obj.append("accounts")
|
||||
ch.account = d['account']
|
||||
ch.account_type = jvd[0]['account_type']
|
||||
ch.account_currency = jvd[0]['account_currency']
|
||||
ch.exchange_rate = jvd[0]['exchange_rate']
|
||||
ch.party_type = d["party_type"]
|
||||
ch.party = d["party"]
|
||||
ch.cost_center = cstr(jvd[0][0])
|
||||
ch.balance = flt(jvd[0][1])
|
||||
ch.set(d['dr_or_cr'], flt(d['unadjusted_amt']) - flt(d['allocated_amt']))
|
||||
ch.set(d['dr_or_cr']== 'debit' and 'credit' or 'debit', 0)
|
||||
ch.against_account = cstr(jvd[0][2])
|
||||
ch.cost_center = cstr(jvd[0]["cost_center"])
|
||||
ch.balance = flt(jvd[0]["balance"])
|
||||
|
||||
ch.set(d['dr_or_cr'], amount_in_account_currency)
|
||||
ch.set('debit' if d['dr_or_cr']=='debit_in_account_currency' else 'credit', amount_in_company_currency)
|
||||
|
||||
ch.set('credit_in_account_currency' if d['dr_or_cr']== 'debit_in_account_currency'
|
||||
else 'debit_in_account_currency', 0)
|
||||
ch.set('credit' if d['dr_or_cr']== 'debit_in_account_currency' else 'debit', 0)
|
||||
|
||||
ch.against_account = cstr(jvd[0]["against_account"])
|
||||
ch.reference_type = original_reference_type
|
||||
ch.reference_name = original_reference_name
|
||||
ch.is_advance = cstr(jvd[0][3])
|
||||
ch.is_advance = cstr(jvd[0]["is_advance"])
|
||||
ch.docstatus = 1
|
||||
|
||||
# will work as update after submit
|
||||
@@ -273,7 +305,7 @@ def get_stock_and_account_difference(account_list=None, posting_date=None):
|
||||
and name in (%s)""" % ', '.join(['%s']*len(account_list)), account_list))
|
||||
|
||||
for account, warehouse in account_warehouse.items():
|
||||
account_balance = get_balance_on(account, posting_date)
|
||||
account_balance = get_balance_on(account, posting_date, in_account_currency=False)
|
||||
stock_value = get_stock_value_on(warehouse, posting_date)
|
||||
if abs(flt(stock_value) - flt(account_balance)) > 0.005:
|
||||
difference.setdefault(account, flt(stock_value) - flt(account_balance))
|
||||
@@ -282,7 +314,7 @@ def get_stock_and_account_difference(account_list=None, posting_date=None):
|
||||
|
||||
def validate_expense_against_budget(args):
|
||||
args = frappe._dict(args)
|
||||
if frappe.db.get_value("Account", {"name": args.account, "report_type": "Profit and Loss"}):
|
||||
if frappe.db.get_value("Account", {"name": args.account, "root_type": "Expense"}):
|
||||
budget = frappe.db.sql("""
|
||||
select bd.budget_allocated, cc.distribution_id
|
||||
from `tabCost Center` cc, `tabBudget Detail` bd
|
||||
@@ -378,7 +410,7 @@ def get_stock_rbnb_difference(posting_date, company):
|
||||
|
||||
# Balance as per system
|
||||
stock_rbnb_account = "Stock Received But Not Billed - " + frappe.db.get_value("Company", company, "abbr")
|
||||
sys_bal = get_balance_on(stock_rbnb_account, posting_date)
|
||||
sys_bal = get_balance_on(stock_rbnb_account, posting_date, in_account_currency=False)
|
||||
|
||||
# Amount should be credited
|
||||
return flt(stock_rbnb) + flt(sys_bal)
|
||||
@@ -393,6 +425,11 @@ def get_outstanding_invoices(amount_query, account, party_type, party):
|
||||
`tabGL Entry`
|
||||
where
|
||||
account = %s and party_type=%s and party=%s and {amount_query} > 0
|
||||
and (CASE
|
||||
WHEN voucher_type = 'Journal Entry'
|
||||
THEN ifnull(against_voucher, '') = ''
|
||||
ELSE 1=1
|
||||
END)
|
||||
group by voucher_type, voucher_no
|
||||
""".format(amount_query = amount_query), (account, party_type, party), as_dict = True)
|
||||
|
||||
|
||||
@@ -157,20 +157,9 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
|
||||
},
|
||||
add_deduct_tax: function(doc, cdt, cdn) {
|
||||
this.calculate_taxes_and_totals();
|
||||
},
|
||||
|
||||
calculate_outstanding_amount: function() {
|
||||
if(this.frm.doc.doctype == "Purchase Invoice" && this.frm.doc.docstatus < 2) {
|
||||
frappe.model.round_floats_in(this.frm.doc, ["base_grand_total", "total_advance", "write_off_amount"]);
|
||||
this.frm.doc.total_amount_to_pay = flt(this.frm.doc.base_grand_total - this.frm.doc.write_off_amount,
|
||||
precision("total_amount_to_pay"));
|
||||
if (!this.frm.doc.is_return) {
|
||||
this.frm.doc.outstanding_amount = flt(this.frm.doc.total_amount_to_pay - this.frm.doc.total_advance,
|
||||
precision("outstanding_amount"));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
cur_frm.add_fetch('project_name', 'cost_center', 'cost_center');
|
||||
|
||||
erpnext.buying.get_default_bom = function(frm) {
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Title",
|
||||
"no_copy": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
@@ -528,7 +528,7 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "items",
|
||||
@@ -1468,6 +1468,7 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"default": "Draft",
|
||||
"fieldname": "status",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
@@ -1478,7 +1479,7 @@
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "status",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "\nDraft\nSubmitted\nStopped\nCancelled",
|
||||
"options": "\nDraft\nTo Receive and Bill\nTo Bill\nTo Receive\nCompleted\nStopped\nCancelled",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
@@ -1704,7 +1705,7 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "supplied_items",
|
||||
@@ -1760,7 +1761,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Column Break",
|
||||
"label": "",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
@@ -1919,7 +1920,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Column Break",
|
||||
"label": "",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
@@ -2032,7 +2033,7 @@
|
||||
"is_submittable": 1,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-08-27 06:26:20.233037",
|
||||
"modified": "2015-10-16 06:13:50.058318",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Purchase Order",
|
||||
@@ -2040,7 +2041,7 @@
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
@@ -2080,7 +2081,7 @@
|
||||
},
|
||||
{
|
||||
"amend": 1,
|
||||
"apply_user_permissions": 1,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
@@ -2100,7 +2101,7 @@
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
|
||||
@@ -36,13 +36,7 @@ class PurchaseOrder(BuyingController):
|
||||
def validate(self):
|
||||
super(PurchaseOrder, self).validate()
|
||||
|
||||
if not self.status:
|
||||
self.status = "Draft"
|
||||
|
||||
from erpnext.controllers.status_updater import validate_status
|
||||
validate_status(self.status, ["Draft", "Submitted", "Stopped",
|
||||
"Cancelled"])
|
||||
|
||||
self.set_status()
|
||||
pc_obj = frappe.get_doc('Purchase Common')
|
||||
pc_obj.validate_for_items(self)
|
||||
self.check_for_stopped_status(pc_obj)
|
||||
@@ -160,13 +154,11 @@ class PurchaseOrder(BuyingController):
|
||||
|
||||
def update_status(self, status):
|
||||
self.check_modified_date()
|
||||
frappe.db.set(self,'status',cstr(status))
|
||||
|
||||
self.db_set('status', status)
|
||||
self.set_status(update=True)
|
||||
self.update_requested_qty()
|
||||
self.update_ordered_qty()
|
||||
|
||||
msgprint(_("Status of {0} {1} is now {2}").format(self.doctype, self.name, status))
|
||||
self.notify_modified()
|
||||
self.notify_update()
|
||||
clear_doctype_notifications(self)
|
||||
|
||||
def on_submit(self):
|
||||
@@ -183,8 +175,6 @@ class PurchaseOrder(BuyingController):
|
||||
|
||||
purchase_controller.update_last_purchase_rate(self, is_submit = 1)
|
||||
|
||||
frappe.db.set(self,'status','Submitted')
|
||||
|
||||
def on_cancel(self):
|
||||
pc_obj = frappe.get_doc('Purchase Common')
|
||||
self.check_for_stopped_status(pc_obj)
|
||||
@@ -238,7 +228,7 @@ def stop_or_unstop_purchase_orders(names, status):
|
||||
po.update_status("Stopped")
|
||||
else:
|
||||
if po.status == "Stopped":
|
||||
po.update_status("Submitted")
|
||||
po.update_status("Draft")
|
||||
|
||||
frappe.local.message_log = []
|
||||
|
||||
|
||||
@@ -4,17 +4,17 @@ frappe.listview_settings['Purchase Order'] = {
|
||||
get_indicator: function(doc) {
|
||||
if(doc.status==="Stopped") {
|
||||
return [__("Stopped"), "darkgrey", "status,=,Stopped"];
|
||||
} else if(flt(doc.per_received) < 100 && doc.status!=="Stopped") {
|
||||
if(flt(doc.per_billed) < 100) {
|
||||
} else if(flt(doc.per_received, 2) < 100 && doc.status!=="Stopped") {
|
||||
if(flt(doc.per_billed, 2) < 100) {
|
||||
return [__("To Receive and Bill"), "orange",
|
||||
"per_received,<,100|per_billed,<,100|status,!=,Stopped"];
|
||||
} else {
|
||||
return [__("To Receive"), "orange",
|
||||
"per_received,<,100|per_billed,=,100|status,!=,Stopped"];
|
||||
}
|
||||
} else if(flt(doc.per_received) == 100 && flt(doc.per_billed) < 100 && doc.status!=="Stopped") {
|
||||
} else if(flt(doc.per_received, 2) == 100 && flt(doc.per_billed, 2) < 100 && doc.status!=="Stopped") {
|
||||
return [__("To Bill"), "orange", "per_received,=,100|per_billed,<,100|status,!=,Stopped"];
|
||||
} else if(flt(doc.per_received) == 100 && flt(doc.per_billed) == 100 && doc.status!=="Stopped") {
|
||||
} else if(flt(doc.per_received, 2) == 100 && flt(doc.per_billed, 2) == 100 && doc.status!=="Stopped") {
|
||||
return [__("Completed"), "green", "per_received,=,100|per_billed,=,100|status,!=,Stopped"];
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1200,7 +1200,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2015-08-27 02:29:53.767477",
|
||||
"modified": "2015-10-19 03:04:51.773011",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Purchase Order Item",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user