feat(cojo): add cojo type de champ
This commit is contained in:
parent
c74351459e
commit
d5820277c0
31 changed files with 361 additions and 12 deletions
|
@ -48,6 +48,8 @@
|
||||||
= render partial: "shared/champs/rna/show", locals: { champ: champ, profile: @profile }
|
= render partial: "shared/champs/rna/show", locals: { champ: champ, profile: @profile }
|
||||||
- when TypeDeChamp.type_champs.fetch(:epci)
|
- when TypeDeChamp.type_champs.fetch(:epci)
|
||||||
= render partial: "shared/champs/epci/show", locals: { champ: champ }
|
= render partial: "shared/champs/epci/show", locals: { champ: champ }
|
||||||
|
- when TypeDeChamp.type_champs.fetch(:cojo)
|
||||||
|
= render partial: "shared/champs/cojo/show", locals: { champ: champ, profile: @profile }
|
||||||
- when TypeDeChamp.type_champs.fetch(:date)
|
- when TypeDeChamp.type_champs.fetch(:date)
|
||||||
%p= champ.to_s
|
%p= champ.to_s
|
||||||
- when TypeDeChamp.type_champs.fetch(:datetime)
|
- when TypeDeChamp.type_champs.fetch(:datetime)
|
||||||
|
|
9
app/components/editable_champ/cojo_component.rb
Normal file
9
app/components/editable_champ/cojo_component.rb
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
class EditableChamp::COJOComponent < EditableChamp::EditableChampBaseComponent
|
||||||
|
def input_group_class
|
||||||
|
if @champ.accreditation_success?
|
||||||
|
'fr-input-group--valid'
|
||||||
|
elsif @champ.accreditation_error?
|
||||||
|
'fr-input-group--error'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
en:
|
||||||
|
accreditation_number_label: Accreditation number
|
||||||
|
accreditation_number_notice: Identification number issued by Paris 2024
|
||||||
|
accreditation_birthdate_label: Date of birth
|
||||||
|
accreditation_number_error: Invalid accreditation number
|
||||||
|
accreditation_number_verification_pending: Accreditation number verification in progress
|
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
fr:
|
||||||
|
accreditation_number_label: Numéro d‘accréditation
|
||||||
|
accreditation_number_notice: Numéro d‘identification délivré par Paris 2024
|
||||||
|
accreditation_birthdate_label: Date de naissance
|
||||||
|
accreditation_number_error: Le numéro d‘accréditation est incorrect
|
||||||
|
accreditation_number_verification_pending: Vérification du numéro d‘accréditation en cours
|
|
@ -0,0 +1,23 @@
|
||||||
|
|
||||||
|
.fr-input-group{ class: input_group_class }
|
||||||
|
= @form.label :accreditation_number, for: @champ.accreditation_number_input_id, class: 'fr-label' do
|
||||||
|
- safe_join [t('.accreditation_number_label'), @champ.required? ? render(EditableChamp::AsteriskMandatoryComponent.new) : ''], ' '
|
||||||
|
%p.fr-hint-text{ id: dom_id(@champ, :accreditation_number_notice) }= t('.accreditation_number_notice')
|
||||||
|
= @form.text_field :accreditation_number,
|
||||||
|
required: @champ.required?,
|
||||||
|
aria: { describedby: [dom_id(@champ, :accreditation_number_notice), @champ.accreditation_error? ? dom_id(@champ, :accreditation_number_error) : nil].compact.join(' ') },
|
||||||
|
data: { controller: 'format', format: 'integer' },
|
||||||
|
class: "width-33-desktop fr-input small-margin", id: @champ.accreditation_number_input_id
|
||||||
|
|
||||||
|
- if @champ.accreditation_error?
|
||||||
|
%p.fr-error-text{ id: dom_id(@champ, :accreditation_number_error) }= t('.accreditation_number_error')
|
||||||
|
- elsif @champ.fetch_external_data_pending?
|
||||||
|
%p.fr-info-text= t('.accreditation_number_verification_pending')
|
||||||
|
|
||||||
|
.fr-input-group{ class: input_group_class }
|
||||||
|
= @form.label :accreditation_birthdate, for: @champ.accreditation_birthdate_input_id, class: 'fr-label' do
|
||||||
|
- safe_join [t('.accreditation_birthdate_label'), @champ.required? ? render(EditableChamp::AsteriskMandatoryComponent.new) : ''], ' '
|
||||||
|
= @form.date_field :accreditation_birthdate,
|
||||||
|
required: @champ.required?,
|
||||||
|
aria: { describedby: dom_id(@champ, :accreditation_birthdate) },
|
||||||
|
class: "width-33-desktop fr-input small-margin", id: @champ.accreditation_birthdate_input_id
|
|
@ -471,8 +471,23 @@ module Users
|
||||||
|
|
||||||
def champs_public_params
|
def champs_public_params
|
||||||
champs_params = params.require(:dossier).permit(champs_public_attributes: [
|
champs_params = params.require(:dossier).permit(champs_public_attributes: [
|
||||||
:id, :value, :value_other, :external_id, :primary_value, :secondary_value, :numero_allocataire, :code_postal, :identifiant, :numero_fiscal, :reference_avis, :ine, :piece_justificative_file, :code_departement, value: [],
|
:id,
|
||||||
champs_attributes: [:id, :_destroy, :value, :value_other, :external_id, :primary_value, :secondary_value, :numero_allocataire, :code_postal, :identifiant, :numero_fiscal, :reference_avis, :ine, :piece_justificative_file, :departement, :code_departement, value: []]
|
:value,
|
||||||
|
:value_other,
|
||||||
|
:external_id,
|
||||||
|
:primary_value,
|
||||||
|
:secondary_value,
|
||||||
|
:numero_allocataire,
|
||||||
|
:code_postal,
|
||||||
|
:identifiant,
|
||||||
|
:numero_fiscal,
|
||||||
|
:reference_avis,
|
||||||
|
:ine,
|
||||||
|
:piece_justificative_file,
|
||||||
|
:code_departement,
|
||||||
|
:accreditation_number,
|
||||||
|
:accreditation_birthdate,
|
||||||
|
value: []
|
||||||
])
|
])
|
||||||
champs_params[:champs_public_all_attributes] = champs_params.delete(:champs_public_attributes) || {}
|
champs_params[:champs_public_all_attributes] = champs_params.delete(:champs_public_attributes) || {}
|
||||||
champs_params
|
champs_params
|
||||||
|
|
|
@ -84,6 +84,7 @@ class API::V2::Schema < GraphQL::Schema
|
||||||
Types::Champs::Descriptor::CheckboxChampDescriptorType,
|
Types::Champs::Descriptor::CheckboxChampDescriptorType,
|
||||||
Types::Champs::Descriptor::CiviliteChampDescriptorType,
|
Types::Champs::Descriptor::CiviliteChampDescriptorType,
|
||||||
Types::Champs::Descriptor::CnafChampDescriptorType,
|
Types::Champs::Descriptor::CnafChampDescriptorType,
|
||||||
|
Types::Champs::Descriptor::COJOChampDescriptorType,
|
||||||
Types::Champs::Descriptor::CommuneChampDescriptorType,
|
Types::Champs::Descriptor::CommuneChampDescriptorType,
|
||||||
Types::Champs::Descriptor::DateChampDescriptorType,
|
Types::Champs::Descriptor::DateChampDescriptorType,
|
||||||
Types::Champs::Descriptor::DatetimeChampDescriptorType,
|
Types::Champs::Descriptor::DatetimeChampDescriptorType,
|
||||||
|
|
|
@ -190,6 +190,34 @@ exceed the size of a 32-bit integer, it's encoded as a string.
|
||||||
"""
|
"""
|
||||||
scalar BigInt
|
scalar BigInt
|
||||||
|
|
||||||
|
type COJOChampDescriptor implements ChampDescriptor {
|
||||||
|
"""
|
||||||
|
Description des champs d’un bloc répétable.
|
||||||
|
"""
|
||||||
|
champDescriptors: [ChampDescriptor!] @deprecated(reason: "Utilisez le champ `RepetitionChampDescriptor.champ_descriptors` à la place.")
|
||||||
|
|
||||||
|
"""
|
||||||
|
Description du champ.
|
||||||
|
"""
|
||||||
|
description: String
|
||||||
|
id: ID!
|
||||||
|
|
||||||
|
"""
|
||||||
|
Libellé du champ.
|
||||||
|
"""
|
||||||
|
label: String!
|
||||||
|
|
||||||
|
"""
|
||||||
|
Est-ce que le champ est obligatoire ?
|
||||||
|
"""
|
||||||
|
required: Boolean!
|
||||||
|
|
||||||
|
"""
|
||||||
|
Type de la valeur du champ.
|
||||||
|
"""
|
||||||
|
type: TypeDeChamp! @deprecated(reason: "Utilisez le champ `__typename` à la place.")
|
||||||
|
}
|
||||||
|
|
||||||
type CarteChamp implements Champ {
|
type CarteChamp implements Champ {
|
||||||
geoAreas: [GeoArea!]!
|
geoAreas: [GeoArea!]!
|
||||||
id: ID!
|
id: ID!
|
||||||
|
@ -3699,6 +3727,11 @@ enum TypeDeChamp {
|
||||||
"""
|
"""
|
||||||
cnaf
|
cnaf
|
||||||
|
|
||||||
|
"""
|
||||||
|
Accréditation Paris 2024
|
||||||
|
"""
|
||||||
|
cojo
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Communes
|
Communes
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -94,6 +94,8 @@ module Types
|
||||||
Types::Champs::Descriptor::MesriChampDescriptorType
|
Types::Champs::Descriptor::MesriChampDescriptorType
|
||||||
when TypeDeChamp.type_champs.fetch(:epci)
|
when TypeDeChamp.type_champs.fetch(:epci)
|
||||||
Types::Champs::Descriptor::EpciChampDescriptorType
|
Types::Champs::Descriptor::EpciChampDescriptorType
|
||||||
|
when TypeDeChamp.type_champs.fetch(:cojo)
|
||||||
|
Types::Champs::Descriptor::COJOChampDescriptorType
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
module Types::Champs::Descriptor
|
||||||
|
class COJOChampDescriptorType < Types::BaseObject
|
||||||
|
implements Types::ChampDescriptorType
|
||||||
|
end
|
||||||
|
end
|
|
@ -15,6 +15,12 @@ export class FormatController extends ApplicationController {
|
||||||
const target = event.target as HTMLInputElement;
|
const target = event.target as HTMLInputElement;
|
||||||
target.value = this.formatIBAN(target.value);
|
target.value = this.formatIBAN(target.value);
|
||||||
});
|
});
|
||||||
|
break;
|
||||||
|
case 'integer':
|
||||||
|
this.on('input', (event) => {
|
||||||
|
const target = event.target as HTMLInputElement;
|
||||||
|
target.value = this.formatInteger(target.value);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,4 +34,8 @@ export class FormatController extends ApplicationController {
|
||||||
.replace(/(.{4})/g, '$1 ')
|
.replace(/(.{4})/g, '$1 ')
|
||||||
.trim();
|
.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private formatInteger(value: string) {
|
||||||
|
return value.replace(/[^\d]/g, '');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
64
app/models/champs/cojo_champ.rb
Normal file
64
app/models/champs/cojo_champ.rb
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
class Champs::COJOChamp < Champ
|
||||||
|
store_accessor :value_json, :accreditation_number, :accreditation_birthdate
|
||||||
|
store_accessor :data, :accreditation_success, :accreditation_first_name, :accreditation_last_name
|
||||||
|
|
||||||
|
after_validation :update_external_id
|
||||||
|
|
||||||
|
def accreditation_birthdate
|
||||||
|
Date.parse(super)
|
||||||
|
rescue ArgumentError, TypeError
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def accreditation_success?
|
||||||
|
accreditation_success == true
|
||||||
|
end
|
||||||
|
|
||||||
|
def accreditation_error?
|
||||||
|
accreditation_success == false
|
||||||
|
end
|
||||||
|
|
||||||
|
def blank?
|
||||||
|
accreditation_success.nil?
|
||||||
|
end
|
||||||
|
|
||||||
|
def fetch_external_data?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def poll_external_data?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def fetch_external_data
|
||||||
|
COJOService.new.(accreditation_number:, accreditation_birthdate:)
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
"#{accreditation_number} – #{accreditation_birthdate}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def accreditation_number_input_id
|
||||||
|
"#{input_id}-accreditation_number"
|
||||||
|
end
|
||||||
|
|
||||||
|
def accreditation_birthdate_input_id
|
||||||
|
"#{input_id}-accreditation_birthdate"
|
||||||
|
end
|
||||||
|
|
||||||
|
def focusable_input_id
|
||||||
|
accreditation_number_input_id
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def update_external_id
|
||||||
|
if accreditation_number_changed? || accreditation_birthdate_changed?
|
||||||
|
if accreditation_number.present? && accreditation_birthdate.present? && /\A\d+\z/.match?(accreditation_number)
|
||||||
|
self.external_id = { accreditation_number:, accreditation_birthdate: }.to_json
|
||||||
|
else
|
||||||
|
self.external_id = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -18,7 +18,9 @@ class TypeDeChamp < ApplicationRecord
|
||||||
self.ignored_columns += [:migrated_parent, :revision_id, :parent_id, :order_place]
|
self.ignored_columns += [:migrated_parent, :revision_id, :parent_id, :order_place]
|
||||||
|
|
||||||
FILE_MAX_SIZE = 200.megabytes
|
FILE_MAX_SIZE = 200.megabytes
|
||||||
FEATURE_FLAGS = {}
|
FEATURE_FLAGS = {
|
||||||
|
cojo: :cojo_type_de_champ
|
||||||
|
}
|
||||||
MINIMUM_TEXTAREA_CHARACTER_LIMIT_LENGTH = 400
|
MINIMUM_TEXTAREA_CHARACTER_LIMIT_LENGTH = 400
|
||||||
|
|
||||||
STRUCTURE = :structure
|
STRUCTURE = :structure
|
||||||
|
@ -68,7 +70,8 @@ class TypeDeChamp < ApplicationRecord
|
||||||
cnaf: REFERENTIEL_EXTERNE,
|
cnaf: REFERENTIEL_EXTERNE,
|
||||||
dgfip: REFERENTIEL_EXTERNE,
|
dgfip: REFERENTIEL_EXTERNE,
|
||||||
pole_emploi: REFERENTIEL_EXTERNE,
|
pole_emploi: REFERENTIEL_EXTERNE,
|
||||||
mesri: REFERENTIEL_EXTERNE
|
mesri: REFERENTIEL_EXTERNE,
|
||||||
|
cojo: REFERENTIEL_EXTERNE
|
||||||
}
|
}
|
||||||
|
|
||||||
enum type_champs: {
|
enum type_champs: {
|
||||||
|
@ -107,7 +110,8 @@ class TypeDeChamp < ApplicationRecord
|
||||||
dgfip: 'dgfip',
|
dgfip: 'dgfip',
|
||||||
pole_emploi: 'pole_emploi',
|
pole_emploi: 'pole_emploi',
|
||||||
mesri: 'mesri',
|
mesri: 'mesri',
|
||||||
epci: 'epci'
|
epci: 'epci',
|
||||||
|
cojo: 'cojo'
|
||||||
}
|
}
|
||||||
|
|
||||||
store_accessor :options,
|
store_accessor :options,
|
||||||
|
@ -569,7 +573,8 @@ class TypeDeChamp < ApplicationRecord
|
||||||
type_champs.fetch(:dossier_link),
|
type_champs.fetch(:dossier_link),
|
||||||
type_champs.fetch(:linked_drop_down_list),
|
type_champs.fetch(:linked_drop_down_list),
|
||||||
type_champs.fetch(:drop_down_list),
|
type_champs.fetch(:drop_down_list),
|
||||||
type_champs.fetch(:textarea)
|
type_champs.fetch(:textarea),
|
||||||
|
type_champs.fetch(:cojo)
|
||||||
true
|
true
|
||||||
else
|
else
|
||||||
false
|
false
|
||||||
|
|
2
app/models/types_de_champ/cojo_type_de_champ.rb
Normal file
2
app/models/types_de_champ/cojo_type_de_champ.rb
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
class TypesDeChamp::COJOTypeDeChamp < TypesDeChamp::TextTypeDeChamp
|
||||||
|
end
|
14
app/schemas/accreditation-cojo.json
Normal file
14
app/schemas/accreditation-cojo.json
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"$id": "http://demarches-simplifiees.fr/accreditation-cojo.schema.json",
|
||||||
|
"title": "Accreditation COJO",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"firstName": { "type": "string" },
|
||||||
|
"lastName": { "type": "string" },
|
||||||
|
"individualExistance": {
|
||||||
|
"enum": ["Yes", "No"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["individualExistance"]
|
||||||
|
}
|
56
app/services/cojo_service.rb
Normal file
56
app/services/cojo_service.rb
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
class COJOService
|
||||||
|
include Dry::Monads[:result]
|
||||||
|
|
||||||
|
def call(accreditation_number:, accreditation_birthdate:)
|
||||||
|
result = API::Client.new.(url:,
|
||||||
|
json: {
|
||||||
|
accreditationNumber: accreditation_number.to_i,
|
||||||
|
birthdate: accreditation_birthdate&.strftime('%d/%m/%Y')
|
||||||
|
},
|
||||||
|
authorization_token:,
|
||||||
|
schema:,
|
||||||
|
method: :post)
|
||||||
|
|
||||||
|
case result
|
||||||
|
in Success(body:)
|
||||||
|
accreditation_success = body[:individualExistance] == 'Yes'
|
||||||
|
Success({
|
||||||
|
accreditation_success:,
|
||||||
|
accreditation_first_name: accreditation_success ? body[:firstName] : nil,
|
||||||
|
accreditation_last_name: accreditation_success ? body[:lastName] : nil
|
||||||
|
})
|
||||||
|
in Failure(code:, reason:) if code.in?(401..403)
|
||||||
|
Failure(API::Client::Error[:unauthorized, code, false, reason])
|
||||||
|
else
|
||||||
|
result
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def schema
|
||||||
|
JSONSchemer.schema(Rails.root.join('app/schemas/accreditation-cojo.json'))
|
||||||
|
end
|
||||||
|
|
||||||
|
def url
|
||||||
|
"#{API_COJO_URL}/api/accreditation"
|
||||||
|
end
|
||||||
|
|
||||||
|
def authorization_token
|
||||||
|
rsa_private_key&.then { JWT.encode(jwt_payload, _1, 'RS256') }
|
||||||
|
end
|
||||||
|
|
||||||
|
def jwt_payload
|
||||||
|
{
|
||||||
|
iss: APPLICATION_NAME,
|
||||||
|
iat: Time.zone.now.to_i,
|
||||||
|
exp: 1.hour.from_now.to_i
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def rsa_private_key
|
||||||
|
if ENV['COJO_JWT_RSA_PRIVATE_KEY'].present?
|
||||||
|
OpenSSL::PKey::RSA.new(ENV['COJO_JWT_RSA_PRIVATE_KEY'])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
9
app/views/shared/champs/cojo/_show.html.haml
Normal file
9
app/views/shared/champs/cojo/_show.html.haml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
= champ.to_s
|
||||||
|
- if profile == 'instructeur'
|
||||||
|
%dl
|
||||||
|
%dt
|
||||||
|
Nom et prénom dans la base d’accréditation :
|
||||||
|
%dd= "#{champ.accreditation_last_name} #{champ.accreditation_first_name}"
|
||||||
|
%dt
|
||||||
|
Nom et prénom saisie dans le dossier :
|
||||||
|
%dd= "#{champ.dossier.individual.nom} #{champ.dossier.individual.prenom}"
|
|
@ -201,3 +201,9 @@ BANNER_MESSAGE=""
|
||||||
ADMINISTRATION_BANNER_MESSAGE=""
|
ADMINISTRATION_BANNER_MESSAGE=""
|
||||||
# for usager only
|
# for usager only
|
||||||
USAGER_BANNER_MESSAGE=""
|
USAGER_BANNER_MESSAGE=""
|
||||||
|
|
||||||
|
# RSA private key to generate JWT tokens for communication with COJO services
|
||||||
|
COJO_JWT_RSA_PRIVATE_KEY=""
|
||||||
|
COJO_JWT_ISS=""
|
||||||
|
|
||||||
|
API_COJO_URL=""
|
||||||
|
|
|
@ -6,6 +6,7 @@ API_EDUCATION_URL = ENV.fetch("API_EDUCATION_URL", "https://data.education.gouv.
|
||||||
API_GEO_URL = ENV.fetch("API_GEO_URL", "https://geo.api.gouv.fr")
|
API_GEO_URL = ENV.fetch("API_GEO_URL", "https://geo.api.gouv.fr")
|
||||||
API_PARTICULIER_URL = ENV.fetch("API_PARTICULIER_URL", "https://particulier.api.gouv.fr/api")
|
API_PARTICULIER_URL = ENV.fetch("API_PARTICULIER_URL", "https://particulier.api.gouv.fr/api")
|
||||||
API_TCHAP_URL = ENV.fetch("API_TCHAP_URL", "https://matrix.agent.tchap.gouv.fr/_matrix/identity/api/v1")
|
API_TCHAP_URL = ENV.fetch("API_TCHAP_URL", "https://matrix.agent.tchap.gouv.fr/_matrix/identity/api/v1")
|
||||||
|
API_COJO_URL = ENV.fetch("API_COJO_URL", nil)
|
||||||
HELPSCOUT_API_URL = ENV.fetch("HELPSCOUT_API_URL", "https://api.helpscout.net/v2")
|
HELPSCOUT_API_URL = ENV.fetch("HELPSCOUT_API_URL", "https://api.helpscout.net/v2")
|
||||||
PIPEDRIVE_API_URL = ENV.fetch("PIPEDRIVE_API_URL", "https://api.pipedrive.com/v1")
|
PIPEDRIVE_API_URL = ENV.fetch("PIPEDRIVE_API_URL", "https://api.pipedrive.com/v1")
|
||||||
SENDINBLUE_API_URL = ENV.fetch("SENDINBLUE_API_URL", "https://in-automate.sendinblue.com/api/v2")
|
SENDINBLUE_API_URL = ENV.fetch("SENDINBLUE_API_URL", "https://in-automate.sendinblue.com/api/v2")
|
||||||
|
|
|
@ -18,7 +18,8 @@ features = [
|
||||||
:hide_instructeur_email,
|
:hide_instructeur_email,
|
||||||
:procedure_routage_api,
|
:procedure_routage_api,
|
||||||
:groupe_instructeur_api_hack,
|
:groupe_instructeur_api_hack,
|
||||||
:rerouting
|
:rerouting,
|
||||||
|
:cojo_type_de_champ
|
||||||
]
|
]
|
||||||
|
|
||||||
def database_exists?
|
def database_exists?
|
||||||
|
|
|
@ -8,6 +8,7 @@ ActiveSupport::Inflector.inflections(:en) do |inflect|
|
||||||
# inflect.singular /^(ox)en/i, '\1'
|
# inflect.singular /^(ox)en/i, '\1'
|
||||||
# inflect.irregular 'person', 'people'
|
# inflect.irregular 'person', 'people'
|
||||||
# inflect.uncountable %w( fish sheep )
|
# inflect.uncountable %w( fish sheep )
|
||||||
|
inflect.acronym 'COJO'
|
||||||
inflect.acronym 'API'
|
inflect.acronym 'API'
|
||||||
inflect.acronym 'ASN1'
|
inflect.acronym 'ASN1'
|
||||||
inflect.acronym 'IP'
|
inflect.acronym 'IP'
|
||||||
|
|
|
@ -50,6 +50,7 @@ en:
|
||||||
pole_emploi: 'Pôle emploi status'
|
pole_emploi: 'Pôle emploi status'
|
||||||
mesri: "Data from Ministère de l’Enseignement Supérieur, de la Recherche et de l’Innovation"
|
mesri: "Data from Ministère de l’Enseignement Supérieur, de la Recherche et de l’Innovation"
|
||||||
epci: "EPCI"
|
epci: "EPCI"
|
||||||
|
cojo: "Accreditation Paris 2024"
|
||||||
errors:
|
errors:
|
||||||
type_de_champ:
|
type_de_champ:
|
||||||
attributes:
|
attributes:
|
||||||
|
|
|
@ -50,6 +50,7 @@ fr:
|
||||||
pole_emploi: 'Situation Pôle emploi'
|
pole_emploi: 'Situation Pôle emploi'
|
||||||
mesri: "Données du Ministère de l’Enseignement Supérieur, de la Recherche et de l’Innovation"
|
mesri: "Données du Ministère de l’Enseignement Supérieur, de la Recherche et de l’Innovation"
|
||||||
epci: "EPCI"
|
epci: "EPCI"
|
||||||
|
cojo: "Accréditation Paris 2024"
|
||||||
errors:
|
errors:
|
||||||
type_de_champ:
|
type_de_champ:
|
||||||
attributes:
|
attributes:
|
||||||
|
|
|
@ -239,6 +239,10 @@ FactoryBot.define do
|
||||||
value { 'W173847273' }
|
value { 'W173847273' }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
factory :champ_cojo, class: 'Champs::COJOChamp' do
|
||||||
|
type_de_champ { association :type_de_champ_cojo, procedure: dossier.procedure }
|
||||||
|
end
|
||||||
|
|
||||||
factory :champ_repetition, class: 'Champs::RepetitionChamp' do
|
factory :champ_repetition, class: 'Champs::RepetitionChamp' do
|
||||||
type_de_champ { association :type_de_champ_repetition, procedure: dossier.procedure }
|
type_de_champ { association :type_de_champ_repetition, procedure: dossier.procedure }
|
||||||
|
|
||||||
|
|
|
@ -181,6 +181,9 @@ FactoryBot.define do
|
||||||
factory :type_de_champ_epci do
|
factory :type_de_champ_epci do
|
||||||
type_champ { TypeDeChamp.type_champs.fetch(:epci) }
|
type_champ { TypeDeChamp.type_champs.fetch(:epci) }
|
||||||
end
|
end
|
||||||
|
factory :type_de_champ_cojo do
|
||||||
|
type_champ { TypeDeChamp.type_champs.fetch(:cojo) }
|
||||||
|
end
|
||||||
factory :type_de_champ_repetition do
|
factory :type_de_champ_repetition do
|
||||||
type_champ { TypeDeChamp.type_champs.fetch(:repetition) }
|
type_champ { TypeDeChamp.type_champs.fetch(:repetition) }
|
||||||
|
|
||||||
|
|
4
spec/fixtures/files/api_cojo/accreditation_invalid.json
vendored
Normal file
4
spec/fixtures/files/api_cojo/accreditation_invalid.json
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"individualExistance": "maybe",
|
||||||
|
"firstName": "Florence"
|
||||||
|
}
|
5
spec/fixtures/files/api_cojo/accreditation_no.json
vendored
Normal file
5
spec/fixtures/files/api_cojo/accreditation_no.json
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"individualExistance": "No",
|
||||||
|
"firstName": "Not found",
|
||||||
|
"lastName": "Not found"
|
||||||
|
}
|
5
spec/fixtures/files/api_cojo/accreditation_yes.json
vendored
Normal file
5
spec/fixtures/files/api_cojo/accreditation_yes.json
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"individualExistance": "Yes",
|
||||||
|
"firstName": "Florence",
|
||||||
|
"lastName": "Griffith-Joyner"
|
||||||
|
}
|
|
@ -14,9 +14,9 @@ describe '20220705164551_remove_unused_champs' do
|
||||||
|
|
||||||
describe 'remove_unused_champs' do
|
describe 'remove_unused_champs' do
|
||||||
it "with bad champs" do
|
it "with bad champs" do
|
||||||
expect(Champ.where(dossier: dossier).count).to eq(40)
|
expect(Champ.where(dossier: dossier).count).to eq(41)
|
||||||
run_task
|
run_task
|
||||||
expect(Champ.where(dossier: dossier).count).to eq(39)
|
expect(Champ.where(dossier: dossier).count).to eq(40)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
50
spec/models/champs/cojo_champ_spec.rb
Normal file
50
spec/models/champs/cojo_champ_spec.rb
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
describe Champs::COJOChamp, type: :model do
|
||||||
|
let(:champ) { build(:champ_cojo, accreditation_number:, accreditation_birthdate:) }
|
||||||
|
let(:external_id) { nil }
|
||||||
|
let(:stub) { stub_request(:post, url).with(body: { accreditationNumber: accreditation_number, birthdate: accreditation_birthdate }).to_return(body:, status:) }
|
||||||
|
let(:url) { COJOService.new.send(:url) }
|
||||||
|
let(:body) { Rails.root.join('spec', 'fixtures', 'files', 'api_cojo', "accreditation_#{response_type}.json").read }
|
||||||
|
let(:status) { 200 }
|
||||||
|
let(:response_type) { 'yes' }
|
||||||
|
let(:accreditation_number) { 123456 }
|
||||||
|
let(:accreditation_birthdate) { '21/12/1959' }
|
||||||
|
|
||||||
|
describe 'fetch_external_data' do
|
||||||
|
subject { stub; champ.fetch_external_data }
|
||||||
|
|
||||||
|
context 'success (yes)' do
|
||||||
|
it { expect(subject.value!).to eq({ accreditation_success: true, accreditation_first_name: 'Florence', accreditation_last_name: 'Griffith-Joyner' }) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'success (no)' do
|
||||||
|
let(:response_type) { 'no' }
|
||||||
|
it { expect(subject.value!).to eq({ accreditation_success: false, accreditation_first_name: nil, accreditation_last_name: nil }) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'failure (schema)' do
|
||||||
|
let(:response_type) { 'invalid' }
|
||||||
|
it {
|
||||||
|
expect(subject.failure.retryable).to be_falsey
|
||||||
|
expect(subject.failure.reason).to be_a(API::Client::SchemaError)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'failure (http 500)' do
|
||||||
|
let(:status) { 500 }
|
||||||
|
let(:response_type) { 'invalid' }
|
||||||
|
it {
|
||||||
|
expect(subject.failure.retryable).to be_truthy
|
||||||
|
expect(subject.failure.reason).to be_a(API::Client::HTTPError)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'failure (http 401)' do
|
||||||
|
let(:status) { 401 }
|
||||||
|
let(:response_type) { 'invalid' }
|
||||||
|
it {
|
||||||
|
expect(subject.failure.retryable).to be_falsey
|
||||||
|
expect(subject.failure.reason).to be_a(API::Client::HTTPError)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -88,7 +88,8 @@ describe ProcedureExportService do
|
||||||
"text",
|
"text",
|
||||||
"epci",
|
"epci",
|
||||||
"epci (Code)",
|
"epci (Code)",
|
||||||
"epci (Département)"
|
"epci (Département)",
|
||||||
|
"cojo"
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -198,7 +199,8 @@ describe ProcedureExportService do
|
||||||
"text",
|
"text",
|
||||||
"epci",
|
"epci",
|
||||||
"epci (Code)",
|
"epci (Code)",
|
||||||
"epci (Département)"
|
"epci (Département)",
|
||||||
|
"cojo"
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -291,7 +293,8 @@ describe ProcedureExportService do
|
||||||
"text",
|
"text",
|
||||||
"epci",
|
"epci",
|
||||||
"epci (Code)",
|
"epci (Code)",
|
||||||
"epci (Département)"
|
"epci (Département)",
|
||||||
|
"cojo"
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue