[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."))