commit
293e7b087a
95 changed files with 948 additions and 1168 deletions
3
Gemfile
3
Gemfile
|
@ -29,6 +29,7 @@ gem 'flipper-active_record'
|
||||||
gem 'flipper-ui'
|
gem 'flipper-ui'
|
||||||
gem 'fog-openstack'
|
gem 'fog-openstack'
|
||||||
gem 'font-awesome-rails'
|
gem 'font-awesome-rails'
|
||||||
|
gem 'geocoder'
|
||||||
gem 'gon'
|
gem 'gon'
|
||||||
gem 'graphiql-rails'
|
gem 'graphiql-rails'
|
||||||
gem 'graphql'
|
gem 'graphql'
|
||||||
|
@ -49,6 +50,7 @@ gem 'openstack'
|
||||||
gem 'pg'
|
gem 'pg'
|
||||||
gem 'phonelib'
|
gem 'phonelib'
|
||||||
gem 'prawn' # PDF Generation
|
gem 'prawn' # PDF Generation
|
||||||
|
gem 'prawn-svg'
|
||||||
gem 'prawn_rails'
|
gem 'prawn_rails'
|
||||||
gem 'premailer-rails'
|
gem 'premailer-rails'
|
||||||
gem 'puma' # Use Puma as the app server
|
gem 'puma' # Use Puma as the app server
|
||||||
|
@ -64,7 +66,6 @@ gem 'rgeo-geojson'
|
||||||
gem 'sanitize-url'
|
gem 'sanitize-url'
|
||||||
gem 'sassc-rails' # Use SCSS for stylesheets
|
gem 'sassc-rails' # Use SCSS for stylesheets
|
||||||
gem 'scenic'
|
gem 'scenic'
|
||||||
gem 'select2-rails'
|
|
||||||
gem 'sentry-raven'
|
gem 'sentry-raven'
|
||||||
gem 'skylight'
|
gem 'skylight'
|
||||||
gem 'smart_listing'
|
gem 'smart_listing'
|
||||||
|
|
|
@ -232,6 +232,7 @@ GEM
|
||||||
font-awesome-rails (4.7.0.4)
|
font-awesome-rails (4.7.0.4)
|
||||||
railties (>= 3.2, < 6.0)
|
railties (>= 3.2, < 6.0)
|
||||||
formatador (0.2.5)
|
formatador (0.2.5)
|
||||||
|
geocoder (1.6.0)
|
||||||
globalid (0.4.2)
|
globalid (0.4.2)
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 4.2.0)
|
||||||
gon (6.2.1)
|
gon (6.2.1)
|
||||||
|
@ -425,6 +426,9 @@ GEM
|
||||||
prawn (2.2.2)
|
prawn (2.2.2)
|
||||||
pdf-core (~> 0.7.0)
|
pdf-core (~> 0.7.0)
|
||||||
ttfunk (~> 1.5)
|
ttfunk (~> 1.5)
|
||||||
|
prawn-svg (0.29.1)
|
||||||
|
css_parser (~> 1.6)
|
||||||
|
prawn (>= 0.11.1, < 3)
|
||||||
prawn_rails (0.0.11)
|
prawn_rails (0.0.11)
|
||||||
prawn (>= 0.11.1)
|
prawn (>= 0.11.1)
|
||||||
railties (>= 3.0.0)
|
railties (>= 3.0.0)
|
||||||
|
@ -592,8 +596,6 @@ GEM
|
||||||
scss_lint (0.57.1)
|
scss_lint (0.57.1)
|
||||||
rake (>= 0.9, < 13)
|
rake (>= 0.9, < 13)
|
||||||
sass (~> 3.5, >= 3.5.5)
|
sass (~> 3.5, >= 3.5.5)
|
||||||
select2-rails (4.0.3)
|
|
||||||
thor (~> 0.14)
|
|
||||||
selectize-rails (0.12.6)
|
selectize-rails (0.12.6)
|
||||||
selenium-webdriver (3.141.0)
|
selenium-webdriver (3.141.0)
|
||||||
childprocess (~> 0.5)
|
childprocess (~> 0.5)
|
||||||
|
@ -742,6 +744,7 @@ DEPENDENCIES
|
||||||
flipper-ui
|
flipper-ui
|
||||||
fog-openstack
|
fog-openstack
|
||||||
font-awesome-rails
|
font-awesome-rails
|
||||||
|
geocoder
|
||||||
gon
|
gon
|
||||||
graphiql-rails
|
graphiql-rails
|
||||||
graphql
|
graphql
|
||||||
|
@ -770,6 +773,7 @@ DEPENDENCIES
|
||||||
pg
|
pg
|
||||||
phonelib
|
phonelib
|
||||||
prawn
|
prawn
|
||||||
|
prawn-svg
|
||||||
prawn_rails
|
prawn_rails
|
||||||
premailer-rails
|
premailer-rails
|
||||||
pry-byebug
|
pry-byebug
|
||||||
|
@ -793,7 +797,6 @@ DEPENDENCIES
|
||||||
sassc-rails
|
sassc-rails
|
||||||
scenic
|
scenic
|
||||||
scss_lint
|
scss_lint
|
||||||
select2-rails
|
|
||||||
sentry-raven
|
sentry-raven
|
||||||
shoulda-matchers
|
shoulda-matchers
|
||||||
simple_xlsx_reader
|
simple_xlsx_reader
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
// = require search
|
// = require search
|
||||||
// = require site_banner
|
// = require site_banner
|
||||||
// = require switch_menu
|
// = require switch_menu
|
||||||
// = require autocomplete
|
|
||||||
// = require users
|
// = require users
|
||||||
// = require attestation_template_edit
|
// = require attestation_template_edit
|
||||||
|
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
.algolia-autocomplete {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.algolia-autocomplete .aa-input,
|
|
||||||
.algolia-autocomplete .aa-hint {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.algolia-autocomplete .aa-hint {
|
|
||||||
color: #999999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.algolia-autocomplete .aa-dropdown-menu {
|
|
||||||
width: 100%;
|
|
||||||
background-color: #FFFFFF;
|
|
||||||
border: 1px solid #999999;
|
|
||||||
border-top: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.algolia-autocomplete .aa-dropdown-menu .aa-suggestion {
|
|
||||||
cursor: pointer;
|
|
||||||
padding: 5px 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.algolia-autocomplete .aa-dropdown-menu .aa-suggestion.aa-cursor {
|
|
||||||
background-color: #B2D7FF;
|
|
||||||
}
|
|
||||||
|
|
||||||
.algolia-autocomplete .aa-dropdown-menu .aa-suggestion em {
|
|
||||||
font-weight: bold;
|
|
||||||
font-style: normal;
|
|
||||||
}
|
|
|
@ -242,6 +242,16 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.select2-selection--single {
|
||||||
|
min-height: 62px;
|
||||||
|
|
||||||
|
// scss-lint:disable SelectorFormat
|
||||||
|
.select2-selection__arrow {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
// scss-lint:enable
|
||||||
|
}
|
||||||
|
|
||||||
// scss-lint:disable SelectorFormat
|
// scss-lint:disable SelectorFormat
|
||||||
.select2-selection__rendered {
|
.select2-selection__rendered {
|
||||||
padding: $default-padding;
|
padding: $default-padding;
|
||||||
|
|
|
@ -63,6 +63,10 @@
|
||||||
width: 200px;
|
width: 200px;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.select2-container {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,5 @@
|
||||||
// = require ./fonts
|
// = require ./fonts
|
||||||
// = require leaflet
|
// = require leaflet
|
||||||
// = require select2
|
// = require select2
|
||||||
// = require autocomplete
|
|
||||||
// = require_tree .
|
// = require_tree .
|
||||||
// = stub ./print.scss
|
// = stub ./print.scss
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
class AddressController < ApplicationController
|
|
||||||
def suggestions
|
|
||||||
request = params[:request]
|
|
||||||
|
|
||||||
json = ApiAdresse::AddressAdapter.new(request).get_suggestions.map do |value|
|
|
||||||
{ label: value }
|
|
||||||
end.to_json
|
|
||||||
|
|
||||||
render json: json
|
|
||||||
end
|
|
||||||
|
|
||||||
def geocode
|
|
||||||
request = params[:request]
|
|
||||||
|
|
||||||
point = ApiAdresse::PointAdapter.new(request).geocode
|
|
||||||
|
|
||||||
if point.present?
|
|
||||||
lon = point.x.to_s
|
|
||||||
lat = point.y.to_s
|
|
||||||
end
|
|
||||||
|
|
||||||
render json: { lon: lon, lat: lat, zoom: '14', dossier_id: params[:dossier_id] }
|
|
||||||
end
|
|
||||||
end
|
|
13
app/controllers/api_geo_test_controller.rb
Normal file
13
app/controllers/api_geo_test_controller.rb
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
class APIGeoTestController < ActionController::Base
|
||||||
|
def regions
|
||||||
|
render json: [{ nom: 'Martinique' }]
|
||||||
|
end
|
||||||
|
|
||||||
|
def departements
|
||||||
|
render json: [{ nom: 'Aisne', code: '02' }]
|
||||||
|
end
|
||||||
|
|
||||||
|
def communes
|
||||||
|
render json: [{ nom: 'Ambléon' }]
|
||||||
|
end
|
||||||
|
end
|
|
@ -117,6 +117,7 @@ class ApplicationController < ActionController::Base
|
||||||
|
|
||||||
def setup_javascript_settings
|
def setup_javascript_settings
|
||||||
gon.autosave = Rails.application.config.ds_autosave
|
gon.autosave = Rails.application.config.ds_autosave
|
||||||
|
gon.autocomplete = Rails.application.secrets.autocomplete
|
||||||
end
|
end
|
||||||
|
|
||||||
def setup_tracking
|
def setup_tracking
|
||||||
|
|
|
@ -27,6 +27,14 @@ module Instructeurs
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@demande_seen_at = current_instructeur.follows.find_by(dossier: dossier)&.demande_seen_at
|
@demande_seen_at = current_instructeur.follows.find_by(dossier: dossier)&.demande_seen_at
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.pdf do
|
||||||
|
@include_infos_administration = true
|
||||||
|
render(file: 'dossiers/show', formats: [:pdf])
|
||||||
|
end
|
||||||
|
format.all
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def messagerie
|
def messagerie
|
||||||
|
|
|
@ -22,11 +22,7 @@ module Manager
|
||||||
def delete
|
def delete
|
||||||
administrateur = Administrateur.find(params[:id])
|
administrateur = Administrateur.find(params[:id])
|
||||||
|
|
||||||
if !administrateur.can_be_deleted?
|
administrateur.delete_and_transfer_services
|
||||||
fail "Impossible de supprimer cet administrateur car il a des dossiers ou des procédures"
|
|
||||||
end
|
|
||||||
administrateur.dossiers.each(&:delete_and_keep_track)
|
|
||||||
administrateur.destroy
|
|
||||||
|
|
||||||
logger.info("L'administrateur #{administrateur.id} est supprimé par #{current_administration.id}")
|
logger.info("L'administrateur #{administrateur.id} est supprimé par #{current_administration.id}")
|
||||||
flash[:notice] = "L'administrateur #{administrateur.id} est supprimé"
|
flash[:notice] = "L'administrateur #{administrateur.id} est supprimé"
|
||||||
|
|
|
@ -6,5 +6,19 @@ module Manager
|
||||||
flash[:notice] = "Instructeur réinvité."
|
flash[:notice] = "Instructeur réinvité."
|
||||||
redirect_to manager_instructeur_path(instructeur)
|
redirect_to manager_instructeur_path(instructeur)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def delete
|
||||||
|
instructeur = Instructeur.find(params[:id])
|
||||||
|
|
||||||
|
if !instructeur.can_be_deleted?
|
||||||
|
fail "Impossible de supprimer cet instructeur car il est administrateur ou il est le seul instructeur sur une démarche"
|
||||||
|
end
|
||||||
|
instructeur.destroy!
|
||||||
|
|
||||||
|
logger.info("L'instructeur #{instructeur.id} est supprimé par #{current_administration.id}")
|
||||||
|
flash[:notice] = "L'instructeur #{instructeur.id} est supprimé"
|
||||||
|
|
||||||
|
redirect_to manager_instructeurs_path
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -24,7 +24,7 @@ module Manager
|
||||||
def delete
|
def delete
|
||||||
user = User.find(params[:id])
|
user = User.find(params[:id])
|
||||||
if !user.can_be_deleted?
|
if !user.can_be_deleted?
|
||||||
fail "Impossible de supprimer cet utilisateur car il a des dossiers en instruction"
|
fail "Impossible de supprimer cet utilisateur. Il a des dossiers en instruction ou il est administrateur."
|
||||||
end
|
end
|
||||||
user.delete_and_keep_track_dossiers(current_administration)
|
user.delete_and_keep_track_dossiers(current_administration)
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,33 @@ module NewAdministrateur
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
if !groupe_instructeur.dossiers.empty?
|
||||||
|
flash[:alert] = "Impossible de supprimer un groupe avec des dossiers. Il faut le réaffecter avant"
|
||||||
|
elsif procedure.groupe_instructeurs.one?
|
||||||
|
flash[:alert] = "Suppression impossible : il doit y avoir au moins un groupe instructeur sur chaque procédure"
|
||||||
|
else
|
||||||
|
label = groupe_instructeur.label
|
||||||
|
groupe_instructeur.destroy!
|
||||||
|
flash[:notice] = "le groupe « #{label} » a été supprimé."
|
||||||
|
end
|
||||||
|
redirect_to procedure_groupe_instructeurs_path(procedure)
|
||||||
|
end
|
||||||
|
|
||||||
|
def reaffecter_dossiers
|
||||||
|
@procedure = procedure
|
||||||
|
@groupe_instructeur = groupe_instructeur
|
||||||
|
@groupes_instructeurs = paginated_groupe_instructeurs
|
||||||
|
.without_group(@groupe_instructeur)
|
||||||
|
end
|
||||||
|
|
||||||
|
def reaffecter
|
||||||
|
target_group = procedure.groupe_instructeurs.find(params[:target_group])
|
||||||
|
groupe_instructeur.dossiers.update_all(groupe_instructeur_id: target_group.id)
|
||||||
|
flash[:notice] = "Les dossiers du groupe « #{groupe_instructeur.label} » ont été réaffectés au groupe « #{target_group.label} »."
|
||||||
|
redirect_to procedure_groupe_instructeurs_path(procedure)
|
||||||
|
end
|
||||||
|
|
||||||
def add_instructeur
|
def add_instructeur
|
||||||
emails = params['emails'].presence || []
|
emails = params['emails'].presence || []
|
||||||
emails = emails.map(&:strip).map(&:downcase)
|
emails = emails.map(&:strip).map(&:downcase)
|
||||||
|
|
|
@ -36,6 +36,13 @@ module Users
|
||||||
end
|
end
|
||||||
|
|
||||||
@dossier = dossier
|
@dossier = dossier
|
||||||
|
respond_to do |format|
|
||||||
|
format.pdf do
|
||||||
|
@include_infos_administration = false
|
||||||
|
render(file: 'dossiers/show', formats: [:pdf])
|
||||||
|
end
|
||||||
|
format.all
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def demande
|
def demande
|
||||||
|
|
|
@ -1012,6 +1012,11 @@ enum TypeDeChamp {
|
||||||
"""
|
"""
|
||||||
civilite
|
civilite
|
||||||
|
|
||||||
|
"""
|
||||||
|
Communes
|
||||||
|
"""
|
||||||
|
communes
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Date
|
Date
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1,46 +1,158 @@
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import 'select2';
|
import 'select2';
|
||||||
|
|
||||||
const optionTemplate = email =>
|
const { api_geo_url, api_adresse_url } = gon.autocomplete || {};
|
||||||
|
|
||||||
|
const language = {
|
||||||
|
errorLoading: function() {
|
||||||
|
return 'Les résultats ne peuvent pas être chargés.';
|
||||||
|
},
|
||||||
|
inputTooLong: function(args) {
|
||||||
|
var overChars = args.input.length - args.maximum;
|
||||||
|
|
||||||
|
return 'Supprimez ' + overChars + ' caractère' + (overChars > 1 ? 's' : '');
|
||||||
|
},
|
||||||
|
inputTooShort: function(args) {
|
||||||
|
var remainingChars = args.minimum - args.input.length;
|
||||||
|
|
||||||
|
return (
|
||||||
|
'Saisissez au moins ' +
|
||||||
|
remainingChars +
|
||||||
|
' caractère' +
|
||||||
|
(remainingChars > 1 ? 's' : '')
|
||||||
|
);
|
||||||
|
},
|
||||||
|
loadingMore: function() {
|
||||||
|
return 'Chargement de résultats supplémentaires…';
|
||||||
|
},
|
||||||
|
maximumSelected: function(args) {
|
||||||
|
return (
|
||||||
|
'Vous pouvez seulement sélectionner ' +
|
||||||
|
args.maximum +
|
||||||
|
' élément' +
|
||||||
|
(args.maximum > 1 ? 's' : '')
|
||||||
|
);
|
||||||
|
},
|
||||||
|
noResults: function() {
|
||||||
|
return 'Aucun résultat trouvé';
|
||||||
|
},
|
||||||
|
searching: function() {
|
||||||
|
return 'Recherche en cours…';
|
||||||
|
},
|
||||||
|
removeAllItems: function() {
|
||||||
|
return 'Supprimer tous les éléments';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const baseOptions = {
|
||||||
|
language,
|
||||||
|
width: '100%'
|
||||||
|
};
|
||||||
|
|
||||||
|
const baseAjaxOptions = {
|
||||||
|
delay: 250,
|
||||||
|
cache: true,
|
||||||
|
data({ term: nom }) {
|
||||||
|
return {
|
||||||
|
nom,
|
||||||
|
fields: 'nom,code'
|
||||||
|
};
|
||||||
|
},
|
||||||
|
processResults(data) {
|
||||||
|
return {
|
||||||
|
results: data.map(({ nom }) => ({ id: nom, text: nom }))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const regionsOptions = {
|
||||||
|
...baseOptions,
|
||||||
|
minimumInputLength: 2,
|
||||||
|
ajax: { url: `${api_geo_url}/regions`, ...baseAjaxOptions }
|
||||||
|
};
|
||||||
|
|
||||||
|
const communesOptions = {
|
||||||
|
...baseOptions,
|
||||||
|
minimumInputLength: 2,
|
||||||
|
ajax: { url: `${api_geo_url}/communes`, ...baseAjaxOptions }
|
||||||
|
};
|
||||||
|
|
||||||
|
const etranger99 = { id: '99 - Étranger', text: '99 - Étranger' };
|
||||||
|
const departementsOptions = {
|
||||||
|
...baseOptions,
|
||||||
|
minimumInputLength: 2,
|
||||||
|
ajax: {
|
||||||
|
...baseAjaxOptions,
|
||||||
|
url: `${api_geo_url}/departements`,
|
||||||
|
processResults(data) {
|
||||||
|
return {
|
||||||
|
results: data
|
||||||
|
.map(({ nom, code }) => ({
|
||||||
|
id: `${code} - ${nom}`,
|
||||||
|
text: `${code} - ${nom}`
|
||||||
|
}))
|
||||||
|
.concat([etranger99])
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const adresseOptions = {
|
||||||
|
...baseOptions,
|
||||||
|
minimumInputLength: 2,
|
||||||
|
ajax: {
|
||||||
|
...baseAjaxOptions,
|
||||||
|
url: `${api_adresse_url}/search`,
|
||||||
|
data({ term: q }) {
|
||||||
|
return {
|
||||||
|
q,
|
||||||
|
limit: 5
|
||||||
|
};
|
||||||
|
},
|
||||||
|
processResults(data) {
|
||||||
|
return {
|
||||||
|
results: data.features.map(({ properties: { label }, geometry }) => ({
|
||||||
|
id: label,
|
||||||
|
text: label,
|
||||||
|
geometry
|
||||||
|
}))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const templateOption = ({ text }) =>
|
||||||
$(
|
$(
|
||||||
'<span class="custom-select2-option"><span class="icon person"></span>' +
|
`<span class="custom-select2-option"><span class="icon person"></span>${text}</span>`
|
||||||
email.text +
|
|
||||||
'</span>'
|
|
||||||
);
|
);
|
||||||
|
|
||||||
addEventListener('ds:page:update', () => {
|
addEventListener('ds:page:update', () => {
|
||||||
$('select.select2').select2({
|
$('select.select2').select2(baseOptions);
|
||||||
language: 'fr',
|
$('select.select2.departements').select2(departementsOptions);
|
||||||
width: '100%'
|
$('select.select2.regions').select2(regionsOptions);
|
||||||
});
|
$('select.select2.communes').select2(communesOptions);
|
||||||
|
$('select.select2.adresse').select2(adresseOptions);
|
||||||
|
|
||||||
$('.columns-form select.select2-limited').select2({
|
$('.columns-form select.select2-limited').select2({
|
||||||
language: 'fr',
|
width: '300px',
|
||||||
placeholder: 'Sélectionnez des colonnes',
|
placeholder: 'Sélectionnez des colonnes',
|
||||||
maximumSelectionLength: '5',
|
maximumSelectionLength: '5'
|
||||||
width: '300px'
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.recipients-form select.select2-limited').select2({
|
$('.recipients-form select.select2-limited').select2({
|
||||||
language: 'fr',
|
language,
|
||||||
|
width: '300px',
|
||||||
placeholder: 'Sélectionnez des instructeurs',
|
placeholder: 'Sélectionnez des instructeurs',
|
||||||
maximumSelectionLength: '30',
|
maximumSelectionLength: '30'
|
||||||
width: '300px'
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$('select.select2-limited.select-instructeurs').select2({
|
$('select.select2-limited.select-instructeurs').select2({
|
||||||
language: 'fr',
|
language,
|
||||||
dropdownParent: $('.instructeur-wrapper'),
|
dropdownParent: $('.instructeur-wrapper'),
|
||||||
placeholder: 'Saisir l’adresse email de l’instructeur',
|
placeholder: 'Saisir l’adresse email de l’instructeur',
|
||||||
tags: true,
|
tags: true,
|
||||||
tokenSeparators: [',', ' '],
|
tokenSeparators: [',', ' '],
|
||||||
templateResult: optionTemplate,
|
templateResult: templateOption,
|
||||||
templateSelection: function(email) {
|
templateSelection: templateOption
|
||||||
return $(
|
|
||||||
'<span class="custom-select2-option"><span class="icon person"></span>' +
|
|
||||||
email.text +
|
|
||||||
'</span>'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,7 +8,6 @@ import '../shared/page-update-event';
|
||||||
import '../shared/activestorage/ujs';
|
import '../shared/activestorage/ujs';
|
||||||
import '../shared/rails-ujs-fix';
|
import '../shared/rails-ujs-fix';
|
||||||
import '../shared/safari-11-file-xhr-workaround';
|
import '../shared/safari-11-file-xhr-workaround';
|
||||||
import '../shared/autocomplete';
|
|
||||||
import '../shared/remote-input';
|
import '../shared/remote-input';
|
||||||
import '../shared/franceconnect';
|
import '../shared/franceconnect';
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,6 @@ import '../shared/activestorage/ujs';
|
||||||
import '../shared/activestorage/attachment-checker';
|
import '../shared/activestorage/attachment-checker';
|
||||||
import '../shared/rails-ujs-fix';
|
import '../shared/rails-ujs-fix';
|
||||||
import '../shared/safari-11-file-xhr-workaround';
|
import '../shared/safari-11-file-xhr-workaround';
|
||||||
import '../shared/autocomplete';
|
|
||||||
import '../shared/remote-input';
|
import '../shared/remote-input';
|
||||||
import '../shared/franceconnect';
|
import '../shared/franceconnect';
|
||||||
import '../shared/toggle-target';
|
import '../shared/toggle-target';
|
||||||
|
|
|
@ -1,51 +0,0 @@
|
||||||
import autocomplete from 'autocomplete.js';
|
|
||||||
import { getJSON, fire } from '@utils';
|
|
||||||
|
|
||||||
const sources = [
|
|
||||||
{
|
|
||||||
type: 'address',
|
|
||||||
url: '/address/suggestions'
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
const options = {
|
|
||||||
autoselect: true,
|
|
||||||
minLength: 1
|
|
||||||
};
|
|
||||||
|
|
||||||
function selector(type) {
|
|
||||||
return `[data-autocomplete=${type}]`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function source(url) {
|
|
||||||
return {
|
|
||||||
source(query, callback) {
|
|
||||||
getJSON(url, { request: query }).then(callback);
|
|
||||||
},
|
|
||||||
templates: {
|
|
||||||
suggestion({ label, mine }) {
|
|
||||||
const mineClass = `path-mine-${mine ? 'true' : 'false'}`;
|
|
||||||
const openTag = `<div class="aa-suggestion ${mineClass}">`;
|
|
||||||
return autocomplete.escapeHighlightedString(label, openTag, '</div>');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
debounce: 300
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
addEventListener('ds:page:update', function() {
|
|
||||||
for (let { type, url } of sources) {
|
|
||||||
for (let element of document.querySelectorAll(selector(type))) {
|
|
||||||
element.removeAttribute('data-autocomplete');
|
|
||||||
autocompleteInitializeElement(element, url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function autocompleteInitializeElement(element, url) {
|
|
||||||
const select = autocomplete(element, options, [source(url)]);
|
|
||||||
select.on('autocomplete:selected', ({ target }, suggestion) => {
|
|
||||||
fire(target, 'autocomplete:select', suggestion);
|
|
||||||
select.autocomplete.setVal(suggestion.label);
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,5 +1,6 @@
|
||||||
/* globals FreeDraw L */
|
/* globals FreeDraw L */
|
||||||
import { fire, getJSON, delegate } from '@utils';
|
import { fire, delegate } from '@utils';
|
||||||
|
import $ from 'jquery';
|
||||||
|
|
||||||
import polygonArea from './polygon_area';
|
import polygonArea from './polygon_area';
|
||||||
|
|
||||||
|
@ -113,14 +114,6 @@ function drawParcellesAgricoles(map, { parcellesAgricoles }, editable = false) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function geocodeAddress(map, query) {
|
|
||||||
getJSON('/address/geocode', { request: query }).then(data => {
|
|
||||||
if (data.lat !== null) {
|
|
||||||
map.setView(new L.LatLng(data.lat, data.lon), data.zoom);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCurrentMap(element) {
|
function getCurrentMap(element) {
|
||||||
if (!element.matches('.carte')) {
|
if (!element.matches('.carte')) {
|
||||||
const closestCarteElement = element.closest('.carte');
|
const closestCarteElement = element.closest('.carte');
|
||||||
|
@ -246,10 +239,12 @@ delegate('click', '.toolbar .new-area', event => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
delegate('autocomplete:select', '.toolbar [data-address]', event => {
|
$(document).on('select2:select', 'select[data-address]', event => {
|
||||||
const map = getCurrentMap(event.target);
|
const map = getCurrentMap(event.target);
|
||||||
|
const { geometry } = event.params.data;
|
||||||
|
|
||||||
if (map) {
|
if (map && geometry && geometry.type === 'Point') {
|
||||||
geocodeAddress(map, event.detail.label);
|
const [lon, lat] = geometry.coordinates;
|
||||||
|
map.setView(new L.LatLng(lat, lon), 14);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
class ApiAdresse::Adapter
|
|
||||||
private
|
|
||||||
|
|
||||||
def initialize(address, limit, blank_return)
|
|
||||||
@address = address
|
|
||||||
@limit = limit
|
|
||||||
@blank_return = blank_return
|
|
||||||
end
|
|
||||||
|
|
||||||
def features
|
|
||||||
@features ||= get_features
|
|
||||||
end
|
|
||||||
|
|
||||||
def get_features
|
|
||||||
response = ApiAdresse::API.call(@address, @limit)
|
|
||||||
result = JSON.parse(response)
|
|
||||||
result['features']
|
|
||||||
rescue RestClient::Exception, JSON::ParserError, TypeError
|
|
||||||
@blank_return
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_result
|
|
||||||
if features.present?
|
|
||||||
process_features
|
|
||||||
else
|
|
||||||
@blank_return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def process_features
|
|
||||||
raise NoMethodError
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,17 +0,0 @@
|
||||||
class ApiAdresse::AddressAdapter < ApiAdresse::Adapter
|
|
||||||
def initialize(address)
|
|
||||||
super(address, 5, [])
|
|
||||||
end
|
|
||||||
|
|
||||||
def get_suggestions
|
|
||||||
handle_result
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def process_features
|
|
||||||
features.map do |feature|
|
|
||||||
feature['properties']['label']
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,12 +0,0 @@
|
||||||
class ApiAdresse::API
|
|
||||||
def self.call(address, limit = 1)
|
|
||||||
search_url = [API_ADRESSE_URL, "search"].join("/")
|
|
||||||
|
|
||||||
RestClient::Request.execute(method: :get,
|
|
||||||
url: search_url,
|
|
||||||
timeout: 5,
|
|
||||||
headers: { params: { q: address, limit: limit } })
|
|
||||||
rescue RestClient::ServiceUnavailable
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,15 +0,0 @@
|
||||||
class ApiAdresse::PointAdapter < ApiAdresse::Adapter
|
|
||||||
def initialize(address)
|
|
||||||
super(address, 1, nil)
|
|
||||||
end
|
|
||||||
|
|
||||||
def geocode
|
|
||||||
handle_result
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def process_features
|
|
||||||
RGeo::GeoJSON.decode(features[0]['geometry'], json_parser: :json)
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,57 +0,0 @@
|
||||||
class ApiGeo::API
|
|
||||||
TIMEOUT = 15
|
|
||||||
CACHE_DURATION = 1.day
|
|
||||||
|
|
||||||
def self.regions
|
|
||||||
url = [API_GEO_URL, "regions"].join("/")
|
|
||||||
call(url, { fields: :nom })
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.departements
|
|
||||||
url = [API_GEO_URL, "departements"].join("/")
|
|
||||||
call(url, { fields: :nom })
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.pays
|
|
||||||
parse(File.open('app/lib/api_geo/pays.json').read)
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.search_rpg(geojson)
|
|
||||||
url = [API_GEO_SANDBOX_URL, "rpg", "parcelles", "search"].join("/")
|
|
||||||
call(url, geojson, :post)
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def self.parse(body)
|
|
||||||
JSON.parse(body, symbolize_names: true)
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.call(url, body, method = :get)
|
|
||||||
# The cache engine is stored, because as of Typhoeus 1.3.1 the cache engine instance
|
|
||||||
# is included in the computed `cache_key`.
|
|
||||||
# (Which means that when the cache instance changes, the cache is invalidated.)
|
|
||||||
@typhoeus_cache ||= Typhoeus::Cache::SuccessfulRequestsRailsCache.new
|
|
||||||
|
|
||||||
response = Typhoeus::Request.new(
|
|
||||||
url,
|
|
||||||
method: method,
|
|
||||||
params: method == :get ? body : nil,
|
|
||||||
body: method == :post ? body : nil,
|
|
||||||
timeout: TIMEOUT,
|
|
||||||
accept_encoding: 'gzip',
|
|
||||||
headers: {
|
|
||||||
'Accept' => 'application/json',
|
|
||||||
'Accept-Encoding' => 'gzip, deflate'
|
|
||||||
}.merge(method == :post ? { 'Content-Type' => 'application/json' } : {}),
|
|
||||||
cache: @typhoeus_cache,
|
|
||||||
cache_ttl: CACHE_DURATION
|
|
||||||
).run
|
|
||||||
|
|
||||||
if response.success?
|
|
||||||
parse(response.body)
|
|
||||||
else
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,27 +0,0 @@
|
||||||
class ApiGeo::RPGAdapter
|
|
||||||
def initialize(coordinates)
|
|
||||||
@coordinates = GeojsonService.to_json_polygon_for_rpg(coordinates)
|
|
||||||
end
|
|
||||||
|
|
||||||
def data_source
|
|
||||||
@data_source ||= ApiGeo::API.search_rpg(@coordinates)
|
|
||||||
end
|
|
||||||
|
|
||||||
def results
|
|
||||||
data_source[:features].map do |feature|
|
|
||||||
feature[:properties]
|
|
||||||
.stringify_keys
|
|
||||||
.transform_keys(&:underscore)
|
|
||||||
.symbolize_keys
|
|
||||||
.slice(
|
|
||||||
:culture,
|
|
||||||
:code_culture,
|
|
||||||
:surface,
|
|
||||||
:bio
|
|
||||||
).merge({
|
|
||||||
geometry: feature[:geometry],
|
|
||||||
geo_reference_id: feature[:properties][:id]
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -70,4 +70,17 @@ class Administrateur < ApplicationRecord
|
||||||
def can_be_deleted?
|
def can_be_deleted?
|
||||||
dossiers.state_instruction_commencee.none? && procedures.all? { |p| p.administrateurs.count > 1 }
|
dossiers.state_instruction_commencee.none? && procedures.all? { |p| p.administrateurs.count > 1 }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def delete_and_transfer_services
|
||||||
|
if !can_be_deleted?
|
||||||
|
fail "Impossible de supprimer cet administrateur car il a des dossiers ou des procédures"
|
||||||
|
end
|
||||||
|
dossiers.each(&:delete_and_keep_track)
|
||||||
|
|
||||||
|
procedures.each do |procedure|
|
||||||
|
next_administrateur = procedure.administrateurs.where.not(id: self.id).first
|
||||||
|
procedure.service.update(administrateur: next_administrateur)
|
||||||
|
end
|
||||||
|
destroy
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
2
app/models/champs/commune_champ.rb
Normal file
2
app/models/champs/commune_champ.rb
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
class Champs::CommuneChamp < Champs::TextChamp
|
||||||
|
end
|
|
@ -1,5 +1,2 @@
|
||||||
class Champs::DepartementChamp < Champs::TextChamp
|
class Champs::DepartementChamp < Champs::TextChamp
|
||||||
def self.departements
|
|
||||||
ApiGeo::API.departements.map { |liste| "#{liste[:code]} - #{liste[:nom]}" }.push('99 - Étranger')
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
class Champs::PaysChamp < Champs::TextChamp
|
class Champs::PaysChamp < Champs::TextChamp
|
||||||
|
PAYS = JSON.parse(Rails.root.join('app', 'lib', 'api_geo', 'pays.json').read, symbolize_names: true)
|
||||||
|
|
||||||
def self.pays
|
def self.pays
|
||||||
ApiGeo::API.pays.pluck(:nom)
|
PAYS.pluck(:nom)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.disabled_options
|
def self.disabled_options
|
||||||
|
|
|
@ -1,5 +1,2 @@
|
||||||
class Champs::RegionChamp < Champs::TextChamp
|
class Champs::RegionChamp < Champs::TextChamp
|
||||||
def self.regions
|
|
||||||
ApiGeo::API.regions.sort_by { |e| e[:nom] }.pluck(:nom)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -343,7 +343,7 @@ class Dossier < ApplicationRecord
|
||||||
|
|
||||||
def geo_position
|
def geo_position
|
||||||
if etablissement.present?
|
if etablissement.present?
|
||||||
point = ApiAdresse::PointAdapter.new(etablissement.geo_adresse).geocode
|
point = Geocoder.search(etablissement.geo_adresse).first
|
||||||
end
|
end
|
||||||
|
|
||||||
lon = "2.428462"
|
lon = "2.428462"
|
||||||
|
@ -351,8 +351,7 @@ class Dossier < ApplicationRecord
|
||||||
zoom = "13"
|
zoom = "13"
|
||||||
|
|
||||||
if point.present?
|
if point.present?
|
||||||
lon = point.x.to_s
|
lat, lon = point.coordinates.map(&:to_s)
|
||||||
lat = point.y.to_s
|
|
||||||
end
|
end
|
||||||
|
|
||||||
{ lon: lon, lat: lat, zoom: zoom }
|
{ lon: lon, lat: lat, zoom: zoom }
|
||||||
|
|
|
@ -10,4 +10,6 @@ class GroupeInstructeur < ApplicationRecord
|
||||||
validates :label, uniqueness: { scope: :procedure, message: 'existe déjà' }
|
validates :label, uniqueness: { scope: :procedure, message: 'existe déjà' }
|
||||||
|
|
||||||
before_validation -> { label&.strip! }
|
before_validation -> { label&.strip! }
|
||||||
|
|
||||||
|
scope :without_group, -> (group) { where.not(id: group) }
|
||||||
end
|
end
|
||||||
|
|
|
@ -17,9 +17,9 @@ class Instructeur < ApplicationRecord
|
||||||
has_many :previously_followed_dossiers, -> { distinct }, through: :previous_follows, source: :dossier
|
has_many :previously_followed_dossiers, -> { distinct }, through: :previous_follows, source: :dossier
|
||||||
has_many :avis
|
has_many :avis
|
||||||
has_many :dossiers_from_avis, through: :avis, source: :dossier
|
has_many :dossiers_from_avis, through: :avis, source: :dossier
|
||||||
has_many :trusted_device_tokens
|
has_many :trusted_device_tokens, dependent: :destroy
|
||||||
|
|
||||||
has_one :user
|
has_one :user, dependent: :nullify
|
||||||
|
|
||||||
default_scope { eager_load(:user) }
|
default_scope { eager_load(:user) }
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ class Instructeur < ApplicationRecord
|
||||||
|
|
||||||
active_procedure_overviews = procedures
|
active_procedure_overviews = procedures
|
||||||
.publiees
|
.publiees
|
||||||
.map { |procedure| procedure.procedure_overview(start_date) }
|
.map { |procedure| procedure.procedure_overview(start_date, groupe_instructeurs) }
|
||||||
.filter(&:had_some_activities?)
|
.filter(&:had_some_activities?)
|
||||||
|
|
||||||
if active_procedure_overviews.count == 0
|
if active_procedure_overviews.count == 0
|
||||||
|
@ -176,6 +176,10 @@ class Instructeur < ApplicationRecord
|
||||||
trusted_device_token&.token_young?
|
trusted_device_token&.token_young?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def can_be_deleted?
|
||||||
|
user.administrateur.nil? && procedures.all? { |p| p.defaut_groupe_instructeur.instructeurs.count > 1 }
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def annotations_hash(demande, annotations_privees, avis, messagerie)
|
def annotations_hash(demande, annotations_privees, avis, messagerie)
|
||||||
|
|
|
@ -464,8 +464,8 @@ class Procedure < ApplicationRecord
|
||||||
export(dossiers).to_ods
|
export(dossiers).to_ods
|
||||||
end
|
end
|
||||||
|
|
||||||
def procedure_overview(start_date)
|
def procedure_overview(start_date, groups)
|
||||||
ProcedureOverview.new(self, start_date)
|
ProcedureOverview.new(self, start_date, groups)
|
||||||
end
|
end
|
||||||
|
|
||||||
def initiated_mail_template
|
def initiated_mail_template
|
||||||
|
|
|
@ -6,24 +6,23 @@ class ProcedureOverview
|
||||||
:dossiers_en_construction_count,
|
:dossiers_en_construction_count,
|
||||||
:old_dossiers_en_construction
|
:old_dossiers_en_construction
|
||||||
|
|
||||||
def initialize(procedure, start_date)
|
def initialize(procedure, start_date, groups)
|
||||||
@start_date = start_date
|
@start_date = start_date
|
||||||
@procedure = procedure
|
@procedure = procedure
|
||||||
|
|
||||||
@dossiers_en_instruction_count = procedure.dossiers.state_en_instruction.count
|
dossiers = procedure.dossiers.where(groupe_instructeur: groups)
|
||||||
@old_dossiers_en_instruction = procedure
|
|
||||||
.dossiers
|
@dossiers_en_instruction_count = dossiers.state_en_instruction.count
|
||||||
|
@old_dossiers_en_instruction = dossiers
|
||||||
.state_en_instruction
|
.state_en_instruction
|
||||||
.where('en_instruction_at < ?', 1.week.ago)
|
.where('en_instruction_at < ?', 1.week.ago)
|
||||||
|
|
||||||
@dossiers_en_construction_count = procedure.dossiers.state_en_construction.count
|
@dossiers_en_construction_count = dossiers.state_en_construction.count
|
||||||
@old_dossiers_en_construction = procedure
|
@old_dossiers_en_construction = dossiers
|
||||||
.dossiers
|
|
||||||
.state_en_construction
|
.state_en_construction
|
||||||
.where('en_construction_at < ?', 1.week.ago)
|
.where('en_construction_at < ?', 1.week.ago)
|
||||||
|
|
||||||
@created_dossiers_count = procedure
|
@created_dossiers_count = dossiers
|
||||||
.dossiers
|
|
||||||
.where(created_at: start_date..Time.zone.now)
|
.where(created_at: start_date..Time.zone.now)
|
||||||
.state_not_brouillon
|
.state_not_brouillon
|
||||||
.count
|
.count
|
||||||
|
|
|
@ -19,6 +19,7 @@ class TypeDeChamp < ApplicationRecord
|
||||||
pays: 'pays',
|
pays: 'pays',
|
||||||
regions: 'regions',
|
regions: 'regions',
|
||||||
departements: 'departements',
|
departements: 'departements',
|
||||||
|
communes: 'communes',
|
||||||
engagement: 'engagement',
|
engagement: 'engagement',
|
||||||
header_section: 'header_section',
|
header_section: 'header_section',
|
||||||
explication: 'explication',
|
explication: 'explication',
|
||||||
|
|
2
app/models/types_de_champ/commune_type_de_champ.rb
Normal file
2
app/models/types_de_champ/commune_type_de_champ.rb
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
class TypesDeChamp::CommuneTypeDeChamp < TypesDeChamp::TypeDeChampBase
|
||||||
|
end
|
|
@ -97,7 +97,7 @@ class User < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def can_be_deleted?
|
def can_be_deleted?
|
||||||
dossiers.state_instruction_commencee.empty?
|
administrateur.nil? && instructeur.nil? && dossiers.state_instruction_commencee.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete_and_keep_track_dossiers(administration)
|
def delete_and_keep_track_dossiers(administration)
|
||||||
|
@ -105,12 +105,11 @@ class User < ApplicationRecord
|
||||||
raise "Cannot delete this user because instruction has started for some dossiers"
|
raise "Cannot delete this user because instruction has started for some dossiers"
|
||||||
end
|
end
|
||||||
|
|
||||||
if can_be_deleted?
|
|
||||||
dossiers.each do |dossier|
|
dossiers.each do |dossier|
|
||||||
dossier.delete_and_keep_track(administration)
|
dossier.delete_and_keep_track(administration)
|
||||||
end
|
end
|
||||||
destroy
|
dossiers.unscoped.destroy_all
|
||||||
end
|
destroy!
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
203
app/views/dossiers/show.pdf.prawn
Normal file
203
app/views/dossiers/show.pdf.prawn
Normal file
|
@ -0,0 +1,203 @@
|
||||||
|
require 'prawn/measurement_extensions'
|
||||||
|
|
||||||
|
def format_in_2_lines(pdf, label, text)
|
||||||
|
pdf.font 'liberation serif', style: :bold, size: 12 do
|
||||||
|
pdf.text label
|
||||||
|
end
|
||||||
|
pdf.text text
|
||||||
|
pdf.text "\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
def format_in_2_columns(pdf, label, text)
|
||||||
|
pdf.text_box label, width: 200, height: 100, overflow: :expand, at: [0, pdf.cursor]
|
||||||
|
pdf.text_box ":", width: 10, height: 100, overflow: :expand, at: [100, pdf.cursor]
|
||||||
|
pdf.text_box text, width: 420, height: 100, overflow: :expand, at: [110, pdf.cursor]
|
||||||
|
pdf.text "\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_title(pdf, title)
|
||||||
|
title_style = {style: :bold, size: 24}
|
||||||
|
pdf.font 'liberation serif', title_style do
|
||||||
|
pdf.text title
|
||||||
|
end
|
||||||
|
pdf.text "\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
def format_date(date)
|
||||||
|
I18n.l(date, format: :message_date_with_year)
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_identite_individual(pdf, dossier)
|
||||||
|
format_in_2_columns(pdf, "Civilité", dossier.individual.gender)
|
||||||
|
format_in_2_columns(pdf, "Nom", dossier.individual.nom)
|
||||||
|
format_in_2_columns(pdf, "Prénom", dossier.individual.prenom)
|
||||||
|
|
||||||
|
if dossier.individual.birthdate.present?
|
||||||
|
format_in_2_columns(pdf, "Date de naissance", try_format_date(dossier.individual.birthdate))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def render_siret_info(pdf, etablissement)
|
||||||
|
pdf.text " - Dénomination : #{raison_sociale_or_name(etablissement)}"
|
||||||
|
pdf.text " - Forme juridique : #{etablissement.entreprise_forme_juridique}"
|
||||||
|
if etablissement.entreprise_capital_social.present?
|
||||||
|
pdf.text " - Capital social : #{pretty_currency(etablissement.entreprise_capital_social)}"
|
||||||
|
end
|
||||||
|
pdf.text "\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
def render_identite_etablissement(pdf, etablissement)
|
||||||
|
pdf.text " - SIRET : #{etablissement.siret}"
|
||||||
|
pdf.text " - SIRET du siège social: #{etablissement.entreprise.siret_siege_social}"
|
||||||
|
pdf.text " - Dénomination : #{raison_sociale_or_name(etablissement)}"
|
||||||
|
pdf.text " - Forme juridique : #{etablissement.entreprise_forme_juridique}"
|
||||||
|
if etablissement.entreprise_capital_social.present?
|
||||||
|
pdf.text " - Capital social : #{pretty_currency(etablissement.entreprise_capital_social)}"
|
||||||
|
end
|
||||||
|
pdf.text " - Libellé NAF : #{etablissement.libelle_naf}"
|
||||||
|
pdf.text " - Code NAF : #{etablissement.naf}"
|
||||||
|
pdf.text " - Date de création : #{try_format_date(etablissement.entreprise.date_creation)}"
|
||||||
|
pdf.text " - Effectif de l'organisation : #{effectif(etablissement)}"
|
||||||
|
pdf.text " - Code effectif : #{etablissement.entreprise.code_effectif_entreprise}"
|
||||||
|
pdf.text " - Numéro de TVA intracommunautaire : #{etablissement.entreprise.numero_tva_intracommunautaire}"
|
||||||
|
pdf.text " - Adresse : #{etablissement.adresse}"
|
||||||
|
if etablissement.association?
|
||||||
|
pdf.text " - Numéro RNA : #{etablissement.association_rna}"
|
||||||
|
pdf.text " - Titre : #{etablissement.association_titre}"
|
||||||
|
pdf.text " - Objet : #{etablissement.association_objet}"
|
||||||
|
pdf.text " - Date de création : #{try_format_date(etablissement.association_date_creation)}"
|
||||||
|
pdf.text " - Date de publication : #{try_format_date(etablissement.association_date_publication)}"
|
||||||
|
pdf.text " - Date de déclaration : #{try_format_date(etablissement.association_date_declaration)}"
|
||||||
|
end
|
||||||
|
pdf.text "\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
def render_single_champ(pdf, champ)
|
||||||
|
case champ.type
|
||||||
|
when 'Champs::RepetitionChamp'
|
||||||
|
raise 'There should not be a RepetitionChamp here !'
|
||||||
|
when 'Champs::PieceJustificativeChamp'
|
||||||
|
return
|
||||||
|
when 'Champs::HeaderSectionChamp'
|
||||||
|
pdf.font 'liberation serif', style: :bold, size: 18 do
|
||||||
|
pdf.text champ.libelle
|
||||||
|
end
|
||||||
|
pdf.text "\n"
|
||||||
|
when 'Champs::ExplicationChamp'
|
||||||
|
format_in_2_lines(pdf, champ.libelle, champ.description)
|
||||||
|
when 'Champs::CarteChamp'
|
||||||
|
format_in_2_lines(pdf, champ.libelle, champ.geo_json.to_s)
|
||||||
|
when 'Champs::SiretChamp'
|
||||||
|
pdf.font 'liberation serif', style: :bold, size: 12 do
|
||||||
|
pdf.text champ.libelle
|
||||||
|
end
|
||||||
|
pdf.text " - SIRET: #{champ.to_s}"
|
||||||
|
render_identite_etablissement(pdf, champ.etablissement) if champ.etablissement.present?
|
||||||
|
pdf.text "\n"
|
||||||
|
else
|
||||||
|
value = champ.to_s.empty? ? 'Non communiqué' : champ.to_s
|
||||||
|
format_in_2_lines(pdf, champ.libelle, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_champs(pdf, champs)
|
||||||
|
champs.each do |champ|
|
||||||
|
if champ.type == 'Champs::RepetitionChamp'
|
||||||
|
champ.rows.each do |row|
|
||||||
|
row.each do |inner_champ|
|
||||||
|
render_single_champ(pdf, inner_champ)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
render_single_champ(pdf, champ)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_message(pdf, message)
|
||||||
|
sender = message.redacted_email
|
||||||
|
if message.sent_by_system?
|
||||||
|
sender = 'Email automatique'
|
||||||
|
elsif message.sent_by?(@dossier.user)
|
||||||
|
sender = @dossier.user.email
|
||||||
|
end
|
||||||
|
|
||||||
|
pdf.text "#{sender}, #{format_date(message.created_at)}", style: :bold
|
||||||
|
pdf.text ActionView::Base.full_sanitizer.sanitize(message.body)
|
||||||
|
pdf.text "\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_avis(pdf, avis)
|
||||||
|
pdf.text "Avis de #{avis.email_to_display}", style: :bold
|
||||||
|
if avis.confidentiel?
|
||||||
|
pdf.text "(confidentiel)", style: :bold
|
||||||
|
end
|
||||||
|
text = avis.answer || 'En attente de réponse'
|
||||||
|
pdf.text text
|
||||||
|
pdf.text "\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_etats_dossier(pdf, dossier)
|
||||||
|
if dossier.en_construction_at.present?
|
||||||
|
format_in_2_columns(pdf, "Déposé le", try_format_date(dossier.en_construction_at))
|
||||||
|
end
|
||||||
|
if dossier.en_instruction_at.present?
|
||||||
|
format_in_2_columns(pdf, "En instruction le", try_format_date(dossier.en_instruction_at))
|
||||||
|
end
|
||||||
|
if dossier.processed_at?.present?
|
||||||
|
format_in_2_columns(pdf, "Décision le", try_format_date(dossier.processed_at))
|
||||||
|
end
|
||||||
|
|
||||||
|
pdf.text "\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
prawn_document(page_size: "A4") do |pdf|
|
||||||
|
pdf.font_families.update( 'liberation serif' => {
|
||||||
|
normal: Rails.root.join('lib/prawn/fonts/liberation_serif/LiberationSerif-Regular.ttf' ),
|
||||||
|
bold: Rails.root.join('lib/prawn/fonts/liberation_serif/LiberationSerif-Bold.ttf' ),
|
||||||
|
})
|
||||||
|
pdf.font 'liberation serif'
|
||||||
|
|
||||||
|
pdf.svg IO.read("app/assets/images/header/logo-ds-wide.svg"), width: 300, position: :center
|
||||||
|
pdf.move_down(40)
|
||||||
|
|
||||||
|
format_in_2_columns(pdf, 'Dossier Nº', @dossier.id.to_s)
|
||||||
|
format_in_2_columns(pdf, 'Démarche', @dossier.procedure.libelle)
|
||||||
|
format_in_2_columns(pdf, 'Organisme', @dossier.procedure.organisation_name)
|
||||||
|
pdf.text "\n"
|
||||||
|
|
||||||
|
pdf.text "Ce dossier est <b>#{dossier_display_state(@dossier, lower: true)}</b>.", inline_format: true
|
||||||
|
pdf.text "\n"
|
||||||
|
if @dossier.motivation.present?
|
||||||
|
format_in_2_lines(pdf, "Motif de la décision", @dossier.motivation)
|
||||||
|
end
|
||||||
|
add_title(pdf, 'Historique')
|
||||||
|
add_etats_dossier(pdf, @dossier)
|
||||||
|
|
||||||
|
add_title(pdf, "Identité du demandeur")
|
||||||
|
|
||||||
|
format_in_2_columns(pdf, "Email", @dossier.user.email)
|
||||||
|
add_identite_individual(pdf, @dossier) if @dossier.individual.present?
|
||||||
|
render_identite_etablissement(pdf, @dossier.etablissement) if @dossier.etablissement.present?
|
||||||
|
pdf.text "\n"
|
||||||
|
|
||||||
|
add_title(pdf, 'Formulaire')
|
||||||
|
add_champs(pdf, @dossier.champs)
|
||||||
|
|
||||||
|
if @include_infos_administration && @dossier.champs_private&.size > 0
|
||||||
|
add_title(pdf, "Annotations privées")
|
||||||
|
add_champs(pdf, @dossier.champs_private)
|
||||||
|
end
|
||||||
|
|
||||||
|
if @include_infos_administration && @dossier.avis.present?
|
||||||
|
add_title(pdf, "Avis")
|
||||||
|
@dossier.avis.each do |avis|
|
||||||
|
add_avis(pdf, avis)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
add_title(pdf, 'Messagerie')
|
||||||
|
@dossier.commentaires.each do |commentaire|
|
||||||
|
add_message(pdf, commentaire)
|
||||||
|
end
|
||||||
|
end
|
|
@ -6,6 +6,8 @@
|
||||||
= link_to "Tout le dossier", print_instructeur_dossier_path(dossier.procedure, dossier), target: "_blank", rel: "noopener", class: "menu-item menu-link"
|
= link_to "Tout le dossier", print_instructeur_dossier_path(dossier.procedure, dossier), target: "_blank", rel: "noopener", class: "menu-item menu-link"
|
||||||
%li
|
%li
|
||||||
= link_to "Uniquement cet onglet", "#", onclick: "window.print()", class: "menu-item menu-link"
|
= link_to "Uniquement cet onglet", "#", onclick: "window.print()", class: "menu-item menu-link"
|
||||||
|
%li
|
||||||
|
= link_to "Export PDF", instructeur_dossier_path(dossier.procedure, dossier, format: :pdf), target: "_blank", rel: "noopener", class: "menu-item menu-link"
|
||||||
|
|
||||||
- if !PiecesJustificativesService.liste_pieces_justificatives(dossier).empty?
|
- if !PiecesJustificativesService.liste_pieces_justificatives(dossier).empty?
|
||||||
%span.dropdown.print-menu-opener
|
%span.dropdown.print-menu-opener
|
||||||
|
|
|
@ -34,7 +34,10 @@ as well as a link to its edit page.
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<%= link_to 'Réinviter', reinvite_manager_instructeur_path(instructeur), method: :post, class: 'button' %>
|
<%= link_to 'Réinviter', reinvite_manager_instructeur_path(instructeur), method: :post, class: 'button' %>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
<%= button_to "Supprimer", delete_manager_instructeur_path(page.resource), method: :delete, disabled: !page.resource.can_be_deleted?, class: "button", data: { confirm: "Confirmez-vous la suppression de l'instructeur ?" }, title: page.resource.can_be_deleted? ? "Supprimer" : "Cet instructeur est administrateur ou a des démarches dont il est le seul instructeur et ne peut être supprimé" %>
|
||||||
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<section class="main-content__body">
|
<section class="main-content__body">
|
||||||
|
|
|
@ -25,7 +25,7 @@ as well as a link to its edit page.
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<%= button_to "supprimer", delete_manager_user_path(page.resource), method: :delete, disabled: !page.resource.can_be_deleted?, class: "button", data: { confirm: "Confirmez-vous la suppression de l'utilisateur ?" }, title: page.resource.can_be_deleted? ? "Supprimer" : "Cet utilisateur a des dossiers dont l'instruction a commencé et ne peut être supprimé" %>
|
<%= button_to "supprimer", delete_manager_user_path(page.resource), method: :delete, disabled: !page.resource.can_be_deleted?, class: "button", data: { confirm: "Confirmez-vous la suppression de l'utilisateur ?" }, title: page.resource.can_be_deleted? ? "Supprimer" : "Cet utilisateur ne peut être supprimé. Il a des dossiers dont l'instruction a commencé ou il est administrateur ou instructeur" %>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -28,11 +28,21 @@
|
||||||
%table.table.mt-2
|
%table.table.mt-2
|
||||||
%thead
|
%thead
|
||||||
%tr
|
%tr
|
||||||
%th{ colspan: 2 }= t(".existing_groupe", count: @groupes_instructeurs.count)
|
%th{ colspan: 2 }= t(".existing_groupe", count: @groupes_instructeurs.total_count)
|
||||||
%tbody
|
%tbody
|
||||||
- @groupes_instructeurs.each do |group|
|
- @groupes_instructeurs.each do |group|
|
||||||
%tr
|
%tr
|
||||||
%td= group.label
|
%td= group.label
|
||||||
%td.actions= link_to "voir", procedure_groupe_instructeur_path(@procedure, group)
|
%td.actions= link_to "voir", procedure_groupe_instructeur_path(@procedure, group)
|
||||||
|
- if @groupes_instructeurs.many?
|
||||||
|
- if group.dossiers.empty?
|
||||||
|
%td.actions
|
||||||
|
= link_to procedure_groupe_instructeur_path(@procedure, group), { method: :delete, class: 'button', data: { confirm: "Êtes-vous sûr de vouloir supprimer le groupe « #{group.label} » ?" }} do
|
||||||
|
%span.icon.delete
|
||||||
|
supprimer ce groupe
|
||||||
|
- else
|
||||||
|
%td.actions
|
||||||
|
= link_to reaffecter_dossiers_procedure_groupe_instructeur_path(@procedure, group), class: 'button', title:'Réaffecter les dossiers à un autre groupe afin de pouvoir le supprimer' do
|
||||||
|
%span.icon.follow
|
||||||
|
déplacer les dossiers
|
||||||
= paginate @groupes_instructeurs
|
= paginate @groupes_instructeurs
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
= render partial: 'new_administrateur/breadcrumbs',
|
||||||
|
locals: { steps: [link_to('Démarches', admin_procedures_path),
|
||||||
|
link_to(@procedure.libelle, admin_procedure_path(@procedure)),
|
||||||
|
link_to('Groupes d’instructeurs', procedure_groupe_instructeurs_path(@procedure)),
|
||||||
|
@groupe_instructeur.label] }
|
||||||
|
|
||||||
|
.container.groupe-instructeur
|
||||||
|
|
||||||
|
.card
|
||||||
|
.card-title Réaffectation des dossiers du groupe « {@groupe_instructeur.label} »
|
||||||
|
%p
|
||||||
|
Le groupe « #{@groupe_instructeur.label} » contient des dossiers. Afin de procéder à sa suppression, vous devez réaffecter ses dossiers à un autre groupe instructeur.
|
||||||
|
|
||||||
|
%table.table.mt-2
|
||||||
|
%thead
|
||||||
|
%tr
|
||||||
|
%th{ colspan: 2 }= t(".existing_groupe", count: @groupes_instructeurs.total_count)
|
||||||
|
%tbody
|
||||||
|
- @groupes_instructeurs.each do |group|
|
||||||
|
%tr
|
||||||
|
%td= group.label
|
||||||
|
%td.actions= button_to 'Réaffecter les dossiers à ce groupe',
|
||||||
|
reaffecter_procedure_groupe_instructeur_path(:target_group => group),
|
||||||
|
{ class: 'button',
|
||||||
|
data: { confirm: "Êtes-vous sûr de vouloir réaffecter les dossiers du groupe « #{@groupe_instructeur.label} » vers le groupe « #{group.label} » ?" } }
|
||||||
|
|
||||||
|
= paginate @groupes_instructeurs
|
|
@ -1,4 +1,4 @@
|
||||||
= form.text_field :value,
|
= form.select :value, [champ.value].compact,
|
||||||
data: { address: true, autocomplete: 'address' },
|
{ include_blank: true },
|
||||||
placeholder: champ.libelle,
|
required: champ.mandatory?,
|
||||||
required: champ.mandatory?
|
class: 'select2 adresse'
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
.toolbar
|
.toolbar
|
||||||
%button.button.primary.new-area Ajouter une zone
|
%button.button.primary.new-area Ajouter une zone
|
||||||
%input.address{ data: { address: true, autocomplete: 'address' }, placeholder: 'Saisissez une adresse ou positionner la carte' }
|
%select.select2.adresse{ data: { address: true }, placeholder: 'Saisissez une adresse ou positionner la carte' }
|
||||||
|
|
||||||
.carte.edit{ data: { geo: geo_data(champ) }, class: "carte-#{form.index}" }
|
.carte.edit{ data: { geo: geo_data(champ) }, class: "carte-#{form.index}" }
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
= form.select :value, [champ.value].compact,
|
||||||
|
{ include_blank: true },
|
||||||
|
required: champ.mandatory?,
|
||||||
|
class: 'select2 communes'
|
|
@ -1,4 +1,4 @@
|
||||||
= form.select :value,
|
= form.select :value, [champ.value].compact,
|
||||||
Champs::DepartementChamp.departements,
|
{ include_blank: true },
|
||||||
include_blank: true,
|
required: champ.mandatory?,
|
||||||
required: champ.mandatory?
|
class: 'select2 departements'
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
= form.select :value,
|
= form.select :value,
|
||||||
Champs::PaysChamp.pays,
|
Champs::PaysChamp.pays,
|
||||||
disabled: Champs::PaysChamp.disabled_options,
|
{ disabled: Champs::PaysChamp.disabled_options, include_blank: true },
|
||||||
include_blank: true,
|
required: champ.mandatory?,
|
||||||
required: champ.mandatory?
|
class: 'select2 pays'
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
= form.select :value,
|
= form.select :value, [champ.value].compact,
|
||||||
Champs::RegionChamp.regions,
|
{ include_blank: true },
|
||||||
include_blank: true,
|
required: champ.mandatory?,
|
||||||
required: champ.mandatory?
|
class: 'select2 regions'
|
||||||
|
|
|
@ -15,6 +15,12 @@
|
||||||
= render partial: 'invites/dropdown', locals: { dossier: dossier }
|
= render partial: 'invites/dropdown', locals: { dossier: dossier }
|
||||||
- if dossier.can_be_updated_by_user? && !current_page?(modifier_dossier_path(dossier))
|
- if dossier.can_be_updated_by_user? && !current_page?(modifier_dossier_path(dossier))
|
||||||
= link_to "Modifier mon dossier", modifier_dossier_path(dossier), class: 'button accepted edit-form', 'title'=> "Vous pouvez modifier votre dossier tant qu'il n'est passé en instruction"
|
= link_to "Modifier mon dossier", modifier_dossier_path(dossier), class: 'button accepted edit-form', 'title'=> "Vous pouvez modifier votre dossier tant qu'il n'est passé en instruction"
|
||||||
|
%span.dropdown.print-menu-opener
|
||||||
|
%button.button.dropdown-button.icon-only{ title: 'imprimer' }
|
||||||
|
%span.icon.printer
|
||||||
|
%ul.print-menu.dropdown-content
|
||||||
|
%li
|
||||||
|
= link_to "Tout le dossier", dossier_path(dossier, format: :pdf), target: "_blank", rel: "noopener", class: "menu-item menu-link"
|
||||||
|
|
||||||
%ul.tabs
|
%ul.tabs
|
||||||
= dynamic_tab_item('Résumé', dossier_path(dossier))
|
= dynamic_tab_item('Résumé', dossier_path(dossier))
|
||||||
|
|
|
@ -105,3 +105,7 @@ LOGRAGE_ENABLED="disabled"
|
||||||
# Service externe d'horodatage des changements de statut des dossiers (effectué quotidiennement)
|
# Service externe d'horodatage des changements de statut des dossiers (effectué quotidiennement)
|
||||||
UNIVERSIGN_API_URL=""
|
UNIVERSIGN_API_URL=""
|
||||||
UNIVERSIGN_USERPWD=""
|
UNIVERSIGN_USERPWD=""
|
||||||
|
|
||||||
|
# API Geo / Adresse
|
||||||
|
API_ADRESSE_URL="https://api-adresse.data.gouv.fr"
|
||||||
|
API_GEO_URL="https://geo.api.gouv.fr"
|
||||||
|
|
|
@ -5,6 +5,7 @@ Rails.application.config.assets.version = '1.0'
|
||||||
|
|
||||||
# Add additional assets to the asset load path
|
# Add additional assets to the asset load path
|
||||||
Rails.application.config.assets.paths << Rails.root.join('node_modules', 'trix', 'dist')
|
Rails.application.config.assets.paths << Rails.root.join('node_modules', 'trix', 'dist')
|
||||||
|
Rails.application.config.assets.paths << Rails.root.join('node_modules', 'select2', 'dist', 'css')
|
||||||
|
|
||||||
# Precompile additional assets.
|
# Precompile additional assets.
|
||||||
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
|
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
|
||||||
|
|
|
@ -13,7 +13,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", :unsafe_inline
|
policy.style_src :self, "*.crisp.chat", "crisp.chat", :unsafe_inline
|
||||||
policy.connect_src :self, "wss://*.crisp.chat", "*.crisp.chat", "*.demarches-simplifiees.fr", "in-automate.sendinblue.com", "app.franceconnect.gouv.fr", "sentry.io"
|
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"
|
||||||
# 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, :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, :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"
|
||||||
|
|
1
config/initializers/geocoder.rb
Normal file
1
config/initializers/geocoder.rb
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Geocoder.configure(lookup: :ban_data_gouv_fr)
|
|
@ -1,9 +1,6 @@
|
||||||
# API URLs
|
# API URLs
|
||||||
API_ADRESSE_URL = ENV.fetch("API_ADRESSE_URL", "https://api-adresse.data.gouv.fr")
|
|
||||||
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_GEO_URL = ENV.fetch("API_GEO_URL", "https://geo.api.gouv.fr")
|
|
||||||
API_GEO_SANDBOX_URL = ENV.fetch("API_GEO_SANDBOX_URL", "https://sandbox.geo.api.gouv.fr")
|
|
||||||
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")
|
||||||
|
|
|
@ -24,6 +24,7 @@ fr:
|
||||||
pays: 'Pays'
|
pays: 'Pays'
|
||||||
regions: 'Régions'
|
regions: 'Régions'
|
||||||
departements: 'Départements'
|
departements: 'Départements'
|
||||||
|
communes: 'Communes'
|
||||||
engagement: 'Engagement'
|
engagement: 'Engagement'
|
||||||
header_section: 'Titre de section'
|
header_section: 'Titre de section'
|
||||||
explication: 'Explication'
|
explication: 'Explication'
|
||||||
|
|
|
@ -16,3 +16,7 @@ fr:
|
||||||
assignment:
|
assignment:
|
||||||
one: "L’instructeur %{value} a été affecté au groupe « %{groupe} »."
|
one: "L’instructeur %{value} a été affecté au groupe « %{groupe} »."
|
||||||
other: "Les instructeurs %{value} ont été affectés au groupe « %{groupe} »."
|
other: "Les instructeurs %{value} ont été affectés au groupe « %{groupe} »."
|
||||||
|
reaffecter_dossiers:
|
||||||
|
existing_groupe:
|
||||||
|
one: "%{count} groupe existe"
|
||||||
|
other: "%{count} groupes existent"
|
||||||
|
|
|
@ -32,6 +32,7 @@ Rails.application.routes.draw do
|
||||||
|
|
||||||
resources :instructeurs, only: [:index, :show] do
|
resources :instructeurs, only: [:index, :show] do
|
||||||
post 'reinvite', on: :member
|
post 'reinvite', on: :member
|
||||||
|
delete 'delete', on: :member
|
||||||
end
|
end
|
||||||
|
|
||||||
resources :dossiers, only: [:show]
|
resources :dossiers, only: [:show]
|
||||||
|
@ -209,13 +210,6 @@ Rails.application.routes.draw do
|
||||||
resources :instructeurs, only: [:index, :create, :destroy]
|
resources :instructeurs, only: [:index, :create, :destroy]
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
|
||||||
# Addresses
|
|
||||||
#
|
|
||||||
|
|
||||||
get 'address/suggestions' => 'address#suggestions'
|
|
||||||
get 'address/geocode' => 'address#geocode'
|
|
||||||
|
|
||||||
resources :invites, only: [:show] do
|
resources :invites, only: [:show] do
|
||||||
collection do
|
collection do
|
||||||
post 'dossier/:dossier_id', to: 'invites#create', as: :dossier
|
post 'dossier/:dossier_id', to: 'invites#create', as: :dossier
|
||||||
|
@ -363,10 +357,12 @@ Rails.application.routes.draw do
|
||||||
get 'annotations'
|
get 'annotations'
|
||||||
end
|
end
|
||||||
|
|
||||||
resources :groupe_instructeurs, only: [:index, :show, :create, :update] do
|
resources :groupe_instructeurs, only: [:index, :show, :create, :update, :destroy] do
|
||||||
member do
|
member do
|
||||||
post 'add_instructeur'
|
post 'add_instructeur'
|
||||||
delete 'remove_instructeur'
|
delete 'remove_instructeur'
|
||||||
|
get 'reaffecter_dossiers'
|
||||||
|
post 'reaffecter'
|
||||||
end
|
end
|
||||||
|
|
||||||
collection do
|
collection do
|
||||||
|
@ -394,6 +390,14 @@ Rails.application.routes.draw do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if Rails.env.test?
|
||||||
|
scope 'test/api_geo' do
|
||||||
|
get 'regions' => 'api_geo_test#regions'
|
||||||
|
get 'communes' => 'api_geo_test#communes'
|
||||||
|
get 'departements' => 'api_geo_test#departements'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# Legacy routes
|
# Legacy routes
|
||||||
#
|
#
|
||||||
|
|
|
@ -68,6 +68,9 @@ defaults: &defaults
|
||||||
client_key: <%= ENV['CRISP_CLIENT_KEY'] %>
|
client_key: <%= ENV['CRISP_CLIENT_KEY'] %>
|
||||||
universign:
|
universign:
|
||||||
userpwd: <%= ENV['UNIVERSIGN_USERPWD'] %>
|
userpwd: <%= ENV['UNIVERSIGN_USERPWD'] %>
|
||||||
|
autocomplete:
|
||||||
|
api_geo_url: <%= ENV['API_GEO_URL'] %>
|
||||||
|
api_adresse_url: <%= ENV['API_ADRESSE_URL'] %>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -98,6 +101,8 @@ test:
|
||||||
logout_endpoint: https://bidon.com/endpoint
|
logout_endpoint: https://bidon.com/endpoint
|
||||||
universign:
|
universign:
|
||||||
userpwd: 'fake:fake'
|
userpwd: 'fake:fake'
|
||||||
|
autocomplete:
|
||||||
|
api_geo_url: /test/api_geo
|
||||||
|
|
||||||
# Do not keep production secrets in the repository,
|
# Do not keep production secrets in the repository,
|
||||||
# instead read values from the environment.
|
# instead read values from the environment.
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
"@rails/webpacker": "4.0.7",
|
"@rails/webpacker": "4.0.7",
|
||||||
"@sentry/browser": "^5.7.1",
|
"@sentry/browser": "^5.7.1",
|
||||||
"@turf/area": "^6.0.1",
|
"@turf/area": "^6.0.1",
|
||||||
"autocomplete.js": "^0.37.0",
|
|
||||||
"babel-plugin-macros": "^2.6.1",
|
"babel-plugin-macros": "^2.6.1",
|
||||||
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
|
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
|
||||||
"chartkick": "^3.1.3",
|
"chartkick": "^3.1.3",
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe AddressController, type: :controller do
|
|
||||||
describe '#GET suggestions' do
|
|
||||||
subject { get :suggestions, params: { request: request } }
|
|
||||||
|
|
||||||
before do
|
|
||||||
subject
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when request return result', vcr: { cassette_name: 'api_adresse_search_paris_2' } do
|
|
||||||
let (:request) { 'Paris' }
|
|
||||||
|
|
||||||
it { expect(response.status).to eq 200 }
|
|
||||||
it { expect(response.body).to eq '[{"label":"Paris"},{"label":"Paris 63120 Courpière"},{"label":"PARIS (Vaillac) 46240 Cœur de Causse"},{"label":"Paris 40500 Saint-Sever"},{"label":"Paris Buton 37140 Bourgueil"}]' }
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when request return nothing', vcr: { cassette_name: 'api_adresse_search_nothing_2' } do
|
|
||||||
let (:request) { 'je recherche pas grand chose' }
|
|
||||||
|
|
||||||
it { expect(response.status).to eq 200 }
|
|
||||||
it { expect(response.body).to eq "[]" }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#GET geocode' do
|
|
||||||
let(:dossier_id) { "1" }
|
|
||||||
subject { get :geocode, params: { request: request, dossier_id: dossier_id } }
|
|
||||||
|
|
||||||
before do
|
|
||||||
subject
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when request return result', vcr: { cassette_name: 'api_adresse_search_paris' } do
|
|
||||||
let(:request) { 'Paris' }
|
|
||||||
|
|
||||||
it { expect(response.body).to eq ({ lon: '2.3469', lat: '48.8589', zoom: '14', dossier_id: dossier_id }).to_json }
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when request return nothing', vcr: { cassette_name: 'api_adresse_search_nothing' } do
|
|
||||||
let(:request) { 'je recherche pas grand chose' }
|
|
||||||
|
|
||||||
it { expect(response.body).to eq ({ lon: nil, lat: nil, zoom: '14', dossier_id: dossier_id }).to_json }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -473,6 +473,34 @@ describe Instructeurs::DossiersController, type: :controller do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "#show" do
|
||||||
|
context "when the dossier is exported as PDF" do
|
||||||
|
let(:instructeur) { create(:instructeur) }
|
||||||
|
let(:dossier) {
|
||||||
|
create(:dossier,
|
||||||
|
:accepte,
|
||||||
|
:with_all_champs,
|
||||||
|
:with_all_annotations,
|
||||||
|
:with_motivation,
|
||||||
|
:with_commentaires, procedure: procedure)
|
||||||
|
}
|
||||||
|
let!(:avis) { create(:avis, dossier: dossier, instructeur: instructeur) }
|
||||||
|
subject do
|
||||||
|
get :show, params: {
|
||||||
|
procedure_id: procedure.id,
|
||||||
|
dossier_id: dossier.id,
|
||||||
|
format: :pdf
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
it { expect(assigns(:include_infos_administration)).to eq(true) }
|
||||||
|
it { expect(response).to render_template 'dossiers/show' }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "#update_annotations" do
|
describe "#update_annotations" do
|
||||||
let(:champ_multiple_drop_down_list) do
|
let(:champ_multiple_drop_down_list) do
|
||||||
create(:type_de_champ_multiple_drop_down_list, :private, libelle: 'libelle').champ.create
|
create(:type_de_champ_multiple_drop_down_list, :private, libelle: 'libelle').champ.create
|
||||||
|
|
17
spec/controllers/manager/instructeurs_controller_spec.rb
Normal file
17
spec/controllers/manager/instructeurs_controller_spec.rb
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
describe Manager::InstructeursController, type: :controller do
|
||||||
|
let(:administration) { create(:administration) }
|
||||||
|
|
||||||
|
describe '#delete' do
|
||||||
|
let!(:instructeur) { create(:instructeur) }
|
||||||
|
|
||||||
|
before { sign_in administration }
|
||||||
|
|
||||||
|
subject { delete :delete, params: { id: instructeur.id } }
|
||||||
|
|
||||||
|
it 'deletes the instructeur' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(Instructeur.find_by(id: instructeur.id)).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -59,6 +59,106 @@ describe NewAdministrateur::GroupeInstructeursController, type: :controller do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#destroy' do
|
||||||
|
def delete_group(group)
|
||||||
|
delete :destroy,
|
||||||
|
params: {
|
||||||
|
procedure_id: procedure.id,
|
||||||
|
id: group.id
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with only one group' do
|
||||||
|
before { delete_group gi_1_1 }
|
||||||
|
|
||||||
|
it { expect(flash.alert).to be_present }
|
||||||
|
it { expect(response).to redirect_to(procedure_groupe_instructeurs_path(procedure)) }
|
||||||
|
it { expect(procedure.groupe_instructeurs.count).to eq(1) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with many groups' do
|
||||||
|
let!(:gi_1_2) { procedure.groupe_instructeurs.create(label: 'groupe instructeur 2') }
|
||||||
|
|
||||||
|
context 'of a group that can be deleted' do
|
||||||
|
before { delete_group gi_1_2 }
|
||||||
|
it { expect(flash.notice).to be_present }
|
||||||
|
it { expect(procedure.groupe_instructeurs.count).to eq(1) }
|
||||||
|
it { expect(response).to redirect_to(procedure_groupe_instructeurs_path(procedure)) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'of a group with dossiers, that cannot be deleted' do
|
||||||
|
let!(:dossier12) { create(:dossier, procedure: procedure, state: Dossier.states.fetch(:en_construction), groupe_instructeur: gi_1_2) }
|
||||||
|
before { delete_group gi_1_2 }
|
||||||
|
|
||||||
|
it { expect(flash.alert).to be_present }
|
||||||
|
it { expect(procedure.groupe_instructeurs.count).to eq(2) }
|
||||||
|
it { expect(response).to redirect_to(procedure_groupe_instructeurs_path(procedure)) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#reaffecter_dossiers' do
|
||||||
|
let!(:gi_1_2) { procedure.groupe_instructeurs.create(label: 'groupe instructeur 2') }
|
||||||
|
let!(:gi_1_3) { procedure.groupe_instructeurs.create(label: 'groupe instructeur 3') }
|
||||||
|
|
||||||
|
before do
|
||||||
|
get :reaffecter_dossiers,
|
||||||
|
params: {
|
||||||
|
procedure_id: procedure.id,
|
||||||
|
id: gi_1_2.id
|
||||||
|
}
|
||||||
|
end
|
||||||
|
def reaffecter_url(group)
|
||||||
|
reaffecter_procedure_groupe_instructeur_path(:id => gi_1_2,
|
||||||
|
:target_group => group)
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect(response).to have_http_status(:ok) }
|
||||||
|
it { expect(response.body).to include(reaffecter_url(procedure.defaut_groupe_instructeur)) }
|
||||||
|
it { expect(response.body).not_to include(reaffecter_url(gi_1_2)) }
|
||||||
|
it { expect(response.body).to include(reaffecter_url(gi_1_3)) }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#reaffecter' do
|
||||||
|
let!(:gi_1_2) { procedure.groupe_instructeurs.create(label: 'groupe instructeur 2') }
|
||||||
|
let!(:dossier12) { create(:dossier, procedure: procedure, state: Dossier.states.fetch(:en_construction), groupe_instructeur: gi_1_1) }
|
||||||
|
|
||||||
|
describe 'when the new group is a group of the procedure' do
|
||||||
|
before do
|
||||||
|
post :reaffecter,
|
||||||
|
params: {
|
||||||
|
procedure_id: procedure.id,
|
||||||
|
id: gi_1_1.id,
|
||||||
|
target_group: gi_1_2.id
|
||||||
|
}
|
||||||
|
dossier12.reload
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect(response).to redirect_to(procedure_groupe_instructeurs_path(procedure)) }
|
||||||
|
it { expect(gi_1_1.dossiers.count).to be(0) }
|
||||||
|
it { expect(gi_1_2.dossiers.count).to be(1) }
|
||||||
|
it { expect(gi_1_2.dossiers.last.id).to be(dossier12.id) }
|
||||||
|
it { expect(dossier12.groupe_instructeur.id).to be(gi_1_2.id) }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'when the target group is not a possible group' do
|
||||||
|
subject {
|
||||||
|
post :reaffecter,
|
||||||
|
params:
|
||||||
|
{
|
||||||
|
procedure_id: procedure.id,
|
||||||
|
id: gi_1_1.id,
|
||||||
|
target_group: gi_2_2.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
before do
|
||||||
|
dossier12.reload
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect { subject }.to raise_error(ActiveRecord::RecordNotFound) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '#update' do
|
describe '#update' do
|
||||||
let(:new_name) { 'nouveau nom du groupe' }
|
let(:new_name) { 'nouveau nom du groupe' }
|
||||||
|
|
||||||
|
|
|
@ -731,6 +731,7 @@ describe Users::DossiersController, type: :controller do
|
||||||
sign_in(user)
|
sign_in(user)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'with default output' do
|
||||||
subject! { get(:show, params: { id: dossier.id }) }
|
subject! { get(:show, params: { id: dossier.id }) }
|
||||||
|
|
||||||
context 'when the dossier is a brouillon' do
|
context 'when the dossier is a brouillon' do
|
||||||
|
@ -745,6 +746,25 @@ describe Users::DossiersController, type: :controller do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "with PDF output" do
|
||||||
|
let(:procedure) { create(:procedure) }
|
||||||
|
let(:dossier) {
|
||||||
|
create(:dossier,
|
||||||
|
:accepte,
|
||||||
|
:with_all_champs,
|
||||||
|
:with_motivation,
|
||||||
|
:with_commentaires,
|
||||||
|
procedure: procedure,
|
||||||
|
user: user)
|
||||||
|
}
|
||||||
|
|
||||||
|
subject! { get(:show, params: { id: dossier.id, format: :pdf }) }
|
||||||
|
|
||||||
|
it { expect(assigns(:include_infos_administration)).to eq(false) }
|
||||||
|
it { expect(response).to render_template 'dossiers/show' }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '#formulaire' do
|
describe '#formulaire' do
|
||||||
let(:dossier) { create(:dossier, :en_construction, user: user) }
|
let(:dossier) { create(:dossier, :en_construction, user: user) }
|
||||||
|
|
||||||
|
|
|
@ -124,6 +124,11 @@ FactoryBot.define do
|
||||||
value { '971 - Guadeloupe' }
|
value { '971 - Guadeloupe' }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
factory :champ_communes, class: 'Champs::CommuneChamp' do
|
||||||
|
type_de_champ { create(:type_de_champ_communes) }
|
||||||
|
value { 'Paris' }
|
||||||
|
end
|
||||||
|
|
||||||
factory :champ_engagement, class: 'Champs::EngagementChamp' do
|
factory :champ_engagement, class: 'Champs::EngagementChamp' do
|
||||||
type_de_champ { create(:type_de_champ_engagement) }
|
type_de_champ { create(:type_de_champ_engagement) }
|
||||||
value { 'true' }
|
value { 'true' }
|
||||||
|
|
|
@ -71,6 +71,9 @@ FactoryBot.define do
|
||||||
factory :type_de_champ_departements do
|
factory :type_de_champ_departements do
|
||||||
type_champ { TypeDeChamp.type_champs.fetch(:departements) }
|
type_champ { TypeDeChamp.type_champs.fetch(:departements) }
|
||||||
end
|
end
|
||||||
|
factory :type_de_champ_communes do
|
||||||
|
type_champ { TypeDeChamp.type_champs.fetch(:communes) }
|
||||||
|
end
|
||||||
factory :type_de_champ_engagement do
|
factory :type_de_champ_engagement do
|
||||||
type_champ { TypeDeChamp.type_champs.fetch(:engagement) }
|
type_champ { TypeDeChamp.type_champs.fetch(:engagement) }
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,10 +10,7 @@ feature 'The user' do
|
||||||
# TODO: check
|
# TODO: check
|
||||||
# the order
|
# the order
|
||||||
# there are no extraneous input
|
# there are no extraneous input
|
||||||
scenario 'fill a dossier', js: true do
|
scenario 'fill a dossier', js: true, vcr: { cassette_name: 'api_geo_departements_regions_et_communes' } do
|
||||||
allow(Champs::RegionChamp).to receive(:regions).and_return(['region1', 'region2']).at_least(:once)
|
|
||||||
allow(Champs::DepartementChamp).to receive(:departements).and_return(['dep1', 'dep2']).at_least(:once)
|
|
||||||
|
|
||||||
log_in(user, procedure)
|
log_in(user, procedure)
|
||||||
|
|
||||||
fill_individual
|
fill_individual
|
||||||
|
@ -33,8 +30,16 @@ feature 'The user' do
|
||||||
select('val1', from: form_id_for('multiple_drop_down_list'))
|
select('val1', from: form_id_for('multiple_drop_down_list'))
|
||||||
select('val3', from: form_id_for('multiple_drop_down_list'))
|
select('val3', from: form_id_for('multiple_drop_down_list'))
|
||||||
select('AUSTRALIE', from: 'pays')
|
select('AUSTRALIE', from: 'pays')
|
||||||
select('region2', from: 'regions')
|
|
||||||
select('dep2', from: 'departements')
|
select_champ_geo('regions', 'Ma', 'Martinique')
|
||||||
|
select('Martinique', from: 'regions')
|
||||||
|
|
||||||
|
select_champ_geo('departements', 'Ai', '02 - Aisne')
|
||||||
|
select('02 - Aisne', from: 'departements')
|
||||||
|
|
||||||
|
select_champ_geo('communes', 'Am', 'Ambléon')
|
||||||
|
select('Ambléon', from: 'communes')
|
||||||
|
|
||||||
check('engagement')
|
check('engagement')
|
||||||
fill_in('dossier_link', with: '123')
|
fill_in('dossier_link', with: '123')
|
||||||
find('.editable-champ-piece_justificative input[type=file]').attach_file(Rails.root + 'spec/fixtures/files/file.pdf')
|
find('.editable-champ-piece_justificative input[type=file]').attach_file(Rails.root + 'spec/fixtures/files/file.pdf')
|
||||||
|
@ -57,8 +62,9 @@ feature 'The user' do
|
||||||
expect(champ_value_for('simple_drop_down_list')).to eq('val2')
|
expect(champ_value_for('simple_drop_down_list')).to eq('val2')
|
||||||
expect(JSON.parse(champ_value_for('multiple_drop_down_list'))).to match(['val1', 'val3'])
|
expect(JSON.parse(champ_value_for('multiple_drop_down_list'))).to match(['val1', 'val3'])
|
||||||
expect(champ_value_for('pays')).to eq('AUSTRALIE')
|
expect(champ_value_for('pays')).to eq('AUSTRALIE')
|
||||||
expect(champ_value_for('regions')).to eq('region2')
|
expect(champ_value_for('regions')).to eq('Martinique')
|
||||||
expect(champ_value_for('departements')).to eq('dep2')
|
expect(champ_value_for('departements')).to eq('02 - Aisne')
|
||||||
|
expect(champ_value_for('communes')).to eq('Ambléon')
|
||||||
expect(champ_value_for('engagement')).to eq('on')
|
expect(champ_value_for('engagement')).to eq('on')
|
||||||
expect(champ_value_for('dossier_link')).to eq('123')
|
expect(champ_value_for('dossier_link')).to eq('123')
|
||||||
expect(champ_value_for('piece_justificative')).to be_nil # antivirus hasn't approved the file yet
|
expect(champ_value_for('piece_justificative')).to be_nil # antivirus hasn't approved the file yet
|
||||||
|
@ -78,8 +84,9 @@ feature 'The user' do
|
||||||
expect(page).to have_selected_value('simple_drop_down_list', selected: 'val2')
|
expect(page).to have_selected_value('simple_drop_down_list', selected: 'val2')
|
||||||
expect(page).to have_selected_value('multiple_drop_down_list', selected: ['val1', 'val3'])
|
expect(page).to have_selected_value('multiple_drop_down_list', selected: ['val1', 'val3'])
|
||||||
expect(page).to have_selected_value('pays', selected: 'AUSTRALIE')
|
expect(page).to have_selected_value('pays', selected: 'AUSTRALIE')
|
||||||
expect(page).to have_selected_value('regions', selected: 'region2')
|
expect(page).to have_selected_value('regions', selected: 'Martinique')
|
||||||
expect(page).to have_selected_value('departement', selected: 'dep2')
|
expect(page).to have_selected_value('departements', selected: '02 - Aisne')
|
||||||
|
expect(page).to have_selected_value('communes', selected: 'Ambléon')
|
||||||
expect(page).to have_checked_field('engagement')
|
expect(page).to have_checked_field('engagement')
|
||||||
expect(page).to have_field('dossier_link', with: '123')
|
expect(page).to have_field('dossier_link', with: '123')
|
||||||
expect(page).to have_text('file.pdf')
|
expect(page).to have_text('file.pdf')
|
||||||
|
@ -270,4 +277,12 @@ feature 'The user' do
|
||||||
expect(page).to have_selected_value("#{field}_4i", selected: date.strftime('%H'))
|
expect(page).to have_selected_value("#{field}_4i", selected: date.strftime('%H'))
|
||||||
expect(page).to have_selected_value("#{field}_5i", selected: date.strftime('%M'))
|
expect(page).to have_selected_value("#{field}_5i", selected: date.strftime('%M'))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def select_champ_geo(champ, fill_with, value)
|
||||||
|
find(".editable-champ-#{champ} .select2-container").click
|
||||||
|
id = find('.select2-container--open [role=listbox]')[:id]
|
||||||
|
find("[aria-controls=#{id}]").fill_in with: fill_with
|
||||||
|
expect(page).to have_content(value)
|
||||||
|
find('li', text: value).click
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -77,7 +77,7 @@ feature 'Creating a new dossier:' do
|
||||||
.to_return(status: 404, body: '')
|
.to_return(status: 404, body: '')
|
||||||
end
|
end
|
||||||
|
|
||||||
scenario 'the user can enter the SIRET of its etablissement and create a new draft', vcr: { cassette_name: 'api_adresse_search_paris_3' } do
|
scenario 'the user can enter the SIRET of its etablissement and create a new draft' do
|
||||||
visit commencer_path(path: procedure.path)
|
visit commencer_path(path: procedure.path)
|
||||||
click_on 'Commencer la démarche'
|
click_on 'Commencer la démarche'
|
||||||
|
|
||||||
|
|
47
spec/fixtures/cassettes/api_adresse_octo.yml
vendored
47
spec/fixtures/cassettes/api_adresse_octo.yml
vendored
|
@ -1,47 +0,0 @@
|
||||||
---
|
|
||||||
http_interactions:
|
|
||||||
- request:
|
|
||||||
method: get
|
|
||||||
uri: https://api-adresse.data.gouv.fr/search?limit=1&q=50%20av%20des%20champs%20elysees
|
|
||||||
body:
|
|
||||||
encoding: US-ASCII
|
|
||||||
string: ''
|
|
||||||
headers:
|
|
||||||
Accept:
|
|
||||||
- "*/*"
|
|
||||||
Accept-Encoding:
|
|
||||||
- gzip, deflate
|
|
||||||
User-Agent:
|
|
||||||
- rest-client/2.0.0 (darwin15.6.0 x86_64) ruby/2.3.1p112
|
|
||||||
response:
|
|
||||||
status:
|
|
||||||
code: 200
|
|
||||||
message: OK
|
|
||||||
headers:
|
|
||||||
Server:
|
|
||||||
- nginx/1.11.3
|
|
||||||
Date:
|
|
||||||
- Fri, 16 Dec 2016 16:22:23 GMT
|
|
||||||
Content-Type:
|
|
||||||
- application/json; charset=utf-8
|
|
||||||
Content-Length:
|
|
||||||
- '628'
|
|
||||||
Connection:
|
|
||||||
- keep-alive
|
|
||||||
Access-Control-Allow-Origin:
|
|
||||||
- "*"
|
|
||||||
Access-Control-Allow-Headers:
|
|
||||||
- X-Requested-With
|
|
||||||
body:
|
|
||||||
encoding: UTF-8
|
|
||||||
string: '{"limit": 1, "attribution": "BAN", "version": "draft", "licence": "ODbL
|
|
||||||
1.0", "query": "50 av des champs elysees", "type": "FeatureCollection", "features":
|
|
||||||
[{"geometry": {"type": "Point", "coordinates": [2.306888, 48.870374]}, "properties":
|
|
||||||
{"citycode": "75108", "postcode": "75008", "name": "50 Avenue des Champs \u00c9lys\u00e9es",
|
|
||||||
"id": "ADRNIVX_0000000270748251", "type": "housenumber", "context": "75, \u00cele-de-France",
|
|
||||||
"score": 0.7561038961038961, "label": "50 Avenue des Champs \u00c9lys\u00e9es
|
|
||||||
75008 Paris", "city": "Paris", "housenumber": "50", "street": "Avenue des
|
|
||||||
Champs \u00c9lys\u00e9es"}, "type": "Feature"}]}'
|
|
||||||
http_version:
|
|
||||||
recorded_at: Fri, 16 Dec 2016 16:22:23 GMT
|
|
||||||
recorded_with: VCR 3.0.3
|
|
|
@ -1,42 +0,0 @@
|
||||||
---
|
|
||||||
http_interactions:
|
|
||||||
- request:
|
|
||||||
method: get
|
|
||||||
uri: https://api-adresse.data.gouv.fr/search?limit=1&q=je%20recherche%20pas%20grand%20chose
|
|
||||||
body:
|
|
||||||
encoding: US-ASCII
|
|
||||||
string: ''
|
|
||||||
headers:
|
|
||||||
Accept:
|
|
||||||
- "*/*"
|
|
||||||
Accept-Encoding:
|
|
||||||
- gzip, deflate
|
|
||||||
User-Agent:
|
|
||||||
- rest-client/2.0.0 (darwin15.6.0 x86_64) ruby/2.3.1p112
|
|
||||||
response:
|
|
||||||
status:
|
|
||||||
code: 200
|
|
||||||
message: OK
|
|
||||||
headers:
|
|
||||||
Server:
|
|
||||||
- nginx/1.11.3
|
|
||||||
Date:
|
|
||||||
- Fri, 16 Dec 2016 14:17:40 GMT
|
|
||||||
Content-Type:
|
|
||||||
- application/json; charset=utf-8
|
|
||||||
Content-Length:
|
|
||||||
- '163'
|
|
||||||
Connection:
|
|
||||||
- keep-alive
|
|
||||||
Access-Control-Allow-Origin:
|
|
||||||
- "*"
|
|
||||||
Access-Control-Allow-Headers:
|
|
||||||
- X-Requested-With
|
|
||||||
body:
|
|
||||||
encoding: UTF-8
|
|
||||||
string: '{"limit": 1, "attribution": "BAN", "version": "draft", "licence": "ODbL
|
|
||||||
1.0", "query": "je recherche pas grand chose", "type": "FeatureCollection",
|
|
||||||
"features": []}'
|
|
||||||
http_version:
|
|
||||||
recorded_at: Fri, 16 Dec 2016 14:17:40 GMT
|
|
||||||
recorded_with: VCR 3.0.3
|
|
|
@ -1,42 +0,0 @@
|
||||||
---
|
|
||||||
http_interactions:
|
|
||||||
- request:
|
|
||||||
method: get
|
|
||||||
uri: https://api-adresse.data.gouv.fr/search?limit=5&q=je%20recherche%20pas%20grand%20chose
|
|
||||||
body:
|
|
||||||
encoding: US-ASCII
|
|
||||||
string: ''
|
|
||||||
headers:
|
|
||||||
Accept:
|
|
||||||
- "*/*"
|
|
||||||
Accept-Encoding:
|
|
||||||
- gzip, deflate
|
|
||||||
User-Agent:
|
|
||||||
- rest-client/2.0.0 (darwin15.6.0 x86_64) ruby/2.3.1p112
|
|
||||||
response:
|
|
||||||
status:
|
|
||||||
code: 200
|
|
||||||
message: OK
|
|
||||||
headers:
|
|
||||||
Server:
|
|
||||||
- nginx/1.11.3
|
|
||||||
Date:
|
|
||||||
- Fri, 16 Dec 2016 16:45:53 GMT
|
|
||||||
Content-Type:
|
|
||||||
- application/json; charset=utf-8
|
|
||||||
Content-Length:
|
|
||||||
- '163'
|
|
||||||
Connection:
|
|
||||||
- keep-alive
|
|
||||||
Access-Control-Allow-Origin:
|
|
||||||
- "*"
|
|
||||||
Access-Control-Allow-Headers:
|
|
||||||
- X-Requested-With
|
|
||||||
body:
|
|
||||||
encoding: UTF-8
|
|
||||||
string: '{"limit": 5, "attribution": "BAN", "version": "draft", "licence": "ODbL
|
|
||||||
1.0", "query": "je recherche pas grand chose", "type": "FeatureCollection",
|
|
||||||
"features": []}'
|
|
||||||
http_version:
|
|
||||||
recorded_at: Fri, 16 Dec 2016 16:45:53 GMT
|
|
||||||
recorded_with: VCR 3.0.3
|
|
|
@ -1,45 +0,0 @@
|
||||||
---
|
|
||||||
http_interactions:
|
|
||||||
- request:
|
|
||||||
method: get
|
|
||||||
uri: https://api-adresse.data.gouv.fr/search?limit=1&q=Paris
|
|
||||||
body:
|
|
||||||
encoding: US-ASCII
|
|
||||||
string: ''
|
|
||||||
headers:
|
|
||||||
Accept:
|
|
||||||
- "*/*"
|
|
||||||
Accept-Encoding:
|
|
||||||
- gzip, deflate
|
|
||||||
User-Agent:
|
|
||||||
- rest-client/2.0.0 (darwin15.6.0 x86_64) ruby/2.3.1p112
|
|
||||||
response:
|
|
||||||
status:
|
|
||||||
code: 200
|
|
||||||
message: OK
|
|
||||||
headers:
|
|
||||||
Server:
|
|
||||||
- nginx/1.11.3
|
|
||||||
Date:
|
|
||||||
- Fri, 16 Dec 2016 14:16:43 GMT
|
|
||||||
Content-Type:
|
|
||||||
- application/json; charset=utf-8
|
|
||||||
Content-Length:
|
|
||||||
- '457'
|
|
||||||
Connection:
|
|
||||||
- keep-alive
|
|
||||||
Access-Control-Allow-Origin:
|
|
||||||
- "*"
|
|
||||||
Access-Control-Allow-Headers:
|
|
||||||
- X-Requested-With
|
|
||||||
body:
|
|
||||||
encoding: UTF-8
|
|
||||||
string: '{"limit": 1, "attribution": "BAN", "version": "draft", "licence": "ODbL
|
|
||||||
1.0", "query": "Paris", "type": "FeatureCollection", "features": [{"geometry":
|
|
||||||
{"type": "Point", "coordinates": [2.3469, 48.8589]}, "properties": {"adm_weight":
|
|
||||||
"6", "citycode": "75056", "name": "Paris", "city": "Paris", "postcode": "75000",
|
|
||||||
"context": "75, \u00cele-de-France", "score": 1.0, "label": "Paris", "id":
|
|
||||||
"75056", "type": "city", "population": "2244"}, "type": "Feature"}]}'
|
|
||||||
http_version:
|
|
||||||
recorded_at: Fri, 16 Dec 2016 14:16:43 GMT
|
|
||||||
recorded_with: VCR 3.0.3
|
|
|
@ -1,63 +0,0 @@
|
||||||
---
|
|
||||||
http_interactions:
|
|
||||||
- request:
|
|
||||||
method: get
|
|
||||||
uri: https://api-adresse.data.gouv.fr/search?limit=5&q=Paris
|
|
||||||
body:
|
|
||||||
encoding: US-ASCII
|
|
||||||
string: ''
|
|
||||||
headers:
|
|
||||||
Accept:
|
|
||||||
- "*/*"
|
|
||||||
Accept-Encoding:
|
|
||||||
- gzip, deflate
|
|
||||||
User-Agent:
|
|
||||||
- rest-client/2.0.0 (darwin15.6.0 x86_64) ruby/2.3.1p112
|
|
||||||
response:
|
|
||||||
status:
|
|
||||||
code: 200
|
|
||||||
message: OK
|
|
||||||
headers:
|
|
||||||
Server:
|
|
||||||
- nginx/1.11.3
|
|
||||||
Date:
|
|
||||||
- Fri, 16 Dec 2016 16:43:34 GMT
|
|
||||||
Content-Type:
|
|
||||||
- application/json; charset=utf-8
|
|
||||||
Content-Length:
|
|
||||||
- '1887'
|
|
||||||
Connection:
|
|
||||||
- keep-alive
|
|
||||||
Access-Control-Allow-Origin:
|
|
||||||
- "*"
|
|
||||||
Access-Control-Allow-Headers:
|
|
||||||
- X-Requested-With
|
|
||||||
body:
|
|
||||||
encoding: UTF-8
|
|
||||||
string: '{"limit": 5, "attribution": "BAN", "version": "draft", "licence": "ODbL
|
|
||||||
1.0", "query": "Paris", "type": "FeatureCollection", "features": [{"geometry":
|
|
||||||
{"type": "Point", "coordinates": [2.3469, 48.8589]}, "properties": {"adm_weight":
|
|
||||||
"6", "citycode": "75056", "name": "Paris", "city": "Paris", "postcode": "75000",
|
|
||||||
"context": "75, \u00cele-de-France", "score": 1.0, "label": "Paris", "id":
|
|
||||||
"75056", "type": "city", "population": "2244"}, "type": "Feature"}, {"geometry":
|
|
||||||
{"type": "Point", "coordinates": [3.564293, 45.766413]}, "properties": {"citycode":
|
|
||||||
"63125", "postcode": "63120", "name": "Paris", "city": "Courpi\u00e8re", "context":
|
|
||||||
"63, Puy-de-D\u00f4me, Auvergne", "score": 0.8255363636363636, "label": "Paris
|
|
||||||
63120 Courpi\u00e8re", "id": "63125_B221_03549b", "type": "locality"}, "type":
|
|
||||||
"Feature"}, {"geometry": {"type": "Point", "coordinates": [1.550208, 44.673592]},
|
|
||||||
"properties": {"citycode": "46138", "postcode": "46240", "name": "PARIS (Vaillac)",
|
|
||||||
"city": "C\u0153ur de Causse", "context": "46, Lot, Midi-Pyr\u00e9n\u00e9es",
|
|
||||||
"score": 0.824090909090909, "label": "PARIS (Vaillac) 46240 C\u0153ur de Causse",
|
|
||||||
"id": "46138_XXXX_6ee4ec", "type": "street"}, "type": "Feature"}, {"geometry":
|
|
||||||
{"type": "Point", "coordinates": [-0.526884, 43.762253]}, "properties": {"citycode":
|
|
||||||
"40282", "postcode": "40500", "name": "Paris", "city": "Saint-Sever", "context":
|
|
||||||
"40, Landes, Aquitaine", "score": 0.8236181818181818, "label": "Paris 40500
|
|
||||||
Saint-Sever", "id": "40282_B237_2364e3", "type": "locality"}, "type": "Feature"},
|
|
||||||
{"geometry": {"type": "Point", "coordinates": [0.157613, 47.336685]}, "properties":
|
|
||||||
{"citycode": "37031", "postcode": "37140", "name": "Paris Buton", "city":
|
|
||||||
"Bourgueil", "context": "37, Indre-et-Loire, Centre Val-de-Loire", "score":
|
|
||||||
0.8235454545454545, "label": "Paris Buton 37140 Bourgueil", "id": "37031_X027_0a5e7a",
|
|
||||||
"type": "locality"}, "type": "Feature"}]}'
|
|
||||||
http_version:
|
|
||||||
recorded_at: Fri, 16 Dec 2016 16:43:34 GMT
|
|
||||||
recorded_with: VCR 3.0.3
|
|
|
@ -1,93 +0,0 @@
|
||||||
---
|
|
||||||
http_interactions:
|
|
||||||
- request:
|
|
||||||
method: get
|
|
||||||
uri: https://api-adresse.data.gouv.fr/search?limit=1&q=50%20AV%20DES%20CHAMPS%20ELYSEES%20complement_adresse%2075008%20PARIS%208
|
|
||||||
body:
|
|
||||||
encoding: US-ASCII
|
|
||||||
string: ''
|
|
||||||
headers:
|
|
||||||
Accept:
|
|
||||||
- "*/*"
|
|
||||||
Accept-Encoding:
|
|
||||||
- gzip, deflate
|
|
||||||
User-Agent:
|
|
||||||
- rest-client/2.0.0 (darwin15.6.0 x86_64) ruby/2.3.1p112
|
|
||||||
response:
|
|
||||||
status:
|
|
||||||
code: 200
|
|
||||||
message: OK
|
|
||||||
headers:
|
|
||||||
Server:
|
|
||||||
- nginx/1.11.3
|
|
||||||
Date:
|
|
||||||
- Tue, 03 Jan 2017 13:00:54 GMT
|
|
||||||
Content-Type:
|
|
||||||
- application/json; charset=utf-8
|
|
||||||
Content-Length:
|
|
||||||
- '660'
|
|
||||||
Connection:
|
|
||||||
- keep-alive
|
|
||||||
Access-Control-Allow-Origin:
|
|
||||||
- "*"
|
|
||||||
Access-Control-Allow-Headers:
|
|
||||||
- X-Requested-With
|
|
||||||
body:
|
|
||||||
encoding: UTF-8
|
|
||||||
string: '{"limit": 1, "attribution": "BAN", "version": "draft", "licence": "ODbL
|
|
||||||
1.0", "query": "50 AV DES CHAMPS ELYSEES complement_adresse 75008 PARIS 8",
|
|
||||||
"type": "FeatureCollection", "features": [{"geometry": {"type": "Point", "coordinates":
|
|
||||||
[2.306888, 48.870374]}, "properties": {"citycode": "75108", "postcode": "75008",
|
|
||||||
"name": "50 Avenue des Champs \u00c9lys\u00e9es", "id": "ADRNIVX_0000000270748251",
|
|
||||||
"type": "housenumber", "context": "75, \u00cele-de-France", "score": 0.596517719568567,
|
|
||||||
"label": "50 Avenue des Champs \u00c9lys\u00e9es 75008 Paris", "city": "Paris",
|
|
||||||
"housenumber": "50", "street": "Avenue des Champs \u00c9lys\u00e9es"}, "type":
|
|
||||||
"Feature"}]}'
|
|
||||||
http_version:
|
|
||||||
recorded_at: Tue, 03 Jan 2017 13:00:54 GMT
|
|
||||||
- request:
|
|
||||||
method: get
|
|
||||||
uri: http://api-adresse.data.gouv.fr/search?limit=1&q=50%20AV%20DES%20CHAMPS%20ELYSEES%20complement_adresse%2075008%20PARIS%208
|
|
||||||
body:
|
|
||||||
encoding: US-ASCII
|
|
||||||
string: ''
|
|
||||||
headers:
|
|
||||||
Accept:
|
|
||||||
- "*/*"
|
|
||||||
Accept-Encoding:
|
|
||||||
- gzip, deflate
|
|
||||||
User-Agent:
|
|
||||||
- rest-client/2.0.0 (darwin15.6.0 x86_64) ruby/2.3.1p112
|
|
||||||
response:
|
|
||||||
status:
|
|
||||||
code: 200
|
|
||||||
message: OK
|
|
||||||
headers:
|
|
||||||
Server:
|
|
||||||
- nginx/1.11.3
|
|
||||||
Date:
|
|
||||||
- Tue, 03 Jan 2017 13:00:55 GMT
|
|
||||||
Content-Type:
|
|
||||||
- application/json; charset=utf-8
|
|
||||||
Content-Length:
|
|
||||||
- '660'
|
|
||||||
Connection:
|
|
||||||
- keep-alive
|
|
||||||
Access-Control-Allow-Origin:
|
|
||||||
- "*"
|
|
||||||
Access-Control-Allow-Headers:
|
|
||||||
- X-Requested-With
|
|
||||||
body:
|
|
||||||
encoding: UTF-8
|
|
||||||
string: '{"limit": 1, "attribution": "BAN", "version": "draft", "licence": "ODbL
|
|
||||||
1.0", "query": "50 AV DES CHAMPS ELYSEES complement_adresse 75008 PARIS 8",
|
|
||||||
"type": "FeatureCollection", "features": [{"geometry": {"type": "Point", "coordinates":
|
|
||||||
[2.306888, 48.870374]}, "properties": {"citycode": "75108", "postcode": "75008",
|
|
||||||
"name": "50 Avenue des Champs \u00c9lys\u00e9es", "id": "ADRNIVX_0000000270748251",
|
|
||||||
"type": "housenumber", "context": "75, \u00cele-de-France", "score": 0.596517719568567,
|
|
||||||
"label": "50 Avenue des Champs \u00c9lys\u00e9es 75008 Paris", "city": "Paris",
|
|
||||||
"housenumber": "50", "street": "Avenue des Champs \u00c9lys\u00e9es"}, "type":
|
|
||||||
"Feature"}]}'
|
|
||||||
http_version:
|
|
||||||
recorded_at: Tue, 03 Jan 2017 13:00:55 GMT
|
|
||||||
recorded_with: VCR 3.0.3
|
|
51
spec/fixtures/cassettes/api_geo_departements.yml
vendored
51
spec/fixtures/cassettes/api_geo_departements.yml
vendored
|
@ -1,51 +0,0 @@
|
||||||
---
|
|
||||||
http_interactions:
|
|
||||||
- request:
|
|
||||||
method: get
|
|
||||||
uri: https://geo.api.gouv.fr/departements?fields=nom
|
|
||||||
body:
|
|
||||||
encoding: US-ASCII
|
|
||||||
string: ''
|
|
||||||
headers:
|
|
||||||
User-Agent:
|
|
||||||
- demarches-simplifiees.fr
|
|
||||||
Accept:
|
|
||||||
- application/json
|
|
||||||
Accept-Encoding:
|
|
||||||
- gzip, deflate
|
|
||||||
Expect:
|
|
||||||
- ''
|
|
||||||
response:
|
|
||||||
status:
|
|
||||||
code: 200
|
|
||||||
message: OK
|
|
||||||
headers:
|
|
||||||
Server:
|
|
||||||
- nginx/1.10.3 (Ubuntu)
|
|
||||||
Date:
|
|
||||||
- Tue, 23 Oct 2018 13:11:36 GMT
|
|
||||||
Content-Type:
|
|
||||||
- application/json; charset=utf-8
|
|
||||||
Transfer-Encoding:
|
|
||||||
- chunked
|
|
||||||
Connection:
|
|
||||||
- keep-alive
|
|
||||||
Vary:
|
|
||||||
- Accept-Encoding
|
|
||||||
X-Powered-By:
|
|
||||||
- Express
|
|
||||||
Access-Control-Allow-Origin:
|
|
||||||
- "*"
|
|
||||||
Etag:
|
|
||||||
- W/"cc1-jlb3C7xpXUEaq56Wojrp9rAkoH8"
|
|
||||||
Strict-Transport-Security:
|
|
||||||
- max-age=15552000
|
|
||||||
Content-Encoding:
|
|
||||||
- gzip
|
|
||||||
body:
|
|
||||||
encoding: ASCII-8BIT
|
|
||||||
string: !binary |-
|
|
||||||
W3sibm9tIjoiQWluIiwiY29kZSI6IjAxIn0seyJub20iOiJBaXNuZSIsImNvZGUiOiIwMiJ9LHsibm9tIjoiQWxsaWVyIiwiY29kZSI6IjAzIn0seyJub20iOiJBbHBlcy1kZS1IYXV0ZS1Qcm92ZW5jZSIsImNvZGUiOiIwNCJ9LHsibm9tIjoiSGF1dGVzLUFscGVzIiwiY29kZSI6IjA1In0seyJub20iOiJBbHBlcy1NYXJpdGltZXMiLCJjb2RlIjoiMDYifSx7Im5vbSI6IkFyZMOoY2hlIiwiY29kZSI6IjA3In0seyJub20iOiJBcmRlbm5lcyIsImNvZGUiOiIwOCJ9LHsibm9tIjoiQXJpw6hnZSIsImNvZGUiOiIwOSJ9LHsibm9tIjoiQXViZSIsImNvZGUiOiIxMCJ9LHsibm9tIjoiQXVkZSIsImNvZGUiOiIxMSJ9LHsibm9tIjoiQXZleXJvbiIsImNvZGUiOiIxMiJ9LHsibm9tIjoiQm91Y2hlcy1kdS1SaMO0bmUiLCJjb2RlIjoiMTMifSx7Im5vbSI6IkNhbHZhZG9zIiwiY29kZSI6IjE0In0seyJub20iOiJDYW50YWwiLCJjb2RlIjoiMTUifSx7Im5vbSI6IkNoYXJlbnRlIiwiY29kZSI6IjE2In0seyJub20iOiJDaGFyZW50ZS1NYXJpdGltZSIsImNvZGUiOiIxNyJ9LHsibm9tIjoiQ2hlciIsImNvZGUiOiIxOCJ9LHsibm9tIjoiQ29ycsOoemUiLCJjb2RlIjoiMTkifSx7Im5vbSI6IkPDtHRlLWQnT3IiLCJjb2RlIjoiMjEifSx7Im5vbSI6IkPDtHRlcy1kJ0FybW9yIiwiY29kZSI6IjIyIn0seyJub20iOiJDcmV1c2UiLCJjb2RlIjoiMjMifSx7Im5vbSI6IkRvcmRvZ25lIiwiY29kZSI6IjI0In0seyJub20iOiJEb3VicyIsImNvZGUiOiIyNSJ9LHsibm9tIjoiRHLDtG1lIiwiY29kZSI6IjI2In0seyJub20iOiJFdXJlIiwiY29kZSI6IjI3In0seyJub20iOiJFdXJlLWV0LUxvaXIiLCJjb2RlIjoiMjgifSx7Im5vbSI6IkZpbmlzdMOocmUiLCJjb2RlIjoiMjkifSx7Im5vbSI6IkNvcnNlLWR1LVN1ZCIsImNvZGUiOiIyQSJ9LHsibm9tIjoiSGF1dGUtQ29yc2UiLCJjb2RlIjoiMkIifSx7Im5vbSI6IkdhcmQiLCJjb2RlIjoiMzAifSx7Im5vbSI6IkhhdXRlLUdhcm9ubmUiLCJjb2RlIjoiMzEifSx7Im5vbSI6IkdlcnMiLCJjb2RlIjoiMzIifSx7Im5vbSI6Ikdpcm9uZGUiLCJjb2RlIjoiMzMifSx7Im5vbSI6IkjDqXJhdWx0IiwiY29kZSI6IjM0In0seyJub20iOiJJbGxlLWV0LVZpbGFpbmUiLCJjb2RlIjoiMzUifSx7Im5vbSI6IkluZHJlIiwiY29kZSI6IjM2In0seyJub20iOiJJbmRyZS1ldC1Mb2lyZSIsImNvZGUiOiIzNyJ9LHsibm9tIjoiSXPDqHJlIiwiY29kZSI6IjM4In0seyJub20iOiJKdXJhIiwiY29kZSI6IjM5In0seyJub20iOiJMYW5kZXMiLCJjb2RlIjoiNDAifSx7Im5vbSI6IkxvaXItZXQtQ2hlciIsImNvZGUiOiI0MSJ9LHsibm9tIjoiTG9pcmUiLCJjb2RlIjoiNDIifSx7Im5vbSI6IkhhdXRlLUxvaXJlIiwiY29kZSI6IjQzIn0seyJub20iOiJMb2lyZS1BdGxhbnRpcXVlIiwiY29kZSI6IjQ0In0seyJub20iOiJMb2lyZXQiLCJjb2RlIjoiNDUifSx7Im5vbSI6IkxvdCIsImNvZGUiOiI0NiJ9LHsibm9tIjoiTG90LWV0LUdhcm9ubmUiLCJjb2RlIjoiNDcifSx7Im5vbSI6IkxvesOocmUiLCJjb2RlIjoiNDgifSx7Im5vbSI6Ik1haW5lLWV0LUxvaXJlIiwiY29kZSI6IjQ5In0seyJub20iOiJNYW5jaGUiLCJjb2RlIjoiNTAifSx7Im5vbSI6Ik1hcm5lIiwiY29kZSI6IjUxIn0seyJub20iOiJIYXV0ZS1NYXJuZSIsImNvZGUiOiI1MiJ9LHsibm9tIjoiTWF5ZW5uZSIsImNvZGUiOiI1MyJ9LHsibm9tIjoiTWV1cnRoZS1ldC1Nb3NlbGxlIiwiY29kZSI6IjU0In0seyJub20iOiJNZXVzZSIsImNvZGUiOiI1NSJ9LHsibm9tIjoiTW9yYmloYW4iLCJjb2RlIjoiNTYifSx7Im5vbSI6Ik1vc2VsbGUiLCJjb2RlIjoiNTcifSx7Im5vbSI6Ik5pw6h2cmUiLCJjb2RlIjoiNTgifSx7Im5vbSI6Ik5vcmQiLCJjb2RlIjoiNTkifSx7Im5vbSI6Ik9pc2UiLCJjb2RlIjoiNjAifSx7Im5vbSI6Ik9ybmUiLCJjb2RlIjoiNjEifSx7Im5vbSI6IlBhcy1kZS1DYWxhaXMiLCJjb2RlIjoiNjIifSx7Im5vbSI6IlB1eS1kZS1Ew7RtZSIsImNvZGUiOiI2MyJ9LHsibm9tIjoiUHlyw6luw6llcy1BdGxhbnRpcXVlcyIsImNvZGUiOiI2NCJ9LHsibm9tIjoiSGF1dGVzLVB5csOpbsOpZXMiLCJjb2RlIjoiNjUifSx7Im5vbSI6IlB5csOpbsOpZXMtT3JpZW50YWxlcyIsImNvZGUiOiI2NiJ9LHsibm9tIjoiQmFzLVJoaW4iLCJjb2RlIjoiNjcifSx7Im5vbSI6IkhhdXQtUmhpbiIsImNvZGUiOiI2OCJ9LHsibm9tIjoiUmjDtG5lIiwiY29kZSI6IjY5In0seyJub20iOiJIYXV0ZS1TYcO0bmUiLCJjb2RlIjoiNzAifSx7Im5vbSI6IlNhw7RuZS1ldC1Mb2lyZSIsImNvZGUiOiI3MSJ9LHsibm9tIjoiU2FydGhlIiwiY29kZSI6IjcyIn0seyJub20iOiJTYXZvaWUiLCJjb2RlIjoiNzMifSx7Im5vbSI6IkhhdXRlLVNhdm9pZSIsImNvZGUiOiI3NCJ9LHsibm9tIjoiUGFyaXMiLCJjb2RlIjoiNzUifSx7Im5vbSI6IlNlaW5lLU1hcml0aW1lIiwiY29kZSI6Ijc2In0seyJub20iOiJTZWluZS1ldC1NYXJuZSIsImNvZGUiOiI3NyJ9LHsibm9tIjoiWXZlbGluZXMiLCJjb2RlIjoiNzgifSx7Im5vbSI6IkRldXgtU8OodnJlcyIsImNvZGUiOiI3OSJ9LHsibm9tIjoiU29tbWUiLCJjb2RlIjoiODAifSx7Im5vbSI6IlRhcm4iLCJjb2RlIjoiODEifSx7Im5vbSI6IlRhcm4tZXQtR2Fyb25uZSIsImNvZGUiOiI4MiJ9LHsibm9tIjoiVmFyIiwiY29kZSI6IjgzIn0seyJub20iOiJWYXVjbHVzZSIsImNvZGUiOiI4NCJ9LHsibm9tIjoiVmVuZMOpZSIsImNvZGUiOiI4NSJ9LHsibm9tIjoiVmllbm5lIiwiY29kZSI6Ijg2In0seyJub20iOiJIYXV0ZS1WaWVubmUiLCJjb2RlIjoiODcifSx7Im5vbSI6IlZvc2dlcyIsImNvZGUiOiI4OCJ9LHsibm9tIjoiWW9ubmUiLCJjb2RlIjoiODkifSx7Im5vbSI6IlRlcnJpdG9pcmUgZGUgQmVsZm9ydCIsImNvZGUiOiI5MCJ9LHsibm9tIjoiRXNzb25uZSIsImNvZGUiOiI5MSJ9LHsibm9tIjoiSGF1dHMtZGUtU2VpbmUiLCJjb2RlIjoiOTIifSx7Im5vbSI6IlNlaW5lLVNhaW50LURlbmlzIiwiY29kZSI6IjkzIn0seyJub20iOiJWYWwtZGUtTWFybmUiLCJjb2RlIjoiOTQifSx7Im5vbSI6IlZhbC1kJ09pc2UiLCJjb2RlIjoiOTUifSx7Im5vbSI6Ikd1YWRlbG91cGUiLCJjb2RlIjoiOTcxIn0seyJub20iOiJNYXJ0aW5pcXVlIiwiY29kZSI6Ijk3MiJ9LHsibm9tIjoiR3V5YW5lIiwiY29kZSI6Ijk3MyJ9LHsibm9tIjoiTGEgUsOpdW5pb24iLCJjb2RlIjoiOTc0In0seyJub20iOiJNYXlvdHRlIiwiY29kZSI6Ijk3NiJ9XQ==
|
|
||||||
http_version:
|
|
||||||
recorded_at: Tue, 23 Oct 2018 13:11:36 GMT
|
|
||||||
recorded_with: VCR 4.0.0
|
|
51
spec/fixtures/cassettes/api_geo_regions.yml
vendored
51
spec/fixtures/cassettes/api_geo_regions.yml
vendored
|
@ -1,51 +0,0 @@
|
||||||
---
|
|
||||||
http_interactions:
|
|
||||||
- request:
|
|
||||||
method: get
|
|
||||||
uri: https://geo.api.gouv.fr/regions?fields=nom
|
|
||||||
body:
|
|
||||||
encoding: US-ASCII
|
|
||||||
string: ''
|
|
||||||
headers:
|
|
||||||
User-Agent:
|
|
||||||
- demarches-simplifiees.fr
|
|
||||||
Accept:
|
|
||||||
- application/json
|
|
||||||
Accept-Encoding:
|
|
||||||
- gzip, deflate
|
|
||||||
Expect:
|
|
||||||
- ''
|
|
||||||
response:
|
|
||||||
status:
|
|
||||||
code: 200
|
|
||||||
message: OK
|
|
||||||
headers:
|
|
||||||
Server:
|
|
||||||
- nginx/1.10.3 (Ubuntu)
|
|
||||||
Date:
|
|
||||||
- Tue, 23 Oct 2018 13:11:36 GMT
|
|
||||||
Content-Type:
|
|
||||||
- application/json; charset=utf-8
|
|
||||||
Transfer-Encoding:
|
|
||||||
- chunked
|
|
||||||
Connection:
|
|
||||||
- keep-alive
|
|
||||||
Vary:
|
|
||||||
- Accept-Encoding
|
|
||||||
X-Powered-By:
|
|
||||||
- Express
|
|
||||||
Access-Control-Allow-Origin:
|
|
||||||
- "*"
|
|
||||||
Etag:
|
|
||||||
- W/"28d-5OgIzgwL+0K2UaO0foKduqMMBrA"
|
|
||||||
Strict-Transport-Security:
|
|
||||||
- max-age=15552000
|
|
||||||
Content-Encoding:
|
|
||||||
- gzip
|
|
||||||
body:
|
|
||||||
encoding: ASCII-8BIT
|
|
||||||
string: !binary |-
|
|
||||||
W3sibm9tIjoiR3VhZGVsb3VwZSIsImNvZGUiOiIwMSJ9LHsibm9tIjoiTWFydGluaXF1ZSIsImNvZGUiOiIwMiJ9LHsibm9tIjoiR3V5YW5lIiwiY29kZSI6IjAzIn0seyJub20iOiJMYSBSw6l1bmlvbiIsImNvZGUiOiIwNCJ9LHsibm9tIjoiTWF5b3R0ZSIsImNvZGUiOiIwNiJ9LHsibm9tIjoiw45sZS1kZS1GcmFuY2UiLCJjb2RlIjoiMTEifSx7Im5vbSI6IkNlbnRyZS1WYWwgZGUgTG9pcmUiLCJjb2RlIjoiMjQifSx7Im5vbSI6IkJvdXJnb2duZS1GcmFuY2hlLUNvbXTDqSIsImNvZGUiOiIyNyJ9LHsibm9tIjoiTm9ybWFuZGllIiwiY29kZSI6IjI4In0seyJub20iOiJIYXV0cy1kZS1GcmFuY2UiLCJjb2RlIjoiMzIifSx7Im5vbSI6IkdyYW5kIEVzdCIsImNvZGUiOiI0NCJ9LHsibm9tIjoiUGF5cyBkZSBsYSBMb2lyZSIsImNvZGUiOiI1MiJ9LHsibm9tIjoiQnJldGFnbmUiLCJjb2RlIjoiNTMifSx7Im5vbSI6Ik5vdXZlbGxlLUFxdWl0YWluZSIsImNvZGUiOiI3NSJ9LHsibm9tIjoiT2NjaXRhbmllIiwiY29kZSI6Ijc2In0seyJub20iOiJBdXZlcmduZS1SaMO0bmUtQWxwZXMiLCJjb2RlIjoiODQifSx7Im5vbSI6IlByb3ZlbmNlLUFscGVzLUPDtHRlIGQnQXp1ciIsImNvZGUiOiI5MyJ9LHsibm9tIjoiQ29yc2UiLCJjb2RlIjoiOTQifV0=
|
|
||||||
http_version:
|
|
||||||
recorded_at: Tue, 23 Oct 2018 13:11:36 GMT
|
|
||||||
recorded_with: VCR 4.0.0
|
|
51
spec/fixtures/cassettes/api_geo_search_rpg.yml
vendored
51
spec/fixtures/cassettes/api_geo_search_rpg.yml
vendored
File diff suppressed because one or more lines are too long
|
@ -1,44 +0,0 @@
|
||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe ApiAdresse::AddressAdapter do
|
|
||||||
describe '#get_suggestions' do
|
|
||||||
let(:request) { 'Paris' }
|
|
||||||
let(:response) { File.open('spec/fixtures/files/api_adresse/search_results.json') }
|
|
||||||
let(:status) { 200 }
|
|
||||||
|
|
||||||
subject { described_class.new(request).get_suggestions }
|
|
||||||
|
|
||||||
before do
|
|
||||||
stub_request(:get, "https://api-adresse.data.gouv.fr/search?&q=#{request}&limit=5")
|
|
||||||
.to_return(status: status, body: response, headers: {})
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when address return a list of address' do
|
|
||||||
it { expect(subject.size).to eq 5 }
|
|
||||||
it { is_expected.to be_an_instance_of Array }
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when address return an empty list' do
|
|
||||||
let(:response) { File.open('spec/fixtures/files/api_adresse/search_no_results.json') }
|
|
||||||
|
|
||||||
it { expect(subject.size).to eq 0 }
|
|
||||||
it { is_expected.to be_an_instance_of Array }
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when BAN is unavailable' do
|
|
||||||
let(:status) { 503 }
|
|
||||||
let(:response) { '' }
|
|
||||||
|
|
||||||
it { expect(subject.size).to eq 0 }
|
|
||||||
it { is_expected.to be_an_instance_of Array }
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when request is empty' do
|
|
||||||
let(:response) { 'Missing query' }
|
|
||||||
let(:request) { '' }
|
|
||||||
|
|
||||||
it { expect(subject.size).to eq 0 }
|
|
||||||
it { is_expected.to be_an_instance_of Array }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,31 +0,0 @@
|
||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe ApiAdresse::PointAdapter do
|
|
||||||
let(:address) { '50 av des champs elysees' }
|
|
||||||
|
|
||||||
describe '.geocode', vcr: { cassette_name: 'api_adresse_octo' } do
|
|
||||||
it 'return a point' do
|
|
||||||
expect(described_class.new(address).geocode.class).to eq(RGeo::Cartesian::PointImpl)
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when RestClient::Exception' do
|
|
||||||
before do
|
|
||||||
allow(ApiAdresse::API).to receive(:call).and_raise(RestClient::Exception)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'return nil' do
|
|
||||||
expect(described_class.new(address).geocode).to be_nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when JSON::ParserError' do
|
|
||||||
before do
|
|
||||||
allow(JSON).to receive(:parse).and_raise(JSON::ParserError)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'return nil' do
|
|
||||||
expect(described_class.new(address).geocode).to be_nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,75 +0,0 @@
|
||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe ApiGeo::API do
|
|
||||||
describe '.regions', vcr: { cassette_name: 'api_geo_regions' } do
|
|
||||||
subject { described_class.regions }
|
|
||||||
|
|
||||||
it { expect(subject.size).to eq 18 }
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '.departements', vcr: { cassette_name: 'api_geo_departements' } do
|
|
||||||
subject { described_class.departements }
|
|
||||||
|
|
||||||
it { expect(subject.size).to eq 101 }
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '.pays' do
|
|
||||||
subject { described_class.pays }
|
|
||||||
let(:pays) {
|
|
||||||
JSON.parse(File.open('app/lib/api_geo/pays.json').read, symbolize_names: true)
|
|
||||||
}
|
|
||||||
|
|
||||||
it { is_expected.to eq pays }
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '.search_rpg', vcr: { cassette_name: 'api_geo_search_rpg' } do
|
|
||||||
let(:coordinates) do
|
|
||||||
[
|
|
||||||
[
|
|
||||||
2.3945903778076176,
|
|
||||||
46.53312237252731
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2.394933700561524,
|
|
||||||
46.532590956418076
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2.3948478698730473,
|
|
||||||
46.53170525134736
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2.393732070922852,
|
|
||||||
46.530760483351195
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2.3909854888916016,
|
|
||||||
46.5309376286023
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2.391414642333985,
|
|
||||||
46.531232869403546
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2.3913288116455083,
|
|
||||||
46.53253190986272
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2.39278793334961,
|
|
||||||
46.53329951007484
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2.3945903778076176,
|
|
||||||
46.53312237252731
|
|
||||||
]
|
|
||||||
]
|
|
||||||
end
|
|
||||||
|
|
||||||
let(:geo_json) {
|
|
||||||
GeojsonService.to_json_polygon_for_rpg(coordinates)
|
|
||||||
}
|
|
||||||
|
|
||||||
subject { described_class.search_rpg(geo_json) }
|
|
||||||
|
|
||||||
it { expect(subject[:features].size).to eq 3 }
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,62 +0,0 @@
|
||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe ApiGeo::RPGAdapter do
|
|
||||||
subject { described_class.new(coordinates).results }
|
|
||||||
|
|
||||||
let(:coordinates) do
|
|
||||||
[
|
|
||||||
[
|
|
||||||
2.3945903778076176,
|
|
||||||
46.53312237252731
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2.394933700561524,
|
|
||||||
46.532590956418076
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2.3948478698730473,
|
|
||||||
46.53170525134736
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2.393732070922852,
|
|
||||||
46.530760483351195
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2.3909854888916016,
|
|
||||||
46.5309376286023
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2.391414642333985,
|
|
||||||
46.531232869403546
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2.3913288116455083,
|
|
||||||
46.53253190986272
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2.39278793334961,
|
|
||||||
46.53329951007484
|
|
||||||
],
|
|
||||||
[
|
|
||||||
2.3945903778076176,
|
|
||||||
46.53312237252731
|
|
||||||
]
|
|
||||||
]
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'coordinates are filled', vcr: { cassette_name: 'api_geo_search_rpg' } do
|
|
||||||
describe 'Attribut filter' do
|
|
||||||
it { expect(subject.size).to eq(3) }
|
|
||||||
it do
|
|
||||||
expect(subject.first.keys).to eq([
|
|
||||||
:culture,
|
|
||||||
:code_culture,
|
|
||||||
:surface,
|
|
||||||
:bio,
|
|
||||||
:geometry,
|
|
||||||
:geo_reference_id
|
|
||||||
])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -46,6 +46,21 @@ describe Administrateur, type: :model do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#delete_and_transfer_services' do
|
||||||
|
let!(:administrateur) { create(:administrateur) }
|
||||||
|
let!(:autre_administrateur) { create(:administrateur) }
|
||||||
|
let!(:procedure) { create(:procedure, :with_service, administrateurs: [administrateur, autre_administrateur]) }
|
||||||
|
let(:service) { procedure.service }
|
||||||
|
|
||||||
|
it "delete and transfer services to other admin" do
|
||||||
|
service.update(administrateur: administrateur)
|
||||||
|
administrateur.delete_and_transfer_services
|
||||||
|
|
||||||
|
expect(Administrateur.find_by(id: administrateur.id)).to be_nil
|
||||||
|
expect(service.reload.administrateur).to eq(autre_administrateur)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# describe '#password_complexity' do
|
# describe '#password_complexity' do
|
||||||
# let(:email) { 'mail@beta.gouv.fr' }
|
# let(:email) { 'mail@beta.gouv.fr' }
|
||||||
# let(:passwords) { ['pass', '12pass23', 'démarches ', 'démarches-simple', 'démarches-simplifiées-pwd'] }
|
# let(:passwords) { ['pass', '12pass23', 'démarches ', 'démarches-simple', 'démarches-simplifiées-pwd'] }
|
||||||
|
|
|
@ -32,12 +32,6 @@ shared_examples 'champ_spec' do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '.departement', vcr: { cassette_name: 'api_geo_departements' } do
|
|
||||||
subject { Champs::DepartementChamp.departements }
|
|
||||||
|
|
||||||
it { expect(subject).to include '99 - Étranger' }
|
|
||||||
end
|
|
||||||
|
|
||||||
context "when type_champ=date" do
|
context "when type_champ=date" do
|
||||||
let(:type_de_champ) { create(:type_de_champ_date) }
|
let(:type_de_champ) { create(:type_de_champ_date) }
|
||||||
let(:champ) { type_de_champ.champ.create }
|
let(:champ) { type_de_champ.champ.create }
|
||||||
|
|
|
@ -1084,4 +1084,39 @@ describe Dossier do
|
||||||
expect { expired_brouillon.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
expect { expired_brouillon.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#geo_position' do
|
||||||
|
let(:lat) { "46.538192" }
|
||||||
|
let(:lon) { "2.428462" }
|
||||||
|
let(:zoom) { "13" }
|
||||||
|
|
||||||
|
let(:etablissement_geo_adresse_lat) { "40.7143528" }
|
||||||
|
let(:etablissement_geo_adresse_lon) { "-74.0059731" }
|
||||||
|
|
||||||
|
let(:result) { { lat: lat, lon: lon, zoom: zoom } }
|
||||||
|
let(:dossier) { create(:dossier) }
|
||||||
|
|
||||||
|
it 'should geolocate' do
|
||||||
|
expect(dossier.geo_position).to eq(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with etablissement' do
|
||||||
|
before do
|
||||||
|
Geocoder::Lookup::Test.add_stub(
|
||||||
|
dossier.etablissement.geo_adresse, [
|
||||||
|
{
|
||||||
|
'coordinates' => [etablissement_geo_adresse_lat.to_f, etablissement_geo_adresse_lon.to_f]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:dossier) { create(:dossier, :with_entreprise) }
|
||||||
|
let(:result) { { lat: etablissement_geo_adresse_lat, lon: etablissement_geo_adresse_lon, zoom: zoom } }
|
||||||
|
|
||||||
|
it 'should geolocate' do
|
||||||
|
expect(dossier.geo_position).to eq(result)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -424,9 +424,40 @@ describe Instructeur, type: :model do
|
||||||
it { expect(instructeur_a.procedures.all.to_ary).to eq([procedure_a]) }
|
it { expect(instructeur_a.procedures.all.to_ary).to eq([procedure_a]) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "#can_be_deleted?" do
|
||||||
|
subject { instructeur.can_be_deleted? }
|
||||||
|
|
||||||
|
context 'when the instructeur is an administrateur' do
|
||||||
|
let!(:administrateur) { create(:administrateur) }
|
||||||
|
let(:instructeur) { administrateur.instructeur }
|
||||||
|
|
||||||
|
it { is_expected.to be false }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when the instructeur's procedures have other instructeurs" do
|
||||||
|
let(:instructeur_not_admin) { create(:instructeur) }
|
||||||
|
let(:autre_instructeur) { create(:instructeur) }
|
||||||
|
|
||||||
|
it "can be deleted" do
|
||||||
|
assign(procedure, instructeur_assigne: instructeur_not_admin)
|
||||||
|
assign(procedure, instructeur_assigne: autre_instructeur)
|
||||||
|
expect(autre_instructeur.can_be_deleted?).to be_truthy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when the instructeur's procedures is the only one" do
|
||||||
|
let(:instructeur_not_admin) { create :instructeur }
|
||||||
|
let(:autre_procedure) { create :procedure }
|
||||||
|
it "can be deleted" do
|
||||||
|
assign(autre_procedure, instructeur_assigne: instructeur_not_admin)
|
||||||
|
expect(instructeur_not_admin.can_be_deleted?).to be_falsy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def assign(procedure_to_assign)
|
def assign(procedure_to_assign, instructeur_assigne: instructeur)
|
||||||
create :assign_to, instructeur: instructeur, procedure: procedure_to_assign, groupe_instructeur: procedure_to_assign.defaut_groupe_instructeur
|
create :assign_to, instructeur: instructeur_assigne, procedure: procedure_to_assign, groupe_instructeur: procedure_to_assign.defaut_groupe_instructeur
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,7 +8,7 @@ describe ProcedureOverview, type: :model do
|
||||||
before { Timecop.freeze(friday) }
|
before { Timecop.freeze(friday) }
|
||||||
after { Timecop.return }
|
after { Timecop.return }
|
||||||
|
|
||||||
let(:procedure_overview) { ProcedureOverview.new(procedure, monday) }
|
let(:procedure_overview) { ProcedureOverview.new(procedure, monday, [procedure.defaut_groupe_instructeur]) }
|
||||||
|
|
||||||
describe 'dossiers_en_instruction_count' do
|
describe 'dossiers_en_instruction_count' do
|
||||||
let!(:en_instruction_dossier) do
|
let!(:en_instruction_dossier) do
|
||||||
|
@ -56,6 +56,27 @@ describe ProcedureOverview, type: :model do
|
||||||
it { expect(procedure_overview.created_dossiers_count).to eq(1) }
|
it { expect(procedure_overview.created_dossiers_count).to eq(1) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'with a procedure routee' do
|
||||||
|
let!(:gi_2) { procedure.groupe_instructeurs.create(label: 'groupe instructeur 2') }
|
||||||
|
let!(:gi_3) { procedure.groupe_instructeurs.create(label: 'groupe instructeur 3') }
|
||||||
|
|
||||||
|
def create_dossier_in_group(g)
|
||||||
|
create(:dossier, procedure: procedure, created_at: monday, state: Dossier.states.fetch(:en_instruction), groupe_instructeur: g)
|
||||||
|
end
|
||||||
|
|
||||||
|
let!(:created_dossier_during_the_week_on_group_2) { create_dossier_in_group(gi_2) }
|
||||||
|
let!(:created_dossier_during_the_week_on_group_3_a) { create_dossier_in_group(gi_3) }
|
||||||
|
let!(:created_dossier_during_the_week_on_group_3_b) { create_dossier_in_group(gi_3) }
|
||||||
|
|
||||||
|
let(:procedure_overview_gi_2) { ProcedureOverview.new(procedure, monday, [gi_2]) }
|
||||||
|
let(:procedure_overview_gi_3) { ProcedureOverview.new(procedure, monday, [gi_3]) }
|
||||||
|
let(:procedure_overview_default) { ProcedureOverview.new(procedure, monday, [procedure.defaut_groupe_instructeur]) }
|
||||||
|
|
||||||
|
it { expect(procedure_overview_gi_2.created_dossiers_count).to eq(1) }
|
||||||
|
it { expect(procedure_overview_gi_3.created_dossiers_count).to eq(2) }
|
||||||
|
it { expect(procedure_overview_default.created_dossiers_count).to eq(0) }
|
||||||
|
end
|
||||||
|
|
||||||
describe 'had_some_activities?' do
|
describe 'had_some_activities?' do
|
||||||
subject { procedure_overview.had_some_activities? }
|
subject { procedure_overview.had_some_activities? }
|
||||||
|
|
||||||
|
|
|
@ -224,6 +224,24 @@ describe User, type: :model do
|
||||||
context 'when the user has no dossier in instruction' do
|
context 'when the user has no dossier in instruction' do
|
||||||
it { is_expected.to be true }
|
it { is_expected.to be true }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when the user is an administrateur' do
|
||||||
|
it 'cannot be deleted' do
|
||||||
|
administrateur = create(:administrateur)
|
||||||
|
user = administrateur.user
|
||||||
|
|
||||||
|
expect(user.can_be_deleted?).to be_falsy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the user is an instructeur' do
|
||||||
|
it 'cannot be deleted' do
|
||||||
|
instructeur = create(:instructeur)
|
||||||
|
user = instructeur.user
|
||||||
|
|
||||||
|
expect(user.can_be_deleted?).to be_falsy
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#delete_and_keep_track_dossiers' do
|
describe '#delete_and_keep_track_dossiers' do
|
||||||
|
@ -241,6 +259,7 @@ describe User, type: :model do
|
||||||
let!(:dossier_en_construction) { create(:dossier, :en_construction, user: user) }
|
let!(:dossier_en_construction) { create(:dossier, :en_construction, user: user) }
|
||||||
let!(:dossier_brouillon) { create(:dossier, user: user) }
|
let!(:dossier_brouillon) { create(:dossier, user: user) }
|
||||||
|
|
||||||
|
context 'without a hidden dossier' do
|
||||||
it "keep track of dossiers and delete user" do
|
it "keep track of dossiers and delete user" do
|
||||||
user.delete_and_keep_track_dossiers(administration)
|
user.delete_and_keep_track_dossiers(administration)
|
||||||
|
|
||||||
|
@ -249,5 +268,21 @@ describe User, type: :model do
|
||||||
expect(User.find_by(id: user.id)).to be_nil
|
expect(User.find_by(id: user.id)).to be_nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'with a hidden dossier' do
|
||||||
|
let!(:dossier_cache) do
|
||||||
|
create(:dossier, :en_construction, user: user)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "keep track of dossiers and delete user" do
|
||||||
|
dossier_cache.delete_and_keep_track(administration)
|
||||||
|
user.delete_and_keep_track_dossiers(administration)
|
||||||
|
|
||||||
|
expect(DeletedDossier.find_by(dossier_id: dossier_en_construction)).to be_present
|
||||||
|
expect(DeletedDossier.find_by(dossier_id: dossier_brouillon)).to be_present
|
||||||
|
expect(User.find_by(id: user.id)).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -69,6 +69,7 @@ describe ProcedureExportService do
|
||||||
"pays",
|
"pays",
|
||||||
"regions",
|
"regions",
|
||||||
"departements",
|
"departements",
|
||||||
|
"communes",
|
||||||
"engagement",
|
"engagement",
|
||||||
"dossier_link",
|
"dossier_link",
|
||||||
"piece_justificative",
|
"piece_justificative",
|
||||||
|
@ -142,6 +143,7 @@ describe ProcedureExportService do
|
||||||
"pays",
|
"pays",
|
||||||
"regions",
|
"regions",
|
||||||
"departements",
|
"departements",
|
||||||
|
"communes",
|
||||||
"engagement",
|
"engagement",
|
||||||
"dossier_link",
|
"dossier_link",
|
||||||
"piece_justificative",
|
"piece_justificative",
|
||||||
|
@ -220,6 +222,7 @@ describe ProcedureExportService do
|
||||||
"pays",
|
"pays",
|
||||||
"regions",
|
"regions",
|
||||||
"departements",
|
"departements",
|
||||||
|
"communes",
|
||||||
"engagement",
|
"engagement",
|
||||||
"dossier_link",
|
"dossier_link",
|
||||||
"piece_justificative",
|
"piece_justificative",
|
||||||
|
|
|
@ -152,6 +152,8 @@ RSpec.configure do |config|
|
||||||
ActionMailer::Base.deliveries.clear
|
ActionMailer::Base.deliveries.clear
|
||||||
|
|
||||||
ActiveStorage::Current.host = 'http://test.host'
|
ActiveStorage::Current.host = 'http://test.host'
|
||||||
|
|
||||||
|
Geocoder.configure(lookup: :test)
|
||||||
}
|
}
|
||||||
|
|
||||||
RSpec::Matchers.define :have_same_attributes_as do |expected, options|
|
RSpec::Matchers.define :have_same_attributes_as do |expected, options|
|
||||||
|
|
12
yarn.lock
12
yarn.lock
|
@ -1521,13 +1521,6 @@ atob@^2.1.1:
|
||||||
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
|
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
|
||||||
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
|
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
|
||||||
|
|
||||||
autocomplete.js@^0.37.0:
|
|
||||||
version "0.37.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/autocomplete.js/-/autocomplete.js-0.37.0.tgz#bcfbfd7bcabe90e90fad4c2b1aaa931379a10c38"
|
|
||||||
integrity sha512-MxYfNb89sl7IRhNdEJv6z8dSfA7lVeU7Dk6m/+/ih0/tPLsbxIM7uPVsnWEUh4j7dFqJktlM7hCeU7jmx6VC8A==
|
|
||||||
dependencies:
|
|
||||||
immediate "^3.2.3"
|
|
||||||
|
|
||||||
autoprefixer@^9.4.9:
|
autoprefixer@^9.4.9:
|
||||||
version "9.5.1"
|
version "9.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.5.1.tgz#243b1267b67e7e947f28919d786b50d3bb0fb357"
|
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.5.1.tgz#243b1267b67e7e947f28919d786b50d3bb0fb357"
|
||||||
|
@ -4362,11 +4355,6 @@ ignore@^4.0.6:
|
||||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
|
resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
|
||||||
integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==
|
integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==
|
||||||
|
|
||||||
immediate@^3.2.3:
|
|
||||||
version "3.2.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c"
|
|
||||||
integrity sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=
|
|
||||||
|
|
||||||
import-cwd@^2.0.0:
|
import-cwd@^2.0.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9"
|
resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9"
|
||||||
|
|
Loading…
Reference in a new issue