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