mirror of
https://github.com/frappe/erpnext.git
synced 2026-02-18 09:05:00 +00:00
Merge pull request #43226 from aerele/reconcile-after-period-closing
fix: map rows on journal entry by validating account, party, debit and credit value
This commit is contained in:
@@ -195,6 +195,11 @@ class JournalEntry(AccountsController):
|
||||
self.update_booked_depreciation()
|
||||
|
||||
def on_update_after_submit(self):
|
||||
# Flag will be set on Reconciliation
|
||||
# Reconciliation tool will anyways repost ledger entries. So, no need to check and do implicit repost.
|
||||
if self.flags.get("ignore_reposting_on_reconciliation"):
|
||||
return
|
||||
|
||||
self.needs_repost = self.check_if_fields_updated(fields_to_check=[], child_tables={"accounts": []})
|
||||
if self.needs_repost:
|
||||
self.validate_for_repost()
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import frappe
|
||||
from frappe import qb
|
||||
from frappe.tests.utils import FrappeTestCase, change_settings
|
||||
from frappe.utils import add_days, flt, nowdate
|
||||
from frappe.utils import add_days, add_years, flt, getdate, nowdate, today
|
||||
|
||||
from erpnext import get_default_cost_center
|
||||
from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
|
||||
@@ -13,6 +13,7 @@ from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_pay
|
||||
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_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.utils import get_fiscal_year
|
||||
from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
|
||||
from erpnext.stock.doctype.item.test_item import create_item
|
||||
|
||||
@@ -1845,6 +1846,78 @@ class TestPaymentReconciliation(FrappeTestCase):
|
||||
self.assertEqual(len(pr.invoices), 1)
|
||||
self.assertEqual(len(pr.payments), 1)
|
||||
|
||||
def test_reconciliation_on_closed_period_payment(self):
|
||||
# create backdated fiscal year
|
||||
first_fy_start_date = frappe.db.get_value("Fiscal Year", {"disabled": 0}, "min(year_start_date)")
|
||||
prev_fy_start_date = add_years(first_fy_start_date, -1)
|
||||
prev_fy_end_date = add_days(first_fy_start_date, -1)
|
||||
create_fiscal_year(
|
||||
company=self.company, year_start_date=prev_fy_start_date, year_end_date=prev_fy_end_date
|
||||
)
|
||||
|
||||
# make journal entry for previous year
|
||||
je_1 = frappe.new_doc("Journal Entry")
|
||||
je_1.posting_date = add_days(prev_fy_start_date, 20)
|
||||
je_1.company = self.company
|
||||
je_1.user_remark = "test"
|
||||
je_1.set(
|
||||
"accounts",
|
||||
[
|
||||
{
|
||||
"account": self.debit_to,
|
||||
"cost_center": self.cost_center,
|
||||
"party_type": "Customer",
|
||||
"party": self.customer,
|
||||
"debit_in_account_currency": 0,
|
||||
"credit_in_account_currency": 1000,
|
||||
},
|
||||
{
|
||||
"account": self.bank,
|
||||
"cost_center": self.sub_cc.name,
|
||||
"credit_in_account_currency": 0,
|
||||
"debit_in_account_currency": 500,
|
||||
},
|
||||
{
|
||||
"account": self.cash,
|
||||
"cost_center": self.sub_cc.name,
|
||||
"credit_in_account_currency": 0,
|
||||
"debit_in_account_currency": 500,
|
||||
},
|
||||
],
|
||||
)
|
||||
je_1.submit()
|
||||
|
||||
# make period closing voucher
|
||||
pcv = make_period_closing_voucher(
|
||||
company=self.company, cost_center=self.cost_center, posting_date=prev_fy_end_date
|
||||
)
|
||||
pcv.reload()
|
||||
# check if period closing voucher is completed
|
||||
self.assertEqual(pcv.gle_processing_status, "Completed")
|
||||
|
||||
# make journal entry for active year
|
||||
je_2 = self.create_journal_entry(
|
||||
acc1=self.debit_to, acc2=self.income_account, amount=1000, posting_date=today()
|
||||
)
|
||||
je_2.accounts[0].party_type = "Customer"
|
||||
je_2.accounts[0].party = self.customer
|
||||
je_2.submit()
|
||||
|
||||
# process reconciliation on closed period payment
|
||||
pr = self.create_payment_reconciliation(party_is_customer=True)
|
||||
pr.from_invoice_date = pr.to_invoice_date = pr.from_payment_date = pr.to_payment_date = None
|
||||
pr.get_unreconciled_entries()
|
||||
invoices = [invoice.as_dict() for invoice in pr.invoices]
|
||||
payments = [payment.as_dict() for payment in pr.payments]
|
||||
pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments}))
|
||||
pr.reconcile()
|
||||
je_1.reload()
|
||||
je_2.reload()
|
||||
|
||||
# check whether the payment reconciliation is done on the closed period
|
||||
self.assertEqual(pr.get("invoices"), [])
|
||||
self.assertEqual(pr.get("payments"), [])
|
||||
|
||||
|
||||
def make_customer(customer_name, currency=None):
|
||||
if not frappe.db.exists("Customer", customer_name):
|
||||
@@ -1872,3 +1945,61 @@ def make_supplier(supplier_name, currency=None):
|
||||
return supplier.name
|
||||
else:
|
||||
return supplier_name
|
||||
|
||||
|
||||
def create_fiscal_year(company, year_start_date, year_end_date):
|
||||
fy_docname = frappe.db.exists(
|
||||
"Fiscal Year", {"year_start_date": year_start_date, "year_end_date": year_end_date}
|
||||
)
|
||||
if not fy_docname:
|
||||
fy_doc = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Fiscal Year",
|
||||
"year": f"{getdate(year_start_date).year}-{getdate(year_end_date).year}",
|
||||
"year_start_date": year_start_date,
|
||||
"year_end_date": year_end_date,
|
||||
"companies": [{"company": company}],
|
||||
}
|
||||
).save()
|
||||
return fy_doc
|
||||
else:
|
||||
fy_doc = frappe.get_doc("Fiscal Year", fy_docname)
|
||||
if not frappe.db.exists("Fiscal Year Company", {"parent": fy_docname, "company": company}):
|
||||
fy_doc.append("companies", {"company": company})
|
||||
fy_doc.save()
|
||||
return fy_doc
|
||||
|
||||
|
||||
def make_period_closing_voucher(company, cost_center, posting_date=None, submit=True):
|
||||
from erpnext.accounts.doctype.account.test_account import create_account
|
||||
|
||||
parent_account = frappe.db.get_value(
|
||||
"Account", {"company": company, "account_name": "Current Liabilities", "is_group": 1}, "name"
|
||||
)
|
||||
surplus_account = create_account(
|
||||
account_name="Reserve and Surplus",
|
||||
is_group=0,
|
||||
company=company,
|
||||
root_type="Liability",
|
||||
report_type="Balance Sheet",
|
||||
account_currency="INR",
|
||||
parent_account=parent_account,
|
||||
doctype="Account",
|
||||
)
|
||||
pcv = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Period Closing Voucher",
|
||||
"transaction_date": posting_date or today(),
|
||||
"posting_date": posting_date or today(),
|
||||
"company": company,
|
||||
"fiscal_year": get_fiscal_year(posting_date or today(), company=company)[0],
|
||||
"cost_center": cost_center,
|
||||
"closing_account_head": surplus_account,
|
||||
"remarks": "test",
|
||||
}
|
||||
)
|
||||
pcv.insert()
|
||||
if submit:
|
||||
pcv.submit()
|
||||
|
||||
return pcv
|
||||
|
||||
@@ -685,6 +685,8 @@ def update_reference_in_journal_entry(d, journal_entry, do_not_save=False):
|
||||
|
||||
# will work as update after submit
|
||||
journal_entry.flags.ignore_validate_update_after_submit = True
|
||||
# Ledgers will be reposted by Reconciliation tool
|
||||
journal_entry.flags.ignore_reposting_on_reconciliation = True
|
||||
if not do_not_save:
|
||||
journal_entry.save(ignore_permissions=True)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user