From ab92e330dae8528faf5a98910b693b31a7ceb2ba Mon Sep 17 00:00:00 2001 From: P-Froggy <60393001+P-Froggy@users.noreply.github.com> Date: Sun, 16 Feb 2020 23:08:32 +0100 Subject: [PATCH 01/26] Fix: Wrong filter for supplier default bank account The query for default bank account field in the supplier master only allowed company bank accounts. With this fix it's now possible to one of the supplier bank accounts as default bank account. --- erpnext/buying/doctype/supplier/supplier.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/buying/doctype/supplier/supplier.js b/erpnext/buying/doctype/supplier/supplier.js index 4ddc458175..074888afd9 100644 --- a/erpnext/buying/doctype/supplier/supplier.js +++ b/erpnext/buying/doctype/supplier/supplier.js @@ -17,10 +17,11 @@ frappe.ui.form.on("Supplier", { } } }); - frm.set_query("default_bank_account", function() { + frm.set_query("default_bank_account", function(doc, cdt, cdn) { return { filters: { - "is_company_account":1 + "is_company_account":0, + "party":doc.name } } }); From 7ee8a209647ee6a09557d8e40fc8712ec9321e49 Mon Sep 17 00:00:00 2001 From: P-Froggy <60393001+P-Froggy@users.noreply.github.com> Date: Mon, 17 Feb 2020 00:15:29 +0100 Subject: [PATCH 02/26] Added bank account reference in supplier dashboard --- erpnext/buying/doctype/supplier/supplier_dashboard.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/erpnext/buying/doctype/supplier/supplier_dashboard.py b/erpnext/buying/doctype/supplier/supplier_dashboard.py index 887a093736..f346e7e72a 100644 --- a/erpnext/buying/doctype/supplier/supplier_dashboard.py +++ b/erpnext/buying/doctype/supplier/supplier_dashboard.py @@ -9,8 +9,9 @@ def get_data(): 'heatmap_message': _('This is based on transactions against this Supplier. See timeline below for details'), 'fieldname': 'supplier', 'non_standard_fieldnames': { - 'Payment Entry': 'party_name' - }, + 'Payment Entry': 'party_name', + 'Bank Account': 'party' + }, 'transactions': [ { 'label': _('Procurement'), @@ -24,6 +25,10 @@ def get_data(): 'label': _('Payments'), 'items': ['Payment Entry'] }, + { + 'label': _('Bank'), + 'items': ['Bank Account'] + }, { 'label': _('Pricing'), 'items': ['Pricing Rule'] From 7ccb8b6707b821b6d38c280c325c1f8349795db2 Mon Sep 17 00:00:00 2001 From: P-Froggy <60393001+P-Froggy@users.noreply.github.com> Date: Mon, 17 Feb 2020 11:33:10 +0100 Subject: [PATCH 03/26] Revert "Merge pull request #1 from P-Froggy/patch-1" This reverts commit 79c5266d0d0057e7c76365d47ff99604f0615700, reversing changes made to bd582cfc39610afe794459a1bb92fb1e15c3577b. --- erpnext/buying/doctype/supplier/supplier.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/erpnext/buying/doctype/supplier/supplier.js b/erpnext/buying/doctype/supplier/supplier.js index 074888afd9..4ddc458175 100644 --- a/erpnext/buying/doctype/supplier/supplier.js +++ b/erpnext/buying/doctype/supplier/supplier.js @@ -17,11 +17,10 @@ frappe.ui.form.on("Supplier", { } } }); - frm.set_query("default_bank_account", function(doc, cdt, cdn) { + frm.set_query("default_bank_account", function() { return { filters: { - "is_company_account":0, - "party":doc.name + "is_company_account":1 } } }); From 4cc929cabbe8630d5919eaf39c483a4933eca72e Mon Sep 17 00:00:00 2001 From: P-Froggy <60393001+P-Froggy@users.noreply.github.com> Date: Tue, 18 Feb 2020 00:38:46 +0100 Subject: [PATCH 04/26] Move SWIFT-number and branch-code from bank account to bank The bank's SWIFT-Number and branch-code should be a field in bank DocType, not in bank account DocType. --- erpnext/accounts/doctype/bank/bank.json | 320 ++++++------------ .../doctype/bank_account/bank_account.json | 13 - .../doctype/bank_guarantee/bank_guarantee.js | 4 +- .../payment_request/payment_request.json | 4 +- erpnext/patches.txt | 3 +- .../move_bank_account_swift_number_to_bank.py | 20 ++ 6 files changed, 136 insertions(+), 228 deletions(-) create mode 100644 erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py diff --git a/erpnext/accounts/doctype/bank/bank.json b/erpnext/accounts/doctype/bank/bank.json index 4fa0e4f29b..7a628b5228 100644 --- a/erpnext/accounts/doctype/bank/bank.json +++ b/erpnext/accounts/doctype/bank/bank.json @@ -1,224 +1,124 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "field:bank_name", - "beta": 0, - "creation": "2018-04-07 16:59:59.496668", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", + "actions": [], + "allow_import": 1, + "allow_rename": 1, + "autoname": "field:bank_name", + "creation": "2018-04-07 16:59:59.496668", + "doctype": "DocType", + "document_type": "Setup", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "bank_name", + "bank_details_section", + "swift_number", + "column_break_1", + "branch_code", + "data_import_configuration_section", + "bank_transaction_mapping", + "section_break_4", + "plaid_access_token" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "bank_name", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Bank Name", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "fieldname": "bank_name", + "fieldtype": "Data", + "label": "Bank Name", + "reqd": 1, "unique": 1 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "fieldname": "data_import_configuration_section", - "fieldtype": "Section 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, - "label": "Data Import Configuration", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "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": "bank_details_section", + "fieldtype": "Section Break", + "label": "Bank Details" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "bank_transaction_mapping", - "fieldtype": "Table", - "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": "Bank Transaction Mapping", - "length": 0, - "no_copy": 0, - "options": "Bank Transaction Mapping", - "permlevel": 0, - "precision": "", - "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": "swift_number", + "fieldtype": "Data", + "in_list_view": 1, + "in_standard_filter": 1, + "label": "SWIFT number", + "reqd": 0, + "unique": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_4", - "fieldtype": "Section 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, - "permlevel": 0, - "precision": "", - "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_break_1", + "fieldtype": "Column Break", + "search_index": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "plaid_access_token", - "fieldtype": "Data", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Plaid Access Token", - "length": 0, - "no_copy": 1, - "permlevel": 0, - "precision": "", - "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": "branch_code", + "fieldtype": "Data", + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Branch Code", + "reqd": 0, + "unique": 1 + }, + { + "collapsible": 1, + "fieldname": "data_import_configuration_section", + "fieldtype": "Section Break", + "label": "Data Import Configuration" + }, + { + "fieldname": "bank_transaction_mapping", + "fieldtype": "Table", + "label": "Bank Transaction Mapping", + "options": "Bank Transaction Mapping" + }, + { + "fieldname": "section_break_4", + "fieldtype": "Section Break" + }, + { + "fieldname": "plaid_access_token", + "fieldtype": "Data", + "hidden": 1, + "label": "Plaid Access Token", + "no_copy": 1, + "read_only": 1 } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2018-11-27 16:12:13.938776", - "modified_by": "Administrator", - "module": "Accounts", - "name": "Bank", - "name_case": "", - "owner": "Administrator", + ], + "has_web_view": 0, + "hide_heading": 0, + "hide_toolbar": 0, + "idx": 0, + "image_view": 0, + "in_create": 0, + "is_submittable": 0, + "issingle": 0, + "istable": 0, + "max_attachments": 0, + "modified": "2018-11-27 16:12:13.938776", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Bank", + "name_case": "", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "amend": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 0, "write": 1 } - ], - "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 + ], + "quick_entry": 1, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/accounts/doctype/bank_account/bank_account.json b/erpnext/accounts/doctype/bank_account/bank_account.json index c8ae26d9f2..ade379b11d 100644 --- a/erpnext/accounts/doctype/bank_account/bank_account.json +++ b/erpnext/accounts/doctype/bank_account/bank_account.json @@ -24,8 +24,6 @@ "iban", "column_break_12", "bank_account_no", - "branch_code", - "swift_number", "address_and_contact", "address_html", "website", @@ -145,17 +143,6 @@ "label": "Bank Account No", "length": 30 }, - { - "fieldname": "branch_code", - "fieldtype": "Data", - "in_list_view": 1, - "label": "Branch Code" - }, - { - "fieldname": "swift_number", - "fieldtype": "Data", - "label": "SWIFT number" - }, { "fieldname": "address_and_contact", "fieldtype": "Section Break", diff --git a/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.js b/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.js index 0acbe2009f..065d25e6c3 100644 --- a/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.js +++ b/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.js @@ -4,8 +4,8 @@ cur_frm.add_fetch('bank_account','account','account'); cur_frm.add_fetch('bank_account','bank_account_no','bank_account_no'); cur_frm.add_fetch('bank_account','iban','iban'); -cur_frm.add_fetch('bank_account','branch_code','branch_code'); -cur_frm.add_fetch('bank_account','swift_number','swift_number'); +cur_frm.add_fetch('bank','branch_code','branch_code'); +cur_frm.add_fetch('bank','swift_number','swift_number'); frappe.ui.form.on('Bank Guarantee', { setup: function(frm) { diff --git a/erpnext/accounts/doctype/payment_request/payment_request.json b/erpnext/accounts/doctype/payment_request/payment_request.json index bff995ec5a..c1559a74f2 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.json +++ b/erpnext/accounts/doctype/payment_request/payment_request.json @@ -839,7 +839,7 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fetch_from": "bank_account.branch_code", + "fetch_from": "bank.branch_code", "fieldname": "branch_code", "fieldtype": "Read Only", "hidden": 0, @@ -873,7 +873,7 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fetch_from": "bank_account.swift_number", + "fetch_from": "bank.swift_number", "fieldname": "swift_number", "fieldtype": "Read Only", "hidden": 0, diff --git a/erpnext/patches.txt b/erpnext/patches.txt index a8938406f2..11a990df73 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -656,4 +656,5 @@ erpnext.patches.v12_0.set_lead_title_field erpnext.patches.v12_0.set_permission_einvoicing erpnext.patches.v12_0.set_published_in_hub_tracked_item erpnext.patches.v12_0.set_job_offer_applicant_email -erpnext.patches.v12_0.create_irs_1099_field_united_states \ No newline at end of file +erpnext.patches.v12_0.create_irs_1099_field_united_states +erpnext.patches.v12_0.move_bank_account_swift_number_to_bank \ No newline at end of file diff --git a/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py b/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py new file mode 100644 index 0000000000..2675b98480 --- /dev/null +++ b/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py @@ -0,0 +1,20 @@ +from __future__ import unicode_literals +import frappe + +def execute(): + frappe.reload_doc('accounts', 'doctype', 'bank', force=1) + + banks = frappe.get_all('Bank', 'name') + for bank in banks: + bank_accounts = frappe.get_all('Bank Account', filters={'bank': bank.name}, fields=['swift_number', 'branch_code']) + bank_account = '' + if len(bank_accounts): + bank_account = bank_accounts[0] + if bank_account and bank_account.swift_number: + bank.swift_number = bank_account.swift_number + if bank_account and bank_account.branch_code: + bank.branch_code = bank_account.branch_code + bank.save() + + frappe.reload_doc('accounts', 'doctype', 'bank_account') + frappe.reload_doc('accounts', 'doctype', 'payment_request') \ No newline at end of file From e4d8ee5ba84e08810182429b6351fffc9ead1358 Mon Sep 17 00:00:00 2001 From: P-Froggy <60393001+P-Froggy@users.noreply.github.com> Date: Tue, 18 Feb 2020 01:05:19 +0100 Subject: [PATCH 05/26] Revert "Added bank account reference in supplier dashboard" This reverts commit 7ee8a209647ee6a09557d8e40fc8712ec9321e49. --- erpnext/buying/doctype/supplier/supplier_dashboard.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/erpnext/buying/doctype/supplier/supplier_dashboard.py b/erpnext/buying/doctype/supplier/supplier_dashboard.py index f346e7e72a..887a093736 100644 --- a/erpnext/buying/doctype/supplier/supplier_dashboard.py +++ b/erpnext/buying/doctype/supplier/supplier_dashboard.py @@ -9,9 +9,8 @@ def get_data(): 'heatmap_message': _('This is based on transactions against this Supplier. See timeline below for details'), 'fieldname': 'supplier', 'non_standard_fieldnames': { - 'Payment Entry': 'party_name', - 'Bank Account': 'party' - }, + 'Payment Entry': 'party_name' + }, 'transactions': [ { 'label': _('Procurement'), @@ -25,10 +24,6 @@ def get_data(): 'label': _('Payments'), 'items': ['Payment Entry'] }, - { - 'label': _('Bank'), - 'items': ['Bank Account'] - }, { 'label': _('Pricing'), 'items': ['Pricing Rule'] From 3cb9f4ab73b3eaa65a50658f7ead1b9733654fdd Mon Sep 17 00:00:00 2001 From: P-Froggy <60393001+P-Froggy@users.noreply.github.com> Date: Tue, 18 Feb 2020 02:14:03 +0100 Subject: [PATCH 06/26] Add address and contact fields to bank Address and contact fields are enabled for DocType Bank --- erpnext/accounts/doctype/bank/bank.js | 13 ++++++++++++- erpnext/accounts/doctype/bank/bank.py | 8 +++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/bank/bank.js b/erpnext/accounts/doctype/bank/bank.js index 463d29c9f8..39f057913d 100644 --- a/erpnext/accounts/doctype/bank/bank.js +++ b/erpnext/accounts/doctype/bank/bank.js @@ -7,7 +7,18 @@ frappe.ui.form.on('Bank', { }, refresh: function(frm) { add_fields_to_mapping_table(frm); - } + + frappe.dynamic_link = { doc: frm.doc, fieldname: 'name', doctype: 'Bank' } + + frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal); + + if (frm.doc.__islocal) { + frappe.contacts.clear_address_and_contact(frm); + } + else { + frappe.contacts.render_address_and_contact(frm); + } + }, }); diff --git a/erpnext/accounts/doctype/bank/bank.py b/erpnext/accounts/doctype/bank/bank.py index b205d56678..41aae14362 100644 --- a/erpnext/accounts/doctype/bank/bank.py +++ b/erpnext/accounts/doctype/bank/bank.py @@ -5,6 +5,12 @@ from __future__ import unicode_literals import frappe from frappe.model.document import Document +from frappe.contacts.address_and_contact import load_address_and_contact, delete_contact_and_address class Bank(Document): - pass + def onload(self): + """Load address and contacts in `__onload`""" + load_address_and_contact(self) + + def on_trash(self): + delete_contact_and_address('Bank', self.name) \ No newline at end of file From 55d10f77f963eb0cdbe29e04fe910f65c4edaec4 Mon Sep 17 00:00:00 2001 From: P-Froggy <60393001+P-Froggy@users.noreply.github.com> Date: Fri, 28 Feb 2020 13:14:11 +0100 Subject: [PATCH 07/26] fix: Add linked bank accounts to supplier dashboard --- erpnext/buying/doctype/supplier/supplier_dashboard.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/erpnext/buying/doctype/supplier/supplier_dashboard.py b/erpnext/buying/doctype/supplier/supplier_dashboard.py index 887a093736..d0d5b73984 100644 --- a/erpnext/buying/doctype/supplier/supplier_dashboard.py +++ b/erpnext/buying/doctype/supplier/supplier_dashboard.py @@ -9,7 +9,8 @@ def get_data(): 'heatmap_message': _('This is based on transactions against this Supplier. See timeline below for details'), 'fieldname': 'supplier', 'non_standard_fieldnames': { - 'Payment Entry': 'party_name' + 'Payment Entry': 'party_name', + 'Bank Account': 'party' }, 'transactions': [ { @@ -24,9 +25,13 @@ def get_data(): 'label': _('Payments'), 'items': ['Payment Entry'] }, + { + 'label': _('Bank'), + 'items': ['Bank Account'] + }, { 'label': _('Pricing'), 'items': ['Pricing Rule'] } ] - } + } \ No newline at end of file From 393a626834ad5b66ce152bd60371b66dab548a44 Mon Sep 17 00:00:00 2001 From: P-Froggy <60393001+P-Froggy@users.noreply.github.com> Date: Fri, 28 Feb 2020 20:45:48 +0100 Subject: [PATCH 08/26] fix: Allow only bank accounts of the respective party in payment entry --- erpnext/accounts/doctype/payment_entry/payment_entry.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js index 2192b7bf98..2aa999d07f 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.js +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js @@ -33,7 +33,9 @@ frappe.ui.form.on('Payment Entry', { frm.set_query("party_bank_account", function() { return { filters: { - "is_company_account":0 + "is_company_account":0, + party_type: frm.doc.party_type, + party: frm.doc.party } } }); From 266e689c4fbdee14cd1c86b4d49255ac52acaa94 Mon Sep 17 00:00:00 2001 From: P-Froggy <60393001+P-Froggy@users.noreply.github.com> Date: Fri, 28 Feb 2020 20:46:36 +0100 Subject: [PATCH 09/26] fix: Show swift number and branch code in quick entry of bank doctype --- erpnext/accounts/doctype/bank/bank.json | 32 +++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/erpnext/accounts/doctype/bank/bank.json b/erpnext/accounts/doctype/bank/bank.json index 7a628b5228..fca171d392 100644 --- a/erpnext/accounts/doctype/bank/bank.json +++ b/erpnext/accounts/doctype/bank/bank.json @@ -14,6 +14,11 @@ "swift_number", "column_break_1", "branch_code", + "address_and_contact", + "address_html", + "website", + "column_break_13", + "contact_html", "data_import_configuration_section", "bank_transaction_mapping", "section_break_4", @@ -33,6 +38,7 @@ "label": "Bank Details" }, { + "allow_in_quick_entry": 1, "fieldname": "swift_number", "fieldtype": "Data", "in_list_view": 1, @@ -47,6 +53,7 @@ "search_index": 1 }, { + "allow_in_quick_entry": 1, "fieldname": "branch_code", "fieldtype": "Data", "in_list_view": 1, @@ -55,6 +62,31 @@ "reqd": 0, "unique": 1 }, + { + "fieldname": "address_and_contact", + "fieldtype": "Section Break", + "label": "Address and Contact", + "options": "fa fa-map-marker" + }, + { + "fieldname": "address_html", + "fieldtype": "HTML", + "label": "Address HTML" + }, + { + "fieldname": "website", + "fieldtype": "Data", + "label": "Website" + }, + { + "fieldname": "column_break_13", + "fieldtype": "Column Break" + }, + { + "fieldname": "contact_html", + "fieldtype": "HTML", + "label": "Contact HTML" + }, { "collapsible": 1, "fieldname": "data_import_configuration_section", From 313efe9b32ddc04e7b18e11b78c12158d12521af Mon Sep 17 00:00:00 2001 From: P-Froggy <60393001+P-Froggy@users.noreply.github.com> Date: Mon, 2 Mar 2020 00:21:08 +0100 Subject: [PATCH 10/26] fix: add missing semicolon --- erpnext/accounts/doctype/bank/bank.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/bank/bank.js b/erpnext/accounts/doctype/bank/bank.js index 39f057913d..e21c77e9ca 100644 --- a/erpnext/accounts/doctype/bank/bank.js +++ b/erpnext/accounts/doctype/bank/bank.js @@ -8,7 +8,7 @@ frappe.ui.form.on('Bank', { refresh: function(frm) { add_fields_to_mapping_table(frm); - frappe.dynamic_link = { doc: frm.doc, fieldname: 'name', doctype: 'Bank' } + frappe.dynamic_link = { doc: frm.doc, fieldname: 'name', doctype: 'Bank' }; frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal); From 95e35f9e81f6d0277977cbd6b4c9fbf318eade7b Mon Sep 17 00:00:00 2001 From: Anupam K Date: Tue, 24 Mar 2020 11:52:34 +0530 Subject: [PATCH 11/26] Better error message --- erpnext/utilities/transaction_base.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/utilities/transaction_base.py b/erpnext/utilities/transaction_base.py index 2099810846..46db510569 100644 --- a/erpnext/utilities/transaction_base.py +++ b/erpnext/utilities/transaction_base.py @@ -123,8 +123,10 @@ class TransactionBase(StatusUpdater): ref_rate = frappe.db.get_value(ref_dt + " Item", d.get(ref_link_field), "rate") if abs(flt(d.rate - ref_rate, d.precision("rate"))) >= .01: - frappe.throw(_("Row #{0}: Rate must be same as {1}: {2} ({3} / {4}) ") + frappe.msgprint(_("Row #{0}: Rate must be same as {1}: {2} ({3} / {4}) ") .format(d.idx, ref_dt, d.get(ref_dn_field), d.rate, ref_rate)) + frappe.throw(_("To allow different rates, disable the {0} checkbox in {1}.") + .format"Maintain Same Rate Throughout Sales Cycle",(get_link_to_form("Selling Settings","Selling Settings","Selling Settings"))) def get_link_filters(self, for_doctype): if hasattr(self, "prev_link_mapper") and self.prev_link_mapper.get(for_doctype): From b14085eb0ee60c1aa78e9d4cb12362dba095283f Mon Sep 17 00:00:00 2001 From: Anupam K Date: Tue, 24 Mar 2020 12:17:28 +0530 Subject: [PATCH 12/26] Better error message --- erpnext/utilities/transaction_base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/utilities/transaction_base.py b/erpnext/utilities/transaction_base.py index 46db510569..c52c55b68e 100644 --- a/erpnext/utilities/transaction_base.py +++ b/erpnext/utilities/transaction_base.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import frappe import frappe.share from frappe import _ -from frappe.utils import cstr, now_datetime, cint, flt, get_time +from frappe.utils import cstr, now_datetime, cint, flt, get_time, get_link_to_form from erpnext.controllers.status_updater import StatusUpdater from six import string_types @@ -126,7 +126,7 @@ class TransactionBase(StatusUpdater): frappe.msgprint(_("Row #{0}: Rate must be same as {1}: {2} ({3} / {4}) ") .format(d.idx, ref_dt, d.get(ref_dn_field), d.rate, ref_rate)) frappe.throw(_("To allow different rates, disable the {0} checkbox in {1}.") - .format"Maintain Same Rate Throughout Sales Cycle",(get_link_to_form("Selling Settings","Selling Settings","Selling Settings"))) + .format("Maintain Same Rate Throughout Sales Cycle", get_link_to_form("Selling Settings","Selling Settings","Selling Settings"))) def get_link_filters(self, for_doctype): if hasattr(self, "prev_link_mapper") and self.prev_link_mapper.get(for_doctype): From 878e4fbcf869219e77d422756ad917cc5f29b010 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Wed, 25 Mar 2020 16:52:07 +0530 Subject: [PATCH 13/26] fix: Place of supply validation in GSTR-1 report --- erpnext/regional/report/gstr_1/gstr_1.py | 27 ++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py index 2c5ab7cb91..86f193d3f4 100644 --- a/erpnext/regional/report/gstr_1/gstr_1.py +++ b/erpnext/regional/report/gstr_1/gstr_1.py @@ -54,8 +54,8 @@ class Gstr1Report(object): return self.columns, self.data def get_data(self): - if self.filters.get("type_of_business") == "B2C Small": - self.get_b2cs_data() + if self.filters.get("type_of_business") in ("B2C Small", "B2C Large"): + self.get_b2c_data() else: for inv, items_based_on_rate in self.items_based_on_tax_rate.items(): invoice_details = self.invoices.get(inv) @@ -69,7 +69,7 @@ class Gstr1Report(object): if taxable_value: self.data.append(row) - def get_b2cs_data(self): + def get_b2c_data(self): b2cs_output = {} for inv, items_based_on_rate in self.items_based_on_tax_rate.items(): @@ -84,7 +84,10 @@ class Gstr1Report(object): "rate": "", "taxable_value": 0, "cess_amount": 0, - "type": "" + "type": "", + "invoice_number": invoice_details.get("invoice_number"), + "posting_date": invoice_details.get("posting_date"), + "invoice_value": invoice_details.get("base_grand_total"), }) row = b2cs_output.get((rate, place_of_supply, ecommerce_gstin)) @@ -139,7 +142,7 @@ class Gstr1Report(object): where docstatus = 1 {where_conditions} order by posting_date desc """.format(select_columns=self.select_columns, doctype=self.doctype, - where_conditions=conditions), self.filters, as_dict=1) + where_conditions=conditions), self.filters, as_dict=1, debug=1) for d in invoice_data: self.invoices.setdefault(d.invoice_number, d) @@ -164,7 +167,7 @@ class Gstr1Report(object): frappe.throw(_("Please set B2C Limit in GST Settings.")) if self.filters.get("type_of_business") == "B2C Large": - conditions += """ and SUBSTR(place_of_supply, 1, 2) != SUBSTR(company_gstin, 1, 2) + conditions += """ and ifnull(SUBSTR(place_of_supply, 1, 2),'') != ifnull(SUBSTR(company_gstin, 1, 2),'') and grand_total > {0} and is_return != 1 and gst_category ='Unregistered' """.format(flt(b2c_limit)) elif self.filters.get("type_of_business") == "B2C Small": @@ -581,6 +584,11 @@ def get_b2b_json(res, gstin): if not gst_in: continue for number, invoice in iteritems(res[gst_in]): + if not invoice[0]["place_of_supply"]: + frappe.throw(_("""{0} not entered in Invoice {1}. + Please update and try again""").format(frappe.bold("Place Of Supply"), + frappe.bold(invoice[0]['invoice_number']))) + inv_item = get_basic_invoice_detail(invoice[0]) inv_item["pos"] = "%02d" % int(invoice[0]["place_of_supply"].split('-')[0]) inv_item["rchrg"] = invoice[0]["reverse_charge"] @@ -606,6 +614,9 @@ def get_b2cs_json(data, gstin): out = [] for d in data: + if not d.get("place_of_supply"): + frappe.throw(_("""{0} not entered in some invoices. + Please update and try again""").format(frappe.bold("Place Of Supply"))) pos = d.get('place_of_supply').split('-')[0] tax_details = {} @@ -642,6 +653,10 @@ def get_b2cs_json(data, gstin): def get_b2cl_json(res, gstin): out = [] for pos in res: + if not pos: + frappe.throw(_("""{0} not entered in some invoices. + Please update and try again""").format(frappe.bold("Place Of Supply"))) + b2cl_item, inv = {"pos": "%02d" % int(pos.split('-')[0]), "inv": []}, [] for row in res[pos]: From 113c6c86b7c93b4618594c84eb0b719a90b0fb9a Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Wed, 25 Mar 2020 16:54:17 +0530 Subject: [PATCH 14/26] fix: Remove debug --- erpnext/regional/report/gstr_1/gstr_1.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py index 86f193d3f4..fd1cc58c20 100644 --- a/erpnext/regional/report/gstr_1/gstr_1.py +++ b/erpnext/regional/report/gstr_1/gstr_1.py @@ -142,7 +142,7 @@ class Gstr1Report(object): where docstatus = 1 {where_conditions} order by posting_date desc """.format(select_columns=self.select_columns, doctype=self.doctype, - where_conditions=conditions), self.filters, as_dict=1, debug=1) + where_conditions=conditions), self.filters, as_dict=1) for d in invoice_data: self.invoices.setdefault(d.invoice_number, d) From 10b7a51805c6cfcbf40674dcc24423726cf58ab3 Mon Sep 17 00:00:00 2001 From: Anupam K Date: Wed, 25 Mar 2020 18:21:42 +0530 Subject: [PATCH 15/26] Better error message --- erpnext/utilities/transaction_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/utilities/transaction_base.py b/erpnext/utilities/transaction_base.py index c52c55b68e..779af4a2b1 100644 --- a/erpnext/utilities/transaction_base.py +++ b/erpnext/utilities/transaction_base.py @@ -126,7 +126,7 @@ class TransactionBase(StatusUpdater): frappe.msgprint(_("Row #{0}: Rate must be same as {1}: {2} ({3} / {4}) ") .format(d.idx, ref_dt, d.get(ref_dn_field), d.rate, ref_rate)) frappe.throw(_("To allow different rates, disable the {0} checkbox in {1}.") - .format("Maintain Same Rate Throughout Sales Cycle", get_link_to_form("Selling Settings","Selling Settings","Selling Settings"))) + .format(frappe.bold("Maintain Same Rate Throughout Sales Cycle"), get_link_to_form("Selling Settings","Selling Settings",frappe.bold("Selling Settings")))) def get_link_filters(self, for_doctype): if hasattr(self, "prev_link_mapper") and self.prev_link_mapper.get(for_doctype): From bdcfab3a0fcd86c03250a6c5328191ca5cb2a226 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Wed, 25 Mar 2020 21:32:10 +0530 Subject: [PATCH 16/26] fix: Update patch and bank form cleanup --- erpnext/accounts/doctype/bank/bank.js | 2 ++ erpnext/accounts/doctype/bank/bank.json | 27 +++---------------- .../doctype/bank_account/bank_account.json | 2 +- .../move_bank_account_swift_number_to_bank.py | 16 ++++------- 4 files changed, 12 insertions(+), 35 deletions(-) diff --git a/erpnext/accounts/doctype/bank/bank.js b/erpnext/accounts/doctype/bank/bank.js index e21c77e9ca..de9498e075 100644 --- a/erpnext/accounts/doctype/bank/bank.js +++ b/erpnext/accounts/doctype/bank/bank.js @@ -13,9 +13,11 @@ frappe.ui.form.on('Bank', { frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal); if (frm.doc.__islocal) { + frm.set_df_property('address_and_contact', 'hidden', 1); frappe.contacts.clear_address_and_contact(frm); } else { + frm.set_df_property('address_and_contact', 'hidden', 0); frappe.contacts.render_address_and_contact(frm); } }, diff --git a/erpnext/accounts/doctype/bank/bank.json b/erpnext/accounts/doctype/bank/bank.json index fca171d392..99978e657d 100644 --- a/erpnext/accounts/doctype/bank/bank.json +++ b/erpnext/accounts/doctype/bank/bank.json @@ -9,14 +9,14 @@ "editable_grid": 1, "engine": "InnoDB", "field_order": [ - "bank_name", "bank_details_section", + "bank_name", "swift_number", "column_break_1", "branch_code", + "website", "address_and_contact", "address_html", - "website", "column_break_13", "contact_html", "data_import_configuration_section", @@ -44,7 +44,6 @@ "in_list_view": 1, "in_standard_filter": 1, "label": "SWIFT number", - "reqd": 0, "unique": 1 }, { @@ -59,7 +58,6 @@ "in_list_view": 1, "in_standard_filter": 1, "label": "Branch Code", - "reqd": 0, "unique": 1 }, { @@ -112,40 +110,23 @@ "read_only": 1 } ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2018-11-27 16:12:13.938776", + "links": [], + "modified": "2020-03-25 21:22:33.496264", "modified_by": "Administrator", "module": "Accounts", "name": "Bank", - "name_case": "", "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, "create": 1, "delete": 1, "email": 1, "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, "print": 1, "read": 1, "report": 1, "role": "System Manager", - "set_user_permissions": 0, "share": 1, - "submit": 0, "write": 1 } ], diff --git a/erpnext/accounts/doctype/bank_account/bank_account.json b/erpnext/accounts/doctype/bank_account/bank_account.json index ade379b11d..aa9c434db0 100644 --- a/erpnext/accounts/doctype/bank_account/bank_account.json +++ b/erpnext/accounts/doctype/bank_account/bank_account.json @@ -200,7 +200,7 @@ } ], "links": [], - "modified": "2020-01-29 20:42:26.458316", + "modified": "2020-01-30 20:42:26.458316", "modified_by": "Administrator", "module": "Accounts", "name": "Bank Account", diff --git a/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py b/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py index 2675b98480..4aad1420e3 100644 --- a/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py +++ b/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py @@ -4,17 +4,11 @@ import frappe def execute(): frappe.reload_doc('accounts', 'doctype', 'bank', force=1) - banks = frappe.get_all('Bank', 'name') - for bank in banks: - bank_accounts = frappe.get_all('Bank Account', filters={'bank': bank.name}, fields=['swift_number', 'branch_code']) - bank_account = '' - if len(bank_accounts): - bank_account = bank_accounts[0] - if bank_account and bank_account.swift_number: - bank.swift_number = bank_account.swift_number - if bank_account and bank_account.branch_code: - bank.branch_code = bank_account.branch_code - bank.save() + frappe.db.sql(""" + UPDATE `tabBank` b, `tabBank Account` ba + SET b.swift_number = ba.swift_number, b.branch_code = ba.branch_code + WHERE b.name = ba.bank + """) frappe.reload_doc('accounts', 'doctype', 'bank_account') frappe.reload_doc('accounts', 'doctype', 'payment_request') \ No newline at end of file From 9062ce5191064e76150fd15f364dca5a0f734fa7 Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Thu, 26 Mar 2020 11:56:03 +0530 Subject: [PATCH 17/26] fix: Spacing and indentations --- erpnext/utilities/transaction_base.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/utilities/transaction_base.py b/erpnext/utilities/transaction_base.py index 779af4a2b1..f88ffd44e3 100644 --- a/erpnext/utilities/transaction_base.py +++ b/erpnext/utilities/transaction_base.py @@ -126,7 +126,8 @@ class TransactionBase(StatusUpdater): frappe.msgprint(_("Row #{0}: Rate must be same as {1}: {2} ({3} / {4}) ") .format(d.idx, ref_dt, d.get(ref_dn_field), d.rate, ref_rate)) frappe.throw(_("To allow different rates, disable the {0} checkbox in {1}.") - .format(frappe.bold("Maintain Same Rate Throughout Sales Cycle"), get_link_to_form("Selling Settings","Selling Settings",frappe.bold("Selling Settings")))) + .format(frappe.bold("Maintain Same Rate Throughout Sales Cycle"), + get_link_to_form("Selling Settings", "Selling Settings", frappe.bold("Selling Settings")))) def get_link_filters(self, for_doctype): if hasattr(self, "prev_link_mapper") and self.prev_link_mapper.get(for_doctype): From ced6898fd72687827b3035f8aec8889b42759ff7 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 20 Mar 2020 12:23:18 +0530 Subject: [PATCH 18/26] fix: Ignored user permission for parent_company and existing_company field in Company --- erpnext/setup/doctype/company/company.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json index 84810b6824..020a93ff6a 100644 --- a/erpnext/setup/doctype/company/company.json +++ b/erpnext/setup/doctype/company/company.json @@ -157,6 +157,7 @@ { "fieldname": "parent_company", "fieldtype": "Link", + "ignore_user_permissions": 1, "in_list_view": 1, "label": "Parent Company", "options": "Company" @@ -277,6 +278,7 @@ "depends_on": "eval:doc.create_chart_of_accounts_based_on===\"Existing Company\"", "fieldname": "existing_company", "fieldtype": "Link", + "ignore_user_permissions": 1, "label": "Existing Company ", "no_copy": 1, "options": "Company" @@ -728,7 +730,7 @@ "image_field": "company_logo", "is_tree": 1, "links": [], - "modified": "2020-03-18 18:09:53.534211", + "modified": "2020-03-21 18:09:53.534211", "modified_by": "Administrator", "module": "Setup", "name": "Company", From 1aa8c2ecc4d14312248fc805101e6a92ce5801f6 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 26 Mar 2020 13:15:31 +0530 Subject: [PATCH 19/26] fix: delete contact email and phone along with contact --- erpnext/tests/utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/tests/utils.py b/erpnext/tests/utils.py index dfd3ed76bc..16ecd5180b 100644 --- a/erpnext/tests/utils.py +++ b/erpnext/tests/utils.py @@ -7,6 +7,8 @@ import frappe def create_test_contact_and_address(): frappe.db.sql('delete from tabContact') + frappe.db.sql('delete from `tabContact Email`') + frappe.db.sql('delete from `tabContact Phone`') frappe.db.sql('delete from tabAddress') frappe.db.sql('delete from `tabDynamic Link`') From faea85451f1f37c7ca0bdc87eb47e0cfabf56258 Mon Sep 17 00:00:00 2001 From: Saqib Date: Thu, 26 Mar 2020 13:18:57 +0530 Subject: [PATCH 20/26] feat: auto set batch no on serial no selection (#20757) * feat: auto set batch no on serial no selection * fix: dialog not shown if set warehouse selected * fix: typo * fix: merge conflict * fix: callback no getting called after serial no selected * fix: available batch qty not fetched without set_warehouse selected * fix: item batch not synced with dialog batch table --- erpnext/public/js/controllers/transaction.js | 15 +- .../js/utils/serial_no_batch_selector.js | 144 +++++++++++------- erpnext/selling/sales_common.js | 9 +- erpnext/stock/doctype/serial_no/serial_no.py | 11 +- 4 files changed, 119 insertions(+), 60 deletions(-) diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index fea2d5e700..1747932af6 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -4,7 +4,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ setup: function() { this._super(); - frappe.flags.hide_serial_batch_dialog = false; + frappe.flags.hide_serial_batch_dialog = true; frappe.ui.form.on(this.frm.doctype + " Item", "rate", function(frm, cdt, cdn) { var item = frappe.get_doc(cdt, cdn); var has_margin_field = frappe.meta.has_field(cdt, 'margin_type'); @@ -519,6 +519,15 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ } }, () => me.toggle_conversion_factor(item), + () => { + if (show_batch_dialog) + return frappe.db.get_value("Item", item.item_code, ["has_batch_no", "has_serial_no"]) + .then((r) => { + if(r.message.has_batch_no || r.message.has_serial_no) { + frappe.flags.hide_serial_batch_dialog = false; + } + }); + }, () => { if(show_batch_dialog && !frappe.flags.hide_serial_batch_dialog) { var d = locals[cdt][cdn]; @@ -528,7 +537,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ erpnext.show_serial_batch_selector(me.frm, d, (item) => { me.frm.script_manager.trigger('qty', item.doctype, item.name); - }); + if (!me.frm.doc.set_warehouse) + me.frm.script_manager.trigger('warehouse', item.doctype, item.name); + }, undefined, !frappe.flags.hide_serial_batch_dialog); } }, () => me.conversion_factor(doc, cdt, cdn, true), diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js index 02bced293f..d75633e5a9 100644 --- a/erpnext/public/js/utils/serial_no_batch_selector.js +++ b/erpnext/public/js/utils/serial_no_batch_selector.js @@ -5,14 +5,13 @@ erpnext.SerialNoBatchSelector = Class.extend({ this.show_dialog = show_dialog; // frm, item, warehouse_details, has_batch, oldest let d = this.item; - if (d && d.has_batch_no && (!d.batch_no || this.show_dialog)) { - this.has_batch = 1; - this.setup(); + this.has_batch = 0; this.has_serial_no = 0; + + if (d && d.has_batch_no && (!d.batch_no || this.show_dialog)) this.has_batch = 1; // !(this.show_dialog == false) ensures that show_dialog is implictly true, even when undefined - } else if(d && d.has_serial_no && !(this.show_dialog == false)) { - this.has_batch = 0; - this.setup(); - } + if(d && d.has_serial_no && !(this.show_dialog == false)) this.has_serial_no = 1; + + this.setup(); }, setup: function() { @@ -36,16 +35,16 @@ erpnext.SerialNoBatchSelector = Class.extend({ label: __('Item Code'), default: me.item_code }, - {fieldtype:'Column Break'}, { fieldname: 'warehouse', fieldtype:'Link', options: 'Warehouse', + reqd: me.has_batch && !me.has_serial_no ? 0 : 1, label: __(me.warehouse_details.type), - default: me.warehouse_details.name, + default: typeof me.warehouse_details.name == "string" ? me.warehouse_details.name : '', onchange: function(e) { - if(me.has_batch) { + if(me.has_batch && !me.has_serial_no) { fields = fields.concat(me.get_batch_fields()); } else { fields = fields.concat(me.get_serial_no_fields()); @@ -74,15 +73,16 @@ erpnext.SerialNoBatchSelector = Class.extend({ { fieldname: 'qty', fieldtype:'Float', - read_only: me.has_batch, - label: __(me.has_batch ? 'Total Qty' : 'Qty'), + read_only: me.has_batch && !me.has_serial_no, + label: __(me.has_batch && !me.has_serial_no ? 'Total Qty' : 'Qty'), default: 0 }, { fieldname: 'auto_fetch_button', fieldtype:'Button', - hidden: me.has_batch, - label: __('Fetch based on FIFO'), + hidden: me.has_batch && !me.has_serial_no, + label: __('Auto Fetch'), + description: __('Fetch Serial Numbers based on FIFO'), click: () => { let qty = this.dialog.fields_dict.qty.get_value(); let numbers = frappe.call({ @@ -90,7 +90,7 @@ erpnext.SerialNoBatchSelector = Class.extend({ args: { qty: qty, item_code: me.item_code, - warehouse: me.warehouse_details.name, + warehouse: typeof me.warehouse_details.name == "string" ? me.warehouse_details.name : '', batch_no: me.item.batch_no || null } }); @@ -109,10 +109,12 @@ erpnext.SerialNoBatchSelector = Class.extend({ } ]; - if (this.has_batch) { + if (this.has_batch && !this.has_serial_no) { title = __("Select Batch Numbers"); fields = fields.concat(this.get_batch_fields()); } else { + // if only serial no OR + // if both batch_no & serial_no then only select serial_no and auto set batches nos title = __("Select Serial Numbers"); fields = fields.concat(this.get_serial_no_fields()); } @@ -122,25 +124,31 @@ erpnext.SerialNoBatchSelector = Class.extend({ fields: fields }); - if (this.item.serial_no) { - this.dialog.fields_dict.serial_no.set_value(this.item.serial_no); - } - this.dialog.set_primary_action(__('Insert'), function() { me.values = me.dialog.get_values(); if(me.validate()) { - me.set_items(); - me.dialog.hide(); + frappe.run_serially([ + () => me.update_batch_items(), + () => me.update_serial_no_item(), + () => me.update_batch_serial_no_items(), + () => { + refresh_field("items"); + if (me.callback) { + return me.callback(me.item); + } + }, + () => me.dialog.hide() + ]) } }); if(this.show_dialog) { let d = this.item; - if (d.has_serial_no && d.serial_no) { - this.dialog.set_value('serial_no', d.serial_no); + if (this.item.serial_no) { + this.dialog.fields_dict.serial_no.set_value(this.item.serial_no); } - - if (d.has_batch_no && d.batch_no) { + + if (this.has_batch && !this.has_serial_no && d.batch_no) { this.frm.doc.items.forEach(data => { if(data.item_code == d.item_code) { this.dialog.fields_dict.batches.df.data.push({ @@ -155,7 +163,7 @@ erpnext.SerialNoBatchSelector = Class.extend({ } } - if (this.has_batch) { + if (this.has_batch && !this.has_serial_no) { this.update_total_qty(); } @@ -174,7 +182,7 @@ erpnext.SerialNoBatchSelector = Class.extend({ frappe.throw(__("Please select a warehouse")); return false; } - if(this.has_batch) { + if(this.has_batch && !this.has_serial_no) { if(values.batches.length === 0 || !values.batches) { frappe.throw(__("Please select batches for batched item " + values.item_code)); @@ -193,34 +201,23 @@ erpnext.SerialNoBatchSelector = Class.extend({ } else { let serial_nos = values.serial_no || ''; if (!serial_nos || !serial_nos.replace(/\s/g, '').length) { - if (!this.show_dialog) { - frappe.throw(__("Please enter serial numbers for serialized item " - + values.item_code)); - return false; - } + frappe.throw(__("Please enter serial numbers for serialized item " + + values.item_code)); + return false; } return true; } }, - set_items: function() { - var me = this; - if(this.has_batch) { + update_batch_items() { + // clones an items if muliple batches are selected. + if(this.has_batch && !this.has_serial_no) { this.values.batches.map((batch, i) => { let batch_no = batch.batch_no; let row = ''; if (i !== 0 && !this.batch_exists(batch_no)) { - row = this.frm.add_child("items", { - 'item_code': this.item.item_code, - 'item_name': this.item.item_name, - 'price_list_rate': this.item.price_list_rate, - 'rate': this.item.rate, - 'qty': batch.selected_qty, - 'batch_no': batch_no, - 'actual_qty': this.item.actual_qty, - 'discount_percentage': this.item.discount_percentage - }); + row = this.frm.add_child("items", { ...this.item }); } else { row = this.frm.doc.items.find(i => i.batch_no === batch_no); } @@ -228,16 +225,59 @@ erpnext.SerialNoBatchSelector = Class.extend({ if (!row) { row = this.item; } - + // this ensures that qty & batch no is set this.map_row_values(row, batch, 'batch_no', 'selected_qty', this.values.warehouse); }); - } else { + } + }, + + update_serial_no_item() { + // just updates serial no for the item + if(this.has_serial_no && !this.has_batch) { this.map_row_values(this.item, this.values, 'serial_no', 'qty'); } + }, - refresh_field("items"); - this.callback && this.callback(this.item); + update_batch_serial_no_items() { + // if serial no selected is from different batches, adds new rows for each batch. + if(this.has_batch && this.has_serial_no) { + const selected_serial_nos = this.values.serial_no.split(/\n/g).filter(s => s); + + return frappe.db.get_list("Serial No", { + filters: { 'name': ["in", selected_serial_nos]}, + fields: ["batch_no", "name"] + }).then((data) => { + // data = [{batch_no: 'batch-1', name: "SR-001"}, + // {batch_no: 'batch-2', name: "SR-003"}, {batch_no: 'batch-2', name: "SR-004"}] + const batch_serial_map = data.reduce((acc, d) => { + if (!acc[d['batch_no']]) acc[d['batch_no']] = []; + acc[d['batch_no']].push(d['name']) + return acc + }, {}) + // batch_serial_map = { "batch-1": ['SR-001'], "batch-2": ["SR-003", "SR-004"]} + Object.keys(batch_serial_map).map((batch_no, i) => { + let row = ''; + const serial_no = batch_serial_map[batch_no]; + if (i == 0) { + row = this.item; + this.map_row_values(row, {qty: serial_no.length, batch_no: batch_no}, 'batch_no', + 'qty', this.values.warehouse); + } else if (!this.batch_exists(batch_no)) { + row = this.frm.add_child("items", { ...this.item }); + row.batch_no = batch_no; + } else { + row = this.frm.doc.items.find(i => i.batch_no === batch_no); + } + const values = { + 'qty': serial_no.length, + 'serial_no': serial_no.join('\n') + } + this.map_row_values(row, values, 'serial_no', + 'qty', this.values.warehouse); + }); + }) + } }, batch_exists: function(batch) { @@ -287,7 +327,7 @@ erpnext.SerialNoBatchSelector = Class.extend({ return { filters: { item_code: me.item_code, - warehouse: me.warehouse || me.warehouse_details.name + warehouse: me.warehouse || typeof me.warehouse_details.name == "string" ? me.warehouse_details.name : '' }, query: 'erpnext.controllers.queries.get_batch_no' }; @@ -448,7 +488,7 @@ erpnext.SerialNoBatchSelector = Class.extend({ { fieldname: 'serial_no', fieldtype: 'Small Text', - label: __(me.has_batch ? 'Selected Batch Numbers' : 'Selected Serial Numbers'), + label: __(me.has_batch && !me.has_serial_no ? 'Selected Batch Numbers' : 'Selected Serial Numbers'), onchange: function() { me.serial_list = this.get_value() .replace(/\n/g, ' ').match(/\S+/g) || []; diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js index 8278745a80..af100692c6 100644 --- a/erpnext/selling/sales_common.js +++ b/erpnext/selling/sales_common.js @@ -413,15 +413,20 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ */ set_batch_number: function(cdt, cdn) { const doc = frappe.get_doc(cdt, cdn); - if (doc && doc.has_batch_no) { + if (doc && doc.has_batch_no && doc.warehouse) { this._set_batch_number(doc); } }, _set_batch_number: function(doc) { + let args = {'item_code': doc.item_code, 'warehouse': doc.warehouse, 'qty': flt(doc.qty) * flt(doc.conversion_factor)}; + if (doc.has_serial_no && doc.serial_no) { + args['serial_no'] = doc.serial_no + } + return frappe.call({ method: 'erpnext.stock.doctype.batch.batch.get_batch_no', - args: {'item_code': doc.item_code, 'warehouse': doc.warehouse, 'qty': flt(doc.qty) * flt(doc.conversion_factor)}, + args: args, callback: function(r) { if(r.message) { frappe.model.set_value(doc.doctype, doc.name, 'batch_no', r.message); diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py index 64d4c6c082..772ac58af6 100644 --- a/erpnext/stock/doctype/serial_no/serial_no.py +++ b/erpnext/stock/doctype/serial_no/serial_no.py @@ -523,12 +523,15 @@ def get_delivery_note_serial_no(item_code, qty, delivery_note): return serial_nos @frappe.whitelist() -def auto_fetch_serial_number(qty, item_code, warehouse, batch_no=None): - serial_numbers = frappe.get_list("Serial No", filters={ +def auto_fetch_serial_number(qty, item_code, warehouse, batch_nos=None): + import json + filters = { "item_code": item_code, "warehouse": warehouse, - "batch_no": batch_no, "delivery_document_no": "", "sales_invoice": "" - }, limit=qty, order_by="creation") + } + if batch_nos: filters["batch_no"] = ["in", json.loads(batch_nos)] + + serial_numbers = frappe.get_list("Serial No", filters=filters, limit=qty, order_by="creation") return [item['name'] for item in serial_numbers] From 74864b3b6117ce7e52dcd841d71f6624182e53e8 Mon Sep 17 00:00:00 2001 From: Saqib Date: Thu, 26 Mar 2020 13:20:31 +0530 Subject: [PATCH 21/26] fix: currency not fetched on quotation creation (#20996) --- erpnext/selling/doctype/customer/customer.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py index 6571ecb404..02667e8c23 100644 --- a/erpnext/selling/doctype/customer/customer.py +++ b/erpnext/selling/doctype/customer/customer.py @@ -268,9 +268,11 @@ def make_quotation(source_name, target_doc=None): target_doc.run_method("set_other_charges") target_doc.run_method("calculate_taxes_and_totals") - price_list = frappe.get_value("Customer", source_name, 'default_price_list') + price_list, currency = frappe.db.get_value("Customer", {'name': source_name}, ['default_price_list', 'default_currency']) if price_list: target_doc.selling_price_list = price_list + if currency: + target_doc.currency = currency return target_doc From b856aae651cfd3832cbd980bb689243494660399 Mon Sep 17 00:00:00 2001 From: Marica Date: Thu, 26 Mar 2020 13:23:49 +0530 Subject: [PATCH 22/26] fix: Project field in Stock Entry Detail should be editable (#20999) --- .../doctype/stock_entry_detail/stock_entry_detail.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json index d86e68b722..a848c80cf2 100644 --- a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json +++ b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json @@ -1,4 +1,5 @@ { + "actions": [], "autoname": "hash", "creation": "2013-03-29 18:22:12", "doctype": "DocType", @@ -479,8 +480,7 @@ "fieldname": "project", "fieldtype": "Link", "label": "Project", - "options": "Project", - "read_only": 1 + "options": "Project" }, { "fieldname": "po_detail", @@ -494,7 +494,8 @@ ], "idx": 1, "istable": 1, - "modified": "2019-08-20 14:01:02.319754", + "links": [], + "modified": "2020-03-19 12:34:09.836295", "modified_by": "Administrator", "module": "Stock", "name": "Stock Entry Detail", From 89cac5af16cefa7ab0c570ea8e5ca0ddf8a29ee5 Mon Sep 17 00:00:00 2001 From: Raffael Meyer Date: Thu, 26 Mar 2020 08:55:58 +0100 Subject: [PATCH 23/26] fix(regional): encoding of DATEV report (#21059) --- erpnext/regional/report/datev/datev.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py index 7ceaf50134..e9b42356a2 100644 --- a/erpnext/regional/report/datev/datev.py +++ b/erpnext/regional/report/datev/datev.py @@ -109,7 +109,7 @@ def get_transactions(filters, as_dict=1): WHERE gl.company = %(company)s AND DATE(gl.posting_date) >= %(from_date)s AND DATE(gl.posting_date) <= %(to_date)s - ORDER BY 'Belegdatum', gl.voucher_no""", filters, as_dict=as_dict, as_utf8=1) + ORDER BY 'Belegdatum', gl.voucher_no""", filters, as_dict=as_dict) return gl_entries @@ -160,7 +160,7 @@ def get_customers(filters): and ccl.company = par.company WHERE par.company = %(company)s - AND par.parenttype = 'Customer'""", filters, as_dict=1, as_utf8=1) + AND par.parenttype = 'Customer'""", filters, as_dict=1) def get_suppliers(filters): @@ -217,7 +217,7 @@ def get_suppliers(filters): and con.is_primary_contact = '1' WHERE par.company = %(company)s - AND par.parenttype = 'Supplier'""", filters, as_dict=1, as_utf8=1) + AND par.parenttype = 'Supplier'""", filters, as_dict=1) def get_account_names(filters): From 38cba153b5f1cb6011e2067dceb2200b11e8c244 Mon Sep 17 00:00:00 2001 From: Marica Date: Thu, 26 Mar 2020 13:29:02 +0530 Subject: [PATCH 24/26] fix: Make shelf life mandatory in Batched Item if it has expiry date (#21044) --- erpnext/stock/doctype/batch/batch.py | 7 +++++-- erpnext/stock/doctype/item/item.json | 5 +++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/erpnext/stock/doctype/batch/batch.py b/erpnext/stock/doctype/batch/batch.py index 8ae978eaf0..9b7249e66b 100644 --- a/erpnext/stock/doctype/batch/batch.py +++ b/erpnext/stock/doctype/batch/batch.py @@ -122,8 +122,11 @@ class Batch(Document): self.expiry_date = add_days(self.manufacturing_date, shelf_life_in_days) if has_expiry_date and not self.expiry_date: - frappe.msgprint(_('Expiry date is mandatory for selected item.')) - frappe.throw(_("Set item's shelf life in days, to set expiry based on manufacturing date plus shelf-life.")) + frappe.throw(msg=_("Please set {0} for Batched Item {1}, which is used to set {2} on Submit.") \ + .format(frappe.bold("Shelf Life in Days"), + frappe.utils.get_link_to_form("Item", self.item), + frappe.bold("Batch Expiry Date")), + title=_("Expiry Date Mandatory")) def get_name_from_naming_series(self): """ diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json index 3503e7cc1c..aa6b2fedd7 100644 --- a/erpnext/stock/doctype/item/item.json +++ b/erpnext/stock/doctype/item/item.json @@ -343,7 +343,8 @@ { "fieldname": "shelf_life_in_days", "fieldtype": "Int", - "label": "Shelf Life In Days" + "label": "Shelf Life In Days", + "mandatory_depends_on": "eval:doc.has_batch_no && doc.has_expiry_date" }, { "default": "2099-12-31", @@ -1045,7 +1046,7 @@ "image_field": "image", "links": [], "max_attachments": 1, - "modified": "2020-01-02 19:13:59.295963", + "modified": "2020-03-24 16:14:36.950677", "modified_by": "Administrator", "module": "Stock", "name": "Item", From fafba10219d88d58735744da3a8d83d7b11418cf Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 26 Mar 2020 13:36:40 +0530 Subject: [PATCH 25/26] fix: Ignored user permission for parent_company and existing_company field in Company (#21009) From d74bcad7afc3869126f18a2fe6ef779fcf93b57c Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Thu, 26 Mar 2020 13:37:40 +0530 Subject: [PATCH 26/26] fix: Added hidden GL column in general ledger (#21021) Co-authored-by: Nabin Hait --- erpnext/accounts/report/general_ledger/general_ledger.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index 8750c2325d..898ac13e0e 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -131,7 +131,7 @@ def get_gl_entries(filters): gl_entries = frappe.db.sql( """ select - posting_date, account, party_type, party, + name as gl_entry, posting_date, account, party_type, party, voucher_type, voucher_no, cost_center, project, against_voucher_type, against_voucher, account_currency, remarks, against, is_opening {select_fields} @@ -362,6 +362,12 @@ def get_columns(filters): currency = get_company_currency(company) columns = [ + { + "fieldname": "gl_entry", + "fieldtype": "Link", + "options": "GL Entry", + "hidden": 1 + }, { "label": _("Posting Date"), "fieldname": "posting_date",