Merge pull request #14023 from mntechnique/accounting_period

Accounting Period
diff --git a/erpnext/accounts/doctype/accounting_period/accounting_period.js b/erpnext/accounts/doctype/accounting_period/accounting_period.js
index 1fb57ea..e3d805a 100644
--- a/erpnext/accounts/doctype/accounting_period/accounting_period.js
+++ b/erpnext/accounts/doctype/accounting_period/accounting_period.js
@@ -2,7 +2,23 @@
 // For license information, please see license.txt
 
 frappe.ui.form.on('Accounting Period', {
-	refresh: function(frm) {
-
+	onload: function(frm) {
+		if(frm.doc.closed_documents.length === 0 || (frm.doc.closed_documents.length === 1 && frm.doc.closed_documents[0].document_type == undefined)) {
+			frappe.call({
+				method: "get_doctypes_for_closing",
+				doc:frm.doc,
+				callback: function(r) {
+					if(r.message) {
+						cur_frm.clear_table("closed_documents");
+						r.message.forEach(function(element) {
+							var c = frm.add_child("closed_documents");
+							c.document_type = element.document_type;
+							c.closed = element.closed;
+						});
+						refresh_field("closed_documents");
+					}
+				}
+			});
+		}
 	}
 });
diff --git a/erpnext/accounts/doctype/accounting_period/accounting_period.py b/erpnext/accounts/doctype/accounting_period/accounting_period.py
index 31f1849..32441db 100644
--- a/erpnext/accounts/doctype/accounting_period/accounting_period.py
+++ b/erpnext/accounts/doctype/accounting_period/accounting_period.py
@@ -7,4 +7,48 @@
 from frappe.model.document import Document
 
 class AccountingPeriod(Document):
-	pass
+	def validate(self):
+		self.validate_overlap()
+
+	def before_insert(self):
+		self.bootstrap_doctypes_for_closing()
+
+	def autoname(self):
+		company_abbr = frappe.db.get_value("Company", self.company, "abbr")
+		self.name = " - ".join([self.period_name, company_abbr])
+	
+	def validate_overlap(self):
+		existing_accounting_period = frappe.db.sql("""select name from `tabAccounting Period`
+			where (
+				(%(start_date)s between start_date and end_date)
+				or (%(end_date)s between start_date and end_date)
+				or (start_date between %(start_date)s and %(end_date)s)
+				or (end_date between %(start_date)s and %(end_date)s)
+			) and name!=%(name)s and company=%(company)s""",
+			{
+				"start_date": self.start_date,
+				"end_date": self.end_date,
+				"name": self.name,
+				"company": self.company
+			}, as_dict=True)
+
+		if len(existing_accounting_period) > 0:
+			frappe.throw("Accounting Period overlaps with {0}".format(existing_accounting_period[0].get("name")))
+
+	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"]
+		closed_doctypes = [{"document_type": doctype, "closed": 1} for doctype in doctypes]
+		for closed_doctype in closed_doctypes:
+			docs_for_closing.append(closed_doctype)
+
+		return docs_for_closing
+
+	def bootstrap_doctypes_for_closing(self):
+		if len(self.closed_documents) == 0:
+			for doctype_for_closing in self.get_doctypes_for_closing():
+				self.append('closed_documents', {
+					"document_type": doctype_for_closing.document_type,
+					"closed": doctype_for_closing.closed
+				})
diff --git a/erpnext/accounts/doctype/accounting_period/test_accounting_period.py b/erpnext/accounts/doctype/accounting_period/test_accounting_period.py
index 99694d2..cc2e6a9 100644
--- a/erpnext/accounts/doctype/accounting_period/test_accounting_period.py
+++ b/erpnext/accounts/doctype/accounting_period/test_accounting_period.py
@@ -7,4 +7,21 @@
 import unittest
 
 class TestAccountingPeriod(unittest.TestCase):
-	pass
+	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