From 6a1ccf94a2fd11e5e2d2785415e234c4c3b1057c Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 1 Jun 2021 21:02:50 +0530 Subject: [PATCH 01/41] fix: Taxable value in GSTR-1 report --- erpnext/regional/report/gstr_1/gstr_1.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py index 96925f90fef..2abdfafa1ba 100644 --- a/erpnext/regional/report/gstr_1/gstr_1.py +++ b/erpnext/regional/report/gstr_1/gstr_1.py @@ -199,7 +199,7 @@ class Gstr1Report(object): self.item_tax_rate = frappe._dict() items = frappe.db.sql(""" - select item_code, parent, base_net_amount, item_tax_rate + select item_code, parent, taxable_value, base_net_amount, item_tax_rate from `tab%s Item` where parent in (%s) """ % (self.doctype, ', '.join(['%s']*len(self.invoices))), tuple(self.invoices), as_dict=1) @@ -207,7 +207,7 @@ class Gstr1Report(object): for d in items: if d.item_code not in self.invoice_items.get(d.parent, {}): self.invoice_items.setdefault(d.parent, {}).setdefault(d.item_code, - sum(i.get('base_net_amount', 0) for i in items + sum((i.get('taxable_value', 0) or i.get('base_net_amount', 0)) for i in items if i.item_code == d.item_code and i.parent == d.parent)) item_tax_rate = {} From 21c15b89ab18b16391cbc34f367d7df222155f3d Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 1 Jun 2021 21:03:33 +0530 Subject: [PATCH 02/41] fix: Add taxable value in Purchase Invoice Item --- erpnext/patches.txt | 1 + ..._taxable_value_field_in_purchase_invoice.py | 18 ++++++++++++++++++ erpnext/regional/india/setup.py | 2 +- 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 erpnext/patches/v12_0/create_taxable_value_field_in_purchase_invoice.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index aa70e709685..5afcd3150c0 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -685,3 +685,4 @@ erpnext.patches.v12_0.create_taxable_value_field erpnext.patches.v12_0.purchase_receipt_status erpnext.patches.v12_0.add_company_link_to_einvoice_settings erpnext.patches.v12_0.add_document_type_field_for_italy_einvoicing +erpnext.patches.v12_0.create_taxable_value_field_in_purchase_invoice diff --git a/erpnext/patches/v12_0/create_taxable_value_field_in_purchase_invoice.py b/erpnext/patches/v12_0/create_taxable_value_field_in_purchase_invoice.py new file mode 100644 index 00000000000..ed323bdd087 --- /dev/null +++ b/erpnext/patches/v12_0/create_taxable_value_field_in_purchase_invoice.py @@ -0,0 +1,18 @@ +from __future__ import unicode_literals +import frappe +from frappe.custom.doctype.custom_field.custom_field import create_custom_fields + +def execute(): + company = frappe.get_all('Company', filters = {'country': 'India'}) + if not company: + return + + custom_fields = { + 'Purchase Invoice Item': [ + dict(fieldname='taxable_value', label='Taxable Value', + fieldtype='Currency', insert_after='base_net_amount', hidden=1, options="Company:company:default_currency", + print_hide=1) + ] + } + + create_custom_fields(custom_fields, update=True) \ No newline at end of file diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py index d417360d938..81dcf36bd3c 100644 --- a/erpnext/regional/india/setup.py +++ b/erpnext/regional/india/setup.py @@ -455,7 +455,7 @@ def make_custom_fields(update=True): 'Sales Order Item': [hsn_sac_field, nil_rated_exempt, is_non_gst], 'Delivery Note Item': [hsn_sac_field, nil_rated_exempt, is_non_gst], 'Sales Invoice Item': [hsn_sac_field, nil_rated_exempt, is_non_gst, taxable_value], - 'Purchase Order Item': [hsn_sac_field, nil_rated_exempt, is_non_gst], + 'Purchase Order Item': [hsn_sac_field, nil_rated_exempt, is_non_gst, taxable_value], 'Purchase Receipt Item': [hsn_sac_field, nil_rated_exempt, is_non_gst], 'Purchase Invoice Item': [hsn_sac_field, nil_rated_exempt, is_non_gst], 'Material Request Item': [hsn_sac_field, nil_rated_exempt, is_non_gst], From 1c3c2b300678811083ffdce85520faaf053e6fac Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Thu, 3 Jun 2021 16:46:30 +0530 Subject: [PATCH 03/41] fix: update shopify api version (#25939) --- .../doctype/shopify_settings/shopify_settings.py | 4 ++-- .../doctype/shopify_settings/sync_product.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.py b/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.py index 25ffd281099..c58b70ccd19 100644 --- a/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.py +++ b/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.py @@ -30,7 +30,7 @@ class ShopifySettings(Document): webhooks = ["orders/create", "orders/paid", "orders/fulfilled"] # url = get_shopify_url('admin/webhooks.json', self) created_webhooks = [d.method for d in self.webhooks] - url = get_shopify_url('admin/api/2020-04/webhooks.json', self) + url = get_shopify_url('admin/api/2021-04/webhooks.json', self) for method in webhooks: session = get_request_session() try: @@ -56,7 +56,7 @@ class ShopifySettings(Document): deleted_webhooks = [] for d in self.webhooks: - url = get_shopify_url('admin/api/2020-04/webhooks/{0}.json'.format(d.webhook_id), self) + url = get_shopify_url('admin/api/2021-04/webhooks/{0}.json'.format(d.webhook_id), self) try: res = session.delete(url, headers=get_header(self)) res.raise_for_status() diff --git a/erpnext/erpnext_integrations/doctype/shopify_settings/sync_product.py b/erpnext/erpnext_integrations/doctype/shopify_settings/sync_product.py index f9f0bb3cecc..16efb6caee1 100644 --- a/erpnext/erpnext_integrations/doctype/shopify_settings/sync_product.py +++ b/erpnext/erpnext_integrations/doctype/shopify_settings/sync_product.py @@ -8,7 +8,7 @@ from erpnext.erpnext_integrations.doctype.shopify_settings.shopify_settings impo shopify_variants_attr_list = ["option1", "option2", "option3"] def sync_item_from_shopify(shopify_settings, item): - url = get_shopify_url("admin/api/2020-04/products/{0}.json".format(item.get("product_id")), shopify_settings) + url = get_shopify_url("admin/api/2021-04/products/{0}.json".format(item.get("product_id")), shopify_settings) session = get_request_session() try: From 5c450cd13fe085d08215f0c88ded8abca5cde0b6 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Thu, 3 Jun 2021 16:48:08 +0530 Subject: [PATCH 04/41] fix: sync shopify customer addresses (#25937) --- .../doctype/shopify_settings/sync_customer.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/erpnext/erpnext_integrations/doctype/shopify_settings/sync_customer.py b/erpnext/erpnext_integrations/doctype/shopify_settings/sync_customer.py index 7866fdea31a..2af57f4c891 100644 --- a/erpnext/erpnext_integrations/doctype/shopify_settings/sync_customer.py +++ b/erpnext/erpnext_integrations/doctype/shopify_settings/sync_customer.py @@ -32,10 +32,12 @@ def create_customer(shopify_customer, shopify_settings): raise e def create_customer_address(customer, shopify_customer): - if not shopify_customer.get("addresses"): - return + addresses = shopify_customer.get("addresses", []) - for i, address in enumerate(shopify_customer.get("addresses")): + if not addresses and "default_address" in shopify_customer: + addresses.append(shopify_customer["default_address"]) + + for i, address in enumerate(addresses): address_title, address_type = get_address_title_and_type(customer.customer_name, i) try : frappe.get_doc({ From 7bb95f0a807670e081ca183d0bbac7e6ba99644f Mon Sep 17 00:00:00 2001 From: Saqib Date: Thu, 3 Jun 2021 17:33:00 +0530 Subject: [PATCH 05/41] feat: cost-center wise period closing entry (#25930) --- .../period_closing_voucher.json | 427 +++++------------- .../period_closing_voucher.py | 111 +++-- .../test_period_closing_voucher.py | 85 ++++ 3 files changed, 268 insertions(+), 355 deletions(-) diff --git a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.json b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.json index d04f25b9aca..81bc03b3eda 100644 --- a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.json +++ b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.json @@ -1,283 +1,95 @@ { - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "ACC-PCV-.YYYY.-.#####", - "beta": 0, - "creation": "2013-01-10 16:34:07", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "editable_grid": 0, - "engine": "InnoDB", + "actions": [], + "autoname": "ACC-PCV-.YYYY.-.#####", + "creation": "2013-01-10 16:34:07", + "doctype": "DocType", + "engine": "InnoDB", + "field_order": [ + "transaction_date", + "posting_date", + "fiscal_year", + "amended_from", + "company", + "cost_center_wise_pnl", + "column_break1", + "closing_account_head", + "remarks" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "transaction_date", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Transaction Date", - "length": 0, - "no_copy": 0, - "oldfieldname": "transaction_date", - "oldfieldtype": "Date", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "transaction_date", + "fieldtype": "Date", + "label": "Transaction Date", + "oldfieldname": "transaction_date", + "oldfieldtype": "Date" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "posting_date", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Posting Date", - "length": 0, - "no_copy": 0, - "oldfieldname": "posting_date", - "oldfieldtype": "Date", - "permlevel": 0, - "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 - }, + "fieldname": "posting_date", + "fieldtype": "Date", + "label": "Posting Date", + "oldfieldname": "posting_date", + "oldfieldtype": "Date", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "fiscal_year", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Closing Fiscal Year", - "length": 0, - "no_copy": 0, - "oldfieldname": "fiscal_year", - "oldfieldtype": "Select", - "options": "Fiscal Year", - "permlevel": 0, - "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 - }, + "fieldname": "fiscal_year", + "fieldtype": "Link", + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Closing Fiscal Year", + "oldfieldname": "fiscal_year", + "oldfieldtype": "Select", + "options": "Fiscal Year", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "amended_from", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Amended From", - "length": 0, - "no_copy": 1, - "oldfieldname": "amended_from", - "oldfieldtype": "Data", - "options": "Period Closing Voucher", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "amended_from", + "fieldtype": "Link", + "ignore_user_permissions": 1, + "label": "Amended From", + "no_copy": 1, + "oldfieldname": "amended_from", + "oldfieldtype": "Data", + "options": "Period Closing Voucher", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "company", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Company", - "length": 0, - "no_copy": 0, - "oldfieldname": "company", - "oldfieldtype": "Select", - "options": "Company", - "permlevel": 0, - "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 - }, + "fieldname": "company", + "fieldtype": "Link", + "label": "Company", + "oldfieldname": "company", + "oldfieldtype": "Select", + "options": "Company", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break1", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "oldfieldtype": "Column Break", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break1", + "fieldtype": "Column Break", + "oldfieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "The account head under Liability or Equity, in which Profit/Loss will be booked", - "fieldname": "closing_account_head", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Closing Account Head", - "length": 0, - "no_copy": 0, - "oldfieldname": "closing_account_head", - "oldfieldtype": "Link", - "options": "Account", - "permlevel": 0, - "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 - }, + "description": "The account head under Liability or Equity, in which Profit/Loss will be booked", + "fieldname": "closing_account_head", + "fieldtype": "Link", + "label": "Closing Account Head", + "oldfieldname": "closing_account_head", + "oldfieldtype": "Link", + "options": "Account", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "remarks", - "fieldtype": "Small Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Remarks", - "length": 0, - "no_copy": 0, - "oldfieldname": "remarks", - "oldfieldtype": "Small Text", - "permlevel": 0, - "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 + "fieldname": "remarks", + "fieldtype": "Small Text", + "label": "Remarks", + "oldfieldname": "remarks", + "oldfieldtype": "Small Text", + "reqd": 1 + }, + { + "default": "0", + "fieldname": "cost_center_wise_pnl", + "fieldtype": "Check", + "label": "Book Cost Center-Wise Profit/Loss" } ], "has_web_view": 0, @@ -291,60 +103,43 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-08-21 16:15:49.089450", + "modified": "2021-05-20 15:27:37.210458", "modified_by": "Administrator", "module": "Accounts", "name": "Period Closing Voucher", "owner": "jai@webnotestech.com", "permissions": [ { - "amend": 1, - "cancel": 1, - "create": 1, - "delete": 1, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 1, + "amend": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "submit": 1, "write": 1 - }, + }, { - "amend": 1, - "cancel": 1, - "create": 1, - "delete": 1, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Accounts Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 1, + "amend": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts Manager", + "share": 1, + "submit": 1, "write": 1 } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "search_fields": "posting_date, fiscal_year", - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "title_field": "closing_account_head", - "track_changes": 0, - "track_seen": 0, - "track_views": 0 + ], + "search_fields": "posting_date, fiscal_year", + "sort_field": "modified", + "sort_order": "DESC", + "title_field": "closing_account_head" } \ No newline at end of file diff --git a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py index b59a177f43b..d479a968999 100644 --- a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py +++ b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py @@ -50,63 +50,96 @@ class PeriodClosingVoucher(AccountsController): def make_gl_entries(self): gl_entries = [] - net_pl_balance = 0 - dimension_fields = ['t1.cost_center'] + net_pl_balance = 0 - accounting_dimensions = get_accounting_dimensions() - for dimension in accounting_dimensions: - dimension_fields.append('t1.{0}'.format(dimension)) - - dimension_filters, default_dimensions = get_dimension_filters() - - pl_accounts = self.get_pl_balances(dimension_fields) + pl_accounts = self.get_pl_balances() for acc in pl_accounts: - if flt(acc.balance_in_company_currency): + if flt(acc.bal_in_company_currency): gl_entries.append(self.get_gl_dict({ "account": acc.account, "cost_center": acc.cost_center, "account_currency": acc.account_currency, - "debit_in_account_currency": abs(flt(acc.balance_in_account_currency)) \ - if flt(acc.balance_in_account_currency) < 0 else 0, - "debit": abs(flt(acc.balance_in_company_currency)) \ - if flt(acc.balance_in_company_currency) < 0 else 0, - "credit_in_account_currency": abs(flt(acc.balance_in_account_currency)) \ - if flt(acc.balance_in_account_currency) > 0 else 0, - "credit": abs(flt(acc.balance_in_company_currency)) \ - if flt(acc.balance_in_company_currency) > 0 else 0 + "debit_in_account_currency": abs(flt(acc.bal_in_account_currency)) if flt(acc.bal_in_account_currency) < 0 else 0, + "debit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) < 0 else 0, + "credit_in_account_currency": abs(flt(acc.bal_in_account_currency)) if flt(acc.bal_in_account_currency) > 0 else 0, + "credit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) > 0 else 0 }, item=acc)) - net_pl_balance += flt(acc.balance_in_company_currency) + net_pl_balance += flt(acc.bal_in_company_currency) if net_pl_balance: - cost_center = frappe.db.get_value("Company", self.company, "cost_center") - gl_entry = self.get_gl_dict({ - "account": self.closing_account_head, - "debit_in_account_currency": abs(net_pl_balance) if net_pl_balance > 0 else 0, - "debit": abs(net_pl_balance) if net_pl_balance > 0 else 0, - "credit_in_account_currency": abs(net_pl_balance) if net_pl_balance < 0 else 0, - "credit": abs(net_pl_balance) if net_pl_balance < 0 else 0, - "cost_center": cost_center - }) - - for dimension in accounting_dimensions: - gl_entry.update({ - dimension: default_dimensions.get(self.company, {}).get(dimension) - }) - - gl_entries.append(gl_entry) + if self.cost_center_wise_pnl: + costcenter_wise_gl_entries = self.get_costcenter_wise_pnl_gl_entries(pl_accounts) + gl_entries += costcenter_wise_gl_entries + else: + gl_entry = self.get_pnl_gl_entry(net_pl_balance) + gl_entries.append(gl_entry) from erpnext.accounts.general_ledger import make_gl_entries make_gl_entries(gl_entries) + + def get_pnl_gl_entry(self, net_pl_balance): + cost_center = frappe.db.get_value("Company", self.company, "cost_center") + gl_entry = self.get_gl_dict({ + "account": self.closing_account_head, + "debit_in_account_currency": abs(net_pl_balance) if net_pl_balance > 0 else 0, + "debit": abs(net_pl_balance) if net_pl_balance > 0 else 0, + "credit_in_account_currency": abs(net_pl_balance) if net_pl_balance < 0 else 0, + "credit": abs(net_pl_balance) if net_pl_balance < 0 else 0, + "cost_center": cost_center + }) + + self.update_default_dimensions(gl_entry) + + return gl_entry + + def get_costcenter_wise_pnl_gl_entries(self, pl_accounts): + company_cost_center = frappe.db.get_value("Company", self.company, "cost_center") + gl_entries = [] + + for acc in pl_accounts: + if flt(acc.bal_in_company_currency): + gl_entry = self.get_gl_dict({ + "account": self.closing_account_head, + "cost_center": acc.cost_center or company_cost_center, + "account_currency": acc.account_currency, + "debit_in_account_currency": abs(flt(acc.bal_in_account_currency)) if flt(acc.bal_in_account_currency) > 0 else 0, + "debit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) > 0 else 0, + "credit_in_account_currency": abs(flt(acc.bal_in_account_currency)) if flt(acc.bal_in_account_currency) < 0 else 0, + "credit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) < 0 else 0 + }, item=acc) + + self.update_default_dimensions(gl_entry) + + gl_entries.append(gl_entry) + + return gl_entries + + def update_default_dimensions(self, gl_entry): + if not self.accounting_dimensions: + self.accounting_dimensions = get_accounting_dimensions() + + _, default_dimensions = get_dimension_filters() + for dimension in self.accounting_dimensions: + gl_entry.update({ + dimension: default_dimensions.get(self.company, {}).get(dimension) + }) + + def get_pl_balances(self): + """Get balance for dimension-wise pl accounts""" + + dimension_fields = ['t1.cost_center'] + + self.accounting_dimensions = get_accounting_dimensions() + for dimension in self.accounting_dimensions: + dimension_fields.append('t1.{0}'.format(dimension)) - def get_pl_balances(self, dimension_fields): - """Get balance for pl accounts""" return frappe.db.sql(""" select t1.account, t2.account_currency, {dimension_fields}, - sum(t1.debit_in_account_currency) - sum(t1.credit_in_account_currency) as balance_in_account_currency, - sum(t1.debit) - sum(t1.credit) as balance_in_company_currency + sum(t1.debit_in_account_currency) - sum(t1.credit_in_account_currency) as bal_in_account_currency, + sum(t1.debit) - sum(t1.credit) as bal_in_company_currency from `tabGL Entry` t1, `tabAccount` t2 where t1.account = t2.name and t2.report_type = 'Profit and Loss' and t2.docstatus < 2 and t2.company = %s diff --git a/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py b/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py index eb02d97b789..2f29372b01c 100644 --- a/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py +++ b/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py @@ -8,6 +8,7 @@ import frappe from frappe.utils import flt, today from erpnext.accounts.utils import get_fiscal_year, now from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry +from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice class TestPeriodClosingVoucher(unittest.TestCase): def test_closing_entry(self): @@ -65,6 +66,58 @@ class TestPeriodClosingVoucher(unittest.TestCase): self.assertEqual(gle_for_random_expense_account[0].amount_in_account_currency, -1*random_expense_account[0].balance_in_account_currency) + def test_cost_center_wise_posting(self): + frappe.db.sql("delete from `tabGL Entry` where company='Test PCV Company'") + + company = create_company() + surplus_account = create_account() + + cost_center1 = create_cost_center("Test Cost Center 1") + cost_center2 = create_cost_center("Test Cost Center 2") + + create_sales_invoice( + company=company, + cost_center=cost_center1, + income_account="Sales - TPC", + expense_account="Cost of Goods Sold - TPC", + rate=400, + debit_to="Debtors - TPC" + ) + create_sales_invoice( + company=company, + cost_center=cost_center2, + income_account="Sales - TPC", + expense_account="Cost of Goods Sold - TPC", + rate=200, + debit_to="Debtors - TPC" + ) + + pcv = frappe.get_doc({ + "transaction_date": today(), + "posting_date": today(), + "fiscal_year": get_fiscal_year(today())[0], + "company": "Test PCV Company", + "cost_center_wise_pnl": 1, + "closing_account_head": surplus_account, + "remarks": "Test", + "doctype": "Period Closing Voucher" + }) + pcv.insert() + pcv.submit() + + expected_gle = ( + ('Sales - TPC', 200.0, 0.0, cost_center2), + (surplus_account, 0.0, 200.0, cost_center2), + ('Sales - TPC', 400.0, 0.0, cost_center1), + (surplus_account, 0.0, 400.0, cost_center1) + ) + + pcv_gle = frappe.db.sql(""" + select account, debit, credit, cost_center from `tabGL Entry` where voucher_no=%s + """, (pcv.name)) + + self.assertTrue(pcv_gle, expected_gle) + def make_period_closing_voucher(self): pcv = frappe.get_doc({ "doctype": "Period Closing Voucher", @@ -80,6 +133,38 @@ class TestPeriodClosingVoucher(unittest.TestCase): return pcv +def create_company(): + company = frappe.get_doc({ + 'doctype': 'Company', + 'company_name': "Test PCV Company", + 'country': 'United States', + 'default_currency': 'USD' + }) + company.insert(ignore_if_duplicate = True) + return company.name + +def create_account(): + account = frappe.get_doc({ + "account_name": "Reserve and Surplus", + "is_group": 0, + "company": "Test PCV Company", + "root_type": "Liability", + "report_type": "Balance Sheet", + "account_currency": "USD", + "parent_account": "Current Liabilities - TPC", + "doctype": "Account" + }).insert(ignore_if_duplicate = True) + return account.name + +def create_cost_center(cc_name): + costcenter = frappe.get_doc({ + "company": "Test PCV Company", + "cost_center_name": cc_name, + "doctype": "Cost Center", + "parent_cost_center": "Test PCV Company - TPC" + }) + costcenter.insert(ignore_if_duplicate = True) + return costcenter.name test_dependencies = ["Customer", "Cost Center"] test_records = frappe.get_test_records("Period Closing Voucher") From a1a3f674a20a012d6732ab23075a795079edf604 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Fri, 4 Jun 2021 11:15:55 +0530 Subject: [PATCH 06/41] fix: invalid 'depends_on' expression in opportunity (#25954) --- erpnext/crm/doctype/opportunity/opportunity.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/crm/doctype/opportunity/opportunity.json b/erpnext/crm/doctype/opportunity/opportunity.json index 918acbfd885..53d3bcc1646 100644 --- a/erpnext/crm/doctype/opportunity/opportunity.json +++ b/erpnext/crm/doctype/opportunity/opportunity.json @@ -277,7 +277,6 @@ "read_only": 1 }, { - "depends_on": "eval:", "fieldname": "territory", "fieldtype": "Link", "label": "Territory", @@ -413,7 +412,7 @@ ], "icon": "fa fa-info-sign", "idx": 195, - "modified": "2020-08-12 23:34:39.665513", + "modified": "2021-06-04 10:11:22.831139", "modified_by": "Administrator", "module": "CRM", "name": "Opportunity", From d789dd38975a558a80b7869e774c0ac5d98ca348 Mon Sep 17 00:00:00 2001 From: Saqib Date: Sun, 6 Jun 2021 10:56:01 +0530 Subject: [PATCH 07/41] fix: wrong round off gl entry posted in case of purchase invoice (#25952) --- erpnext/accounts/general_ledger.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py index 8d265080747..f42899ab5d9 100644 --- a/erpnext/accounts/general_ledger.py +++ b/erpnext/accounts/general_ledger.py @@ -240,10 +240,10 @@ def make_round_off_gle(gl_map, debit_credit_diff, precision): for d in gl_map: if d.account == round_off_account: round_off_gle = d - if d.debit_in_account_currency: - debit_credit_diff -= flt(d.debit_in_account_currency) + if d.debit: + debit_credit_diff -= flt(d.debit) else: - debit_credit_diff += flt(d.credit_in_account_currency) + debit_credit_diff += flt(d.credit) round_off_account_exists = True if round_off_account_exists and abs(debit_credit_diff) <= (1.0 / (10**precision)): From 85dca013ee467c526d3d64b0c7222b7fbfec528f Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Mon, 7 Jun 2021 15:02:49 +0530 Subject: [PATCH 08/41] fix: update employee field on renaming employee (#25958) --- erpnext/hr/doctype/employee/employee.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/hr/doctype/employee/employee.py b/erpnext/hr/doctype/employee/employee.py index a746a9c3a8b..01fc5cf6c20 100755 --- a/erpnext/hr/doctype/employee/employee.py +++ b/erpnext/hr/doctype/employee/employee.py @@ -57,6 +57,9 @@ class Employee(NestedSet): remove_user_permission( "Employee", self.name, existing_user_id) + def after_rename(self, old, new, merge): + self.db_set("employee", new) + def set_employee_name(self): self.employee_name = ' '.join(filter(lambda x: x, [self.first_name, self.middle_name, self.last_name])) From 3c5b33c241dd5b3ebdeb1d597e96dedd55534bd6 Mon Sep 17 00:00:00 2001 From: Anuja Pawar <60467153+Anuja-pawar@users.noreply.github.com> Date: Mon, 7 Jun 2021 21:15:27 +0530 Subject: [PATCH 09/41] fix: update cost center in SI (#25972) --- erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 124daa36be3..3e341ff0c6d 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -450,7 +450,7 @@ class SalesInvoice(SellingController): # set pos values in items for item in self.get("items"): if item.get('item_code'): - profile_details = get_pos_profile_item_details(pos, frappe._dict(item.as_dict()), pos) + profile_details = get_pos_profile_item_details(pos, frappe._dict(item.as_dict()), pos, update_data=True) for fname, val in iteritems(profile_details): if (not for_validate) or (for_validate and not item.get(fname)): item.set(fname, val) @@ -539,7 +539,7 @@ class SalesInvoice(SellingController): def add_remarks(self): if not self.remarks: if self.po_no and self.po_date: - self.remarks = _("Against Customer Order {0} dated {1}").format(self.po_no, + self.remarks = _("Against Customer Order {0} dated {1}").format(self.po_no, formatdate(self.po_date)) else: self.remarks = _("No Remarks") From 371d124a0ec5391f0ddf6b484056b33837d4257c Mon Sep 17 00:00:00 2001 From: hasnain2808 Date: Wed, 9 Jun 2021 18:40:15 +0530 Subject: [PATCH 10/41] fix: do not translate issue priority --- erpnext/setup/setup_wizard/operations/install_fixtures.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/setup/setup_wizard/operations/install_fixtures.py b/erpnext/setup/setup_wizard/operations/install_fixtures.py index 85e070a97f7..77c387ab931 100644 --- a/erpnext/setup/setup_wizard/operations/install_fixtures.py +++ b/erpnext/setup/setup_wizard/operations/install_fixtures.py @@ -175,9 +175,9 @@ def install(country=None): ]}, # Issue Priority - {'doctype': 'Issue Priority', 'name': _('Low')}, - {'doctype': 'Issue Priority', 'name': _('Medium')}, - {'doctype': 'Issue Priority', 'name': _('High')}, + {'doctype': 'Issue Priority', 'name': 'Low'}, + {'doctype': 'Issue Priority', 'name': 'Medium'}, + {'doctype': 'Issue Priority', 'name': 'High'}, #Job Applicant Source {'doctype': 'Job Applicant Source', 'source_name': _('Website Listing')}, From bda432303cc73c67f2f50b03e5e62de909b1c7cd Mon Sep 17 00:00:00 2001 From: gavin Date: Thu, 10 Jun 2021 13:25:44 +0530 Subject: [PATCH 11/41] ci: Use only compatible version of bench CLI bench CLI has dropped support for < PY3.6 --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 213445b806e..7968edc40ba 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,8 +40,7 @@ install: - cd ~ - nvm install 10 - - git clone https://github.com/frappe/bench --depth 1 - - pip install -e ./bench + - pip install -U frappe-bench --only-binary='all' - git clone https://github.com/frappe/frappe --branch $TRAVIS_BRANCH --depth 1 - bench init --skip-assets --frappe-path ~/frappe --python $(which python) frappe-bench From 57832fc9f825388e5a7440e588c9176c6bc9f5b0 Mon Sep 17 00:00:00 2001 From: pateljannat Date: Thu, 17 Jun 2021 10:53:45 +0530 Subject: [PATCH 12/41] fix: material request status issue --- .../buying/doctype/purchase_order/purchase_order.js | 2 +- .../request_for_quotation/request_for_quotation.js | 4 ++-- .../supplier_quotation/supplier_quotation.js | 2 +- .../material_request/material_request_list.js | 13 +++++++------ 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js index 84480468dad..2c48b7995bf 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.js +++ b/erpnext/buying/doctype/purchase_order/purchase_order.js @@ -355,7 +355,7 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend( material_request_type: "Purchase", docstatus: 1, status: ["!=", "Stopped"], - per_ordered: ["<", 99.99], + per_ordered: ["<", 100], } }) }, __("Get items from")); diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js index 4a937f7f0d3..d284e2ef318 100644 --- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js +++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js @@ -271,7 +271,7 @@ erpnext.buying.RequestforQuotationController = erpnext.buying.BuyingController.e material_request_type: "Purchase", docstatus: 1, status: ["!=", "Stopped"], - per_ordered: ["<", 99.99] + per_ordered: ["<", 100] } }) }, __("Get items from")); @@ -316,7 +316,7 @@ erpnext.buying.RequestforQuotationController = erpnext.buying.BuyingController.e material_request_type: "Purchase", docstatus: 1, status: ["!=", "Stopped"], - per_ordered: ["<", 99.99] + per_ordered: ["<", 100] } }); $(btn).done_working(); diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js index 16061c61ba0..2fae2572a9b 100644 --- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js +++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js @@ -46,7 +46,7 @@ erpnext.buying.SupplierQuotationController = erpnext.buying.BuyingController.ext material_request_type: "Purchase", docstatus: 1, status: ["!=", "Stopped"], - per_ordered: ["<", 99.99] + per_ordered: ["<", 100] } }) }, __("Get items from")); diff --git a/erpnext/stock/doctype/material_request/material_request_list.js b/erpnext/stock/doctype/material_request/material_request_list.js index 614ecb8a8f9..31c5afe3f5f 100644 --- a/erpnext/stock/doctype/material_request/material_request_list.js +++ b/erpnext/stock/doctype/material_request/material_request_list.js @@ -1,16 +1,17 @@ frappe.listview_settings['Material Request'] = { add_fields: ["material_request_type", "status", "per_ordered", "per_received"], get_indicator: function(doc) { - if(doc.status=="Stopped") { + var precision = frappe.defaults.get_default("float_precision"); + if (doc.status=="Stopped") { return [__("Stopped"), "red", "status,=,Stopped"]; - } else if(doc.docstatus==1 && flt(doc.per_ordered, 2) == 0) { + } else if (doc.docstatus==1 && flt(doc.per_ordered, precision) == 0) { return [__("Pending"), "orange", "per_ordered,=,0"]; - } else if(doc.docstatus==1 && flt(doc.per_ordered, 2) < 100) { + } else if (doc.docstatus==1 && flt(doc.per_ordered, precision) < 100) { return [__("Partially ordered"), "yellow", "per_ordered,<,100"]; - } else if(doc.docstatus==1 && flt(doc.per_ordered, 2) == 100) { - if (doc.material_request_type == "Purchase" && flt(doc.per_received, 2) < 100 && flt(doc.per_received, 2) > 0) { + } else if (doc.docstatus==1 && flt(doc.per_ordered, precision) == 100) { + if (doc.material_request_type == "Purchase" && flt(doc.per_received, precision) < 100 && flt(doc.per_received, precision) > 0) { return [__("Partially Received"), "yellow", "per_received,<,100"]; - } else if (doc.material_request_type == "Purchase" && flt(doc.per_received, 2) == 100) { + } else if (doc.material_request_type == "Purchase" && flt(doc.per_received, precision) == 100) { return [__("Received"), "green", "per_received,=,100"]; } else if (doc.material_request_type == "Purchase") { return [__("Ordered"), "green", "per_ordered,=,100"]; From fe1d985432787cad2fba7da808e1a34a32cfe9de Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Thu, 17 Jun 2021 17:15:05 +0530 Subject: [PATCH 13/41] fix: Update positions in default cashflow mappers --- .../doctype/cash_flow_mapper/default_cash_flow_mapper.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/cash_flow_mapper/default_cash_flow_mapper.py b/erpnext/accounts/doctype/cash_flow_mapper/default_cash_flow_mapper.py index 43ebcb0cac9..729d4ae2368 100644 --- a/erpnext/accounts/doctype/cash_flow_mapper/default_cash_flow_mapper.py +++ b/erpnext/accounts/doctype/cash_flow_mapper/default_cash_flow_mapper.py @@ -7,19 +7,19 @@ DEFAULT_MAPPERS = [ 'section_header': 'Cash flows from operating activities', 'section_leader': 'Adjustments for', 'section_name': 'Operating Activities', - 'position': 0, + 'position': 1, 'section_subtotal': 'Cash generated from operations', }, { 'doctype': 'Cash Flow Mapper', - 'position': 1, + 'position': 2, 'section_footer': 'Net cash used in investing activities', 'section_header': 'Cash flows from investing activities', 'section_name': 'Investing Activities' }, { 'doctype': 'Cash Flow Mapper', - 'position': 2, + 'position': 3, 'section_footer': 'Net cash used in financing activites', 'section_header': 'Cash flows from financing activities', 'section_name': 'Financing Activities', From 94f0aae625d632d1f6a75e0280d304ec5732def4 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 17 Jun 2021 18:56:13 +0530 Subject: [PATCH 14/41] chore: Added change log for v12.22.0 --- erpnext/change_log/v12/v12_22_0.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 erpnext/change_log/v12/v12_22_0.md diff --git a/erpnext/change_log/v12/v12_22_0.md b/erpnext/change_log/v12/v12_22_0.md new file mode 100644 index 00000000000..4dc49412a4c --- /dev/null +++ b/erpnext/change_log/v12/v12_22_0.md @@ -0,0 +1,16 @@ +## Version 12.22.0 Release Notes + +### Fixes & Enhancements + +- Cost-center wise period closing entry ([#25930](https://github.com/frappe/erpnext/pull/25930)) +- Wrong round off gl entry posted in case of purchase invoice ([#25952](https://github.com/frappe/erpnext/pull/25952)) +- Sync shopify customer addresses (#25481) ([#25937](https://github.com/frappe/erpnext/pull/25937)) +- Plaid NoneType error ([#25662](https://github.com/frappe/erpnext/pull/25662)) +- Cashlfow mapper not showing data ([#25739](https://github.com/frappe/erpnext/pull/25739)) +- Update shopify api version (#25600) ([#25939](https://github.com/frappe/erpnext/pull/25939)) +- Invalid 'depends_on' expression in opportunity ([#25954](https://github.com/frappe/erpnext/pull/25954)) +- Ignore rounding diff while importing JV using data import ([#25715](https://github.com/frappe/erpnext/pull/25715)) +- update cost center from POS ([#25972](https://github.com/frappe/erpnext/pull/25972)) +- update employee field on renaming employee ([#25958](https://github.com/frappe/erpnext/pull/25958)) +- student invalid password reset link ([#25827](https://github.com/frappe/erpnext/pull/25827)) +- Backward compatibility for GSTR-1 report ([#25913](https://github.com/frappe/erpnext/pull/25913)) \ No newline at end of file From 83b6746cd1634fae819fd54a85ef5b2dae7d2b64 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 17 Jun 2021 19:20:32 +0550 Subject: [PATCH 15/41] bumped to version 12.22.0 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 1fdf73a0595..ea60039da09 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '12.21.0' +__version__ = '12.22.0' def get_default_company(user=None): '''Get default company for user''' From b9fb2349d6d2774e453ac6ecefed2a07b5d2d344 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Fri, 11 Jun 2021 17:27:08 +0530 Subject: [PATCH 16/41] fix: material request and supplier quotation not linked if sq created from supplier portal against rfq --- .../request_for_quotation.py | 22 ++++++++++--------- .../templates/includes/transaction_row.html | 8 ++++--- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py index bef2965bf02..51af59f5eeb 100644 --- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py +++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py @@ -279,19 +279,21 @@ def add_items(sq_doc, supplier, items): create_rfq_items(sq_doc, supplier, data) def create_rfq_items(sq_doc, supplier, data): - sq_doc.append('items', { - "item_code": data.item_code, - "item_name": data.item_name, - "description": data.description, - "qty": data.qty, - "rate": data.rate, - "conversion_factor": data.conversion_factor if data.conversion_factor else None, - "supplier_part_no": frappe.db.get_value("Item Supplier", {'parent': data.item_code, 'supplier': supplier}, "supplier_part_no"), - "warehouse": data.warehouse or '', + args = {} + + for field in ['item_code', 'item_name', 'description', 'qty', 'rate', 'conversion_factor', + 'warehouse', 'material_request', 'material_request_item', 'stock_qty']: + args[field] = data.get(field) + + args.update({ "request_for_quotation_item": data.name, - "request_for_quotation": data.parent + "request_for_quotation": data.parent, + "supplier_part_no": frappe.db.get_value("Item Supplier", + {'parent': data.item_code, 'supplier': supplier}, "supplier_part_no") }) + sq_doc.append('items', args) + @frappe.whitelist() def get_pdf(doctype, name, supplier_idx): doc = get_rfq_doc(doctype, name, supplier_idx) diff --git a/erpnext/templates/includes/transaction_row.html b/erpnext/templates/includes/transaction_row.html index 80a542f74bf..553ae2ac61c 100644 --- a/erpnext/templates/includes/transaction_row.html +++ b/erpnext/templates/includes/transaction_row.html @@ -13,9 +13,11 @@ {{ doc.items_preview }} -
- {{ doc.get_formatted("grand_total") }} -
+ {% if doc.get('grand_total') %} +
+ {{ doc.get_formatted("grand_total") }} +
+ {% endif %} Link From a80d9d81c88e1a9f3bd254cdfcdfa3aebe05cfde Mon Sep 17 00:00:00 2001 From: Saqib Date: Tue, 22 Jun 2021 14:25:53 +0530 Subject: [PATCH 17/41] fix(e-invoicing): service item check (#26141) --- erpnext/regional/india/e_invoice/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/regional/india/e_invoice/utils.py b/erpnext/regional/india/e_invoice/utils.py index c9f0b0b2592..879fb8871aa 100644 --- a/erpnext/regional/india/e_invoice/utils.py +++ b/erpnext/regional/india/e_invoice/utils.py @@ -202,7 +202,7 @@ def get_item_list(invoice): item.batch_expiry_date = frappe.db.get_value('Batch', d.batch_no, 'expiry_date') if d.batch_no else None item.batch_expiry_date = format_date(item.batch_expiry_date, 'dd/mm/yyyy') if item.batch_expiry_date else None - item.is_service_item = 'N' if frappe.db.get_value('Item', d.item_code, 'is_stock_item') else 'Y' + item.is_service_item = 'Y' if item.gst_hsn_code and item.gst_hsn_code[:2] == "99" else 'N' item.serial_no = "" item = update_item_taxes(invoice, item) From fc447129768451370bc4e19281a7caaed3ac16ea Mon Sep 17 00:00:00 2001 From: Jannat Patel <31363128+pateljannat@users.noreply.github.com> Date: Wed, 23 Jun 2021 12:30:30 +0530 Subject: [PATCH 18/41] fix: job applicant link issue (#25935) Co-authored-by: Rucha Mahabal --- erpnext/hr/doctype/job_applicant/job_applicant_list.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/hr/doctype/job_applicant/job_applicant_list.js b/erpnext/hr/doctype/job_applicant/job_applicant_list.js index 3b9141ba79c..2ad0d591d8c 100644 --- a/erpnext/hr/doctype/job_applicant/job_applicant_list.js +++ b/erpnext/hr/doctype/job_applicant/job_applicant_list.js @@ -2,7 +2,7 @@ // MIT License. See license.txt frappe.listview_settings['Job Applicant'] = { - add_fields: ["company", "designation", "job_applicant", "status"], + add_fields: ["status"], get_indicator: function (doc) { if (doc.status == "Accepted") { return [__(doc.status), "green", "status,=," + doc.status]; From 57a68c317e47273cf5f443a00d131cd272c6b8aa Mon Sep 17 00:00:00 2001 From: Jannat Patel <31363128+pateljannat@users.noreply.github.com> Date: Wed, 23 Jun 2021 14:38:18 +0530 Subject: [PATCH 19/41] fix: Staffing plan vacancies data type issue (#25940) * fix: staffing plan vacancies data type issue * fix: translation issue * fix: removed greater than 0 condition Co-authored-by: Rucha Mahabal --- .../hr/doctype/staffing_plan/staffing_plan.py | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/erpnext/hr/doctype/staffing_plan/staffing_plan.py b/erpnext/hr/doctype/staffing_plan/staffing_plan.py index 595bcaa8d4a..c2a25d84e9d 100644 --- a/erpnext/hr/doctype/staffing_plan/staffing_plan.py +++ b/erpnext/hr/doctype/staffing_plan/staffing_plan.py @@ -40,7 +40,7 @@ class StaffingPlan(Document): detail.current_openings = designation_counts['job_openings'] if detail.number_of_positions > 0: - if detail.vacancies > 0 and detail.estimated_cost_per_position: + if detail.vacancies and detail.estimated_cost_per_position: detail.total_estimated_cost = cint(detail.vacancies) * flt(detail.estimated_cost_per_position) self.total_estimated_budget += detail.total_estimated_cost @@ -57,8 +57,7 @@ class StaffingPlan(Document): and sp.to_date >= %s and sp.from_date <= %s and sp.company = %s """, (staffing_plan_detail.designation, self.from_date, self.to_date, self.company)) if overlap and overlap [0][0]: - frappe.throw(_("Staffing Plan {0} already exist for designation {1}" - .format(overlap[0][0], staffing_plan_detail.designation))) + frappe.throw(_("Staffing Plan {0} already exist for designation {1}").format(overlap[0][0], staffing_plan_detail.designation)) def validate_with_parent_plan(self, staffing_plan_detail): if not frappe.get_cached_value('Company', self.company, "parent_company"): @@ -75,12 +74,12 @@ class StaffingPlan(Document): if cint(staffing_plan_detail.vacancies) > cint(parent_plan_details[0].vacancies) or \ flt(staffing_plan_detail.total_estimated_cost) > flt(parent_plan_details[0].total_estimated_cost): frappe.throw(_("You can only plan for upto {0} vacancies and budget {1} \ - for {2} as per staffing plan {3} for parent company {4}." - .format(cint(parent_plan_details[0].vacancies), + for {2} as per staffing plan {3} for parent company {4}.").format( + cint(parent_plan_details[0].vacancies), parent_plan_details[0].total_estimated_cost, frappe.bold(staffing_plan_detail.designation), parent_plan_details[0].name, - parent_company)), ParentCompanyError) + parent_company), ParentCompanyError) #Get vacanices already planned for all companies down the hierarchy of Parent Company lft, rgt = frappe.get_cached_value('Company', parent_company, ["lft", "rgt"]) @@ -97,14 +96,14 @@ class StaffingPlan(Document): (flt(parent_plan_details[0].total_estimated_cost) < \ (flt(staffing_plan_detail.total_estimated_cost) + flt(all_sibling_details.total_estimated_cost))): frappe.throw(_("{0} vacancies and {1} budget for {2} already planned for subsidiary companies of {3}. \ - You can only plan for upto {4} vacancies and and budget {5} as per staffing plan {6} for parent company {3}." - .format(cint(all_sibling_details.vacancies), + You can only plan for upto {4} vacancies and and budget {5} as per staffing plan {6} for parent company {3}.").format( + cint(all_sibling_details.vacancies), all_sibling_details.total_estimated_cost, frappe.bold(staffing_plan_detail.designation), parent_company, cint(parent_plan_details[0].vacancies), parent_plan_details[0].total_estimated_cost, - parent_plan_details[0].name))) + parent_plan_details[0].name)) def validate_with_subsidiary_plans(self, staffing_plan_detail): #Valdate this plan with all child company plan @@ -120,11 +119,11 @@ class StaffingPlan(Document): cint(staffing_plan_detail.vacancies) < cint(children_details.vacancies) or \ flt(staffing_plan_detail.total_estimated_cost) < flt(children_details.total_estimated_cost): frappe.throw(_("Subsidiary companies have already planned for {1} vacancies at a budget of {2}. \ - Staffing Plan for {0} should allocate more vacancies and budget for {3} than planned for its subsidiary companies" - .format(self.company, + Staffing Plan for {0} should allocate more vacancies and budget for {3} than planned for its subsidiary companies").format( + self.company, cint(children_details.vacancies), children_details.total_estimated_cost, - frappe.bold(staffing_plan_detail.designation))), SubsidiaryCompanyError) + frappe.bold(staffing_plan_detail.designation)), SubsidiaryCompanyError) @frappe.whitelist() def get_designation_counts(designation, company): From 7270b8913314907ca47feeca26197f2817b6a21f Mon Sep 17 00:00:00 2001 From: Saqib Date: Wed, 23 Jun 2021 19:00:10 +0530 Subject: [PATCH 20/41] fix: invoices can alter profit and loss of a closed year (#26161) --- 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 b4599ba0f46..7d4679690ea 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.py +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py @@ -97,8 +97,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 266563a99acd2c9e9150363004a7d22527e9a3ff Mon Sep 17 00:00:00 2001 From: Noah Jacob Date: Thu, 24 Jun 2021 21:21:22 +0530 Subject: [PATCH 21/41] fix: fixed rounding off ordered percent to 100 in condition (#26153) --- erpnext/stock/doctype/material_request/material_request.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js index 1ccd8cf31a0..9ce2125065a 100644 --- a/erpnext/stock/doctype/material_request/material_request.js +++ b/erpnext/stock/doctype/material_request/material_request.js @@ -69,7 +69,8 @@ frappe.ui.form.on('Material Request', { } if (frm.doc.docstatus == 1 && frm.doc.status != 'Stopped') { - if (flt(frm.doc.per_ordered, 2) < 100) { + let precision = frappe.defaults.get_default("float_precision"); + if (flt(frm.doc.per_ordered, precision) < 100) { let add_create_pick_list_button = () => { frm.add_custom_button(__('Pick List'), () => frm.events.create_pick_list(frm), __('Create')); From 8070d76450af1f49adc4e8e550e140025789fe6c Mon Sep 17 00:00:00 2001 From: meike289 <63092915+meike289@users.noreply.github.com> Date: Mon, 28 Jun 2021 15:05:03 +0200 Subject: [PATCH 22/41] feat: add check field for subscription invoice (#25560) Co-authored-by: Meike Nedwidek --- erpnext/accounts/doctype/subscription/subscription.json | 9 ++++++++- erpnext/accounts/doctype/subscription/subscription.py | 4 +++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/subscription/subscription.json b/erpnext/accounts/doctype/subscription/subscription.json index fb5bb4839c4..bbe8cca9152 100644 --- a/erpnext/accounts/doctype/subscription/subscription.json +++ b/erpnext/accounts/doctype/subscription/subscription.json @@ -30,6 +30,7 @@ "additional_discount_percentage", "additional_discount_amount", "sb_3", + "submit_invoice", "invoices", "accounting_dimensions_section", "dimension_col_break" @@ -202,9 +203,15 @@ "fieldname": "generate_new_invoices_past_due_date", "fieldtype": "Check", "label": "Generate New Invoices Past Due Date" + }, + { + "default": "1", + "fieldname": "submit_invoice", + "fieldtype": "Check", + "label": "Submit Invoice Automatically" } ], - "modified": "2020-11-29 22:46:14.879289", + "modified": "2021-05-03 13:35:21.422940", "modified_by": "Administrator", "module": "Accounts", "name": "Subscription", diff --git a/erpnext/accounts/doctype/subscription/subscription.py b/erpnext/accounts/doctype/subscription/subscription.py index 07fc68334a8..1abb93464b0 100644 --- a/erpnext/accounts/doctype/subscription/subscription.py +++ b/erpnext/accounts/doctype/subscription/subscription.py @@ -289,7 +289,9 @@ class Subscription(Document): invoice.flags.ignore_mandatory = True invoice.save() - invoice.submit() + + if self.submit_invoice: + invoice.submit() return invoice From 704f7b57b8e3099936da582e8dad52be7a2f1217 Mon Sep 17 00:00:00 2001 From: Saqib Date: Fri, 2 Jul 2021 11:18:55 +0530 Subject: [PATCH 23/41] fix(plaid): cannot reset plaid link for a bank account (#26282) --- erpnext/accounts/doctype/bank/bank.js | 3 +- .../doctype/plaid_settings/plaid_connector.py | 2 + .../doctype/plaid_settings/plaid_settings.js | 4 ++ .../doctype/plaid_settings/plaid_settings.py | 42 ++++++++++++++++--- 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/erpnext/accounts/doctype/bank/bank.js b/erpnext/accounts/doctype/bank/bank.js index 6b221433aa3..9fa2083a355 100644 --- a/erpnext/accounts/doctype/bank/bank.js +++ b/erpnext/accounts/doctype/bank/bank.js @@ -109,5 +109,4 @@ erpnext.integrations.refreshPlaidLink = class refreshPlaidLink { plaid_success(token, response) { frappe.show_alert({ message: __('Plaid Link Updated'), indicator: 'green' }); } -}; - +}; \ No newline at end of file diff --git a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_connector.py b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_connector.py index 5f990cdd034..42d4b9b2b43 100644 --- a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_connector.py +++ b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_connector.py @@ -99,5 +99,7 @@ class PlaidConnector(): response = self.client.Transactions.get(self.access_token, start_date=start_date, end_date=end_date, offset=len(transactions)) transactions.extend(response["transactions"]) return transactions + except ItemError as e: + raise e except Exception: frappe.log_error(frappe.get_traceback(), _("Plaid transactions sync error")) diff --git a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.js b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.js index 72705158251..6d59895258d 100644 --- a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.js +++ b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.js @@ -15,6 +15,10 @@ frappe.ui.form.on('Plaid Settings', { frm.add_custom_button(__('Link a new bank account'), () => { new erpnext.integrations.plaidLink(frm); }); + + frm.add_custom_button(__('Reset Plaid Link'), () => { + new erpnext.integrations.plaidLink(frm); + }); } } }); diff --git a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py index 05b7d11b794..75b2bd6b810 100644 --- a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py +++ b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py @@ -12,6 +12,7 @@ from frappe.desk.doctype.tag.tag import add_tag from frappe.model.document import Document from frappe.utils import add_months, formatdate, getdate, today +from plaid.errors import ItemError class PlaidSettings(Document): @staticmethod @@ -50,7 +51,7 @@ def add_institution(token, response): }) bank.insert() except Exception: - frappe.throw(frappe.get_traceback()) + frappe.log_error(frappe.get_traceback(), title=_('Plaid Link Error')) else: bank = frappe.get_doc("Bank", response["institution"]["name"]) bank.plaid_access_token = access_token @@ -82,7 +83,12 @@ def add_bank_accounts(response, bank, company): if not acc_subtype: add_account_subtype(account["subtype"]) - if not frappe.db.exists("Bank Account", dict(integration_id=account["id"])): + existing_bank_account = frappe.db.exists("Bank Account", { + 'account_name': account["name"], + 'bank': bank["bank_name"] + }) + + if not existing_bank_account: try: new_account = frappe.get_doc({ "doctype": "Bank Account", @@ -102,10 +108,27 @@ def add_bank_accounts(response, bank, company): except frappe.UniqueValidationError: frappe.msgprint(_("Bank account {0} already exists and could not be created again").format(account["name"])) except Exception: - frappe.throw(frappe.get_traceback()) + frappe.log_error(frappe.get_traceback(), title=_("Plaid Link Error")) + frappe.throw(_("There was an error creating Bank Account while linking with Plaid."), + title=_("Plaid Link Failed")) else: - result.append(frappe.db.get_value("Bank Account", dict(integration_id=account["id"]), "name")) + try: + existing_account = frappe.get_doc('Bank Account', existing_bank_account) + existing_account.update({ + "bank": bank["bank_name"], + "account_name": account["name"], + "account_type": account.get("type", ""), + "account_subtype": account.get("subtype", ""), + "mask": account.get("mask", ""), + "integration_id": account["id"] + }) + existing_account.save() + result.append(existing_bank_account) + except Exception: + frappe.log_error(frappe.get_traceback(), title=_("Plaid Link Error")) + frappe.throw(_("There was an error updating Bank Account {} while linking with Plaid.").format( + existing_bank_account), title=_("Plaid Link Failed")) return result @@ -174,9 +197,16 @@ def get_transactions(bank, bank_account=None, start_date=None, end_date=None): account_id = None plaid = PlaidConnector(access_token) - transactions = plaid.get_transactions(start_date=start_date, end_date=end_date, account_id=account_id) - return transactions + try: + transactions = plaid.get_transactions(start_date=start_date, end_date=end_date, account_id=account_id) + except ItemError as e: + if e.code == "ITEM_LOGIN_REQUIRED": + msg = _("There was an error syncing transactions.") + " " + msg += _("Please refresh or reset the Plaid linking of the Bank {}.").format(bank) + " " + frappe.log_error(msg, title=_("Plaid Link Refresh Required")) + + return transactions or [] def new_bank_transaction(transaction): From b2a090f0738f06f518ded2d07b8868ae54a059b0 Mon Sep 17 00:00:00 2001 From: Mohammed Yusuf Shaikh <49878143+mohammedyusufshaikh@users.noreply.github.com> Date: Fri, 2 Jul 2021 12:28:43 +0530 Subject: [PATCH 24/41] fix: Added Permissions for employee to book an appointment (#26246) Co-authored-by: Rucha Mahabal --- erpnext/crm/doctype/appointment/appointment.json | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/erpnext/crm/doctype/appointment/appointment.json b/erpnext/crm/doctype/appointment/appointment.json index 32df8ec4295..7dff80855bc 100644 --- a/erpnext/crm/doctype/appointment/appointment.json +++ b/erpnext/crm/doctype/appointment/appointment.json @@ -93,7 +93,7 @@ "fieldtype": "Column Break" } ], - "modified": "2019-10-14 15:23:54.630731", + "modified": "2021-06-28 16:27:53.235714", "modified_by": "Administrator", "module": "CRM", "name": "Appointment", @@ -144,6 +144,18 @@ "role": "Sales User", "share": 1, "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Employee", + "share": 1, + "write": 1 } ], "quick_entry": 1, From ee7de6b1074315dcf6d3cfebb403a107ffdad25f Mon Sep 17 00:00:00 2001 From: Mohammed Yusuf Shaikh <49878143+mohammedyusufshaikh@users.noreply.github.com> Date: Fri, 2 Jul 2021 12:31:59 +0530 Subject: [PATCH 25/41] fix: half day to be accounted in its leave type (#26267) --- erpnext/hr/doctype/attendance/attendance.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/hr/doctype/attendance/attendance.json b/erpnext/hr/doctype/attendance/attendance.json index 20974a0b7d2..fb102a4aa17 100644 --- a/erpnext/hr/doctype/attendance/attendance.json +++ b/erpnext/hr/doctype/attendance/attendance.json @@ -78,7 +78,7 @@ "search_index": 1 }, { - "depends_on": "eval:doc.status==\"On Leave\"", + "depends_on": "eval:doc.status==\"On Leave\" || doc.status==\"Half Day\"", "fieldname": "leave_type", "fieldtype": "Link", "in_standard_filter": 1, @@ -174,7 +174,7 @@ "icon": "fa fa-ok", "idx": 1, "is_submittable": 1, - "modified": "2020-02-19 14:25:32.945842", + "modified": "2021-06-30 14:42:39.162146", "modified_by": "Administrator", "module": "HR", "name": "Attendance", From dfc68950c19e9c6a7ef8ad5d502cc13af0e30bb4 Mon Sep 17 00:00:00 2001 From: Jannat Patel <31363128+pateljannat@users.noreply.github.com> Date: Fri, 2 Jul 2021 13:08:38 +0530 Subject: [PATCH 26/41] fix: lms progress issue (#26254) Co-authored-by: Rucha Mahabal --- erpnext/education/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/education/utils.py b/erpnext/education/utils.py index e0b278c2b1d..9f833dba328 100644 --- a/erpnext/education/utils.py +++ b/erpnext/education/utils.py @@ -345,11 +345,11 @@ def get_or_create_course_enrollment(course, program): student = get_current_student() course_enrollment = get_enrollment("course", course, student.name) if not course_enrollment: - program_enrollment = get_enrollment('program', program, student.name) + program_enrollment = get_enrollment('program', program.name, student.name) if not program_enrollment: frappe.throw(_("You are not enrolled in program {0}".format(program))) return - return student.enroll_in_course(course_name=course, program_enrollment=get_enrollment('program', program, student.name)) + return student.enroll_in_course(course_name=course, program_enrollment=get_enrollment('program', program.name, student.name)) else: return frappe.get_doc('Course Enrollment', course_enrollment) From 0ecf8f5d66420292cd4e0583a700b400dc6e06c8 Mon Sep 17 00:00:00 2001 From: Saqib Date: Fri, 9 Jul 2021 15:33:40 +0530 Subject: [PATCH 27/41] fix(e-invoicing): allow export invoice even if no taxes applied (#26406) --- erpnext/regional/india/e_invoice/utils.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/erpnext/regional/india/e_invoice/utils.py b/erpnext/regional/india/e_invoice/utils.py index 879fb8871aa..d9727ec3786 100644 --- a/erpnext/regional/india/e_invoice/utils.py +++ b/erpnext/regional/india/e_invoice/utils.py @@ -38,9 +38,13 @@ def validate_eligibility(doc): invalid_company = not frappe.db.get_value('E Invoice User', { 'company': doc.get('company') }) invalid_supply_type = doc.get('gst_category') not in ['Registered Regular', 'SEZ', 'Overseas', 'Deemed Export'] company_transaction = doc.get('billing_address_gstin') == doc.get('company_gstin') - no_taxes_applied = not doc.get('taxes') - if invalid_company or invalid_supply_type or company_transaction or no_taxes_applied: + # if export invoice, then taxes can be empty + # invoice can only be ineligible if no taxes applied and is not an export invoice + no_taxes_applied = not doc.get('taxes') and not doc.get('gst_category') == 'Overseas' + has_non_gst_item = any(d for d in doc.get('items', []) if d.get('is_non_gst')) + + if invalid_company or invalid_supply_type or company_transaction or no_taxes_applied or has_non_gst_item: return False return True From 6f7410073f023ef9a1980b1d14d81653f84c3cf1 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Sat, 10 Jul 2021 22:54:15 +0530 Subject: [PATCH 28/41] fix: serial no issue in purchase receipt --- erpnext/controllers/buying_controller.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index 9d777ef31ea..e5012f972b2 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -981,8 +981,16 @@ def get_non_stock_items(purchase_order, fg_item_code): def set_serial_nos(raw_material, consumed_serial_nos, qty): - serial_nos = set(get_serial_nos(raw_material.serial_nos)) - \ - set(get_serial_nos(consumed_serial_nos)) + consumed_serial_nos_list = [] + + if isinstance(consumed_serial_nos, list): + for row in consumed_serial_nos: + consumed_serial_nos_list.extend(get_serial_nos(row)) + else: + consumed_serial_nos_list = get_serial_nos(row) + + serial_nos = set(get_serial_nos(raw_material.serial_nos)) - set(consumed_serial_nos_list) + if serial_nos and qty <= len(serial_nos): raw_material.serial_no = '\n'.join(list(serial_nos)[0:frappe.utils.cint(qty)]) From 4c58fb40a890e218204abd557f17906ba10145c7 Mon Sep 17 00:00:00 2001 From: Saqib Date: Mon, 12 Jul 2021 11:05:37 +0530 Subject: [PATCH 29/41] fix: omit item discount amount for e-invoicing (#26408) --- erpnext/regional/india/e_invoice/einvoice.js | 4 ++- erpnext/regional/india/e_invoice/utils.py | 28 +++++--------------- erpnext/regional/india/utils.py | 8 ++---- 3 files changed, 12 insertions(+), 28 deletions(-) diff --git a/erpnext/regional/india/e_invoice/einvoice.js b/erpnext/regional/india/e_invoice/einvoice.js index cda732b0fb7..6ee57520495 100644 --- a/erpnext/regional/india/e_invoice/einvoice.js +++ b/erpnext/regional/india/e_invoice/einvoice.js @@ -1,6 +1,8 @@ erpnext.setup_einvoice_actions = (doctype) => { frappe.ui.form.on(doctype, { async refresh(frm) { + if (frm.doc.docstatus == 2) return; + const res = await frappe.call({ method: 'erpnext.regional.india.e_invoice.utils.validate_eligibility', args: { doc: frm.doc } @@ -115,7 +117,7 @@ erpnext.setup_einvoice_actions = (doctype) => { if (irn && ewaybill && !irn_cancelled && !eway_bill_cancelled) { const action = () => { - let message = __('Cancellation of e-way bill is currently not supported. '); + let message = __('Cancellation of e-way bill is currently not supported.') + ' '; message += '

'; message += __('You must first use the portal to cancel the e-way bill and then update the cancelled status in the ERPNext system.'); diff --git a/erpnext/regional/india/e_invoice/utils.py b/erpnext/regional/india/e_invoice/utils.py index d9727ec3786..f788ce9a8d5 100644 --- a/erpnext/regional/india/e_invoice/utils.py +++ b/erpnext/regional/india/e_invoice/utils.py @@ -195,14 +195,10 @@ def get_item_list(invoice): item.qty = abs(item.qty) - if invoice.apply_discount_on == 'Net Total' and invoice.discount_amount: - item.discount_amount = abs(item.base_amount - item.base_net_amount) - else: - item.discount_amount = 0 - - item.unit_rate = abs((abs(item.taxable_value) - item.discount_amount)/ item.qty) - item.gross_amount = abs(item.taxable_value) + item.discount_amount + item.unit_rate = abs(item.taxable_value / item.qty) + item.gross_amount = abs(item.taxable_value) item.taxable_value = abs(item.taxable_value) + item.discount_amount = 0 item.batch_expiry_date = frappe.db.get_value('Batch', d.batch_no, 'expiry_date') if d.batch_no else None item.batch_expiry_date = format_date(item.batch_expiry_date, 'dd/mm/yyyy') if item.batch_expiry_date else None @@ -258,18 +254,8 @@ def update_item_taxes(invoice, item): def get_invoice_value_details(invoice): invoice_value_details = frappe._dict(dict()) - - if invoice.apply_discount_on == 'Net Total' and invoice.discount_amount: - # Discount already applied on net total which means on items - invoice_value_details.base_total = abs(sum([i.taxable_value for i in invoice.get('items')])) - invoice_value_details.invoice_discount_amt = 0 - elif invoice.apply_discount_on == 'Grand Total' and invoice.discount_amount: - invoice_value_details.invoice_discount_amt = invoice.base_discount_amount - invoice_value_details.base_total = abs(sum([i.taxable_value for i in invoice.get('items')])) - else: - invoice_value_details.base_total = abs(sum([i.taxable_value for i in invoice.get('items')])) - # since tax already considers discount amount - invoice_value_details.invoice_discount_amt = 0 + invoice_value_details.base_total = abs(sum([i.taxable_value for i in invoice.get('items')])) + invoice_value_details.invoice_discount_amt = 0 invoice_value_details.round_off = invoice.base_rounding_adjustment invoice_value_details.base_grand_total = abs(invoice.base_rounded_total) or abs(invoice.base_grand_total) @@ -291,8 +277,8 @@ def update_invoice_taxes(invoice, invoice_value_details): considered_rows = [] for t in invoice.taxes: - tax_amount = t.base_tax_amount if (invoice.apply_discount_on == 'Grand Total' and invoice.discount_amount) \ - else t.base_tax_amount_after_discount_amount + tax_amount = t.base_tax_amount_after_discount_amount + if t.account_head in gst_accounts_list: if t.account_head in gst_accounts.cess_account: # using after discount amt since item also uses after discount amt for cess calc diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py index 7b28d21a45b..5685c174737 100644 --- a/erpnext/regional/india/utils.py +++ b/erpnext/regional/india/utils.py @@ -856,12 +856,8 @@ def update_taxable_values(doc, method): considered_rows.append(prev_row_id) for item in doc.get('items'): - if doc.apply_discount_on == 'Grand Total' and doc.discount_amount: - proportionate_value = item.base_amount if doc.base_total else item.qty - total_value = doc.base_total if doc.base_total else doc.total_qty - else: - proportionate_value = item.base_net_amount if doc.base_net_total else item.qty - total_value = doc.base_net_total if doc.base_net_total else doc.total_qty + proportionate_value = item.base_net_amount if doc.base_net_total else item.qty + total_value = doc.base_net_total if doc.base_net_total else doc.total_qty applicable_charges = flt(flt(proportionate_value * (flt(additional_taxes) / flt(total_value)), item.precision('taxable_value'))) From 23db6a8e3a1f4688f3fcb833f52bfd9a6aba3532 Mon Sep 17 00:00:00 2001 From: Jannat Patel <31363128+pateljannat@users.noreply.github.com> Date: Mon, 12 Jul 2021 13:17:27 +0530 Subject: [PATCH 30/41] fix: added company filter while fetching loans (#26296) Co-authored-by: Rucha Mahabal --- erpnext/hr/doctype/loan/loan.js | 9 +++++++++ .../hr/doctype/loan_application/loan_application.js | 11 +++++++++-- erpnext/hr/doctype/salary_slip/salary_slip.py | 4 ++-- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/erpnext/hr/doctype/loan/loan.js b/erpnext/hr/doctype/loan/loan.js index 3f5c30c4758..97504980225 100644 --- a/erpnext/hr/doctype/loan/loan.js +++ b/erpnext/hr/doctype/loan/loan.js @@ -15,6 +15,15 @@ frappe.ui.form.on('Loan', { }; }); + frm.set_query("loan_type", function () { + return { + "filters": { + "docstatus": 1, + "company": frm.doc.company + } + }; + }); + frm.set_query("interest_income_account", function () { return { "filters": { diff --git a/erpnext/hr/doctype/loan_application/loan_application.js b/erpnext/hr/doctype/loan_application/loan_application.js index a73b62a894e..e150a220b86 100644 --- a/erpnext/hr/doctype/loan_application/loan_application.js +++ b/erpnext/hr/doctype/loan_application/loan_application.js @@ -5,8 +5,15 @@ frappe.ui.form.on('Loan Application', { refresh: function(frm) { - frm.trigger("toggle_fields") - frm.trigger("add_toolbar_buttons") + frm.trigger("toggle_fields"); + frm.trigger("add_toolbar_buttons"); + frm.set_query('loan_type', () => { + return { + filters: { + company: frm.doc.company + } + }; + }); }, repayment_method: function(frm) { frm.doc.repayment_amount = frm.doc.repayment_periods = "" diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py index 6e6ae4351c8..2213fa6fb57 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/salary_slip.py @@ -869,8 +869,8 @@ class SalarySlip(TransactionBase): `tabRepayment Schedule` as rps, `tabLoan` as l where l.name = rps.parent and rps.payment_date between %s and %s and - l.repay_from_salary = 1 and l.docstatus = 1 and l.applicant = %s""", - (self.start_date, self.end_date, self.employee), as_dict=True) or [] + l.repay_from_salary = 1 and l.docstatus = 1 and l.applicant = %s and l.company = %s""", + (self.start_date, self.end_date, self.employee, self.company), as_dict=True) or [] def update_salary_slip_in_additional_salary(self): salary_slip = self.name if self.docstatus==1 else None From 1b8670b2634f9a6cc9b9bd9150ef31ef82264710 Mon Sep 17 00:00:00 2001 From: Jannat Patel <31363128+pateljannat@users.noreply.github.com> Date: Tue, 13 Jul 2021 15:29:58 +0530 Subject: [PATCH 31/41] fix: Removed company filter for Loan Type (#26463) --- erpnext/hr/doctype/loan/loan.js | 9 --------- erpnext/hr/doctype/loan_application/loan_application.js | 7 ------- 2 files changed, 16 deletions(-) diff --git a/erpnext/hr/doctype/loan/loan.js b/erpnext/hr/doctype/loan/loan.js index 97504980225..3f5c30c4758 100644 --- a/erpnext/hr/doctype/loan/loan.js +++ b/erpnext/hr/doctype/loan/loan.js @@ -15,15 +15,6 @@ frappe.ui.form.on('Loan', { }; }); - frm.set_query("loan_type", function () { - return { - "filters": { - "docstatus": 1, - "company": frm.doc.company - } - }; - }); - frm.set_query("interest_income_account", function () { return { "filters": { diff --git a/erpnext/hr/doctype/loan_application/loan_application.js b/erpnext/hr/doctype/loan_application/loan_application.js index e150a220b86..eae419accab 100644 --- a/erpnext/hr/doctype/loan_application/loan_application.js +++ b/erpnext/hr/doctype/loan_application/loan_application.js @@ -7,13 +7,6 @@ frappe.ui.form.on('Loan Application', { refresh: function(frm) { frm.trigger("toggle_fields"); frm.trigger("add_toolbar_buttons"); - frm.set_query('loan_type', () => { - return { - filters: { - company: frm.doc.company - } - }; - }); }, repayment_method: function(frm) { frm.doc.repayment_amount = frm.doc.repayment_periods = "" From 5399891b25ac59d462a20568d26e6fdeb040e679 Mon Sep 17 00:00:00 2001 From: Jannat Patel <31363128+pateljannat@users.noreply.github.com> Date: Wed, 14 Jul 2021 14:43:59 +0530 Subject: [PATCH 32/41] fix: task status loop (#26007) --- erpnext/projects/doctype/task/task.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py index 6238306ae25..75cd6219908 100755 --- a/erpnext/projects/doctype/task/task.py +++ b/erpnext/projects/doctype/task/task.py @@ -73,9 +73,6 @@ class Task(NestedSet): if (self.progress or 0) > 100: frappe.throw(_("Progress % for a task cannot be more than 100.")) - if self.progress == 100: - self.status = 'Completed' - if self.status == 'Completed': self.progress = 100 From 24e1786e4910c85b35cfffd72a98b78732bdb274 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 14 Jul 2021 22:52:40 +0530 Subject: [PATCH 33/41] fix: taxes not set correctly when items pulled from PO to PI --- erpnext/stock/doctype/purchase_receipt/purchase_receipt.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js index 27946586eaa..d530a966778 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js @@ -22,7 +22,7 @@ frappe.ui.form.on("Purchase Receipt", { frappe.set_route("Form", lcv.doctype, lcv.name); }, } - + frm.custom_make_buttons = { 'Stock Entry': 'Return', 'Purchase Invoice': 'Purchase Invoice' @@ -34,7 +34,7 @@ frappe.ui.form.on("Purchase Receipt", { filters: {'company': frm.doc.company } } }); - + }, onload: function(frm) { erpnext.queries.setup_queries(frm, "Warehouse", function() { @@ -107,6 +107,8 @@ erpnext.stock.PurchaseReceiptController = erpnext.buying.BuyingController.extend message: __("Please Select a Supplier") }); } + + me.frm.doc.taxes = []; erpnext.utils.map_current_doc({ method: "erpnext.buying.doctype.purchase_order.purchase_order.make_purchase_receipt", source_doctype: "Purchase Order", From b22cbb31224bc417ce39d99cc4d926c63a820116 Mon Sep 17 00:00:00 2001 From: Noah Jacob Date: Fri, 16 Jul 2021 15:01:14 +0530 Subject: [PATCH 34/41] fix: validation check when no conversion_factor (#26528) --- erpnext/stock/utils.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py index 1fc9f202fed..43a7c5dd48f 100644 --- a/erpnext/stock/utils.py +++ b/erpnext/stock/utils.py @@ -316,13 +316,16 @@ def update_included_uom_in_report(columns, result, include_uom, conversion_facto for row_idx, row in enumerate(result): data = row.items() if is_dict_obj else enumerate(row) for key, value in data: - if key not in convertible_columns or not conversion_factors[row_idx-1]: + if key not in convertible_columns: continue + # If no conversion factor for the UOM, defaults to 1 + if not conversion_factors[row_idx]: + conversion_factors[row_idx] = 1 if convertible_columns.get(key) == 'rate': - new_value = flt(value) * conversion_factors[row_idx-1] + new_value = flt(value) * conversion_factors[row_idx] else: - new_value = flt(value) / conversion_factors[row_idx-1] + new_value = flt(value) / conversion_factors[row_idx] if not is_dict_obj: row.insert(key+1, new_value) @@ -370,4 +373,4 @@ def add_additional_uom_columns(columns, result, include_uom, conversion_factors) else: row[data.converted_col] = flt(value_before_conversion) / conversion_factor - result[row_idx] = row \ No newline at end of file + result[row_idx] = row From 9a1caddacc88628346179139e58a3ff1d3c4f409 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 16 Jul 2021 16:08:40 +0530 Subject: [PATCH 35/41] chore: added change log for v12.23.0 --- erpnext/change_log/v12/v12_23_0.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 erpnext/change_log/v12/v12_23_0.md diff --git a/erpnext/change_log/v12/v12_23_0.md b/erpnext/change_log/v12/v12_23_0.md new file mode 100644 index 00000000000..3b4ca5ce568 --- /dev/null +++ b/erpnext/change_log/v12/v12_23_0.md @@ -0,0 +1,20 @@ +## Version 12.23.0 Release Notes + +### Fixes & Enhancements +- Added Permissions for employee to book an appointment ([#26246](https://github.com/frappe/erpnext/pull/26246)) +- New check field in subscriptions for (not) submitting invoices (BP #25394) ([#25560](https://github.com/frappe/erpnext/pull/25560)) +- fix(e-invoicing): allow export invoice even if no taxes applied (#26363) ([#26406](https://github.com/frappe/erpnext/pull/26406)) +- Omit item discount amount for e-invoicing (#26353) ([#26408](https://github.com/frappe/erpnext/pull/26408)) +- fix(plaid): cannot reset plaid link for a bank account ([#26282](https://github.com/frappe/erpnext/pull/26282)) +- Job applicant link issue ([#25935](https://github.com/frappe/erpnext/pull/25935)) +- LMS progress issue ([#26254](https://github.com/frappe/erpnext/pull/26254)) +- Half day to be accounted in its leave type ([#26267](https://github.com/frappe/erpnext/pull/26267)) +- Material request status issue ([#26089](https://github.com/frappe/erpnext/pull/26089)) +- fix(e-invoicing): service item check ([#26141](https://github.com/frappe/erpnext/pull/26141)) +- Invoices can alter profit and loss of a closed year ([#26161](https://github.com/frappe/erpnext/pull/26161)) +- Material request and supplier quotation not linked if supplier quotation created from supplier portal ([#26117](https://github.com/frappe/erpnext/pull/26117)) +- Update positions in default cashflow mappers ([#26091](https://github.com/frappe/erpnext/pull/26091)) +- Staffing plan vacancies data type issue ([#25940](https://github.com/frappe/erpnext/pull/25940)) +- Added company filter while fetching loans ([#26296](https://github.com/frappe/erpnext/pull/26296)) +- Serial no issue in subcontract purchase receipt ([#26423](https://github.com/frappe/erpnext/pull/26423)) +- Fixed rounding off ordered percent to 100 in condition ([#26153](https://github.com/frappe/erpnext/pull/26153)) \ No newline at end of file From fc0459fba905e648222cc1cbefc6e04f1c212ab4 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 16 Jul 2021 16:30:30 +0550 Subject: [PATCH 36/41] bumped to version 12.23.0 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index ea60039da09..4cd5982e877 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '12.22.0' +__version__ = '12.23.0' def get_default_company(user=None): '''Get default company for user''' From 01f8833bd1836d4e5d1eea66a475bc714c9f0c45 Mon Sep 17 00:00:00 2001 From: Subin Tom <36098155+nemesis189@users.noreply.github.com> Date: Tue, 20 Jul 2021 21:04:10 +0530 Subject: [PATCH 37/41] fix: Fixed clearing issue of payment references on setting cost center (#26548) Co-authored-by: Subin Tom Co-authored-by: Afshan <33727827+AfshanKhan@users.noreply.github.com> --- .../accounts/doctype/payment_entry/payment_entry.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js index 0bd54cd6055..bd6acb8dcb5 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.js +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js @@ -1041,18 +1041,10 @@ frappe.ui.form.on('Payment Entry', { }, callback: function(r, rt) { if(r.message) { - frappe.run_serially([ - () => { + frm.set_value("paid_from_account_balance", r.message.paid_from_account_balance); frm.set_value("paid_to_account_balance", r.message.paid_to_account_balance); frm.set_value("party_balance", r.message.party_balance); - }, - () => { - if(frm.doc.payment_type != "Internal") { - frm.clear_table("references"); - } - } - ]); } } From 2e5a358e9617be8efe2a661008788aef0c2f7744 Mon Sep 17 00:00:00 2001 From: pateljannat Date: Fri, 23 Jul 2021 13:06:57 +0530 Subject: [PATCH 38/41] fix: salary component account filter --- erpnext/hr/doctype/salary_component/salary_component.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/erpnext/hr/doctype/salary_component/salary_component.js b/erpnext/hr/doctype/salary_component/salary_component.js index c455eb3303b..f2a0e2e715d 100644 --- a/erpnext/hr/doctype/salary_component/salary_component.js +++ b/erpnext/hr/doctype/salary_component/salary_component.js @@ -5,10 +5,17 @@ frappe.ui.form.on('Salary Component', { setup: function(frm) { frm.set_query("default_account", "accounts", function(doc, cdt, cdn) { var d = locals[cdt][cdn]; + + var root_type = "Liability"; + if (frm.doc.type == "Deduction") { + root_type = "Expense"; + } + return { filters: { "is_group": 0, - "company": d.company + "company": d.company, + "root_type": root_type } }; }); From c908add82edbcf1b636bc8f44e4f58572c937b6a Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sun, 25 Jul 2021 19:46:20 +0530 Subject: [PATCH 39/41] fix: Exchange rate revaluation posting date and precision fixes --- .../exchange_rate_revaluation.py | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py index 9594706d0f6..7d562d6c57f 100644 --- a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py +++ b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py @@ -81,10 +81,12 @@ class ExchangeRateRevaluation(Document): sum(debit) - sum(credit) as balance from `tabGL Entry` where account in (%s) + and posting_date <= %s + and is_cancelled = 0 group by account, party_type, party having sum(debit) != sum(credit) order by account - """ % ', '.join(['%s']*len(accounts)), tuple(accounts), as_dict=1) + """ % (', '.join(['%s']*len(accounts)), '%s'), tuple(accounts + [self.posting_date]), as_dict=1) return account_details @@ -124,9 +126,9 @@ class ExchangeRateRevaluation(Document): "party_type": d.get("party_type"), "party": d.get("party"), "account_currency": d.get("account_currency"), - "balance": d.get("balance_in_account_currency"), - dr_or_cr: abs(d.get("balance_in_account_currency")), - "exchange_rate":d.get("new_exchange_rate"), + "balance": flt(d.get("balance_in_account_currency"), d.precision("balance_in_account_currency")), + dr_or_cr: flt(abs(d.get("balance_in_account_currency")), d.precision("balance_in_account_currency")), + "exchange_rate": flt(d.get("new_exchange_rate"), d.precision("new_exchange_rate")), "reference_type": "Exchange Rate Revaluation", "reference_name": self.name, }) @@ -135,9 +137,9 @@ class ExchangeRateRevaluation(Document): "party_type": d.get("party_type"), "party": d.get("party"), "account_currency": d.get("account_currency"), - "balance": d.get("balance_in_account_currency"), - reverse_dr_or_cr: abs(d.get("balance_in_account_currency")), - "exchange_rate": d.get("current_exchange_rate"), + "balance": flt(d.get("balance_in_account_currency"), d.precision("balance_in_account_currency")), + reverse_dr_or_cr: flt(abs(d.get("balance_in_account_currency")), d.precision("balance_in_account_currency")), + "exchange_rate": flt(d.get("current_exchange_rate"), d.precision("current_exchange_rate")), "reference_type": "Exchange Rate Revaluation", "reference_name": self.name }) @@ -166,9 +168,9 @@ def get_account_details(account, company, posting_date, party_type=None, party=N account_details = {} company_currency = erpnext.get_company_currency(company) - balance = get_balance_on(account, party_type=party_type, party=party, in_account_currency=False) + balance = get_balance_on(account, date=posting_date, party_type=party_type, party=party, in_account_currency=False) if balance: - balance_in_account_currency = get_balance_on(account, party_type=party_type, party=party) + balance_in_account_currency = get_balance_on(account, date=posting_date, party_type=party_type, party=party) current_exchange_rate = balance / balance_in_account_currency if balance_in_account_currency else 0 new_exchange_rate = get_exchange_rate(account_currency, company_currency, posting_date) new_balance_in_base_currency = balance_in_account_currency * new_exchange_rate From 12c3e5dfd6268ed56aad7ba4404a3833979c1aeb Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sun, 25 Jul 2021 21:27:56 +0530 Subject: [PATCH 40/41] fix: Remove unintended changes --- .../exchange_rate_revaluation/exchange_rate_revaluation.py | 1 - 1 file changed, 1 deletion(-) diff --git a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py index 7d562d6c57f..d56f5b660f6 100644 --- a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py +++ b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py @@ -82,7 +82,6 @@ class ExchangeRateRevaluation(Document): from `tabGL Entry` where account in (%s) and posting_date <= %s - and is_cancelled = 0 group by account, party_type, party having sum(debit) != sum(credit) order by account From b549287b94d69cc780fd0a941a1226a0801d165e Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sun, 25 Jul 2021 21:26:22 +0530 Subject: [PATCH 41/41] fix: Convert null values to empty string on grouping --- .../exchange_rate_revaluation/exchange_rate_revaluation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py index d56f5b660f6..8d47bcbd118 100644 --- a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py +++ b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py @@ -82,7 +82,7 @@ class ExchangeRateRevaluation(Document): from `tabGL Entry` where account in (%s) and posting_date <= %s - group by account, party_type, party + group by account, NULLIF(party_type,''), NULLIF(party,'') having sum(debit) != sum(credit) order by account """ % (', '.join(['%s']*len(accounts)), '%s'), tuple(accounts + [self.posting_date]), as_dict=1)