[Fix] make PE unique for the combination of academic year and academic term (#12214)

diff --git a/erpnext/docs/user/manual/en/education/admission/program-enrollment.md b/erpnext/docs/user/manual/en/education/admission/program-enrollment.md
index 0bf16df..6fe9692 100644
--- a/erpnext/docs/user/manual/en/education/admission/program-enrollment.md
+++ b/erpnext/docs/user/manual/en/education/admission/program-enrollment.md
@@ -1,12 +1,21 @@
 # Program Enrollment
 
-Program Enrollment describes an educational model where students must complete a  defined set of courses towards their academic objective in a specified sequence. Enrollment is a program driven process in which the student select the Program to enrol for in a Academic Year. 
+**Program Enrollment** is the record of enrollment of a student in a given program and choose courses for a particular Academic Year and Academic Term (optional). If a student is enrolled in a program then his/her Program Enrollment must be created. The mandatory course in that program is automatically filled in Enrolled Courses table while the elective/optional courses can be selected manually.
 
-Once a student have applied for the **Program** and the application is approved, the program enrollment is done for that student. 
+If the student has applied online for the admission in a particular **Program** and the application is approved, then the Program Enrollment can be created from within the Student Applicant record via clicking on the **Enroll** button.
+
+Else, to create the new Program Enrollment manually, go to:
+> Education > Program Enrollment > New
 
 <img class="screenshot" alt="Student Applicant Enrollment" src="/docs/assets/img/education/admission/program-enrollment.gif">
 
-- A student can be enrolled in multiple Course for a program in a given academeic year. 
-- Based on the Fee structure selected at the time of enrollment Fee detials are created of the student.
+If any institution has skipped the online admission process then Program Enrollment can also be considered as the confirmation of the admission in a particular Program.
 
-{next}
+> TIP: Academic Term is optional in the Program Enrollment. If your institution has only annual curriculum, you can skip the Academic Term
+
+Student Batch: To categorize student into different sections/batches, you can assign the batch to the student. On the basis of this field, later student groups can be created.
+
+Student Category: For the Institutions having multiple Fees Structure, this field can be used to differentiate the student enrollment in a given fee category. 
+
+
+{next}
\ No newline at end of file
diff --git a/erpnext/education/doctype/program_enrollment/program_enrollment.json b/erpnext/education/doctype/program_enrollment/program_enrollment.json
index 9badf93..00b1373 100644
--- a/erpnext/education/doctype/program_enrollment/program_enrollment.json
+++ b/erpnext/education/doctype/program_enrollment/program_enrollment.json
@@ -112,19 +112,19 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "fieldname": "school_house", 
+   "fieldname": "student_batch_name", 
    "fieldtype": "Link", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
-   "in_global_search": 0, 
+   "in_global_search": 1, 
    "in_list_view": 0, 
    "in_standard_filter": 0, 
-   "label": "School House", 
+   "label": "Student Batch", 
    "length": 0, 
    "no_copy": 0, 
-   "options": "School House", 
+   "options": "Student Batch Name", 
    "permlevel": 0, 
    "precision": "", 
    "print_hide": 0, 
@@ -139,14 +139,12 @@
   }, 
   {
    "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
+   "allow_on_submit": 1, 
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "default": "0", 
-   "description": "Check this if the Student is residing at the Institute's Hostel.", 
-   "fieldname": "boarding_student", 
-   "fieldtype": "Check", 
+   "fieldname": "school_house", 
+   "fieldtype": "Link", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
@@ -154,10 +152,10 @@
    "in_global_search": 0, 
    "in_list_view": 0, 
    "in_standard_filter": 0, 
-   "label": "Boarding Student", 
+   "label": "School House", 
    "length": 0, 
    "no_copy": 0, 
-   "options": "", 
+   "options": "School House", 
    "permlevel": 0, 
    "precision": "", 
    "print_hide": 0, 
@@ -232,37 +230,6 @@
   }, 
   {
    "allow_bulk_edit": 0, 
-   "allow_on_submit": 1, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "student_batch_name", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 1, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Student Batch", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Student Batch Name", 
-   "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, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -294,7 +261,7 @@
   }, 
   {
    "allow_bulk_edit": 0, 
-   "allow_on_submit": 1, 
+   "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
@@ -358,6 +325,39 @@
    "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "default": "0", 
+   "description": "Check this if the Student is residing at the Institute's Hostel.", 
+   "fieldname": "boarding_student", 
+   "fieldtype": "Check", 
+   "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": "Boarding Student", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "", 
+   "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, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
    "collapsible": 1, 
    "collapsible_depends_on": "vehicle_no", 
    "columns": 0, 
@@ -671,7 +671,7 @@
  "istable": 0, 
  "max_attachments": 0, 
  "menu_index": 0, 
- "modified": "2017-11-16 13:20:28.650637", 
+ "modified": "2017-12-27 10:59:36.838548", 
  "modified_by": "Administrator", 
  "module": "Education", 
  "name": "Program Enrollment", 
diff --git a/erpnext/education/doctype/program_enrollment/program_enrollment.py b/erpnext/education/doctype/program_enrollment/program_enrollment.py
index 79772b0..0f9bb96 100644
--- a/erpnext/education/doctype/program_enrollment/program_enrollment.py
+++ b/erpnext/education/doctype/program_enrollment/program_enrollment.py
@@ -22,8 +22,14 @@
 		self.make_fee_records()
 	
 	def validate_duplication(self):
-		enrollment = frappe.db.sql("""select name from `tabProgram Enrollment` where student= %s and program= %s 
-			and academic_year= %s and docstatus<2 and name != %s""", (self.student, self.program, self.academic_year, self.name))
+		enrollment = frappe.get_all("Program Enrollment", filters={
+			"student": self.student,
+			"program": self.program,
+			"academic_year": self.academic_year,
+			"academic_term": self.academic_term,
+			"docstatus": ("<", 2),
+			"name": ("!=", self.name)
+		})
 		if enrollment:
 			frappe.throw(_("Student is already enrolled."))