mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-31 18:59:08 +00:00
feat(Education): added form dashboards and refactored custom buttons for better linking (#22727)
* feat: add form dashboards to all forms in Education Module * feat: Add Course to Programs button in Course DocType * refactor: custom buttons in Education module forms * feat: buttons to add topic, article, quiz to their respective parent doctypes * feat: add charts to form dashboards * fix: code cleanup
This commit is contained in:
@@ -0,0 +1,25 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
from frappe import _
|
||||||
|
|
||||||
|
def get_data():
|
||||||
|
return {
|
||||||
|
'fieldname': 'academic_term',
|
||||||
|
'transactions': [
|
||||||
|
{
|
||||||
|
'label': _('Student'),
|
||||||
|
'items': ['Student Applicant', 'Student Group', 'Student Log']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Fee'),
|
||||||
|
'items': ['Fees', 'Fee Schedule', 'Fee Structure']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Program'),
|
||||||
|
'items': ['Program Enrollment']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Assessment'),
|
||||||
|
'items': ['Assessment Plan', 'Assessment Result']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,10 +1,2 @@
|
|||||||
frappe.ui.form.on("Academic Year", "refresh", function(frm) {
|
frappe.ui.form.on("Academic Year", {
|
||||||
if(!frm.doc.__islocal) {
|
|
||||||
frm.add_custom_button(__("Student Group"), function() {
|
|
||||||
frappe.route_options = {
|
|
||||||
academic_year: frm.doc.name
|
|
||||||
}
|
|
||||||
frappe.set_route("List", "Student Group");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
from frappe import _
|
||||||
|
|
||||||
|
def get_data():
|
||||||
|
return {
|
||||||
|
'fieldname': 'academic_year',
|
||||||
|
'transactions': [
|
||||||
|
{
|
||||||
|
'label': _('Student'),
|
||||||
|
'items': ['Student Admission', 'Student Applicant', 'Student Group', 'Student Log']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Fee'),
|
||||||
|
'items': ['Fees', 'Fee Schedule', 'Fee Structure']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Academic Term and Program'),
|
||||||
|
'items': ['Academic Term', 'Program Enrollment']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Assessment'),
|
||||||
|
'items': ['Assessment Plan', 'Assessment Result']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -3,6 +3,54 @@
|
|||||||
|
|
||||||
frappe.ui.form.on('Article', {
|
frappe.ui.form.on('Article', {
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
|
if (!frm.doc.__islocal) {
|
||||||
|
frm.add_custom_button(__('Add to Topics'), function() {
|
||||||
|
frm.trigger('add_article_to_topics');
|
||||||
|
}, __('Action'));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
add_article_to_topics: function(frm) {
|
||||||
|
get_topics_without_article(frm.doc.name).then(r => {
|
||||||
|
if (r.message.length) {
|
||||||
|
frappe.prompt([
|
||||||
|
{
|
||||||
|
fieldname: 'topics',
|
||||||
|
label: __('Topics'),
|
||||||
|
fieldtype: 'MultiSelectPills',
|
||||||
|
get_data: function() {
|
||||||
|
return r.message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
function(data) {
|
||||||
|
frappe.call({
|
||||||
|
method: 'erpnext.education.doctype.topic.topic.add_content_to_topics',
|
||||||
|
args: {
|
||||||
|
'content_type': 'Article',
|
||||||
|
'content': frm.doc.name,
|
||||||
|
'topics': data.topics,
|
||||||
|
},
|
||||||
|
callback: function(r) {
|
||||||
|
if (!r.exc) {
|
||||||
|
frm.reload_doc();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
freeze: true,
|
||||||
|
freeze_message: __('...Adding Article to Topics')
|
||||||
|
});
|
||||||
|
}, __('Add Article to Topics'), __('Add'));
|
||||||
|
} else {
|
||||||
|
frappe.msgprint(__('This article is already added to the existing topics'));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let get_topics_without_article = function(article) {
|
||||||
|
return frappe.call({
|
||||||
|
type: 'GET',
|
||||||
|
method: 'erpnext.education.doctype.article.article.get_topics_without_article',
|
||||||
|
args: {'article': article}
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -7,9 +7,15 @@ import frappe
|
|||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
||||||
class Article(Document):
|
class Article(Document):
|
||||||
|
|
||||||
|
|
||||||
def get_article(self):
|
def get_article(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def get_topics_without_article(article):
|
||||||
|
data = []
|
||||||
|
for entry in frappe.db.get_all('Topic'):
|
||||||
|
topic = frappe.get_doc('Topic', entry.name)
|
||||||
|
topic_contents = [tc.content for tc in topic.topic_content]
|
||||||
|
if not topic_contents or article not in topic_contents:
|
||||||
|
data.append(topic.name)
|
||||||
|
return data
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
from frappe import _
|
||||||
|
|
||||||
|
def get_data():
|
||||||
|
return {
|
||||||
|
'fieldname': 'assessment_group',
|
||||||
|
'transactions': [
|
||||||
|
{
|
||||||
|
'label': _('Assessment'),
|
||||||
|
'items': ['Assessment Plan', 'Assessment Result']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -2,9 +2,9 @@
|
|||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
|
|
||||||
|
|
||||||
frappe.ui.form.on("Assessment Plan", {
|
frappe.ui.form.on('Assessment Plan', {
|
||||||
onload: function(frm) {
|
onload: function(frm) {
|
||||||
frm.set_query("assessment_group", function(doc, cdt, cdn) {
|
frm.set_query('assessment_group', function(doc, cdt, cdn) {
|
||||||
return{
|
return{
|
||||||
filters: {
|
filters: {
|
||||||
'is_group': 0
|
'is_group': 0
|
||||||
@@ -22,20 +22,20 @@ frappe.ui.form.on("Assessment Plan", {
|
|||||||
|
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
if (frm.doc.docstatus == 1) {
|
if (frm.doc.docstatus == 1) {
|
||||||
frm.add_custom_button(__("Assessment Result"), function() {
|
frm.add_custom_button(__('Assessment Result Tool'), function() {
|
||||||
frappe.route_options = {
|
frappe.route_options = {
|
||||||
assessment_plan: frm.doc.name,
|
assessment_plan: frm.doc.name,
|
||||||
student_group: frm.doc.student_group
|
student_group: frm.doc.student_group
|
||||||
}
|
}
|
||||||
frappe.set_route("Form", "Assessment Result Tool");
|
frappe.set_route('Form', 'Assessment Result Tool');
|
||||||
});
|
}, __('Tools'));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
course: function(frm) {
|
course: function(frm) {
|
||||||
if (frm.doc.course && frm.doc.maximum_assessment_score) {
|
if (frm.doc.course && frm.doc.maximum_assessment_score) {
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: "erpnext.education.api.get_assessment_criteria",
|
method: 'erpnext.education.api.get_assessment_criteria',
|
||||||
args: {
|
args: {
|
||||||
course: frm.doc.course
|
course: frm.doc.course
|
||||||
},
|
},
|
||||||
@@ -43,12 +43,12 @@ frappe.ui.form.on("Assessment Plan", {
|
|||||||
if (r.message) {
|
if (r.message) {
|
||||||
frm.doc.assessment_criteria = [];
|
frm.doc.assessment_criteria = [];
|
||||||
$.each(r.message, function(i, d) {
|
$.each(r.message, function(i, d) {
|
||||||
var row = frappe.model.add_child(frm.doc, "Assessment Plan Criteria", "assessment_criteria");
|
var row = frappe.model.add_child(frm.doc, 'Assessment Plan Criteria', 'assessment_criteria');
|
||||||
row.assessment_criteria = d.assessment_criteria;
|
row.assessment_criteria = d.assessment_criteria;
|
||||||
row.maximum_score = d.weightage / 100 * frm.doc.maximum_assessment_score;
|
row.maximum_score = d.weightage / 100 * frm.doc.maximum_assessment_score;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
refresh_field("assessment_criteria");
|
refresh_field('assessment_criteria');
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -56,6 +56,6 @@ frappe.ui.form.on("Assessment Plan", {
|
|||||||
},
|
},
|
||||||
|
|
||||||
maximum_assessment_score: function(frm) {
|
maximum_assessment_score: function(frm) {
|
||||||
frm.trigger("course");
|
frm.trigger('course');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -6,12 +6,16 @@ from frappe import _
|
|||||||
def get_data():
|
def get_data():
|
||||||
return {
|
return {
|
||||||
'fieldname': 'assessment_plan',
|
'fieldname': 'assessment_plan',
|
||||||
'non_standard_fieldnames': {
|
|
||||||
},
|
|
||||||
'transactions': [
|
'transactions': [
|
||||||
{
|
{
|
||||||
'label': _('Assessment'),
|
'label': _('Assessment'),
|
||||||
'items': ['Assessment Result']
|
'items': ['Assessment Result']
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
'reports': [
|
||||||
|
{
|
||||||
|
'label': _('Report'),
|
||||||
|
'items': ['Assessment Plan Status']
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,13 @@
|
|||||||
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
|
|
||||||
frappe.ui.form.on("Assessment Result", {
|
frappe.ui.form.on('Assessment Result', {
|
||||||
|
refresh: function(frm) {
|
||||||
|
if (!frm.doc.__islocal) {
|
||||||
|
frm.trigger('setup_chart');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
onload: function(frm) {
|
onload: function(frm) {
|
||||||
frm.set_query('assessment_plan', function(){
|
frm.set_query('assessment_plan', function(){
|
||||||
return {
|
return {
|
||||||
@@ -15,7 +21,7 @@ frappe.ui.form.on("Assessment Result", {
|
|||||||
assessment_plan: function(frm) {
|
assessment_plan: function(frm) {
|
||||||
if (frm.doc.assessment_plan) {
|
if (frm.doc.assessment_plan) {
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: "erpnext.education.api.get_assessment_details",
|
method: 'erpnext.education.api.get_assessment_details',
|
||||||
args: {
|
args: {
|
||||||
assessment_plan: frm.doc.assessment_plan
|
assessment_plan: frm.doc.assessment_plan
|
||||||
},
|
},
|
||||||
@@ -23,40 +29,75 @@ frappe.ui.form.on("Assessment Result", {
|
|||||||
if (r.message) {
|
if (r.message) {
|
||||||
frm.doc.details = [];
|
frm.doc.details = [];
|
||||||
$.each(r.message, function(i, d) {
|
$.each(r.message, function(i, d) {
|
||||||
var row = frappe.model.add_child(frm.doc, "Assessment Result Detail", "details");
|
var row = frappe.model.add_child(frm.doc, 'Assessment Result Detail', 'details');
|
||||||
row.assessment_criteria = d.assessment_criteria;
|
row.assessment_criteria = d.assessment_criteria;
|
||||||
row.maximum_score = d.maximum_score;
|
row.maximum_score = d.maximum_score;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
refresh_field("details");
|
refresh_field('details');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
setup_chart: function(frm) {
|
||||||
|
let labels = [];
|
||||||
|
let maximum_scores = [];
|
||||||
|
let scores = [];
|
||||||
|
$.each(frm.doc.details, function(_i, e) {
|
||||||
|
labels.push(e.assessment_criteria);
|
||||||
|
maximum_scores.push(e.maximum_score);
|
||||||
|
scores.push(e.score);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (labels.length && maximum_scores.length && scores.length) {
|
||||||
|
frm.dashboard.chart_area.empty().removeClass('hidden');
|
||||||
|
new frappe.Chart('.form-graph', {
|
||||||
|
title: 'Assessment Results',
|
||||||
|
data: {
|
||||||
|
labels: labels,
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
name: 'Maximum Score',
|
||||||
|
chartType: 'bar',
|
||||||
|
values: maximum_scores,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Score Obtained',
|
||||||
|
chartType: 'bar',
|
||||||
|
values: scores,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
colors: ['#4CA746', '#98D85B'],
|
||||||
|
type: 'bar'
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
frappe.ui.form.on("Assessment Result Detail", {
|
frappe.ui.form.on('Assessment Result Detail', {
|
||||||
score: function(frm, cdt, cdn) {
|
score: function(frm, cdt, cdn) {
|
||||||
var d = locals[cdt][cdn];
|
var d = locals[cdt][cdn];
|
||||||
|
|
||||||
if(!d.maximum_score || !frm.doc.grading_scale) {
|
if(!d.maximum_score || !frm.doc.grading_scale) {
|
||||||
d.score = "";
|
d.score = '';
|
||||||
frappe.throw(__("Please fill in all the details to generate Assessment Result."));
|
frappe.throw(__('Please fill in all the details to generate Assessment Result.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d.score > d.maximum_score) {
|
if (d.score > d.maximum_score) {
|
||||||
frappe.throw(__("Score cannot be greater than Maximum Score"));
|
frappe.throw(__('Score cannot be greater than Maximum Score'));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: "erpnext.education.api.get_grade",
|
method: 'erpnext.education.api.get_grade',
|
||||||
args: {
|
args: {
|
||||||
grading_scale: frm.doc.grading_scale,
|
grading_scale: frm.doc.grading_scale,
|
||||||
percentage: ((d.score/d.maximum_score) * 100)
|
percentage: ((d.score/d.maximum_score) * 100)
|
||||||
},
|
},
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
if (r.message) {
|
if (r.message) {
|
||||||
frappe.model.set_value(cdt, cdn, "grade", r.message);
|
frappe.model.set_value(cdt, cdn, 'grade', r.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
from frappe import _
|
||||||
|
|
||||||
|
def get_data():
|
||||||
|
return {
|
||||||
|
'reports': [
|
||||||
|
{
|
||||||
|
'label': _('Reports'),
|
||||||
|
'items': ['Final Assessment Grades', 'Course wise Assessment Report']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,41 +1,60 @@
|
|||||||
frappe.ui.form.on("Course", "refresh", function(frm) {
|
frappe.ui.form.on('Course', {
|
||||||
if(!cur_frm.doc.__islocal) {
|
refresh: function(frm) {
|
||||||
frm.add_custom_button(__("Program"), function() {
|
if (!cur_frm.doc.__islocal) {
|
||||||
frappe.route_options = {
|
frm.add_custom_button(__('Add to Programs'), function() {
|
||||||
"Program Course.course": frm.doc.name
|
frm.trigger('add_course_to_programs')
|
||||||
}
|
}, __('Action'));
|
||||||
frappe.set_route("List", "Program");
|
}
|
||||||
});
|
|
||||||
|
|
||||||
frm.add_custom_button(__("Student Group"), function() {
|
frm.set_query('default_grading_scale', function(){
|
||||||
frappe.route_options = {
|
return {
|
||||||
course: frm.doc.name
|
filters: {
|
||||||
|
docstatus: 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
frappe.set_route("List", "Student Group");
|
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
|
||||||
frm.add_custom_button(__("Course Schedule"), function() {
|
add_course_to_programs: function(frm) {
|
||||||
frappe.route_options = {
|
get_programs_without_course(frm.doc.name).then(r => {
|
||||||
course: frm.doc.name
|
if (r.message.length) {
|
||||||
|
frappe.prompt([
|
||||||
|
{
|
||||||
|
fieldname: 'programs',
|
||||||
|
label: __('Programs'),
|
||||||
|
fieldtype: 'MultiSelectPills',
|
||||||
|
get_data: function() {
|
||||||
|
return r.message;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldtype: 'Check',
|
||||||
|
label: __('Is Mandatory'),
|
||||||
|
fieldname: 'mandatory',
|
||||||
|
}
|
||||||
|
],
|
||||||
|
function(data) {
|
||||||
|
frappe.call({
|
||||||
|
method: 'erpnext.education.doctype.course.course.add_course_to_programs',
|
||||||
|
args: {
|
||||||
|
'course': frm.doc.name,
|
||||||
|
'programs': data.programs,
|
||||||
|
'mandatory': data.mandatory
|
||||||
|
},
|
||||||
|
callback: function(r) {
|
||||||
|
if (!r.exc) {
|
||||||
|
frm.reload_doc();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
freeze: true,
|
||||||
|
freeze_message: __('...Adding Course to Programs')
|
||||||
|
})
|
||||||
|
}, __('Add Course to Programs'), __('Add'));
|
||||||
|
} else {
|
||||||
|
frappe.msgprint(__('This course is already added to the existing programs'));
|
||||||
}
|
}
|
||||||
frappe.set_route("List", "Course Schedule");
|
|
||||||
});
|
|
||||||
|
|
||||||
frm.add_custom_button(__("Assessment Plan"), function() {
|
|
||||||
frappe.route_options = {
|
|
||||||
course: frm.doc.name
|
|
||||||
}
|
|
||||||
frappe.set_route("List", "Assessment Plan");
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
frm.set_query('default_grading_scale', function(){
|
|
||||||
return {
|
|
||||||
filters: {
|
|
||||||
docstatus: 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
frappe.ui.form.on('Course Topic', {
|
frappe.ui.form.on('Course Topic', {
|
||||||
@@ -50,3 +69,11 @@ frappe.ui.form.on('Course Topic', {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let get_programs_without_course = function(course) {
|
||||||
|
return frappe.call({
|
||||||
|
type: 'GET',
|
||||||
|
method: 'erpnext.education.doctype.course.course.get_programs_without_course',
|
||||||
|
args: {'course': course}
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
|
import json
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from frappe import _
|
from frappe import _
|
||||||
|
|
||||||
@@ -17,12 +18,39 @@ class Course(Document):
|
|||||||
for criteria in self.assessment_criteria:
|
for criteria in self.assessment_criteria:
|
||||||
total_weightage += criteria.weightage or 0
|
total_weightage += criteria.weightage or 0
|
||||||
if total_weightage != 100:
|
if total_weightage != 100:
|
||||||
frappe.throw(_("Total Weightage of all Assessment Criteria must be 100%"))
|
frappe.throw(_('Total Weightage of all Assessment Criteria must be 100%'))
|
||||||
|
|
||||||
def get_topics(self):
|
def get_topics(self):
|
||||||
topic_data= []
|
topic_data= []
|
||||||
for topic in self.topics:
|
for topic in self.topics:
|
||||||
topic_doc = frappe.get_doc("Topic", topic.topic)
|
topic_doc = frappe.get_doc('Topic', topic.topic)
|
||||||
if topic_doc.topic_content:
|
if topic_doc.topic_content:
|
||||||
topic_data.append(topic_doc)
|
topic_data.append(topic_doc)
|
||||||
return topic_data
|
return topic_data
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def add_course_to_programs(course, programs, mandatory=False):
|
||||||
|
programs = json.loads(programs)
|
||||||
|
for entry in programs:
|
||||||
|
program = frappe.get_doc('Program', entry)
|
||||||
|
program.append('courses', {
|
||||||
|
'course': course,
|
||||||
|
'course_name': course,
|
||||||
|
'mandatory': mandatory
|
||||||
|
})
|
||||||
|
program.flags.ignore_mandatory = True
|
||||||
|
program.save()
|
||||||
|
frappe.db.commit()
|
||||||
|
frappe.msgprint(_('Course {0} has been added to all the selected programs successfully.').format(frappe.bold(course)),
|
||||||
|
title=_('Programs updated'), indicator='green')
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def get_programs_without_course(course):
|
||||||
|
data = []
|
||||||
|
for entry in frappe.db.get_all('Program'):
|
||||||
|
program = frappe.get_doc('Program', entry.name)
|
||||||
|
courses = [c.course for c in program.courses]
|
||||||
|
if not courses or course not in courses:
|
||||||
|
data.append(program.name)
|
||||||
|
return data
|
||||||
@@ -6,12 +6,10 @@ from frappe import _
|
|||||||
def get_data():
|
def get_data():
|
||||||
return {
|
return {
|
||||||
'fieldname': 'course',
|
'fieldname': 'course',
|
||||||
'non_standard_fieldnames': {
|
|
||||||
},
|
|
||||||
'transactions': [
|
'transactions': [
|
||||||
{
|
{
|
||||||
'label': _('Course'),
|
'label': _('Program and Course'),
|
||||||
'items': ['Course Enrollment', 'Course Schedule']
|
'items': ['Program', 'Course Enrollment', 'Course Schedule']
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'label': _('Student'),
|
'label': _('Student'),
|
||||||
@@ -19,7 +17,7 @@ def get_data():
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
'label': _('Assessment'),
|
'label': _('Assessment'),
|
||||||
'items': ['Assessment Plan']
|
'items': ['Assessment Plan', 'Assessment Result']
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
from frappe import _
|
||||||
|
|
||||||
|
def get_data():
|
||||||
|
return {
|
||||||
|
'fieldname': 'enrollment',
|
||||||
|
'transactions': [
|
||||||
|
{
|
||||||
|
'label': _('Activity'),
|
||||||
|
'items': ['Course Activity', 'Quiz Activity']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -4,13 +4,13 @@ cur_frm.add_fetch("student_group", "course", "course")
|
|||||||
frappe.ui.form.on("Course Schedule", {
|
frappe.ui.form.on("Course Schedule", {
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
if (!frm.doc.__islocal) {
|
if (!frm.doc.__islocal) {
|
||||||
frm.add_custom_button(__("Attendance"), function() {
|
frm.add_custom_button(__("Mark Attendance"), function() {
|
||||||
frappe.route_options = {
|
frappe.route_options = {
|
||||||
based_on: "Course Schedule",
|
based_on: "Course Schedule",
|
||||||
course_schedule: frm.doc.name
|
course_schedule: frm.doc.name
|
||||||
}
|
}
|
||||||
frappe.set_route("Form", "Student Attendance Tool");
|
frappe.set_route("Form", "Student Attendance Tool");
|
||||||
});
|
}).addClass("btn-primary");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,15 @@
|
|||||||
|
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
from frappe import _
|
||||||
|
|
||||||
|
def get_data():
|
||||||
|
return {
|
||||||
|
'fieldname': 'course_schedule',
|
||||||
|
'transactions': [
|
||||||
|
{
|
||||||
|
'label': _('Attendance'),
|
||||||
|
'items': ['Student Attendance']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -3,13 +3,13 @@
|
|||||||
|
|
||||||
frappe.ui.form.on('Fee Schedule', {
|
frappe.ui.form.on('Fee Schedule', {
|
||||||
setup: function(frm) {
|
setup: function(frm) {
|
||||||
frm.add_fetch("fee_structure", "receivable_account", "receivable_account");
|
frm.add_fetch('fee_structure', 'receivable_account', 'receivable_account');
|
||||||
frm.add_fetch("fee_structure", "income_account", "income_account");
|
frm.add_fetch('fee_structure', 'income_account', 'income_account');
|
||||||
frm.add_fetch("fee_structure", "cost_center", "cost_center");
|
frm.add_fetch('fee_structure', 'cost_center', 'cost_center');
|
||||||
},
|
},
|
||||||
|
|
||||||
onload: function(frm) {
|
onload: function(frm) {
|
||||||
frm.set_query("receivable_account", function(doc) {
|
frm.set_query('receivable_account', function(doc) {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
'account_type': 'Receivable',
|
'account_type': 'Receivable',
|
||||||
@@ -18,7 +18,8 @@ frappe.ui.form.on('Fee Schedule', {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
frm.set_query("income_account", function(doc) {
|
|
||||||
|
frm.set_query('income_account', function(doc) {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
'account_type': 'Income Account',
|
'account_type': 'Income Account',
|
||||||
@@ -27,57 +28,59 @@ frappe.ui.form.on('Fee Schedule', {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
frm.set_query("student_group", "student_groups", function() {
|
|
||||||
|
frm.set_query('student_group', 'student_groups', function() {
|
||||||
return {
|
return {
|
||||||
"program": frm.doc.program,
|
'program': frm.doc.program,
|
||||||
"academic_term": frm.doc.academic_term,
|
'academic_term': frm.doc.academic_term,
|
||||||
"academic_year": frm.doc.academic_year,
|
'academic_year': frm.doc.academic_year,
|
||||||
"disabled": 0
|
'disabled': 0
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
frappe.realtime.on("fee_schedule_progress", function(data) {
|
|
||||||
|
frappe.realtime.on('fee_schedule_progress', function(data) {
|
||||||
if (data.reload && data.reload === 1) {
|
if (data.reload && data.reload === 1) {
|
||||||
frm.reload_doc();
|
frm.reload_doc();
|
||||||
}
|
}
|
||||||
if (data.progress) {
|
if (data.progress) {
|
||||||
let progress_bar = $(cur_frm.dashboard.progress_area).find(".progress-bar");
|
let progress_bar = $(cur_frm.dashboard.progress_area).find('.progress-bar');
|
||||||
if (progress_bar) {
|
if (progress_bar) {
|
||||||
$(progress_bar).removeClass("progress-bar-danger").addClass("progress-bar-success progress-bar-striped");
|
$(progress_bar).removeClass('progress-bar-danger').addClass('progress-bar-success progress-bar-striped');
|
||||||
$(progress_bar).css("width", data.progress+"%");
|
$(progress_bar).css('width', data.progress+'%');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
if(!frm.doc.__islocal && frm.doc.__onload && frm.doc.__onload.dashboard_info &&
|
if (!frm.doc.__islocal && frm.doc.__onload && frm.doc.__onload.dashboard_info &&
|
||||||
frm.doc.fee_creation_status=="Successful") {
|
frm.doc.fee_creation_status === 'Successful') {
|
||||||
var info = frm.doc.__onload.dashboard_info;
|
var info = frm.doc.__onload.dashboard_info;
|
||||||
frm.dashboard.add_indicator(__('Total Collected: {0}', [format_currency(info.total_paid,
|
frm.dashboard.add_indicator(__('Total Collected: {0}', [format_currency(info.total_paid,
|
||||||
info.currency)]), 'blue');
|
info.currency)]), 'blue');
|
||||||
frm.dashboard.add_indicator(__('Total Outstanding: {0}', [format_currency(info.total_unpaid,
|
frm.dashboard.add_indicator(__('Total Outstanding: {0}', [format_currency(info.total_unpaid,
|
||||||
info.currency)]), info.total_unpaid ? 'orange' : 'green');
|
info.currency)]), info.total_unpaid ? 'orange' : 'green');
|
||||||
}
|
}
|
||||||
if (frm.doc.fee_creation_status=="In Process") {
|
if (frm.doc.fee_creation_status === 'In Process') {
|
||||||
frm.dashboard.add_progress("Fee Creation Status", "0");
|
frm.dashboard.add_progress('Fee Creation Status', '0');
|
||||||
}
|
}
|
||||||
if (frm.doc.docstatus==1 && !frm.doc.fee_creation_status || frm.doc.fee_creation_status == "Failed") {
|
if (frm.doc.docstatus === 1 && !frm.doc.fee_creation_status || frm.doc.fee_creation_status === 'Failed') {
|
||||||
frm.add_custom_button(__('Create Fees'), function() {
|
frm.add_custom_button(__('Create Fees'), function() {
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: "create_fees",
|
method: 'create_fees',
|
||||||
doc: frm.doc,
|
doc: frm.doc,
|
||||||
callback: function() {
|
callback: function() {
|
||||||
frm.refresh();
|
frm.refresh();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, "fa fa-play", "btn-success");
|
}).addClass('btn-primary');;
|
||||||
}
|
}
|
||||||
if (frm.doc.fee_creation_status == "Successful") {
|
if (frm.doc.fee_creation_status === 'Successful') {
|
||||||
frm.add_custom_button(__("View Fees Records"), function() {
|
frm.add_custom_button(__('View Fees Records'), function() {
|
||||||
frappe.route_options = {
|
frappe.route_options = {
|
||||||
fee_schedule: frm.doc.name
|
fee_schedule: frm.doc.name
|
||||||
};
|
};
|
||||||
frappe.set_route("List", "Fees");
|
frappe.set_route('List', 'Fees');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,35 +89,35 @@ frappe.ui.form.on('Fee Schedule', {
|
|||||||
fee_structure: function(frm) {
|
fee_structure: function(frm) {
|
||||||
if (frm.doc.fee_structure) {
|
if (frm.doc.fee_structure) {
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: "erpnext.education.doctype.fee_schedule.fee_schedule.get_fee_structure",
|
method: 'erpnext.education.doctype.fee_schedule.fee_schedule.get_fee_structure',
|
||||||
args: {
|
args: {
|
||||||
"target_doc": frm.doc.name,
|
'target_doc': frm.doc.name,
|
||||||
"source_name": frm.doc.fee_structure
|
'source_name': frm.doc.fee_structure
|
||||||
},
|
},
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
var doc = frappe.model.sync(r.message);
|
var doc = frappe.model.sync(r.message);
|
||||||
frappe.set_route("Form", doc[0].doctype, doc[0].name);
|
frappe.set_route('Form', doc[0].doctype, doc[0].name);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
frappe.ui.form.on("Fee Schedule Student Group", {
|
frappe.ui.form.on('Fee Schedule Student Group', {
|
||||||
student_group: function(frm, cdt, cdn) {
|
student_group: function(frm, cdt, cdn) {
|
||||||
var row = locals[cdt][cdn];
|
var row = locals[cdt][cdn];
|
||||||
if (row.student_group && frm.doc.academic_year) {
|
if (row.student_group && frm.doc.academic_year) {
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: "erpnext.education.doctype.fee_schedule.fee_schedule.get_total_students",
|
method: 'erpnext.education.doctype.fee_schedule.fee_schedule.get_total_students',
|
||||||
args: {
|
args: {
|
||||||
"student_group": row.student_group,
|
'student_group': row.student_group,
|
||||||
"academic_year": frm.doc.academic_year,
|
'academic_year': frm.doc.academic_year,
|
||||||
"academic_term": frm.doc.academic_term,
|
'academic_term': frm.doc.academic_term,
|
||||||
"student_category": frm.doc.student_category
|
'student_category': frm.doc.student_category
|
||||||
},
|
},
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
if(!r.exc) {
|
if (!r.exc) {
|
||||||
frappe.model.set_value(cdt, cdn, "total_students", r.message);
|
frappe.model.set_value(cdt, cdn, 'total_students', r.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
def get_data():
|
||||||
|
return {
|
||||||
|
'fieldname': 'fee_schedule',
|
||||||
|
'transactions': [
|
||||||
|
{
|
||||||
|
'items': ['Fees']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -3,21 +3,21 @@
|
|||||||
|
|
||||||
frappe.ui.form.on('Fee Structure', {
|
frappe.ui.form.on('Fee Structure', {
|
||||||
setup: function(frm) {
|
setup: function(frm) {
|
||||||
frm.add_fetch("company", "default_receivable_account", "receivable_account");
|
frm.add_fetch('company', 'default_receivable_account', 'receivable_account');
|
||||||
frm.add_fetch("company", "default_income_account", "income_account");
|
frm.add_fetch('company', 'default_income_account', 'income_account');
|
||||||
frm.add_fetch("company", "cost_center", "cost_center");
|
frm.add_fetch('company', 'cost_center', 'cost_center');
|
||||||
},
|
},
|
||||||
|
|
||||||
onload: function(frm) {
|
onload: function(frm) {
|
||||||
frm.set_query("academic_term", function() {
|
frm.set_query('academic_term', function() {
|
||||||
return {
|
return {
|
||||||
"filters": {
|
'filters': {
|
||||||
"academic_year": frm.doc.academic_year
|
'academic_year': frm.doc.academic_year
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
frm.set_query("receivable_account", function(doc) {
|
frm.set_query('receivable_account', function(doc) {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
'account_type': 'Receivable',
|
'account_type': 'Receivable',
|
||||||
@@ -26,7 +26,7 @@ frappe.ui.form.on('Fee Structure', {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
frm.set_query("income_account", function(doc) {
|
frm.set_query('income_account', function(doc) {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
'account_type': 'Income Account',
|
'account_type': 'Income Account',
|
||||||
@@ -38,27 +38,27 @@ frappe.ui.form.on('Fee Structure', {
|
|||||||
},
|
},
|
||||||
|
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
if(frm.doc.docstatus === 1) {
|
if (frm.doc.docstatus === 1) {
|
||||||
frm.add_custom_button(__('Create Fee Schedule'), function() {
|
frm.add_custom_button(__('Create Fee Schedule'), function() {
|
||||||
frm.events.make_fee_schedule(frm);
|
frm.events.make_fee_schedule(frm);
|
||||||
});
|
}).addClass('btn-primary');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
make_fee_schedule: function(frm) {
|
make_fee_schedule: function(frm) {
|
||||||
frappe.model.open_mapped_doc({
|
frappe.model.open_mapped_doc({
|
||||||
method: "erpnext.education.doctype.fee_structure.fee_structure.make_fee_schedule",
|
method: 'erpnext.education.doctype.fee_structure.fee_structure.make_fee_schedule',
|
||||||
frm: frm
|
frm: frm
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
frappe.ui.form.on("Fee Component", {
|
frappe.ui.form.on('Fee Component', {
|
||||||
amount: function(frm) {
|
amount: function(frm) {
|
||||||
var total_amount = 0;
|
var total_amount = 0;
|
||||||
for(var i=0;i<frm.doc.components.length;i++) {
|
for (var i=0;i<frm.doc.components.length;i++) {
|
||||||
total_amount += frm.doc.components[i].amount;
|
total_amount += frm.doc.components[i].amount;
|
||||||
}
|
}
|
||||||
frm.set_value("total_amount", total_amount);
|
frm.set_value('total_amount', total_amount);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
from frappe import _
|
||||||
|
|
||||||
|
def get_data():
|
||||||
|
return {
|
||||||
|
'fieldname': 'fee_structure',
|
||||||
|
'transactions': [
|
||||||
|
{
|
||||||
|
'label': _('Fee'),
|
||||||
|
'items': ['Fees', 'Fee Schedule']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
from frappe import _
|
||||||
|
|
||||||
|
def get_data():
|
||||||
|
return {
|
||||||
|
'fieldname': 'grading_scale',
|
||||||
|
'non_standard_fieldnames': {
|
||||||
|
'Course': 'default_grading_scale'
|
||||||
|
},
|
||||||
|
'transactions': [
|
||||||
|
{
|
||||||
|
'label': _('Course'),
|
||||||
|
'items': ['Course']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Assessment'),
|
||||||
|
'items': ['Assessment Plan', 'Assessment Result']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -3,8 +3,8 @@ cur_frm.add_fetch("employee", "image", "image");
|
|||||||
|
|
||||||
frappe.ui.form.on("Instructor", {
|
frappe.ui.form.on("Instructor", {
|
||||||
employee: function(frm) {
|
employee: function(frm) {
|
||||||
if(!frm.doc.employee) return;
|
if (!frm.doc.employee) return;
|
||||||
frappe.db.get_value('Employee', {name: frm.doc.employee}, 'company', (d) => {
|
frappe.db.get_value("Employee", {name: frm.doc.employee}, "company", (d) => {
|
||||||
frm.set_query("department", function() {
|
frm.set_query("department", function() {
|
||||||
return {
|
return {
|
||||||
"filters": {
|
"filters": {
|
||||||
@@ -22,30 +22,16 @@ frappe.ui.form.on("Instructor", {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
if(!frm.doc.__islocal) {
|
if (!frm.doc.__islocal) {
|
||||||
frm.add_custom_button(__("Student Group"), function() {
|
|
||||||
frappe.route_options = {
|
|
||||||
instructor: frm.doc.name
|
|
||||||
}
|
|
||||||
frappe.set_route("List", "Student Group");
|
|
||||||
});
|
|
||||||
frm.add_custom_button(__("Course Schedule"), function() {
|
|
||||||
frappe.route_options = {
|
|
||||||
instructor: frm.doc.name
|
|
||||||
}
|
|
||||||
frappe.set_route("List", "Course Schedule");
|
|
||||||
});
|
|
||||||
frm.add_custom_button(__("As Examiner"), function() {
|
frm.add_custom_button(__("As Examiner"), function() {
|
||||||
frappe.route_options = {
|
frappe.new_doc("Assessment Plan", {
|
||||||
examiner: frm.doc.name
|
examiner: frm.doc.name
|
||||||
}
|
});
|
||||||
frappe.set_route("List", "Assessment Plan");
|
|
||||||
}, __("Assessment Plan"));
|
}, __("Assessment Plan"));
|
||||||
frm.add_custom_button(__("As Supervisor"), function() {
|
frm.add_custom_button(__("As Supervisor"), function() {
|
||||||
frappe.route_options = {
|
frappe.new_doc("Assessment Plan", {
|
||||||
supervisor: frm.doc.name
|
supervisor: frm.doc.name
|
||||||
}
|
});
|
||||||
frappe.set_route("List", "Assessment Plan");
|
|
||||||
}, __("Assessment Plan"));
|
}, __("Assessment Plan"));
|
||||||
}
|
}
|
||||||
frm.set_query("employee", function(doc) {
|
frm.set_query("employee", function(doc) {
|
||||||
|
|||||||
@@ -30,4 +30,14 @@ class Instructor(Document):
|
|||||||
if self.employee and frappe.db.get_value("Instructor", {'employee': self.employee, 'name': ['!=', self.name]}, 'name'):
|
if self.employee and frappe.db.get_value("Instructor", {'employee': self.employee, 'name': ['!=', self.name]}, 'name'):
|
||||||
frappe.throw(_("Employee ID is linked with another instructor"))
|
frappe.throw(_("Employee ID is linked with another instructor"))
|
||||||
|
|
||||||
|
def get_timeline_data(doctype, name):
|
||||||
|
"""Return timeline for course schedule"""
|
||||||
|
return dict(frappe.db.sql(
|
||||||
|
"""
|
||||||
|
SELECT unix_timestamp(`schedule_date`), count(*)
|
||||||
|
FROM `tabCourse Schedule`
|
||||||
|
WHERE
|
||||||
|
instructor=%s and
|
||||||
|
`schedule_date` > date_sub(curdate(), interval 1 year)
|
||||||
|
GROUP BY schedule_date
|
||||||
|
""", name))
|
||||||
|
|||||||
24
erpnext/education/doctype/instructor/instructor_dashboard.py
Normal file
24
erpnext/education/doctype/instructor/instructor_dashboard.py
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
from frappe import _
|
||||||
|
|
||||||
|
def get_data():
|
||||||
|
return {
|
||||||
|
'heatmap': True,
|
||||||
|
'heatmap_message': _('This is based on the course schedules of this Instructor'),
|
||||||
|
'fieldname': 'instructor',
|
||||||
|
'non_standard_fieldnames': {
|
||||||
|
'Assessment Plan': 'supervisor'
|
||||||
|
},
|
||||||
|
'transactions': [
|
||||||
|
{
|
||||||
|
'label': _('Course and Assessment'),
|
||||||
|
'items': ['Course Schedule', 'Assessment Plan']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Students'),
|
||||||
|
'items': ['Student Group']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -10,11 +10,15 @@ def get_data():
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
'label': _('Student Activity'),
|
'label': _('Student Activity'),
|
||||||
'items': ['Student Group' ]
|
'items': ['Student Group', 'Student Log']
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'label': _('Fee'),
|
'label': _('Fee'),
|
||||||
'items': ['Fees','Fee Structure']
|
'items': ['Fees','Fee Structure', 'Fee Schedule']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Assessment'),
|
||||||
|
'items': ['Assessment Plan', 'Assessment Result']
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
from frappe import _
|
||||||
|
|
||||||
|
def get_data():
|
||||||
|
return {
|
||||||
|
'fieldname': 'program_enrollment',
|
||||||
|
'transactions': [
|
||||||
|
{
|
||||||
|
'label': _('Course and Fee'),
|
||||||
|
'items': ['Course Enrollment', 'Fees']
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'reports': [
|
||||||
|
{
|
||||||
|
'label': _('Report'),
|
||||||
|
'items': ['Student and Guardian Contact Details']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -3,11 +3,17 @@
|
|||||||
|
|
||||||
frappe.ui.form.on('Quiz', {
|
frappe.ui.form.on('Quiz', {
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
|
if (!frm.doc.__islocal) {
|
||||||
|
frm.add_custom_button(__('Add to Topics'), function() {
|
||||||
|
frm.trigger('add_quiz_to_topics');
|
||||||
|
}, __('Action'));
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
validate: function(frm){
|
validate: function(frm){
|
||||||
frm.events.check_duplicate_question(frm.doc.question);
|
frm.events.check_duplicate_question(frm.doc.question);
|
||||||
},
|
},
|
||||||
|
|
||||||
check_duplicate_question: function(questions_data){
|
check_duplicate_question: function(questions_data){
|
||||||
var questions = [];
|
var questions = [];
|
||||||
questions_data.forEach(function(q){
|
questions_data.forEach(function(q){
|
||||||
@@ -15,7 +21,51 @@ frappe.ui.form.on('Quiz', {
|
|||||||
});
|
});
|
||||||
var questions_set = new Set(questions);
|
var questions_set = new Set(questions);
|
||||||
if (questions.length != questions_set.size) {
|
if (questions.length != questions_set.size) {
|
||||||
frappe.throw(__("The question cannot be duplicate"));
|
frappe.throw(__('The question cannot be duplicate'));
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
add_quiz_to_topics: function(frm) {
|
||||||
|
get_topics_without_quiz(frm.doc.name).then(r => {
|
||||||
|
if (r.message.length) {
|
||||||
|
frappe.prompt([
|
||||||
|
{
|
||||||
|
fieldname: 'topics',
|
||||||
|
label: __('Topics'),
|
||||||
|
fieldtype: 'MultiSelectPills',
|
||||||
|
get_data: function() {
|
||||||
|
return r.message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
function(data) {
|
||||||
|
frappe.call({
|
||||||
|
method: 'erpnext.education.doctype.topic.topic.add_content_to_topics',
|
||||||
|
args: {
|
||||||
|
'content_type': 'Quiz',
|
||||||
|
'content': frm.doc.name,
|
||||||
|
'topics': data.topics,
|
||||||
|
},
|
||||||
|
callback: function(r) {
|
||||||
|
if (!r.exc) {
|
||||||
|
frm.reload_doc();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
freeze: true,
|
||||||
|
freeze_message: __('...Adding Quiz to Topics')
|
||||||
|
});
|
||||||
|
}, __('Add Quiz to Topics'), __('Add'));
|
||||||
|
} else {
|
||||||
|
frappe.msgprint(__('This quiz is already added to the existing topics'));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let get_topics_without_quiz = function(quiz) {
|
||||||
|
return frappe.call({
|
||||||
|
type: 'GET',
|
||||||
|
method: 'erpnext.education.doctype.quiz.quiz.get_topics_without_quiz',
|
||||||
|
args: {'quiz': quiz}
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
|
import json
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
||||||
@@ -59,3 +60,12 @@ def compare_list_elementwise(*args):
|
|||||||
except TypeError:
|
except TypeError:
|
||||||
frappe.throw(_("Compare List function takes on list arguments"))
|
frappe.throw(_("Compare List function takes on list arguments"))
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def get_topics_without_quiz(quiz):
|
||||||
|
data = []
|
||||||
|
for entry in frappe.db.get_all('Topic'):
|
||||||
|
topic = frappe.get_doc('Topic', entry.name)
|
||||||
|
topic_contents = [tc.content for tc in topic.topic_content]
|
||||||
|
if not topic_contents or quiz not in topic_contents:
|
||||||
|
data.append(topic.name)
|
||||||
|
return data
|
||||||
@@ -1,10 +1,2 @@
|
|||||||
frappe.ui.form.on("Room", "refresh", function(frm) {
|
frappe.ui.form.on("Room", {
|
||||||
if(!cur_frm.doc.__islocal) {
|
|
||||||
frm.add_custom_button(__("Course Schedule"), function() {
|
|
||||||
frappe.route_options = {
|
|
||||||
room: frm.doc.name
|
|
||||||
}
|
|
||||||
frappe.set_route("List", "Course Schedule");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
19
erpnext/education/doctype/room/room_dashboard.py
Normal file
19
erpnext/education/doctype/room/room_dashboard.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
from frappe import _
|
||||||
|
|
||||||
|
def get_data():
|
||||||
|
return {
|
||||||
|
'fieldname': 'room',
|
||||||
|
'transactions': [
|
||||||
|
{
|
||||||
|
'label': _('Course'),
|
||||||
|
'items': ['Course Schedule']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Assessment'),
|
||||||
|
'items': ['Assessment Plan']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
from frappe import _
|
||||||
|
|
||||||
|
def get_data():
|
||||||
|
return {
|
||||||
|
'reports': [
|
||||||
|
{
|
||||||
|
'label': _('Reports'),
|
||||||
|
'items': ['Student Monthly Attendance Sheet', 'Student Batch-Wise Attendance']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
from frappe import _
|
||||||
|
|
||||||
|
def get_data():
|
||||||
|
return {
|
||||||
|
'fieldname': 'student_category',
|
||||||
|
'transactions': [
|
||||||
|
{
|
||||||
|
'label': _('Fee'),
|
||||||
|
'items': ['Fee Structure', 'Fee Schedule', 'Fees']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,18 +1,18 @@
|
|||||||
cur_frm.add_fetch("student", "title", "student_name");
|
cur_frm.add_fetch('student', 'title', 'student_name');
|
||||||
|
|
||||||
frappe.ui.form.on("Student Group", {
|
frappe.ui.form.on('Student Group', {
|
||||||
onload: function(frm) {
|
onload: function(frm) {
|
||||||
frm.set_query("academic_term", function() {
|
frm.set_query('academic_term', function() {
|
||||||
return {
|
return {
|
||||||
"filters": {
|
filters: {
|
||||||
"academic_year": (frm.doc.academic_year)
|
'academic_year': (frm.doc.academic_year)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
if (!frm.__islocal) {
|
if (!frm.__islocal) {
|
||||||
frm.set_query("student", "students", function() {
|
frm.set_query('student', 'students', function() {
|
||||||
return{
|
return{
|
||||||
query: "erpnext.education.doctype.student_group.student_group.fetch_students",
|
query: 'erpnext.education.doctype.student_group.student_group.fetch_students',
|
||||||
filters: {
|
filters: {
|
||||||
'academic_year': frm.doc.academic_year,
|
'academic_year': frm.doc.academic_year,
|
||||||
'group_based_on': frm.doc.group_based_on,
|
'group_based_on': frm.doc.group_based_on,
|
||||||
@@ -30,87 +30,86 @@ frappe.ui.form.on("Student Group", {
|
|||||||
|
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
if (!frm.doc.__islocal) {
|
if (!frm.doc.__islocal) {
|
||||||
frm.add_custom_button(__("Attendance"), function() {
|
|
||||||
frappe.route_options = {
|
frm.add_custom_button(__('Add Guardians to Email Group'), function() {
|
||||||
based_on: "Student Group",
|
|
||||||
student_group: frm.doc.name
|
|
||||||
}
|
|
||||||
frappe.set_route("List", "Student Attendance Tool");
|
|
||||||
});
|
|
||||||
frm.add_custom_button(__("Course Schedule"), function() {
|
|
||||||
frappe.route_options = {
|
|
||||||
student_group: frm.doc.name
|
|
||||||
}
|
|
||||||
frappe.set_route("List", "Course Schedule");
|
|
||||||
});
|
|
||||||
frm.add_custom_button(__("Assessment Plan"), function() {
|
|
||||||
frappe.route_options = {
|
|
||||||
student_group: frm.doc.name
|
|
||||||
}
|
|
||||||
frappe.set_route("List", "Assessment Plan");
|
|
||||||
});
|
|
||||||
frm.add_custom_button(__("Update Email Group"), function() {
|
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: "erpnext.education.api.update_email_group",
|
method: 'erpnext.education.api.update_email_group',
|
||||||
args: {
|
args: {
|
||||||
"doctype": "Student Group",
|
'doctype': 'Student Group',
|
||||||
"name": frm.doc.name
|
'name': frm.doc.name
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
}, __('Actions'));
|
||||||
frm.add_custom_button(__("Newsletter"), function() {
|
|
||||||
|
frm.add_custom_button(__('Student Attendance Tool'), function() {
|
||||||
frappe.route_options = {
|
frappe.route_options = {
|
||||||
"Newsletter Email Group.email_group": frm.doc.name
|
based_on: 'Student Group',
|
||||||
|
student_group: frm.doc.name
|
||||||
}
|
}
|
||||||
frappe.set_route("List", "Newsletter");
|
frappe.set_route('Form', 'Student Attendance Tool', 'Student Attendance Tool');
|
||||||
});
|
}, __('Tools'));
|
||||||
|
|
||||||
|
frm.add_custom_button(__('Course Scheduling Tool'), function() {
|
||||||
|
frappe.route_options = {
|
||||||
|
student_group: frm.doc.name
|
||||||
|
}
|
||||||
|
frappe.set_route('Form', 'Course Scheduling Tool', 'Course Scheduling Tool');
|
||||||
|
}, __('Tools'));
|
||||||
|
|
||||||
|
frm.add_custom_button(__('Newsletter'), function() {
|
||||||
|
frappe.route_options = {
|
||||||
|
'Newsletter Email Group.email_group': frm.doc.name
|
||||||
|
}
|
||||||
|
frappe.set_route('List', 'Newsletter');
|
||||||
|
}, __('View'));
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
group_based_on: function(frm) {
|
group_based_on: function(frm) {
|
||||||
if (frm.doc.group_based_on == "Batch") {
|
if (frm.doc.group_based_on == 'Batch') {
|
||||||
frm.doc.course = null;
|
frm.doc.course = null;
|
||||||
frm.set_df_property('program', 'reqd', 1);
|
frm.set_df_property('program', 'reqd', 1);
|
||||||
frm.set_df_property('course', 'reqd', 0);
|
frm.set_df_property('course', 'reqd', 0);
|
||||||
}
|
}
|
||||||
else if (frm.doc.group_based_on == "Course") {
|
else if (frm.doc.group_based_on == 'Course') {
|
||||||
frm.set_df_property('program', 'reqd', 0);
|
frm.set_df_property('program', 'reqd', 0);
|
||||||
frm.set_df_property('course', 'reqd', 1);
|
frm.set_df_property('course', 'reqd', 1);
|
||||||
}
|
}
|
||||||
else if (frm.doc.group_based_on == "Activity") {
|
else if (frm.doc.group_based_on == 'Activity') {
|
||||||
frm.set_df_property('program', 'reqd', 0);
|
frm.set_df_property('program', 'reqd', 0);
|
||||||
frm.set_df_property('course', 'reqd', 0);
|
frm.set_df_property('course', 'reqd', 0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
get_students: function(frm) {
|
get_students: function(frm) {
|
||||||
if (frm.doc.group_based_on == "Batch" || frm.doc.group_based_on == "Course") {
|
if (frm.doc.group_based_on == 'Batch' || frm.doc.group_based_on == 'Course') {
|
||||||
var student_list = [];
|
var student_list = [];
|
||||||
var max_roll_no = 0;
|
var max_roll_no = 0;
|
||||||
$.each(frm.doc.students, function(i,d) {
|
$.each(frm.doc.students, function(_i,d) {
|
||||||
student_list.push(d.student);
|
student_list.push(d.student);
|
||||||
if (d.group_roll_number>max_roll_no) {
|
if (d.group_roll_number>max_roll_no) {
|
||||||
max_roll_no = d.group_roll_number;
|
max_roll_no = d.group_roll_number;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if(frm.doc.academic_year) {
|
if (frm.doc.academic_year) {
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: "erpnext.education.doctype.student_group.student_group.get_students",
|
method: 'erpnext.education.doctype.student_group.student_group.get_students',
|
||||||
args: {
|
args: {
|
||||||
"academic_year": frm.doc.academic_year,
|
'academic_year': frm.doc.academic_year,
|
||||||
"academic_term": frm.doc.academic_term,
|
'academic_term': frm.doc.academic_term,
|
||||||
"group_based_on": frm.doc.group_based_on,
|
'group_based_on': frm.doc.group_based_on,
|
||||||
"program": frm.doc.program,
|
'program': frm.doc.program,
|
||||||
"batch" : frm.doc.batch,
|
'batch' : frm.doc.batch,
|
||||||
"student_category" : frm.doc.student_category,
|
'student_category' : frm.doc.student_category,
|
||||||
"course": frm.doc.course
|
'course': frm.doc.course
|
||||||
},
|
},
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
if(r.message) {
|
if (r.message) {
|
||||||
$.each(r.message, function(i, d) {
|
$.each(r.message, function(i, d) {
|
||||||
if(!in_list(student_list, d.student)) {
|
if(!in_list(student_list, d.student)) {
|
||||||
var s = frm.add_child("students");
|
var s = frm.add_child('students');
|
||||||
s.student = d.student;
|
s.student = d.student;
|
||||||
s.student_name = d.student_name;
|
s.student_name = d.student_name;
|
||||||
if (d.active === 0) {
|
if (d.active === 0) {
|
||||||
@@ -119,16 +118,16 @@ frappe.ui.form.on("Student Group", {
|
|||||||
s.group_roll_number = ++max_roll_no;
|
s.group_roll_number = ++max_roll_no;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
refresh_field("students");
|
refresh_field('students');
|
||||||
frm.save();
|
frm.save();
|
||||||
} else {
|
} else {
|
||||||
frappe.msgprint(__("Student Group is already updated."))
|
frappe.msgprint(__('Student Group is already updated.'))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
frappe.msgprint(__("Select students manually for the Activity based Group"));
|
frappe.msgprint(__('Select students manually for the Activity based Group'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
from frappe import _
|
||||||
|
|
||||||
|
def get_data():
|
||||||
|
return {
|
||||||
|
'fieldname': 'student_group',
|
||||||
|
'transactions': [
|
||||||
|
{
|
||||||
|
'label': _('Assessment'),
|
||||||
|
'items': ['Assessment Plan', 'Assessment Result']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Course'),
|
||||||
|
'items': ['Course Schedule']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -3,6 +3,53 @@
|
|||||||
|
|
||||||
frappe.ui.form.on('Topic', {
|
frappe.ui.form.on('Topic', {
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
|
if (!cur_frm.doc.__islocal) {
|
||||||
|
frm.add_custom_button(__('Add to Courses'), function() {
|
||||||
|
frm.trigger('add_topic_to_courses');
|
||||||
|
}, __('Action'));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
add_topic_to_courses: function(frm) {
|
||||||
|
get_courses_without_topic(frm.doc.name).then(r => {
|
||||||
|
if (r.message.length) {
|
||||||
|
frappe.prompt([
|
||||||
|
{
|
||||||
|
fieldname: 'courses',
|
||||||
|
label: __('Courses'),
|
||||||
|
fieldtype: 'MultiSelectPills',
|
||||||
|
get_data: function() {
|
||||||
|
return r.message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
function(data) {
|
||||||
|
frappe.call({
|
||||||
|
method: 'erpnext.education.doctype.topic.topic.add_topic_to_courses',
|
||||||
|
args: {
|
||||||
|
'topic': frm.doc.name,
|
||||||
|
'courses': data.courses
|
||||||
|
},
|
||||||
|
callback: function(r) {
|
||||||
|
if (!r.exc) {
|
||||||
|
frm.reload_doc();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
freeze: true,
|
||||||
|
freeze_message: __('...Adding Topic to Courses')
|
||||||
|
});
|
||||||
|
}, __('Add Topic to Courses'), __('Add'));
|
||||||
|
} else {
|
||||||
|
frappe.msgprint(__('This topic is already added to the existing courses'));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let get_courses_without_topic = function(topic) {
|
||||||
|
return frappe.call({
|
||||||
|
type: 'GET',
|
||||||
|
method: 'erpnext.education.doctype.topic.topic.get_courses_without_topic',
|
||||||
|
args: {'topic': topic}
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
|
import json
|
||||||
|
from frappe import _
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
||||||
class Topic(Document):
|
class Topic(Document):
|
||||||
@@ -14,4 +16,44 @@ class Topic(Document):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
frappe.log_error(frappe.get_traceback())
|
frappe.log_error(frappe.get_traceback())
|
||||||
return None
|
return None
|
||||||
return content_data
|
return content_data
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def get_courses_without_topic(topic):
|
||||||
|
data = []
|
||||||
|
for entry in frappe.db.get_all('Course'):
|
||||||
|
course = frappe.get_doc('Course', entry.name)
|
||||||
|
topics = [t.topic for t in course.topics]
|
||||||
|
if not topics or topic not in topics:
|
||||||
|
data.append(course.name)
|
||||||
|
return data
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def add_topic_to_courses(topic, courses, mandatory=False):
|
||||||
|
courses = json.loads(courses)
|
||||||
|
for entry in courses:
|
||||||
|
course = frappe.get_doc('Course', entry)
|
||||||
|
course.append('topics', {
|
||||||
|
'topic': topic,
|
||||||
|
'topic_name': topic
|
||||||
|
})
|
||||||
|
course.flags.ignore_mandatory = True
|
||||||
|
course.save()
|
||||||
|
frappe.db.commit()
|
||||||
|
frappe.msgprint(_('Topic {0} has been added to all the selected courses successfully.').format(frappe.bold(topic)),
|
||||||
|
title=_('Courses updated'), indicator='green')
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def add_content_to_topics(content_type, content, topics):
|
||||||
|
topics = json.loads(topics)
|
||||||
|
for entry in topics:
|
||||||
|
topic = frappe.get_doc('Topic', entry)
|
||||||
|
topic.append('topic_content', {
|
||||||
|
'content_type': content_type,
|
||||||
|
'content': content,
|
||||||
|
})
|
||||||
|
topic.flags.ignore_mandatory = True
|
||||||
|
topic.save()
|
||||||
|
frappe.db.commit()
|
||||||
|
frappe.msgprint(_('{0} {1} has been added to all the selected topics successfully.').format(content_type, frappe.bold(content)),
|
||||||
|
title=_('Topics updated'), indicator='green')
|
||||||
Reference in New Issue
Block a user