コード例 #1
0
ファイル: action_test.py プロジェクト: tkoutangni/bob-emploi
    def test_dynamic_sticky_steps(self):
        """Check that dynamic fields of sticky steps are populated."""
        new_action = action_pb2.Action()
        database = mongomock.MongoClient().test
        database.sticky_action_steps.insert_one({
            '_id': 'step1',
            'title': 'Trouver un job de %masculineJobName',
            'content': 'Regarder sur le [ROME](http://go/rome/%romeId).',
            'link': 'http://lbb.fr/city/%cityId/rome/%romeId',
            'linkName': 'Les bonnes boites de %cityName',
            'finishCheckboxCaption': "J'ai trouvé un job de %masculineJobName",
        })
        action.instantiate(
            new_action,
            user_pb2.User(),
            project_pb2.Project(
                mobility=geo_pb2.Location(city=geo_pb2.FrenchCity(
                    city_id='45123',
                    name='Orléans',
                    departement_id='45',
                    region_id='84')),
                target_job=job_pb2.Job(
                    masculine_name='Pompier',
                    code_ogr='78910',
                    job_group=job_pb2.JobGroup(rome_id='A1101', name='Combattants')),
            ),
            action_pb2.ActionTemplate(
                action_template_id='my-sticky',
                step_ids=['step1']),
            set(), database, None)

        step = new_action.steps[0]
        self.assertEqual('http://lbb.fr/city/45123/rome/A1101', step.link)
        self.assertEqual('Regarder sur le [ROME](http://go/rome/A1101).', step.content)
コード例 #2
0
    def test_advice_job_boards_extra_data(self):
        """Test that the advisor computes extra data for the "Find a Job Board" advice."""
        project = project_pb2.Project(
            target_job=job_pb2.Job(job_group=job_pb2.JobGroup(
                rome_id='A1234')),
            mobility=geo_pb2.Location(city=geo_pb2.FrenchCity(
                departement_id='14')),
            job_search_length_months=7,
            weekly_applications_estimate=project_pb2.A_LOT,
            total_interview_count=1,
        )
        self.database.jobboards.insert_one({
            'title': 'Indeed',
            'filters': ['for-departement(14)']
        })
        self.database.advice_modules.insert_one({
            'adviceId': 'job-boards',
            'triggerScoringModel': 'advice-job-boards',
            'extraDataFieldName': 'job_boards_data',
            'isReadyForProd': True,
        })
        advisor.clear_cache()

        advisor.maybe_advise(self.user, project, self.database)

        advice = next(a for a in project.advices
                      if a.advice_id == 'job-boards')
        self.assertEqual(project_pb2.ADVICE_RECOMMENDED, advice.status)
        self.assertEqual('Indeed', advice.job_boards_data.job_board_title)
        self.assertFalse(advice.job_boards_data.is_specific_to_job_group)
        self.assertTrue(advice.job_boards_data.is_specific_to_region)
コード例 #3
0
    def test_advice_spontaneous_application_extra_data(self, mock_get_lbb_companies):
        """Test that the advisor computes extra data for the "Spontaneous Application" advice."""
        project = project_pb2.Project(
            target_job=job_pb2.Job(job_group=job_pb2.JobGroup(rome_id='A1234')),
            mobility=geo_pb2.Location(city=geo_pb2.FrenchCity(departement_id='14')),
            job_search_length_months=7,
            weekly_applications_estimate=project_pb2.A_LOT,
            total_interview_count=1,
        )
        self.database.local_diagnosis.insert_one({
            '_id': '14:A1234',
            'imt': {'applicationModes': {'Foo': {'first': 'SPONTANEOUS_APPLICATION'}}},
        })
        self.database.advice_modules.insert_one({
            'adviceId': 'my-advice',
            'triggerScoringModel': 'chantier-spontaneous-application',
            'extraDataFieldName': 'spontaneous_application_data',
            'isReadyForProd': True,
        })
        mock_get_lbb_companies.return_value = iter([
            {'name': 'EX NIHILO'},
            {'name': 'M.F.P MULTIMEDIA FRANCE PRODUCTIONS'},
        ])
        advisor.clear_cache()

        advisor.maybe_advise(self.user, project, self.database)

        advice = next(a for a in project.advices if a.advice_id == 'my-advice')
        self.assertEqual(project_pb2.ADVICE_RECOMMENDED, advice.status)
        self.assertEqual(
            ['EX NIHILO', 'M.F.P MULTIMEDIA FRANCE PRODUCTIONS'],
            [c.name for c in advice.spontaneous_application_data.companies])
コード例 #4
0
    def test_advice_spontaneous_application_extra_data(self,
                                                       mock_get_lbb_companies):
        """Test that the advisor computes extra data for the "Spontaneous Application" advice."""

        project = project_pb2.Project(
            target_job=job_pb2.Job(job_group=job_pb2.JobGroup(
                rome_id='A1234')),
            mobility=geo_pb2.Location(city=geo_pb2.FrenchCity(
                departement_id='14')),
            job_search_length_months=7,
            weekly_applications_estimate=project_pb2.A_LOT,
            total_interview_count=1,
        )
        self.database.job_group_info.insert_one({
            '_id': 'A1234',
            'applicationModes': {
                'R4Z92': {
                    'modes': [{
                        'percentage': 36.38,
                        'mode': 'SPONTANEOUS_APPLICATION'
                    }, {
                        'percentage': 29.46,
                        'mode': 'PERSONAL_OR_PROFESSIONAL_CONTACTS'
                    }, {
                        'percentage': 18.38,
                        'mode': 'PLACEMENT_AGENCY'
                    }, {
                        'percentage': 15.78,
                        'mode': 'UNDEFINED_APPLICATION_MODE'
                    }],
                }
            },
        })
        self.database.advice_modules.insert_one({
            'adviceId': 'my-advice',
            'categories': ['first'],
            'triggerScoringModel': 'advice-spontaneous-application',
            'extraDataFieldName': 'spontaneous_application_data',
            'isReadyForProd': True,
        })
        mock_get_lbb_companies.return_value = iter([
            {
                'name': 'EX NIHILO'
            },
            {
                'name': 'M.F.P MULTIMEDIA FRANCE PRODUCTIONS'
            },
        ])
        advisor.clear_cache()

        advisor.maybe_advise(self.user, project, self.database)

        advice = next(a for a in project.advices if a.advice_id == 'my-advice')
        self.assertEqual(project_pb2.ADVICE_RECOMMENDED, advice.status)
        self.assertEqual(
            ['EX NIHILO', 'M.F.P MULTIMEDIA FRANCE PRODUCTIONS'],
            [c.name for c in advice.spontaneous_application_data.companies])
コード例 #5
0
    def test_advice_better_job_in_group_extra_data(self):
        """Test that the advisor computes extra data for the "Better Job in Group" advice."""
        project = project_pb2.Project(
            target_job=job_pb2.Job(
                code_ogr='1234', job_group=job_pb2.JobGroup(rome_id='A1234')),
            mobility=geo_pb2.Location(city=geo_pb2.FrenchCity(
                departement_id='14')),
            job_search_length_months=7,
            weekly_applications_estimate=project_pb2.A_LOT,
            total_interview_count=1,
        )
        self.database.job_group_info.insert_one({
            '_id':
            'A1234',
            'jobs': [
                {
                    'codeOgr': '1234',
                    'name': 'Pilote'
                },
                {
                    'codeOgr': '5678',
                    'name': 'Pompier'
                },
                {
                    'codeOgr': '9012',
                    'name': 'Facteur'
                },
            ],
            'requirements': {
                'specificJobs': [
                    {
                        'codeOgr': '5678',
                        'percentSuggested': 55,
                    },
                    {
                        'codeOgr': '1234',
                        'percentSuggested': 45,
                    },
                ],
            },
        })
        self.database.advice_modules.insert_one({
            'adviceId': 'my-advice',
            'triggerScoringModel': 'advice-better-job-in-group',
            'extraDataFieldName': 'better_job_in_group_data',
            'isReadyForProd': True,
        })
        advisor.clear_cache()

        advisor.maybe_advise(self.user, project, self.database)

        advice = next(a for a in project.advices if a.advice_id == 'my-advice')
        self.assertEqual(project_pb2.ADVICE_RECOMMENDED, advice.status)
        self.assertEqual('Pompier',
                         advice.better_job_in_group_data.better_job.name)
        self.assertEqual(1, advice.better_job_in_group_data.num_better_jobs)
コード例 #6
0
    def test_advice_improve_success_rate_extra_data(self):
        """Test that the advisor computes extra data for the "Improve Success Rate" advice."""
        project = project_pb2.Project(
            target_job=job_pb2.Job(job_group=job_pb2.JobGroup(
                rome_id='A1234')),
            mobility=geo_pb2.Location(city=geo_pb2.FrenchCity(
                departement_id='14')),
            job_search_length_months=6,
            weekly_applications_estimate=project_pb2.A_LOT,
            total_interview_count=1,
        )
        self.database.local_diagnosis.insert_one({
            '_id': '14:A1234',
            'imt': {
                'yearlyAvgOffersDenominator': 10,
                'yearlyAvgOffersPer10Candidates': 2,
            },
        })
        self.database.job_group_info.insert_one({
            '_id': 'A1234',
            'requirements': {
                'skills': [{
                    'name': 'Humour'
                }, {
                    'name': 'Empathie'
                }],
                'skillsShortText': '**Humour** et **empathie**',
            },
        })
        self.database.advice_modules.insert_one({
            'adviceId': 'improve-success',
            'triggerScoringModel': 'advice-improve-resume',
            'extraDataFieldName': 'improve_success_rate_data',
            'isReadyForProd': True,
        })
        advisor.clear_cache()

        advisor.maybe_advise(self.user, project, self.database)

        advice = next(a for a in project.advices
                      if a.advice_id == 'improve-success')
        self.assertEqual(project_pb2.ADVICE_RECOMMENDED, advice.status)
        self.assertGreater(
            advice.improve_success_rate_data.num_interviews_increase, 50)
        self.assertFalse(advice.improve_success_rate_data.requirements.skills)
        self.assertEqual(
            '**Humour** et **empathie**',
            advice.improve_success_rate_data.requirements.skills_short_text)
コード例 #7
0
    def test_advice_events_extra_data(self, mock_now):
        """Test that the advisor computes extra data for the "Events" advice."""
        mock_now.return_value = datetime.datetime(2017, 8, 15)
        project = project_pb2.Project(
            target_job=job_pb2.Job(
                code_ogr='1234', job_group=job_pb2.JobGroup(rome_id='A1234')),
            mobility=geo_pb2.Location(city=geo_pb2.FrenchCity(
                departement_id='75')),
            job_search_length_months=7,
            weekly_applications_estimate=project_pb2.A_LOT,
            total_interview_count=1,
        )
        self.database.advice_modules.insert_one({
            'adviceId': 'my-advice',
            'triggerScoringModel': 'advice-event',
            'extraDataFieldName': 'events_data',
            'isReadyForProd': True,
        })
        self.database.events.insert_many([
            {
                'title': 'AP HEROS CANDIDATS MADIRCOM - BORDEAUX',
                'link':
                'https://www.workuper.com/events/ap-heros-candidats-madircom-bordeaux',
                'organiser': 'MADIRCOM',
                'startDate': '2017-08-29',
            },
            {
                'title':
                'Le Salon du Travail et de la Mobilité Professionnelle',
                'link':
                'https://www.workuper.com/events/le-salon-du-travail-et-de-la-mobilite-'
                'professionnelle',
                'organiser':
                'Altice Media Events',
                'startDate':
                '2018-01-19',
            },
        ])
        advisor.clear_cache()
        self.user.features_enabled.alpha = True

        advisor.maybe_advise(self.user, project, self.database)

        advice = next(a for a in project.advices if a.advice_id == 'my-advice')
        self.assertEqual(project_pb2.ADVICE_RECOMMENDED, advice.status)
        self.assertEqual('AP HEROS CANDIDATS MADIRCOM - BORDEAUX',
                         advice.events_data.event_name)
コード例 #8
0
    def test_advice_volunteer_extra_data(self):
        """Test that the advisor computes extra data for the "Volunteer" advice."""
        project = project_pb2.Project(
            target_job=job_pb2.Job(
                code_ogr='1234', job_group=job_pb2.JobGroup(rome_id='A1234')),
            mobility=geo_pb2.Location(city=geo_pb2.FrenchCity(
                departement_id='75')),
            job_search_length_months=7,
            weekly_applications_estimate=project_pb2.A_LOT,
            total_interview_count=1,
        )
        self.database.volunteering_missions.insert_one({
            '_id':
            '75',
            'missions': [
                {
                    'associationName': 'BackUp Rural'
                },
                {
                    'associationName': 'Construisons Ensemble Comment Faire'
                },
            ],
        })
        self.database.advice_modules.insert_one({
            'adviceId': 'my-advice',
            'triggerScoringModel': 'advice-volunteer',
            'extraDataFieldName': 'volunteer_data',
            'isReadyForProd': True,
        })
        advisor.clear_cache()

        advisor.maybe_advise(self.user, project, self.database)

        advice = next(a for a in project.advices if a.advice_id == 'my-advice')
        self.assertEqual(project_pb2.ADVICE_RECOMMENDED, advice.status)
        self.assertEqual(
            ['BackUp Rural', 'Construisons Ensemble Comment Faire'],
            sorted(advice.volunteer_data.association_names))
コード例 #9
0
    def test_advice_association_help_extra_data(self):
        """Test that the advisor computes extra data for the "Find an association" advice."""
        project = project_pb2.Project(
            target_job=job_pb2.Job(
                code_ogr='1234', job_group=job_pb2.JobGroup(rome_id='A1234')),
            mobility=geo_pb2.Location(city=geo_pb2.FrenchCity(
                departement_id='14')),
            job_search_length_months=7,
            weekly_applications_estimate=project_pb2.A_LOT,
            total_interview_count=1,
        )
        self.database.associations.insert_many([
            {
                'name': 'Pôle emploi'
            },
            {
                'name': 'SNC',
                'filters': ['for-departement(14,15,16)']
            },
            {
                'name': 'Ressort',
                'filters': ['for-departement(69)']
            },
        ])
        self.database.advice_modules.insert_one({
            'adviceId': 'my-advice',
            'triggerScoringModel': 'advice-association-help',
            'extraDataFieldName': 'associations_data',
            'isReadyForProd': True,
        })
        advisor.clear_cache()

        advisor.maybe_advise(self.user, project, self.database)

        advice = next(a for a in project.advices if a.advice_id == 'my-advice')
        self.assertEqual(project_pb2.ADVICE_RECOMMENDED, advice.status)
        self.assertEqual('SNC', advice.associations_data.association_name)
コード例 #10
0
ファイル: auth.py プロジェクト: IanMadlenya/bob-emploi
    def _pe_connect_authenticate(self, code, nonce):
        token_data = _get_oauth2_access_token(
            'https://authentification-candidat.pole-emploi.fr/connexion/oauth2/access_token?'
            'realm=/individu',
            code=code,
            client_id=_EMPLOI_STORE_CLIENT_ID,
            client_secret=_EMPLOI_STORE_CLIENT_SECRET,
            auth_name='PE Connect',
        )

        if token_data.get('nonce') != nonce:
            flask.abort(403, 'Mauvais paramètre nonce')
        authorization_header = '{} {}'.format(
            token_data.get('token_type', 'Bearer'),
            token_data.get('access_token', ''))
        scopes = token_data.get('scope', '').split(' ')

        user_info_response = requests.get(
            'https://api.emploi-store.fr/partenaire/peconnect-individu/v1/userinfo',
            headers={'Authorization': authorization_header})
        if user_info_response.status_code < 200 or user_info_response.status_code >= 400:
            logging.warning('PE Connect fails (%d): "%s"',
                            user_info_response.status_code,
                            user_info_response.text)
            flask.abort(403, user_info_response.text)

        user_info = user_info_response.json()

        city = None
        if 'coordonnees' in scopes:
            coordinates_response = requests.get(
                'https://api.emploi-store.fr/partenaire/peconnect-coordonnees/v1/coordonnees',
                headers={
                    'Authorization': authorization_header,
                    'pe-nom-application': 'Bob Emploi',
                })
            if coordinates_response.status_code >= 200 and coordinates_response.status_code < 400:
                coordinates = coordinates_response.json()
                city = geo.get_city_proto(coordinates.get('codeINSEE'))

        job = None
        if 'competences' in scopes:
            competences_response = requests.get(
                'https://api.emploi-store.fr/partenaire/peconnect-competences/v1/competences',
                headers={'Authorization': authorization_header},
            )
            if competences_response.status_code >= 200 and competences_response.status_code < 400:
                competences = competences_response.json()
                job_id, rome_id = next(
                    ((c.get('codeAppellation'), c.get('codeRome'))
                     for c in competences), (None, None))
                job = jobs.get_job_proto(self._db, job_id, rome_id)

        response = user_pb2.AuthResponse()
        user_dict = self._user_db.user.find_one(
            {'peConnectId': user_info['sub']})
        user_id = str(user_dict.pop('_id')) if user_dict else ''
        if proto.parse_from_mongo(user_dict, response.authenticated_user):
            response.authenticated_user.user_id = user_id
            self._handle_returning_user(response)
        else:
            email = user_info.get('email')
            if email:
                self._assert_user_not_existing(email)
                response.authenticated_user.profile.email = email
            user = response.authenticated_user
            user.pe_connect_id = user_info['sub']
            # TODO(pascal): Handle the case where one of the name is missing.
            user.profile.name = french.cleanup_firstname(
                user_info.get('given_name', ''))
            user.profile.last_name = french.cleanup_firstname(
                user_info.get('family_name', ''))
            user.profile.gender = \
                _PE_CONNECT_GENDER.get(user_info.get('gender', ''), user_pb2.UNKNOWN_GENDER)
            if city or job:
                user.projects.add(
                    is_incomplete=True,
                    mobility=geo_pb2.Location(city=city) if city else None,
                    target_job=job)
            self._save_new_user(user)
            response.is_new_user = True

        response.auth_token = create_token(response.authenticated_user.user_id,
                                           'auth')

        return response
コード例 #11
0
    def test_seasonal_extra_data(self, mock_now):
        """Test that the advisor computes extra data for the seasonal-relocate advice."""
        mock_now.return_value = datetime.datetime(2017, 2, 15)

        self.user.profile.year_of_birth = datetime.date.today().year - 28
        self.user.profile.highest_degree = job_pb2.BAC_BACPRO
        self.user.profile.family_situation = user_pb2.SINGLE
        project = project_pb2.Project(
            mobility=geo_pb2.Location(area_type=geo_pb2.COUNTRY),
            job_search_length_months=7,
            employment_types=[
                job_pb2.INTERIM, job_pb2.CDD_LESS_EQUAL_3_MONTHS
            ])
        self.database.advice_modules.insert_one({
            'adviceId': 'seasonal-relocate',
            'triggerScoringModel': 'advice-seasonal-relocate',
            'extraDataFieldName': 'seasonal_data',
            'isReadyForProd': True,
        })
        self.database.seasonal_jobbing.insert_one({
            '_id':
            2,
            'departementStats': [
                {
                    'departementId':
                    '06',
                    'departementSeasonalOffers':
                    900,
                    'jobGroups': [
                        {
                            'romeId': 'I1202',
                            'name': 'Professeur de piano',
                            'offers': 123,
                        },
                        {
                            'romeId': 'I1203',
                            'name': 'Professeur de guitarre',
                            'offers': 120,
                        },
                    ],
                },
                {
                    'departementId':
                    '2A',
                    'departementSeasonalOffers':
                    800,
                    'jobGroups': [
                        {
                            'romeId': 'I1202',
                            'name': 'Professeur de piano',
                            'offers': 123,
                        },
                        {
                            'romeId': 'I1203',
                            'name': 'Professeur de guitarre',
                            'offers': 120,
                        },
                    ],
                },
            ],
        })

        advisor.maybe_advise(self.user, project, self.database)

        advice = next(a for a in project.advices
                      if a.advice_id == 'seasonal-relocate')
        self.assertEqual(project_pb2.ADVICE_RECOMMENDED, advice.status)
        self.assertEqual(2, len(advice.seasonal_data.departement_stats))
        first_dep = advice.seasonal_data.departement_stats[0]
        self.assertEqual('06', first_dep.departement_id)
        self.assertEqual(900, first_dep.departement_seasonal_offers)
        self.assertEqual(2, len(first_dep.job_groups))
        self.assertEqual('I1202', first_dep.job_groups[0].rome_id)
        self.assertEqual('Professeur de piano', first_dep.job_groups[0].name)
        self.assertEqual(123, first_dep.job_groups[0].offers)