• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

gcivil-nyu-org / INT2-Monday-Spring2024-Team-2 / 800

29 Apr 2024 09:02AM UTC coverage: 91.218% (+1.7%) from 89.518%
800

push

travis-pro

web-flow
Merge pull request #250 from gcivil-nyu-org/Community-v3

add tests

8 of 39 new or added lines in 1 file covered. (20.51%)

764 existing lines in 16 files now uncovered.

1984 of 2175 relevant lines covered (91.22%)

1.23 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

74.44
/Dashboard/views.py
1
from django.shortcuts import render, redirect
2✔
2
from django.db.models.functions import Coalesce
2✔
3
from django.contrib.auth import logout
2✔
4
from django.contrib.auth.decorators import login_required
2✔
5
from .forms.tutor_info import (
2✔
6
    TutorForm,
7
    AvailabilityForm,
8
    TutorImageForm,
9
    TutorTranscriptForm,
10
)
11
from django.db.models import Count, F, ExpressionWrapper, FloatField, Value, Case, When
2✔
12
from .forms.student_info import StudentForm, StudentImageForm
2✔
13
from .forms.review_form import TutorReviewForm
2✔
14
from .forms.survey_form import SurveyForm
2✔
15
from TutorRegister.models import (
2✔
16
    Expertise,
17
    Availability,
18
    ProfileT,
19
    ProfileS,
20
    TutoringSession,
21
    TutorReview,
22
)
23
from django.urls import reverse
2✔
24
from django.http import HttpResponseRedirect
2✔
25
import json
2✔
26
from datetime import datetime, time, date
2✔
27
from django.db.models import Q
2✔
28
from PIL import Image, ImageDraw, ImageOps
2✔
29
from io import BytesIO
2✔
30
from django.core.files.base import ContentFile
2✔
31
from django.core.mail import send_mail
2✔
32
from django.core.mail import EmailMessage
2✔
33
from django.template.loader import render_to_string
2✔
34
from django.contrib.auth.models import User
2✔
35
from django.utils import timezone
2✔
36
from django.http import FileResponse
2✔
37
from django.shortcuts import get_object_or_404
2✔
38
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
2✔
39
from django.views.decorators.csrf import csrf_exempt
2✔
40
from django.contrib import messages
2✔
41

42
import mimetypes
2✔
43

44

45
@login_required
2✔
46
def TutorInformation(request):
2✔
UNCOV
47
    if request.user.usertype.user_type == "tutor":
1✔
UNCOV
48
        initial_availabilities_json = "[]"
1✔
UNCOV
49
        tutor_form = TutorForm()
1✔
UNCOV
50
        try:
1✔
UNCOV
51
            tutor_image_form = TutorImageForm(
1✔
52
                instance=ProfileT.objects.get(user=request.user)
53
            )
UNCOV
54
            tutor_transcript_form = TutorTranscriptForm(
1✔
55
                instance=ProfileT.objects.get(user=request.user)
56
            )
57
        except ProfileT.DoesNotExist:
×
58
            tutor_image_form = TutorImageForm()
×
59
            tutor_transcript_form = TutorTranscriptForm()
×
UNCOV
60
        existing_expertise = list(
1✔
61
            Expertise.objects.filter(user=request.user).values_list(
62
                "subject", flat=True
63
            )
64
        )
65

UNCOV
66
        if request.method == "POST":
1✔
UNCOV
67
            profile, created = ProfileT.objects.get_or_create(user=request.user)
1✔
UNCOV
68
            tutor_form = TutorForm(request.POST, instance=profile)
1✔
UNCOV
69
            tutor_image_form = TutorImageForm(
1✔
70
                request.POST, request.FILES, instance=profile
71
            )
UNCOV
72
            tutor_transcript_form = TutorTranscriptForm(
1✔
73
                request.POST, request.FILES, instance=profile
74
            )
UNCOV
75
            availability_form = AvailabilityForm(request.POST)
1✔
UNCOV
76
            if (
1✔
77
                tutor_form.is_valid()
78
                and tutor_image_form.is_valid()
79
                and tutor_transcript_form.is_valid()
80
                and availability_form.is_valid()
81
            ):
UNCOV
82
                user = request.user
1✔
UNCOV
83
                profile = tutor_form.save(commit=False)
1✔
84
                # Handle the image field separately using tutor_image_form
UNCOV
85
                if "image" in request.FILES:
1✔
86
                    image = Image.open(request.FILES["image"])
×
87
                    image = image.resize((300, 300), Image.Resampling.LANCZOS)
×
88
                    # Resize and fill with white background
89
                    new_image = Image.new("RGB", (300, 300), (255, 255, 255))
×
90
                    image.thumbnail((300, 300), Image.Resampling.LANCZOS)
×
91
                    new_image.paste(
×
92
                        image, ((300 - image.width) // 2, (300 - image.height) // 2)
93
                    )
94

95
                    # Crop as a circle
96
                    mask = Image.new("L", (300, 300), 0)
×
97
                    draw = ImageDraw.Draw(mask)
×
98
                    draw.ellipse((0, 0, 300, 300), fill=255)
×
99
                    circle_image = ImageOps.fit(
×
100
                        new_image, (300, 300), centering=(0.5, 0.5)
101
                    )
102
                    circle_image.putalpha(mask)
×
103

104
                    # Save the image
105
                    image_io = BytesIO()
×
106
                    circle_image.save(image_io, format="PNG")
×
107
                    image_name = request.FILES["image"].name
×
108
                    profile.image.save(
×
109
                        image_name, ContentFile(image_io.getvalue()), save=False
110
                    )
UNCOV
111
                if "transcript" in request.FILES:
1✔
UNCOV
112
                    profile.transcript = request.FILES["transcript"]
1✔
113

UNCOV
114
                profile.user = user
1✔
UNCOV
115
                profile.save()
1✔
116

UNCOV
117
                Availability.objects.filter(user=request.user).delete()
1✔
UNCOV
118
                serialized_availabilities = request.POST.get("availabilities")
1✔
UNCOV
119
                availabilities = json.loads(serialized_availabilities)
1✔
120

UNCOV
121
                for availability_data in availabilities:
1✔
UNCOV
122
                    availability_data["user"] = user
1✔
UNCOV
123
                    Availability.objects.create(**availability_data)
1✔
124

125
                # Save expertise data to database
UNCOV
126
                Expertise.objects.filter(user=request.user).delete()
1✔
UNCOV
127
                selected_expertise = request.POST.getlist("expertise")
1✔
UNCOV
128
                if selected_expertise:
1✔
UNCOV
129
                    for expertise in selected_expertise:
1✔
UNCOV
130
                        Expertise.objects.create(user=user, subject=expertise)
1✔
UNCOV
131
                user.usertype.has_profile_complete = True
1✔
UNCOV
132
                user.usertype.save()
1✔
UNCOV
133
                return HttpResponseRedirect(reverse("Dashboard:dashboard"))
1✔
134
        else:
UNCOV
135
            profile = None
1✔
UNCOV
136
            existing_availabilities = None
1✔
UNCOV
137
            try:
1✔
UNCOV
138
                profile = ProfileT.objects.get(user=request.user)
1✔
UNCOV
139
                existing_availabilities = Availability.objects.filter(user=request.user)
1✔
UNCOV
140
                initial_availabilities_json = json.dumps(
1✔
141
                    list(
142
                        existing_availabilities.values(
143
                            "day_of_week", "start_time", "end_time"
144
                        )
145
                    ),
146
                    cls=DateTimeEncoder,
147
                )
UNCOV
148
                tutor_form = TutorForm(instance=profile)
1✔
149
            except Exception as e:
×
150
                print("Error " + str(e))
×
UNCOV
151
            availability_form = AvailabilityForm()
1✔
UNCOV
152
            tutor_form.initial["expertise"] = existing_expertise
1✔
UNCOV
153
        context = {
1✔
154
            "tutor_form": tutor_form,
155
            "tutor_image_form": tutor_image_form,
156
            "tutor_transcript_form": tutor_transcript_form,  # Add this to the context
157
            "availability_form": availability_form,
158
            "initial_availabilities_json": initial_availabilities_json,
159
        }
160

UNCOV
161
        return render(request, "Dashboard/tutor_info.html", context)
1✔
162

163
    else:
164
        return redirect("Dashboard:student_profile")
×
165

166

167
@login_required
2✔
168
def StudentInformation(request):
2✔
UNCOV
169
    if request.user.usertype.user_type == "student":
1✔
UNCOV
170
        if request.method == "POST":
1✔
UNCOV
171
            profile, created = ProfileS.objects.get_or_create(user=request.user)
1✔
UNCOV
172
            student_form = StudentForm(request.POST, instance=profile)
1✔
UNCOV
173
            student_image_form = StudentImageForm(
1✔
174
                request.POST, request.FILES, instance=profile
175
            )
176

UNCOV
177
            if student_form.is_valid() and student_image_form.is_valid():
1✔
UNCOV
178
                user = request.user
1✔
UNCOV
179
                profile = student_form.save(commit=False)
1✔
180

181
                # Handle the image field separately using student_image_form
UNCOV
182
                if "image" in request.FILES:
1✔
183
                    image = Image.open(request.FILES["image"])
×
184
                    # Resize to 300x300, enlarging if necessary
185
                    image = image.resize((300, 300), Image.Resampling.LANCZOS)
×
186
                    # Fill with white background and crop as a circle
187
                    new_image = Image.new("RGB", (300, 300), (255, 255, 255))
×
188
                    new_image.paste(
×
189
                        image, ((300 - image.width) // 2, (300 - image.height) // 2)
190
                    )
191
                    mask = Image.new("L", (300, 300), 0)
×
192
                    draw = ImageDraw.Draw(mask)
×
193
                    draw.ellipse((0, 0, 300, 300), fill=255)
×
194
                    new_image.putalpha(mask)
×
195
                    # Save the image
196
                    image_io = BytesIO()
×
197
                    new_image.save(image_io, format="PNG")
×
198
                    image_name = request.FILES["image"].name
×
199
                    profile.image.save(
×
200
                        image_name, ContentFile(image_io.getvalue()), save=False
201
                    )
202

UNCOV
203
                profile.user = user
1✔
UNCOV
204
                profile.save()
1✔
UNCOV
205
                user.usertype.has_profile_complete = True
1✔
UNCOV
206
                user.usertype.save()
1✔
UNCOV
207
                return HttpResponseRedirect(reverse("Dashboard:dashboard"))
1✔
208
        else:
209
            profile = None
×
210
            try:
×
211
                profile = ProfileS.objects.get(user=request.user)
×
212
            except Exception as e:
×
213
                print("Error " + str(e))
×
214

215
            student_form = StudentForm(instance=profile)
×
216
            student_image_form = StudentImageForm(instance=profile)
×
217

218
        context = {
×
219
            "student_form": student_form,
220
            "student_image_form": student_image_form,
221
            "profile": profile,
222
        }
223

224
        return render(request, "Dashboard/student_info.html", context)
×
225

226
    else:
227
        return redirect("Dashboard:tutor_profile")
×
228

229

230
@login_required
2✔
231
def UserDashboard(request):
2✔
UNCOV
232
    userType = request.user.usertype.user_type
1✔
233

UNCOV
234
    if userType == "student":
1✔
UNCOV
235
        sessions = TutoringSession.objects.filter(
1✔
236
            student_id=request.user.id, status="Accepted"
237
        ).select_related("tutor_id__profilet")
238
    else:
UNCOV
239
        sessions = TutoringSession.objects.filter(
1✔
240
            tutor_id=request.user.id, status="Accepted"
241
        ).select_related("student_id__profiles")
242

UNCOV
243
    now = datetime.now()
1✔
244

UNCOV
245
    upcomingSessions = sessions.filter(
1✔
246
        Q(date__gt=now.date()) | Q(date=now.date(), end_time__gt=now.time())
247
    )
248

UNCOV
249
    pastSessions = sessions.filter(
1✔
250
        Q(date__lt=now.date()) | Q(date=now.date(), end_time__lt=now.time())
251
    )
UNCOV
252
    has_upcomingSessions = upcomingSessions
1✔
UNCOV
253
    has_pastSessions = pastSessions
1✔
254

UNCOV
255
    page_number1 = request.GET.get("upcoming_page", 1)
1✔
UNCOV
256
    page_number2 = request.GET.get("past_page", 1)
1✔
257

UNCOV
258
    paginator1 = Paginator(upcomingSessions, 3)
1✔
UNCOV
259
    paginator2 = Paginator(pastSessions, 3)
1✔
260

UNCOV
261
    try:
1✔
UNCOV
262
        upcomingSessions = paginator1.page(page_number1)
1✔
263
    except PageNotAnInteger:
×
264
        upcomingSessions = paginator1.page(1)
×
265
    except EmptyPage:
×
266
        upcomingSessions = paginator1.page(paginator1.num_pages)
×
267

UNCOV
268
    try:
1✔
UNCOV
269
        pastSessions = paginator2.page(page_number2)
1✔
270
    except PageNotAnInteger:
×
271
        pastSessions = paginator2.page(1)
×
272
    except EmptyPage:
×
273
        pastSessions = paginator2.page(paginator2.num_pages)
×
274

UNCOV
275
    context = {
1✔
276
        "baseTemplate": (
277
            "Dashboard/base_student.html"
278
            if userType == "student"
279
            else "Dashboard/base_tutor.html"
280
        ),
281
        "userType": userType,
282
        "upcomingSessions": upcomingSessions,
283
        "has_upcomingSessions": has_upcomingSessions,
284
        "pastSessions": pastSessions,
285
        "has_pastSessions": has_pastSessions,
286
        "upcoming_page": page_number1,
287
        "past_page": page_number2,
288
    }
289

UNCOV
290
    return render(request, "Dashboard/dashboard.html", context)
1✔
291

292

293
@login_required
2✔
294
def Survey(request, session_id):
2✔
UNCOV
295
    session = TutoringSession.objects.get(pk=session_id)
1✔
UNCOV
296
    s_id = session.student_id
1✔
UNCOV
297
    t_id = session.tutor_id
1✔
UNCOV
298
    if request.method == "POST":
1✔
UNCOV
299
        form = SurveyForm(request.POST)
1✔
UNCOV
300
        print(form.errors)
1✔
UNCOV
301
        if form.is_valid():
1✔
UNCOV
302
            survey = form.save(commit=False)
1✔
UNCOV
303
            survey.session = session
1✔
UNCOV
304
            survey.reviewer = s_id
1✔
UNCOV
305
            survey.reviewee = t_id
1✔
UNCOV
306
            survey.save()
1✔
307

UNCOV
308
            session.survey_completed = True
1✔
UNCOV
309
            session.save()
1✔
UNCOV
310
            return redirect("Dashboard:dashboard")
1✔
311

312
    else:
313
        form = SurveyForm()
×
314
    userType = request.user.usertype.user_type
×
315
    context = {
×
316
        "baseTemplate": (
317
            "Dashboard/base_student.html"
318
            if userType == "student"
319
            else "Dashboard/base_tutor.html"
320
        ),
321
        "userType": userType,
322
        "form": form,
323
        "session_id": session_id,
324
    }
325
    return render(request, "Dashboard/survey.html", context)
×
326

327

328
@login_required
2✔
329
def ProvideFeedback(request, session_id):
2✔
UNCOV
330
    session = TutoringSession.objects.get(pk=session_id)
1✔
331

UNCOV
332
    s_id = session.student_id
1✔
UNCOV
333
    t_id = session.tutor_id
1✔
334

UNCOV
335
    tutor_profile = get_object_or_404(ProfileT, user=t_id)
1✔
336

UNCOV
337
    if request.method == "POST":
1✔
UNCOV
338
        form = TutorReviewForm(request.POST)
1✔
339

UNCOV
340
        if form.is_valid():
1✔
UNCOV
341
            review = form.save(commit=False)
1✔
UNCOV
342
            review.student_id = s_id
1✔
UNCOV
343
            review.tutor_id = t_id
1✔
UNCOV
344
            review.tutoring_session = session
1✔
UNCOV
345
            review.save()
1✔
346

UNCOV
347
            session.reviewed_by_student = True
1✔
UNCOV
348
            session.save()
1✔
UNCOV
349
            return redirect("Dashboard:dashboard")
1✔
350
    else:
351
        form = TutorReviewForm()
×
352
    return render(
×
353
        request, "Dashboard/feedback.html", {"form": form, "profilet": tutor_profile}
354
    )
355

356

357
@login_required
2✔
358
def TutorFeedback(request):
2✔
UNCOV
359
    reviews = (
1✔
360
        TutorReview.objects.all()
361
        .filter(tutor_id=request.user.id)
362
        .select_related("student_id__profiles")
363
    )
364

UNCOV
365
    has_reviews = reviews
1✔
UNCOV
366
    page = request.GET.get("page")
1✔
UNCOV
367
    paginator = Paginator(reviews, 5)
1✔
UNCOV
368
    try:
1✔
UNCOV
369
        reviews = paginator.page(page)
1✔
UNCOV
370
    except PageNotAnInteger:
1✔
371
        # If page is not an integer, deliver first page.
UNCOV
372
        reviews = paginator.page(1)
1✔
373
    except EmptyPage:
×
374
        # If page is out of range, deliver last page of results.
375
        reviews = paginator.page(paginator.num_pages)
×
376

UNCOV
377
    return render(
1✔
378
        request,
379
        "Dashboard/tutor_feedback.html",
380
        {"has_reviews": has_reviews, "reviews": reviews},
381
    )
382

383

384
@login_required
2✔
385
def CancelSession(request, session_id):
2✔
UNCOV
386
    userType = request.user.usertype.user_type
1✔
387

UNCOV
388
    session = TutoringSession.objects.get(pk=session_id)
1✔
389

UNCOV
390
    student = session.student_id
1✔
UNCOV
391
    student_email = student.username
1✔
UNCOV
392
    studentFname = student.first_name
1✔
UNCOV
393
    studentLname = student.last_name
1✔
394

UNCOV
395
    tutor = session.tutor_id
1✔
UNCOV
396
    tutor_email = tutor.username
1✔
UNCOV
397
    tutorFname = tutor.first_name
1✔
UNCOV
398
    tutorLname = tutor.last_name
1✔
399

UNCOV
400
    sessionDate = session.date
1✔
UNCOV
401
    sessionTime = session.start_time
1✔
UNCOV
402
    session.status = "Cancelled"
1✔
UNCOV
403
    session.save()
1✔
404

405
    # send email notification to the students about session cancellation
UNCOV
406
    html_content = render_to_string(
1✔
407
        "Email/cancellation_template.html",
408
        {
409
            "studentFname": studentFname,
410
            "studentLname": studentLname,
411
            "tutorFname": tutorFname,
412
            "tutorLname": tutorLname,
413
            "sessionDate": sessionDate,
414
            "sessionTime": sessionTime,
415
        },
416
    )
417

UNCOV
418
    email = EmailMessage(
1✔
419
        "Tutoring Session Cancelled",
420
        html_content,
421
        "tutornyuengineeringverify@gmail.com",
422
        [student_email if userType == "tutor" else tutor_email],
423
    )
UNCOV
424
    email.content_subtype = "html"
1✔
UNCOV
425
    email.send()
1✔
426

UNCOV
427
    return redirect("Dashboard:dashboard")
1✔
428

429

430
@login_required
2✔
431
def Requests(request):
2✔
UNCOV
432
    userType = request.user.usertype.user_type
1✔
433

UNCOV
434
    if userType == "tutor":
1✔
UNCOV
435
        tutorRequests = TutoringSession.objects.filter(
1✔
436
            tutor_id=request.user.id, status="Pending", date__gte=date.today()
437
        ).select_related("student_id__profiles")
438
    else:
439
        tutorRequests = TutoringSession.objects.filter(
×
440
            student_id=request.user.id,
441
            status__in=["Pending", "Declined"],
442
            date__gte=date.today(),
443
        ).select_related("tutor_id__profilet")
444

UNCOV
445
    has_tutorRequests = tutorRequests
1✔
UNCOV
446
    page = request.GET.get("page")
1✔
UNCOV
447
    paginator = Paginator(tutorRequests, 5)
1✔
UNCOV
448
    try:
1✔
UNCOV
449
        tutorRequests = paginator.page(page)
1✔
UNCOV
450
    except PageNotAnInteger:
1✔
451
        # If page is not an integer, deliver first page.
UNCOV
452
        tutorRequests = paginator.page(1)
1✔
453
    except EmptyPage:
×
454
        # If page is out of range, deliver last page of results.
455
        tutorRequests = paginator.page(paginator.num_pages)
×
456

UNCOV
457
    context = {
1✔
458
        "baseTemplate": (
459
            "Dashboard/base_student.html"
460
            if userType == "student"
461
            else "Dashboard/base_tutor.html"
462
        ),
463
        "userType": userType,
464
        "tutorRequests": tutorRequests,
465
        "has_tutorRequests": has_tutorRequests,
466
    }
UNCOV
467
    return render(request, "Dashboard/requests.html", context)
1✔
468

469

470
def AcceptRequest(request, session_id):
2✔
UNCOV
471
    accepted_session = TutoringSession.objects.get(pk=session_id)
1✔
UNCOV
472
    accepted_session.status = "Accepted"
1✔
UNCOV
473
    accepted_session.save()
1✔
UNCOV
474
    overlapping_sessions = (
1✔
475
        TutoringSession.objects.filter(
476
            tutor_id=accepted_session.tutor_id,
477
            date=accepted_session.date,
478
            status="Pending",
479
        )
480
        .exclude(pk=session_id)
481
        .exclude(
482
            Q(start_time__gte=accepted_session.end_time)
483
            | Q(end_time__lte=accepted_session.start_time)
484
        )
485
    )
UNCOV
486
    overlapping_sessions.update(status="Declined")
1✔
UNCOV
487
    return redirect("Dashboard:requests")
1✔
488

489

490
def DeclineRequest(request, session_id):
2✔
UNCOV
491
    session = TutoringSession.objects.get(pk=session_id)
1✔
492

UNCOV
493
    if session.status == "Pending":
1✔
UNCOV
494
        session.status = "Declined"
1✔
UNCOV
495
        session.save()
1✔
496
    else:
497
        # If status is not 'Pending', raise an error message
498
        messages.error(
×
499
            request, "This request has been cancelled and cannot be declined."
500
        )
501

UNCOV
502
    return redirect("Dashboard:requests")
1✔
503

504

505
@login_required
2✔
506
def DeleteRequest(request, session_id):
2✔
507
    session = TutoringSession.objects.get(pk=session_id)
×
508
    if session.status == "Declined":
×
509
        session.delete()
×
510

511
    return redirect("Dashboard:requests")
×
512

513

514
@login_required
2✔
515
def CancelRequest(request, session_id):
2✔
516
    session = TutoringSession.objects.get(pk=session_id)
×
517
    if session.status == "Pending":
×
518
        session.status = "Cancelled"
×
519
        session.save()
×
520

521
    return redirect("Dashboard:requests")
×
522

523

524
def logout_view(request):
2✔
UNCOV
525
    logout(request)
1✔
UNCOV
526
    return redirect("home")
1✔
527

528

529
class DateTimeEncoder(json.JSONEncoder):
2✔
530
    def default(self, obj):
2✔
531
        if isinstance(obj, (datetime, time)):
×
532
            return obj.strftime("%H:%M")
×
533
        return json.JSONEncoder.default(self, obj)
×
534

535

536
@login_required
2✔
537
def download_attachment(request, session_id):
2✔
UNCOV
538
    session = get_object_or_404(TutoringSession, pk=session_id)
1✔
539

UNCOV
540
    if session.attachment:
1✔
541
        # Open the file directly from the storage backend
UNCOV
542
        file = session.attachment.open("rb")
1✔
543
        # Create a FileResponse with the file's content
UNCOV
544
        response = FileResponse(
1✔
545
            file, as_attachment=True, filename=session.attachment.name
546
        )
547
        # Set the content type to the file's content type, if available
UNCOV
548
        content_type, _ = mimetypes.guess_type(session.attachment.name)
1✔
UNCOV
549
        if content_type:
1✔
UNCOV
550
            response["Content-Type"] = content_type
1✔
UNCOV
551
        return response
1✔
552

553
    return redirect("Dashboard:requests")
×
554

555

556
@login_required
2✔
557
def download_transcript(request, tutor_id):
2✔
UNCOV
558
    tutor_profile = get_object_or_404(ProfileT, pk=tutor_id)
1✔
559

UNCOV
560
    if tutor_profile.transcript:
1✔
561
        # Open the file directly from the storage backend
UNCOV
562
        file = tutor_profile.transcript.open("rb")
1✔
563
        # Create a FileResponse with the file's content
UNCOV
564
        response = FileResponse(
1✔
565
            file, as_attachment=True, filename=tutor_profile.transcript.name
566
        )
567
        # Set the content type to the file's content type, if available
UNCOV
568
        content_type, _ = mimetypes.guess_type(tutor_profile.transcript.name)
1✔
UNCOV
569
        if content_type:
1✔
UNCOV
570
            response["Content-Type"] = content_type
1✔
UNCOV
571
        return response
1✔
572

573
    return redirect("Dashboard:tutor_profile")
×
574

575

576
@csrf_exempt
2✔
577
def VideoCall(request):
2✔
UNCOV
578
    if request.method == "POST":
1✔
579
        action = request.POST.get("action")
×
580
        if action == "session":
×
581
            sessionId = request.POST.get("sessionID", "")
×
582
            request.session["temp"] = sessionId
×
583
            print("Session ID:", sessionId)
×
584
        elif action == "url":
×
585
            url = request.POST.get("url", "")
×
586
            sessionId = request.session.get("temp")
×
587
            if sessionId:
×
588
                session = TutoringSession.objects.get(pk=sessionId)
×
589
                session.meeting_link = url
×
590
                session.save()
×
591
                print("Received URL:", url)
×
592
            else:
593
                print("SessionId not found")
×
594

UNCOV
595
    if request.user.usertype.user_type == "tutor":
1✔
UNCOV
596
        tutor = ProfileT.objects.get(user=request.user)
1✔
UNCOV
597
        fname = tutor.fname
1✔
UNCOV
598
        lname = tutor.lname
1✔
599
    else:
UNCOV
600
        student = ProfileS.objects.get(user=request.user)
1✔
UNCOV
601
        fname = student.fname
1✔
UNCOV
602
        lname = student.lname
1✔
UNCOV
603
    return render(request, "Dashboard/video_call.html", {"name": fname + " " + lname})
1✔
604

605

606
@login_required
2✔
607
def AdminDashboard(request):
2✔
UNCOV
608
    tutors = ProfileT.objects.annotate(
1✔
609
        total_reviewee_count=Count("user__user_reviewee", distinct=True),
610
        total_true=ExpressionWrapper(
611
            Case(
612
                When(
613
                    total_reviewee_count__gt=0,
614
                    then=100
615
                    * (
616
                        Count(
617
                            "user__user_reviewee__q1",
618
                            filter=F("user__user_reviewee__q1"),
619
                        )
620
                        + Count(
621
                            "user__user_reviewee__q2",
622
                            filter=F("user__user_reviewee__q2"),
623
                        )
624
                        + Count(
625
                            "user__user_reviewee__q3",
626
                            filter=F("user__user_reviewee__q3"),
627
                        )
628
                    )
629
                    / (3 * Count("user__user_reviewee", distinct=True)),
630
                ),
631
                default=None,
632
            ),
633
            output_field=FloatField(),
634
        ),
635
    ).order_by("id")
UNCOV
636
    expertise = Expertise.objects.all()
1✔
UNCOV
637
    return render(
1✔
638
        request,
639
        "Dashboard/admin_dashboard.html",
640
        {"tutors": tutors, "expertise": expertise},
641
    )
642

643

644
def UpdateQualification(request):
2✔
UNCOV
645
    if request.method == "POST":
1✔
UNCOV
646
        tutor_id = request.POST.get("tutor_id")
1✔
UNCOV
647
        qualifiction = request.POST.get(f"qualification_{tutor_id}")
1✔
UNCOV
648
        tutor = ProfileT.objects.get(id=tutor_id)
1✔
UNCOV
649
        tutor.qualified = qualifiction == "qualified"
1✔
UNCOV
650
        tutor.save()
1✔
651

UNCOV
652
        tutor_name = tutor.fname
1✔
UNCOV
653
        tutor_user = tutor.user
1✔
UNCOV
654
        tutor_email = tutor_user.username
1✔
655

UNCOV
656
        if tutor.qualified:
1✔
657
            html_content = render_to_string(
×
658
                "Email/qualification_email.html", {"tutor_name": tutor_name}
659
            )
660
        else:
UNCOV
661
            html_content = render_to_string(
1✔
662
                "Email/unqualify_email.html", {"tutor_name": tutor_name}
663
            )
664

UNCOV
665
        email = EmailMessage(
1✔
666
            "Qualification Updated -- TutorNYU",
667
            html_content,
668
            "tutornyuengineeringverify@gmail.com",
669
            [tutor_email],
670
        )
UNCOV
671
        email.content_subtype = "html"
1✔
UNCOV
672
        email.send()
1✔
673

UNCOV
674
        return HttpResponseRedirect(reverse("Dashboard:admin_dashboard"))
1✔
675

676
    return render(request, "Dashboard/admin_dashboard.html")
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc