def _get_improve_cv_vars(user: user_pb2.User, *, now: datetime.datetime, **unused_kwargs: Any) -> dict[str, Any]: """Compute vars for the "Improve your CV" email.""" if user_profile_pb2.RESUME not in user.profile.frustrations: raise campaign.DoNotSend('User is not frustrated by its CV') if not user.projects: raise scoring.NotEnoughDataException('No project yet', {'projects.0'}) project = user.projects[0] if project.kind == project_pb2.FIND_A_FIRST_JOB: has_experience = 'False' elif project.kind in (project_pb2.FIND_A_NEW_JOB, project_pb2.FIND_ANOTHER_JOB): has_experience = 'True' else: has_experience = '' deep_link_advice_url = \ campaign.get_deep_link_advice(user.user_id, project, 'improve-resume') or \ campaign.get_deep_link_advice(user.user_id, project, 'fresh-resume') return campaign.get_default_coaching_email_vars(user) | { 'deepLinkAdviceUrl': deep_link_advice_url, 'hasExperience': has_experience, 'isSeptember': campaign.as_template_boolean(now.month == 9), 'loginUrl': campaign.create_logged_url(user.user_id) }
def _get_short_diploma_vars(user: user_pb2.User, *, database: mongo.NoPiiMongoDatabase, **unused_kwargs: Any) -> dict[str, Any]: if not user.projects: raise scoring.NotEnoughDataException('No project yet', {'projects.0'}) project = user.projects[0] if user.projects[0].diagnostic.category_id != 'missing-diploma': raise campaign.DoNotSend('The user has no missing-diploma category') scoring_project = scoring.ScoringProject(project, user, database) login_url = campaign.create_logged_url(user.user_id, f'/projet/{project.project_id}') # TODO(sil): Let's check if this is needed to have access to the method. if not project.target_job.job_group.rome_id: raise scoring.NotEnoughDataException( 'Need a job group to find trainings', # TODO(pascal): Use project_id instead of 0. {'projects.0.targetJob.jobGroup.romeId'}) deep_link_training_url = \ campaign.get_deep_link_advice(user.user_id, project, 'training') return campaign.get_default_coaching_email_vars(user) | { 'deepTrainingAdviceUrl': deep_link_training_url, 'ofJobName': scoring_project.populate_template('%ofJobName'), 'productUrl': f'{login_url}?utm_source=bob-emploi&utm_medium=email', }
def _make_application_mode_section( best_application_mode: Optional[job_pb2.ModePercentage], project: project_pb2.Project, user_id: str, scoring_project: scoring.ScoringProject) -> Optional[dict[str, str]]: if not best_application_mode or best_application_mode.mode == job_pb2.OTHER_CHANNELS: return None application_mode_advice = '' if best_application_mode.mode == job_pb2.SPONTANEOUS_APPLICATION: application_mode_advice = 'spontaneous-application' elif best_application_mode.mode == job_pb2.PERSONAL_OR_PROFESSIONAL_CONTACTS: application_mode_advice = next(( advice.advice_id for advice in project.advices if advice.advice_id.startswith('network')), '') application_mode_link = '' if application_mode_advice: application_mode_link = campaign.get_deep_link_advice( user_id, project, application_mode_advice) return { 'link': application_mode_link, 'title': scoring_project.translate_static_string( _APPLICATION_MODES_SHORT[best_application_mode.mode]), 'name': scoring_project.translate_static_string( scoring.APPLICATION_MODES[best_application_mode.mode]), 'percent': str(round(best_application_mode.percentage)), }
def test_get_deep_link_missing_advice(self) -> None: """Test the deep link.""" project = project_pb2.Project() project.project_id = '0' project.advices.add().advice_id = 'improve-interview' deep_link = campaign.get_deep_link_advice('my-user-id', project, 'improve-cv') self.assertFalse(deep_link)
def test_get_deep_link_advice(self) -> None: """Test the deep link.""" project = project_pb2.Project() project.project_id = '0' project.advices.add().advice_id = 'improve-cv' deep_link = campaign.get_deep_link_advice('my-user-id', project, 'improve-cv') self.assertRegex( deep_link, '^' + re.escape( 'https://www.bob-emploi.fr/projet/0/methode/improve-cv?'), )
def _get_galita3_vars(user: user_pb2.User, **unused_kwargs: Any) -> dict[str, str]: if user_profile_pb2.NO_OFFER_ANSWERS not in user.profile.frustrations: raise campaign.DoNotSend( 'User is getting enough answers from recruiters.') # We set a string with a blank as this is the only way to exclude a section # on Passport except to check equality or inequality with a non-empty # string. deep_link_to_follow_up_advice = ' ' if user.projects: for project in user.projects: link = campaign.get_deep_link_advice(user.user_id, project, 'follow-up') if link: deep_link_to_follow_up_advice = link return campaign.get_default_coaching_email_vars(user) | { 'deepLinkToAdvice': deep_link_to_follow_up_advice, }
def _get_prepare_your_application_vars(user: user_pb2.User, **unused_kwargs: Any) -> dict[str, Any]: """Compute vars for the "Prepare your application" email.""" if not user.projects: raise scoring.NotEnoughDataException('No project yet', {'projects.0'}) project = user.projects[0] deep_link_motivation_email_url = \ campaign.get_deep_link_advice(user.user_id, project, 'motivation-email') return campaign.get_default_coaching_email_vars(user) | { 'deepLinkMotivationEmailUrl': deep_link_motivation_email_url, 'hasInterviewFrustration': campaign.as_template_boolean(user_profile_pb2.INTERVIEW in user.profile.frustrations), 'hasSelfConfidenceFrustration': campaign.as_template_boolean(user_profile_pb2.SELF_CONFIDENCE in user.profile.frustrations), 'loginUrl': campaign.create_logged_url(user.user_id, f'/projet/{project.project_id}'), }
def _get_find_diploma_vars(user: user_pb2.User, *, database: mongo.NoPiiMongoDatabase, **unused_kwargs: Any) -> dict[str, Any]: """Compute vars for the "Prepare your application" email.""" if not user.projects: raise scoring.NotEnoughDataException('No project yet', {'projects.0'}) project = user.projects[0] scoring_project = scoring.ScoringProject(project, user, database) if not any(s.strategy_id == 'get-diploma' for s in project.opened_strategies): raise campaign.DoNotSend( 'The user has not started a strategy to get a diploma') if not project.target_job.job_group.rome_id: raise scoring.NotEnoughDataException( 'Need a job group to find trainings', # TODO(pascal): Use project_id instead of 0. {'projects.0.targetJob.jobGroup.romeId'}) trainings = scoring_project.get_trainings()[:3] deep_link_training_url = \ campaign.get_deep_link_advice(user.user_id, project, 'training') return campaign.get_default_coaching_email_vars(user) | { 'deepTrainingAdviceUrl': deep_link_training_url, 'inDepartement': scoring_project.populate_template('%inDepartement'), 'loginUrl': campaign.create_logged_url(user.user_id, f'/projet/{project.project_id}'), 'numTrainings': len(trainings), 'ofJobName': scoring_project.populate_template('%ofJobName'), 'trainings': [json_format.MessageToDict(t) for t in trainings], }
def _get_post_covid_vars(user: user_pb2.User, *, database: mongo.NoPiiMongoDatabase, **unused_kwargs: Any) -> dict[str, str]: if not user.projects: raise scoring.NotEnoughDataException( 'Project is required.', fields={'user.projects.0.advices'}) project = user.projects[0] scoring_project = scoring.ScoringProject(project, user, database) if scoring_project.job_group_info().covid_risk != job_pb2.COVID_RISKY: raise campaign.DoNotSend("The user's project job is not covid risky.") try: network_advice_link = next( campaign.get_deep_link_advice(user.user_id, project, a.advice_id) for a in project.advices if a.advice_id.startswith('network-application')) except StopIteration: raise campaign.DoNotSend('No network-application advice found for the user.')\ from None return campaign.get_default_coaching_email_vars(user) | { 'deepLinkAdviceUrl': network_advice_link, 'ofJobName': scoring_project.populate_template('%ofJobName'), }
def _christmas_vars(user: user_pb2.User, *, now: datetime.datetime, database: mongo.NoPiiMongoDatabase, **unused_kwargs: Any) -> dict[str, str]: """Compute all variables required for the Christmas campaign.""" if now.month != 12 and not user.features_enabled.alpha: raise campaign.DoNotSend('Only send christmas email in December') project = next((p for p in user.projects), project_pb2.Project()) job_search_started_months_ago = campaign.job_search_started_months_ago( project, now) if job_search_started_months_ago < 0: started_searching_since = '' elif job_search_started_months_ago < 2: started_searching_since = 'depuis peu' else: try: num_months = french.try_stringify_number( round(job_search_started_months_ago)) started_searching_since = f'depuis {num_months} mois' except NotImplementedError: started_searching_since = 'depuis un moment' # A city to commute to. commute_city = next( (city for a in project.advices for city in a.commute_data.cities), '') if commute_city: commute_city = french.in_city(commute_city) commute_advice_url = campaign.get_deep_link_advice(user.user_id, project, 'commute') if not commute_advice_url: commute_city = '' # A departement to relocate to. relocate_departement = next( (departement.name for a in project.advices for departement in a.relocate_data.departement_scores), '') if relocate_departement: try: departement_id = geo.get_departement_id(database, relocate_departement) relocate_departement = geo.get_in_a_departement_text( database, departement_id) except KeyError: relocate_departement = '' relocate_advice_url = campaign.get_deep_link_advice( user.user_id, project, 'relocate') if not relocate_advice_url: relocate_departement = '' # Whether the job may have freelancers. job_group_info = jobs.get_group_proto(database, project.target_job.job_group.rome_id) could_freelance = job_group_info and job_group_info.has_freelancers return campaign.get_default_coaching_email_vars(user) | { 'adviceUrlBodyLanguage': campaign.get_deep_link_advice(user.user_id, project, 'body-language'), 'adviceUrlCommute': commute_advice_url, 'adviceUrlCreateYourCompany': campaign.get_deep_link_advice(user.user_id, project, 'create-your-company'), 'adviceUrlExploreOtherJobs': campaign.get_deep_link_advice(user.user_id, project, 'explore-other-jobs'), 'adviceUrlImproveInterview': campaign.get_deep_link_advice(user.user_id, project, 'improve-interview'), 'adviceUrlRelocate': relocate_advice_url, 'adviceUrlVolunteer': campaign.get_deep_link_advice(user.user_id, project, 'volunteer'), 'couldFreelance': campaign.as_template_boolean(could_freelance), 'emailInUrl': parse.quote(user.profile.email), 'inCommuteCity': commute_city, 'inRelocateDepartement': relocate_departement, 'nextYear': str(now.year + 1), 'startedSearchingSince': started_searching_since, 'year': str(now.year), }