+
{{college}}
+
+
+
+
+
+
+
+
+ {% if completed == 0 %}
+
+ List is empty
+
+
+ {% else %}
+
+
+ User
+ Academic Year
+ Completion Date & Time
+ Amount
+ Transaction ID
+ Reference No
+ Status
+
+
+ {% for detail in paymentdetails %}
+ {% if detail.status == 'S' %}
+
+
+ {{ user }}
+ {{ detail.paymentdetail_id__academic_year }}
+ {{ detail.created }}
+ {{detail.amount}}
+ {{detail.transId}}
+ {{detail.refNo}}
+ {{detail.msg}}
+
+
+ {% endif %}
+ {% endfor %}
+
+ {% endif %}
+
+
+
+
+
+ {% if failed == 0 %}
+
+ List is empty
+
+
+ {% else %}
+
+
+ User
+ Academic Year
+ Completion Date & Time
+ Amount
+ Transaction ID
+ Reference No
+ Status
+
+
+
+ {% for detail in paymentdetails %}
+ {% if detail.status == 'F' %}
+
+
+ {{ user }}
+ {{ detail.paymentdetail_id__academic_year }}
+ {{ detail.created }}
+ {{detail.amount}}
+ {{detail.transId}}
+ {% if detail.refNo != 'null'%}
+ {{detail.refNo}}
+ {%else%}
+ Not Generated
+ {% endif %}
+
+ {% if detail.msg != 'null'%}
+ {{detail.msg}}
+ {%else%}
+ Failed
+ {% endif %}
+
+
+
+ {% endif %}
+ {% endfor %}
+
+ {% endif %}
+
+
+
+
+ {% if ongoing == 0 %}
+
+ List is empty
+
+
+ {% else %}
+
+
+ User
+ Academic Year
+ Completion Date & Time
+ Amount
+ Transaction ID
+ Reference No
+ Status
+
+
+
+ {% for detail in ongoing_details %}
+ {% if detail.status == 0 %}
+
+
+ {{ user }}
+ {{ detail.academic_year }}
+ {{ detail.created }}
+ {{detail.amount}}
+ Transaction Ongoing
+ Not Generated
+ {{detail.description}}
+
+
+ {% endif %}
+ {% endfor %}
+
+ {% endif %}
+
+
+
+
+
+
+
+
+{% endblock %}
+{% block jsblock %}
+
+{% endblock %}
diff --git a/events/events/templates/payment_home.html b/events/events/templates/payment_home.html
new file mode 100644
index 000000000..546003114
--- /dev/null
+++ b/events/events/templates/payment_home.html
@@ -0,0 +1,130 @@
+{% extends 'spoken/templates/base.html' %}
+{% load widget_tweaks %}
+{% load static %}
+{% load eventsdata %}
+{% load cmsdata %}
+{% block title %} Pay here {% endblock %}
+{% block heading %}
Pay here{% endblock %}
+{% block search %}{% endblock %}
+{% block content %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This is an academic year subscription. Hence the subscription will end on 30 Jun 2019
+ Money once paid, cannot be refunded in part or whole, for any reason
+ Payment to be made by 30 Sept 2018
+ Any number of students from your college can avail this training
+ You can contact Training Managers 24/7 for any queries. If the transaction has failed and your account is debited, please contact your respective state manager
+ e-Certificates will have only the logo of Spoken Tutorial, IIT Bombay
+
+
+
+
+
+
+
+
+
+
+
+{% endblock %}
+{% block jsblock %}
+
+{% endblock %}
\ No newline at end of file
diff --git a/events/events/templates/payment_status.html b/events/events/templates/payment_status.html
new file mode 100644
index 000000000..0f1f8913d
--- /dev/null
+++ b/events/events/templates/payment_status.html
@@ -0,0 +1,66 @@
+{% extends 'spoken/templates/base.html' %}
+{% load widget_tweaks %}
+{% load static %}
+{% load eventsdata %}
+{% load cmsdata %}
+{% load creationdata %}
+{% block search %}{% endblock %}
+{% block title %}Payment{% endblock %}
+{% block compressinlinecssblock %}
+
+{% endblock %}
+{% block content %}
+
+
+
+
+
You are getting redirected to external payment gateway!!
+
Please do not refresh or close the window
+
+
+ The process may take upto 5 minutes
+
+
+
+
+
+{% endblock %}
+{% block jsblock %}
+
+{% endblock %}
diff --git a/events/events/templates/payment_success.html b/events/events/templates/payment_success.html
new file mode 100644
index 000000000..1fa245aa6
--- /dev/null
+++ b/events/events/templates/payment_success.html
@@ -0,0 +1,54 @@
+{% extends 'spoken/templates/base.html' %}
+{% load widget_tweaks %}
+{% load static %}
+{% load eventsdata %}
+{% load cmsdata %}
+{% load creationdata %}
+{% block search %}{% endblock %}
+{% block content %}
+
+
+
+ {% if status == 'S'%}
+
Thank you {{user.first_name}}
+
Your Transaction is successful.
+ {% elif status == 'F' %}
+
Transaction failed. Kindly try again.
+ {% endif %}
+
+
+
+
+ Transaction Id :
+ {{transId}}
+
+ {% if status == 'S'%}
+
+ Reference No. :
+ {{refNo}}
+
+
+ Status message :
+ {{msg}}
+
+ {% elif status == 'F' %}
+
+ Status message :
+ Transaction failed
+
+ {% endif %}
+
+ Amount :
+ {{amount}}
+
+
+
Print Receipt for Transaction Id : {{transId}}
+
+
+
+{% endblock %}
+{% block jsblock %}
+
+{% endblock %}
diff --git a/events/events/templates/select_participants.html b/events/events/templates/select_participants.html
new file mode 100644
index 000000000..1bb0404ee
--- /dev/null
+++ b/events/events/templates/select_participants.html
@@ -0,0 +1,275 @@
+
+{% extends 'spoken/templates/base.html' %}
+{% load static %}
+{% block title %}Semester Training Planner Summary{% endblock %}
+{% load announcements %}
+{% block heading %}
+
Select participant List
+
Instructions for Selecting Participant List
+
Back To Training Planner Summary
+{% endblock %}
+{% block announcement %}
+
+ {% get_notifications as notifications %}
+ {% if notifications %}
+ {% for notification in notifications %}
+
+
+
+ {{ notification.body|safe }}
+
+
+
+
+ {% endfor %}
+ {% endif %}
+
+{% endblock %}
+{% block search %}{% endblock %}
+
+{% block cssblock %}
+
+{% endblock %}
+
+{% block content %}
+
+
+
+
+
×
+
+ For detailed instruction on Step 3 click here : Select Participant List from MB: http://process.spoken-tutorial.org/images/4/49/Upload_Select_Participant_list.pdf
+ Select the list of students taking the course/s you have chosen in this semester from the Master Batch .
+ Make sure you mark the attendance within 60 Days from Semester Start Date.
+ Make sure you do this before you plan to start the training for the particular course.
+ Repeat the same when you move to the next course of the semester.
+ Organiser will have option to re-open the training and mark Participant List multiple times for the current semester .
+
+
+
+
+
+
+
+
+
+ {{current_planner.academic.institution_name}}, {{current_planner.academic.district.name}}
+
+
+
+
+
+ {{ current_planner.get_semester }} (Current Semester)
+ completed : {{ current_planner.completed_training.count }}
+ Ongoing : {{ current_planner.ongoing_training.count }}
+
+
+ {% if current_planner.training_requests %}
+
+
+ #
+ Semester State Date
+ Software Course
+ Department
+ Batch
+ Participant List Status
+ Action
+
+ {% for training in current_planner.training_requests %}
+
+ {{ forloop.counter }}
+ {{ training.sem_start_date }}
+ {{ training.course.course_name }}
+ {{ training.department }}
+ {{training.batch.batch_name}}
+ {{ training.attendance_summery }}
+
+
+ {% if training.status == 0 %}
+ | Participant List |
+ {% if training.can_edit %}
+ Edit |
+ {% endif %}
+ {% endif %}
+
+ {% if training.status == 1 %}
+ {% if training.is_learners_allowed and training.get_partipants_from_attendance and training.cert_status == 1 %}
+ | Download Participation Certificate |
+
+ {% elif training.is_learners_allowed and training.get_partipants_from_attendance and training.cert_status == 0%}
+ | Generate Participation Certificate |
+
+ {% elif training.is_learners_allowed and training.get_partipants_from_attendance and training.cert_status == 2%}
+ | Request sent for Participation Certificate | Participant List {% endif %}
+
+ | Re-Open |
+
+ {% if not training.is_learners_allowed and not training.have_test%}
+ | Training Completed. No Certificates
+
+ | Participant List
+
+ | Re-Open |
+ {% endif %}
+ {% endif %}
+
+
+ {% endfor %}
+
+ {% else %}
+
+ Training planner is empty
+
+ {% endif %}
+
+
+
+ {% if next_planner %}
+
+
+ {{ next_planner.get_semester }} (Next Semester)
+ Planned : {{ next_planner.ongoing_training.count }}
+
+
+ {% if next_planner.training_requests %}
+
+
+ #
+ Semester State Date
+ Software Course
+ Department
+ Batch
+ Participant List Status
+ Action
+
+ {% for training in next_planner.training_requests %}
+
+ {{ forloop.counter }}
+ {{ training.sem_start_date }}
+ {{ training.course.course_name }}
+ {{ training.department }}
+ {{training.batch.batch_name}}
+ {{ training.attendance_summery }}
+
+ {% if training.can_mark_attendance %}
+ | Select Participant List
+ {% endif %}
+ {% if training.can_edit %}
+ | Edit |
+ {% endif %}
+
+
+ {% endfor %}
+
+ {% else %}
+
+ Training planner is empty
+
+ {% endif %}
+
+
+ {% endif %}
+
+ {% for record in object_list %}
+ {% if record.training_with_no_attend %}
+ {% if not record.id == current_planner.id and not record.id == next_planner.id %}
+
+
+ {{ record.get_semester }} (Past Semester)
+ Total : {{ record.completed_training.count }}
+
+
+
+
+ #
+ Semester State Date
+ Software Course
+ Department
+ Batch Year
+ Participant List Status
+ Action
+
+ {% for training in record.training_with_no_attend %}
+
+ {{ forloop.counter }}
+ {{ training.sem_start_date }}
+ {{ training.course.course_name }}
+ {{ training.department }}
+ {{training.batch.year}}
+ {{ training.attendance_summery }}
+
+ {% if training %}
+ | Participant List |
+ {% endif %}
+
+
+ {% endfor %}
+
+
+
+
+ {% endif %}
+ {% endif %}
+ {% endfor %}
+
+{% endblock %}
+
+{% block compressjsblock %}
+
+{% endblock %}
+{% block jsblock %}
+
+
+{% endblock %}
diff --git a/events/events/templates/single-training-attendance.html b/events/events/templates/single-training-attendance.html
new file mode 100644
index 000000000..70fbf5456
--- /dev/null
+++ b/events/events/templates/single-training-attendance.html
@@ -0,0 +1,125 @@
+{% extends 'base.html' %}
+{% load widget_tweaks %}
+{% load static %}
+{% load eventsdata %}
+{% block title %}Training - Request- Attendance{% endblock %}
+{% block heading %}Dashboard {% endblock %}
+{% block compresscssblock %}
+
+{% endblock %}
+{% block compressinlinecssblock %}
+
+{% endblock %}
+{% block search %} {% endblock %}
+{% block content %}
+
+
+
+ One Day Workshop/Training Participants
+
+
+
+
+Institute name
+{{ single_training.academic.institution_name }}
+FOSS
+{{ single_training.course.foss.foss }}
+Date
+{{ single_training.tdate }}
+Participant count
+{{ single_training.participant_count }}
+Organiser
+{{ single_training.organiser.user.first_name }}
+Training Type
+
+ {% if training.training_type == 0 %}
+ School
+ {% elif training.training_type == 1 %}
+ Live workshop
+ {% elif training.training_type == 2 %}
+ Pilot workshop
+ {% else %}
+ Vocational
+ {% endif %}
+
+
+
+
+
+{% endblock %}
+{% block jsblock %}
+
+{% endblock %}
diff --git a/events/events/templates/single-training-certificate.html b/events/events/templates/single-training-certificate.html
new file mode 100644
index 000000000..145b00579
--- /dev/null
+++ b/events/events/templates/single-training-certificate.html
@@ -0,0 +1,54 @@
+
+{% extends 'base.html' %}
+{% load attendance %}
+{% load widget_tweaks %}
+{% load static %}
+{% block title %}Student List{% endblock %}
+{% block heading %}Participant List {% endblock %}
+{% block cssblock %}
+
+{% endblock %}
+{% block search %}{% endblock %}
+{% block content %}
+
+{% endblock %}
diff --git a/events/events/templates/single-training-form.html b/events/events/templates/single-training-form.html
new file mode 100644
index 000000000..5a540a658
--- /dev/null
+++ b/events/events/templates/single-training-form.html
@@ -0,0 +1,213 @@
+{% extends 'spoken/templates/base.html' %}
+{% load widget_tweaks %}
+{% load static %}
+{% load eventsdata %}
+{% block title %}Training - Request{% endblock %}
+{% block heading %}
Dashboard {% endblock %}
+{% block compresscssblock %}
+
+{% endblock %}
+{% block compressinlinecssblock %}
+
+{% endblock %}
+{% block search %} {% endblock %}
+{% block content %}
+ {{form.errors}}
+
+ {% if instance %}
+ {{ instance.academic.state }} - {{ instance.academic }}
+ {% else %}
+ {{ user.organiser.academic.state }} - {{ user.organiser.academic }}
+ {% endif %}
+
+
+
+{% endblock %}
+{% block compressjsblock %}
+
+{% endblock %}
+{% block compressinlinejsblock %}
+
+{% endblock %}
diff --git a/events/events/templates/single-training.html b/events/events/templates/single-training.html
new file mode 100644
index 000000000..6284e9fc0
--- /dev/null
+++ b/events/events/templates/single-training.html
@@ -0,0 +1,165 @@
+{% extends 'base.html' %}
+{% load widget_tweaks %}
+{% load static %}
+{% load eventsdata %}
+{% block title %}Training - Request{% endblock %}
+{% block heading %}
Dashboard {% endblock %}
+{% block compresscssblock %}
+
+{% endblock %}
+{% block compressinlinecssblock %}
+
+{% endblock %}
+{% block search %} {% endblock %}
+{% block content %}
+
+
+
+
+
+
Section A
+
+
+
+ #
+ Training Date
+ Software Course
+ Language
+ Institution name
+ Participant Count
+ Training type
+
+ {% for training in object_list %}
+
+ {{ forloop.counter }}
+ {{ training.tdate }}
+ {{ training.course.course_name }}
+ {{ training.language }}
+ {{ training.academic }}
+ {% if user|is_administrator %}
+ {% if request.path == '/software-training/single-training/pendingattendance/' %}
+ {{ training.participant_count }}
+ {% elif request.path == '/software-training/single-training/approved/' %}
+ {{ training.participant_count }}
+ {% elif request.path == '/software-training/single-training/rejected/' %}
+ {{ training.participant_count }}
+ {% elif request.path == '/software-training/single-training/ongoing/' %}
+ {{ training.participant_count }}
+ {% elif request.path == '/software-training/single-training/pending/' %}
+ {{ training.participant_count }}
+ {% elif request.path == '/software-training/single-training/completed/' %}
+
+ {% if training.is_singletraining_certificate_allowed %}
+ {{ training.participant_count }} | {{ training.total_participant_count }} Download Certificate
+ {% elif not training.is_singletraining_certificate_allowed %}
+ {{ training.participant_count }} | {{ training.total_participant_count }} Training Completed
+ {% endif %}
+
+ {% endif %}
+
+
+ {% elif user|is_organiser %}
+ {% if request.path == '/software-training/single-training/approved/' %}
+ {{ training.participant_count }}
+ {% elif request.path == '/software-training/single-training/pending/' %}
+
+ {{ training.participant_count }}
+ | Edit
+
+ {% elif request.path == '/software-training/single-training/rejected/' %}
+ {{ training.participant_count }}
+ {% elif request.path == '/software-training/single-training/ongoing/' %}
+ {{ training.participant_count }} / {{ training.total_participant_count }}
+ {% elif request.path == '/software-training/single-training/pendingattendance/' %}
+
+ {% if 'Administrator' not in group and 'Resource Person' not in group %}
+ {{ training.participant_count }} | Request to mark attendance
+ {% else %}
+
+ {{ training.participant_count }}
+ {% endif %}
+ {% elif request.path == '/software-training/single-training/completed/' %}
+
+ {% if training.is_singletraining_certificate_allowed %}
+ {{ training.participant_count }} | {{ training.total_participant_count }} Download Certificate
+ {% elif not training.is_singletraining_certificate_allowed %}
+ {{ training.participant_count }} | {{ training.total_participant_count }} Training Completed
+ {% endif %}
+
+ {% endif %}
+ {% elif user|is_resource_person %}
+ {% if request.path == '/software-training/single-training/pendingattendance/' %}
+ {{ training.participant_count }}
+ {% elif request.path == '/software-training/single-training/approved/' %}
+ {{ training.participant_count }}
+ {% elif request.path == '/software-training/single-training/rejected/' %}
+ {{ training.participant_count }}
+ {% elif request.path == '/software-training/single-training/ongoing/' %}
+ {{ training.participant_count }}
+ {% elif request.path == '/software-training/single-training/pending/' %}
+ {{ training.participant_count }}
+ {% elif request.path == '/software-training/single-training/completed/' %}
+
+ {% if training.is_singletraining_certificate_allowed %}
+ {{ training.participant_count }} | {{ training.total_participant_count }} Download Certificate
+ {% elif not training.is_singletraining_certificate_allowed %}
+ {{ training.participant_count }} | {{ training.total_participant_count }} Training Completed
+ {% endif %}
+
+ {% endif %}
+ {% else %}
+ {{ training.participant_count }}
+ {% endif %}
+ {% if training.training_type == 0 %}
+ School
+ {% elif training.training_type == 1 %}
+ Live workshop
+ {% elif training.training_type == 2 %}
+ Pilot workshop
+ {% else %}
+ Vocational
+ {% endif %}
+ {% if user|is_resource_person %}
+ {% if request.path == "/software-training/single-training/pending/" %}
+ Approve
+ Reject
+ {% endif %}
+ {% endif %}
+
+ {% endfor %}
+
+
+
+
+
+{% endblock %}
+{% block compressinlinejsblock %}
+
+{% endblock %}
diff --git a/events/events/templates/student_batch_list.html b/events/events/templates/student_batch_list.html
new file mode 100644
index 000000000..cec67f81b
--- /dev/null
+++ b/events/events/templates/student_batch_list.html
@@ -0,0 +1,131 @@
+
+{% extends 'base.html' %}
+{% load widget_tweaks %}
+{% load static %}
+{% block title %}Master Batch Student List{% endblock %}
+{% block heading %}
Master Batch Student List Dashboard {% endblock %}
+{% load announcements %}
+{% block announcement %}
+
+ {% get_notifications as notifications %}
+ {% if notifications %}
+ {% for notification in notifications %}
+
+
+
+ {{ notification.body|safe }}
+
+
+
+
+ {% endfor %}
+ {% endif %}
+
+{% endblock %}
+{% block search %}{% endblock %}
+{% block content %}
+{% load cmsdata %}
+{% load student %}
+
+
+
+
+
+
+
+
×
+
+ Create a spreadsheet in LibreOffice Calc or MS Excel of student with the following details: First Name, Last Name, Email ID and Gender .
+ Please upload Master Batch of all students in that department and year in .csv file .
+ Please ensure that you fill in only the genuine Email ID's of the Participants/Students. If they don't have any, please help them to create one.
+ One Master Batch must contain names from only one department. βDO NOT COMBINE DEPARTMENTSβ
+ For additional students Add student details in the existing Master Batch of same year and department.
+ Organiser can EDIT department , year, students name, Email ID, Gender if entered incorrectly in Master Batch.
+ If students does not receive any username-password mail, kindly guide them to verify and activate their account from this link: https://spoken-tutorial.org/accounts/verify/
+
+
+
+
+
+
+{% if object_list %}
+
+ If you have completed adding Master Batch/es , kindly continue with Step 2 and Step 3 from STP Summary page.
+
+{% else %}
+ kindly add your master batches.
+{% endif %}
+
+ {% if object_list %}
+
+ {% get_sortable_header header ordering request.GET %}
+ {% for record in object_list %}
+
+ {{ forloop.counter }}
+ {{ record.batch_name }}
+ {{ record.academic }}
+ {{ record.department }}
+ {{ record.year }}
+ {{ record.student_count }}
+
+ {% if record.organiser.user == request.user %}
+ Edit |
+ {% endif %}
+ Student List
+ {% if record|can_add_student:request.user %}
+ | Add Student
+ {% endif %}
+
+
+ {% endfor %}
+
+ {% else %}
+
No record found!
+ {% endif %}
+{% endblock %}
+{% block compressjsblock %}
+
+{% endblock %}
+{% block jsblock %}
+
+
+{% endblock %}
+
diff --git a/events/events/templates/student_delete.html b/events/events/templates/student_delete.html
new file mode 100644
index 000000000..fe7da3f98
--- /dev/null
+++ b/events/events/templates/student_delete.html
@@ -0,0 +1,13 @@
+
+{% extends 'spoken/templates/base.html' %}
+{% load widget_tweaks %}
+{% load static %}
+{% block title %}Delete Student{% endblock %}
+{% block heading %}
Delete Student {% endblock %}
+{% block search %}{% endblock %}
+{% block content %}
+
+{% endblock %}
diff --git a/events/events/templates/student_delete_masterbatch.html b/events/events/templates/student_delete_masterbatch.html
new file mode 100644
index 000000000..6df84b0db
--- /dev/null
+++ b/events/events/templates/student_delete_masterbatch.html
@@ -0,0 +1,13 @@
+
+{% extends 'spoken/templates/base.html' %}
+{% load widget_tweaks %}
+{% load static %}
+{% block title %}Delete Student{% endblock %}
+{% block heading %}
Delete Student {% endblock %}
+{% block search %}{% endblock %}
+{% block content %}
+
+{% endblock %}
diff --git a/events/events/templates/stworkshop_feedback.html b/events/events/templates/stworkshop_feedback.html
new file mode 100644
index 000000000..b759a06a7
--- /dev/null
+++ b/events/events/templates/stworkshop_feedback.html
@@ -0,0 +1,685 @@
+{% extends 'base.html' %}
+{% load widget_tweaks %}
+{% load static %}
+{% load eventsdata %}
+{% block title %} Feedback{% endblock %}
+{% block compresscssblock %}
+
+{% endblock %}
+{% block compressinlinecssblock %}
+
+{% endblock %}
+{% block content %}
+{{Success}}
+
Workshop Feedback Form
+
+{% endblock %}
+{% block compressjsblock %}
+
+{% endblock %}
+{% block compressinlinejsblock %}
+
+{% endblock %}
diff --git a/events/events/templates/stworkshop_feedback_post.html b/events/events/templates/stworkshop_feedback_post.html
new file mode 100644
index 000000000..b66dde725
--- /dev/null
+++ b/events/events/templates/stworkshop_feedback_post.html
@@ -0,0 +1,1015 @@
+ο»Ώ{% extends 'base.html' %}
+{% load widget_tweaks %}
+{% load static %}
+{% load eventsdata %}
+{% block title %} Feedback{% endblock %}
+{% block compressinlinecssblock %}
+
+{% endblock %}
+{% block content %}
+{{Success}}
+
Workshop Feedback Form
+
Dear Respondent,
+Your valuable feedback about the Workshop and Self-Learning experience is appreciated and will help us to improve the quality of work we do. Kindly put a tick-mark for the response that describes your views using the key given below. Your response will be kept highly confidential.
+
+
+{% endblock %}
diff --git a/events/events/templates/stworkshop_feedback_pre.html b/events/events/templates/stworkshop_feedback_pre.html
new file mode 100644
index 000000000..95d43542c
--- /dev/null
+++ b/events/events/templates/stworkshop_feedback_pre.html
@@ -0,0 +1,309 @@
+{% extends 'base.html' %}
+{% load widget_tweaks %}
+{% load static %}
+{% load eventsdata %}
+{% block title %} PreFeedback{% endblock %}
+{% block compressinlinecssblock %}
+
+{% endblock %}
+{% block content %}
+{{Success}}
+
Workshop Feedback Form
+
Dear Respondent,
+Your valuable feedback about the Workshop and Self-Learning experience is appreciated and will help us to improve the quality of work we do. Kindly put a tick-mark for the response that describes your views using the key given below. Your response will be kept highly confidential.
+
+
+{% endblock %}
diff --git a/events/events/templates/training_attendance.html b/events/events/templates/training_attendance.html
new file mode 100644
index 000000000..7a6b295cd
--- /dev/null
+++ b/events/events/templates/training_attendance.html
@@ -0,0 +1,201 @@
+
+{% extends 'base.html' %}
+{% load attendance %}
+{% load widget_tweaks %}
+{% load static %}
+{% block title %}Participant List{% endblock %}
+{% block heading %}
Participant List {% endblock %}
+{% block cssblock %}
+
+{% endblock %}
+{% block search %}{% endblock %}
+{% block content %}
+
+ {% endif %}
+
+ {% endwith %}
+ {% endif %}
+{% endblock %}
+{% block jsblock %}
+
+{% endblock %}
diff --git a/events/events/templates/training_certificate.html b/events/events/templates/training_certificate.html
new file mode 100644
index 000000000..3415ccd58
--- /dev/null
+++ b/events/events/templates/training_certificate.html
@@ -0,0 +1,93 @@
+
+{% extends 'base.html' %}
+{% load attendance %}
+{% load widget_tweaks %}
+{% load static %}
+{% block title %}Participant List{% endblock %}
+{% block heading %}
Participant List {% endblock %}
+{% load announcements %}
+{% block announcement %}
+
+ {% get_notifications as notifications %}
+ {% if notifications %}
+ {% for notification in notifications %}
+
+
+
+ {{ notification.body|safe }}
+
+
+
+
+ {% endfor %}
+ {% endif %}
+
+{% endblock %}
+{% block search %}{% endblock %}
+{% block content %}
+
+{% endblock %}
+{% block jsblock %}
+
+{% endblock %}
\ No newline at end of file
diff --git a/events/events/templates/training_list.html b/events/events/templates/training_list.html
new file mode 100644
index 000000000..00e310e0b
--- /dev/null
+++ b/events/events/templates/training_list.html
@@ -0,0 +1,191 @@
+{% extends 'spoken/templates/base.html' %}
+{% load widget_tweaks %}
+{% load static %}
+{% load eventsdata %}
+{% load cmsdata %}
+{% load creationdata %}
+{% block title %}Training - {{ status}} {% endblock %}
+{% block uncompresscssblock %}
+
+{% endblock %}
+{% block compresscssblock %}
+
+{% endblock%}
+{% block heading %}
+
Training
Dashboard
+{% endblock %}
+{% block content %}
+
+
+
+
+
+
+ {% if collection %}
+
+ {% else %}
+
No record found!
+ {% endif %}
+
+
+{% endblock %}
+
+{% block uncompressjsblock %}
+
+
+{% endblock %}
+{% block compressjsblock %}
+
+
+{% endblock %}
+{% block compressinlinejsblock %}
+
+{% endblock %}
diff --git a/events/events/templates/training_planner.html b/events/events/templates/training_planner.html
new file mode 100644
index 000000000..7605d7574
--- /dev/null
+++ b/events/events/templates/training_planner.html
@@ -0,0 +1,315 @@
+
+{% extends 'spoken/templates/base.html' %}
+{% load announcements %}
+{% block title %}Semester Training Planner Summary{% endblock %}
+{% block heading %}
+
Semester Training Planner Summary (STPS)
+
Dashboard
+
Instructions
+{% endblock %}
+{% block announcement %}
+
+ {% get_notifications as notifications %}
+ {% if notifications %}
+ {% for notification in notifications %}
+
+
+
+ {{ notification.body|safe }}
+
+
+
+
+ {% endfor %}
+ {% endif %}
+
+{% endblock %}
+{% block search %}{% endblock %}
+
+{% block cssblock %}
+
+{% endblock %}
+
+{% block content %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
×
+
+ You are on the STPS page.
+ Complete the 3 steps in sequence and follow all the instructions.
+ The Click here will give a detailed instruction sheet for the particular step:
+
+ For Master Batch : Click Here .
+ For STPF : Click Here .
+ For Participants List : Click Here .
+ Proceed with Test after 30 days of Semester Start Date.
+
+
+ Please download a copy of tutorials on all the machines. For instructions to download tutorials Click Here
+ Please check if your machine is ready. For the Machine Readiness document Click Here .
+
+
+
+
+
+
+ {{message}}
+
+
+ {{current_planner.academic.institution_name}}, {{current_planner.academic.district.name}}
+
+
+
+
+
+ {{ current_planner.get_semester }} (Current Semester)
+ completed : {{ current_planner.completed_training.count }}
+ Ongoing : {{ current_planner.ongoing_training.count }}
+
+
+ {% if current_planner.training_requests %}
+
+
+ #
+ Semester Start Date
+ Software Course
+ Department
+ Batch Year
+ Participant List Status
+
+ {% for training in current_planner.training_requests %}
+
+ {{ forloop.counter }}
+ {{ training.sem_start_date }}
+ {{ training.course.course_name }}
+ {{ training.department }}
+ {{training.batch.year}}
+ {{ training.attendance_summery }}
+
+ {% endfor %}
+
+ {% else %}
+
+ Training planner is empty
+
+ {% endif %}
+
+
+
+ {% if next_planner %}
+
+
+ {{ next_planner.get_semester }} (Next Semester)
+ Planned : {{ next_planner.ongoing_training.count }}
+
+
+ {% if next_planner.training_requests %}
+
+
+ #
+ Semester Start Date
+ Software Course
+ Department
+ Batch Year
+ Participant List Status
+ Action
+
+ {% for training in next_planner.training_requests %}
+
+ {{ forloop.counter }}
+ {{ training.sem_start_date }}
+ {{ training.course.course_name }}
+ {{ training.department }}
+ {{training.batch.year}}
+ {{ training.attendance_summery }}
+
+ {% if training.can_edit %}
+ | Edit |
+ {% endif %}
+
+
+ {% endfor %}
+
+ {% else %}
+
+ Training planner is empty
+
+ {% endif %}
+
+
+ {% endif %}
+ {% for record in object_list %}
+ {% if not record.id == current_planner.id and not record.id == next_planner.id %}
+
+
+ {{ record.get_semester }}
+ Total : {{ record.completed_training.count }}
+
+ {% if record.training_requests %}
+
+
+
+ #
+ Semester Start Date
+ Software Course
+ Department
+ Participant List Status
+ Action
+
+ {% for training in record.training_requests %}
+
+ {{ forloop.counter }}
+ {{ training.sem_start_date }}
+ {{ training.course.course_name }}
+ {{ training.department }}
+ {{ training.attendance_summery }} {% if training.can_edit %}{% endif %}
+
+ {% if training.status == 0 %}
+ {% if training.get_partipants_from_attendance %}
+ | Participant List |
+ {% if training.can_edit %} Edit {% endif %}
+ {% endif %}
+ {% else %}
+ {% if training.get_partipants_from_attendance %}
+ | Participant List |
+ {% if training.cert_status == 0 %}
+ Generate Participation Certificate
+ {% elif training.cert_status == 1 %}
+ Participation certificates available
+ {% else %}
+ Certificate request awaiting at Training manager
+ {% endif %}
+ |
+ {% endif %}
+ {% endif %}
+
+
+ {% endfor %}
+
+
+ {% endif %}
+
+ {% endif %}
+ {% endfor %}
+
+{% endblock %}
+
+{% block jsblock %}
+
+{% endblock %}
+
diff --git a/events/events/templates/training_request.html b/events/events/templates/training_request.html
new file mode 100644
index 000000000..9dc6ff506
--- /dev/null
+++ b/events/events/templates/training_request.html
@@ -0,0 +1,613 @@
+
+{% extends 'spoken/templates/base.html' %}
+{% load widget_tweaks %}
+{% load static %}
+{% block title %}Training Planner Form{% endblock %}
+{% block compresscssblock %}
+
+{% endblock %}
+{% block cssblock %}
+
+{% endblock %}
+{% block heading %}
+ Training Planner Form
+ Instructions for STPF
+{% endblock %}
+{% block search %}{% endblock %}
+{% block content %}
+{% for message in messages %}
+{% if message.tags == 'success' %}
+
+
+
+
+ {{ message|safe }}
+
+
+
+
+
+{% endif %}
+{% endfor %}
+
+
+
+
+
+
×
+
+ For detailed instruction on Step 2 click here : Semester Training Planner Form: http://process.spoken-tutorial.org/images/b/bc/Semester_Training_Planner.pdf
+ It is best to select Software courses mapped to relevant courses being taught during this semester in the department.
+ You can also select Software courses which are unmapped with courses being taught during this semester in the department.
+ Unmapped Software courses can be planned during designated computer lab hours present in the time table during this semester.
+ Please Note - Not more than 2 courses with assessment test can be requested in one semester.
+ Test are available for the following FOSS : Applications of GeoGebra, Arduino, Avogadro, BASH, Biopython, Blender, C and C++, Advanced C++, CellDesigner, Chemcollective Virtual Labs, Drupal, DWSIM, eSim, Expeyes, GchemPaint, GeoGebra 5.04, gedit Text Editor, GIMP, GIT, Inkscape, Introduction to Computers, Java, Java Business Application, Joomla, Jmol Application, Kturtle, LaTeX, LibreOffice Suite, Linux & Ubuntu, Linux AWK, OpenFOAM, OpenModelica, Perl, PHP & MySQL, Python 3.4.3, QCAD, RDBMS, Ruby, Scilab, Single Board Heater System, UCSF Chimera .
+
+
+
+
+
+
+
+ {% if form %}
+
+ {% endif %}
+{% endblock %}
+{% block compressjsblock %}
+
+
+{% endblock %}
+{% block jsblock %}
+
+
+{% endblock %}
diff --git a/events/events/templates/trainingrequest_list.html b/events/events/templates/trainingrequest_list.html
new file mode 100644
index 000000000..9cc3fcbd0
--- /dev/null
+++ b/events/events/templates/trainingrequest_list.html
@@ -0,0 +1,340 @@
+
+{% extends 'spoken/templates/base.html' %}
+{% load widget_tweaks %}
+{% load static %}
+{% block title %}Training Planner Form{% endblock %}
+{% block compresscssblock %}
+
+{% endblock %}
+{% block cssblock %}
+
+{% endblock %}
+{% block heading %}
+ Training Planner Form
+ Instructions for STPF
+{% endblock %}
+{% block search %}{% endblock %}
+{% block content %}
+{% for message in messages %}
+{% if message.tags == 'success' %}
+
+
+
+
+ {{ message|safe }}
+
+
+
+
+
+{% endif %}
+{% endfor %}
+
+
+
+
+
+
×
+
+ For detailed instruction on Step 2 click here : Semester Training Planner Form: http://process.spoken-tutorial.org/images/b/bc/Semester_Training_Planner.pdf
+ It is best to select Software courses mapped to relevant courses being taught during this semester in the department.
+ You can also select Software courses which are unmapped with courses being taught during this semester in the department.
+ Unmapped Software courses can be planned during designated computer lab hours present in the time table during this semester.
+ Please Note - Not more than 2 courses with assessment test can be requested in one semester.
+ Test are available for the following FOSS : BASH, C, CPP, CellDesigner, Drupal, GChemPaint, Geogebra, Git, Java, Jmol Application, Linux, LaTeX, PERL, PHP & MySQL, Python and Scilab .
+
+
+
+
+
+
+
+ {% if form %}
+
+ {% endif %}
+{% endblock %}
+{% block compressjsblock %}
+
+
+{% endblock %}
+{% block jsblock %}
+
+{% endblock %}
diff --git a/events/events/templates/update_batch.html b/events/events/templates/update_batch.html
new file mode 100644
index 000000000..42e7133f3
--- /dev/null
+++ b/events/events/templates/update_batch.html
@@ -0,0 +1,184 @@
+
+{% extends 'spoken/templates/base.html' %}
+{% load widget_tweaks %}
+{% load static %}
+{% block title %}Student Batch{% endblock %}
+{% block heading %}Student Batch Back to MB Master Batch {% endblock %}
+{% block search %}{% endblock %}
+{% block content %}
+ {% if form %}
+
+ {% if existing_student %}
+ Existing Student List
+
+
+ #
+ Department
+ Year
+ First Name
+ Last Name
+ Email
+ Gender
+
+ {% for record in existing_student %}
+
+ {{ forloop.counter }}
+ {{ batch.department}}
+ {{ batch.year}}
+ {{ record.user.first_name }}
+ {{ record.user.last_name }}
+ {{ record.user.email }}
+ {{ record.gender }}
+
+ {% endfor %}
+
+ {% endif %}
+ {% else %}
+ {{ batch.get_batch_info }}
+
+ {% endif %}
+ {% if warning %}
+
+
Warning Note: Click on the email to correct email format
+
+
+
+ #
+ Full name
+ Email
+ Gender
+
+
+ {% for e in warning %}
+
+ {{ forloop.counter }}
+ {{ e.0 }} {{ e.1 }}
+ {{ e.2 }}
+ {{ e.3 }}
+ {{ e.4 }}
+
+ {% endfor %}
+
+
+ {% endif %}
+{% endblock %}
+{% block jsblock %}
+
+
+{% endblock %}
diff --git a/events/events/templates/update_student.html b/events/events/templates/update_student.html
new file mode 100644
index 000000000..f040aefc9
--- /dev/null
+++ b/events/events/templates/update_student.html
@@ -0,0 +1,86 @@
+
+{% extends 'base.html' %}
+{% load widget_tweaks %}
+{% load cmsdata %}
+{% load static %}
+{% block cssblock %}
+
+{% endblock %}
+{% block title %}Participant Details{% endblock %}
+{% block heading %}
Participant Details : {% endblock %}
+{% block search %}{% endblock %}
+{% block content %}
+{% if form %}
+
+{% endif %}
+{% endblock %}
+{% block jsblock %}
+
+{% endblock %}
diff --git a/events/events/templates/verify_test_certificate.html b/events/events/templates/verify_test_certificate.html
new file mode 100644
index 000000000..27d55e85b
--- /dev/null
+++ b/events/events/templates/verify_test_certificate.html
@@ -0,0 +1,113 @@
+{% extends 'base.html' %}
+{% load announcements %}
+
+{% block header%}
+
Test Certificate Verification
+{% endblock %}
+{% block announcement %}
+
+ {% get_notifications as notifications %}
+ {% if notifications %}
+ {% for notification in notifications %}
+
+
+
+ {{ notification.body|safe }}
+
+
+
+
+ {% endfor %}
+ {% endif %}
+
+{% endblock %}
+{% block content %}
+{% if serial_no %}
+
+
+ Participation Details
+
+ {% for key, value in detail.items %}
+
+ {{ key }}
+ {{ value }}
+
+ {% endfor %}
+
+ Certificate
+ Download Certificate
+
+
+
+
+
+{% else %}
+
+
+
+
+
+ Sorry ! The serial number you entered seems to be invalid. Please try again !
+
+
+
+
+
Enter the serial number from your test certificate
+
+
+
+
+{% endblock %}
+
+{% block compressjsblock %}
+
+{% endblock %}
+{% block jsblock %}
+
+{% endblock %}
+
+
diff --git a/events/events/templatetags/__init__.py b/events/events/templatetags/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/events/events/templatetags/attendance.py b/events/events/templatetags/attendance.py
new file mode 100644
index 000000000..f1a09d3b4
--- /dev/null
+++ b/events/events/templatetags/attendance.py
@@ -0,0 +1,34 @@
+from django import template
+
+register = template.Library()
+from events.models import TrainingAttend
+
+@register.filter
+def is_attendance_marked(training, student):
+ if TrainingAttend.objects.filter(training=training, student=student).exists():
+ return True
+ return False
+
+@register.filter
+def get_attendance(training, student):
+ if TrainingAttend.objects.filter(training=training, student=student).exists():
+ return TrainingAttend.objects.filter(training=training, student=student).first()
+ if training.batch_id:
+ return True
+ return False
+
+@register.filter
+def get_langid(training, student):
+ try:
+ training_attend = TrainingAttend.objects.get(training=training, student=student)
+ return training_attend.language_id
+ except:
+ pass
+ return False
+
+@register.filter
+def is_attendance_allowed(training, student):
+ # checking existing attendance for course
+ if TrainingAttend.objects.filter(student=student, training__course=training.course).exclude(training=training).exists():
+ return False
+ return True
diff --git a/events/events/templatetags/eventsdata.py b/events/events/templatetags/eventsdata.py
new file mode 100644
index 000000000..a2f7282dd
--- /dev/null
+++ b/events/events/templatetags/eventsdata.py
@@ -0,0 +1,239 @@
+
+from builtins import str
+from django import template
+from django.contrib.auth.models import User
+from events.models import *
+from events.views import is_organiser, is_invigilator, is_resource_person, is_accountexecutive, is_event_manager, can_clone_training, \
+ is_administrator, is_organiser_deactivated, is_invigilator_deactivated, is_school_training_manager
+import datetime
+from django.conf import settings
+from django.core.exceptions import ObjectDoesNotExist
+from dateutil.relativedelta import relativedelta
+import os
+import os.path
+from mdldjango.models import MdlUser
+register = template.Library()
+
+
+def participant_picture(user_id):
+ print(user_id)
+ try:
+ return settings.ONLINE_TEST_URL + "get_profile_picture.php?id=" + str(user_id)
+ except Exception as e:
+ print(e)
+ return None
+
+def get_trainingstatus(key, training):
+ wa = None
+ try:
+ #if training.organiser.academic.institution_type.name == "School":
+ # wa = SchoolTrainingAttendance.objects.get(id = key, training = training)
+ #else:
+ wa = TrainingAttendance.objects.get(id=key, training = training)
+ except Exception as e:
+ print(e)
+ return ''
+
+ if wa.status == 1:
+ return 'checked'
+
+ if wa.status > 1:
+ return 'disabled=disabled checked'
+
+ return ''
+
+def get_trainingparticipant_status(key, wcode):
+ status_list = ['Waiting for Attendance', 'Completed', 'Got certificate', 'Got certificate']
+ try:
+ wa = TrainingAttendance.objects.get(id=key, training_id = wcode)
+ except:
+ return 'error'
+ return status_list[wa.status]
+
+def participant_count(objects, category):
+ if category == 'Training':
+ try:
+ return objects.trainingattendance_set.all().count()
+ except Exception as e:
+ return 0
+ elif category == 'Test':
+ count = objects.testattendance_set.all().count()
+ if not count:
+ if objects.training:
+ return objects.training.participants
+ else:
+ return 'N/A'
+ return count
+
+def can_close_test(testcode):
+ try:
+ ta = TestAttendance.objects.filter(test_id = testcode, status__range=(0, 3)).first()
+ except:
+ return True
+ return False
+
+def get_status(key, testcode):
+ try:
+ ta = TestAttendance.objects.get(mdluser_id=key, test_id=testcode)
+ except:
+ return 'error'
+
+ if ta.status == 1:
+ return 'checked'
+
+ if ta.status > 1:
+ return 'disabled=disabled checked'
+
+ return ''
+
+def get_participant_status(key, testcode):
+ status_list = ['Waiting for Attendance', 'Ready for test', 'Ongoing Test', 'Test Completed', 'Certificate Issued']
+ try:
+ ta = TestAttendance.objects.get(mdluser_id=key, test_id=testcode)
+ except:
+ return 'Add'
+ return status_list[ta.status]
+
+def can_upload_final_training_list(tdate):
+ try:
+ date_after_one_month = tdate + relativedelta(days=30)
+ if datetime.date.today() >= date_after_one_month:
+ return True
+ return False
+ except Exception as e:
+ print(e)
+ return False
+
+def can_download_workshop_certificate(key, training):
+ try:
+ wa = TrainingAttendance.objects.get(mdluser_id=key, training = training)
+ if wa.status > 0:
+ return wa.id
+ return False
+ except:
+ return 'errors'
+
+def can_enter_test(key, testcode):
+ try:
+ ta = TestAttendance.objects.get(mdluser_id=key, test_id=testcode)
+ mdl = MdlQuizGrades.objects.filter(quiz=ta.mdlquiz_id, userid=key).order_by('-grade').first()
+ if mdl and mdl.grade >= 40:
+ return 3 # test completed with pass grade of 40 or more for given quiz
+ return ta.status
+ except TestAttendance.DoesNotExist:
+ return None
+
+def training_file_exits(wid):
+ file_path = settings.MEDIA_ROOT + 'training/' + str(wid) + '/' + str(wid) + '.pdf'
+ if os.path.isfile(file_path):
+ return True
+ return False
+
+def is_feedback_exits(w, record):
+ try:
+ TrainingFeedback.objects.get(training_id=w.id, mdluser_id=record.mdluser_id)
+ return True
+ except Exception as e:
+ print(e)
+ return False
+
+def feedback_status_good(status):
+ status_dict = {0 : 'Very Bad', 1 : 'Very Bad', 2 : 'Bad', 3 : 'Fair', 4 : 'Good', 5 : 'Very Good'}
+ return status_dict[status]
+
+def feedback_status_moderately(status):
+ status_dict = {0 : 'Not at All', 1 : 'Not at All', 2 : 'Slightly', 3 : 'Moderately', 4 : 'Very Good', 5 : 'Extremely'}
+ return status_dict[status]
+
+def feedback_status_appropriate(status):
+ status_dict = {0 : 'Slow', 1 : 'Slow', 2 : 'Appropriate', 3 : 'Fast'}
+ return status_dict[status]
+
+def feedback_status_satisfactory(status):
+ status_dict = {0 : 'Very Bad', 0 : 'Very Bad', 1 : 'Very Bad', 2 : 'Bad', 3 : 'Satisfactory', 4 : 'Good', 5 : 'Excellent'}
+ return status_dict[status]
+
+def feedback_status_somewhat(status):
+ status_dict = {0 : 'Very Bad', 0 : 'Very Bad', 1 : 'Very Bad', 2 : 'A little bit', 3 : 'Somewhat', 4 : 'Quite a bit', 5 : 'A lot'}
+ return status_dict[status]
+
+def feedback_status_average(status):
+ status_dict = {0 : 'Very Low', 1 : 'Very Low', 2 : 'Below average', 3 : 'Average', 4 : 'Above average', 5 : 'Very High'}
+ return status_dict[status]
+
+def feedback_status_neutral(status):
+ status_dict = {0 : 'Strongly Disagree', 1 : 'Strongly Disagree', 2 : 'Disagree', 3 : 'Likely', 4 : 'Agree', 5 : 'Strongly Agree'}
+ return status_dict[status]
+
+def feedback_status_likely(status):
+ status_dict = {0 : 'Not at All', 1 : 'Not at All', 2 : 'Maybe', 3 : 'Likely', 4 : 'Quite likely', 5 : 'Definitely'}
+ return status_dict[status]
+
+@register.filter
+def is_college_subscribed(college_id):
+ try:
+ idcase = AcademicKey.objects.filter(academic_id=college_id, expiry_date__gte=date.today()).first()
+ college_paid = True if (idcase.expiry_date >= date.today()) else False
+ return college_paid
+ except:
+ college_paid = False
+
+ return college_paid
+
+register.filter('participant_picture', participant_picture)
+register.filter('get_trainingstatus', get_trainingstatus)
+register.filter('get_trainingparticipant_status', get_trainingparticipant_status)
+register.filter('participant_count', participant_count)
+register.filter('can_close_test', can_close_test)
+register.filter('get_status', get_status)
+register.filter('get_participant_status', get_participant_status)
+register.filter('can_upload_final_training_list', can_upload_final_training_list)
+register.filter('can_enter_test', can_enter_test)
+
+register.filter('is_administrator', is_administrator)
+register.filter('is_organiser', is_organiser)
+register.filter('is_invigilator', is_invigilator)
+register.filter('is_resource_person', is_resource_person)
+register.filter('is_accountexecutive', is_accountexecutive)
+register.filter('is_event_manager', is_event_manager)
+register.filter('is_school_training_manager', is_school_training_manager)
+register.filter('is_organiser_deactivated', is_organiser_deactivated)
+register.filter('is_invigilator_deactivated', is_invigilator_deactivated)
+register.filter('can_download_workshop_certificate', can_download_workshop_certificate)
+register.filter('training_file_exits', training_file_exits)
+register.filter('is_feedback_exits', is_feedback_exits)
+register.filter('feedback_status_good', feedback_status_good)
+register.filter('feedback_status_moderately', feedback_status_moderately)
+register.filter('feedback_status_appropriate', feedback_status_appropriate)
+register.filter('feedback_status_satisfactory', feedback_status_satisfactory)
+register.filter('feedback_status_somewhat', feedback_status_somewhat)
+register.filter('feedback_status_average', feedback_status_average)
+register.filter('feedback_status_neutral', feedback_status_neutral)
+register.filter('feedback_status_likely', feedback_status_likely)
+register.filter('can_clone_training', can_clone_training)
+
+
+@register.filter
+def get_grade_mdluser(Dict, ta):
+ return Dict[ta.mdluser_id][ta.mdlquiz_id][0]
+
+@register.filter
+def get_grade_mdluser_first_name(id):
+ try:
+ return MdlUser.objects.using('moodle').get(id=id).firstname
+ except MdlUser.DoesNotExist:
+ return None
+
+@register.filter
+def get_grade_mdluser_last_name(id):
+ try:
+ return MdlUser.objects.using('moodle').get(id=id).lastname
+ except MdlUser.DoesNotExist:
+ return None
+
+@register.filter
+def get_grade_mdluser_email(id):
+ try:
+ return MdlUser.objects.using('moodle').get(id=id).email
+ except MdlUser.DoesNotExist:
+ return None
\ No newline at end of file
diff --git a/events/events/templatetags/student.py b/events/events/templatetags/student.py
new file mode 100644
index 000000000..a55d00b6d
--- /dev/null
+++ b/events/events/templatetags/student.py
@@ -0,0 +1,12 @@
+from django import template
+
+register = template.Library()
+from events.models import StudentBatch, StudentMaster
+
+@register.filter
+def can_add_student(student_batch, user):
+ return student_batch.can_add_student(user.organiser.id)
+
+@register.filter
+def get_student_master(batch_id, student_id):
+ return StudentMaster.objects.get(batch_id=batch_id, student_id=student_id)
diff --git a/events/events/tests.py b/events/events/tests.py
new file mode 100644
index 000000000..8d1c77386
--- /dev/null
+++ b/events/events/tests.py
@@ -0,0 +1,141 @@
+import os
+from django.test import TestCase
+from django.urls import reverse
+from django.contrib.auth.models import User, Group, Permission
+from spoken.forms import TestimonialsForm
+
+class TestimonialTestClass(TestCase):
+ '''
+ This class contains test cases for audio /
+ video / text testimonial pages.
+ '''
+
+ @classmethod
+ def setUpTestData(self):
+ """
+ Function creates elements required during testing
+ this function is executed only once.
+ """
+ user_administrator = User.objects.create_user(
+ username='user_administrator',
+ password='atb00ker'
+ )
+ adminuser_permission = Permission.objects.get(name='Can add testimonials')
+ user_administrator.user_permissions.add(adminuser_permission)
+
+ user_normal = User.objects.create_user(
+ username='user_normal',
+ password='atb00ker'
+ )
+
+ # Check status code with no login
+ def test_new_testimonial_no_user(self):
+ """
+ Since only administrator is allowed to
+ create new testimonials, this should redirect.
+ """
+ response = self.client.get(reverse('testimonials_new'))
+ self.assertEqual(response.status_code, 403)
+
+
+ def test_new_media_testimonial_no_user(self):
+ """
+ Since only administrator is allowed to
+ create new testimonials, this should redirect.
+ """
+ response = self.client.get(reverse('testimonials_new_media',kwargs={'type':'tutorial'}))
+ self.assertEqual(response.status_code, 403)
+
+
+ def test_new_series_testimonial_no_user(self):
+ """
+ Since only administrator is allowed to
+ create new testimonials, this should redirect.
+ """
+ response = self.client.get(reverse('testimonials_new_media',kwargs={'type':'series'}))
+ self.assertEqual(response.status_code, 403)
+
+
+ # Check status code with normal_user login
+ def test_new_testimonial_normal_user(self):
+ """
+ Since only administrator is allowed to
+ create new testimonials, this should return page not found.
+ """
+ login = self.client.login(username='user_normal', password='atb00ker')
+ response = self.client.get(reverse('testimonials_new'))
+ self.assertEqual(response.status_code, 403)
+
+
+ def test_new_media_testimonial_normal_user(self):
+ """
+ Since only administrator is allowed to
+ create new testimonials, this should return page not found.
+ """
+ login = self.client.login(username='user_normal', password='atb00ker')
+ response = self.client.get(reverse('testimonials_new_media',kwargs={'type':'tutorial'}))
+ self.assertEqual(response.status_code, 403)
+
+
+ def test_new_series_testimonial_normal_user(self):
+ """
+ Since only administrator is allowed to
+ create new testimonials, this should return page not found.
+ """
+ login = self.client.login(username='user_normal', password='atb00ker')
+ response = self.client.get(reverse('testimonials_new_media',kwargs={'type':'series'}))
+ self.assertEqual(response.status_code, 403)
+
+
+ # Check status code with administrator login
+ def test_new_testimonial_normal_user(self):
+ """
+ Since only administrator is allowed to
+ create new testimonials, this should accept the request.
+ """
+ login = self.client.login(username='user_administrator', password='atb00ker')
+ response = self.client.get(reverse('testimonials_new'))
+ self.assertEqual(response.status_code, 200)
+
+
+ def test_new_media_testimonial_normal_user(self):
+ """
+ Since only administrator is allowed to
+ create new testimonials, this should accept the request.
+ """
+ login = self.client.login(username='user_administrator', password='atb00ker')
+ response = self.client.get(reverse('testimonials_new_media',kwargs={'type':'tutorial'}))
+ self.assertEqual(response.status_code, 200)
+
+
+ def test_new_series_testimonial_normal_user(self):
+ """
+ Since only administrator is allowed to
+ create new testimonials, this should accept the request.
+ """
+ login = self.client.login(username='user_administrator', password='atb00ker')
+ response = self.client.get(reverse('testimonials_new_media',kwargs={'type':'series'}))
+ self.assertEqual(response.status_code, 200)
+
+ # TestimonialsForm Test Case
+ def test_testimonialform_valid(self):
+ # Fill fields
+ source_title = 'Title Message'
+ source_link = 'https://www.spoken-tutorials.org'
+ status = True
+ short_description = 'This field is required.'
+ actual_content = 'This field is required.'
+ user_name = 'This field is required.'
+ minified_content = 'This field is required.'
+ # Create form and check validity
+ form_data = {
+ 'source_title': source_title,
+ 'source_link': source_link,
+ 'status': status,
+ 'short_description': short_description,
+ 'actual_content': actual_content,
+ 'user_name': user_name,
+ 'minified_content': minified_content,
+ }
+ form = TestimonialsForm(data=form_data)
+ self.assertTrue(form.is_valid())
\ No newline at end of file
diff --git a/events/events/urls.py b/events/events/urls.py
new file mode 100644
index 000000000..2f6f85f40
--- /dev/null
+++ b/events/events/urls.py
@@ -0,0 +1,120 @@
+from django.conf.urls import url, include
+from events.views import *
+from events.notification import nemail
+from .views import get_schools, get_batches
+
+app_name = 'events'
+urlpatterns = [
+ url(r'^$', events_dashboard, name='events_dashboard'),
+ url(r'^init/$', init_events_app, name='init_events_app'),
+
+ #cron job
+ #todo: test and workshop auto close
+ url(r'^fix-date-for-first-training/$', fix_date_for_first_training, name='fix_date_for_first_training'),
+ #url(r'^training-gentle-reminder/$', training_gentle_reminder', name='training_gentle_reminder'),
+ #url(r'^training-completion-reminder/$', training_completion_reminder', name='training_completion_reminder'),
+ url(r'^close-predated-ongoing-workshop/$', close_predated_ongoing_workshop, name='close_predated_ongoing_workshop'),
+ url(r'^close-predated-ongoing-test/$', close_predated_ongoing_test, name='close_predated_ongoing_test'),
+
+ url(r'^test/$', nemail, name='test'),
+
+ url(r'^ac/$', ac, name='ac'),
+ url(r'^ac/new/$', new_ac, name='new_ac'),
+ url(r'^ac/(\d+)/edit/$', edit_ac, name='edit_ac'),
+
+ #url(r'^xmlparse/$', xmlparse', name='xmlparse'),
+ #url(r'^pdf/$', pdf', name='pdf'),
+ url(r'^training/permission/$', training_permission, name='training_permission'),
+ url(r'^training/accessrole/$', accessrole, name='training_accessrole'),
+ url(r'^training/old-training-attendance/$', old_training_attendance, name='old_training_attendance'),
+ url(r'^training/old-training-attendance-upload/(\d+)/$', old_training_attendance_upload, name='old_training_attendance_upload'),
+
+ url(r'^(?P\w+)/(?P\w+)/$', organiser_invigilator_index, name='organiser_invigilator_index'),
+ url(r'^organiser/(?P\w+)/(?P\w+)/(?P\d+)/$', rp_organiser, name='rp_organiser'),
+ url(r'^organiser-handover/$', handover, name='handover'),
+
+ url(r'^activate-academics/$', activate_academics, name='activate_academics'),
+ url(r'^activate-academics-org/(?P\d+)/$', activate_academic_org, name='activate_academic_org'),
+
+ url(r"^accountexecutive/request/(?P[\w. @-]+)/$", accountexecutive_request, name='accountexecutive_request'),
+ url(r"^accountexecutive/view/(?P[\w. @-]+)/$", accountexecutive_view, name='accountexecutive_view'),
+ url(r"^accountexecutive/(?P[\w. @-]+)/edit/$", accountexecutive_edit, name='accountexecutive_edit'),
+ url(r'^accountexecutive/(?P\w+)/(?P\w+)/(?P\d+)/$', rp_accountexecutive, name='rp_accountexecutive'),
+
+ url(r"^organiser/request/(?P[\w. @-]+)/$", organiser_request, name='organiser_request'),
+ url(r"^organiser/(?P[\w. @-]+)/edit/$", organiser_edit, name='organiser_edit'),
+ url(r"^organiser/view/(?P[\w. @-]+)/$", organiser_view, name='organiser_view'),
+
+ url(r'^invigilator/(?P\w+)/(?P\w+)/(?P\d+)/$', rp_invigilator, name='rp_invigilator'),
+ url(r"^invigilator/request/(?P[\w. @-]+)/$", invigilator_request, name='invigilator_request'),
+ url(r"^invigilator/(?P[\w. @-]+)/edit/$", invigilator_edit, name='invigilator_edit'),
+ url(r"^invigilator/view/(?P[\w. @-]+)/$", invigilator_view, name='invigilator_view'),
+
+ #live feedback
+ url(r'^training/live/list/$', live_training, name='live_training'),
+ url(r'^training/live/list/(\d+)/$', live_training, name='live_training'),
+
+ url(r'^training/subscribe/(\w+)/(\d+)/(\d+)/$', training_subscribe, name='student_subscribe'),
+ url(r'^training/(\d+)/attendance/$', training_attendance, name='training_attend'),
+ url(r'^training/(\d+)/participant/$', training_participant, name='training_participant'),
+ url(r'^training/participant/certificate/(\d+)/(\d+)/$', training_participant_ceritificate, name='training_participant_ceritificate'),
+ url(r'^training/participant/feedback/(\d+)/(\d+)/$', training_participant_feedback, name='training_participant_feedback'),
+
+ #live feedback
+ url(r'^training/participant/lfeedback/(\d+)/(\d+)/$', training_participant_viewlivefeedback, name='training_participant_viewlivefeedback'),
+ url(r'^training/participant/lfeedback/(\d+)/$', training_participant_livefeedback, name='training_participant_livefeedback'),
+
+ #language Feedback
+ #url(r'^training/participant/language-feedback/(\d+)/(\d+)/$', training_participant_view_language_feedback', name='training_participant_viewlivefeedback'),
+ url(r'^training/participant/language-feedback/(\d+)/(\d+)/$', training_participant_language_feedback, name='training_participant_language_feedback'),
+
+ url(r'^training/(?P\w+)/request/$', training_request, name='training_request'),
+ url(r'^training/(?P\w+)/clone/$', training_clone, name='training_clone'),
+ url(r'^training/(?P\w+)/(?P\d+)/approvel/$', training_approvel, name='training_approvel'),
+ url(r'^training/(?P\w+)/(?P\w+)/$', training_list, name='training_list'),
+ url(r'^training/(?P\w+)/(?P\d+)/edit/$', training_request, name='training_edit'),
+ url(r'^training/(?P\w+)/(?P\d+)/clone/$', training_clone, name='training_clone'),
+ #url(r'^training/training-completion/(?P\d+)/$', training_completion', name="training_completion"),
+ url(r'^training/view/training-completion/(?P\d+)/$', view_training_completion, name="view_training_completion"),
+
+ #url(r'^test/subscribe/(\d+)/(\d+)/$', test_student_subscribe', name='test_student_subscribe'),
+ url(r'^test/(\d+)/participant/$', test_participant, name='test_participant'),
+ url(r'^test/participant/certificate/(\d+)/(\d+)/$', test_participant_ceritificate, name='test_participant_ceritificate'),
+ url(r'^test/participant/certificate/all/(\d+)/$', test_participant_ceritificate_all, name='test_participant_ceritificate_all'),
+ url(r'^test/(\d+)/attendance/$', test_attendance, name='test_attendance'),
+ url(r'^test/(?P\w+)/request/$', test_request, name='test_request'),
+ url(r'^test/(?P\w+)/(?P\d+)/approvel/$', test_approvel, name='test_approvel'),
+ url(r'^test/(?P\w+)/(?P\w+)/$', test_list, name='test_list'),
+ url(r'^test/(?P\w+)/(?P\d+)/edit/$', test_request, name='test_request'),
+ url(r'^test/verify-test-certificate/$', verify_test_certificate, name='verify_test_certificate'),
+
+ url(r'^delete-notification/(\w+)/(\d+)/$', delete_events_notification, name="delete_events_notification"),
+ url(r'^clear-notifications/(\w+)/$', clear_events_notification, name="clear_events_notification"),
+
+ url(r'^resource-center/$', resource_center, name="resource_center"),
+ url(r'^resource-center/(?P[\w-]+)/$', resource_center, name="resource_center"),
+
+ url(r'^academic-center/(?P\d+)/$', academic_center, name="academic_center"),
+ url(r'^academic-center/(?P\d+)/(?P[\w-]+)/$', academic_center, name="academic_center"),
+
+ #Ajax
+ url(r'ajax-ac-state/$', ajax_ac_state, name='ajax_ac_state'),
+ url(r'ajax-ac-location/$', ajax_ac_location, name='ajax_ac_location'),
+ url(r'ajax-ac-pincode/$', ajax_ac_pincode, name='ajax_ac_pincode'),
+ url(r'ajax-district/$', ajax_district_data, name='ajax_district_data'),
+ url(r'ajax-district-collage/$', ajax_district_collage, name='ajax_district_collage'),
+ url(r'ajax-state-collage/$', ajax_state_collage, name='ajax_state_collage'),
+ url(r'ajax-dept-foss/$', ajax_dept_foss, name='ajax_dept_foss'),
+ url(r'ajax-language/$', ajax_language, name='ajax_language'),
+ url(r'ajax_state_details/$', ajax_state_details, name='ajax_state_details'),
+ url(r'ajax-academic-center/$', ajax_academic_center, name='ajax_academic_center'),
+ url(r'ajax-check-foss/$', ajax_check_foss, name='ajax_check_foss'),
+ #url(r'add$', add_contact', name='add_contact'),
+ #url(r'edit/(\d+)$', edit_contact', name='edit_contact'),
+ #url(r'delete/(\d+)$', delete_contact', name='delete_contact'),
+ # EVENTS V2 URLs
+ url(r'^', include('events.urlsv2')),
+ url(r'reset-student-password/$', reset_student_pwd, name='reset_student_pwd'),
+ url(r'^ajax-get-schools/$', get_schools, name='get_schools'),
+ url(r'^ajax-get-batches/$', get_batches, name='get_batches'),
+]
\ No newline at end of file
diff --git a/events/events/urlsv2.py b/events/events/urlsv2.py
new file mode 100644
index 000000000..94586e5d1
--- /dev/null
+++ b/events/events/urlsv2.py
@@ -0,0 +1,370 @@
+# urls.py
+from django.conf.urls import url
+from . import viewsv2
+from events.viewsv2 import *
+from events.decorators import *
+from events.formsv2 import *
+from events.urls import *
+from events.viewsv2 import *
+
+app_name = 'eventsv2'
+urlpatterns = [
+ url(
+ r'^training-planner/',
+ TrainingPlannerListView.as_view(template_name="training_planner.html"),
+ name="training_planner"
+ ),
+ url(
+ r'^select-participants/',
+ TrainingPlannerListView.as_view(template_name="select_participants.html"),
+ name="select_participants"
+ ),
+ url(
+ r'^student-batch/new/$',
+ StudentBatchCreateView.as_view(template_name="new_batch.html", \
+ form_class=StudentBatchForm),
+ name="add_batch"
+ ),
+ url(
+ r'^student-batch/(?P\d+)/new/$',
+ StudentBatchCreateView.as_view(template_name="update_batch.html", \
+ form_class=NewStudentBatchForm),
+ name="add_student"
+ ),
+ url(
+ r'^student-batch/(?P\d+)/$',
+ StudentBatchUpdateView.as_view(template_name="edit_batch.html", \
+ form_class=UpdateStudentBatchForm),
+ name="edit_batch"
+ ),
+ url(
+ r'^student-batch/edit/(?P\d+)/$',
+ StudentBatchYearUpdateView.as_view(template_name="edit_batch_year.html", \
+ form_class=UpdateStudentYearBatchForm),
+ name="edit_year"
+ ),
+ url(
+ r'^student-batch/(?P\d+)/view/$',
+ StudentListView.as_view(template_name="list_student.html"),
+ name="list_student"
+ ),
+ url(
+ r'^student-batch/$',
+ StudentBatchListView.as_view(template_name="student_batch_list.html"),
+ name="batch_list"
+ ),
+ url(
+ r'^(?P\d+)/training-request',
+ TrainingRequestCreateView.as_view(template_name="training_request.html"),
+ name="training_request"
+ ),
+ url(r'^get-language-level-option/$', viewsv2.get_language_level_option, name='get_language_level_option'),
+
+
+ url(
+ r'^(?P\d+)/attendance',
+ TrainingAttendanceListView.as_view(template_name=\
+ "training_attendance.html"),
+ name="training_attendance"
+ ),
+ url(
+ r'^(?P\d+)/certificate',
+ TrainingCertificateListView.as_view(template_name=\
+ "training_certificate.html"),
+ name="training_certificate"
+ ),
+ url(
+ r'^training-request/(?P\d+)/$',
+ TrainingRequestEditView.as_view(template_name=\
+ "edit_training_request.html"),
+ name="edit_training_request"
+ ),
+ url(
+ r'^(?P\d+)/student-delete/(?P\d+)/$',
+ StudentMasterDeleteView.as_view(template_name="student_delete_masterbatch.html", \
+ success_url="/software-training/student-batch"),
+ name="student_delete"
+ ),
+ url(
+ r'^training-certificate/(?P\d+)/organiser/$',
+ OrganiserTrainingCertificateView.as_view(), \
+ name="organiser_training_certificate"
+ ),
+ url(
+ r'^training-certificate/(?P\d+)/student/$',
+ StudentTrainingCertificateView.as_view(), \
+ name="student_training_certificate"
+ ),
+ url(
+ r'^course-map-list/$',
+ CourseMapListView.as_view(template_name="coursemap_list.html"),
+ name="coursemaplist"
+ ),
+ url(
+ r'^course-map/(?P\d+)$',
+ CourseMapUpdateView.as_view(template_name=\
+ "coursemap.html"),
+ name="coursemapupdate"
+ ),
+# url(
+# r'^single-training/pending/$',
+# SingleTrainingNewListView.as_view(template_name="single-training.html"),
+# name="single-training-pending"
+# ),
+# url(
+# r'^single-training/approved/$',
+# SingletrainingApprovedListView.as_view(template_name="single-training.html"),
+# name="single-training-approved"
+# ),
+# url(
+# r'^single-training/rejected/$',
+# SingletrainingRejectedListView.as_view(template_name="single-training.html"),
+# name="single-training-rejected"
+# ),
+# url(
+# r'^single-training/ongoing/$',
+# SingletrainingOngoingListView.as_view(template_name="single-training.html"),
+# name="single-training-ongoing"
+# ),
+# url(
+# r'^single-training/pendingattendance/$',
+# SingletrainingPendingAttendanceListView.as_view(template_name="single-training.html"),
+# name="single-training-pendingattendance"
+# ),
+# url(
+# r'^single-training/completed/$',
+# SingletrainingCompletedListView.as_view(template_name="single-training.html"),
+# name="single-training-completed"
+# ),
+ # url(
+ # r'^single-training/new/$',
+ # SingletrainingCreateView.as_view(template_name="single-training-form.html"),
+ # name="new-single-training"
+ # ),
+ url(
+ r'^single-training/(?P\d+)/edit/$',
+ SingletrainingUpdateView.as_view(template_name="single-training-form.html"),
+ name="update-single-training"
+ ),
+ url(
+ r'^single-training/(?P\w+)/$',
+ SingleTrainingListView.as_view(template_name="single-training.html"),
+ name="single-training-list"
+ ),
+ url(
+ r'^single-training/(?P\d+)/complete/$',
+ SingletrainingMarkCompleteUpdateView.as_view(template_name=""),
+ name="markcomplete-single-training"
+ ),
+ url(
+ r'^single-training/(?P\d+)/certificate',
+ SingleTrainingCertificateListView.as_view(template_name=\
+ "single-training-certificate.html"),
+ name="single-training-certificate"
+ ),
+ url(
+ r'^single-training-certificate/(?P\d+)/organiser/$',
+ OrganiserSingleTrainingCertificateView.as_view(), \
+ name="organiser_singletraining_certificate"
+ ),
+ #ajax
+ url(
+ r'^save-student/',
+ SaveStudentView.as_view()
+ ),
+ # url(
+ # r'^get-course-option/',
+ # GetCourseOptionView.as_view()
+ # ),
+ url(
+ r'^get-batch-option/',
+ GetBatchOptionView.as_view()
+ ),
+ url(
+ r'^get-course-option/',
+ GetCourseOptionView.as_view()
+ ),
+ url(
+ r'^get-batch-course-status/',
+ GetBatchStatusView.as_view()
+ ),
+ url(
+ r'^get-department-organiser-status/',
+ GetDepartmentOrganiserStatusView.as_view()
+ ),
+ # url(
+ # r'^training-request/(?P\w+)/(?P\w+)/$',
+ # TrainingRequestListView.as_view(template_name='training_list.html'),
+ # name='training_list'
+ # ),
+ #url(r'^get-language-option/', GetLanguageOptionView.as_view()),
+ url(
+ r'^single-training/pending/(?P\d+)/approve/$',
+ SingleTrainingApprove,
+ name="single-training-approve"
+ ),
+ url(
+ r'^single-training/pending/(?P\d+)/reject/$',
+ SingleTrainingReject,
+ name="single-training-reject"
+ ),
+ url(
+ r'^single-training/pending/(?P\d+)/requestmarkattendance/$',
+ SingleTrainingPendingAttendance,
+ name="single_training_pending"
+ ),
+ url(
+ r'^markas/(?P\d+)/complete/$',
+ MarkAsComplete,
+ name="mark_as_complete"
+ ),
+ url(
+ r'^mark/(?P\d+)/complete/$',
+ MarkComplete,
+ name="mark_complete"
+ ),
+ url(
+ r'^single-training/(?P\d+)/attendance',
+ SingleTrainingAttendanceListView.as_view(template_name=\
+ "single-training-attendance.html"),
+ name="single_training_attendance"
+ ),
+ url(
+ r'^organiser-feedback/',
+ OrganiserFeedbackCreateView.as_view(template_name='organiser_feedback.html'),
+ name='organiser_feedback'
+ ),
+ url(
+ r'^organiser-feedback-display/$',
+ OrganiserFeedbackListView.as_view(template_name="organiser_feedback_display.html"),
+ name="organiser-feedback-display"
+ ),
+ url(
+ r'^old-training/$',
+ OldTrainingListView.as_view(template_name=\
+ "old_training.html"),
+ name="old_training"
+ ),
+ url(
+ r'^old-training/(?P\d+)/participant/$',
+ OldStudentListView.as_view(template_name="old_list_student.html"),
+ name="old_list_student"
+ ),
+ url(
+ r'^old-training/(?P\d+)/close/$',
+ OldTrainingCloseView.as_view(template_name=""),
+ name="old_training_close"
+ ),
+ url(
+ r'^latex_workshop/$',
+ LatexWorkshopFileUpload,
+ name="latex-workshop"
+ ),
+ url(
+ r'^student-batch/(?P\d+)/view/(?P\d+)$',
+ UpdateStudentName.as_view(template_name="update_student.html"),
+ name="update_student"
+ ),
+ url(
+ r'^stworkshop-feedback/',
+ STWorkshopFeedbackCreateView.as_view(template_name='stworkshop_feedback.html'),
+ name='stworkshop_feedback'
+ ),
+ url(
+ r'^stworkshop-feedback-pre/',
+ STWorkshopFeedbackPreCreateView.as_view(template_name='stworkshop_feedback_pre.html'),
+ name='stworkshop_feedback_pre'
+ ),
+ url(
+ r'^stworkshop-feedback-post/',
+ STWorkshopFeedbackPostCreateView.as_view(template_name='stworkshop_feedback_post.html'),
+ name='stworkshop_feedback_post'
+ ),
+ url(
+ r'^learn-drupal-feedback/',
+ LearnDrupalFeedbackCreateView.as_view(template_name='learndrupalfeedback.html'),
+ name='learndrupalfeedback'
+ ),
+ url(
+ r'^(?P\d+)/oldattendance',
+ TrainingAttendanceListView.as_view(template_name=\
+ "mark_prev_attendance.html"),
+ name="previous_training_attendance"
+ ),
+ url(
+ r'^(?P\d+)/reopen-training/$',
+ ReOpenTraining,
+ name="re-open-training"
+ ),
+ url(
+ r'^payment-home/$',
+ payment_home,
+ name="payment_home"
+ ),
+ url(
+ r'^payment-status/$',
+ payment_status,
+ name="payment_status"
+ ),
+ url(
+ r'^payment-success/$',
+ payment_success,
+ name="payment_success"
+ ),
+ url(
+ r'^payment-details/(?P\w+)/$',
+ payment_details,
+ name="payment_details"
+ ),
+ url(
+ r'^payment-reconciliation-update/$',
+ payment_reconciliation_update,
+ name="payment_reconciliation_update"
+ ),
+
+ url(r'^academic-transactions/$', academic_transactions,name="payment"),
+ url(
+ r'^training-request/(?P\w+)/(?P\w+)/$',
+ trainingrequest,
+ name='training_list'
+ ),
+ url(
+ r'^request/(?P\d+)/certificate/$',
+ RequestCertificate,
+ name="request_certificate"
+ ),
+
+ url(
+ r'^certificate-request/(?P\w+)/(?P\w+)/$',
+ CertificateRequest,
+ name='certificate_request_list'
+ ),
+ url(
+ r'^generate/(?P\d+)/certificate/$',
+ GenerateCertificate,
+ name="generate_certificate"
+ ),
+ url(
+ r'^training-certificate/(?P\d+)/allcertificates/$',
+ AllTrainingCertificateView.as_view(), \
+ name="alltraining_certificate"
+ ),
+ url(
+ r'^student-grade-filter/$',
+ StudentGradeFilter.as_view(),
+ name="student_grade_filter"
+ ),
+ url(
+ r'^academic_payment_details/',
+ AcademicKeyCreateView.as_view(template_name='academic_payment_details_form.html'),
+ name='academic_payment_details'
+ ),
+ url(
+ # r'^software-training/ajax-academic-details/',
+ r'^ajax-academic-details/',
+ FetchAcademicDetailsView.as_view(),
+ name='ajax_academic_details'
+ ),
+
+
+]
diff --git a/events/events/views.py b/events/events/views.py
new file mode 100644
index 000000000..80aaec974
--- /dev/null
+++ b/events/events/views.py
@@ -0,0 +1,3303 @@
+from django.http import JsonResponse
+from .models import StudentBatch
+from django.urls import reverse
+
+def get_batches(request):
+ school_id = request.GET.get('school_id')
+ if school_id:
+ batches = StudentBatch.objects.filter(academic_id=school_id).values('id', 'batch_name')
+ return JsonResponse(list(batches), safe=False)
+ return JsonResponse([])
+
+from django.core.exceptions import PermissionDenied
+
+from django.contrib.auth.decorators import login_required
+from django.contrib.auth.models import Group
+from django.contrib import messages
+
+from django.shortcuts import render, redirect
+from django.template import RequestContext
+from django.http import HttpResponse, HttpResponseRedirect
+from django.shortcuts import get_object_or_404
+
+from django.views.decorators.csrf import csrf_exempt
+
+from django.http import Http404
+from django.db.models import Q
+from django.db import IntegrityError
+
+try:
+ from urllib.parse import urlparse
+except ImportError:
+ from urllib.parse import urlparse
+
+try:
+ from BeautifulSoup import BeautifulSoup
+except ImportError:
+ from bs4 import BeautifulSoup
+
+import xml.etree.cElementTree as etree
+from django.conf import settings
+import json
+import os,time, csv, random, string
+from validate_email import validate_email
+
+import os.path
+
+try:
+ import urllib.request, urllib.error, urllib.parse
+except ImportError:
+ import urllib.request as urllib2
+
+from events.models import *
+from cms.models import Profile
+from mdldjango.forms import OfflineDataForm
+
+from .forms import *
+from django.utils import formats
+from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
+from mdldjango.get_or_create_participant import get_or_create_participant, check_csvfile, update_participants_count, clone_participant
+from mdldjango.helper import get_moodle_user, get_moodle_grade
+from django.template.defaultfilters import slugify
+
+#pdf generate
+from reportlab.pdfgen import canvas
+from reportlab.lib.pagesizes import letter, landscape
+from reportlab.platypus import Paragraph
+from reportlab.lib.styles import ParagraphStyle
+from reportlab.lib.units import cm
+from reportlab.lib.enums import TA_CENTER
+from PyPDF2 import PdfFileWriter, PdfFileReader
+from django.template.context_processors import csrf
+
+from io import StringIO, BytesIO
+
+
+#randon string
+import string
+import random
+
+from .filters import *
+from cms.views import create_profile
+from cms.sortable import *
+from .events_email import send_email
+import datetime
+from django.http import JsonResponse
+from django.contrib.auth.hashers import make_password
+
+from mdldjango.get_or_create_participant import encript_password
+from .helpers import send_bulk_student_reset_mail
+from .certificates import *
+
+def can_clone_training(training):
+ if training.tdate > datetime.datetime.strptime('01-02-2015', "%d-%m-%Y").date() and training.organiser.academic.institution_type.name != 'School':
+ return True
+ return False
+
+def _get_training_participant(training):
+ #if training.organiser.academic.institution_type.name == "School":
+ # if training.status == 4:
+ # return SchoolTrainingAttendance.objects.filter(training = training, status__gte=1)
+ # return SchoolTrainingAttendance.objects.filter(training = training)
+ #else:
+ participants = None
+ if training.status == 4:
+ participants = TrainingAttendance.objects.filter(training = training, status__gte=1)
+ else:
+ participants = TrainingAttendance.objects.filter(training = training)
+ return participants
+
+def _mark_training_attendance(training, participant_id):
+ #if training.organiser.academic.institution_type.name == "School":
+ # ta = SchoolTrainingAttendance.objects.get(id = participant_id, training = training)
+ # ta.status = 1
+ # ta.save()
+ #else:
+ try:
+ ta = TrainingAttendance.objects.get(id = participant_id, training = training)
+ ta.status = 1
+ ta.save()
+ except:
+ ta = TrainingAttendance()
+ ta.training = training
+ ta.mdluser_id = participant_id
+ ta.status = 1
+ ta.save()
+
+def _mark_all_training_participants_to_zero(training):
+ #if training.organiser.academic.institution_type.name == "School":
+ # SchoolTrainingAttendance.objects.filter(training = training).update(status = 0)
+ #else:
+ TrainingAttendance.objects.filter(training = training).update(status = 0)
+
+@login_required
+def init_events_app(request):
+ try:
+ # Group
+ if Group.objects.filter(name = 'Resource Person').count() == 0:
+ Group.objects.create(name = 'Resource Person')
+ if Group.objects.filter(name = 'Organiser').count() == 0:
+ Group.objects.create(name = 'Organiser')
+ if Group.objects.filter(name = 'Invigilator').count() == 0:
+ Group.objects.create(name = 'Invigilator')
+
+ #testcategory
+ try:
+ TestCategory.objects.get_or_create(name= 'Workshop')
+ TestCategory.objects.get_or_create(name= 'Training')
+ TestCategory.objects.get_or_create(name= 'Others')
+ except Exception as e:
+ print((e, "test_category"))
+
+ try:
+ InstituteType.objects.get_or_create(name= 'Workshop')
+ InstituteType.objects.get_or_create(name= 'Training')
+ InstituteType.objects.get_or_create(name= 'ITI')
+ InstituteType.objects.get_or_create(name= 'Vocational')
+ InstituteType.objects.get_or_create(name= 'School')
+ InstituteType.objects.get_or_create(name= 'Uncategorised')
+ except Exception as e:
+ print((e, "institute_type"))
+
+ #institutecategory
+ try:
+ InstituteCategory.objects.get_or_create(name= 'Govt')
+ InstituteCategory.objects.get_or_create(name= 'Private')
+ InstituteCategory.objects.get_or_create(name= 'NGO')
+ InstituteCategory.objects.get_or_create(name= 'Uncategorised')
+ except Exception as e:
+ print((e, "InstituteCategory"))
+
+ #permissiontype
+ try:
+ PermissionType.objects.get_or_create(name= 'State')
+ PermissionType.objects.get_or_create(name= 'District')
+ PermissionType.objects.get_or_create(name= 'University')
+ PermissionType.objects.get_or_create(name= 'Institution Type')
+ PermissionType.objects.get_or_create(name= 'Institution')
+ except Exception as e:
+ print((e, "PermissionType"))
+
+ #state
+ state = None
+ try:
+ state = State.objects.get_or_create(name= 'Uncategorised')
+ except Exception as e:
+ print((e, "State"))
+ #District
+ try:
+ District.objects.get_or_create(name= 'Uncategorised', state_id = state[0].id)
+ except Exception as e:
+ print((e, "District"))
+
+ #City
+ try:
+ City.objects.get_or_create(name= 'Uncategorised', state_id = state[0].id)
+ except Exception as e:
+ print((e, "City"))
+
+ #University
+ try:
+ University.objects.get_or_create(name= 'Uncategorised', state_id = state[0].id, user_id = 1)
+ except Exception as e:
+ print((e, "University"))
+
+ messages.success(request, 'Events application initialised successfully!')
+ except Exception as e:
+ messages.error(request, str(e))
+ return HttpResponseRedirect('/software-training/')
+
+def id_generator(size=6, chars=string.ascii_uppercase + string.digits):
+ return ''.join(random.choice(chars) for _ in range(size))
+
+def is_event_manager(user):
+ """Check if the user is having event manger rights"""
+ if user.groups.filter(name='Event Manager').count() == 1:
+ return True
+
+def is_resource_person(user):
+ """Check if the user is having resource person rights"""
+ if user.groups.filter(name='Resource Person').count() == 1:
+ return True
+
+def is_accountexecutive(user):
+ """Check if the user is having accountexecutive rights"""
+ try:
+ if user.groups.filter(name='Account Executive').count() == 1 and user.accountexecutive.status == 1:
+ return True
+ except:
+ pass
+
+def is_organiser_deactivated(user):
+ try:
+ if user.organiser and user.organiser.status == 3:
+ return True
+ except:
+ pass
+
+def is_invigilator_deactivated(user):
+ try:
+ if user.invigilator and user.invigilator.status == 3:
+ return True
+ except:
+ pass
+
+def is_organiser(user):
+ """Check if the user is having organiser rights"""
+ try:
+ if user.groups.filter(name='Organiser').count() == 1 and user.organiser and user.organiser.status == 1:
+ return True
+ except:
+ pass
+
+def is_administrator(user):
+ """Check if the user is having resource person rights"""
+ if user.groups.filter(name='Administrator').count() == 1:
+ return True
+
+def is_invigilator(user):
+ """Check if the user is having invigilator rights"""
+ if user.groups.filter(name='Invigilator').count() == 1 and user.invigilator and user.invigilator.status == 1:
+ return True
+
+def is_school_training_manager(user):
+ return user.groups.filter(name="School Training Manager").exists()
+
+def get_page(resource, page, limit=20):
+ paginator = Paginator(resource, limit)
+ if page is None:
+ page = 1
+ try:
+ resource = paginator.page(page)
+ except PageNotAnInteger:
+ resource = paginator.page(1)
+ except EmptyPage:
+ resource = paginator.page(paginator.num_pages)
+ return resource
+
+
+def search_participant(form):
+ if form.is_valid():
+ onlinetest_user = {}
+ if form.cleaned_data['email']:
+ onlinetest_user = MdlUser.objects.filter(email = form.cleaned_data['email'])
+ #else:
+ # onlinetest_user = MdlUser.objects.filter(Q(username__icontains = form.cleaned_data['username']) | Q(firstname__icontains = form.cleaned_data['username']))
+ if not onlinetest_user:
+ onlinetest_user = 'None'
+ return onlinetest_user
+
+def add_participant(request, cid, category ):
+ userid = request.POST['userid']
+ if userid:
+ if category == 'Training':
+ try:
+ wa = TrainingAttendance.objects.get(mdluser_id = userid, training_id = cid)
+ print((wa.id, " => Exits"))
+ messages.success(request, "User has already in the attendance list")
+ except:
+ mdluser = MdlUser.objects.get(pk=userid)
+ wa = TrainingAttendance()
+ wa.training_id = cid
+ wa.mdluser_id = mdluser.id
+ wa.firstname = mdluser.firstname
+ wa.lastname = mdluser.lastname
+ wa.email = mdluser.email
+ # wa.gender = mdluser.gender
+ wa.status = 0
+ wa.save()
+ messages.success(request, "User has added in the attendance list")
+ print((wa.id, " => Inserted"))
+ elif category == 'Training':
+ try:
+ wa = TrainingAttendance.objects.get(mdluser_id = userid, training_id = cid)
+ print((wa.id, " => Exits"))
+ messages.success(request, "User has already in the attendance list")
+ except:
+ wa = TrainingAttendance()
+ wa.training_id = cid
+ wa.mdluser_id = userid
+ wa.status = 0
+ wa.save()
+ messages.success(request, "User has added in the attendance list")
+ print((wa.id, " => Inserted"))
+
+ elif category == 'Test':
+ try:
+ wa = TestAttendance.objects.get(mdluser_id = userid, test_id = cid)
+ print((wa.id, " => Exits"))
+ messages.success(request, "User has already in the attendance list")
+ except:
+ wa = TestAttendance()
+ wa.test_id = cid
+ wa.mdluser_id = userid
+ wa.status = 0
+ wa.save()
+ messages.success(request, "User has added in the attendance list")
+ print((wa.id, " => Inserted"))
+
+def fix_date_for_first_training(request):
+ organisers = Organiser.objects.exclude(id__in = Training.objects.values_list('organiser_id').distinct(), status=1).filter(Q(created__startswith=datetime.date.today() - datetime.timedelta(days=15)) | Q(created__startswith=datetime.date.today() - datetime.timedelta(days=30)))
+ if organisers:
+ status = 'Fix a date for your first training'
+ for o in organisers:
+ try:
+ to = [o.user.email]
+ send_email(status, to)
+ except:
+ pass
+ return HttpResponse("Done!")
+
+#def training_gentle_reminder(request):
+# tomorrow_training = Training.objects.filter(training_type__gt=0, status__lte=2, tdate=datetime.date.today() + datetime.timedelta(days=1))
+# if tomorrow_training:
+# for t in tomorrow_training:
+# status = 'How to upload the attendance on the Workshop day'
+# try:
+# to = [t.organiser.user.email]
+# #if t.training_type == 0:
+# # status = 'How to upload the attendance on the Training day'
+# send_email(status, to, t)
+# except:
+# pass
+# return HttpResponse("Done!")
+
+#def reminder_mail_to_close_training(request):
+# predated_ongoing_workshop = Training.objects.filter(Q(status = 2) | Q(status = 3), training_type__gte = 0, tdate__lt = datetime.date.today() - datetime.timedelta(days = 1))
+# if predated_ongoing_workshop:
+# status = "Reminder mail to close Training"
+# for w in predated_ongoing_workshop:
+# try:
+# to = [w.organiser.user.email]
+# send_email(status, to, w)
+# except:
+# pass
+# return HttpResponse("Done!")
+
+#def training_completion_reminder(request):
+# training_need_to_complete = Training.objects.filter(training_type = 0, status__lte = 3, tdate__lte=datetime.date.today() - datetime.timedelta(days=30))
+# if training_need_to_complete:
+# status = 'How to upload the attendance on the Training day'
+# for t in training_need_to_complete:
+# try:
+# to = [t.organiser.user.email]
+# send_email(status, to, t)
+# except:
+# pass
+# return HttpResponse("Done!")
+
+# only for workshop, pilot, live workshop
+def close_predated_ongoing_workshop(request):
+ predated_ongoing_workshop = Training.objects.filter(status = 3, training_type__gte = 0, tdate__lt = datetime.date.today() - datetime.timedelta(days = 2))
+ if predated_ongoing_workshop:
+ for w in predated_ongoing_workshop:
+ try:
+ present = TrainingAttendance.objects.filter(training = w, status__gte = 1).count()
+ absentees = TrainingAttendance.objects.filter(training = w, status = 0).count()
+ if not present and not absentees:
+ continue
+ if present:
+ final_count = present
+ else:
+ final_count = absentees
+ TrainingAttendance.objects.filter(training = w, status = 0).update(status = 1)
+
+ w.participant_count = final_count
+ w.status = 4
+ w.trusted = 0
+ w.save()
+ except:
+ pass
+ return HttpResponse("Done!")
+
+# Mark as complelete when invigilator forgot to close the Test
+def close_predated_ongoing_test(request):
+ predated_ongoing_test = Test.objects.filter(status = 3, tdate__lt = datetime.date.today())
+ if predated_ongoing_test:
+ for t in predated_ongoing_test:
+ try:
+ present = TestAttendance.objects.filter(test = t, status__gt = 1).count()
+ # absentees = TestAttendance.objects.filter(test = t, status = 0).count()
+ if present:
+ TestAttendance.objects.filter(test_id=t.id, status = 2).update(status = 3)
+ t.participant_count = present
+ t.status = 4
+ t.save()
+ except:
+ pass
+ return HttpResponse("Done!")
+
+def get_academic_code(state):
+ # find the academic code available number
+ try:
+ ac = AcademicCenter.objects.filter(state = state).order_by('-academic_code')[:1].get()
+ except:
+ #print "This is first record"
+ ac = None
+ academic_code = 1
+
+ if ac:
+ code_range = int(ac.academic_code.split('-')[1])
+ available_code_range = []
+ for i in range(code_range):
+ available_code_range.insert(i, i+1)
+
+ #find the existing numbers
+ ac = AcademicCenter.objects.filter(state = state).order_by('-academic_code')
+ for record in ac:
+ a = int(record.academic_code.split('-')[1])-1
+ available_code_range[a] = 0
+ academic_code = code_range + 1
+ #finding Missing number
+ for code in available_code_range:
+ if code != 0:
+ academic_code = code
+ break
+
+ # Generate academic code
+ if academic_code < 10:
+ ac_code = '0000'+str(academic_code)
+ elif academic_code <= 99:
+ ac_code = '000'+str(academic_code)
+ elif academic_code <= 999:
+ ac_code = '00'+str(academic_code)
+ elif academic_code <= 9999:
+ ac_code = '0'+str(academic_code)
+
+ #get state code
+ state_code = State.objects.get(pk = state.id).code
+ return state_code +'-'+ ac_code
+
+@login_required
+def old_training_attendance(request):
+ user = request.user
+ context = {}
+ if not (user.is_authenticated() and (is_event_manager(user) or is_resource_person(user))):
+ raise PermissionDenied()
+ collectionSet = Training.objects.exclude(id__in=TrainingAttendance.objects.all().values_list('training_id').distinct()).filter(status=4, academic__in = AcademicCenter.objects.filter(state__in = State.objects.filter(resourceperson__user_id=user, resourceperson__status=1)))
+ if not collectionSet:
+ raise PermissionDenied()
+ header = {
+ 1: SortableHeader('#', False),
+ 2: SortableHeader('training_type', True, 'Training Type'),
+ 3: SortableHeader('academic__state', True, 'State'),
+ 4: SortableHeader('academic__academic_code', True, 'Academic Code'),
+ 5: SortableHeader('academic', True, 'Institution'),
+ 6: SortableHeader('foss', True, 'FOSS'),
+ 7: SortableHeader('organiser__user', True, 'Organiser'),
+ 8: SortableHeader('tdate', True, 'Date'),
+ 9: SortableHeader('Participants', False),
+ 10: SortableHeader('Action', False)
+ }
+
+ raw_get_data = request.GET.get('o', None)
+ collection = get_sorted_list(request, collectionSet, header, raw_get_data)
+ ordering = get_field_index(raw_get_data)
+ collection = TrainingFilter(request.GET, user = user, queryset=collection)
+ context['form'] = collection.form
+
+ page = request.GET.get('page')
+ collection = get_page(collection, page)
+
+ context['collection'] = collection
+ context['header'] = header
+ context['ordering'] = ordering
+ context.update(csrf(request))
+ return render(request, 'events/templates/training/old-index.html', context)
+
+def old_training_attendance_upload(request, wid):
+ user = request.user
+ form = OfflineDataForm()
+ enable_form = True
+ try:
+ training = Training.objects.get(pk=wid, status=4)
+ if TrainingAttendance.objects.filter(training=training).count():
+ messages.info(request, "You have already submited the training attendance!")
+ return HttpResponseRedirect('/software-training/training/old-training-attendance/')
+ except Exception as e:
+ raise PermissionDenied('You are not allowed to view this page!')
+ if request.method == 'POST':
+ form = OfflineDataForm(request.POST, request.FILES)
+ if form.is_valid():
+ file_path = settings.MEDIA_ROOT + 'training/' + str(wid) + str(time.time())
+ f = request.FILES['xml_file']
+ fout = open(file_path, 'wb+')
+ for chunk in f.chunks():
+ fout.write(chunk)
+ fout.close()
+ error_line_no = ''
+ csv_file_error = 0
+ csv_file_error, error_line_no = check_csvfile(user, file_path, training, 3)
+ if not csv_file_error:
+ csv_file_error, error_line_no = check_csvfile(user, file_path, training, 1)
+ os.unlink(file_path)
+ #update participant count
+ #update_participants_count(training)
+ if error_line_no:
+ messages.error(request, error_line_no)
+ else:
+ enable_form = False
+ messages.info(request, "Thank you for submitting attendance!. Now you can download the certificate.")
+ #return HttpResponseRedirect('/software-training/training/old-training-attendance/')
+ context = {
+ 'form': form,
+ 'enable_form' : enable_form
+ }
+ if enable_form:
+ messages.info(request, """
+ Please upload the CSV file which you have generated.
+ To know more Click here .
+ Note: Participant list should not be exced {0}
+ """.format(training.participant_count))
+ context.update(csrf(request))
+ return render(request, 'events/templates/training/old-attendance.html', context)
+
+@login_required
+def events_dashboard(request):
+ user = request.user
+ user_roles = user.groups.all()
+ roles = []
+ events_roles = ['Resource Person', 'Organiser', 'Invigilator']
+ for role in user_roles:
+ if role.name in events_roles:
+ roles.append(role.name)
+
+ # print roles
+
+ organiser_workshop_notification = None
+ organiser_test_notification = None
+ invigilator_test_notification = None
+ organiser_training_notification = None
+ rp_workshop_notification = None
+ rp_test_notification = None
+ rp_training_notification = None
+ institute_name = None
+
+ if is_organiser(user):
+ institution_type = AcademicCenter.objects.get(id=user.organiser.academic_id)
+ institute_name = InstituteType.objects.get(id=institution_type.institution_type_id)
+ organiser_test_notification = EventsNotification.objects.filter((Q(status = 1) | Q(status = 2)), category = 1, academic_id = user.organiser.academic_id, categoryid__in = user.organiser.academic.test_set.filter(organiser_id = user.id).values_list('id')).order_by('-created')[:30]
+
+ organiser_test_notification = \
+ EventsNotification.objects.filter(Q(status=1)
+ | Q(status=2), category=1,
+ academic_id=user.organiser.academic_id,
+ categoryid__in=user.organiser.academic.test_set.filter(organiser_id=user.id).values_list('id'
+ )).order_by('-created')[:30]
+
+ # organiser_training_notification = EventsNotification.objects.filter((Q(status = 1) | Q(status = 3)), category = 2, status = 1, academic_id = user.organiser.academic_id, categoryid__in = user.organiser.academic.workshop_set.filter(organiser_id = user.id).values_list('id')).order_by('-created')[:30]
+
+ if is_resource_person(user):
+ rp_workshop_notification = \
+ EventsNotification.objects.filter(Q(status=0) | Q(status=5)
+ | Q(status=2), category=0).order_by('-created')[:30]
+ rp_training_notification = \
+ EventsNotification.objects.filter(Q(status=0) | Q(status=5)
+ | Q(status=2), category=2).order_by('-created')[:30]
+ rp_test_notification = \
+ EventsNotification.objects.filter(Q(status=0) | Q(status=4)
+ | Q(status=5) | Q(status=8) | Q(status=9), category=1,
+ categoryid__in=Training.objects.filter(academic__in=AcademicCenter.objects.filter(state__in=State.objects.filter(resourceperson__user_id=user,
+ resourceperson__status=1))).values_list('id'
+ )).order_by('-created')[:30]
+ if is_invigilator(user):
+ invigilator_test_notification = \
+ EventsNotification.objects.filter(Q(status=0)
+ | Q(status=1), category=1,
+ academic_id=user.invigilator.academic_id,
+ categoryid__in=user.invigilator.academic.test_set.filter(invigilator_id=user.id).values_list('id'
+ )).order_by('-created')[:30]
+
+ context = {
+ 'roles': roles,
+ 'institution_type': institute_name,
+ 'organiser_workshop_notification': organiser_workshop_notification,
+ 'organiser_test_notification': organiser_test_notification,
+ 'organiser_training_notification': organiser_training_notification,
+ 'rp_test_notification': rp_test_notification,
+ 'rp_workshop_notification': rp_workshop_notification,
+ 'rp_training_notification': rp_training_notification,
+ 'invigilator_test_notification': invigilator_test_notification,
+ }
+ return render(request, 'events/templates/events_dashboard.html',
+ context)
+
+@login_required
+def delete_events_notification(request, notif_type, notif_id):
+ notif_rec = None
+ try:
+ if notif_type == "organiser":
+ notif_rec = EventsNotification.objects.select_related().get(pk = notif_id)
+ elif notif_type == "invigilator":
+ notif_rec = EventsNotification.objects.select_related().get(pk = notif_id)
+ elif notif_type == "rp":
+ notif_rec = EventsNotification.objects.select_related().get(pk = notif_id)
+ except Exception as e:
+ print(e)
+ messages.warning(request, 'Selected notification is already deleted (or) You do not have permission to delete it.')
+ if notif_rec:
+ notif_rec.delete()
+ return HttpResponseRedirect(request.META['HTTP_REFERER'])
+
+@login_required
+def clear_events_notification(request, notif_type):
+ notif_rec = None
+ try:
+ if notif_type == "organiser":
+ notif_rec = EventsNotification.objects.filter(user = request.user).delete()
+ elif notif_type == "invigilator":
+ notif_rec = EventsNotification.objects.filter(user = request.user).delete()
+ elif notif_type == "rp":
+ notif_rec = EventsNotification.objects.filter(user = request.user).delete()
+ except Exception as e:
+ print(e)
+ messages.warning(request, 'Something went wrong, contact site administrator.')
+
+ return HttpResponseRedirect(request.META['HTTP_REFERER'])
+
+@login_required
+def new_ac(request):
+ """ Create new academic center. Academic code generate by autimatic.
+ if any code missing in between first assign that code then continue the serial
+ """
+ user = request.user
+ if not (user.is_authenticated() and (is_event_manager(user) or is_resource_person(user))):
+ raise PermissionDenied()
+
+ if request.method == 'POST':
+ form = AcademicForm(user, request.POST)
+ if form.is_valid():
+ form_data = form.save(commit=False)
+ form_data.user_id = user.id
+
+ state = form.cleaned_data['state']
+ academic_code = get_academic_code(state)
+
+ form_data.academic_code = academic_code
+ ic = InstituteCategory.objects.get(name = 'Uncategorised')
+ form_data.institute_category = ic
+ form_data.save()
+ messages.success(request, form_data.institution_name+" has been added")
+ return HttpResponseRedirect("/software-training/ac/")
+
+ context = {'form':form}
+ return render(request, 'events/templates/ac/form.html', context)
+ else:
+ context = {}
+ context.update(csrf(request))
+ context['form'] = AcademicForm(user=request.user)
+ return render(request, 'events/templates/ac/form.html', context)
+
+@login_required
+def edit_ac(request, rid = None):
+ """ Edit academic center """
+ user = request.user
+ if not (user.is_authenticated() and (is_event_manager(user) or is_resource_person(user))):
+ raise PermissionDenied()
+
+ if request.method == 'POST':
+ academic = AcademicCenter.objects.get(id = rid)
+ form = AcademicForm(request.user, request.POST, instance=academic)
+ if form.is_valid():
+ #change academic_code if state change
+ form_state = form.cleaned_data['state']
+ if academic.state_id != form_state:
+ form_data = form.save(commit=False)
+ form_data.academic_code = get_academic_code(form_state)
+ if form.save():
+ return HttpResponseRedirect("/software-training/ac/")
+ context = {'form':form}
+ return render(request, 'events/templates/ac/form.html', context)
+ else:
+ try:
+ record = AcademicCenter.objects.get(id = rid)
+ context = {}
+ context['form'] = AcademicForm(user=request.user, instance = record)
+ context['edit'] = rid
+ context.update(csrf(request))
+ return render(request, 'events/templates/ac/form.html', context)
+ except:
+ raise PermissionDenied()
+
+@login_required
+def ac(request):
+ """ Academic index page """
+ user = request.user
+ if not (user.is_authenticated() and (is_event_manager(user) or is_resource_person(user))):
+ raise PermissionDenied()
+
+ context = {}
+ header = {
+ 1: SortableHeader('#', False),
+ 2: SortableHeader('State', False),
+ 3: SortableHeader('academic_code', True, 'Academic Code'),
+ 4: SortableHeader('institution_name', True, 'Institution Name'),
+ 5: SortableHeader('university__name', True, 'University'),
+ 6: SortableHeader('institution_type__name', True, 'Institute Type'),
+ 7: SortableHeader('academickey__expiry_date', True, 'Subscription Status'),
+ 8: SortableHeader('Action', False)
+ }
+
+ collectionSet = AcademicCenter.objects.filter(state__in = user.resource_person.filter(resourceperson__status=1))
+ raw_get_data = request.GET.get('o', None)
+ collection = get_sorted_list(request, collectionSet, header, raw_get_data)
+ ordering = get_field_index(raw_get_data)
+
+ collection = AcademicCenterFilter(request.GET, user = user, queryset=collection)
+ context['form'] = collection.form
+
+ page = request.GET.get('page')
+ collection = get_page(collection.qs, page)
+
+ context['collection'] = collection
+ context['header'] = header
+ context['ordering'] = ordering
+
+ context.update(csrf(request))
+ return render(request, 'events/templates/ac/index.html', context)
+ return HttpResponse('RP')
+
+def has_profile_data(request, user):
+ ''' check weather user profile having blank data or not '''
+ if user:
+ profile = Profile.objects.filter(user=user).first()
+ if not profile:
+ return HttpResponseRedirect("/accounts/profile/"+user.username+"/")
+
+ for field in profile._meta.get_all_field_names():
+ if not getattr(profile, field, None):
+ return HttpResponseRedirect("/accounts/profile/"+user.username+"/")
+
+
+@login_required
+def accountexecutive_request(request, username):
+ """ request to bacome a new accountexecutive """
+ user = request.user
+ if not user.is_authenticated():
+ raise PermissionDenied()
+
+ if username == request.user.username:
+ user = User.objects.get(username=username)
+
+
+
+ if request.method == 'POST':
+ form = AccountexecutiveForm(request.POST)
+ if form.is_valid():
+ user.groups.add(Group.objects.get(name='Account Executive'))
+ accountexecutive = Accountexecutive()
+ accountexecutive.user_id=request.user.id
+ accountexecutive.academic_id=request.POST['college']
+ try:
+ accountexecutive.save()
+ except:
+ accountexecutive = Accountexecutive.objects.get(user = user)
+ accountexecutive.academic_id=request.POST['college']
+ accountexecutive.save()
+ messages.success(request, "Thank you. Your request has been sent for Training Manager's approval. You will get the approval with in 24 hours. Once the request is approved, you can proceed with the payment. ")
+ return HttpResponseRedirect("/software-training/accountexecutive/view/"+user.username+"/")
+ messages.error(request, "Please fill the following details")
+ context = {'form':form}
+ return render(request, 'events/templates/accountexecutive/form.html', context)
+
+ else:
+ try:
+ accountexecutive = Accountexecutive.objects.get(user=user)
+
+ if accountexecutive.status == 1:
+ messages.error(request, "You are already an accountexecutive ")
+ return HttpResponseRedirect("/software-training/accountexecutive/view/"+user.username+"/")
+ else:
+ messages.info(request, "Your Account Executive request is yet to be approved. Please contact the Resource person of your State. For more details Click Here ")
+ print("Accountexecutive not yet approve ")
+ return HttpResponseRedirect("/software-training/accountexecutive/view/"+user.username+"/")
+ except:
+ messages.info(request, "Please fill the following details")
+ context = {}
+ context.update(csrf(request))
+ context['form'] = AccountexecutiveForm()
+ return render(request, 'events/templates/accountexecutive/form.html', context)
+
+ else:
+ raise PermissionDenied()
+
+@login_required
+def accountexecutive_view(request, username):
+ """ view accountexecutive details """
+ user = request.user
+ if not (user.is_authenticated() and (username == request.user.username or is_event_manager(user) or is_resource_person(user))):
+ raise PermissionDenied()
+
+ context = {}
+ try:
+ user = User.objects.get(username=username)
+ accountexecutive = Accountexecutive.objects.get(user=user)
+ context['record'] = accountexecutive
+ context['profile'] = accountexecutive.user.profile_set.get(user= user)
+ except Exception as e:
+ print(e)
+ raise PermissionDenied()
+ return render(request, 'events/templates/accountexecutive/view.html', context)
+
+#@login_required
+def accountexecutive_edit(request, username):
+ """ view accountexecutive details """
+ #todo: confirm event_manager and resource_center can edit accountexecutive details
+ user = request.user
+ if not (user.is_authenticated() and (username == request.user.username or is_event_manager(user) or is_resource_person(user))):
+ raise PermissionDenied()
+
+ user = User.objects.get(username=username)
+ if request.method == 'POST':
+ form = AccountexecutiveForm(request.POST)
+ if form.is_valid():
+ accountexecutive = Accountexecutive.objects.get(user=user)
+ #accountexecutive.user_id=request.user.id
+ accountexecutive.academic_id=request.POST['college']
+ accountexecutive.save()
+ messages.success(request, "Details has been updated")
+ return HttpResponseRedirect("/software-training/accountexecutive/view/"+user.username+"/")
+ context = {'form':form}
+ return render(request, 'events/templates/accountexecutive/form.html', context)
+ else:
+ #todo : if any training and test under this accountexecutive disable the edit
+ record = Accountexecutive.objects.get(user=user)
+ context = {}
+ context['form'] = AccountexecutiveForm(instance = record)
+ context.update(csrf(request))
+ return render(request, 'events/templates/accountexecutive/form.html', context)
+
+
+@login_required
+def organiser_request(request, username):
+ """ request to bacome a new organiser """
+ user = request.user
+ if not user.is_authenticated():
+ raise PermissionDenied()
+
+ if username == request.user.username:
+ user = User.objects.get(username=username)
+ if request.method == 'POST':
+ form = OrganiserForm(request.POST)
+ if form.is_valid():
+ user.groups.add(Group.objects.get(name='Organiser'))
+ organiser = Organiser()
+ organiser.user_id=request.user.id
+ organiser.academic_id=request.POST['college']
+ try:
+ organiser.save()
+ except:
+ organiser = Organiser.objects.get(user = user)
+ organiser.academic_id=request.POST['college']
+ organiser.save()
+ messages.success(request, "Thank you. Your request has been sent for Training Manager's approval. You will get the approval with in 24 hours. Once the request is approved, you can request for the Training. For more details Click Here ")
+ return HttpResponseRedirect("/software-training/organiser/view/"+user.username+"/")
+ messages.error(request, "Please fill the following details")
+ context = {'form':form}
+ return render(request, 'events/templates/organiser/form.html', context)
+ else:
+ try:
+ organiser = Organiser.objects.get(user=user)
+ if not is_organiser(organiser):
+ messages.info(request, "Please fill the following details")
+ context = {}
+ context.update(csrf(request))
+ context['form'] = OrganiserForm()
+ return render(request, 'events/templates/organiser/form.html', context)
+ if organiser.status:
+ messages.error(request, "You are already an Organiser ")
+ return HttpResponseRedirect("/software-training/organiser/view/"+user.username+"/")
+ else:
+ messages.info(request, "Your Organiser request is yet to be approved. Please contact the Resource person of your State. For more details Click Here ")
+ print("Organiser not yet approve ")
+ return HttpResponseRedirect("/software-training/organiser/view/"+user.username+"/")
+ except:
+ pass
+
+ messages.info(request, "Please fill the following details")
+ context = {}
+ context.update(csrf(request))
+ context['form'] = OrganiserForm()
+ return render(request, 'events/templates/organiser/form.html', context)
+ else:
+ raise PermissionDenied()
+
+@login_required
+def organiser_view(request, username):
+ """ view organiser details """
+ user = request.user
+ if not (user.is_authenticated() and (username == request.user.username or is_event_manager(user) or is_resource_person(user))):
+ raise PermissionDenied()
+
+ context = {}
+ try:
+ user = User.objects.get(username=username)
+ organiser = Organiser.objects.get(user=user)
+ context['record'] = organiser
+ context['profile'] = organiser.user.profile_set.get(user= user)
+ except Exception as e:
+ print(e)
+ raise PermissionDenied()
+ return render(request, 'events/templates/organiser/view.html', context)
+
+#@login_required
+def organiser_edit(request, username):
+ """ view organiser details """
+ #todo: confirm event_manager and resource_center can edit organiser details
+ user = request.user
+ if not (user.is_authenticated() and (username == request.user.username or is_event_manager(user) or is_resource_person(user))):
+ raise PermissionDenied()
+
+ user = User.objects.get(username=username)
+ if request.method == 'POST':
+ form = OrganiserForm(request.POST)
+ if form.is_valid():
+ organiser = Organiser.objects.get(user=user)
+ #organiser.user_id=request.user.id
+ organiser.academic_id=request.POST['college']
+ organiser.save()
+ messages.success(request, "Details has been updated")
+ return HttpResponseRedirect("/software-training/organiser/view/"+user.username+"/")
+ context = {'form':form}
+ return render(request, 'events/templates/organiser/form.html', context)
+ else:
+ #todo : if any training and test under this organiser disable the edit
+ record = Organiser.objects.get(user=user)
+ context = {}
+ context['form'] = OrganiserForm(instance = record)
+ context.update(csrf(request))
+ return render(request, 'events/templates/organiser/form.html', context)
+
+@login_required
+def rp_organiser(request, status, code, userid):
+ """ Resource person: active organiser """
+ user = request.user
+ organiser_in_rp_state = Organiser.objects.filter(user_id=userid, academic__in=AcademicCenter.objects.filter(state__in=State.objects.filter(resourceperson__user_id=user, resourceperson__status=1)))
+ if not (user.is_authenticated() and organiser_in_rp_state and ( is_event_manager(user) or is_resource_person(user) or (status == 'active' or status == 'block'))):
+ raise PermissionDenied('You are not allowed to view this page ')
+
+ try:
+ if User.objects.get(pk=userid).profile_set.get().confirmation_code == code:
+ organiser = Organiser.objects.get(user_id = userid)
+ organiser.appoved_by_id = request.user.id
+ message = "activated"
+ organiser.status = 1
+ if status == 'block':
+ organiser.status = 2
+ message = "blocked"
+ organiser.save()
+ messages.success(request, "The Organiser account has been "+message)
+ return HttpResponseRedirect('/software-training/organiser/inactive/')
+ else:
+ raise PermissionDenied()
+ except:
+ raise PermissionDenied('You are not allowed to view this page')
+
+@login_required
+def invigilator_request(request, username):
+ """ Request to bacome a invigilator """
+ user = request.user
+ if not user.is_authenticated():
+ raise PermissionDenied()
+
+ if username == user.username:
+ user = User.objects.get(username=username)
+ if request.method == 'POST':
+ form = InvigilatorForm(request.POST)
+ if form.is_valid():
+ user.groups.add(Group.objects.get(name='Invigilator'))
+ invigilator = Invigilator()
+ invigilator.user_id=request.user.id
+ invigilator.academic_id=request.POST['college']
+ try:
+ invigilator.save()
+ except:
+ invigilator = Invigilator.objects.get(user = user)
+ invigilator.academic_id=request.POST['college']
+ invigilator.save()
+
+ messages.success(request, "Thank you. Your request has been sent for Training Manager's approval. You will get the approval with in 24 hours. Once the request is approved, you can request for the workshop. For more details Click Here")
+ return HttpResponseRedirect("/software-training/invigilator/view/"+user.username+"/")
+ messages.error(request, "Please fill the following details")
+ context = {'form':form}
+ return render(request, 'events/templates/invigilator/form.html', context)
+ else:
+ try:
+ invigilator = Invigilator.objects.get(user=user)
+ #todo: send status message
+ if not is_invigilator(invigilator):
+ messages.info(request, "Please fill the following details")
+ context = {}
+ context.update(csrf(request))
+ context['form'] = InvigilatorForm()
+ return render(request, 'events/templates/invigilator/form.html', context)
+
+ if invigilator.status:
+ messages.success(request, "You have already invigilator role ")
+ return HttpResponseRedirect("/software-training/invigilator/view/"+user.username+"/")
+ else:
+ messages.info(request, "Your Invigilator request is yet to be approved. Please contact the Resource person of your State. For more details Click Here ")
+ return HttpResponseRedirect("/software-training/invigilator/view/"+user.username+"/")
+ except:
+ messages.info(request, "Please fill the following details")
+ context = {}
+ context.update(csrf(request))
+ context['form'] = InvigilatorForm()
+ return render(request, 'events/templates/invigilator/form.html', context)
+ else:
+ raise PermissionDenied()
+
+@login_required
+def invigilator_view(request, username):
+ """ Invigilator view page """
+ user = request.user
+ if not (user.is_authenticated() and (username == request.user.username or is_event_manager(user) or is_resource_person(user))):
+ raise PermissionDenied()
+
+ context = {}
+ try:
+ user = User.objects.get(username=username)
+ invigilator = Invigilator.objects.get(user=user)
+ context['record'] = invigilator
+ context['profile'] = invigilator.user.profile_set.get(user= user)
+ except Exception as e:
+ print(e)
+ raise PermissionDenied()
+ return render(request, 'events/templates/invigilator/view.html', context)
+
+@login_required
+def invigilator_edit(request, username):
+ """ Invigilator edit page """
+ user = request.user
+ if not (user.is_authenticated() and (username == request.user.username or is_event_manager(user) or is_resource_person(user))):
+ raise PermissionDenied()
+
+ user = User.objects.get(username=username)
+ if request.method == 'POST':
+ form = InvigilatorForm(request.POST)
+ if form.is_valid():
+ invigilator = Invigilator.objects.get(user=user)
+ invigilator.academic_id=request.POST['college']
+ invigilator.save()
+ messages.success(request, "Details has been updated")
+ return HttpResponseRedirect("/software-training/invigilator/view/"+user.username+"/")
+ context = {'form':form}
+ return render(request, 'events/templates/invigilator/form.html', context)
+ else:
+ #todo : if any training and test under this invigilator disable the edit
+ record = Invigilator.objects.get(user=user)
+ context = {}
+ context['form'] = InvigilatorForm(instance = record)
+ context.update(csrf(request))
+ return render(request, 'events/templates/invigilator/form.html', context)
+
+@login_required
+def rp_invigilator(request, status, code, userid):
+ """ Resource person: active invigilator """
+ user = request.user
+ invigilator_in_rp_state = Invigilator.objects.filter(user_id=userid, academic__in=AcademicCenter.objects.filter(state__in=State.objects.filter(resourceperson__user_id=user, resourceperson__status=1)))
+ if not (user.is_authenticated() and invigilator_in_rp_state and ( is_event_manager(user) or is_resource_person(user) or (status == 'active' or status == 'block'))):
+ raise PermissionDenied('You are not allowed to view this page')
+
+ try:
+ if User.objects.get(pk=userid).profile_set.get().confirmation_code == code:
+ invigilator = Invigilator.objects.get(user_id = userid)
+ invigilator.appoved_by_id = request.user.id
+ invigilator.status = 1
+ message = "accepted"
+ if status == 'block':
+ invigilator.status = 2
+ message = "blocked"
+ invigilator.save()
+ messages.success(request, "Invigilator has "+message)
+ return HttpResponseRedirect('/software-training/invigilator/inactive/')
+ else:
+ raise PermissionDenied()
+ except:
+ raise PermissionDenied('You are not allowed to view this page')
+
+@login_required
+def rp_accountexecutive(request, status, code, userid):
+ """ Resource person: active accountexecutive """
+ user = request.user
+ accountexecutive_in_rp_state = Accountexecutive.objects.filter(user_id=userid, academic__in=AcademicCenter.objects.filter(state__in=State.objects.filter(resourceperson__user_id=user, resourceperson__status=1)))
+ if not (user.is_authenticated() and accountexecutive_in_rp_state and ( is_event_manager(user) or is_resource_person(user) or (status == 'active' or status == 'block'))):
+ raise PermissionDenied('You are not allowed to view this page')
+
+ try:
+ if User.objects.get(pk=userid).profile_set.get().confirmation_code == code:
+ accountexecutive = Accountexecutive.objects.get(user_id = userid)
+ accountexecutive.appoved_by_id = request.user.id
+ accountexecutive.status = 1
+ message = "accepted"
+ if status == 'block':
+ accountexecutive.status = 2
+ message = "blocked"
+ accountexecutive.save()
+ messages.success(request, "Accountexecutive has "+message)
+ return HttpResponseRedirect('/software-training/accountexecutive/inactive/')
+ else:
+ raise PermissionDenied()
+ except:
+ raise PermissionDenied('You are not allowed to view this page')
+
+
+@login_required
+def training_request(request, role, rid = None):
+ ''' Training request by organiser '''
+ user = request.user
+ context = {}
+ if not (user.is_authenticated() and ( is_organiser(user) or is_resource_person(user) or is_event_manager(user))):
+ raise PermissionDenied()
+ form = None
+ if request.method == 'POST':
+ if rid:
+ form = TrainingForm(request.POST, request.FILES, instance = Training.objects.get(pk = rid), user = request.user)
+ else:
+ form = TrainingForm(request.POST, request.FILES, user = request.user)
+ if form.is_valid():
+ #existing_training = Training.objects.filter(organiser = request.user.organiser, academic = request.user.organiser.academic, foss = request.POST['foss'], tdate = request.POST['tdate'])
+ #if existing_training:
+ # messages.error(request, "You have already scheduled "+ str(request.POST['tdate']) + " training on "+ str(master_training.tdate) + " . Please select some other date.")
+ # break
+ ####
+ csv_file_error = 0
+ error_line_no = ''
+ wid = 1
+ f = None
+ file_path = settings.MEDIA_ROOT +'training/' + str(wid) + str(time.time())
+ if 'xml_file' in request.FILES:
+ f = request.FILES['xml_file']
+
+ if f:
+ fout = open(file_path, 'wb+')
+ for chunk in f.chunks():
+ fout.write(chunk)
+ fout.close()
+
+ #validate file
+ csv_file_error, error_line_no = check_csvfile(user, file_path, form_data = request.POST)
+ #return
+ ####
+ if not csv_file_error:
+ dateTime = request.POST['tdate'].split(' ')
+ w = Training()
+ if rid:
+ w = Training.objects.get(pk = rid)
+ else:
+ w.organiser_id = user.organiser.id
+ w.academic = user.organiser.academic
+ w.course_id = request.POST['course']
+ if request.POST['no_of_lab_session'] == '1':
+ w.training_type = 1
+ else:
+ w.training_type = request.POST['training_type']
+ w.language_id = request.POST['language']
+ w.foss_id = request.POST['foss']
+ w.tdate = dateTime[0]
+ w.ttime = '00:00'
+ w.skype = request.POST['skype']
+
+ error = 0
+ try:
+ w.save()
+ except IntegrityError:
+ error = 1
+ prev_training = Training.objects.filter(organiser = w.organiser_id, academic = w.academic, foss = w.foss_id, tdate = w.tdate, ttime = w.ttime)
+ if prev_training:
+ messages.error(request, "You have already scheduled "+ w.foss.foss + " training on "+w.tdate + " "+ w.ttime + " . Please select some other time.")
+ except:
+ messages.error(request, "Sorry, Something went wrong. try again!")
+ error = 1
+
+ if not error:
+ w.training_code = "WC-"+str(w.id)
+ w.department.clear()
+ for dept in form.cleaned_data.get('department'):
+ w.department.add(dept)
+ #if request.POST['training_type'] == '1':
+ if rid and w.extra_fields:
+ w.extra_fields.paper_name = request.POST['course_number']
+ w.extra_fields.no_of_lab_session = request.POST['no_of_lab_session']
+ w.extra_fields.save()
+ elif not rid and not w.extra_fields:
+ tef = TrainingExtraFields.objects.create(paper_name = request.POST['course_number'], no_of_lab_session = request.POST['no_of_lab_session'])
+ w.extra_fields_id = tef.id
+ elif rid and not w.extra_fields:
+ tef = TrainingExtraFields.objects.create(paper_name = request.POST['course_number'], no_of_lab_session = request.POST['no_of_lab_session'])
+ w.extra_fields_id = tef.id
+ else:
+ pass
+ #else:
+ # if w.extra_fields:
+ # eid = w.extra_fields_id
+ # w.extra_fields_id = None
+ # w.save()
+ # TrainingExtraFields.objects.filter(pk=eid).delete()
+ w.status = 1
+ w.save()
+ #####
+ #get or create participants list
+ if f:
+ csv_file_error, error_line_no = check_csvfile(user, file_path, w, flag=1)
+ os.unlink(file_path)
+
+ #file the participant count
+ w.participant_count = TrainingAttendance.objects.filter(training = w, status__gte = 1).count()
+ w.save()
+ #####
+ '''messages.success(request, """
+
+
+ Before the Training/Workshop date upload the Participants name
+ list. It is necessary for approving your Training/Workshop request.
+
+
+ Please click on Upload Participant Data and upload the
+ CSV (.csv) file which you have generated (using LibreOffice
+ Calc / MS Excel) and click Submit .
+
+
+ For more details on how to create the .csv file.
+ Please Click here
+
+
+ """)'''
+ #update logs
+ message = None
+ if rid:
+ if w.training_type == 0:
+ message = w.academic.institution_name+" has updated training request for "+w.foss.foss+" on dated "+w.tdate
+ else:
+ message = w.academic.institution_name+" has updated a Workshop request for "+w.foss.foss+" on dated "+w.tdate
+ else:
+ if w.training_type == 0:
+ message = w.academic.institution_name+" has made a training request for "+w.foss.foss+" on dated "+w.tdate
+ else:
+ message = w.academic.institution_name+" has made a Workshop request for "+w.foss.foss+" on dated "+w.tdate
+
+ update_events_log(user_id = user.id, role = 0, category = 0, category_id = w.id, academic = w.academic_id, status = 0)
+ update_events_notification(user_id = user.id, role = 0, category = 0, category_id = w.id, academic = w.academic_id, status = 0, message = message)
+
+ if role == 'organiser' and not rid:
+ return HttpResponseRedirect("/software-training/training/" + str(w.id) + "/attendance/?clone=1")
+ return HttpResponseRedirect("/software-training/training/" + role + "/pending/")
+ else:
+ os.unlink(file_path)
+ messages.error(request, error_line_no)
+ messages.error(request, "Please fill the following details ")
+ context = {'form' : form, 'role' : role, 'status' : 'request'}
+ return render(request, 'events/templates/training/form.html', context)
+ else:
+ messages.info(request, """
+
+ TO HAVE YOUR TRAINING REQUEST APPROVED IT IS NECESSARY TO UPLOAD THE LIST OF PARTICIPANTS Click Here
+ PLEASE ENSURE THAT YOU FILL IN ONLY THE GENUINE EMAIL ID'S OF THE PARTICIPANTS / STUDENTS. IF THEY DON'T HAVE ANY, PLEASE HELP THEM CREATE ONE.
+ Select a Timing in the Training Request where the chosen FOSS is relevant/useful/matching to the Course/Paper.
+ One can also select FOSS which might not be relevant/matching to any Course/Paper.
+ Please download a copy of tutorials on all the machines. For instructions to download tutorials Click Here
+ Please check if your machine is ready. For the Machine Readiness document Click Here .
+
+ """)
+ if rid and not form:
+ form = TrainingForm(instance = Training.objects.get(pk = rid), user = request.user)
+
+ if not form:
+ form = TrainingForm(user = request.user)
+
+ context['form'] = form
+ context['role'] = role
+ context.update(csrf(request))
+ return render(request, 'events/templates/training/form.html', context)
+
+def copy_participant(training, participants):
+ for p in participants:
+ ta = TrainingAttendance()
+ ta.training_id = training.id
+ ta.mdluser_id = p.mdluser_id
+ ta.status = 1
+ ta.firstname = p.firstname
+ ta.lastname = p.lastname
+ ta.gender = p.gender
+ ta.email = p.email
+ ta.save()
+
+@login_required
+def training_clone(request, role, rid = None):
+ ''' Training request by organiser '''
+ user = request.user
+ context = {}
+ participant = None
+ csv_file_error = 0
+ if not (user.is_authenticated() and ( is_organiser(user) or is_resource_person(user) or is_event_manager(user))):
+ raise PermissionDenied()
+
+ if not rid and request.method=="POST" and 'clone-training' in request.POST:
+ return HttpResponseRedirect('/software-training/training/organiser/'+str(request.POST['clone-training'])+'/clone/')
+ master_training = None
+ try:
+ master_training = Training.objects.get(pk=rid)
+ if not can_clone_training(master_training):
+ raise PermissionDenied()
+ except:
+ raise PermissionDenied()
+
+ form = TrainingReUseForm()
+ if rid and request.method=="POST":
+ form = TrainingReUseForm(request.POST, user = request.user)
+ if form.is_valid():
+ csv_file_error, error_line_no, reattempt_list, more_then_two_per_day_list = clone_participant(master_training, request.POST)
+ if csv_file_error:
+ messages.error(request, error_line_no)
+ existing_training = Training.objects.filter(organiser = request.user.organiser, academic = request.user.organiser.academic, foss = request.POST['foss'], tdate = request.POST['tdate'])
+ if existing_training:
+ csv_file_error = 1
+ messages.error(request, "You have already scheduled "+ str(request.POST['tdate']) + " training on "+ str(master_training.tdate) + " . Please select some other date.")
+
+
+ if not csv_file_error:# and request.POST.get('remove-error'):
+ existing_emails = None
+ if reattempt_list and more_then_two_per_day_list:
+ existing_emails = set(reattempt_list.split(',')).union(set(more_then_two_per_day_list.split(',')))
+ elif reattempt_list:
+ existing_emails = reattempt_list.split(',')
+ else:
+ existing_emails = more_then_two_per_day_list.split(',')
+ participants = master_training.trainingattendance_set.exclude(email__in=existing_emails)
+ if participants:
+ training = master_training
+ training.id = None
+ training.status = 1
+ training.appoved_by_id = None
+ training.foss = form.cleaned_data['foss']
+ training.language = form.cleaned_data['language']
+ training.tdate = form.cleaned_data['tdate']
+ training.extra_fields.id = None
+ training.extra_fields.save()
+ training.extra_fields_id = training.extra_fields.id
+ training.save()
+ training.training_code = "WC-" + str(training.id)
+ training.save()
+ copy_participant(training, participants)
+ messages.success(request, "Training has been created! ")
+ return HttpResponseRedirect("/software-training/training/" + str(training.id) + "/attendance/?clone=1")
+ messages.error(request, "Participants are empty!")
+ context['form'] = form
+ context['role'] = role
+ context['participant'] = participant
+ context['error'] = csv_file_error
+ context['rid'] = rid
+ context.update(csrf(request))
+ return render(request, 'events/templates/training/request-reuse.html', context)
+
+@login_required
+def training_list(request, role, status):
+ """ Organiser index page """
+ user = request.user
+ if not (user.is_authenticated() and ( is_organiser(user) or is_resource_person(user) or is_event_manager(user))):
+ raise PermissionDenied()
+
+ status_dict = {'pending': 0, 'approved' : 2, 'completed' : 4, 'rejected' : 5, 'reschedule' : 2, 'ongoing': 2, 'predated' : ''}
+ if status in status_dict:
+ context = {}
+ collectionSet = None
+ if is_event_manager(user) and role == 'em':
+ collectionSet = Training.objects.filter(academic__in = AcademicCenter.objects.filter(state__in = State.objects.filter(resourceperson__user_id=user, resourceperson__status=1)), status = status_dict[status])
+ elif is_resource_person(user) and role == 'rp':
+ if status == 'approved':
+ collectionSet = Training.objects.filter(academic__in = AcademicCenter.objects.filter(state__in = State.objects.filter(resourceperson__user_id=user, resourceperson__status=1)), status = status_dict[status], tdate__gt=datetime.date.today()).order_by('-tdate')
+ elif status == 'predated':
+ collectionSet = Training.objects.filter((Q(status = 0) | Q(status = 1) | Q(status = 2) | Q(status = 3)), academic__in = AcademicCenter.objects.filter(state__in = State.objects.filter(resourceperson__user_id=user, resourceperson__status=1)), tdate__lt=datetime.date.today()).order_by('-tdate')
+ elif status =='ongoing':
+ collectionSet = Training.objects.filter((Q(status = 2) | Q(status = 3)), academic__in = AcademicCenter.objects.filter(state__in = State.objects.filter(resourceperson__user_id=user, resourceperson__status=1)), tdate__lte=datetime.date.today()).order_by('-tdate')
+ elif status =='pending':
+ collectionSet = Training.objects.filter((Q(status = 0) | Q(status = 1)), academic__in = AcademicCenter.objects.filter(state__in = State.objects.filter(resourceperson__user_id=user, resourceperson__status=1)), tdate__gte = datetime.date.today()).order_by('-tdate')
+
+ else:
+ collectionSet = Training.objects.filter(academic__in = AcademicCenter.objects.filter(state__in = State.objects.filter(resourceperson__user_id=user, resourceperson__status=1)), status = status_dict[status]).order_by('-tdate')
+ elif is_organiser(user) and role == 'organiser':
+ if status == 'approved':
+ collectionSet = Training.objects.filter(organiser__user = user, status = status_dict[status], tdate__gt=datetime.date.today()).order_by('-tdate')
+ elif status == 'predated':
+ collectionSet = Training.objects.filter((Q(status = 0) | Q(status = 1) | Q(status = 2) | Q(status = 3)), organiser__user = user, tdate__lt=datetime.date.today()).order_by('-tdate')
+ elif status == 'ongoing':
+ collectionSet = Training.objects.filter((Q(status = 2) | Q(status = 3)), organiser__user = user, tdate__lte=datetime.date.today()).order_by('-tdate')
+ elif status == 'pending':
+ collectionSet = Training.objects.filter((Q(status = 0) | Q(status = 1)), organiser__user = user, tdate__gte=datetime.date.today()).order_by('-tdate')
+ #print collectionSet
+ else:
+ collectionSet = Training.objects.filter(organiser__user = user, status = status_dict[status]).order_by('-tdate')
+
+ if collectionSet == None:
+ raise PermissionDenied()
+
+ header = {
+ 1: SortableHeader('#', False),
+ 2: SortableHeader('training_type', True, 'Training Type'),
+ 3: SortableHeader('academic__state__name', True, 'State'),
+ 4: SortableHeader('academic__academic_code', True, 'Academic Code'),
+ 5: SortableHeader('academic__institution_name', True, 'Institution'),
+ 6: SortableHeader('foss__foss', True, 'FOSS'),
+ 7: SortableHeader('organiser__user__first_name', True, 'Organiser'),
+ 8: SortableHeader('tdate', True, 'Date'),
+ 9: SortableHeader('participant_count', True, 'Participants'),
+ 10: SortableHeader('Action', False)
+ }
+
+ raw_get_data = request.GET.get('o', None)
+ collection = get_sorted_list(request, collectionSet, header, raw_get_data)
+ ordering = get_field_index(raw_get_data)
+
+ collection = TrainingFilter(request.GET, user = user, queryset=collection)
+ context['form'] = collection.form
+
+ page = request.GET.get('page')
+ collection = get_page(collection.qs, page)
+
+ context['collection'] = collection
+ context['header'] = header
+ context['ordering'] = ordering
+ context['status'] = status
+ context['status_code'] = status_dict[status]
+ context['role'] = role
+ context.update(csrf(request))
+ return render(request, 'events/templates/training/index.html', context)
+ else:
+ raise PermissionDenied()
+
+@login_required
+@csrf_exempt
+def training_approvel(request, role, rid):
+ """ Resource person: confirm or reject training """
+ user = request.user
+ if not (user.is_authenticated() and (is_resource_person(user) or (is_organiser(user) and request.GET['status'] == 'completed'))):
+ raise PermissionDenied()
+ try:
+ w = Training.objects.get(pk=rid)
+ if request.GET['status'] == 'accept':
+ w.status = 2
+ w.appoved_by_id = user.id
+ if request.GET['status'] == 'reject':
+ w.status = 5
+ w.appoved_by_id = user.id
+ if request.GET['status'] == 'completed':
+ if w.tdate <= datetime.date.today():
+ update_participants_count(w)
+ w.status = 4
+ else:
+ raise PermissionDenied()
+ except Exception as e:
+ print(e)
+ raise PermissionDenied()
+ #todo: add training code
+ if w.status == 2:
+ w.training_code = "WC-"+str(w.id)
+ send_email('Instructions to be followed before conducting the training', [w.organiser.user.email], w)
+ w.save()
+ #send email
+ if w.status == 4:
+ status = 'Future activities after conducting the Training'
+ to = [w.organiser.user.email]
+ send_email(status, to, w)
+ message = w.academic.institution_name +" has completed "+w.foss.foss+" training dated "+w.tdate.strftime("%Y-%m-%d")
+ if request.GET['status'] == 'accept':
+ #delete admin notification
+ try:
+ EventsNotification.objects.get(academic_id = w.academic_id, categoryid = w.id, status = 0).delete()
+ except Exception as e:
+ print(e)
+ message = "Training Manager has approved your "+w.foss.foss+" training request dated "+w.tdate.strftime("%Y-%m-%d")
+ if request.GET['status'] == 'reject':
+ message = "Training Manager has rejected your "+w.foss.foss+" training request dated "+w.tdate.strftime("%Y-%m-%d")
+ #update logs
+ update_events_log(user_id = user.id, role = 2, category = 0, category_id = w.id, academic = w.academic_id, status = w.status)
+ update_events_notification(user_id = user.id, role = 2, category = 0, category_id = w.id, academic = w.academic_id, status = w.status, message = message)
+ if w.status == 4:
+ messages.success(request, "Training has been completed. For downloading the learner's certificate click on View Participants ")
+ return HttpResponseRedirect('/software-training/training/'+role+'/completed/')
+ elif w.status == 5:
+ messages.success(request, "Training has been rejected ")
+ return HttpResponseRedirect('/software-training/training/'+role+'/rejected/')
+ elif w.status == 2:
+ messages.success(request, "Training has been approved ")
+ return HttpResponseRedirect('/software-training/training/'+role+'/approved/')
+ return HttpResponseRedirect('/software-training/training/'+role+'/approved/')
+
+@login_required
+def training_permission(request):
+ user = request.user
+ if not (user.is_authenticated() and (is_resource_person(user) or is_event_manager(user))):
+ raise PermissionDenied()
+
+ permissions = Permission.objects.select_related().all()
+ form = TrainingPermissionForm()
+ if request.method == 'POST':
+ form = TrainingPermissionForm(request.POST)
+ if form.is_valid():
+ wp = Permission()
+ wp.permissiontype_id = form.cleaned_data['permissiontype']
+ wp.user_id = form.cleaned_data['user']
+ wp.state_id = form.cleaned_data['state']
+ wp.assigned_by_id = user.id
+ if form.cleaned_data['district']:
+ wp.district_id = form.cleaned_data['district']
+ if form.cleaned_data['institute']:
+ wp.institute_id = form.cleaned_data['institute']
+ elif form.cleaned_data['institutiontype']:
+ wp.institute_type_id = form.cleaned_data['institutiontype']
+ elif form.cleaned_data['university']:
+ wp.university_id = form.cleaned_data['university']
+ wp.save()
+ return HttpResponseRedirect("/software-training/training/permission/")
+
+ context = {}
+ context.update(csrf(request))
+ context['form'] = form
+ context['collection'] = permissions
+ return render(request, 'events/templates/accessrole/workshop_permission.html', context)
+
+@login_required
+def training_completion(request, rid):
+ user = request.user
+ if not (user.is_authenticated() and is_organiser(user)):
+ raise PermissionDenied()
+
+ context = {}
+ form = TrainingCompletionForm(user = user)
+ if request.method == 'POST':
+ form = TrainingCompletionForm(request.POST, user = user)
+ if form.is_valid():
+ t = Training.objects.get(pk = rid)
+ t.extra_fields.approximate_hour = form.cleaned_data['approximate_hour']
+ t.extra_fields.online_test = form.cleaned_data['online_test']
+ t.extra_fields.is_tutorial_useful = int(form.cleaned_data['is_tutorial_useful'])
+ t.extra_fields.future_training = int(form.cleaned_data['future_training'])
+ t.extra_fields.recommend_to_others = int(form.cleaned_data['recommend_to_others'])
+ t.extra_fields.save()
+
+ t.participant_count = t.trainingattendance_set.filter(status__gte = 1).count()
+ t.status = 4
+ t.save()
+ messages.success(request, "Training has been completed. Close the window and download the learner's certificate.")
+ form = None
+ context['form'] = form
+ context.update(csrf(request))
+ return render(request, 'events/templates/training/training_approvel_form.html', context)
+
+@login_required
+def view_training_completion(request, rid):
+ user = request.user
+ context = {}
+ if not (user.is_authenticated() and is_resource_person(user)):
+ raise PermissionDenied()
+ try:
+ context['training'] = Training.objects.get(pk = rid)
+ except Exception as e:
+ raise PermissionDenied()
+ return render(request, 'events/templates/training/view_training_completion.html', context)
+
+@login_required
+def accessrole(request):
+ user = request.user
+ state = list(AcademicCenter.objects.filter(state__in = Permission.objects.filter(user=user, permissiontype_id=1).values_list('state_id')).values_list('id'))
+ district = list(AcademicCenter.objects.filter(district__in = Permission.objects.filter(user=user, permissiontype_id=2, district_id__gt=0).values_list('district_id')).values_list('id'))
+ university = list(AcademicCenter.objects.filter(university__in = Permission.objects.filter(user=user, permissiontype_id=3, university_id__gt=0).values_list('university_id')).values_list('id'))
+ institution_type = list(AcademicCenter.objects.filter(institution_type__in = Permission.objects.filter(user=user, permissiontype_id=4, institute_type_id__gt=0).values_list('institute_type_id')). values_list('id'))
+ institute = list(AcademicCenter.objects.filter(id__in = Permission.objects.filter(user=user, permissiontype_id=5, institute_id__gt=0).values_list('institute_id')).values_list('id'))
+ all_academic_ids = list(set(state) | set(district) | set(university) | set(institution_type) | set(institute))
+ workshops = Training.objects.filter(academic__in = all_academic_ids)
+ context = {'collection':workshops}
+ return render(request, 'events/templates/accessrole/workshop_accessrole.html', context)
+
+@login_required
+def training_attendance(request, wid):
+ user = request.user
+ onlinetest_user = ''
+ psform = ParticipantSearchForm()
+ sform = TrainingScanCopyForm()
+ if not (user.is_authenticated() and (is_organiser(user))):
+ raise PermissionDenied()
+ try:
+ training = Training.objects.get(pk = wid)
+ if training.status == 4:
+ return HttpResponseRedirect("/software-training/training/" + str(training.id) + "/participant/")
+ except Exception as e:
+ print(e)
+ raise PermissionDenied()
+ #todo check request user and training organiser same or not
+ show_success_message = False
+ if request.method == 'POST':
+ if 'submit-mark-attendance' in request.POST:
+ users = request.POST
+ if users:
+ #set all record to 0 if status = 1
+ _mark_all_training_participants_to_zero(training)
+ training.status = 3
+ training.save()
+ for u in users:
+ if not (u =='submit-mark-attendance' or u == 'csrfmiddlewaretoken'):
+ _mark_training_attendance(training, users[u])
+ #update participant
+ #update_participants_count(training)
+
+ message = training.academic.institution_name+" has submited training attendance"
+ update_events_log(user_id = user.id, role = 2, category = 0, category_id = training.id, academic = training.academic_id, status = 6)
+ update_events_notification(user_id = user.id, role = 2, category = 0, category_id = training.id, academic = training.academic_id, status = 6, message = message)
+
+ messages.success(request, """
+
+ Thank you for uploading the Attendance. Now make sure that you cross check and verify the details before submiting.
+
+ """
+ )
+ show_success_message = True
+ if 'search-participant' in request.POST:
+ psform = ParticipantSearchForm(request.POST)
+ onlinetest_user = search_participant(psform)
+
+ if 'add-participant' in request.POST:
+ add_participant(request, wid, 'Training')
+
+ if 'submit-attendance' in request.POST:
+ training.status = 1
+ training.save()
+
+ if 'submit-scaned-copy' in request.POST:
+ form = TrainingScanCopyForm(request.POST, request.FILES)
+ file_type = ['application/pdf']
+ if 'scan_copy' in request.FILES:
+ if request.FILES['scan_copy'].content_type in file_type:
+ file_path = settings.MEDIA_ROOT + 'training/'
+ try:
+ os.mkdir(file_path)
+ except Exception as e:
+ print(e)
+ file_path = settings.MEDIA_ROOT + 'training/'+wid+'/'
+ try:
+ os.mkdir(file_path)
+ except Exception as e:
+ print(e)
+ full_path = file_path + wid +".pdf"
+ fout = open(full_path, 'wb+')
+ f = request.FILES['scan_copy']
+ # Iterate through the chunks.
+ for chunk in f.chunks():
+ fout.write(chunk)
+ fout.close()
+ messages.success(request, "Waiting for Training Manager approval.")
+ else:
+ messages.success(request, "Choose a PDF File")
+ else:
+ messages.success(request, "Choose a PDF File.")
+
+ wp = _get_training_participant(training)
+
+ if not show_success_message:
+ messages.success(request, """
+
+
+ Before the Training/Workshop date upload the Participants name
+ list. It is necessary for approving your Training/Workshop request.
+
+
+ Please click on Upload Participant Data and upload the
+ CSV (.csv) file which you have generated (using LibreOffice
+ Calc / MS Excel) and click Submit .
+
+
+ For more details on how to create the .csv file.
+ Please Click here
+
+
+ """)
+
+ context = {}
+ context['psform'] = psform
+ context['sform'] = sform
+ context['collection'] = wp
+ context['onlinetest_user'] = onlinetest_user
+ context['training'] = training
+ context['file_path'] = '/media/training/'+wid+'/'+wid+'.pdf'
+ context['clone'] = request.GET.get('clone', None)
+ context.update(csrf(request))
+ return render(request, 'events/templates/training/attendance.html', context)
+
+
+def training_participant(request, wid=None):
+ user = request.user
+ training = None
+ if user.is_authenticated():
+ if not ((is_resource_person(user) or is_event_manager(user) or is_organiser(user))):
+ raise PermissionDenied()
+ can_download_certificate = 0
+ if wid:
+ try:
+ training = Training.objects.get(id=wid)
+ except:
+ raise PermissionDenied()
+ wp = _get_training_participant(training)
+ if (is_resource_person(user) or is_event_manager(user) or user == training.organiser.user) and training.status == 4:
+ can_download_certificate = 1
+ context = {
+ 'collection' : wp,
+ 'wc' : training,
+ 'can_download_certificate':can_download_certificate,
+ 'file_path' : '/media/training/'+wid+'/'+wid+'.pdf',
+ }
+ return render(request, 'events/templates/training/participant.html', context)
+
+
+def suffix(d):
+ return 'th' if 11<=d<=13 else {1:'st',2:'nd',3:'rd'}.get(d%10, 'th')
+
+def custom_strftime(format, t):
+ return t.strftime(format)
+
+
+def training_participant_ceritificate(request, wid, participant_id):
+ #response = HttpResponse(content_type='application/pdf')
+ #response['Content-Disposition'] = 'attachment; filename="somefilename.pdf"'
+
+ # Create the PDF object, using the response object as its "file."
+ #p = canvas.Canvas(response)
+
+ # Draw things on the PDF. Here's where the PDF generation happens.
+ # See the ReportLab documentation for the full list of functionality.
+ #p.drawString(200, 500, "Hello world.")
+
+ # Close the PDF object cleanly, and we're done.
+ #p.showPage()
+ #p.save()
+ #return response
+ # Using ReportLab to insert image into PDF
+
+ #store Certificate details
+
+ certificate_pass = ''
+ if wid and participant_id:
+ try:
+ w = Training.objects.get(id = wid)
+ # check if user can get certificate
+ wa = TrainingAttendance.objects.get(training_id = w.id, id = participant_id)
+ #if wa.status < 1:
+ # raise PermissionDenied()
+ if wa.password:
+ certificate_pass = wa.password
+ wa.count += 1
+ wa.status = 3
+ wa.save()
+ else:
+ certificate_pass = str(wa.id)+id_generator(10-len(str(wa.id)))
+ wa.password = certificate_pass
+ wa.status = 3
+ wa.count += 1
+ wa.save()
+ except Exception as e:
+ print(e)
+ raise PermissionDenied()
+
+ response = HttpResponse(content_type='application/pdf')
+ filename = (wa.firstname+'-'+w.foss.foss+"-Participant-Certificate").replace(" ", "-");
+
+ response['Content-Disposition'] = 'attachment; filename='+filename+'.pdf'
+ imgTemp = BytesIO()
+ imgDoc = canvas.Canvas(imgTemp)
+
+ # Title
+ imgDoc.setFont('Helvetica', 40, leading=None)
+ imgDoc.drawCentredString(415, 480, "Certificate of Appreciation")
+
+ #date
+ imgDoc.setFont('Helvetica', 18, leading=None)
+ imgDoc.drawCentredString(211, 115, "29 August 2015")
+
+ #password
+ imgDoc.setFillColorRGB(211, 211, 211)
+ imgDoc.setFont('Helvetica', 10, leading=None)
+ imgDoc.drawString(10, 6, certificate_pass)
+ #imgDoc.drawString(100, 100, 'transparent')
+
+
+ # Draw image on Canvas and save PDF in buffer
+ imgPath = settings.MEDIA_ROOT +"sign.jpg"
+ imgDoc.drawImage(imgPath, 600, 100, 150, 76) ## at (399,760) with size 160x160
+
+ #paragraphe
+ text = "This is to certify that "+wa.firstname +" "+wa.lastname+" participated in the "+w.foss.foss+" workshop organized at "+w.academic.institution_name+" by Spoken Tutorial Project on 29 August 2015 A comprehensive set of topics pertaining to "+w.foss.foss+" were covered in the workshop. The Spoken Tutorial Project, IIT Bombay, funded by National Mission on Education through ICT, MHRD, Govt. of India."
+
+ centered = ParagraphStyle(name = 'centered',
+ fontSize = 16,
+ leading = 30,
+ alignment = 0,
+ spaceAfter = 20)
+
+ p = Paragraph(text, centered)
+ p.wrap(650, 200)
+ p.drawOn(imgDoc, 4.2 * cm, 7 * cm)
+
+ imgDoc.save()
+
+ # Use PyPDF to merge the image-PDF into the template
+ page = PdfFileReader(file(settings.MEDIA_ROOT +"Blank-Certificate.pdf","rb")).getPage(0)
+ overlay = PdfFileReader(StringIO(imgTemp.getvalue())).getPage(0)
+ page.mergePage(overlay)
+
+ #Save the result
+ output = PdfFileWriter()
+ output.addPage(page)
+
+ #stream to browser
+ outputStream = response
+ output.write(response)
+ outputStream.close()
+
+ return response
+
+@login_required
+def test_request(request, role, rid = None):
+ ''' Test request by organiser '''
+ user = request.user
+ if not (user.is_authenticated() and ( is_organiser(user) or is_resource_person(user) or is_event_manager(user))):
+ raise PermissionDenied()
+ context = {}
+ form = TestForm(user = user)
+ if rid:
+ t = Test.objects.get(pk = rid)
+ user = t.organiser.user
+ form = TestForm(user = user, instance = t)
+ context['instance'] = t
+ if request.method == 'POST':
+ form = TestForm(request.POST, user = user)
+ if form.is_valid():
+ dateTime = request.POST['tdate'].split(' ')
+ t = Test()
+ if rid:
+ t = Test.objects.get(pk = rid)
+ else:
+ print("New Test.............")
+ t.organiser_id = user.organiser.id
+ t.academic = user.organiser.academic
+ t.test_category_id = request.POST['test_category']
+
+ """if int(request.POST['test_category']) == 1:
+ t.training_id = request.POST['workshop']"""
+ if int(request.POST['test_category']) == 2:
+ t.training_id = request.POST['training']
+ if int(request.POST['test_category']) == 3:
+ t.training_id = None
+ test_trainings = request.POST['training']
+ test_training_dept = t.training.department_id
+ if request.POST['id_foss']:
+ test_foss = request.POST['id_foss']
+ else:
+ test_foss = t.training.course.foss_id
+
+ t.invigilator_id = request.POST['invigilator']
+ t.foss_id = test_foss
+ t.tdate = dateTime[0]
+ t.ttime = dateTime[1]
+ error = 0
+ errmsg = ""
+ try:
+ t.save()
+ except IntegrityError:
+ error = 1
+ errmsg = "Test already created"
+ prev_test = Test.objects.filter(organiser = t.organiser_id, academic = t.academic, foss = t.foss_id, tdate = t.tdate, ttime = t.ttime)
+ if prev_test:
+ messages.error(request, "You have already scheduled "+ t.foss.foss + " Test on "+t.tdate + " "+ t.ttime + " . Please select some other time.")
+
+ if t and t.training_id:
+ tras = TrainingAttend.objects.filter(training=t.training)
+ fossmdlcourse = FossMdlCourses.objects.get(foss_id = t.foss_id)
+ for tra in tras:
+ user = tra.student.user
+ mdluser = get_moodle_user(tra.training.training_planner.academic_id, user.first_name, user.last_name, tra.student.gender, tra.student.user.email)# if it create user rest password for django user too
+
+ if mdluser:
+ print("mdluser present", mdluser.id)
+ try:
+ instance = TestAttendance.objects.get(test_id=t.id, mdluser_id=mdluser.id)
+ except Exception as e:
+ print(e)
+ instance = TestAttendance()
+ instance.student_id = tra.student.id
+ instance.test_id = t.id
+ instance.mdluser_id = mdluser.id
+ instance.mdlcourse_id = fossmdlcourse.mdlcourse_id
+ instance.mdlquiz_id = fossmdlcourse.mdlquiz_id
+ instance.mdlattempt_id = 0
+ instance.status = 0
+ instance.save()
+
+ print("test_attendance created for ",tra.student.id)
+ else:
+ print("mdluser not found for", user.email)
+ error = 1
+ if not error:
+ t.department.clear()
+ t.department.add(test_training_dept)
+ #update logs
+ message = t.academic.institution_name+" has made a test request for "+t.foss.foss+" on "+t.tdate
+ if rid:
+ message = t.academic.institution_name+" has updated test for "+t.foss.foss+" on dated "+t.tdate
+ update_events_log(user_id = user.id, role = 0, category = 1, category_id = t.id, academic = t.academic_id, status = 0)
+ update_events_notification(user_id = user.id, role = 0, category = 1, category_id = t.id, academic = t.academic_id, status = 0, message = message)
+
+ return HttpResponseRedirect("/software-training/test/"+role+"/pending/")
+ messages.info(request, """
+
+ Please make sure that before making the test request a faculty/trainer should have registered as invigilator.
+ Same person cannot be an organiser and the invigilator for the same test.
+ Please confirm the Invigilator's availability and acceptance to invigilate before selecting his name in this form.
+ Upgrade the browser with version of Mozilla Firefox 30 or higher on all the systems before the test.
+
+ """)
+ context['role'] = role
+ context['status'] = 'request'
+ context.update(csrf(request))
+ context['form'] = form
+ return render(request, 'events/templates/test/form.html', context)
+
+@login_required
+def test_list(request, role, status):
+ """ Organiser test index page """
+ user = request.user
+ if not (user.is_authenticated() and ( is_organiser(user) or is_invigilator(user) or is_resource_person(user) or is_event_manager(user))):
+ raise PermissionDenied()
+
+ status_dict = {'pending': 0, 'waitingforinvigilator': 1, 'approved' : 2, 'ongoing': 3, 'completed' : 4, 'rejected' : 5, 'reschedule' : 2, 'predated' : ''}
+ if status in status_dict:
+ context = {}
+ collectionSet = None
+ todaytest = None
+ if is_event_manager(user) and role == 'em':
+ if status == 'ongoing':
+ collectionSet = Test.objects.filter(academic__in = AcademicCenter.objects.filter(state__in = State.objects.filter(resourceperson__user_id=user, resourceperson__status=1)), status = status_dict[status], tdate = datetime.datetime.now().strftime("%Y-%m-%d")).order_by('-tdate')
+ else:
+ collectionSet = Test.objects.filter(academic__in = AcademicCenter.objects.filter(state__in = State.objects.filter(resourceperson__user_id=user, resourceperson__status=1)), status = status_dict[status]).order_by('-tdate')
+ elif is_resource_person(user) and role == 'rp':
+ if status == 'ongoing':
+ collectionSet = Test.objects.filter(academic__in = AcademicCenter.objects.filter(state__in = State.objects.filter(resourceperson__user_id=user, resourceperson__status=1)), status = status_dict[status], tdate = datetime.datetime.now().strftime("%Y-%m-%d")).order_by('-tdate')
+ elif status == 'predated':
+ collectionSet = Test.objects.filter((Q(status = 0) | Q(status = 1) | Q(status = 2) | Q(status = 3)), academic__in = AcademicCenter.objects.filter(state__in = State.objects.filter(resourceperson__user_id=user, resourceperson__status=1)), tdate__lt=datetime.date.today()).order_by('-tdate')
+ else:
+ collectionSet = Test.objects.filter(academic__in = AcademicCenter.objects.filter(state__in = State.objects.filter(resourceperson__user_id=user, resourceperson__status=1)), status = status_dict[status]).order_by('-tdate')
+ elif is_organiser(user) and role == 'organiser':
+ if status == 'ongoing':
+ collectionSet = Test.objects.filter((Q(status = 2) | Q(status = 3)), organiser__user = user , tdate__lte = datetime.date.today().strftime("%Y-%m-%d")).order_by('-tdate')
+ elif status == 'predated':
+ collectionSet = Test.objects.filter((Q(status = 0) | Q(status = 1) | Q(status = 2) | Q(status = 3)), organiser__user = user, tdate__lt=datetime.date.today()).order_by('-tdate')
+ elif status == 'approved':
+ collectionSet = Test.objects.filter(organiser__user = user, status = status_dict[status], tdate__gt=datetime.date.today()).order_by('-tdate')
+ else:
+ collectionSet = Test.objects.filter(organiser__user = user, status = status_dict[status]).order_by('-tdate')
+ elif is_invigilator(user) and role == 'invigilator':
+ if status == 'ongoing':
+ collectionSet = Test.objects.filter((Q(status = 2) | Q(status = 3)), tdate__lte = datetime.date.today(), invigilator_id = user.invigilator.id).order_by('-tdate')
+ messages.info(request, "Click on the Attendance link below to see the participant list.")
+ elif status == 'predated':
+ collectionSet = Test.objects.none()
+ elif status == 'approved':
+ collectionSet = Test.objects.filter(invigilator_id=user.invigilator.id, status = status_dict[status], tdate__gt=datetime.date.today()).order_by('-tdate')
+ else:
+ todaytest = datetime.datetime.now().strftime("%Y-%m-%d")
+ collectionSet = Test.objects.filter(invigilator_id=user.invigilator.id, status = status_dict[status]).order_by('-tdate')
+
+ if collectionSet == None:
+ raise PermissionDenied()
+
+ header = {
+ 1: SortableHeader('#', False),
+ 2: SortableHeader('academic__state', True, 'State'),
+ 3: SortableHeader('academic__academic_code', True, 'Academic Code'),
+ 4: SortableHeader('academic', True, 'Institution'),
+ 5: SortableHeader('organiser', True, 'Organiser'),
+ 6: SortableHeader('invigilator', True, 'Invigilator'),
+ 7: SortableHeader('training__department', True, 'Department'),
+ 8: SortableHeader('foss', True, 'FOSS'),
+ 9: SortableHeader('tdate', True, 'Date'),
+ 10: SortableHeader('Participants', False),
+ 11: SortableHeader('', False)
+ }
+ raw_get_data = request.GET.get('o', None)
+ collection = get_sorted_list(request, collectionSet, header, raw_get_data)
+ ordering = get_field_index(raw_get_data)
+
+ collection = TestFilter(request.GET, user = user, queryset=collection)
+ context['form'] = collection.form
+
+ page = request.GET.get('page')
+ collection = get_page(collection.qs, page)
+
+ context['collection'] = collection
+ context['header'] = header
+ context['ordering'] = ordering
+
+ context['status'] = status
+ context['role'] = role
+ context['todaytest'] = todaytest
+ context['can_manage'] = user.groups.filter(Q(name="Event Manager") | Q(name="Resource Person"))
+ context.update(csrf(request))
+ return render(request, 'events/templates/test/index.html', context)
+ else:
+ raise PermissionDenied()
+
+@login_required
+@csrf_exempt
+def test_approvel(request, role, rid):
+ """ Resource person: confirm or reject training """
+ user = request.user
+ status = 0
+ message = None
+ alert = None
+ logrole = 0
+ try:
+ t = Test.objects.get(pk=rid)
+ if request.GET['status'] == 'accept':
+ print("!!!!!!!!")
+ status = 1
+ t.test_code = "TC-" + str(t.id)
+ message = "The Training Manager has approved "+t.foss.foss+" test dated "+t.tdate.strftime("%Y-%m-%d")
+ alert = "Test has been approved"
+ #send email
+ send_email('Instructions to be followed before conducting the test-organiser', [t.organiser.user.email], t)
+ send_email('Instructions to be followed before conducting the test-invigilator', [t.invigilator.user.email], t)
+ logrole = 2
+ if request.GET['status'] == 'invigilatoraccept':
+ message = "The Invigilator "+t.organiser.user.first_name +" "+t.organiser.user.last_name+" has approved "+t.foss.foss+" test dated "+t.tdate.strftime("%Y-%m-%d")
+ status = 2
+ logrole = 1
+ alert = "Test has been approved"
+ if request.GET['status'] == 'ongoing':
+ status = 3
+ if request.GET['status'] == 'completed':
+ status = 4
+ logrole = 1
+ alert = "Test has been Completed"
+ message = t.academic.institution_name +" has completed "+t.foss.foss+" test dated "+t.tdate.strftime("%Y-%m-%d")
+ if request.GET['status'] == 'reject':
+ message = "The Training Manager has rejected "+t.foss.foss+" test dated "+t.tdate.strftime("%Y-%m-%d")
+ status = 5
+ logrole = 2
+ alert = "Test has been rejected"
+ if request.GET['status'] == 'invigilatorreject':
+ message = "The Invigilator "+t.organiser.user.first_name +" "+t.organiser.user.last_name+" has rejected "+t.foss.foss+" test dated "+t.tdate.strftime("%Y-%m-%d")
+ status = 6
+ logrole = 1
+ alert = "Test has been rejected"
+ except Exception as e:
+ print(e)
+ raise PermissionDenied()
+
+ #if status = 2:
+ # if not (user.is_authenticated() and w.academic.state in State.objects.filter(resourceperson__user_id=user, resourceperson__status=1) and ( is_event_manager(user) or is_resource_person(user))):
+ # raise PermissionDenied('You are not allowed to view this page')
+ if status == 1:
+ t.appoved_by_id = user.id
+ t.workshop_code = "TC-"+str(t.id)
+ if status == 4:
+ TestAttendance.objects.filter(test_id=t.id, status = 2).update(status = 3)
+ testatten = TestAttendance.objects.filter(test_id=t.id, status__gt=2)
+ if not testatten:
+ messages.error(request, "Students are processing the test. Check the status for each students!")
+ return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
+ t.participant_count = TestAttendance.objects.filter(test_id=t.id, status__gte=2).count()
+
+ t.status = status
+ t.save()
+
+ #events log
+ #message = user.first_name+" "+user.last_name+" has accepted your "+t.foss.foss+" Test"
+ update_events_log(user_id = user.id, role = logrole, category = 1, category_id = t.id, academic = t.academic_id, status = status)
+ update_events_notification(user_id = user.id, role = logrole, category = 1, category_id = t.id, academic = t.academic_id, status = status, message = message)
+ messages.success(request, alert)
+ if request.GET['status'] == 'completed':
+ return HttpResponseRedirect('/software-training/test/'+role+'/completed/')
+ return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
+
+@login_required
+def test_attendance(request, tid):
+
+ user = request.user
+ test = None
+ onlinetest_user = ''
+ form = ParticipantSearchForm()
+ try:
+ test = Test.objects.get(pk=tid)
+ if test.status == 4 or test.status == 1:
+ return HttpResponseRedirect('/software-training/test/' + str(test.id) + '/participant/')
+
+ test.status = 3
+ test.save()
+ except:
+ raise PermissionDenied()
+ ta_status = request.GET.get('status',None)
+ if request.method == 'POST':
+ users = request.POST
+ if users:
+ #set all record to 0 if status = 1
+ if 'submit-attendance' in users:
+ if ta_status is None or ta_status == '1':
+ TestAttendance.objects.filter(test_id = tid, status = 1).update(status = 0)
+ for u in users:
+ if not (u == 'csrfmiddlewaretoken' or u == 'submit-attendance'):
+ try:
+ ta = TestAttendance.objects.get(mdluser_id = users[u], test_id = tid)
+ if ta.status > 1:
+ continue
+ except TestAttendance.DoesNotExist:
+ fossmdlcourse = FossMdlCourses.objects.get(foss_id = test.foss_id)
+ ta = TestAttendance()
+ ta.test_id = test.id
+ ta.mdluser_id = users[u]
+ ta.mdlcourse_id = fossmdlcourse.mdlcourse_id
+ ta.mdlquiz_id = fossmdlcourse.mdlquiz_id
+ ta.mdlattempt_id = 0
+ ta.status = 0
+ ta.save()
+ if ta:
+ #todo: if the status = 2 check in moodle if he completed the test set status = 3 (completed)
+ t = TestAttendance.objects.get(mdluser_id = ta.mdluser_id, test_id = tid)
+ fossmdlcourse = FossMdlCourses.objects.get(foss_id = test.foss_id)
+ t.mdlcourse_id = fossmdlcourse.mdlcourse_id
+ t.mdlquiz_id = fossmdlcourse.mdlquiz_id
+ t.status = 1
+ t.save()
+ #enroll to the course
+ #get the course enrole id
+ #todo: If mark absent delete enrolement
+ mdlenrol = None
+ try:
+ mdlenrol = MdlEnrol.objects.get(enrol='self', courseid = fossmdlcourse.mdlcourse_id )
+ print("Role Exits")
+ except Exception as e:
+ print(("MdlEnrol => ", e))
+ print("No self enrolement for this course")
+
+ #if mdlenrol:
+ # try:
+ # MdlUserEnrolments.objects.get(enrolid = mdlenrol.id, userid = ta.mdluser_id)
+ # print "MdlUserEnrolments Exits"
+ # #update dateTime
+ # except Exception as e:
+ # print "MdlUserEnrolments => ", e
+ # MdlRoleAssignments.objects.create(roleid = 5, contextid = 16, userid = ta.mdluser_id, timemodified = datetime.datetime.now().strftime("%s"), modifierid = ta.mdluser_id, itemid = 0, sortorder = 0)
+ # MdlUserEnrolments.objects.create(enrolid = mdlenrol.id, userid = ta.mdluser_id, status = 0, timestart = datetime.datetime.now().strftime("%s"), timeend = 0, modifierid = ta.mdluser_id, timecreated = datetime.datetime.now().strftime("%s"), timemodified = datetime.datetime.now().strftime("%s"))
+
+ if 'search-participant' in request.POST:
+ form = ParticipantSearchForm(request.POST)
+ onlinetest_user = search_participant(form)
+
+ if 'add-participant' in request.POST:
+ add_participant(request, tid, 'Test')
+
+ message = test.academic.institution_name+" has submited Test attendance dated "+test.tdate.strftime("%Y-%m-%d")
+ update_events_log(user_id = user.id, role = 1, category = 1, category_id = test.id, academic = test.academic_id, status = 8)
+ update_events_notification(user_id = user.id, role = 1, category = 1, category_id = test.id, academic = test.academic_id, status = 8, message = message)
+ messages.success(request, """
+
+ Thank you for uploading the Attendance. Now make sure that you cross check and verify the details before submiting.
+ If you want to add more participants please upload a new CSV file containing the missing participants details.
+ Once you confirm the list of participants please click on 'Mark as Complete'
+
+ """)
+ mdlids = []
+ participant_ids = []
+ ta_status = int(ta_status) if ta_status is not None else None
+
+ # Ensure Training Attendance records match with Test Attendance
+ test_mdl_ids = TestAttendance.objects.filter(test_id = test.id).values_list('mdluser_id', flat=True) # Test Mdl Ids
+ test_student_emails = MdlUser.objects.filter(id__in=test_mdl_ids).values_list('email', flat=True)
+
+ # Find users who have attented training but does not have test attendance records
+ tr_users = TrainingAttend.objects.filter(training_id = test.training_id).exclude(student__user__email__in=test_student_emails).select_related(
+ 'student','student__user',
+ 'training__training_planner__academic')
+ # create test attendance records for missing students
+ for tra in tr_users:
+ user = tra.student.user
+ mdluser = get_moodle_user(tra.training.training_planner.academic_id, user.first_name, user.last_name, tra.student.gender, user.email)
+ if mdluser:
+ try:
+ instance = TestAttendance.objects.get(test_id=test.id, mdluser_id=mdluser.id)
+ except TestAttendance.DoesNotExist:
+ instance = TestAttendance()
+ instance.mdluser_firstname = user.first_name
+ instance.mdluser_lastname = user.last_name
+ instance.student_id = tra.student.id
+ instance.test_id = test.id
+ instance.mdluser_id = mdluser.id
+ # get course and quiz id
+ foss = test.foss
+ f = FossMdlCourses.objects.get(foss=foss)
+ instance.mdlcourse_id = f.mdlcourse_id
+ instance.mdlquiz_id = f.mdlquiz_id
+ instance.mdlattempt_id = 0
+ instance.status = 0
+ instance.save()
+
+ if ta_status is not None:
+ mdlids = list(TestAttendance.objects.filter(test_id = test.id, status=ta_status).values_list('mdluser_id', flat=True))
+ else:
+ mdlids = list(TestAttendance.objects.filter(test_id = test.id).values_list('mdluser_id', flat=True))
+ wp = None
+ mdlids.extend(participant_ids)
+
+ if mdlids:
+ wp = MdlUser.objects.filter(id__in = mdlids)
+ #check can close the test
+ testatten = TestAttendance.objects.filter(test_id=test.id, status__gte=2)
+ enable_close_test = None
+ if testatten:
+ enable_close_test = True
+ context = {}
+ context['collection'] = wp
+ context['test'] = test
+ context['form'] = form
+ context['onlinetest_user'] = onlinetest_user
+ context['enable_close_test'] = enable_close_test
+ context.update(csrf(request))
+ messages.info(request, "Instruct the students to Register and Login on the Online Test link of Spoken Tutorial. Click on the checkbox so that usernames of all the students who are present for the test are marked, then click the submit button. Students can now proceed for the Test.")
+ return render(request, 'events/templates/test/attendance.html', context)
+
+@login_required
+def test_participant(request, tid=None):
+ user = request.user
+ can_download_certificate = 0
+ if tid:
+ try:
+ t = Test.objects.get(id=tid)
+ except:
+ raise PermissionDenied()
+
+ if t.status == 4:
+ test_mdlusers = TestAttendance.objects.filter(test_id=tid, status__gte=2)
+ else:
+ test_mdlusers = TestAttendance.objects.filter(test_id=tid)
+ #ids = []
+ #print test_mdlusers
+ #for tp in test_mdlusers:
+ # ids.append(tp[0])
+ #print ids, 'ssssssssssss', tid
+ #tp = MdlUser.objects.using('moodle').filter(id__in=ids)
+ #if t.status == 4 and (user == t.organiser or user == t.invigilator):
+ # can_download_certificate = 1
+ context = {'collection' : test_mdlusers, 'test' : t, 'can_download_certificate':can_download_certificate}
+ return render(request, 'events/templates/test/test_participant.html', context)
+
+def test_participant_ceritificate(request, wid, participant_id):
+ #response = HttpResponse(content_type='application/pdf')
+ #response['Content-Disposition'] = 'attachment; filename="somefilename.pdf"'
+
+ # Create the PDF object, using the response object as its "file."
+ #p = canvas.Canvas(response)
+
+ # Draw things on the PDF. Here's where the PDF generation happens.
+ # See the ReportLab documentation for the full list of functionality.
+ #p.drawString(200, 500, "Hello world.")
+
+ # Close the PDF object cleanly, and we're done.
+ #p.showPage()
+ #p.save()
+ #return response
+ # Using ReportLab to insert image into PDF
+
+ #store Certificate details
+
+ certificate_pass = ''
+ if wid and participant_id:
+ try:
+ w = Test.objects.get(id = wid)
+ mdluser = MdlUser.objects.get(id = participant_id)
+ ta = TestAttendance.objects.get(test_id = w.id, mdluser_id = participant_id)
+ mdlgrade = MdlQuizGrades.objects.get(quiz = ta.mdlquiz_id, userid = participant_id)
+ print(w.foss.credits,"#########################&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&")
+ if ta.status < 1 or round(mdlgrade.grade, 1) < 40 or not w.invigilator:
+ raise PermissionDenied()
+
+ if ta.password:
+ certificate_pass = ta.password
+ ta.count += 1
+ ta.status = 4
+ ta.save()
+ else:
+ certificate_pass = str(mdluser.id)+id_generator(10-len(str(mdluser.id)))
+ ta.password = certificate_pass
+ ta.status = 4
+ ta.count += 1
+ ta.save()
+ except Exception as e:
+ print(e)
+ raise PermissionDenied()
+ response = HttpResponse(content_type='application/pdf')
+ filename = (mdluser.firstname+'-'+mdluser.lastname+"-Participant-Certificate").replace(" ", "-");
+
+ response['Content-Disposition'] = 'attachment; filename='+filename+'.pdf'
+ imgTemp = BytesIO()
+ imgDoc = canvas.Canvas(imgTemp)
+
+ # Title
+ #imgDoc.setFont('Helvetica', 40, leading=None)
+ #imgDoc.drawCentredString(415, 480, "Certificate for Completion of c ")
+ if ta.test.training.department.id != 169:
+ imgDoc.setFont('Helvetica', 18, leading=None)
+ imgDoc.drawCentredString(211, 115, custom_strftime('%d %B %Y', w.tdate))
+
+ #password
+ imgDoc.setFillColorRGB(0, 0, 0)
+ imgDoc.setFont('Helvetica', 10, leading=None)
+ imgDoc.drawString(10, 6, certificate_pass)
+ #imgDoc.drawString(100, 100, 'transparent')
+
+
+ # Draw image on Canvas and save PDF in buffer
+ imgPath = get_signature(ta.test.tdate)
+ imgDoc.drawImage(imgPath, 600, 95, 150, 76) ## at (399,760) with size 160x160
+
+ credits = "Credits: "+str(w.foss.credits)+"   Score: "+str('{:.2f}'.format(mdlgrade.grade))+"%
"
+
+ #paragraphe
+ text = get_test_cert_text(ta.test, mdluser, credits=credits)
+ centered = ParagraphStyle(name = 'centered',
+ fontSize = 15,
+ leading = 24,
+ alignment = 1,
+ spaceAfter = 20)
+
+ p = Paragraph(text, centered)
+ p.wrap(700, 200)
+ p.drawOn(imgDoc, 3 * cm, 6.5 * cm)
+
+ #paragraphe
+ text = "Certificate for the Completion of "+w.foss.foss+" Training"
+
+ centered = ParagraphStyle(name = 'centered',
+ fontSize = 25,
+ leading = 25,
+ alignment = 1,
+ spaceAfter = 15)
+
+ p = Paragraph(text, centered)
+ p.wrap(500,20)
+ p.drawOn(imgDoc, 6.2 * cm, 17 * cm)
+
+
+ imgDoc.save()
+
+ # Use PyPDF to merge the image-PDF into the template
+ template_path = get_test_certificate(ta)
+ page = PdfFileReader(open(template_path,"rb")).getPage(0)
+ overlay = PdfFileReader(BytesIO(imgTemp.getvalue())).getPage(0)
+ page.mergePage(overlay)
+
+ #Save the result
+ output = PdfFileWriter()
+ output.addPage(page)
+
+ #stream to browser
+ outputStream = response
+ output.write(response)
+ outputStream.close()
+
+ return response
+
+
+def test_participant_ceritificate_all(request, testid):
+ certificate_pass = ''
+ w = Test.objects.get(id = testid)
+ if not (w.organiser.user == request.user or w.invigilator.user == request.user):
+ raise PermissionDenied()
+ testattendances = TestAttendance.objects.filter(test_id = testid)
+
+ response = HttpResponse(content_type='application/pdf')
+ filename = (w.foss.foss+"-Participant-Certificate").replace(" ", "-")
+
+ response['Content-Disposition'] = 'attachment; filename='+filename+'.pdf'
+
+ output = PdfFileWriter()
+
+ for ta in testattendances:
+ try:
+ mdlgrade = MdlQuizGrades.objects.get(quiz = ta.mdlquiz_id, userid = ta.mdluser_id)
+ mdluser = MdlUser.objects.get(id=ta.mdluser_id)
+ except:
+ continue
+ if ta.status < 1 or round(mdlgrade.grade, 1) < 40:
+ continue
+
+ if ta.password:
+ certificate_pass = ta.password
+ ta.count += 1
+ ta.status = 4
+ ta.save()
+ else:
+ certificate_pass = str(ta.mdluser_id)+id_generator(10-len(str(ta.mdluser_id)))
+ ta.password = certificate_pass
+ ta.status = 4
+ ta.count += 1
+ ta.save()
+ imgTemp = BytesIO()
+ imgDoc = canvas.Canvas(imgTemp)
+
+ if ta.test.training.department.id != 169:
+ imgDoc.setFont('Helvetica', 18, leading=None)
+ imgDoc.drawCentredString(211, 115, custom_strftime('%d %B %Y', w.tdate))
+
+ #password
+ imgDoc.setFillColorRGB(0, 0, 0)
+ imgDoc.setFont('Helvetica', 10, leading=None)
+ imgDoc.drawString(10, 6, certificate_pass)
+ #imgDoc.drawString(100, 100, 'transparent')
+
+
+ # Draw image on Canvas and save PDF in buffer
+ imgPath = get_signature(ta.test.tdate)
+ imgDoc.drawImage(imgPath, 600, 95, 150, 76) ## at (399,760) with size 160x160
+
+ credits = "Credits: "+str(w.foss.credits)+"   Score: "+str('{:.2f}'.format(mdlgrade.grade))+"%
"
+
+ #paragraphe
+ text = get_test_cert_text(ta.test, mdluser, credits=credits)
+ centered = ParagraphStyle(name = 'centered',
+ fontSize = 15,
+ leading = 24,
+ alignment = 1,
+ spaceAfter = 20)
+
+ p = Paragraph(text, centered)
+ p.wrap(700, 200)
+ p.drawOn(imgDoc, 3 * cm, 6.5 * cm)
+
+ #paragraphe
+ text = "Certificate for Completion of "+w.foss.foss+" Training"
+
+ centered = ParagraphStyle(name = 'centered',
+ fontSize = 25,
+ leading = 25,
+ alignment = 1,
+ spaceAfter = 15)
+
+ p = Paragraph(text, centered)
+ p.wrap(500,20)
+ p.drawOn(imgDoc, 6.2 * cm, 17 * cm)
+ imgDoc.save()
+ template_path = get_test_certificate(ta)
+ page = PdfFileReader(open(template_path,"rb")).getPage(0)
+ overlay = PdfFileReader(BytesIO(imgTemp.getvalue())).getPage(0)
+ page.mergePage(overlay)
+
+ #Save the result
+ output.addPage(page)
+
+ #stream to browser
+ outputStream = response
+ output.write(response)
+ outputStream.close()
+
+ return response
+
+
+@csrf_exempt
+def training_subscribe(request, events, eventid = None, mdluser_id = None):
+ try:
+ mdluser = MdlUser.objects.get(id = mdluser_id)
+ if events == 'test':
+ try:
+ TestAttendance.objects.create(test_id=eventid, mdluser_id = mdluser_id, mdluser_firstname = mdluser.firstname, mdluser_lastname = mdluser.lastname)
+ except Exception as e:
+ print(e)
+ pass
+ messages.success(request, "You have sucessfully subscribe to the "+events+"")
+ return HttpResponseRedirect('/participant/index/#Upcoming-Test')
+ elif events == 'training':
+ try:
+ TrainingAttendance.objects.create(training_id=eventid, mdluser_id = mdluser_id)
+ except Exception as e:
+ print(e)
+ pass
+ messages.success(request, "You have sucessfully subscribe to the "+events+"")
+ return HttpResponseRedirect('/participant/index/#Upcoming-Training')
+ else:
+ raise PermissionDenied()
+ except:
+ raise PermissionDenied()
+
+ return HttpResponseRedirect('/participant/index/')
+
+@login_required
+def organiser_invigilator_index(request, role, status):
+ """ Resource person: List all inactive organiser under resource person states """
+ #todo: filter to diaplay block and active user
+ active = status
+ user = request.user
+ context = {}
+ if not (user.is_authenticated() and (is_event_manager(user) or is_resource_person(user))):
+ raise PermissionDenied()
+ if status == 'active':
+ status = 1
+ elif status == 'inactive':
+ status = 0
+ elif status == 'blocked':
+ status = 2
+ elif status == 'deactivated':
+ status = 3
+ else:
+ raise PermissionDenied()
+
+ user = User.objects.get(pk=user.id)
+
+ header = {
+ 1: SortableHeader('#', False),
+ 2: SortableHeader('academic__state', True, 'State'),
+ 3: SortableHeader('academic__academic_code', True, 'Academic Code'),
+ 4: SortableHeader('academic__institution_name', True, 'Institution'),
+ 5: SortableHeader('user__first_name', True, 'Name'),
+ 6: SortableHeader('Email', False),
+ 7: SortableHeader('Phone', False),
+ 8: SortableHeader('Action', False)
+ }
+
+ if role == 'organiser':
+ try:
+ #collectionSet = Organiser.objects.select_related().filter(academic__in=AcademicCenter.objects.filter(state__in=State.objects.filter(resourceperson__user_id=user, resourceperson__status=1)), status=status)
+ states = user.resource_person.prefetch_related().filter(resourceperson__status = 1,resourceperson__user_id=user)
+ academics = AcademicCenter.objects.filter(state__in = states)
+ collectionSet = Organiser.objects.filter(academic__in = academics, status = status)
+
+ raw_get_data = request.GET.get('o', None)
+ collection = get_sorted_list(request, collectionSet, header, raw_get_data)
+ ordering = get_field_index(raw_get_data)
+
+ collection = OrganiserFilter(request.GET, user = user, queryset=collection)
+ context['form'] = collection.form
+
+ page = request.GET.get('page')
+ collection = get_page(collection.qs, page)
+ except Exception as e:
+ print(e)
+ collection = {}
+ elif role == 'invigilator':
+ try:
+ #collectionSet = Invigilator.objects.select_related().filter(academic__in=AcademicCenter.objects.filter(state=State.objects.filter(resourceperson__user_id=user, resourceperson__status=1)), status=status)
+ states = user.resource_person.prefetch_related().filter(resourceperson__status=1, resourceperson__user_id=user)
+ academics = AcademicCenter.objects.filter(state__in=states)
+ collectionSet = Invigilator.objects.filter(academic__in=academics, status=status)
+
+ raw_get_data = request.GET.get('o', None)
+ collection = get_sorted_list(request, collectionSet, header, raw_get_data)
+ ordering = get_field_index(raw_get_data)
+
+ collection = InvigilatorFilter(request.GET, user = user, queryset=collection)
+ context['form'] = collection.form
+
+ page = request.GET.get('page')
+ collection = get_page(collection.qs, page)
+
+ except Exception as e:
+ print(e)
+ collection = {}
+ elif role == 'accountexecutive':
+ try:
+ #collectionSet = Accountexecutive.objects.select_related().filter(academic__in=AcademicCenter.objects.filter(state__in=State.objects.filter(resourceperson__user_id=user, resourceperson__status=1)), status=status)
+ states = user.resource_person.prefetch_related().filter(resourceperson__status=1, resourceperson__user_id=user)
+ academics = AcademicCenter.objects.filter(state__in=states)
+ collectionSet = Accountexecutive.objects.filter(academic__in=academics, status=status)
+
+
+ raw_get_data = request.GET.get('o', None)
+ collection = get_sorted_list(request, collectionSet, header, raw_get_data)
+ ordering = get_field_index(raw_get_data)
+
+ collection = AccountexecutiveFilter(request.GET, user = user, queryset=collection)
+ context['form'] = collection.form
+
+ page = request.GET.get('page')
+ collection = get_page(collection.qs, page)
+
+ except Exception as e:
+ print(e)
+ collection = {}
+ else:
+ raise PermissionDenied()
+
+ for record in collection:
+ try:
+ record.user.profile_set.get()
+ except:
+ create_profile(record.user, None)
+
+ context['header'] = header
+ context['ordering'] = ordering
+ context['collection'] = collection
+ context['status'] = active
+ context['role'] = role
+ context.update(csrf(request))
+ return render(request, 'events/templates/organiser_invigilator_index.html', context)
+
+
+def update_events_log(user_id, role, category, category_id, academic, status):
+ if category == 0:
+ try:
+ TrainingLog.objects.create(user_id = user_id, training_id = category_id, role = role, academic_id = academic, status = status)
+ except Exception as e:
+ print(("Training Log =>",e))
+ elif category == 1:
+ try:
+ TestLog.objects.create(user_id = user_id, test_id = category_id, role = role, academic_id = academic, status = status)
+ except Exception as e:
+ print(("Test Log => ",e))
+ else:
+ print("************ Error in events log ***********")
+
+def update_events_notification(user_id, role, category, category_id, status, academic, message):
+ try:
+ EventsNotification.objects.create(user_id = user_id, role = role, category = category, categoryid = category_id, academic_id = academic, status = status, message = message)
+ except Exception as e:
+ print(("Error in Events Notification => ", e))
+
+def training_participant_feedback(request, training_id, participant_id):
+ try:
+ tf = TrainingFeedback.objects.get(training_id = training_id, mdluser_id = participant_id)
+ except:
+ messages.success(request, 'Feedback does not exist!')
+ return HttpResponseRedirect("/software-training/training/" + str(training_id) + "/participant/")
+ context = {
+ 'feedback' : tf,
+ }
+ context.update(csrf(request))
+ return render(request, 'events/templates/training/view-feedback.html', context)
+
+def training_participant_language_feedback(request, training_id, user_id):
+ w = None
+ try:
+ w = TrainingRequest.objects.get(pk=training_id)
+ MdlUser.objects.get(id = user_id)
+ except Exception as e:
+ raise PermissionDenied()
+ form = TrainingLanguageFeedbackForm(training = w)
+ if request.method == 'POST':
+ form = TrainingLanguageFeedbackForm(request.POST, training = w)
+ if form.is_valid():
+ try:
+ form_data = form.save(commit=False)
+ form_data.training_id = w.id
+ form_data.mdluser_id = user_id
+ form_data.language_id = form.cleaned_data['language_prefered']
+ form_data.save()
+ messages.success(request, "Thank you for your valuable feedback.")
+ return HttpResponseRedirect('/')
+ except Exception as e:
+ print(e)
+ messages.success(request, "Sorry, something went wrong, Please try again!")
+ #return HttpResponseRedirect('/')
+ context = {
+ 'form' : form,
+ 'w' : w
+ }
+
+
+ context = {}
+ context['form'] = form
+ return render(request, 'events/templates/training/language_feedback.html', context)
+
+def live_training(request, training_id=None):
+
+ context = {}
+ if not training_id:
+ context['training_list'] = SingleTraining.objects.filter(
+ training_type = 2
+ )
+ else:
+ try:
+ context['training'] = TrainingLiveFeedback.objects.filter(
+ training_id = training_id
+ )
+ except Exception as e:
+ print(e)
+ raise PermissionDenied()
+
+ context.update(csrf(request))
+ return render(request, 'events/templates/training/live-feedback-list.html', context)
+
+def training_participant_livefeedback(request, training_id):
+ form = LiveFeedbackForm()
+ w = None
+ try:
+ w = SingleTraining.objects.get(pk=training_id)
+ except Exception as e:
+ raise PermissionDenied()
+ if request.method == 'POST':
+ form = LiveFeedbackForm(request.POST)
+ if form.is_valid():
+ try:
+ form_data = form.save(commit=False)
+ form_data.training_id = w.id
+ form_data.save()
+ messages.success(request, "Thank you for your valuable feedback.")
+ return HttpResponseRedirect('/')
+ except Exception as e:
+ print(e)
+ messages.success(request, "Something went wrong, please contact site administrator.")
+ return HttpResponseRedirect('/')
+ context = {
+ 'form' : form,
+ 'w' : w
+ }
+ return render(request, 'events/templates/training/lfeedback.html', context)
+
+def training_participant_viewlivefeedback(request, training_id, feedback_id):
+ tf = None
+ try:
+ tf = TrainingLiveFeedback.objects.get(training_id = training_id, id = feedback_id)
+ except:
+ raise PermissionDenied()
+ context = {
+ 'feedback' : tf,
+ 'live' : True
+ }
+ context.update(csrf(request))
+ return render(request, 'events/templates/training/view-feedback.html', context)
+
+def resource_center(request, slug = None):
+ context = {}
+ header = {
+ 1: SortableHeader('#', False),
+ 2: SortableHeader('State', False),
+ 3: SortableHeader('institution_name', True, 'Institution Name'),
+ 4: SortableHeader('Address', False),
+ 5: SortableHeader('Contact Person', False),
+ 6: SortableHeader('Action', False)
+ }
+
+ collection = None
+ if slug:
+ collection = AcademicCenter.objects.filter(resource_center = 1, state__slug = slug).order_by('state__name', 'institution_name')
+ else:
+ collection = AcademicCenter.objects.filter(resource_center = 1).order_by('state__name', 'institution_name')
+
+ raw_get_data = request.GET.get('o', None)
+ collection = get_sorted_list(request, collection, header, raw_get_data)
+ ordering = get_field_index(raw_get_data)
+
+ collection = AcademicCenterFilter(request.GET, queryset=collection)
+ context['form'] = collection.form
+
+ page = request.GET.get('page')
+ collection = get_page(collection.qs, page)
+
+ context['collection'] = collection
+ context['header'] = header
+ context['ordering'] = ordering
+ return render(request, 'events/templates/ac/resource-center.html', context)
+
+def academic_center(request, academic_id = None, slug = None):
+ collection = get_object_or_404(AcademicCenter, id=academic_id)
+ slug_title = slugify(collection.institution_name)
+ if slug != slug_title:
+ return HttpResponseRedirect('/software-training/academic-center/'+ str(collection.id) + '/' + slug_title)
+ context = {
+ 'collection' : collection
+ }
+ return render(request, 'events/templates/ac/academic-center.html', context)
+
+#Ajax Request and Responces
+@csrf_exempt
+def ajax_ac_state(request):
+ """ Ajax: Get University, District, City based State selected """
+ if request.method == 'POST':
+ state = request.POST.get('state')
+ data = {}
+ if request.POST.get('fields[district]'):
+ district = District.objects.filter(state=state).order_by('name')
+ tmp = ''
+ for i in district:
+ tmp +=''+i.name+' '
+
+ if(tmp):
+ data['district'] = ' -- None -- '+tmp
+ else:
+ data['district'] = tmp
+
+ if request.POST.get('fields[city]'):
+ city = City.objects.filter(state=state).order_by('name')
+ tmp = ''
+ for i in city:
+ tmp +=''+i.name+' '
+
+ if(tmp):
+ data['city'] = ' -- None -- '+tmp
+ else:
+ data['city'] = tmp
+
+ if request.POST.get('fields[university]'):
+ university = University.objects.filter(state=state).order_by('name')
+ tmp = ''
+ for i in university:
+ tmp +=''+i.name+' '
+ if(tmp):
+ data['university'] = ' -- None -- '+tmp
+ else:
+ data['university'] = tmp
+
+ return HttpResponse(json.dumps(data), content_type='application/json')
+
+@csrf_exempt
+def ajax_state_details(request):
+ """ Ajax: Get District, City based State selected """
+ if request.method == 'POST':
+ state = request.POST.get('state')
+ data = {}
+ if request.POST.get('fields[district]'):
+ district = District.objects.filter(state=state).order_by('name')
+ tmp = ''
+ for i in district:
+ tmp +=''+i.name+' '
+ if(tmp):
+ data['district'] = ' -- None -- '+tmp
+ else:
+ data['district'] = tmp
+ if request.POST.get('fields[city]'):
+ city = City.objects.filter(state=state).order_by('name')
+ tmp = ''
+ for i in city:
+ tmp +=''+i.name+' '
+ if(tmp):
+ data['city'] = ' -- None -- '+tmp
+ else:
+ data['city'] = tmp
+ return HttpResponse(json.dumps(data), content_type='application/json')
+
+
+@csrf_exempt
+def ajax_ac_location(request):
+ """ Ajax: Get the location based on district selected """
+ if request.method == 'POST':
+ district = request.POST.get('district')
+ location = Location.objects.filter(district=district).order_by('name')
+ tmp = ' -- None -- '
+ for i in location:
+ tmp +=''+i.name+' '
+ return HttpResponse(json.dumps(tmp), content_type='application/json')
+
+@csrf_exempt
+def ajax_district_data(request):
+ """ Ajax: Get the location based on district selected """
+ data = {}
+ if request.method == 'POST':
+ tmp = ''
+ district = request.POST.get('district')
+ if district and district != None:
+ if request.POST.get('fields[location]'):
+ location = Location.objects.filter(district_id=district).order_by('name')
+ tmp = ' -- None -- '
+ for i in location:
+ tmp +=''+i.name+' '
+ data['location'] = tmp
+
+ if request.POST.get('fields[institute]'):
+ collages = AcademicCenter.objects.filter(district=district).order_by('institution_name')
+ if collages:
+ tmp = ' -- None -- '
+ for i in collages:
+ tmp +=''+i.institution_name+' '
+ data['institute'] = tmp
+
+ return HttpResponse(json.dumps(data), content_type='application/json')
+
+@csrf_exempt
+def ajax_ac_pincode(request):
+ """ Ajax: Get the pincode based on location selected """
+ if request.method == 'POST':
+ location = request.POST.get('location')
+ location = Location.objects.get(pk=location)
+ return HttpResponse(json.dumps(location.pincode), content_type='application/json')
+
+@csrf_exempt
+def ajax_district_collage(request):
+ """ Ajax: Get the Colleges (Academic) based on District selected """
+ if request.method == 'POST':
+ district = request.POST.get('district')
+ collages = AcademicCenter.objects.filter(district=district).order_by('institution_name')
+ tmp = None
+ if collages:
+ tmp = ' -- None -- '
+ for i in collages:
+ tmp +=''+i.institution_name+' '
+ return HttpResponse(json.dumps(tmp), content_type='application/json')
+
+@csrf_exempt
+def ajax_state_collage(request):
+ """ Ajax: Get the Colleges (Academic) based on District selected """
+ if request.method == 'POST':
+ state = request.POST.get('state')
+ collages = AcademicCenter.objects.filter(state=state).order_by('institution_name')
+ tmp = ' --------- '
+ if collages:
+ for i in collages:
+ tmp +=''+i.institution_name+', '+i.academic_code+' '
+ return HttpResponse(json.dumps(tmp), content_type='application/json')
+
+
+@csrf_exempt
+def ajax_academic_center(request):
+ """Ajax: Get academic centers according to institute type and state"""
+
+ if request.method == 'POST':
+ state = request.POST.get('state')
+ itype = request.POST.get('itype')
+ center = AcademicCenter.objects.filter(state=state,
+ institution_type=itype).order_by('institution_name')
+ html = ' --------- '
+ if center:
+ for ac in center:
+ html += '{1} '.format(ac.id,
+ ac.institution_name)
+ return HttpResponse(json.dumps(html),
+ content_type='application/json')
+
+
+@csrf_exempt
+def ajax_dept_foss(request):
+ """ Ajax: Get the dept and foss based on training selected """
+ data = {}
+ if request.method == 'POST':
+ tmp = ''
+ category = int(request.POST.get('fields[type]'))
+ print(category)
+ print((request.POST))
+ if category == 1:
+ print((request.POST))
+ training = request.POST.get('workshop')
+ if request.POST.get('fields[dept]'):
+ dept = Department.objects.filter(training__id = training).order_by('name')
+ for i in dept:
+ tmp +=''+i.name+' '
+ data['dept'] = tmp
+
+ if request.POST.get('fields[foss]'):
+ training = Training.objects.filter(pk=training).order_by('name')
+ tmp = ' -- None -- '
+ if training:
+ tmp +=''+training[0].foss.foss+' '
+ data['foss'] = tmp
+ elif category == 0:
+ workshop = request.POST.get('workshop')
+ if request.POST.get('fields[dept]'):
+ dept = Department.objects.filter(training__id = workshop).order_by('name')
+ for i in dept:
+ tmp +=''+i.name+' '
+ data['dept'] = tmp
+
+ if request.POST.get('fields[foss]'):
+ workshop = Training.objects.filter(pk=workshop)
+ tmp = ' -- None -- '
+ if workshop:
+ tmp +=''+workshop[0].foss.foss+' '
+ data['foss'] = tmp
+ else:
+ dept = Department.objects.all().order_by('name')
+ for i in dept:
+ tmp +=''+i.name+' '
+ data['dept'] = tmp
+
+ tmp = ' -- None -- '
+ foss = FossCategory.objects.all(status = 1)
+ for i in foss:
+ tmp +=''+i.foss+' '
+ data['foss'] = tmp
+ return HttpResponse(json.dumps(data), content_type='application/json')
+
+@csrf_exempt
+def ajax_language(request):
+ """ Ajax: Get the Colleges (Academic) based on District selected """
+ if request.method == 'POST':
+ foss = request.POST.get('foss')
+ tmp = ' --------- '
+ if foss:
+ language = FossAvailableForWorkshop.objects.select_related().filter(foss_id=foss)
+ for i in language:
+ tmp +=''+i.language.name+' '
+ return HttpResponse(json.dumps(tmp), content_type='application/json')
+
+@csrf_exempt
+def test(request):
+ academics = AcademicCenter.objects.filter(Q(institution_name__icontains="Engineering")).exclude(Q(institution_type__name="Engineering") | Q(institution_type__name="Polytechnic") | Q(institution_type__name="ITI") | Q(institution_type__name="University"))
+ for academic in academics:
+ print((academic.institution_name, " => ", academic.institution_type))
+ academic.institution_type = InstituteType.objects.get(name='Engineering')
+ academic.save()
+ return HttpResponse("Done!")
+
+@csrf_exempt
+def ajax_check_foss(request):
+ """ Ajax: Get the get the foss name of selected batch """
+ training = request.GET.get('training',None)
+ trid = TrainingRequest.objects.get(pk=training)
+ foss_id = trid.course.foss.id
+
+ # is_c_and_cpp = False
+
+ is_multiquiz_foss = False
+ multiquiz_foss = 0
+
+ if foss_id == 43:
+ is_multiquiz_foss = True
+ multiquiz_foss = 43
+
+ if foss_id == 97:
+ is_multiquiz_foss = True
+ multiquiz_foss = 97
+ data = {
+ "is_multiquiz_foss": is_multiquiz_foss,
+ "multiquiz_foss": multiquiz_foss
+ }
+ return JsonResponse(data)
+
+@csrf_exempt
+def activate_academics(request):
+ context = {}
+ collection = None
+ header = {
+ 1: SortableHeader('#', False),
+ 2: SortableHeader('State', False),
+ 3: SortableHeader('institution_name', True, 'Institution Name'),
+ 4: SortableHeader('academic_code', True, 'Academic Code'),
+ 5: SortableHeader('Action', False),
+ 6: SortableHeader('Status', False)
+ }
+ print(request)
+ if request.method == 'POST':
+ collegeid = request.POST.get('collegeid')
+ action = request.POST.get('action')
+
+ if action == 'activate':
+ activate_academic_org(collegeid)
+
+ if action == 'deactivate':
+ deactivate_academic_org(collegeid)
+
+ return HttpResponseRedirect("/software-training/activate-academics/")
+ else:
+ status = request.GET.get('status')
+ if status:
+ collection = AcademicCenter.objects.filter(status=status).order_by('state__name', 'institution_name')
+ else:
+ collection = AcademicCenter.objects.filter(status=3).order_by('state__name', 'institution_name')
+
+ raw_get_data = request.GET.get('o', None)
+ collection = get_sorted_list(request, collection, header, raw_get_data)
+ ordering = get_field_index(raw_get_data)
+
+ collection = ActivateAcademicCenterFilter(request.GET, queryset=collection)
+
+ context['form'] = collection.form
+ page = request.GET.get('page')
+ collection = get_page(collection.qs, page)
+
+
+ context['collection'] = collection
+ context['header'] = header
+ context['ordering'] = ordering
+
+
+
+ return render(request, 'activate_academics.html', context)
+
+def activate_academic_org(academic_id):
+ ac = AcademicCenter.objects.get(id=academic_id)
+ deactivate_status = 3
+ if ac:
+ #check if college paid the subscription fees
+ #activate all organiser fom this college
+ organisers_from_academic = Organiser.objects.filter(status=deactivate_status, academic_id=ac.id)
+ invigilators_from_academic = Invigilator.objects.filter(status=deactivate_status, academic_id=ac.id)
+
+ for organiser in organisers_from_academic:
+ #all the organisers from this academic are activated here.
+ organiser.status = 1
+ organiser.save()
+
+ for invigilator in invigilators_from_academic:
+ #all the organisers from this academic are activated here.
+ invigilator.status = 1
+ invigilator.save()
+
+ #Activate that collge
+ ac.status = 1
+ ac.save()
+
+
+def deactivate_academic_org(academic_id):
+ ac = AcademicCenter.objects.get(id=academic_id)
+ activate_status = 1
+ if ac:
+ #check if college paid the subscription fees
+ #activate all organiser fom this college
+ organisers_from_academic = Organiser.objects.filter(status=activate_status, academic_id=ac.id)
+ invigilators_from_academic = Invigilator.objects.filter(status=activate_status, academic_id=ac.id)
+ for organiser in organisers_from_academic:
+ #all the organisers from this academic are activated here.
+ organiser.status = 3
+ organiser.save()
+
+ for invigilator in invigilators_from_academic:
+ #all the organisers from this academic are activated here.
+ invigilator.status = 3
+ invigilator.save()
+
+ #Activate that collge
+ ac.status = 3
+ ac.save()
+
+def key_verification(serial):
+ context = {}
+ try:
+ certificate = TestAttendance.objects.get(password=serial)
+ if not certificate.student:
+ name = certificate.mdluser_firstname+" "+certificate.mdluser_lastname
+ else:
+ name = certificate.student.user.first_name+ " "+certificate.student.user.last_name
+
+
+ grade = get_moodle_grade(certificate.mdluser_id, certificate.mdlquiz_id)
+ print(grade.grade)
+ foss = certificate.test.foss.foss
+ tdate = certificate.test.tdate
+ detail = {}
+ detail['Participant_Name'] = name
+ detail['Foss'] = foss
+ detail['Test_Date'] = tdate
+ detail['grade'] = grade.grade
+
+ context['certificate'] = certificate
+ context['detail'] = detail
+ context['serial_no'] = True
+ except TestAttendance.DoesNotExist:
+ context["invalidserial"] = 1
+ return context
+
+@csrf_exempt
+def verify_test_certificate(request):
+ context = {}
+ ci = RequestContext(request)
+ if request.method == 'POST':
+ serial_no = request.POST.get('serial_no').strip()
+ context = key_verification(serial_no)
+ return render(request, 'verify_test_certificate.html', context)
+ return render(request, 'verify_test_certificate.html', {})
+
+def check_user_email_exist(email):
+ users = User.objects.filter(email=email)
+ if users.exists():
+ user = users.first()
+ return user
+ return None
+
+def check_email_already_organiser(userid):
+ org = Organiser.objects.filter(user_id=userid)
+ if org.exists():
+ return org
+ return None
+
+@login_required
+def handover(request):
+ user = request.user
+ context = {}
+ if not (user.is_authenticated() and (is_event_manager(user))):
+ raise PermissionDenied()
+ # ci = RequestContext(request)
+ if request.method == 'POST':
+ old_email = request.POST.get('old_email').strip()
+ new_email = request.POST.get('new_email').strip()
+
+ #check if old email id registerd or not
+ old_user = check_user_email_exist(old_email)
+ if old_user:
+ #check if old email id organiser or not
+ old_org = check_email_already_organiser(old_user.id)
+ if not old_org:
+ context['msg'] = 'Old organiser entry not found.'
+ context['error_status'] = 'True'
+ return render(request, 'handover.html', context)
+ else:
+ context['msg'] = 'Old organiser entry not found. Not a registered user.'
+ context['error_status'] = 'True'
+ return render(request, 'handover.html', context)
+
+
+ #check if new email id registerd or not
+ new_user = check_user_email_exist(new_email)
+ if new_user:
+ new_org = check_email_already_organiser(new_user.id)
+ if new_org:
+ context['msg'] = 'New user is already an organiser. Can not continue work handover.'
+ context['error_status'] = 'True'
+ return render(request, 'handover.html', context)
+ else:
+ organiser = Organiser.objects.filter(user_id=old_user.id).update(user_id=new_user.id)
+
+ old_user.groups.remove(Group.objects.get(name='Organiser'))
+ new_user.groups.add(Group.objects.get(name='Organiser'))
+
+ context['msg'] = 'Organiser work handover completed successfully.'
+ context['error_status'] = 'False'
+
+ else:
+ context['msg'] = 'New user is not registerd with spoken-tutorial'
+ context['error_status'] = 'True'
+ return render(request, 'handover.html', context)
+
+ return render(request, 'handover.html', context)
+
+def reset_student_pwd(request):
+ context = {}
+ template = 'events/templates/reset_student_password.html'
+ form = StudentPasswordResetForm()
+ context['form'] = form
+
+ if request.method == "POST":
+ form = StudentPasswordResetForm(request.POST)
+ context['form'] = form
+
+ if form.is_valid():
+ school = form.cleaned_data['school']
+ batches = form.cleaned_data['batches']
+ new_password = form.cleaned_data['new_password']
+
+ batch_ids = [x.id for x in batches]
+ batches = StudentBatch.objects.filter(id__in=batch_ids)
+ student_ids = StudentMaster.objects.filter(batch__in=batches).values_list('student_id', flat=True)
+ students = Student.objects.filter(id__in=student_ids)
+ students.update(verified=1, error=0)
+ user_ids = [stu.user_id for stu in students]
+ users = User.objects.filter(id__in=user_ids)
+ new_hashed_pwd = make_password(new_password)
+ users.update(password=new_hashed_pwd, is_active=1)
+ emails = [user.email for user in users]
+ mdlUsers = MdlUser.objects.filter(email__in=emails)
+ mdlUsers.update(password=encript_password(new_password))
+ send_bulk_student_reset_mail(school,batches,users.count(), new_password,request.user)
+
+ # Add the success message
+ success_msg = "Password updated for {} students.".format(users.count())
+ messages.success(request, success_msg)
+
+
+ redirect_url = reverse('events:reset_student_pwd')
+ return HttpResponseRedirect(redirect_url)
+ return render(request,template,context)
+
+
+def get_schools(request):
+ state_id = request.GET.get('state_id')
+ if state_id:
+ schools = AcademicCenter.objects.filter(
+ state_id=state_id,
+ studentbatch__isnull=False).distinct().values(
+ 'id', 'institution_name', 'academic_code').order_by('institution_name')
+ return JsonResponse(list(schools), safe=False)
+ return JsonResponse([])
+
+
+
diff --git a/events/events/viewsv2.py b/events/events/viewsv2.py
new file mode 100644
index 000000000..5e5d6f795
--- /dev/null
+++ b/events/events/viewsv2.py
@@ -0,0 +1,3716 @@
+from builtins import str
+from builtins import range
+from builtins import object
+from django.shortcuts import render
+import time
+from datetime import datetime
+from datetime import date
+from datetime import timedelta
+import re
+from django.conf import settings
+from rq import Queue
+import os
+
+from config import TARGET, CHANNEL_ID, CHANNEL_KEY, EXCLUDE_FROM_STP
+# Create your views here.
+from django.views.generic import View, ListView
+from django.views.generic.edit import CreateView, UpdateView, DeleteView
+from events.models import *
+from donate.models import *
+from training.models import *
+from events.filters import TrainingRequestFilter
+from django.core.exceptions import ObjectDoesNotExist
+from django.db import IntegrityError
+from django.utils.decorators import method_decorator
+from events.decorators import group_required
+from events import display
+from events.forms import StudentBatchForm, TrainingRequestForm, \
+ TrainingRequestEditForm, CourseMapForm, SingleTrainingForm, \
+ OrganiserFeedbackForm,STWorkshopFeedbackForm,STWorkshopFeedbackFormPre,STWorkshopFeedbackFormPost,LearnDrupalFeedbackForm, LatexWorkshopFileUploadForm, UserForm, \
+ SingleTrainingEditForm,TrainingManagerForm
+
+from django.http import HttpResponse, HttpResponseRedirect
+from django.shortcuts import render, redirect
+from django.core.validators import validate_email
+from django.contrib.auth.models import Group, User
+from django.template import RequestContext
+from django.views.decorators.csrf import csrf_exempt
+from django.middleware import csrf
+from django.views.decorators.csrf import csrf_protect
+from django.http import JsonResponse
+from django.core.exceptions import PermissionDenied
+from creation.models import FossAvailableForWorkshop
+import csv
+from cms.sortable import *
+from django.contrib import messages
+from django.template import RequestContext, loader
+from mdldjango.get_or_create_participant import get_or_create_participant
+from django.contrib.auth.decorators import login_required
+from mdldjango.models import MdlUser, MdlQuizGrades
+from django.contrib.auth.mixins import UserPassesTestMixin
+from events.formsv2 import StudentGradeFilterForm, AcademicPaymentStatusForm
+from django.views.generic import FormView
+
+#pdf generate
+from reportlab.pdfgen import canvas
+from reportlab.lib.pagesizes import letter, landscape
+from reportlab.platypus import Paragraph
+from reportlab.lib.styles import ParagraphStyle
+from reportlab.lib.units import cm
+from reportlab.lib.enums import TA_CENTER
+from PyPDF2 import PdfFileWriter, PdfFileReader
+from events.views import get_page
+from io import BytesIO
+from django.db.models import Q
+from cron import TOPPER_QUEUE, REDIS_CLIENT, DEFAULT_QUEUE
+import uuid
+from django.core.cache import caches
+from rq.job import Job
+from rq import Worker
+# import helpers
+from events.views import is_organiser, is_invigilator, is_resource_person, is_administrator, is_accountexecutive
+from events.helpers import get_prev_semester_duration, get_updated_form
+from cron.tasks import async_filter_student_grades, filter_student_grades
+from spoken.config import TOPPER_WORKER_STATUS
+from django.db import connection
+from donate.utils import send_transaction_email
+from .certificates import *
+
+class JSONResponseMixin(object):
+ """
+ A mixin that can be used to render a JSON response.
+ """
+ def render_to_json_response(self, context, **response_kwargs):
+ """
+ Returns a JSON response, transforming 'context' to make the payload.
+ """
+ return JsonResponse(
+ self.get_data(context),
+ **response_kwargs
+ )
+
+ def get_data(self, context):
+ """
+ Returns an object that will be serialized as JSON by json.dumps().
+ """
+ # Note: This is *EXTREMELY* naive; in reality, you'll need
+ # to do much more complex handling to ensure that arbitrary
+ # objects -- such as Django model instances or querysets
+ # -- can be serialized as JSON.
+ return context
+
+# This class is to display the taining planner details of that organiser on main page of STP.
+class TrainingPlannerListView(ListView):
+ queryset = None
+ paginate_by = 20
+ user = None
+ template_name = None
+ @method_decorator(group_required("Organiser"))
+ # following function is only applicable to organiser login
+ def dispatch(self, *args, **kwargs):
+ self.user = self.request.user
+ self.get_current_planner()
+ self.queryset = TrainingPlanner.objects.filter(
+ organiser_id = self.request.user.organiser.id,
+ academic_id = self.request.user.organiser.academic.id,
+ ).order_by('-year')
+ return super(TrainingPlannerListView, self).dispatch(*args, **kwargs)
+
+ def get_context_data(self, **kwargs):
+ # Call the base implementation first to get a context
+ context = super(TrainingPlannerListView, self).get_context_data(**kwargs)
+ # Add in a QuerySet of all the books
+ context['current_planner'] = self.get_current_planner()
+ context['next_planner'] = self.get_next_planner(context['current_planner'])
+ return context
+
+ #def get(self, request):
+ # return render(request, self.template_name)
+
+ def post(self, request):
+ return HttpResponse('Post')
+
+ def is_even_sem(self, month):
+ # 0 => odd sem, 1 => even sem
+ if month > 6 and month < 13:
+ return 0
+ return 1
+
+ def get_year(self, sem, year):
+ if sem:
+ return year - 1
+ return year
+
+ def get_semester(self, sem):
+ return Semester.objects.get(even=sem)
+
+ def get_current_planner(self):
+ now = datetime.datetime.now()
+ sem = self.is_even_sem(now.month)
+ year = self.get_year(sem, now.year)
+ try:
+ return TrainingPlanner.objects.get(year=year, semester__even=sem, \
+ academic=self.user.organiser.academic, organiser=self.user.organiser)
+ except ObjectDoesNotExist:
+ return TrainingPlanner.objects.create(year=year, \
+ semester=self.get_semester(sem), academic=self.user.organiser.academic,\
+ organiser=self.user.organiser)
+ except Exception as e:
+ print(e)
+ return False
+ def get_next_planner(self, current_planner):
+ year = int(current_planner.year)
+ even = True
+ if current_planner.semester.even:
+ year = year + 1
+ even = False
+ sem = self.get_semester(even)
+ try:
+ next_planner = TrainingPlanner.objects.get(year=year, semester=sem, \
+ academic=self.user.organiser.academic, organiser=self.user.organiser)
+ return next_planner
+ except ObjectDoesNotExist:
+ return TrainingPlanner.objects.create(year=year, \
+ semester=sem, academic=self.user.organiser.academic, \
+ organiser=self.user.organiser)
+ except Exception as e:
+ print(e)
+ return False
+
+@csrf_exempt
+def get_language_level_option(request):
+ """
+ AJAX endpoint that returns HTML for language and level tags.
+ """
+ try:
+ foss_category = request.POST.get('foss_category', '').strip()
+ course_id = request.POST.get('course_id', '').strip()
+
+ # Show language/level only for "Training and Test"
+ show_for_tests = (foss_category == '1')
+ data = {'languages': '', 'levels': ''}
+
+ if not show_for_tests:
+ return JsonResponse(data)
+
+ # Get all languages and levels
+ languages = Language.objects.all().order_by('code')
+ levels = Level.objects.all().order_by('code')
+
+ # Build language options - Force English as selected
+ lang_options = ' --------- '
+ english_selected = False
+ for lang in languages:
+ selected = ''
+ # Check if this is English
+ if (hasattr(lang, 'code') and lang.code and 'english' in lang.code.lower()) or \
+ (hasattr(lang, 'name') and lang.name and 'english' in lang.name.lower()):
+ selected = ' selected'
+ english_selected = True
+ lang_options += f'{lang.name if hasattr(lang, "name") else str(lang)} '
+
+ # If no English was found, select the first one
+ if not english_selected and languages.exists():
+ # Replace the first option with selected
+ first_lang = languages.first()
+ lang_options = lang_options.replace(
+ f'',
+ f' '
+ )
+
+ # Build level options - Force Advanced as selected
+ level_options = ' --------- '
+ advanced_selected = False
+ for level in levels:
+ selected = ''
+ # Check if this is Advanced
+ if (hasattr(level, 'code') and level.code and 'advanced' in level.code.lower()) or \
+ (hasattr(level, 'name') and level.name and 'advanced' in level.name.lower()):
+ selected = ' selected'
+ advanced_selected = True
+ level_options += f'{level.name if hasattr(level, "name") else str(level)} '
+
+ # If no Advanced was found, select the first one
+ if not advanced_selected and levels.exists():
+ # Replace the first option with selected
+ first_level = levels.first()
+ level_options = level_options.replace(
+ f'',
+ f' '
+ )
+
+ data['languages'] = lang_options
+ data['levels'] = level_options
+
+ return JsonResponse(data)
+
+ except Exception as e:
+ # Fallback with English and Advanced as defaults
+ data = {
+ 'languages': ' --------- English ',
+ 'levels': '--------- Advanced '
+ }
+ return JsonResponse(data)
+
+
+# @csrf_exempt
+# def get_language_level_option(request):
+# """
+# AJAX endpoint that returns HTML for language and level tags.
+# """
+# try:
+# foss_category = request.POST.get('foss_category', '').strip()
+# course_id = request.POST.get('course_id', '').strip()
+
+# # Show language/level only for "Training and Test"
+# show_for_tests = (foss_category == '1')
+# data = {'languages': '', 'levels': ''}
+
+# if not show_for_tests:
+# return JsonResponse(data)
+
+# # Get all languages and levels
+# languages = Language.objects.all().order_by('code')
+# levels = Level.objects.all().order_by('code')
+
+# # Build language options - Force English as selected
+# lang_options = ' --------- '
+# english_selected = False
+# for lang in languages:
+# selected = ''
+# # Check if this is English
+# if (hasattr(lang, 'code') and lang.code and 'english' in lang.code.lower()) or \
+# (hasattr(lang, 'name') and lang.name and 'english' in lang.name.lower()):
+# selected = ' selected'
+# english_selected = True
+# lang_options += f'{lang.name if hasattr(lang, "name") else str(lang)} '
+
+# # If no English was found, select the first one
+# if not english_selected and languages.exists():
+# # Replace the first option with selected
+# first_lang = languages.first()
+# lang_options = lang_options.replace(
+# f'',
+# f' '
+# )
+
+# # Build level options - Force Advanced as selected
+# level_options = ' --------- '
+# advanced_selected = False
+# for level in levels:
+# selected = ''
+# # Check if this is Advanced
+# if (hasattr(level, 'code') and level.code and 'advanced' in level.code.lower()) or \
+# (hasattr(level, 'name') and level.name and 'advanced' in level.name.lower()):
+# selected = ' selected'
+# advanced_selected = True
+# level_options += f'{level.name if hasattr(level, "name") else str(level)} '
+
+# # If no Advanced was found, select the first one
+# if not advanced_selected and levels.exists():
+# # Replace the first option with selected
+# first_level = levels.first()
+# level_options = level_options.replace(
+# f'',
+# f' '
+# )
+
+# data['languages'] = lang_options
+# data['levels'] = level_options
+
+# return JsonResponse(data)
+
+# except Exception as e:
+# # Fallback with English and Advanced as defaults
+# data = {
+# 'languages': ' --------- English ',
+# 'levels': '--------- Advanced '
+# }
+# return JsonResponse(data)
+
+
+class StudentBatchCreateView(CreateView):
+ form_class = None
+ template_name = None
+ user = None
+ batch = None
+ organiser = None
+
+ @method_decorator(group_required("Organiser"))
+ def dispatch(self, *args, **kwargs):
+ if 'bid' in kwargs:
+ sb = StudentBatch.objects.filter(pk=kwargs['bid'])
+ if sb.exists():
+ self.batch = sb.first()
+ return super(StudentBatchCreateView, self).dispatch(*args, **kwargs)
+
+ #def get_form_kwargs(self):
+ # kwargs = super(StudentBatchCreateView, self).get_form_kwargs()
+ # kwargs.update({'user' : self.request.user})
+ # return kwargs
+
+ def get_context_data(self, **kwargs):
+ context = super(StudentBatchCreateView, self).get_context_data(**kwargs)
+ if self.batch:
+ existing_student = Student.objects.filter(
+ id__in=StudentMaster.objects.filter(
+ batch_id=self.batch.id,
+ moved=False
+ ).values_list(
+ 'student_id'
+ )
+ )
+ context['batch'] = self.batch
+ context['existing_student'] = existing_student
+ return context
+
+ def post(self, request, *args, **kwargs):
+ self.object = None
+ self.user = request.user
+ form_class = self.get_form_class()
+ form = self.get_form(form_class)
+ if form.is_valid():
+ return self.form_valid(form)
+ else:
+ return self.form_invalid(form)
+
+ def form_valid(self, form, **kwargs):
+ form_data = form.save(commit=False)
+ form_data.academic = self.user.organiser.academic
+ self.organiser = self.user.organiser
+ form_data.organiser = self.user.organiser
+ studentcount = 0
+
+
+ if 'bid' in self.kwargs:
+ try:
+ form_data = StudentBatch.objects.get(pk=self.kwargs['bid'])
+ except StudentBatch.DoesNotExist:
+ messages.error(self.request, 'Invalid Batch Id')
+ return self.form_invalid(form)
+ studentcount = form_data.stcount
+ if studentcount >= 500 :
+ messages.error(self.request, 'Can not add more than 500 students in one batch.')
+ return self.form_invalid(form)
+ else:
+ # new MB
+ # one organiser for one department
+ # It will check only the new department batch upload
+ # Will allow to upload if organiser already having batch for that department
+
+ department = StudentBatch.objects.filter(department=form.cleaned_data['department'],year=form.cleaned_data['year'], academic=self.user.organiser.academic )
+ this_organiser_dept = department.filter(organiser=self.request.user.organiser);
+
+ if not this_organiser_dept.exists() and department.exists():
+ messages.error(self.request, "%s department is already assigened to organiser %s in your College." % (form.cleaned_data['department'], department.first().organiser))
+ return self.form_invalid(form)
+ form_data.save()
+ batch_name = StudentBatch.objects.get(pk=form_data.id).create_batch_name()
+
+
+ # StudentBatch.objects.get(pk=batch_id).update_student_count()
+
+ skipped, error, warning, write_flag = \
+ self.csv_email_validate(form.cleaned_data['csv_file'], form_data.id , studentcount)
+ context = {'error' : error, 'warning' : warning, 'batch':form_data}
+
+ if error or warning:
+ return render(self.request, self.template_name, context)
+ return HttpResponseRedirect('/software-training/student-batch/%s/new/'%(str(form_data.id)))
+
+ def email_validator(self, email):
+ if email and email.strip():
+ email = email.strip().lower()
+ try:
+ validate_email(email)
+ return True
+ except:
+ pass
+ return False
+
+ def get_student(self, email):
+ if email and email.strip():
+ email = email.strip().lower()
+ try:
+ student = Student.objects.get(user__email=email)
+ return student
+ except ObjectDoesNotExist:
+ pass
+ return False
+
+ def create_student(self, fname, lname, email, gender):
+ # check params for empty/None
+ if not fname or not lname or not email or not gender:
+ return False
+ user = None
+ fname = fname.strip().upper()
+ lname = lname.strip().upper()
+ email = email.strip().lower()
+ gender = gender.strip().lower()
+ # check stripped params for non-empty
+ if fname and lname and email and gender:
+ if gender == 'male' or gender == 'm':
+ gender = 'Male'
+ else:
+ gender = 'Female'
+ try:
+ user = User.objects.get(email = email)
+ except ObjectDoesNotExist:
+ user = User.objects.create_user(email, email, fname)
+ user.is_active = False
+ if user:
+ user.first_name = fname
+ user.last_name = lname
+ user.save()
+ try:
+ student_group = Group.objects.get(name = 'Student')
+ user.groups.add(student_group)
+ except:
+ pass
+ student = Student.objects.create(user = user, gender = gender)
+ get_or_create_participant(self.organiser, fname, lname, gender, email, 0)
+ return student
+ return False
+
+ def csv_email_validate(self, file_data, batch_id , studentcount):
+ skipped = []
+ error = []
+ warning = []
+ write_flag = False
+ stu_row_count = 0
+ try:
+ rowcsv = csv.reader(file_data, delimiter=',', quotechar='|')
+ rowcount = len(list(rowcsv))
+ gencount = studentcount + rowcount
+ if rowcount > 500:
+ messages.warning(self.request, "MB will accept only 500 students, if number is more than 500, divide the batch and upload under different departments eg. Chemistry1 & Chemistry2")
+ if gencount > 500:
+ messages.warning(self.request, "Total number of students per Master Batch exceeding. Masterbatch can accept maximum 500 students.")
+ else :
+ csvdata = csv.reader(file_data, delimiter=',', quotechar='|')
+ for row in csvdata:
+ stu_row_count = stu_row_count+1
+ if len(row) < 4:
+ skipped.append(row)
+ continue
+ if not self.email_validator(row[2]):
+ error.append(row)
+ continue
+ student = self.get_student(row[2])
+ if not student:
+ student = self.create_student(row[0], row[1], row[2], row[3])
+ if student:
+ try:
+ smrec = StudentMaster.objects.get(student=student, moved=False)
+ if int(batch_id) == int(smrec.batch_id):
+ row.append('Already exists in this batch.')
+ else:
+ row.append('Already exists in %s, %s' % (smrec.batch, smrec.batch.academic))
+ warning.append(row)
+ continue
+ except ObjectDoesNotExist:
+ StudentMaster.objects.create(student=student, batch_id=batch_id)
+ write_flag = True
+
+ StudentBatch.objects.get(pk=batch_id).update_student_count()
+ except Exception as e:
+ print(e)
+ messages.warning(self.request, "The file you uploaded is not a valid CSV file, please add a valid CSV file")
+ return skipped, error, warning, write_flag
+
+class StudentBatchUpdateView(UpdateView):
+ model = StudentBatch
+ success_url = "/software-training/student-batch/"
+ sb = None
+ @method_decorator(group_required("Organiser"))
+ def dispatch(self, *args, **kwargs):
+ self.sb = StudentBatch.objects.get(pk=kwargs['pk'])
+ return super(StudentBatchUpdateView, self).dispatch(*args, **kwargs)
+
+ def get_context_data(self, **kwargs):
+ context = super(StudentBatchUpdateView, self).get_context_data(**kwargs)
+ context['sb'] = self.sb
+ return context
+
+ def form_valid(self, form, **kwargs):
+ try:
+ if str(self.sb.year) == str(form.cleaned_data['year']) and str(self.sb.department) == str(form.cleaned_data['department']):
+ return HttpResponseRedirect(self.success_url)
+ print('****************',form.cleaned_data['year'], self.request.user.organiser.academic.id)
+ print('****************',str(form.cleaned_data['department']))
+
+ sb = StudentBatch.objects.filter(~Q(organiser_id=self.request.user.organiser.id),
+ department=form.cleaned_data['department'],
+ year = form.cleaned_data['year'],
+ academic_id=self.request.user.organiser.academic.id
+ )
+ print(sb)
+ if sb:
+ messages.warning(self.request, "%s - %s Batch is already chosen by another Organiser in your College." % (sb.department, sb.year))
+ return self.form_invalid(form)
+ form.save()
+ batch_name = StudentBatch.objects.get(pk=self.sb.id).create_batch_name()
+
+
+ except:
+ pass
+ return HttpResponseRedirect(self.success_url)
+
+class StudentBatchYearUpdateView(UpdateView):
+ model = StudentBatch
+ success_url = "/software-training/student-batch/"
+
+class StudentBatchListView(ListView):
+ queryset = StudentBatch.objects.none()
+ paginate_by = 20
+ template_name = ""
+ header = None
+ raw_get_data = None
+ @method_decorator(group_required("Organiser"))
+ def dispatch(self, *args, **kwargs):
+ self.queryset = StudentBatch.objects.filter(academic_id=self.request.user.organiser.academic_id)
+ self.header = {
+ 1: SortableHeader('#', False),
+ 2: SortableHeader('batch_name', True, 'Batch Name'),
+ 3: SortableHeader('academic', True, 'Institution'),
+ 4: SortableHeader('department', True, 'Department'),
+ 5: SortableHeader('year', True, 'Year'),
+ 6: SortableHeader('stcount', True, 'Student Count'),
+ 7: SortableHeader('', False, ''),
+ }
+ self.raw_get_data = self.request.GET.get('o', None)
+ self.queryset = get_sorted_list(self.request, self.queryset, self.header, self.raw_get_data)
+ return super(StudentBatchListView, self).dispatch(*args, **kwargs)
+
+ def get_context_data(self, **kwargs):
+ context = super(StudentBatchListView, self).get_context_data(**kwargs)
+ context['header'] = self.header
+ context['ordering'] = get_field_index(self.raw_get_data)
+ return context
+
+class StudentListView(ListView):
+ queryset = Student.objects.none()
+ paginate_by = 30
+ template_name = None
+ batch = None
+ header = None
+ raw_get_data = None
+ @method_decorator(group_required("Organiser"))
+ def dispatch(self, *args, **kwargs):
+ self.batch = StudentBatch.objects.filter(pk=kwargs['bid'])
+ if not self.batch.exists():
+ return HttpResponseRedirect('/student-batch')
+ self.batch = self.batch.first()
+ self.header = {
+ 1: SortableHeader('#', False),
+ 2: SortableHeader('Edit', False),
+ 3: SortableHeader('', False, 'Department'),
+ 4: SortableHeader('', False, 'Year'),
+ 5: SortableHeader('user__first_name', True, 'First Name'),
+ 6: SortableHeader('user__last_name', True, 'Last Name'),
+ 7: SortableHeader('user__email', True, 'Email'),
+ 8: SortableHeader('gender', True, 'Gender'),
+ 9: SortableHeader('', False, 'Status'),
+ 10: SortableHeader('', False, ''),
+ }
+ self.queryset = Student.objects.filter(
+ id__in = StudentMaster.objects.filter(
+ batch_id=self.batch.id,
+ moved=False
+ ).values_list(
+ 'student'
+ )
+ )
+ self.raw_get_data = self.request.GET.get('o', None)
+ self.queryset = get_sorted_list(self.request, self.queryset, self.header, self.raw_get_data)
+ return super(StudentListView, self).dispatch(*args, **kwargs)
+
+ def get_context_data(self, **kwargs):
+ context = super(StudentListView, self).get_context_data(**kwargs)
+ context['header'] = self.header
+ context['ordering'] = get_field_index(self.raw_get_data)
+ context['batch'] = self.batch
+ return context
+
+class TrainingRequestCreateView(CreateView):
+ form_class = TrainingRequestForm
+ template_name = None
+ user = None
+ tpid = None
+
+ @method_decorator(group_required("Organiser"))
+ def dispatch(self, *args, **kwargs):
+ if not StudentBatch.objects.filter(academic=self.request.user.organiser.academic).exists():
+ messages.warning(self.request, 'Please upload the master batch.')
+ return HttpResponseRedirect("/software-training/training-planner")
+
+ if 'tpid' in self.kwargs:
+ self.tpid = self.kwargs['tpid']
+ training_planner = TrainingPlanner.objects.filter(pk=self.tpid, organiser_id = self.request.user.organiser.id)
+ if not training_planner.exists():
+ # message say Not found
+ messages.warning(self.request, 'Invalid Training Planner ID passed')
+ return HttpResponseRedirect("/software-training/training-planner")
+ else:
+ training_planner = training_planner.first()
+ if not training_planner.is_current_planner() and not training_planner.is_next_planner():
+ messages.warning(self.request, 'Selected Training Planner is already expired')
+ return HttpResponseRedirect("/software-training/training-planner")
+ return super(TrainingRequestCreateView, self).dispatch(*args, **kwargs)
+
+ def get_context_data(self, **kwargs):
+ context = super(TrainingRequestCreateView, self).get_context_data(**kwargs)
+ context['training_planner_id'] = self.tpid
+ context['tp'] = TrainingPlanner.objects.filter(pk=self.tpid, organiser_id = self.request.user.organiser.id)[0]
+ return context
+
+ def get_form_kwargs(self):
+ kwargs = super(TrainingRequestCreateView, self).get_form_kwargs()
+ kwargs.update({'user' : self.request.user})
+ username = self.request.user
+ if username.organiser.academic.institution_type.id == 5 or username.organiser.academic.institution_type.id == 13 or username.organiser.academic.institution_type.id == 15:
+ kwargs.update({'course_type' :(('', '---------'), (0, 'Software Course outside lab hours'), (1, 'Software Course mapped in lab hours'), (2, ' Software Course unmapped in lab hours'), (3, ' EduEasy Software')) })
+ else:
+ kwargs.update({'course_type' :(('', '---------'), (0, 'Software Course outside lab hours'), (1, 'Software Course mapped in lab hours'), (2, ' Software Course unmapped in lab hours')) })
+
+ return kwargs
+
+ def post(self, request, *args, **kwargs):
+ self.object = None
+ self.user = request.user
+ form_class = self.get_form_class()
+ form = self.get_form(form_class)
+ if form.is_valid():
+ return self.form_valid(form)
+ else:
+ return self.form_invalid(form)
+
+ def form_valid(self, form, **kwargs):
+ # Check if all student participate in selected foss
+ try:
+ form_data = form.save(commit=False)
+ sb = StudentBatch.objects.get(pk=form_data.batch.id)
+ if sb.student_count():
+ training_planner = TrainingPlanner.objects.get(pk=self.tpid)
+ # checking if requested batch already have training request in requsted course
+ is_batch_has_course = TrainingRequest.objects.filter(
+ batch_id = form_data.batch.id,
+ course_id = form_data.course.id,
+ training_planner_id = training_planner.id
+ ).count()
+ if is_batch_has_course:
+ messages.error(self.request, 'This "%s" already taken/requested the selected "%s" course in current semester.' % (form_data.batch, form_data.course))
+ return self.form_invalid(form)
+ # Check if course is full for this semester
+ if form_data.department.id == 24:
+ if training_planner.is_school_full(form_data.department.id, form_data.batch.id):
+ messages.error(self.request, 'No. of training requests exceeded for this semester.')
+ return self.form_invalid(form)
+ else:
+ if training_planner.is_full(form_data.department.id, form_data.batch.id):
+ messages.error(self.request, 'No. of training requests exceeded for this semester.')
+ return self.form_invalid(form)
+
+ form_data.training_planner_id = self.kwargs['tpid']
+ form_data.save()
+
+ else:
+ sb.update_student_count()
+ messages.error(self.request, 'There is no student present in this batch.')
+ return self.form_invalid(form)
+ except:
+ messages.error(self.request, 'Something went wrong, Contact site administrator.')
+ return self.form_invalid(form)
+ context = {}
+ messages.success(self.request,'STP has been added successfully. Now continue with step 3 "Select Participants " on STPS page. Select the participants from the Master Batch Student List for any one course that you are starting with. This is necessary for receiving certificates.')
+ return HttpResponseRedirect('/software-training/{0}/training-request/'.format(self.tpid))
+
+class TrainingRequestEditView(CreateView):
+ form_class = TrainingRequestEditForm
+ user = None
+ training = None
+ @method_decorator(group_required("Organiser"))
+ def dispatch(self, *args, **kwargs):
+ if 'pk' in self.kwargs:
+ self.training = TrainingRequest.objects.get(pk=self.kwargs['pk'])
+ if not self.training.can_edit():
+ messages.error(self.request, "Training has attendance, edit is not permitted for training.")
+ return HttpResponseRedirect('/software-training/training-planner/')
+ return super(TrainingRequestEditView, self).dispatch(*args, **kwargs)
+
+ def get_form_kwargs(self):
+ kwargs = super(TrainingRequestEditView, self).get_form_kwargs()
+ kwargs.update({'training' : self.training})
+ kwargs.update({'user' : self.request.user})
+ return kwargs
+
+ def get_context_data(self, **kwargs):
+ context = super(TrainingRequestEditView, self).get_context_data(**kwargs)
+ context['training'] = self.training
+ return context
+
+ def form_valid(self, form, **kwargs):
+ # Check if all student participate in selected foss
+ try:
+ # Check if batch has student?
+ sb = StudentBatch.objects.get(pk=form.cleaned_data['batch'].id)
+ selectedBatch = form.cleaned_data['batch']
+ selectedDept = form.cleaned_data['department']
+ selectedCourse = form.cleaned_data['course']
+ if not sb.student_count():
+ messages.error(self.request, 'There is no student present in this batch.')
+ return self.form_invalid(form)
+ training_planner = self.training.training_planner
+
+ # Check if batch has already has same foss course?
+ if not ( (selectedBatch == self.training.batch) and (selectedCourse == self.training.course)):
+ is_batch_has_course = TrainingRequest.objects.filter(
+ batch = selectedBatch,
+ course = selectedCourse,
+ training_planner_id = training_planner.id
+ ).count()
+ if is_batch_has_course:
+ messages.error(self.request, 'This "%s" already taken/requested the selected "%s" course in current semester.' % (selectedBatch, selectedCourse))
+ return self.form_invalid(form)
+ # Check if course is full for this semester
+ if not ( (selectedBatch == self.training.batch) and (selectedDept == self.training.department)):
+ if training_planner.is_full(selectedDept.id, selectedBatch.id):
+ messages.error(self.request, 'No. of training requests exceeded for this semester.')
+ return self.form_invalid(form)
+
+ # Assigning values
+ self.training.department = selectedDept
+ self.training.batch = selectedBatch
+ self.training.course_type = form.cleaned_data['course_type']
+
+ if self.training.batch.is_foss_batch_acceptable(selectedCourse):
+ self.training.sem_start_date = form.cleaned_data['sem_start_date']
+ self.training.training_start_date = form.cleaned_data['training_start_date']
+ self.training.training_end_date = form.cleaned_data['training_end_date']
+ self.training.course_id = selectedCourse
+ else:
+ messages.error(self.request, 'This student batch already taken the selected course.')
+ return self.form_invalid(form)
+ # save form
+ self.training.save()
+
+ except:
+ return self.form_invalid(form)
+ context = {}
+ return HttpResponseRedirect('/software-training/select-participants/')
+
+ def post(self, request, *args, **kwargs):
+ self.object = None
+ self.user = request.user
+ form_class = self.get_form_class()
+ form = self.get_form(form_class)
+
+ if form.is_valid():
+ return self.form_valid(form)
+ else:
+ return self.form_invalid(form)
+ return HttpResponseRedirect('/software-training/select-participants/')
+
+
+class TrainingAttendanceListView(ListView):
+ queryset = StudentMaster.objects.none()
+ paginate_by = 500
+ template_name = ""
+ training_request = None
+
+ def dispatch(self, *args, **kwargs):
+ self.training_request = TrainingRequest.objects.get(pk=kwargs['tid'])
+ if self.training_request.status == 1 and not self.training_request.participants == 0:
+ self.queryset = self.training_request.trainingattend_set.all()
+ else:
+ self.queryset = StudentMaster.objects.filter(batch_id=self.training_request.batch_id,student__verified__lte=3,student__error=0, moved=False)
+ return super(TrainingAttendanceListView, self).dispatch(*args, **kwargs)
+
+ def get_context_data(self, **kwargs):
+ context = super(TrainingAttendanceListView, self).get_context_data(**kwargs)
+ context['training'] = self.training_request
+ context['department'] = self.training_request.department
+ languages = Language.objects.filter(
+ id__in = FossAvailableForWorkshop.objects.filter(
+ foss_id = self.training_request.course.foss_id
+ ).values_list('language_id')
+ )
+ context['languages'] = languages
+ return context
+
+ def post(self, request, *args, **kwargs):
+ self.object = None
+ self.user = request.user
+ training_id = kwargs['tid']
+ if request.POST and 'user' in request.POST:
+ # commented out as Django 1.11 + creates new csrf token for every POST request
+ #if csrf.get_token(request) == request.POST['csrfmiddlewaretoken']:
+ marked_student = request.POST.getlist('user', None)
+ # delete un marked record if exits
+ TrainingAttend.objects.filter(training_id =training_id).exclude(student_id__in = marked_student).delete()
+ # insert new record if not exits
+ for record in marked_student:
+ language_id = request.POST.get(record)
+ training_attend = TrainingAttend.objects.filter(training_id =training_id, student_id = record)
+ if not training_attend.exists():
+ TrainingAttend.objects.create(training_id =training_id, student_id = record, language_id=language_id)
+ else:
+ training_attend = training_attend.first()
+ training_attend.language_id = language_id
+ training_attend.save()
+ #print marked_student
+ else:
+ TrainingAttend.objects.filter(training_id =training_id).delete()
+ self.training_request.update_participants_count()
+ return HttpResponseRedirect('/software-training/training-planner')
+
+class TrainingCertificateListView(ListView):
+ queryset = StudentMaster.objects.none()
+ paginate_by = 500
+ template_name = ""
+ training_request = None
+
+ def dispatch(self, *args, **kwargs):
+ self.training_request = TrainingRequest.objects.get(pk=kwargs['tid'])
+ if self.training_request.status:
+ self.queryset = self.training_request.trainingattend_set.all()
+ else:
+ self.queryset = StudentMaster.objects.filter(batch_id=self.training_request.batch_id, moved=False)
+ return super(TrainingCertificateListView, self).dispatch(*args, **kwargs)
+
+ def get_context_data(self, **kwargs):
+ context = super(TrainingCertificateListView, self).get_context_data(**kwargs)
+ context['training'] = self.training_request
+ languages = Language.objects.filter(
+ id__in = FossAvailableForWorkshop.objects.filter(
+ foss_id = self.training_request.course.foss_id
+ ).values_list('language_id')
+ )
+ #language
+ #for lang in languages:
+ context['languages'] = languages
+ return context
+
+
+"""
+Delete Student
+"""
+class StudentDeleteView(DeleteView):
+ model=Student
+ def dispatch(self, *args, **kwargs):
+ self.success_url="/software-training/student-batch/"+str(kwargs['bid'])+"/view"
+ student = super(StudentDeleteView, self).get_object()
+ if student.is_student_has_attendance():
+ messages.error(self.request,
+ "You do not have permission to delete {0}\
+ because you have marked the attendance".format(student.student_fullname()))
+ return HttpResponseRedirect(self.success_url)
+ try:
+ sm = StudentMaster.objects.get(student=student, moved=False)
+ if not sm.batch.organiser.academic_id == self.request.user.organiser.academic_id:
+ messages.error(self.request, "You do not have permission to delete " + student.student_fullname())
+ return HttpResponseRedirect(self.success_url)
+ except:
+ pass
+ return super(StudentDeleteView, self).dispatch(*args, **kwargs)
+
+
+"""
+Delete StudentMaster if student not having attendance
+args['pk'] - student id
+args['bid'] - batch id
+"""
+class StudentMasterDeleteView(DeleteView):
+ model=StudentMaster
+
+ def dispatch(self, *args, **kwargs):
+ self.success_url="/software-training/student-batch/"+str(kwargs['bid'])+"/view"
+ sm = super(StudentMasterDeleteView, self).get_object()
+ student = sm.student
+ if sm.is_student_has_attendance():
+ messages.error(self.request,
+ "You do not have permission to delete {0}\
+ because you have marked the attendance".format(student.student_fullname()))
+ return HttpResponseRedirect(self.success_url)
+ try:
+ sm = StudentMaster.objects.get(student=student, moved=False)
+ if not sm.batch.organiser.academic_id == self.request.user.organiser.academic_id:
+ messages.error(self.request, "You do not have permission to delete " + student.student_fullname())
+ return HttpResponseRedirect(self.success_url)
+ except:
+ pass
+ return super(StudentMasterDeleteView, self).dispatch(*args, **kwargs)
+
+
+class TrainingCertificate(object):
+ def custom_strftime(self, format, t):
+ return t.strftime(format)
+
+ def suffix(self, d):
+ return 'th' if 11<=d<=13 else {1:'st',2:'nd',3:'rd'}.get(d%10, 'th')
+
+ def training_certificate(self, ta):
+ training_end = ta.training.sem_start_date+timedelta(days=60)
+
+ response = HttpResponse(content_type='application/pdf')
+ filename = (ta.student.user.first_name+'-'+ta.training.course.foss.foss+"-Participant-Certificate").replace(" ", "-");
+
+ response['Content-Disposition'] = 'attachment; filename='+filename+'.pdf'
+ imgTemp = BytesIO ()
+ imgDoc = canvas.Canvas(imgTemp)
+
+ # Title
+ imgDoc.setFont('Helvetica', 35, leading=None)
+ imgDoc.drawCentredString(405, 470, "Certificate of Participation")
+
+ #date
+ if ta.training.department.id != 169:
+ imgDoc.setFont('Helvetica', 18, leading=None)
+ imgDoc.drawCentredString(211, 115, self.custom_strftime('%d %B %Y', training_end))
+
+ # Draw image on Canvas and save PDF in buffer
+ imgPath = get_signature(ta.training.training_start_date)
+ imgDoc.drawImage(imgPath, 600, 100, 150, 76)
+
+ #paragraphe
+ text = get_training_cert_text(ta)
+
+ centered = ParagraphStyle(name = 'centered',
+ fontSize = 16,
+ leading = 30,
+ alignment = 0,
+ spaceAfter = 20
+ )
+
+ p = Paragraph(text, centered)
+ p.wrap(630, 200)
+ p.drawOn(imgDoc, 4.2 * cm, 7 * cm)
+ imgDoc.save()
+ # Use PyPDF to merge the image-PDF into the template
+ template_path = get_training_certificate(ta)
+ page = PdfFileReader(open(template_path,"rb")).getPage(0)
+ overlay = PdfFileReader(BytesIO(imgTemp.getvalue())).getPage(0)
+ page.mergePage(overlay)
+
+ #Save the result
+ output = PdfFileWriter()
+ output.addPage(page)
+
+ #stream to browser
+ outputStream = response
+ output.write(response)
+ outputStream.close()
+
+ return response
+
+class SingleTrainingCertificate(object):
+ def custom_strftime(self, format, t):
+ return t.strftime(format).replace('{S}', str(t.day) + self.suffix(t.day))
+
+ def suffix(self, d):
+ return 'th' if 11<=d<=13 else {1:'st',2:'nd',3:'rd'}.get(d%10, 'th')
+
+ def single_training_certificate(self, ta):
+ response = HttpResponse(content_type='application/pdf')
+ filename = (ta.firstname+'-'+ta.training.course.foss.foss+"-Participant-Certificate").replace(" ", "-");
+
+ response['Content-Disposition'] = 'attachment; filename='+filename+'.pdf'
+ imgTemp = BytesIO()
+ imgDoc = canvas.Canvas(imgTemp)
+
+ # Title
+ imgDoc.setFont('Helvetica', 40, leading=None)
+ imgDoc.drawCentredString(415, 480, "Certificate of Learning")
+
+ #date
+ imgDoc.setFont('Helvetica', 18, leading=None)
+ imgDoc.drawCentredString(211, 115, self.custom_strftime('%B {S} %Y', ta.training.tdate))
+
+ #password
+ certificate_pass = ''
+ imgDoc.setFillColorRGB(211, 211, 211)
+ imgDoc.setFont('Helvetica', 10, leading=None)
+ imgDoc.drawString(10, 6, certificate_pass)
+
+ # Draw image on Canvas and save PDF in buffer
+ imgPath = settings.MEDIA_ROOT +"sign.jpg"
+ imgDoc.drawImage(imgPath, 600, 100, 150, 76)
+
+ #paragraphe
+ text = "This is to certify that "+ta.firstname +" "+ta.lastname+" participated in the "+ta.training.course.foss.foss+" training organized at "+ ta.training.academic.institution_name+" by "+ta.training.organiser.user.first_name + " "+ta.training.organiser.user.last_name+" on "+self.custom_strftime('%B {S} %Y', ta.training.tdate)+" with course material provided by the Spoken Tutorial Project, IIT Bombay. A comprehensive set of topics pertaining to "+ta.training.course.foss.foss+" were covered in the workshop. This training is offered by the Spoken Tutorial Project, IIT Bombay, funded by National Mission on Education through ICT, MHRD, Govt. of India."
+
+ centered = ParagraphStyle(name = 'centered',
+ fontSize = 16,
+ leading = 30,
+ alignment = 0,
+ spaceAfter = 20
+ )
+
+ p = Paragraph(text, centered)
+ p.wrap(650, 200)
+ p.drawOn(imgDoc, 4.2 * cm, 7 * cm)
+
+ imgDoc.save()
+
+ # Use PyPDF to merge the image-PDF into the template
+ page = PdfFileReader(open(settings.MEDIA_ROOT +"Blank-Certificate.pdf","rb")).getPage(0)
+ overlay = PdfFileReader(BytesIO(imgTemp.getvalue())).getPage(0)
+ page.mergePage(overlay)
+
+ #Save the result
+ output = PdfFileWriter()
+ output.addPage(page)
+
+ #stream to browser
+ outputStream = response
+ output.write(response)
+ outputStream.close()
+
+ return response
+
+
+class OrganiserTrainingCertificateView(TrainingCertificate, View):
+ template_name = ""
+ @method_decorator(group_required("Organiser"))
+ def dispatch(self, *args, **kwargs):
+ return super(OrganiserTrainingCertificateView, self).dispatch(*args, **kwargs)
+
+ def get(self, request, *args, **kwargs):
+ ta = None
+ try:
+ ta = TrainingAttend.objects.get(pk=kwargs['taid'])
+ except ObjectDoesNotExist:
+ messages.error(self.request, "Record not found")
+ pass
+
+ if ta and ta.training.training_planner.organiser == self.request.user.organiser:
+ return self.training_certificate(ta)
+ else:
+ messages.error(self.request, "Permission Denied!")
+ return HttpResponseRedirect("/")
+
+class OrganiserSingleTrainingCertificateView(SingleTrainingCertificate, View):
+ template_name = ""
+ @method_decorator(group_required("Organiser"))
+ def dispatch(self, *args, **kwargs):
+ return super(OrganiserSingleTrainingCertificateView, self).dispatch(*args, **kwargs)
+
+ def get(self, request, *args, **kwargs):
+ ta = None
+ try:
+ ta = SingleTrainingAttendance.objects.get(pk=kwargs['taid'])
+ except ObjectDoesNotExist:
+ messages.error(self.request, "Record not found")
+ pass
+
+ if ta:
+ return self.single_training_certificate(ta)
+ else:
+ messages.error(self.request, "PermissionDenied!")
+ return HttpResponseRedirect("/")
+
+class StudentTrainingCertificateView(TrainingCertificate, View):
+ template_name = ""
+ @method_decorator(group_required("Student"))
+ def dispatch(self, *args, **kwargs):
+ return super(StudentTrainingCertificateView, self).dispatch(*args, **kwargs)
+
+ def get(self, request, *args, **kwargs):
+ ta = None
+ try:
+ ta = TrainingAttend.objects.get(pk=kwargs['taid'])
+ except ObjectDoesNotExist:
+ messages.error(self.request, "Record not found")
+ pass
+
+ try:
+ mdluserid = request.session.get('mdluserid', None)
+ mdluser = MdlUser.objects.get(id=mdluserid)
+ if ta and ta.student.user.email == mdluser.email:
+ return self.training_certificate(ta)
+ except Exception as e:
+ messages.error(self.request, "PermissionDenied!")
+ return HttpResponseRedirect("/")
+
+class CourseMapCreateView(CreateView):
+ form_class = CourseMapForm
+ @method_decorator(group_required("Organiser"))
+ def dispatch(self, *args, **kwargs):
+ return super(CourseMapCreateView, self).dispatch(*args, **kwargs)
+
+ def get_context_data(self, **kwargs):
+ context = super(CourseMapCreateView, self).get_context_data(**kwargs)
+ return context
+
+ def form_valid(self, form, **kwargs):
+ # Check if all student participate in selected foss
+ try:
+ form_data = form.save(commit=False)
+ if FossAvailableForTest.objects.filter(foss_id=form_data.foss).exists():
+ form_data.test = 1
+ form_data.save()
+ except IntegrityError:
+ messages.error(self.request, 'Course with this Foss and Category already exists.')
+ return self.form_invalid(form)
+ return HttpResponseRedirect('/software-training/course-map/')
+
+class CourseMapListView(ListView):
+ queryset = CourseMap.objects.none()
+ paginate_by = 50
+ header = None
+ raw_get_data = None
+ @method_decorator(group_required("Organiser"))
+ def dispatch(self, *args, **kwargs):
+ self.header = {
+ 1: SortableHeader('#', False),
+ 2: SortableHeader('course', True, 'Course'),
+ 3: SortableHeader('test', True, 'Test'),
+ 4: SortableHeader('category', True, 'Category'),
+ 5: SortableHeader('', False, ''),
+ }
+ self.queryset = CourseMap.objects.exclude(category=0)
+ self.raw_get_data = self.request.GET.get('o', None)
+ collection = get_sorted_list(self.request, self.queryset, self.header, self.raw_get_data)
+ return super(CourseMapListView, self).dispatch(*args, **kwargs)
+
+ def get_context_data(self, **kwargs):
+ context = super(CourseMapListView, self).get_context_data(**kwargs)
+ context['header'] = self.header
+ context['ordering'] = get_field_index(self.raw_get_data)
+ return context
+
+class CourseMapUpdateView(UpdateView):
+ model = CourseMap
+ form_class = CourseMapForm
+ success_url = "/software-training/course-map-list/"
+
+
+### Ajax
+class SaveStudentView(JSONResponseMixin, View):
+ @method_decorator(csrf_exempt)
+ def dispatch(self, *args, **kwargs):
+ return super(SaveStudentView, self).dispatch(*args, **kwargs)
+
+ def post(self, request, *args, **kwargs):
+ sb = StudentBatchCreateView()
+ email = self.request.POST.get('email').strip().lower()
+ message = ''
+ code = 0 # 0 => None, 1 => Warning, 2 => Error
+ if sb.email_validator(email):
+ student = sb.get_student(email)
+ batch = self.request.POST.get('batch')
+
+ if not student:
+ sdetails = self.request.POST.get('student_details').split(',')
+ student = sb.create_student(sdetails[0], sdetails[1], email, sdetails[2])
+ if student:
+ try:
+ smrec = StudentMaster.objects.get(student=student)
+ message = "Student with this email already exists in some other batch."
+ code = 2
+ # check student in different batch
+ if int(batch) == int(smrec.batch_id):
+ code = 1
+ message = "Student with this email already exists in this batch."
+ except ObjectDoesNotExist:
+ StudentMaster.objects.create(student=student, batch_id=batch)
+ StudentBatch.objects.get(pk=batch).update_student_count()
+ else:
+ code = 2
+ message = "Something went wrong. Please contact site administrator."
+ else:
+ code = 4
+ message = "Invalid email address"
+
+ context = {
+ 'code' : code,
+ 'message' : message
+ }
+ return self.render_to_json_response(context)
+
+class GetBatchOptionView(JSONResponseMixin, View):
+ @method_decorator(csrf_exempt)
+ def dispatch(self, *args, **kwargs):
+ return super(GetBatchOptionView, self).dispatch(*args, **kwargs)
+
+ def post(self, request, *args, **kwargs):
+ department_id = self.request.POST.get('department')
+ context = {}
+
+ batches = StudentBatch.objects.filter(
+ academic_id=request.user.organiser.academic.id,
+ stcount__gt=0,
+ department_id=department_id
+ )
+ batch_option = "--------- "
+ for batch in batches:
+ if batch.batch_name:
+ batch_option += "" + str(batch.batch_name) + " Batch "
+ else:
+ batch_option += "" + str(batch) + " "
+ context = {
+ 'batch_option' : batch_option,
+ }
+ return self.render_to_json_response(context)
+
+class GetCourseOptionView(JSONResponseMixin, View):
+ @method_decorator(csrf_exempt)
+ def dispatch(self, *args, **kwargs):
+ return super(GetCourseOptionView, self).dispatch(*args, **kwargs)
+
+ def post(self, request, *args, **kwargs):
+ foss_category = self.request.POST.get('foss_category')
+ context = {}
+
+ course_option = "--------- "
+ courses = CourseMap.objects.filter(category=0, test=foss_category).exclude(foss_id__in=EXCLUDE_FROM_STP)
+
+ for course in courses:
+ course_option += "" + str(course) + " "
+ context = {
+ 'course_option' : course_option,
+ }
+ return self.render_to_json_response(context)
+
+class GetBatchStatusView(JSONResponseMixin, View):
+ department_id = None
+ @method_decorator(csrf_exempt)
+ def dispatch(self, *args, **kwargs):
+ return super(GetBatchStatusView, self).dispatch(*args, **kwargs)
+
+ def post(self, request, *args, **kwargs):
+ department_id = self.request.POST.get('department')
+ batch_id = self.request.POST.get('batch')
+ tp = TrainingPlanner.objects.get(pk=self.request.POST.get('training_planner'))
+ context = {}
+
+ batch_status = True
+
+ if department_id == '24':
+ if tp.is_school_full(department_id, batch_id):
+ batch_status = False
+ else:
+ if tp.is_full(department_id, batch_id):
+ batch_status = False
+
+ context = {
+ 'batch_status' : batch_status,
+ }
+ return self.render_to_json_response(context)
+
+
+class GetDepartmentOrganiserStatusView(JSONResponseMixin, View):
+ department_id = None
+ year = None
+ @method_decorator(csrf_exempt)
+ def dispatch(self, *args, **kwargs):
+ return super(GetDepartmentOrganiserStatusView, self).dispatch(*args, **kwargs)
+
+ def post(self, request, *args, **kwargs):
+ department_id = self.request.POST.get('department')
+ year = self.request.POST.get('year')
+ context = {}
+ dept_status = True
+ msg = ""
+
+ try:
+ resultdata = StudentBatch.objects.filter(
+ ~Q(organiser_id = request.user.organiser.id),
+ academic_id=request.user.organiser.academic.id,
+ department_id=department_id,
+ year = year
+ )
+ if resultdata:
+ dept_status = False
+ msg = "This department with selected year is already chosen by another Organiser in your College."
+ except ObjectDoesNotExist:
+ pass
+
+ context = {
+ 'dept_status' : dept_status,
+ 'msg' : msg
+ }
+ return self.render_to_json_response(context)
+
+
+# class TrainingRequestListView(ListView):
+# queryset = None
+# paginate_by = 20
+# user = None
+# template_name = None
+# header = None
+# raw_get_data = None
+# role = None
+# status = None
+# now= datetime.now()
+# year = now.year
+# month =now.month
+
+# current_sem_type_even = 0 #odd
+# if month < 6:
+# current_sem_type_even = 1 #even
+
+# prev_sem_type = 'even'
+# prev_sem_year = year
+# if current_sem_type_even:
+# prev_sem_type = 'odd'
+# prev_sem_year = (year - 1)
+# prev_sem_start_date, prev_sem_end_date = get_prev_semester_duration(prev_sem_type, prev_sem_year)
+
+# @method_decorator(group_required("Resource Person","Administrator"))
+# def dispatch(self, *args, **kwargs):
+# if (not 'role' in kwargs) or (not 'status' in kwargs):
+# raise PermissionDenied()
+# self.role = kwargs['role']
+# self.status = kwargs['status']
+# status_list = {'pending': 0, 'completed': 1, 'markcomplete':2, 'pendingattendance':3}
+# roles = ['rp', 'em']
+# self.user = self.request.user
+# if self.role in roles and self.status in status_list:
+# if self.status == 'completed':
+# self.queryset = TrainingRequest.objects.filter(
+# training_planner__academic_id__in=AcademicCenter.objects.filter(
+# state__in = State.objects.filter(
+# resourceperson__user_id=self.user,
+# resourceperson__status=1
+# )
+# ).values_list('id'),
+# status=1,
+# participants__gt=0
+# ).order_by('-updated')
+# elif self.status == 'pending':
+# self.queryset = TrainingRequest.objects.filter(
+# training_planner__academic_id__in=AcademicCenter.objects.filter(
+# state__in = State.objects.filter(
+# resourceperson__user_id=self.user,
+# resourceperson__status=1
+# )
+# ).values_list('id'),
+# status=0
+# ).order_by('-updated')
+# elif self.status == 'markcomplete':
+# if is_administrator(self.user):
+# self.queryset = TrainingRequest.objects.filter(status=2).order_by('-updated')
+# else:
+# self.queryset = TrainingRequest.objects.filter(
+# training_planner__academic_id__in=AcademicCenter.objects.filter(
+# state__in = State.objects.filter(
+# resourceperson__user_id=self.user,
+# resourceperson__status=1
+# )
+# ).values_list('id'),
+# status=2
+# ).order_by('-updated')
+# elif self.status == 'pendingattendance':
+# self.queryset = TrainingRequest.objects.filter(
+# training_planner__academic_id__in=AcademicCenter.objects.filter(
+# state__in = State.objects.filter(
+# resourceperson__user_id=self.user,
+# resourceperson__status=1,
+# )
+# ).values_list('id'),
+# status = 1, participants = 0, training_planner__semester__name = self.prev_sem_type , sem_start_date__gte = self.prev_sem_start_date
+# )
+
+# self.header = {
+# 1: SortableHeader('#', False),
+# 2: SortableHeader(
+# 'training_planner__academic__state__name',
+# True,
+# 'State'
+# ),
+# 3: SortableHeader(
+# 'training_planner__academic__academic_code',
+# True,
+# 'Code'
+# ),
+# 4: SortableHeader(
+# 'training_planner__academic__institution_name',
+# True,
+# 'Institution'
+# ),
+# 5: SortableHeader('batch__department__name', True, 'Department / Batch'),
+# 6: SortableHeader('course__foss__foss', True, 'Course Name'),
+# 7: SortableHeader('course_type', True, 'Course Type'),
+# 8: SortableHeader(
+# 'training_planner__organiser__user__first_name',
+# True,
+# 'Organiser'
+# ),
+# 9: SortableHeader(
+# 'sem_start_date',
+# True,
+# 'Sem Start Date / Training Date'
+# ),
+# 10: SortableHeader('participants', True, 'Participants'),
+# #11: SortableHeader('Action', False)
+# }
+# self.raw_get_data = self.request.GET.get('o', None)
+# self.queryset = get_sorted_list(
+# self.request,
+# self.queryset,
+# self.header,
+# self.raw_get_data
+# )
+# if self.status == 'completed':
+# self.queryset.qs = TrainingRequestFilter(self.request.GET, queryset=self.queryset, user=self.user, rp_completed=True)
+# elif self.status == 'pending':
+# self.queryset.qs = TrainingRequestFilter(self.request.GET, queryset=self.queryset, user=self.user, rp_ongoing=True)
+# elif self.status == 'markcomplete':
+# self.queryset.qs = TrainingRequestFilter(self.request.GET, queryset=self.queryset, user=self.user, rp_markcomplete=True)
+# elif self.status == 'pendingattendance':
+# self.queryset.qs = TrainingRequestFilter(self.request.GET, queryset=self.queryset, user=self.user, rp_pendingattendance=True)
+# else:
+# raise PermissionDenied()
+# return super(TrainingRequestListView, self).dispatch(*args, **kwargs)
+
+# def get_context_data(self, **kwargs):
+# context = super(TrainingRequestListView, self).get_context_data(**kwargs)
+# context['form'] = self.queryset.qs.form
+# context['collection'] = self.queryset.qs
+# context['role'] = self.role
+# context['status'] = self.status
+# context['header'] = self.header
+# context['ordering'] = get_field_index(self.raw_get_data)
+# return context
+class TrainingRequestListView(ListView):
+ queryset = None
+ paginate_by = 20
+ user = None
+ template_name = None
+ header = None
+ raw_get_data = None
+ role = None
+ status = None
+ now= datetime.datetime.now()
+ year = now.year
+ month =now.month
+
+ current_sem_type_even = 0 #odd
+ if month < 6:
+ current_sem_type_even = 1 #even
+
+ prev_sem_type = 'even'
+ prev_sem_year = year
+ if current_sem_type_even:
+ prev_sem_type = 'odd'
+ prev_sem_year = (year - 1)
+ prev_sem_start_date, prev_sem_end_date = get_prev_semester_duration(prev_sem_type, prev_sem_year)
+
+ @method_decorator(group_required("Resource Person","Administrator"))
+ def dispatch(self, *args, **kwargs):
+ if (not 'role' in kwargs) or (not 'status' in kwargs):
+ raise PermissionDenied()
+ self.role = kwargs['role']
+ self.status = kwargs['status']
+ status_list = {'pending': 0, 'completed': 1, 'markcomplete':2, 'pendingattendance':3}
+ roles = ['rp', 'em']
+ self.user = self.request.user
+ if self.role in roles and self.status in status_list:
+ if self.status == 'completed':
+ self.queryset = TrainingRequest.objects.filter(
+ training_planner__academic_id__in=AcademicCenter.objects.filter(
+ state__in = State.objects.filter(
+ resourceperson__user_id=self.user,
+ resourceperson__status=1
+ )
+ ).values_list('id'),
+ status=1,
+ participants__gt=0
+ ).order_by('-updated')
+ elif self.status == 'pending':
+ self.queryset = TrainingRequest.objects.filter(
+ training_planner__academic_id__in=AcademicCenter.objects.filter(
+ state__in = State.objects.filter(
+ resourceperson__user_id=self.user,
+ resourceperson__status=1
+ )
+ ).values_list('id'),
+ status=0
+ ).order_by('-updated')
+ elif self.status == 'markcomplete':
+ if is_administrator(self.user):
+ self.queryset = TrainingRequest.objects.filter(status=2).order_by('-updated')
+ else:
+ self.queryset = TrainingRequest.objects.filter(
+ training_planner__academic_id__in=AcademicCenter.objects.filter(
+ state__in = State.objects.filter(
+ resourceperson__user_id=self.user,
+ resourceperson__status=1
+ )
+ ).values_list('id'),
+ status=2
+ ).order_by('-updated')
+ elif self.status == 'pendingattendance':
+ self.queryset = TrainingRequest.objects.filter(
+ training_planner__academic_id__in=AcademicCenter.objects.filter(
+ state__in = State.objects.filter(
+ resourceperson__user_id=self.user,
+ resourceperson__status=1,
+ )
+ ).values_list('id'),
+ status = 1, participants = 0, training_planner__semester__name = self.prev_sem_type , sem_start_date__gte = self.prev_sem_start_date
+ )
+
+ self.header = {
+ 1: SortableHeader('#', False),
+ 2: SortableHeader(
+ 'training_planner__academic__state__name',
+ True,
+ 'State'
+ ),
+ 3: SortableHeader(
+ 'training_planner__academic__academic_code',
+ True,
+ 'Code'
+ ),
+ 4: SortableHeader(
+ 'training_planner__academic__institution_name',
+ True,
+ 'Institution'
+ ),
+ 5: SortableHeader('batch__department__name', True, 'Department / Batch'),
+ 6: SortableHeader('course__foss__foss', True, 'Course Name'),
+ 7: SortableHeader('course_type', True, 'Course Type'),
+ 8: SortableHeader(
+ 'training_planner__organiser__user__first_name',
+ True,
+ 'Organiser'
+ ),
+ 9: SortableHeader(
+ 'sem_start_date',
+ True,
+ 'Sem Start Date / Training Date'
+ ),
+ 10: SortableHeader('participants', True, 'Participants'),
+ #11: SortableHeader('Action', False)
+ }
+ self.raw_get_data = self.request.GET.get('o', None)
+ self.queryset = get_sorted_list(
+ self.request,
+ self.queryset,
+ self.header,
+ self.raw_get_data
+ )
+ if self.status == 'completed':
+ self.queryset.qs = TrainingRequestFilter(self.request.GET, queryset=self.queryset, user=self.user, rp_completed=True)
+ elif self.status == 'pending':
+ self.queryset.qs = TrainingRequestFilter(self.request.GET, queryset=self.queryset, user=self.user, rp_ongoing=True)
+ elif self.status == 'markcomplete':
+ self.queryset.qs = TrainingRequestFilter(self.request.GET, queryset=self.queryset, user=self.user, rp_markcomplete=True)
+ elif self.status == 'pendingattendance':
+ self.queryset.qs = TrainingRequestFilter(self.request.GET, queryset=self.queryset, user=self.user, rp_pendingattendance=True)
+ else:
+ raise PermissionDenied()
+ return super(TrainingRequestListView, self).dispatch(*args, **kwargs)
+
+ def get_context_data(self, **kwargs):
+ context = super(TrainingRequestListView, self).get_context_data(**kwargs)
+ context['form'] = self.queryset.qs.form
+ context['role'] = self.role
+ context['status'] = self.status
+ context['header'] = self.header
+ context['ordering'] = get_field_index(self.raw_get_data)
+ return context
+
+
+############################## Single Training one day workshop #############################################################################
+
+"""
+'''
+SingleTrainingNewListView will list all the new/pending training requests in the single-training page pertaining to a specific user, i.e, Organiser or Resource Person.
+
+'''
+class SingleTrainingNewListView(ListView):
+ queryset = None
+ paginate_by = 10
+
+ def get_context_data(self, **kwargs):
+ context = super(SingleTrainingNewListView, self).get_context_data(**kwargs)
+ temp = self.request.user.groups.all()
+ grup = []
+ for i in temp:
+ grup.append(i.name)
+ context['group'] = grup
+ return context
+
+ def dispatch(self, *args, **kwargs):
+ user_groups_object = self.request.user.groups.all()
+ user_group = []
+ for i in user_groups_object:
+ user_group.append(i.name)
+ if 'Administrator' in user_group:
+ self.queryset = SingleTraining.objects.filter(Q(status=0)).order_by('-tdate')
+ return super(SingleTrainingNewListView, self).dispatch(*args, **kwargs)
+ if 'Resource Person' in user_group and 'Organiser' in user_group:
+ state_list = []
+ rp_state = self.request.user.id
+ a = ResourcePerson.objects.filter(user__id=rp_state)
+ for i in a:
+ state_list.append(i.state_id)
+ self.queryset = SingleTraining.objects.filter(Q(status=0), academic__state__id__in = state_list).order_by('-tdate')
+ return super(SingleTrainingNewListView, self).dispatch(*args, **kwargs)
+ elif 'Organiser' in user_group:
+ rp_state = self.request.user.organiser.academic_id
+ self.queryset = SingleTraining.objects.filter(Q(status=0), academic__id = rp_state).order_by('-tdate')
+ return super(SingleTrainingNewListView, self).dispatch(*args, **kwargs)
+ elif 'Resource Person' in user_group:
+ state_list = []
+ rp_state = self.request.user.id
+ a = ResourcePerson.objects.filter(user__id=rp_state)
+ for i in a:
+ state_list.append(i.state_id)
+ self.queryset = SingleTraining.objects.filter(Q(status=0), academic__state__id__in = state_list).order_by('-tdate')
+ return super(SingleTrainingNewListView, self).dispatch(*args, **kwargs)
+
+
+'''
+SingletrainingApprovedListView will list all the approved training requests in the single-training page.
+
+'''
+class SingletrainingApprovedListView(ListView):
+ queryset = None
+ paginate_by = 10
+
+ def get_context_data(self, **kwargs):
+ context = super(SingletrainingApprovedListView, self).get_context_data(**kwargs)
+ temp = self.request.user.groups.all()
+ grup = []
+ for i in temp:
+ grup.append(i.name)
+ context['group'] = grup
+ return context
+
+ def dispatch(self, *args, **kwargs):
+ user_groups_object = self.request.user.groups.all()
+ user_group = []
+ for i in user_groups_object:
+ user_group.append(i.name)
+ if 'Administrator' in user_group:
+ self.queryset = SingleTraining.objects.filter(tdate__gt=datetime.today().date().isoformat(), status=2).order_by('-tdate')
+ return super(SingletrainingApprovedListView, self).dispatch(*args, **kwargs)
+ if 'Resource Person' in user_group and 'Organiser' in user_group:
+ state_list = []
+ rp_state = self.request.user.id
+ a = ResourcePerson.objects.filter(user__id=rp_state)
+ for i in a:
+ state_list.append(i.state_id)
+ self.queryset = SingleTraining.objects.filter(tdate__gt=datetime.today().date().isoformat(),status=2, academic__state__id__in = state_list).order_by('-tdate')
+ return super(SingletrainingApprovedListView, self).dispatch(*args, **kwargs)
+ elif 'Organiser' in user_group:
+ rp_state = self.request.user.organiser.academic_id
+ self.queryset = SingleTraining.objects.filter(status=2, academic__id = rp_state,tdate__gt=datetime.today().date().isoformat()).order_by('-tdate')
+ return super(SingletrainingApprovedListView, self).dispatch(*args, **kwargs)
+ elif 'Resource Person' in user_group:
+ state_list = []
+ rp_state = self.request.user.id
+ a = ResourcePerson.objects.filter(user__id=rp_state)
+ for i in a:
+ state_list.append(i.state_id)
+ self.queryset = SingleTraining.objects.filter(tdate__gt=datetime.today().date().isoformat(),status=2, academic__state__id__in = state_list).order_by('-tdate')
+ return super(SingletrainingApprovedListView, self).dispatch(*args, **kwargs)
+
+'''
+ SingletrainingRejectedListView displays the workshop requests which have been rejected
+'''
+class SingletrainingRejectedListView(ListView):
+ queryset = None
+ paginate_by = 10
+
+ def get_context_data(self, **kwargs):
+ context = super(SingletrainingRejectedListView, self).get_context_data(**kwargs)
+ temp = self.request.user.groups.all()
+ grup = []
+ for i in temp:
+ grup.append(i.name)
+ context['group'] = grup
+ return context
+
+ def dispatch(self, *args, **kwargs):
+ user_groups_object = self.request.user.groups.all()
+ user_group = []
+ for i in user_groups_object:
+ user_group.append(i.name)
+ if 'Administrator' in user_group:
+ self.queryset = SingleTraining.objects.filter(tdate__gt=datetime.today().date().isoformat(), status=5).order_by('-tdate')
+ return super(SingletrainingRejectedListView, self).dispatch(*args, **kwargs)
+ if 'Resource Person' in user_group and 'Organiser' in user_group:
+ state_list = []
+ rp_state = self.request.user.id
+ a = ResourcePerson.objects.filter(user__id=rp_state)
+ for i in a:
+ state_list.append(i.state_id)
+ self.queryset = SingleTraining.objects.filter(tdate__gt=datetime.today().date().isoformat(),status=5, academic__state__id__in = state_list).order_by('-tdate')
+ return super(SingletrainingRejectedListView, self).dispatch(*args, **kwargs)
+ elif 'Organiser' in user_group:
+ rp_state = self.request.user.organiser.academic_id
+ self.queryset = SingleTraining.objects.filter(status=5, academic__id = rp_state,tdate__gt=datetime.today().date().isoformat()).order_by('-tdate')
+ return super(SingletrainingRejectedListView, self).dispatch(*args, **kwargs)
+ elif 'Resource Person' in user_group:
+ state_list = []
+ rp_state = self.request.user.id
+ a = ResourcePerson.objects.filter(user__id=rp_state)
+ for i in a:
+ state_list.append(i.state_id)
+ self.queryset = SingleTraining.objects.filter(tdate__gt=datetime.today().date().isoformat(),status=5, academic__state__id__in = state_list).order_by('-tdate')
+ return super(SingletrainingRejectedListView, self).dispatch(*args, **kwargs)
+
+''' SingletrainingOngoingListView displays the workshops going on that particular day '''
+class SingletrainingOngoingListView(ListView):
+ queryset = None
+ paginate_by = 10
+
+ def get_context_data(self, **kwargs):
+ context = super(SingletrainingOngoingListView, self).get_context_data(**kwargs)
+ temp = self.request.user.groups.all()
+ grup = []
+ for i in temp:
+ grup.append(i.name)
+ context['group'] = grup
+ return context
+
+ def dispatch(self, *args, **kwargs):
+ user_groups_object = self.request.user.groups.all()
+ user_group = []
+ for i in user_groups_object:
+ user_group.append(i.name)
+ if 'Administrator' in user_group:
+ self.queryset = SingleTraining.objects.filter(tdate=datetime.today().date().isoformat(), status=2).order_by('-tdate')
+ return super(SingletrainingOngoingListView, self).dispatch(*args, **kwargs)
+ if 'Resource Person' in user_group and 'Organiser' in user_group:
+ state_list = []
+ rp_state = self.request.user.id
+ a = ResourcePerson.objects.filter(user__id=rp_state)
+ for i in a:
+ state_list.append(i.state_id)
+ self.queryset = SingleTraining.objects.filter(tdate=datetime.today().date().isoformat(), status=2, academic__state__id__in = state_list).order_by('-tdate')
+ return super(SingletrainingOngoingListView, self).dispatch(*args, **kwargs)
+ elif 'Organiser' in user_group:
+ rp_state = self.request.user.organiser.academic_id
+ self.queryset = SingleTraining.objects.filter(tdate=datetime.today().date().isoformat(), status=2, academic__id = rp_state).order_by('-tdate')
+ return super(SingletrainingOngoingListView, self).dispatch(*args, **kwargs)
+ elif 'Resource Person' in user_group:
+ state_list = []
+ rp_state = self.request.user.id
+ a = ResourcePerson.objects.filter(user__id=rp_state)
+ for i in a:
+ state_list.append(i.state_id)
+ self.queryset = SingleTraining.objects.filter(tdate=datetime.today().date().isoformat(), status=2, academic__state__id__in = state_list).order_by('-tdate')
+ return super(SingletrainingOngoingListView, self).dispatch(*args, **kwargs)
+
+'''
+SingleTrainingCompletedListView will list all the completed training requests in the single-training page.
+
+'''
+class SingletrainingCompletedListView(ListView):
+ queryset = None
+ paginate_by = 10
+
+
+ def dispatch(self, *args, **kwargs):
+ user_groups_object = self.request.user.groups.all()
+ user_group = []
+ for i in user_groups_object:
+ user_group.append(i.name)
+ if 'Administrator' in user_group:
+ self.queryset = SingleTraining.objects.filter(Q(status=4)).order_by('-tdate')
+ return super(SingletrainingCompletedListView, self).dispatch(*args, **kwargs)
+ if 'Resource Person' in user_group and 'Organiser' in user_group:
+ state_list = []
+ rp_state = self.request.user.id
+ a = ResourcePerson.objects.filter(user__id=rp_state)
+ for i in a:
+ state_list.append(i.state_id)
+ self.queryset = SingleTraining.objects.filter(Q(status=4), academic__state__id__in = state_list).order_by('-tdate')
+ return super(SingletrainingCompletedListView, self).dispatch(*args, **kwargs)
+ elif 'Organiser' in user_group:
+ rp_state = self.request.user.organiser.academic_id
+ self.queryset = SingleTraining.objects.filter(Q(status=4), academic__id = rp_state).order_by('-tdate')
+ return super(SingletrainingCompletedListView, self).dispatch(*args, **kwargs)
+ elif 'Resource Person' in user_group:
+ state_list = []
+ rp_state = self.request.user.id
+ a = ResourcePerson.objects.filter(user__id=rp_state)
+ for i in a:
+ state_list.append(i.state_id)
+ self.queryset = SingleTraining.objects.filter(Q(status=4), academic__state__id__in = state_list).order_by('-tdate')
+ return super(SingletrainingCompletedListView, self).dispatch(*args, **kwargs)
+
+ def get_context_data(self, **kwargs):
+ context = super(SingletrainingCompletedListView, self).get_context_data(**kwargs)
+ temp = self.request.user.groups.all()
+ grup = []
+ for i in temp:
+ grup.append(i.name)
+ context['group'] = grup
+ return context
+"""
+#$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$4444
+class SingleTrainingCertificateListView(ListView):
+ queryset = SingleTrainingAttendance.objects.none()
+ paginate_by = 500
+ template_name = ""
+ training_request = None
+
+ def dispatch(self, *args, **kwargs):
+ self.training_request = SingleTraining.objects.get(pk=kwargs['tid'])
+ print((self.training_request.id))
+ self.queryset = SingleTrainingAttendance.objects.filter(training_id=self.training_request.id, status=1)
+ return super(SingleTrainingCertificateListView, self).dispatch(*args, **kwargs)
+
+ def get_context_data(self, **kwargs):
+ context = super(SingleTrainingCertificateListView, self).get_context_data(**kwargs)
+ context['training'] = self.training_request
+ languages = Language.objects.filter(
+ id__in = FossAvailableForWorkshop.objects.filter(
+ foss_id = self.training_request.course.foss_id
+ ).values_list('language_id')
+ )
+ #language
+ #for lang in languages:
+ context['languages'] = languages
+ return context
+
+"""
+''' Pending Attendance '''
+class SingletrainingPendingAttendanceListView(ListView):
+ queryset = None
+ paginate_by = 10
+
+ def dispatch(self, *args, **kwargs):
+ user_groups_object = self.request.user.groups.all()
+ user_group = []
+ for i in user_groups_object:
+ user_group.append(i.name)
+ if 'Administrator' in user_group:
+ # self.queryset = SingleTraining.objects.filter(tdate__lt=datetime.today().date().isoformat(), status=2).order_by('-tdate')
+ # return super(SingletrainingPendingAttendanceListView, self).dispatch(*args, **kwargs)
+ state_list = []
+ rp_state = self.request.user.id
+ a = ResourcePerson.objects.filter(user__id=rp_state)
+ for i in a:
+ state_list.append(i.state_id)
+ self.queryset = SingleTraining.objects.filter(tdate__lt=datetime.today().date().isoformat(), status=2,).order_by('-tdate')
+ return super(SingletrainingPendingAttendanceListView, self).dispatch(*args, **kwargs)
+ if 'Resource Person' in user_group and 'Organiser' in user_group:
+ state_list = []
+ rp_state = self.request.user.id
+ a = ResourcePerson.objects.filter(user__id=rp_state)
+ for i in a:
+ state_list.append(i.state_id)
+ self.queryset = SingleTraining.objects.filter(tdate__lt=datetime.today().date().isoformat(), status=6, academic__state_id__in=state_list).order_by('-tdate')
+ return super(SingletrainingPendingAttendanceListView, self).dispatch(*args, **kwargs)
+ elif 'Organiser' in user_group:
+ org_inst = self.request.user.organiser.academic_id
+ self.queryset = SingleTraining.objects.filter(tdate__lt=datetime.today().date().isoformat(), status=2, academic__id=org_inst).order_by('-tdate')
+ return super(SingletrainingPendingAttendanceListView, self).dispatch(*args, **kwargs)
+ elif 'Resource Person' in user_group:
+ state_list = []
+ rp_state = self.request.user.id
+ a = ResourcePerson.objects.filter(user__id=rp_state)
+ for i in a:
+ state_list.append(i.state_id)
+ self.queryset = SingleTraining.objects.filter(tdate__lt=datetime.today().date().isoformat(), status=6, academic__state_id__in=state_list).order_by('-tdate')
+ return super(SingletrainingPendingAttendanceListView, self).dispatch(*args, **kwargs)
+
+ def get_context_data(self, **kwargs):
+ context = super(SingletrainingPendingAttendanceListView, self).get_context_data(**kwargs)
+ temp = self.request.user.groups.all()
+ date_today = datetime.today().date().isoformat()
+ grup = []
+ for i in temp:
+ grup.append(i.name)
+ context['group'] = grup
+ context['date'] = date_today
+ return context
+"""
+
+'''
+SingleTrainingCreateView will create a request for a new One day workshop.
+
+'''
+
+# class SingletrainingCreateView(CreateView):
+# form_class = SingleTrainingForm
+# template_name = ""
+# success_url = "/software-training/single-training/pending/"
+
+# def form_valid(self, form, **kwargs):
+# form_data = form.save(commit=False)
+# if 'academic' not in self.request.POST:
+# form_data.academic = self.request.user.organiser.academic
+# elif not self.request.POST.get('academic'):
+# form_data.academic = self.request.user.organiser.academic
+
+# form_data.organiser = self.request.user.organiser
+# student = None
+# skipped, error, warning, write_flag = self.csv_email_validate(self.request.FILES['csv_file'], str(self.request.POST.get('training_type')))
+# context = {'error': error, 'warning': warning, 'batch': form_data}
+# csv_error_line_num = ''
+
+# if error or skipped:
+# messages.error(self.request, "Batch not added: Error in CSV file")
+# for i in error:
+# csv_error_line_num = (csv_error_line_num+'%d, ')%(i+1)
+# messages.error(self.request, "You have error(s) in your CSV file on line numbers %s"%(csv_error_line_num))
+
+# else:
+# form_data.save()
+# student_exists, student_count, csv_data_list = self.create_singletraining_db(self.request.FILES['csv_file'], form_data.id, form_data.course.id)
+# if len(student_exists) == len(csv_data_list):
+# messages.error(self.request, "Batch not added: Batch already exists for the same course")
+# elif student_exists:
+# messages.error(self.request, "Batch added but Duplicate entries exist in CSV file")
+# else:
+# messages.success(self.request, "Student Batch added successfully.")
+# #SingleTraining.objects.get(id=form_data.id).update(total_participant_count=student_count)
+# form_data.participant_count = student_count
+# form_data.total_participant_count = student_count
+# form_data.save()
+# if not student_count:
+# form_data.delete()
+# return HttpResponseRedirect(self.success_url)
+
+# def email_validator(self, email):
+# if email and email.strip():
+# email = email.strip().lower()
+# try:
+# validate_email(email)
+# return True
+# except:
+# pass
+# return False
+
+# '''
+# get_student_vocational() will fetch the student object having the email id passed to it as an argument.
+
+# '''
+# def get_student_vocational(self, batch_id, email):
+# if email and email.strip():
+# email = email.strip().lower()
+# try:
+# student = SingleTrainingAttendance.objects.get(email=email, foss=batch_id)
+# return student
+# except ObjectDoesNotExist:
+# pass
+# return False
+
+# '''
+# create_student_vocational() will add the database entry for the student
+
+# '''
+# def create_student_vocational(self, training_id, fossid, fname, lname, email, gender):
+# if not fname or not lname or not email or not gender:
+# return False
+# user = None
+# fname = fname.strip().upper()
+# lname = lname.strip().upper()
+# email = email.strip().lower()
+# gender = gender.strip().lower()
+
+# if fname and lname and email and gender:
+# if gender == 'male' or gender == 'm':
+# gender = 'Male'
+# else:
+# gender = 'Female'
+# student = SingleTrainingAttendance.objects.create(training_id = training_id, foss = fossid, firstname = fname, lastname = lname, email = email, gender = gender)
+# return student
+# return False
+
+# '''
+# csv_email_validate() will validate the email field, from the CSV file, for the School and Vocational training type.
+
+# '''
+# def csv_email_validate(self, file_path, ttype):
+# skipped = []
+# error = []
+# warning = []
+# write_flag = False
+# csv_data = []
+# csvdata = csv.reader(file_path, delimiter=',', quotechar='|')
+
+# # School
+
+# if ttype == '0':
+
+# for i in csvdata:
+# csv_data.append(i)
+# for j in range(len(csv_data)):
+# if len(csv_data[j]) < 3:
+# skipped.append(j)
+# continue
+# if csv_data[j][0] == '':
+# error.append(j)
+# continue
+# if csv_data[j][1] == '':
+# error.append(j)
+# continue
+# if csv_data[j][3] == '':
+# error.append(j)
+# continue
+
+# #Vocational
+# else:
+# for i in csvdata:
+# csv_data.append(i)
+# for j in range(len(csv_data)):
+# if len(csv_data[j]) < 4:
+# skipped.append(j)
+# continue
+# if csv_data[j][0]=='':
+# error.append(j)
+# continue
+# if csv_data[j][1]=='':
+# error.append(j)
+# continue
+# if not self.email_validator(csv_data[j][2]):
+# error.append(j)
+# continue
+# if csv_data[j][3]=='':
+# error .append(j)
+# continue
+
+# return (skipped, error, warning, write_flag)
+
+# '''
+# This will call the create_student_vocational() method to create the student entry, from the CSV file, in the SingleTraining database.
+
+# '''
+# def create_singletraining_db(self, file_path, tr_id, batch_id):
+# csv_data_list = []
+# student_exists = []
+# count = 0
+# csvdata = csv.reader(file_path, delimiter=',', quotechar='|')
+# for i in csvdata:
+# csv_data_list.append(i)
+# for j in range(len(csv_data_list)):
+# student = self.get_student_vocational(batch_id, csv_data_list[j][2])
+# if student:
+# student_exists.append(student)
+# else:
+# self.create_student_vocational(tr_id, batch_id, csv_data_list[j][0], csv_data_list[j][1], csv_data_list[j][2], csv_data_list[j][3])
+# student_count = SingleTrainingAttendance.objects.filter(training_id=tr_id).count()
+# return student_exists, student_count, csv_data_list
+
+'''
+SingleTrainingUpdateView will update a request for a existing One day workshop.
+
+'''
+
+class SingletrainingUpdateView(UpdateView):
+ model = SingleTraining
+ form_class = SingleTrainingEditForm
+ success_url = "/software-training/single-training/pending/"
+
+ def form_valid(self, form, **kwargs):
+ form_data = form.save(commit=False)
+ if 'csv_file' in self.request.FILES and self.request.FILES['csv_file']:
+ stcv = SingletrainingCreateView()
+ skipped, error, warning, write_flag = stcv.csv_email_validate(self.request.FILES['csv_file'], str(self.request.POST.get('training_type')))
+ context = {'error': error, 'warning': warning, 'batch': form_data}
+ csv_error_line_num = ''
+ if error or skipped:
+ for i in error:
+ csv_error_line_num = (csv_error_line_num+'%d, ')%(i+1)
+ messages.error(self.request, "You have error(s) in your CSV file on line numbers %s"%(csv_error_line_num))
+
+ else:
+ form_data.save()
+ student_exists, student_count, csv_data_list = stcv.create_singletraining_db(self.request.FILES['csv_file'], form_data.id, form_data.course.id)
+
+ form_data.participant_count = student_count
+ form_data.total_participant_count = student_count
+ form_data.save()
+ messages.success(self.request, "Student Batch updated successfully.")
+ return HttpResponseRedirect(self.success_url)
+
+'''
+SingleTrainingListView will list all the new/pending training requests in the single-training page pertaining to a specific user, i.e, Organiser or Resource Person.
+
+'''
+
+class SingleTrainingListView(ListView):
+ queryset = None
+ paginate_by = 10
+ user = None
+ status = None
+
+ @method_decorator(group_required("Organiser", "Resource Person", "Administrator"))
+ def dispatch(self, *args, **kwargs):
+ user = self.request.user
+ status_list = {
+ 'pending' : 0,
+ 'approved' : 2,
+ 'ongoing' : 3,
+ 'completed' : 4,
+ 'rejected' : 5,
+ 'pendingattendance' : 6,
+ }
+ self.status = kwargs['status']
+ if not self.status in status_list :
+ raise PermissionDenied()
+
+ if is_administrator(user):
+ self.queryset = SingleTraining.objects.filter(Q(status=status_list[self.status])).order_by('-tdate')
+ return super(SingleTrainingListView, self).dispatch(*args, **kwargs)
+
+ if is_resource_person(user) and is_organiser(user):
+ self.queryset = SingleTraining.objects.filter(Q(status=status_list[self.status]), academic__state = user.resource_person.filter(resourceperson__status=1)).order_by('-tdate')
+
+ elif is_organiser(user):
+ self.queryset = SingleTraining.objects.filter(Q(status=status_list[self.status]), academic__id = self.request.user.organiser.academic_id).order_by('-tdate')
+
+ elif is_resource_person(user):
+ self.queryset = SingleTraining.objects.filter(Q(status=status_list[self.status]), academic__state=user.resource_person.filter(resourceperson__status=1)).order_by('-tdate')
+ return super(SingleTrainingListView, self).dispatch(*args, **kwargs)
+
+ def get_context_data(self, **kwargs):
+ context = super(SingleTrainingListView, self).get_context_data(**kwargs)
+ context['status'] = self.status
+ return context
+
+
+'''
+SingletrainingMarkCompleteUpdateView will update ongoing to completed.
+'''
+#@method_decorator(group_required("Organiser", "Resource Person", "Administrator"))
+class SingletrainingMarkCompleteUpdateView(UpdateView):
+ model = SingleTraining
+ form_class = SingleTrainingEditForm
+ success_url = "/software-training/single-training/completed/"
+
+ def dispatch(self, *args, **kwargs):
+ st = SingleTraining.objects.get(pk=kwargs['pk'])
+ if not self.request.user.id == st.organiser.user_id:
+ return HttpResponseRedirect('/software-training/single-training/ongoing/')
+
+ if st.training_type in [1,2] and st.tdate <= datetime.today().date() and st.status == 3:
+ st.status = 4
+ st.save()
+ return HttpResponseRedirect(self.success_url)
+
+ date_extn = datetime.today().date() + timedelta(days=15)
+ if date_extn >= st.tdate or st.status != 3:
+ return HttpResponseRedirect('/software-training/single-training/ongoing/')
+
+ st.status = 4
+ st.save()
+ return HttpResponseRedirect(self.success_url)
+ return super(SingletrainingMarkCompleteUpdateView, self).dispatch(*args, **kwargs)
+
+
+''' SingleTrainingAttendance is used to (1) List the attendance view, (2) Mark the attendance '''
+
+class SingleTrainingAttendanceListView(ListView):
+ queryset = SingleTrainingAttendance.objects.none()
+ paginate_by = 500
+ template_name = ""
+ single_training = None
+ @method_decorator(group_required("Organiser", "Resource Person", "Administrator"))
+ def dispatch(self, *args, **kwargs):
+ self.single_training = SingleTraining.objects.get(pk=kwargs['tid'])
+ # if status 4 redirect to download certificate page
+ if self.single_training.status == 4:
+ return HttpResponseRedirect('/software-training/single-training/completed/')
+
+ if self.single_training.status == 2 or self.single_training.status == 3:
+# self.queryset = self.training_request.trainingattend_set.all()
+ self.queryset = SingleTrainingAttendance.objects.filter(training_id=self.single_training.id)
+ elif self.single_training.status == 4:
+ self.queryset = SingleTrainingAttendance.objects.filter(training_id=self.single_training.id, status=1)
+ else:
+ self.queryset = SingleTrainingAttendance.objects.filter(training_id=self.single_training.id)
+ return super(SingleTrainingAttendanceListView, self).dispatch(*args, **kwargs)
+
+ def get_context_data(self, **kwargs):
+ context = super(SingleTrainingAttendanceListView, self).get_context_data(**kwargs)
+ """date_today = datetime.today().date().isoformat()
+ participant_count = self.queryset[0].training.participant_count
+ tr_date = self.queryset[0].training.tdate
+ training_date = self.queryset[0].training.tdate.isoformat()
+ training_status = self.queryset[0].training.status
+ institute_id = self.queryset[0].training.academic_id
+ institute = AcademicCenter.objects.get(id=institute_id)
+ foss_id = self.queryset[0].training.course_id
+ foss_list = CourseMap.objects.get(id=foss_id)
+ foss_name_list = foss_list.foss
+ organiser_id = self.queryset[0].training.organiser_id
+ organiser_object = Organiser.objects.get(id=organiser_id).user_id
+ organiser_firstname = User.objects.get(id=organiser_object).first_name
+ organiser_lastname = User.objects.get(id=organiser_object).last_name
+ organiser_name = organiser_firstname + " " + organiser_lastname
+ date_extn = tr_date + timedelta(days=15)
+ date_extn = date_extn.isoformat()
+ total_participant_count = SingleTrainingAttendance.objects.filter(training_id=self.single_training_request.id)
+ temp = self.request.user.groups.all()
+ grup = []
+ for i in temp:
+ grup.append(i.name)
+ context['total_participant_count'] = total_participant_count
+ context['organiser_name'] = organiser_name
+ context['pr_count'] = participant_count
+ context['tdate'] = tr_date
+ context['extn_date'] = date_extn
+ context['foss'] = foss_name_list
+ context['institute'] = institute
+ context['group'] = grup
+ context['date'] = date_today
+ context['training_date'] = training_date
+ context['training_status'] = training_status"""
+ attendance = self.single_training.singletrainingattendance_set.filter(status=True).count()
+ canComplete = False
+ if self.single_training.training_type in [1,2] and self.single_training.tdate <= datetime.today().date() and self.single_training.status == 3 and attendance:
+ canComplete = True
+
+ date_extn = datetime.today().date() - timedelta(days=15)
+ if date_extn <= self.single_training.tdate and self.single_training.status == 3 and is_resource_person(self.request.user) and attendance:
+ canComplete = True
+
+ context['single_training'] = self.single_training
+ context['canComplete'] = canComplete
+ return context
+
+ def post(self, request, *args, **kwargs):
+ training_id = kwargs['tid']
+ if request.POST:
+ if csrf.get_token(request) == request.POST['csrfmiddlewaretoken']:
+ marked_student = request.POST.getlist('user',None)
+ if marked_student:
+ SingleTrainingAttendance.objects.filter(training_id=training_id).update(status=0)
+ for record in marked_student:
+ student = SingleTrainingAttendance.objects.get(id=record)
+ student.status = 1
+ training_id = student.training_id
+ student.save()
+ training_status = SingleTraining.objects.get(id=training_id)
+ training_status.status = 3
+ training_status.participant_count = len(marked_student)
+ training_status.save()
+ return HttpResponseRedirect('/software-training/single-training/'+str(self.
+ single_training.id)+'/attendance')
+
+ '''
+ def post(self, request, *args, **kwargs):
+ self.object = None
+ self.user = request.user
+ training_id = kwargs['tid']
+ if request.POST and 'user' in request.POST:
+ if csrf.get_token(request) == request.POST['csrfmiddlewaretoken']:
+ marked_student = request.POST.getlist('user', None)
+ # delete un marked record if exits
+ TrainingAttend.objects.filter(training_id =training_id).exclude(student_id__in = marked_student).delete()
+ # insert new record if not exits
+ for record in marked_student:
+ language_id = request.POST.get(record)
+ training_attend = TrainingAttend.objects.filter(training_id =training_id, student_id = record)
+ if not training_attend.exists():
+ TrainingAttend.objects.create(training_id =training_id, student_id = record, language_id=language_id)
+ else:
+ training_attend = training_attend.first()
+ training_attend.language_id = language_id
+ training_attend.save()
+ #print marked_student
+ else:
+ TrainingAttend.objects.filter(training_id =training_id).delete()
+ self.training_request.update_participants_count()
+ return HttpResponseRedirect('/software-training/training-planner')
+ '''
+
+
+''' SingleTrainingApprove will take an argument(primary key of a training batch) and change the status of the SingleTraining batch, in the SingleTraining database, from pending to approved.
+
+Status code:
+------------
+0 - new/pending
+2 - approved
+3 - ongoing
+4 - completed
+5 - Rejected
+6 - PendingAttendanceMark
+
+'''
+def SingleTrainingApprove(request, pk):
+ st = SingleTraining.objects.get(pk=pk)
+ if st:
+ st.status = 2
+ st.save()
+ #Send Emails from here
+ else:
+ print("Error")
+ return HttpResponseRedirect('/software-training/single-training/approved/')
+
+''' SingleTrainingReject will take an argument(primary key of a training batch) and change the status of the SingleTraining batch, in the database, from pending to rejected
+'''
+
+def SingleTrainingReject(request, pk):
+ st = SingleTraining.objects.get(pk=pk)
+ if st:
+ st.status = 5
+ st.save()
+ else:
+ print("Error")
+ return HttpResponseRedirect("/software-training/single-training/approved/")
+
+#using in stp mark attendance also
+def SingleTrainingPendingAttendance(request, pk):
+ st = SingleTraining.objects.get(pk=pk)
+ if st:
+ st.status = 6
+ st.save()
+ else:
+ print("Error")
+ return HttpResponseRedirect("/software-training/single-training/pending/")
+
+def MarkAsComplete(request, pk):
+ #pk =0
+ st = TrainingRequest.objects.get(pk=pk)
+ if st:
+ st.status = 2 #request mark to complete
+ st.save()
+ messages.success(request, 'Request to mark training complete successfully sent')
+ else:
+ print("Error")
+ messages.error(request, 'Request not sent.Please try again.')
+ return HttpResponseRedirect("/software-training/training-planner/")
+
+def MarkComplete(request, pk):
+ #pk =0
+ st = TrainingRequest.objects.get(pk=pk)
+ if st and st.status == 2:
+ st.status = 1 #mark to complete
+ st.cert_status = 1 #allow certificate
+ st.save()
+ messages.success(request, 'Training Marked as complete.')
+ else:
+ messages.error(request, 'Something went wrong Please try again')
+ return HttpResponseRedirect("/software-training/training-request/rp/markcomplete/")
+
+class OldTrainingListView(ListView):
+ queryset = Training.objects.none()
+ paginate_by = 50
+ template_name = ""
+ header = None
+ raw_get_data = None
+ @method_decorator(group_required("Resource Person"))
+ def dispatch(self, *args, **kwargs):
+ self.queryset = Training.objects.exclude(id__in=TrainingRequest.objects.filter(participants__gt=0).values_list('id'), ).filter(Q(status__gte=1) & Q(status__lte=3), id__in=TrainingAttendance.objects.all().values_list('training_id').distinct(), academic__state_id__in=self.request.user.resourceperson_set.all().values_list('state_id').distinct())
+ self.header = {
+ 1: SortableHeader('#', False),
+ 2: SortableHeader('academic', True, 'Institution'),
+ 3: SortableHeader('academic__state', True, 'State'),
+ 4: SortableHeader('foss_foss', True, 'Foss'),
+ 5: SortableHeader('tdate', True, 'Date'),
+ 6: SortableHeader('id', True, 'Workshop Code'),
+ 7: SortableHeader('Action', False, ''),
+ }
+ self.raw_get_data = self.request.GET.get('o', None)
+ self.queryset = get_sorted_list(self.request, self.queryset, self.header, self.raw_get_data)
+ return super(OldTrainingListView, self).dispatch(*args, **kwargs)
+
+ def get_context_data(self, **kwargs):
+ context = super(OldTrainingListView, self).get_context_data(**kwargs)
+ context['header'] = self.header
+ context['ordering'] = get_field_index(self.raw_get_data)
+ return context
+
+
+class OldStudentListView(ListView):
+ queryset = TrainingAttendance.objects.none()
+ paginate_by = 0
+ template_name = None
+ header = None
+ raw_get_data = None
+ @method_decorator(group_required("Resource Person"))
+ def dispatch(self, *args, **kwargs):
+ self.queryset = TrainingAttendance.objects.filter(training_id=kwargs['tid'])
+ self.header = {
+ 1: SortableHeader('#', False),
+ 2: SortableHeader('firstname', True, 'First Name'),
+ 3: SortableHeader('lastname', True, 'Last Name'),
+ 4: SortableHeader('email', True, 'Email'),
+ 5: SortableHeader('gender', True, 'Gender'),
+ 6: SortableHeader('', False, ''),
+ }
+ self.raw_get_data = self.request.GET.get('o', None)
+ self.queryset = get_sorted_list(self.request, self.queryset, self.header, self.raw_get_data)
+ return super(OldStudentListView, self).dispatch(*args, **kwargs)
+
+ def get_context_data(self, **kwargs):
+ context = super(OldStudentListView, self).get_context_data(**kwargs)
+ context['header'] = self.header
+ context['ordering'] = get_field_index(self.raw_get_data)
+ return context
+
+
+class OldTrainingCloseView(CreateView):
+ def _find_course(self, foss, category):
+ return CourseMap.objects.get(foss= foss, category = category)
+
+ def _create_training_planner(self, year, academic_id, organiser_id, created, even=False):
+ tp = None
+ semester = 2
+ if even:
+ year = int(year) -1
+ semester = 1
+ try:
+ tp = TrainingPlanner.objects.get(year=year, academic_id=academic_id, organiser_id=organiser_id, semester__even=even)
+ except:
+ try:
+ tp = TrainingPlanner()
+ tp.semester_id = semester
+ tp.year = year
+ tp.academic_id = academic_id
+ tp.organiser_id = organiser_id
+ tp.created = created
+ tp.updated = created
+ tp.save()
+ except Exception as e:
+ print(e)
+ return tp
+
+ def _get_student(self, ta):
+ mail = ta.email.strip().lower()
+ firstname = ta.firstname.strip()
+ lastname = ta.lastname.strip()
+ student = None
+ if firstname:
+ firstname = firstname.upper()
+ if lastname:
+ lastname = lastname.upper()
+ gender = 'Female'
+ if ta.gender == 'Male' or ta.gender == 'M':
+ gender = 'Male'
+ user = None
+ try:
+ user = User.objects.get(email = mail)
+ except:
+ user = User.objects.create_user(mail, mail, firstname)
+ if user:
+ try:
+ user.groups.add(student)
+ except:
+ pass
+ try:
+ student = Student.objects.get(user = user)
+ except:
+ student = Student.objects.create(user = user, gender = gender)
+ return student
+
+ def _fill_participants_attendance(self, tr, otr, language):
+ st_count = 0
+ tas = TrainingAttendance.objects.exclude(email=None).filter(training=otr)
+ for ta in tas:
+ student = self._get_student(ta)
+ if not student:
+ continue
+ if not TrainingAttend.objects.filter(training=tr, student=student).count():
+ TrainingAttend.objects.create(training=tr, student=student, language=language)
+ st_count += 1
+ return st_count
+
+ def dispatch(self, *args, **kwargs):
+ if 'tid' in kwargs:
+ training = Training.objects.filter(pk=kwargs['tid'])
+ others = Department.objects.get(name="Others")
+ if training.exists():
+ training = training.first()
+ try:
+ new_training = TrainingRequest.objects.get(pk=training.id)
+ new_training = self._fill_participants_attendance(tr, training, training.language)
+ new_training.save()
+ messages.error(self.request, 'The selected training is already added to Semester-Planner')
+ except:
+ year = str(datetime.datetime.now().year)
+ tdate = datetime.strptime(training.tdate.strftime('%Y-%m-%d'), '%Y-%m-%d')
+ even_start = datetime.strptime(year + '-01-01', '%Y-%m-%d')
+ even_end = datetime.strptime(year + '-06-30', '%Y-%m-%d')
+ if tdate >= even_start and tdate <= even_end:
+ tp = self._create_training_planner(year, training.academic_id, training.organiser_id, training.tdate, even=True)
+ else:
+ tp = self._create_training_planner(year, training.academic_id, training.organiser_id, training.tdate)
+ if tp:
+ tr = TrainingRequest()
+ tr.id = training.id
+ tr.sem_start_date = training.tdate
+ tr.created = training.created
+ tr.updated = training.updated
+ tr.batch_id = None
+ tr.course = self._find_course(training.foss, 0)
+ if not training.department.first():
+ training.department.add(others.id)
+ tr.department = training.department.first() # what to do if multiple dept
+ tr.language = training.language
+ tr.training_planner = tp
+ tr.status = 1
+ tr.save()
+ tr_count = self._fill_participants_attendance(tr, training, training.language)
+ tr.participants = tr_count
+ tr.save()
+ messages.success(self.request, 'Training status updated successfully')
+ return HttpResponseRedirect('/software-training/old-training/')
+ else:
+ return PermissionDenied()
+ return super(OldTrainingCloseView, self).dispatch(*args, **kwargs)
+
+class OrganiserFeedbackCreateView(CreateView):
+ form_class = OrganiserFeedbackForm
+ template_name = "organiser_feedback.html"
+ success_url = "/home"
+
+ @method_decorator(group_required("Organiser"))
+ def get(self, request, *args, **kwargs):
+ return render(self.request, self.template_name, {'form': self.form_class()})
+
+ def post(self, request, *args, **kwargs):
+ self.object = None
+ form = self.get_form(self.get_form_class())
+ if form.is_valid():
+ form.save()
+ messages.success(self.request, "Thank you for completing this feedback form. We appreciate your input and valuable suggestions.")
+ return HttpResponseRedirect(self.success_url)
+ else:
+ return self.form_invalid(form)
+
+class OrganiserFeedbackListView(ListView):
+ queryset = None
+ paginate_by = 10
+
+ def dispatch(self, *args, **kwargs):
+ self.queryset = OrganiserFeedback.objects.all()
+ return super(OrganiserFeedbackListView, self).dispatch(*args, **kwargs)
+
+ def get_context_data(self, **kwargs):
+ context = super(OrganiserFeedbackListView, self).get_context_data(**kwargs)
+ context['count'] = OrganiserFeedback.objects.all().count()
+ return context
+
+def LatexWorkshopFileUpload(request):
+ template_name = 'latex_workshop_file_upload.html'
+ if request.method == 'POST':
+ form = LatexWorkshopFileUploadForm(request.POST, request.FILES)
+ if form.is_valid():
+ uploaded_file = request.FILES['file_upload']
+ '''
+ email = request.POST['email']
+ email = email.replace('.', '_')
+ email = email.replace('@', '_')
+ print(e)mail
+ f = open('media/latex/{0}/{1}'.format(email, uploaded_file), 'wb+')
+ for data in uploaded_file.chunks():
+ f.write(data)
+ f.close()
+ '''
+ form.save()
+ form = LatexWorkshopFileUploadForm()
+ context=RequestContext(request, {'form': form, 'success': True})
+ return render(request, template_name, context)
+ else:
+ context=RequestContext(request, {'form': form})
+ return render(request, template_name, context)
+ else:
+ form = LatexWorkshopFileUploadForm()
+ context=RequestContext(request, {'form':form})
+ return render(request, template_name, context)
+
+class UpdateStudentName(UpdateView):
+ model = User
+ form_class = UserForm
+ user = None
+ def dispatch(self, *args, **kwargs):
+ self.user = User.objects.get(pk=kwargs['pk'])
+ self.success_url="/software-training/student-batch/"+str(kwargs['bid'])+"/view"
+ return super(UpdateStudentName, self).dispatch(*args, **kwargs)
+
+ def get_context_data(self, **kwargs):
+ context = super(UpdateStudentName, self).get_context_data(**kwargs)
+ context['user'] = self.user
+ return context
+
+ def form_valid(self, form, **kwargs):
+ try:
+ email = form.cleaned_data['email']
+ old_email = self.user.email
+ self.user.student.gender = form.cleaned_data['gender']
+ self.user.student.save()
+ self.user.first_name = form.cleaned_data['first_name']
+ self.user.last_name = form.cleaned_data['last_name']
+ if self.user.email != email:
+ try:
+ user = User.objects.get(email = email)
+ messages.error(self.request, "%s already exists." % (email))
+ return self.form_invalid(form)
+ except User.DoesNotExist:
+ pass
+ # Set verify as false
+ self.user.is_active = 0
+ self.user.student.verified = 0
+ self.user.student.error = 0
+ # Save student
+ self.user.student.save()
+ self.user.email = email
+ self.user.username = email
+ self.user.save()
+ mdluser = MdlUser.objects.get(email=old_email)
+ mdluser.email = email
+ mdluser.username = email
+ mdluser.firstname = form.cleaned_data['first_name']
+ mdluser.lastname = form.cleaned_data['last_name']
+ mdluser.save()
+ #save testattendance table
+ test_attendance = TestAttendance.objects.filter(student_id = self.user.student.id)
+ if not test_attendance:
+ # mdluser = MdlUser.objects.get(email=old_email)
+ test_attendance = TestAttendance.objects.filter(mdluser_id=mdluser.id)
+ if not test_attendance:
+ return HttpResponseRedirect(self.success_url)
+ for test in test_attendance:
+ test.mdluser_firstname = form.cleaned_data['first_name']
+ test.mdluser_lastname = form.cleaned_data['last_name']
+ test.save()
+ else:
+ for test in test_attendance:
+ test.mdluser_firstname = form.cleaned_data['first_name']
+ test.mdluser_lastname = form.cleaned_data['last_name']
+ test.save()
+ except Exception:
+ pass
+ return HttpResponseRedirect(self.success_url)
+
+class STWorkshopFeedbackCreateView(CreateView):
+ form_class = STWorkshopFeedbackForm
+ template_name = "stworkshop_feedback.html"
+ success_url = "/home"
+
+ def get(self, request, *args, **kwargs):
+ return render(self.request, self.template_name, {'form': self.form_class()})
+
+ def post(self, request, *args, **kwargs):
+ self.object = None
+ form = self.get_form(self.get_form_class())
+ if form.is_valid():
+ form.save()
+ messages.success(self.request, "Thank you for completing this feedback form. We appreciate your input and valuable suggestions.")
+ return HttpResponseRedirect(self.success_url)
+ else:
+ return self.form_invalid(form)
+
+class STWorkshopFeedbackPreCreateView(CreateView):
+ form_class = STWorkshopFeedbackFormPre
+ template_name = "stworkshop_feedback_pre.html"
+ success_url = "/home"
+ user= None
+
+ @method_decorator(login_required)
+ def get(self, request, *args, **kwargs):
+ return render(self.request, self.template_name, {'form': self.form_class()})
+
+ def post(self, request, *args, **kwargs):
+ self.object = None
+ self.user = self.request.user.id
+ print((self.user))
+ form = self.get_form(self.get_form_class())
+ if form.is_valid():
+ #form.save()
+ return self.form_valid(form)
+ #messages.success(self.request, "Thank you for completing this feedback form. We appreciate your input and valuable suggestions.")
+ #return HttpResponseRedirect(self.success_url)
+ else:
+ print((form.errors))
+ return self.form_invalid(form)
+
+ def form_valid(self, form, **kwargs):
+ form_data = form.save(commit=False)
+ form_data.user = self.request.user
+ form_data.save()
+ print("saved")
+ messages.success(self.request, "Thank you for completing this feedback form. We appreciate your input and valuable suggestions.")
+ return HttpResponseRedirect(self.success_url)
+
+
+
+
+
+class STWorkshopFeedbackPostCreateView(CreateView):
+ form_class = STWorkshopFeedbackFormPost
+ template_name = "stworkshop_feedback_post.html"
+ success_url = "/home"
+
+ @method_decorator(login_required)
+ def get(self, request, *args, **kwargs):
+ return render(self.request, self.template_name, {'form': self.form_class()})
+
+ def post(self, request, *args, **kwargs):
+ self.object = None
+ form = self.get_form(self.get_form_class())
+ if form.is_valid():
+ return self.form_valid(form)
+ #form.save()
+ #messages.success(self.request, "Thank you for completing this feedback form. We appreciate your input and valuable suggestions.")
+ return HttpResponseRedirect(self.success_url)
+ else:
+ print((form.errors))
+ return self.form_invalid(form)
+
+ def form_valid(self, form, **kwargs):
+ form_data = form.save(commit=False)
+ form_data.user = self.request.user
+ form_data.save()
+ messages.success(self.request, "Thank you for completing this feedback form. We appreciate your input and valuable suggestions.")
+ return HttpResponseRedirect(self.success_url)
+
+class LearnDrupalFeedbackCreateView(CreateView):
+ form_class = LearnDrupalFeedbackForm
+ template_name = "learndrupalfeedback.html"
+ success_url = "/home"
+
+ def get(self, request, *args, **kwargs):
+ # import ipdb; ipdb.set_trace()
+ return render(self.request, self.template_name, {'form': self.form_class()})
+
+ def post(self, request, *args, **kwargs):
+ self.object = None
+ form = self.get_form(self.get_form_class())
+ if form.is_valid():
+ return self.form_valid(form)
+ else:
+ print((form.errors))
+ return self.form_invalid(form)
+
+ def form_valid(self, form, **kwargs):
+ form_data = form.save(commit=False)
+ form_data.save()
+ messages.success(self.request, "Thank you for completing this feedback form. We appreciate your input and valuable suggestions.")
+ return HttpResponseRedirect(self.success_url)
+
+def ReOpenTraining(request, pk):
+ st = TrainingRequest.objects.get(pk=pk)
+ if st:
+ st.status = 0
+ st.save()
+ messages.success(request, 'Training is now open to mark further attendance.')
+ else:
+ messages.error(request, 'Request to re-open training is not sent.Please try again.')
+ return HttpResponseRedirect("/software-training/select-participants/")
+
+
+@login_required
+def payment_home(request):
+ #to get - College name & College Type based on login user
+ user = User.objects.get(id = request.user.id)
+ try:
+ accountexecutive = Accountexecutive.objects.get(user_id = user,status=1)
+ except:
+ messages.error(request, 'Permission denied. You are not an Account Executive.')
+ return HttpResponseRedirect('/software-training')
+
+ amount = "0"
+ if accountexecutive.academic.institution_type_id == 5:
+ amount = "5000"
+ else:
+ amount = "25000"
+
+ context ={}
+ context['accountexecutive'] = accountexecutive
+ context['amount'] = amount
+ context['user_id'] = user.id
+ context['user'] = user
+ context['username'] = user.username
+ return render(request, 'payment_home.html', context)
+
+@csrf_exempt
+@login_required
+def payment_status(request):
+ context ={}
+ academic_year = datetime.datetime.today().year
+
+ if request.method == 'POST':
+ user = User.objects.get(id = request.user.id)
+ try:
+ accountexecutive = Accountexecutive.objects.get(user_id = user,status=1)
+ except:
+ messages.error(request, 'Permission denied. You are not an Account Executive.')
+ return HttpResponseRedirect('/software-training')
+ amount = "0"
+
+ if accountexecutive.academic.institution_type_id == 5:
+ amount = "5000"
+ else:
+ amount = "25000"
+
+ reqId = 0
+ try:
+ paymentdetails = PaymentDetails()
+ paymentdetails.user = user
+ paymentdetails.amount = amount
+ paymentdetails.purpose = "Subscription"
+ paymentdetails.status = 0
+ paymentdetails.description = "Payment Initiated"
+ paymentdetails.academic_id = accountexecutive.academic
+ paymentdetails.academic_year = academic_year
+ paymentdetails.gstno = request.POST['id_gstin']
+ paymentdetails.save()
+ reqId = paymentdetails.id
+
+ except Exception as e:
+ try:
+ paymentdetails = PaymentDetails.objects.get(academic_id = accountexecutive.academic.id, academic_year = academic_year)
+ reqId = paymentdetail.id
+ except:
+ return HttpResponseRedirect('/software-training/payment-home')
+
+ if paymentdetails.status == 2:
+ return render(request,'payment_status.html',data)
+ if paymentdetails.status == 1:
+ messages.error(request, 'This college has aready completed the payment.')
+ return HttpResponseRedirect('/software-training/payment-home')
+
+ messages.error(request, 'This college has aready initiated the payment.')
+ return HttpResponseRedirect('/software-training/payment-home')
+
+
+ STdata = ''
+ user_name = user.first_name+' '+user.last_name
+ STdata = CHANNEL_IDstr(reqId)+str(user.id)+str(user_name)+str(amount)+"Subscription"+CHANNEL_ID+CHANNEL_KEY
+ print(STdata)
+ s = display.value(str(STdata))
+
+ data = {
+ 'reqId' : CHANNEL_ID+str(reqId),
+ 'userId':user.id,
+ 'name':user_name,
+ 'amount':amount,
+ 'purpose':'Subscription',
+ 'channelId':CHANNEL_ID,
+ 'target':TARGET,
+ 'random':s
+ }
+ return render(request,'payment_status.html',data)
+ #not post
+ else:
+ return HttpResponseRedirect('/software-training')
+
+@csrf_exempt
+def payment_success(request):
+ context = {}
+ default_response = '/'
+ if request.method == 'POST':
+ # requestType // I/R/J (I - Immediate response,R- Reconciled & J - Transaction rejected)
+ # userId; // Id of the user
+ # amount; // amount which is to be paid
+ # reqId; // Unique request id of the transaction
+ # transId; // Unique transaction id of IITB Payment gateway
+ # refNo; // Bank transaction reference number
+ # provId; // Payment method like Credit Card/Net Banking etc..
+ # status; // S/F (Status of the transaction)
+ # msg; // Detailed transaction message
+ # purpose // Short Description
+ # random; // Hash string
+
+ requestType = request.POST.get('requestType')
+ userId = request.POST.get('userId')
+ amount = request.POST.get('amount')
+ reqId = request.POST.get('reqId')
+ transId = request.POST.get('transId')
+ refNo = request.POST.get('refNo')
+ provId = request.POST.get('provId')
+ status = request.POST.get('status')
+ msg = request.POST.get('msg')
+ purpose = request.POST.get('purpose')
+ random = request.POST.get('random')
+
+ # Update Context
+ context['transId'] = transId
+ context['refNo'] = refNo
+ context['msg'] = msg
+ context['status'] = status
+ context['amount'] = amount
+
+ STresponsedata = ''
+ STresponsedata = reqId+str(userId)+transId+refNo+amount+status+msg+purpose+CHANNEL_KEY
+ STresponsedata_hexa = display.value(str(STresponsedata))
+ template_name = 'payment_success.html'
+
+ if STresponsedata_hexa == random:
+ #School Donation Response
+ if 'school_donation' in purpose :
+ template = 'donate/school_donation_status.html'
+ try:
+ sd = SchoolDonation.objects.get(reqId=reqId)
+ context['email'] = sd.email
+ context['reqId'] = sd.reqId
+ context['name'] = sd.name
+ context['date'] = sd.created
+ transaction = add_transaction(purpose, sd.id, requestType, userId, amount, reqId, transId, refNo, provId, status, msg)
+ #send email
+ email_status, status_msg = send_transaction_email(sd.email, context)
+ sd.mail_status = email_status
+ sd.mail_response = status_msg
+ sd.save()
+ except Exception as e:
+ messages.error(request, 'Transaction failed')
+ return render(request, template, context)
+ #Subscription Responses
+ if purpose == 'Subscription':
+ try:
+ accountexecutive = Accountexecutive.objects.get(user_id = user,status=1)
+ except:
+ messages.error(request, 'Permission denied. You are not an Account Executive.')
+ return HttpResponseRedirect('/software-training')
+
+ try:
+ pd = PaymentDetails.objects.get(user = user.id, academic_id = accountexecutive.academic.id)
+ transaction = add_transaction(purpose, pd.id, requestType, userId, amount, reqId, transId, refNo, provId, status, msg)
+ default_response = '/software-training'
+ except Exception as e:
+ print(e)
+ messages.error(request, 'Something went wrong. Can not collect your transaction details. Kindly contact your state resource person.')
+ return HttpResponseRedirect('/software-training')
+
+ # Donation Responses
+ elif 'Donate' in purpose :
+ try:
+ pd = DonationPayee.objects.get(id = purpose.split('DonateNEW')[1])
+ transaction = add_transaction(purpose, pd.id, requestType, userId, amount, reqId, transId, refNo, provId, status, msg)
+ context['form'] = get_updated_form(transaction, 'Donate')
+ #template_name = ''
+ except:
+ messages.error(request, 'Validation of Donation transaction failed')
+ return render(request,template_name,context)
+
+ # Spoken Goodie Payment Responses
+ elif 'Goodie' in purpose:
+ try:
+ pd = Goodies.objects.get(id = purpose.split('GoodieNEW')[1])
+ transaction = add_transaction(purpose, pd.id, requestType, userId, amount, reqId, transId, refNo, provId, status, msg)
+ context['form'] = get_updated_form(transaction, 'Goodie')
+ #template_name = ''
+ except:
+ messages.error(request, 'Validation of Goodie Transaction failed')
+ return render(request,template_name,context)
+
+ else:
+ template_name = 'donate/templates/payment_response.html'
+ # Participant of events
+ if 'cdcontent' not in purpose:
+ try:
+ # Getting the participant
+ # NEW
+ training_participant = Participant.objects.get(
+ event=int(purpose.split("NEW")[0]), user=int(userId),
+ payment_status_id = int(purpose.split("NEW")[1]))
+ default_response = '/training/list_events/ongoing/'
+ template_name = 'reg_success.html'
+ context['user'] = User.objects.get(id=int(request.POST.get('userId')))
+ if status != 'S':
+ training_participant.delete()
+ else:
+ context['participant_obj'] = training_participant
+ except:
+ messages.error(request, 'Validation of Participant data failed')
+
+ # This part is common for CD Content Payments and Participant payment of events
+ try:
+ pd = get_payee_id(purpose)
+ if pd == 'incorrect_data':
+ messages.error(request, 'Incorrect Data')
+ return HttpResponseRedirect('/training/list_events/ongoing/')
+ transaction = add_transaction(purpose, pd.id, requestType, userId, amount, reqId, transId, refNo, provId, status, msg)
+ context['form'] = get_updated_form(transaction , 'CD-Events')
+ except :
+ messages.error(request, 'Something went wrong. Can not collect your transaction details. Kindly try again in some time.')
+ return render(request,template_name,context)
+ update_status(pd, status)
+ return render(request,template_name,context)
+ else:
+ messages.error(request, 'Invalid Transaction')
+ return HttpResponseRedirect(default_response)
+ else:
+ messages.error(request, 'Invalid Request')
+ return HttpResponseRedirect(default_response)
+
+def add_transaction(purpose, pid, requestType, userId, amount, reqId, transId, refNo, provId, status, msg):
+ if purpose == 'Subscription':
+ transaction = PaymentTransactionDetails()
+ elif 'Donate' in purpose :
+ transaction = DonationTransaction()
+ elif 'Goodie' in purpose:
+ transaction = GoodiesTransaction()
+ elif 'school_donation' in purpose:
+ transaction = SchoolDonationTransactions()
+ else:
+ transaction = PaymentTransaction()
+
+ transaction.paymentdetail_id = pid
+ transaction.requestType = requestType
+ transaction.userId_id = userId
+ transaction.amount = amount
+ transaction.reqId = reqId
+ transaction.transId = transId
+ transaction.refNo = refNo
+ transaction.provId = provId
+ transaction.status = status
+ transaction.msg = msg
+ transaction.save()
+ return transaction
+
+def get_payee_id(purpose):
+ try:
+ payee_id = purpose.split('NEW')[1]
+ pd = Payee.objects.get(id=int(payee_id))
+ return pd
+ except :
+ return 'incorrect_data'
+
+def update_status(pd, status):
+ if status == 'S':
+ pd.status = 1
+ pd.description = 'Payment successfull'
+ elif status == 'F':
+ pd.status = 2
+ pd.description = 'Payment fail'
+ pd.save()
+
+def payment_details(request,choice):
+ academic_id = Accountexecutive.objects.filter(user = request.user).values('academic_id','academic_id__institution_name')
+ paymentdetails = PaymentDetails.objects.filter(academic_id=academic_id[0]['academic_id'])
+ paymenttransactionetails = PaymentTransactionDetails.objects.filter(paymentdetail_id = paymentdetails)
+ user = User.objects.get(id = request.user.id)
+
+ context ={}
+ context['user'] = user
+ context['completed'] = paymenttransactionetails.filter(status='S').count()
+ context['failed'] = paymenttransactionetails.filter(status='F').count()
+ context['ongoing'] = paymentdetails.filter(status=0).count()
+ context['paymentdetails'] = paymenttransactionetails.values('msg','refNo','transId','provId','status',
+ 'created','paymentdetail_id__amount','paymentdetail_id__academic_year','paymentdetail_id__description')
+ context['ongoing_details'] = paymentdetails
+ context['tabid'] = choice
+ context['college'] = academic_id[0]['academic_id__institution_name']
+ return render(request,'payment_details.html',context)
+
+@csrf_exempt
+def payment_reconciliation_update(request):
+ requestType = request.GET.get('requestType')
+ userId = request.GET.get('userId')
+ amount = request.GET.get('amount')
+ reqId = request.GET.get('reqId')
+ transId = request.GET.get('transId')
+ refNo = request.GET.get('refNo')
+ provId = request.GET.get('provId')
+ status = request.GET.get('status')
+ msg = request.GET.get('msg')
+ purpose = request.GET.get('purpose')
+ random = request.GET.get('random')
+
+ STresponsedata = ''
+ STresponsedata = str(reqId)+str(userId)+transId+refNo+amount+status+msg+purpose+CHANNEL_KEY
+ STresponsedata_hexa = display.value(str(STresponsedata))
+
+ if STresponsedata_hexa == random:
+ if purpose == 'Subscription':
+ try:
+ accountexecutive = Accountexecutive.objects.get(user_id = userId,status__gt=0)
+ except:
+ print("no ac")
+ pass
+ try:
+ pd = PaymentDetails.objects.get(user_id = userId, academic_id_id = accountexecutive.academic_id)
+ except:
+ return HttpResponseRedirect("Failed1")
+ else:
+ pd = get_payee_id(purpose)
+ if pd == 'incorrect_data':
+ messages.error(request, 'Incorrect Data')
+ return HttpResponseRedirect('/training/list_events/ongoing/')
+ try:
+ transaction = add_transaction(purpose, pd.id, requestType, userId, amount, reqId, transId, refNo, provId, status, msg)
+ print("saved")
+ except:
+ return HttpResponseRedirect("Failed2")
+ update_status(pd, status)
+ else:
+ return HttpResponseRedirect("Invalid")
+ return HttpResponse("OK")
+
+@csrf_protect
+@login_required
+def academic_transactions(request):
+ user = User.objects.get(id=request.user.id)
+ rp_states = ResourcePerson.objects.filter(status=1,user=user)
+ state = State.objects.filter(id__in=rp_states.values('state'))
+ academic_center = request.POST.get('college')
+ paymenttransactiondetails = ''
+ context = {}
+ context['user'] = user
+ if request.method == 'POST':
+ form = TrainingManagerForm(user,request.POST)
+
+ # if form.is_valid():
+ # form_data = form.cleaned_data
+ get_state = request.POST.get('state')
+ status = request.POST.get('choices')
+ if academic_center in ('None','0',0):
+ academic_center = False
+ else:
+ academic_center = request.POST.get('college')
+
+ if get_state:
+ academic_centers = AcademicCenter.objects.filter(state=get_state)
+ if academic_center :
+ paymentdetails = PaymentDetails.objects.filter(academic_id=academic_center)
+ else:
+ paymentdetails = PaymentDetails.objects.filter(academic_id__in=academic_centers)
+ else:
+ academic_centers = AcademicCenter.objects.filter(state__in=state)
+ paymentdetails = PaymentDetails.objects.filter(academic_id__in=academic_centers)
+
+ if status == 'O':
+ paymentdetails = paymentdetails.filter(status=0)
+ if request.POST.get('fdate'):
+ if request.POST.get('tdate'):
+ paymentdetails = paymentdetails.filter(Q(created__gt=request.POST.get('fdate')) & Q(created__lt= request.POST.get('tdate')))
+ else:
+ paymentdetails = paymentdetails.filter(created__gt=request.POST.get('fdate'))
+ context['ongoing_details'] = paymentdetails.order_by('created')
+ else:
+ if status in ('S','F'):
+ paymenttransactiondetails = PaymentTransactionDetails.objects.filter(paymentdetail_id__in = paymentdetails, status=str(status)).exclude(requestType='R')
+ if status == 'R':
+ paymenttransactiondetails = PaymentTransactionDetails.objects.filter(paymentdetail_id__in = paymentdetails, requestType='R')
+
+ if request.POST.get('fdate'):
+ if request.POST.get('tdate'):
+ paymenttransactiondetails = paymenttransactiondetails.filter(Q(created__gt=request.POST.get('fdate')) & Q(created__lt= request.POST.get('tdate')))
+ else:
+ paymenttransactiondetails = paymenttransactiondetails.filter(created__gt=request.POST.get('fdate'))
+
+ context['transactiondetails'] = paymenttransactiondetails
+ if status == 'R':
+ context['total'] = paymenttransactiondetails.aggregate(Sum('amount'))
+
+ else:
+ form = TrainingManagerForm(user=request.user)
+ context['form'] = form
+ return render(request, 'payment.html', context)
+
+def trainingrequest(request, role, status):
+ context = {}
+ user = request.user
+ template_name = None
+ header = None
+ raw_get_data = None
+ now= datetime.datetime.now()
+ year = now.year
+ month =now.month
+
+ current_sem_type_even = 0 #odd
+ if month < 6:
+ current_sem_type_even = 1 #even
+
+ prev_sem_type = 'even'
+ prev_sem_year = year
+ if current_sem_type_even:
+ prev_sem_type = 'odd'
+ prev_sem_year = (year - 1)
+ prev_sem_start_date, prev_sem_end_date = get_prev_semester_duration(prev_sem_type, prev_sem_year)
+
+ if not (user.is_authenticated() and (is_resource_person(user) or is_administrator(user))):
+ raise PermissionDenied()
+
+ if (not role ) or (not status):
+ raise PermissionDenied()
+ else:
+ status_list = {'pending': 0, 'completed': 1, 'markcomplete':2, 'pendingattendance':3}
+ roles = ['rp', 'em']
+ user = request.user
+ if role in roles and status in status_list:
+ if status == 'completed':
+ queryset = TrainingRequest.objects.filter(
+ training_planner__academic_id__in=AcademicCenter.objects.filter(
+ state__in = State.objects.filter(
+ resourceperson__user_id=user,
+ resourceperson__status=1
+ )
+ ).values_list('id'),
+ status=1,
+ participants__gt=0
+ ).order_by('-updated')
+ elif status == 'pending':
+ queryset = TrainingRequest.objects.filter(
+ training_planner__academic_id__in=AcademicCenter.objects.filter(
+ state__in = State.objects.filter(
+ resourceperson__user_id=user,
+ resourceperson__status=1
+ )
+ ).values_list('id'),
+ status=0
+ ).order_by('-updated')
+ elif status == 'markcomplete':
+ if is_administrator(user):
+ queryset = TrainingRequest.objects.filter(status=2).order_by('-updated')
+ else:
+ queryset = TrainingRequest.objects.filter(
+ training_planner__academic_id__in=AcademicCenter.objects.filter(
+ state__in = State.objects.filter(
+ resourceperson__user_id=user,
+ resourceperson__status=1
+ )
+ ).values_list('id'),
+ status=2
+ ).order_by('-updated')
+ elif status == 'pendingattendance':
+ queryset = TrainingRequest.objects.filter(
+ training_planner__academic_id__in=AcademicCenter.objects.filter(
+ state__in = State.objects.filter(
+ resourceperson__user_id=user,
+ resourceperson__status=1,
+ )
+ ).values_list('id'),
+ status = 1, participants = 0, training_planner__semester__name = prev_sem_type , sem_start_date__gte = prev_sem_start_date
+ )
+
+ header = {
+ 1: SortableHeader('#', False),
+ 2: SortableHeader(
+ 'training_planner__academic__state__name',
+ True,
+ 'State'
+ ),
+ 3: SortableHeader(
+ 'training_planner__academic__academic_code',
+ True,
+ 'Code'
+ ),
+ 4: SortableHeader(
+ 'training_planner__academic__institution_name',
+ True,
+ 'Institution'
+ ),
+ 5: SortableHeader('batch__department__name', True, 'Department / Batch'),
+ 6: SortableHeader('course__foss__foss', True, 'Course Name'),
+ 7: SortableHeader('course_type', True, 'Course Type'),
+ 8: SortableHeader(
+ 'training_planner__organiser__user__first_name',
+ True,
+ 'Organiser'
+ ),
+ 9: SortableHeader(
+ 'sem_start_date',
+ True,
+ 'Sem Start Date / Training Date'
+ ),
+ 10: SortableHeader('participants', True, 'Participants'),
+ #11: SortableHeader('Action', False)
+ }
+ raw_get_data = request.GET.get('o', None)
+ queryset = get_sorted_list(
+ request,
+ queryset,
+ header,
+ raw_get_data
+ )
+ if status == 'completed':
+ collection= TrainingRequestFilter(request.GET, queryset=queryset, user=user, rp_completed=True)
+ elif status == 'pending':
+ collection= TrainingRequestFilter(request.GET, queryset=queryset, user=user, rp_ongoing=True)
+ elif status == 'markcomplete':
+ collection= TrainingRequestFilter(request.GET, queryset=queryset, user=user, rp_markcomplete=True)
+ elif status == 'pendingattendance':
+ collection= TrainingRequestFilter(request.GET, queryset=queryset, user=user, rp_pendingattendance=True)
+ else:
+ raise PermissionDenied()
+
+ context['form'] = collection.form
+ page = request.GET.get('page')
+ collection = get_page(collection.qs, page)
+ context['collection'] = collection
+ context['role'] = role
+ context['status'] = status
+ context['header'] = header
+ context['ordering'] = get_field_index(raw_get_data)
+
+ return render(request,'training_list.html',context)
+
+
+def CertificateRequest(request, role, choice):
+ queryset = None
+ user = request.user
+ header = None
+ raw_get_data = None
+ now= datetime.datetime.now()
+ year = now.year
+ month =now.month
+ roles = ['rp', 'em']
+ context = {}
+
+ if not (user.is_authenticated() and (is_resource_person(user) or is_administrator(user))):
+ raise PermissionDenied()
+
+ if (not 'role') or (not 'choice'):
+ raise PermissionDenied()
+
+ if role in roles and choice == 'training':
+ if is_administrator(user):
+ queryset = TrainingRequest.objects.filter(status=1, cert_status=2).order_by('-updated')
+ else:
+ queryset = TrainingRequest.objects.filter(
+ training_planner__academic_id__in=AcademicCenter.objects.filter(
+ state__in = State.objects.filter(
+ resourceperson__user_id=user,
+ resourceperson__status=1
+ )
+ ).values_list('id'),
+ status=1,
+ cert_status=2
+ ).order_by('-updated')
+ header = {
+ 1: SortableHeader('#', False),
+ 2: SortableHeader(
+ 'training_planner__academic__state__name',
+ True,
+ 'State'
+ ),
+ 3: SortableHeader(
+ 'training_planner__academic__academic_code',
+ True,
+ 'Code'
+ ),
+ 4: SortableHeader(
+ 'training_planner__academic__institution_name',
+ True,
+ 'Institution'
+ ),
+ 5: SortableHeader('batch__department__name', True, 'Department / Batch'),
+ 6: SortableHeader('course__foss__foss', True, 'Course Name'),
+ 7: SortableHeader('course_type', True, 'Course Type'),
+ 8: SortableHeader(
+ 'training_planner__organiser__user__first_name',
+ True,
+ 'Organiser'
+ ),
+ 9: SortableHeader(
+ 'sem_start_date',
+ True,
+ 'Sem Start Date / Training Date'
+ ),
+ 10: SortableHeader('participants', True, 'Participants'),
+ 11: SortableHeader('Action', False)
+ }
+ raw_get_data = request.GET.get('o', None)
+ queryset = get_sorted_list(
+ request,
+ queryset,
+ header,
+ raw_get_data
+ )
+ collection = TrainingRequestFilter(request.GET, queryset=queryset, user=user, rp_completed=True)
+ else:
+ raise PermissionDenied()
+
+ context['form'] = collection.form
+ page = request.GET.get('page')
+ collection = get_page(collection.qs, page)
+ context['collection'] = collection
+ context['role'] = role
+ context['choice'] = choice
+ context['header'] = header
+ context['ordering'] = get_field_index(raw_get_data)
+ return render(request,'certificate_request_list.html',context)
+
+def RequestCertificate(request, trid):
+ training = TrainingRequest.objects.get(pk=trid)
+ if training:
+ training.cert_status = 2 #request to generate
+ training.save()
+ messages.success(request, 'Request to generate participation certificate has successfully sent')
+ else:
+ print("Error")
+ messages.error(request, 'Request not sent.Please try again.')
+ return HttpResponseRedirect("/software-training/training-planner/")
+
+def GenerateCertificate(request, trid):
+ training = TrainingRequest.objects.get(pk=trid)
+ if training and training.status == 1 and training.cert_status == 2:
+ training.cert_status = 1 #mark to generate
+ training.save()
+ messages.success(request, 'Certificates generated.')
+ else:
+ messages.error(request, 'Something went wrong Please try again')
+ return HttpResponseRedirect("/software-training/certificate-request/rp/training/")
+
+
+class AllTrainingCertificateView(TrainingCertificate, View):
+ @method_decorator(group_required("Organiser"))
+ def dispatch(self, *args, **kwargs):
+ return super(AllTrainingCertificateView, self).dispatch(*args, **kwargs)
+ def get(self, request, *args, **kwargs):
+ ta_list = None
+ try:
+ ta_list = TrainingAttend.objects.filter(training_id=kwargs['trid'])
+ except ObjectDoesNotExist:
+ messages.error(self.request, "Record not found")
+ pass
+
+ output = PdfFileWriter()
+
+ for ta in ta_list:
+ semsplit = re.split('-|, ',ta.training.training_planner.get_semester())
+ sem_start = semsplit[0]+semsplit[2]
+
+ training_end = ta.training.sem_start_date+timedelta(days=60)
+
+ response = HttpResponse(content_type='application/pdf')
+ filename = (ta.training.course.foss.foss+"-Participant-Certificate").replace(" ", "-");
+
+ response['Content-Disposition'] = 'attachment; filename='+filename+'.pdf'
+ imgTemp = BytesIO ()
+ imgDoc = canvas.Canvas(imgTemp)
+
+ # Title
+ imgDoc.setFont('Helvetica', 35, leading=None)
+ imgDoc.drawCentredString(405, 480, "Certificate of Participation")
+
+ #date
+ if ta.training.department.id != 169:
+ imgDoc.setFont('Helvetica', 18, leading=None)
+ imgDoc.drawCentredString(211, 115, self.custom_strftime('%d %B %Y', training_end))
+
+ #password
+ certificate_pass = ''
+ imgDoc.setFillColorRGB(211, 211, 211)
+ imgDoc.setFont('Helvetica', 10, leading=None)
+ imgDoc.drawString(10, 6, certificate_pass)
+
+ # Draw image on Canvas and save PDF in buffer
+ imgPath = get_signature(ta.training.training_start_date)
+ imgDoc.drawImage(imgPath, 600, 100, 150, 76)
+
+ #paragraphe
+ text = get_training_cert_text(ta)
+
+ centered = ParagraphStyle(name = 'centered',
+ fontSize = 16,
+ leading = 30,
+ alignment = 0,
+ spaceAfter = 20
+ )
+
+ p = Paragraph(text, centered)
+ p.wrap(630, 200)
+ p.drawOn(imgDoc, 4.2 * cm, 7 * cm)
+ imgDoc.save()
+ # Use PyPDF to merge the image-PDF into the template
+ template_path = get_training_certificate(ta)
+ page = PdfFileReader(open(template_path,"rb")).getPage(0)
+ overlay = PdfFileReader(BytesIO(imgTemp.getvalue())).getPage(0)
+ page.mergePage(overlay)
+
+ #Save the result
+ output.addPage(page)
+
+ #stream to browser
+ outputStream = response
+ output.write(response)
+ outputStream.close()
+
+ return response
+
+
+class StudentGradeFilter(UserPassesTestMixin, FormView):
+ template_name = 'events/templates/student_grade_filter.html'
+ form_class = StudentGradeFilterForm
+ success_url = '/software-training/student-grade-filter/'
+
+ #get current job(Job) & pending jobs(List of Jobs)
+ def get_redis_data(self):
+ redis_data = {}
+ try:
+ workers = Worker.all(queue=TOPPER_QUEUE)
+ if workers:
+ worker = workers[0]
+ worker_status = worker.get_state()
+ current_job = worker.get_current_job()
+ redis_data['current_job'] = current_job
+ redis_data['worker_status']=worker_status
+ pending_jobs = TOPPER_QUEUE.get_jobs()
+ redis_data['pending_jobs']=pending_jobs
+ except:
+ print("error in getting worker ")
+ return redis_data
+
+ def get_topper_cache_keys(self):
+ cache_keys = ()
+ with connection.cursor() as cursor:
+ cursor.execute("SELECT * FROM topper_cache_table")
+ cache_keys=cursor.fetchall()
+ keys = [item[0][3:] for item in cache_keys]
+
+ return keys
+
+ def get_dict_val(self):
+ fosses = FossCategory.objects.values('id','foss')
+ dict_id_foss = {}
+ for item in fosses:
+ dict_id_foss[item['id']] = item['foss']
+
+ states = State.objects.values('id','name')
+ dict_id_state = {}
+ for item in states:
+ dict_id_state[item['id']] = item['name']
+
+ cities = City.objects.values('id','name')
+ dict_id_city = {}
+ for item in cities:
+ dict_id_city[item['id']] = item['name']
+
+ institutes = InstituteType.objects.values('id','name')
+ dict_id_insti = {}
+ for item in institutes:
+ dict_id_insti[item['id']] = item['name']
+ return dict_id_foss, dict_id_state, dict_id_city, dict_id_insti
+
+ def get_formatted_query(self,keys):
+ dict_id_foss, dict_id_state, dict_id_city, dict_id_insti = self.get_dict_val()
+ formatted_queries = [] # list of dictionaries, id = filter field & value = selected value
+ foss_str,state_str,city_str,institutes_str='','','',''
+ for key in keys:
+ d = {}
+ if isinstance(key,str):
+ fields = key.split(':')
+ elif isinstance(key,Job):
+ fields = key.id.split(':')
+ d['enqueued_at'] = key.enqueued_at
+ else :
+ return formatted_queries
+ foss_ids, state, city, grade, insti, active_status, from_date, to_date = fields
+ if foss_ids : foss_str = ','.join(dict_id_foss.get(int(id)) for id in foss_ids.split(';'))
+ if state : state_str = ','.join(dict_id_state.get(int(id)) for id in state.split(';'))
+ if city : city_str = ','.join(dict_id_city.get(int(id)) for id in city.split(';'))
+ if insti : institutes_str = ','.join(dict_id_insti.get(int(id)) for id in insti.split(';'))
+
+ d['foss'] = foss_str
+ d['grade'] = grade
+ d['state'] = state_str
+ d['city'] = city_str
+ d['insti'] = institutes_str
+ d['from_date'] = from_date
+ d['to_date'] = to_date
+ formatted_queries.append(d)
+ return formatted_queries
+
+ def get_query_data(self):
+ redis_data=self.get_redis_data()
+ topper_cache_keys=self.get_topper_cache_keys()
+ completed = self.get_formatted_query(topper_cache_keys)
+ pending = self.get_formatted_query(redis_data.get('pending_jobs'))
+ current = self.get_formatted_query([redis_data.get('current_job')])
+
+ return redis_data,topper_cache_keys,completed,pending,current
+
+ def get(self, request, *args, **kwargs):
+ redis_data,topper_cache_keys,completed,pending,current=self.get_query_data()
+ form = StudentGradeFilterForm()
+ return self.render_to_response(self.get_context_data(form=form,redis_data=redis_data,topper_cache_keys=topper_cache_keys,completed=completed,pending=pending,current=current))
+
+ def test_func(self):
+ return self.request.user.is_superuser or self.request.user.groups.filter(name='HR-Manager').exists()
+
+ def form_valid(self, form):
+ """
+ If the form is valid, redirect to the supplied URL.
+ """
+ result=[]
+ if form.is_valid:
+ foss = [x for x in form.cleaned_data['foss']]
+ state = [s for s in form.cleaned_data['state']]
+ city = [c for c in form.cleaned_data['city']]
+ grade = form.cleaned_data['grade']
+ activation_status = form.cleaned_data['activation_status']
+ institution_type = [t for t in form.cleaned_data['institution_type']]
+ from_date = form.cleaned_data['from_date']
+ to_date = form.cleaned_data['to_date']
+ foss_ids=[f.pk for f in foss]
+ foss_ids.sort()
+ state_ids=[s.pk for s in state]
+ state_ids.sort()
+ city_ids=[c.pk for c in city]
+ city_ids.sort()
+ institution_type_ids=[t.pk for t in institution_type]
+ institution_type_ids.sort()
+ key=';'.join([str(f) for f in foss_ids])+':'+';'.join([str(s) for s in state_ids])+':'+';'.join([str(c) for c in city_ids])+':'+str(grade)+':'+';'.join([str(t) for t in institution_type_ids])+':'+str(activation_status)+':'+str(from_date).replace(" ", "")+':'+str(to_date).replace(" ", "")
+ result=caches['file_cache'].get(key)
+ if not result:
+ if TOPPER_WORKER_STATUS:
+ try:
+ Job.fetch(key, connection=REDIS_CLIENT)
+ messages.success(self.request, "We are working on filtering the results for you. Please refresh after some time.")
+ except:
+ async_filter_student_grades(key)
+ messages.success(self.request, "We are working on filtering the results for you. Please refresh after some time.")
+ else:
+ result=filter_student_grades(key)
+
+ redis_data,topper_cache_keys,completed,pending,current=self.get_query_data()
+ return self.render_to_response(self.get_context_data(form=form, result=result,redis_data=redis_data,topper_cache_keys=topper_cache_keys,completed=completed,pending=pending,current=current))
+
+
+class AcademicKeyCreateView(CreateView):
+ form_class = AcademicPaymentStatusForm
+ model = AcademicPaymentStatus
+ template_name = "academic_payment_details_form.html"
+ success_url = "/software-training/academic_payment_details/"
+
+ @method_decorator(group_required("Resource Person"))
+ def get(self, request, *args, **kwargs):
+ return render(self.request, self.template_name, {'form': self.form_class()})
+
+ def form_valid(self, form, **kwargs):
+ self.object = form.save(commit=False)
+ self.object.entry_user = self.request.user
+ self.object.save()
+
+
+ u_key = uuid.uuid1()
+ hex_key = u_key.hex
+
+
+ Subscription_time = int(self.object.subscription)
+ expiry_date = self.object.payment_date + timedelta(days=Subscription_time)
+
+ ac_key = AcademicKey()
+ ac_key.ac_pay_status = self.object
+ ac_key.academic = self.object.academic
+ ac_key.u_key = u_key
+ ac_key.hex_key = hex_key
+ ac_key.expiry_date = expiry_date
+ ac_key.save()
+
+ messages.success(self.request, "Payment Details for academic is added successfully.")
+ return HttpResponseRedirect(self.success_url)
+
+
+class FetchAcademicDetailsView(View):
+ def get(self, request):
+ academic_id = request.GET.get('academic_id')
+ if academic_id:
+ try:
+ # Retrieve the latest entry for the given academic center
+ ac = AcademicCenter.objects.get(id=academic_id)
+ data = {
+ 'college_type': ac.institution_type.name,
+ }
+ latest_payment = AcademicPaymentStatus.objects.filter(academic_id=academic_id).latest('entry_date')
+ data['success'] = True
+ data['name_of_the_payer'] = latest_payment.name_of_the_payer
+ data['email'] = latest_payment.email
+ data['phone'] = latest_payment.phone
+ data['pan_number'] = latest_payment.pan_number
+ data['gst_number'] = latest_payment.gst_number
+ data['payment_status'] = "Renewal"
+ except Exception as e:
+ data['success'] = False
+ data['payment_status'] = "New"
+ else:
+ data['success'] = False
+ data['payment_status'] = "New"
+ return JsonResponse(data)
diff --git a/events/helpers.py b/events/helpers.py
index ea1764e97..338564334 100644
--- a/events/helpers.py
+++ b/events/helpers.py
@@ -80,7 +80,6 @@ def send_bulk_student_reset_mail(ac, batches, count, new_password, user):
send_mail(subject, message, from_email, recipient_list, fail_silently=False)
-
def get_fossmdlcourse(foss_id, fossmdlmap_id=None):
if fossmdlmap_id is not None:
return FossMdlCourses.objects.get(id = fossmdlmap_id)
@@ -93,4 +92,4 @@ def get_fossmdlcourse(foss_id, fossmdlmap_id=None):
fossmdlcourse = FossMdlCourses.objects.get(foss_id=foss_id, language_id=english, level_id=advanced)
except FossMdlCourses.DoesNotExist:
fossmdlcourse = FossMdlCourses.objects.get(foss_id=foss_id, language__isnull=True, level__isnull=True)
- return fossmdlcourse
\ No newline at end of file
+ return fossmdlcourse
diff --git a/events/migrations/0054_auto_20251104_1245.py b/events/migrations/0054_auto_20251104_1245.py
new file mode 100644
index 000000000..237c0e7e3
--- /dev/null
+++ b/events/migrations/0054_auto_20251104_1245.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.29 on 2025-11-04 07:15
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('creation', '0032_domain_is_active'),
+ ('events', '0053_auto_20251028_1507'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='trainingattend',
+ name='level',
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='creation.Level'),
+ ),
+ migrations.AlterField(
+ model_name='trainingattend',
+ name='language',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='creation.Language'),
+ ),
+ ]
diff --git a/events/migrations/0055_merge_20251106_1205.py b/events/migrations/0055_merge_20251106_1205.py
new file mode 100644
index 000000000..ae750993d
--- /dev/null
+++ b/events/migrations/0055_merge_20251106_1205.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.29 on 2025-11-06 06:35
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('events', '0054_trainingrequest_fossmdlmap'),
+ ('events', '0054_auto_20251104_1245'),
+ ]
+
+ operations = [
+ ]
diff --git a/events/migrations/0056_auto_20251119_1434.py b/events/migrations/0056_auto_20251119_1434.py
new file mode 100644
index 000000000..bd4c8e93f
--- /dev/null
+++ b/events/migrations/0056_auto_20251119_1434.py
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.29 on 2025-11-19 09:04
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('events', '0055_merge_20251106_1205'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='trainingattend',
+ name='level',
+ ),
+ migrations.AlterField(
+ model_name='trainingattend',
+ name='language',
+ field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.PROTECT, to='creation.Language'),
+ ),
+ ]
diff --git a/events/migrations/0057_auto_20251202_1147.py b/events/migrations/0057_auto_20251202_1147.py
new file mode 100644
index 000000000..b205192bd
--- /dev/null
+++ b/events/migrations/0057_auto_20251202_1147.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.29 on 2025-12-02 06:17
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('events', '0056_auto_20251119_1434'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='academicpaymentstatus',
+ name='subscription',
+ field=models.CharField(choices=[('', '-----'), ('365', 'One_Year'), ('182', 'Six_Months'), ('455', 'Fifteen_Months')], max_length=50),
+ ),
+ ]
diff --git a/events/migrations/0058_merge_20260105_1154.py b/events/migrations/0058_merge_20260105_1154.py
new file mode 100644
index 000000000..d140e5b17
--- /dev/null
+++ b/events/migrations/0058_merge_20260105_1154.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.29 on 2026-01-05 06:24
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('events', '0056_auto_20251212_0002'),
+ ('events', '0057_auto_20251202_1147'),
+ ]
+
+ operations = [
+ ]
diff --git a/events/migrations/0059_studentpasswordresethistory.py b/events/migrations/0059_studentpasswordresethistory.py
new file mode 100644
index 000000000..a494c4a55
--- /dev/null
+++ b/events/migrations/0059_studentpasswordresethistory.py
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.29 on 2026-02-09 05:19
+from __future__ import unicode_literals
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ('events', '0058_merge_20260105_1154'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='StudentPasswordResetHistory',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('changed_on', models.DateTimeField(auto_now_add=True)),
+ ('status', models.PositiveSmallIntegerField(default=0, help_text='1 = success, 0 = failed')),
+ ('batch', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='events.StudentBatch')),
+ ('changed_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)),
+ ],
+ options={
+ 'db_table': 'student_password_reset_history',
+ 'ordering': ['-changed_on'],
+ },
+ ),
+ ]
diff --git a/events/migrations/0060_auto_20260209_1107.py b/events/migrations/0060_auto_20260209_1107.py
new file mode 100644
index 000000000..6f32be575
--- /dev/null
+++ b/events/migrations/0060_auto_20260209_1107.py
@@ -0,0 +1,23 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.29 on 2026-02-09 05:37
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('events', '0059_studentpasswordresethistory'),
+ ]
+
+ operations = [
+ migrations.AlterModelOptions(
+ name='studentpasswordresethistory',
+ options={},
+ ),
+ migrations.AlterModelTable(
+ name='studentpasswordresethistory',
+ table=None,
+ ),
+ ]
diff --git a/events/models.py b/events/models.py
index a0c700ade..2cdfe73ee 100755
--- a/events/models.py
+++ b/events/models.py
@@ -1820,3 +1820,12 @@ class AcademicKey(models.Model):
def __str__(self):
return self.academic.institution_name
+
+class StudentPasswordResetHistory(models.Model):
+ batch = models.ForeignKey('StudentBatch',on_delete=models.CASCADE)
+ changed_by = models.ForeignKey(User,on_delete=models.PROTECT)
+ changed_on = models.DateTimeField(auto_now_add=True)
+ status = models.PositiveSmallIntegerField(default=0,help_text="1 = success, 0 = failed")
+
+ def __str__(self):
+ return f"Batch {self.batch.id} | Status {self.status}"
\ No newline at end of file
diff --git a/events/templates/academic_payment_details_form.html b/events/templates/academic_payment_details_form.html
index 90fea50fd..fc76e4af7 100644
--- a/events/templates/academic_payment_details_form.html
+++ b/events/templates/academic_payment_details_form.html
@@ -248,6 +248,22 @@
}
})
+ // $('#id_state').change(function(){
+ // var stateid = $('#id_state').val();
+ // $.ajax({
+ // type : "POST",
+ // url:"/software-training/ajax-state-collage/",
+ // dataType : "json",
+ // data: {
+ // 'state' : stateid,
+ // },
+ // success: function(data)
+ // {
+ // $('#id_academic').html(data);
+ // }
+ // });
+ // });
+
$('#id_state').change(function () {
var stateid = $(this).val();
diff --git a/events/urls.py b/events/urls.py
index 2f6f85f40..900005797 100644
--- a/events/urls.py
+++ b/events/urls.py
@@ -78,6 +78,15 @@
url(r'^training/view/training-completion/(?P\d+)/$', view_training_completion, name="view_training_completion"),
#url(r'^test/subscribe/(\d+)/(\d+)/$', test_student_subscribe', name='test_student_subscribe'),
+
+
+ url(
+ r'^test/(?P\d+)/participants/download/$',
+ download_test_participants_csv,
+ name='download_test_participants_csv'
+),
+
+
url(r'^test/(\d+)/participant/$', test_participant, name='test_participant'),
url(r'^test/participant/certificate/(\d+)/(\d+)/$', test_participant_ceritificate, name='test_participant_ceritificate'),
url(r'^test/participant/certificate/all/(\d+)/$', test_participant_ceritificate_all, name='test_participant_ceritificate_all'),
diff --git a/events/views.py b/events/views.py
index 87f466027..abd761eeb 100644
--- a/events/views.py
+++ b/events/views.py
@@ -762,9 +762,9 @@ def ac(request):
collection = AcademicCenterFilter(request.GET, user = user, queryset=collection)
context['form'] = collection.form
-
+ collection_qs = collection.qs.order_by('id')
page = request.GET.get('page')
- collection = get_page(collection.qs, page)
+ collection = get_page(collection_qs, page)
context['collection'] = collection
context['header'] = header
@@ -2345,6 +2345,40 @@ def test_participant(request, tid=None):
# can_download_certificate = 1
return render(request, 'events/templates/test/test_participant.html', context)
+
+@login_required
+def download_test_participants_csv(request, test_id):
+ user = request.user
+ try:
+ test = Test.objects.get(id=test_id)
+ except Test.DoesNotExist:
+ raise PermissionDenied()
+ if not (user == test.organiser.user or user == test.invigilator.user or user.groups.filter( name__in=["Event Manager", "Resource Person"] ).exists()):
+ raise PermissionDenied()
+
+ if test.status == 4:
+ participants = TestAttendance.objects.filter(test_id=test.id,status__gte=2)
+ else:
+ participants = TestAttendance.objects.filter(test_id=test.id)
+ participants = participants.order_by('id')
+ response = HttpResponse(content_type='text/csv')
+ response['Content-Disposition'] = ('attachment; filename="{}_participants.csv"'.format(test.foss.foss))
+
+ writer = csv.writer(response)
+ writer.writerow(['First Name','Last Name','Email ID','Score (%)'])
+
+ for ta in participants:
+ firstname = ta.mdluser_firstname or ''
+ lastname = ta.mdluser_lastname or ''
+ mdluser = MdlUser.objects.filter(id=ta.mdluser_id).first()
+ email = mdluser.email if mdluser and mdluser.email else ''
+ grade = MdlQuizGrades.objects.filter(quiz=ta.mdlquiz_id,userid=ta.mdluser_id).first()
+ score = round(grade.grade, 2) if grade else 'NA'
+ writer.writerow([firstname,lastname,email,score])
+
+ return response
+
+
def test_participant_ceritificate(request, wid, participant_id):
#response = HttpResponse(content_type='application/pdf')
@@ -2986,6 +3020,19 @@ def ajax_district_collage(request):
tmp +=''+i.institution_name+' '
return HttpResponse(json.dumps(tmp), content_type='application/json')
+# @csrf_exempt
+# def ajax_state_collage(request):
+# """ Ajax: Get the Colleges (Academic) based on District selected """
+# if request.method == 'POST':
+# state = request.POST.get('state')
+# collages = AcademicCenter.objects.filter(state=state).order_by('institution_name')
+# tmp = ' --------- '
+# if collages:
+# for i in collages:
+# tmp +=''+i.institution_name+', '+i.academic_code+' '
+# return HttpResponse(json.dumps(tmp), content_type='application/json')
+
+
@csrf_exempt
def ajax_state_collage(request):
@@ -3336,6 +3383,45 @@ def handover(request):
return render(request, 'handover.html', context)
+# def reset_student_pwd(request):
+# context = {}
+# template = 'events/templates/reset_student_password.html'
+# form = StudentPasswordResetForm()
+# context['form'] = form
+
+# if request.method == "POST":
+# form = StudentPasswordResetForm(request.POST)
+# context['form'] = form
+
+# if form.is_valid():
+# school = form.cleaned_data['school']
+# batches = form.cleaned_data['batches']
+# new_password = form.cleaned_data['new_password']
+
+# batch_ids = [x.id for x in batches]
+# batches = StudentBatch.objects.filter(id__in=batch_ids)
+# student_ids = StudentMaster.objects.filter(batch__in=batches).values_list('student_id', flat=True)
+# students = Student.objects.filter(id__in=student_ids)
+# students.update(verified=1, error=0)
+# user_ids = [stu.user_id for stu in students]
+# users = User.objects.filter(id__in=user_ids)
+# new_hashed_pwd = make_password(new_password)
+# users.update(password=new_hashed_pwd, is_active=1)
+# emails = [user.email for user in users]
+# mdlUsers = MdlUser.objects.filter(email__in=emails)
+# mdlUsers.update(password=encript_password(new_password))
+# send_bulk_student_reset_mail(school,batches,users.count(), new_password,request.user)
+
+# # Add the success message
+# success_msg = "Password updated for {} students.".format(users.count())
+# messages.success(request, success_msg)
+
+
+# redirect_url = reverse('events:reset_student_pwd')
+# return HttpResponseRedirect(redirect_url)
+# return render(request,template,context)
+
+
def reset_student_pwd(request):
context = {}
template = 'events/templates/reset_student_password.html'
@@ -3350,6 +3436,7 @@ def reset_student_pwd(request):
school = form.cleaned_data['school']
batches = form.cleaned_data['batches']
new_password = form.cleaned_data['new_password']
+ status = 0
batch_ids = [x.id for x in batches]
batches = StudentBatch.objects.filter(id__in=batch_ids)
@@ -3364,7 +3451,9 @@ def reset_student_pwd(request):
mdlUsers = MdlUser.objects.filter(email__in=emails)
mdlUsers.update(password=encript_password(new_password))
send_bulk_student_reset_mail(school,batches,users.count(), new_password,request.user)
-
+ status = 1
+
+ for batch in batches:StudentPasswordResetHistory.objects.create(batch=batch,changed_by=request.user,status=status)
# Add the success message
success_msg = "Password updated for {} students.".format(users.count())
messages.success(request, success_msg)
@@ -3375,6 +3464,8 @@ def reset_student_pwd(request):
return render(request,template,context)
+
+
def get_schools(request):
state_id = request.GET.get('state_id')
if state_id:
diff --git a/events/viewsv2.py b/events/viewsv2.py
index 6d57854b1..58951bd8b 100755
--- a/events/viewsv2.py
+++ b/events/viewsv2.py
@@ -77,6 +77,7 @@
from django.db import connection
from donate.utils import send_transaction_email
from .certificates import *
+from spoken.config import BASIC_LEVEL_INSTITUTIONS
from spoken.config import BASIC_LEVEL_INSTITUTIONS
@@ -650,93 +651,100 @@ def form_valid(self, form, **kwargs):
messages.success(self.request,'STP has been added successfully. Now continue with step 3 "Select Participants " on STPS page. Select the participants from the Master Batch Student List for any one course that you are starting with. This is necessary for receiving certificates.')
return HttpResponseRedirect('/software-training/{0}/training-request/'.format(self.tpid))
-class TrainingRequestEditView(CreateView):
- form_class = TrainingRequestEditForm
- user = None
- training = None
- @method_decorator(group_required("Organiser"))
- def dispatch(self, *args, **kwargs):
- if 'pk' in self.kwargs:
- self.training = TrainingRequest.objects.get(pk=self.kwargs['pk'])
- if not self.training.can_edit():
- messages.error(self.request, "Training has attendance, edit is not permitted for training.")
- return HttpResponseRedirect('/software-training/training-planner/')
- return super(TrainingRequestEditView, self).dispatch(*args, **kwargs)
+class TrainingRequestEditView(UpdateView):
+ model = TrainingRequest
+ form_class = TrainingRequestEditForm
+ template_name = "software_training/training_request_edit.html"
- def get_form_kwargs(self):
- kwargs = super(TrainingRequestEditView, self).get_form_kwargs()
- kwargs.update({'training' : self.training})
- kwargs.update({'user' : self.request.user})
- return kwargs
+ training = None
- def get_context_data(self, **kwargs):
- context = super(TrainingRequestEditView, self).get_context_data(**kwargs)
- context['training'] = self.training
- return context
+ @method_decorator(group_required("Organiser"))
+ def dispatch(self, request, *args, **kwargs):
+ self.training = TrainingRequest.objects.get(pk=kwargs.get('pk'))
- def form_valid(self, form, **kwargs):
- # Check if all student participate in selected foss
- try:
- # Check if batch has student?
- sb = StudentBatch.objects.get(pk=form.cleaned_data['batch'].id)
- selectedBatch = form.cleaned_data['batch']
- selectedDept = form.cleaned_data['department']
- selectedCourse = form.cleaned_data['course']
- if not sb.student_count():
- messages.error(self.request, 'There is no student present in this batch.')
- return self.form_invalid(form)
- training_planner = self.training.training_planner
+ if not self.training.can_edit():
+ messages.error(
+ request,
+ "Training has attendance, edit is not permitted for training."
+ )
+ return HttpResponseRedirect('/software-training/training-planner/')
- # Check if batch has already has same foss course?
- if not ( (selectedBatch == self.training.batch) and (selectedCourse == self.training.course)):
- is_batch_has_course = TrainingRequest.objects.filter(
- batch = selectedBatch,
- course = selectedCourse,
- training_planner_id = training_planner.id
- ).count()
- if is_batch_has_course:
- messages.error(self.request, 'This "%s" already taken/requested the selected "%s" course in current semester.' % (selectedBatch, selectedCourse))
+ return super(TrainingRequestEditView, self).dispatch(request, *args, **kwargs)
+
+ def get_form_kwargs(self):
+ kwargs = super(TrainingRequestEditView, self).get_form_kwargs()
+ kwargs['instance'] = self.training
+ kwargs['training'] = self.training
+ kwargs['user'] = self.request.user
+ return kwargs
+
+ def get_context_data(self, **kwargs):
+ context = super(TrainingRequestEditView, self).get_context_data(**kwargs)
+ context['training'] = self.training
+ return context
+
+ def form_valid(self, form, **kwargs):
+ # Check if all student participate in selected foss
+ try:
+ # Check if batch has student?
+ sb = StudentBatch.objects.get(pk=form.cleaned_data['batch'].id)
+ selectedBatch = form.cleaned_data['batch']
+ selectedDept = form.cleaned_data['department']
+ selectedCourse = form.cleaned_data['course']
+ if not sb.student_count():
+ messages.error(self.request, 'There is no student present in this batch.')
return self.form_invalid(form)
- # Check if course is full for this semester
- if not ( (selectedBatch == self.training.batch) and (selectedDept == self.training.department)):
- if training_planner.is_full(selectedDept.id, selectedBatch.id):
- messages.error(self.request, 'No. of training requests exceeded for this semester.')
+ training_planner = self.training.training_planner
+
+ # Check if batch has already has same foss course?
+ if not ( (selectedBatch == self.training.batch) and (selectedCourse == self.training.course)):
+ is_batch_has_course = TrainingRequest.objects.filter(
+ batch = selectedBatch,
+ course = selectedCourse,
+ training_planner_id = training_planner.id
+ ).count()
+ if is_batch_has_course:
+ messages.error(self.request, 'This "%s" already taken/requested the selected "%s" course in current semester.' % (selectedBatch, selectedCourse))
+ return self.form_invalid(form)
+ # Check if course is full for this semester
+ if not ( (selectedBatch == self.training.batch) and (selectedDept == self.training.department)):
+ if training_planner.is_full(selectedDept.id, selectedBatch.id):
+ messages.error(self.request, 'No. of training requests exceeded for this semester.')
+ return self.form_invalid(form)
+
+ # Assigning values
+ self.training.department = selectedDept
+ self.training.batch = selectedBatch
+ self.training.course_type = form.cleaned_data['course_type']
+ self.training.fossmdlmap = form.cleaned_data.get('fossmdlmap')
+
+ if self.training.batch.is_foss_batch_acceptable(selectedCourse):
+ self.training.sem_start_date = form.cleaned_data['sem_start_date']
+ self.training.training_start_date = form.cleaned_data['training_start_date']
+ self.training.training_end_date = form.cleaned_data['training_end_date']
+ self.training.course_id = selectedCourse
+ else:
+ messages.error(self.request, 'This student batch already taken the selected course.')
return self.form_invalid(form)
+ # save form
+ self.training.save()
- # Assigning values
- self.training.department = selectedDept
- self.training.batch = selectedBatch
- self.training.course_type = form.cleaned_data['course_type']
- self.training.fossmdlmap = form.cleaned_data.get('fossmdlmap')
-
- if self.training.batch.is_foss_batch_acceptable(selectedCourse):
- self.training.sem_start_date = form.cleaned_data['sem_start_date']
- self.training.training_start_date = form.cleaned_data['training_start_date']
- self.training.training_end_date = form.cleaned_data['training_end_date']
- self.training.course_id = selectedCourse
- else:
- messages.error(self.request, 'This student batch already taken the selected course.')
+ except:
return self.form_invalid(form)
- # save form
- self.training.save()
-
- except:
- return self.form_invalid(form)
- context = {}
- return HttpResponseRedirect('/software-training/select-participants/')
-
- def post(self, request, *args, **kwargs):
- self.object = None
- self.user = request.user
- form_class = self.get_form_class()
- form = self.get_form(form_class)
+ context = {}
+ return HttpResponseRedirect('/software-training/select-participants/')
- if form.is_valid():
- return self.form_valid(form)
- else:
- return self.form_invalid(form)
- return HttpResponseRedirect('/software-training/select-participants/')
+ def post(self, request, *args, **kwargs):
+ self.object = None
+ self.user = request.user
+ form_class = self.get_form_class()
+ form = self.get_form(form_class)
+ if form.is_valid():
+ return self.form_valid(form)
+ else:
+ return self.form_invalid(form)
+ return HttpResponseRedirect('/software-training/select-participants/')
class TrainingAttendanceListView(ListView):
queryset = StudentMaster.objects.none()
@@ -745,50 +753,94 @@ class TrainingAttendanceListView(ListView):
training_request = None
def dispatch(self, *args, **kwargs):
- self.training_request = TrainingRequest.objects.get(pk=kwargs['tid'])
+ self.training_request = (
+ TrainingRequest.objects
+ .select_related('department', 'course', 'course__foss')
+ .get(pk=kwargs['tid'])
+ )
if self.training_request.status == 1 and not self.training_request.participants == 0:
- self.queryset = self.training_request.attendances.all()
+ self.queryset = self.queryset = (
+ self.training_request.trainingattend_set
+ .select_related('student', 'language')
+ .all()
+ )
else:
- self.queryset = StudentMaster.objects.filter(batch_id=self.training_request.batch_id,student__verified__lte=3,student__error=0, moved=False)
+ self.queryset = self.queryset = (
+ StudentMaster.objects
+ .select_related('student')
+ .filter(
+ batch_id=self.training_request.batch_id,
+ student__verified__lte=3,
+ student__error=0,
+ moved=False
+ )
+ )
return super(TrainingAttendanceListView, self).dispatch(*args, **kwargs)
def get_context_data(self, **kwargs):
context = super(TrainingAttendanceListView, self).get_context_data(**kwargs)
context['training'] = self.training_request
context['department'] = self.training_request.department
- languages = Language.objects.filter(
- id__in = FossAvailableForWorkshop.objects.filter(
- foss_id = self.training_request.course.foss_id
- ).values_list('language_id')
- )
+ language_ids = (
+ FossAvailableForWorkshop.objects
+ .filter(foss_id=self.training_request.course.foss_id)
+ .values_list('language_id', flat=True)
+ )
+ languages = Language.objects.filter(id__in=language_ids)
context['languages'] = languages
return context
-
+
def post(self, request, *args, **kwargs):
- self.object = None
- self.user = request.user
- training_id = kwargs['tid']
- if request.POST and 'user' in request.POST:
- # commented out as Django 1.11 + creates new csrf token for every POST request
- #if csrf.get_token(request) == request.POST['csrfmiddlewaretoken']:
- marked_student = request.POST.getlist('user', None)
- # delete un marked record if exits
- TrainingAttend.objects.filter(training_id =training_id).exclude(student_id__in = marked_student).delete()
- # insert new record if not exits
- for record in marked_student:
- language_id = request.POST.get(record)
- training_attend = TrainingAttend.objects.filter(training_id =training_id, student_id = record)
- if not training_attend.exists():
- TrainingAttend.objects.create(training_id =training_id, student_id = record, language_id=language_id)
- else:
- training_attend = training_attend.first()
- training_attend.language_id = language_id
- training_attend.save()
- #print marked_student
- else:
- TrainingAttend.objects.filter(training_id =training_id).delete()
- self.training_request.update_participants_count()
- return HttpResponseRedirect('/software-training/training-planner')
+ self.object = None
+ training_id = kwargs['tid']
+ marked_students = request.POST.getlist('user', None)
+
+ # If some selected, update accordingly
+ if marked_students:
+ # Delete unselected entries in ONE query
+ TrainingAttend.objects.filter(training_id=training_id).exclude(
+ student_id__in=marked_students
+ ).delete()
+ # Fetch all existing records for faster lookup (avoid `.exists()` loop)
+ existing_records = {
+ ta.student_id: ta
+ for ta in TrainingAttend.objects.filter(training_id=training_id)
+ }
+ new_objects = []
+ for student_id in marked_students:
+ language_id = request.POST.get(student_id)
+
+ if int(student_id) not in existing_records:
+ # create new object
+ new_objects.append(
+ TrainingAttend(
+ training_id=training_id,
+ student_id=student_id,
+ language_id=language_id
+ )
+ )
+ else:
+ # update only once
+ ta = existing_records[int(student_id)]
+ if ta.language_id != language_id:
+ ta.language_id = language_id
+ ta.save()
+
+ # Bulk create new rows in ONE query
+ if new_objects:
+ TrainingAttend.objects.bulk_create(new_objects)
+
+ else:
+ # No students marked: delete all attendance entries
+ TrainingAttend.objects.filter(training_id=training_id).delete()
+
+ # Update count
+ self.training_request.update_participants_count()
+
+ # Redirect
+ return HttpResponseRedirect('/software-training/training-planner')
+
+
@method_decorator(login_required(login_url="/accounts/login/"), name="dispatch")
class TrainingCertificateListView(ListView):
diff --git a/forums/migrations/0001_initial.py b/forums/migrations/0001_initial.py
new file mode 100644
index 000000000..08beccfb8
--- /dev/null
+++ b/forums/migrations/0001_initial.py
@@ -0,0 +1,121 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.29 on 2025-11-04 07:15
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Answer',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('uid', models.IntegerField()),
+ ('body', models.TextField()),
+ ('date_created', models.DateTimeField(auto_now_add=True)),
+ ('date_modified', models.DateTimeField(auto_now=True)),
+ ],
+ options={
+ 'db_table': 'website_answer',
+ },
+ ),
+ migrations.CreateModel(
+ name='AnswerComment',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('uid', models.IntegerField()),
+ ('body', models.TextField()),
+ ('date_created', models.DateTimeField(auto_now_add=True)),
+ ('date_modified', models.DateTimeField(auto_now=True)),
+ ('answer', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='forums.Answer')),
+ ],
+ options={
+ 'db_table': 'website_answercomment',
+ },
+ ),
+ migrations.CreateModel(
+ name='AnswerVote',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('uid', models.IntegerField()),
+ ('answer', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='forums.Answer')),
+ ],
+ options={
+ 'db_table': 'website_answervote',
+ },
+ ),
+ migrations.CreateModel(
+ name='Notification',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('uid', models.IntegerField()),
+ ('pid', models.IntegerField()),
+ ('qid', models.IntegerField()),
+ ('aid', models.IntegerField(default=0)),
+ ('cid', models.IntegerField(default=0)),
+ ('date_created', models.DateTimeField(auto_now_add=True)),
+ ],
+ options={
+ 'db_table': 'website_notification',
+ },
+ ),
+ migrations.CreateModel(
+ name='Question',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('uid', models.IntegerField()),
+ ('category', models.CharField(max_length=200)),
+ ('tutorial', models.CharField(max_length=200)),
+ ('minute_range', models.CharField(max_length=10)),
+ ('second_range', models.CharField(max_length=10)),
+ ('title', models.CharField(max_length=200)),
+ ('body', models.TextField()),
+ ('date_created', models.DateTimeField(auto_now_add=True)),
+ ('date_modified', models.DateTimeField(auto_now=True)),
+ ('views', models.IntegerField(default=1)),
+ ('status', models.IntegerField(default=1)),
+ ],
+ options={
+ 'db_table': 'website_question',
+ 'get_latest_by': 'date_created',
+ },
+ ),
+ migrations.CreateModel(
+ name='QuestionComment',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('uid', models.IntegerField()),
+ ('body', models.TextField()),
+ ('date_created', models.DateTimeField(auto_now_add=True)),
+ ('date_modified', models.DateTimeField(auto_now=True)),
+ ('question', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='forums.Question')),
+ ],
+ options={
+ 'db_table': 'website_questioncomment',
+ },
+ ),
+ migrations.CreateModel(
+ name='QuestionVote',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('uid', models.IntegerField()),
+ ('question', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='forums.Question')),
+ ],
+ options={
+ 'db_table': 'website_questionvote',
+ },
+ ),
+ migrations.AddField(
+ model_name='answer',
+ name='question',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='forums.Question'),
+ ),
+ ]
diff --git a/health_app/migrations/0001_initial.py b/health_app/migrations/0001_initial.py
new file mode 100644
index 000000000..8f185e30b
--- /dev/null
+++ b/health_app/migrations/0001_initial.py
@@ -0,0 +1,74 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.29 on 2025-11-04 07:15
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Category',
+ fields=[
+ ('category_id', models.IntegerField(primary_key=True, serialize=False)),
+ ('category_name', models.CharField(max_length=255)),
+ ('date_added', models.DateTimeField()),
+ ('description', models.CharField(max_length=2000)),
+ ('image_path', models.CharField(max_length=255)),
+ ('status', models.TextField()),
+ ('user_id', models.BigIntegerField(blank=True, null=True)),
+ ('order_value', models.IntegerField()),
+ ],
+ options={
+ 'db_table': 'category',
+ 'managed': False,
+ },
+ ),
+ migrations.CreateModel(
+ name='HNContributorRole',
+ fields=[
+ ('id', models.IntegerField(primary_key=True, serialize=False)),
+ ('date_added', models.DateTimeField(blank=True, null=True)),
+ ('language_id', models.IntegerField(blank=True, null=True)),
+ ('topic_cat_id', models.IntegerField(blank=True, null=True)),
+ ],
+ options={
+ 'db_table': 'contributor_role',
+ 'managed': False,
+ },
+ ),
+ migrations.CreateModel(
+ name='HNLanguage',
+ fields=[
+ ('lan_id', models.IntegerField(primary_key=True, serialize=False)),
+ ('date_added', models.DateTimeField()),
+ ('lang_name', models.CharField(max_length=255)),
+ ('status', models.TextField()),
+ ('user_id', models.BigIntegerField(blank=True, null=True)),
+ ],
+ options={
+ 'db_table': 'language',
+ 'managed': False,
+ },
+ ),
+ migrations.CreateModel(
+ name='TopicCategory',
+ fields=[
+ ('topic_category_id', models.IntegerField(primary_key=True, serialize=False)),
+ ('order_value', models.IntegerField(blank=True, null=True)),
+ ('status', models.TextField()),
+ ('category_id', models.IntegerField(blank=True, null=True)),
+ ('topic_id', models.IntegerField(blank=True, null=True)),
+ ],
+ options={
+ 'db_table': 'topic_category',
+ 'managed': False,
+ },
+ ),
+ ]
diff --git a/mdldjango/migrations/0003_auto_20251104_1245.py b/mdldjango/migrations/0003_auto_20251104_1245.py
new file mode 100644
index 000000000..137da12cd
--- /dev/null
+++ b/mdldjango/migrations/0003_auto_20251104_1245.py
@@ -0,0 +1,63 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.29 on 2025-11-04 07:15
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('mdldjango', '0002_auto_20190531_0547'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='mdluser',
+ name='academic_code',
+ ),
+ migrations.RemoveField(
+ model_name='mdluser',
+ name='age_range',
+ ),
+ migrations.RemoveField(
+ model_name='mdluser',
+ name='aim',
+ ),
+ migrations.RemoveField(
+ model_name='mdluser',
+ name='flag',
+ ),
+ migrations.RemoveField(
+ model_name='mdluser',
+ name='gender',
+ ),
+ migrations.RemoveField(
+ model_name='mdluser',
+ name='icq',
+ ),
+ migrations.RemoveField(
+ model_name='mdluser',
+ name='invigilator',
+ ),
+ migrations.RemoveField(
+ model_name='mdluser',
+ name='msn',
+ ),
+ migrations.RemoveField(
+ model_name='mdluser',
+ name='organizer',
+ ),
+ migrations.RemoveField(
+ model_name='mdluser',
+ name='skype',
+ ),
+ migrations.RemoveField(
+ model_name='mdluser',
+ name='url',
+ ),
+ migrations.RemoveField(
+ model_name='mdluser',
+ name='yahoo',
+ ),
+ ]
diff --git a/spoken/decorators.py b/spoken/decorators.py
index 439fca203..e054d63c6 100644
--- a/spoken/decorators.py
+++ b/spoken/decorators.py
@@ -29,7 +29,8 @@ def _wrapped_view(request, *args, **kwargs):
okay = False
if USE_STATS:
okay = check_server_status()
- if not okay:
+ print("========================",okay)
+ if not okay:
message = "This page is temporarily unavailable due to high server load. Weβre working to restore access soon β thank you for your patience."
return render(request, 'statistics/templates/temporary_disabled.html', {"message": message})
# check rate limit
diff --git a/spoken/helpers.py b/spoken/helpers.py
index 30e97976f..47a3a5cc4 100644
--- a/spoken/helpers.py
+++ b/spoken/helpers.py
@@ -12,6 +12,7 @@
from cms.cache_registry import register_cache_key
from .config import CACHE_RANDOM_TUTORIALS, CACHE_TR_REC, CACHE_TESTIMONIALS, CACHE_NOTIFICATIONS, CACHE_EVENTS, CACHE_TUTORIALS
+
def get_key(identifier, key_val):
return f"{identifier}:{key_val.lower().strip().replace(' ','_')}"
@@ -46,7 +47,6 @@ def get_home_random_tutorials():
tutorials = []
return tutorials
-
# ---- 2. Random TutorialResource record ----
def get_home_tr_rec(request=None):
cache_key = "home_tr_rec"
diff --git a/spoken/settings.py b/spoken/settings.py
index bd2275787..ca2ef7cf9 100644
--- a/spoken/settings.py
+++ b/spoken/settings.py
@@ -72,6 +72,7 @@
'django.contrib.redirects',
'django.contrib.sitemaps',
'django_extensions',
+ # 'debug_toolbar',
'widget_tweaks',
'captcha',
'nicedit',
@@ -129,81 +130,84 @@
# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases
-CONN_MAX_AGE = DB_CONN_MAX_AGE_DEFAULT
+# CONN_MAX_AGE = DB_CONN_MAX_AGE_DEFAULT
+CONN_MAX_AGE = 60
+DB_CONN_MAX_AGE_DEFAULT = 0 # connections close after each request
+DB_CONN_MAX_AGE_FREQUENT = 60
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
- 'NAME': DB,
- 'USER': DB_USER,
- 'PASSWORD': DB_PASS,
- 'HOST': '', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP.
+ 'NAME': 'ST_20Feb2023',
+ 'USER':'lisha',
+ 'PASSWORD': '1947',
+ 'HOST': '127.0.0.1', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP.
'PORT': '',
- "CONN_MAX_AGE": DB_CONN_MAX_AGE_FREQUENT,
+ # "CONN_MAX_AGE": DB_CONN_MAX_AGE_FREQUENT,
},
'moodle': {
'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
- 'NAME': MDB, # Or path to database file if using sqlite3.
- # The following settings are not used with sqlite3:
- 'USER': MDB_USER,
- 'PASSWORD': MDB_PASS,
- 'HOST': MDB_HOST, # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP.
- 'PORT': '', # Set to empty string for default.
- "CONN_MAX_AGE": DB_CONN_MAX_AGE_FREQUENT,
- },
- 'ilwmoodle': {
- 'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
- 'NAME': ILWMDB, # Or path to database file if using sqlite3.
- # The following settings are not used with sqlite3:
- 'USER': ILW_MDB_USER,
- 'PASSWORD': ILW_MDB_PASS,
- 'HOST': ILW_MDB_HOST, # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP.
- 'PORT': ILW_MDB_PORT, # Set to empty string for default.
- },
- 'cdeep': {
- 'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
- 'NAME': CDB, # Or path to database file if using sqlite3.
- # The following settings are not used with sqlite3:
- 'USER': CDB_USER,
- 'PASSWORD': CDB_PASS,
- 'HOST': '', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP.
- 'PORT': '', # Set to empty string for default.
- },
- 'workshop_info': {
- 'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
- 'NAME': WDB, # Or path to database file if using sqlite3.
- # The following settings are not used with sqlite3:
- 'USER': WDB_USER,
- 'PASSWORD': WDB_PASS,
- 'HOST': '', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP.
- 'PORT': '', # Set to empty string for default.
- },
- 'forums': {
- 'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
- 'NAME': FDB, # Or path to database file if using sqlite3.
- # The following settings are not used with sqlite3:
- 'USER': FDB_USER,
- 'PASSWORD': FDB_PASS,
- 'HOST': '', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP.
- 'PORT': '', # Set to empty string for default.
+ 'NAME': 'ST_20Feb2023', # Or path to database file if using sqlite3.
+ # # The following settings are not used with sqlite3:
+ 'USER':'lisha',
+ 'PASSWORD': '1947',
+ 'HOST': '127.0.0.1', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP.
+ 'PORT': '', # Set to empty string for default.
+ # "CONN_MAX_AGE": DB_CONN_MAX_AGE_FREQUENT,
},
+ # 'ilwmoodle': {
+ # 'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
+ # 'NAME': 'ST_20Feb2023', # Or path to database file if using sqlite3.
+ # # The following settings are not used with sqlite3:
+ # 'USER':'lisha',
+ # 'PASSWORD': '1947',
+ # 'HOST': '127.0.0.1', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP.
+ # 'PORT': '', # Set to empty string for default.
+ # },
+ # 'cdeep': {
+ # 'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
+ # 'NAME': CDB, # Or path to database file if using sqlite3.
+ # # The following settings are not used with sqlite3:
+ # 'USER': CDB_USER,
+ # 'PASSWORD': CDB_PASS,
+ # 'HOST': '', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP.
+ # 'PORT': '', # Set to empty string for default.
+ # },
+ # 'workshop_info': {
+ # 'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
+ # 'NAME': WDB, # Or path to database file if using sqlite3.
+ # # The following settings are not used with sqlite3:
+ # 'USER': WDB_USER,
+ # 'PASSWORD': WDB_PASS,
+ # 'HOST': '', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP.
+ # 'PORT': '', # Set to empty string for default.
+ # },
+ # 'forums': {
+ # 'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
+ # 'NAME': FDB, # Or path to database file if using sqlite3.
+ # # The following settings are not used with sqlite3:
+ # 'USER': FDB_USER,
+ # 'PASSWORD': FDB_PASS,
+ # 'HOST': '', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP.
+ # 'PORT': '', # Set to empty string for default.
+ # },
'healthdb': {
'ENGINE': 'django.db.backends.mysql',
- 'NAME': HN,
- 'USER': HN_USER,
- 'PASSWORD': HN_PASS,
- 'HOST': HN_HOST,
- 'PORT': HN_PORT,
+ 'NAME': 'ST_20Feb2023',
+ 'USER': 'lisha',
+ 'PASSWORD': '1947',
+ 'HOST': '127.0.0.1',
+ 'PORT': '',
},
'stats': {
'ENGINE': 'django.db.backends.mysql',
- 'NAME': STATS_DB,
- 'USER': STATS_USER,
- 'PASSWORD': STATS_PWD,
- 'HOST': STATS_HOST,
- 'PORT': STATS_PORT,
- "CONN_MAX_AGE": DB_CONN_MAX_AGE_FREQUENT,
+ 'NAME': 'ST_20Feb2023',
+ 'USER': 'lisha',
+ 'PASSWORD': '1947',
+ 'HOST': '127.0.0.1',
+ 'PORT': '',
+ # "CONN_MAX_AGE": DB_CONN_MAX_AGE_FREQUENT,
}
}
@@ -364,7 +368,9 @@
'django.middleware.common.BrokenLinkEmailsMiddleware',
#'masquerade.middleware.MasqueradeMiddleware',
'django.contrib.redirects.middleware.RedirectFallbackMiddleware',
- 'impersonate.middleware.ImpersonateMiddleware'
+ 'impersonate.middleware.ImpersonateMiddleware',
+ # 'debug_toolbar.middleware.DebugToolbarMiddleware',
+
]
CORS_ORIGIN_ALLOW_ALL = True
@@ -392,7 +398,7 @@
}
}
-DATA_UPLOAD_MAX_NUMBER_FIELDS = DATA_UPLOAD_MAX_NUMBER_FIELDS
+DATA_UPLOAD_MAX_NUMBER_FIELDS = 10000
REST_FRAMEWORK = {
@@ -421,4 +427,6 @@
HDFC_POLL_MAX_RETRIES=HDFC_POLL_MAX_RETRIES
HDFC_POLL_INTERVAL=HDFC_POLL_INTERVAL
RESPONSE_KEY=RESPONSE_KEY
-DEVELOPER_EMAIL=DEVELOPER_EMAIL
+EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
+DEFAULT_FROM_EMAIL = NO_REPLY_EMAIL
+
diff --git a/spoken/urls.py b/spoken/urls.py
index f29dbd6ed..c91cb8910 100644
--- a/spoken/urls.py
+++ b/spoken/urls.py
@@ -13,10 +13,16 @@
from donate.views import ilw_payment_callback
from donate.payment import check_ilw_payment_status
+# import debug_toolbar
+
+from django.conf import settings
+
+
app_name = 'spoken'
admin.autodiscover()
urlpatterns = [
+ # url(r'^__debug__/', include(debug_toolbar.urls)),
url(r'^robots\.txt', robots_txt, name='robots-txt'),
#url(r'^sitemap\.xml$', TemplateView.as_view(template_name='sitemap.xml', content_type='text/xml')),
url(r'^sitemap\.html$', sitemap, name='sitemap'),
@@ -142,10 +148,23 @@
#donation
url(r'^donate/', include('donate.urls', namespace='donate')),
+ #Caches
+ url(r'^system-tools/', include('cms.cacheurls')),
+
+
# cms
url(r'^', include('cms.urls', namespace='cms')),
-
+
+
#nep book fiar
url(r'wbf-book-fair-2023', bookfair,name="bookfair"),
] + static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)
+
+if settings.DEBUG:
+ import debug_toolbar
+ urlpatterns += [
+ url(r'^__debug__/', include(debug_toolbar.urls)),
+ ]
+
+
diff --git a/spoken/utils.py b/spoken/utils.py
index b2f80f108..e30b634e3 100644
--- a/spoken/utils.py
+++ b/spoken/utils.py
@@ -14,6 +14,7 @@ def is_valid_page_param(request):
return False
def check_server_status():
+ return True
try:
load1, load5, load15 = os.getloadavg() # CPU load average
cpu_cores = os.cpu_count()
diff --git a/spoken/views.py b/spoken/views.py
index e1a9116a5..6c8e412c4 100644
--- a/spoken/views.py
+++ b/spoken/views.py
@@ -350,6 +350,7 @@ def watch_tutorial(request, foss, tutorial, lang):
'user_authorized': is_authorized_user,
'restriction_date': TUTORIAL_RESTRICTION_DATE.strftime("%-d %b. %Y")
}
+
return render(request, 'spoken/templates/watch_tutorial.html', context)
# link to watch what is spoken tutorial video in english
@@ -957,8 +958,10 @@ def subscription(request):
state = form.cleaned_data.get('state')
subscription_amount = 0
+ total_academic_centers = len(academic)
+
for ac in academic:
- if ac.institute_type_id in settings.SUBSCRIPTION_INSTITUTE_TYPES:
+ if ac.institution_type_id in settings.SUBSCRIPTION_INSTITUTE_TYPES:
subscription_amount += settings.SUBSCRIPTION_AMOUNT_COLLEGE
else:
subscription_amount += settings.SUBSCRIPTION_AMOUNT
@@ -979,7 +982,7 @@ def subscription(request):
for ac in academic:
gst_no = request.POST.get(f"gst_no_{ac.id}")
gst_name = request.POST.get(f"gst_name_{ac.id}")
- if ac.institute_type_id in settings.SUBSCRIPTION_INSTITUTE_TYPES:
+ if ac.institution_type_id in settings.SUBSCRIPTION_INSTITUTE_TYPES:
amount = settings.SUBSCRIPTION_AMOUNT_COLLEGE
else:
amount = settings.SUBSCRIPTION_AMOUNT
@@ -990,7 +993,6 @@ def subscription(request):
subscription_end_date=expiry_date,
gst_number=gst_no.strip() if gst_no else None,
gst_name=gst_name.strip() if gst_name else None,
- amount=amount
)
else:
diff --git a/static/cms/templates/manage_cache.html b/static/cms/templates/manage_cache.html
index 81f4166b6..e6d18c5a9 100644
--- a/static/cms/templates/manage_cache.html
+++ b/static/cms/templates/manage_cache.html
@@ -75,7 +75,6 @@ Option 3: Clear homepage cache
Clear Homepage Cache
-
{% endblock %}
{% block jsblock %}
diff --git a/static/events/templates/events_dashboard.html b/static/events/templates/events_dashboard.html
index abb9f986d..7173dee9e 100755
--- a/static/events/templates/events_dashboard.html
+++ b/static/events/templates/events_dashboard.html
@@ -165,6 +165,18 @@