commit
cae41fb473
73 changed files with 891 additions and 16 deletions
1
Gemfile
1
Gemfile
|
@ -46,6 +46,7 @@ gem 'http_accept_language'
|
||||||
gem 'iban-tools'
|
gem 'iban-tools'
|
||||||
gem 'image_processing'
|
gem 'image_processing'
|
||||||
gem 'jquery-rails' # Use jquery as the JavaScript library
|
gem 'jquery-rails' # Use jquery as the JavaScript library
|
||||||
|
gem 'json_schemer'
|
||||||
gem 'jwt'
|
gem 'jwt'
|
||||||
gem 'kaminari', '1.2.1' # Pagination
|
gem 'kaminari', '1.2.1' # Pagination
|
||||||
gem 'lograge'
|
gem 'lograge'
|
||||||
|
|
10
Gemfile.lock
10
Gemfile.lock
|
@ -230,6 +230,8 @@ GEM
|
||||||
railties (>= 3.2)
|
railties (>= 3.2)
|
||||||
dry-inflector (0.2.0)
|
dry-inflector (0.2.0)
|
||||||
dumb_delegator (0.8.1)
|
dumb_delegator (0.8.1)
|
||||||
|
ecma-re-validator (0.2.1)
|
||||||
|
regexp_parser (~> 1.2)
|
||||||
em-websocket (0.5.1)
|
em-websocket (0.5.1)
|
||||||
eventmachine (>= 0.12.9)
|
eventmachine (>= 0.12.9)
|
||||||
http_parser.rb (~> 0.6.0)
|
http_parser.rb (~> 0.6.0)
|
||||||
|
@ -339,6 +341,7 @@ GEM
|
||||||
rainbow
|
rainbow
|
||||||
rubocop (>= 0.50.0)
|
rubocop (>= 0.50.0)
|
||||||
sysexits (~> 1.1)
|
sysexits (~> 1.1)
|
||||||
|
hana (1.3.7)
|
||||||
hashdiff (1.0.1)
|
hashdiff (1.0.1)
|
||||||
hashie (4.1.0)
|
hashie (4.1.0)
|
||||||
html2haml (2.2.0)
|
html2haml (2.2.0)
|
||||||
|
@ -370,6 +373,11 @@ GEM
|
||||||
activesupport (>= 4.2)
|
activesupport (>= 4.2)
|
||||||
aes_key_wrap
|
aes_key_wrap
|
||||||
bindata
|
bindata
|
||||||
|
json_schemer (0.2.16)
|
||||||
|
ecma-re-validator (~> 0.2)
|
||||||
|
hana (~> 1.3)
|
||||||
|
regexp_parser (~> 1.5)
|
||||||
|
uri_template (~> 0.7)
|
||||||
jsonapi-renderer (0.2.2)
|
jsonapi-renderer (0.2.2)
|
||||||
jwt (2.2.2)
|
jwt (2.2.2)
|
||||||
kaminari (1.2.1)
|
kaminari (1.2.1)
|
||||||
|
@ -721,6 +729,7 @@ GEM
|
||||||
unf_ext
|
unf_ext
|
||||||
unf_ext (0.0.7.7)
|
unf_ext (0.0.7.7)
|
||||||
unicode-display_width (1.7.0)
|
unicode-display_width (1.7.0)
|
||||||
|
uri_template (0.7.0)
|
||||||
validate_email (0.1.6)
|
validate_email (0.1.6)
|
||||||
activemodel (>= 3.0)
|
activemodel (>= 3.0)
|
||||||
mail (>= 2.2.5)
|
mail (>= 2.2.5)
|
||||||
|
@ -835,6 +844,7 @@ DEPENDENCIES
|
||||||
iban-tools
|
iban-tools
|
||||||
image_processing
|
image_processing
|
||||||
jquery-rails
|
jquery-rails
|
||||||
|
json_schemer
|
||||||
jwt
|
jwt
|
||||||
kaminari (= 1.2.1)
|
kaminari (= 1.2.1)
|
||||||
launchy
|
launchy
|
||||||
|
|
|
@ -323,8 +323,8 @@ module Users
|
||||||
def champs_params
|
def champs_params
|
||||||
params.permit(dossier: {
|
params.permit(dossier: {
|
||||||
champs_attributes: [
|
champs_attributes: [
|
||||||
:id, :value, :primary_value, :secondary_value, :piece_justificative_file, value: [],
|
:id, :value, :external_id, :primary_value, :secondary_value, :piece_justificative_file, value: [],
|
||||||
champs_attributes: [:id, :_destroy, :value, :primary_value, :secondary_value, :piece_justificative_file, value: []]
|
champs_attributes: [:id, :_destroy, :value, :external_id, :primary_value, :secondary_value, :piece_justificative_file, value: []]
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
30
app/graphql/api/v2/context.rb
Normal file
30
app/graphql/api/v2/context.rb
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
class Api::V2::Context < GraphQL::Query::Context
|
||||||
|
def has_fragment?(name)
|
||||||
|
if self["has_fragment_#{name}"]
|
||||||
|
true
|
||||||
|
else
|
||||||
|
visitor = HasFragment.new(self.query.selected_operation, name)
|
||||||
|
visitor.visit
|
||||||
|
self["has_fragment_#{name}"] = visitor.found
|
||||||
|
self["has_fragment_#{name}"]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class HasFragment < GraphQL::Language::Visitor
|
||||||
|
def initialize(document, name)
|
||||||
|
super(document)
|
||||||
|
@name = name.to_s
|
||||||
|
@found = false
|
||||||
|
end
|
||||||
|
|
||||||
|
attr_reader :found
|
||||||
|
|
||||||
|
def on_inline_fragment(node, parent)
|
||||||
|
if node.type.name == @name
|
||||||
|
@found = true
|
||||||
|
end
|
||||||
|
|
||||||
|
super
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -6,6 +6,8 @@ class Api::V2::Schema < GraphQL::Schema
|
||||||
query Types::QueryType
|
query Types::QueryType
|
||||||
mutation Types::MutationType
|
mutation Types::MutationType
|
||||||
|
|
||||||
|
context_class Api::V2::Context
|
||||||
|
|
||||||
def self.id_from_object(object, type_definition, ctx)
|
def self.id_from_object(object, type_definition, ctx)
|
||||||
object.to_typed_id
|
object.to_typed_id
|
||||||
end
|
end
|
||||||
|
@ -41,6 +43,7 @@ class Api::V2::Schema < GraphQL::Schema
|
||||||
Types::Champs::CheckboxChampType,
|
Types::Champs::CheckboxChampType,
|
||||||
Types::Champs::CiviliteChampType,
|
Types::Champs::CiviliteChampType,
|
||||||
Types::Champs::DateChampType,
|
Types::Champs::DateChampType,
|
||||||
|
Types::Champs::DatetimeChampType,
|
||||||
Types::Champs::DecimalNumberChampType,
|
Types::Champs::DecimalNumberChampType,
|
||||||
Types::Champs::DossierLinkChampType,
|
Types::Champs::DossierLinkChampType,
|
||||||
Types::Champs::IntegerNumberChampType,
|
Types::Champs::IntegerNumberChampType,
|
||||||
|
|
|
@ -180,6 +180,33 @@ type CreateDirectUploadPayload {
|
||||||
}
|
}
|
||||||
|
|
||||||
type DateChamp implements Champ {
|
type DateChamp implements Champ {
|
||||||
|
"""
|
||||||
|
La valeur du champ formaté en ISO8601 (Date).
|
||||||
|
"""
|
||||||
|
date: ISO8601Date
|
||||||
|
id: ID!
|
||||||
|
|
||||||
|
"""
|
||||||
|
Libellé du champ.
|
||||||
|
"""
|
||||||
|
label: String!
|
||||||
|
|
||||||
|
"""
|
||||||
|
La valeur du champ sous forme texte.
|
||||||
|
"""
|
||||||
|
stringValue: String
|
||||||
|
|
||||||
|
"""
|
||||||
|
La valeur du champ formaté en ISO8601 (DateTime).
|
||||||
|
"""
|
||||||
|
value: ISO8601DateTime @deprecated(reason: "Utilisez le champ 'date' ou le fragment 'DatetimeChamp' à la place.")
|
||||||
|
}
|
||||||
|
|
||||||
|
type DatetimeChamp implements Champ {
|
||||||
|
"""
|
||||||
|
La valeur du champ formaté en ISO8601 (DateTime).
|
||||||
|
"""
|
||||||
|
datetime: ISO8601DateTime
|
||||||
id: ID!
|
id: ID!
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -191,7 +218,6 @@ type DateChamp implements Champ {
|
||||||
La valeur du champ sous forme texte.
|
La valeur du champ sous forme texte.
|
||||||
"""
|
"""
|
||||||
stringValue: String
|
stringValue: String
|
||||||
value: ISO8601DateTime
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type DecimalNumberChamp implements Champ {
|
type DecimalNumberChamp implements Champ {
|
||||||
|
@ -1230,6 +1256,11 @@ enum TypeDeChamp {
|
||||||
"""
|
"""
|
||||||
address
|
address
|
||||||
|
|
||||||
|
"""
|
||||||
|
Annuaire de l’éducation
|
||||||
|
"""
|
||||||
|
annuaire_education
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Carte
|
Carte
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -11,8 +11,14 @@ module Types
|
||||||
case object
|
case object
|
||||||
when ::Champs::EngagementChamp, ::Champs::YesNoChamp, ::Champs::CheckboxChamp
|
when ::Champs::EngagementChamp, ::Champs::YesNoChamp, ::Champs::CheckboxChamp
|
||||||
Types::Champs::CheckboxChampType
|
Types::Champs::CheckboxChampType
|
||||||
when ::Champs::DateChamp, ::Champs::DatetimeChamp
|
when ::Champs::DateChamp
|
||||||
Types::Champs::DateChampType
|
Types::Champs::DateChampType
|
||||||
|
when ::Champs::DatetimeChamp
|
||||||
|
if context.has_fragment?(:DatetimeChamp)
|
||||||
|
Types::Champs::DatetimeChampType
|
||||||
|
else
|
||||||
|
Types::Champs::DateChampType
|
||||||
|
end
|
||||||
when ::Champs::DossierLinkChamp
|
when ::Champs::DossierLinkChamp
|
||||||
Types::Champs::DossierLinkChampType
|
Types::Champs::DossierLinkChampType
|
||||||
when ::Champs::PieceJustificativeChamp
|
when ::Champs::PieceJustificativeChamp
|
||||||
|
|
|
@ -2,12 +2,19 @@ module Types::Champs
|
||||||
class DateChampType < Types::BaseObject
|
class DateChampType < Types::BaseObject
|
||||||
implements Types::ChampType
|
implements Types::ChampType
|
||||||
|
|
||||||
field :value, GraphQL::Types::ISO8601DateTime, null: true
|
field :value, GraphQL::Types::ISO8601DateTime, "La valeur du champ formaté en ISO8601 (DateTime).", null: true, deprecation_reason: "Utilisez le champ 'date' ou le fragment 'DatetimeChamp' à la place."
|
||||||
|
field :date, GraphQL::Types::ISO8601Date, "La valeur du champ formaté en ISO8601 (Date).", null: true
|
||||||
|
|
||||||
def value
|
def value
|
||||||
if object.value.present?
|
if object.value.present?
|
||||||
Time.zone.parse(object.value)
|
Time.zone.parse(object.value)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def date
|
||||||
|
if object.value.present?
|
||||||
|
Date.parse(object.value)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
13
app/graphql/types/champs/datetime_champ_type.rb
Normal file
13
app/graphql/types/champs/datetime_champ_type.rb
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
module Types::Champs
|
||||||
|
class DatetimeChampType < Types::BaseObject
|
||||||
|
implements Types::ChampType
|
||||||
|
|
||||||
|
field :datetime, GraphQL::Types::ISO8601DateTime, "La valeur du champ formaté en ISO8601 (DateTime).", null: true
|
||||||
|
|
||||||
|
def datetime
|
||||||
|
if object.value.present?
|
||||||
|
Time.zone.parse(object.value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
28
app/javascript/components/ComboAnnuaireEducationSearch.js
Normal file
28
app/javascript/components/ComboAnnuaireEducationSearch.js
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { ReactQueryCacheProvider } from 'react-query';
|
||||||
|
|
||||||
|
import ComboSearch from './ComboSearch';
|
||||||
|
import { queryCache } from './shared/queryCache';
|
||||||
|
|
||||||
|
function ComboAnnuaireEducationSearch(params) {
|
||||||
|
return (
|
||||||
|
<ReactQueryCacheProvider queryCache={queryCache}>
|
||||||
|
<ComboSearch
|
||||||
|
required={params.mandatory}
|
||||||
|
hiddenFieldId={params.hiddenFieldId}
|
||||||
|
scope="annuaire-education"
|
||||||
|
minimumInputLength={3}
|
||||||
|
transformResults={(_, { records }) => records}
|
||||||
|
transformResult={({
|
||||||
|
fields: {
|
||||||
|
identifiant_de_l_etablissement: id,
|
||||||
|
nom_etablissement,
|
||||||
|
nom_commune
|
||||||
|
}
|
||||||
|
}) => [id, `${nom_etablissement}, ${nom_commune} (${id})`]}
|
||||||
|
/>
|
||||||
|
</ReactQueryCacheProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ComboAnnuaireEducationSearch;
|
|
@ -10,6 +10,7 @@ import {
|
||||||
ComboboxOption
|
ComboboxOption
|
||||||
} from '@reach/combobox';
|
} from '@reach/combobox';
|
||||||
import '@reach/combobox/styles.css';
|
import '@reach/combobox/styles.css';
|
||||||
|
import { fire } from '@utils';
|
||||||
|
|
||||||
function defaultTransformResults(_, results) {
|
function defaultTransformResults(_, results) {
|
||||||
return results;
|
return results;
|
||||||
|
@ -27,21 +28,38 @@ function ComboSearch({
|
||||||
transformResults = defaultTransformResults
|
transformResults = defaultTransformResults
|
||||||
}) {
|
}) {
|
||||||
const label = scope;
|
const label = scope;
|
||||||
const hiddenField = useMemo(
|
const hiddenValueField = useMemo(
|
||||||
() => document.querySelector(`input[data-uuid="${hiddenFieldId}"]`),
|
() => document.querySelector(`input[data-uuid="${hiddenFieldId}"]`),
|
||||||
[hiddenFieldId]
|
[hiddenFieldId]
|
||||||
);
|
);
|
||||||
const initialValue = hiddenField && hiddenField.value;
|
const hiddenIdField = useMemo(
|
||||||
|
() =>
|
||||||
|
document.querySelector(
|
||||||
|
`input[data-uuid="${hiddenFieldId}"] + input[data-reference]`
|
||||||
|
),
|
||||||
|
[hiddenFieldId]
|
||||||
|
);
|
||||||
|
const initialValue = hiddenValueField && hiddenValueField.value;
|
||||||
const [searchTerm, setSearchTerm] = useState('');
|
const [searchTerm, setSearchTerm] = useState('');
|
||||||
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState('');
|
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState('');
|
||||||
const [value, setValue] = useState(initialValue);
|
const [value, setValue] = useState(initialValue);
|
||||||
const resultsMap = useRef({});
|
const resultsMap = useRef({});
|
||||||
const setExternalValue = useCallback((value) => {
|
const setExternalValue = useCallback((value) => {
|
||||||
if (hiddenField) {
|
if (hiddenValueField) {
|
||||||
hiddenField.setAttribute('value', value);
|
hiddenValueField.setAttribute('value', value);
|
||||||
|
fire(hiddenValueField, 'autosave:trigger');
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
const setExternalId = useCallback((key) => {
|
||||||
|
if (hiddenIdField) {
|
||||||
|
hiddenIdField.setAttribute('value', key);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const setExternalValueAndId = useCallback((value) => {
|
||||||
|
const [key, result] = resultsMap.current[value];
|
||||||
|
setExternalId(key);
|
||||||
|
setExternalValue(value);
|
||||||
if (onChange) {
|
if (onChange) {
|
||||||
const result = resultsMap.current[value];
|
|
||||||
onChange(value, result);
|
onChange(value, result);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -60,6 +78,7 @@ function ComboSearch({
|
||||||
if (value.length >= minimumInputLength) {
|
if (value.length >= minimumInputLength) {
|
||||||
setSearchTerm(value.trim());
|
setSearchTerm(value.trim());
|
||||||
if (allowInputValues) {
|
if (allowInputValues) {
|
||||||
|
setExternalId('');
|
||||||
setExternalValue(value);
|
setExternalValue(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,7 +87,7 @@ function ComboSearch({
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleOnSelect = useCallback((value) => {
|
const handleOnSelect = useCallback((value) => {
|
||||||
setExternalValue(value);
|
setExternalValueAndId(value);
|
||||||
setValue(value);
|
setValue(value);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -93,7 +112,7 @@ function ComboSearch({
|
||||||
<ComboboxList>
|
<ComboboxList>
|
||||||
{results.map((result) => {
|
{results.map((result) => {
|
||||||
const [key, str] = transformResult(result);
|
const [key, str] = transformResult(result);
|
||||||
resultsMap.current[str] = result;
|
resultsMap.current[str] = [key, result];
|
||||||
return (
|
return (
|
||||||
<ComboboxOption
|
<ComboboxOption
|
||||||
key={key}
|
key={key}
|
||||||
|
|
|
@ -2,7 +2,8 @@ import { QueryCache } from 'react-query';
|
||||||
import { isNumeric } from '@utils';
|
import { isNumeric } from '@utils';
|
||||||
import matchSorter from 'match-sorter';
|
import matchSorter from 'match-sorter';
|
||||||
|
|
||||||
const { api_geo_url, api_adresse_url } = gon.autocomplete || {};
|
const { api_geo_url, api_adresse_url, api_education_url } =
|
||||||
|
gon.autocomplete || {};
|
||||||
|
|
||||||
export const queryCache = new QueryCache({
|
export const queryCache = new QueryCache({
|
||||||
defaultConfig: {
|
defaultConfig: {
|
||||||
|
@ -13,8 +14,11 @@ export const queryCache = new QueryCache({
|
||||||
});
|
});
|
||||||
|
|
||||||
function buildURL(scope, term) {
|
function buildURL(scope, term) {
|
||||||
|
term = encodeURIComponent(term);
|
||||||
if (scope === 'adresse') {
|
if (scope === 'adresse') {
|
||||||
return `${api_adresse_url}/search?q=${term}&limit=5`;
|
return `${api_adresse_url}/search?q=${term}&limit=5`;
|
||||||
|
} else if (scope === 'annuaire-education') {
|
||||||
|
return `${api_education_url}/search?dataset=fr-en-annuaire-education&q=${term}&rows=5`;
|
||||||
} else if (isNumeric(term)) {
|
} else if (isNumeric(term)) {
|
||||||
const code = term.padStart(2, '0');
|
const code = term.padStart(2, '0');
|
||||||
return `${api_geo_url}/${scope}?code=${code}&limit=5`;
|
return `${api_geo_url}/${scope}?code=${code}&limit=5`;
|
||||||
|
|
5
app/javascript/loaders/ComboAnnuaireEducationSearch.js
Normal file
5
app/javascript/loaders/ComboAnnuaireEducationSearch.js
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import Loadable from '../components/Loadable';
|
||||||
|
|
||||||
|
export default Loadable(() =>
|
||||||
|
import('../components/ComboAnnuaireEducationSearch')
|
||||||
|
);
|
16
app/jobs/annuaire_education_update_job.rb
Normal file
16
app/jobs/annuaire_education_update_job.rb
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
class AnnuaireEducationUpdateJob < ApplicationJob
|
||||||
|
def perform(champ)
|
||||||
|
external_id = champ.external_id
|
||||||
|
|
||||||
|
if external_id.present?
|
||||||
|
data = ApiEducation::AnnuaireEducationAdapter.new(external_id).to_params
|
||||||
|
|
||||||
|
if data.present?
|
||||||
|
champ.data = data
|
||||||
|
else
|
||||||
|
champ.external_id = nil
|
||||||
|
end
|
||||||
|
champ.save!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
36
app/lib/api_education/annuaire_education_adapter.rb
Normal file
36
app/lib/api_education/annuaire_education_adapter.rb
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
require 'json_schemer'
|
||||||
|
|
||||||
|
class ApiEducation::AnnuaireEducationAdapter
|
||||||
|
class InvalidSchemaError < ::StandardError
|
||||||
|
def initialize(errors)
|
||||||
|
super(errors.map(&:to_json).join("\n"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize(id)
|
||||||
|
@id = id
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_params
|
||||||
|
record = data_source[:records].first
|
||||||
|
if record.present?
|
||||||
|
properties = record[:fields].merge({ geometry: record[:geometry] }).deep_stringify_keys
|
||||||
|
if schemer.valid?(properties)
|
||||||
|
properties
|
||||||
|
else
|
||||||
|
errors = schemer.validate(properties).to_a
|
||||||
|
raise InvalidSchemaError.new(errors)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def data_source
|
||||||
|
@data_source ||= JSON.parse(ApiEducation::API.get_annuaire_education(@id), symbolize_names: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
def schemer
|
||||||
|
@schemer ||= JSONSchemer.schema(Rails.root.join('app/schemas/etablissement-annuaire-education.json'))
|
||||||
|
end
|
||||||
|
end
|
22
app/lib/api_education/api.rb
Normal file
22
app/lib/api_education/api.rb
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
class ApiEducation::API
|
||||||
|
class ResourceNotFound < StandardError
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.get_annuaire_education(id)
|
||||||
|
call([API_EDUCATION_URL, 'search'].join('/'), 'fr-en-annuaire-education', { 'refine.identifiant_de_l_etablissement': id })
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def self.call(url, dataset, params)
|
||||||
|
response = Typhoeus.get(url, params: { rows: 1, dataset: dataset }.merge(params))
|
||||||
|
|
||||||
|
if response.success?
|
||||||
|
response.body
|
||||||
|
else
|
||||||
|
message = response.code == 0 ? response.return_message : response.code.to_s
|
||||||
|
Rails.logger.error "[ApiEducation] Error on #{url}: #{message}"
|
||||||
|
raise ResourceNotFound
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -3,6 +3,7 @@
|
||||||
# Table name: champs
|
# Table name: champs
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
# private :boolean default(FALSE), not null
|
# private :boolean default(FALSE), not null
|
||||||
# row :integer
|
# row :integer
|
||||||
# type :string
|
# type :string
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# dossier_id :integer
|
# dossier_id :integer
|
||||||
# etablissement_id :integer
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
# parent_id :bigint
|
# parent_id :bigint
|
||||||
# type_de_champ_id :integer
|
# type_de_champ_id :integer
|
||||||
#
|
#
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# Table name: champs
|
# Table name: champs
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
# private :boolean default(FALSE), not null
|
# private :boolean default(FALSE), not null
|
||||||
# row :integer
|
# row :integer
|
||||||
# type :string
|
# type :string
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# dossier_id :integer
|
# dossier_id :integer
|
||||||
# etablissement_id :integer
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
# parent_id :bigint
|
# parent_id :bigint
|
||||||
# type_de_champ_id :integer
|
# type_de_champ_id :integer
|
||||||
#
|
#
|
||||||
|
|
36
app/models/champs/annuaire_education_champ.rb
Normal file
36
app/models/champs/annuaire_education_champ.rb
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
# == Schema Information
|
||||||
|
#
|
||||||
|
# Table name: champs
|
||||||
|
#
|
||||||
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
|
# private :boolean default(FALSE), not null
|
||||||
|
# row :integer
|
||||||
|
# type :string
|
||||||
|
# value :string
|
||||||
|
# created_at :datetime
|
||||||
|
# updated_at :datetime
|
||||||
|
# dossier_id :integer
|
||||||
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
|
# parent_id :bigint
|
||||||
|
# type_de_champ_id :integer
|
||||||
|
#
|
||||||
|
class Champs::AnnuaireEducationChamp < Champs::TextChamp
|
||||||
|
before_save :cleanup_if_empty
|
||||||
|
after_update_commit :fetch_data
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def cleanup_if_empty
|
||||||
|
if external_id_changed?
|
||||||
|
self.data = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def fetch_data
|
||||||
|
if external_id.present? && data.nil?
|
||||||
|
AnnuaireEducationUpdateJob.perform_later(self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -3,6 +3,7 @@
|
||||||
# Table name: champs
|
# Table name: champs
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
# private :boolean default(FALSE), not null
|
# private :boolean default(FALSE), not null
|
||||||
# row :integer
|
# row :integer
|
||||||
# type :string
|
# type :string
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# dossier_id :integer
|
# dossier_id :integer
|
||||||
# etablissement_id :integer
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
# parent_id :bigint
|
# parent_id :bigint
|
||||||
# type_de_champ_id :integer
|
# type_de_champ_id :integer
|
||||||
#
|
#
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# Table name: champs
|
# Table name: champs
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
# private :boolean default(FALSE), not null
|
# private :boolean default(FALSE), not null
|
||||||
# row :integer
|
# row :integer
|
||||||
# type :string
|
# type :string
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# dossier_id :integer
|
# dossier_id :integer
|
||||||
# etablissement_id :integer
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
# parent_id :bigint
|
# parent_id :bigint
|
||||||
# type_de_champ_id :integer
|
# type_de_champ_id :integer
|
||||||
#
|
#
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# Table name: champs
|
# Table name: champs
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
# private :boolean default(FALSE), not null
|
# private :boolean default(FALSE), not null
|
||||||
# row :integer
|
# row :integer
|
||||||
# type :string
|
# type :string
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# dossier_id :integer
|
# dossier_id :integer
|
||||||
# etablissement_id :integer
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
# parent_id :bigint
|
# parent_id :bigint
|
||||||
# type_de_champ_id :integer
|
# type_de_champ_id :integer
|
||||||
#
|
#
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# Table name: champs
|
# Table name: champs
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
# private :boolean default(FALSE), not null
|
# private :boolean default(FALSE), not null
|
||||||
# row :integer
|
# row :integer
|
||||||
# type :string
|
# type :string
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# dossier_id :integer
|
# dossier_id :integer
|
||||||
# etablissement_id :integer
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
# parent_id :bigint
|
# parent_id :bigint
|
||||||
# type_de_champ_id :integer
|
# type_de_champ_id :integer
|
||||||
#
|
#
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# Table name: champs
|
# Table name: champs
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
# private :boolean default(FALSE), not null
|
# private :boolean default(FALSE), not null
|
||||||
# row :integer
|
# row :integer
|
||||||
# type :string
|
# type :string
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# dossier_id :integer
|
# dossier_id :integer
|
||||||
# etablissement_id :integer
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
# parent_id :bigint
|
# parent_id :bigint
|
||||||
# type_de_champ_id :integer
|
# type_de_champ_id :integer
|
||||||
#
|
#
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# Table name: champs
|
# Table name: champs
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
# private :boolean default(FALSE), not null
|
# private :boolean default(FALSE), not null
|
||||||
# row :integer
|
# row :integer
|
||||||
# type :string
|
# type :string
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# dossier_id :integer
|
# dossier_id :integer
|
||||||
# etablissement_id :integer
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
# parent_id :bigint
|
# parent_id :bigint
|
||||||
# type_de_champ_id :integer
|
# type_de_champ_id :integer
|
||||||
#
|
#
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# Table name: champs
|
# Table name: champs
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
# private :boolean default(FALSE), not null
|
# private :boolean default(FALSE), not null
|
||||||
# row :integer
|
# row :integer
|
||||||
# type :string
|
# type :string
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# dossier_id :integer
|
# dossier_id :integer
|
||||||
# etablissement_id :integer
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
# parent_id :bigint
|
# parent_id :bigint
|
||||||
# type_de_champ_id :integer
|
# type_de_champ_id :integer
|
||||||
#
|
#
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# Table name: champs
|
# Table name: champs
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
# private :boolean default(FALSE), not null
|
# private :boolean default(FALSE), not null
|
||||||
# row :integer
|
# row :integer
|
||||||
# type :string
|
# type :string
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# dossier_id :integer
|
# dossier_id :integer
|
||||||
# etablissement_id :integer
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
# parent_id :bigint
|
# parent_id :bigint
|
||||||
# type_de_champ_id :integer
|
# type_de_champ_id :integer
|
||||||
#
|
#
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# Table name: champs
|
# Table name: champs
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
# private :boolean default(FALSE), not null
|
# private :boolean default(FALSE), not null
|
||||||
# row :integer
|
# row :integer
|
||||||
# type :string
|
# type :string
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# dossier_id :integer
|
# dossier_id :integer
|
||||||
# etablissement_id :integer
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
# parent_id :bigint
|
# parent_id :bigint
|
||||||
# type_de_champ_id :integer
|
# type_de_champ_id :integer
|
||||||
#
|
#
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# Table name: champs
|
# Table name: champs
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
# private :boolean default(FALSE), not null
|
# private :boolean default(FALSE), not null
|
||||||
# row :integer
|
# row :integer
|
||||||
# type :string
|
# type :string
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# dossier_id :integer
|
# dossier_id :integer
|
||||||
# etablissement_id :integer
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
# parent_id :bigint
|
# parent_id :bigint
|
||||||
# type_de_champ_id :integer
|
# type_de_champ_id :integer
|
||||||
#
|
#
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# Table name: champs
|
# Table name: champs
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
# private :boolean default(FALSE), not null
|
# private :boolean default(FALSE), not null
|
||||||
# row :integer
|
# row :integer
|
||||||
# type :string
|
# type :string
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# dossier_id :integer
|
# dossier_id :integer
|
||||||
# etablissement_id :integer
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
# parent_id :bigint
|
# parent_id :bigint
|
||||||
# type_de_champ_id :integer
|
# type_de_champ_id :integer
|
||||||
#
|
#
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# Table name: champs
|
# Table name: champs
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
# private :boolean default(FALSE), not null
|
# private :boolean default(FALSE), not null
|
||||||
# row :integer
|
# row :integer
|
||||||
# type :string
|
# type :string
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# dossier_id :integer
|
# dossier_id :integer
|
||||||
# etablissement_id :integer
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
# parent_id :bigint
|
# parent_id :bigint
|
||||||
# type_de_champ_id :integer
|
# type_de_champ_id :integer
|
||||||
#
|
#
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# Table name: champs
|
# Table name: champs
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
# private :boolean default(FALSE), not null
|
# private :boolean default(FALSE), not null
|
||||||
# row :integer
|
# row :integer
|
||||||
# type :string
|
# type :string
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# dossier_id :integer
|
# dossier_id :integer
|
||||||
# etablissement_id :integer
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
# parent_id :bigint
|
# parent_id :bigint
|
||||||
# type_de_champ_id :integer
|
# type_de_champ_id :integer
|
||||||
#
|
#
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# Table name: champs
|
# Table name: champs
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
# private :boolean default(FALSE), not null
|
# private :boolean default(FALSE), not null
|
||||||
# row :integer
|
# row :integer
|
||||||
# type :string
|
# type :string
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# dossier_id :integer
|
# dossier_id :integer
|
||||||
# etablissement_id :integer
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
# parent_id :bigint
|
# parent_id :bigint
|
||||||
# type_de_champ_id :integer
|
# type_de_champ_id :integer
|
||||||
#
|
#
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# Table name: champs
|
# Table name: champs
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
# private :boolean default(FALSE), not null
|
# private :boolean default(FALSE), not null
|
||||||
# row :integer
|
# row :integer
|
||||||
# type :string
|
# type :string
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# dossier_id :integer
|
# dossier_id :integer
|
||||||
# etablissement_id :integer
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
# parent_id :bigint
|
# parent_id :bigint
|
||||||
# type_de_champ_id :integer
|
# type_de_champ_id :integer
|
||||||
#
|
#
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# Table name: champs
|
# Table name: champs
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
# private :boolean default(FALSE), not null
|
# private :boolean default(FALSE), not null
|
||||||
# row :integer
|
# row :integer
|
||||||
# type :string
|
# type :string
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# dossier_id :integer
|
# dossier_id :integer
|
||||||
# etablissement_id :integer
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
# parent_id :bigint
|
# parent_id :bigint
|
||||||
# type_de_champ_id :integer
|
# type_de_champ_id :integer
|
||||||
#
|
#
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# Table name: champs
|
# Table name: champs
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
# private :boolean default(FALSE), not null
|
# private :boolean default(FALSE), not null
|
||||||
# row :integer
|
# row :integer
|
||||||
# type :string
|
# type :string
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# dossier_id :integer
|
# dossier_id :integer
|
||||||
# etablissement_id :integer
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
# parent_id :bigint
|
# parent_id :bigint
|
||||||
# type_de_champ_id :integer
|
# type_de_champ_id :integer
|
||||||
#
|
#
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# Table name: champs
|
# Table name: champs
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
# private :boolean default(FALSE), not null
|
# private :boolean default(FALSE), not null
|
||||||
# row :integer
|
# row :integer
|
||||||
# type :string
|
# type :string
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# dossier_id :integer
|
# dossier_id :integer
|
||||||
# etablissement_id :integer
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
# parent_id :bigint
|
# parent_id :bigint
|
||||||
# type_de_champ_id :integer
|
# type_de_champ_id :integer
|
||||||
#
|
#
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# Table name: champs
|
# Table name: champs
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
# private :boolean default(FALSE), not null
|
# private :boolean default(FALSE), not null
|
||||||
# row :integer
|
# row :integer
|
||||||
# type :string
|
# type :string
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# dossier_id :integer
|
# dossier_id :integer
|
||||||
# etablissement_id :integer
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
# parent_id :bigint
|
# parent_id :bigint
|
||||||
# type_de_champ_id :integer
|
# type_de_champ_id :integer
|
||||||
#
|
#
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# Table name: champs
|
# Table name: champs
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
# private :boolean default(FALSE), not null
|
# private :boolean default(FALSE), not null
|
||||||
# row :integer
|
# row :integer
|
||||||
# type :string
|
# type :string
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# dossier_id :integer
|
# dossier_id :integer
|
||||||
# etablissement_id :integer
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
# parent_id :bigint
|
# parent_id :bigint
|
||||||
# type_de_champ_id :integer
|
# type_de_champ_id :integer
|
||||||
#
|
#
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# Table name: champs
|
# Table name: champs
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
# private :boolean default(FALSE), not null
|
# private :boolean default(FALSE), not null
|
||||||
# row :integer
|
# row :integer
|
||||||
# type :string
|
# type :string
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# dossier_id :integer
|
# dossier_id :integer
|
||||||
# etablissement_id :integer
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
# parent_id :bigint
|
# parent_id :bigint
|
||||||
# type_de_champ_id :integer
|
# type_de_champ_id :integer
|
||||||
#
|
#
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# Table name: champs
|
# Table name: champs
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
# private :boolean default(FALSE), not null
|
# private :boolean default(FALSE), not null
|
||||||
# row :integer
|
# row :integer
|
||||||
# type :string
|
# type :string
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# dossier_id :integer
|
# dossier_id :integer
|
||||||
# etablissement_id :integer
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
# parent_id :bigint
|
# parent_id :bigint
|
||||||
# type_de_champ_id :integer
|
# type_de_champ_id :integer
|
||||||
#
|
#
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# Table name: champs
|
# Table name: champs
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
# private :boolean default(FALSE), not null
|
# private :boolean default(FALSE), not null
|
||||||
# row :integer
|
# row :integer
|
||||||
# type :string
|
# type :string
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# dossier_id :integer
|
# dossier_id :integer
|
||||||
# etablissement_id :integer
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
# parent_id :bigint
|
# parent_id :bigint
|
||||||
# type_de_champ_id :integer
|
# type_de_champ_id :integer
|
||||||
#
|
#
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# Table name: champs
|
# Table name: champs
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
# private :boolean default(FALSE), not null
|
# private :boolean default(FALSE), not null
|
||||||
# row :integer
|
# row :integer
|
||||||
# type :string
|
# type :string
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# dossier_id :integer
|
# dossier_id :integer
|
||||||
# etablissement_id :integer
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
# parent_id :bigint
|
# parent_id :bigint
|
||||||
# type_de_champ_id :integer
|
# type_de_champ_id :integer
|
||||||
#
|
#
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# Table name: champs
|
# Table name: champs
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
# private :boolean default(FALSE), not null
|
# private :boolean default(FALSE), not null
|
||||||
# row :integer
|
# row :integer
|
||||||
# type :string
|
# type :string
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# dossier_id :integer
|
# dossier_id :integer
|
||||||
# etablissement_id :integer
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
# parent_id :bigint
|
# parent_id :bigint
|
||||||
# type_de_champ_id :integer
|
# type_de_champ_id :integer
|
||||||
#
|
#
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# Table name: champs
|
# Table name: champs
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
# private :boolean default(FALSE), not null
|
# private :boolean default(FALSE), not null
|
||||||
# row :integer
|
# row :integer
|
||||||
# type :string
|
# type :string
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# dossier_id :integer
|
# dossier_id :integer
|
||||||
# etablissement_id :integer
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
# parent_id :bigint
|
# parent_id :bigint
|
||||||
# type_de_champ_id :integer
|
# type_de_champ_id :integer
|
||||||
#
|
#
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# Table name: champs
|
# Table name: champs
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
# private :boolean default(FALSE), not null
|
# private :boolean default(FALSE), not null
|
||||||
# row :integer
|
# row :integer
|
||||||
# type :string
|
# type :string
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# dossier_id :integer
|
# dossier_id :integer
|
||||||
# etablissement_id :integer
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
# parent_id :bigint
|
# parent_id :bigint
|
||||||
# type_de_champ_id :integer
|
# type_de_champ_id :integer
|
||||||
#
|
#
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# Table name: champs
|
# Table name: champs
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
# private :boolean default(FALSE), not null
|
# private :boolean default(FALSE), not null
|
||||||
# row :integer
|
# row :integer
|
||||||
# type :string
|
# type :string
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# dossier_id :integer
|
# dossier_id :integer
|
||||||
# etablissement_id :integer
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
# parent_id :bigint
|
# parent_id :bigint
|
||||||
# type_de_champ_id :integer
|
# type_de_champ_id :integer
|
||||||
#
|
#
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# Table name: champs
|
# Table name: champs
|
||||||
#
|
#
|
||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
|
# data :jsonb
|
||||||
# private :boolean default(FALSE), not null
|
# private :boolean default(FALSE), not null
|
||||||
# row :integer
|
# row :integer
|
||||||
# type :string
|
# type :string
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
# updated_at :datetime
|
# updated_at :datetime
|
||||||
# dossier_id :integer
|
# dossier_id :integer
|
||||||
# etablissement_id :integer
|
# etablissement_id :integer
|
||||||
|
# external_id :string
|
||||||
# parent_id :bigint
|
# parent_id :bigint
|
||||||
# type_de_champ_id :integer
|
# type_de_champ_id :integer
|
||||||
#
|
#
|
||||||
|
|
|
@ -47,7 +47,8 @@ class TypeDeChamp < ApplicationRecord
|
||||||
carte: 'carte',
|
carte: 'carte',
|
||||||
repetition: 'repetition',
|
repetition: 'repetition',
|
||||||
titre_identite: 'titre_identite',
|
titre_identite: 'titre_identite',
|
||||||
iban: 'iban'
|
iban: 'iban',
|
||||||
|
annuaire_education: 'annuaire_education'
|
||||||
}
|
}
|
||||||
|
|
||||||
belongs_to :revision, class_name: 'ProcedureRevision', optional: true
|
belongs_to :revision, class_name: 'ProcedureRevision', optional: true
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
class TypesDeChamp::AnnuaireEducationTypeDeChamp < TypesDeChamp::TextTypeDeChamp
|
||||||
|
end
|
185
app/schemas/etablissement-annuaire-education.json
Normal file
185
app/schemas/etablissement-annuaire-education.json
Normal file
|
@ -0,0 +1,185 @@
|
||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"$id": "http://demarches-simplifiees.fr/etablissement-annuaire-education.schema.json",
|
||||||
|
"title": "Établissement annuaire education",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"date_ouverture": {
|
||||||
|
"type": "date"
|
||||||
|
},
|
||||||
|
"ministere_tutelle": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"statut_public_prive": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"libelle_region": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"telephone": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"date_maj_ligne": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"libelle_nature": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"etat": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type_etablissement": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"identifiant_de_l_etablissement": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"code_region": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"siren_siret": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"mail": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"nom_circonscription": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"nom_commune": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"adresse_3": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"adresse_1": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"nombre_d_eleves": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0
|
||||||
|
},
|
||||||
|
"code_commune": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"code_departement": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"precision_localisation": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type_contrat_prive": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"code_postal": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"libelle_departement": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"code_academie": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"libelle_academie": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"nom_etablissement": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"epsg_origine": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"pial": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"code_nature": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0
|
||||||
|
},
|
||||||
|
"code_type_contrat_prive": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0
|
||||||
|
},
|
||||||
|
"ecole_elementaire": {
|
||||||
|
"enum": [0, 1]
|
||||||
|
},
|
||||||
|
"hebergement": {
|
||||||
|
"enum": [0, 1]
|
||||||
|
},
|
||||||
|
"rpi_concentre": {
|
||||||
|
"enum": [0, 1]
|
||||||
|
},
|
||||||
|
"ulis": {
|
||||||
|
"enum": [0, 1]
|
||||||
|
},
|
||||||
|
"restauration": {
|
||||||
|
"enum": [0, 1]
|
||||||
|
},
|
||||||
|
"ecole_maternelle": {
|
||||||
|
"enum": [0, 1]
|
||||||
|
},
|
||||||
|
"multi_uai": {
|
||||||
|
"enum": [0, 1]
|
||||||
|
},
|
||||||
|
"section_theatre": {
|
||||||
|
"enum": ["0", "1"]
|
||||||
|
},
|
||||||
|
"section_internationale": {
|
||||||
|
"enum": ["0", "1"]
|
||||||
|
},
|
||||||
|
"post_bac": {
|
||||||
|
"enum": ["0", "1"]
|
||||||
|
},
|
||||||
|
"section_cinema": {
|
||||||
|
"enum": ["0", "1"]
|
||||||
|
},
|
||||||
|
"section_europeenne": {
|
||||||
|
"enum": ["0", "1"]
|
||||||
|
},
|
||||||
|
"lycee_des_metiers": {
|
||||||
|
"enum": ["0", "1"]
|
||||||
|
},
|
||||||
|
"voie_professionnelle": {
|
||||||
|
"enum": ["0", "1"]
|
||||||
|
},
|
||||||
|
"lycee_militaire": {
|
||||||
|
"enum": ["0", "1"]
|
||||||
|
},
|
||||||
|
"section_sport": {
|
||||||
|
"enum": ["0", "1"]
|
||||||
|
},
|
||||||
|
"voie_technologique": {
|
||||||
|
"enum": ["0", "1"]
|
||||||
|
},
|
||||||
|
"section_arts": {
|
||||||
|
"enum": ["0", "1"]
|
||||||
|
},
|
||||||
|
"lycee_agricole": {
|
||||||
|
"enum": ["0", "1"]
|
||||||
|
},
|
||||||
|
"apprentissage": {
|
||||||
|
"enum": ["0", "1"]
|
||||||
|
},
|
||||||
|
"voie_generale": {
|
||||||
|
"enum": ["0", "1"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"identifiant_de_l_etablissement",
|
||||||
|
"nom_etablissement",
|
||||||
|
"statut_public_prive",
|
||||||
|
"type_contrat_prive",
|
||||||
|
"nom_commune",
|
||||||
|
"code_commune",
|
||||||
|
"nombre_d_eleves",
|
||||||
|
"siren_siret",
|
||||||
|
"libelle_academie",
|
||||||
|
"code_academie",
|
||||||
|
"libelle_nature",
|
||||||
|
"code_nature",
|
||||||
|
"adresse_1",
|
||||||
|
"code_postal",
|
||||||
|
"libelle_region",
|
||||||
|
"code_region"
|
||||||
|
]
|
||||||
|
}
|
54
app/views/shared/champs/annuaire_education/_show.html.haml
Normal file
54
app/views/shared/champs/annuaire_education/_show.html.haml
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
- if champ.data.blank?
|
||||||
|
= champ.to_s
|
||||||
|
- else
|
||||||
|
%table.table.vertical.dossier-champs
|
||||||
|
%tbody
|
||||||
|
%tr
|
||||||
|
%th.libelle Nom de l’établissement :
|
||||||
|
%td= champ.data['nom_etablissement']
|
||||||
|
%tr
|
||||||
|
%th.libelle L’identifiant de l’etablissement :
|
||||||
|
%td= champ.data['identifiant_de_l_etablissement']
|
||||||
|
%tr
|
||||||
|
%th.libelle SIREN/SIRET :
|
||||||
|
%td= champ.data['siren_siret']
|
||||||
|
%tr
|
||||||
|
%th.libelle Commune :
|
||||||
|
%td= "#{champ.data['nom_commune']} (#{champ.data['code_commune']})"
|
||||||
|
%tr
|
||||||
|
%th.libelle Academie :
|
||||||
|
%td= "#{champ.data['libelle_academie']} (#{champ.data['code_academie']})"
|
||||||
|
%tr
|
||||||
|
%th.libelle Nature de l’établissement :
|
||||||
|
%td= "#{champ.data['libelle_nature']} (#{champ.data['code_nature']})"
|
||||||
|
- if champ.data['type_contrat_prive'] != 'SANS OBJET'
|
||||||
|
%tr
|
||||||
|
%th.libelle Type de contrat privé :
|
||||||
|
%td= champ.data['type_contrat_prive']
|
||||||
|
%tr
|
||||||
|
%th.libelle Nombre d’élèves :
|
||||||
|
%td= champ.data['nombre_d_eleves']
|
||||||
|
|
||||||
|
%tr
|
||||||
|
%th.libelle Adresse :
|
||||||
|
%td
|
||||||
|
= champ.data['adresse_1']
|
||||||
|
%br
|
||||||
|
= "#{champ.data['code_postal']} #{champ.data['nom_commune']}"
|
||||||
|
%br
|
||||||
|
= "#{champ.data['libelle_region']} (#{champ.data['code_region']})"
|
||||||
|
|
||||||
|
- if champ.data['telephone'].present?
|
||||||
|
%tr
|
||||||
|
%th.libelle Téléphone :
|
||||||
|
%td= champ.data['telephone']
|
||||||
|
|
||||||
|
- if champ.data['mail'].present?
|
||||||
|
%tr
|
||||||
|
%th.libelle Email :
|
||||||
|
%td= champ.data['mail']
|
||||||
|
|
||||||
|
- if champ.data['web'].present?
|
||||||
|
%tr
|
||||||
|
%th.libelle Site internet :
|
||||||
|
%td= champ.data['web']
|
|
@ -34,6 +34,8 @@
|
||||||
= render partial: "shared/champs/iban/show", locals: { champ: c }
|
= render partial: "shared/champs/iban/show", locals: { champ: c }
|
||||||
- when TypeDeChamp.type_champs.fetch(:textarea)
|
- when TypeDeChamp.type_champs.fetch(:textarea)
|
||||||
= render partial: "shared/champs/textarea/show", locals: { champ: c }
|
= render partial: "shared/champs/textarea/show", locals: { champ: c }
|
||||||
|
- when TypeDeChamp.type_champs.fetch(:annuaire_education)
|
||||||
|
= render partial: "shared/champs/annuaire_education/show", locals: { champ: c }
|
||||||
- when TypeDeChamp.type_champs.fetch(:date)
|
- when TypeDeChamp.type_champs.fetch(:date)
|
||||||
= c.to_s
|
= c.to_s
|
||||||
- when TypeDeChamp.type_champs.fetch(:datetime)
|
- when TypeDeChamp.type_champs.fetch(:datetime)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
- hidden_field_id = SecureRandom.uuid
|
- hidden_field_id = SecureRandom.uuid
|
||||||
= form.hidden_field :value, { data: { uuid: hidden_field_id } }
|
= form.hidden_field :value, { data: { uuid: hidden_field_id } }
|
||||||
|
= form.hidden_field :external_id, { data: { reference: true } }
|
||||||
= react_component("ComboAdresseSearch", mandatory: champ.mandatory?, hiddenFieldId: hidden_field_id)
|
= react_component("ComboAdresseSearch", mandatory: champ.mandatory?, hiddenFieldId: hidden_field_id)
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
- hidden_field_id = SecureRandom.uuid
|
||||||
|
= form.hidden_field :value, { data: { uuid: hidden_field_id } }
|
||||||
|
= form.hidden_field :external_id, { data: { reference: true } }
|
||||||
|
= react_component("ComboAnnuaireEducationSearch", mandatory: champ.mandatory?, hiddenFieldId: hidden_field_id )
|
|
@ -1,3 +1,4 @@
|
||||||
- hidden_field_id = SecureRandom.uuid
|
- hidden_field_id = SecureRandom.uuid
|
||||||
= form.hidden_field :value, { data: { uuid: hidden_field_id } }
|
= form.hidden_field :value, { data: { uuid: hidden_field_id } }
|
||||||
|
= form.hidden_field :external_id, { data: { reference: true } }
|
||||||
= react_component("ComboCommunesSearch", mandatory: champ.mandatory?, hiddenFieldId: hidden_field_id)
|
= react_component("ComboCommunesSearch", mandatory: champ.mandatory?, hiddenFieldId: hidden_field_id)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
- hidden_field_id = SecureRandom.uuid
|
- hidden_field_id = SecureRandom.uuid
|
||||||
= form.hidden_field :value, { data: { uuid: hidden_field_id } }
|
= form.hidden_field :value, { data: { uuid: hidden_field_id } }
|
||||||
|
= form.hidden_field :external_id, { data: { reference: true } }
|
||||||
= react_component("ComboDepartementsSearch", mandatory: champ.mandatory?, hiddenFieldId: hidden_field_id)
|
= react_component("ComboDepartementsSearch", mandatory: champ.mandatory?, hiddenFieldId: hidden_field_id)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
- hidden_field_id = SecureRandom.uuid
|
- hidden_field_id = SecureRandom.uuid
|
||||||
= form.hidden_field :value, { data: { uuid: hidden_field_id } }
|
= form.hidden_field :value, { data: { uuid: hidden_field_id } }
|
||||||
|
= form.hidden_field :external_id, { data: { reference: true } }
|
||||||
= react_component("ComboRegionsSearch", mandatory: champ.mandatory?, hiddenFieldId: hidden_field_id)
|
= react_component("ComboRegionsSearch", mandatory: champ.mandatory?, hiddenFieldId: hidden_field_id)
|
||||||
|
|
|
@ -112,6 +112,9 @@ UNIVERSIGN_USERPWD=""
|
||||||
API_ADRESSE_URL="https://api-adresse.data.gouv.fr"
|
API_ADRESSE_URL="https://api-adresse.data.gouv.fr"
|
||||||
API_GEO_URL="https://geo.api.gouv.fr"
|
API_GEO_URL="https://geo.api.gouv.fr"
|
||||||
|
|
||||||
|
# API Education
|
||||||
|
API_EDUCATION_URL="https://data.education.gouv.fr/api/records/1.0"
|
||||||
|
|
||||||
# Modifier le nb de tentatives de relance de job si echec
|
# Modifier le nb de tentatives de relance de job si echec
|
||||||
# MAX_ATTEMPTS_JOBS=25
|
# MAX_ATTEMPTS_JOBS=25
|
||||||
# MAX_ATTEMPTS_API_ENTREPRISE_JOBS=5
|
# MAX_ATTEMPTS_API_ENTREPRISE_JOBS=5
|
||||||
|
|
|
@ -9,7 +9,7 @@ Rails.application.config.content_security_policy do |policy|
|
||||||
# c'est trop compliqué pour être rectifié immédiatement (et sans valeur ajoutée:
|
# c'est trop compliqué pour être rectifié immédiatement (et sans valeur ajoutée:
|
||||||
# c'est hardcodé dans les vues, donc pas injectable).
|
# c'est hardcodé dans les vues, donc pas injectable).
|
||||||
policy.style_src :self, "*.crisp.chat", "crisp.chat", 'cdn.jsdelivr.net', 'maxcdn.bootstrapcdn.com', :unsafe_inline
|
policy.style_src :self, "*.crisp.chat", "crisp.chat", 'cdn.jsdelivr.net', 'maxcdn.bootstrapcdn.com', :unsafe_inline
|
||||||
policy.connect_src :self, "wss://*.crisp.chat", "*.crisp.chat", "*.demarches-simplifiees.fr", "in-automate.sendinblue.com", "app.franceconnect.gouv.fr", "sentry.io", "geo.api.gouv.fr", "api-adresse.data.gouv.fr", "openmaptiles.geo.data.gouv.fr", "openmaptiles.github.io", "tiles.geo.api.gouv.fr", "wxs.ign.fr"
|
policy.connect_src :self, "wss://*.crisp.chat", "*.crisp.chat", "*.demarches-simplifiees.fr", "in-automate.sendinblue.com", "app.franceconnect.gouv.fr", "sentry.io", "geo.api.gouv.fr", "api-adresse.data.gouv.fr", "openmaptiles.geo.data.gouv.fr", "openmaptiles.github.io", "tiles.geo.api.gouv.fr", "wxs.ign.fr", "data.education.gouv.fr"
|
||||||
# Pour tout le reste, par défaut on accepte uniquement ce qui vient de chez nous
|
# Pour tout le reste, par défaut on accepte uniquement ce qui vient de chez nous
|
||||||
# et dans la notification on inclue la source de l'erreur
|
# et dans la notification on inclue la source de l'erreur
|
||||||
policy.default_src :self, :data, :blob, :report_sample, "fonts.gstatic.com", "in-automate.sendinblue.com", "player.vimeo.com", "app.franceconnect.gouv.fr", "sentry.io", "static.demarches-simplifiees.fr", "*.crisp.chat", "crisp.chat", "*.crisp.help", "*.sibautomation.com", "sibautomation.com", "data"
|
policy.default_src :self, :data, :blob, :report_sample, "fonts.gstatic.com", "in-automate.sendinblue.com", "player.vimeo.com", "app.franceconnect.gouv.fr", "sentry.io", "static.demarches-simplifiees.fr", "*.crisp.chat", "crisp.chat", "*.crisp.help", "*.sibautomation.com", "sibautomation.com", "data"
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
# API URLs
|
# API URLs
|
||||||
API_CARTO_URL = ENV.fetch("API_CARTO_URL", "https://sandbox.geo.api.gouv.fr/apicarto")
|
API_CARTO_URL = ENV.fetch("API_CARTO_URL", "https://sandbox.geo.api.gouv.fr/apicarto")
|
||||||
API_ENTREPRISE_URL = ENV.fetch("API_ENTREPRISE_URL", "https://entreprise.api.gouv.fr/v2")
|
API_ENTREPRISE_URL = ENV.fetch("API_ENTREPRISE_URL", "https://entreprise.api.gouv.fr/v2")
|
||||||
|
API_EDUCATION_URL = ENV.fetch("API_EDUCATION_URL", "https://data.education.gouv.fr/api/records/1.0")
|
||||||
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")
|
||||||
|
|
|
@ -35,3 +35,4 @@ fr:
|
||||||
repetition: 'Bloc répétable'
|
repetition: 'Bloc répétable'
|
||||||
titre_identite: 'Titre identité'
|
titre_identite: 'Titre identité'
|
||||||
iban: 'Iban'
|
iban: 'Iban'
|
||||||
|
annuaire_education: 'Annuaire de l’éducation'
|
||||||
|
|
|
@ -60,6 +60,7 @@ defaults: &defaults
|
||||||
autocomplete:
|
autocomplete:
|
||||||
api_geo_url: <%= ENV['API_GEO_URL'] %>
|
api_geo_url: <%= ENV['API_GEO_URL'] %>
|
||||||
api_adresse_url: <%= ENV['API_ADRESSE_URL'] %>
|
api_adresse_url: <%= ENV['API_ADRESSE_URL'] %>
|
||||||
|
api_education_url: <%= ENV['API_EDUCATION_URL'] %>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
5
db/migrate/20210113150013_add_data_to_champs.rb
Normal file
5
db/migrate/20210113150013_add_data_to_champs.rb
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
class AddDataToChamps < ActiveRecord::Migration[6.0]
|
||||||
|
def change
|
||||||
|
add_column :champs, :data, :jsonb
|
||||||
|
end
|
||||||
|
end
|
5
db/migrate/20210114224721_add_external_id_to_champs.rb
Normal file
5
db/migrate/20210114224721_add_external_id_to_champs.rb
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
class AddExternalIdToChamps < ActiveRecord::Migration[6.0]
|
||||||
|
def change
|
||||||
|
add_column :champs, :external_id, :string
|
||||||
|
end
|
||||||
|
end
|
|
@ -10,7 +10,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema.define(version: 2020_11_17_122923) do
|
ActiveRecord::Schema.define(version: 2021_01_14_224721) do
|
||||||
|
|
||||||
# These are extensions that must be enabled in order to support this database
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "plpgsql"
|
enable_extension "plpgsql"
|
||||||
|
@ -143,6 +143,8 @@ ActiveRecord::Schema.define(version: 2020_11_17_122923) do
|
||||||
t.integer "etablissement_id"
|
t.integer "etablissement_id"
|
||||||
t.bigint "parent_id"
|
t.bigint "parent_id"
|
||||||
t.integer "row"
|
t.integer "row"
|
||||||
|
t.jsonb "data"
|
||||||
|
t.string "external_id"
|
||||||
t.index ["dossier_id"], name: "index_champs_on_dossier_id"
|
t.index ["dossier_id"], name: "index_champs_on_dossier_id"
|
||||||
t.index ["parent_id"], name: "index_champs_on_parent_id"
|
t.index ["parent_id"], name: "index_champs_on_parent_id"
|
||||||
t.index ["private"], name: "index_champs_on_private"
|
t.index ["private"], name: "index_champs_on_private"
|
||||||
|
|
|
@ -409,6 +409,7 @@ describe API::V2::GraphqlController do
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
end
|
end
|
||||||
|
|
||||||
context "in the nominal case" do
|
context "in the nominal case" do
|
||||||
it "should be returned" do
|
it "should be returned" do
|
||||||
expect(gql_errors).to eq(nil)
|
expect(gql_errors).to eq(nil)
|
||||||
|
@ -497,6 +498,93 @@ describe API::V2::GraphqlController do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "champs" do
|
||||||
|
let(:procedure) { create(:procedure, :published, :for_individual, administrateurs: [admin], types_de_champ: [type_de_champ_date, type_de_champ_datetime]) }
|
||||||
|
let(:dossier) { create(:dossier, :en_construction, procedure: procedure) }
|
||||||
|
let(:type_de_champ_date) { build(:type_de_champ_date) }
|
||||||
|
let(:type_de_champ_datetime) { build(:type_de_champ_datetime) }
|
||||||
|
let(:champ_date) { dossier.champs.first }
|
||||||
|
let(:champ_datetime) { dossier.champs.second }
|
||||||
|
|
||||||
|
before do
|
||||||
|
champ_date.update(value: '2019-07-10')
|
||||||
|
champ_datetime.update(value: '15/09/1962 15:35')
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with Date" do
|
||||||
|
let(:query) do
|
||||||
|
"{
|
||||||
|
dossier(number: #{dossier.id}) {
|
||||||
|
champs {
|
||||||
|
id
|
||||||
|
label
|
||||||
|
... on DateChamp {
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should be returned" do
|
||||||
|
expect(gql_errors).to eq(nil)
|
||||||
|
expect(gql_data).to eq(dossier: {
|
||||||
|
champs: [
|
||||||
|
{
|
||||||
|
id: champ_date.to_typed_id,
|
||||||
|
label: champ_date.libelle,
|
||||||
|
value: '2019-07-10T00:00:00+02:00'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: champ_datetime.to_typed_id,
|
||||||
|
label: champ_datetime.libelle,
|
||||||
|
value: '1962-09-15T15:35:00+01:00'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with Datetime" do
|
||||||
|
let(:query) do
|
||||||
|
"{
|
||||||
|
dossier(number: #{dossier.id}) {
|
||||||
|
champs {
|
||||||
|
id
|
||||||
|
label
|
||||||
|
... on DateChamp {
|
||||||
|
value
|
||||||
|
date
|
||||||
|
}
|
||||||
|
... on DatetimeChamp {
|
||||||
|
datetime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should be returned" do
|
||||||
|
expect(gql_errors).to eq(nil)
|
||||||
|
expect(gql_data).to eq(dossier: {
|
||||||
|
champs: [
|
||||||
|
{
|
||||||
|
id: champ_date.to_typed_id,
|
||||||
|
label: champ_date.libelle,
|
||||||
|
value: '2019-07-10T00:00:00+02:00',
|
||||||
|
date: '2019-07-10'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: champ_datetime.to_typed_id,
|
||||||
|
label: champ_datetime.libelle,
|
||||||
|
datetime: '1962-09-15T15:35:00+01:00'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "groupeInstructeur" do
|
context "groupeInstructeur" do
|
||||||
|
|
|
@ -159,6 +159,10 @@ FactoryBot.define do
|
||||||
type_de_champ { association :type_de_champ_iban, procedure: dossier.procedure }
|
type_de_champ { association :type_de_champ_iban, procedure: dossier.procedure }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
factory :champ_annuaire_education, class: 'Champs::AnnuaireEducationChamp' do
|
||||||
|
type_de_champ { association :type_de_champ_annuaire_education, procedure: dossier.procedure }
|
||||||
|
end
|
||||||
|
|
||||||
factory :champ_siret, class: 'Champs::SiretChamp' do
|
factory :champ_siret, class: 'Champs::SiretChamp' do
|
||||||
association :type_de_champ, factory: [:type_de_champ_siret]
|
association :type_de_champ, factory: [:type_de_champ_siret]
|
||||||
association :etablissement, factory: [:etablissement]
|
association :etablissement, factory: [:etablissement]
|
||||||
|
|
|
@ -142,6 +142,9 @@ FactoryBot.define do
|
||||||
factory :type_de_champ_iban do
|
factory :type_de_champ_iban do
|
||||||
type_champ { TypeDeChamp.type_champs.fetch(:iban) }
|
type_champ { TypeDeChamp.type_champs.fetch(:iban) }
|
||||||
end
|
end
|
||||||
|
factory :type_de_champ_annuaire_education do
|
||||||
|
type_champ { TypeDeChamp.type_champs.fetch(:annuaire_education) }
|
||||||
|
end
|
||||||
factory :type_de_champ_carte do
|
factory :type_de_champ_carte do
|
||||||
type_champ { TypeDeChamp.type_champs.fetch(:carte) }
|
type_champ { TypeDeChamp.type_champs.fetch(:carte) }
|
||||||
end
|
end
|
||||||
|
|
91
spec/fixtures/files/api_education/annuaire_education.json
vendored
Normal file
91
spec/fixtures/files/api_education/annuaire_education.json
vendored
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
{
|
||||||
|
"nhits": 1,
|
||||||
|
"parameters": {
|
||||||
|
"dataset": "fr-en-annuaire-education",
|
||||||
|
"q": "0050009H",
|
||||||
|
"timezone": "UTC",
|
||||||
|
"rows": 1,
|
||||||
|
"start": 0,
|
||||||
|
"format": "json"
|
||||||
|
},
|
||||||
|
"records": [
|
||||||
|
{
|
||||||
|
"datasetid": "fr-en-annuaire-education",
|
||||||
|
"recordid": "0fd6a58dc6c7e5346e3bd62ada6216f476ebeeac",
|
||||||
|
"fields": {
|
||||||
|
"section_arts": "0",
|
||||||
|
"lycee_agricole": "0",
|
||||||
|
"apprentissage": "1",
|
||||||
|
"voie_generale": "0",
|
||||||
|
"ministere_tutelle": "MINISTERE DE L'EDUCATION NATIONALE",
|
||||||
|
"statut_public_prive": "Public",
|
||||||
|
"libelle_region": "Provence-Alpes-Côte d'Azur",
|
||||||
|
"telephone": "04 92 56 56 10",
|
||||||
|
"date_maj_ligne": "2021-01-12",
|
||||||
|
"hebergement": 1,
|
||||||
|
"libelle_nature": "LYCEE PROFESSIONNEL",
|
||||||
|
"lycee_militaire": "0",
|
||||||
|
"section_sport": "0",
|
||||||
|
"voie_technologique": "0",
|
||||||
|
"fiche_onisep": "http://geolocalisation.onisep.fr/05-hautes-alpes/gap/lycee/lycee-professionnel-sevigne.html",
|
||||||
|
"etat": "OUVERT",
|
||||||
|
"web": "www.lyc-sevigne.ac-aix-marseille.fr",
|
||||||
|
"rpi_concentre": 0,
|
||||||
|
"identifiant_de_l_etablissement": "0050009H",
|
||||||
|
"code_region": "93",
|
||||||
|
"ulis": 1,
|
||||||
|
"restauration": 1,
|
||||||
|
"code_departement": "05",
|
||||||
|
"date_ouverture": "1965-05-01",
|
||||||
|
"voie_professionnelle": "1",
|
||||||
|
"greta": "1",
|
||||||
|
"coordy_origine": 6389542.2,
|
||||||
|
"siren_siret": "19050009000013",
|
||||||
|
"mail": "ce.0050009H@ac-aix-marseille.fr",
|
||||||
|
"type_contrat_prive": "SANS OBJET",
|
||||||
|
"nom_commune": "Gap",
|
||||||
|
"segpa": "0",
|
||||||
|
"adresse_3": "05000 GAP",
|
||||||
|
"fax": "04 92 56 56 30",
|
||||||
|
"type_etablissement": "Lycée",
|
||||||
|
"nombre_d_eleves": 451,
|
||||||
|
"libelle_zone_animation_pedagogique": "GAP",
|
||||||
|
"code_commune": "05061",
|
||||||
|
"latitude": 44.562179100043984,
|
||||||
|
"section_theatre": "0",
|
||||||
|
"section_internationale": "0",
|
||||||
|
"post_bac": "1",
|
||||||
|
"precision_localisation": "Numéro de rue",
|
||||||
|
"multi_uai": 0,
|
||||||
|
"code_postal": "05000",
|
||||||
|
"libelle_departement": "Hautes-Alpes",
|
||||||
|
"section_cinema": "0",
|
||||||
|
"section_europeenne": "1",
|
||||||
|
"libelle_academie": "Aix-Marseille",
|
||||||
|
"longitude": 6.0746303437466915,
|
||||||
|
"code_zone_animation_pedagogique": "02104",
|
||||||
|
"code_academie": "02",
|
||||||
|
"lycee_des_metiers": "1",
|
||||||
|
"epsg_origine": "EPSG:2154",
|
||||||
|
"adresse_1": "6 rue Jean Macé",
|
||||||
|
"nom_etablissement": "Lycée professionnel Sévigné",
|
||||||
|
"pial": "0050009H",
|
||||||
|
"code_nature": 320,
|
||||||
|
"position": [
|
||||||
|
44.562179100043984,
|
||||||
|
6.0746303437466915
|
||||||
|
],
|
||||||
|
"code_type_contrat_prive": 99,
|
||||||
|
"coordx_origine": 944110.8
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
6.0746303437466915,
|
||||||
|
44.562179100043984
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"record_timestamp": "2021-01-12T18:03:00+00:00"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
58
spec/fixtures/files/api_education/annuaire_education_invalid.json
vendored
Normal file
58
spec/fixtures/files/api_education/annuaire_education_invalid.json
vendored
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
{
|
||||||
|
"nhits": 1,
|
||||||
|
"parameters": {
|
||||||
|
"dataset": "fr-en-annuaire-education",
|
||||||
|
"q": "0050009H",
|
||||||
|
"timezone": "UTC",
|
||||||
|
"rows": 1,
|
||||||
|
"start": 0,
|
||||||
|
"format": "json"
|
||||||
|
},
|
||||||
|
"records": [
|
||||||
|
{
|
||||||
|
"datasetid": "fr-en-annuaire-education",
|
||||||
|
"recordid": "0fd6a58dc6c7e5346e3bd62ada6216f476ebeeac",
|
||||||
|
"fields": {
|
||||||
|
"section_arts": "0",
|
||||||
|
"lycee_agricole": "0",
|
||||||
|
"apprentissage": "1",
|
||||||
|
"voie_generale": "0",
|
||||||
|
"ministere_tutelle": "MINISTERE DE L'EDUCATION NATIONALE",
|
||||||
|
"statut_public_prive": "Public",
|
||||||
|
"libelle_region": "Provence-Alpes-Côte d'Azur",
|
||||||
|
"telephone": "04 92 56 56 10",
|
||||||
|
"date_maj_ligne": "2021-01-12",
|
||||||
|
"hebergement": 1,
|
||||||
|
"libelle_nature": "LYCEE PROFESSIONNEL",
|
||||||
|
"lycee_militaire": "0",
|
||||||
|
"section_sport": "0",
|
||||||
|
"voie_technologique": "0",
|
||||||
|
"fiche_onisep": "http://geolocalisation.onisep.fr/05-hautes-alpes/gap/lycee/lycee-professionnel-sevigne.html",
|
||||||
|
"etat": "OUVERT",
|
||||||
|
"web": "www.lyc-sevigne.ac-aix-marseille.fr",
|
||||||
|
"rpi_concentre": 0,
|
||||||
|
"code_region": "93",
|
||||||
|
"ulis": 1,
|
||||||
|
"restauration": 1,
|
||||||
|
"code_departement": "05",
|
||||||
|
"date_ouverture": "1965-05-01",
|
||||||
|
"voie_professionnelle": "1",
|
||||||
|
"greta": "1",
|
||||||
|
"coordy_origine": 6389542.2,
|
||||||
|
"siren_siret": "19050009000013",
|
||||||
|
"mail": "ce.0050009H@ac-aix-marseille.fr",
|
||||||
|
"type_contrat_prive": "SANS OBJET",
|
||||||
|
"nom_commune": "Gap",
|
||||||
|
"segpa": "0"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
6.0746303437466915,
|
||||||
|
44.562179100043984
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"record_timestamp": "2021-01-12T18:03:00+00:00"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
29
spec/lib/api_education/annuaire_education_adapter_spec.rb
Normal file
29
spec/lib/api_education/annuaire_education_adapter_spec.rb
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
describe ApiEducation::AnnuaireEducationAdapter do
|
||||||
|
let(:search_term) { '0050009H' }
|
||||||
|
let(:adapter) { described_class.new(search_term) }
|
||||||
|
subject { adapter.to_params }
|
||||||
|
|
||||||
|
before do
|
||||||
|
stub_request(:get, /https:\/\/data.education.gouv.fr\/api\/records\/1.0/)
|
||||||
|
.to_return(body: body, status: status)
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when responds with valid schema" do
|
||||||
|
let(:body) { File.read('spec/fixtures/files/api_education/annuaire_education.json') }
|
||||||
|
let(:status) { 200 }
|
||||||
|
|
||||||
|
it '#to_params return vaid hash' do
|
||||||
|
expect(subject).to be_an_instance_of(Hash)
|
||||||
|
expect(subject['identifiant_de_l_etablissement']).to eq(search_term)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when responds with invalid schema" do
|
||||||
|
let(:body) { File.read('spec/fixtures/files/api_education/annuaire_education_invalid.json') }
|
||||||
|
let(:status) { 200 }
|
||||||
|
|
||||||
|
it '#to_params raise exception' do
|
||||||
|
expect { subject }.to raise_exception(ApiEducation::AnnuaireEducationAdapter::InvalidSchemaError)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -75,6 +75,7 @@ describe ProcedureExportService do
|
||||||
"carte",
|
"carte",
|
||||||
"titre_identite",
|
"titre_identite",
|
||||||
"iban",
|
"iban",
|
||||||
|
"annuaire_education",
|
||||||
"text"
|
"text"
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
@ -160,6 +161,7 @@ describe ProcedureExportService do
|
||||||
"carte",
|
"carte",
|
||||||
"titre_identite",
|
"titre_identite",
|
||||||
"iban",
|
"iban",
|
||||||
|
"annuaire_education",
|
||||||
"text"
|
"text"
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
@ -241,6 +243,7 @@ describe ProcedureExportService do
|
||||||
"carte",
|
"carte",
|
||||||
"titre_identite",
|
"titre_identite",
|
||||||
"iban",
|
"iban",
|
||||||
|
"annuaire_education",
|
||||||
"text"
|
"text"
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue