toulouse-foederis: add candidature endpoint (#77524)
gitea/passerelle/pipeline/head This commit looks good
Details
gitea/passerelle/pipeline/head This commit looks good
Details
This commit is contained in:
parent
816da0f6b6
commit
7395fa5560
|
@ -30,6 +30,229 @@ from passerelle.utils.api import endpoint
|
||||||
from passerelle.utils.json import datasource_array_schema, datasource_schema, response_schema
|
from passerelle.utils.json import datasource_array_schema, datasource_schema, response_schema
|
||||||
|
|
||||||
|
|
||||||
|
def boolean_field(description):
|
||||||
|
return {
|
||||||
|
'description': description,
|
||||||
|
'oneOf': [
|
||||||
|
{'type': 'boolean'},
|
||||||
|
{
|
||||||
|
'type': 'string',
|
||||||
|
'pattern': '[Oo]|[Nn]|[Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee]|1|0',
|
||||||
|
'pattern_description': _(
|
||||||
|
'Values "0", "1", "O", "N", "true" or "false" are allowed (case insensitive).'
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def get_bool(obj):
|
||||||
|
if obj is True or str(obj).lower() in ['true', 'o', '1']:
|
||||||
|
return True
|
||||||
|
if obj is False or str(obj).lower() in ['false', 'n', '0']:
|
||||||
|
return False
|
||||||
|
return obj
|
||||||
|
|
||||||
|
|
||||||
|
APPLICATION_SCHEMA = {
|
||||||
|
'$schema': 'http://json-schema.org/draft-04/schema#',
|
||||||
|
'title': 'Toulouse Foederis application',
|
||||||
|
'description': '',
|
||||||
|
'type': 'object',
|
||||||
|
'properties': {
|
||||||
|
'type': {
|
||||||
|
'description': _('Application Type (External or Internal).'),
|
||||||
|
'type': 'string',
|
||||||
|
},
|
||||||
|
'announce_id': {
|
||||||
|
'description': _('ID of the concerned job offer.'),
|
||||||
|
'type': 'string',
|
||||||
|
'pattern': '^[0-9]*$',
|
||||||
|
},
|
||||||
|
'civility': {
|
||||||
|
'description': _("ID of an element of the data source 'civilite'."),
|
||||||
|
'type': 'string',
|
||||||
|
'pattern': '^[0-9]+$',
|
||||||
|
},
|
||||||
|
'first_name': {
|
||||||
|
'description': _('Applicant first name.'),
|
||||||
|
'type': 'string',
|
||||||
|
},
|
||||||
|
'last_name': {
|
||||||
|
'description': _('Applicant last name.'),
|
||||||
|
'type': 'string',
|
||||||
|
},
|
||||||
|
'gender': {
|
||||||
|
'description': _('Applicant gender.'),
|
||||||
|
'type': 'string',
|
||||||
|
'enum': ['H', 'F', ''],
|
||||||
|
},
|
||||||
|
'birth_date': {
|
||||||
|
'description': _('Applicant birth date.'),
|
||||||
|
'type': 'string',
|
||||||
|
'pattern': '^([0-9]{4}-[0-9]{2}-[0-9]{2})?$',
|
||||||
|
},
|
||||||
|
'nationality': {
|
||||||
|
'description': _("ID of an element of the data source 'nationalite'."),
|
||||||
|
'type': 'string',
|
||||||
|
'pattern': '^[0-9]+$',
|
||||||
|
},
|
||||||
|
'work_authorization_end_date': {
|
||||||
|
'description': _("Applicant end of working authorization, if nationality is 'other'."),
|
||||||
|
'example_value': '2023-04-05',
|
||||||
|
'type': 'string',
|
||||||
|
'pattern': '^([0-9]{4}-[0-9]{2}-[0-9]{2})?$',
|
||||||
|
},
|
||||||
|
'rqth': boolean_field(_('RQTH.')),
|
||||||
|
'rqth_end_date': {
|
||||||
|
'description': _('End of RQTH, or none if not applicable.'),
|
||||||
|
'type': 'string',
|
||||||
|
'pattern': '^([0-9]{4}-[0-9]{2}-[0-9]{2})?$',
|
||||||
|
},
|
||||||
|
'driving_license': {
|
||||||
|
'description': _('Driving license.'),
|
||||||
|
'type': 'string',
|
||||||
|
},
|
||||||
|
'fimo': boolean_field(_('FIMO licence.')),
|
||||||
|
'fimo_delivrance_date': {
|
||||||
|
'description': _('FIMO licence delivrance date.'),
|
||||||
|
'type': 'string',
|
||||||
|
'pattern': '^([0-9]{4}-[0-9]{2}-[0-9]{2})?$',
|
||||||
|
},
|
||||||
|
'fimo_end_validity_date': {
|
||||||
|
'description': _('FIMO licence end validity date.'),
|
||||||
|
'type': 'string',
|
||||||
|
'pattern': '^([0-9]{4}-[0-9]{2}-[0-9]{2})?$',
|
||||||
|
},
|
||||||
|
'current_situation': {
|
||||||
|
'description': _("ID of an element of the data source 'situation-actuelle'."),
|
||||||
|
'type': 'string',
|
||||||
|
'pattern': '^[0-9]+$',
|
||||||
|
},
|
||||||
|
'agent_collectivity': {
|
||||||
|
'description': _("Agent's collectivity"),
|
||||||
|
'type': 'string',
|
||||||
|
},
|
||||||
|
'availability_start_date': {
|
||||||
|
'description': _('Applicant availability start date.'),
|
||||||
|
'type': 'string',
|
||||||
|
'pattern': '^([0-9]{4}-[0-9]{2}-[0-9]{2})?$',
|
||||||
|
},
|
||||||
|
'availability_end_date': {
|
||||||
|
'description': _('Applicant availability end date.'),
|
||||||
|
'type': 'string',
|
||||||
|
'pattern': '^([0-9]{4}-[0-9]{2}-[0-9]{2})?$',
|
||||||
|
},
|
||||||
|
'salary_expectations': {
|
||||||
|
'description': _('Applicant salary expectations.'),
|
||||||
|
'type': 'string',
|
||||||
|
},
|
||||||
|
'address': {
|
||||||
|
'description': _('Applicant address.'),
|
||||||
|
'type': 'string',
|
||||||
|
},
|
||||||
|
'address_complement': {
|
||||||
|
'description': _('Applicant address complement.'),
|
||||||
|
'type': 'string',
|
||||||
|
},
|
||||||
|
'zip': {
|
||||||
|
'description': _('Applicant zip code.'),
|
||||||
|
'type': 'string',
|
||||||
|
},
|
||||||
|
'city': {
|
||||||
|
'description': _('Applicant city.'),
|
||||||
|
'type': 'string',
|
||||||
|
},
|
||||||
|
'phone': {
|
||||||
|
'description': _('Applicant phone number.'),
|
||||||
|
'type': 'string',
|
||||||
|
},
|
||||||
|
'email': {
|
||||||
|
'description': _('Applicant email.'),
|
||||||
|
'type': 'string',
|
||||||
|
},
|
||||||
|
'contract_start_date': {
|
||||||
|
'description': _('Applicant contract start date.'),
|
||||||
|
'type': 'string',
|
||||||
|
'pattern': '^([0-9]{4}-[0-9]{2}-[0-9]{2})?$',
|
||||||
|
},
|
||||||
|
'contract_end_date': {
|
||||||
|
'description': _('Applicant contract end date.'),
|
||||||
|
'type': 'string',
|
||||||
|
'pattern': '^([0-9]{4}-[0-9]{2}-[0-9]{2})?$',
|
||||||
|
},
|
||||||
|
'additional_informations': {
|
||||||
|
'description': _('Application information complement.'),
|
||||||
|
'type': 'string',
|
||||||
|
},
|
||||||
|
'origin': {
|
||||||
|
'description': _("ID of an element of the data source 'origine-candidature'."),
|
||||||
|
'pattern': '^[0-9]*$',
|
||||||
|
'type': 'string',
|
||||||
|
},
|
||||||
|
'origin_precisions': {
|
||||||
|
'description': _("Precisions if 'origine' is 'other'."),
|
||||||
|
'type': 'string',
|
||||||
|
},
|
||||||
|
'rgpd_agreement': boolean_field(_('RGPD agreement.')),
|
||||||
|
'job_type': {
|
||||||
|
'description': _("ID of an element of the data source 'type-emploi'."),
|
||||||
|
'type': 'string',
|
||||||
|
'pattern': '^[0-9]*$',
|
||||||
|
},
|
||||||
|
'job_realm': {
|
||||||
|
'description': _("ID of an element of the data source 'domaine-emploi'."),
|
||||||
|
'type': 'string',
|
||||||
|
'pattern': '^[0-9]*$',
|
||||||
|
},
|
||||||
|
'job_family': {
|
||||||
|
'description': _("ID of an element of the data source 'sous-domaine-emploi'."),
|
||||||
|
'type': 'string',
|
||||||
|
'pattern': '^[0-9]*$',
|
||||||
|
},
|
||||||
|
'job': {
|
||||||
|
'description': _("ID of an element of the data source 'emploi'."),
|
||||||
|
'type': 'string',
|
||||||
|
'pattern': '^[0-9]*$',
|
||||||
|
},
|
||||||
|
'desired_work_time': {
|
||||||
|
'description': _('TC / TNC.'),
|
||||||
|
'type': 'string',
|
||||||
|
'enum': ['TC', 'TNC'],
|
||||||
|
},
|
||||||
|
'internship_duration': {
|
||||||
|
'description': _('Duration of the desired internship.'),
|
||||||
|
'type': 'string',
|
||||||
|
},
|
||||||
|
'school_name': {
|
||||||
|
'description': _("Candidate trainee's school name."),
|
||||||
|
'type': 'string',
|
||||||
|
},
|
||||||
|
'diploma_name': {
|
||||||
|
'description': _("Candidate trainee's diploma name."),
|
||||||
|
'type': 'string',
|
||||||
|
},
|
||||||
|
'diploma_speciality': {
|
||||||
|
'description': _("Candidate trainee's diploma speciality."),
|
||||||
|
'type': 'string',
|
||||||
|
},
|
||||||
|
'aimed_diploma_level': {
|
||||||
|
'description': _("ID of an element of the data source 'niveau-diplome'."),
|
||||||
|
'type': 'string',
|
||||||
|
'pattern': '^[0-9]*$',
|
||||||
|
},
|
||||||
|
'last_obtained_diploma': {
|
||||||
|
'description': _("Candidate trainee's last obtained diploma."),
|
||||||
|
'type': 'string',
|
||||||
|
},
|
||||||
|
'last_course_taken': {
|
||||||
|
'description': _("Candidate trainee's last taken course."),
|
||||||
|
'type': 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class UpdateError(Exception):
|
class UpdateError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -295,6 +518,78 @@ class Resource(BaseResource, HTTPResource):
|
||||||
with document.pdf.open() as fd:
|
with document.pdf.open() as fd:
|
||||||
return HttpResponse(fd, content_type='application/pdf')
|
return HttpResponse(fd, content_type='application/pdf')
|
||||||
|
|
||||||
|
@endpoint(
|
||||||
|
perm="can_access",
|
||||||
|
name="create-application",
|
||||||
|
post={
|
||||||
|
"description": _("Creates an application"),
|
||||||
|
"request_body": {"schema": {"application/json": APPLICATION_SCHEMA}},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
def create_application(self, request, post_data):
|
||||||
|
def _get_id(field_name):
|
||||||
|
id = post_data.get(field_name, None)
|
||||||
|
if id is None or id == '':
|
||||||
|
return None
|
||||||
|
return int(id)
|
||||||
|
|
||||||
|
request_data = {
|
||||||
|
'type_de_candidature': post_data.get('type', 'E'),
|
||||||
|
'annonce': _get_id('announce_id'),
|
||||||
|
self.REFERENTIELS_FKEYS['civilite']: _get_id('civility'),
|
||||||
|
'firstName': post_data.get('first_name', None),
|
||||||
|
'lastName': post_data.get('last_name', None),
|
||||||
|
'sexe': post_data.get('gender', None),
|
||||||
|
'date_de_naissance': post_data.get('birth_date', None),
|
||||||
|
self.REFERENTIELS_FKEYS['nationalite']: _get_id('nationality'),
|
||||||
|
'date_fin_autorisation_de_travail': post_data.get('work_authorization_end_date', None),
|
||||||
|
'rqth': 'O' if get_bool(post_data.get('rqth', False)) else 'N',
|
||||||
|
'date_fin_rqth': post_data.get('rqth_end_date', None),
|
||||||
|
'permis_de_conduire': post_data.get('driving_license', None),
|
||||||
|
'fimo': 'O' if get_bool(post_data.get('fimo', False)) else 'N',
|
||||||
|
'Date_delivrance_fimo': post_data.get('fimo_delivrance_date', None),
|
||||||
|
'date_fin_validite_fimo': post_data.get('fimo_end_validity_date', None),
|
||||||
|
self.REFERENTIELS_FKEYS['situation_actuelle']: _get_id('current_situation'),
|
||||||
|
'collectivite_agent': post_data.get('agent_collectivity', None),
|
||||||
|
'date_debut_disponibilite': post_data.get('availability_start_date', None),
|
||||||
|
'date_fin_disponibilite': post_data.get('availability_end_date', None),
|
||||||
|
'pretentions_salariales': post_data.get('salary_expectations', None),
|
||||||
|
'adresse': post_data.get('address', None),
|
||||||
|
'adresse_ligne_2': post_data.get('address_complement', None),
|
||||||
|
'code_postal': post_data.get('zip', None),
|
||||||
|
'ville': post_data.get('city', None),
|
||||||
|
'telephone': post_data.get('phone', None),
|
||||||
|
'email': post_data.get('email', None),
|
||||||
|
'date_debut_contrat': post_data.get('contract_start_date', None),
|
||||||
|
'date_fin_contrat': post_data.get('contract_end_date', None),
|
||||||
|
'complement_information_candidature': post_data.get('additional_informations', None),
|
||||||
|
self.REFERENTIELS_FKEYS['origine_candidature']: _get_id('origin'),
|
||||||
|
'precision_origine_candidature': post_data.get('origin_precisions', None),
|
||||||
|
'accord_RGPD': get_bool(post_data.get('rgpd_agreement', False)),
|
||||||
|
self.REFERENTIELS_FKEYS['type_emploi']: _get_id('job_type'),
|
||||||
|
self.REFERENTIELS_FKEYS['domaine_emploi']: _get_id('job_realm'),
|
||||||
|
self.REFERENTIELS_FKEYS['sous_domaine_emploi']: _get_id('job_family'),
|
||||||
|
self.REFERENTIELS_FKEYS['emploi']: _get_id('job'),
|
||||||
|
'temps_de_travail_souhaite': post_data.get('desired_work_time', None),
|
||||||
|
'duree_du_contrat_de_stage_apprentissage': post_data.get('internship_duration', None),
|
||||||
|
'ecole_centre_de_formation_mission_loc': post_data.get('school_name', None),
|
||||||
|
'intitule_diplome_vise': post_data.get('diploma_name', None),
|
||||||
|
'specialite_diplome': post_data.get('diploma_speciality', None),
|
||||||
|
self.REFERENTIELS_FKEYS['niveau_diplome']: _get_id('aimed_diploma_level'),
|
||||||
|
'dernier_diplome_obtenu': post_data.get('last_obtained_diploma', None),
|
||||||
|
'derniere_classe_suivie': post_data.get('last_course_taken', None),
|
||||||
|
}
|
||||||
|
|
||||||
|
request_data = {k: v for k, v in request_data.items() if v is not None and v != ''}
|
||||||
|
|
||||||
|
results = self.http_request(
|
||||||
|
'POST', 'data/candidature?viewIntegrationName=api_publik', json=request_data
|
||||||
|
)
|
||||||
|
return {
|
||||||
|
'err': 0,
|
||||||
|
'data': {'application_id': results[0]['id']},
|
||||||
|
}
|
||||||
|
|
||||||
@endpoint(
|
@endpoint(
|
||||||
description=_('List announces'),
|
description=_('List announces'),
|
||||||
long_description=_(
|
long_description=_(
|
||||||
|
|
|
@ -405,6 +405,114 @@ class TestEndpoints:
|
||||||
app.get('/toulouse-foederis/foederis/announce/111/pdf/', status=404)
|
app.get('/toulouse-foederis/foederis/announce/111/pdf/', status=404)
|
||||||
assert response.headers['content-type'] == 'application/pdf'
|
assert response.headers['content-type'] == 'application/pdf'
|
||||||
|
|
||||||
|
def test_create_application(self, resource, app):
|
||||||
|
@httmock.urlmatch(path=r'^.*/data/candidature$')
|
||||||
|
def handler(url, request):
|
||||||
|
assert request.headers['content-type'] == 'application/json'
|
||||||
|
assert request.headers['api-key'] == APIKEY
|
||||||
|
payload = json.loads(request.body)
|
||||||
|
assert payload == {
|
||||||
|
"type_de_candidature": "E",
|
||||||
|
"annonce": 524522,
|
||||||
|
"R60284409": 170013,
|
||||||
|
"firstName": "John",
|
||||||
|
"lastName": "Doe",
|
||||||
|
"sexe": "H",
|
||||||
|
"date_de_naissance": "1985-03-06",
|
||||||
|
"R1249730": 93421,
|
||||||
|
"date_fin_autorisation_de_travail": "2023-05-09",
|
||||||
|
"rqth": "N",
|
||||||
|
"date_fin_rqth": "2023-05-08",
|
||||||
|
"permis_de_conduire": "A,B",
|
||||||
|
"fimo": "O",
|
||||||
|
"Date_delivrance_fimo": "2023-05-07",
|
||||||
|
"date_fin_validite_fimo": "2023-05-08",
|
||||||
|
"R1258320": 1258319,
|
||||||
|
"collectivite_agent": "Mairie de Toulouse",
|
||||||
|
"date_debut_disponibilite": "2023-05-02",
|
||||||
|
"date_fin_disponibilite": "2023-05-01",
|
||||||
|
"pretentions_salariales": "1000",
|
||||||
|
"adresse": "12 Sesame Street",
|
||||||
|
"code_postal": "77710",
|
||||||
|
"ville": "Nemours",
|
||||||
|
"telephone": "+33 636656565",
|
||||||
|
"email": "csechet@entrouvert.com",
|
||||||
|
"date_debut_contrat": "2023-05-06",
|
||||||
|
"date_fin_contrat": "2023-05-04",
|
||||||
|
"complement_information_candidature": "I need money.",
|
||||||
|
"R1261279": 1561049,
|
||||||
|
"accord_RGPD": True,
|
||||||
|
"R1249707": 157193,
|
||||||
|
"R60845221": 5776395,
|
||||||
|
"R60845244": 5776394,
|
||||||
|
"temps_de_travail_souhaite": "TC",
|
||||||
|
"duree_du_contrat_de_stage_apprentissage": "2h",
|
||||||
|
"ecole_centre_de_formation_mission_loc": "Ecole de la vie",
|
||||||
|
"intitule_diplome_vise": "BE",
|
||||||
|
"specialite_diplome": "Curling",
|
||||||
|
"R1249737": 1124022,
|
||||||
|
"dernier_diplome_obtenu": "BAC",
|
||||||
|
"derniere_classe_suivie": "Terminale",
|
||||||
|
}
|
||||||
|
|
||||||
|
return httmock.response(200, json.dumps({"code": 200, "results": [{"id": 42}]}))
|
||||||
|
|
||||||
|
@httmock.urlmatch()
|
||||||
|
def error_handler(url, request):
|
||||||
|
assert False, 'should not be reached'
|
||||||
|
|
||||||
|
with httmock.HTTMock(handler, error_handler):
|
||||||
|
response = app.post_json(
|
||||||
|
'/toulouse-foederis/foederis/create-application',
|
||||||
|
params={
|
||||||
|
"additional_informations": "I need money.",
|
||||||
|
"address": "12 Sesame Street",
|
||||||
|
"address_complement": "",
|
||||||
|
"agent_collectivity": "Mairie de Toulouse",
|
||||||
|
"aimed_diploma_level": "1124022",
|
||||||
|
"announce_id": "0524522",
|
||||||
|
"availability_end_date": "2023-05-01",
|
||||||
|
"availability_start_date": "2023-05-02",
|
||||||
|
"birth_date": "1985-03-06",
|
||||||
|
"city": "Nemours",
|
||||||
|
"civility": "170013",
|
||||||
|
"contract_end_date": "2023-05-04",
|
||||||
|
"contract_start_date": "2023-05-06",
|
||||||
|
"current_situation": "1258319",
|
||||||
|
"desired_work_time": "TC",
|
||||||
|
"diploma_name": "BE",
|
||||||
|
"diploma_speciality": "Curling",
|
||||||
|
"driving_license": "A,B",
|
||||||
|
"email": "csechet@entrouvert.com",
|
||||||
|
"fimo": "o",
|
||||||
|
"fimo_delivrance_date": "2023-05-07",
|
||||||
|
"fimo_end_validity_date": "2023-05-08",
|
||||||
|
"first_name": "John",
|
||||||
|
"gender": "H",
|
||||||
|
"internship_duration": "2h",
|
||||||
|
"job_family": "5776394",
|
||||||
|
"job_realm": "5776395",
|
||||||
|
"job_type": "157193",
|
||||||
|
"last_course_taken": "Terminale",
|
||||||
|
"last_name": "Doe",
|
||||||
|
"last_obtained_diploma": "BAC",
|
||||||
|
"nationality": "93421",
|
||||||
|
"origin": "1561049",
|
||||||
|
"origin_precisions": "",
|
||||||
|
"phone": "+33 636656565",
|
||||||
|
"rgpd_agreement": "tRuE",
|
||||||
|
"rqth": False,
|
||||||
|
"rqth_end_date": "2023-05-08",
|
||||||
|
"salary_expectations": "1000",
|
||||||
|
"school_name": "Ecole de la vie",
|
||||||
|
"type": "E",
|
||||||
|
"work_authorization_end_date": "2023-05-09",
|
||||||
|
"zip": "77710",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.json["data"]["application_id"] == 42
|
||||||
|
|
||||||
|
|
||||||
def test_migration_0003_no_null_no_charfield(migration):
|
def test_migration_0003_no_null_no_charfield(migration):
|
||||||
with connection.cursor() as cur:
|
with connection.cursor() as cur:
|
||||||
|
|
Loading…
Reference in New Issue