示例#1
0
    def test_accept_after_cancel(self, *args, **kwargs):
        # A canceled job application is not linked to an approval
        # unless the job seeker has an accepted job application.
        create_test_cities(["54", "57"], num_per_department=2)
        city = City.objects.first()
        job_seeker = JobSeekerWithAddressFactory(city=city.name)
        job_application = JobApplicationSentByJobSeekerFactory(
            state=JobApplicationWorkflow.STATE_CANCELLED, job_seeker=job_seeker
        )
        siae_user = job_application.to_siae.members.first()
        self.client.login(username=siae_user.email, password=DEFAULT_PASSWORD)

        url_accept = reverse("apply:accept", kwargs={"job_application_id": job_application.pk})
        hiring_start_at = timezone.localdate()
        hiring_end_at = Approval.get_default_end_date(hiring_start_at)
        post_data = {
            "hiring_start_at": hiring_start_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "hiring_end_at": hiring_end_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "pole_emploi_id": job_application.job_seeker.pole_emploi_id,
            "answer": "",
            "address_line_1": job_seeker.address_line_1,
            "post_code": job_seeker.post_code,
            "city": city.name,
            "city_slug": city.slug,
        }
        response = self.client.post(url_accept, data=post_data)

        next_url = reverse("apply:details_for_siae", kwargs={"job_application_id": job_application.pk})
        self.assertRedirects(response, next_url)

        job_application.refresh_from_db()
        self.assertEqual(job_seeker.approvals.count(), 1)
        approval = job_seeker.approvals.first()
        self.assertEqual(approval.start_at, job_application.hiring_start_at)
        self.assertTrue(job_application.state.is_accepted)
示例#2
0
    def test_fecth_city(self):
        """
        The city name should be fetched from the slug.
        """

        create_test_cities(["67"], num_per_department=1)
        city = City.objects.first()

        form_data = {
            "city_slug": city.slug,
            "city": "",
            "address_line_1": "11 rue des pixels cassés",
            "address_line_2": "",
            "post_code": "67000",
        }

        form = OptionalAddressFormMixin(data=form_data)

        with self.assertNumQueries(1):
            self.assertTrue(form.is_valid())
            expected_cleaned_data = {
                "city_slug": city.slug,
                "city": city.name,
                "address_line_1": form_data["address_line_1"],
                "address_line_2": form_data["address_line_2"],
                "post_code": form_data["post_code"],
            }
            self.assertDictEqual(form.cleaned_data, expected_cleaned_data)
示例#3
0
    def test_accept_with_manual_approval_delivery(self, *args, **kwargs):
        """
        Test the "manual approval delivery mode" path of the view.
        """
        create_test_cities(["57"], num_per_department=1)
        city = City.objects.first()

        job_application = JobApplicationSentByJobSeekerFactory(
            state=JobApplicationWorkflow.STATE_PROCESSING,
            # The state of the 2 `pole_emploi_*` fields will trigger a manual delivery.
            job_seeker__pole_emploi_id="",
            job_seeker__lack_of_pole_emploi_id_reason=User.REASON_FORGOTTEN,
        )

        siae_user = job_application.to_siae.members.first()
        self.client.login(username=siae_user.email, password=DEFAULT_PASSWORD)

        url = reverse("apply:accept", kwargs={"job_application_id": job_application.pk})
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)

        post_data = {
            # Data for `JobSeekerPoleEmploiStatusForm`.
            "pole_emploi_id": job_application.job_seeker.pole_emploi_id,
            "lack_of_pole_emploi_id_reason": job_application.job_seeker.lack_of_pole_emploi_id_reason,
            # Data for `UserAddressForm`.
            "address_line_1": "11 rue des Lilas",
            "post_code": "57000",
            "city": city.name,
            "city_slug": city.slug,
            # Data for `AcceptForm`.
            "hiring_start_at": timezone.localdate().strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "hiring_end_at": (timezone.localdate() + relativedelta(days=360)).strftime(
                DuetDatePickerWidget.INPUT_DATE_FORMAT
            ),
            "answer": "",
        }
        response = self.client.post(url, data=post_data)
        next_url = reverse("apply:details_for_siae", kwargs={"job_application_id": job_application.pk})
        self.assertRedirects(response, next_url)

        job_application.refresh_from_db()
        self.assertEqual(job_application.approval_delivery_mode, job_application.APPROVAL_DELIVERY_MODE_MANUAL)
示例#4
0
文件: tests.py 项目: NathHense/itou
    def test_autocomplete(self):

        create_test_cities(["67"], num_per_department=10)

        url = reverse("autocomplete:cities")

        response = self.client.get(url, {"term": "alte"})
        self.assertEqual(response.status_code, 200)
        expected = [
            {
                "value": "Altenheim (67)",
                "slug": "altenheim-67"
            },
            {
                "value": "Altorf (67)",
                "slug": "altorf-67"
            },
            {
                "value": "Alteckendorf (67)",
                "slug": "alteckendorf-67"
            },
            {
                "value": "Albé (67)",
                "slug": "albe-67"
            },
            {
                "value": "Altwiller (67)",
                "slug": "altwiller-67"
            },
        ]
        self.assertEqual(json.loads(response.content), expected)

        response = self.client.get(url, {"term": "    "})
        self.assertEqual(response.status_code, 200)
        expected = b"[]"
        self.assertEqual(response.content, expected)

        response = self.client.get(url, {"term": "paris"})
        self.assertEqual(response.status_code, 200)
        expected = b"[]"
        self.assertEqual(response.content, expected)
示例#5
0
    def test_with_instance(self):
        """
        If an instance is passed, `city` and `city_slug` should be prepopulated.
        """

        create_test_cities(["57"], num_per_department=1)

        city = City.objects.first()

        user = JobSeekerFactory()
        user.address_line_1 = "11 rue des pixels cassés"
        user.department = city.department
        user.post_code = city.post_codes[0]
        user.city = city.name

        with self.assertNumQueries(1):

            form = DummyUserModelForm(data={}, instance=user)

            self.assertEqual(form.initial["city_slug"], city.slug)
            self.assertEqual(form.initial["city"], city.name)
示例#6
0
 def setUp(self):
     create_test_cities(["57"], num_per_department=1)
     self.city = City.objects.first()
示例#7
0
 def setUp(self):
     create_test_cities(["67"], num_per_department=10)
示例#8
0
 def test_create_test_cities(self):
     create_test_cities(["62", "67", "93"], num_per_department=10)
     self.assertEqual(City.objects.count(), 30)
     self.assertEqual(City.objects.filter(department="62").count(), 10)
     self.assertEqual(City.objects.filter(department="67").count(), 10)
     self.assertEqual(City.objects.filter(department="93").count(), 10)
示例#9
0
    def test_accept_and_update_hiring_start_date_of_two_job_applications(self, *args, **kwargs):
        create_test_cities(["54", "57"], num_per_department=2)
        city = City.objects.first()
        job_seeker = JobSeekerWithAddressFactory()
        base_for_post_data = {
            "address_line_1": job_seeker.address_line_1,
            "post_code": job_seeker.post_code,
            "city": city.name,
            "city_slug": city.slug,
            "pole_emploi_id": job_seeker.pole_emploi_id,
            "answer": "",
        }
        hiring_start_at = timezone.localdate() + relativedelta(months=2)
        hiring_end_at = hiring_start_at + relativedelta(months=2)
        approval_default_ending = Approval.get_default_end_date(start_at=hiring_start_at)

        # Send 3 job applications to 3 different structures
        job_application = JobApplicationSentByJobSeekerFactory(
            job_seeker=job_seeker, state=JobApplicationWorkflow.STATE_PROCESSING
        )
        job_app_starting_earlier = JobApplicationSentByJobSeekerFactory(
            job_seeker=job_seeker, state=JobApplicationWorkflow.STATE_PROCESSING
        )
        job_app_starting_later = JobApplicationSentByJobSeekerFactory(
            job_seeker=job_seeker, state=JobApplicationWorkflow.STATE_PROCESSING
        )

        # SIAE 1 logs in and accepts the first job application.
        # The delivered approval should start at the same time as the contract.
        user = job_application.to_siae.members.first()
        self.client.login(username=user.email, password=DEFAULT_PASSWORD)
        url_accept = reverse("apply:accept", kwargs={"job_application_id": job_application.pk})
        post_data = {
            "hiring_start_at": hiring_start_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "hiring_end_at": hiring_end_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            **base_for_post_data,
        }
        response = self.client.post(url_accept, data=post_data)
        self.assertEqual(response.status_code, 302)

        # First job application has been accepted.
        # All other job applications are obsolete.
        job_application.refresh_from_db()
        self.assertTrue(job_application.state.is_accepted)
        self.assertEqual(job_application.approval.start_at, job_application.hiring_start_at)
        self.assertEqual(job_application.approval.end_at, approval_default_ending)
        self.client.logout()

        # SIAE 2 accepts the second job application
        # but its contract starts earlier than the approval delivered the first time.
        # Approval's starting date should be brought forward.
        user = job_app_starting_earlier.to_siae.members.first()
        hiring_start_at = hiring_start_at - relativedelta(months=1)
        hiring_end_at = hiring_start_at + relativedelta(months=2)
        approval_default_ending = Approval.get_default_end_date(start_at=hiring_start_at)
        job_app_starting_earlier.refresh_from_db()
        self.assertTrue(job_app_starting_earlier.state.is_obsolete)

        self.client.login(username=user.email, password=DEFAULT_PASSWORD)
        url_accept = reverse("apply:accept", kwargs={"job_application_id": job_app_starting_earlier.pk})
        post_data = {
            "hiring_start_at": hiring_start_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "hiring_end_at": hiring_end_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            **base_for_post_data,
        }
        response = self.client.post(url_accept, data=post_data)
        job_app_starting_earlier.refresh_from_db()

        # Second job application has been accepted.
        # The job seeker has now two part-time jobs at the same time.
        self.assertEqual(response.status_code, 302)
        self.assertTrue(job_app_starting_earlier.state.is_accepted)
        self.assertEqual(job_app_starting_earlier.approval.start_at, job_app_starting_earlier.hiring_start_at)
        self.assertEqual(job_app_starting_earlier.approval.end_at, approval_default_ending)
        self.client.logout()

        # SIAE 3 accepts the third job application.
        # Its contract starts later than the corresponding approval.
        # Approval's starting date should not be updated.
        user = job_app_starting_later.to_siae.members.first()
        hiring_start_at = hiring_start_at + relativedelta(months=6)
        hiring_end_at = hiring_start_at + relativedelta(months=2)
        job_app_starting_later.refresh_from_db()
        self.assertTrue(job_app_starting_later.state.is_obsolete)

        self.client.login(username=user.email, password=DEFAULT_PASSWORD)
        url_accept = reverse("apply:accept", kwargs={"job_application_id": job_app_starting_later.pk})
        post_data = {
            "hiring_start_at": hiring_start_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "hiring_end_at": hiring_end_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            **base_for_post_data,
        }
        response = self.client.post(url_accept, data=post_data)
        job_app_starting_later.refresh_from_db()

        # Third job application has been accepted.
        # The job seeker has now three part-time jobs at the same time.
        self.assertEqual(response.status_code, 302)
        self.assertTrue(job_app_starting_later.state.is_accepted)
        self.assertEqual(job_app_starting_later.approval.start_at, job_app_starting_earlier.hiring_start_at)
示例#10
0
    def test_accept_with_active_suspension(self, *args, **kwargs):
        """Test the `accept` transition with active suspension for active user"""
        create_test_cities(["54", "57"], num_per_department=2)
        city = City.objects.first()
        today = timezone.localdate()
        # the old job of job seeker
        job_seeker_user = JobSeekerWithAddressFactory()
        old_job_application = JobApplicationWithApprovalFactory(
            state=JobApplicationWorkflow.STATE_ACCEPTED,
            job_seeker=job_seeker_user,
            # Ensure that the old_job_application cannot be canceled.
            hiring_start_at=today - relativedelta(days=100),
        )
        # create suspension for the job seeker
        approval_job_seeker = old_job_application.approval
        siae_user = old_job_application.to_siae.members.first()
        susension_start_at = today
        suspension_end_at = today + relativedelta(days=50)

        SuspensionFactory(
            approval=approval_job_seeker,
            start_at=susension_start_at,
            end_at=suspension_end_at,
            created_by=siae_user,
            reason=Suspension.Reason.BROKEN_CONTRACT.value,
        )

        # Now, another Siae wants to hire the job seeker
        other_siae = SiaeWithMembershipFactory()
        job_application = JobApplicationSentByJobSeekerFactory(
            approval=approval_job_seeker,
            state=JobApplicationWorkflow.STATE_PROCESSING,
            job_seeker=job_seeker_user,
            to_siae=other_siae,
        )
        other_siae_user = job_application.to_siae.members.first()

        # login with other siae
        self.client.login(username=other_siae_user.email, password=DEFAULT_PASSWORD)
        url = reverse("apply:accept", kwargs={"job_application_id": job_application.pk})

        hiring_start_at = today + relativedelta(days=20)
        hiring_end_at = Approval.get_default_end_date(hiring_start_at)

        post_data = {
            # Data for `JobSeekerPoleEmploiStatusForm`.
            "pole_emploi_id": job_application.job_seeker.pole_emploi_id,
            # Data for `AcceptForm`.
            "hiring_start_at": hiring_start_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "hiring_end_at": hiring_end_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "answer": "",
            "address_line_1": job_seeker_user.address_line_1,
            "post_code": job_seeker_user.post_code,
            "city": city.name,
            "city_slug": city.slug,
        }
        response = self.client.post(url, data=post_data)
        self.assertEqual(response.status_code, 302)
        get_job_application = JobApplication.objects.get(pk=job_application.pk)
        g_suspension = get_job_application.approval.suspension_set.in_progress().last()

        # The end date of suspension is set to d-1 of hiring start day
        self.assertEqual(g_suspension.end_at, get_job_application.hiring_start_at - relativedelta(days=1))
        # Check if the duration of approval was updated correctly
        self.assertEqual(
            get_job_application.approval.end_at,
            approval_job_seeker.end_at + relativedelta(days=(g_suspension.end_at - g_suspension.start_at).days),
        )
示例#11
0
    def test_accept(self, *args, **kwargs):
        """Test the `accept` transition."""
        create_test_cities(["54", "57"], num_per_department=2)
        city = City.objects.first()
        today = timezone.localdate()

        job_seeker = JobSeekerWithAddressFactory(city=city.name)
        address = {
            "address_line_1": job_seeker.address_line_1,
            "post_code": job_seeker.post_code,
            "city": city.name,
            "city_slug": city.slug,
        }
        siae = SiaeWithMembershipFactory()
        siae_user = siae.members.first()

        for state in JobApplicationWorkflow.CAN_BE_ACCEPTED_STATES:
            job_application = JobApplicationSentByJobSeekerFactory(state=state, job_seeker=job_seeker, to_siae=siae)
            self.client.login(username=siae_user.email, password=DEFAULT_PASSWORD)

            url = reverse("apply:accept", kwargs={"job_application_id": job_application.pk})
            response = self.client.get(url)
            self.assertEqual(response.status_code, 200)

            # Good duration.
            hiring_start_at = today
            hiring_end_at = Approval.get_default_end_date(hiring_start_at)
            post_data = {
                # Data for `JobSeekerPoleEmploiStatusForm`.
                "pole_emploi_id": job_application.job_seeker.pole_emploi_id,
                # Data for `AcceptForm`.
                "hiring_start_at": hiring_start_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
                "hiring_end_at": hiring_end_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
                "answer": "",
                **address,
            }
            response = self.client.post(url, data=post_data)
            next_url = reverse("apply:details_for_siae", kwargs={"job_application_id": job_application.pk})
            self.assertRedirects(response, next_url)

            job_application = JobApplication.objects.get(pk=job_application.pk)
            self.assertEqual(job_application.hiring_start_at, hiring_start_at)
            self.assertEqual(job_application.hiring_end_at, hiring_end_at)
            self.assertTrue(job_application.state.is_accepted)

        ##############
        # Exceptions #
        ##############
        job_application = JobApplicationSentByJobSeekerFactory(state=state, job_seeker=job_seeker, to_siae=siae)
        url = reverse("apply:accept", kwargs={"job_application_id": job_application.pk})

        # Wrong dates.
        hiring_start_at = today
        hiring_end_at = Approval.get_default_end_date(hiring_start_at)
        # Force `hiring_start_at` in past.
        hiring_start_at = hiring_start_at - relativedelta(days=1)
        post_data = {
            "hiring_start_at": hiring_start_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "hiring_end_at": hiring_end_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "answer": "",
            **address,
        }
        response = self.client.post(url, data=post_data)
        self.assertFormError(response, "form_accept", "hiring_start_at", JobApplication.ERROR_START_IN_PAST)

        # Wrong dates: end < start.
        hiring_start_at = today
        hiring_end_at = hiring_start_at - relativedelta(days=1)
        post_data = {
            "hiring_start_at": hiring_start_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "hiring_end_at": hiring_end_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "answer": "",
            **address,
        }
        response = self.client.post(url, data=post_data)
        self.assertFormError(response, "form_accept", None, JobApplication.ERROR_END_IS_BEFORE_START)

        # No address provided.
        job_application = JobApplicationSentByJobSeekerFactory(
            state=JobApplicationWorkflow.STATE_PROCESSING, to_siae=siae
        )
        url = reverse("apply:accept", kwargs={"job_application_id": job_application.pk})

        hiring_start_at = today
        hiring_end_at = Approval.get_default_end_date(hiring_start_at)
        post_data = {
            # Data for `JobSeekerPoleEmploiStatusForm`.
            "pole_emploi_id": job_application.job_seeker.pole_emploi_id,
            # Data for `AcceptForm`.
            "hiring_start_at": hiring_start_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "hiring_end_at": hiring_end_at.strftime(DuetDatePickerWidget.INPUT_DATE_FORMAT),
            "answer": "",
        }
        response = self.client.post(url, data=post_data)
        self.assertFormError(response, "form_user_address", "address_line_1", "Ce champ est obligatoire.")
        self.assertFormError(response, "form_user_address", "city", "Ce champ est obligatoire.")
        self.assertFormError(response, "form_user_address", "post_code", "Ce champ est obligatoire.")
示例#12
0
    def test_accept(self):
        """Test the `accept` transition."""
        create_test_cities(["54", "57"], num_per_department=2)
        city = City.objects.first()

        job_seeker = JobSeekerWithAddressFactory(city=city.name)
        address = {
            "address_line_1": job_seeker.address_line_1,
            "post_code": job_seeker.post_code,
            "city_name": city.name,
            "city": city.slug,
        }
        job_application = JobApplicationSentByAuthorizedPrescriberOrganizationFactory(
            state=JobApplicationWorkflow.STATE_PROCESSING,
            job_seeker=job_seeker)
        self.assertTrue(job_application.state.is_processing)
        siae_user = job_application.to_siae.members.first()
        self.client.login(username=siae_user.email, password=DEFAULT_PASSWORD)

        url = reverse("apply:accept",
                      kwargs={"job_application_id": job_application.pk})
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)

        # Wrong dates: force `hiring_start_at` in past.
        hiring_start_at = datetime.date.today() - relativedelta(days=1)
        hiring_end_at = hiring_start_at + relativedelta(years=2)
        post_data = {
            "hiring_start_at": hiring_start_at.strftime("%d/%m/%Y"),
            "hiring_end_at": hiring_end_at.strftime("%d/%m/%Y"),
            "answer": "",
            **address,
        }
        response = self.client.post(url, data=post_data)
        self.assertFormError(response, "form_accept", "hiring_start_at",
                             JobApplication.ERROR_START_IN_PAST)

        # Wrong dates: end < start.
        hiring_start_at = datetime.date.today()
        hiring_end_at = hiring_start_at - relativedelta(days=1)
        post_data = {
            "hiring_start_at": hiring_start_at.strftime("%d/%m/%Y"),
            "hiring_end_at": hiring_end_at.strftime("%d/%m/%Y"),
            "answer": "",
            **address,
        }
        response = self.client.post(url, data=post_data)
        self.assertFormError(response, "form_accept", None,
                             JobApplication.ERROR_END_IS_BEFORE_START)

        # Duration too long.
        hiring_start_at = datetime.date.today()
        hiring_end_at = hiring_start_at + relativedelta(years=2, days=1)
        post_data = {
            "hiring_start_at": hiring_start_at.strftime("%d/%m/%Y"),
            "hiring_end_at": hiring_end_at.strftime("%d/%m/%Y"),
            "answer": "",
            **address,
        }
        response = self.client.post(url, data=post_data)
        self.assertFormError(response, "form_accept", None,
                             JobApplication.ERROR_DURATION_TOO_LONG)

        # Good duration.
        hiring_start_at = datetime.date.today()
        hiring_end_at = hiring_start_at + relativedelta(years=2)
        post_data = {
            # Data for `JobSeekerPoleEmploiStatusForm`.
            "pole_emploi_id": job_application.job_seeker.pole_emploi_id,
            # Data for `AcceptForm`.
            "hiring_start_at": hiring_start_at.strftime("%d/%m/%Y"),
            "hiring_end_at": hiring_end_at.strftime("%d/%m/%Y"),
            "answer": "",
            **address,
        }
        response = self.client.post(url, data=post_data)
        self.assertEqual(response.status_code, 302)

        next_url = reverse("apply:details_for_siae",
                           kwargs={"job_application_id": job_application.pk})
        self.assertEqual(response.url, next_url)

        job_application = JobApplication.objects.get(pk=job_application.pk)
        self.assertEqual(job_application.hiring_start_at, hiring_start_at)
        self.assertEqual(job_application.hiring_end_at, hiring_end_at)
        self.assertTrue(job_application.state.is_accepted)

        # No address provided
        job_application = JobApplicationSentByAuthorizedPrescriberOrganizationFactory(
            state=JobApplicationWorkflow.STATE_PROCESSING)
        hiring_start_at = datetime.date.today()
        hiring_end_at = hiring_start_at + relativedelta(years=2)
        post_data = {
            # Data for `JobSeekerPoleEmploiStatusForm`.
            "pole_emploi_id": job_application.job_seeker.pole_emploi_id,
            # Data for `AcceptForm`.
            "hiring_start_at": hiring_start_at.strftime("%d/%m/%Y"),
            "hiring_end_at": hiring_end_at.strftime("%d/%m/%Y"),
            "answer": "",
        }
        with self.assertRaises(KeyError):
            response = self.client.post(url, data=post_data)