Refactor party type (#13831)
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index 3eaf994..e388601 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -79,6 +79,16 @@
return frappe.local.enable_perpetual_inventory[company]
+def get_party_account_type(party_type):
+ if not hasattr(frappe.local, 'party_account_types'):
+ frappe.local.party_account_types = {}
+
+ if not party_type in frappe.local.party_account_types:
+ frappe.local.party_account_types[party_type] = frappe.db.get_value("Party Type",
+ party_type, "account_type") or ''
+
+ return frappe.local.party_account_types[party_type]
+
def get_region(company=None):
'''Return the default country based on flag, company or global settings
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.js b/erpnext/accounts/doctype/journal_entry/journal_entry.js
index 9aa8de1..afa1ffe 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.js
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.js
@@ -158,9 +158,14 @@
};
});
- me.frm.set_query("party_type", "accounts", function() {
- return{
- query: "erpnext.setup.doctype.party_type.party_type.get_party_type"
+ me.frm.set_query("party_type", "accounts", function(doc, cdt, cdn) {
+ const row = locals[cdt][cdn];
+
+ return {
+ query: "erpnext.setup.doctype.party_type.party_type.get_party_type",
+ filters: {
+ 'account': row.account
+ }
}
});
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index f79efed..ca50e2d 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -12,10 +12,8 @@
setup: function(frm) {
frm.set_query("paid_from", function() {
- var party_account_type = in_list(["Customer", "Student"], frm.doc.party_type) ?
- "Receivable" : "Payable";
var account_types = in_list(["Pay", "Internal Transfer"], frm.doc.payment_type) ?
- ["Bank", "Cash"] : party_account_type;
+ ["Bank", "Cash"] : [frappe.boot.party_account_types[frm.doc.party_type]];
return {
filters: {
@@ -29,16 +27,14 @@
frm.set_query("party_type", function() {
return{
"filters": {
- "name": ["in",["Customer","Supplier", "Employee", "Student"]],
+ "name": ["in", Object.keys(frappe.boot.party_account_types)],
}
}
});
frm.set_query("paid_to", function() {
- var party_account_type = in_list(["Customer", "Student"], frm.doc.party_type) ?
- "Receivable" : "Payable";
var account_types = in_list(["Receive", "Internal Transfer"], frm.doc.payment_type) ?
- ["Bank", "Cash"] : party_account_type;
+ ["Bank", "Cash"] : [frappe.boot.party_account_types[frm.doc.party_type]];
return {
filters: {
@@ -86,9 +82,9 @@
});
frm.set_query("reference_name", "references", function(doc, cdt, cdn) {
- child = locals[cdt][cdn];
- filters = {"docstatus": 1, "company": doc.company};
- party_type_doctypes = ['Sales Invoice', 'Sales Order', 'Purchase Invoice',
+ const child = locals[cdt][cdn];
+ const filters = {"docstatus": 1, "company": doc.company};
+ const party_type_doctypes = ['Sales Invoice', 'Sales Order', 'Purchase Invoice',
'Purchase Order', 'Expense Claim', 'Fees'];
if (in_list(party_type_doctypes, child.reference_doctype)) {
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 9b50252..96b997f 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -160,9 +160,9 @@
if not frappe.db.exists(self.party_type, self.party):
frappe.throw(_("Invalid {0}: {1}").format(self.party_type, self.party))
- if self.party_account and self.party_type != "Employee":
- party_account_type = "Receivable" if self.party_type in ("Customer", "Student") else "Payable"
- self.validate_account_type(self.party_account, [party_account_type])
+ if self.party_account:
+ self.validate_account_type(self.party_account,
+ [erpnext.get_party_account_type(self.party_type)])
def validate_bank_accounts(self):
if self.payment_type in ("Pay", "Internal Transfer"):
@@ -413,7 +413,6 @@
else:
against_account = self.paid_from
-
party_gl_dict = self.get_gl_dict({
"account": self.party_account,
"party_type": self.party_type,
@@ -422,7 +421,7 @@
"account_currency": self.party_account_currency
})
- dr_or_cr = "credit" if self.party_type in ["Customer", "Student"] else "debit"
+ dr_or_cr = "credit" if erpnext.get_party_account_type(self.party_type) == 'Receivable' else "debit"
for d in self.get("references"):
gle = party_gl_dict.copy()
diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js
index 0901046..4c24a9f 100644
--- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js
+++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js
@@ -24,8 +24,10 @@
onload: function() {
var me = this;
this.frm.set_query("party_type", function() {
- return{
- query: "erpnext.setup.doctype.party_type.party_type.get_party_type"
+ return {
+ "filters": {
+ "name": ["in", Object.keys(frappe.boot.party_account_types)],
+ }
}
});
@@ -37,7 +39,7 @@
filters: {
"company": me.frm.doc.company,
"is_group": 0,
- "account_type": (me.frm.doc.party_type == "Customer" ? "Receivable" : "Payable")
+ "account_type": frappe.boot.party_account_types[me.frm.doc.party_type]
}
};
}
diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
index 3c87fe5..7cd951a 100644
--- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
+++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
@@ -2,7 +2,7 @@
# For license information, please see license.txt
from __future__ import unicode_literals
-import frappe
+import frappe, erpnext
from frappe.utils import flt
from frappe import msgprint, _
from frappe.model.document import Document
@@ -30,8 +30,8 @@
return payment_entries
def get_jv_entries(self):
- dr_or_cr = "credit_in_account_currency" if self.party_type == "Customer" \
- else "debit_in_account_currency"
+ dr_or_cr = ("credit_in_account_currency" if erpnext.get_party_account_type(self.party_type) == 'Receivable'
+ else "debit_in_account_currency")
bank_account_condition = "t2.against_account like %(bank_cash_account)s" \
if self.bank_cash_account else "1=1"
@@ -104,8 +104,8 @@
self.get_invoice_entries()
self.validate_invoice()
- dr_or_cr = "credit_in_account_currency" \
- if self.party_type == "Customer" else "debit_in_account_currency"
+ dr_or_cr = ("credit_in_account_currency"
+ if erpnext.get_party_account_type(self.party_type) == 'Receivable' else "debit_in_account_currency")
lst = []
for e in self.get('payments'):
@@ -173,11 +173,8 @@
def check_condition(self):
cond = " and posting_date >= '{0}'".format(frappe.db.escape(self.from_date)) if self.from_date else ""
cond += " and posting_date <= '{0}'".format(frappe.db.escape(self.to_date)) if self.to_date else ""
-
- if self.party_type == "Customer":
- dr_or_cr = "debit_in_account_currency"
- else:
- dr_or_cr = "credit_in_account_currency"
+ dr_or_cr = ("debit_in_account_currency" if erpnext.get_party_account_type(self.party_type) == 'Receivable'
+ else "credit_in_account_currency")
if self.minimum_amount:
cond += " and `{0}` >= {1}".format(dr_or_cr, flt(self.minimum_amount))
diff --git a/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.js b/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.js
index 7ccec30..29f798e 100644
--- a/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.js
+++ b/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.js
@@ -46,9 +46,10 @@
{
"fieldname":"party_type",
"label": __("Party Type"),
- "fieldtype": "Select",
- "options": ["Customer", "Supplier"],
- "default": "Customer"
+ "fieldtype": "Link",
+ "options": "Party Type",
+ "default": "Customer",
+ "reqd": 1
},
{
"fieldname":"party",
diff --git a/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.py b/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.py
index 6480623..8be63a0 100644
--- a/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.py
+++ b/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.py
@@ -7,26 +7,28 @@
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"
+ party_name_field = "{0}_name".format(frappe.scrub(filters.get('party_type')))
+ if filters.get('party_type') == 'Student':
+ party_name_field = 'first_name'
+
party_filters = {"name": filters.get("party")} if filters.get("party") else {}
parties = frappe.get_all(filters.get("party_type"), fields = ["name", party_name_field],
filters = party_filters, order_by="name")
company_currency = frappe.db.get_value("Company", filters.company, "default_currency")
opening_balances = get_opening_balances(filters)
balances_within_period = get_balances_within_period(filters)
-
+
data = []
# total_debit, total_credit = 0, 0
total_row = frappe._dict({
@@ -41,28 +43,28 @@
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
})
-
+
# closing
closing_debit, closing_credit = toggle_debit_credit(opening_debit + debit, opening_credit + credit)
row.update({
"closing_debit": closing_debit,
"closing_credit": closing_credit
})
-
+
# totals
for col in total_row:
total_row[col] += row.get(col)
@@ -70,24 +72,24 @@
row.update({
"currency": company_currency
})
-
+
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
-
+
total_row.update({
"party": "'" + _("Totals") + "'",
"currency": company_currency
})
data.append(total_row)
-
+
return data
-
+
def get_opening_balances(filters):
gle = frappe.db.sql("""
select party, sum(debit) as opening_debit, sum(credit) as opening_credit
@@ -100,14 +102,14 @@
"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(debit) as debit, sum(credit) as credit
@@ -122,13 +124,13 @@
"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)
@@ -136,9 +138,9 @@
else:
credit = flt(credit) - flt(debit)
debit = 0.0
-
+
return debit, credit
-
+
def get_columns(filters, show_party_name):
columns = [
{
@@ -198,7 +200,7 @@
"hidden": 1
}
]
-
+
if show_party_name:
columns.insert(1, {
"fieldname": "party_name",
@@ -206,17 +208,21 @@
"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")
+
+ if filters.get('party_type') in ['Customer', 'Supplier']:
+ 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
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
\ No newline at end of file
diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py
index b5d9cd8..9c7310f 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -3,7 +3,7 @@
from __future__ import unicode_literals
-import frappe
+import frappe, erpnext
import frappe.defaults
from frappe.utils import nowdate, cstr, flt, cint, now, getdate
from frappe import throw, _
@@ -322,7 +322,9 @@
and t1.name = %(voucher_no)s and t2.name = %(voucher_detail_no)s
and t1.docstatus=1 """.format(dr_or_cr = args.get("dr_or_cr")), args)
else:
- party_account_field = "paid_from" if args.party_type == "Customer" else "paid_to"
+ party_account_field = ("paid_from"
+ if erpnext.get_party_account_type(args.party_type) == 'Receivable' else "paid_to")
+
if args.voucher_detail_no:
ret = frappe.db.sql("""select t1.name
from `tabPayment Entry` t1, `tabPayment Entry Reference` t2
@@ -574,14 +576,14 @@
outstanding_invoices = []
precision = frappe.get_precision("Sales Invoice", "outstanding_amount")
- if party_type in ("Customer", "Student"):
+ if erpnext.get_party_account_type(party_type) == 'Receivable':
dr_or_cr = "debit_in_account_currency - credit_in_account_currency"
payment_dr_or_cr = "payment_gl_entry.credit_in_account_currency - payment_gl_entry.debit_in_account_currency"
else:
dr_or_cr = "credit_in_account_currency - debit_in_account_currency"
payment_dr_or_cr = "payment_gl_entry.debit_in_account_currency - payment_gl_entry.credit_in_account_currency"
- invoice = 'Sales Invoice' if party_type == 'Customer' else 'Purchase Invoice'
+ invoice = 'Sales Invoice' if erpnext.get_party_account_type(party_type) == 'Receivable' else 'Purchase Invoice'
invoice_list = frappe.db.sql("""
select
voucher_no, voucher_type, posting_date, ifnull(sum({dr_or_cr}), 0) as invoice_amount,
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index abee28f..a8c6cea 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -523,6 +523,7 @@
erpnext.patches.v11_0.add_default_email_template_for_leave
erpnext.patches.v11_0.set_default_email_template_in_hr
erpnext.patches.v10_0.taxes_issue_with_pos
+erpnext.patches.v11_0.update_account_type_in_party_type
erpnext.patches.v10_1.transfer_subscription_to_auto_repeat
erpnext.patches.v10_1.drop_old_subscription_records
erpnext.patches.v11_0.update_brand_in_item_price
diff --git a/erpnext/patches/v11_0/update_account_type_in_party_type.py b/erpnext/patches/v11_0/update_account_type_in_party_type.py
new file mode 100644
index 0000000..efa04fd
--- /dev/null
+++ b/erpnext/patches/v11_0/update_account_type_in_party_type.py
@@ -0,0 +1,13 @@
+# Copyright (c) 2017, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+ frappe.reload_doc('setup', 'doctype', 'party_type')
+ party_types = {'Customer': 'Receivable', 'Supplier': 'Payable',
+ 'Employee': 'Payable', 'Member': 'Receivable', 'Shareholder': 'Payable', 'Student': 'Receivable'}
+
+ for party_type, account_type in party_types.items():
+ frappe.db.set_value('Party Type', party_type, 'account_type', account_type)
\ No newline at end of file
diff --git a/erpnext/setup/doctype/party_type/party_type.json b/erpnext/setup/doctype/party_type/party_type.json
index e1814ae..00f06a0 100644
--- a/erpnext/setup/doctype/party_type/party_type.json
+++ b/erpnext/setup/doctype/party_type/party_type.json
@@ -42,6 +42,39 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "account_type",
+ "fieldtype": "Select",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 1,
+ "in_standard_filter": 0,
+ "label": "Account Type",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Payable\nReceivable",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
"unique": 0
}
],
@@ -55,7 +88,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2017-11-23 17:46:27.075001",
+ "modified": "2018-04-26 13:00:49.457439",
"modified_by": "Administrator",
"module": "Setup",
"name": "Party Type",
@@ -64,7 +97,6 @@
"permissions": [
{
"amend": 0,
- "apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
@@ -84,7 +116,6 @@
},
{
"amend": 0,
- "apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
@@ -104,7 +135,6 @@
},
{
"amend": 0,
- "apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
diff --git a/erpnext/setup/doctype/party_type/party_type.py b/erpnext/setup/doctype/party_type/party_type.py
index 74db037..8baddf4 100644
--- a/erpnext/setup/doctype/party_type/party_type.py
+++ b/erpnext/setup/doctype/party_type/party_type.py
@@ -11,10 +11,15 @@
@frappe.whitelist()
def get_party_type(doctype, txt, searchfield, start, page_len, filters):
+ cond = ''
+ if filters and filters.get('account'):
+ account_type = frappe.db.get_value('Account', filters.get('account'), 'account_type')
+ cond = "and account_type = '%s'" % account_type
+
return frappe.db.sql("""select name from `tabParty Type`
- where `{key}` LIKE %(txt)s
+ where `{key}` LIKE %(txt)s {cond}
order by name limit %(start)s, %(page_len)s"""
- .format(key=searchfield), {
+ .format(key=searchfield, cond=cond), {
'txt': "%%%s%%" % frappe.db.escape(txt),
'start': start, 'page_len': page_len
})
diff --git a/erpnext/setup/setup_wizard/operations/install_fixtures.py b/erpnext/setup/setup_wizard/operations/install_fixtures.py
index f2eaece..3309cbc 100644
--- a/erpnext/setup/setup_wizard/operations/install_fixtures.py
+++ b/erpnext/setup/setup_wizard/operations/install_fixtures.py
@@ -198,12 +198,12 @@
{'doctype': "Email Account", "email_id": "support@example.com", "append_to": "Issue"},
{'doctype': "Email Account", "email_id": "jobs@example.com", "append_to": "Job Applicant"},
- {'doctype': "Party Type", "party_type": "Customer"},
- {'doctype': "Party Type", "party_type": "Supplier"},
- {'doctype': "Party Type", "party_type": "Employee"},
- {'doctype': "Party Type", "party_type": "Member"},
- {'doctype': "Party Type", "party_type": "Shareholder"},
- {'doctype': "Party Type", "party_type": "Student"},
+ {'doctype': "Party Type", "party_type": "Customer", "account_type": "Receivable"},
+ {'doctype': "Party Type", "party_type": "Supplier", "account_type": "Payable"},
+ {'doctype': "Party Type", "party_type": "Employee", "account_type": "Payable"},
+ {'doctype': "Party Type", "party_type": "Member", "account_type": "Receivable"},
+ {'doctype': "Party Type", "party_type": "Shareholder", "account_type": "Payable"},
+ {'doctype': "Party Type", "party_type": "Student", "account_type": "Receivable"},
{'doctype': "Opportunity Type", "name": "Hub"},
{'doctype': "Opportunity Type", "name": _("Sales")},
diff --git a/erpnext/startup/boot.py b/erpnext/startup/boot.py
index 8c43306..62c9e7b 100644
--- a/erpnext/startup/boot.py
+++ b/erpnext/startup/boot.py
@@ -36,6 +36,9 @@
default_letter_head, default_bank_account, enable_perpetual_inventory from `tabCompany`""",
as_dict=1, update={"doctype":":Company"})
+ party_account_types = frappe.db.sql(""" select name, ifnull(account_type, '') from `tabParty Type`""")
+ bootinfo.party_account_types = frappe._dict(party_account_types)
+
def load_country_and_currency(bootinfo):
country = frappe.db.get_default("country")
if country and frappe.db.exists("Country", country):