Add student count to course's classes, prevent empty add student
This commit is contained in:
parent
8f56a74a55
commit
a914171cb3
|
@ -339,7 +339,7 @@ class TrainingViewSet(Base, Retrieve, Create, Update):
|
||||||
|
|
||||||
if data.get('member_id', None):
|
if data.get('member_id', None):
|
||||||
if not (is_admin_director(user) or session.instructor == user):
|
if not (is_admin_director(user) or session.instructor == user):
|
||||||
raise exceptions.ValidationError('Not allowed to register others')
|
raise exceptions.ValidationError(dict(non_field_errors='Not allowed to register others'))
|
||||||
|
|
||||||
member = get_object_or_404(models.Member, id=data['member_id'])
|
member = get_object_or_404(models.Member, id=data['member_id'])
|
||||||
user = member.user
|
user = member.user
|
||||||
|
@ -354,9 +354,9 @@ class TrainingViewSet(Base, Retrieve, Create, Update):
|
||||||
else:
|
else:
|
||||||
training = models.Training.objects.filter(user=user, session=session)
|
training = models.Training.objects.filter(user=user, session=session)
|
||||||
if training.exists():
|
if training.exists():
|
||||||
raise exceptions.ValidationError('Already registered')
|
raise exceptions.ValidationError(dict(non_field_errors='Already registered'))
|
||||||
if user == session.instructor:
|
if user == session.instructor:
|
||||||
raise exceptions.ValidationError('You are teaching this session')
|
raise exceptions.ValidationError(dict(non_field_errors='You are teaching this session'))
|
||||||
if status == 'Waiting for payment' and session.cost == 0:
|
if status == 'Waiting for payment' and session.cost == 0:
|
||||||
status = 'Confirmed'
|
status = 'Confirmed'
|
||||||
serializer.save(user=user, attendance_status=status)
|
serializer.save(user=user, attendance_status=status)
|
||||||
|
|
22
apiserver/export_class_report.py
Normal file
22
apiserver/export_class_report.py
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import django, sys, os
|
||||||
|
os.environ['DJANGO_SETTINGS_MODULE'] = 'apiserver.settings'
|
||||||
|
django.setup()
|
||||||
|
|
||||||
|
import csv
|
||||||
|
from apiserver.api import models
|
||||||
|
|
||||||
|
sessions = models.Session.objects.filter(datetime__gte='2021-01-01')
|
||||||
|
|
||||||
|
with open('output.csv', 'w', newline='') as csvfile:
|
||||||
|
fields = ['date', 'name', 'num_students']
|
||||||
|
writer = csv.DictWriter(csvfile, fieldnames=fields)
|
||||||
|
|
||||||
|
writer.writeheader()
|
||||||
|
|
||||||
|
for s in sessions:
|
||||||
|
writer.writerow(dict(
|
||||||
|
date=s.datetime.date(),
|
||||||
|
name=s.course.name,
|
||||||
|
num_students=s.students.filter(attendance_status='Attended').count(),
|
||||||
|
))
|
||||||
|
|
104
apiserver/output.csv
Normal file
104
apiserver/output.csv
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
date,name,num_students
|
||||||
|
2021-07-25,New Members: Orientation and Basic Safety,5
|
||||||
|
2021-07-17,Monthly Cleanup and Group Lunch,0
|
||||||
|
2021-08-07,Woodworking Tools 1: Intro to Saws,5
|
||||||
|
2021-08-08,Woodworking Tools 1: Intro to Saws,1
|
||||||
|
2021-08-07,"Woodworking Tools 2: Jointer, Thickness Planer, Drum Sander",6
|
||||||
|
2021-08-08,"Woodworking Tools 2: Jointer, Thickness Planer, Drum Sander",1
|
||||||
|
2021-08-07,Introduction to the Wood Lathe,4
|
||||||
|
2021-08-08,Introduction to the Wood Lathe,0
|
||||||
|
2021-08-07,New Members: Orientation and Basic Safety,3
|
||||||
|
2021-08-22,New Members: Orientation and Basic Safety,6
|
||||||
|
2021-08-21,Woodworking Tools 1: Intro to Saws,3
|
||||||
|
2021-08-21,Monthly Cleanup and Group Lunch,0
|
||||||
|
2021-09-11,Annual General Meeting,0
|
||||||
|
2021-09-11,Monthly Members Meeting,0
|
||||||
|
2021-09-25,Metal: Metal Cutting & Manual Lathe,5
|
||||||
|
2021-08-21,Introduction to the Wood Lathe,5
|
||||||
|
2021-09-02,New Members: Orientation and Basic Safety,3
|
||||||
|
2021-09-12,Basic CNC Wood Router,6
|
||||||
|
2021-09-04,"Woodworking Tools 2: Jointer, Thickness Planer, Drum Sander",2
|
||||||
|
2021-09-12,Woodworking Tools 1: Intro to Saws,4
|
||||||
|
2021-09-12,Introduction to the Wood Lathe,2
|
||||||
|
2021-09-11,New Members: Orientation and Basic Safety,1
|
||||||
|
2021-10-21,Monthly Members Meeting,0
|
||||||
|
2021-09-18,Monthly Cleanup and Group Lunch,0
|
||||||
|
2021-09-23,New Members: Orientation and Basic Safety,5
|
||||||
|
2021-10-03,New Members: Orientation and Basic Safety,1
|
||||||
|
2021-09-18,Basic CNC Wood Router,6
|
||||||
|
2021-10-02,Woodworking Tools 1: Intro to Saws,3
|
||||||
|
2021-10-09,Basic CNC Wood Router,5
|
||||||
|
2021-10-23,Laser: Cutting and Engraving,5
|
||||||
|
2021-11-06,Laser: Cutting and Engraving,3
|
||||||
|
2021-10-23,Laser: Cutting and Engraving,6
|
||||||
|
2021-10-16,Laser II: Trotec Course (For Rabbit-Certified members),0
|
||||||
|
2021-10-16,Laser II: Trotec Course (For Rabbit-Certified members),3
|
||||||
|
2021-10-23,Laser II: Trotec Course (For Rabbit-Certified members),1
|
||||||
|
2021-10-23,Laser II: Trotec Course (For Rabbit-Certified members),0
|
||||||
|
2021-10-30,Laser II: Trotec Course (For Rabbit-Certified members),8
|
||||||
|
2021-10-30,Laser II: Trotec Course (For Rabbit-Certified members),0
|
||||||
|
2021-10-22,New Members: Orientation and Basic Safety,1
|
||||||
|
2021-10-17,Woodworking Tools 1: Intro to Saws,5
|
||||||
|
2021-10-17,"Woodworking Tools 2: Jointer, Thickness Planer, Drum Sander",8
|
||||||
|
2021-10-17,Introduction to the Wood Lathe,3
|
||||||
|
2021-10-16,Monthly Cleanup and Group Lunch,0
|
||||||
|
2021-11-21,Woodworking Tools 1: Intro to Saws,4
|
||||||
|
2021-11-06,CAD/CAM for The Complete Beginner: Fusion 360,4
|
||||||
|
2021-11-07,New Members: Orientation and Basic Safety,6
|
||||||
|
2021-11-07,Laser II: Trotec Course (For Rabbit-Certified members),0
|
||||||
|
2021-11-05,Electronics Night,0
|
||||||
|
2021-11-13,Basic CNC Wood Router,4
|
||||||
|
2021-11-28,Basic CNC Wood Router,4
|
||||||
|
2021-12-03,Electronics Night,0
|
||||||
|
2021-11-25,New Members: Orientation and Basic Safety,7
|
||||||
|
2021-12-11,New Members: Orientation and Basic Safety,5
|
||||||
|
2021-11-19,Monthly Members Meeting,0
|
||||||
|
2021-11-20,Monthly Cleanup and Group Lunch,0
|
||||||
|
2022-01-15,CAD/CAM for The Complete Beginner: Fusion 360,0
|
||||||
|
2021-12-18,Monthly Cleanup and Group Lunch,0
|
||||||
|
2022-01-16,Woodworking Tools 1: Intro to Saws,6
|
||||||
|
2022-03-13,Woodworking Tools 1: Intro to Saws,0
|
||||||
|
2022-05-15,Woodworking Tools 1: Intro to Saws,0
|
||||||
|
2021-11-27,CRT Retro Computing Club,0
|
||||||
|
2021-12-23,New Members: Orientation and Basic Safety,1
|
||||||
|
2021-12-11,Roots2STEM tour,5
|
||||||
|
2021-12-18,Basic CNC Wood Router,4
|
||||||
|
2021-12-11,Woodworking Tools 1: Intro to Saws,3
|
||||||
|
2021-12-11,"Woodworking Tools 2: Jointer, Thickness Planer, Drum Sander",5
|
||||||
|
2021-12-12,Introduction to the Wood Lathe,1
|
||||||
|
2021-12-19,CRT Retro Computing Club,0
|
||||||
|
2022-01-23,3D Printing: Introduction to 3D Printing,7
|
||||||
|
2022-01-09,New Members: Orientation and Basic Safety,5
|
||||||
|
2022-01-22,New Members: Orientation and Basic Safety,4
|
||||||
|
2022-01-29,Basic CNC Wood Router,0
|
||||||
|
2022-01-07,Electronics Night,0
|
||||||
|
2022-02-04,Electronics Night,0
|
||||||
|
2022-02-13,Woodworking Tools 1: Intro to Saws,0
|
||||||
|
2022-02-03,New Members: Orientation and Basic Safety,0
|
||||||
|
2022-02-27,Basic CNC Wood Router,0
|
||||||
|
2022-03-05,Tormach: CAM and Tormach Intro,0
|
||||||
|
2022-02-05,CAD: Introduction to 3D CAD (Fusion),0
|
||||||
|
2022-01-30,Laser: Cutting and Engraving,0
|
||||||
|
2022-01-22,CAD/CAM for The Complete Beginner Part II (Classroom Booking Edition),0
|
||||||
|
2022-02-12,Metal: Metal Cutting & Manual Lathe,0
|
||||||
|
2022-01-21,Monthly Members Meeting,0
|
||||||
|
2022-02-12,New Members: Orientation and Basic Safety,0
|
||||||
|
2022-02-24,New Members: Orientation and Basic Safety,0
|
||||||
|
2022-03-26,Basic CNC Wood Router,0
|
||||||
|
2022-01-29,"Woodworking Tools 2: Jointer, Thickness Planer, Drum Sander",0
|
||||||
|
2022-02-06,Laser: Cutting and Engraving,0
|
||||||
|
2022-01-28,New Members: Orientation and Basic Safety,2
|
||||||
|
2022-01-23,New Members: Orientation and Basic Safety,2
|
||||||
|
2022-01-25,New Members: Orientation and Basic Safety,1
|
||||||
|
2022-01-29,New Members: Orientation and Basic Safety,0
|
||||||
|
2022-02-17,Monthly Members Meeting,0
|
||||||
|
2022-02-19,Monthly Cleanup and Group Lunch,0
|
||||||
|
2022-01-30,Intro to Blade Sharpening,0
|
||||||
|
2022-01-29,Welding 101 - MIG Welding and Safety,0
|
||||||
|
2021-12-30,Woodworking Tools 1: Intro to Saws,0
|
||||||
|
2022-01-27,Woodworking Tools 1: Intro to Saws,2
|
||||||
|
2022-02-03,Woodworking Tools 1: Intro to Saws,0
|
||||||
|
2022-02-05,"Woodworking Tools 2: Jointer, Thickness Planer, Drum Sander",0
|
||||||
|
2022-02-12,Roots 2 STEM classes,0
|
||||||
|
2022-02-12,Laser II: Trotec Course (For Rabbit-Certified members),0
|
||||||
|
2022-02-19,Laser II: Trotec Course (For Rabbit-Certified members),0
|
|
|
@ -137,6 +137,8 @@ export function CourseDetail(props) {
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const now = new Date().toISOString();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
{!error ?
|
{!error ?
|
||||||
|
@ -170,21 +172,32 @@ export function CourseDetail(props) {
|
||||||
<Table.HeaderCell>Time</Table.HeaderCell>
|
<Table.HeaderCell>Time</Table.HeaderCell>
|
||||||
<Table.HeaderCell>Instructor</Table.HeaderCell>
|
<Table.HeaderCell>Instructor</Table.HeaderCell>
|
||||||
<Table.HeaderCell>Cost</Table.HeaderCell>
|
<Table.HeaderCell>Cost</Table.HeaderCell>
|
||||||
|
<Table.HeaderCell>Students</Table.HeaderCell>
|
||||||
</Table.Row>
|
</Table.Row>
|
||||||
</Table.Header>
|
</Table.Header>
|
||||||
|
|
||||||
<Table.Body>
|
<Table.Body>
|
||||||
{course.sessions.length ?
|
{course.sessions.length ?
|
||||||
course.sessions.sort((a, b) => a.datetime < b.datetime ? 1 : -1).slice(0,10).map(x =>
|
course.sessions.sort((a, b) => a.datetime < b.datetime ? 1 : -1).slice(0,10).map(x =>
|
||||||
<Table.Row key={x.id}>
|
<Table.Row key={x.id} active={x.datetime < now || x.is_cancelled}>
|
||||||
<Table.Cell>
|
<Table.Cell>
|
||||||
<Link to={'/classes/'+x.id}>
|
<Link to={'/classes/'+x.id}>
|
||||||
{moment.utc(x.datetime).tz('America/Edmonton').format('ll')}
|
{moment.utc(x.datetime).tz('America/Edmonton').format('ll')}
|
||||||
</Link>
|
</Link>
|
||||||
</Table.Cell>
|
</Table.Cell>
|
||||||
<Table.Cell>{x.is_cancelled ? 'Cancelled' : moment.utc(x.datetime).tz('America/Edmonton').format('LT')}</Table.Cell>
|
<Table.Cell>{x.is_cancelled ? 'Cancelled' : moment.utc(x.datetime).tz('America/Edmonton').format('LT')}</Table.Cell>
|
||||||
<Table.Cell>{getInstructor(x)}</Table.Cell>
|
<Table.Cell>{getInstructor(x)}</Table.Cell>
|
||||||
<Table.Cell>{x.cost === '0.00' ? 'Free' : '$'+x.cost}</Table.Cell>
|
<Table.Cell>{x.cost === '0.00' ? 'Free' : '$'+x.cost}</Table.Cell>
|
||||||
|
<Table.Cell>
|
||||||
|
{!!x.max_students ?
|
||||||
|
x.max_students <= x.student_count ?
|
||||||
|
'Full'
|
||||||
|
:
|
||||||
|
x.student_count + ' / ' + x.max_students
|
||||||
|
:
|
||||||
|
x.student_count
|
||||||
|
}
|
||||||
|
</Table.Cell>
|
||||||
</Table.Row>
|
</Table.Row>
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
|
|
|
@ -209,7 +209,11 @@ export function InstructorClassAttendance(props) {
|
||||||
/>
|
/>
|
||||||
</Form.Field>
|
</Form.Field>
|
||||||
|
|
||||||
<Form.Button loading={loading} error={error.non_field_errors}>
|
<Form.Button
|
||||||
|
loading={loading}
|
||||||
|
error={error.non_field_errors}
|
||||||
|
disabled={!input.member_id}
|
||||||
|
>
|
||||||
Submit
|
Submit
|
||||||
</Form.Button>
|
</Form.Button>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user