Esempio n. 1
0
    def test_siae_multiple_memberships(self):

        siae1 = SiaeWithMembershipFactory()
        user = siae1.members.first()
        self.assertTrue(user.siaemembership_set.get(siae=siae1).is_siae_admin)

        siae2 = SiaeFactory()
        siae2.members.add(user)
        self.assertFalse(user.siaemembership_set.get(siae=siae2).is_siae_admin)

        siae3 = SiaeFactory()
        siae3.members.add(user)
        self.assertFalse(user.siaemembership_set.get(siae=siae3).is_siae_admin)

        factory = RequestFactory()
        request = factory.get("/")
        request.user = user
        middleware = SessionMiddleware()
        middleware.process_request(request)
        request.session[settings.ITOU_SESSION_CURRENT_SIAE_KEY] = siae3.pk
        request.session.save()

        with self.assertNumQueries(1):
            result = get_current_organization_and_perms(request)
            expected = {
                "current_prescriber_organization": None,
                "current_siae": siae3,
                "user_is_prescriber_org_admin": False,
                "user_is_siae_admin": False,
                "user_siae_set": [siae1, siae2, siae3],
            }
            self.assertDictEqual(expected, result)
Esempio n. 2
0
    def test_select_siae_form_errors(self):
        """
        Test SelectSiaeForm errors.
        """

        # Missing email and SIRET.
        post_data = {"kind": Siae.KIND_ACI}
        form = SelectSiaeForm(data=post_data)
        form.is_valid()
        expected_error = _(
            "Merci de renseigner l'e-mail utilisé par le référent technique ASP"
            " ou un numéro de SIRET connu de nos services."
        )
        self.assertIn(expected_error, form.errors["__all__"])

        # (email, kind) or (siret, kind) does not match any siae.
        post_data = {"email": "*****@*****.**", "siret": "12345678901234", "kind": Siae.KIND_ACI}
        form = SelectSiaeForm(data=post_data)
        form.is_valid()
        expected_error = _("Votre numéro de SIRET ou votre e-mail nous sont inconnus.")
        self.assertTrue(form.errors["__all__"][0].startswith(expected_error))

        # (email, kind) matches two siaes, (siret, kind) does not match any siae.
        user_email = "*****@*****.**"
        SiaeFactory.create_batch(2, kind=Siae.KIND_ACI, auth_email=user_email)
        post_data = {"email": user_email, "siret": "12345678901234", "kind": Siae.KIND_ACI}
        form = SelectSiaeForm(data=post_data)
        form.is_valid()
        expected_error = _("Votre e-mail est partagé par plusieurs structures")
        self.assertTrue(form.errors["__all__"][0].startswith(expected_error))
Esempio n. 3
0
    def test_district(self):
        city_slug = "paris-75"
        paris_city = City.objects.create(name="Paris",
                                         slug=city_slug,
                                         department="75",
                                         post_codes=["75001"],
                                         coords=Point(5, 23))
        siae_1 = SiaeFactory(department="75",
                             coords=paris_city.coords,
                             post_code="75001")
        SiaeFactory(department="75",
                    coords=paris_city.coords,
                    post_code="75002")

        # Filter on city
        response = self.client.get(self.url, {"city": city_slug})

        self.assertContains(
            response, "Employeurs solidaires à 25 km du centre de Paris (75)")
        self.assertContains(response, "<b>2</b> résultats")
        self.assertContains(response, "Arrondissements de Paris")

        # Filter on district
        response = self.client.get(self.url, {
            "city": city_slug,
            "districts_75": ["75001"]
        })
        self.assertContains(response, "<b>1</b> résultat")
        self.assertContains(response, siae_1.display_name)
Esempio n. 4
0
    def test_siae_multiple_memberships(self):

        siae1 = SiaeWithMembershipFactory()
        user = siae1.members.first()
        self.assertTrue(siae1.has_admin(user))

        siae2 = SiaeFactory()
        siae2.members.add(user)
        self.assertFalse(siae2.has_admin(user))

        request = self.go_to_dashboard(
            user=user, establishment_session_key=settings.ITOU_SESSION_CURRENT_SIAE_KEY, establishment_pk=siae2.pk
        )

        with self.assertNumQueries(1):
            result = get_current_organization_and_perms(request)

            expected = self.default_result | {
                "current_siae": siae2,
                "user_siaes": [siae1, siae2],
                "user_is_siae_admin": False,
                "matomo_custom_variables": OrderedDict(
                    [
                        ("is_authenticated", "yes"),
                        ("account_type", "employer"),
                        ("account_sub_type", "employer_not_admin"),
                    ]
                ),
            }
            self.assertDictEqual(expected, result)
Esempio n. 5
0
    def test_cleaning(self):
        """Test dataframe cleaning: rows formatting and validation."""
        command = self.command

        # Perfect data.
        df = pandas.DataFrame([AiCSVFileMock()])
        df = command.clean_df(df)
        row = df.iloc[0]
        self.assertTrue(isinstance(row[BIRTHDATE_COL], datetime.datetime))
        self.assertTrue(
            isinstance(row[CONTRACT_STARTDATE_COL], datetime.datetime))
        self.assertTrue(row["nir_is_valid"])
        self.assertTrue(row["siret_validated_by_asp"])

        # Invalid birth date.
        df = pandas.DataFrame([AiCSVFileMock(**{BIRTHDATE_COL: "1668-11-09"})])
        df = command.clean_df(df)
        row = df.iloc[0]
        self.assertEqual(row[BIRTHDATE_COL].strftime(DATE_FORMAT),
                         "1968-11-09")
        self.assertTrue(isinstance(row[BIRTHDATE_COL], datetime.datetime))

        # Invalid NIR.
        df = pandas.DataFrame([AiCSVFileMock(**{NIR_COL: "56987534"})])
        df = command.clean_df(df)
        row = df.iloc[0]
        self.assertEqual(row[NIR_COL], "")
        self.assertFalse(row["nir_is_valid"])

        # Excluded SIRET from the ASP.
        siret = "33491197100029"
        df = pandas.DataFrame([AiCSVFileMock(**{SIRET_COL: siret})])
        df = command.clean_df(df)
        row = df.iloc[0]
        self.assertEqual(row[SIRET_COL], siret)
        self.assertFalse(row["siret_validated_by_asp"])

        # Employer email.
        domain = "unenouvellechance.fr"
        siae = SiaeFactory(auth_email=f"accueil@{domain}", kind=Siae.KIND_AI)
        df = pandas.DataFrame([
            AiCSVFileMock(**{
                EMAIL_COL: f"colette@{domain}",
                SIRET_COL: siae.siret
            })
        ])
        df = command.clean_df(df)
        row = df.iloc[0]
        self.assertEqual(row[EMAIL_COL], "")

        # Generic email.
        domain = "gmail.fr"
        siae = SiaeFactory(auth_email=f"accueil@{domain}", kind=Siae.KIND_AI)
        df = pandas.DataFrame(
            [AiCSVFileMock(**{EMAIL_COL: f"colette@{domain}"})])
        df = command.clean_df(df)
        row = df.iloc[0]
        self.assertEqual(row[EMAIL_COL], "*****@*****.**")
Esempio n. 6
0
    def test_order_by(self):
        """
        Check SIAE results sorting.
        Don't test sorting by active members to avoid creating too much data.
        """
        guerande = create_city_guerande()
        created_siaes = []

        # Several job descriptions but no job application.
        siae = SiaeWithJobsFactory(department="44",
                                   coords=guerande.coords,
                                   post_code="44350")
        created_siaes.append(siae)

        # Many job descriptions and job applications.
        siae = SiaeWithJobsFactory(department="44",
                                   coords=guerande.coords,
                                   post_code="44350")
        JobApplicationFactory(to_siae=siae)
        created_siaes.append(siae)

        # Many job descriptions and more job applications than the first one.
        siae = SiaeWithJobsFactory(department="44",
                                   coords=guerande.coords,
                                   post_code="44350")
        JobApplicationFactory(to_siae=siae)
        JobApplicationFactory(to_siae=siae)
        created_siaes.append(siae)

        # No job description and a job application
        siae = SiaeFactory(department="44",
                           coords=guerande.coords,
                           post_code="44350")
        JobApplicationFactory(to_siae=siae)
        created_siaes.append(siae)

        # No job description, no job application.
        siae = SiaeFactory(department="44",
                           coords=guerande.coords,
                           post_code="44350")
        created_siaes.append(siae)

        # Does not want to receive any job application.
        siae = SiaeFactory(department="44",
                           coords=guerande.coords,
                           post_code="44350",
                           block_job_applications=True)
        created_siaes.append(siae)

        response = self.client.get(self.url, {"city": guerande.slug})
        siaes_results = response.context["siaes_page"]

        for i, siae in enumerate(siaes_results):
            self.assertEqual(siae.pk, created_siaes[i].pk)
Esempio n. 7
0
File: tests.py Progetto: ronnix/itou
    def test_siae_signup(self):
        """SIAE signup."""

        siae = SiaeFactory()

        url = reverse("signup:siae")
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)

        post_data = {
            "first_name": "John",
            "last_name": "Doe",
            "email": "*****@*****.**",
            "siret": siae.siret,
            "password1": "!*p4ssw0rd123-",
            "password2": "!*p4ssw0rd123-",
        }
        response = self.client.post(url, data=post_data)
        self.assertEqual(response.status_code, 302)

        user = get_user_model().objects.get(email=post_data["email"])
        self.assertFalse(user.is_job_seeker)
        self.assertFalse(user.is_prescriber)
        self.assertTrue(user.is_siae_staff)

        siae = Siae.active_objects.get(siret=post_data["siret"])
        self.assertTrue(user.siaemembership_set.get(siae=siae).is_siae_admin)
        self.assertEqual(1, siae.members.count())
Esempio n. 8
0
 def test_inactive_siae(self):
     siae = SiaeFactory(convention__is_active=False)
     invitation = SentSiaeStaffInvitationFactory(siae=siae)
     user = SiaeStaffFactory(email=invitation.email)
     self.client.login(email=user.email, password=DEFAULT_PASSWORD)
     join_url = reverse("invitations_views:join_siae",
                        kwargs={"invitation_id": invitation.id})
     response = self.client.get(join_url, follow=True)
     self.assertContains(response,
                         escape("Cette structure n'est plus active."))
Esempio n. 9
0
    def test_create_preexisting_siae_outside_of_siren_fails(self):

        siae = SiaeWithMembershipFactory()
        user = siae.members.first()

        self.client.login(username=user.email, password=DEFAULT_PASSWORD)

        url = reverse("siaes_views:create_siae")
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)

        preexisting_siae = SiaeFactory()
        new_siret = preexisting_siae.siret
        self.assertNotEqual(siae.siren, preexisting_siae.siren)
        self.assertTrue(Siae.objects.filter(siret=new_siret).exists())

        post_data = {
            "siret":
            new_siret,
            "kind":
            preexisting_siae.kind,
            "name":
            "FAMOUS SIAE SUB STRUCTURE",
            "source":
            Siae.SOURCE_USER_CREATED,
            "address_line_1":
            "2 Rue de Soufflenheim",
            "city":
            "Betschdorf",
            "post_code":
            "67660",
            "department":
            "67",
            "email":
            "",
            "phone":
            "0610203050",
            "website":
            "https://famous-siae.com",
            "description":
            "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
        }
        response = self.client.post(url, data=post_data)
        self.assertEqual(response.status_code, 200)

        expected_message = "Le SIRET doit commencer par le SIREN"
        self.assertNotContains(response, escape(expected_message))
        expected_message = "La structure à laquelle vous souhaitez vous rattacher est déjà"
        self.assertContains(response, escape(expected_message))

        self.assertEqual(
            Siae.objects.filter(siret=post_data["siret"]).count(), 1)
Esempio n. 10
0
    def test_select_siae_form_priority(self):
        """
        Test SelectSiaeForm priority.
        """

        # Priority is given to SIRET match over email match.
        user_email = "*****@*****.**"
        siae1 = SiaeFactory(kind=Siae.KIND_ACI, auth_email=user_email)
        siae2 = SiaeFactory(kind=Siae.KIND_ACI, auth_email=user_email)
        siae3 = SiaeWithMembershipFactory(kind=Siae.KIND_ACI, siret="12345678901234")
        post_data = {"email": user_email, "siret": siae3.siret, "kind": Siae.KIND_ACI}
        form = SelectSiaeForm(data=post_data)
        form.is_valid()
        self.assertEqual(form.selected_siae, siae3)

        # Priority is given to (siret, kind) when same SIRET is used for 2 SIAEs.
        siae1 = SiaeWithMembershipFactory(kind=Siae.KIND_ETTI)
        siae2 = SiaeFactory(kind=Siae.KIND_ACI, siret=siae1.siret)  # noqa F841
        post_data = {"email": user_email, "siret": siae1.siret, "kind": siae1.kind}
        form = SelectSiaeForm(data=post_data)
        form.is_valid()
        self.assertEqual(form.selected_siae, siae1)
Esempio n. 11
0
    def test_kind(self):
        city = create_city_saint_andre()
        SiaeFactory(department="44",
                    coords=city.coords,
                    post_code="44117",
                    kind=Siae.KIND_AI)

        response = self.client.get(self.url, {
            "city": city.slug,
            "kinds": [Siae.KIND_AI]
        })
        self.assertContains(response, "<b>1</b> résultat")

        response = self.client.get(self.url, {
            "city": city.slug,
            "kinds": [Siae.KIND_EI]
        })
        self.assertContains(response, "Aucun résultat")
Esempio n. 12
0
    def test_switch_siae(self):
        siae = SiaeWithMembershipFactory()
        user = siae.members.first()
        self.client.login(username=user.email, password=DEFAULT_PASSWORD)

        related_siae = SiaeFactory()
        related_siae.members.add(user)

        url = reverse("dashboard:index")
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.context["current_siae"], siae)

        url = reverse("siaes_views:card", kwargs={"siae_id": siae.pk})
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.context["current_siae"], siae)
        self.assertEqual(response.context["siae"], siae)

        url = reverse("dashboard:switch_siae")
        response = self.client.post(url, data={"siae_id": related_siae.pk})
        self.assertEqual(response.status_code, 302)

        url = reverse("dashboard:index")
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.context["current_siae"], related_siae)

        url = reverse("siaes_views:card", kwargs={"siae_id": related_siae.pk})
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.context["current_siae"], related_siae)
        self.assertEqual(response.context["siae"], related_siae)

        url = reverse("siaes_views:configure_jobs")
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.context["current_siae"], related_siae)

        url = reverse("apply:list_for_siae")
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.context["current_siae"], related_siae)
Esempio n. 13
0
    def test_can_download_approval_as_pdf(self, mock_can_be_cancelled):
        """
        A user can download an approval only when certain conditions
        are met:
        - the job_application.to_siae is subject to eligibility rules,
        - an approval exists (ie is not in the process of being delivered),
        - this approval is valid,
        - the job_application has been accepted.
        """
        job_application = JobApplicationWithApprovalFactory()
        self.assertTrue(job_application.can_download_approval_as_pdf)

        # SIAE not subject to eligibility rules.
        not_eligible_kinds = [
            choice[0] for choice in Siae.KIND_CHOICES
            if choice[0] not in Siae.ELIGIBILITY_REQUIRED_KINDS
        ]
        not_eligible_siae = SiaeFactory(kind=not_eligible_kinds[0])
        job_application = JobApplicationWithApprovalFactory(
            to_siae=not_eligible_siae)
        self.assertFalse(job_application.can_download_approval_as_pdf)

        # Application is not accepted.
        job_application = JobApplicationWithApprovalFactory(
            state=JobApplicationWorkflow.STATE_OBSOLETE)
        self.assertFalse(job_application.can_download_approval_as_pdf)

        # Application accepted but without approval.
        job_application = JobApplicationFactory(
            state=JobApplicationWorkflow.STATE_ACCEPTED)
        self.assertFalse(job_application.can_download_approval_as_pdf)

        # Approval has ended
        start = datetime.date.today() - relativedelta(years=2)
        end = start + relativedelta(years=1) - relativedelta(days=1)
        ended_approval = ApprovalFactory(start_at=start, end_at=end)

        job_application = JobApplicationWithApprovalFactory(
            approval=ended_approval)
        self.assertFalse(job_application.can_download_approval_as_pdf)
Esempio n. 14
0
    def test_siae_multiple_memberships(self):

        siae1 = SiaeWithMembershipFactory()
        user = siae1.members.first()
        self.assertTrue(siae1.has_admin(user))

        siae2 = SiaeFactory()
        siae2.members.add(user)
        self.assertFalse(siae2.has_admin(user))

        siae3 = SiaeFactory()
        siae3.members.add(user)
        self.assertFalse(siae3.has_admin(user))

        factory = RequestFactory()
        request = factory.get("/")
        request.user = user
        middleware = SessionMiddleware()
        middleware.process_request(request)
        request.session[settings.ITOU_SESSION_CURRENT_SIAE_KEY] = siae3.pk
        request.session.save()

        with self.assertNumQueries(1):
            result = get_current_organization_and_perms(request)
            expected = {
                "current_prescriber_organization":
                None,
                "current_siae":
                siae3,
                "user_is_prescriber_org_admin":
                False,
                "user_is_siae_admin":
                False,
                "user_siae_set": [siae1, siae2, siae3],
                "matomo_custom_variables":
                OrderedDict([
                    ("is_authenticated", "yes"),
                    ("account_type", "employer"),
                    ("account_sub_type", "employer_not_admin"),
                ]),
            }
            self.assertDictEqual(expected, result)
Esempio n. 15
0
File: tests.py Progetto: ronnix/itou
    def test_siae_signup_when_two_siaes_have_the_same_siret(self):
        """SIAE signup using a SIRET shared by two siaes."""

        siae1 = SiaeFactory()
        siae1.name = "FIRST SIAE"
        siae1.kind = Siae.KIND_ETTI
        siae1.save()

        siae2 = SiaeFactory()
        siae2.name = "SECOND SIAE"
        siae2.kind = Siae.KIND_ACI
        siae2.siret = siae1.siret
        siae2.save()

        url = reverse("signup:siae")
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)

        post_data = {
            "first_name": "John",
            "last_name": "Doe",
            "email": "*****@*****.**",
            "siret": siae1.siret,
            "password1": "!*p4ssw0rd123-",
            "password2": "!*p4ssw0rd123-",
        }
        response = self.client.post(url, data=post_data)
        self.assertEqual(response.status_code, 302)

        user = get_user_model().objects.get(email=post_data["email"])
        self.assertFalse(user.is_job_seeker)
        self.assertFalse(user.is_prescriber)
        self.assertTrue(user.is_siae_staff)

        siae1 = Siae.active_objects.get(name=siae1.name)
        self.assertTrue(user.siaemembership_set.get(siae=siae1).is_siae_admin)
        self.assertEqual(1, siae1.members.count())

        siae2 = Siae.active_objects.get(name=siae2.name)
        self.assertTrue(user.siaemembership_set.get(siae=siae2).is_siae_admin)
        self.assertEqual(1, siae2.members.count())
Esempio n. 16
0
    def test_join_an_siae_without_members(self):
        """
        A user joins an SIAE without members.

        The full "email confirmation process" is tested here.
        Further Siae's signup tests doesn't have to fully test it again.
        """

        user_first_name = "Jacques"
        user_email = "*****@*****.**"
        user_secondary_email = "*****@*****.**"
        password = "******"

        siae = SiaeFactory(kind=Siae.KIND_ETTI)
        self.assertEqual(0, siae.members.count())

        token = siae.get_token()
        with mock.patch("itou.utils.tokens.SiaeSignupTokenGenerator.make_token", return_value=token):

            url = reverse("signup:select_siae")
            response = self.client.get(url)
            self.assertEqual(response.status_code, 200)

            # Find an SIAE: (siret, kind) matches one SIAE.
            post_data = {"email": user_email, "siret": siae.siret, "kind": siae.kind}
            response = self.client.post(url, data=post_data)
            self.assertEqual(response.status_code, 302)
            self.assertRedirects(response, reverse("home:hp"))

            self.assertEqual(len(mail.outbox), 1)
            email = mail.outbox[0]
            self.assertIn("Un nouvel utilisateur souhaite rejoindre votre structure", email.subject)

            magic_link = siae.signup_magic_link
            response = self.client.get(magic_link)
            self.assertEqual(response.status_code, 200)

            # No error when opening magic link a second time.
            response = self.client.get(magic_link)
            self.assertEqual(response.status_code, 200)

            # Create user.
            url = reverse("signup:siae")
            post_data = {
                # Hidden fields.
                "encoded_siae_id": siae.get_encoded_siae_id(),
                "token": siae.get_token(),
                # Readonly fields.
                "siret": siae.siret,
                "kind": siae.kind,
                "siae_name": siae.display_name,
                # Regular fields.
                "first_name": user_first_name,
                "last_name": "Doe",
                "email": user_secondary_email,
                "password1": password,
                "password2": password,
            }
            response = self.client.post(url, data=post_data)
            self.assertEqual(response.status_code, 302)
            self.assertRedirects(response, reverse("account_email_verification_sent"))

            self.assertFalse(get_user_model().objects.filter(email=user_email).exists())
            user = get_user_model().objects.get(email=user_secondary_email)

            # Check `User` state.
            self.assertFalse(user.is_job_seeker)
            self.assertFalse(user.is_prescriber)
            self.assertTrue(user.is_siae_staff)
            self.assertTrue(user.is_active)
            self.assertTrue(siae.has_admin(user))
            self.assertEqual(1, siae.members.count())
            self.assertEqual(user.first_name, user_first_name)
            self.assertEqual(user.last_name, post_data["last_name"])
            self.assertEqual(user.email, user_secondary_email)
            # Check `EmailAddress` state.
            self.assertEqual(user.emailaddress_set.count(), 1)
            user_email = user.emailaddress_set.first()
            self.assertFalse(user_email.verified)

            # Check sent email.
            self.assertEqual(len(mail.outbox), 2)
            subjects = [email.subject for email in mail.outbox]
            self.assertIn("[Action requise] Un nouvel utilisateur souhaite rejoindre votre structure", subjects)
            self.assertIn("Confirmer l'adresse email pour la Plateforme de l'inclusion", subjects)

            # Magic link is no longer valid because siae.members.count() has changed.
            response = self.client.get(magic_link, follow=True)
            redirect_url, status_code = response.redirect_chain[-1]
            self.assertEqual(status_code, 302)
            next_url = reverse("signup:select_siae")
            self.assertEqual(redirect_url, next_url)
            self.assertEqual(response.status_code, 200)
            expected_message = _(
                "Ce lien d'inscription est invalide ou a expiré. " "Veuillez procéder à une nouvelle inscription."
            )
            self.assertContains(response, escape(expected_message))

            # User cannot log in until confirmation.
            post_data = {"login": user.email, "password": password}
            url = reverse("account_login")
            response = self.client.post(url, data=post_data)
            self.assertEqual(response.status_code, 302)
            self.assertEqual(response.url, reverse("account_email_verification_sent"))

            # Confirm email + auto login.
            confirmation_token = EmailConfirmationHMAC(user_email).key
            confirm_email_url = reverse("account_confirm_email", kwargs={"key": confirmation_token})
            response = self.client.post(confirm_email_url)
            self.assertEqual(response.status_code, 302)
            self.assertEqual(response.url, reverse("dashboard:index"))
            user_email = user.emailaddress_set.first()
            self.assertTrue(user_email.verified)
Esempio n. 17
0
    def test_find_or_create_job_application__create(self):
        developer = UserFactory(
            email=settings.AI_EMPLOYEES_STOCK_DEVELOPER_EMAIL)
        command = self.command

        # Employers canceled the job application we created, hence removing the PASS IAE we delivered.
        # Remove those job applications and deliver a new PASS IAE.
        nir = getattr(CleanedAiCsvFileMock(), NIR_COL)
        siret = getattr(CleanedAiCsvFileMock(), SIRET_COL)
        approval = ApprovalFactory(user__nir=nir)
        df = pandas.DataFrame([CleanedAiCsvFileMock(**{SIRET_COL: siret})])
        job_application = JobApplicationSentBySiaeFactory(
            to_siae__kind=Siae.KIND_AI,
            to_siae__siret=siret,
            state=JobApplicationWorkflow.STATE_CANCELLED,
            job_seeker=approval.user,
            approval_delivery_mode=JobApplication.
            APPROVAL_DELIVERY_MODE_MANUAL,
            approval=None,
            approval_manually_delivered_by=developer,
            created_at=settings.AI_EMPLOYEES_STOCK_IMPORT_DATE,
            hiring_start_at=df.iloc[0][CONTRACT_STARTDATE_COL],
        )
        created, new_job_application, cancelled_job_app_deleted = command.find_or_create_job_application(
            approval=approval,
            job_seeker=job_application.job_seeker,
            row=df.iloc[0],
            approval_manually_delivered_by=developer,
        )
        self.assertTrue(created)
        self.assertTrue(cancelled_job_app_deleted)
        # Assert employee records creation is blocked.
        self.assertNotIn(
            new_job_application,
            JobApplication.objects.eligible_as_employee_record(
                new_job_application.to_siae))
        self.assertEqual(new_job_application.approval.pk, approval.pk)
        self.assertFalse(
            JobApplication.objects.filter(pk=job_application.pk).exists())
        self.assertFalse(new_job_application.can_be_cancelled)
        self.assertTrue(new_job_application.is_from_ai_stock)
        self.assertEqual(JobApplication.objects.count(), 1)
        job_application.job_seeker.delete()

        # Different contract starting date.
        nir = getattr(CleanedAiCsvFileMock(), NIR_COL)
        approval = ApprovalFactory(user__nir=nir)
        siae = SiaeFactory(kind=Siae.KIND_AI)
        job_application = JobApplicationFactory(
            to_siae=siae,
            sender_siae=siae,
            job_seeker=approval.user,
            approval=approval,
            state=JobApplicationWorkflow.STATE_ACCEPTED,
            approval_delivery_mode=JobApplication.
            APPROVAL_DELIVERY_MODE_MANUAL,
            approval_manually_delivered_by=developer,
            created_at=settings.AI_EMPLOYEES_STOCK_IMPORT_DATE,
            hiring_start_at=datetime.date(2021, 1, 1),
        )
        df = pandas.DataFrame(
            [CleanedAiCsvFileMock(**{SIRET_COL: siae.siret})])
        created, new_job_application, cancelled_job_app_deleted = command.find_or_create_job_application(
            approval=job_application.approval,
            job_seeker=job_application.job_seeker,
            row=df.iloc[0],
            approval_manually_delivered_by=developer,
        )
        self.assertTrue(created)
        self.assertNotEqual(job_application.pk, new_job_application.pk)
        self.assertFalse(cancelled_job_app_deleted)
        job_application.job_seeker.delete()
Esempio n. 18
0
    def test_remove_ignored_rows(self):
        command = self.command
        SiaeFactory(kind=Siae.KIND_AI,
                    siret=getattr(CleanedAiCsvFileMock(), SIRET_COL))

        # Ended contracts are removed.
        df = pandas.DataFrame([
            CleanedAiCsvFileMock(),
            CleanedAiCsvFileMock(**{CONTRACT_ENDDATE_COL: "2020-11-30"})
        ])
        total_df, filtered_df = command.remove_ignored_rows(df)
        self.assertEqual(len(total_df), 2)
        self.assertEqual(len(filtered_df), 1)
        expected_comment = "Ligne ignorée : contrat terminé."
        self.assertEqual(total_df.iloc[1][COMMENTS_COL], expected_comment)

        # Continue even if df.CONTRACT_ENDDATE_COL does not exists.
        df = pandas.DataFrame([
            CleanedAiCsvFileMock(),
            CleanedAiCsvFileMock(**{CONTRACT_ENDDATE_COL: "2020-11-30"})
        ])
        df = df.drop(columns=[CONTRACT_ENDDATE_COL])
        total_df, filtered_df = command.remove_ignored_rows(df)
        self.assertEqual(len(total_df), 2)
        self.assertEqual(len(filtered_df), 2)

        # SIRET provided by the ASP are removed.
        df = pandas.DataFrame([
            CleanedAiCsvFileMock(),
            CleanedAiCsvFileMock(**{
                SIRET_COL: "33491197100029",
                "siret_validated_by_asp": False
            }),
        ])
        total_df, filtered_df = command.remove_ignored_rows(df)
        self.assertEqual(len(total_df), 2)
        self.assertEqual(len(filtered_df), 1)
        expected_comment = "Ligne ignorée : entreprise inexistante communiquée par l'ASP."
        self.assertEqual(total_df.iloc[1][COMMENTS_COL], expected_comment)

        # Inexistent structures are removed.
        df = pandas.DataFrame([
            CleanedAiCsvFileMock(),
            CleanedAiCsvFileMock(**{SIRET_COL: "202020202"})
        ])
        total_df, filtered_df = command.remove_ignored_rows(df)
        self.assertEqual(len(total_df), 2)
        self.assertEqual(len(filtered_df), 1)
        expected_comment = "Ligne ignorée : entreprise inexistante."
        self.assertEqual(total_df.iloc[1][COMMENTS_COL], expected_comment)

        # Rows with approvals are removed.
        df = pandas.DataFrame([
            CleanedAiCsvFileMock(),
            CleanedAiCsvFileMock(**{APPROVAL_COL: "670929"})
        ])
        total_df, filtered_df = command.remove_ignored_rows(df)
        self.assertEqual(len(total_df), 2)
        self.assertEqual(len(filtered_df), 1)
        expected_comment = "Ligne ignorée : agrément ou PASS IAE renseigné."
        self.assertEqual(total_df.iloc[1][COMMENTS_COL], expected_comment)
Esempio n. 19
0
File: tests.py Progetto: ronnix/itou
    def test_is_subject_to_eligibility_rules(self):
        siae = SiaeFactory(kind=Siae.KIND_GEIQ)
        self.assertFalse(siae.is_subject_to_eligibility_rules)

        siae = SiaeFactory(kind=Siae.KIND_EI)
        self.assertTrue(siae.is_subject_to_eligibility_rules)
Esempio n. 20
0
    def test_distance(self):
        # 3 SIAEs in two departments to test distance and department filtering
        vannes = create_city_vannes()
        SIAE_VANNES = "SIAE Vannes"
        SiaeFactory(name=SIAE_VANNES,
                    department="56",
                    coords=vannes.coords,
                    post_code="56760",
                    kind=Siae.KIND_AI)

        guerande = create_city_guerande()
        SIAE_GUERANDE = "SIAE Guérande"
        SiaeFactory(name=SIAE_GUERANDE,
                    department="44",
                    coords=guerande.coords,
                    post_code="44350",
                    kind=Siae.KIND_AI)
        saint_andre = create_city_saint_andre()
        SIAE_SAINT_ANDRE = "SIAE Saint André des Eaux"
        SiaeFactory(name=SIAE_SAINT_ANDRE,
                    department="44",
                    coords=saint_andre.coords,
                    post_code="44117",
                    kind=Siae.KIND_AI)

        # 100 km
        response = self.client.get(self.url, {
            "city": guerande.slug,
            "distance": 100
        })
        self.assertContains(response, "<b>3</b> résultats")
        self.assertContains(response, SIAE_VANNES.capitalize())
        self.assertContains(response, SIAE_GUERANDE.capitalize())
        self.assertContains(response, SIAE_SAINT_ANDRE.capitalize())

        # 15 km
        response = self.client.get(self.url, {
            "city": guerande.slug,
            "distance": 15
        })
        self.assertContains(response, "<b>2</b> résultats")
        self.assertContains(response, SIAE_GUERANDE.capitalize())
        self.assertContains(response, SIAE_SAINT_ANDRE.capitalize())

        # 100 km and 44
        response = self.client.get(self.url, {
            "city": guerande.slug,
            "distance": 100,
            "departments": ["44"]
        })
        self.assertContains(response, "<b>2</b> résultats")
        self.assertContains(response, SIAE_GUERANDE.capitalize())
        self.assertContains(response, SIAE_SAINT_ANDRE.capitalize())

        # 100 km and 56
        response = self.client.get(self.url, {
            "city": vannes.slug,
            "distance": 100,
            "departments": ["56"]
        })
        self.assertContains(response, "<b>1</b> résultat")
        self.assertContains(response, SIAE_VANNES.capitalize())
Esempio n. 21
0
    def test_import_data_into_itou(self):
        developer = UserFactory(
            email=settings.AI_EMPLOYEES_STOCK_DEVELOPER_EMAIL)
        CommuneFactory(code=getattr(CleanedAiCsvFileMock, CITY_INSEE_COL))
        command = self.command
        base_data = CleanedAiCsvFileMock()
        siae = SiaeFactory(siret=getattr(base_data, SIRET_COL),
                           kind=Siae.KIND_AI)

        # User, approval and job application creation.
        input_df = pandas.DataFrame([base_data])
        output_df = command.import_data_into_itou(df=input_df,
                                                  to_be_imported_df=input_df)
        self.assertEqual(User.objects.count(), 2)
        self.assertEqual(Approval.objects.count(), 1)
        self.assertEqual(JobApplication.objects.count(), 1)
        job_seeker = User.objects.filter(is_job_seeker=True).get()
        self.assertEqual(job_seeker.job_applications.count(), 1)
        self.assertEqual(job_seeker.approvals.count(), 1)
        job_seeker.delete()

        # User, approval and job application retrieval.
        job_seeker = JobSeekerFactory(nir=getattr(base_data, NIR_COL))
        ApprovalFactory(user=job_seeker)
        JobApplicationFactory(
            sender_kind=JobApplication.SENDER_KIND_SIAE_STAFF,
            sender_siae=siae,
            to_siae=siae,
            created_at=settings.AI_EMPLOYEES_STOCK_IMPORT_DATE,
            approval_manually_delivered_by=developer,
            approval_delivery_mode=JobApplication.
            APPROVAL_DELIVERY_MODE_MANUAL,
            job_seeker=job_seeker,
            hiring_start_at=getattr(base_data, CONTRACT_STARTDATE_COL),
        )
        input_df = pandas.DataFrame([CleanedAiCsvFileMock()])
        output_df = command.import_data_into_itou(df=input_df,
                                                  to_be_imported_df=input_df)
        self.assertEqual(User.objects.filter(is_job_seeker=True).count(), 1)
        self.assertEqual(Approval.objects.count(), 1)
        self.assertEqual(JobApplication.objects.count(), 1)
        job_seeker.delete()

        # Only values to be imported are imported but the whole input data frame
        # is updated for logging purposes.
        input_df = pandas.DataFrame([
            CleanedAiCsvFileMock(**{CONTRACT_ENDDATE_COL: "2020-05-11"
                                    }),  # Ended contracts are ignored.
            CleanedAiCsvFileMock(
                **{SIRET_COL: "598742121322354"}),  # Not existing SIAE.
            CleanedAiCsvFileMock(
                **{
                    NIR_COL: "141062a78200555",
                    EMAIL_COL: "*****@*****.**",
                    BIRTHDATE_COL: datetime.date(1997, 3, 12),
                }),
            # Different contract start date.
            CleanedAiCsvFileMock(
                **{CONTRACT_STARTDATE_COL: datetime.date(2020, 4, 12)}),
            CleanedAiCsvFileMock(),
        ])
        input_df = command.add_columns_for_asp(input_df)
        input_df, to_be_imported_df = command.remove_ignored_rows(input_df)
        output_df = command.import_data_into_itou(
            df=input_df, to_be_imported_df=to_be_imported_df)

        self.assertEqual(User.objects.count(), 3)
        self.assertEqual(Approval.objects.count(), 2)
        self.assertEqual(JobApplication.objects.count(), 3)

        job_seeker = User.objects.get(email=getattr(base_data, EMAIL_COL))
        self.assertEqual(job_seeker.job_applications.count(), 2)
        self.assertEqual(job_seeker.approvals.count(), 1)

        # Different contract start date.
        job_seeker = User.objects.get(email="*****@*****.**")
        self.assertEqual(job_seeker.job_applications.count(), 1)
        self.assertEqual(job_seeker.approvals.count(), 1)

        # Ignored rows.
        for _, row in output_df[:2].iterrows():
            self.assertTrue(row[COMMENTS_COL])
            self.assertFalse(row[PASS_IAE_NUMBER_COL])
            self.assertFalse(row[USER_PK_COL])

        for _, row in output_df[2:].iterrows():
            job_seeker = User.objects.get(nir=row[NIR_COL])
            approval = job_seeker.approvals.first()
            self.assertEqual(row[PASS_IAE_NUMBER_COL], approval.number)
            self.assertEqual(row[PASS_IAE_START_DATE_COL],
                             approval.start_at.strftime(DATE_FORMAT))
            self.assertEqual(row[PASS_IAE_END_DATE_COL],
                             approval.end_at.strftime(DATE_FORMAT))
            self.assertEqual(row[USER_PK_COL], job_seeker.jobseeker_hash_id)
            self.assertEqual(row[USER_ITOU_EMAIL_COL], job_seeker.email)

        # Clean
        job_seeker = User.objects.get(nir=getattr(base_data, NIR_COL))
        job_seeker.delete()
        job_seeker = User.objects.get(email="*****@*****.**")
        job_seeker.delete()

        # If transaction: raise and pass.
        job_seeker = JobSeekerFactory(
            nir=getattr(CleanedAiCsvFileMock(), NIR_COL))
        future_date = datetime.date.today() + relativedelta(months=2)
        ApprovalFactory(user=job_seeker, start_at=future_date)
        input_df = pandas.DataFrame([
            base_data,
            CleanedAiCsvFileMock(
                **{
                    NIR_COL: "141062a78200555",
                    EMAIL_COL: "*****@*****.**",
                    BIRTHDATE_COL: datetime.date(1997, 3, 12),
                }),
        ])

        output_df = None
        output_df = command.import_data_into_itou(df=input_df,
                                                  to_be_imported_df=input_df)
        self.assertEqual(len(output_df), 2)
Esempio n. 22
0
    def test_has_members(self):
        siae1 = SiaeFactory()
        siae2 = SiaeWithMembershipFactory()

        self.assertFalse(siae1.has_members)
        self.assertTrue(siae2.has_members)
Esempio n. 23
0
    def test_join_an_siae_without_members(self):
        """
        A user joins an SIAE without members.

        The full "email confirmation process" is tested here.
        Further Siae's signup tests doesn't have to fully test it again.
        """

        user_first_name = "Jacques"
        user_email = "*****@*****.**"
        user_secondary_email = "*****@*****.**"

        siae = SiaeFactory(kind=Siae.KIND_ETTI)
        self.assertEqual(0, siae.members.count())

        token = siae.get_token()
        with mock.patch(
                "itou.utils.tokens.SiaeSignupTokenGenerator.make_token",
                return_value=token):

            url = reverse("signup:siae_select")
            response = self.client.get(url)
            self.assertEqual(response.status_code, 200)

            # Find an SIAE by SIREN.
            response = self.client.get(url, {"siren": siae.siret[:9]})
            self.assertEqual(response.status_code, 200)

            # Choose an SIAE between results.
            post_data = {"siaes": siae.pk}
            # Pass `siren` in request.GET
            response = self.client.post(f"{url}?siren={siae.siret[:9]}",
                                        data=post_data)
            self.assertEqual(response.status_code, 302)
            self.assertRedirects(response, "/")

            self.assertEqual(len(mail.outbox), 1)
            email = mail.outbox[0]
            self.assertIn(
                "Un nouvel utilisateur souhaite rejoindre votre structure",
                email.subject)

            magic_link = siae.signup_magic_link
            response = self.client.get(magic_link)
            self.assertEqual(response.status_code, 200)

            # No error when opening magic link a second time.
            response = self.client.get(magic_link)
            self.assertEqual(response.status_code, 200)

            # Create user.
            url = siae.signup_magic_link
            post_data = {
                # Hidden fields
                "encoded_siae_id": siae.get_encoded_siae_id(),
                "token": siae.get_token(),
                # Readonly fields
                "siret": siae.siret,
                "kind": siae.kind,
                "siae_name": siae.display_name,
                # Regular fields
                "first_name": user_first_name,
                "last_name": "Doe",
                "email": user_secondary_email,
                "password1": DEFAULT_PASSWORD,
                "password2": DEFAULT_PASSWORD,
            }
            response = self.client.post(url, data=post_data)
            self.assertEqual(response.status_code, 302)
            self.assertRedirects(response,
                                 reverse("account_email_verification_sent"))

            self.assertFalse(User.objects.filter(email=user_email).exists())
            user = User.objects.get(email=user_secondary_email)

            # Check `User` state.
            self.assertFalse(user.is_job_seeker)
            self.assertFalse(user.is_prescriber)
            self.assertTrue(user.is_siae_staff)
            self.assertTrue(user.is_active)
            self.assertTrue(siae.has_admin(user))
            self.assertEqual(1, siae.members.count())
            # `username` should be a valid UUID, see `User.generate_unique_username()`.
            self.assertEqual(user.username,
                             uuid.UUID(user.username, version=4).hex)
            self.assertEqual(user.first_name, user_first_name)
            self.assertEqual(user.last_name, post_data["last_name"])
            self.assertEqual(user.email, user_secondary_email)
            # Check `EmailAddress` state.
            self.assertEqual(user.emailaddress_set.count(), 1)
            user_email = user.emailaddress_set.first()
            self.assertFalse(user_email.verified)

            # Check sent email.
            self.assertEqual(len(mail.outbox), 2)
            subjects = [email.subject for email in mail.outbox]
            self.assertIn(
                "[Action requise] Un nouvel utilisateur souhaite rejoindre votre structure !",
                subjects)
            self.assertIn("Confirmez votre adresse e-mail", subjects)

            # Magic link is no longer valid because siae.members.count() has changed.
            response = self.client.get(magic_link, follow=True)
            redirect_url, status_code = response.redirect_chain[-1]
            self.assertEqual(status_code, 302)
            next_url = reverse("signup:siae_select")
            self.assertEqual(redirect_url, next_url)
            self.assertEqual(response.status_code, 200)
            expected_message = (
                "Ce lien d'inscription est invalide ou a expiré. "
                "Veuillez procéder à une nouvelle inscription.")
            self.assertContains(response, escape(expected_message))

            # User cannot log in until confirmation.
            post_data = {"login": user.email, "password": DEFAULT_PASSWORD}
            url = reverse("account_login")
            response = self.client.post(url, data=post_data)
            self.assertEqual(response.status_code, 302)
            self.assertEqual(response.url,
                             reverse("account_email_verification_sent"))

            # Confirm email + auto login.
            confirmation_token = EmailConfirmationHMAC(user_email).key
            confirm_email_url = reverse("account_confirm_email",
                                        kwargs={"key": confirmation_token})
            response = self.client.post(confirm_email_url)
            self.assertEqual(response.status_code, 302)
            self.assertEqual(response.url, reverse("welcoming_tour:index"))
            user_email = user.emailaddress_set.first()
            self.assertTrue(user_email.verified)