From 28890fa833b31a40fd4f11affef4a15274335ebb Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 30 Jul 2024 17:20:21 +0530 Subject: [PATCH 1/6] feat: report to identify incorrectly cleared cheques --- .../__init__.py | 0 ...heques_and_deposits_incorrectly_cleared.js | 6 ++++ ...ques_and_deposits_incorrectly_cleared.json | 29 +++++++++++++++++++ ...heques_and_deposits_incorrectly_cleared.py | 9 ++++++ 4 files changed, 44 insertions(+) create mode 100644 erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/__init__.py create mode 100644 erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.js create mode 100644 erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.json create mode 100644 erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.py diff --git a/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/__init__.py b/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.js b/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.js new file mode 100644 index 000000000000..f28714d70faf --- /dev/null +++ b/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.js @@ -0,0 +1,6 @@ +// Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.query_reports["Cheques and Deposits Incorrectly cleared"] = { + filters: [], +}; diff --git a/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.json b/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.json new file mode 100644 index 000000000000..50cf765ca3d4 --- /dev/null +++ b/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.json @@ -0,0 +1,29 @@ +{ + "add_total_row": 0, + "columns": [], + "creation": "2024-07-30 17:20:07.570971", + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "filters": [], + "idx": 0, + "is_standard": "Yes", + "letterhead": null, + "modified": "2024-07-30 17:20:07.570971", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Cheques and Deposits Incorrectly cleared", + "owner": "Administrator", + "prepared_report": 0, + "ref_doctype": "Payment Entry", + "report_name": "Cheques and Deposits Incorrectly cleared", + "report_type": "Script Report", + "roles": [ + { + "role": "Accounts User" + }, + { + "role": "Accounts Manager" + } + ] +} \ No newline at end of file diff --git a/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.py b/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.py new file mode 100644 index 000000000000..9a1d41262fc8 --- /dev/null +++ b/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.py @@ -0,0 +1,9 @@ +# Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +# import frappe + + +def execute(filters=None): + columns, data = [], [] + return columns, data From ceaa1be72935e8bd46921f465659d04edb164482 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 30 Jul 2024 17:24:46 +0530 Subject: [PATCH 2/6] refactor: barebones functions --- ...heques_and_deposits_incorrectly_cleared.js | 45 ++++++++++++++++++- ...heques_and_deposits_incorrectly_cleared.py | 37 ++++++++++++++- 2 files changed, 80 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.js b/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.js index f28714d70faf..f2554c4442cc 100644 --- a/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.js +++ b/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.js @@ -2,5 +2,48 @@ // For license information, please see license.txt frappe.query_reports["Cheques and Deposits Incorrectly cleared"] = { - filters: [], + filters: [ + { + fieldname: "company", + label: __("Company"), + fieldtype: "Link", + options: "Company", + reqd: 1, + default: frappe.defaults.get_user_default("Company"), + }, + { + fieldname: "account", + label: __("Bank Account"), + fieldtype: "Link", + options: "Account", + default: frappe.defaults.get_user_default("Company") + ? locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"] + : "", + reqd: 1, + get_query: function () { + var company = frappe.query_report.get_filter_value("company"); + return { + query: "erpnext.controllers.queries.get_account_list", + filters: [ + ["Account", "account_type", "in", "Bank, Cash"], + ["Account", "is_group", "=", 0], + ["Account", "disabled", "=", 0], + ["Account", "company", "=", company], + ], + }; + }, + }, + { + fieldname: "report_date", + label: __("Date"), + fieldtype: "Date", + default: frappe.datetime.get_today(), + reqd: 1, + }, + { + fieldname: "include_pos_transactions", + label: __("Include POS Transactions"), + fieldtype: "Check", + }, + ], }; diff --git a/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.py b/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.py index 9a1d41262fc8..774c843b90aa 100644 --- a/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.py +++ b/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.py @@ -1,9 +1,44 @@ # Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt -# import frappe +import frappe +from frappe import _ def execute(filters=None): columns, data = [], [] return columns, data + + +def get_columns(): + return [ + {"fieldname": "posting_date", "label": _("Posting Date"), "fieldtype": "Date", "width": 90}, + { + "fieldname": "payment_document", + "label": _("Payment Document Type"), + "fieldtype": "Data", + "width": 220, + }, + { + "fieldname": "payment_entry", + "label": _("Payment Document"), + "fieldtype": "Dynamic Link", + "options": "payment_document", + "width": 220, + }, + { + "fieldname": "debit", + "label": _("Debit"), + "fieldtype": "Currency", + "options": "account_currency", + "width": 120, + }, + { + "fieldname": "credit", + "label": _("Credit"), + "fieldtype": "Currency", + "options": "account_currency", + "width": 120, + }, + {"fieldname": "clearance_date", "label": _("Clearance Date"), "fieldtype": "Date", "width": 110}, + ] From 4cd023444acc8b951d24c1a04ec8bbb120c4aeb7 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 30 Jul 2024 17:52:52 +0530 Subject: [PATCH 3/6] refactor: working state with minimum functions --- ...heques_and_deposits_incorrectly_cleared.py | 71 ++++++++++++++++++- 1 file changed, 69 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.py b/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.py index 774c843b90aa..14295a5a7115 100644 --- a/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.py +++ b/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.py @@ -2,14 +2,80 @@ # For license information, please see license.txt import frappe -from frappe import _ +from frappe import _, qb +from frappe.query_builder import CustomFunction def execute(filters=None): - columns, data = [], [] + columns = get_columns() + data = build_data(filters) return columns, data +def build_data(filters): + vouchers = get_amounts_not_reflected_in_system_for_bank_reconciliation_statement(filters) + data = [] + for x in vouchers: + data.append( + frappe._dict( + payment_document="Payment Entry", + payment_entry=x.name, + debit=x.amount, + credit=0, + posting_date=x.posting_date, + clearance_date=x.clearance_date, + ) + ) + return data + + +def get_amounts_not_reflected_in_system_for_bank_reconciliation_statement(filters): + je = qb.DocType("Journal Entry") + jea = qb.DocType("Journal Entry Account") + + journals = ( + qb.from_(je) + .inner_join(jea) + .on(je.name == jea.parent) + .select( + je.name, + jea.debit_in_account_currency, + jea.credit_in_account_currency, + je.posting_date, + je.clearance_date, + ) + .where( + je.docstatus.eq(1) + & jea.account.eq(filters.account) + & je.posting_date.gt(filters.report_date) + & je.clearance_date.lte(filters.report_date) + & (je.is_opening.isnull() | je.is_opening.eq("No")) + ) + .run(as_dict=1) + ) + + ifelse = CustomFunction("IF", ["condition", "then", "else"]) + pe = qb.DocType("Payment Entry") + payments = ( + qb.from_(pe) + .select( + pe.name, + ifelse(pe.paid_from.eq(filters.account), pe.paid_amount, pe.received_amount).as_("amount"), + pe.posting_date, + pe.clearance_date, + ) + .where( + pe.docstatus.eq(1) + & (pe.paid_from.eq(filters.account) | pe.paid_to.eq(filters.account)) + & pe.posting_date.gt(filters.report_date) + & pe.clearance_date.lte(filters.report_date) + ) + .run(as_dict=1) + ) + + return journals + payments + + def get_columns(): return [ {"fieldname": "posting_date", "label": _("Posting Date"), "fieldtype": "Date", "width": 90}, @@ -40,5 +106,6 @@ def get_columns(): "options": "account_currency", "width": 120, }, + {"fieldname": "posting_date", "label": _("Posting Date"), "fieldtype": "Date", "width": 110}, {"fieldname": "clearance_date", "label": _("Clearance Date"), "fieldtype": "Date", "width": 110}, ] From 784dec24c8c521461f232658aca8c58c82c39ff8 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 31 Jul 2024 17:57:25 +0530 Subject: [PATCH 4/6] refactor: build dict for payment entry --- ...heques_and_deposits_incorrectly_cleared.py | 44 ++++++++++++++----- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.py b/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.py index 14295a5a7115..995ce4efd0b6 100644 --- a/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.py +++ b/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.py @@ -4,6 +4,7 @@ import frappe from frappe import _, qb from frappe.query_builder import CustomFunction +from frappe.query_builder.custom import ConstantColumn def execute(filters=None): @@ -12,20 +13,39 @@ def execute(filters=None): return columns, data +def build_payment_entry_dict(row: dict) -> dict: + row_dict = frappe._dict() + row_dict.update( + { + "payment_document": row.get("doctype"), + "payment_entry": row.get("name"), + "posting_date": row.get("posting_date"), + "clearance_date": row.get("clearance_date"), + } + ) + if row.get("payment_type") == "Receive" and row.get("party_type") in ["Customer", "Supplier"]: + row_dict.update( + { + "debit": row.get("amount"), + "credit": 0, + } + ) + else: + row_dict.update( + { + "debit": 0, + "credit": row.get("amount"), + } + ) + return row_dict + + def build_data(filters): vouchers = get_amounts_not_reflected_in_system_for_bank_reconciliation_statement(filters) data = [] for x in vouchers: - data.append( - frappe._dict( - payment_document="Payment Entry", - payment_entry=x.name, - debit=x.amount, - credit=0, - posting_date=x.posting_date, - clearance_date=x.clearance_date, - ) - ) + if x.doctype == "Payment Entry": + data.append(build_payment_entry_dict(x)) return data @@ -56,11 +76,15 @@ def get_amounts_not_reflected_in_system_for_bank_reconciliation_statement(filter ifelse = CustomFunction("IF", ["condition", "then", "else"]) pe = qb.DocType("Payment Entry") + doctype_name = ConstantColumn("Payment Entry") payments = ( qb.from_(pe) .select( + doctype_name.as_("doctype"), pe.name, ifelse(pe.paid_from.eq(filters.account), pe.paid_amount, pe.received_amount).as_("amount"), + pe.payment_type, + pe.party_type, pe.posting_date, pe.clearance_date, ) From 74b36db24e54e8e0a881259f51e79270a7057be2 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 26 Aug 2024 14:16:32 +0530 Subject: [PATCH 5/6] chore: remove redundant column --- .../cheques_and_deposits_incorrectly_cleared.py | 1 - 1 file changed, 1 deletion(-) diff --git a/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.py b/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.py index 995ce4efd0b6..6bb090fd1b72 100644 --- a/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.py +++ b/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.py @@ -102,7 +102,6 @@ def get_amounts_not_reflected_in_system_for_bank_reconciliation_statement(filter def get_columns(): return [ - {"fieldname": "posting_date", "label": _("Posting Date"), "fieldtype": "Date", "width": 90}, { "fieldname": "payment_document", "label": _("Payment Document Type"), From 2144e0337d8194e466c315b8585872f8b21b7a44 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 26 Aug 2024 14:29:47 +0530 Subject: [PATCH 6/6] refactor: build dictionary for Journal remove redundant filter --- ...heques_and_deposits_incorrectly_cleared.js | 5 ----- ...heques_and_deposits_incorrectly_cleared.py | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.js b/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.js index f2554c4442cc..e83fc6f5b57b 100644 --- a/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.js +++ b/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.js @@ -40,10 +40,5 @@ frappe.query_reports["Cheques and Deposits Incorrectly cleared"] = { default: frappe.datetime.get_today(), reqd: 1, }, - { - fieldname: "include_pos_transactions", - label: __("Include POS Transactions"), - fieldtype: "Check", - }, ], }; diff --git a/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.py b/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.py index 6bb090fd1b72..891dc2c4bb10 100644 --- a/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.py +++ b/erpnext/accounts/report/cheques_and_deposits_incorrectly_cleared/cheques_and_deposits_incorrectly_cleared.py @@ -40,24 +40,43 @@ def build_payment_entry_dict(row: dict) -> dict: return row_dict +def build_journal_entry_dict(row: dict) -> dict: + row_dict = frappe._dict() + row_dict.update( + { + "payment_document": row.get("doctype"), + "payment_entry": row.get("name"), + "posting_date": row.get("posting_date"), + "clearance_date": row.get("clearance_date"), + "debit": row.get("debit_in_account_currency"), + "credit": row.get("credit_in_account_currency"), + } + ) + return row_dict + + def build_data(filters): vouchers = get_amounts_not_reflected_in_system_for_bank_reconciliation_statement(filters) data = [] for x in vouchers: if x.doctype == "Payment Entry": data.append(build_payment_entry_dict(x)) + elif x.doctype == "Journal Entry": + data.append(build_journal_entry_dict(x)) return data def get_amounts_not_reflected_in_system_for_bank_reconciliation_statement(filters): je = qb.DocType("Journal Entry") jea = qb.DocType("Journal Entry Account") + doctype_name = ConstantColumn("Journal Entry") journals = ( qb.from_(je) .inner_join(jea) .on(je.name == jea.parent) .select( + doctype_name.as_("doctype"), je.name, jea.debit_in_account_currency, jea.credit_in_account_currency,