Esempio n. 1
0
def new_diagnostic_vars(user: user_pb2.User,
                        **unused_kwargs: Any) -> Dict[str, str]:
    """Compute vars for the "New Diagnostic"."""

    frustrations_set = set(user.profile.frustrations)
    frustrations_vars = {
        f'frustration_{name}':
        campaign.as_template_boolean(key in frustrations_set)
        for name, key in user_pb2.Frustration.items()
    }
    age = datetime.date.today().year - user.profile.year_of_birth
    has_children = user.profile.family_situation in {
        user_pb2.FAMILY_WITH_KIDS,
        user_pb2.SINGLE_PARENT_SITUATION,
    }
    survey_token = parse.quote(
        auth.create_token(user.user_id, role='employment-status'))
    auth_token = parse.quote(
        auth.create_token(user.user_id, is_using_timestamp=True))
    redirect_url = f'{campaign.BASE_URL}/statut/ne-recherche-plus'
    return dict(
        dict(frustrations_vars, **campaign.get_default_vars(user)), **{
            'mayHaveSeekingChildren':
            campaign.as_template_boolean(has_children and age >= 45),
            'loginUrl':
            f'{campaign.BASE_URL}?userId={user.user_id}&authToken={auth_token}',
            'stopSeekingUrl':
            f'{campaign.BASE_URL}/api/employment-status?user={user.user_id}&token={survey_token}&'
            f'seeking=STOP_SEEKING&redirect={parse.quote(redirect_url)}',
        })
Esempio n. 2
0
def _get_improve_cv_vars(
        user: user_pb2.User, now: datetime.datetime,
        **unused_kwargs: Any) -> Optional[Dict[str, Any]]:
    """Compute vars for the "Improve your CV" email."""

    if user_pb2.RESUME not in user.profile.frustrations:
        logging.info('User is not frustrated by its CV')
        return None

    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')

    auth_token = parse.quote(auth.create_token(user.user_id, is_using_timestamp=True))
    return dict(campaign.get_default_coaching_email_vars(user), **{
        'deepLinkAdviceUrl': deep_link_advice_url,
        'hasExperience': has_experience,
        'isSeptember': campaign.as_template_boolean(now.month == 9),
        'loginUrl': f'{campaign.BASE_URL}?userId={user.user_id}&authToken={auth_token}',
    })
Esempio n. 3
0
def _get_vars(user: user_pb2.User,
              **unused_kwargs: Any) -> Optional[Dict[str, str]]:
    """Compute vars for one user's email."""

    project = next((p for p in user.projects), project_pb2.Project())
    area_type = project.area_type

    is_local = False
    if not area_type:
        return None
    city = project.city
    if area_type < geo_pb2.COUNTRY:
        if city.region_id != '93':
            return None
        if area_type < geo_pb2.REGION:
            if city.departement_id != '13':
                return None
            if area_type < geo_pb2.DEPARTEMENT:
                if city.city_id != '13004':
                    return None
                is_local = True

    return dict(
        campaign.get_default_vars(user), **{
            'improveInterviewAdviceUrl':
            campaign.get_deep_link_advice(user.user_id, project,
                                          'improve-interview'),
            'isLocal':
            campaign.as_template_boolean(is_local),
        })
def _get_prepare_your_application_vars(
        user: user_pb2.User, **unused_kwargs: Any) -> Optional[Dict[str, Any]]:
    """Compute vars for the "Prepare your application" email."""

    project = user.projects[0]

    deep_link_motivation_email_url = \
        campaign.get_deep_link_advice(user.user_id, project, 'motivation-email')

    return dict(campaign.get_default_coaching_email_vars(user), **{
        'deepLinkMotivationEmailUrl': deep_link_motivation_email_url,
        'hasInterviewFrustration':
        campaign.as_template_boolean(user_pb2.INTERVIEW in user.profile.frustrations),
        'hasSelfConfidenceFrustration':
        campaign.as_template_boolean(user_pb2.SELF_CONFIDENCE in user.profile.frustrations),
        'loginUrl': campaign.create_logged_url(user.user_id, f'/projet/{project.project_id}'),
    })
Esempio n. 5
0
def _make_months_section(months):
    active_months = [
        _FRENCH_MONTHS[month] for month in months if month in _FRENCH_MONTHS
    ]
    if not active_months:
        return None
    return {
        'activeMonths': ' - '.join(active_months),
        'onlyOneMonth': campaign.as_template_boolean(len(active_months) == 1),
    }
Esempio n. 6
0
def _make_months_section(
        months: Iterable['job_pb2.Month']) -> Optional[Dict[str, str]]:
    active_months = [
        _FRENCH_MONTHS[month] for month in months if month in _FRENCH_MONTHS
    ]
    if not active_months:
        return None
    return {
        'activeMonths': ' - '.join(active_months),
        'onlyOneMonth': campaign.as_template_boolean(len(active_months) == 1),
    }
Esempio n. 7
0
def body_language_vars(user, unused_db=None):
    """Compute vars for a given user for the body language email.

    Returns:
        a dict with all vars required for the template, or None if no email
        should be sent.
    """

    if not user.projects:
        logging.info('User has no project')
        return None

    registered_months_ago = campaign.get_french_months_ago(
        user.registered_at.ToDatetime())
    if not registered_months_ago:
        logging.info('User registered only recently (%s)', user.registered_at)
        return None

    has_read_last_focus_email = any(email.status in _READ_EMAIL_STATUSES
                                    for email in user.emails_sent
                                    if email.campaign_id.startswith('focus-'))

    worst_frustration = next(
        (user_pb2.Frustration.Name(frustration)
         for frustration in (user_pb2.SELF_CONFIDENCE, user_pb2.INTERVIEW,
                             user_pb2.ATYPIC_PROFILE)
         if frustration in user.profile.frustrations), '')
    if not worst_frustration:
        return None

    unsubscribe_token = parse.quote(
        auth.create_token(user.profile.email, role='unsubscribe'))

    return {
        'firstName':
        french.cleanup_firstname(user.profile.name),
        'gender':
        user_pb2.Gender.Name(user.profile.gender),
        'hasReadLastFocusEmail':
        campaign.as_template_boolean(has_read_last_focus_email),
        'registeredMonthsAgo':
        registered_months_ago,
        'unsubscribeLink':
        '{}/unsubscribe.html?email={}&auth={}'.format(
            campaign.BASE_URL, parse.quote(user.profile.email),
            unsubscribe_token),
        'worstFrustration':
        worst_frustration,
    }
Esempio n. 8
0
def _get_galita2_vars(user: user_pb2.User,
                      **unused_kwargs: Any) -> Optional[Dict[str, str]]:
    if not user.projects:
        return None
    project = user.projects[0]
    if project.kind not in {project_pb2.FIND_A_FIRST_JOB, project_pb2.REORIENTATION} and \
            project.previous_job_similarity != project_pb2.NEVER_DONE:
        return None
    genderized_job_name = french.lower_first_letter(
        french.genderize_job(project.target_job, user.profile.gender))
    return dict(
        campaign.get_default_coaching_email_vars(user), **{
            'isReorienting':
            campaign.as_template_boolean(
                project.kind == project_pb2.REORIENTATION),
            'ofJobName':
            french.maybe_contract_prefix('de ', "d'", genderized_job_name)
        })
Esempio n. 9
0
def new_diagnostic_vars(user, unused_db=None):
    """Compute vars for the "New Diagnostic"."""

    unsubscribe_token = parse.quote(
        auth.create_token(user.profile.email, role='unsubscribe'))
    frustrations_vars = {
        'frustration_{}'.format(user_pb2.Frustration.Name(f)): 'True'
        for f in user.profile.frustrations
    }
    age = datetime.date.today().year - user.profile.year_of_birth
    has_children = user.profile.family_situation in {
        user_pb2.FAMILY_WITH_KIDS,
        user_pb2.SINGLE_PARENT_SITUATION,
    }
    survey_token = parse.quote(
        auth.create_token(user.user_id, role='employment-status'))
    auth_token = parse.quote(
        auth.create_token(user.user_id, is_using_timestamp=True))
    return dict(
        frustrations_vars, **{
            'firstName':
            french.cleanup_firstname(user.profile.name),
            'gender':
            user_pb2.Gender.Name(user.profile.gender),
            'mayHaveSeekingChildren':
            campaign.as_template_boolean(has_children and age >= 45),
            'loginUrl':
            '{}?userId={}&authToken={}'.format(campaign.BASE_URL, user.user_id,
                                               auth_token),
            'stopSeekingUrl':
            '{}/api/employment-status?user={}&token={}&seeking={}&redirect={}'.
            format(
                campaign.BASE_URL,
                user.user_id,
                survey_token,
                'STOP_SEEKING',
                parse.quote('{}/statut/ne-recherche-plus'.format(
                    campaign.BASE_URL)),
            ),
            'unsubscribeLink':
            '{}/unsubscribe.html?email={}&auth={}'.format(
                campaign.BASE_URL, parse.quote(user.profile.email),
                unsubscribe_token),
        })
Esempio n. 10
0
def _get_self_development_vars(user: user_pb2.User, now: datetime.datetime, **unused_kwargs: Any) \
        -> Optional[Dict[str, str]]:
    """Compute vars for a given user for the self-development email.

    Returns:
        a dict with all vars required for the template, or None if no email
        should be sent.
    """

    project = user.projects[0]

    job_search_length = campaign.job_search_started_months_ago(project, now)
    if job_search_length < 0:
        logging.info('No info on user search duration')
        return None

    if job_search_length > 12:
        logging.info('User has been searching for too long (%s)',
                     job_search_length)
        return None

    genderized_job_name = french.lower_first_letter(
        french.genderize_job(project.target_job, user.profile.gender))
    age = datetime.date.today().year - user.profile.year_of_birth

    max_young = 30
    min_old = 50

    return dict(
        campaign.get_default_coaching_email_vars(user), **{
            'hasEnoughExperience':
            campaign.as_template_boolean(
                project.seniority > project_pb2.JUNIOR),
            'isAdministrativeAssistant':
            campaign.as_template_boolean(
                project.target_job.job_group.name == 'Secrétariat'),
            'isOld':
            campaign.as_template_boolean(age >= min_old),
            'isOldNotWoman':
            campaign.as_template_boolean(
                age >= min_old and user.profile.gender != user_pb2.FEMININE),
            'isYoung':
            campaign.as_template_boolean(age <= max_young),
            'isYoungNotWoman':
            campaign.as_template_boolean(
                age <= max_young and user.profile.gender != user_pb2.FEMININE),
            'jobName':
            genderized_job_name,
            'ofJobName':
            french.maybe_contract_prefix('de ', "d'", genderized_job_name),
        })
Esempio n. 11
0
def _make_departements_section(user_departement_id, best_departements,
                               area_type, database):
    if area_type < geo_pb2.COUNTRY or not best_departements:
        return None
    best_departements_title = '<br />'.join(
        geo.get_departement_name(database, dep) for dep in best_departements)
    try:
        best_departements.remove(user_departement_id)
        is_best_departement = True
    except ValueError:
        is_best_departement = False
    best_departements_sentence = ' et '.join(
        geo.get_in_a_departement_text(database, dep)
        for dep in best_departements)
    return {
        'count': str(len(best_departements)),
        'isInBest': campaign.as_template_boolean(is_best_departement),
        'title': best_departements_title,
        'sentence': best_departements_sentence,
    }
Esempio n. 12
0
def _get_vars(user, unused_database):
    """Compute vars for one user's email."""

    project = next((p for p in user.projects), project_pb2.Project())

    is_local = False
    if not project.mobility.area_type:
        return
    if project.mobility.area_type < geo_pb2.COUNTRY:
        if project.mobility.city.region_id != '93':
            return
        if project.mobility.area_type < geo_pb2.REGION:
            if project.mobility.city.departement_id != '13':
                return
            if project.mobility.area_type < geo_pb2.DEPARTEMENT:
                if project.mobility.city.city_id != '13004':
                    return
                is_local = True

    return dict(campaign.get_default_vars(user), **{
        'isLocal': campaign.as_template_boolean(is_local),
    })
Esempio n. 13
0
def _open_classrooms_vars(user: user_pb2.User,
                          database: Optional[pymongo.database.Database] = None,
                          **unused_kwargs: Any) -> Optional[Dict[str, str]]:
    """Template variables for viral sharing emails."""

    if user.registered_at.ToDatetime() < _SIX_MONTHS_AGO:
        return None

    age = datetime.date.today().year - user.profile.year_of_birth
    if age < 18 or age > 54:
        return None
    if user.profile.highest_degree > job_pb2.BAC_BACPRO:
        return None

    if user.employment_status and user.employment_status[
            -1].seeking != user_pb2.STILL_SEEKING:
        return None
    # User has not project.
    if not (user.projects and user.projects[0]):
        return None

    # If the user is happy with their job (no reorientation and enthusiastic about their job)
    project = user.projects[0]
    if project.kind != project_pb2.REORIENTATION and not (
            project.kind == project_pb2.FIND_A_NEW_JOB
            and project.passionate_level == project_pb2.ALIMENTARY_JOB):
        return None

    has_children = user.profile.family_situation in {
        user_pb2.FAMILY_WITH_KIDS,
        user_pb2.SINGLE_PARENT_SITUATION,
    }

    assert database
    job_group_info = jobs.get_group_proto(database,
                                          project.target_job.job_group.rome_id)
    if not job_group_info:
        return None

    return dict(
        campaign.get_default_coaching_email_vars(user), **{
            'hasAtypicProfile':
            campaign.as_template_boolean(
                user_pb2.ATYPIC_PROFILE in user.profile.frustrations),
            'hasFamilyAndManagementIssue':
            campaign.as_template_boolean(
                has_children
                and user_pb2.TIME_MANAGEMENT in user.profile.frustrations),
            'hasSeniority':
            campaign.as_template_boolean(
                project.seniority > project_pb2.INTERMEDIARY),
            'hasSimpleApplication':
            campaign.as_template_boolean(
                job_group_info.application_complexity ==
                job_pb2.SIMPLE_APPLICATION_PROCESS),
            'isReorienting':
            campaign.as_template_boolean(
                project.kind == project_pb2.REORIENTATION),
            'isFrustratedOld':
            campaign.as_template_boolean(
                age >= 40
                and user_pb2.AGE_DISCRIMINATION in user.profile.frustrations),
            'ofFirstName':
            french.maybe_contract_prefix('de ', "d'", user.profile.name)
        })
Esempio n. 14
0
def self_development_vars(user, unused_db=None):
    """Compute vars for a given user for the self-development email.

    Returns:
        a dict with all vars required for the template, or None if no email
        should be sent.
    """

    if not user.projects:
        logging.info('User has no project')
        return None
    project = user.projects[0]

    registered_months_ago = campaign.get_french_months_ago(
        user.registered_at.ToDatetime())
    if not registered_months_ago:
        logging.info('User registered only recently (%s)', user.registered_at)
        return None

    job_search_length = campaign.job_search_started_months_ago(project)
    if job_search_length < 0:
        logging.info('No info on user search duration')
        return None

    if job_search_length >= 12:
        logging.info('User has been searching for too long (%s)',
                     job_search_length)
        return None

    genderized_job_name = french.lower_first_letter(
        french.genderize_job(project.target_job, user.profile.gender))
    age = datetime.date.today().year - user.profile.year_of_birth
    unsubscribe_token = parse.quote(
        auth.create_token(user.profile.email, role='unsubscribe'))

    max_young = 30
    min_old = 50

    return {
        'firstName':
        french.cleanup_firstname(user.profile.name),
        'gender':
        user_pb2.Gender.Name(user.profile.gender),
        'hasEnoughExperience':
        campaign.as_template_boolean(project.seniority > project_pb2.JUNIOR),
        'isAdministrativeAssistant':
        campaign.as_template_boolean(
            project.target_job.job_group.name == 'Secrétariat'),
        'isOld':
        campaign.as_template_boolean(age >= min_old),
        'isOldNotWoman':
        campaign.as_template_boolean(
            age >= min_old and user.profile.gender != user_pb2.FEMININE),
        'isYoung':
        campaign.as_template_boolean(age <= max_young),
        'isYoungNotWoman':
        campaign.as_template_boolean(
            age <= max_young and user.profile.gender != user_pb2.FEMININE),
        'jobName':
        genderized_job_name,
        'ofJobName':
        french.maybe_contract_prefix('de ', "d'", genderized_job_name),
        'registeredMonthsAgo':
        registered_months_ago,
        'unsubscribeLink':
        '{}/unsubscribe.html?email={}&auth={}'.format(
            campaign.BASE_URL, parse.quote(user.profile.email),
            unsubscribe_token),
    }
Esempio n. 15
0
def imt_vars(user, database):
    """Compute vars for the "IMT" email."""

    if not user.projects:
        logging.info('User has no project')
        return None
    project = user.projects[0]

    genderized_job_name = french.lower_first_letter(
        french.genderize_job(project.target_job, user.profile.gender))

    departement_id = project.mobility.city.departement_id
    rome_id = project.target_job.job_group.rome_id
    diagnosis_key = '{}:{}'.format(departement_id, rome_id)
    local_diagnosis = _LOCAL_DIAGNOSIS.get_collection(database).get(
        diagnosis_key)
    if not local_diagnosis:
        logging.info('User market does not exist')
        return None
    imt = local_diagnosis.imt
    if not imt:
        logging.info('User market has no IMT data')
        return None

    shown_sections = 0

    market_stress_section = _make_market_stress_section(
        imt.yearly_avg_offers_per_10_candidates)
    if market_stress_section:
        shown_sections += 1

    application_modes_section = _make_application_mode_section(
        campaign.get_application_modes(rome_id, database), project.advices,
        user.user_id)
    if application_modes_section:
        shown_sections += 1

    departements_section = _make_departements_section(
        project.mobility.city.departement_id,
        _get_best_departements_for_job_group(rome_id, database),
        project.mobility.area_type, database)
    if departements_section:
        shown_sections += 1

    employment_types_section = _make_employment_type_section(
        sorted(imt.employment_type_percentages, key=lambda e: e.percentage))
    if employment_types_section:
        shown_sections += 1

    months_section = _make_months_section(imt.active_months)
    if months_section:
        shown_sections += 1

    if shown_sections < 3:
        logging.info('Only %d section(s) to be shown for user.',
                     shown_sections)
        return None

    imt_link = 'http://candidat.pole-emploi.fr/marche-du-travail/statistiques?' + \
        'codeMetier={}&codeZoneGeographique={}&typeZoneGeographique=DEPARTEMENT'.format(
            project.target_job.code_ogr, departement_id)

    job_name_in_departement = '{} {}'.format(
        genderized_job_name,
        geo.get_in_a_departement_text(database,
                                      project.mobility.city.departement_id))

    return dict(
        campaign.get_default_vars(user), **{
            'applicationModes':
            _make_section(application_modes_section),
            'departements':
            _make_section(departements_section),
            'employmentType':
            _make_section(employment_types_section),
            'imtLink':
            imt_link,
            'inCity':
            french.in_city(project.mobility.city.name),
            'jobNameInDepartement':
            job_name_in_departement,
            'loginUrl':
            campaign.create_logged_url(user.user_id),
            'marketStress':
            _make_section(market_stress_section),
            'months':
            _make_section(months_section),
            'ofJobNameInDepartement':
            french.maybe_contract_prefix('de ', "d'", job_name_in_departement),
            'ofJobName':
            french.maybe_contract_prefix('de ', "d'", genderized_job_name),
            'showPs':
            campaign.as_template_boolean(
                _can_go_to_arles_hotellerie_event(rome_id, project.mobility)),
            'statusUpdateUrl':
            campaign.get_status_update_link(user.user_id, user.profile),
        })
Esempio n. 16
0
def _make_section(values):
    return dict({'showSection': campaign.as_template_boolean(values)},
                **(values or {}))
Esempio n. 17
0
def christmas_vars(user: user_pb2.User,
                   now: datetime.datetime,
                   database: Optional[pymongo.database.Database] = None,
                   **unused_kwargs: Any) -> Optional[Dict[str, str]]:
    """Compute all variables required for the Christmas campaign."""

    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), '')
    assert database
    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 dict(
        campaign.get_default_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'),
            'adviceUrlImproveInterview':
            campaign.get_deep_link_advice(user.user_id, project,
                                          'improve-interview'),
            'adviceUrlRelocate':
            relocate_advice_url,
            'couldFreelance':
            campaign.as_template_boolean(could_freelance),
            'emailInUrl':
            parse.quote(user.profile.email),
            'inCommuteCity':
            commute_city,
            'inRelocateDepartement':
            relocate_departement,
            'startedSearchingSince':
            started_searching_since,
        })
Esempio n. 18
0
def spontaneous_vars(user, previous_email_campaign_id):
    """Compute vars for a given user for the spontaneous email.

    Returns:
        a dict with all vars required for the template, or None if no email
        should be sent.
    """

    if not user.projects:
        logging.info('User has no project')
        return None
    project = user.projects[0]

    job_group_info = jobs.get_group_proto(_DB,
                                          project.target_job.job_group.rome_id)

    def _should_use_spontaneous(modes):
        return any(mode.mode == job_pb2.SPONTANEOUS_APPLICATION
                   and mode.percentage > 20 for mode in modes.modes)

    application_modes = job_group_info.application_modes
    if not any(
            _should_use_spontaneous(modes)
            for modes in application_modes.values()):
        return None

    registered_months_ago = campaign.get_french_months_ago(
        user.registered_at.ToDatetime())
    if not registered_months_ago:
        logging.warning('User registered only recently (%s)',
                        user.registered_at)
        return None

    has_read_previous_email = previous_email_campaign_id and any(
        email.campaign_id == previous_email_campaign_id and email.status in
        (user_pb2.EMAIL_SENT_OPENED, user_pb2.EMAIL_SENT_CLICKED)
        for email in user.emails_sent)

    contact_mode = job_group_info.preferred_application_medium
    if not contact_mode:
        logging.error('There is no contact mode for the job group "%s"',
                      project.target_job.job_group.rome_id)
        return None
    contact_mode = job_pb2.ApplicationMedium.Name(contact_mode).replace(
        'APPLY_', '')

    in_a_workplace = job_group_info.in_a_workplace
    if not in_a_workplace and contact_mode != 'BY_EMAIL':
        logging.error(
            'There is no "in_a_workplace" field for the job group "%s".',
            project.target_job.job_group.rome_id)
        return None

    like_your_workplace = job_group_info.like_your_workplace
    if in_a_workplace and not like_your_workplace:
        logging.error(
            'There is no "like_your_workplace" field for the job group "%s".',
            project.target_job.job_group.rome_id)
        return None

    to_the_workplace = job_group_info.to_the_workplace
    if not to_the_workplace:
        to_the_workplace = "à l'entreprise"

    some_companies = job_group_info.place_plural
    if not some_companies:
        some_companies = 'des entreprises'

    what_i_love_about = job_group_info.what_i_love_about
    if user.profile.gender == user_pb2.FEMININE:
        what_i_love_about_feminine = job_group_info.what_i_love_about_feminine
        if what_i_love_about_feminine:
            what_i_love_about = what_i_love_about_feminine
    if not what_i_love_about and contact_mode == 'BY_EMAIL':
        logging.error(
            'There is no "What I love about" field for the job group "%s".',
            project.target_job.job_group.rome_id)
        return None

    why_specific_company = job_group_info.why_specific_company
    if not why_specific_company:
        logging.error(
            'There is no "Why this specific company" field for the job group "%s".',
            project.target_job.job_group.rome_id)
        return None

    at_various_companies = job_group_info.at_various_companies

    if project.weekly_applications_estimate == project_pb2.SOME:
        weekly_application_count = '5'
    elif project.weekly_applications_estimate > project_pb2.SOME:
        weekly_application_count = '15'
    else:
        weekly_application_count = ''

    survey_token = parse.quote(
        auth.create_token(user.user_id, role='employment-status'))
    unsubscribe_token = parse.quote(
        auth.create_token(user.profile.email, role='unsubscribe'))
    return {
        'applicationComplexity':
        job_pb2.ApplicationProcessComplexity.Name(
            job_group_info.application_complexity),
        'atVariousCompanies':
        at_various_companies,
        'contactMode':
        contact_mode,
        'deepLinkLBB':
        'https://labonneboite.pole-emploi.fr/entreprises/commune/{}/rome/'
        '{}?utm_medium=web&utm_source=bob&utm_campaign=bob-email'.format(
            project.mobility.city.city_id,
            project.target_job.job_group.rome_id),
        'emailInUrl':
        parse.quote(user.profile.email),
        'experienceAsText':
        _EXPERIENCE_AS_TEXT.get(project.seniority, 'peu'),
        'firstName':
        french.cleanup_firstname(user.profile.name),
        'gender':
        user_pb2.Gender.Name(user.profile.gender),
        'hasReadPreviousEmail':
        campaign.as_template_boolean(has_read_previous_email),
        'inWorkPlace':
        in_a_workplace,
        'jobName':
        french.lower_first_letter(
            french.genderize_job(project.target_job, user.profile.gender)),
        'lastName':
        user.profile.last_name,
        'likeYourWorkplace':
        like_your_workplace,
        'registeredMonthsAgo':
        registered_months_ago,
        'someCompanies':
        some_companies,
        # TODO(cyrille): Use campaign.get_status_update_link
        'statusUpdateUrl':
        '{}/statut/mise-a-jour?user={}&token={}&gender={}'.format(
            campaign.BASE_URL, user.user_id, survey_token,
            user_pb2.Gender.Name(user.profile.gender)),
        'toTheWorkplace':
        to_the_workplace,
        'unsubscribeLink':
        '{}/unsubscribe.html?email={}&auth={}'.format(
            campaign.BASE_URL, parse.quote(user.profile.email),
            unsubscribe_token),
        'weeklyApplicationOptions':
        weekly_application_count,
        'whatILoveAbout':
        what_i_love_about,
        'whySpecificCompany':
        why_specific_company,
    }
Esempio n. 19
0
def network_plus_vars(user, database):
    """Compute vars for a given user for the network email.

    Returns:
        a dict with all vars required for the template, or None if no email
        should be sent.
    """

    if not user.projects:
        logging.info('User has no project')
        return None
    project = user.projects[0]

    registered_months_ago = campaign.get_french_months_ago(
        user.registered_at.ToDatetime())
    if not registered_months_ago:
        logging.warning('User registered only recently (%s)',
                        user.registered_at)
        return None

    job_group_info = jobs.get_group_proto(database,
                                          project.target_job.job_group.rome_id)
    in_target_domain = job_group_info.in_domain
    application_modes = job_group_info.application_modes.values()
    if not in_target_domain:
        logging.warning('Could not find a target domain (%s)',
                        project.target_job.job_group)
        return None

    fap_modes = [
        fap_modes.modes for fap_modes in application_modes
        if len(fap_modes.modes)
    ]
    if not fap_modes:
        return None
    flat_fap_modes = [mode for modes in fap_modes for mode in modes]
    network_percentages = [
        mode.percentage for mode in flat_fap_modes
        if (mode.mode == job_pb2.PERSONAL_OR_PROFESSIONAL_CONTACTS)
    ]
    # We want to focus on the user for which network,
    # as an application mode, has a substantial importance.
    if not network_percentages:
        return None
    average_network_percentage = sum(network_percentages) / len(
        network_percentages)
    if average_network_percentage < 55:
        network_application_importance = 'que la majorité'
    if average_network_percentage >= 45 and average_network_percentage <= 55:
        network_application_importance = 'que la moitié'
    if average_network_percentage >= 25 and average_network_percentage < 45:
        network_application_importance = "qu'un tiers"
    else:
        return None

    worst_frustration = next(
        (f for f in (user_pb2.SELF_CONFIDENCE, user_pb2.MOTIVATION)
         if f in user.profile.frustrations), None)
    has_children = user.profile.family_situation in {
        user_pb2.FAMILY_WITH_KIDS, user_pb2.SINGLE_PARENT_SITUATION
    }

    age = datetime.date.today().year - user.profile.year_of_birth
    max_young = 35

    return dict(
        campaign.get_default_vars(user), **{
            'frustration':
            user_pb2.Frustration.Name(worst_frustration)
            if worst_frustration else '',
            'hasChildren':
            campaign.as_template_boolean(has_children),
            'hasHandicap':
            campaign.as_template_boolean(user.profile.has_handicap),
            'hasHighSchoolDegree':
            campaign.as_template_boolean(
                user.profile.highest_degree >= job_pb2.BAC_BACPRO),
            'hasLargeNetwork':
            campaign.as_template_boolean(project.network_estimate >= 2),
            'hasWorkedBefore':
            campaign.as_template_boolean(
                project.kind != project_pb2.FIND_A_FIRST_JOB),
            'inCity':
            french.in_city(project.mobility.city.name),
            'inTargetDomain':
            in_target_domain,
            'isYoung':
            campaign.as_template_boolean(age <= max_young),
            'jobGroupInDepartement':
            '{} {}'.format(
                french.lower_first_letter(project.target_job.job_group.name),
                geo.get_in_a_departement_text(
                    database, project.mobility.city.departement_id)),
            'networkApplicationPercentage':
            network_application_importance,
        })
Esempio n. 20
0
def _make_section(values: Optional[Dict[str, str]]) -> Dict[str, str]:
    return dict({'showSection': campaign.as_template_boolean(bool(values))},
                **(values or {}))
Esempio n. 21
0
def network_plus_vars(user: user_pb2.User,
                      database: Optional[pymongo.database.Database] = None,
                      **unused_kwargs: Any) -> Optional[Dict[str, str]]:
    """Compute vars for a given user for the network email.

    Returns:
        a dict with all vars required for the template, or None if no email
        should be sent.
    """

    project = user.projects[0]

    if project.network_estimate < 2:
        logging.info('User does not have a strong network')
        return None

    assert database
    job_group_info = jobs.get_group_proto(database,
                                          project.target_job.job_group.rome_id)
    if not job_group_info:
        logging.warning('Could not find job group info for "%s"',
                        project.target_job.job_group.rome_id)
        return None
    in_target_domain = job_group_info.in_domain
    application_modes = job_group_info.application_modes.values()
    if not in_target_domain:
        logging.warning('Could not find a target domain (%s)',
                        project.target_job.job_group)
        return None

    fap_modes = [
        fap_modes.modes for fap_modes in application_modes
        if len(fap_modes.modes)
    ]
    if not fap_modes:
        return None
    flat_fap_modes = [mode for modes in fap_modes for mode in modes]
    network_percentages = [
        mode.percentage for mode in flat_fap_modes
        if (mode.mode == job_pb2.PERSONAL_OR_PROFESSIONAL_CONTACTS)
    ]
    # We want to focus on the user for which network,
    # as an application mode, has a substantial importance.
    if not network_percentages:
        return None
    average_network_percentage = sum(network_percentages) / len(
        network_percentages)
    if average_network_percentage > 55:
        network_application_importance = 'que la majorité'
    elif average_network_percentage >= 45:
        network_application_importance = 'que la moitié'
    elif average_network_percentage >= 25:
        network_application_importance = "qu'un tiers"
    else:
        return None

    worst_frustration = next(
        (f for f in (user_pb2.SELF_CONFIDENCE, user_pb2.MOTIVATION)
         if f in user.profile.frustrations), None)
    has_children = user.profile.family_situation in {
        user_pb2.FAMILY_WITH_KIDS, user_pb2.SINGLE_PARENT_SITUATION
    }

    age = datetime.date.today().year - user.profile.year_of_birth
    max_young = 35

    try:
        in_departement = geo.get_in_a_departement_text(
            database, project.city.departement_id)
    except KeyError:
        logging.warning('Could not find departement (%s)',
                        project.city.departement_id)
        return None

    job_group_name = french.lower_first_letter(
        project.target_job.job_group.name)

    return dict(
        campaign.get_default_coaching_email_vars(user), **{
            'frustration':
            user_pb2.Frustration.Name(worst_frustration)
            if worst_frustration else '',
            'hasChildren':
            campaign.as_template_boolean(has_children),
            'hasHighSchoolDegree':
            campaign.as_template_boolean(
                user.profile.highest_degree >= job_pb2.BAC_BACPRO),
            'hasLargeNetwork':
            campaign.as_template_boolean(project.network_estimate >= 2),
            'hasWorkedBefore':
            campaign.as_template_boolean(
                project.kind != project_pb2.FIND_A_FIRST_JOB),
            'inCity':
            french.in_city(project.city.name),
            'inTargetDomain':
            in_target_domain,
            'isAbleBodied':
            campaign.as_template_boolean(not user.profile.has_handicap),
            'isYoung':
            campaign.as_template_boolean(age <= max_young),
            'jobGroupInDepartement':
            f'{job_group_name} {in_departement}',
            'networkApplicationPercentage':
            network_application_importance,
        })