Merge pull request #33335 from ruthra-kumar/cost_center_issue_on_reconciliation_tool
fix: paid invoices shows up as outstanding when 'cost_center' filter is applied
This commit is contained in:
commit
d126c8030f
@ -1187,6 +1187,7 @@ def get_outstanding_reference_documents(args):
|
|||||||
|
|
||||||
ple = qb.DocType("Payment Ledger Entry")
|
ple = qb.DocType("Payment Ledger Entry")
|
||||||
common_filter = []
|
common_filter = []
|
||||||
|
accounting_dimensions_filter = []
|
||||||
posting_and_due_date = []
|
posting_and_due_date = []
|
||||||
|
|
||||||
# confirm that Supplier is not blocked
|
# confirm that Supplier is not blocked
|
||||||
@ -1216,7 +1217,7 @@ def get_outstanding_reference_documents(args):
|
|||||||
# Add cost center condition
|
# Add cost center condition
|
||||||
if args.get("cost_center"):
|
if args.get("cost_center"):
|
||||||
condition += " and cost_center='%s'" % args.get("cost_center")
|
condition += " and cost_center='%s'" % args.get("cost_center")
|
||||||
common_filter.append(ple.cost_center == args.get("cost_center"))
|
accounting_dimensions_filter.append(ple.cost_center == args.get("cost_center"))
|
||||||
|
|
||||||
date_fields_dict = {
|
date_fields_dict = {
|
||||||
"posting_date": ["from_posting_date", "to_posting_date"],
|
"posting_date": ["from_posting_date", "to_posting_date"],
|
||||||
@ -1242,6 +1243,7 @@ def get_outstanding_reference_documents(args):
|
|||||||
posting_date=posting_and_due_date,
|
posting_date=posting_and_due_date,
|
||||||
min_outstanding=args.get("outstanding_amt_greater_than"),
|
min_outstanding=args.get("outstanding_amt_greater_than"),
|
||||||
max_outstanding=args.get("outstanding_amt_less_than"),
|
max_outstanding=args.get("outstanding_amt_less_than"),
|
||||||
|
accounting_dimensions=accounting_dimensions_filter,
|
||||||
)
|
)
|
||||||
|
|
||||||
outstanding_invoices = split_invoices_based_on_payment_terms(outstanding_invoices)
|
outstanding_invoices = split_invoices_based_on_payment_terms(outstanding_invoices)
|
||||||
|
|||||||
@ -23,6 +23,7 @@ class PaymentReconciliation(Document):
|
|||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(PaymentReconciliation, self).__init__(*args, **kwargs)
|
super(PaymentReconciliation, self).__init__(*args, **kwargs)
|
||||||
self.common_filter_conditions = []
|
self.common_filter_conditions = []
|
||||||
|
self.accounting_dimension_filter_conditions = []
|
||||||
self.ple_posting_date_filter = []
|
self.ple_posting_date_filter = []
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
@ -193,6 +194,7 @@ class PaymentReconciliation(Document):
|
|||||||
posting_date=self.ple_posting_date_filter,
|
posting_date=self.ple_posting_date_filter,
|
||||||
min_outstanding=self.minimum_invoice_amount if self.minimum_invoice_amount else None,
|
min_outstanding=self.minimum_invoice_amount if self.minimum_invoice_amount else None,
|
||||||
max_outstanding=self.maximum_invoice_amount if self.maximum_invoice_amount else None,
|
max_outstanding=self.maximum_invoice_amount if self.maximum_invoice_amount else None,
|
||||||
|
accounting_dimensions=self.accounting_dimension_filter_conditions,
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.invoice_limit:
|
if self.invoice_limit:
|
||||||
@ -381,7 +383,7 @@ class PaymentReconciliation(Document):
|
|||||||
self.common_filter_conditions.append(ple.company == self.company)
|
self.common_filter_conditions.append(ple.company == self.company)
|
||||||
|
|
||||||
if self.get("cost_center") and (get_invoices or get_return_invoices):
|
if self.get("cost_center") and (get_invoices or get_return_invoices):
|
||||||
self.common_filter_conditions.append(ple.cost_center == self.cost_center)
|
self.accounting_dimension_filter_conditions.append(ple.cost_center == self.cost_center)
|
||||||
|
|
||||||
if get_invoices:
|
if get_invoices:
|
||||||
if self.from_invoice_date:
|
if self.from_invoice_date:
|
||||||
|
|||||||
@ -8,6 +8,8 @@ from frappe import qb
|
|||||||
from frappe.tests.utils import FrappeTestCase
|
from frappe.tests.utils import FrappeTestCase
|
||||||
from frappe.utils import add_days, nowdate
|
from frappe.utils import add_days, nowdate
|
||||||
|
|
||||||
|
from erpnext import get_default_cost_center
|
||||||
|
from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
|
||||||
from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_payment_entry
|
from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_payment_entry
|
||||||
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
||||||
from erpnext.accounts.party import get_party_account
|
from erpnext.accounts.party import get_party_account
|
||||||
@ -20,6 +22,7 @@ class TestPaymentReconciliation(FrappeTestCase):
|
|||||||
self.create_item()
|
self.create_item()
|
||||||
self.create_customer()
|
self.create_customer()
|
||||||
self.create_account()
|
self.create_account()
|
||||||
|
self.create_cost_center()
|
||||||
self.clear_old_entries()
|
self.clear_old_entries()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
@ -216,6 +219,22 @@ class TestPaymentReconciliation(FrappeTestCase):
|
|||||||
)
|
)
|
||||||
return je
|
return je
|
||||||
|
|
||||||
|
def create_cost_center(self):
|
||||||
|
# Setup cost center
|
||||||
|
cc_name = "Sub"
|
||||||
|
|
||||||
|
self.main_cc = frappe.get_doc("Cost Center", get_default_cost_center(self.company))
|
||||||
|
|
||||||
|
cc_exists = frappe.db.get_list("Cost Center", filters={"cost_center_name": cc_name})
|
||||||
|
if cc_exists:
|
||||||
|
self.sub_cc = frappe.get_doc("Cost Center", cc_exists[0].name)
|
||||||
|
else:
|
||||||
|
sub_cc = frappe.new_doc("Cost Center")
|
||||||
|
sub_cc.cost_center_name = "Sub"
|
||||||
|
sub_cc.parent_cost_center = self.main_cc.parent_cost_center
|
||||||
|
sub_cc.company = self.main_cc.company
|
||||||
|
self.sub_cc = sub_cc.save()
|
||||||
|
|
||||||
def test_filter_min_max(self):
|
def test_filter_min_max(self):
|
||||||
# check filter condition minimum and maximum amount
|
# check filter condition minimum and maximum amount
|
||||||
self.create_sales_invoice(qty=1, rate=300)
|
self.create_sales_invoice(qty=1, rate=300)
|
||||||
@ -578,3 +597,24 @@ class TestPaymentReconciliation(FrappeTestCase):
|
|||||||
self.assertEqual(len(pr.payments), 1)
|
self.assertEqual(len(pr.payments), 1)
|
||||||
self.assertEqual(pr.payments[0].amount, amount)
|
self.assertEqual(pr.payments[0].amount, amount)
|
||||||
self.assertEqual(pr.payments[0].currency, "EUR")
|
self.assertEqual(pr.payments[0].currency, "EUR")
|
||||||
|
|
||||||
|
def test_differing_cost_center_on_invoice_and_payment(self):
|
||||||
|
"""
|
||||||
|
Cost Center filter should not affect outstanding amount calculation
|
||||||
|
"""
|
||||||
|
|
||||||
|
si = self.create_sales_invoice(qty=1, rate=100, do_not_submit=True)
|
||||||
|
si.cost_center = self.main_cc.name
|
||||||
|
si.submit()
|
||||||
|
pr = get_payment_entry(si.doctype, si.name)
|
||||||
|
pr.cost_center = self.sub_cc.name
|
||||||
|
pr = pr.save().submit()
|
||||||
|
|
||||||
|
pr = self.create_payment_reconciliation()
|
||||||
|
pr.cost_center = self.main_cc.name
|
||||||
|
|
||||||
|
pr.get_unreconciled_entries()
|
||||||
|
|
||||||
|
# check PR tool output
|
||||||
|
self.assertEqual(len(pr.get("invoices")), 0)
|
||||||
|
self.assertEqual(len(pr.get("payments")), 0)
|
||||||
|
|||||||
@ -836,6 +836,7 @@ def get_outstanding_invoices(
|
|||||||
posting_date=None,
|
posting_date=None,
|
||||||
min_outstanding=None,
|
min_outstanding=None,
|
||||||
max_outstanding=None,
|
max_outstanding=None,
|
||||||
|
accounting_dimensions=None,
|
||||||
):
|
):
|
||||||
|
|
||||||
ple = qb.DocType("Payment Ledger Entry")
|
ple = qb.DocType("Payment Ledger Entry")
|
||||||
@ -866,6 +867,7 @@ def get_outstanding_invoices(
|
|||||||
min_outstanding=min_outstanding,
|
min_outstanding=min_outstanding,
|
||||||
max_outstanding=max_outstanding,
|
max_outstanding=max_outstanding,
|
||||||
get_invoices=True,
|
get_invoices=True,
|
||||||
|
accounting_dimensions=accounting_dimensions or [],
|
||||||
)
|
)
|
||||||
|
|
||||||
for d in invoice_list:
|
for d in invoice_list:
|
||||||
@ -1615,6 +1617,7 @@ class QueryPaymentLedger(object):
|
|||||||
.where(ple.delinked == 0)
|
.where(ple.delinked == 0)
|
||||||
.where(Criterion.all(filter_on_voucher_no))
|
.where(Criterion.all(filter_on_voucher_no))
|
||||||
.where(Criterion.all(self.common_filter))
|
.where(Criterion.all(self.common_filter))
|
||||||
|
.where(Criterion.all(self.dimensions_filter))
|
||||||
.where(Criterion.all(self.voucher_posting_date))
|
.where(Criterion.all(self.voucher_posting_date))
|
||||||
.groupby(ple.voucher_type, ple.voucher_no, ple.party_type, ple.party)
|
.groupby(ple.voucher_type, ple.voucher_no, ple.party_type, ple.party)
|
||||||
)
|
)
|
||||||
@ -1702,6 +1705,7 @@ class QueryPaymentLedger(object):
|
|||||||
max_outstanding=None,
|
max_outstanding=None,
|
||||||
get_payments=False,
|
get_payments=False,
|
||||||
get_invoices=False,
|
get_invoices=False,
|
||||||
|
accounting_dimensions=None,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Fetch voucher amount and outstanding amount from Payment Ledger using Database CTE
|
Fetch voucher amount and outstanding amount from Payment Ledger using Database CTE
|
||||||
@ -1717,6 +1721,7 @@ class QueryPaymentLedger(object):
|
|||||||
self.reset()
|
self.reset()
|
||||||
self.vouchers = vouchers
|
self.vouchers = vouchers
|
||||||
self.common_filter = common_filter or []
|
self.common_filter = common_filter or []
|
||||||
|
self.dimensions_filter = accounting_dimensions or []
|
||||||
self.voucher_posting_date = posting_date or []
|
self.voucher_posting_date = posting_date or []
|
||||||
self.min_outstanding = min_outstanding
|
self.min_outstanding = min_outstanding
|
||||||
self.max_outstanding = max_outstanding
|
self.max_outstanding = max_outstanding
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user