From e5c733bdb399ba1a7d206207f7784297c9b7b3f1 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Thu, 8 Aug 2019 15:44:11 +0530 Subject: [PATCH] fix: Accounting period (#18630) * fix: accounting period * test: accounting period * fix: account period creation * fix: remove status field from accounting period --- .../accounting_period/accounting_period.json | 36 +----------- .../accounting_period/accounting_period.py | 11 ++-- .../test_accounting_period.py | 57 ++++++++++++------- erpnext/accounts/general_ledger.py | 23 ++++++++ 4 files changed, 70 insertions(+), 57 deletions(-) diff --git a/erpnext/accounts/doctype/accounting_period/accounting_period.json b/erpnext/accounts/doctype/accounting_period/accounting_period.json index ed30b83c26..57f8e32dc6 100644 --- a/erpnext/accounts/doctype/accounting_period/accounting_period.json +++ b/erpnext/accounts/doctype/accounting_period/accounting_period.json @@ -167,39 +167,7 @@ "set_only_once": 0, "translatable": 0, "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "status", - "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": "Status", - "length": 0, - "no_copy": 0, - "options": "Open\nClosed", - "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_on_submit": 0, @@ -273,7 +241,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-04-13 19:14:47.593753", + "modified": "2019-08-01 19:14:47.593753", "modified_by": "Administrator", "module": "Accounts", "name": "Accounting Period", diff --git a/erpnext/accounts/doctype/accounting_period/accounting_period.py b/erpnext/accounts/doctype/accounting_period/accounting_period.py index de45f3a252..180460c091 100644 --- a/erpnext/accounts/doctype/accounting_period/accounting_period.py +++ b/erpnext/accounts/doctype/accounting_period/accounting_period.py @@ -7,6 +7,8 @@ import frappe from frappe.model.document import Document from frappe import _ +class OverlapError(frappe.ValidationError): pass + class AccountingPeriod(Document): def validate(self): self.validate_overlap() @@ -34,12 +36,13 @@ class AccountingPeriod(Document): }, as_dict=True) if len(existing_accounting_period) > 0: - frappe.throw(_("Accounting Period overlaps with {0}".format(existing_accounting_period[0].get("name")))) + frappe.throw(_("Accounting Period overlaps with {0}") + .format(existing_accounting_period[0].get("name")), OverlapError) def get_doctypes_for_closing(self): docs_for_closing = [] - #if not self.closed_documents or len(self.closed_documents) == 0: - doctypes = ["Sales Invoice", "Purchase Invoice", "Journal Entry", "Payroll Entry", "Bank Reconciliation", "Asset", "Purchase Order", "Sales Order", "Leave Application", "Leave Allocation", "Stock Entry"] + doctypes = ["Sales Invoice", "Purchase Invoice", "Journal Entry", "Payroll Entry", "Bank Reconciliation", + "Asset", "Purchase Order", "Sales Order", "Leave Application", "Leave Allocation", "Stock Entry"] closed_doctypes = [{"document_type": doctype, "closed": 1} for doctype in doctypes] for closed_doctype in closed_doctypes: docs_for_closing.append(closed_doctype) @@ -52,4 +55,4 @@ class AccountingPeriod(Document): self.append('closed_documents', { "document_type": doctype_for_closing.document_type, "closed": doctype_for_closing.closed - }) + }) \ No newline at end of file diff --git a/erpnext/accounts/doctype/accounting_period/test_accounting_period.py b/erpnext/accounts/doctype/accounting_period/test_accounting_period.py index 29deefdbed..022d7a7e80 100644 --- a/erpnext/accounts/doctype/accounting_period/test_accounting_period.py +++ b/erpnext/accounts/doctype/accounting_period/test_accounting_period.py @@ -5,23 +5,42 @@ from __future__ import unicode_literals import frappe import unittest +from frappe.utils import nowdate, add_months +from erpnext.accounts.general_ledger import ClosedAccountingPeriod +from erpnext.accounts.doctype.accounting_period.accounting_period import OverlapError +from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice -# class TestAccountingPeriod(unittest.TestCase): -# def test_overlap(self): -# ap1 = create_accounting_period({"start_date":"2018-04-01", "end_date":"2018-06-30", "company":"Wind Power LLC"}) -# ap1.save() -# ap2 = create_accounting_period({"start_date":"2018-06-30", "end_date":"2018-07-10", "company":"Wind Power LLC"}) -# self.assertRaises(frappe.OverlapError, accounting_period_2.save()) -# -# def tearDown(self): -# pass -# -# -# def create_accounting_period(**args): -# accounting_period = frappe.new_doc("Accounting Period") -# accounting_period.start_date = args.start_date or frappe.utils.datetime.date(2018, 4, 1) -# accounting_period.end_date = args.end_date or frappe.utils.datetime.date(2018, 6, 30) -# accounting_period.company = args.company -# accounting_period.period_name = "_Test_Period_Name_1" -# -# return accounting_period +class TestAccountingPeriod(unittest.TestCase): + def test_overlap(self): + ap1 = create_accounting_period(start_date = "2018-04-01", + end_date = "2018-06-30", company = "Wind Power LLC") + ap1.save() + + ap2 = create_accounting_period(start_date = "2018-06-30", + end_date = "2018-07-10", company = "Wind Power LLC", period_name = "Test Accounting Period 1") + self.assertRaises(OverlapError, ap2.save) + + def test_accounting_period(self): + ap1 = create_accounting_period(period_name = "Test Accounting Period 2") + ap1.save() + + doc = create_sales_invoice(do_not_submit=1, cost_center = "_Test Company - _TC", warehouse = "Stores - _TC") + self.assertRaises(ClosedAccountingPeriod, doc.submit) + + def tearDown(self): + for d in frappe.get_all("Accounting Period"): + frappe.delete_doc("Accounting Period", d.name) + +def create_accounting_period(**args): + args = frappe._dict(args) + + accounting_period = frappe.new_doc("Accounting Period") + accounting_period.start_date = args.start_date or nowdate() + accounting_period.end_date = args.end_date or add_months(nowdate(), 1) + accounting_period.company = args.company or "_Test Company" + accounting_period.period_name =args.period_name or "_Test_Period_Name_1" + accounting_period.append("closed_documents", { + "document_type": 'Sales Invoice', "closed": 1 + }) + + return accounting_period \ No newline at end of file diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py index be1448df3a..5c9e93d019 100644 --- a/erpnext/accounts/general_ledger.py +++ b/erpnext/accounts/general_ledger.py @@ -10,11 +10,13 @@ from erpnext.accounts.doctype.budget.budget import validate_expense_against_budg from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions +class ClosedAccountingPeriod(frappe.ValidationError): pass class StockAccountInvalidTransaction(frappe.ValidationError): pass def make_gl_entries(gl_map, cancel=False, adv_adj=False, merge_entries=True, update_outstanding='Yes', from_repost=False): if gl_map: if not cancel: + validate_accounting_period(gl_map) gl_map = process_gl_map(gl_map, merge_entries) if gl_map and len(gl_map) > 1: save_entries(gl_map, adv_adj, update_outstanding, from_repost) @@ -23,6 +25,27 @@ def make_gl_entries(gl_map, cancel=False, adv_adj=False, merge_entries=True, upd else: delete_gl_entries(gl_map, adv_adj=adv_adj, update_outstanding=update_outstanding) +def validate_accounting_period(gl_map): + accounting_periods = frappe.db.sql(""" SELECT + ap.name as name + FROM + `tabAccounting Period` ap, `tabClosed Document` cd + WHERE + ap.name = cd.parent + AND ap.company = %(company)s + AND cd.closed = 1 + AND cd.document_type = %(voucher_type)s + AND %(date)s between ap.start_date and ap.end_date + """, { + 'date': gl_map[0].posting_date, + 'company': gl_map[0].company, + 'voucher_type': gl_map[0].voucher_type + }, as_dict=1) + + if accounting_periods: + frappe.throw(_("You can't create accounting entries in the closed accounting period {0}") + .format(accounting_periods[0].name), ClosedAccountingPeriod) + def process_gl_map(gl_map, merge_entries=True): if merge_entries: gl_map = merge_similar_entries(gl_map)