From fc6be5bfb9a2cf1a79d0150fc5867ba0cb988f64 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Sat, 26 Aug 2023 20:29:50 +0530 Subject: [PATCH] feat: UI for unreconcile --- .../doctype/sales_invoice/sales_invoice.js | 44 +++++++++++++++++ .../unreconcile_payments.py | 49 ++++++++++++++++++- 2 files changed, 92 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index 642e99cd58a..fe931ee822c 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -183,6 +183,50 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends e }, __('Create')); } } + + if (doc.docstatus == 1) { + frappe.call({ + "method": "erpnext.accounts.doctype.unreconcile_payments.unreconcile_payments.doc_has_payments", + "args": { + "doctype": this.frm.doc.doctype, + "docname": this.frm.doc.name + }, + callback: function(r) { + if (r.message) { + me.frm.add_custom_button(__("Un-Reconcile"), function() { + me.unreconcile_prompt(); + }); + } + } + }); + } + } + + unreconcile_prompt() { + // get linked payments + let query_args = { + query:"erpnext.accounts.doctype.unreconcile_payments.unreconcile_payments.get_linked_payments_for_doc", + filters: { + doctype: this.frm.doc.doctype, + docname: this.frm.doc.name + } + } + + new frappe.ui.form.MultiSelectDialog({ + doctype: "Payment Ledger Entry", + target: this.cur_frm, + setters: { }, + add_filters_group: 0, + date_field: "posting_date", + columns: ["voucher_type", "voucher_no", "allocated_amount"], + get_query() { + return query_args; + }, + action(selections) { + console.log(selections); + } + }); + } make_maintenance_schedule() { diff --git a/erpnext/accounts/doctype/unreconcile_payments/unreconcile_payments.py b/erpnext/accounts/doctype/unreconcile_payments/unreconcile_payments.py index ab2cc718ada..ed978cbc376 100644 --- a/erpnext/accounts/doctype/unreconcile_payments/unreconcile_payments.py +++ b/erpnext/accounts/doctype/unreconcile_payments/unreconcile_payments.py @@ -4,7 +4,7 @@ import frappe from frappe import qb from frappe.model.document import Document -from frappe.query_builder.functions import Sum +from frappe.query_builder.functions import Abs, Sum from erpnext.accounts.utils import unlink_ref_doc_from_payment_entries, update_voucher_outstanding @@ -55,3 +55,50 @@ class UnreconcilePayments(Document): alloc.reference_doctype, alloc.reference_name, account, party_type, party ) frappe.db.set_value("Unreconcile Payment Entries", alloc.name, "unlinked", True) + + +@frappe.whitelist() +def doc_has_payments(doctype, docname): + if doctype in ["Sales Invoice", "Purchase Invoice"]: + return frappe.db.count( + "Payment Ledger Entry", + filters={"delinked": 0, "against_voucher_no": docname, "amount": ["<", 0]}, + ) + else: + return frappe.db.count( + "Payment Ledger Entry", + filters={"delinked": 0, "voucher_no": docname, "against_voucher_no": ["!=", docname]}, + ) + + +@frappe.whitelist() +def get_linked_payments_for_doc(doctype, txt, searchfield, start, page_len, filters): + if filters.get("doctype") and filters.get("docname"): + _dt = filters.get("doctype") + _dn = filters.get("docname") + ple = qb.DocType("Payment Ledger Entry") + if _dt in ["Sales Invoice", "Purchase Invoice"]: + res = ( + qb.from_(ple) + .select( + ple.voucher_type, + ple.voucher_no, + Abs(Sum(ple.amount_in_account_currency)).as_("allocated_amount"), + ) + .where((ple.delinked == 0) & (ple.against_voucher_no == _dn) & (ple.amount < 0)) + .groupby(ple.against_voucher_no) + .run(as_dict=True) + ) + return res + else: + return frappe.db.get_all( + "Payment Ledger Entry", + filters={ + "delinked": 0, + "voucher_no": _dn, + "against_voucher_no": ["!=", _dn], + "amount": ["<", 0], + }, + group_by="against_voucher_no", + fields=["against_voucher_type", "against_voucher_no", "Sum(amount_in_account_currency)"], + )