From f5a1bea189bc177a6cc8d88801c1d0aad1661d0b Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Wed, 1 May 2019 18:46:30 +0530 Subject: [PATCH 01/41] feat: create payment order from payment entry --- .../doctype/payment_entry/payment_entry.py | 20 +++++++++++++++++++ .../doctype/payment_order/payment_order.js | 19 ++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 9033f659e7..928d9a02dc 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -967,3 +967,23 @@ def get_party_and_account_balance(company, date, paid_from=None, paid_to=None, p "paid_from_account_balance": get_balance_on(paid_from, date, cost_center=cost_center), "paid_to_account_balance": get_balance_on(paid_to, date=date, cost_center=cost_center) }) + +@frappe.whitelist() +def make_payment_order(source_name, target_doc=None): + def set_missing_values(source, target): + target.append('references', { + 'amount': source.base_paid_amount, + 'supplier': source.party, + 'payment_request': source_name, + 'mode_of_payment': source.mode_of_payment, + 'bank_account': source.bank_account, + 'account': source.account + }) + + doclist = get_mapped_doc("Payment Request", source_name, { + "Payment Request": { + "doctype": "Payment Order", + } + }, target_doc, set_missing_values) + + return doclist diff --git a/erpnext/accounts/doctype/payment_order/payment_order.js b/erpnext/accounts/doctype/payment_order/payment_order.js index 10e199580b..5b4f9fbd1a 100644 --- a/erpnext/accounts/doctype/payment_order/payment_order.js +++ b/erpnext/accounts/doctype/payment_order/payment_order.js @@ -7,6 +7,9 @@ frappe.ui.form.on('Payment Order', { frm.add_custom_button(__('Payment Request'), function() { frm.trigger("get_from_payment_request"); }, __("Get from")); + frm.add_custom_button(__('Payment Entry'), function() { + frm.trigger("get_from_payment_entry"); + }, __("Get from")); } // payment Entry @@ -18,6 +21,22 @@ frappe.ui.form.on('Payment Order', { } }, + get_from_payment_entry: function(frm) { + erpnext.utils.map_current_doc({ + method: "erpnext.accounts.doctype.payment_entry.payment_entry.make_payment_order", + source_doctype: "Payment Entry", + target: frm, + date_field: "posting_date", + setters: { + party: frm.doc.supplier || "" + }, + get_query_filters: { + bank: frm.doc.bank, + docstatus: 1, + } + }); + }, + get_from_payment_request: function(frm) { erpnext.utils.map_current_doc({ method: "erpnext.accounts.doctype.payment_request.payment_request.make_payment_order", From 0faf9f5f8c1fca976fc91aaa9ca78c451c2ca3f4 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Fri, 3 May 2019 21:18:24 +0530 Subject: [PATCH 02/41] feat: add mapping logic for creating payment order --- .../doctype/payment_entry/payment_entry.py | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 928d9a02dc..2c56dc40ed 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -970,20 +970,28 @@ def get_party_and_account_balance(company, date, paid_from=None, paid_to=None, p @frappe.whitelist() def make_payment_order(source_name, target_doc=None): + from frappe.model.mapper import get_mapped_doc def set_missing_values(source, target): - target.append('references', { - 'amount': source.base_paid_amount, - 'supplier': source.party, - 'payment_request': source_name, - 'mode_of_payment': source.mode_of_payment, - 'bank_account': source.bank_account, - 'account': source.account - }) + pass - doclist = get_mapped_doc("Payment Request", source_name, { - "Payment Request": { + def update_item(source_doc, target_doc, source_parent): + target_doc.bank_account = source_parent.bank_account + target_doc.amount = source_parent.base_paid_amount + target_doc.account = source_parent.paid_to or source_parent.paid_from + target_doc.payment_entry = source_doc.name + target_doc.supplier = source_doc.party + target_doc.mode_of_payment = source_doc.mode_of_payment + + + doclist = get_mapped_doc("Payment Entry", source_name, { + "Payment Entry": { "doctype": "Payment Order", - } + }, + "Payment Entry Reference": { + "doctype": "Payment Order Reference", + "postprocess": update_item + }, + }, target_doc, set_missing_values) return doclist From 48d88b047805353a4ee5f6ce0b3578c0774c254b Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Fri, 3 May 2019 21:19:02 +0530 Subject: [PATCH 03/41] feat: add generate txt file button for india region --- .../doctype/payment_order/regional/india.js | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 erpnext/accounts/doctype/payment_order/regional/india.js diff --git a/erpnext/accounts/doctype/payment_order/regional/india.js b/erpnext/accounts/doctype/payment_order/regional/india.js new file mode 100644 index 0000000000..6971cb6b32 --- /dev/null +++ b/erpnext/accounts/doctype/payment_order/regional/india.js @@ -0,0 +1,22 @@ +frappe.ui.form.on('Payment Order', { + refresh: function(frm) { + if (frm.doc.docstatus==1) { + frm.add_custom_button(__('Generate Text File'), + function() { + frm.trigger("generate_text_and_download_file"); + }); + } + }, + generate_text_and_download_file: (frm) => { + return frappe.call({ + method: "erpnext.regional.india.bank_remittance_txt.generate_report_and_get_url", + args: { + name: this.frm.name, + }, + freeze: true, + callback: function(r) { + frm.refresh(); + } + }); + } +}); \ No newline at end of file From e56eaf6364ac592bb1e1393dbb21e88e4afbed04 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Fri, 3 May 2019 21:19:59 +0530 Subject: [PATCH 04/41] perf: improve mapping function speed --- erpnext/accounts/doctype/payment_request/payment_request.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py index 64c4124da6..9b0ef42b8e 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.py +++ b/erpnext/accounts/doctype/payment_request/payment_request.py @@ -14,7 +14,6 @@ from frappe.integrations.utils import get_payment_gateway_controller from frappe.utils.background_jobs import enqueue from erpnext.erpnext_integrations.stripe_integration import create_stripe_subscription from erpnext.accounts.doctype.subscription_plan.subscription_plan import get_plan_rate -from frappe.model.mapper import get_mapped_doc class PaymentRequest(Document): def validate(self): @@ -426,6 +425,7 @@ def get_subscription_details(reference_doctype, reference_name): @frappe.whitelist() def make_payment_order(source_name, target_doc=None): + from frappe.model.mapper import get_mapped_doc def set_missing_values(source, target): target.append('references', { 'reference_doctype': source.reference_doctype, @@ -444,4 +444,4 @@ def make_payment_order(source_name, target_doc=None): } }, target_doc, set_missing_values) - return doclist + return doclist \ No newline at end of file From 07a5471dd2c3588c901b352b98039ef6d144f544 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Fri, 3 May 2019 21:20:42 +0530 Subject: [PATCH 05/41] feat: add payment entry field --- .../payment_order_reference.json | 523 ++++-------------- 1 file changed, 106 insertions(+), 417 deletions(-) diff --git a/erpnext/accounts/doctype/payment_order_reference/payment_order_reference.json b/erpnext/accounts/doctype/payment_order_reference/payment_order_reference.json index 0d01281730..1eeb5e9d31 100644 --- a/erpnext/accounts/doctype/payment_order_reference/payment_order_reference.json +++ b/erpnext/accounts/doctype/payment_order_reference/payment_order_reference.json @@ -1,433 +1,122 @@ { - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "beta": 0, - "creation": "2018-07-20 16:38:06.630813", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", + "creation": "2018-07-20 16:38:06.630813", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "reference_doctype", + "reference_name", + "amount", + "column_break_4", + "supplier", + "payment_request", + "payment_entry", + "mode_of_payment", + "bank_account_details", + "bank_account", + "column_break_10", + "account", + "payment_reference" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "reference_doctype", - "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": 0, - "label": "Type", - "length": 0, - "no_copy": 0, - "options": "DocType", - "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": "reference_doctype", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Type", + "options": "DocType", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "reference_name", - "fieldtype": "Dynamic 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": 0, - "label": "Name", - "length": 0, - "no_copy": 0, - "options": "reference_doctype", - "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": "reference_name", + "fieldtype": "Dynamic Link", + "in_list_view": 1, + "label": "Name", + "options": "reference_doctype", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "amount", - "fieldtype": "Currency", - "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": "Amount", - "length": 0, - "no_copy": 0, - "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": "amount", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Amount", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_4", - "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, - "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_4", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "supplier", - "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": 1, - "label": "Supplier", - "length": 0, - "no_copy": 0, - "options": "Supplier", - "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": "supplier", + "fieldtype": "Link", + "in_standard_filter": 1, + "label": "Supplier", + "options": "Supplier", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "payment_request", - "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": "Payment Request", - "length": 0, - "no_copy": 0, - "options": "Payment Request", - "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": "payment_request", + "fieldtype": "Link", + "label": "Payment Request", + "options": "Payment Request", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "payment_request.mode_of_payment", - "fieldname": "mode_of_payment", - "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": "Mode of Payment", - "length": 0, - "no_copy": 0, - "options": "Mode of Payment", - "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 - }, + "fetch_from": "payment_request.mode_of_payment", + "fieldname": "mode_of_payment", + "fieldtype": "Link", + "label": "Mode of Payment", + "options": "Mode of Payment", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "bank_account_details", - "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": "Bank Account Details", - "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_account_details", + "fieldtype": "Section Break", + "label": "Bank Account Details" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "bank_account", - "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": "Bank Account", - "length": 0, - "no_copy": 0, - "options": "Bank Account", - "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": "bank_account", + "fieldtype": "Link", + "label": "Bank Account", + "options": "Bank Account", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_10", - "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, - "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_10", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "account", - "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": "Account", - "length": 0, - "no_copy": 0, - "options": "Account", - "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": "account", + "fieldtype": "Link", + "label": "Account", + "options": "Account", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "payment_reference", - "fieldtype": "Data", - "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": "Payment Reference", - "length": 0, - "no_copy": 1, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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": "payment_reference", + "fieldtype": "Data", + "label": "Payment Reference", + "no_copy": 1, + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "payment_entry", + "fieldtype": "Link", + "label": "Payment Entry", + "options": "Payment Entry", + "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": 1, - "max_attachments": 0, - "modified": "2018-07-31 17:21:37.698644", - "modified_by": "Administrator", - "module": "Accounts", - "name": "Payment Order Reference", - "name_case": "", - "owner": "Administrator", - "permissions": [], - "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 + ], + "istable": 1, + "modified": "2019-05-03 17:28:01.648394", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Payment Order Reference", + "owner": "Administrator", + "permissions": [], + "quick_entry": 1, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 } \ No newline at end of file From b89db7f5a812aa3bb9c9b133baf6300608c1865e Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Fri, 3 May 2019 21:21:37 +0530 Subject: [PATCH 06/41] feat: add logic to generate txt file --- erpnext/regional/india/bank_remittance_txt.py | 133 ++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 erpnext/regional/india/bank_remittance_txt.py diff --git a/erpnext/regional/india/bank_remittance_txt.py b/erpnext/regional/india/bank_remittance_txt.py new file mode 100644 index 0000000000..7c4995e9f1 --- /dev/null +++ b/erpnext/regional/india/bank_remittance_txt.py @@ -0,0 +1,133 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2018, Frappe and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe +from frappe.model.document import Document +from frappe.utils import cint,cstr, today +from functools import reduce +import re +import datetime +from collections import OrderedDict + +def create_bank_remittance_txt(name): + payment_order = frappe.get_doc("Payment Order", name) + + no_of_records = len(payment_order.get("references")) + total_amount = reduce(lambda x, y: x.get("amount") + y.get("amount"), payment_order.get("references")) + + header = get_header_row(payment_order) + batch = get_batch_row(payment_order, no_of_records, total_amount) + + detail = [] + for ref_doc in payment_order.get("references"): + detail.append(get_detail_row(ref_doc, format_date(doc.posting_date)) + + trailer = get_trailer_row(no_of_records, total_amount) + + detail_records = "\n".join(detail) + + return "~".join([header, batch , detail_records, trailer]) + +@frappe.whitelist() +def generate_report_and_get_url(name): + data = create_bank_remittance_txt(name) + file_name = generate_file_name(name) + f = frappe.get_doc({ + 'doctype': 'File', + 'file_name': file_name+'.txt', + 'content': data, + 'is_private': True + }) + f.save() + +def generate_file_name(name): + ''' generate file name with format (account_code)_mmdd_(payment_order_no) ''' + return name + +def get_header_row(doc): + client_code = "ELECTROLAB" + file_name = generate_file_name(doc.name) + header = ["H"] + header.append(cstr(client_code)[:20]) + header += [''] * 3 + header.append(cstr(file_name)[:20]) + return "~".join(header) + +def get_batch_row(doc, no_of_records, total_amount): + product_code = "VENPAY" + batch = ["B"] + batch.append(cstr(no_of_records)[:5]) # 5 + batch.append(cstr(total_amount)[:17]) #amt 17.2 + batch.append(sanitize_to_alphanumeric(doc.name)[:20]) + batch.append(format_date(doc.posting_date)) + batch.append(product_code[:20]) + return "~".join(batch) + +def get_detail_row(ref_doc, payment_date): + payment_entry = frappe.get_cached_doc('Payment Entry', ref_doc.payment_entry) + supplier_bank_details = frappe.get_cached_doc('Bank Account', ref_doc.bank_account) + addr_link = frappe.db.get_value('Dynamic Link', + { + 'link_doctype': 'Supplier', + 'link_name': 'Sample Supplier', + 'parenttype':'Address', + 'parent': ('like', '%-Billing') + },'parent') + supplier_billing_address = frappe.get_doc('Address', addr_link) + detail = OrderedDict( + record_identifier='D', + payment_ref_no=sanitize_to_alphanumeric(ref_doc.payment_entry), + payment_type=ref_doc.mode_of_payment[:10], + amount=str(ref_doc.amount)[:13], + payment_date=payment_date, + instrument_date=payment_date, + instrument_number='', + dr_account_no_client=str(payment_entry.bank_account_no)[:20], + dr_description='', + dr_ref_no='', + cr_ref_no='', + bank_code_indicator='M', + beneficiary_code='', + beneficiary_name=sanitize_to_alphanumeric(payment_entry.party)[:160], + beneficiary_bank=sanitize_to_alphanumeric(supplier_bank_details.bank)[:10], + beneficiary_branch_ifsc_code=supplier_bank_details.branch_code, + beneficiary_acc_no=supplier_bank_details.bank_account_no, + location=supplier_billing_address.city, + print_location=supplier_billing_address.city, + beneficiary_address_1=supplier_billing_address.address_line1, + beneficiary_address_2=supplier_billing_address.address_line2, + beneficiary_address_3='', + beneficiary_address_4='', + beneficiary_address_5='', + beneficiary_city=supplier_billing_address.address_line1, + beneficiary_zipcode=supplier_billing_address.pincode, + beneficiary_state=supplier_billing_address.state, + beneficiary_email=supplier_billing_address.email_address, + beneficiary_mobile=supplier_billing_address.phone, + payment_details_1='', + payment_details_2='', + payment_details_3='', + payment_details_4='', + delivery_mode='' + ) + return "~".join(list(detail.values())) + +def get_advice_row(doc): + advice = ['A'] + +def get_trailer_row(no_of_records, total_amount): + trailer = ["T"] + trailer.append(cstr(no_of_records)[:5]) # 5 + trailer.append(cstr(total_amount)[:17]) # 17.2 + return "~".join(trailer) + +def sanitize_to_alphanumeric(val): + ''' Remove all the non-alphanumeric characters from string ''' + pattern = pattern = re.compile('[\W_]+') + return pattern.sub(' ', val) + +def format_date(val): + ''' Convert a datetime object to DD/MM/YYYY format ''' + return val.strftime("%d/%m/%Y") \ No newline at end of file From 6bc48b8bfb700a38ec38e78b1844e33bbec9e63e Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Sun, 5 May 2019 20:43:48 +0530 Subject: [PATCH 07/41] fix: pass account paid information to postprocess --- erpnext/accounts/doctype/payment_entry/payment_entry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 2c56dc40ed..d50ed95f6a 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -977,7 +977,7 @@ def make_payment_order(source_name, target_doc=None): def update_item(source_doc, target_doc, source_parent): target_doc.bank_account = source_parent.bank_account target_doc.amount = source_parent.base_paid_amount - target_doc.account = source_parent.paid_to or source_parent.paid_from + target_doc.account = source_parent.paid_to target_doc.payment_entry = source_doc.name target_doc.supplier = source_doc.party target_doc.mode_of_payment = source_doc.mode_of_payment From 08a375beb8ef1e2d77542ea332c86c32182cb818 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Sun, 5 May 2019 20:45:21 +0530 Subject: [PATCH 08/41] feat: add advice row --- .../doctype/payment_order/regional/india.js | 4 +- erpnext/regional/india/bank_remittance_txt.py | 47 +++++++++++++------ 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/erpnext/accounts/doctype/payment_order/regional/india.js b/erpnext/accounts/doctype/payment_order/regional/india.js index 6971cb6b32..e92145c071 100644 --- a/erpnext/accounts/doctype/payment_order/regional/india.js +++ b/erpnext/accounts/doctype/payment_order/regional/india.js @@ -9,9 +9,9 @@ frappe.ui.form.on('Payment Order', { }, generate_text_and_download_file: (frm) => { return frappe.call({ - method: "erpnext.regional.india.bank_remittance_txt.generate_report_and_get_url", + method: "erpnext.regional.india.bank_remittance_txt.generate_report", args: { - name: this.frm.name, + name: frm.doc.name, }, freeze: true, callback: function(r) { diff --git a/erpnext/regional/india/bank_remittance_txt.py b/erpnext/regional/india/bank_remittance_txt.py index 7c4995e9f1..83f49fed3a 100644 --- a/erpnext/regional/india/bank_remittance_txt.py +++ b/erpnext/regional/india/bank_remittance_txt.py @@ -10,6 +10,7 @@ from functools import reduce import re import datetime from collections import OrderedDict +from frappe.core.doctype.file.file import download_file def create_bank_remittance_txt(name): payment_order = frappe.get_doc("Payment Order", name) @@ -22,25 +23,27 @@ def create_bank_remittance_txt(name): detail = [] for ref_doc in payment_order.get("references"): - detail.append(get_detail_row(ref_doc, format_date(doc.posting_date)) + detail += get_detail_row(ref_doc, format_date(payment_order.posting_date)) trailer = get_trailer_row(no_of_records, total_amount) - detail_records = "\n".join(detail) - return "~".join([header, batch , detail_records, trailer]) + return "\n".join([header, batch , detail_records, trailer]) @frappe.whitelist() -def generate_report_and_get_url(name): +def generate_report(name): data = create_bank_remittance_txt(name) file_name = generate_file_name(name) f = frappe.get_doc({ 'doctype': 'File', 'file_name': file_name+'.txt', 'content': data, + "attached_to_doctype": 'Payment Order', + "attached_to_name": name, 'is_private': True }) f.save() + download_file(f.file_url) def generate_file_name(name): ''' generate file name with format (account_code)_mmdd_(payment_order_no) ''' @@ -79,7 +82,7 @@ def get_detail_row(ref_doc, payment_date): detail = OrderedDict( record_identifier='D', payment_ref_no=sanitize_to_alphanumeric(ref_doc.payment_entry), - payment_type=ref_doc.mode_of_payment[:10], + payment_type=cstr(payment_entry.mode_of_payment)[:10], amount=str(ref_doc.amount)[:13], payment_date=payment_date, instrument_date=payment_date, @@ -92,19 +95,19 @@ def get_detail_row(ref_doc, payment_date): beneficiary_code='', beneficiary_name=sanitize_to_alphanumeric(payment_entry.party)[:160], beneficiary_bank=sanitize_to_alphanumeric(supplier_bank_details.bank)[:10], - beneficiary_branch_ifsc_code=supplier_bank_details.branch_code, + beneficiary_branch_code=cstr(supplier_bank_details.branch_code), beneficiary_acc_no=supplier_bank_details.bank_account_no, location=supplier_billing_address.city, print_location=supplier_billing_address.city, - beneficiary_address_1=supplier_billing_address.address_line1, - beneficiary_address_2=supplier_billing_address.address_line2, + beneficiary_address_1=cstr(supplier_billing_address.address_line1)[:50], + beneficiary_address_2=cstr(supplier_billing_address.address_line2)[:50], beneficiary_address_3='', beneficiary_address_4='', beneficiary_address_5='', - beneficiary_city=supplier_billing_address.address_line1, - beneficiary_zipcode=supplier_billing_address.pincode, + beneficiary_city=supplier_billing_address.city, + beneficiary_zipcode=cstr(supplier_billing_address.pincode), beneficiary_state=supplier_billing_address.state, - beneficiary_email=supplier_billing_address.email_address, + beneficiary_email=supplier_billing_address.email_id, beneficiary_mobile=supplier_billing_address.phone, payment_details_1='', payment_details_2='', @@ -112,10 +115,26 @@ def get_detail_row(ref_doc, payment_date): payment_details_4='', delivery_mode='' ) - return "~".join(list(detail.values())) + detail_record = ["~".join(list(detail.values()))] + detail_record += get_advice_rows(payment_entry) + return detail_record -def get_advice_row(doc): - advice = ['A'] +def get_advice_rows(payment_entry): + payment_entry_date = payment_entry.posting_date.strftime("%b%y%d%m").upper() + mode_of_payment = payment_entry.mode_of_payment + advice_rows = [] + for record in payment_entry.references: + advice = ['E'] + advice.append(cstr(mode_of_payment)) + advice.append(cstr(record.total_amount)) + advice.append('') + advice.append(cstr(record.outstanding_amount)) + advice.append(sanitize_to_alphanumeric(record.reference_name)) + advice.append(format_date(record.due_date)) + advice.append(payment_entry_date) + advice += ['']*3 + advice_rows.append("~".join(advice)) + return advice_rows def get_trailer_row(no_of_records, total_amount): trailer = ["T"] From 0fac6f1c4b91713f3d13a591be271df151323f71 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Sun, 5 May 2019 22:35:23 +0530 Subject: [PATCH 09/41] feat: check bulk update option --- .../doctype/payment_order/payment_order.json | 459 ++++-------------- .../payment_order_reference.json | 11 +- 2 files changed, 110 insertions(+), 360 deletions(-) diff --git a/erpnext/accounts/doctype/payment_order/payment_order.json b/erpnext/accounts/doctype/payment_order/payment_order.json index bc57b964fd..85192db194 100644 --- a/erpnext/accounts/doctype/payment_order/payment_order.json +++ b/erpnext/accounts/doctype/payment_order/payment_order.json @@ -1,375 +1,122 @@ { - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "naming_series:", - "beta": 0, - "creation": "2018-07-20 16:43:08.505978", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", + "autoname": "naming_series:", + "creation": "2018-07-20 16:43:08.505978", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "naming_series", + "company", + "party", + "column_break_2", + "posting_date", + "bank", + "section_break_5", + "references", + "amended_from" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "PMO-", - "fieldname": "naming_series", - "fieldtype": "Select", - "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": "Series", - "length": 0, - "no_copy": 0, - "options": "PMO-", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "PMO-", + "fieldname": "naming_series", + "fieldtype": "Select", + "label": "Series", + "options": "PMO-", + "reqd": 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, - "options": "Company", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "company", + "fieldtype": "Link", + "label": "Company", + "options": "Company", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "party", - "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": 0, - "label": "Supplier", - "length": 0, - "no_copy": 0, - "options": "Supplier", - "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": "party", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Supplier", + "options": "Supplier" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_2", - "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, - "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_2", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Today", - "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": 1, - "in_standard_filter": 0, - "label": "Posting Date", - "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 - }, + "default": "Today", + "fieldname": "posting_date", + "fieldtype": "Date", + "in_list_view": 1, + "label": "Posting Date" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "bank", - "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": 0, - "label": "Bank", - "length": 0, - "no_copy": 0, - "options": "Bank", - "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", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Bank", + "options": "Bank" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_5", - "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": "section_break_5", + "fieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "references", - "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": "Payment Order Reference", - "length": 0, - "no_copy": 0, - "options": "Payment Order Reference", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "allow_bulk_edit": 1, + "fieldname": "references", + "fieldtype": "Table", + "label": "Payment Order Reference", + "options": "Payment Order Reference", + "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": 0, - "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, - "options": "Payment Order", - "permlevel": 0, - "print_hide": 1, - "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", + "label": "Amended From", + "no_copy": 1, + "options": "Payment Order", + "print_hide": 1, + "read_only": 1 } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 1, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2018-07-31 18:48:00.681271", - "modified_by": "Administrator", - "module": "Accounts", - "name": "Payment Order", - "name_case": "", - "owner": "Administrator", + ], + "is_submittable": 1, + "modified": "2019-05-05 22:26:22.170326", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Payment Order", + "owner": "Administrator", "permissions": [ { - "amend": 1, - "cancel": 1, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Accounts User", - "set_user_permissions": 0, - "share": 1, - "submit": 1, + "amend": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts User", + "share": 1, + "submit": 1, "write": 1 - }, + }, { - "amend": 1, - "cancel": 1, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "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, + "export": 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, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 + ], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/accounts/doctype/payment_order_reference/payment_order_reference.json b/erpnext/accounts/doctype/payment_order_reference/payment_order_reference.json index 1eeb5e9d31..d0ee93b1e1 100644 --- a/erpnext/accounts/doctype/payment_order_reference/payment_order_reference.json +++ b/erpnext/accounts/doctype/payment_order_reference/payment_order_reference.json @@ -25,7 +25,8 @@ "in_list_view": 1, "label": "Type", "options": "DocType", - "read_only": 1 + "read_only": 1, + "reqd": 1 }, { "fieldname": "reference_name", @@ -33,14 +34,16 @@ "in_list_view": 1, "label": "Name", "options": "reference_doctype", - "read_only": 1 + "read_only": 1, + "reqd": 1 }, { "fieldname": "amount", "fieldtype": "Currency", "in_list_view": 1, "label": "Amount", - "read_only": 1 + "read_only": 1, + "reqd": 1 }, { "fieldname": "column_break_4", @@ -109,7 +112,7 @@ } ], "istable": 1, - "modified": "2019-05-03 17:28:01.648394", + "modified": "2019-05-05 22:23:32.723766", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Order Reference", From c448664e6b36045c83714d794d0b61635488d07e Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Sun, 5 May 2019 22:36:32 +0530 Subject: [PATCH 10/41] feat: generate file name --- .../doctype/payment_order/regional/india.js | 2 +- erpnext/regional/india/bank_remittance_txt.py | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/erpnext/accounts/doctype/payment_order/regional/india.js b/erpnext/accounts/doctype/payment_order/regional/india.js index e92145c071..598223d2a7 100644 --- a/erpnext/accounts/doctype/payment_order/regional/india.js +++ b/erpnext/accounts/doctype/payment_order/regional/india.js @@ -11,7 +11,7 @@ frappe.ui.form.on('Payment Order', { return frappe.call({ method: "erpnext.regional.india.bank_remittance_txt.generate_report", args: { - name: frm.doc.name, + name: frm.doc.name }, freeze: true, callback: function(r) { diff --git a/erpnext/regional/india/bank_remittance_txt.py b/erpnext/regional/india/bank_remittance_txt.py index 83f49fed3a..0fc7ce6781 100644 --- a/erpnext/regional/india/bank_remittance_txt.py +++ b/erpnext/regional/india/bank_remittance_txt.py @@ -18,7 +18,7 @@ def create_bank_remittance_txt(name): no_of_records = len(payment_order.get("references")) total_amount = reduce(lambda x, y: x.get("amount") + y.get("amount"), payment_order.get("references")) - header = get_header_row(payment_order) + header, file_name = get_header_row(payment_order) batch = get_batch_row(payment_order, no_of_records, total_amount) detail = [] @@ -28,12 +28,12 @@ def create_bank_remittance_txt(name): trailer = get_trailer_row(no_of_records, total_amount) detail_records = "\n".join(detail) - return "\n".join([header, batch , detail_records, trailer]) + return "\n".join([header, batch , detail_records, trailer]), file_name @frappe.whitelist() def generate_report(name): - data = create_bank_remittance_txt(name) - file_name = generate_file_name(name) + data, file_name = create_bank_remittance_txt(name) + f = frappe.get_doc({ 'doctype': 'File', 'file_name': file_name+'.txt', @@ -45,18 +45,18 @@ def generate_report(name): f.save() download_file(f.file_url) -def generate_file_name(name): +def generate_file_name(name, date): ''' generate file name with format (account_code)_mmdd_(payment_order_no) ''' - return name + return date.strftime("%m%d")+sanitize_to_alphanumeric(name) def get_header_row(doc): client_code = "ELECTROLAB" - file_name = generate_file_name(doc.name) + file_name = generate_file_name(doc.name, doc.posting_date) header = ["H"] header.append(cstr(client_code)[:20]) header += [''] * 3 header.append(cstr(file_name)[:20]) - return "~".join(header) + return "~".join(header), file_name def get_batch_row(doc, no_of_records, total_amount): product_code = "VENPAY" @@ -78,7 +78,7 @@ def get_detail_row(ref_doc, payment_date): 'parenttype':'Address', 'parent': ('like', '%-Billing') },'parent') - supplier_billing_address = frappe.get_doc('Address', addr_link) + supplier_billing_address = frappe.get_cached_doc('Address', addr_link) detail = OrderedDict( record_identifier='D', payment_ref_no=sanitize_to_alphanumeric(ref_doc.payment_entry), From 525d8cefc1628c8137997f5b12ef6affb213381b Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Sun, 5 May 2019 22:36:59 +0530 Subject: [PATCH 11/41] fix: post process mapping --- erpnext/accounts/doctype/payment_entry/payment_entry.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index d50ed95f6a..f73eacdd0c 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -979,8 +979,8 @@ def make_payment_order(source_name, target_doc=None): target_doc.amount = source_parent.base_paid_amount target_doc.account = source_parent.paid_to target_doc.payment_entry = source_doc.name - target_doc.supplier = source_doc.party - target_doc.mode_of_payment = source_doc.mode_of_payment + target_doc.supplier = source_parent.party + target_doc.mode_of_payment = source_parent.mode_of_payment doclist = get_mapped_doc("Payment Entry", source_name, { From 9215de02c54dfa54e50fac739ef6ac0d97bca16e Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Mon, 6 May 2019 16:24:10 +0530 Subject: [PATCH 12/41] feat: add india specific custom fields in company --- erpnext/patches.txt | 4 ++-- erpnext/regional/india/setup.py | 12 ++++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 01270e4779..fce848ab5f 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -568,7 +568,7 @@ execute:frappe.delete_doc_if_exists("Page", "sales-analytics") execute:frappe.delete_doc_if_exists("Page", "purchase-analytics") execute:frappe.delete_doc_if_exists("Page", "stock-analytics") execute:frappe.delete_doc_if_exists("Page", "production-analytics") -erpnext.patches.v11_0.ewaybill_fields_gst_india #2019-05-01 +erpnext.patches.v11_0.ewaybill_fields_gst_india #2019-05-06 erpnext.patches.v11_0.drop_column_max_days_allowed erpnext.patches.v10_0.update_user_image_in_employee erpnext.patches.v10_0.repost_gle_for_purchase_receipts_with_rejected_items @@ -600,4 +600,4 @@ erpnext.patches.v11_1.woocommerce_set_creation_user erpnext.patches.v11_1.set_salary_details_submittable erpnext.patches.v11_1.rename_depends_on_lwp execute:frappe.delete_doc("Report", "Inactive Items") -erpnext.patches.v11_1.delete_scheduling_tool +erpnext.patches.v11_1.delete_scheduling_tool \ No newline at end of file diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py index e1aa233559..ab17521f6e 100644 --- a/erpnext/regional/india/setup.py +++ b/erpnext/regional/india/setup.py @@ -281,7 +281,15 @@ def make_custom_fields(update=True): dict(fieldname='hra_component', label='HRA Component', fieldtype='Link', options='Salary Component', insert_after='basic_component'), dict(fieldname='arrear_component', label='Arrear Component', - fieldtype='Link', options='Salary Component', insert_after='hra_component') + fieldtype='Link', options='Salary Component', insert_after='hra_component'), + dict(fieldname='bank_remittance_section', label='Bank Remittance Settings', + fieldtype='Section Break', collapsible=1, insert_after='arrear_component'), + dict(fieldname='client_code', label='Client Code', fieldtype='Data', + insert_after='bank_remittance_section'), + dict(fieldname='remittance_column_break', fieldtype='Column Break', + insert_after='client_code'), + dict(fieldname='product_code', label='Product Code', fieldtype='Data', + insert_after='remittance_column_break'), ], 'Employee Tax Exemption Declaration':[ dict(fieldname='hra_section', label='HRA Exemption', @@ -566,4 +574,4 @@ def get_tds_details(accounts, fiscal_year): doctype="Tax Withholding Category", accounts=accounts, rates=[{"fiscal_year": fiscal_year, "tax_withholding_rate": 20, "single_threshold": 2500, "cumulative_threshold": 0}]) - ] + ] \ No newline at end of file From 66a3c99800fca59231c86d96480c96503d4df42b Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Mon, 6 May 2019 16:26:05 +0530 Subject: [PATCH 13/41] feat: fetch custom fields for remittance creation --- erpnext/regional/india/bank_remittance_txt.py | 39 +++++++++++-------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/erpnext/regional/india/bank_remittance_txt.py b/erpnext/regional/india/bank_remittance_txt.py index 0fc7ce6781..7ccfa988fc 100644 --- a/erpnext/regional/india/bank_remittance_txt.py +++ b/erpnext/regional/india/bank_remittance_txt.py @@ -18,8 +18,12 @@ def create_bank_remittance_txt(name): no_of_records = len(payment_order.get("references")) total_amount = reduce(lambda x, y: x.get("amount") + y.get("amount"), payment_order.get("references")) - header, file_name = get_header_row(payment_order) - batch = get_batch_row(payment_order, no_of_records, total_amount) + product_code, client_code = frappe.db.get_value("Company", + filters={'name' : payment_order.company}, + fieldname=['product_code', 'client_code']) + + header, file_name = get_header_row(payment_order, client_code) + batch = get_batch_row(payment_order, no_of_records, total_amount, product_code) detail = [] for ref_doc in payment_order.get("references"): @@ -36,7 +40,7 @@ def generate_report(name): f = frappe.get_doc({ 'doctype': 'File', - 'file_name': file_name+'.txt', + 'file_name': file_name, 'content': data, "attached_to_doctype": 'Payment Order', "attached_to_name": name, @@ -47,10 +51,10 @@ def generate_report(name): def generate_file_name(name, date): ''' generate file name with format (account_code)_mmdd_(payment_order_no) ''' - return date.strftime("%m%d")+sanitize_to_alphanumeric(name) + return '_'+date.strftime("%m%d")+sanitize_data(name, '_')+'.txt' -def get_header_row(doc): - client_code = "ELECTROLAB" +def get_header_row(doc, client_code): + ''' Returns header row and generated file name ''' file_name = generate_file_name(doc.name, doc.posting_date) header = ["H"] header.append(cstr(client_code)[:20]) @@ -58,12 +62,11 @@ def get_header_row(doc): header.append(cstr(file_name)[:20]) return "~".join(header), file_name -def get_batch_row(doc, no_of_records, total_amount): - product_code = "VENPAY" +def get_batch_row(doc, no_of_records, total_amount, product_code): batch = ["B"] batch.append(cstr(no_of_records)[:5]) # 5 batch.append(cstr(total_amount)[:17]) #amt 17.2 - batch.append(sanitize_to_alphanumeric(doc.name)[:20]) + batch.append(sanitize_data(doc.name, '_')[:20]) batch.append(format_date(doc.posting_date)) batch.append(product_code[:20]) return "~".join(batch) @@ -81,7 +84,7 @@ def get_detail_row(ref_doc, payment_date): supplier_billing_address = frappe.get_cached_doc('Address', addr_link) detail = OrderedDict( record_identifier='D', - payment_ref_no=sanitize_to_alphanumeric(ref_doc.payment_entry), + payment_ref_no=sanitize_data(ref_doc.payment_entry), payment_type=cstr(payment_entry.mode_of_payment)[:10], amount=str(ref_doc.amount)[:13], payment_date=payment_date, @@ -93,12 +96,12 @@ def get_detail_row(ref_doc, payment_date): cr_ref_no='', bank_code_indicator='M', beneficiary_code='', - beneficiary_name=sanitize_to_alphanumeric(payment_entry.party)[:160], - beneficiary_bank=sanitize_to_alphanumeric(supplier_bank_details.bank)[:10], + beneficiary_name=sanitize_data(payment_entry.party, ' ')[:160], + beneficiary_bank=sanitize_data(supplier_bank_details.bank, ' ')[:10], beneficiary_branch_code=cstr(supplier_bank_details.branch_code), beneficiary_acc_no=supplier_bank_details.bank_account_no, - location=supplier_billing_address.city, - print_location=supplier_billing_address.city, + location='', + print_location='', beneficiary_address_1=cstr(supplier_billing_address.address_line1)[:50], beneficiary_address_2=cstr(supplier_billing_address.address_line2)[:50], beneficiary_address_3='', @@ -120,6 +123,7 @@ def get_detail_row(ref_doc, payment_date): return detail_record def get_advice_rows(payment_entry): + ''' Returns multiple advice rows for a single detail entry ''' payment_entry_date = payment_entry.posting_date.strftime("%b%y%d%m").upper() mode_of_payment = payment_entry.mode_of_payment advice_rows = [] @@ -129,7 +133,7 @@ def get_advice_rows(payment_entry): advice.append(cstr(record.total_amount)) advice.append('') advice.append(cstr(record.outstanding_amount)) - advice.append(sanitize_to_alphanumeric(record.reference_name)) + advice.append(record.reference_name) advice.append(format_date(record.due_date)) advice.append(payment_entry_date) advice += ['']*3 @@ -137,15 +141,16 @@ def get_advice_rows(payment_entry): return advice_rows def get_trailer_row(no_of_records, total_amount): + ''' Returns trailer row ''' trailer = ["T"] trailer.append(cstr(no_of_records)[:5]) # 5 trailer.append(cstr(total_amount)[:17]) # 17.2 return "~".join(trailer) -def sanitize_to_alphanumeric(val): +def sanitize_data(val, replace_str=''): ''' Remove all the non-alphanumeric characters from string ''' pattern = pattern = re.compile('[\W_]+') - return pattern.sub(' ', val) + return pattern.sub(replace_str, val) def format_date(val): ''' Convert a datetime object to DD/MM/YYYY format ''' From 27ea17118767309d809f8ae6c7b5e42dea003ca0 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Mon, 6 May 2019 16:37:34 +0530 Subject: [PATCH 14/41] style: change formatting --- erpnext/regional/india/bank_remittance_txt.py | 224 +++++++++--------- 1 file changed, 112 insertions(+), 112 deletions(-) diff --git a/erpnext/regional/india/bank_remittance_txt.py b/erpnext/regional/india/bank_remittance_txt.py index 7ccfa988fc..178a3662eb 100644 --- a/erpnext/regional/india/bank_remittance_txt.py +++ b/erpnext/regional/india/bank_remittance_txt.py @@ -13,145 +13,145 @@ from collections import OrderedDict from frappe.core.doctype.file.file import download_file def create_bank_remittance_txt(name): - payment_order = frappe.get_doc("Payment Order", name) + payment_order = frappe.get_doc("Payment Order", name) - no_of_records = len(payment_order.get("references")) - total_amount = reduce(lambda x, y: x.get("amount") + y.get("amount"), payment_order.get("references")) + no_of_records = len(payment_order.get("references")) + total_amount = reduce(lambda x, y: x.get("amount") + y.get("amount"), payment_order.get("references")) - product_code, client_code = frappe.db.get_value("Company", + product_code, client_code = frappe.db.get_value("Company", filters={'name' : payment_order.company}, fieldname=['product_code', 'client_code']) header, file_name = get_header_row(payment_order, client_code) batch = get_batch_row(payment_order, no_of_records, total_amount, product_code) - detail = [] - for ref_doc in payment_order.get("references"): - detail += get_detail_row(ref_doc, format_date(payment_order.posting_date)) + detail = [] + for ref_doc in payment_order.get("references"): + detail += get_detail_row(ref_doc, format_date(payment_order.posting_date)) - trailer = get_trailer_row(no_of_records, total_amount) - detail_records = "\n".join(detail) + trailer = get_trailer_row(no_of_records, total_amount) + detail_records = "\n".join(detail) - return "\n".join([header, batch , detail_records, trailer]), file_name + return "\n".join([header, batch , detail_records, trailer]), file_name @frappe.whitelist() def generate_report(name): - data, file_name = create_bank_remittance_txt(name) + data, file_name = create_bank_remittance_txt(name) - f = frappe.get_doc({ - 'doctype': 'File', - 'file_name': file_name, - 'content': data, - "attached_to_doctype": 'Payment Order', - "attached_to_name": name, - 'is_private': True - }) - f.save() - download_file(f.file_url) + f = frappe.get_doc({ + 'doctype': 'File', + 'file_name': file_name, + 'content': data, + "attached_to_doctype": 'Payment Order', + "attached_to_name": name, + 'is_private': True + }) + f.save() + download_file(f.file_url) def generate_file_name(name, date): - ''' generate file name with format (account_code)_mmdd_(payment_order_no) ''' - return '_'+date.strftime("%m%d")+sanitize_data(name, '_')+'.txt' + ''' generate file name with format (account_code)_mmdd_(payment_order_no) ''' + return '_'+date.strftime("%m%d")+sanitize_data(name, '_')+'.txt' def get_header_row(doc, client_code): - ''' Returns header row and generated file name ''' - file_name = generate_file_name(doc.name, doc.posting_date) - header = ["H"] - header.append(cstr(client_code)[:20]) - header += [''] * 3 - header.append(cstr(file_name)[:20]) - return "~".join(header), file_name + ''' Returns header row and generated file name ''' + file_name = generate_file_name(doc.name, doc.posting_date) + header = ["H"] + header.append(cstr(client_code)[:20]) + header += [''] * 3 + header.append(cstr(file_name)[:20]) + return "~".join(header), file_name def get_batch_row(doc, no_of_records, total_amount, product_code): - batch = ["B"] - batch.append(cstr(no_of_records)[:5]) # 5 - batch.append(cstr(total_amount)[:17]) #amt 17.2 - batch.append(sanitize_data(doc.name, '_')[:20]) - batch.append(format_date(doc.posting_date)) - batch.append(product_code[:20]) - return "~".join(batch) + batch = ["B"] + batch.append(cstr(no_of_records)[:5]) # 5 + batch.append(cstr(total_amount)[:17]) #amt 17.2 + batch.append(sanitize_data(doc.name, '_')[:20]) + batch.append(format_date(doc.posting_date)) + batch.append(product_code[:20]) + return "~".join(batch) def get_detail_row(ref_doc, payment_date): - payment_entry = frappe.get_cached_doc('Payment Entry', ref_doc.payment_entry) - supplier_bank_details = frappe.get_cached_doc('Bank Account', ref_doc.bank_account) - addr_link = frappe.db.get_value('Dynamic Link', - { - 'link_doctype': 'Supplier', - 'link_name': 'Sample Supplier', - 'parenttype':'Address', - 'parent': ('like', '%-Billing') - },'parent') - supplier_billing_address = frappe.get_cached_doc('Address', addr_link) - detail = OrderedDict( - record_identifier='D', - payment_ref_no=sanitize_data(ref_doc.payment_entry), - payment_type=cstr(payment_entry.mode_of_payment)[:10], - amount=str(ref_doc.amount)[:13], - payment_date=payment_date, - instrument_date=payment_date, - instrument_number='', - dr_account_no_client=str(payment_entry.bank_account_no)[:20], - dr_description='', - dr_ref_no='', - cr_ref_no='', - bank_code_indicator='M', - beneficiary_code='', - beneficiary_name=sanitize_data(payment_entry.party, ' ')[:160], - beneficiary_bank=sanitize_data(supplier_bank_details.bank, ' ')[:10], - beneficiary_branch_code=cstr(supplier_bank_details.branch_code), - beneficiary_acc_no=supplier_bank_details.bank_account_no, - location='', - print_location='', - beneficiary_address_1=cstr(supplier_billing_address.address_line1)[:50], - beneficiary_address_2=cstr(supplier_billing_address.address_line2)[:50], - beneficiary_address_3='', - beneficiary_address_4='', - beneficiary_address_5='', - beneficiary_city=supplier_billing_address.city, - beneficiary_zipcode=cstr(supplier_billing_address.pincode), - beneficiary_state=supplier_billing_address.state, - beneficiary_email=supplier_billing_address.email_id, - beneficiary_mobile=supplier_billing_address.phone, - payment_details_1='', - payment_details_2='', - payment_details_3='', - payment_details_4='', - delivery_mode='' - ) - detail_record = ["~".join(list(detail.values()))] - detail_record += get_advice_rows(payment_entry) - return detail_record + payment_entry = frappe.get_cached_doc('Payment Entry', ref_doc.payment_entry) + supplier_bank_details = frappe.get_cached_doc('Bank Account', ref_doc.bank_account) + addr_link = frappe.db.get_value('Dynamic Link', + { + 'link_doctype': 'Supplier', + 'link_name': 'Sample Supplier', + 'parenttype':'Address', + 'parent': ('like', '%-Billing') + },'parent') + supplier_billing_address = frappe.get_cached_doc('Address', addr_link) + detail = OrderedDict( + record_identifier='D', + payment_ref_no=sanitize_data(ref_doc.payment_entry), + payment_type=cstr(payment_entry.mode_of_payment)[:10], + amount=str(ref_doc.amount)[:13], + payment_date=payment_date, + instrument_date=payment_date, + instrument_number='', + dr_account_no_client=str(payment_entry.bank_account_no)[:20], + dr_description='', + dr_ref_no='', + cr_ref_no='', + bank_code_indicator='M', + beneficiary_code='', + beneficiary_name=sanitize_data(payment_entry.party, ' ')[:160], + beneficiary_bank=sanitize_data(supplier_bank_details.bank, ' ')[:10], + beneficiary_branch_code=cstr(supplier_bank_details.branch_code), + beneficiary_acc_no=supplier_bank_details.bank_account_no, + location='', + print_location='', + beneficiary_address_1=cstr(supplier_billing_address.address_line1)[:50], + beneficiary_address_2=cstr(supplier_billing_address.address_line2)[:50], + beneficiary_address_3='', + beneficiary_address_4='', + beneficiary_address_5='', + beneficiary_city=supplier_billing_address.city, + beneficiary_zipcode=cstr(supplier_billing_address.pincode), + beneficiary_state=supplier_billing_address.state, + beneficiary_email=supplier_billing_address.email_id, + beneficiary_mobile=supplier_billing_address.phone, + payment_details_1='', + payment_details_2='', + payment_details_3='', + payment_details_4='', + delivery_mode='' + ) + detail_record = ["~".join(list(detail.values()))] + detail_record += get_advice_rows(payment_entry) + return detail_record def get_advice_rows(payment_entry): - ''' Returns multiple advice rows for a single detail entry ''' - payment_entry_date = payment_entry.posting_date.strftime("%b%y%d%m").upper() - mode_of_payment = payment_entry.mode_of_payment - advice_rows = [] - for record in payment_entry.references: - advice = ['E'] - advice.append(cstr(mode_of_payment)) - advice.append(cstr(record.total_amount)) - advice.append('') - advice.append(cstr(record.outstanding_amount)) - advice.append(record.reference_name) - advice.append(format_date(record.due_date)) - advice.append(payment_entry_date) - advice += ['']*3 - advice_rows.append("~".join(advice)) - return advice_rows + ''' Returns multiple advice rows for a single detail entry ''' + payment_entry_date = payment_entry.posting_date.strftime("%b%y%d%m").upper() + mode_of_payment = payment_entry.mode_of_payment + advice_rows = [] + for record in payment_entry.references: + advice = ['E'] + advice.append(cstr(mode_of_payment)) + advice.append(cstr(record.total_amount)) + advice.append('') + advice.append(cstr(record.outstanding_amount)) + advice.append(record.reference_name) + advice.append(format_date(record.due_date)) + advice.append(payment_entry_date) + advice += ['']*3 + advice_rows.append("~".join(advice)) + return advice_rows def get_trailer_row(no_of_records, total_amount): - ''' Returns trailer row ''' - trailer = ["T"] - trailer.append(cstr(no_of_records)[:5]) # 5 - trailer.append(cstr(total_amount)[:17]) # 17.2 - return "~".join(trailer) + ''' Returns trailer row ''' + trailer = ["T"] + trailer.append(cstr(no_of_records)[:5]) # 5 + trailer.append(cstr(total_amount)[:17]) # 17.2 + return "~".join(trailer) def sanitize_data(val, replace_str=''): - ''' Remove all the non-alphanumeric characters from string ''' - pattern = pattern = re.compile('[\W_]+') - return pattern.sub(replace_str, val) + ''' Remove all the non-alphanumeric characters from string ''' + pattern = pattern = re.compile('[\W_]+') + return pattern.sub(replace_str, val) def format_date(val): - ''' Convert a datetime object to DD/MM/YYYY format ''' - return val.strftime("%d/%m/%Y") \ No newline at end of file + ''' Convert a datetime object to DD/MM/YYYY format ''' + return val.strftime("%d/%m/%Y") \ No newline at end of file From f709f330ce655903b8e276158f2498ae4a8e4647 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Mon, 6 May 2019 19:50:17 +0530 Subject: [PATCH 15/41] feat: show generate txt button for payment entry --- .../doctype/payment_order/payment_order.js | 4 ++-- .../doctype/payment_order/payment_order.json | 17 ++++++++++++++++- .../doctype/payment_order/regional/india.js | 2 +- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/payment_order/payment_order.js b/erpnext/accounts/doctype/payment_order/payment_order.js index 5b4f9fbd1a..f0071b83f2 100644 --- a/erpnext/accounts/doctype/payment_order/payment_order.js +++ b/erpnext/accounts/doctype/payment_order/payment_order.js @@ -13,7 +13,7 @@ frappe.ui.form.on('Payment Order', { } // payment Entry - if (frm.doc.docstatus==1) { + if (frm.doc.docstatus===1 && frm.doc.payment_order_type==='Payment Request') { frm.add_custom_button(__('Create Payment Entries'), function() { frm.trigger("make_payment_records"); @@ -99,4 +99,4 @@ frappe.ui.form.on('Payment Order', { dialog.show(); }, -}); +}); \ No newline at end of file diff --git a/erpnext/accounts/doctype/payment_order/payment_order.json b/erpnext/accounts/doctype/payment_order/payment_order.json index 85192db194..006974194a 100644 --- a/erpnext/accounts/doctype/payment_order/payment_order.json +++ b/erpnext/accounts/doctype/payment_order/payment_order.json @@ -7,10 +7,12 @@ "field_order": [ "naming_series", "company", + "payment_order_type", "party", "column_break_2", "posting_date", "bank", + "bank_account", "section_break_5", "references", "amended_from" @@ -50,6 +52,7 @@ "label": "Posting Date" }, { + "fetch_from": "Company.default_bank", "fieldname": "bank", "fieldtype": "Link", "in_list_view": 1, @@ -76,10 +79,22 @@ "options": "Payment Order", "print_hide": 1, "read_only": 1 + }, + { + "fieldname": "bank_account", + "fieldtype": "Link", + "label": "Bank Account", + "options": "Bank Account" + }, + { + "fieldname": "payment_order_type", + "fieldtype": "Select", + "label": "Payment Order Type", + "options": "\nPayment Request\nPayment Entry" } ], "is_submittable": 1, - "modified": "2019-05-05 22:26:22.170326", + "modified": "2019-05-06 16:40:11.397341", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Order", diff --git a/erpnext/accounts/doctype/payment_order/regional/india.js b/erpnext/accounts/doctype/payment_order/regional/india.js index 598223d2a7..28d2a2a677 100644 --- a/erpnext/accounts/doctype/payment_order/regional/india.js +++ b/erpnext/accounts/doctype/payment_order/regional/india.js @@ -1,6 +1,6 @@ frappe.ui.form.on('Payment Order', { refresh: function(frm) { - if (frm.doc.docstatus==1) { + if (frm.doc.docstatus==1 && frm.doc.payment_order_type==='Payment Request') { frm.add_custom_button(__('Generate Text File'), function() { frm.trigger("generate_text_and_download_file"); From e8bea2e936f0c6799903c24aae809b7e84f8d929 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Mon, 6 May 2019 19:54:11 +0530 Subject: [PATCH 16/41] feat: set payment order type on mapping --- erpnext/accounts/doctype/payment_entry/payment_entry.py | 2 +- erpnext/accounts/doctype/payment_request/payment_request.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index f73eacdd0c..601813dc3b 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -972,7 +972,7 @@ def get_party_and_account_balance(company, date, paid_from=None, paid_to=None, p def make_payment_order(source_name, target_doc=None): from frappe.model.mapper import get_mapped_doc def set_missing_values(source, target): - pass + target.payment_order_type = "Payment Entry" def update_item(source_doc, target_doc, source_parent): target_doc.bank_account = source_parent.bank_account diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py index 9b0ef42b8e..73758bea85 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.py +++ b/erpnext/accounts/doctype/payment_request/payment_request.py @@ -427,6 +427,7 @@ def get_subscription_details(reference_doctype, reference_name): def make_payment_order(source_name, target_doc=None): from frappe.model.mapper import get_mapped_doc def set_missing_values(source, target): + target.payment_order_type = "Payment Request" target.append('references', { 'reference_doctype': source.reference_doctype, 'reference_name': source.reference_name, From b8d0dec7f505fd0d25267c796f450181f554a251 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Tue, 7 May 2019 11:29:20 +0530 Subject: [PATCH 17/41] feat: filter bank from company account --- .../doctype/payment_entry/payment_entry.js | 7 +++++++ .../doctype/payment_order/payment_order.js | 9 +++++++++ .../doctype/payment_order/payment_order.json | 16 ++++++++-------- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js index 5707d154c1..ffba8c8f7f 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.js +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js @@ -30,6 +30,13 @@ frappe.ui.form.on('Payment Entry', { } } }); + frm.set_query("bank_account", function() { + return { + filters: { + "is_company_account":0 + } + } + }); frm.set_query("contact_person", function() { if (frm.doc.party) { return { diff --git a/erpnext/accounts/doctype/payment_order/payment_order.js b/erpnext/accounts/doctype/payment_order/payment_order.js index f0071b83f2..61ead01747 100644 --- a/erpnext/accounts/doctype/payment_order/payment_order.js +++ b/erpnext/accounts/doctype/payment_order/payment_order.js @@ -2,6 +2,15 @@ // For license information, please see license.txt frappe.ui.form.on('Payment Order', { + setup: function(frm) { + frm.set_query("company_bank_account", function() { + return { + filters: { + "is_company_account":1 + } + } + }); + }, refresh: function(frm) { if (frm.doc.docstatus == 0) { frm.add_custom_button(__('Payment Request'), function() { diff --git a/erpnext/accounts/doctype/payment_order/payment_order.json b/erpnext/accounts/doctype/payment_order/payment_order.json index 006974194a..0018359134 100644 --- a/erpnext/accounts/doctype/payment_order/payment_order.json +++ b/erpnext/accounts/doctype/payment_order/payment_order.json @@ -12,7 +12,7 @@ "column_break_2", "posting_date", "bank", - "bank_account", + "company_bank_account", "section_break_5", "references", "amended_from" @@ -80,21 +80,21 @@ "print_hide": 1, "read_only": 1 }, - { - "fieldname": "bank_account", - "fieldtype": "Link", - "label": "Bank Account", - "options": "Bank Account" - }, { "fieldname": "payment_order_type", "fieldtype": "Select", "label": "Payment Order Type", "options": "\nPayment Request\nPayment Entry" + }, + { + "fieldname": "company_bank_account", + "fieldtype": "Link", + "label": "Company Bank Account", + "options": "Bank Account" } ], "is_submittable": 1, - "modified": "2019-05-06 16:40:11.397341", + "modified": "2019-05-06 19:57:03.661653", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Order", From 0b2fc4fbc1c768d466a3e9c9549e0fe2d5d3d677 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Wed, 8 May 2019 15:57:29 +0530 Subject: [PATCH 18/41] fix: multiple changes --- erpnext/regional/india/bank_remittance_txt.py | 64 +++++++++++-------- 1 file changed, 37 insertions(+), 27 deletions(-) diff --git a/erpnext/regional/india/bank_remittance_txt.py b/erpnext/regional/india/bank_remittance_txt.py index 178a3662eb..bd2097cd0a 100644 --- a/erpnext/regional/india/bank_remittance_txt.py +++ b/erpnext/regional/india/bank_remittance_txt.py @@ -6,7 +6,6 @@ from __future__ import unicode_literals import frappe from frappe.model.document import Document from frappe.utils import cint,cstr, today -from functools import reduce import re import datetime from collections import OrderedDict @@ -16,23 +15,23 @@ def create_bank_remittance_txt(name): payment_order = frappe.get_doc("Payment Order", name) no_of_records = len(payment_order.get("references")) - total_amount = reduce(lambda x, y: x.get("amount") + y.get("amount"), payment_order.get("references")) + total_amount = sum(entry.get("amount") for entry in payment_order.get("references")) - product_code, client_code = frappe.db.get_value("Company", + product_code, client_code, company_email = frappe.db.get_value("Company", filters={'name' : payment_order.company}, - fieldname=['product_code', 'client_code']) + fieldname=['product_code', 'client_code', 'email']) header, file_name = get_header_row(payment_order, client_code) batch = get_batch_row(payment_order, no_of_records, total_amount, product_code) detail = [] for ref_doc in payment_order.get("references"): - detail += get_detail_row(ref_doc, format_date(payment_order.posting_date)) + detail += get_detail_row(ref_doc, payment_order, company_email) trailer = get_trailer_row(no_of_records, total_amount) detail_records = "\n".join(detail) - return "\n".join([header, batch , detail_records, trailer]), file_name + return "\n".join([header, batch, detail_records, trailer]), file_name @frappe.whitelist() def generate_report(name): @@ -47,15 +46,19 @@ def generate_report(name): 'is_private': True }) f.save() - download_file(f.file_url) + return { + 'file_url': f.file_url, + 'file_name': file_name + } -def generate_file_name(name, date): +def generate_file_name(name, company_account, date): ''' generate file name with format (account_code)_mmdd_(payment_order_no) ''' - return '_'+date.strftime("%m%d")+sanitize_data(name, '_')+'.txt' + bank, acc_no = frappe.db.get_value("Bank Account", {"name": company_account}, ['bank', 'bank_account_no']) + return bank[:1]+str(acc_no)[-4:]+'_'+date.strftime("%m%d")+sanitize_data(name, '')[4:]+'.txt' def get_header_row(doc, client_code): ''' Returns header row and generated file name ''' - file_name = generate_file_name(doc.name, doc.posting_date) + file_name = generate_file_name(doc.name, doc.company_bank_account, doc.posting_date) header = ["H"] header.append(cstr(client_code)[:20]) header += [''] * 3 @@ -64,54 +67,61 @@ def get_header_row(doc, client_code): def get_batch_row(doc, no_of_records, total_amount, product_code): batch = ["B"] - batch.append(cstr(no_of_records)[:5]) # 5 - batch.append(cstr(total_amount)[:17]) #amt 17.2 + batch.append(cstr(no_of_records)[:5]) + batch.append(cstr(format(total_amount, '0.2f'))[:17]) batch.append(sanitize_data(doc.name, '_')[:20]) batch.append(format_date(doc.posting_date)) batch.append(product_code[:20]) return "~".join(batch) -def get_detail_row(ref_doc, payment_date): +def get_detail_row(ref_doc, payment_entry, company_email): + + payment_date = format_date(payment_entry.posting_date) payment_entry = frappe.get_cached_doc('Payment Entry', ref_doc.payment_entry) supplier_bank_details = frappe.get_cached_doc('Bank Account', ref_doc.bank_account) + company_bank_acc_no = frappe.db.get_value("Bank Account", {'name': payment_entry.bank_account}, ['bank_account_no']) + addr_link = frappe.db.get_value('Dynamic Link', { 'link_doctype': 'Supplier', 'link_name': 'Sample Supplier', 'parenttype':'Address', 'parent': ('like', '%-Billing') - },'parent') + }, 'parent') + supplier_billing_address = frappe.get_cached_doc('Address', addr_link) + email = ', '.join(filter(None, [supplier_billing_address.email_id, company_email])) + detail = OrderedDict( record_identifier='D', payment_ref_no=sanitize_data(ref_doc.payment_entry), payment_type=cstr(payment_entry.mode_of_payment)[:10], - amount=str(ref_doc.amount)[:13], + amount=str(format(ref_doc.amount, '.2f'))[:13], payment_date=payment_date, instrument_date=payment_date, instrument_number='', - dr_account_no_client=str(payment_entry.bank_account_no)[:20], + dr_account_no_client=str(company_bank_acc_no)[:20], dr_description='', dr_ref_no='', cr_ref_no='', bank_code_indicator='M', beneficiary_code='', beneficiary_name=sanitize_data(payment_entry.party, ' ')[:160], - beneficiary_bank=sanitize_data(supplier_bank_details.bank, ' ')[:10], + beneficiary_bank=sanitize_data(supplier_bank_details.bank)[:10], beneficiary_branch_code=cstr(supplier_bank_details.branch_code), beneficiary_acc_no=supplier_bank_details.bank_account_no, location='', print_location='', - beneficiary_address_1=cstr(supplier_billing_address.address_line1)[:50], - beneficiary_address_2=cstr(supplier_billing_address.address_line2)[:50], + beneficiary_address_1=sanitize_data(cstr(supplier_billing_address.address_line1), ' ')[:50], + beneficiary_address_2=sanitize_data(cstr(supplier_billing_address.address_line2), ' ')[:50], beneficiary_address_3='', beneficiary_address_4='', beneficiary_address_5='', - beneficiary_city=supplier_billing_address.city, - beneficiary_zipcode=cstr(supplier_billing_address.pincode), - beneficiary_state=supplier_billing_address.state, - beneficiary_email=supplier_billing_address.email_id, - beneficiary_mobile=supplier_billing_address.phone, + beneficiary_city=supplier_billing_address.city[:20], + beneficiary_zipcode=cstr(supplier_billing_address.pincode)[:6], + beneficiary_state=supplier_billing_address.state[:20], + beneficiary_email=cstr(email)[:255], + beneficiary_mobile=cstr(supplier_billing_address.phone), payment_details_1='', payment_details_2='', payment_details_3='', @@ -119,6 +129,7 @@ def get_detail_row(ref_doc, payment_date): delivery_mode='' ) detail_record = ["~".join(list(detail.values()))] + detail_record += get_advice_rows(payment_entry) return detail_record @@ -136,15 +147,14 @@ def get_advice_rows(payment_entry): advice.append(record.reference_name) advice.append(format_date(record.due_date)) advice.append(payment_entry_date) - advice += ['']*3 advice_rows.append("~".join(advice)) return advice_rows def get_trailer_row(no_of_records, total_amount): ''' Returns trailer row ''' trailer = ["T"] - trailer.append(cstr(no_of_records)[:5]) # 5 - trailer.append(cstr(total_amount)[:17]) # 17.2 + trailer.append(cstr(no_of_records)[:5]) + trailer.append(cstr(format(total_amount, '.2f'))[:17]) return "~".join(trailer) def sanitize_data(val, replace_str=''): From 8aa9589aafecedcf1508c813c99d8dadab60cfa2 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Wed, 8 May 2019 15:58:26 +0530 Subject: [PATCH 19/41] fix: display generate txt on submission --- .../accounts/doctype/payment_order/regional/india.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/payment_order/regional/india.js b/erpnext/accounts/doctype/payment_order/regional/india.js index 28d2a2a677..2b49a06cdb 100644 --- a/erpnext/accounts/doctype/payment_order/regional/india.js +++ b/erpnext/accounts/doctype/payment_order/regional/india.js @@ -1,6 +1,6 @@ frappe.ui.form.on('Payment Order', { refresh: function(frm) { - if (frm.doc.docstatus==1 && frm.doc.payment_order_type==='Payment Request') { + if (frm.doc.docstatus==1 && frm.doc.payment_order_type==='Payment Entry') { frm.add_custom_button(__('Generate Text File'), function() { frm.trigger("generate_text_and_download_file"); @@ -15,7 +15,15 @@ frappe.ui.form.on('Payment Order', { }, freeze: true, callback: function(r) { - frm.refresh(); + { + frm.refresh(); + const a = document.createElement('a'); + let file_obj = r.message; + a.href = file_obj.file_url; + a.target = '_blank'; + a.download = file_obj.file_name; + a.click(); + } } }); } From a4d55c98582999ed0e98135703ece8166d7009b4 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Wed, 8 May 2019 16:04:18 +0530 Subject: [PATCH 20/41] feat: assign pe status on creation of payment order --- .../doctype/payment_order/payment_order.json | 28 +++++++++++-------- .../doctype/payment_order/payment_order.py | 12 ++++---- .../payment_order_reference.json | 5 ++-- 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/erpnext/accounts/doctype/payment_order/payment_order.json b/erpnext/accounts/doctype/payment_order/payment_order.json index 0018359134..285168f247 100644 --- a/erpnext/accounts/doctype/payment_order/payment_order.json +++ b/erpnext/accounts/doctype/payment_order/payment_order.json @@ -11,7 +11,7 @@ "party", "column_break_2", "posting_date", - "bank", + "company_bank", "company_bank_account", "section_break_5", "references", @@ -23,6 +23,7 @@ "fieldname": "naming_series", "fieldtype": "Select", "label": "Series", + "no_copy": 1, "options": "PMO-", "reqd": 1 }, @@ -34,6 +35,7 @@ "reqd": 1 }, { + "depends_on": "eval: doc.payment_order_type=='Payment Request';", "fieldname": "party", "fieldtype": "Link", "in_list_view": 1, @@ -51,14 +53,6 @@ "in_list_view": 1, "label": "Posting Date" }, - { - "fetch_from": "Company.default_bank", - "fieldname": "bank", - "fieldtype": "Link", - "in_list_view": 1, - "label": "Bank", - "options": "Bank" - }, { "fieldname": "section_break_5", "fieldtype": "Section Break" @@ -84,17 +78,27 @@ "fieldname": "payment_order_type", "fieldtype": "Select", "label": "Payment Order Type", - "options": "\nPayment Request\nPayment Entry" + "options": "\nPayment Request\nPayment Entry", + "reqd": 1 }, { "fieldname": "company_bank_account", "fieldtype": "Link", "label": "Company Bank Account", - "options": "Bank Account" + "options": "Bank Account", + "reqd": 1 + }, + { + "fetch_from": "company_bank_account.bank", + "fieldname": "company_bank", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Bank", + "options": "Bank" } ], "is_submittable": 1, - "modified": "2019-05-06 19:57:03.661653", + "modified": "2019-05-08 16:00:09.027739", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Order", diff --git a/erpnext/accounts/doctype/payment_order/payment_order.py b/erpnext/accounts/doctype/payment_order/payment_order.py index 8491bb7e10..2a29293bbf 100644 --- a/erpnext/accounts/doctype/payment_order/payment_order.py +++ b/erpnext/accounts/doctype/payment_order/payment_order.py @@ -11,18 +11,18 @@ from frappe.model.document import Document class PaymentOrder(Document): def on_submit(self): - self.update_payment_request_status() + self.update_payment_status() def on_cancel(self): - self.update_payment_request_status(cancel=True) + self.update_payment_status(cancel=True) - def update_payment_request_status(self, cancel=False): + def update_payment_status(self, cancel=False): status = 'Payment Ordered' if cancel: status = 'Initiated' for d in self.references: - frappe.db.set_value('Payment Request', d.payment_request, 'status', status) + frappe.db.set_value(self.payment_order_type, d.get(frappe.scrub(self.payment_order_type)), 'status', status) def get_mop_query(doctype, txt, searchfield, start, page_len, filters): return frappe.db.sql(""" select mode_of_payment from `tabPayment Order Reference` @@ -60,7 +60,7 @@ def make_journal_entry(doc, supplier, mode_of_payment=None): je.voucher_type = 'Bank Entry' if mode_of_payment and mode_of_payment_type.get(mode_of_payment) == 'Cash': je.voucher_type = "Cash Entry" - + paid_amt = 0 party_account = get_party_account('Supplier', supplier, doc.company) for d in doc.references: @@ -84,4 +84,4 @@ def make_journal_entry(doc, supplier, mode_of_payment=None): je.flags.ignore_mandatory = True je.save() - frappe.msgprint(_("{0} {1} created").format(je.doctype, je.name)) + frappe.msgprint(_("{0} {1} created").format(je.doctype, je.name)) \ No newline at end of file diff --git a/erpnext/accounts/doctype/payment_order_reference/payment_order_reference.json b/erpnext/accounts/doctype/payment_order_reference/payment_order_reference.json index d0ee93b1e1..db0b76135d 100644 --- a/erpnext/accounts/doctype/payment_order_reference/payment_order_reference.json +++ b/erpnext/accounts/doctype/payment_order_reference/payment_order_reference.json @@ -82,7 +82,8 @@ "fieldtype": "Link", "label": "Bank Account", "options": "Bank Account", - "read_only": 1 + "read_only": 1, + "reqd": 1 }, { "fieldname": "column_break_10", @@ -112,7 +113,7 @@ } ], "istable": 1, - "modified": "2019-05-05 22:23:32.723766", + "modified": "2019-05-08 13:56:25.724557", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Order Reference", From f353f1d805084d0790cc18e4c62253ccb39d9211 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Wed, 8 May 2019 16:04:48 +0530 Subject: [PATCH 21/41] feat: add status field to create payment order --- .../doctype/payment_entry/payment_entry.json | 1960 ++--------------- 1 file changed, 145 insertions(+), 1815 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.json b/erpnext/accounts/doctype/payment_entry/payment_entry.json index 96e1e1eb16..b988b481d1 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.json +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.json @@ -1,2215 +1,556 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, "allow_import": 1, - "allow_rename": 0, "autoname": "naming_series:", - "beta": 0, "creation": "2016-06-01 14:38:51.012597", - "custom": 0, - "docstatus": 0, "doctype": "DocType", - "document_type": "", - "editable_grid": 0, + "field_order": [ + "type_of_payment", + "naming_series", + "payment_type", + "status", + "column_break_5", + "posting_date", + "company", + "cost_center", + "mode_of_payment", + "party_section", + "party_type", + "party", + "party_name", + "column_break_11", + "bank_account", + "contact_person", + "contact_email", + "payment_accounts_section", + "party_balance", + "paid_from", + "paid_from_account_currency", + "paid_from_account_balance", + "column_break_18", + "paid_to", + "paid_to_account_currency", + "paid_to_account_balance", + "payment_amounts_section", + "paid_amount", + "source_exchange_rate", + "base_paid_amount", + "column_break_21", + "received_amount", + "target_exchange_rate", + "base_received_amount", + "section_break_14", + "allocate_payment_amount", + "references", + "section_break_34", + "total_allocated_amount", + "base_total_allocated_amount", + "set_exchange_gain_loss", + "column_break_36", + "unallocated_amount", + "difference_amount", + "write_off_difference_amount", + "deductions_or_loss_section", + "deductions", + "transaction_references", + "reference_no", + "column_break_23", + "reference_date", + "clearance_date", + "section_break_12", + "project", + "remarks", + "column_break_16", + "letter_head", + "print_heading", + "bank", + "bank_account_no", + "payment_order", + "subscription_section", + "auto_repeat", + "amended_from", + "title" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "type_of_payment", "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": "Type of Payment", - "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 + "label": "Type of Payment" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, "bold": 1, - "collapsible": 0, - "columns": 0, - "default": "", - "fetch_if_empty": 0, "fieldname": "naming_series", "fieldtype": "Select", - "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": "Series", - "length": 0, - "no_copy": 0, "options": "ACC-PAY-.YYYY.-", - "permlevel": 0, - "precision": "", "print_hide": 1, - "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": 1, - "translatable": 0, - "unique": 0 + "set_only_once": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, "bold": 1, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "payment_type", "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, "in_list_view": 1, "in_standard_filter": 1, "label": "Payment Type", - "length": 0, - "no_copy": 0, "options": "Receive\nPay\nInternal Transfer", - "permlevel": 0, - "precision": "", "print_hide": 1, - "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 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "column_break_5", - "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, - "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 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, "bold": 1, - "collapsible": 0, - "columns": 0, "default": "Today", - "fetch_if_empty": 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": 1, - "in_standard_filter": 0, "label": "Posting Date", - "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, - "unique": 0 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 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, "options": "Company", - "permlevel": 0, - "precision": "", "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, "remember_last_selected_value": 1, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "cost_center", "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": "Cost Center", - "length": 0, - "no_copy": 0, - "options": "Cost Center", - "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 + "options": "Cost Center" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "mode_of_payment", "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": 0, "label": "Mode of Payment", - "length": 0, - "no_copy": 0, - "options": "Mode of Payment", - "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 + "options": "Mode of Payment" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "depends_on": "eval:in_list([\"Receive\", \"Pay\"], doc.payment_type)", - "fetch_if_empty": 0, "fieldname": "party_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": "Payment From / To", - "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 + "label": "Payment From / To" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "", "depends_on": "eval:in_list([\"Receive\", \"Pay\"], doc.payment_type) && doc.docstatus==0", - "fetch_if_empty": 0, "fieldname": "party_type", "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": 1, "label": "Party Type", - "length": 0, - "no_copy": 0, "options": "DocType", - "permlevel": 0, - "precision": "", "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "search_index": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, "bold": 1, - "collapsible": 0, - "columns": 0, "depends_on": "eval:in_list([\"Receive\", \"Pay\"], doc.payment_type) && doc.party_type", - "fetch_if_empty": 0, "fieldname": "party", "fieldtype": "Dynamic 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": 1, "label": "Party", - "length": 0, - "no_copy": 0, - "options": "party_type", - "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 + "options": "party_type" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, "depends_on": "eval:in_list([\"Receive\", \"Pay\"], doc.payment_type) && doc.party_type", - "description": "", - "fetch_if_empty": 0, "fieldname": "party_name", "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, "in_global_search": 1, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Party 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": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Party Name" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "column_break_11", - "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, - "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 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "depends_on": "party", - "fetch_if_empty": 0, - "fieldname": "bank_account", - "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": "Bank Account", - "length": 0, - "no_copy": 0, - "options": "Bank Account", - "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 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "party", - "fetch_if_empty": 0, "fieldname": "contact_person", "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": "Contact", - "length": 0, - "no_copy": 0, - "options": "Contact", - "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 + "options": "Contact" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "depends_on": "contact_person", - "fetch_if_empty": 0, "fieldname": "contact_email", "fieldtype": "Data", - "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": "Email", - "length": 0, - "no_copy": 0, "options": "Email", - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, "collapsible": 1, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "payment_accounts_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": "Accounts", - "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 + "label": "Accounts" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "depends_on": "party", - "fetch_if_empty": 0, "fieldname": "party_balance", "fieldtype": "Currency", - "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": "Party Balance", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, "bold": 1, - "collapsible": 0, - "columns": 0, "depends_on": "eval:(in_list([\"Internal Transfer\", \"Pay\"], doc.payment_type) || doc.party)", - "fetch_if_empty": 0, "fieldname": "paid_from", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, "in_global_search": 1, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Account Paid From", - "length": 0, - "no_copy": 0, "options": "Account", - "permlevel": 0, - "precision": "", "print_hide": 1, - "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 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "depends_on": "paid_from", - "fetch_if_empty": 0, "fieldname": "paid_from_account_currency", "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": "Account Currency", - "length": 0, - "no_copy": 0, "options": "Currency", - "permlevel": 0, - "precision": "", "print_hide": 1, - "print_hide_if_no_value": 0, "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "depends_on": "paid_from", - "fetch_if_empty": 0, "fieldname": "paid_from_account_balance", "fieldtype": "Currency", - "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": "Account Balance", - "length": 0, - "no_copy": 0, "options": "paid_from_account_currency", - "permlevel": 0, - "precision": "", "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "column_break_18", - "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, - "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 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "depends_on": "eval:(in_list([\"Internal Transfer\", \"Receive\"], doc.payment_type) || doc.party)", - "fetch_if_empty": 0, "fieldname": "paid_to", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, "in_global_search": 1, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Account Paid To", - "length": 0, - "no_copy": 0, "options": "Account", - "permlevel": 0, - "precision": "", "print_hide": 1, - "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 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "depends_on": "paid_to", - "fetch_if_empty": 0, "fieldname": "paid_to_account_currency", "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": "Account Currency", - "length": 0, - "no_copy": 0, "options": "Currency", - "permlevel": 0, - "precision": "", "print_hide": 1, - "print_hide_if_no_value": 0, "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "depends_on": "paid_to", - "fetch_if_empty": 0, "fieldname": "paid_to_account_balance", "fieldtype": "Currency", - "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": "Account Balance", - "length": 0, - "no_copy": 0, "options": "paid_to_account_currency", - "permlevel": 0, - "precision": "", "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "collapsible_depends_on": "", - "columns": 0, "depends_on": "eval:(doc.paid_to && doc.paid_from)", - "fetch_if_empty": 0, "fieldname": "payment_amounts_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": "Amount", - "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 + "label": "Amount" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, "bold": 1, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fetch_if_empty": 0, "fieldname": "paid_amount", "fieldtype": "Currency", - "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": "Paid Amount", - "length": 0, - "no_copy": 0, "options": "paid_from_account_currency", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fetch_if_empty": 0, "fieldname": "source_exchange_rate", "fieldtype": "Float", - "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": "Exchange Rate", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", "print_hide": 1, - "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 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fetch_if_empty": 0, "fieldname": "base_paid_amount", "fieldtype": "Currency", - "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": "Paid Amount (Company Currency)", - "length": 0, - "no_copy": 0, "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", "print_hide": 1, - "print_hide_if_no_value": 0, "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "column_break_21", - "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, - "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 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, "bold": 1, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fetch_if_empty": 0, "fieldname": "received_amount", "fieldtype": "Currency", - "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": "Received Amount", - "length": 0, - "no_copy": 0, "options": "paid_to_account_currency", - "permlevel": 0, - "precision": "", "print_hide": 1, - "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 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fetch_if_empty": 0, "fieldname": "target_exchange_rate", "fieldtype": "Float", - "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": "Exchange Rate", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", "print_hide": 1, - "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 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fetch_if_empty": 0, "fieldname": "base_received_amount", "fieldtype": "Currency", - "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": "Received Amount (Company Currency)", - "length": 0, - "no_copy": 0, "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", "print_hide": 1, - "print_hide_if_no_value": 0, "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, "collapsible": 1, "collapsible_depends_on": "references", - "columns": 0, "depends_on": "eval:(doc.party && doc.paid_from && doc.paid_to && doc.paid_amount && doc.received_amount)", - "fetch_if_empty": 0, "fieldname": "section_break_14", "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": "Reference", - "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 + "label": "Reference" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "default": "1", "depends_on": "eval:in_list(['Pay', 'Receive'], doc.payment_type)", - "fetch_if_empty": 0, "fieldname": "allocate_payment_amount", "fieldtype": "Check", - "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": "Allocate Payment Amount", - "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 + "label": "Allocate Payment Amount" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fetch_if_empty": 0, "fieldname": "references", "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": "Payment References", - "length": 0, - "no_copy": 0, - "options": "Payment Entry Reference", - "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 + "options": "Payment Entry Reference" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fetch_if_empty": 0, "fieldname": "section_break_34", "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": "Writeoff", - "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 + "label": "Writeoff" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, "bold": 1, - "collapsible": 0, - "columns": 0, "depends_on": "eval:(doc.paid_amount && doc.received_amount && doc.references)", - "fetch_if_empty": 0, "fieldname": "total_allocated_amount", "fieldtype": "Currency", - "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": "Total Allocated Amount", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fetch_if_empty": 0, "fieldname": "base_total_allocated_amount", "fieldtype": "Currency", - "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": "Total Allocated Amount (Company Currency)", - "length": 0, - "no_copy": 0, "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "set_exchange_gain_loss", "fieldtype": "Button", - "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": "Set Exchange Gain / Loss", - "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 + "label": "Set Exchange Gain / Loss" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "column_break_36", - "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, - "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 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "depends_on": "eval:(doc.paid_amount && doc.received_amount && doc.references)", - "fetch_if_empty": 0, "fieldname": "unallocated_amount", "fieldtype": "Currency", - "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": "Unallocated Amount", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 + "print_hide": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, "bold": 1, - "collapsible": 0, - "columns": 0, "depends_on": "eval:(doc.paid_amount && doc.received_amount)", - "fetch_if_empty": 0, "fieldname": "difference_amount", "fieldtype": "Currency", - "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": "Difference Amount (Company Currency)", - "length": 0, - "no_copy": 0, "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "depends_on": "difference_amount", - "fetch_if_empty": 0, "fieldname": "write_off_difference_amount", "fieldtype": "Button", - "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": "Write Off Difference Amount", - "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 + "label": "Write Off Difference Amount" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, "collapsible": 1, "collapsible_depends_on": "deductions", - "columns": 0, "depends_on": "eval:(doc.paid_amount && doc.received_amount)", - "fetch_if_empty": 0, "fieldname": "deductions_or_loss_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": "Deductions or Loss", - "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 + "label": "Deductions or Loss" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "deductions", "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": "Payment Deductions or Loss", - "length": 0, - "no_copy": 0, - "options": "Payment Entry Deduction", - "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 + "options": "Payment Entry Deduction" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "transaction_references", "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": "Transaction ID", - "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 + "label": "Transaction ID" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, "bold": 1, - "collapsible": 0, - "columns": 0, "depends_on": "eval:(doc.paid_from && doc.paid_to)", - "fetch_if_empty": 0, "fieldname": "reference_no", "fieldtype": "Data", - "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": "Cheque/Reference No", - "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 + "label": "Cheque/Reference No" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "column_break_23", - "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, - "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 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, "bold": 1, - "collapsible": 0, - "columns": 0, "depends_on": "eval:(doc.paid_from && doc.paid_to)", - "fetch_if_empty": 0, "fieldname": "reference_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": "Cheque/Reference Date", - "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": 1, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "search_index": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "depends_on": "eval:doc.docstatus==1", - "fetch_if_empty": 0, "fieldname": "clearance_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": "Clearance Date", - "length": 0, "no_copy": 1, - "permlevel": 0, - "precision": "", "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, "collapsible": 1, - "collapsible_depends_on": "", - "columns": 0, "depends_on": "eval:(doc.paid_from && doc.paid_to && doc.paid_amount && doc.received_amount)", - "fetch_if_empty": 0, "fieldname": "section_break_12", "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": "More Information", - "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 + "label": "More Information" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fetch_if_empty": 0, "fieldname": "project", "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": "Project", - "length": 0, - "no_copy": 0, "options": "Project", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 + "print_hide": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 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": 1, - "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 + "no_copy": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "column_break_16", - "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, - "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 + "fieldtype": "Column Break" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "letter_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": "Letter Head", - "length": 0, - "no_copy": 0, "options": "Letter Head", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 + "print_hide": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "print_heading", "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": "Print Heading", - "length": 0, - "no_copy": 0, "options": "Print Heading", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 + "print_hide": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fetch_from": "bank_account.bank", - "fetch_if_empty": 0, "fieldname": "bank", "fieldtype": "Read Only", - "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", - "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 + "label": "Bank" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fetch_from": "bank_account.bank_account_no", - "fetch_if_empty": 0, "fieldname": "bank_account_no", "fieldtype": "Read Only", - "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 Account No", - "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 + "label": "Bank Account No" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "payment_order", "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": "Payment Order", - "length": 0, "no_copy": 1, "options": "Payment Order", - "permlevel": 0, - "precision": "", "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "subscription_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": "Subscription Section", - "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 + "label": "Subscription Section" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "auto_repeat", "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": "Auto Repeat", - "length": 0, "no_copy": 1, "options": "Auto Repeat", - "permlevel": 0, - "precision": "", "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "amended_from", "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": "Amended From", - "length": 0, "no_copy": 1, "options": "Payment Entry", - "permlevel": 0, "print_hide": 1, - "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 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, "fieldname": "title", "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": "Title", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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 + "print_hide": 1 + }, + { + "fieldname": "status", + "fieldtype": "Select", + "label": "Status", + "options": "Initiated\nCompleted" + }, + { + "depends_on": "party", + "fieldname": "bank_account", + "fieldtype": "Link", + "label": "Bank Account", + "options": "Bank Account" } ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, "is_submittable": 1, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2019-03-27 17:39:54.163016", + "modified": "2019-05-08 12:35:05.407422", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Entry", - "name_case": "", "owner": "Administrator", "permissions": [ { @@ -2219,14 +560,11 @@ "delete": 1, "email": 1, "export": 1, - "if_owner": 0, "import": 1, - "permlevel": 0, "print": 1, "read": 1, "report": 1, "role": "Accounts User", - "set_user_permissions": 0, "share": 1, "submit": 1, "write": 1 @@ -2238,27 +576,19 @@ "delete": 1, "email": 1, "export": 1, - "if_owner": 0, "import": 1, - "permlevel": 0, "print": 1, "read": 1, "report": 1, "role": "Accounts Manager", - "set_user_permissions": 0, "share": 1, "submit": 1, "write": 1 } ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, "show_name_in_global_search": 1, "sort_field": "modified", "sort_order": "DESC", "title_field": "title", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 + "track_changes": 1 } \ No newline at end of file From 3ca897603760318b4e103ef6f0c8b29acb99e00f Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Wed, 8 May 2019 16:06:26 +0530 Subject: [PATCH 22/41] feat: add validation for fetching doc status --- erpnext/accounts/doctype/payment_entry/payment_entry.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 601813dc3b..c506090f32 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -978,7 +978,7 @@ def make_payment_order(source_name, target_doc=None): target_doc.bank_account = source_parent.bank_account target_doc.amount = source_parent.base_paid_amount target_doc.account = source_parent.paid_to - target_doc.payment_entry = source_doc.name + target_doc.payment_entry = source_parent.name target_doc.supplier = source_parent.party target_doc.mode_of_payment = source_parent.mode_of_payment @@ -986,9 +986,15 @@ def make_payment_order(source_name, target_doc=None): doclist = get_mapped_doc("Payment Entry", source_name, { "Payment Entry": { "doctype": "Payment Order", + "validation": { + "docstatus": ["=", 1] + } }, "Payment Entry Reference": { "doctype": "Payment Order Reference", + "validation": { + "docstatus": ["=", 1] + }, "postprocess": update_item }, From 644e1817291ccfdc1ebe2685f333986ad62dba73 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Wed, 8 May 2019 16:17:31 +0530 Subject: [PATCH 23/41] feat: remove first row if empty --- erpnext/accounts/doctype/payment_order/payment_order.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/erpnext/accounts/doctype/payment_order/payment_order.js b/erpnext/accounts/doctype/payment_order/payment_order.js index 61ead01747..a5e18e8097 100644 --- a/erpnext/accounts/doctype/payment_order/payment_order.js +++ b/erpnext/accounts/doctype/payment_order/payment_order.js @@ -31,6 +31,10 @@ frappe.ui.form.on('Payment Order', { }, get_from_payment_entry: function(frm) { + // remove if first row is empty + if (!frm.doc.references[0].reference_name) { + frm.doc.references = []; + } erpnext.utils.map_current_doc({ method: "erpnext.accounts.doctype.payment_entry.payment_entry.make_payment_order", source_doctype: "Payment Entry", @@ -42,11 +46,16 @@ frappe.ui.form.on('Payment Order', { get_query_filters: { bank: frm.doc.bank, docstatus: 1, + status: ["=", "Initiated"], } }); }, get_from_payment_request: function(frm) { + // remove if first row is empty + if (!frm.doc.references[0].reference_name) { + frm.doc.references = []; + } erpnext.utils.map_current_doc({ method: "erpnext.accounts.doctype.payment_request.payment_request.make_payment_order", source_doctype: "Payment Request", From 93c9a995482d33d48c6de6b4e7c45bb7089d45d2 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Thu, 9 May 2019 12:23:24 +0530 Subject: [PATCH 24/41] style: change formatting --- .../doctype/payment_order/regional/india.js | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/erpnext/accounts/doctype/payment_order/regional/india.js b/erpnext/accounts/doctype/payment_order/regional/india.js index 2b49a06cdb..3601b4fdce 100644 --- a/erpnext/accounts/doctype/payment_order/regional/india.js +++ b/erpnext/accounts/doctype/payment_order/regional/india.js @@ -1,30 +1,30 @@ frappe.ui.form.on('Payment Order', { refresh: function(frm) { - if (frm.doc.docstatus==1 && frm.doc.payment_order_type==='Payment Entry') { - frm.add_custom_button(__('Generate Text File'), + if (frm.doc.docstatus==1 && frm.doc.payment_order_type==='Payment Entry') { + frm.add_custom_button(__('Generate Text File'), function() { frm.trigger("generate_text_and_download_file"); - }); - } - }, - generate_text_and_download_file: (frm) => { - return frappe.call({ - method: "erpnext.regional.india.bank_remittance_txt.generate_report", - args: { - name: frm.doc.name - }, - freeze: true, - callback: function(r) { - { - frm.refresh(); - const a = document.createElement('a'); - let file_obj = r.message; + }); + } + }, + generate_text_and_download_file: (frm) => { + return frappe.call({ + method: "erpnext.regional.india.bank_remittance_txt.generate_report", + args: { + name: frm.doc.name + }, + freeze: true, + callback: function(r) { + { + frm.refresh(); + const a = document.createElement('a'); + let file_obj = r.message; a.href = file_obj.file_url; a.target = '_blank'; a.download = file_obj.file_name; a.click(); } - } - }); - } + } + }); + } }); \ No newline at end of file From 5f1632cf1f307688e4884988e03a1678557bb79c Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Thu, 9 May 2019 18:50:14 +0530 Subject: [PATCH 25/41] fix(hr): Use event_status instead of status Training Feedback DocType has event_status field (not status) This was broken since PR #10379, PR #17197 made this failure explicit. --- erpnext/hr/doctype/training_feedback/training_feedback.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/erpnext/hr/doctype/training_feedback/training_feedback.py b/erpnext/hr/doctype/training_feedback/training_feedback.py index b47e2b4be8..1a33450791 100644 --- a/erpnext/hr/doctype/training_feedback/training_feedback.py +++ b/erpnext/hr/doctype/training_feedback/training_feedback.py @@ -15,11 +15,11 @@ class TrainingFeedback(Document): def on_submit(self): training_event = frappe.get_doc("Training Event", self.training_event) - status = None + event_status = None for e in training_event.employees: if e.employee == self.employee: - status = 'Feedback Submitted' + event_status = 'Feedback Submitted' break - if status: - frappe.db.set_value("Training Event", self.training_event, "status", status) + if event_status: + frappe.db.set_value("Training Event", self.training_event, "event_status", event_status) From cd4289e10e4a3e8be392c98d325a7583f515c920 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Sat, 11 May 2019 20:04:03 +0530 Subject: [PATCH 26/41] feat: remove button on import of an order --- .../doctype/payment_order/payment_order.js | 39 +++++++++++------ .../doctype/payment_order/payment_order.json | 3 +- .../doctype/payment_order/regional/india.js | 43 +++++++++---------- 3 files changed, 50 insertions(+), 35 deletions(-) diff --git a/erpnext/accounts/doctype/payment_order/payment_order.js b/erpnext/accounts/doctype/payment_order/payment_order.js index a5e18e8097..91d7f1f110 100644 --- a/erpnext/accounts/doctype/payment_order/payment_order.js +++ b/erpnext/accounts/doctype/payment_order/payment_order.js @@ -16,25 +16,44 @@ frappe.ui.form.on('Payment Order', { frm.add_custom_button(__('Payment Request'), function() { frm.trigger("get_from_payment_request"); }, __("Get from")); + frm.add_custom_button(__('Payment Entry'), function() { frm.trigger("get_from_payment_entry"); }, __("Get from")); + + frm.trigger('remove_button'); } // payment Entry if (frm.doc.docstatus===1 && frm.doc.payment_order_type==='Payment Request') { frm.add_custom_button(__('Create Payment Entries'), - function() { - frm.trigger("make_payment_records"); - }); + function() { + frm.trigger("make_payment_records"); + }); + } + }, + + remove_row_if_empty: function(frm) { + // remove if first row is empty + if (frm.doc.references.length > 0 && !frm.doc.references[0].reference_name) { + frm.doc.references = []; + } + }, + + remove_button: function(frm) { + let label = ["Payment Request", "Payment Entry"] + + if (frm.doc.references.length > 0 && frm.doc.payment_order_type) { + label = label.reduce(x => { + x!= frm.doc.payment_order_type; + return x; + }); + frm.remove_custom_button(label, "Get from"); } }, get_from_payment_entry: function(frm) { - // remove if first row is empty - if (!frm.doc.references[0].reference_name) { - frm.doc.references = []; - } + frm.trigger("remove_row_if_empty"); erpnext.utils.map_current_doc({ method: "erpnext.accounts.doctype.payment_entry.payment_entry.make_payment_order", source_doctype: "Payment Entry", @@ -52,10 +71,7 @@ frappe.ui.form.on('Payment Order', { }, get_from_payment_request: function(frm) { - // remove if first row is empty - if (!frm.doc.references[0].reference_name) { - frm.doc.references = []; - } + frm.trigger("remove_row_if_empty") erpnext.utils.map_current_doc({ method: "erpnext.accounts.doctype.payment_request.payment_request.make_payment_order", source_doctype: "Payment Request", @@ -116,5 +132,4 @@ frappe.ui.form.on('Payment Order', { dialog.show(); }, - }); \ No newline at end of file diff --git a/erpnext/accounts/doctype/payment_order/payment_order.json b/erpnext/accounts/doctype/payment_order/payment_order.json index 285168f247..c0dd4bc735 100644 --- a/erpnext/accounts/doctype/payment_order/payment_order.json +++ b/erpnext/accounts/doctype/payment_order/payment_order.json @@ -79,6 +79,7 @@ "fieldtype": "Select", "label": "Payment Order Type", "options": "\nPayment Request\nPayment Entry", + "read_only": 1, "reqd": 1 }, { @@ -98,7 +99,7 @@ } ], "is_submittable": 1, - "modified": "2019-05-08 16:00:09.027739", + "modified": "2019-05-09 13:57:12.974008", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Order", diff --git a/erpnext/accounts/doctype/payment_order/regional/india.js b/erpnext/accounts/doctype/payment_order/regional/india.js index 2b49a06cdb..87d9cdcc26 100644 --- a/erpnext/accounts/doctype/payment_order/regional/india.js +++ b/erpnext/accounts/doctype/payment_order/regional/india.js @@ -1,30 +1,29 @@ frappe.ui.form.on('Payment Order', { refresh: function(frm) { - if (frm.doc.docstatus==1 && frm.doc.payment_order_type==='Payment Entry') { - frm.add_custom_button(__('Generate Text File'), - function() { - frm.trigger("generate_text_and_download_file"); - }); - } - }, - generate_text_and_download_file: (frm) => { - return frappe.call({ - method: "erpnext.regional.india.bank_remittance_txt.generate_report", - args: { - name: frm.doc.name - }, - freeze: true, - callback: function(r) { - { - frm.refresh(); - const a = document.createElement('a'); - let file_obj = r.message; + if (frm.doc.docstatus==1 && frm.doc.payment_order_type==='Payment Entry') { + frm.add_custom_button(__('Generate Text File'), function() { + frm.trigger("generate_text_and_download_file"); + }); + } + }, + generate_text_and_download_file: (frm) => { + return frappe.call({ + method: "erpnext.regional.india.bank_remittance_txt.generate_report", + args: { + name: frm.doc.name + }, + freeze: true, + callback: function(r) { + { + frm.refresh(); + const a = document.createElement('a'); + let file_obj = r.message; a.href = file_obj.file_url; a.target = '_blank'; a.download = file_obj.file_name; a.click(); } - } - }); - } + } + }); + } }); \ No newline at end of file From 6175eb2cf93e27be149d4308f59f0eb2ade6dcc7 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Tue, 14 May 2019 18:25:57 +0530 Subject: [PATCH 27/41] feat: add validation for fields --- erpnext/regional/india/bank_remittance_txt.py | 70 +++++++++++++------ 1 file changed, 47 insertions(+), 23 deletions(-) diff --git a/erpnext/regional/india/bank_remittance_txt.py b/erpnext/regional/india/bank_remittance_txt.py index 423e239864..289de32f49 100644 --- a/erpnext/regional/india/bank_remittance_txt.py +++ b/erpnext/regional/india/bank_remittance_txt.py @@ -6,13 +6,13 @@ from __future__ import unicode_literals import frappe from frappe.model.document import Document from frappe.utils import cint,cstr, today +from frappe import _ import re import datetime from collections import OrderedDict -from frappe.core.doctype.file.file import download_file def create_bank_remittance_txt(name): - payment_order = frappe.get_doc("Payment Order", name) + payment_order = frappe.get_cached_doc("Payment Order", name) no_of_records = len(payment_order.get("references")) total_amount = sum(entry.get("amount") for entry in payment_order.get("references")) @@ -60,18 +60,19 @@ def get_header_row(doc, client_code): ''' Returns header row and generated file name ''' file_name = generate_file_name(doc.name, doc.company_bank_account, doc.posting_date) header = ["H"] - header.append(cstr(client_code)[:20]) + header.append(validate_field_size(client_code, "Client Code", 20)) header += [''] * 3 - header.append(cstr(file_name)[:20]) + header.append(validate_field_size(file_name, "File Name", 20)) return "~".join(header), file_name def get_batch_row(doc, no_of_records, total_amount, product_code): batch = ["B"] - batch.append(cstr(no_of_records)[:5]) - batch.append(cstr(format(total_amount, '0.2f'))[:17]) + batch.append(validate_field_size(no_of_records, "No Of Records", 5)) + batch.append(validate_amount(format(total_amount, '0.2f'), 17)) batch.append(sanitize_data(doc.name, '_')[:20]) batch.append(format_date(doc.posting_date)) - batch.append(product_code[:20]) + batch.append(validate_field_size(product_code,"Product Code", 20)) + print(batch) return "~".join(batch) def get_detail_row(ref_doc, payment_entry, company_email): @@ -96,32 +97,32 @@ def get_detail_row(ref_doc, payment_entry, company_email): record_identifier='D', payment_ref_no=sanitize_data(ref_doc.payment_entry), payment_type=cstr(payment_entry.mode_of_payment)[:10], - amount=str(format(ref_doc.amount, '.2f'))[:13], + amount=str(validate_amount(format(ref_doc.amount, '.2f'),13)), payment_date=payment_date, instrument_date=payment_date, instrument_number='', - dr_account_no_client=str(company_bank_acc_no)[:20], + dr_account_no_client=str(validate_field_size(company_bank_acc_no, "Company Bank Account", 20)), dr_description='', dr_ref_no='', cr_ref_no='', bank_code_indicator='M', beneficiary_code='', - beneficiary_name=sanitize_data(payment_entry.party, ' ')[:160], - beneficiary_bank=sanitize_data(supplier_bank_details.bank)[:10], - beneficiary_branch_code=cstr(supplier_bank_details.branch_code), - beneficiary_acc_no=supplier_bank_details.bank_account_no, + beneficiary_name=sanitize_data(validate_information(payment_entry, "party", 160), ' '), + beneficiary_bank=sanitize_data(validate_information(supplier_bank_details, "bank", 10)), + beneficiary_branch_code=cstr(validate_information(supplier_bank_details, "branch_code", 11)), + beneficiary_acc_no=validate_information(supplier_bank_details, "bank_account_no", 20), location='', print_location='', - beneficiary_address_1=sanitize_data(cstr(supplier_billing_address.address_line1), ' ')[:50], - beneficiary_address_2=sanitize_data(cstr(supplier_billing_address.address_line2), ' ')[:50], + beneficiary_address_1=validate_field_size(sanitize_data(cstr(supplier_billing_address.address_line1), ' '), " Beneficiary Address 1", 50), + beneficiary_address_2=validate_field_size(sanitize_data(cstr(supplier_billing_address.address_line2), ' '), " Beneficiary Address 2", 50), beneficiary_address_3='', beneficiary_address_4='', beneficiary_address_5='', - beneficiary_city=supplier_billing_address.city[:20], - beneficiary_zipcode=cstr(supplier_billing_address.pincode)[:6], - beneficiary_state=supplier_billing_address.state[:20], + beneficiary_city=validate_field_size(cstr(supplier_billing_address.city), "Beneficiary City", 20), + beneficiary_zipcode=validate_field_size(cstr(supplier_billing_address.pincode), "Pin Code", 6), + beneficiary_state=validate_field_size(cstr(supplier_billing_address.state), "Beneficiary State", 20), beneficiary_email=cstr(email)[:255], - beneficiary_mobile=cstr(supplier_billing_address.phone), + beneficiary_mobile=validate_field_size(cstr(supplier_billing_address.phone), "Beneficiary Mobile", 10), payment_details_1='', payment_details_2='', payment_details_3='', @@ -153,15 +154,38 @@ def get_advice_rows(payment_entry): def get_trailer_row(no_of_records, total_amount): ''' Returns trailer row ''' trailer = ["T"] - trailer.append(cstr(no_of_records)[:5]) - trailer.append(cstr(format(total_amount, '.2f'))[:17]) + trailer.append(validate_field_size(no_of_records, "No of Records", 5)) + trailer.append(validate_amount(format(total_amount, "0.2f"), 17)) return "~".join(trailer) def sanitize_data(val, replace_str=''): ''' Remove all the non-alphanumeric characters from string ''' - pattern = pattern = re.compile('[\W_]+') + pattern = re.compile('[\W_]+') return pattern.sub(replace_str, val) def format_date(val): ''' Convert a datetime object to DD/MM/YYYY format ''' - return val.strftime("%d/%m/%Y") \ No newline at end of file + return val.strftime("%d/%m/%Y") + +def validate_amount(val, max_int_size): + ''' Validate amount to be within the allowed limits ''' + int_size = len(str(val).split('.')[0]) + + if int_size > max_int_size: + frappe.throw(_("Amount for a single transaction is more than maximum allowed amount, create a separate payment order by splitting the transactions")) + + return val + +def validate_information(obj, attr, max_size): + ''' Checks if the information is not set in the system and is within the size ''' + if hasattr(obj, attr): + return validate_field_size(getattr(obj, attr), frappe.unscrub(attr), max_size) + + else: + frappe.throw(_("%s is mandatory for generating remittance payments, set the field and try again" % attr)) + +def validate_field_size(val, label, max_size): + ''' check the size of the val ''' + if len(cstr(val)) > max_size: + frappe.throw("%s field is limited to size %d" % (label, max_size)) + return cstr(val) \ No newline at end of file From d9140dc77201308605428b7fb8707bebd6ee9a70 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Tue, 14 May 2019 18:28:24 +0530 Subject: [PATCH 28/41] feat: add party bank account field --- .../doctype/payment_entry/payment_entry.js | 9 ++++++- .../doctype/payment_entry/payment_entry.json | 24 ++++++++++++------- .../doctype/payment_entry/payment_entry.py | 2 +- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js index ffba8c8f7f..2c382c58f6 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.js +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js @@ -30,13 +30,20 @@ frappe.ui.form.on('Payment Entry', { } } }); - frm.set_query("bank_account", function() { + frm.set_query("party_bank_account", function() { return { filters: { "is_company_account":0 } } }); + frm.set_query("bank_account", function() { + return { + filters: { + "is_company_account":1 + } + } + }); frm.set_query("contact_person", function() { if (frm.doc.party) { return { diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.json b/erpnext/accounts/doctype/payment_entry/payment_entry.json index b988b481d1..1fb4b7bf8d 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.json +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.json @@ -19,6 +19,7 @@ "party_name", "column_break_11", "bank_account", + "party_bank_account", "contact_person", "contact_email", "payment_accounts_section", @@ -532,22 +533,29 @@ "label": "Title", "print_hide": 1 }, - { - "fieldname": "status", - "fieldtype": "Select", - "label": "Status", - "options": "Initiated\nCompleted" - }, { "depends_on": "party", "fieldname": "bank_account", "fieldtype": "Link", - "label": "Bank Account", + "label": "Company Bank Account", "options": "Bank Account" + }, + { + "depends_on": "party", + "fieldname": "party_bank_account", + "fieldtype": "Link", + "label": "Party Bank Account", + "options": "Bank Account" + }, + { + "fieldname": "status", + "fieldtype": "Select", + "label": "Payment Order Status", + "options": "Initiated\nCompleted" } ], "is_submittable": 1, - "modified": "2019-05-08 12:35:05.407422", + "modified": "2019-05-14 17:00:48.759155", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Entry", diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index c506090f32..e224ee7146 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -975,7 +975,7 @@ def make_payment_order(source_name, target_doc=None): target.payment_order_type = "Payment Entry" def update_item(source_doc, target_doc, source_parent): - target_doc.bank_account = source_parent.bank_account + target_doc.bank_account = source_parent.party_bank_account target_doc.amount = source_parent.base_paid_amount target_doc.account = source_parent.paid_to target_doc.payment_entry = source_parent.name From 557419a745be1a5387e80457449b8a32d287022d Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Tue, 14 May 2019 18:30:19 +0530 Subject: [PATCH 29/41] feat: load company bank account --- erpnext/buying/doctype/supplier/supplier.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/erpnext/buying/doctype/supplier/supplier.js b/erpnext/buying/doctype/supplier/supplier.js index db6b8ca825..4ddc458175 100644 --- a/erpnext/buying/doctype/supplier/supplier.js +++ b/erpnext/buying/doctype/supplier/supplier.js @@ -17,6 +17,13 @@ frappe.ui.form.on("Supplier", { } } }); + frm.set_query("default_bank_account", function() { + return { + filters: { + "is_company_account":1 + } + } + }); }, refresh: function (frm) { frappe.dynamic_link = { doc: frm.doc, fieldname: 'name', doctype: 'Supplier' } From c68ee1fcc63c1111cb7de4ba431f537065b4422a Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Tue, 14 May 2019 18:31:14 +0530 Subject: [PATCH 30/41] feat: add account field in payment order --- .../accounts/doctype/payment_order/payment_order.js | 4 ++++ .../accounts/doctype/payment_order/payment_order.json | 11 ++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/payment_order/payment_order.js b/erpnext/accounts/doctype/payment_order/payment_order.js index 91d7f1f110..fd122a3e8f 100644 --- a/erpnext/accounts/doctype/payment_order/payment_order.js +++ b/erpnext/accounts/doctype/payment_order/payment_order.js @@ -41,6 +41,8 @@ frappe.ui.form.on('Payment Order', { }, remove_button: function(frm) { + // remove custom button of order type that is not imported + let label = ["Payment Request", "Payment Entry"] if (frm.doc.references.length > 0 && frm.doc.payment_order_type) { @@ -65,6 +67,8 @@ frappe.ui.form.on('Payment Order', { get_query_filters: { bank: frm.doc.bank, docstatus: 1, + bank_account: frm.doc.company_bank_account, + paid_from: frm.doc.account, status: ["=", "Initiated"], } }); diff --git a/erpnext/accounts/doctype/payment_order/payment_order.json b/erpnext/accounts/doctype/payment_order/payment_order.json index c0dd4bc735..2e12ad3523 100644 --- a/erpnext/accounts/doctype/payment_order/payment_order.json +++ b/erpnext/accounts/doctype/payment_order/payment_order.json @@ -13,6 +13,7 @@ "posting_date", "company_bank", "company_bank_account", + "account", "section_break_5", "references", "amended_from" @@ -90,16 +91,24 @@ "reqd": 1 }, { + "depends_on": "company_bank_account", "fetch_from": "company_bank_account.bank", "fieldname": "company_bank", "fieldtype": "Link", "in_list_view": 1, "label": "Bank", "options": "Bank" + }, + { + "depends_on": "company_bank_account", + "fetch_from": "company_bank_account.account", + "fieldname": "account", + "fieldtype": "Data", + "label": "Account" } ], "is_submittable": 1, - "modified": "2019-05-09 13:57:12.974008", + "modified": "2019-05-14 17:12:24.912666", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Order", From cd59263736ba97107b2ace55a369553ab378b25b Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Tue, 14 May 2019 18:34:14 +0530 Subject: [PATCH 31/41] fix: reload doc on generation of text file --- erpnext/accounts/doctype/payment_order/regional/india.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/payment_order/regional/india.js b/erpnext/accounts/doctype/payment_order/regional/india.js index 87d9cdcc26..8300f74a04 100644 --- a/erpnext/accounts/doctype/payment_order/regional/india.js +++ b/erpnext/accounts/doctype/payment_order/regional/india.js @@ -15,7 +15,7 @@ frappe.ui.form.on('Payment Order', { freeze: true, callback: function(r) { { - frm.refresh(); + frm.reload_doc(); const a = document.createElement('a'); let file_obj = r.message; a.href = file_obj.file_url; From cf71a84976fd11aec2ed5fbebc48abb0dbe450cb Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Tue, 14 May 2019 18:50:40 +0530 Subject: [PATCH 32/41] style: formatting changes --- erpnext/accounts/doctype/payment_order/payment_order.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/payment_order/payment_order.js b/erpnext/accounts/doctype/payment_order/payment_order.js index fd122a3e8f..b1b1139637 100644 --- a/erpnext/accounts/doctype/payment_order/payment_order.js +++ b/erpnext/accounts/doctype/payment_order/payment_order.js @@ -26,8 +26,7 @@ frappe.ui.form.on('Payment Order', { // payment Entry if (frm.doc.docstatus===1 && frm.doc.payment_order_type==='Payment Request') { - frm.add_custom_button(__('Create Payment Entries'), - function() { + frm.add_custom_button(__('Create Payment Entries'), function() { frm.trigger("make_payment_records"); }); } @@ -43,7 +42,7 @@ frappe.ui.form.on('Payment Order', { remove_button: function(frm) { // remove custom button of order type that is not imported - let label = ["Payment Request", "Payment Entry"] + let label = ["Payment Request", "Payment Entry"]; if (frm.doc.references.length > 0 && frm.doc.payment_order_type) { label = label.reduce(x => { @@ -75,7 +74,7 @@ frappe.ui.form.on('Payment Order', { }, get_from_payment_request: function(frm) { - frm.trigger("remove_row_if_empty") + frm.trigger("remove_row_if_empty"); erpnext.utils.map_current_doc({ method: "erpnext.accounts.doctype.payment_request.payment_request.make_payment_order", source_doctype: "Payment Request", From 6e3586423fe82a7cf1dadac416e07d733ecd3c73 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Wed, 15 May 2019 15:50:50 +0530 Subject: [PATCH 33/41] fix: multiple changes --- .../accounts/doctype/payment_entry/payment_entry.json | 10 ++++++---- .../accounts/doctype/payment_order/payment_order.py | 4 +++- .../{bank_remittance_txt.py => bank_remittance.py} | 7 +++---- 3 files changed, 12 insertions(+), 9 deletions(-) rename erpnext/regional/india/{bank_remittance_txt.py => bank_remittance.py} (95%) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.json b/erpnext/accounts/doctype/payment_entry/payment_entry.json index 1fb4b7bf8d..a335717f7f 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.json +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.json @@ -7,7 +7,7 @@ "type_of_payment", "naming_series", "payment_type", - "status", + "payment_order_status", "column_break_5", "posting_date", "company", @@ -548,14 +548,16 @@ "options": "Bank Account" }, { - "fieldname": "status", + "fieldname": "payment_order_status", "fieldtype": "Select", + "hidden": 1, "label": "Payment Order Status", - "options": "Initiated\nCompleted" + "options": "Initiated\nPayment Ordered", + "read_only": 1 } ], "is_submittable": 1, - "modified": "2019-05-14 17:00:48.759155", + "modified": "2019-05-15 15:43:29.229496", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Entry", diff --git a/erpnext/accounts/doctype/payment_order/payment_order.py b/erpnext/accounts/doctype/payment_order/payment_order.py index 2a29293bbf..3f3174a69b 100644 --- a/erpnext/accounts/doctype/payment_order/payment_order.py +++ b/erpnext/accounts/doctype/payment_order/payment_order.py @@ -21,8 +21,10 @@ class PaymentOrder(Document): if cancel: status = 'Initiated' + ref_field = "status" if self.payment_order_type == "Payment Request" else "payment_order_status" + for d in self.references: - frappe.db.set_value(self.payment_order_type, d.get(frappe.scrub(self.payment_order_type)), 'status', status) + frappe.db.set_value(self.payment_order_type, d.get(frappe.scrub(self.payment_order_type)), ref_field, status) def get_mop_query(doctype, txt, searchfield, start, page_len, filters): return frappe.db.sql(""" select mode_of_payment from `tabPayment Order Reference` diff --git a/erpnext/regional/india/bank_remittance_txt.py b/erpnext/regional/india/bank_remittance.py similarity index 95% rename from erpnext/regional/india/bank_remittance_txt.py rename to erpnext/regional/india/bank_remittance.py index 289de32f49..85c9564722 100644 --- a/erpnext/regional/india/bank_remittance_txt.py +++ b/erpnext/regional/india/bank_remittance.py @@ -72,7 +72,6 @@ def get_batch_row(doc, no_of_records, total_amount, product_code): batch.append(sanitize_data(doc.name, '_')[:20]) batch.append(format_date(doc.posting_date)) batch.append(validate_field_size(product_code,"Product Code", 20)) - print(batch) return "~".join(batch) def get_detail_row(ref_doc, payment_entry, company_email): @@ -172,7 +171,7 @@ def validate_amount(val, max_int_size): int_size = len(str(val).split('.')[0]) if int_size > max_int_size: - frappe.throw(_("Amount for a single transaction is more than maximum allowed amount, create a separate payment order by splitting the transactions")) + frappe.throw(_("Amount for a single transaction exceeds maximum allowed amount, create a separate payment order by splitting the transactions")) return val @@ -182,10 +181,10 @@ def validate_information(obj, attr, max_size): return validate_field_size(getattr(obj, attr), frappe.unscrub(attr), max_size) else: - frappe.throw(_("%s is mandatory for generating remittance payments, set the field and try again" % attr)) + frappe.throw(_("{0} is mandatory for generating remittance payments, set the field and try again".format(frappe.unscrub(attr)))) def validate_field_size(val, label, max_size): ''' check the size of the val ''' if len(cstr(val)) > max_size: - frappe.throw("%s field is limited to size %d" % (label, max_size)) + frappe.throw(_("{0} field is limited to size {1}".format(label, max_size))) return cstr(val) \ No newline at end of file From 3f119ec2565f894eba216338ebba365c899f8d6e Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 16 May 2019 17:28:39 +0530 Subject: [PATCH 34/41] fix: GL Entry for opening stock reconciliation --- erpnext/controllers/stock_controller.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index d11c644817..cee7e5a22b 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -80,6 +80,7 @@ class StockController(AccountsController): "cost_center": item_row.cost_center, "remarks": self.get("remarks") or "Accounting Entry for Stock", "debit": flt(sle.stock_value_difference, 2), + "is_opening": item_row.get("is_opening"), }, warehouse_account[sle.warehouse]["account_currency"])) # to target warehouse / expense account @@ -89,7 +90,8 @@ class StockController(AccountsController): "cost_center": item_row.cost_center, "remarks": self.get("remarks") or "Accounting Entry for Stock", "credit": flt(sle.stock_value_difference, 2), - "project": item_row.get("project") or self.get("project") + "project": item_row.get("project") or self.get("project"), + "is_opening": item_row.get("is_opening") })) elif sle.warehouse not in warehouse_with_no_account: warehouse_with_no_account.append(sle.warehouse) @@ -123,8 +125,17 @@ class StockController(AccountsController): def get_voucher_details(self, default_expense_account, default_cost_center, sle_map): if self.doctype == "Stock Reconciliation": - return [frappe._dict({ "name": voucher_detail_no, "expense_account": default_expense_account, - "cost_center": default_cost_center }) for voucher_detail_no, sle in sle_map.items()] + reconciliation_purpose = frappe.db.get_value(self.doctype, self.name, "purpose") + is_opening = "Yes" if reconciliation_purpose == "Opening Stock" else "No" + details = [] + for voucher_detail_no, sle in sle_map.items(): + details.append(frappe._dict({ + "name": voucher_detail_no, + "expense_account": default_expense_account, + "cost_center": default_cost_center, + "is_opening": is_opening + })) + return details else: details = self.get("items") From 97d2a46052917bfdb1aa02c28af7f177540834e9 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 20 May 2019 12:25:53 +0530 Subject: [PATCH 35/41] feat: added checkbox in the filter of general ledger to show opening entries --- erpnext/accounts/report/general_ledger/general_ledger.js | 5 +++++ erpnext/accounts/report/general_ledger/general_ledger.py | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.js b/erpnext/accounts/report/general_ledger/general_ledger.js index 2826760dd8..e74c16af6f 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.js +++ b/erpnext/accounts/report/general_ledger/general_ledger.js @@ -211,6 +211,11 @@ frappe.query_reports["General Ledger"] = { "label": __("Currency"), "fieldtype": "Select", "options": erpnext.get_presentation_currency_list() + }, + { + "fieldname": "show_opening_entries", + "label": __("Show Opening Entries"), + "fieldtype": "Check" } ] } diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index 44ca8d3549..1f1f738ff0 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -283,7 +283,8 @@ def get_accountwise_gle(filters, gl_entries, gle_map): from_date, to_date = getdate(filters.from_date), getdate(filters.to_date) for gle in gl_entries: - if gle.posting_date < from_date or cstr(gle.is_opening) == "Yes": + if (gle.posting_date < from_date or + (cstr(gle.is_opening) == "Yes" and not filters.get("show_opening_entries"))): update_value_in_dict(gle_map[gle.get(group_by)].totals, 'opening', gle) update_value_in_dict(totals, 'opening', gle) From 57c861efc3f37bc0ea55ddce620e94221f5007e8 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Mon, 20 May 2019 13:08:18 +0530 Subject: [PATCH 36/41] feat: add patch to create custom fields for india specific client --- erpnext/patches.txt | 5 +++-- .../v12_0/make_custom_fields_for_bank_remittance.py | 10 ++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 erpnext/patches/v12_0/make_custom_fields_for_bank_remittance.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index fce848ab5f..accdeeea35 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -568,7 +568,7 @@ execute:frappe.delete_doc_if_exists("Page", "sales-analytics") execute:frappe.delete_doc_if_exists("Page", "purchase-analytics") execute:frappe.delete_doc_if_exists("Page", "stock-analytics") execute:frappe.delete_doc_if_exists("Page", "production-analytics") -erpnext.patches.v11_0.ewaybill_fields_gst_india #2019-05-06 +erpnext.patches.v11_0.ewaybill_fields_gst_india #2019-05-01 erpnext.patches.v11_0.drop_column_max_days_allowed erpnext.patches.v10_0.update_user_image_in_employee erpnext.patches.v10_0.repost_gle_for_purchase_receipts_with_rejected_items @@ -600,4 +600,5 @@ erpnext.patches.v11_1.woocommerce_set_creation_user erpnext.patches.v11_1.set_salary_details_submittable erpnext.patches.v11_1.rename_depends_on_lwp execute:frappe.delete_doc("Report", "Inactive Items") -erpnext.patches.v11_1.delete_scheduling_tool \ No newline at end of file +erpnext.patches.v11_1.delete_scheduling_tool +erpnext.patches.v12_0.make_custom_fields_for_bank_remittance \ No newline at end of file diff --git a/erpnext/patches/v12_0/make_custom_fields_for_bank_remittance.py b/erpnext/patches/v12_0/make_custom_fields_for_bank_remittance.py new file mode 100644 index 0000000000..9925b70a96 --- /dev/null +++ b/erpnext/patches/v12_0/make_custom_fields_for_bank_remittance.py @@ -0,0 +1,10 @@ +from __future__ import unicode_literals +import frappe +from erpnext.regional.india.setup import make_custom_fields + +def execute(): + company = frappe.get_all('Company', filters = {'country': 'India'}) + if not company: + return + + make_custom_fields() \ No newline at end of file From 29d4ae671629adc295e9b1a1ee98df0387c2f221 Mon Sep 17 00:00:00 2001 From: Himanshu Date: Mon, 20 May 2019 15:14:07 +0530 Subject: [PATCH 37/41] feat(Communication): Move Timeline DocType and Name to Dynamic Links (#17593) * fix: ambigious error --- erpnext/accounts/party.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index f25473e308..29bae4b609 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -463,8 +463,8 @@ def get_timeline_data(doctype, name): after = add_years(None, -1).strftime('%Y-%m-%d') group_by='group by date(creation)' - data = get_communication_data(doctype, name, - fields=fields, after=after, group_by=group_by, as_dict=False) + data = get_communication_data(doctype, name, after=after, group_by='group by date(`tabCommunication`.creation)', + fields='date(`tabCommunication`.creation), count(`tabCommunication`.name)',as_dict=False) # fetch and append data from Activity Log data += frappe.db.sql("""select {fields} From 6358370735c432352fdc0109d08ed7a943d19b03 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Tue, 21 May 2019 01:46:55 +0530 Subject: [PATCH 38/41] fix: item group not disaplying in the website if shopping cart is disabled --- erpnext/setup/doctype/item_group/item_group.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/setup/doctype/item_group/item_group.py b/erpnext/setup/doctype/item_group/item_group.py index 37df150e17..cab21162c7 100644 --- a/erpnext/setup/doctype/item_group/item_group.py +++ b/erpnext/setup/doctype/item_group/item_group.py @@ -113,8 +113,9 @@ def get_product_list_for_group(product_group=None, start=0, limit=10, search=Non data = frappe.db.sql(query, {"product_group": product_group,"search": search, "today": nowdate()}, as_dict=1) data = adjust_qty_for_expired_items(data) - for item in data: - set_product_info_for_website(item) + if cint(frappe.db.get_single_value("Shopping Cart Settings", "enabled")): + for item in data: + set_product_info_for_website(item) return data From 8c78299158f7552abc028e5669564c60e772b6ea Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Tue, 21 May 2019 11:57:33 +0530 Subject: [PATCH 39/41] fix(readme): logo --- README.md | 2 +- erpnext/public/images/erpnext-logo.jpg | Bin 2776 -> 0 bytes erpnext/public/images/erpnext-logo.png | Bin 0 -> 11639 bytes 3 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 erpnext/public/images/erpnext-logo.jpg create mode 100644 erpnext/public/images/erpnext-logo.png diff --git a/README.md b/README.md index db8dd7904d..4d468be107 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@
- +

ERPNext

ERP made simple

diff --git a/erpnext/public/images/erpnext-logo.jpg b/erpnext/public/images/erpnext-logo.jpg deleted file mode 100644 index b5acc5af1a1df1ea1948ef3c97dea380ae8b384a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2776 zcmb7GdpuOz7vE=|n86G)lr(1YxRf+Ap2=fIQ6V)*7$A`PtbNu#Yk$|?-*x6Y=lcP{)n&a4 zfFK0G!41sIz-oX*AQTD<3Rbid8jV7sRj^o$5?%$5$Eo0Os%jbpRW+g-4oA=;5H(3; zG8wO~y+Dh!K!ZdkDHef{un!8Yj7BSyRB@`L|6At8fT#q5KoAll0t6945~2A(!~#3lgTYYxiJZ_PL# zTeJ>dS2;c1tv=!A#m-2CxhTEp!?H2xq$x$7(k9i~m_~rx;(q6E$}& z>8lE%%Hhv4r(J`I+l&nd6S-uYQ{2z(UmC`PZ0xEV4z{3MOo<)NodXJ+WF>9%zBZn* z=-L9(Vx8Y^pLP$-$m}p%9Z)XXBvdc<`mFV$veGMjoVhklDxaBn^sYm%l8XkJ9bYIe zLF2a31(L=l-4Atze?Hk5Ff{RGqfeAcPE|>k(FW#R{w!BJth)UbcjvQNZ=Jav9VAni z`@;77-dkLjkLT1^CYvsUw@ro5350^v|6l&$Q%%&+q$6oe0*mo&&+x1x6miALyTEmb z-D6*H;*;L5X!jboHL!+}q>qLvNlk6~?x%2?#To7P$I~9~Ch2d~tIRFG8_3^a7h4=> z#h;np(W2!mlz85OF8yz}7c)Ow{Hk8FLaotNZGfCE8umuk{{}~6K?DE|A#n&4_Inl} z1bmx_WV!~4#<1Xcdhv^-1c4?yP)J>(&ty3ze2WmFh_IyXQ023T$uIXqESi10LmHU3 zd~@A)u>DUrZ{pu%-ryZ=qIWS{xhrxEy7{gVgK?OPGsSByi+!IOjH~xNjQlAt_O*Gl z-Tlvu!u7B9em@b^@x+Pinb!2V-zR+auoF}HQRc7v%xQ<#^!5Zuts}H8HuN?gAr2OL z1-B*mb*Yysebn^0e1CdD{m#+fLYI8W5XaOdFO~QCS@{SG=X9Pl#jGAeKy1VIlN}i{CQ$Aks0*Cg+4=fcdv&vt1V2m3w^pCQ$)^i=#k++*Cl@9XQPXqT> zgl-?V*P2u}m)d$23o7b5t<$s)WdBvywbMDMye;;cMPFIAv)S3T7V#3gpLp|%se;MI zJ-DnqdGK{Ip}O49$MhO0OZ+G9<-M2u$?N`YM#rBU@cJuyb?1TCv;9}+u9Wq1rZ;ZB zQ#@99&Dk({?TgNb_hirOxQUU-epeoS9^{=O|9UyP3GnIV#|$ zL|?~fxNM9PVYxrU)KGwgEa!rHbxbdqoE);5ii7w5t>^#+M1&j}uSUQV$#~T=MSm+P zOC$@4lk-HK@m4aPFup=0+YQ@Aw?tO5ayOnlLGjjk*wDF7F;H-d9uWpzQT~1~93avI z2{bB$&tiXrT0wAxF8%j5f{|*fA31%^wb6vM)(r-*3Z1Ib8%M!R0IkYsER@=jx@q}2 zqo%M8gZA~z@MZM;eRRk2gXy9_u6V?_)A ziG_*wUtUuro)JiAbNC4jqkBeXQofv$G?i`PV0> zbE?H<`$JXsPdXse#(NgAdMhXNmby`tEh&APoDXuvXKH zD|cws3s$d5Hovu0=M^hfD+9$b?_QZ~s7uhTJ~|IVcVFOYW~%ti)W!r@C~*er#x-3w zi67IK)e3zWHc(kZv}{{`@Dz-fK0#4vk*FU(EfA3g7;HKxkWWn@u;haOt_Y!y_R6Qr z!;9L#q+2D%KXanW4)taTgJ_&>D*;jW%s8@8-8cB85YB*&%W<)7vG8P2v4k}m#-J(} zN>-7!b$s%QH#A^!GX3^wuYQIyj;U}|Zo8sAEn238={dCLoTS@-F*x9HP!G?4xXU%l zDlqnm?J7gL>cV97nf^FtkmwmMeVVYprM0tGO0sl+uRc_?9x!coq0epvrJ+%q@|`4No$o# zPUDH9>Fo}he?49LUi~U>)3JP~WAtD$DeCM8>yVqtai*uXK_ly$QX7v9GZDK~HKcEP ze%8sOc$^a*MsE>b8=*Ze~3yI8hqNa=ZRKsf}dSqo`>TMRjkCluOj{*md Ju4Bf0*WVV!XQTiC diff --git a/erpnext/public/images/erpnext-logo.png b/erpnext/public/images/erpnext-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..115faaa6a8f389d8324950b887e70c24acceb718 GIT binary patch literal 11639 zcmeG?_g_=nlQ$ti0BIskDG?NG6rU&^f>NXeP^3wV`V^!X5HR#4q6pILBGN1f(oyLG zK`AOIN*5^+5D207638AB-hOv~*neO@@2BM6J7>5Ua$*Y1q zAmhH@sxbYqn3R<=`{~bZ#G1t0@jHcH&xq%IzOkQiYJYiPlXNk`EWCGzhL3wz(;mam zs0e+J`ZsNdWnaL%1s@oR-{|@nY0_G}Z*~;Fq-{^TrrOsRdZj;jv2vtvX*DTpP}?JQ z-LAUX-M+t~S!d1WM@>Vyf2HVnw{UjwT8po7l6a-v!xZ_9(-tuYwC9?`o1K;7s3_7s zqyP$yGqrmwBco62Ww$mzZntUOgC;^Scr1HM&#Zo;gOssu_1irIaaJx;co%=` zqPH`A^4O0Z?8INVDTT_Zlu~bklA!Km z4k9g&mRv@_Ii{M=RLdq0xEy;OuxhZ$5#o~2Nom1xQ`a1vL%CK*zxRoSX-`_L$BI5X zk=8l?t#_AC=vZ4dMu<@U?L+wH0^~af6g%m)pUB!=qijchzg@5H{&q8c$gZLoA7)}K zZGL~_sT{kZ?xygG;g7G ziU8`n4oNxVjf#U?Hc!BB)`98Q?<#C*j?tNXNMER$}tG_){YX{v6` zXnmpPuCrUoCCtMW1t&FR(9qS^`m0_#-{R!XikKb zX(tE$-0Caxt8*QHwZ%gn&b@2cM0)i@Zsiqz-yIWAH>oS%;~kWuIVYjf^gQA!2g>CS zVWNB4u6(YBGva69njBL!P9k=v>r(qmck8Ic;J6M2LCZt(!Huf8IExIP^}e5f^iJ*C z)Q^Bz6k0gdspvpn>Fk#SP6tZ^;thDAU8;*VSAL1OoV?Gt7~N?QEW<>3ljqD#k(EVk zNv^$>m&>6j10IOVzx+O+zi-)OtcyLmU43mg6A+OiTI%|9c6ojN*3GaL`aSmdb`PSV zIoyUEgFWUthRG|r2QE5PcC5L~H(z6ECl4RAa)d!`-3XgYb@;WDDL3pn0HLnhT*>nb zb7+1U2nIK%4%^8g^tc*Zd$yc@QdE4#G3p-+S^S4LH-l4Qq3=sHc7 z$^4*bfG72h8t%I;N@cnPnsr$)ElQ*}=u(1MvUx+Ma*hm>R5-YyPRHJgFRAmApE|#= zI39%uUis!bkK#;RGJ-l?dNnnBZ!Gt{^G#jjm+^FBlBv9tRC)Qj4q+YB9zLhu^Zpw& zG_`XwcR;C?53@0Ms)&!J)k^ZLmTmLW1~kVFd34sVwR{azlnPadJIP|B$pQ7Xz14S7 z>sZ2^EYY79q}09PsC94A|BKe5tMHaQ-oq{Ow07I%JJ_y|x%DQ@Z6n7`_?+k_eP+1b z?qe}~U)K9eP1#zew#Jw^(eGpGT(H$l@4H(s^6+i40r#0FNkFU!t<;Me#kcTYpRHR9 zl{V64`yS1ok!!XQN<1EC3I*PIzF$j9;eM{q?AeZMnsk~n znX$}6Ti2agMKS!TXNl4s!mAe3RzAs}tIg9fO!VD*m9-yds8_n=$E&dwT)|AelN8j& z>{6ipXNzD&i#;*4!RYY`0 z**w$C$&3*guHQ~h`_D+ScqQWyvl6Kzt0zoT_@VwaXU7LsYlQA+s&tkp5gL2$3@=m5 zHn7HE`RmuEFHc-NaFeBpOs=LRS}H$8jey{2UK5sn{EV@~j=GZ26%foES5qiAoerE< z*xKqhJTR}>H_TZ>5-RqJif*L|-^zc*3I#|%Gi+UrIs*-Lxzwdg9<)^7QiU|>b-473 zbSVd!%Fxjl5oDgzNv@aqY|am|H3Xn6wYR~0vm#j(sU4?Kl3a2fI)iH#M+T^}HU%vE z6c~L;{vtH+a&N`8x-oN`jD1^z1QK3*{PHPWZN2|-!*S-z?--KS(ufC?1REV*&brOS z+ay;IWL(Z*Wc}TblpgS(RW1XJN37<1QTFX2?fpL3m-7C`JDy0=cfOs5%X!42MMh^9oox08_6O9kcRgA+pH70&W<2%C_dWG6uUWqOO|r3 zV<}++4o4G2Oi{}*jx?K85i9JASNav}r1iVJ3>O8E>#Q3H?Ha;-dZmL`N` zo3^g-agF~JD)b$}rDzr#c?QZ16iOS>=Q9LXLiyqM_n{!Ofy^B}8CK>|YP6ilBQCpU z9IAy2{Vvytnc!}ceHsjgMw%Laj!3v+Fb1BObCjwzS>VO^Zrpf63&dcP;O&Xo!IeJO z$c0>glkQu@m5#>>RC}DKWC3>){iL^~fQwR-b?Tqh)e$Y!b~-}Q!%D!-i{no89v)1Z7pFcX zoS$8?c;-kt(yTSjAcYiWbCP_JNNCVfiJpK9I8j^CCs`O0_*>wMk~8I9t4!aVRA=Q5 z2LCxT2u@C*m}-yHTnLo&)u(B;s-$wVc(!cc{P5~&FZf4r>LYODNKSU=6%)p@xp)#< zmn0G6GJ7v<%FYlQ0Ed&OJtqPq&{aOo6|Jw$ZC9JoGxx}PBzk)%Ayk|X{z6y)GNd_; z|LEITj1;XZ=$aKa$C{JgHpi(gw5i*^g_8_~1R#;vmbgnopE5R@gL*xu&YBa^BA;Ag zvn3a_kTE7`NbI3sO+(qxz3b7o8YCFPrt%W;VXg_51a^nRyu$oQkE>J$QZs_rf(1~@ zCFm-3o2mnD91Xek-k~bP;7-C_^cQ(Hukws{2taZ^XXc|Ik_>y; zbhu2T&3poo!r>atL%=s*;?|nCtR0MRb{sfL`VE-+xKM-#4!mjqcbY-S#MH3kS8jxe zH5#%zW3CB;2$=%!XE@hBQV7Sn^1yinfw4SybpQ(vSyI3$580UG>52Nvr2^EsGwtUM z5UZkhPdB<4hOD*v2bdBF-yRi>{6jB1I5jTp7<%osaDNCJs6Cv%MS3x zSfctTlw78lVsZLI(F~v=Q=sd|?+3S|EFX|lv<3SaVYNCC1eU;RTb=~NI>6*ykso1Wf?DeCs(=W7Fq9^TohF5lkr3~RG z&F%*WO_~YO<0J(gQq`u7LW{4&CL|t+GpJDj44(bVvRplcRK2XP&j*tNac`dyAofK_Nguy>ZG$mKj4cxscFN0SpW3I@t5WzHH`29oYs@?~IgVLhaK- zL;KD>XlJGJ?f^BfJ}Z@bfI>kJl)t#M2t5i=b38X@CJZJ(StkFo^RIUPHMakCb{gHi zFz`BVdPRxRc(0Y`O0GhP#m=`*6|KIVH6!05y?)6^5wy-be&{)=ICRsx_96{WHyHg3SSO)NVyG2_pIM41H$YUW%;{jkCbc zgV&>9CGSEcE}>7I@Fd@FH~dZT$Zht(HUCx6D}?&aM{4X7yIZX>s+YC{xR?ibZRBBa zBjHa=+tg_OMox845gL2JWyM`h_ym!B9AT4McqiA(G|dS(s)~A39G8IDb8=SaHlLAe z80-h&*SK~G^zKGuL*PnbKDD3a~r=w^-IqyGJFvtz_i;ix>tNhmXDCfWg_h#=A~g7Mdu4TiL## zWnl{<+6mjRxVqg7-U}jbxq4m}Son;11mgYe*`WbM;eX=QM+9=46{Tz>q71(#r>qXR z7>c=>0+OUlq|h~BOd(Cl-T`n~knR{FCX^9Kvnuk1c!MDUieB1(Lc!d25ZMEBFYSdV z0}W~%j=2p=(}xjKL2ic^&r2h^ccY+p7n0`hL8RTAs*9432ob1|SJnf&A$TM5z;03` zXQcrTf@;bI%>yJK5LO27;T=I0#gIbclqvRnk}x@nB;5s(O!nM00r1`$Yr5Lq&sa^p z->tbWqpSt2E}(ePj7Yx0qqXi=o1r6I=-PY(e`X1}O%MB1VDa)}5WW%uNFg=-E{vr} z*OVvAd1ENjGl22Lxgx7gj3}3Bd}p$t%f{8(jrIH8rT}dSK)YNY2T}~cIL1J0_GGPU zwcyO?3!(43oq&kI=O#AFG!UUJrL#J&l(7*x6{0!tIwKiOdoi7xIF7PMKQMZlI||3=h*6NG=$H*muK%|`z(S5T01L#F*CRtJ92 zMqk3WDWu~aA4!(|)hn6B3C*izdx6hGLkVqnf8^igajd*Fbjyz%$2HzBT^Nk7&2yrb z9T|AyDl5gXuWjbjNewH%zIWw?5y&0;ray=pI$pD{-PI>B^HJI`WZ|HoE+dd6V3L9a zUQ{MRPaa%ijIqY$^wpfVGB){f%O>0~e6RQq+QU6*9mWFF3PfWu_E6ybPLeKCZ3|SZ z)d%7k7iwq!7;N7c6aylO*osS zUXz0h4ktecg~n)e_gf$;xXF3{HW18LfAO=pSVnm>7H1|bfNPMlK1sF8CsMP-1AYWV zeQ_~oaBIT$!1IIJe=qTg;RzDe6+j&L1{+Y+e|Ls*z5nv%2LB4{O%X+yx^jU#8Kpgc zF_yT!KCtH~H#8^(YXDt9GzQggzI;(BTcK@F!6!hsOnA2>xF?C6proe1g`_~5g@U$O zl~6(}vM<+!=g%7ms!`da-|W)dt(*;rI~c1fB6EkaBMTG?zOu);{0wn$*q#s%zDVz- zZ96pGvq(}cguwvKv;O}R+mryrEft!s6hVXv#BMM8sK8(pH;q0Iu);T1wP-gCZj7a# z-iC-c2)6Gm>8ixxInufcZPj4#2@uq~51Z%G{Ros<}CH{$IedIVu^3F?? z_i(||8eeD*cOPT8HA#XbLqVkLxART~smg19PLNxJTG5-w7FvS8e?hqt8p$aTDMT`s zlXPyg9?(`aRXQStL?BfJ1I8OL#cy~?D?p)hC2uaVk#M0$KD0OSQan$;BZFw`P`m?^ zwk)`rI-nI-1XjYJr^g;1O1lOR=b;Z3My6C}9#u=rBnA0b za$k{>FeXB!Ymz_G~9@fP>)ZVucIs5(%SJMepKYiraehAp@ z>Gpg>`Y1ybF!Z5AXeaRSIxt&H3N#`EYeG*D@F$$T%nF?Djsj+7rwXNu_RpTTV%9?BJ zA81k4cl6e)ZAsThKG=Q7Vu|s!Umw&nFSccW`3!0VayYZw6F;JzcgzG=i~4lXWX#o` z*>T*&+hIXov^EvJ+)*MkE8RGYQZ@%iK4~>hJDYsaS%lp5lJG&kB;il49J6z!gECp}-@fLcv46u? zJVI6u=B=zgk_6r>G((r6K2CS21`BuC9g9kCkq7Ookis)z8?%oW@b5M&9cfWS98BfZ zTV7_N!mSJ#>nyA-lv&XDt`90#&oAv_JzNEm<_}xu8mkHt1pxKG9%DWH0VlqZ({hPb zIuQbZQHfrxHbo;aoJag=ldR^i8~_wL`fIa{2az5DgH@15_p$~9Fu=pexfiqA(F&lX zdRB*6Zow>tBm&dLw0W}nxn~tYDjfp(rvgv6Y5oFGV&=~X=EFNjK<^4Pro-Yz1_k}g z*#8@iVU4ZpQsj1Zvs5kMmI3;TbK*qTUq3@DSq)gkPHwG(kjjI%tVW(&Au!Q_npS_7 z`JO?s6I0@$#Ic{OUfsLXpp~ctcl+~+s=~AvyE|xZ$eJFcS5a`7`2zJ_k)*OT0u_`w zRd#GvQ-RrH_28E$T~31mBcAT4Sf;&0Bpa@wGJ_a8$L{%gjGv;TJQbd`|*B;1)*D;jZD1EeUk*^LG1|$_HgsX-%3Nj99o&DOuQ z#oP){Q^IBk+Vo&2tjXp3RuME5eq>~IgpC|1`Z6BM>guk#I-kHIEWrx(b*9yKy+#-; zdhFsnVd27C>iP)zmW)mroO2{(4uWR)d#t_E74`XuRHkr=Xgp%fH-sB;OSi>~ zG-ZM3(ioXeKfCqKfxYE#2D*HGs_e)bp-Y@dH$3~EWqNG+Lt`FJ(&Az9$UfSGjfzN0wCpwB1uWmJT+ zp`CH|!h{aj(CDopmPg1#@f+3aBa_WLp$=Tmq(uf_RolIt{#%0<3A^u%Olv)Ew)5+1 zv}YsFpS2Fzvu@@pptZGJgloQKX>|@vSqx^vupcAF`W~P*+&gkB^;lXpOG2kq%t?g3 zi<3MG4e`dih39mUCNYa@oYcRd{$TQS=RGy+2`fprV2*8Hy?=6}uC-r|P~Orv#2- zr!WT|FPZd|bF7vOqtx%p&S(*iASA>M1QAJ@xh#Vhal+zK?$7mTjizvdNhOFn41e0< z%IU$W%}i}K<4>K?CtshG`%lLUPeGqJyS=RzX7*as1Mi3b<74a+&?(__jy--#Y%U13 zIrPc~)R`0O&}u-MN+|2`*rFv8ZXI$gw4c#CxBkVYIz>f??GFACKYh%4W~wzAUfqEk zdBkkygQm-&JHtKJ*#oz4nr)OB@c;>N+B(}$XfLz{I0OY+Tw!)!fKi(xu5xzdye?L9kg85~=7#Y|3T_QjZNQh9(^%{MQl8Z7d9X}r_rdzUFJ8X}c&IoI zM;n60*7$f3@Nx_f+uI0`Mgv<1%$7Iyd#waj z)TvGAzLk%bf@Z(Xm9XVG?UH^vR>yfss_7q&H{dJTVX9Xm`4#4`SBDu%m_TZNX+^e6 zItd$6za!e5!`z;19cXeAJh&B6d2M(9Tq+HDf)`q$cyul*j$`UZS{hqN#$x_Cq5+5c z`%0*i8^g4cef@B??wYGG)5mpzD@wwWUfNTvVTcy?S;r?MP3J5&eg=+$`3}C}qqa+V ziMLA+E6m*`n~CK!^BF%!yE6D&O zOm)4D!8041W*YYGt}7{_9= z=_6S_qn*$^4Xx-mSU+ZU&?2&(Iv2-C>M(W@ncmE9U~mKE{A|zT5wezO+=bcZFBjC= zET#MAF{C*w#IkpJ;PUKO zl5}O|M{k90tqy>)?WU@>kyNM_=`L5R3vzDjI#d^y6AmwyiLE7MLf)Baeuk8yC|dar zMBm-(L#7SDmy!o%6(fC(9h`y&O zBNAsPS=%I>A*mGV+({{su&s0L^vWqV_tup!^0>8hkPzzaa#Rx0_i%gr>4Vg|X zVhS-C z^^%`_6KH$L%wR!CrmE6aO0<%O6ELR1GYkJr?fUAiNzB#f@m8jMpJ(4kz_qJx%GKwTKWOef}0LL{kd6(F)kV6RF~iCSg5W* n`1|v{faQNCip%Tg7_fs)7Fl=4t)GEOYRK5YTtDwP_WFMTgYc}M literal 0 HcmV?d00001 From 7327f8a90180dab331bf22cd05ac67ce006e971f Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 21 May 2019 15:05:26 +0530 Subject: [PATCH 40/41] fix: Person / Org name is not mandatory while creation of lead from email (#17676) --- erpnext/crm/doctype/lead/lead.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/crm/doctype/lead/lead.py b/erpnext/crm/doctype/lead/lead.py index 6e98ebb6c0..4f507f1b46 100644 --- a/erpnext/crm/doctype/lead/lead.py +++ b/erpnext/crm/doctype/lead/lead.py @@ -110,7 +110,7 @@ class Lead(SellingController): def set_lead_name(self): if not self.lead_name: # Check for leads being created through data import - if not self.company_name: + if not self.company_name and not self.flags.ignore_mandatory: frappe.throw(_("A Lead requires either a person's name or an organization's name")) self.lead_name = self.company_name From 68a145667269872e9ef7735606be787f7406cc94 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 22 May 2019 13:17:46 +0530 Subject: [PATCH 41/41] fix: removed translation for customer type and tax charge type --- erpnext/regional/italy/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/regional/italy/utils.py b/erpnext/regional/italy/utils.py index 88e7c3e6f4..0c421244ca 100644 --- a/erpnext/regional/italy/utils.py +++ b/erpnext/regional/italy/utils.py @@ -75,7 +75,7 @@ def prepare_invoice(invoice, progressive_number): invoice.tax_data = tax_data #Check if stamp duty (Bollo) of 2 EUR exists. - stamp_duty_charge_row = next((tax for tax in invoice.taxes if tax.charge_type == _("Actual") and tax.tax_amount == 2.0 ), None) + stamp_duty_charge_row = next((tax for tax in invoice.taxes if tax.charge_type == "Actual" and tax.tax_amount == 2.0 ), None) if stamp_duty_charge_row: invoice.stamp_duty = stamp_duty_charge_row.tax_amount @@ -222,7 +222,7 @@ def sales_invoice_validate(doc): #Validate customer details customer = frappe.get_doc("Customer", doc.customer) - if customer.customer_type == _("Individual"): + if customer.customer_type == "Individual": doc.customer_fiscal_code = customer.fiscal_code if not doc.customer_fiscal_code: frappe.throw(_("Please set Fiscal Code for the customer '%s'" % doc.customer), title=_("E-Invoicing Information Missing"))