From f5a1bea189bc177a6cc8d88801c1d0aad1661d0b Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Wed, 1 May 2019 18:46:30 +0530 Subject: [PATCH 01/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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/35] 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 cd4289e10e4a3e8be392c98d325a7583f515c920 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Sat, 11 May 2019 20:04:03 +0530 Subject: [PATCH 25/35] 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 26/35] 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 27/35] 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 28/35] 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 29/35] 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 30/35] 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 31/35] 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 32/35] 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 97d2a46052917bfdb1aa02c28af7f177540834e9 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 20 May 2019 12:25:53 +0530 Subject: [PATCH 33/35] 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 34/35] 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 35/35] 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}