Suggested Changes to School (#6223)
* Linkage of academic term to academic year
* School improvements. Modifications to Academic Term, Assessment, Fees, Student Batch, Student Group. Addition of Grading System.
* Removed Grading System from Assessment and put it on Program
* Removed the field Grading System from Program and added it back to Assessment. Added some validations for dates in controller of Academic Term and Academic Year
* Added validation comparing term start dates with academic year start dates and term end dates with academic year end dates where both are available.
* Renamed Grading System to Grading Structure. Implemented the code in Assessment.js to derive the Grade Code from the result entered for the student. Assumes that result is always a number. Will rename the field result in Results to score.
* Added validation to check if any grade intervals were overlapping when a Grading Structure is being saved.
* Corrections to error in autonaming for Academic Term
* Correction in white_list method get_grade in Assessment. Solves problem with grades not being derived when the score is at the boundaries of a grade interval
* Correction to setup_wizard.py to make sure that creation of academic terms in create_academic_term includes the academic_year which is now mandatory
* Corrections to test_records.json for doctype Academic Term
* Correction of test_records.json in doctype Student Groups
* Correction of test_records.json for doctype Student Group 2
* Correction to test_course_schedule.py in doctype Course Schedule
* More corrections to test_course_schedule.py in doctype Course Schedule
* Corrections to test_course_schedule.py
* Updates to Student DocType. Enrollment date, Nationality
* Linkage of academic term to academic year
* School improvements. Modifications to Academic Term, Assessment, Fees, Student Batch, Student Group. Addition of Grading System.
* Removed Grading System from Assessment and put it on Program
* Removed the field Grading System from Program and added it back to Assessment. Added some validations for dates in controller of Academic Term and Academic Year
* Added validation comparing term start dates with academic year start dates and term end dates with academic year end dates where both are available.
* Renamed Grading System to Grading Structure. Implemented the code in Assessment.js to derive the Grade Code from the result entered for the student. Assumes that result is always a number. Will rename the field result in Results to score.
* Added validation to check if any grade intervals were overlapping when a Grading Structure is being saved.
* Corrections to error in autonaming for Academic Term
diff --git a/erpnext/config/schools.py b/erpnext/config/schools.py
index 5e73fce..857a422 100644
--- a/erpnext/config/schools.py
+++ b/erpnext/config/schools.py
@@ -122,6 +122,10 @@
},
{
"type": "doctype",
+ "name": "Grading Structure"
+ },
+ {
+ "type": "doctype",
"name": "Program"
},
{
diff --git a/erpnext/schools/doctype/academic_term/academic_term.json b/erpnext/schools/doctype/academic_term/academic_term.json
index 9d9c9e0..ca10ebf 100644
--- a/erpnext/schools/doctype/academic_term/academic_term.json
+++ b/erpnext/schools/doctype/academic_term/academic_term.json
@@ -2,7 +2,7 @@
"allow_copy": 0,
"allow_import": 1,
"allow_rename": 1,
- "autoname": "field:term_name",
+ "autoname": "field:title",
"beta": 0,
"creation": "2015-09-08 17:19:19.158228",
"custom": 0,
@@ -15,6 +15,32 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
+ "fieldname": "academic_year",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Academic Year",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Academic Year",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
"fieldname": "term_name",
"fieldtype": "Data",
"hidden": 0,
@@ -31,6 +57,81 @@
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "term_start_date",
+ "fieldtype": "Date",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 1,
+ "label": "Term Start Date",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 1,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "term_end_date",
+ "fieldtype": "Date",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 1,
+ "label": "Term End Date",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 1,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "title",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Title",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
@@ -47,7 +148,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2016-07-25 05:24:23.032319",
+ "modified": "2016-08-27 23:02:03.565866",
"modified_by": "Administrator",
"module": "Schools",
"name": "Academic Term",
@@ -78,7 +179,8 @@
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
- "sort_field": "modified",
+ "sort_field": "name",
"sort_order": "DESC",
+ "title_field": "title",
"track_seen": 0
}
\ No newline at end of file
diff --git a/erpnext/schools/doctype/academic_term/academic_term.py b/erpnext/schools/doctype/academic_term/academic_term.py
index 1a4526b..891feb8 100644
--- a/erpnext/schools/doctype/academic_term/academic_term.py
+++ b/erpnext/schools/doctype/academic_term/academic_term.py
@@ -4,7 +4,35 @@
from __future__ import unicode_literals
import frappe
+from frappe import msgprint, _
+from frappe.utils import get_datetime, get_datetime_str
from frappe.model.document import Document
class AcademicTerm(Document):
- pass
+ def autoname(self):
+ self.name = self.academic_year + " ({})".format(self.term_name) if self.term_name else ""
+
+ def validate(self):
+ #Check if entry with same academic_year and the term_name already exists
+ validate_duplication(self)
+ self.title = self.academic_year + " ({})".format(self.term_name) if self.term_name else ""
+
+ #Check that start of academic year is earlier than end of academic year
+ if self.term_start_date and self.term_end_date and self.term_start_date > self.term_end_date:
+ frappe.throw(_("The Term End Date cannot be earlier than the Term Start Date. Please correct the dates and try again."))
+
+ """Check that the start of the term is not before the start of the academic year and end of term is not after
+ the end of the academic year"""
+ year = frappe.get_doc("Academic Year",self.academic_year)
+ if self.term_start_date and get_datetime_str(year.year_start_date) and (self.term_start_date < get_datetime_str(year.year_start_date)):
+ frappe.throw(_("The Term Start Date cannot be earlier than the Year Start Date of the Academic Year to which the term is linked (Academic Year {}). Please correct the dates and try again.").format(self.academic_year))
+
+ if self.term_end_date and get_datetime_str(year.year_end_date) and (self.term_end_date > get_datetime_str(year.year_end_date)):
+ frappe.throw(_("The Term End Date cannot be later than the Year End Date of the Academic Year to which the term is linked (Academic Year {}). Please correct the dates and try again.").format(self.academic_year))
+
+
+def validate_duplication(self):
+ term = frappe.db.sql("""select name from `tabAcademic Term` where academic_year= %s and term_name= %s
+ and docstatus<2 and name != %s""", (self.academic_year, self.term_name, self.name))
+ if term:
+ frappe.throw(_("An academic term with this 'Academic Year' {0} and 'Term Name' {1} already exists. Please modify these entries and try again.").format(self.academic_year,self.term_name))
diff --git a/erpnext/schools/doctype/academic_term/test_records.json b/erpnext/schools/doctype/academic_term/test_records.json
index 9807221..2d84383 100644
--- a/erpnext/schools/doctype/academic_term/test_records.json
+++ b/erpnext/schools/doctype/academic_term/test_records.json
@@ -1,11 +1,17 @@
[
- {
- "term_name": "_Test Academic Term"
- },
- {
- "term_name": "_Test Academic Term 1"
- },
- {
- "term_name": "_Test Academic Term 2"
- }
-]
\ No newline at end of file
+ {
+ "doctype": "Academic Term",
+ "academic_year": "2014-2015",
+ "term_name": "_Test Academic Term"
+ },
+ {
+ "doctype": "Academic Term",
+ "academic_year": "2014-2015",
+ "term_name": "_Test Academic Term 1"
+ },
+ {
+ "doctype": "Academic Term",
+ "academic_year": "2014-2015",
+ "term_name": "_Test Academic Term 2"
+ }
+]
\ No newline at end of file
diff --git a/erpnext/schools/doctype/academic_year/academic_year.py b/erpnext/schools/doctype/academic_year/academic_year.py
index 4b955de..f2858a4 100644
--- a/erpnext/schools/doctype/academic_year/academic_year.py
+++ b/erpnext/schools/doctype/academic_year/academic_year.py
@@ -4,7 +4,11 @@
from __future__ import unicode_literals
import frappe
+from frappe import msgprint, _
from frappe.model.document import Document
class AcademicYear(Document):
- pass
+ def validate(self):
+ #Check that start of academic year is earlier than end of academic year
+ if self.year_start_date and self.year_end_date and self.year_start_date > self.year_end_date:
+ frappe.throw(_("The Year End Date cannot be earlier than the Year Start Date. Please correct the dates and try again."))
diff --git a/erpnext/schools/doctype/assessment/assessment.js b/erpnext/schools/doctype/assessment/assessment.js
index 799ae7b..efadbd6 100644
--- a/erpnext/schools/doctype/assessment/assessment.js
+++ b/erpnext/schools/doctype/assessment/assessment.js
@@ -28,4 +28,24 @@
});
}
}
+});
+
+frappe.ui.form.on("Assessment Result" ,{
+ result : function(frm, cdt, cdn) {
+ if(frm.doc.grading_structure){
+ var assessment_result = locals[cdt][cdn];
+ frappe.call({
+ method:"erpnext.schools.doctype.assessment.assessment.get_grade",
+ args:{
+ grading_structure: frm.doc.grading_structure,
+ result: assessment_result.result
+ },
+ callback: function(r){
+ if(r.message){
+ frappe.model.set_value(cdt, cdn, 'grade', r.message);
+ }
+ }
+ });
+ }
+ }
});
\ No newline at end of file
diff --git a/erpnext/schools/doctype/assessment/assessment.json b/erpnext/schools/doctype/assessment/assessment.json
index 30ac1ed..e978d08 100644
--- a/erpnext/schools/doctype/assessment/assessment.json
+++ b/erpnext/schools/doctype/assessment/assessment.json
@@ -91,6 +91,32 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
+ "fieldname": "grading_structure",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Grading Structure",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Grading Structure",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
"fieldname": "course",
"fieldtype": "Link",
"hidden": 0,
@@ -506,7 +532,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
- "modified": "2016-08-05 04:57:41.018614",
+ "modified": "2016-08-27 14:18:51.852078",
"modified_by": "Administrator",
"module": "Schools",
"name": "Assessment",
diff --git a/erpnext/schools/doctype/assessment/assessment.py b/erpnext/schools/doctype/assessment/assessment.py
index a23d5cc..de6a653 100644
--- a/erpnext/schools/doctype/assessment/assessment.py
+++ b/erpnext/schools/doctype/assessment/assessment.py
@@ -8,39 +8,56 @@
from frappe import _
class Assessment(Document):
- def validate(self):
- self.validate_overlap()
-
- def validate_overlap(self):
- """Validates overlap for Student Group, Supervisor, Room"""
+ def validate(self):
+ self.validate_overlap()
+
+ def validate_overlap(self):
+ """Validates overlap for Student Group, Supervisor, Room"""
- from erpnext.schools.utils import validate_overlap_for
+ from erpnext.schools.utils import validate_overlap_for
- validate_overlap_for(self, "Assessment", "student_group")
- validate_overlap_for(self, "Course Schedule", "student_group" )
-
- if self.room:
- validate_overlap_for(self, "Assessment", "room")
- validate_overlap_for(self, "Course Schedule", "room")
+ validate_overlap_for(self, "Assessment", "student_group")
+ validate_overlap_for(self, "Course Schedule", "student_group" )
+
+ if self.room:
+ validate_overlap_for(self, "Assessment", "room")
+ validate_overlap_for(self, "Course Schedule", "room")
- if self.supervisor:
- validate_overlap_for(self, "Assessment", "supervisor")
- validate_overlap_for(self, "Course Schedule", "instructor", self.supervisor)
+ if self.supervisor:
+ validate_overlap_for(self, "Assessment", "supervisor")
+ validate_overlap_for(self, "Course Schedule", "instructor", self.supervisor)
def get_assessment_list(doctype, txt, filters, limit_start, limit_page_length=20):
- user = frappe.session.user
- student = frappe.db.sql("select name from `tabStudent` where student_email_id= %s", user)
- if student:
- return frappe. db.sql('''select course, schedule_date, from_time, to_time, sgs.name from `tabAssessment` as assessment,
- `tabStudent Group Student` as sgs where assessment.student_group = sgs.parent and sgs.student = %s and assessment.docstatus=1
- order by assessment.name asc limit {0} , {1}'''
- .format(limit_start, limit_page_length), student, as_dict = True)
+ user = frappe.session.user
+ student = frappe.db.sql("select name from `tabStudent` where student_email_id= %s", user)
+ if student:
+ return frappe. db.sql('''select course, schedule_date, from_time, to_time, sgs.name from `tabAssessment` as assessment,
+ `tabStudent Group Student` as sgs where assessment.student_group = sgs.parent and sgs.student = %s and assessment.docstatus=1
+ order by assessment.name asc limit {0} , {1}'''
+ .format(limit_start, limit_page_length), student, as_dict = True)
def get_list_context(context=None):
- return {
- "show_sidebar": True,
- 'no_breadcrumbs': True,
- "title": _("Assessment Schedule"),
- "get_list": get_assessment_list,
- "row_template": "templates/includes/assessment/assessment_row.html"
- }
+ return {
+ "show_sidebar": True,
+ 'no_breadcrumbs': True,
+ "title": _("Assessment Schedule"),
+ "get_list": get_assessment_list,
+ "row_template": "templates/includes/assessment/assessment_row.html"
+ }
+
+@frappe.whitelist()
+def get_grade(grading_structure, result):
+ grade = frappe.db.sql("""select gi.from_score, gi.to_score, gi.grade_code, gi.grade_description
+ from `tabGrading Structure` as gs, `tabGrade Interval` as gi
+ where gs.name = gi.parent and gs.name = %(grading_structure)s and gi.from_score <= %(result)s
+ and gi.to_score >= %(result)s""".format(),
+ {
+ "grading_structure":grading_structure,
+ "result": result
+ },
+ as_dict=True)
+
+ return grade[0].grade_code if grade else ""
+
+def validate_grade(score, grade):
+ pass
\ No newline at end of file
diff --git a/erpnext/schools/doctype/assessment_result/assessment_result.json b/erpnext/schools/doctype/assessment_result/assessment_result.json
index 19339eb..91e580d 100644
--- a/erpnext/schools/doctype/assessment_result/assessment_result.json
+++ b/erpnext/schools/doctype/assessment_result/assessment_result.json
@@ -109,6 +109,31 @@
"search_index": 0,
"set_only_once": 0,
"unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "grade",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 1,
+ "label": "Grade",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
}
],
"hide_heading": 0,
@@ -121,7 +146,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
- "modified": "2016-08-01 10:37:23.571679",
+ "modified": "2016-08-27 12:15:01.923000",
"modified_by": "Administrator",
"module": "Schools",
"name": "Assessment Result",
diff --git a/erpnext/schools/doctype/course_schedule/test_course_schedule.py b/erpnext/schools/doctype/course_schedule/test_course_schedule.py
index b527303..e9fce4b 100644
--- a/erpnext/schools/doctype/course_schedule/test_course_schedule.py
+++ b/erpnext/schools/doctype/course_schedule/test_course_schedule.py
@@ -24,27 +24,27 @@
cs1 = make_course_schedule_test_record(simulate= True)
cs2 = make_course_schedule_test_record(from_time= cs1.from_time, to_time= cs1.to_time,
- student_group="TC2-TP-2014-2015-_Test Academic Term", room="RM0002", do_not_save= 1)
+ student_group="TC2-TP-2014-2015-2014-2015 (_Test Academic Term)", room="RM0002", do_not_save= 1)
self.assertRaises(OverlapError, cs2.save)
def test_room_conflict(self):
cs1 = make_course_schedule_test_record(simulate= True)
cs2 = make_course_schedule_test_record(from_time= cs1.from_time, to_time= cs1.to_time,
- student_group="TC2-TP-2014-2015-_Test Academic Term", instructor="_T-Instructor-00002", do_not_save= 1)
+ student_group="TC2-TP-2014-2015-2014-2015 (_Test Academic Term)", instructor="_T-Instructor-00002", do_not_save= 1)
self.assertRaises(OverlapError, cs2.save)
def test_no_conflict(self):
cs1 = make_course_schedule_test_record(simulate= True)
make_course_schedule_test_record(from_time= cs1.from_time, to_time= cs1.to_time,
- student_group="TC2-TP-2014-2015-_Test Academic Term", instructor="_T-Instructor-00002", room="RM0002")
+ student_group="TC2-TP-2014-2015-2014-2015 (_Test Academic Term)", instructor="_T-Instructor-00002", room="RM0002")
def make_course_schedule_test_record(**args):
args = frappe._dict(args)
course_schedule = frappe.new_doc("Course Schedule")
- course_schedule.student_group = args.student_group or "TC-TP-2014-2015-_Test Academic Term"
+ course_schedule.student_group = args.student_group or "TC-TP-2014-2015-2014-2015 (_Test Academic Term)"
course_schedule.course = args.course or "_Test Course"
course_schedule.instructor = args.instructor or "_T-Instructor-00001"
course_schedule.room = args.room or "RM0001"
diff --git a/erpnext/schools/doctype/fees/fees.js b/erpnext/schools/doctype/fees/fees.js
index 22c6d8a..7c35de4 100644
--- a/erpnext/schools/doctype/fees/fees.js
+++ b/erpnext/schools/doctype/fees/fees.js
@@ -2,6 +2,25 @@
cur_frm.add_fetch("student", "title", "student_name");
frappe.ui.form.on("Fees", {
+
+ onload: function(frm){
+ cur_frm.set_query("academic_term",function(){
+ return{
+ "filters":{
+ "academic_year": (frm.doc.academic_year)
+ }
+ };
+ });
+
+ cur_frm.set_query("fee_structure",function(){
+ return{
+ "filters":{
+ "academic_term": (frm.doc.academic_term)
+ }
+ };
+ });
+ },
+
refresh: function(frm) {
if (frm.doc.docstatus === 1 && (frm.doc.total_amount > frm.doc.paid_amount)) {
frm.add_custom_button(__("Collect Fees"), function() {
diff --git a/erpnext/schools/doctype/fees/fees.json b/erpnext/schools/doctype/fees/fees.json
index ce911ad..5682ef9 100644
--- a/erpnext/schools/doctype/fees/fees.json
+++ b/erpnext/schools/doctype/fees/fees.json
@@ -41,17 +41,17 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
- "fieldname": "academic_term",
+ "fieldname": "academic_year",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
- "label": "Academic Term",
+ "label": "Academic Year",
"length": 0,
"no_copy": 0,
- "options": "Academic Term",
+ "options": "Academic Year",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -67,17 +67,17 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
- "fieldname": "academic_year",
+ "fieldname": "academic_term",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
- "label": "Academic Year",
+ "label": "Academic Term",
"length": 0,
"no_copy": 0,
- "options": "Academic Year",
+ "options": "Academic Term",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -480,7 +480,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
- "modified": "2016-07-27 03:52:28.509757",
+ "modified": "2016-08-26 02:28:48.877990",
"modified_by": "Administrator",
"module": "Schools",
"name": "Fees",
diff --git a/erpnext/schools/doctype/grade_interval/__init__.py b/erpnext/schools/doctype/grade_interval/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/schools/doctype/grade_interval/__init__.py
diff --git a/erpnext/schools/doctype/grade_interval/grade_interval.json b/erpnext/schools/doctype/grade_interval/grade_interval.json
new file mode 100644
index 0000000..79ef9f4
--- /dev/null
+++ b/erpnext/schools/doctype/grade_interval/grade_interval.json
@@ -0,0 +1,137 @@
+{
+ "allow_copy": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "beta": 0,
+ "creation": "2016-08-26 03:11:09.591049",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "fields": [
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "grade_code",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 1,
+ "label": "Grade Code",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "from_score",
+ "fieldtype": "Float",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 1,
+ "label": "From Score",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "1",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "to_score",
+ "fieldtype": "Float",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 1,
+ "label": "To Score",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "1",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "grade_description",
+ "fieldtype": "Small Text",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 1,
+ "label": "Grade Description",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ }
+ ],
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "in_dialog": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 1,
+ "max_attachments": 0,
+ "modified": "2016-08-27 15:45:04.657328",
+ "modified_by": "Administrator",
+ "module": "Schools",
+ "name": "Grade Interval",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/schools/doctype/grade_interval/grade_interval.py b/erpnext/schools/doctype/grade_interval/grade_interval.py
new file mode 100644
index 0000000..c8ded13
--- /dev/null
+++ b/erpnext/schools/doctype/grade_interval/grade_interval.py
@@ -0,0 +1,11 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class GradeInterval(Document):
+ def validate(self):
+ pass
\ No newline at end of file
diff --git a/erpnext/schools/doctype/grading_structure/__init__.py b/erpnext/schools/doctype/grading_structure/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/schools/doctype/grading_structure/__init__.py
diff --git a/erpnext/schools/doctype/grading_structure/grading_structure.js b/erpnext/schools/doctype/grading_structure/grading_structure.js
new file mode 100644
index 0000000..36f4504
--- /dev/null
+++ b/erpnext/schools/doctype/grading_structure/grading_structure.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Grading Structure', {
+ refresh: function(frm) {
+
+ }
+});
diff --git a/erpnext/schools/doctype/grading_structure/grading_structure.json b/erpnext/schools/doctype/grading_structure/grading_structure.json
new file mode 100644
index 0000000..cda6bd4
--- /dev/null
+++ b/erpnext/schools/doctype/grading_structure/grading_structure.json
@@ -0,0 +1,185 @@
+{
+ "allow_copy": 0,
+ "allow_import": 0,
+ "allow_rename": 1,
+ "autoname": "field:grading_system_name",
+ "beta": 0,
+ "creation": "2016-08-26 03:06:53.922972",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "fields": [
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "grading_system_name",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 1,
+ "label": "Grading System Name",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "description",
+ "fieldtype": "Text",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 1,
+ "label": "Description",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "column_break_3",
+ "fieldtype": "Column Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "grading_intervals_section",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Grading Intervals",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "grade_intervals",
+ "fieldtype": "Table",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Grade Intervals",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Grade Interval",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ }
+ ],
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "in_dialog": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 0,
+ "max_attachments": 0,
+ "modified": "2016-08-27 14:20:50.709823",
+ "modified_by": "Administrator",
+ "module": "Schools",
+ "name": "Grading Structure",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "amend": 0,
+ "apply_user_permissions": 0,
+ "cancel": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Academics User",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 0,
+ "write": 1
+ }
+ ],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "grading_system_name",
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/schools/doctype/grading_structure/grading_structure.py b/erpnext/schools/doctype/grading_structure/grading_structure.py
new file mode 100644
index 0000000..1b5d6a8
--- /dev/null
+++ b/erpnext/schools/doctype/grading_structure/grading_structure.py
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+from frappe import _
+from frappe.utils import cstr
+
+class GradingStructure(Document):
+ def validate(self):
+ grade_intervals = self.get("grade_intervals")
+ check_overlap(grade_intervals, self)
+
+#Check if any of the grade intervals for this grading structure overlap
+def check_overlap(grade_intervals, parent_doc):
+ for interval1 in grade_intervals:
+ for interval2 in grade_intervals:
+ if interval1.name == interval2.name:
+ pass
+ else:
+ if (interval1.from_score <= interval2.from_score and interval1.to_score >= interval2.from_score) or (interval1.from_score <= interval2.to_score and interval1.to_score >= interval2.to_score):
+ frappe.throw(_("""The intervals for Grade Code {0} overlaps with the grade intervals for other grades.
+ Please check intervals {0} and {1} and try again""".format(interval1.grade_code, interval2.grade_code)))
\ No newline at end of file
diff --git a/erpnext/schools/doctype/grading_structure/test_grading_structure.py b/erpnext/schools/doctype/grading_structure/test_grading_structure.py
new file mode 100644
index 0000000..0e36080
--- /dev/null
+++ b/erpnext/schools/doctype/grading_structure/test_grading_structure.py
@@ -0,0 +1,12 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+
+# test_records = frappe.get_test_records('Grading Structure')
+
+class TestGradingStructure(unittest.TestCase):
+ pass
diff --git a/erpnext/schools/doctype/program/program.json b/erpnext/schools/doctype/program/program.json
index acd5a8e..ca6e1df 100644
--- a/erpnext/schools/doctype/program/program.json
+++ b/erpnext/schools/doctype/program/program.json
@@ -250,7 +250,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
- "modified": "2016-07-25 01:33:56.912243",
+ "modified": "2016-08-27 03:21:35.806511",
"modified_by": "Administrator",
"module": "Schools",
"name": "Program",
diff --git a/erpnext/schools/doctype/program_enrollment/program_enrollment.js b/erpnext/schools/doctype/program_enrollment/program_enrollment.js
index 038afd9..72fc6f2 100644
--- a/erpnext/schools/doctype/program_enrollment/program_enrollment.js
+++ b/erpnext/schools/doctype/program_enrollment/program_enrollment.js
@@ -18,5 +18,23 @@
}
});
}
+ },
+
+ onload: function(frm, cdt, cdn){
+ cur_frm.set_query("academic_term", "fees", function(){
+ return{
+ "filters":{
+ "academic_year": (frm.doc.academic_year)
+ }
+ };
+ });
+
+ cur_frm.fields_dict['fees'].grid.get_field('fee_structure').get_query = function(doc, cdt, cdn) {
+ var d = locals[cdt][cdn];
+ return {
+ filters: {'academic_term': d.academic_term}
+ }
+ };
+
}
});
diff --git a/erpnext/schools/doctype/student/student.json b/erpnext/schools/doctype/student/student.json
index 22b8c4e..454aeb2 100644
--- a/erpnext/schools/doctype/student/student.json
+++ b/erpnext/schools/doctype/student/student.json
@@ -165,7 +165,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
- "default": "Today",
+ "default": "",
"fieldname": "joining_date",
"fieldtype": "Date",
"hidden": 0,
@@ -180,7 +180,7 @@
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
- "read_only": 1,
+ "read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -371,7 +371,7 @@
"bold": 0,
"collapsible": 0,
"fieldname": "nationality",
- "fieldtype": "Data",
+ "fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -380,6 +380,7 @@
"label": "Nationality",
"length": 0,
"no_copy": 0,
+ "options": "Country",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -456,7 +457,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
- "modified": "2016-07-25 07:22:57.581638",
+ "modified": "2016-08-21 05:41:34.091353",
"modified_by": "Administrator",
"module": "Schools",
"name": "Student",
diff --git a/erpnext/schools/doctype/student_applicant/student_applicant.json b/erpnext/schools/doctype/student_applicant/student_applicant.json
index b9505a5..8dbd22a 100644
--- a/erpnext/schools/doctype/student_applicant/student_applicant.json
+++ b/erpnext/schools/doctype/student_applicant/student_applicant.json
@@ -525,7 +525,7 @@
"bold": 0,
"collapsible": 0,
"fieldname": "nationality",
- "fieldtype": "Data",
+ "fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -534,6 +534,7 @@
"label": "Nationality",
"length": 0,
"no_copy": 0,
+ "options": "Country",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -633,7 +634,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
- "modified": "2016-07-25 01:24:27.384647",
+ "modified": "2016-08-26 01:01:45.669665",
"modified_by": "Administrator",
"module": "Schools",
"name": "Student Applicant",
diff --git a/erpnext/schools/doctype/student_batch/student_batch.js b/erpnext/schools/doctype/student_batch/student_batch.js
index 73d4faa..931e41b 100644
--- a/erpnext/schools/doctype/student_batch/student_batch.js
+++ b/erpnext/schools/doctype/student_batch/student_batch.js
@@ -4,7 +4,18 @@
frappe.ui.form.on('Student Batch', {
refresh: function(frm) {
+ },
+
+ onload: function(frm){
+ cur_frm.set_query("academic_term",function(){
+ return{
+ "filters":{
+ "academic_year": (frm.doc.academic_year)
+ }
+ };
+ });
}
+
});
cur_frm.add_fetch("student", "title", "student_name");
diff --git a/erpnext/schools/doctype/student_batch/student_batch.json b/erpnext/schools/doctype/student_batch/student_batch.json
index a806ae3..fa7e6b5 100644
--- a/erpnext/schools/doctype/student_batch/student_batch.json
+++ b/erpnext/schools/doctype/student_batch/student_batch.json
@@ -199,7 +199,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2016-07-22 09:19:51.141234",
+ "modified": "2016-08-24 05:32:00.585277",
"modified_by": "Administrator",
"module": "Schools",
"name": "Student Batch",
diff --git a/erpnext/schools/doctype/student_batch/student_batch.py b/erpnext/schools/doctype/student_batch/student_batch.py
index 107ef93..ec2dc79 100644
--- a/erpnext/schools/doctype/student_batch/student_batch.py
+++ b/erpnext/schools/doctype/student_batch/student_batch.py
@@ -8,12 +8,12 @@
import frappe
class StudentBatch(Document):
- def autoname(self):
- prog_abb = frappe.db.get_value("Program", self.program, "program_abbreviation")
- if not prog_abb:
- prog_abb = self.program
- self.name = prog_abb + "-"+ self.student_batch_name + "-" + self.academic_year
-
- def validate(self):
- validate_duplicate_student(self.students)
-
\ No newline at end of file
+ def autoname(self):
+ prog_abb = frappe.db.get_value("Program", self.program, "program_abbreviation")
+ if not prog_abb:
+ prog_abb = self.program
+ self.name = prog_abb + "-"+ self.student_batch_name + "-" + self.academic_year
+
+ def validate(self):
+ validate_duplicate_student(self.students)
+
\ No newline at end of file
diff --git a/erpnext/schools/doctype/student_group/student_group.js b/erpnext/schools/doctype/student_group/student_group.js
index eed3342..784f557 100644
--- a/erpnext/schools/doctype/student_group/student_group.js
+++ b/erpnext/schools/doctype/student_group/student_group.js
@@ -16,4 +16,19 @@
frappe.set_route("List", "Assessment");
});
}
-});
\ No newline at end of file
+});
+
+frappe.ui.form.on("Student Group", "onload", function(frm){
+ cur_frm.set_query("academic_term",function(){
+ return{
+ "filters":{
+ "academic_year": (frm.doc.academic_year)
+ }
+ };
+ });
+});
+
+//If Student Batch is entered, deduce program, academic_year and academic term from it
+cur_frm.add_fetch("student_batch", "program", "program");
+cur_frm.add_fetch("student_batch", "academic_term", "academic_term");
+cur_frm.add_fetch("student_batch", "academic_year", "academic_year");
diff --git a/erpnext/schools/doctype/student_group/student_group.json b/erpnext/schools/doctype/student_group/student_group.json
index e4b4ea3..a0584e3 100644
--- a/erpnext/schools/doctype/student_group/student_group.json
+++ b/erpnext/schools/doctype/student_group/student_group.json
@@ -41,17 +41,17 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
- "fieldname": "academic_term",
+ "fieldname": "academic_year",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
- "label": "Academic Term",
+ "label": "Academic Year",
"length": 0,
"no_copy": 0,
- "options": "Academic Term",
+ "options": "Academic Year",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -67,17 +67,17 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
- "fieldname": "academic_year",
+ "fieldname": "academic_term",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
- "label": "Academic Year",
+ "label": "Academic Term",
"length": 0,
"no_copy": 0,
- "options": "Academic Year",
+ "options": "Academic Term",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -280,7 +280,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
- "modified": "2016-07-25 06:23:43.903111",
+ "modified": "2016-08-24 05:21:05.058875",
"modified_by": "Administrator",
"module": "Schools",
"name": "Student Group",
diff --git a/erpnext/schools/doctype/student_group/test_records.json b/erpnext/schools/doctype/student_group/test_records.json
index a14f670..27cd181 100644
--- a/erpnext/schools/doctype/student_group/test_records.json
+++ b/erpnext/schools/doctype/student_group/test_records.json
@@ -3,12 +3,12 @@
"program": "_Test Program",
"course": "_Test Course",
"academic_year": "2014-2015",
- "academic_term": "_Test Academic Term"
+ "academic_term": "2014-2015 (_Test Academic Term)"
},
{
"program": "_Test Program",
"course": "_Test Course 2",
"academic_year": "2014-2015",
- "academic_term": "_Test Academic Term"
+ "academic_term": "2014-2015 (_Test Academic Term)"
}
]
\ No newline at end of file
diff --git a/erpnext/schools/doctype/student_group_creation_tool/student_group_creation_tool.js b/erpnext/schools/doctype/student_group_creation_tool/student_group_creation_tool.js
index 056574c..9c796bb 100644
--- a/erpnext/schools/doctype/student_group_creation_tool/student_group_creation_tool.js
+++ b/erpnext/schools/doctype/student_group_creation_tool/student_group_creation_tool.js
@@ -20,4 +20,14 @@
}
}
})
+});
+
+frappe.ui.form.on("Student Group Creation Tool", "onload", function(frm){
+ cur_frm.set_query("academic_term",function(){
+ return{
+ "filters":{
+ "academic_year": (frm.doc.academic_year)
+ }
+ };
+ });
});
\ No newline at end of file
diff --git a/erpnext/setup/setup_wizard/setup_wizard.py b/erpnext/setup/setup_wizard/setup_wizard.py
index 191f169..945dfb1 100644
--- a/erpnext/setup/setup_wizard/setup_wizard.py
+++ b/erpnext/setup/setup_wizard/setup_wizard.py
@@ -15,538 +15,541 @@
from erpnext.setup.setup_wizard.domainify import setup_domain
def setup_complete(args=None):
- if frappe.db.sql("select name from tabCompany"):
- frappe.throw(_("Setup Already Complete!!"))
+ if frappe.db.sql("select name from tabCompany"):
+ frappe.throw(_("Setup Already Complete!!"))
- install_fixtures.install(args.get("country"))
+ install_fixtures.install(args.get("country"))
- create_price_lists(args)
- create_fiscal_year_and_company(args)
- create_users(args)
- set_defaults(args)
- create_territories()
- create_feed_and_todo()
- create_email_digest()
- create_letter_head(args)
- create_taxes(args)
- create_items(args)
- create_customers(args)
- create_suppliers(args)
+ create_price_lists(args)
+ create_fiscal_year_and_company(args)
+ create_users(args)
+ set_defaults(args)
+ create_territories()
+ create_feed_and_todo()
+ create_email_digest()
+ create_letter_head(args)
+ create_taxes(args)
+ create_items(args)
+ create_customers(args)
+ create_suppliers(args)
- if args.domain.lower() == 'education':
- create_academic_term()
- create_academic_year()
- create_program(args)
- create_course(args)
- create_instructor(args)
- create_room(args)
+ if args.domain.lower() == 'education':
+ create_academic_year()
+ create_academic_term()
+ create_program(args)
+ create_course(args)
+ create_instructor(args)
+ create_room(args)
- if args.get('setup_website'):
- website_maker(args)
+ if args.get('setup_website'):
+ website_maker(args)
- create_logo(args)
+ create_logo(args)
- frappe.local.message_log = []
- setup_domain(args.get('domain'))
+ frappe.local.message_log = []
+ setup_domain(args.get('domain'))
- frappe.db.commit()
- login_as_first_user(args)
+ frappe.db.commit()
+ login_as_first_user(args)
- frappe.db.commit()
- frappe.clear_cache()
+ frappe.db.commit()
+ frappe.clear_cache()
- if args.get("add_sample_data"):
- try:
- make_sample_data()
- frappe.clear_cache()
- except:
- # clear message
- if frappe.message_log:
- frappe.message_log.pop()
+ if args.get("add_sample_data"):
+ try:
+ make_sample_data()
+ frappe.clear_cache()
+ except:
+ # clear message
+ if frappe.message_log:
+ frappe.message_log.pop()
- pass
+ pass
def create_fiscal_year_and_company(args):
- if (args.get('fy_start_date')):
- curr_fiscal_year = get_fy_details(args.get('fy_start_date'), args.get('fy_end_date'))
- frappe.get_doc({
- "doctype":"Fiscal Year",
- 'year': curr_fiscal_year,
- 'year_start_date': args.get('fy_start_date'),
- 'year_end_date': args.get('fy_end_date'),
- }).insert()
- args["curr_fiscal_year"] = curr_fiscal_year
+ if (args.get('fy_start_date')):
+ curr_fiscal_year = get_fy_details(args.get('fy_start_date'), args.get('fy_end_date'))
+ frappe.get_doc({
+ "doctype":"Fiscal Year",
+ 'year': curr_fiscal_year,
+ 'year_start_date': args.get('fy_start_date'),
+ 'year_end_date': args.get('fy_end_date'),
+ }).insert()
+ args["curr_fiscal_year"] = curr_fiscal_year
- # Company
- if (args.get('company_name')):
- frappe.get_doc({
- "doctype":"Company",
- 'company_name':args.get('company_name').strip(),
- 'abbr':args.get('company_abbr'),
- 'default_currency':args.get('currency'),
- 'country': args.get('country'),
- 'chart_of_accounts': args.get(('chart_of_accounts')),
- 'domain': args.get('domain')
- }).insert()
+ # Company
+ if (args.get('company_name')):
+ frappe.get_doc({
+ "doctype":"Company",
+ 'company_name':args.get('company_name').strip(),
+ 'abbr':args.get('company_abbr'),
+ 'default_currency':args.get('currency'),
+ 'country': args.get('country'),
+ 'chart_of_accounts': args.get(('chart_of_accounts')),
+ 'domain': args.get('domain')
+ }).insert()
- #Enable shopping cart
- enable_shopping_cart(args)
+ #Enable shopping cart
+ enable_shopping_cart(args)
- # Bank Account
- create_bank_account(args)
+ # Bank Account
+ create_bank_account(args)
def enable_shopping_cart(args):
- frappe.get_doc({
- "doctype": "Shopping Cart Settings",
- "enabled": 1,
- 'company': args.get('company_name').strip(),
- 'price_list': frappe.db.get_value("Price List", {"selling": 1}),
- 'default_customer_group': _("Individual"),
- 'quotation_series': "QTN-",
- }).insert()
+ frappe.get_doc({
+ "doctype": "Shopping Cart Settings",
+ "enabled": 1,
+ 'company': args.get('company_name').strip(),
+ 'price_list': frappe.db.get_value("Price List", {"selling": 1}),
+ 'default_customer_group': _("Individual"),
+ 'quotation_series': "QTN-",
+ }).insert()
def create_bank_account(args):
- if args.get("bank_account"):
- company_name = args.get('company_name').strip()
- bank_account_group = frappe.db.get_value("Account",
- {"account_type": "Bank", "is_group": 1, "root_type": "Asset",
- "company": company_name})
- if bank_account_group:
- bank_account = frappe.get_doc({
- "doctype": "Account",
- 'account_name': args.get("bank_account"),
- 'parent_account': bank_account_group,
- 'is_group':0,
- 'company': company_name,
- "account_type": "Bank",
- })
- try:
- return bank_account.insert()
- except RootNotEditable:
- frappe.throw(_("Bank account cannot be named as {0}").format(args.get("bank_account")))
- except frappe.DuplicateEntryError:
- # bank account same as a CoA entry
- pass
+ if args.get("bank_account"):
+ company_name = args.get('company_name').strip()
+ bank_account_group = frappe.db.get_value("Account",
+ {"account_type": "Bank", "is_group": 1, "root_type": "Asset",
+ "company": company_name})
+ if bank_account_group:
+ bank_account = frappe.get_doc({
+ "doctype": "Account",
+ 'account_name': args.get("bank_account"),
+ 'parent_account': bank_account_group,
+ 'is_group':0,
+ 'company': company_name,
+ "account_type": "Bank",
+ })
+ try:
+ return bank_account.insert()
+ except RootNotEditable:
+ frappe.throw(_("Bank account cannot be named as {0}").format(args.get("bank_account")))
+ except frappe.DuplicateEntryError:
+ # bank account same as a CoA entry
+ pass
def create_price_lists(args):
- for pl_type, pl_name in (("Selling", _("Standard Selling")), ("Buying", _("Standard Buying"))):
- frappe.get_doc({
- "doctype": "Price List",
- "price_list_name": pl_name,
- "enabled": 1,
- "buying": 1 if pl_type == "Buying" else 0,
- "selling": 1 if pl_type == "Selling" else 0,
- "currency": args["currency"]
- }).insert()
+ for pl_type, pl_name in (("Selling", _("Standard Selling")), ("Buying", _("Standard Buying"))):
+ frappe.get_doc({
+ "doctype": "Price List",
+ "price_list_name": pl_name,
+ "enabled": 1,
+ "buying": 1 if pl_type == "Buying" else 0,
+ "selling": 1 if pl_type == "Selling" else 0,
+ "currency": args["currency"]
+ }).insert()
def set_defaults(args):
- # enable default currency
- frappe.db.set_value("Currency", args.get("currency"), "enabled", 1)
+ # enable default currency
+ frappe.db.set_value("Currency", args.get("currency"), "enabled", 1)
- global_defaults = frappe.get_doc("Global Defaults", "Global Defaults")
- global_defaults.update({
- 'current_fiscal_year': args.curr_fiscal_year,
- 'default_currency': args.get('currency'),
- 'default_company':args.get('company_name').strip(),
- "country": args.get("country"),
- })
+ global_defaults = frappe.get_doc("Global Defaults", "Global Defaults")
+ global_defaults.update({
+ 'current_fiscal_year': args.curr_fiscal_year,
+ 'default_currency': args.get('currency'),
+ 'default_company':args.get('company_name').strip(),
+ "country": args.get("country"),
+ })
- global_defaults.save()
+ global_defaults.save()
- frappe.db.set_value("System Settings", None, "email_footer_address", args.get("company"))
+ frappe.db.set_value("System Settings", None, "email_footer_address", args.get("company"))
- accounts_settings = frappe.get_doc("Accounts Settings")
- accounts_settings.auto_accounting_for_stock = 1
- accounts_settings.save()
+ accounts_settings = frappe.get_doc("Accounts Settings")
+ accounts_settings.auto_accounting_for_stock = 1
+ accounts_settings.save()
- stock_settings = frappe.get_doc("Stock Settings")
- stock_settings.item_naming_by = "Item Code"
- stock_settings.valuation_method = "FIFO"
- stock_settings.default_warehouse = frappe.db.get_value('Warehouse', {'warehouse_name': _('Stores')})
- stock_settings.stock_uom = _("Nos")
- stock_settings.auto_indent = 1
- stock_settings.auto_insert_price_list_rate_if_missing = 1
- stock_settings.automatically_set_serial_nos_based_on_fifo = 1
- stock_settings.save()
+ stock_settings = frappe.get_doc("Stock Settings")
+ stock_settings.item_naming_by = "Item Code"
+ stock_settings.valuation_method = "FIFO"
+ stock_settings.default_warehouse = frappe.db.get_value('Warehouse', {'warehouse_name': _('Stores')})
+ stock_settings.stock_uom = _("Nos")
+ stock_settings.auto_indent = 1
+ stock_settings.auto_insert_price_list_rate_if_missing = 1
+ stock_settings.automatically_set_serial_nos_based_on_fifo = 1
+ stock_settings.save()
- selling_settings = frappe.get_doc("Selling Settings")
- selling_settings.cust_master_name = "Customer Name"
- selling_settings.so_required = "No"
- selling_settings.dn_required = "No"
- selling_settings.save()
+ selling_settings = frappe.get_doc("Selling Settings")
+ selling_settings.cust_master_name = "Customer Name"
+ selling_settings.so_required = "No"
+ selling_settings.dn_required = "No"
+ selling_settings.save()
- buying_settings = frappe.get_doc("Buying Settings")
- buying_settings.supp_master_name = "Supplier Name"
- buying_settings.po_required = "No"
- buying_settings.pr_required = "No"
- buying_settings.maintain_same_rate = 1
- buying_settings.save()
+ buying_settings = frappe.get_doc("Buying Settings")
+ buying_settings.supp_master_name = "Supplier Name"
+ buying_settings.po_required = "No"
+ buying_settings.pr_required = "No"
+ buying_settings.maintain_same_rate = 1
+ buying_settings.save()
- notification_control = frappe.get_doc("Notification Control")
- notification_control.quotation = 1
- notification_control.sales_invoice = 1
- notification_control.purchase_order = 1
- notification_control.save()
+ notification_control = frappe.get_doc("Notification Control")
+ notification_control.quotation = 1
+ notification_control.sales_invoice = 1
+ notification_control.purchase_order = 1
+ notification_control.save()
- hr_settings = frappe.get_doc("HR Settings")
- hr_settings.emp_created_by = "Naming Series"
- hr_settings.save()
+ hr_settings = frappe.get_doc("HR Settings")
+ hr_settings.emp_created_by = "Naming Series"
+ hr_settings.save()
def create_feed_and_todo():
- """update Activity feed and create todo for creation of item, customer, vendor"""
- add_info_comment(**{
- "subject": _("ERPNext Setup Complete!")
- })
+ """update Activity feed and create todo for creation of item, customer, vendor"""
+ add_info_comment(**{
+ "subject": _("ERPNext Setup Complete!")
+ })
def create_email_digest():
- from frappe.utils.user import get_system_managers
- system_managers = get_system_managers(only_name=True)
- if not system_managers:
- return
+ from frappe.utils.user import get_system_managers
+ system_managers = get_system_managers(only_name=True)
+ if not system_managers:
+ return
- companies = frappe.db.sql_list("select name FROM `tabCompany`")
- for company in companies:
- if not frappe.db.exists("Email Digest", "Default Weekly Digest - " + company):
- edigest = frappe.get_doc({
- "doctype": "Email Digest",
- "name": "Default Weekly Digest - " + company,
- "company": company,
- "frequency": "Weekly",
- "recipient_list": "\n".join(system_managers)
- })
+ companies = frappe.db.sql_list("select name FROM `tabCompany`")
+ for company in companies:
+ if not frappe.db.exists("Email Digest", "Default Weekly Digest - " + company):
+ edigest = frappe.get_doc({
+ "doctype": "Email Digest",
+ "name": "Default Weekly Digest - " + company,
+ "company": company,
+ "frequency": "Weekly",
+ "recipient_list": "\n".join(system_managers)
+ })
- for df in edigest.meta.get("fields", {"fieldtype": "Check"}):
- if df.fieldname != "scheduler_errors":
- edigest.set(df.fieldname, 1)
+ for df in edigest.meta.get("fields", {"fieldtype": "Check"}):
+ if df.fieldname != "scheduler_errors":
+ edigest.set(df.fieldname, 1)
- edigest.insert()
+ edigest.insert()
- # scheduler errors digest
- if companies:
- edigest = frappe.new_doc("Email Digest")
- edigest.update({
- "name": "Scheduler Errors",
- "company": companies[0],
- "frequency": "Daily",
- "recipient_list": "\n".join(system_managers),
- "scheduler_errors": 1,
- "enabled": 1
- })
- edigest.insert()
+ # scheduler errors digest
+ if companies:
+ edigest = frappe.new_doc("Email Digest")
+ edigest.update({
+ "name": "Scheduler Errors",
+ "company": companies[0],
+ "frequency": "Daily",
+ "recipient_list": "\n".join(system_managers),
+ "scheduler_errors": 1,
+ "enabled": 1
+ })
+ edigest.insert()
def get_fy_details(fy_start_date, fy_end_date):
- start_year = getdate(fy_start_date).year
- if start_year == getdate(fy_end_date).year:
- fy = cstr(start_year)
- else:
- fy = cstr(start_year) + '-' + cstr(start_year + 1)
- return fy
+ start_year = getdate(fy_start_date).year
+ if start_year == getdate(fy_end_date).year:
+ fy = cstr(start_year)
+ else:
+ fy = cstr(start_year) + '-' + cstr(start_year + 1)
+ return fy
def create_taxes(args):
- for i in xrange(1,6):
- if args.get("tax_" + str(i)):
- # replace % in case someone also enters the % symbol
- tax_rate = cstr(args.get("tax_rate_" + str(i)) or "").replace("%", "")
+ for i in xrange(1,6):
+ if args.get("tax_" + str(i)):
+ # replace % in case someone also enters the % symbol
+ tax_rate = cstr(args.get("tax_rate_" + str(i)) or "").replace("%", "")
- try:
- tax_group = frappe.db.get_value("Account", {"company": args.get("company_name"),
- "is_group": 1, "account_type": "Tax", "root_type": "Liability"})
- if tax_group:
- account = make_tax_head(args, i, tax_group, tax_rate)
- make_sales_and_purchase_tax_templates(account)
+ try:
+ tax_group = frappe.db.get_value("Account", {"company": args.get("company_name"),
+ "is_group": 1, "account_type": "Tax", "root_type": "Liability"})
+ if tax_group:
+ account = make_tax_head(args, i, tax_group, tax_rate)
+ make_sales_and_purchase_tax_templates(account)
- except frappe.NameError, e:
- if e.args[2][0]==1062:
- pass
- else:
- raise
- except RootNotEditable, e:
- pass
+ except frappe.NameError, e:
+ if e.args[2][0]==1062:
+ pass
+ else:
+ raise
+ except RootNotEditable, e:
+ pass
def make_tax_head(args, i, tax_group, tax_rate):
- return frappe.get_doc({
- "doctype":"Account",
- "company": args.get("company_name").strip(),
- "parent_account": tax_group,
- "account_name": args.get("tax_" + str(i)),
- "is_group": 0,
- "report_type": "Balance Sheet",
- "account_type": "Tax",
- "tax_rate": flt(tax_rate) if tax_rate else None
- }).insert(ignore_permissions=True)
+ return frappe.get_doc({
+ "doctype":"Account",
+ "company": args.get("company_name").strip(),
+ "parent_account": tax_group,
+ "account_name": args.get("tax_" + str(i)),
+ "is_group": 0,
+ "report_type": "Balance Sheet",
+ "account_type": "Tax",
+ "tax_rate": flt(tax_rate) if tax_rate else None
+ }).insert(ignore_permissions=True)
def make_sales_and_purchase_tax_templates(account):
- doc = {
- "doctype": "Sales Taxes and Charges Template",
- "title": account.name,
- "taxes": [{
- "category": "Valuation and Total",
- "charge_type": "On Net Total",
- "account_head": account.name,
- "description": "{0} @ {1}".format(account.account_name, account.tax_rate),
- "rate": account.tax_rate
- }]
- }
+ doc = {
+ "doctype": "Sales Taxes and Charges Template",
+ "title": account.name,
+ "taxes": [{
+ "category": "Valuation and Total",
+ "charge_type": "On Net Total",
+ "account_head": account.name,
+ "description": "{0} @ {1}".format(account.account_name, account.tax_rate),
+ "rate": account.tax_rate
+ }]
+ }
- # Sales
- frappe.get_doc(copy.deepcopy(doc)).insert()
+ # Sales
+ frappe.get_doc(copy.deepcopy(doc)).insert()
- # Purchase
- doc["doctype"] = "Purchase Taxes and Charges Template"
- frappe.get_doc(copy.deepcopy(doc)).insert()
+ # Purchase
+ doc["doctype"] = "Purchase Taxes and Charges Template"
+ frappe.get_doc(copy.deepcopy(doc)).insert()
def create_items(args):
- for i in xrange(1,6):
- item = args.get("item_" + str(i))
- if item:
- item_group = args.get("item_group_" + str(i))
- is_sales_item = args.get("is_sales_item_" + str(i))
- is_purchase_item = args.get("is_purchase_item_" + str(i))
- is_stock_item = item_group!=_("Services")
- default_warehouse = ""
- if is_stock_item:
- default_warehouse = frappe.db.get_value("Warehouse", filters={
- "warehouse_name": _("Finished Goods") if is_sales_item else _("Stores"),
- "company": args.get("company_name").strip()
- })
+ for i in xrange(1,6):
+ item = args.get("item_" + str(i))
+ if item:
+ item_group = args.get("item_group_" + str(i))
+ is_sales_item = args.get("is_sales_item_" + str(i))
+ is_purchase_item = args.get("is_purchase_item_" + str(i))
+ is_stock_item = item_group!=_("Services")
+ default_warehouse = ""
+ if is_stock_item:
+ default_warehouse = frappe.db.get_value("Warehouse", filters={
+ "warehouse_name": _("Finished Goods") if is_sales_item else _("Stores"),
+ "company": args.get("company_name").strip()
+ })
- try:
- frappe.get_doc({
- "doctype":"Item",
- "item_code": item,
- "item_name": item,
- "description": item,
- "show_in_website": 1,
- "is_sales_item": is_sales_item,
- "is_purchase_item": is_purchase_item,
- "is_stock_item": is_stock_item and 1 or 0,
- "item_group": item_group,
- "stock_uom": args.get("item_uom_" + str(i)),
- "default_warehouse": default_warehouse
- }).insert()
+ try:
+ frappe.get_doc({
+ "doctype":"Item",
+ "item_code": item,
+ "item_name": item,
+ "description": item,
+ "show_in_website": 1,
+ "is_sales_item": is_sales_item,
+ "is_purchase_item": is_purchase_item,
+ "is_stock_item": is_stock_item and 1 or 0,
+ "item_group": item_group,
+ "stock_uom": args.get("item_uom_" + str(i)),
+ "default_warehouse": default_warehouse
+ }).insert()
- if args.get("item_img_" + str(i)):
- item_image = args.get("item_img_" + str(i)).split(",")
- if len(item_image)==3:
- filename, filetype, content = item_image
- fileurl = save_file(filename, content, "Item", item, decode=True).file_url
- frappe.db.set_value("Item", item, "image", fileurl)
+ if args.get("item_img_" + str(i)):
+ item_image = args.get("item_img_" + str(i)).split(",")
+ if len(item_image)==3:
+ filename, filetype, content = item_image
+ fileurl = save_file(filename, content, "Item", item, decode=True).file_url
+ frappe.db.set_value("Item", item, "image", fileurl)
- if args.get("item_price_" + str(i)):
- item_price = flt(args.get("item_price_" + str(i)))
+ if args.get("item_price_" + str(i)):
+ item_price = flt(args.get("item_price_" + str(i)))
- if is_sales_item:
- price_list_name = frappe.db.get_value("Price List", {"selling": 1})
- make_item_price(item, price_list_name, item_price)
+ if is_sales_item:
+ price_list_name = frappe.db.get_value("Price List", {"selling": 1})
+ make_item_price(item, price_list_name, item_price)
- if is_purchase_item:
- price_list_name = frappe.db.get_value("Price List", {"buying": 1})
- make_item_price(item, price_list_name, item_price)
+ if is_purchase_item:
+ price_list_name = frappe.db.get_value("Price List", {"buying": 1})
+ make_item_price(item, price_list_name, item_price)
- except frappe.NameError:
- pass
+ except frappe.NameError:
+ pass
def make_item_price(item, price_list_name, item_price):
- frappe.get_doc({
- "doctype": "Item Price",
- "price_list": price_list_name,
- "item_code": item,
- "price_list_rate": item_price
- }).insert()
+ frappe.get_doc({
+ "doctype": "Item Price",
+ "price_list": price_list_name,
+ "item_code": item,
+ "price_list_rate": item_price
+ }).insert()
def create_customers(args):
- for i in xrange(1,6):
- customer = args.get("customer_" + str(i))
- if customer:
- try:
- doc = frappe.get_doc({
- "doctype":"Customer",
- "customer_name": customer,
- "customer_type": "Company",
- "customer_group": _("Commercial"),
- "territory": args.get("country"),
- "company": args.get("company_name").strip()
- }).insert()
+ for i in xrange(1,6):
+ customer = args.get("customer_" + str(i))
+ if customer:
+ try:
+ doc = frappe.get_doc({
+ "doctype":"Customer",
+ "customer_name": customer,
+ "customer_type": "Company",
+ "customer_group": _("Commercial"),
+ "territory": args.get("country"),
+ "company": args.get("company_name").strip()
+ }).insert()
- if args.get("customer_contact_" + str(i)):
- create_contact(args.get("customer_contact_" + str(i)),
- "customer", doc.name)
- except frappe.NameError:
- pass
+ if args.get("customer_contact_" + str(i)):
+ create_contact(args.get("customer_contact_" + str(i)),
+ "customer", doc.name)
+ except frappe.NameError:
+ pass
def create_suppliers(args):
- for i in xrange(1,6):
- supplier = args.get("supplier_" + str(i))
- if supplier:
- try:
- doc = frappe.get_doc({
- "doctype":"Supplier",
- "supplier_name": supplier,
- "supplier_type": _("Local"),
- "company": args.get("company_name").strip()
- }).insert()
+ for i in xrange(1,6):
+ supplier = args.get("supplier_" + str(i))
+ if supplier:
+ try:
+ doc = frappe.get_doc({
+ "doctype":"Supplier",
+ "supplier_name": supplier,
+ "supplier_type": _("Local"),
+ "company": args.get("company_name").strip()
+ }).insert()
- if args.get("supplier_contact_" + str(i)):
- create_contact(args.get("supplier_contact_" + str(i)),
- "supplier", doc.name)
- except frappe.NameError:
- pass
+ if args.get("supplier_contact_" + str(i)):
+ create_contact(args.get("supplier_contact_" + str(i)),
+ "supplier", doc.name)
+ except frappe.NameError:
+ pass
def create_contact(contact, party_type, party):
- """Create contact based on given contact name"""
- contact = contact.strip().split(" ")
+ """Create contact based on given contact name"""
+ contact = contact.strip().split(" ")
- frappe.get_doc({
- "doctype":"Contact",
- party_type: party,
- "first_name":contact[0],
- "last_name": len(contact) > 1 and contact[1] or ""
- }).insert()
+ frappe.get_doc({
+ "doctype":"Contact",
+ party_type: party,
+ "first_name":contact[0],
+ "last_name": len(contact) > 1 and contact[1] or ""
+ }).insert()
def create_letter_head(args):
- if args.get("attach_letterhead"):
- frappe.get_doc({
- "doctype":"Letter Head",
- "letter_head_name": _("Standard"),
- "is_default": 1
- }).insert()
+ if args.get("attach_letterhead"):
+ frappe.get_doc({
+ "doctype":"Letter Head",
+ "letter_head_name": _("Standard"),
+ "is_default": 1
+ }).insert()
- attach_letterhead = args.get("attach_letterhead").split(",")
- if len(attach_letterhead)==3:
- filename, filetype, content = attach_letterhead
- fileurl = save_file(filename, content, "Letter Head", _("Standard"), decode=True).file_url
- frappe.db.set_value("Letter Head", _("Standard"), "content", "<img src='%s' style='max-width: 100%%;'>" % fileurl)
+ attach_letterhead = args.get("attach_letterhead").split(",")
+ if len(attach_letterhead)==3:
+ filename, filetype, content = attach_letterhead
+ fileurl = save_file(filename, content, "Letter Head", _("Standard"), decode=True).file_url
+ frappe.db.set_value("Letter Head", _("Standard"), "content", "<img src='%s' style='max-width: 100%%;'>" % fileurl)
def create_logo(args):
- if args.get("attach_logo"):
- attach_logo = args.get("attach_logo").split(",")
- if len(attach_logo)==3:
- filename, filetype, content = attach_logo
- fileurl = save_file(filename, content, "Website Settings", "Website Settings",
- decode=True).file_url
- frappe.db.set_value("Website Settings", "Website Settings", "brand_html",
- "<img src='{0}' style='max-width: 40px; max-height: 25px;'> {1}".format(fileurl, args.get("company_name").strip()))
+ if args.get("attach_logo"):
+ attach_logo = args.get("attach_logo").split(",")
+ if len(attach_logo)==3:
+ filename, filetype, content = attach_logo
+ fileurl = save_file(filename, content, "Website Settings", "Website Settings",
+ decode=True).file_url
+ frappe.db.set_value("Website Settings", "Website Settings", "brand_html",
+ "<img src='{0}' style='max-width: 40px; max-height: 25px;'> {1}".format(fileurl, args.get("company_name").strip()))
def create_territories():
- """create two default territories, one for home country and one named Rest of the World"""
- from frappe.utils.nestedset import get_root_of
- country = frappe.db.get_default("country")
- root_territory = get_root_of("Territory")
- for name in (country, _("Rest Of The World")):
- if name and not frappe.db.exists("Territory", name):
- frappe.get_doc({
- "doctype": "Territory",
- "territory_name": name.replace("'", ""),
- "parent_territory": root_territory,
- "is_group": "No"
- }).insert()
+ """create two default territories, one for home country and one named Rest of the World"""
+ from frappe.utils.nestedset import get_root_of
+ country = frappe.db.get_default("country")
+ root_territory = get_root_of("Territory")
+ for name in (country, _("Rest Of The World")):
+ if name and not frappe.db.exists("Territory", name):
+ frappe.get_doc({
+ "doctype": "Territory",
+ "territory_name": name.replace("'", ""),
+ "parent_territory": root_territory,
+ "is_group": "No"
+ }).insert()
def login_as_first_user(args):
- if args.get("email") and hasattr(frappe.local, "login_manager"):
- frappe.local.login_manager.login_as(args.get("email"))
+ if args.get("email") and hasattr(frappe.local, "login_manager"):
+ frappe.local.login_manager.login_as(args.get("email"))
def create_users(args):
- if frappe.session.user == 'Administrator':
- return
+ if frappe.session.user == 'Administrator':
+ return
- # create employee for self
- emp = frappe.get_doc({
- "doctype": "Employee",
- "employee_name": " ".join(filter(None, [args.get("first_name"), args.get("last_name")])),
- "user_id": frappe.session.user,
- "status": "Active",
- "company": args.get("company_name")
- })
- emp.flags.ignore_mandatory = True
- emp.insert(ignore_permissions = True)
+ # create employee for self
+ emp = frappe.get_doc({
+ "doctype": "Employee",
+ "employee_name": " ".join(filter(None, [args.get("first_name"), args.get("last_name")])),
+ "user_id": frappe.session.user,
+ "status": "Active",
+ "company": args.get("company_name")
+ })
+ emp.flags.ignore_mandatory = True
+ emp.insert(ignore_permissions = True)
- for i in xrange(1,5):
- email = args.get("user_email_" + str(i))
- fullname = args.get("user_fullname_" + str(i))
- if email:
- if not fullname:
- fullname = email.split("@")[0]
+ for i in xrange(1,5):
+ email = args.get("user_email_" + str(i))
+ fullname = args.get("user_fullname_" + str(i))
+ if email:
+ if not fullname:
+ fullname = email.split("@")[0]
- parts = fullname.split(" ", 1)
+ parts = fullname.split(" ", 1)
- user = frappe.get_doc({
- "doctype": "User",
- "email": email,
- "first_name": parts[0],
- "last_name": parts[1] if len(parts) > 1 else "",
- "enabled": 1,
- "user_type": "System User"
- })
+ user = frappe.get_doc({
+ "doctype": "User",
+ "email": email,
+ "first_name": parts[0],
+ "last_name": parts[1] if len(parts) > 1 else "",
+ "enabled": 1,
+ "user_type": "System User"
+ })
- # default roles
- user.append_roles("Projects User", "Stock User", "Support Team")
+ # default roles
+ user.append_roles("Projects User", "Stock User", "Support Team")
- if args.get("user_sales_" + str(i)):
- user.append_roles("Sales User", "Sales Manager", "Accounts User")
- if args.get("user_purchaser_" + str(i)):
- user.append_roles("Purchase User", "Purchase Manager", "Accounts User")
- if args.get("user_accountant_" + str(i)):
- user.append_roles("Accounts Manager", "Accounts User")
+ if args.get("user_sales_" + str(i)):
+ user.append_roles("Sales User", "Sales Manager", "Accounts User")
+ if args.get("user_purchaser_" + str(i)):
+ user.append_roles("Purchase User", "Purchase Manager", "Accounts User")
+ if args.get("user_accountant_" + str(i)):
+ user.append_roles("Accounts Manager", "Accounts User")
- user.flags.delay_emails = True
+ user.flags.delay_emails = True
- if not frappe.db.get_value("User", email):
- user.insert(ignore_permissions=True)
+ if not frappe.db.get_value("User", email):
+ user.insert(ignore_permissions=True)
- # create employee
- emp = frappe.get_doc({
- "doctype": "Employee",
- "employee_name": fullname,
- "user_id": email,
- "status": "Active",
- "company": args.get("company_name")
- })
- emp.flags.ignore_mandatory = True
- emp.insert(ignore_permissions = True)
+ # create employee
+ emp = frappe.get_doc({
+ "doctype": "Employee",
+ "employee_name": fullname,
+ "user_id": email,
+ "status": "Active",
+ "company": args.get("company_name")
+ })
+ emp.flags.ignore_mandatory = True
+ emp.insert(ignore_permissions = True)
def create_academic_term():
- at = ["Semester 1", "Semester 2", "Semester 3"]
- for d in at:
- academic_term = frappe.new_doc("Academic Term")
- academic_term.term_name = d
- academic_term.save()
+ at = ["Semester 1", "Semester 2", "Semester 3"]
+ ay = ["2013-14", "2014-15", "2015-16", "2016-17", "2017-18"]
+ for y in ay:
+ for t in at:
+ academic_term = frappe.new_doc("Academic Term")
+ academic_term.academic_year = y
+ academic_term.term_name = t
+ academic_term.save()
def create_academic_year():
- ac = ["2013-14", "2014-15", "2015-16", "2016-17", "2017-18"]
- for d in ac:
- academic_year = frappe.new_doc("Academic Year")
- academic_year.academic_year_name = d
- academic_year.save()
+ ac = ["2013-14", "2014-15", "2015-16", "2016-17", "2017-18"]
+ for d in ac:
+ academic_year = frappe.new_doc("Academic Year")
+ academic_year.academic_year_name = d
+ academic_year.save()
def create_program(args):
- for i in xrange(1,6):
- if args.get("program_" + str(i)):
- program = frappe.new_doc("Program")
- program.program_name = args.get("program_" + str(i))
- program.save()
+ for i in xrange(1,6):
+ if args.get("program_" + str(i)):
+ program = frappe.new_doc("Program")
+ program.program_name = args.get("program_" + str(i))
+ program.save()
def create_course(args):
- for i in xrange(1,6):
- if args.get("course_" + str(i)):
- course = frappe.new_doc("Course")
- course.course_name = args.get("course_" + str(i))
- course.save()
+ for i in xrange(1,6):
+ if args.get("course_" + str(i)):
+ course = frappe.new_doc("Course")
+ course.course_name = args.get("course_" + str(i))
+ course.save()
def create_instructor(args):
- for i in xrange(1,6):
- if args.get("instructor_" + str(i)):
- instructor = frappe.new_doc("Instructor")
- instructor.instructor_name = args.get("instructor_" + str(i))
- instructor.save()
+ for i in xrange(1,6):
+ if args.get("instructor_" + str(i)):
+ instructor = frappe.new_doc("Instructor")
+ instructor.instructor_name = args.get("instructor_" + str(i))
+ instructor.save()
def create_room(args):
- for i in xrange(1,6):
- if args.get("room_" + str(i)):
- room = frappe.new_doc("Room")
- room.room_name = args.get("room_" + str(i))
- room.seating_capacity = args.get("room_capacity_" + str(i))
- room.save()
+ for i in xrange(1,6):
+ if args.get("room_" + str(i)):
+ room = frappe.new_doc("Room")
+ room.room_name = args.get("room_" + str(i))
+ room.seating_capacity = args.get("room_capacity_" + str(i))
+ room.save()
diff --git a/patches.txt b/patches.txt
new file mode 100644
index 0000000..8f127fe
--- /dev/null
+++ b/patches.txt
@@ -0,0 +1 @@
+bench.patches.v3.deprecate_old_config