From 48036b4bab25fcecf2728decc78ae2c598f54c0e Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Fri, 4 Jun 2021 09:54:34 +0530 Subject: [PATCH 01/12] fix: invoices can alter profit and loss of a closed year --- erpnext/accounts/doctype/gl_entry/gl_entry.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py index 948c51364e..11465b711e 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.py +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py @@ -121,8 +121,7 @@ class GLEntry(Document): def check_pl_account(self): if self.is_opening=='Yes' and \ - frappe.db.get_value("Account", self.account, "report_type")=="Profit and Loss" and \ - self.voucher_type not in ['Purchase Invoice', 'Sales Invoice']: + frappe.db.get_value("Account", self.account, "report_type")=="Profit and Loss": frappe.throw(_("{0} {1}: 'Profit and Loss' type account {2} not allowed in Opening Entry") .format(self.voucher_type, self.voucher_no, self.account)) From 0511ffcf30459a8646978429101c7edf6315f69b Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Mon, 14 Jun 2021 13:22:44 +0530 Subject: [PATCH 02/12] fix(General Ledger): Implement multi-account selection --- .../report/general_ledger/general_ledger.js | 15 +++++------- .../report/general_ledger/general_ledger.py | 24 ++++++++++++++----- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.js b/erpnext/accounts/report/general_ledger/general_ledger.js index 84f786814d..f3c3865b4e 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.js +++ b/erpnext/accounts/report/general_ledger/general_ledger.js @@ -36,16 +36,13 @@ frappe.query_reports["General Ledger"] = { { "fieldname":"account", "label": __("Account"), - "fieldtype": "Link", + "fieldtype": "MultiSelectList", "options": "Account", - "get_query": function() { - var company = frappe.query_report.get_filter_value('company'); - return { - "doctype": "Account", - "filters": { - "company": company, - } - } + get_data: function(txt) { + console.log("txt = ", txt) + return frappe.db.get_link_options('Account', txt, { + company: frappe.query_report.get_filter_value("company") + }); } }, { diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index 562df4f6f7..53c638bf4a 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -49,8 +49,12 @@ def validate_filters(filters, account_details): if not filters.get("from_date") and not filters.get("to_date"): frappe.throw(_("{0} and {1} are mandatory").format(frappe.bold(_("From Date")), frappe.bold(_("To Date")))) - if filters.get("account") and not account_details.get(filters.account): - frappe.throw(_("Account {0} does not exists").format(filters.account)) + for account in filters.account: + if not account_details.get(account): + frappe.throw(_("Account {0} does not exists").format(account)) + + if filters.get('account'): + filters.account = frappe.parse_json(filters.get('account')) if (filters.get("account") and filters.get("group_by") == _('Group by Account') and account_details[filters.account].is_group == 0): @@ -87,7 +91,7 @@ def set_account_currency(filters): account_currency = None if filters.get("account"): - account_currency = get_account_currency(filters.account) + account_currency = get_account_currency(filters.account[0]) elif filters.get("party"): gle_currency = frappe.db.get_value( "GL Entry", { @@ -205,10 +209,18 @@ def get_gl_entries(filters, accounting_dimensions): def get_conditions(filters): conditions = [] + if filters.get("account") and not filters.get("include_dimensions"): - lft, rgt = frappe.db.get_value("Account", filters["account"], ["lft", "rgt"]) - conditions.append("""account in (select name from tabAccount - where lft>=%s and rgt<=%s and docstatus<2)""" % (lft, rgt)) + account_conditions = "" + for account in filters["account"]: + lft, rgt = frappe.db.get_value("Account", account, ["lft", "rgt"]) + account_conditions += """account in (select name from tabAccount + where lft>=%s and rgt<=%s and docstatus<2)""" % (lft, rgt) + + # so that the OR doesn't get added to the last account condition + if account != filters["account"][-1]: + account_conditions += " OR " + conditions.append(account_conditions) if filters.get("cost_center"): filters.cost_center = get_cost_centers_with_children(filters.cost_center) From 27ec51f021931c6d9505e73e6852cb6c4bb97f86 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Mon, 14 Jun 2021 16:41:56 +0530 Subject: [PATCH 03/12] fix(General Ledger): Filter Cost Center drop-down list by Company --- erpnext/accounts/report/general_ledger/general_ledger.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.js b/erpnext/accounts/report/general_ledger/general_ledger.js index 84f786814d..80a25c907e 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.js +++ b/erpnext/accounts/report/general_ledger/general_ledger.js @@ -135,7 +135,9 @@ frappe.query_reports["General Ledger"] = { "label": __("Cost Center"), "fieldtype": "MultiSelectList", get_data: function(txt) { - return frappe.db.get_link_options('Cost Center', txt); + return frappe.db.get_link_options('Cost Center', txt, { + company: frappe.query_report.get_filter_value("company") + }); } }, { From 75b30efb050ed333d519ebad924b4cb188098521 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Mon, 14 Jun 2021 16:42:27 +0530 Subject: [PATCH 04/12] fix(General Ledger): Filter Project drop-down list by Company --- erpnext/accounts/report/general_ledger/general_ledger.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.js b/erpnext/accounts/report/general_ledger/general_ledger.js index 80a25c907e..a8e55307f9 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.js +++ b/erpnext/accounts/report/general_ledger/general_ledger.js @@ -145,7 +145,9 @@ frappe.query_reports["General Ledger"] = { "label": __("Project"), "fieldtype": "MultiSelectList", get_data: function(txt) { - return frappe.db.get_link_options('Project', txt); + return frappe.db.get_link_options('Project', txt, { + company: frappe.query_report.get_filter_value("company") + }); } }, { From 79dc0f0afce6df44e88b223f8db7fb947047c710 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Wed, 16 Jun 2021 03:37:11 +0530 Subject: [PATCH 05/12] fix: Remove console.log() --- erpnext/accounts/report/general_ledger/general_ledger.js | 1 - 1 file changed, 1 deletion(-) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.js b/erpnext/accounts/report/general_ledger/general_ledger.js index f3c3865b4e..28139d14b2 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.js +++ b/erpnext/accounts/report/general_ledger/general_ledger.js @@ -39,7 +39,6 @@ frappe.query_reports["General Ledger"] = { "fieldtype": "MultiSelectList", "options": "Account", get_data: function(txt) { - console.log("txt = ", txt) return frappe.db.get_link_options('Account', txt, { company: frappe.query_report.get_filter_value("company") }); From 53a9ac44662be877160c5acbbafc9fcaaa16bf21 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Wed, 16 Jun 2021 04:10:29 +0530 Subject: [PATCH 06/12] fix(General Ledger): Condense account_conditions --- erpnext/accounts/report/general_ledger/general_ledger.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index 53c638bf4a..aed9c4a049 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -211,15 +211,16 @@ def get_conditions(filters): conditions = [] if filters.get("account") and not filters.get("include_dimensions"): - account_conditions = "" + account_conditions = "account in (select name from tabAccount where" for account in filters["account"]: lft, rgt = frappe.db.get_value("Account", account, ["lft", "rgt"]) - account_conditions += """account in (select name from tabAccount - where lft>=%s and rgt<=%s and docstatus<2)""" % (lft, rgt) + account_conditions += """ (lft>=%s and rgt<=%s) """ % (lft, rgt) # so that the OR doesn't get added to the last account condition if account != filters["account"][-1]: - account_conditions += " OR " + account_conditions += "OR" + + account_conditions += "and docstatus<2)" conditions.append(account_conditions) if filters.get("cost_center"): From 1fd80992d705f55215a89a89a90e445224937e1b Mon Sep 17 00:00:00 2001 From: Saqib Date: Wed, 16 Jun 2021 13:27:34 +0530 Subject: [PATCH 07/12] fix(pos): 'NoneType' object is not iterable (#26066) --- erpnext/selling/page/point_of_sale/point_of_sale.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.py b/erpnext/selling/page/point_of_sale/point_of_sale.py index 7742f24385..296c8c2fd9 100644 --- a/erpnext/selling/page/point_of_sale/point_of_sale.py +++ b/erpnext/selling/page/point_of_sale/point_of_sale.py @@ -9,7 +9,7 @@ from erpnext.accounts.doctype.pos_profile.pos_profile import get_item_groups from erpnext.accounts.doctype.pos_invoice.pos_invoice import get_stock_availability def search_by_term(search_term, warehouse, price_list): - result = search_for_serial_or_batch_or_barcode_number(search_term) + result = search_for_serial_or_batch_or_barcode_number(search_term) or {} item_code = result.get("item_code") or search_term serial_no = result.get("serial_no") or "" @@ -23,9 +23,9 @@ def search_by_term(search_term, warehouse, price_list): item_stock_qty = get_stock_availability(item_code, warehouse) price_list_rate, currency = frappe.db.get_value('Item Price', { - 'price_list': price_list, - 'item_code': item_code - }, ["price_list_rate", "currency"]) + 'price_list': price_list, + 'item_code': item_code + }, ["price_list_rate", "currency"]) or [None, None] item_info.update({ 'serial_no': serial_no, @@ -46,7 +46,7 @@ def get_items(start, page_length, price_list, item_group, pos_profile, search_te result = [] if search_term: - result = search_by_term(search_term, warehouse, price_list) + result = search_by_term(search_term, warehouse, price_list) or [] if result: return result From 86f689e54aeafc33d2c90e5511fd04cf0458d613 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Wed, 16 Jun 2021 14:23:02 +0530 Subject: [PATCH 08/12] fix(General Ledger): Get account_currency accurately --- .../report/general_ledger/general_ledger.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index aed9c4a049..8be6aaf564 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -91,7 +91,19 @@ def set_account_currency(filters): account_currency = None if filters.get("account"): - account_currency = get_account_currency(filters.account[0]) + if len(filters.get("account")) == 1: + account_currency = get_account_currency(filters.account[0]) + else: + currency = get_account_currency(filters.account[0]) + is_same_account_currency = True + for account in filters.get("account"): + if get_account_currency(account) != currency: + is_same_account_currency = False + break + + if is_same_account_currency: + account_currency = currency + elif filters.get("party"): gle_currency = frappe.db.get_value( "GL Entry", { From 60ce00531d0028741044bf7ed92b3feded139126 Mon Sep 17 00:00:00 2001 From: Saqib Date: Wed, 16 Jun 2021 14:25:55 +0530 Subject: [PATCH 09/12] fix: label for enabling ledger posting of change amount (#26070) --- .../doctype/accounts_settings/accounts_settings.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json index 2735b1ccee..0ff7230e55 100644 --- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json +++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json @@ -257,9 +257,10 @@ }, { "default": "1", + "description": "If enabled, ledger entries will be posted for change amount in POS transactions", "fieldname": "post_change_gl_entries", "fieldtype": "Check", - "label": "Post Ledger Entries for Given Change" + "label": "Change Ledger Entries for Change Amount" } ], "icon": "icon-cog", @@ -267,7 +268,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2021-05-25 12:34:05.858669", + "modified": "2021-06-16 13:14:45.739107", "modified_by": "Administrator", "module": "Accounts", "name": "Accounts Settings", From 8c73f6f19e90e1be54d17a3e1f88e7ed535bef90 Mon Sep 17 00:00:00 2001 From: Afshan <33727827+AfshanKhan@users.noreply.github.com> Date: Wed, 16 Jun 2021 14:28:26 +0530 Subject: [PATCH 10/12] fix(pos): pos loyalty card alignment (#26051) --- erpnext/public/scss/point-of-sale.scss | 10 +++++++++- erpnext/selling/page/point_of_sale/pos_payment.js | 4 ++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/erpnext/public/scss/point-of-sale.scss b/erpnext/public/scss/point-of-sale.scss index 9bdaa8d1ee..c77b2ce3df 100644 --- a/erpnext/public/scss/point-of-sale.scss +++ b/erpnext/public/scss/point-of-sale.scss @@ -806,6 +806,9 @@ display: none; float: right; font-weight: 700; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } > .cash-shortcuts { @@ -829,6 +832,11 @@ } } } + + > .loyalty-card { + display: flex; + flex-direction: column; + } } } @@ -1134,4 +1142,4 @@ } } } -} \ No newline at end of file +} diff --git a/erpnext/selling/page/point_of_sale/pos_payment.js b/erpnext/selling/page/point_of_sale/pos_payment.js index 156fb777fe..c484873d3e 100644 --- a/erpnext/selling/page/point_of_sale/pos_payment.js +++ b/erpnext/selling/page/point_of_sale/pos_payment.js @@ -481,7 +481,7 @@ erpnext.PointOfSale.Payment = class { const amount = doc.loyalty_amount > 0 ? format_currency(doc.loyalty_amount, doc.currency) : ''; this.$payment_modes.append( `
-
+
Redeem Loyalty Points
${amount}
${loyalty_program}
@@ -563,4 +563,4 @@ erpnext.PointOfSale.Payment = class { toggle_component(show) { show ? this.$component.css('display', 'flex') : this.$component.css('display', 'none'); } -}; \ No newline at end of file +}; From 3b1b4684ba37b950657fe32d44001738c4438df9 Mon Sep 17 00:00:00 2001 From: Afshan <33727827+AfshanKhan@users.noreply.github.com> Date: Wed, 16 Jun 2021 14:30:45 +0530 Subject: [PATCH 11/12] fix: check for duplicate payment terms in Payment Term Template (#26003) --- .../doctype/payment_terms_template/payment_terms_template.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.py b/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.py index 80e3348d81..39627eb376 100644 --- a/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.py +++ b/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.py @@ -26,7 +26,7 @@ class PaymentTermsTemplate(Document): def check_duplicate_terms(self): terms = [] for term in self.terms: - term_info = (term.credit_days, term.credit_months, term.due_date_based_on) + term_info = (term.payment_term, term.credit_days, term.credit_months, term.due_date_based_on) if term_info in terms: frappe.msgprint( _('The Payment Term at row {0} is possibly a duplicate.').format(term.idx), From 41b7c1aec0ae507430a6aa433c0c52b91a1ff92e Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Wed, 16 Jun 2021 14:40:14 +0530 Subject: [PATCH 12/12] fix(General Ledger): Improve account filter --- .../report/general_ledger/general_ledger.py | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index 8be6aaf564..03808c3640 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -223,17 +223,8 @@ def get_conditions(filters): conditions = [] if filters.get("account") and not filters.get("include_dimensions"): - account_conditions = "account in (select name from tabAccount where" - for account in filters["account"]: - lft, rgt = frappe.db.get_value("Account", account, ["lft", "rgt"]) - account_conditions += """ (lft>=%s and rgt<=%s) """ % (lft, rgt) - - # so that the OR doesn't get added to the last account condition - if account != filters["account"][-1]: - account_conditions += "OR" - - account_conditions += "and docstatus<2)" - conditions.append(account_conditions) + filters.account = get_accounts_with_children(filters.account) + conditions.append("account in %(account)s") if filters.get("cost_center"): filters.cost_center = get_cost_centers_with_children(filters.cost_center) @@ -291,6 +282,20 @@ def get_conditions(filters): return "and {}".format(" and ".join(conditions)) if conditions else "" +def get_accounts_with_children(accounts): + if not isinstance(accounts, list): + accounts = [d.strip() for d in accounts.strip().split(',') if d] + + all_accounts = [] + for d in accounts: + if frappe.db.exists("Account", d): + lft, rgt = frappe.db.get_value("Account", d, ["lft", "rgt"]) + children = frappe.get_all("Account", filters={"lft": [">=", lft], "rgt": ["<=", rgt]}) + all_accounts += [c.name for c in children] + else: + frappe.throw(_("Account: {0} does not exist").format(d)) + + return list(set(all_accounts)) def get_data_with_opening_closing(filters, account_details, accounting_dimensions, gl_entries): data = []