예제 #1
0
def candidate_submission_upload_view(request: HttpRequest,
                                     submission_type: str) -> HttpResponse:
    submission_type_ = getattr(SubmissionTypes, submission_type)

    file = request.FILES["file"]
    now_str = datetime.now().strftime("%m_%d_%Y__%H_%M_%S")
    upload_key = f"{submission_type_.uname}/{request.user.uuid}/{file.name}@{now_str}"
    interface.storage_client.save(upload_key, file)

    submission_result = interface.grader_client.grade(
        assignment_id=submission_type_.uname,
        user_uuid=request.user.uuid,
        submission_s3_bucket=settings.STORAGE_BUCKET,
        submission_s3_key=upload_key,
    )

    application = Application.objects.get(user=request.user)
    sub = Submission(file_location=upload_key,
                     score=submission_result.score,
                     feedback_location=submission_result.feedback_s3_key)
    Domain.add_submission(application, submission_type_, sub)

    if submission_type == SubmissionTypes.coding_test.uname:
        return HttpResponseRedirect("/candidate/coding-test")
    return HttpResponseRedirect(f"/candidate/slu/{submission_type}")
예제 #2
0
    def test_add_submission_error_close_applications(self) -> None:
        interface.feature_flag_client.set_applications_opening_date(
            datetime.now() - timedelta(hours=5))
        interface.feature_flag_client.set_applications_closing_date(
            datetime.now() - timedelta(hours=2))
        a = Application.objects.create(user=User.objects.create(
            email="*****@*****.**"))

        with self.assertRaises(DomainException):
            Domain.add_submission(a, SubmissionTypes.coding_test, Submission())
        with self.assertRaises(DomainException):
            Domain.add_submission(a, SubmissionTypes.slu01, Submission())
예제 #3
0
    def handle(self, *args, **options) -> None:
        bucket = options["bucket"]
        directory = options["dir"]

        if bucket is None and directory is None:
            raise CommandError("you need to specify --bucket or --dir")

        expected_keys = {
            # "key": "description",
            "public-assets/ldssa_logo.png":
            "this is LDSA Logo, displayed in the login/signup pages",
            Domain.get_candidate_release_zip("coding_test"):
            "this is the candidate nbgrader `coding_test` release, the one candidates can donwload",
            Domain.get_candidate_release_zip("slu01"):
            "this is the candidate nbgrader `slu01` release, the one candidates can donwload",
            Domain.get_candidate_release_zip("slu02"):
            "this is the candidate nbgrader `slu02` release, the one candidates can donwload",
            Domain.get_candidate_release_zip("slu03"):
            "this is the candidate nbgrader `slu03` release, the one candidates can donwload",
        }

        fail = False
        if bucket is not None:
            s3 = boto3.client("s3")

            for k, d in expected_keys.items():
                try:
                    s3.head_object(Bucket=bucket, Key=k)
                    self.stdout.write(f"{k} -> " +
                                      self.style.SUCCESS("found."))
                except ClientError:
                    self.stdout.write(f"{k} -> " +
                                      self.style.ERROR("not found."))
                    fail = True

        elif directory is not None:
            for k, d in expected_keys.items():
                if os.path.isfile(os.path.join(directory, k)):
                    self.stdout.write(f"{k} -> " +
                                      self.style.SUCCESS("found."))
                else:
                    self.stdout.write(f"{k} -> " +
                                      self.style.ERROR("not found."))
                    self.stdout.write(self.style.WARNING(d))
                    fail = True
        else:
            raise Exception

        if fail:
            raise CommandError("At least one key is missing...")
        else:
            self.stdout.write(self.style.SUCCESS("All Good!"))
예제 #4
0
    def test_add_submission_error_not_started_coding_test(self) -> None:
        interface.feature_flag_client.set_applications_opening_date(
            datetime.now() - timedelta(minutes=30))
        interface.feature_flag_client.set_applications_closing_date(
            datetime.now() + timedelta(minutes=30))
        a = Application.objects.create(user=User.objects.create(
            email="*****@*****.**"))

        a.coding_test_started_at = None
        a.save()
        with self.assertRaises(DomainException):
            Domain.add_submission(a, SubmissionTypes.coding_test, Submission())
        self.assertEqual(a.submissions.count(), 0)
예제 #5
0
    def test_add_submission_error_max_submissions(self) -> None:
        interface.feature_flag_client.set_applications_opening_date(
            datetime.now() - timedelta(minutes=30))
        interface.feature_flag_client.set_applications_closing_date(
            datetime.now() + timedelta(minutes=30))
        a = Application.objects.create(user=User.objects.create(
            email="*****@*****.**"))

        for _ in range(0, 251):
            Submission.objects.create(
                application=a,
                submission_type=SubmissionTypes.coding_test.uname)
            Submission.objects.create(
                application=a, submission_type=SubmissionTypes.slu01.uname)
            Submission.objects.create(
                application=a, submission_type=SubmissionTypes.slu02.uname)
            Submission.objects.create(
                application=a, submission_type=SubmissionTypes.slu03.uname)

        a.coding_test_started_at = datetime.now()
        a.save()

        with self.assertRaises(DomainException):
            Domain.add_submission(a, SubmissionTypes.coding_test, Submission())
        with self.assertRaises(DomainException):
            Domain.add_submission(a, SubmissionTypes.slu01, Submission())
        with self.assertRaises(DomainException):
            Domain.add_submission(a, SubmissionTypes.slu02, Submission())
        with self.assertRaises(DomainException):
            Domain.add_submission(a, SubmissionTypes.slu03, Submission())

        self.assertEqual(a.submissions.count(), 251 * 4)
예제 #6
0
    def get_candidate_state(candidate: User) -> CandidateState:
        state = {}

        state["confirmed_email"] = candidate.email_confirmed

        state["accepted_coc"] = candidate.code_of_conduct_accepted

        state[
            "decided_scholarship"] = candidate.applying_for_scholarship is not None
        state["applying_for_scholarship"] = candidate.applying_for_scholarship

        try:
            _ = candidate.profile
            state["created_profile"] = True
        except Profile.DoesNotExist:
            state["created_profile"] = False

        application, _ = Application.objects.get_or_create(user=candidate)
        status = ApplicationsDomain.get_application_detailed_status(
            application)
        state["application_status"] = status["application"]
        state["coding_test_status"] = status[SubmissionTypes.coding_test.uname]
        state["slu01_status"] = status[SubmissionTypes.slu01.uname]
        state["slu02_status"] = status[SubmissionTypes.slu02.uname]
        state["slu03_status"] = status[SubmissionTypes.slu03.uname]

        try:
            state["selection_status"] = SelectionDomain.get_status(
                candidate.selection)

        except Selection.DoesNotExist:
            state["selection_status"] = None

        return CandidateState(**state)
예제 #7
0
    def test_get_close_date(self) -> None:
        a = Application.objects.create(user=User.objects.create(
            email="*****@*****.**"))

        expected_domain_buffer_delta = timedelta(minutes=2)

        self.assertEqual(Domain.get_end_date(a, SubmissionTypes.coding_test),
                         self.acd)
        self.assertEqual(
            Domain.get_end_date(a,
                                SubmissionTypes.coding_test,
                                apply_buffer=True),
            self.acd + expected_domain_buffer_delta,
        )

        self.assertEqual(Domain.get_end_date(a, SubmissionTypes.slu01),
                         self.acd)
        self.assertEqual(
            Domain.get_end_date(a, SubmissionTypes.slu01, apply_buffer=True),
            self.acd + expected_domain_buffer_delta)

        self.assertEqual(Domain.get_end_date(a, SubmissionTypes.slu02),
                         self.acd)
        self.assertEqual(
            Domain.get_end_date(a, SubmissionTypes.slu02, apply_buffer=True),
            self.acd + expected_domain_buffer_delta)

        self.assertEqual(Domain.get_end_date(a, SubmissionTypes.slu03),
                         self.acd)
        self.assertEqual(
            Domain.get_end_date(a, SubmissionTypes.slu03, apply_buffer=True),
            self.acd + expected_domain_buffer_delta)

        coding_test_delta = timedelta(
            minutes=interface.feature_flag_client.get_coding_test_duration())
        dt_now = datetime.now()
        a.coding_test_started_at = dt_now
        a.save()
        self.assertEqual(Domain.get_end_date(a, SubmissionTypes.coding_test),
                         dt_now + coding_test_delta)
        self.assertEqual(
            Domain.get_end_date(a,
                                SubmissionTypes.coding_test,
                                apply_buffer=True),
            dt_now + coding_test_delta + expected_domain_buffer_delta,
        )
예제 #8
0
    def test_get_start_date(self) -> None:
        a = Application.objects.create(user=User.objects.create(
            email="*****@*****.**"))

        self.assertEqual(Domain.get_start_date(a, SubmissionTypes.coding_test),
                         None)
        self.assertEqual(Domain.get_start_date(a, SubmissionTypes.slu01),
                         self.aod)
        self.assertEqual(Domain.get_start_date(a, SubmissionTypes.slu02),
                         self.aod)
        self.assertEqual(Domain.get_start_date(a, SubmissionTypes.slu03),
                         self.aod)

        dt_now = datetime.now()
        a.coding_test_started_at = dt_now
        a.save()
        self.assertEqual(Domain.get_start_date(a, SubmissionTypes.coding_test),
                         dt_now)
예제 #9
0
파일: domain.py 프로젝트: LDSSA/adm-portal
    def trigger_applications_are_over() -> None:
        if datetime.now() < interface.feature_flag_client.get_applications_closing_date():
            logger.error("trying to trigger `applications over` event but applications are still open")
            raise EventsException("Can't trigger `applications over` event")

        sent_count = 0
        q = ApplicationDomainQueries.all()
        for a in q:
            try:
                ApplicationDomain.application_over(a)
                sent_count += 1
            except ApplicationDomainException:
                pass  # means that email was already sent

            a.refresh_from_db()
            if a.application_over_email_sent == "passed":
                SelectionDomain.create(a.user)

        logger.info(f"sent {sent_count} `application_over` emails")
예제 #10
0
    def test_add_submission(self) -> None:
        interface.feature_flag_client.set_applications_opening_date(
            datetime.now() - timedelta(minutes=30))
        interface.feature_flag_client.set_applications_closing_date(
            datetime.now() + timedelta(minutes=30))
        a = Application.objects.create(user=User.objects.create(
            email="*****@*****.**"))

        a.coding_test_started_at = datetime.now()
        a.save()

        Domain.add_submission(a, SubmissionTypes.coding_test, Submission())
        Domain.add_submission(a, SubmissionTypes.slu01, Submission())
        Domain.add_submission(a, SubmissionTypes.slu02, Submission())
        Domain.add_submission(a, SubmissionTypes.slu03, Submission())
        self.assertEqual(a.submissions.count(), 4)

        interface.feature_flag_client.set_applications_closing_date(
            datetime.now() - timedelta(minutes=30))
        # will work because end-date will be based on start_end + duration, not on the ff.closing_date
        Domain.add_submission(a, SubmissionTypes.coding_test, Submission())
        self.assertEqual(a.submissions.count(), 5)
예제 #11
0
    def test_has_positive_score(self) -> None:
        target_app = Application.objects.create(user=User.objects.create(
            email="*****@*****.**"))
        other_app = Application.objects.create(user=User.objects.create(
            email="*****@*****.**"))
        Submission.objects.create(
            application=target_app,
            score=10,
            submission_type=SubmissionTypes.coding_test.uname)
        Submission.objects.create(
            application=target_app,
            score=89,
            submission_type=SubmissionTypes.coding_test.uname)

        Submission.objects.create(application=target_app,
                                  score=15,
                                  submission_type=SubmissionTypes.slu01.uname)

        Submission.objects.create(application=target_app,
                                  score=14,
                                  submission_type=SubmissionTypes.slu03.uname)
        Submission.objects.create(application=target_app,
                                  score=5,
                                  submission_type=SubmissionTypes.slu03.uname)
        Submission.objects.create(application=target_app,
                                  score=19,
                                  submission_type=SubmissionTypes.slu03.uname)

        self.assertEqual(
            Domain.has_positive_score(target_app, SubmissionTypes.coding_test),
            True)
        self.assertEqual(
            Domain.has_positive_score(target_app, SubmissionTypes.slu01),
            False)
        self.assertEqual(
            Domain.has_positive_score(target_app, SubmissionTypes.slu02),
            False)
        self.assertEqual(
            Domain.has_positive_score(target_app, SubmissionTypes.slu03), True)

        self.assertEqual(
            Domain.has_positive_score(other_app, SubmissionTypes.coding_test),
            False)
        self.assertEqual(
            Domain.has_positive_score(other_app, SubmissionTypes.slu01), False)
        self.assertEqual(
            Domain.has_positive_score(other_app, SubmissionTypes.slu02), False)
        self.assertEqual(
            Domain.has_positive_score(other_app, SubmissionTypes.slu03), False)
예제 #12
0
def candidate_assignment_download_view(request: HttpRequest) -> HttpResponse:
    try:
        assignment_id = request.GET["assignment_id"]
    except Exception:
        raise Http404

    application = Application.objects.get(user=request.user)
    if assignment_id == SubmissionTypes.coding_test.uname and application.coding_test_started_at is None:
        raise Http404

    key = Domain.get_candidate_release_zip(assignment_id)
    url = interface.storage_client.get_attachment_url(
        key, content_type="application/zip")
    return HttpResponseRedirect(url)
예제 #13
0
    def test_get_best_score(self) -> None:
        target_app = Application.objects.create(user=User.objects.create(
            email="*****@*****.**"))
        other_app = Application.objects.create(user=User.objects.create(
            email="*****@*****.**"))
        Submission.objects.create(
            application=target_app,
            score=10,
            submission_type=SubmissionTypes.coding_test.uname)
        Submission.objects.create(
            application=target_app,
            score=89,
            submission_type=SubmissionTypes.coding_test.uname)

        Submission.objects.create(application=target_app,
                                  score=73,
                                  submission_type=SubmissionTypes.slu01.uname)

        Submission.objects.create(application=target_app,
                                  score=71,
                                  submission_type=SubmissionTypes.slu03.uname)
        Submission.objects.create(application=target_app,
                                  score=21,
                                  submission_type=SubmissionTypes.slu03.uname)
        Submission.objects.create(application=target_app,
                                  score=92,
                                  submission_type=SubmissionTypes.slu03.uname)

        self.assertEqual(
            Domain.get_best_score(target_app, SubmissionTypes.coding_test), 89)
        self.assertEqual(
            Domain.get_best_score(target_app, SubmissionTypes.slu01), 73)
        self.assertEqual(
            Domain.get_best_score(target_app, SubmissionTypes.slu02), None)
        self.assertEqual(
            Domain.get_best_score(target_app, SubmissionTypes.slu03), 92)

        self.assertEqual(
            Domain.get_best_score(other_app, SubmissionTypes.coding_test),
            None)
        self.assertEqual(
            Domain.get_best_score(other_app, SubmissionTypes.slu01), None)
        self.assertEqual(
            Domain.get_best_score(other_app, SubmissionTypes.slu02), None)
        self.assertEqual(
            Domain.get_best_score(other_app, SubmissionTypes.slu03), None)
예제 #14
0
def submission_view_ctx(application: Application,
                        submission_type: SubmissionType) -> Dict[str, Any]:
    return {
        "submission_type":
        submission_type,
        "status":
        Domain.get_sub_type_status(application, submission_type).name,
        "submissions_closes_at":
        Domain.get_end_date(application,
                            submission_type).strftime("%Y-%m-%d %H:%M"),
        "best_score":
        Domain.get_best_score(application, submission_type),
        "download_enabled":
        Domain.can_add_submission(application, submission_type),
        "upload_enabled":
        Domain.can_add_submission(application, submission_type),
        "submissions":
        Submission.objects.filter(
            application=application,
            submission_type=submission_type.uname).order_by("-updated_at"),
        "coding_test_started_at_ms":
        int(application.coding_test_started_at.timestamp() *
            1000) if application.coding_test_started_at is not None else None,
    }
예제 #15
0
def staff_candidate_view(request: HttpRequest, user_id: int) -> HttpResponse:
    try:
        user = User.objects.filter(is_staff=False).filter(is_admin=False).get(
            id=user_id)
    except User.DoesNotExist:
        raise Http404

    try:
        application = user.application
        total_submissions = Submission.objects.filter(
            application=application).count()
        application_best_scores = {
            SubmissionTypes.coding_test.uname:
            ApplicationDomain.get_best_score(application,
                                             SubmissionTypes.coding_test),
            SubmissionTypes.slu01.uname:
            ApplicationDomain.get_best_score(application,
                                             SubmissionTypes.slu01),
            SubmissionTypes.slu02.uname:
            ApplicationDomain.get_best_score(application,
                                             SubmissionTypes.slu02),
            SubmissionTypes.slu03.uname:
            ApplicationDomain.get_best_score(application,
                                             SubmissionTypes.slu03),
        }
    except Application.DoesNotExist:
        total_submissions = 0
        application_best_scores = {}

    ctx = {
        "user": user,
        "total_submissions": total_submissions,
        "application_best_scores": application_best_scores
    }
    template = loader.get_template("./staff_templates/candidate.html")
    return HttpResponse(template.render(ctx, request))
예제 #16
0
    def test_get_status(self) -> None:
        a = Application.objects.create(user=User.objects.create(
            email="*****@*****.**"))

        interface.feature_flag_client.set_applications_opening_date(
            datetime.now() + timedelta(minutes=5))
        self.assertEqual(
            Domain.get_sub_type_status(a, SubmissionTypes.coding_test),
            SubmissionStatus.not_started)
        self.assertEqual(Domain.get_sub_type_status(a, SubmissionTypes.slu01),
                         SubmissionStatus.not_started)
        self.assertEqual(Domain.get_sub_type_status(a, SubmissionTypes.slu02),
                         SubmissionStatus.not_started)
        self.assertEqual(Domain.get_sub_type_status(a, SubmissionTypes.slu03),
                         SubmissionStatus.not_started)
        self.assertEqual(Domain.get_application_status(a),
                         ApplicationStatus.not_started)

        interface.feature_flag_client.set_applications_opening_date(
            datetime.now() - timedelta(minutes=5))
        interface.feature_flag_client.set_applications_closing_date(
            datetime.now() + timedelta(minutes=5))
        self.assertEqual(
            Domain.get_sub_type_status(a, SubmissionTypes.coding_test),
            SubmissionStatus.not_started)
        self.assertEqual(Domain.get_sub_type_status(a, SubmissionTypes.slu01),
                         SubmissionStatus.ongoing)
        self.assertEqual(Domain.get_sub_type_status(a, SubmissionTypes.slu02),
                         SubmissionStatus.ongoing)
        self.assertEqual(Domain.get_sub_type_status(a, SubmissionTypes.slu03),
                         SubmissionStatus.ongoing)
        self.assertEqual(Domain.get_application_status(a),
                         ApplicationStatus.ongoing)

        Submission.objects.create(application=a,
                                  score=99,
                                  submission_type=SubmissionTypes.slu01.uname)
        self.assertEqual(Domain.get_sub_type_status(a, SubmissionTypes.slu01),
                         SubmissionStatus.passed)
        self.assertEqual(Domain.get_application_status(a),
                         ApplicationStatus.ongoing)

        Submission.objects.create(
            application=a,
            score=99,
            submission_type=SubmissionTypes.coding_test.uname)
        Submission.objects.create(application=a,
                                  score=99,
                                  submission_type=SubmissionTypes.slu01.uname)
        slu02_sub = Submission.objects.create(
            application=a,
            score=99,
            submission_type=SubmissionTypes.slu02.uname)
        Submission.objects.create(application=a,
                                  score=99,
                                  submission_type=SubmissionTypes.slu03.uname)

        self.assertEqual(
            Domain.get_sub_type_status(a, SubmissionTypes.coding_test),
            SubmissionStatus.passed)
        self.assertEqual(Domain.get_sub_type_status(a, SubmissionTypes.slu01),
                         SubmissionStatus.passed)
        self.assertEqual(Domain.get_sub_type_status(a, SubmissionTypes.slu02),
                         SubmissionStatus.passed)
        self.assertEqual(Domain.get_sub_type_status(a, SubmissionTypes.slu02),
                         SubmissionStatus.passed)
        self.assertEqual(Domain.get_application_status(a),
                         ApplicationStatus.passed)

        slu02_sub.delete()
        interface.feature_flag_client.set_applications_closing_date(
            datetime.now() - timedelta(minutes=5))
        a.save()
        self.assertEqual(Domain.get_sub_type_status(a, SubmissionTypes.slu02),
                         SubmissionStatus.failed)
        self.assertEqual(Domain.get_application_status(a),
                         ApplicationStatus.failed)
예제 #17
0
def staff_applications_view(request: HttpRequest) -> HttpResponse:
    query = Application.objects.all().order_by("user__email")

    filter_by_application_status = request.GET.get("application_status")

    applications = []
    count_by_type: Dict[Any, Any] = {
        "application": {
            s: 0
            for s in [
                Status.not_started.name, Status.ongoing.name,
                Status.passed.name, Status.failed.name
            ]
        },
        SubmissionTypes.coding_test.uname: {
            s: 0
            for s in [
                Status.not_started.name, Status.ongoing.name,
                Status.passed.name, Status.failed.name
            ]
        },
        SubmissionTypes.slu01.uname: {
            s: 0
            for s in [
                Status.not_started.name, Status.ongoing.name,
                Status.passed.name, Status.failed.name
            ]
        },
        SubmissionTypes.slu02.uname: {
            s: 0
            for s in [
                Status.not_started.name, Status.ongoing.name,
                Status.passed.name, Status.failed.name
            ]
        },
        SubmissionTypes.slu03.uname: {
            s: 0
            for s in [
                Status.not_started.name, Status.ongoing.name,
                Status.passed.name, Status.failed.name
            ]
        },
    }
    for a in query:
        application_det_status = Domain.get_application_detailed_status(a)
        for sub_type, sub_status in application_det_status.items():
            count_by_type[sub_type][sub_status.name] += 1

        if (filter_by_application_status is not None
                and application_det_status["application"].name !=
                filter_by_application_status):
            continue

        applications.append({
            "ref":
            a,
            "status_list": [
                application_det_status["application"],
                *[
                    Domain.get_sub_type_status(a, sub_type)
                    for sub_type in SubmissionTypes.all
                ],
            ],
        })

    status_enum = {
        s.name: {
            "name": s.name,
            "value": s.value,
            "count": count_by_type["application"][s.name]
        }
        for s in Status
    }
    ctx = {
        "status_enum": status_enum,
        "applications": applications,
        "summary": count_by_type
    }

    template = loader.get_template("./staff_templates/applications.html")
    return HttpResponse(template.render(ctx, request))