Example #1
0
def update_jobs_form():
    """
    Allow a recruiter to add or delete ROME codes related to his company.
    """
    # Use POST params if available, GET params otherwise.
    form_data = request.form or request.args.copy()

    try:
        office = models.Office.query.filter(models.Office.siret == form_data['siret']).one()
    except NoResultFound:
        flash(unknown_siret_message(), 'error')
        return redirect(url_for('contact_form.change_info'))

    if request.method == 'GET':

        # Prepare form's initial data.
        romes_to_boost = office.romes_codes
        romes_alternance_to_boost = office.romes_codes
        extra_romes_to_add = set()
        extra_romes_alternance_to_add = set()

        office_update = OfficeAdminUpdate.query.filter(OfficeAdminUpdate.sirets == office.siret).first()
        if office_update:
            if office_update.romes_to_boost:
                romes_to_boost = set(OfficeAdminUpdate.as_list(office_update.romes_to_boost))
                extra_romes_to_add = romes_to_boost - office.romes_codes
            if office_update.romes_alternance_to_boost:
                romes_alternance_to_boost = set(OfficeAdminUpdate.as_list(office_update.romes_alternance_to_boost))
                extra_romes_alternance_to_add = romes_alternance_to_boost - office.romes_codes

        form_data['romes_to_keep'] = romes_to_boost
        form_data['romes_alternance_to_keep'] = romes_alternance_to_boost

    else:
        # Those form fields are defined outside of the form class, we use `request.form` to get them.
        extra_romes_to_add = set(request.form.getlist('extra_romes_to_add'))
        extra_romes_alternance_to_add = set(request.form.getlist('extra_romes_alternance_to_add'))

    form = forms.OfficeUpdateJobsForm(data=form_data, office=office)

    if form.validate_on_submit():
        recruiter_message = models.UpdateJobsRecruiterMessage.create_from_form(
            form,
            is_certified_recruiter=peam_recruiter.is_certified_recruiter(),
            uid=peam_recruiter.get_recruiter_uid()
        )
        mail_content = mail.generate_update_jobs_mail(form, recruiter_message)

        try:
            mail.send_mail(mail_content, get_subject())
        except MailNoSendException as e:
            logger.exception(e)
            flash(generate_fail_flash_content(), 'error')

        params = request.args.to_dict()
        params.update({
            'custom_ga_pageview': '/recruteur/update_jobs/success',
            'suggest_update_coordinates': '1',
        })
        return redirect(url_for('contact_form.success', **params))

    extra_added_jobs = [
        {
            'rome_code': rome_code,
            'label': settings.ROME_DESCRIPTIONS[rome_code],
            'lbb': rome_code in extra_romes_to_add,
            'lba': rome_code in extra_romes_alternance_to_add,
        }
        for rome_code in extra_romes_to_add | extra_romes_alternance_to_add
    ]

    return render_template('contact_form/change_job_infos.html',
        title='Demande de modification des métiers',
        form=form,
        params=urlencode(get_office_identification_data()),
        use_lba_template=is_recruiter_from_lba(),
        extra_added_jobs=extra_added_jobs,
        custom_ga_pageview='/recruteur/update_jobs/update_jobs',
    )
Example #2
0
def update_offices():
    """
    Update offices (overload the data provided by the importer).
    """
    # Good engineering eliminates users being able to do the wrong thing as much as possible.
    # But since it is possible to store multiple SIRETs, there is no longer any constraint of uniqueness
    # on a SIRET. As a result, it shouldn't but there may be `n` entries in `OfficeAdminUpdate`
    # for the same SIRET. We order the query by creation date ASC so that the most recent changes take
    # priority over any older ones.
    for office_to_update in db_session.query(OfficeAdminUpdate).order_by(
            asc(OfficeAdminUpdate.date_created)).all():

        for siret in OfficeAdminUpdate.as_list(office_to_update.sirets):

            office = Office.query.filter_by(siret=siret).first()

            if office:
                # Apply changes in DB.
                office.company_name = office_to_update.new_company_name or office.company_name
                office.office_name = office_to_update.new_office_name or office.office_name
                office.email = '' if office_to_update.remove_email else (
                    office_to_update.new_email or office.email)
                office.tel = '' if office_to_update.remove_phone else (
                    office_to_update.new_phone or office.tel)
                office.website = '' if office_to_update.remove_website else (
                    office_to_update.new_website or office.website)

                office.email_alternance = office_to_update.email_alternance
                office.phone_alternance = office_to_update.phone_alternance
                office.website_alternance = office_to_update.website_alternance

                # Note : we need to handle when score and score_alternance = 0
                office.score = office_to_update.score if office_to_update.score is not None else office.score
                office.score_alternance = office_to_update.score_alternance if office_to_update.score_alternance is not None else office.score_alternance
                office.social_network = office_to_update.social_network
                office.contact_mode = office_to_update.contact_mode
                office.save()

                # Apply changes in ElasticSearch.
                body = {
                    'doc': {
                        'email': office.email,
                        'phone': office.tel,
                        'website': office.website,
                        'flag_alternance': 1 if office.flag_alternance else 0
                    }
                }

                scores_by_rome, scores_alternance_by_rome, boosted_romes, boosted_alternance_romes = get_scores_by_rome_and_boosted_romes(
                    office, office_to_update)
                if scores_by_rome:
                    body['doc']['scores_by_rome'] = scores_by_rome
                    body['doc']['boosted_romes'] = boosted_romes
                if scores_alternance_by_rome:
                    body['doc'][
                        'scores_alternance_by_rome'] = scores_alternance_by_rome
                    body['doc'][
                        'boosted_alternance_romes'] = boosted_alternance_romes

                # The update API makes partial updates: existing `scalar` fields are overwritten,
                # but `objects` fields are merged together.
                # https://www.elastic.co/guide/en/elasticsearch/guide/1.x/partial-updates.html
                # However `scores_by_rome` and `boosted_romes` need to be overwritten because they
                # may change over time.
                # To do this, we perform 2 requests: the first one resets `scores_by_rome` and
                # `boosted_romes` and the second one populates them.
                delete_body = {'doc': {}}
                delete_body = {
                    'doc': {
                        'scores_by_rome': None,
                        'boosted_romes': None,
                        'scores_alternance_by_rome': None,
                        'boosted_alternance_romes': None
                    }
                }

                # Unfortunately these cannot easily be bulked :-(
                # The reason is there is no way to tell bulk to ignore missing documents (404)
                # for a partial update. Tried it and failed it on Oct 2017 @vermeer.
                es.Elasticsearch().update(index=settings.ES_INDEX,
                                          doc_type=es.OFFICE_TYPE,
                                          id=siret,
                                          body=delete_body,
                                          params={'ignore': 404})
                es.Elasticsearch().update(index=settings.ES_INDEX,
                                          doc_type=es.OFFICE_TYPE,
                                          id=siret,
                                          body=body,
                                          params={'ignore': 404})

                # Delete the current PDF thus it will be regenerated at the next download attempt.
                pdf_util.delete_file(office)