Compare commits
283 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
0bd145a608 | ||
|
|
c663f5c2bd | ||
|
|
adde1cff48 | ||
|
|
bb9427d1ef | ||
|
|
052babc6b6 | ||
|
|
24fa06bc53 | ||
|
|
7c867ae9ad | ||
|
|
8f7317175d | ||
|
|
957e7a37be | ||
|
|
def71d4d5d | ||
|
|
ef511b160e | ||
|
|
09f9c96c53 | ||
|
|
1a2d121073 | ||
|
|
810bd35609 | ||
|
|
949d7dbaba | ||
|
|
72e6aa160c | ||
|
|
deb38f7a68 |
@@ -1,2 +1,2 @@
|
||||
from __future__ import unicode_literals
|
||||
__version__ = '6.2.0'
|
||||
__version__ = '6.5.0'
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -50,20 +50,20 @@ 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):
|
||||
@@ -89,11 +89,11 @@ class Account(Document):
|
||||
frappe.throw(_("Account balance already in Debit, you are not allowed to set 'Balance Must Be' as 'Credit'"))
|
||||
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"))
|
||||
@@ -207,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)
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -249,7 +249,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2015-08-10 16:59:43.974705",
|
||||
"modified": "2015-10-02 07:38:39.149782",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Bank Reconciliation Detail",
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2015-02-19 01:06:59.471417",
|
||||
"modified": "2015-10-02 07:38:40.727468",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Budget Detail",
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Series",
|
||||
"label": "Series",
|
||||
"no_copy": 0,
|
||||
"options": "C-FORM-",
|
||||
"permlevel": 0,
|
||||
@@ -192,7 +192,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Quarter",
|
||||
"label": "Quarter",
|
||||
"no_copy": 0,
|
||||
"options": "\nI\nII\nIII\nIV",
|
||||
"permlevel": 0,
|
||||
@@ -344,7 +344,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 3,
|
||||
"modified": "2015-09-07 15:51:26",
|
||||
"modified": "2015-10-02 07:38:40.926061",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "C-Form",
|
||||
|
||||
@@ -136,7 +136,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2015-01-01 14:29:58.597428",
|
||||
"modified": "2015-10-02 07:38:41.105885",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "C-Form Invoice Detail",
|
||||
|
||||
@@ -17,8 +17,7 @@ erpnext.accounts.CostCenterController = frappe.ui.form.Controller.extend({
|
||||
return {
|
||||
filters:[
|
||||
['Account', 'company', '=', me.frm.doc.company],
|
||||
['Account', 'root_type', '=', 'Expense'],
|
||||
['Account', 'is_group', '=', '0'],
|
||||
['Account', 'is_group', '=', '0']
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
@@ -298,7 +298,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-09-14 02:55:55.020690",
|
||||
"modified": "2015-10-02 07:38:42.617993",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Cost Center",
|
||||
|
||||
@@ -32,13 +32,13 @@ class CostCenter(NestedSet):
|
||||
for d in self.get('budgets'):
|
||||
if d.account:
|
||||
account_details = frappe.db.get_value("Account", d.account,
|
||||
["is_group", "company", "root_type"], as_dict=1)
|
||||
["is_group", "company", "report_type"], as_dict=1)
|
||||
if account_details.is_group:
|
||||
frappe.throw(_("Budget cannot be assigned against Group Account {0}").format(d.account))
|
||||
elif account_details.company != self.company:
|
||||
frappe.throw(_("Account {0} does not belongs to company {1}").format(d.account, self.company))
|
||||
elif account_details.root_type != "Expense":
|
||||
frappe.throw(_("Budget cannot be assigned against {0}, as it's not an Expense account")
|
||||
elif account_details.report_type != "Profit and Loss":
|
||||
frappe.throw(_("Budget cannot be assigned against {0}, as it's not an Income or Expense account")
|
||||
.format(d.account))
|
||||
|
||||
if [d.account, d.fiscal_year] in check_acc_list:
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-09-14 02:55:56.280252",
|
||||
"modified": "2015-10-02 07:38:50.942038",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Fiscal Year",
|
||||
|
||||
@@ -1,32 +1,38 @@
|
||||
[
|
||||
{
|
||||
"doctype": "Fiscal Year",
|
||||
"year": "_Test Fiscal Year 2012",
|
||||
"year_end_date": "2012-12-31",
|
||||
"doctype": "Fiscal Year",
|
||||
"year": "_Test Fiscal Year 2012",
|
||||
"year_end_date": "2012-12-31",
|
||||
"year_start_date": "2012-01-01"
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "Fiscal Year",
|
||||
"year": "_Test Fiscal Year 2013",
|
||||
"year_end_date": "2013-12-31",
|
||||
"doctype": "Fiscal Year",
|
||||
"year": "_Test Fiscal Year 2013",
|
||||
"year_end_date": "2013-12-31",
|
||||
"year_start_date": "2013-01-01"
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "Fiscal Year",
|
||||
"year": "_Test Fiscal Year 2014",
|
||||
"year_end_date": "2014-12-31",
|
||||
"doctype": "Fiscal Year",
|
||||
"year": "_Test Fiscal Year 2014",
|
||||
"year_end_date": "2014-12-31",
|
||||
"year_start_date": "2014-01-01"
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "Fiscal Year",
|
||||
"year": "_Test Fiscal Year 2015",
|
||||
"year_end_date": "2015-12-31",
|
||||
"doctype": "Fiscal Year",
|
||||
"year": "_Test Fiscal Year 2015",
|
||||
"year_end_date": "2015-12-31",
|
||||
"year_start_date": "2015-01-01"
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "Fiscal Year",
|
||||
"year": "_Test Fiscal Year 2016",
|
||||
"year_end_date": "2016-12-31",
|
||||
"doctype": "Fiscal Year",
|
||||
"year": "_Test Fiscal Year 2016",
|
||||
"year_end_date": "2016-12-31",
|
||||
"year_start_date": "2016-01-01"
|
||||
},
|
||||
{
|
||||
"doctype": "Fiscal Year",
|
||||
"year": "_Test Fiscal Year 2017",
|
||||
"year_end_date": "2017-12-31",
|
||||
"year_start_date": "2017-01-01"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2015-09-14 02:55:56.368682",
|
||||
"modified": "2015-10-02 07:38:51.045350",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Fiscal Year Company",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,15 +3,15 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
from frappe.utils import flt, fmt_money, getdate, formatdate
|
||||
from frappe import _
|
||||
|
||||
from frappe.utils import flt, fmt_money, getdate, formatdate
|
||||
from frappe.model.document import Document
|
||||
from erpnext.accounts.party import validate_party_gle_currency, 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
|
||||
class InvalidCurrency(frappe.ValidationError): pass
|
||||
class InvalidAccountCurrency(frappe.ValidationError): pass
|
||||
exclude_from_linked_with = True
|
||||
|
||||
class GLEntry(Document):
|
||||
def validate(self):
|
||||
@@ -101,25 +101,26 @@ class GLEntry(Document):
|
||||
if not frozen_accounts_modifier in frappe.get_roles():
|
||||
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 = frappe.db.get_value("Company", self.company, "default_currency")
|
||||
account_currency = frappe.db.get_value("Account", self.account, "account_currency") or company_currency
|
||||
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 = frappe.db.get_value(self.party_type, self.party, "party_account_currency") \
|
||||
or company_currency
|
||||
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)
|
||||
.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:
|
||||
@@ -159,7 +160,7 @@ def update_outstanding_amt(account, party_type, party, against_voucher_type, aga
|
||||
where against_voucher_type=%s and against_voucher=%s
|
||||
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":
|
||||
|
||||
@@ -335,6 +335,7 @@ 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,
|
||||
@@ -350,6 +351,9 @@ frappe.ui.form.on("Journal Entry Account", {
|
||||
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: {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@ import frappe
|
||||
from frappe.utils import cstr, flt, fmt_money, formatdate
|
||||
from frappe import msgprint, _, scrub
|
||||
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
|
||||
|
||||
|
||||
@@ -37,7 +37,8 @@ class JournalEntry(AccountsController):
|
||||
self.validate_credit_debit_note()
|
||||
self.validate_empty_accounts_table()
|
||||
self.set_account_and_party_balance()
|
||||
self.set_title()
|
||||
if not self.title:
|
||||
self.title = self.get_title()
|
||||
|
||||
def on_submit(self):
|
||||
self.check_credit_limit()
|
||||
@@ -45,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()
|
||||
@@ -146,7 +147,7 @@ class JournalEntry(AccountsController):
|
||||
|
||||
self.reference_totals = {}
|
||||
self.reference_types = {}
|
||||
self.reference_parties = {}
|
||||
self.reference_accounts = {}
|
||||
|
||||
for d in self.get("accounts"):
|
||||
if not d.reference_type:
|
||||
@@ -169,8 +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
|
||||
if d.party_type and d.party:
|
||||
self.reference_parties[d.reference_name] = [d.party_type, d.party]
|
||||
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)])
|
||||
@@ -196,7 +196,7 @@ 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]
|
||||
party_type, party = self.reference_parties.get(reference_name)
|
||||
account = self.reference_accounts[reference_name]
|
||||
|
||||
if reference_type in ("Sales Order", "Purchase Order"):
|
||||
order = frappe.db.get_value(reference_type, reference_name,
|
||||
@@ -212,8 +212,8 @@ class JournalEntry(AccountsController):
|
||||
if cstr(order.status) == "Stopped":
|
||||
frappe.throw(_("{0} {1} is stopped").format(reference_type, reference_name))
|
||||
|
||||
party_account_currency = frappe.db.get_value(party_type, party, "party_account_currency")
|
||||
if party_account_currency == self.company_currency:
|
||||
account_currency = get_account_currency(account)
|
||||
if account_currency == self.company_currency:
|
||||
voucher_total = order.base_grand_total
|
||||
else:
|
||||
voucher_total = order.grand_total
|
||||
@@ -278,9 +278,6 @@ class JournalEntry(AccountsController):
|
||||
if not self.multi_currency:
|
||||
frappe.throw(_("Please check Multi Currency option to allow accounts with other currency"))
|
||||
|
||||
if len(alternate_currency) > 1:
|
||||
frappe.throw(_("Only one alternate currency can be used in a single Journal Entry"))
|
||||
|
||||
self.set_exchange_rate()
|
||||
|
||||
for d in self.get("accounts"):
|
||||
@@ -386,6 +383,7 @@ class JournalEntry(AccountsController):
|
||||
|
||||
# If any row without amount, set the diff on that row
|
||||
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
|
||||
@@ -475,9 +473,18 @@ class JournalEntry(AccountsController):
|
||||
frappe.throw("Accounts table cannot be blank.")
|
||||
|
||||
def set_account_and_party_balance(self):
|
||||
account_balance = {}
|
||||
party_balance = {}
|
||||
for d in self.get("accounts"):
|
||||
d.account_balance = get_balance_on(account=d.account, date=self.posting_date)
|
||||
d.party_balance = get_balance_on(party_type=d.party_type, party=d.party, date=self.posting_date)
|
||||
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):
|
||||
@@ -551,7 +558,7 @@ 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.debit_to, pi.party_account_currency, pi.company,
|
||||
exchange_rate = get_exchange_rate(pi.credit_to, pi.party_account_currency, pi.company,
|
||||
pi.doctype, pi.name)
|
||||
|
||||
jv = get_payment_entry(pi)
|
||||
@@ -599,8 +606,8 @@ 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")
|
||||
party_account_currency = frappe.db.get_value("Account", party_account, "account_currency")
|
||||
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)
|
||||
|
||||
@@ -650,8 +657,8 @@ 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")
|
||||
party_account_currency = frappe.db.get_value("Account", party_account, "account_currency")
|
||||
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)
|
||||
|
||||
@@ -769,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)
|
||||
@@ -816,17 +823,20 @@ def get_exchange_rate(account, account_currency, company,
|
||||
if account_currency != company_currency:
|
||||
if reference_type in ("Sales Invoice", "Purchase Invoice") and reference_name:
|
||||
exchange_rate = frappe.db.get_value(reference_type, reference_name, "conversion_rate")
|
||||
elif account_details.account_type == "Bank" and \
|
||||
|
||||
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:
|
||||
if not exchange_rate and account_currency:
|
||||
exchange_rate = get_exchange_rate(account_currency, company_currency)
|
||||
|
||||
else:
|
||||
exchange_rate = 1
|
||||
|
||||
return exchange_rate
|
||||
# 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
|
||||
|
||||
@@ -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):
|
||||
@@ -166,15 +167,15 @@ class TestJournalEntry(unittest.TestCase):
|
||||
existing_expense = self.get_actual_expense(posting_date)
|
||||
make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
||||
"_Test Bank - _TC", -existing_expense, "_Test Cost Center - _TC", submit=True)
|
||||
|
||||
|
||||
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,
|
||||
|
||||
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)
|
||||
@@ -197,12 +198,10 @@ class TestJournalEntry(unittest.TestCase):
|
||||
"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()
|
||||
@@ -212,6 +211,40 @@ class TestJournalEntry(unittest.TestCase):
|
||||
|
||||
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"
|
||||
@@ -231,7 +264,7 @@ def make_journal_entry(account1, account2, amount, cost_center=None, exchange_ra
|
||||
"cost_center": cost_center,
|
||||
"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
|
||||
"exchange_rate": exchange_rate
|
||||
}
|
||||
])
|
||||
if save or submit:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -65,7 +65,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-09-14 02:55:58.003800",
|
||||
"modified": "2015-10-02 07:38:57.318104",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Mode of Payment",
|
||||
|
||||
@@ -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("""
|
||||
@@ -79,8 +77,12 @@ class PaymentReconciliation(Document):
|
||||
`tabGL Entry`
|
||||
where
|
||||
party_type = %(party_type)s and party = %(party)s
|
||||
and voucher_type != "Journal Entry"
|
||||
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,
|
||||
@@ -102,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
|
||||
|
||||
@@ -136,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",
|
||||
|
||||
@@ -141,7 +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;
|
||||
c.payment_amount = d.outstanding_amount;
|
||||
|
||||
if (frm.doc.set_payment_amount) {
|
||||
c.payment_amount = d.outstanding_amount;
|
||||
}
|
||||
});
|
||||
}
|
||||
refresh_field("vouchers");
|
||||
|
||||
@@ -185,6 +185,28 @@
|
||||
"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,
|
||||
@@ -474,7 +496,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 1,
|
||||
"istable": 0,
|
||||
"modified": "2015-08-31 18:58:21.813054",
|
||||
"modified": "2015-10-01 09:43:24.199025",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Tool",
|
||||
|
||||
@@ -7,6 +7,7 @@ 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):
|
||||
@@ -59,7 +60,7 @@ def get_outstanding_vouchers(args):
|
||||
|
||||
args = json.loads(args)
|
||||
|
||||
party_account_currency = frappe.db.get_value("Account", args.get("party_account"), "account_currency")
|
||||
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":
|
||||
@@ -71,7 +72,7 @@ def get_outstanding_vouchers(args):
|
||||
|
||||
# Get all outstanding sales /purchase invoices
|
||||
outstanding_invoices = get_outstanding_invoices(amount_query, args.get("party_account"),
|
||||
args.get("party_type"), args.get("party"), with_journal_entry=False)
|
||||
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"),
|
||||
@@ -112,7 +113,7 @@ def get_orders_to_be_billed(party_type, party, party_account_currency, company_c
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_against_voucher_amount(against_voucher_type, against_voucher_no, party_account, company):
|
||||
party_account_currency = frappe.db.get_value("Account", party_account, "account_currency")
|
||||
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"
|
||||
|
||||
|
||||
@@ -149,7 +149,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2015-08-31 18:58:35.537060",
|
||||
"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",
|
||||
|
||||
@@ -622,7 +622,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-09-07 15:51:26",
|
||||
"modified": "2015-10-02 07:39:00.196535",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "POS Profile",
|
||||
|
||||
@@ -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-09-11 12:19:52.242771",
|
||||
"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
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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,7 @@ 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 = frappe.db.get_value("Account", self.credit_to,
|
||||
["account_type", "report_type", "account_currency"], as_dict=True)
|
||||
|
||||
if account.report_type != "Balance Sheet":
|
||||
@@ -99,7 +100,7 @@ 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):
|
||||
@@ -251,7 +252,7 @@ class PurchaseInvoice(BuyingController):
|
||||
expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation")
|
||||
|
||||
gl_entries = []
|
||||
|
||||
|
||||
# parent's gl entry
|
||||
if self.base_grand_total:
|
||||
gl_entries.append(
|
||||
@@ -272,10 +273,10 @@ class PurchaseInvoice(BuyingController):
|
||||
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 = frappe.db.get_value("Account", tax.account_head, "account_currency")
|
||||
|
||||
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,
|
||||
@@ -301,7 +302,7 @@ class PurchaseInvoice(BuyingController):
|
||||
stock_items = self.get_stock_items()
|
||||
for item in self.get("items"):
|
||||
if flt(item.base_net_amount):
|
||||
account_currency = frappe.db.get_value("Account", item.expense_account, "account_currency")
|
||||
account_currency = get_account_currency(item.expense_account)
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": item.expense_account,
|
||||
@@ -363,8 +364,8 @@ 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 = frappe.db.get_value("Account", self.write_off_account, "account_currency")
|
||||
|
||||
write_off_account_currency = get_account_currency(self.write_off_account)
|
||||
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": self.credit_to,
|
||||
@@ -420,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,7 +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.controllers.accounts_controller import InvalidCurrency
|
||||
from erpnext.exceptions import InvalidCurrency
|
||||
|
||||
test_dependencies = ["Item", "Cost Center"]
|
||||
test_ignore = ["Serial No"]
|
||||
@@ -219,7 +219,7 @@ class TestPurchaseInvoice(unittest.TestCase):
|
||||
pi.load_from_db()
|
||||
|
||||
self.assertTrue(frappe.db.sql("""select name from `tabJournal Entry Account`
|
||||
where reference_type='Purchase Invoice'
|
||||
where reference_type='Purchase Invoice'
|
||||
and reference_name=%s and debit_in_account_currency=300""", pi.name))
|
||||
|
||||
self.assertEqual(pi.outstanding_amount, 1212.30)
|
||||
@@ -237,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()
|
||||
@@ -278,14 +278,14 @@ class TestPurchaseInvoice(unittest.TestCase):
|
||||
self.assertEquals(expected_values[gle.account][1], gle.credit)
|
||||
|
||||
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",
|
||||
|
||||
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,
|
||||
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)
|
||||
@@ -308,16 +308,16 @@ class TestPurchaseInvoice(unittest.TestCase):
|
||||
"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
|
||||
|
||||
@@ -164,7 +164,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2015-08-25 17:51:30.274069",
|
||||
"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",
|
||||
|
||||
@@ -176,7 +176,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-09-11 12:19:53.741725",
|
||||
"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);
|
||||
@@ -175,7 +182,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
||||
me.apply_pricing_rule();
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
debit_to: function() {
|
||||
var me = this;
|
||||
if(this.frm.doc.debit_to) {
|
||||
@@ -193,7 +200,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
allocated_amount: function() {
|
||||
@@ -369,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}
|
||||
}
|
||||
});
|
||||
@@ -417,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);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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()
|
||||
@@ -90,7 +100,7 @@ class SalesInvoice(SellingController):
|
||||
|
||||
# this sequence because outstanding may get -ve
|
||||
self.make_gl_entries()
|
||||
|
||||
|
||||
if not self.is_return:
|
||||
self.update_billing_status_for_zero_amount_refdoc("Sales Order")
|
||||
self.check_credit_limit()
|
||||
@@ -161,10 +171,10 @@ class SalesInvoice(SellingController):
|
||||
'extra_cond': """ and exists (select name from `tabSales Invoice` where name=`tabSales Invoice Item`.parent and update_stock=1 and is_return=1)"""
|
||||
}
|
||||
])
|
||||
|
||||
|
||||
def check_credit_limit(self):
|
||||
from erpnext.selling.doctype.customer.customer import check_credit_limit
|
||||
|
||||
|
||||
validate_against_credit_limit = False
|
||||
for d in self.get("items"):
|
||||
if not (d.sales_order or d.delivery_note):
|
||||
@@ -177,7 +187,7 @@ class SalesInvoice(SellingController):
|
||||
pos = self.set_pos_fields(for_validate)
|
||||
|
||||
if not self.debit_to:
|
||||
self.debit_to = get_party_account(self.company, self.customer, "Customer")
|
||||
self.debit_to = get_party_account("Customer", self.customer, self.company)
|
||||
if not self.due_date and self.customer:
|
||||
self.due_date = get_due_date(self.posting_date, "Customer", self.customer, self.company)
|
||||
|
||||
@@ -197,8 +207,8 @@ class SalesInvoice(SellingController):
|
||||
def validate_time_logs_are_submitted(self):
|
||||
for d in self.get("items"):
|
||||
if d.time_log_batch:
|
||||
status = frappe.db.get_value("Time Log Batch", d.time_log_batch, "status")
|
||||
if status!="Submitted":
|
||||
docstatus = frappe.db.get_value("Time Log Batch", d.time_log_batch, "docstatus")
|
||||
if docstatus!=1:
|
||||
frappe.throw(_("Time Log Batch {0} must be 'Submitted'").format(d.time_log_batch))
|
||||
|
||||
def set_pos_fields(self, for_validate=False):
|
||||
@@ -246,7 +256,7 @@ class SalesInvoice(SellingController):
|
||||
def get_advances(self):
|
||||
if not self.is_return:
|
||||
super(SalesInvoice, self).get_advances(self.debit_to, "Customer", self.customer,
|
||||
"Sales Invoice Advance", "advances", "credit", "sales_order")
|
||||
"Sales Invoice Advance", "advances", "credit_in_account_currency", "sales_order")
|
||||
|
||||
def get_company_abbr(self):
|
||||
return frappe.db.sql("select abbr from tabCompany where name=%s", self.company)[0][0]
|
||||
@@ -282,7 +292,7 @@ class SalesInvoice(SellingController):
|
||||
reconcile_against_document(lst)
|
||||
|
||||
def validate_debit_to_acc(self):
|
||||
account = frappe.db.get_value("Account", self.debit_to,
|
||||
account = frappe.db.get_value("Account", self.debit_to,
|
||||
["account_type", "report_type", "account_currency"], as_dict=True)
|
||||
|
||||
if account.report_type != "Balance Sheet":
|
||||
@@ -290,7 +300,7 @@ 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):
|
||||
@@ -412,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', [])
|
||||
|
||||
@@ -437,18 +447,18 @@ class SalesInvoice(SellingController):
|
||||
if cint(self.is_pos) == 1:
|
||||
if flt(self.paid_amount) == 0:
|
||||
if self.cash_bank_account:
|
||||
frappe.db.set(self, 'paid_amount',
|
||||
flt(flt(self.grand_total) - flt(self.write_off_amount), self.precision("paid_amount")))
|
||||
frappe.db.set(self, 'paid_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)
|
||||
frappe.msgprint(_("Note: Payment Entry will not be created since 'Cash or Bank Account' was not specified"))
|
||||
else:
|
||||
frappe.db.set(self,'paid_amount',0)
|
||||
|
||||
frappe.db.set(self, 'base_paid_amount',
|
||||
|
||||
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 +497,7 @@ class SalesInvoice(SellingController):
|
||||
from erpnext.accounts.general_ledger import merge_similar_entries
|
||||
|
||||
gl_entries = []
|
||||
|
||||
|
||||
self.make_customer_gl_entry(gl_entries)
|
||||
|
||||
self.make_tax_gl_entries(gl_entries)
|
||||
@@ -522,7 +532,7 @@ class SalesInvoice(SellingController):
|
||||
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 = frappe.db.get_value("Account", tax.account_head, "account_currency")
|
||||
account_currency = get_account_currency(tax.account_head)
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": tax.account_head,
|
||||
@@ -538,7 +548,7 @@ class SalesInvoice(SellingController):
|
||||
# income account gl entries
|
||||
for item in self.get("items"):
|
||||
if flt(item.base_net_amount):
|
||||
account_currency = frappe.db.get_value("Account", item.income_account, "account_currency")
|
||||
account_currency = get_account_currency(item.income_account)
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": item.income_account,
|
||||
@@ -557,7 +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 = frappe.db.get_value("Account", self.cash_bank_account, "account_currency")
|
||||
bank_account_currency = get_account_currency(self.cash_bank_account)
|
||||
# POS, make payment entries
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
@@ -585,8 +595,8 @@ class SalesInvoice(SellingController):
|
||||
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 = frappe.db.get_value("Account", self.write_off_account, "account_currency")
|
||||
|
||||
write_off_account_currency = get_account_currency(self.write_off_account)
|
||||
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": self.debit_to,
|
||||
@@ -627,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,8 +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.controllers.accounts_controller import InvalidCurrency
|
||||
from erpnext.accounts.doctype.gl_entry.gl_entry import InvalidAccountCurrency
|
||||
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):
|
||||
@@ -689,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)
|
||||
@@ -703,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,13 +835,13 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
self.assertEquals(si.total_taxes_and_charges, 234.44)
|
||||
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",
|
||||
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,
|
||||
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)
|
||||
@@ -871,7 +864,7 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
"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])
|
||||
@@ -883,38 +876,38 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
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",
|
||||
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",
|
||||
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",
|
||||
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",
|
||||
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",
|
||||
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):
|
||||
|
||||
@@ -164,7 +164,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2015-08-21 16:22:28.866049",
|
||||
"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();
|
||||
});
|
||||
|
||||
@@ -164,29 +164,6 @@
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"description": "Specify a list of Territories, for which, this Taxes Master is valid",
|
||||
"fieldname": "territories",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Valid for Territories",
|
||||
"no_copy": 0,
|
||||
"options": "Applicable Territory",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
@@ -198,7 +175,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-09-11 12:19:46.488710",
|
||||
"modified": "2015-10-02 07:39:12.157257",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Taxes and Charges Template",
|
||||
@@ -206,7 +183,7 @@
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
|
||||
@@ -5,7 +5,6 @@ from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
from erpnext.controllers.accounts_controller import validate_taxes_and_charges, validate_inclusive_tax
|
||||
from frappe.utils.nestedset import get_root_of
|
||||
|
||||
class SalesTaxesandChargesTemplate(Document):
|
||||
def validate(self):
|
||||
@@ -20,10 +19,6 @@ def valdiate_taxes_and_charges_template(doc):
|
||||
where ifnull(is_default,0) = 1 and name != %s and company = %s""".format(doc.doctype),
|
||||
(doc.name, doc.company))
|
||||
|
||||
if doc.meta.get_field("territories"):
|
||||
if not doc.territories:
|
||||
doc.append("territories", {"territory": get_root_of("Territory") })
|
||||
|
||||
for tax in doc.get("taxes"):
|
||||
validate_taxes_and_charges(tax)
|
||||
validate_inclusive_tax(tax, doc)
|
||||
|
||||
@@ -20,19 +20,7 @@
|
||||
"rate": 6.36
|
||||
}
|
||||
],
|
||||
"title": "_Test Sales Taxes and Charges Template",
|
||||
"territories": [
|
||||
{
|
||||
"doctype": "Applicable Territory",
|
||||
"parentfield": "territories",
|
||||
"territory": "All Territories"
|
||||
},
|
||||
{
|
||||
"doctype": "Applicable Territory",
|
||||
"parentfield": "territories",
|
||||
"territory": "_Test Territory Rest Of The World"
|
||||
}
|
||||
]
|
||||
"title": "_Test Sales Taxes and Charges Template"
|
||||
},
|
||||
{
|
||||
"company": "_Test Company",
|
||||
@@ -115,14 +103,7 @@
|
||||
"row_id": 7
|
||||
}
|
||||
],
|
||||
"title": "_Test India Tax Master",
|
||||
"territories": [
|
||||
{
|
||||
"doctype": "Applicable Territory",
|
||||
"parentfield": "territories",
|
||||
"territory": "_Test Territory India"
|
||||
}
|
||||
]
|
||||
"title": "_Test India Tax Master"
|
||||
},
|
||||
{
|
||||
"company": "_Test Company",
|
||||
@@ -145,13 +126,76 @@
|
||||
"rate": 4
|
||||
}
|
||||
],
|
||||
"title": "_Test Sales Taxes and Charges Template - Rest of the World",
|
||||
"territories": [
|
||||
"title": "_Test Sales Taxes and Charges Template - Rest of the World"
|
||||
},
|
||||
{
|
||||
"company": "_Test Company",
|
||||
"doctype": "Sales Taxes and Charges Template",
|
||||
"taxes": [
|
||||
{
|
||||
"doctype": "Applicable Territory",
|
||||
"parentfield": "territories",
|
||||
"territory": "_Test Territory Rest Of The World"
|
||||
"account_head": "_Test Account VAT - _TC",
|
||||
"charge_type": "On Net Total",
|
||||
"description": "VAT",
|
||||
"doctype": "Sales Taxes and Charges",
|
||||
"parentfield": "taxes",
|
||||
"rate": 12
|
||||
},
|
||||
{
|
||||
"account_head": "_Test Account Service Tax - _TC",
|
||||
"charge_type": "On Net Total",
|
||||
"description": "Service Tax",
|
||||
"doctype": "Sales Taxes and Charges",
|
||||
"parentfield": "taxes",
|
||||
"rate": 4
|
||||
}
|
||||
]
|
||||
],
|
||||
"title": "_Test Sales Taxes and Charges Template 1"
|
||||
},
|
||||
{
|
||||
"company": "_Test Company",
|
||||
"doctype": "Sales Taxes and Charges Template",
|
||||
"taxes": [
|
||||
{
|
||||
"account_head": "_Test Account VAT - _TC",
|
||||
"charge_type": "On Net Total",
|
||||
"description": "VAT",
|
||||
"doctype": "Sales Taxes and Charges",
|
||||
"parentfield": "taxes",
|
||||
"rate": 12
|
||||
},
|
||||
{
|
||||
"account_head": "_Test Account Service Tax - _TC",
|
||||
"charge_type": "On Net Total",
|
||||
"description": "Service Tax",
|
||||
"doctype": "Sales Taxes and Charges",
|
||||
"parentfield": "taxes",
|
||||
"rate": 4
|
||||
}
|
||||
],
|
||||
"title": "_Test Sales Taxes and Charges Template 2"
|
||||
},
|
||||
{
|
||||
"doctype" : "Sales Taxes and Charges Template",
|
||||
"title": "_Test Tax 1",
|
||||
"company": "_Test Company",
|
||||
"taxes":[{
|
||||
"charge_type": "Actual",
|
||||
"account_head": "Sales Expenses - _TC",
|
||||
"cost_center": "Main - _TC",
|
||||
"description": "Test Shopping cart taxes with Tax Rule",
|
||||
"tax_amount": 1000
|
||||
}]
|
||||
},
|
||||
{
|
||||
"doctype" : "Sales Taxes and Charges Template",
|
||||
"title": "_Test Tax 2",
|
||||
"company": "_Test Company",
|
||||
"taxes":[{
|
||||
"charge_type": "Actual",
|
||||
"account_head": "Sales Expenses - _TC",
|
||||
"cost_center": "Main - _TC",
|
||||
"description": "Test Shopping cart taxes with Tax Rule",
|
||||
"tax_amount": 200
|
||||
}]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
$.extend(cur_frm.cscript, {
|
||||
onload: function() {
|
||||
erpnext.add_applicable_territory();
|
||||
}
|
||||
});
|
||||
@@ -35,14 +35,16 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "column_break_2",
|
||||
"fieldtype": "Column Break",
|
||||
"fieldname": "disabled",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Disabled",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
@@ -62,7 +64,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Calculate Based On",
|
||||
"label": "Calculate Based On",
|
||||
"no_copy": 0,
|
||||
"options": "Net Total\nNet Weight",
|
||||
"permlevel": 0,
|
||||
@@ -78,6 +80,7 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "eval:!doc.disabled",
|
||||
"fieldname": "rule_conditions_section",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -121,12 +124,14 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "eval:!doc.disabled",
|
||||
"fieldname": "section_break_6",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Valid for Countries",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
@@ -141,21 +146,20 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"description": "Specify a list of Territories, for which, this Shipping Rule is valid",
|
||||
"fieldname": "territories",
|
||||
"fieldtype": "Table",
|
||||
"fieldname": "worldwide_shipping",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Valid For Territories",
|
||||
"label": "Worldwide Shipping",
|
||||
"no_copy": 0,
|
||||
"options": "Applicable Territory",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
@@ -164,8 +168,33 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "column_break_8",
|
||||
"fieldtype": "Column Break",
|
||||
"depends_on": "eval:!doc.worldwide_shipping",
|
||||
"fieldname": "countries",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Valid for Countries",
|
||||
"no_copy": 0,
|
||||
"options": "Shipping Rule Country",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "eval:!doc.disabled",
|
||||
"fieldname": "section_break_10",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
@@ -206,8 +235,8 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "section_break_10",
|
||||
"fieldtype": "Section Break",
|
||||
"fieldname": "column_break_12",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
@@ -244,26 +273,6 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "column_break_12",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -296,7 +305,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-09-07 15:51:26",
|
||||
"modified": "2015-10-02 07:39:12.778062",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Shipping Rule",
|
||||
@@ -304,7 +313,7 @@
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
@@ -324,7 +333,7 @@
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
|
||||
@@ -22,6 +22,12 @@ class ShippingRule(Document):
|
||||
self.sort_shipping_rule_conditions()
|
||||
self.validate_overlapping_shipping_rule_conditions()
|
||||
|
||||
if self.worldwide_shipping:
|
||||
self.countries = []
|
||||
|
||||
elif not len([d.country for d in self.countries if d.country]):
|
||||
frappe.throw(_("Please specify a country for this Shipping Rule or check Worldwide Shipping"))
|
||||
|
||||
def validate_from_to_values(self):
|
||||
zero_to_values = []
|
||||
|
||||
|
||||
@@ -1,116 +1,100 @@
|
||||
[
|
||||
{
|
||||
"account": "_Test Account Shipping Charges - _TC",
|
||||
"calculate_based_on": "Net Total",
|
||||
"company": "_Test Company",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"doctype": "Shipping Rule",
|
||||
"label": "_Test Shipping Rule",
|
||||
"name": "_Test Shipping Rule",
|
||||
"account": "_Test Account Shipping Charges - _TC",
|
||||
"calculate_based_on": "Net Total",
|
||||
"company": "_Test Company",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"doctype": "Shipping Rule",
|
||||
"label": "_Test Shipping Rule",
|
||||
"name": "_Test Shipping Rule",
|
||||
"conditions": [
|
||||
{
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 0,
|
||||
"parentfield": "conditions",
|
||||
"shipping_amount": 50.0,
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 0,
|
||||
"parentfield": "conditions",
|
||||
"shipping_amount": 50.0,
|
||||
"to_value": 100
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 101,
|
||||
"parentfield": "conditions",
|
||||
"shipping_amount": 100.0,
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 101,
|
||||
"parentfield": "conditions",
|
||||
"shipping_amount": 100.0,
|
||||
"to_value": 200
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 201,
|
||||
"parentfield": "conditions",
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 201,
|
||||
"parentfield": "conditions",
|
||||
"shipping_amount": 0.0
|
||||
}
|
||||
],
|
||||
"territories": [
|
||||
{
|
||||
"doctype": "Applicable Territory",
|
||||
"parentfield": "territories",
|
||||
"territory": "_Test Territory"
|
||||
}
|
||||
]
|
||||
},
|
||||
],
|
||||
"worldwide_shipping": 1
|
||||
},
|
||||
{
|
||||
"account": "_Test Account Shipping Charges - _TC",
|
||||
"calculate_based_on": "Net Total",
|
||||
"company": "_Test Company",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"doctype": "Shipping Rule",
|
||||
"label": "_Test Shipping Rule - India",
|
||||
"name": "_Test Shipping Rule - India",
|
||||
"account": "_Test Account Shipping Charges - _TC",
|
||||
"calculate_based_on": "Net Total",
|
||||
"company": "_Test Company",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"doctype": "Shipping Rule",
|
||||
"label": "_Test Shipping Rule - India",
|
||||
"name": "_Test Shipping Rule - India",
|
||||
"conditions": [
|
||||
{
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 0,
|
||||
"parentfield": "conditions",
|
||||
"shipping_amount": 50.0,
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 0,
|
||||
"parentfield": "conditions",
|
||||
"shipping_amount": 50.0,
|
||||
"to_value": 100
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 101,
|
||||
"parentfield": "conditions",
|
||||
"shipping_amount": 100.0,
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 101,
|
||||
"parentfield": "conditions",
|
||||
"shipping_amount": 100.0,
|
||||
"to_value": 200
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 201,
|
||||
"parentfield": "conditions",
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 201,
|
||||
"parentfield": "conditions",
|
||||
"shipping_amount": 0.0
|
||||
}
|
||||
],
|
||||
"territories": [
|
||||
{
|
||||
"doctype": "Applicable Territory",
|
||||
"parentfield": "territories",
|
||||
"territory": "_Test Territory India"
|
||||
}
|
||||
],
|
||||
"countries": [
|
||||
{"country": "India"}
|
||||
]
|
||||
},
|
||||
},
|
||||
{
|
||||
"account": "_Test Account Shipping Charges - _TC",
|
||||
"calculate_based_on": "Net Total",
|
||||
"company": "_Test Company",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"doctype": "Shipping Rule",
|
||||
"label": "_Test Shipping Rule - Rest of the World",
|
||||
"name": "_Test Shipping Rule - Rest of the World",
|
||||
"account": "_Test Account Shipping Charges - _TC",
|
||||
"calculate_based_on": "Net Total",
|
||||
"company": "_Test Company",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"doctype": "Shipping Rule",
|
||||
"label": "_Test Shipping Rule - Rest of the World",
|
||||
"name": "_Test Shipping Rule - Rest of the World",
|
||||
"conditions": [
|
||||
{
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 0,
|
||||
"parentfield": "conditions",
|
||||
"shipping_amount": 500.0,
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 0,
|
||||
"parentfield": "conditions",
|
||||
"shipping_amount": 500.0,
|
||||
"to_value": 1000
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 1001,
|
||||
"parentfield": "conditions",
|
||||
"shipping_amount": 1000.0,
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 1001,
|
||||
"parentfield": "conditions",
|
||||
"shipping_amount": 1000.0,
|
||||
"to_value": 2000
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 2001,
|
||||
"parentfield": "conditions",
|
||||
"doctype": "Shipping Rule Condition",
|
||||
"from_value": 2001,
|
||||
"parentfield": "conditions",
|
||||
"shipping_amount": 1500.0
|
||||
}
|
||||
],
|
||||
"territories": [
|
||||
{
|
||||
"doctype": "Applicable Territory",
|
||||
"parentfield": "territories",
|
||||
"territory": "_Test Territory Rest Of The World"
|
||||
}
|
||||
]
|
||||
],
|
||||
"worldwide_shipping": 1
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2013-12-20 19:21:46",
|
||||
"modified": "2015-10-02 07:39:12.974539",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Shipping Rule Condition",
|
||||
|
||||
@@ -2,26 +2,27 @@
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"creation": "2013-06-20 12:48:38",
|
||||
"creation": "2015-09-17 06:43:22.767534",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Other",
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"description": "",
|
||||
"fieldname": "territory",
|
||||
"fieldname": "country",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Territory",
|
||||
"label": "Country",
|
||||
"no_copy": 0,
|
||||
"options": "Territory",
|
||||
"options": "Country",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
@@ -33,18 +34,20 @@
|
||||
],
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 1,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2015-01-01 14:29:58.724652",
|
||||
"modified": "2015-10-02 07:39:13.035775",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Setup",
|
||||
"name": "Applicable Territory",
|
||||
"module": "Accounts",
|
||||
"name": "Shipping Rule Country",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0
|
||||
"read_only_onload": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
||||
@@ -1,12 +1,10 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
from frappe.model.document import Document
|
||||
|
||||
class ApplicableTerritory(Document):
|
||||
pass
|
||||
class ShippingRuleCountry(Document):
|
||||
pass
|
||||
60
erpnext/accounts/doctype/tax_rule/tax_rule.js
Normal file
60
erpnext/accounts/doctype/tax_rule/tax_rule.js
Normal file
@@ -0,0 +1,60 @@
|
||||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
cur_frm.add_fetch("customer", "customer_group", "customer_group" );
|
||||
cur_frm.add_fetch("supplier", "supplier_type", "supplier_type" );
|
||||
|
||||
cur_frm.toggle_reqd("sales_tax_template", cur_frm.doc.tax_type=="Sales");
|
||||
cur_frm.toggle_reqd("purchase_tax_template", cur_frm.doc.tax_type=="Purchase");
|
||||
|
||||
|
||||
frappe.ui.form.on("Tax Rule", "onload", function(frm) {
|
||||
if(frm.doc.__islocal){
|
||||
frm.set_value("use_for_shopping_cart", 1);
|
||||
}
|
||||
})
|
||||
|
||||
frappe.ui.form.on("Tax Rule", "use_for_shopping_cart", function(frm) {
|
||||
if(!frm.doc.use_for_shopping_cart && (frappe.get_list("Tax Rule", {"use_for_shopping_cart":1}).length == 0)){
|
||||
frappe.model.get_value("Shopping Cart Settings", "Shopping Cart Settings", "enabled", function(docfield) {
|
||||
if(docfield.enabled){
|
||||
frm.set_value("use_for_shopping_cart", 1);
|
||||
frappe.throw(__("Shopping Cart is enabled"));
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
frappe.ui.form.on("Tax Rule", "customer", function(frm) {
|
||||
frappe.call({
|
||||
method:"erpnext.accounts.doctype.tax_rule.tax_rule.get_party_details",
|
||||
args: {
|
||||
"party": frm.doc.customer,
|
||||
"party_type": "customer"
|
||||
},
|
||||
callback: function(r) {
|
||||
if(!r.exc) {
|
||||
$.each(r.message, function(k, v) {
|
||||
frm.set_value(k, v);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
frappe.ui.form.on("Tax Rule", "supplier", function(frm) {
|
||||
frappe.call({
|
||||
method:"erpnext.accounts.doctype.tax_rule.tax_rule.get_party_details",
|
||||
args: {
|
||||
"party": frm.doc.supplier,
|
||||
"party_type": "supplier"
|
||||
},
|
||||
callback: function(r) {
|
||||
if(!r.exc) {
|
||||
$.each(r.message, function(k, v) {
|
||||
frm.set_value(k, v);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,27 +1,30 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 0,
|
||||
"creation": "2013-04-30 12:58:38",
|
||||
"autoname": "TR.####",
|
||||
"creation": "2015-08-07 02:33:52.670866",
|
||||
"custom": 0,
|
||||
"description": "System for managing Backups",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "System",
|
||||
"document_type": "Setup",
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "setup",
|
||||
"fieldtype": "Section Break",
|
||||
"default": "Sales",
|
||||
"fieldname": "tax_type",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Download Backups",
|
||||
"in_list_view": 1,
|
||||
"label": "Tax Type",
|
||||
"no_copy": 0,
|
||||
"options": "Sales\nPurchase",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
@@ -34,13 +37,13 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "current_backups",
|
||||
"fieldtype": "HTML",
|
||||
"fieldname": "use_for_shopping_cart",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Current Backups",
|
||||
"label": "Use for Shopping Cart",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
@@ -56,56 +59,12 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"description": "",
|
||||
"fieldname": "sync_with_dropbox",
|
||||
"fieldtype": "Section Break",
|
||||
"fieldname": "column_break_1",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Sync with Dropbox",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "backup_right_now",
|
||||
"fieldtype": "Button",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Backup Right Now",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "send_backups_to_dropbox",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Send Backups to Dropbox",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
@@ -121,18 +80,18 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "send_backups_to_dropbox",
|
||||
"description": "Note: Backups and files are not deleted from Dropbox, you will have to delete them manually.",
|
||||
"fieldname": "upload_backups_to_dropbox",
|
||||
"fieldtype": "Select",
|
||||
"depends_on": "eval:doc.tax_type==\"Sales\"",
|
||||
"fieldname": "sales_tax_template",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Upload Backups to Dropbox",
|
||||
"label": "Sales Tax Template",
|
||||
"no_copy": 0,
|
||||
"options": "Never\nWeekly\nDaily",
|
||||
"options": "Sales Taxes and Charges Template",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
@@ -145,17 +104,18 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "send_backups_to_dropbox",
|
||||
"description": "Email ids separated by commas.",
|
||||
"fieldname": "send_notifications_to",
|
||||
"fieldtype": "Data",
|
||||
"depends_on": "eval:doc.tax_type==\"Purchase\"",
|
||||
"fieldname": "purchase_tax_template",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Send Notifications To",
|
||||
"label": "Purchase Tax Template",
|
||||
"no_copy": 0,
|
||||
"options": "Purchase Taxes and Charges Template",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
@@ -168,123 +128,16 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "dropbox_access_key",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Dropbox Access Key",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "dropbox_access_secret",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Dropbox Access Secret",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "dropbox_access_allowed",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Dropbox Access Allowed",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "send_backups_to_dropbox",
|
||||
"fieldname": "allow_dropbox_access",
|
||||
"fieldtype": "Button",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Allow Dropbox Access",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"description": "Note: Backups and files are not deleted from Google Drive, you will have to delete them manually.",
|
||||
"fieldname": "sync_with_gdrive",
|
||||
"fieldname": "filters",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Sync with Google Drive",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "upload_backups_to_gdrive",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Upload Backups to Google Drive",
|
||||
"label": "Filters",
|
||||
"no_copy": 0,
|
||||
"options": "Never\nDaily\nWeekly",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
@@ -297,15 +150,18 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "allow_gdrive_access",
|
||||
"fieldtype": "Button",
|
||||
"depends_on": "eval:doc.tax_type==\"Sales\"",
|
||||
"fieldname": "customer",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Allow Google Drive Access",
|
||||
"label": "Customer",
|
||||
"no_copy": 0,
|
||||
"options": "Customer",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
@@ -318,15 +174,40 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "verification_code",
|
||||
"depends_on": "eval:doc.tax_type==\"Purchase\"",
|
||||
"fieldname": "supplier",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Supplier",
|
||||
"no_copy": 0,
|
||||
"options": "Supplier",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "billing_city",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Enter Verification Code",
|
||||
"label": "Billing City",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
@@ -339,15 +220,16 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "validate_gdrive",
|
||||
"fieldtype": "Button",
|
||||
"fieldname": "billing_state",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Validate",
|
||||
"label": "Billing State",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
@@ -360,17 +242,19 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "gdrive_access_allowed",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"fieldname": "billing_country",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Google Drive Access Allowed",
|
||||
"label": "Billing Country",
|
||||
"no_copy": 0,
|
||||
"options": "Country",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@@ -381,17 +265,17 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "gdrive_credentials",
|
||||
"fieldtype": "Text",
|
||||
"hidden": 1,
|
||||
"fieldname": "column_break_2",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Credentials",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@@ -402,17 +286,66 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "database_folder_id",
|
||||
"depends_on": "eval:doc.tax_type==\"Sales\"",
|
||||
"fieldname": "customer_group",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Customer Group",
|
||||
"no_copy": 0,
|
||||
"options": "Customer Group",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "eval:doc.tax_type==\"Purchase\"",
|
||||
"fieldname": "supplier_type",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Supplier Type",
|
||||
"no_copy": 0,
|
||||
"options": "Supplier Type",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "shipping_city",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Database Folder ID",
|
||||
"label": "Shipping City",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@@ -423,17 +356,216 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "files_folder_id",
|
||||
"fieldname": "shipping_state",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Files Folder ID",
|
||||
"label": "Shipping State",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "shipping_country",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Shipping Country",
|
||||
"no_copy": 0,
|
||||
"options": "Country",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "section_break_4",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Validity",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "from_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "From Date",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "column_break_7",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "to_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "To Date",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "section_break_6",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"default": "1",
|
||||
"fieldname": "priority",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Priority",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "column_break_20",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Company",
|
||||
"no_copy": 0,
|
||||
"options": "Company",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@@ -443,17 +575,16 @@
|
||||
],
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"icon": "icon-cloud-upload",
|
||||
"idx": 1,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 1,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-05-26 04:54:10.193573",
|
||||
"modified": "2015-10-02 07:39:16.298546",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Setup",
|
||||
"name": "Backup Manager",
|
||||
"module": "Accounts",
|
||||
"name": "Tax Rule",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
@@ -461,16 +592,16 @@
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 0,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 0,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 0,
|
||||
"role": "System Manager",
|
||||
"report": 1,
|
||||
"role": "Accounts Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
@@ -478,5 +609,7 @@
|
||||
}
|
||||
],
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0
|
||||
"read_only_onload": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
||||
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
|
||||
@@ -10,9 +10,9 @@ from frappe.defaults import get_user_permissions
|
||||
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 InvalidCurrency(frappe.ValidationError): pass
|
||||
class InvalidAccountCurrency(frappe.ValidationError): pass
|
||||
class DuplicatePartyAccountError(frappe.ValidationError): pass
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_party_details(party=None, account=None, party_type="Customer", company=None,
|
||||
@@ -20,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))
|
||||
|
||||
@@ -29,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()]
|
||||
@@ -43,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
|
||||
@@ -51,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
|
||||
@@ -99,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", []))
|
||||
@@ -111,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
|
||||
@@ -134,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"
|
||||
|
||||
@@ -144,69 +153,22 @@ def set_account_and_due_date(party, account, party_type, company, posting_date,
|
||||
"due_date": get_due_date(posting_date, party_type, party, company)
|
||||
}
|
||||
return out
|
||||
|
||||
def validate_accounting_currency(party):
|
||||
company_currency = get_company_currency()
|
||||
|
||||
# set party account currency
|
||||
if not party.party_account_currency:
|
||||
if party.default_currency:
|
||||
party.party_account_currency = party.default_currency
|
||||
elif len(set(company_currency.values())) == 1:
|
||||
party.party_account_currency = company_currency.values()[0]
|
||||
|
||||
party_account_currency_in_db = frappe.db.get_value(party.doctype, party.name, "party_account_currency")
|
||||
if party_account_currency_in_db != party.party_account_currency:
|
||||
existing_gle = frappe.db.get_value("GL Entry", {"party_type": party.doctype,
|
||||
"party": party.name}, ["name", "account_currency"], as_dict=1)
|
||||
if existing_gle:
|
||||
if party_account_currency_in_db:
|
||||
frappe.throw(_("Accounting Currency cannot be changed, as GL Entry exists for this {0}")
|
||||
.format(party.doctype), InvalidCurrency)
|
||||
else:
|
||||
party.party_account_currency = existing_gle.account_currency
|
||||
|
||||
|
||||
def validate_party_account(party):
|
||||
company_currency = get_company_currency()
|
||||
if party.party_account_currency:
|
||||
companies_with_different_currency = []
|
||||
for company, currency in company_currency.items():
|
||||
if currency != party.party_account_currency:
|
||||
companies_with_different_currency.append(company)
|
||||
|
||||
for d in party.get("accounts"):
|
||||
if d.company in companies_with_different_currency:
|
||||
companies_with_different_currency.remove(d.company)
|
||||
|
||||
selected_account_currency = frappe.db.get_value("Account", d.account, "account_currency")
|
||||
if selected_account_currency != party.party_account_currency:
|
||||
frappe.throw(_("Account {0} is invalid, account currency must be {1}")
|
||||
.format(d.account, selected_account_currency), InvalidAccountCurrency)
|
||||
|
||||
if companies_with_different_currency:
|
||||
frappe.msgprint(_("Please mention Default {0} Account for the following companies, as accounting currency is different from company's default currency: {1}")
|
||||
.format(
|
||||
"Receivable" if party.doctype=="Customer" else "Payable",
|
||||
"\n" + "\n".join(companies_with_different_currency)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
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",
|
||||
@@ -224,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"""
|
||||
@@ -240,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):
|
||||
@@ -248,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)
|
||||
|
||||
@@ -38,7 +38,14 @@ class ReceivablePayableReport(object):
|
||||
"width": 120
|
||||
})
|
||||
|
||||
columns += [_("Age (Days)") + "::80"]
|
||||
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),
|
||||
@@ -75,9 +82,9 @@ class ReceivablePayableReport(object):
|
||||
voucher_details = self.get_voucher_details(args.get("party_type"))
|
||||
|
||||
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):
|
||||
@@ -117,7 +124,7 @@ class ReceivablePayableReport(object):
|
||||
row += [self.get_territory(gle.party)]
|
||||
if args.get("party_type") == "Supplier":
|
||||
row += [self.get_supplier_type(gle.party)]
|
||||
|
||||
|
||||
if self.filters.get(scrub(args.get("party_type"))):
|
||||
row.append(gle.account_currency)
|
||||
else:
|
||||
@@ -209,7 +216,8 @@ class ReceivablePayableReport(object):
|
||||
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 {1} order by posting_date, party"""
|
||||
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
|
||||
|
||||
@@ -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,10 +13,10 @@ def execute(filters=None):
|
||||
account_details.setdefault(acc.name, acc)
|
||||
|
||||
validate_filters(filters, account_details)
|
||||
|
||||
|
||||
validate_party(filters)
|
||||
|
||||
filters = set_account_currency(filters)
|
||||
|
||||
filters = set_account_currency(filters)
|
||||
|
||||
columns = get_columns(filters)
|
||||
|
||||
@@ -46,49 +47,49 @@ def validate_party(filters):
|
||||
frappe.throw(_("To filter based on Party, select Party Type first"))
|
||||
elif not frappe.db.exists(party_type, party):
|
||||
frappe.throw(_("Invalid {0}: {1}").format(party_type, party))
|
||||
|
||||
|
||||
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 = frappe.db.get_value("Account", filters.account, "account_currency")
|
||||
account_currency = get_account_currency(filters.account)
|
||||
elif filters.get("party"):
|
||||
gle_currency = frappe.db.get_value("GL Entry", {"party_type": filters.party_type,
|
||||
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",
|
||||
_("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"
|
||||
]
|
||||
|
||||
|
||||
return columns
|
||||
|
||||
def get_result(filters, account_details):
|
||||
@@ -101,21 +102,21 @@ def get_result(filters, account_details):
|
||||
return result
|
||||
|
||||
def get_gl_entries(filters):
|
||||
select_fields = """, sum(ifnull(debit_in_account_currency, 0)) as debit_in_account_currency,
|
||||
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,
|
||||
sum(ifnull(debit, 0)) as debit, sum(ifnull(credit, 0)) as credit,
|
||||
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(select_fields=select_fields, conditions=get_conditions(filters),
|
||||
.format(select_fields=select_fields, conditions=get_conditions(filters),
|
||||
group_by_condition=group_by_condition), filters, as_dict=1)
|
||||
|
||||
return gl_entries
|
||||
@@ -135,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")
|
||||
|
||||
@@ -156,33 +157,38 @@ def get_data_with_opening_closing(filters, account_details, gl_entries):
|
||||
if filters.get("account") or filters.get("party"):
|
||||
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
|
||||
if filters.get("group_by_account"):
|
||||
# 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
|
||||
|
||||
|
||||
data += [{"account": "'" + _("Totals") + "'", "debit": acc_dict.total_debit,
|
||||
"credit": acc_dict.total_credit},
|
||||
get_balance_row(_("Closing (Opening + Totals)"),
|
||||
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,
|
||||
"account": "'" + _("Totals") + "'",
|
||||
"debit": total_debit,
|
||||
"credit": total_credit,
|
||||
"debit_in_account_currency": total_debit_in_account_currency,
|
||||
"debit_in_account_currency": total_debit_in_account_currency,
|
||||
"credit_in_account_currency": total_credit_in_account_currency
|
||||
})
|
||||
|
||||
@@ -191,7 +197,7 @@ def get_data_with_opening_closing(filters, account_details, gl_entries):
|
||||
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)"),
|
||||
closing, closing_in_account_currency))
|
||||
|
||||
@@ -216,38 +222,38 @@ def initialize_gle_map(gl_entries):
|
||||
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)
|
||||
gle_map[gle.account].total_credit += flt(gle.credit, 3)
|
||||
|
||||
|
||||
total_debit += flt(gle.debit, 3)
|
||||
total_credit += flt(gle.credit, 3)
|
||||
|
||||
|
||||
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)
|
||||
|
||||
|
||||
total_debit_in_account_currency += flt(gle.debit_in_account_currency, 3)
|
||||
total_credit_in_account_currency += flt(gle.credit_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
|
||||
@@ -258,27 +264,27 @@ def get_balance_row(label, balance, balance_in_account_currency=None):
|
||||
"debit": balance if balance > 0 else 0,
|
||||
"credit": -1*balance if balance < 0 else 0
|
||||
}
|
||||
|
||||
|
||||
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:
|
||||
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"),
|
||||
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -81,7 +84,9 @@ def get_balance_on(account=None, date=None, party_type=None, party=None, in_acco
|
||||
|
||||
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,8 +99,8 @@ def get_balance_on(account=None, date=None, party_type=None, party=None, in_acco
|
||||
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,
|
||||
|
||||
# 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
|
||||
@@ -195,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
|
||||
@@ -204,21 +211,32 @@ def update_against_doc(d, jv_obj):
|
||||
|
||||
if d['allocated_amt'] < d['unadjusted_amt']:
|
||||
jvd = frappe.db.sql("""
|
||||
select cost_center, balance, against_account, is_advance, account_type, exchange_rate
|
||||
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]["cost_center"])
|
||||
ch.balance = flt(jvd[0]["balance"])
|
||||
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.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
|
||||
@@ -296,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
|
||||
@@ -397,7 +415,7 @@ def get_stock_rbnb_difference(posting_date, company):
|
||||
# Amount should be credited
|
||||
return flt(stock_rbnb) + flt(sys_bal)
|
||||
|
||||
def get_outstanding_invoices(amount_query, account, party_type, party, with_journal_entry=True):
|
||||
def get_outstanding_invoices(amount_query, account, party_type, party):
|
||||
all_outstanding_vouchers = []
|
||||
outstanding_voucher_list = frappe.db.sql("""
|
||||
select
|
||||
@@ -407,6 +425,11 @@ def get_outstanding_invoices(amount_query, account, party_type, party, with_jour
|
||||
`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)
|
||||
|
||||
@@ -425,9 +448,6 @@ def get_outstanding_invoices(amount_query, account, party_type, party, with_jour
|
||||
payment_amount = -1*payment_amount[0][0] if payment_amount else 0
|
||||
precision = frappe.get_precision("Sales Invoice", "outstanding_amount")
|
||||
|
||||
if not with_journal_entry and d.voucher_type=="Journal Entry":
|
||||
continue
|
||||
|
||||
if d.invoice_amount > payment_amount:
|
||||
|
||||
all_outstanding_vouchers.append({
|
||||
|
||||
@@ -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-09-11 12:19:55.502661",
|
||||
"modified": "2015-10-16 06:13:50.058318",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Purchase Order",
|
||||
|
||||
@@ -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,12 +154,10 @@ 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_update()
|
||||
clear_doctype_notifications(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",
|
||||
|
||||
@@ -226,7 +226,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2015-03-03 03:40:45.982762",
|
||||
"modified": "2015-10-02 07:39:05.021801",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Purchase Order Item Supplied",
|
||||
|
||||
@@ -360,7 +360,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2015-08-19 12:45:54.810580",
|
||||
"modified": "2015-10-02 07:39:06.224300",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Purchase Receipt Item Supplied",
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Series",
|
||||
"label": "Series",
|
||||
"no_copy": 1,
|
||||
"options": "QI-",
|
||||
"permlevel": 0,
|
||||
@@ -85,7 +85,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Inspection Type",
|
||||
"label": "Inspection Type",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "inspection_type",
|
||||
"oldfieldtype": "Select",
|
||||
@@ -547,7 +547,7 @@
|
||||
"is_submittable": 1,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-06-08 02:40:25.121948",
|
||||
"modified": "2015-10-02 07:39:06.674821",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Quality Inspection",
|
||||
|
||||
@@ -295,7 +295,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Status",
|
||||
"label": "Status",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "status",
|
||||
"oldfieldtype": "Select",
|
||||
@@ -318,7 +318,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2015-02-19 01:07:01.658125",
|
||||
"modified": "2015-10-02 07:39:06.876419",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Quality Inspection Reading",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@ from frappe import msgprint, _
|
||||
from frappe.model.naming import make_autoname
|
||||
from erpnext.utilities.address_and_contact import load_address_and_contact
|
||||
from erpnext.utilities.transaction_base import TransactionBase
|
||||
from erpnext.accounts.party import validate_accounting_currency, validate_party_account
|
||||
from erpnext.accounts.party import validate_party_accounts
|
||||
|
||||
class Supplier(TransactionBase):
|
||||
def get_feed(self):
|
||||
@@ -45,9 +45,8 @@ class Supplier(TransactionBase):
|
||||
if frappe.defaults.get_global_default('supp_master_name') == 'Naming Series':
|
||||
if not self.naming_series:
|
||||
msgprint(_("Series is mandatory"), raise_exception=1)
|
||||
|
||||
validate_accounting_currency(self)
|
||||
validate_party_account(self)
|
||||
|
||||
validate_party_accounts(self)
|
||||
|
||||
def get_contacts(self,nm):
|
||||
if nm:
|
||||
@@ -96,14 +95,14 @@ def get_dashboard_info(supplier):
|
||||
billing_this_year = frappe.db.sql("""
|
||||
select sum(ifnull(credit_in_account_currency, 0)) - sum(ifnull(debit_in_account_currency, 0))
|
||||
from `tabGL Entry`
|
||||
where voucher_type='Purchase Invoice' and party_type = 'Supplier'
|
||||
and party=%s and fiscal_year = %s""",
|
||||
where voucher_type='Purchase Invoice' and party_type = 'Supplier'
|
||||
and party=%s and fiscal_year = %s""",
|
||||
(supplier, frappe.db.get_default("fiscal_year")))
|
||||
|
||||
|
||||
total_unpaid = frappe.db.sql("""select sum(outstanding_amount)
|
||||
from `tabPurchase Invoice`
|
||||
where supplier=%s and docstatus = 1""", supplier)
|
||||
|
||||
|
||||
|
||||
out["billing_this_year"] = billing_this_year[0][0] if billing_this_year else 0
|
||||
out["total_unpaid"] = total_unpaid[0][0] if total_unpaid else 0
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
[
|
||||
{
|
||||
"doctype": "Supplier",
|
||||
"supplier_name": "_Test Supplier",
|
||||
"doctype": "Supplier",
|
||||
"supplier_name": "_Test Supplier",
|
||||
"supplier_type": "_Test Supplier Type"
|
||||
},
|
||||
{
|
||||
"doctype": "Supplier",
|
||||
"supplier_name": "_Test Supplier 1",
|
||||
"doctype": "Supplier",
|
||||
"supplier_name": "_Test Supplier 1",
|
||||
"supplier_type": "_Test Supplier Type"
|
||||
},
|
||||
{
|
||||
"doctype": "Supplier",
|
||||
"supplier_name": "_Test Supplier USD",
|
||||
"doctype": "Supplier",
|
||||
"supplier_name": "_Test Supplier USD",
|
||||
"supplier_type": "_Test Supplier Type",
|
||||
"party_account_currency": "USD",
|
||||
"accounts": [{
|
||||
"company": "_Test Company",
|
||||
"account": "_Test Payable USD - _TC"
|
||||
}]
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Series",
|
||||
"label": "Series",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "naming_series",
|
||||
"oldfieldtype": "Select",
|
||||
@@ -509,7 +509,7 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "items",
|
||||
@@ -981,7 +981,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,
|
||||
@@ -1463,7 +1463,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 1,
|
||||
"in_list_view": 0,
|
||||
"label": "Status",
|
||||
"label": "Status",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "status",
|
||||
"oldfieldtype": "Select",
|
||||
@@ -1488,7 +1488,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Is Subcontracted",
|
||||
"label": "Is Subcontracted",
|
||||
"no_copy": 0,
|
||||
"options": "\nYes\nNo",
|
||||
"permlevel": 0,
|
||||
@@ -1554,7 +1554,7 @@
|
||||
"is_submittable": 1,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-09-11 12:20:10.684388",
|
||||
"modified": "2015-10-02 07:39:15.027459",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Supplier Quotation",
|
||||
|
||||
@@ -925,7 +925,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2015-08-26 11:51:55.140967",
|
||||
"modified": "2015-10-19 03:04:51.597343",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Supplier Quotation Item",
|
||||
|
||||
8
erpnext/change_log/v6/v6_3_0.md
Normal file
8
erpnext/change_log/v6/v6_3_0.md
Normal file
@@ -0,0 +1,8 @@
|
||||
- **Tax Rule:** Define rules to automatically select a Tax Template based on Customer, Supplier, Billing Address or Shipping Address
|
||||
- Changes to **Shopping Cart:**
|
||||
- The prices will be based on only a single Price List defined in Shopping Cart Settings. Essentially, it means that your Shopping Cart will be available only in a single currency.
|
||||
- Shipping Rule will be defined per Country, instead of Territory.
|
||||
- Taxes will be applied based on the new Tax Rule system, instead of Territory.
|
||||
- **Important Note:** Your Shopping Cart Settings have been disabled. The new changes require you to review your Price List, Tax Rules and Shipping Rule, update the settings, and then enable Shopping Cart again.
|
||||
- Enhancements in Customer Portal user interface
|
||||
- Sales Team is now editable after submission of Sales Order, Sales Invoice and Delivery Note
|
||||
4
erpnext/change_log/v6/v6_4_0.md
Normal file
4
erpnext/change_log/v6/v6_4_0.md
Normal file
@@ -0,0 +1,4 @@
|
||||
- Trial Balance for Customer and Supplier
|
||||
- Chart of Accounts for Guatemala
|
||||
- Address and Contact permissions based on Customer and Supplier
|
||||
- Multi-currency Accounting: Allow Accounts in different currencies for a Customer or Supplier, if they belong to a different Company
|
||||
7
erpnext/change_log/v6/v6_5_0.md
Normal file
7
erpnext/change_log/v6/v6_5_0.md
Normal file
@@ -0,0 +1,7 @@
|
||||
- Income type Account can now be added to Cost Center Budget
|
||||
- Target Warehouse added to Delivery Note. Sponsored by [Startrack GPS (Guatemala)](http://gps.gt/)
|
||||
- Serial No validations will now be based on Warehouse and not Status
|
||||
- New Design for Email Digests. Now Email Digest will show Accounting Status and notifications. And, something special at the end!
|
||||
- Thumbnail generation for Website views of product listing
|
||||
- Ability to select Variant in shopping cart
|
||||
- Now you can invite a Contact to become a portal user
|
||||
@@ -106,6 +106,11 @@ def get_data():
|
||||
"name": "Accounts Settings",
|
||||
"description": _("Default settings for accounting transactions.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Tax Rule",
|
||||
"description": _("Tax Rule for transactions.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Sales Taxes and Charges Template",
|
||||
@@ -182,6 +187,12 @@ def get_data():
|
||||
"doctype": "GL Entry",
|
||||
"is_query_report": True,
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Trial Balance for Party",
|
||||
"doctype": "GL Entry",
|
||||
"is_query_report": True,
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Gross Profit",
|
||||
|
||||
@@ -6,16 +6,15 @@ import frappe
|
||||
from frappe import _, throw
|
||||
from frappe.utils import today, flt, cint
|
||||
from erpnext.setup.utils import get_company_currency, get_exchange_rate
|
||||
from erpnext.accounts.utils import get_fiscal_year, validate_fiscal_year
|
||||
from erpnext.accounts.utils import get_fiscal_year, validate_fiscal_year, get_account_currency
|
||||
from erpnext.utilities.transaction_base import TransactionBase
|
||||
from erpnext.controllers.recurring_document import convert_to_recurring, validate_recurring_document
|
||||
from erpnext.controllers.sales_and_purchase_return import validate_return
|
||||
from erpnext.accounts.party import get_party_account_currency, validate_party_gle_currency
|
||||
from erpnext.exceptions import CustomerFrozen, InvalidCurrency
|
||||
|
||||
force_item_fields = ("item_group", "barcode", "brand", "stock_uom")
|
||||
|
||||
class CustomerFrozen(frappe.ValidationError): pass
|
||||
class InvalidCurrency(frappe.ValidationError): pass
|
||||
|
||||
class AccountsController(TransactionBase):
|
||||
def __init__(self, arg1, arg2=None):
|
||||
super(AccountsController, self).__init__(arg1, arg2)
|
||||
@@ -167,6 +166,9 @@ class AccountsController(TransactionBase):
|
||||
if ret.get("pricing_rule_for") == "Price":
|
||||
item.set("pricing_list_rate", ret.get("pricing_list_rate"))
|
||||
|
||||
if item.price_list_rate:
|
||||
item.rate = flt(item.price_list_rate *
|
||||
(1.0 - (flt(item.discount_percentage) / 100.0)), item.precision("rate"))
|
||||
|
||||
def set_taxes(self):
|
||||
if not self.meta.get_field("taxes"):
|
||||
@@ -217,16 +219,15 @@ class AccountsController(TransactionBase):
|
||||
gl_dict.update(args)
|
||||
|
||||
if not account_currency:
|
||||
account_currency = frappe.db.get_value("Account", gl_dict.account, "account_currency")
|
||||
account_currency = get_account_currency(gl_dict.account)
|
||||
|
||||
self.validate_account_currency(gl_dict.account, account_currency)
|
||||
gl_dict = self.set_balance_in_account_currency(gl_dict, account_currency)
|
||||
if self.doctype != "Journal Entry":
|
||||
self.validate_account_currency(gl_dict.account, account_currency)
|
||||
self.set_balance_in_account_currency(gl_dict, account_currency)
|
||||
|
||||
return gl_dict
|
||||
|
||||
def validate_account_currency(self, account, account_currency=None):
|
||||
if self.doctype == "Journal Entry":
|
||||
return
|
||||
valid_currency = [self.company_currency]
|
||||
if self.get("currency") and self.currency != self.company_currency:
|
||||
valid_currency.append(self.currency)
|
||||
@@ -236,8 +237,7 @@ class AccountsController(TransactionBase):
|
||||
.format(account, _(" or ").join(valid_currency)))
|
||||
|
||||
def set_balance_in_account_currency(self, gl_dict, account_currency=None):
|
||||
if (not self.get("conversion_rate") and self.doctype!="Journal Entry"
|
||||
and account_currency!=self.company_currency):
|
||||
if (not self.get("conversion_rate") and account_currency!=self.company_currency):
|
||||
frappe.throw(_("Account: {0} with currency: {1} can not be selected")
|
||||
.format(gl_dict.account, account_currency))
|
||||
|
||||
@@ -253,8 +253,6 @@ class AccountsController(TransactionBase):
|
||||
gl_dict.credit_in_account_currency = gl_dict.credit if account_currency==self.company_currency \
|
||||
else flt(gl_dict.credit / (self.get("conversion_rate")), 2)
|
||||
|
||||
return gl_dict
|
||||
|
||||
def clear_unallocated_advances(self, childtype, parentfield):
|
||||
self.set(parentfield, self.get(parentfield, {"allocated_amount": ["not in", [0, None, ""]]}))
|
||||
|
||||
@@ -428,10 +426,12 @@ class AccountsController(TransactionBase):
|
||||
if self.get("currency"):
|
||||
party_type, party = self.get_party()
|
||||
if party_type and party:
|
||||
party_account_currency = frappe.db.get_value(party_type, party, "party_account_currency") \
|
||||
or self.company_currency
|
||||
party_account_currency = get_party_account_currency(party_type, party, self.company)
|
||||
|
||||
if (party_account_currency
|
||||
and party_account_currency != self.company_currency
|
||||
and self.currency != party_account_currency):
|
||||
|
||||
if party_account_currency != self.company_currency and self.currency != party_account_currency:
|
||||
frappe.throw(_("Accounting Entry for {0}: {1} can only be made in currency: {2}")
|
||||
.format(party_type, party, party_account_currency), InvalidCurrency)
|
||||
|
||||
|
||||
@@ -293,3 +293,27 @@ def get_account_list(doctype, txt, searchfield, start, page_len, filters):
|
||||
fields = ["name", "parent_account"],
|
||||
limit_start=start, limit_page_length=page_len, as_list=True)
|
||||
|
||||
|
||||
@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"
|
||||
if not filters: filters = {}
|
||||
|
||||
condition = ""
|
||||
if filters.get("company"):
|
||||
condition += "and tabAccount.company = %(company)s"
|
||||
|
||||
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.`{key}` LIKE %(txt)s
|
||||
{condition} {match_condition}"""
|
||||
.format(condition=condition, match_condition=get_match_cond(doctype), key=searchfield), {
|
||||
'txt': "%%%s%%" % frappe.db.escape(txt),
|
||||
'company': filters.get("company", "")
|
||||
})
|
||||
@@ -173,7 +173,8 @@ class SellingController(StockController):
|
||||
'uom': p.uom,
|
||||
'batch_no': cstr(p.batch_no).strip(),
|
||||
'serial_no': cstr(p.serial_no).strip(),
|
||||
'name': d.name
|
||||
'name': d.name,
|
||||
'target_warehouse': p.target_warehouse
|
||||
}))
|
||||
else:
|
||||
il.append(frappe._dict({
|
||||
@@ -184,7 +185,8 @@ class SellingController(StockController):
|
||||
'stock_uom': d.stock_uom,
|
||||
'batch_no': cstr(d.get("batch_no")).strip(),
|
||||
'serial_no': cstr(d.get("serial_no")).strip(),
|
||||
'name': d.name
|
||||
'name': d.name,
|
||||
'target_warehouse': d.target_warehouse
|
||||
}))
|
||||
return il
|
||||
|
||||
|
||||
@@ -30,7 +30,20 @@ status_map = {
|
||||
],
|
||||
"Sales Order": [
|
||||
["Draft", None],
|
||||
["Submitted", "eval:self.docstatus==1"],
|
||||
["To Deliver and Bill", "eval:self.per_delivered < 100 and self.per_billed < 100 and self.docstatus == 1"],
|
||||
["To Bill", "eval:self.per_delivered == 100 and self.per_billed < 100 and self.docstatus == 1"],
|
||||
["To Deliver", "eval:self.per_delivered < 100 and self.per_billed == 100 and self.docstatus == 1"],
|
||||
["Completed", "eval:self.per_delivered == 100 and self.per_billed == 100 and self.docstatus == 1"],
|
||||
["Completed", "eval:self.order_type == 'Maintenance' and self.per_billed == 100 and self.docstatus == 1"],
|
||||
["Stopped", "eval:self.status=='Stopped'"],
|
||||
["Cancelled", "eval:self.docstatus==2"],
|
||||
],
|
||||
"Purchase Order": [
|
||||
["Draft", None],
|
||||
["To Receive and Bill", "eval:self.per_received < 100 and self.per_billed < 100 and self.docstatus == 1"],
|
||||
["To Bill", "eval:self.per_received == 100 and self.per_billed < 100 and self.docstatus == 1"],
|
||||
["To Receive", "eval:self.per_received < 100 and self.per_billed == 100 and self.docstatus == 1"],
|
||||
["Completed", "eval:self.per_received == 100 and self.per_billed == 100 and self.docstatus == 1"],
|
||||
["Stopped", "eval:self.status=='Stopped'"],
|
||||
["Cancelled", "eval:self.docstatus==2"],
|
||||
],
|
||||
@@ -207,10 +220,10 @@ class StatusUpdater(Document):
|
||||
# update percent complete in the parent table
|
||||
if args.get('target_parent_field'):
|
||||
frappe.db.sql("""update `tab%(target_parent_dt)s`
|
||||
set %(target_parent_field)s = (select sum(if(%(target_ref_field)s >
|
||||
set %(target_parent_field)s = round((select sum(if(%(target_ref_field)s >
|
||||
ifnull(%(target_field)s, 0), %(target_field)s,
|
||||
%(target_ref_field)s))/sum(%(target_ref_field)s)*100
|
||||
from `tab%(target_dt)s` where parent="%(name)s") %(set_modified)s
|
||||
from `tab%(target_dt)s` where parent="%(name)s"), 2) %(set_modified)s
|
||||
where name='%(name)s'""" % args)
|
||||
|
||||
# update field
|
||||
@@ -222,7 +235,9 @@ class StatusUpdater(Document):
|
||||
where name='%(name)s'""" % args)
|
||||
|
||||
if args.get("set_modified"):
|
||||
frappe.get_doc(args["target_parent_dt"], name).notify_update()
|
||||
target = frappe.get_doc(args["target_parent_dt"], name)
|
||||
target.set_status(update=True)
|
||||
target.notify_update()
|
||||
|
||||
def update_billing_status_for_zero_amount_refdoc(self, ref_dt):
|
||||
ref_fieldname = ref_dt.lower().replace(" ", "_")
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user