Merge branch 'dev'

This commit is contained in:
simon lehericey 2018-05-23 13:54:16 +02:00
commit a0d3f2c818
65 changed files with 808 additions and 190 deletions

View file

@ -79,6 +79,9 @@ Layout/EmptyLineBetweenDefs:
Layout/EmptyLines:
Enabled: true
Layout/EmptyLineAfterGuardClause:
Enabled: false
Layout/EmptyLinesAroundAccessModifier:
Enabled: true
@ -899,9 +902,6 @@ Style/EmptyElse:
Style/EmptyLambdaParameter:
Enabled: true
Style/EmptyLineAfterGuardClause:
Enabled: false
Style/EmptyLiteral:
Enabled: false
@ -995,7 +995,7 @@ Style/MethodCalledOnDoEndBlock:
Style/MethodDefParentheses:
Enabled: true
Style/MethodMissing:
Style/MethodMissingSuper:
Enabled: false
Style/MinMax:
@ -1004,6 +1004,9 @@ Style/MinMax:
Style/MissingElse:
Enabled: false
Style/MissingRespondToMissing:
Enabled: false
Style/MixinGrouping:
Enabled: false

View file

@ -95,7 +95,7 @@ GEM
sass-rails (~> 5.0)
selectize-rails (~> 0.6)
aes_key_wrap (1.0.1)
apipie-rails (0.5.7)
apipie-rails (0.5.8)
rails (>= 4.1)
arel (9.0.0)
ast (2.4.0)
@ -114,7 +114,7 @@ GEM
sass (>= 3.3.4)
bootstrap-wysihtml5-rails (0.3.3.8)
railties (>= 3.0)
brakeman (4.2.1)
brakeman (4.3.0)
browser (2.5.3)
builder (3.2.3)
byebug (10.0.2)
@ -178,9 +178,9 @@ GEM
diff-lcs (1.3)
domain_name (0.5.20170404)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.3.0)
dotenv-rails (2.3.0)
dotenv (= 2.3.0)
dotenv (2.4.0)
dotenv-rails (2.4.0)
dotenv (= 2.4.0)
railties (>= 3.2, < 6.0)
draper (3.0.1)
actionpack (~> 5.0)
@ -420,12 +420,10 @@ GEM
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
json (2.1.0)
json-jwt (1.9.2)
json-jwt (1.9.4)
activesupport
aes_key_wrap
bindata
securecompare
url_safe_base64
jsonapi-renderer (0.2.0)
jwt (1.5.6)
kaminari (1.1.1)
@ -486,7 +484,7 @@ GEM
mustermann (1.0.2)
nenv (0.3.0)
netrc (0.11.0)
nio4r (2.3.0)
nio4r (2.3.1)
nokogiri (1.8.2)
mini_portile2 (~> 2.3.0)
notiffany (0.1.1)
@ -508,7 +506,7 @@ GEM
oauth2 (~> 1.1)
omniauth (~> 1.2)
open4 (1.3.4)
openid_connect (1.1.5)
openid_connect (1.1.6)
activemodel
attr_required (>= 1.0.0)
json-jwt (>= 1.5.0)
@ -518,7 +516,7 @@ GEM
validate_email
validate_url
webfinger (>= 1.0.1)
openstack (3.3.17)
openstack (3.3.18)
json
orm_adapter (0.5.0)
parallel (1.12.1)
@ -540,12 +538,12 @@ GEM
byebug (~> 10.0)
pry (~> 0.10)
public_suffix (3.0.2)
rack (2.0.4)
rack (2.0.5)
rack-handlers (0.7.3)
rack
rack-mini-profiler (0.10.7)
rack-mini-profiler (1.0.0)
rack (>= 1.2.0)
rack-oauth2 (1.9.0)
rack-oauth2 (1.9.2)
activesupport
attr_required
httpclient
@ -641,7 +639,7 @@ GEM
rspec-support (3.7.1)
rspec_junit_formatter (0.3.0)
rspec-core (>= 2, < 4, != 2.12.0)
rubocop (0.55.0)
rubocop (0.56.0)
parallel (~> 1.10)
parser (>= 2.5)
powerpack (~> 0.1)
@ -674,14 +672,13 @@ GEM
scss_lint (0.57.0)
rake (>= 0.9, < 13)
sass (~> 3.5.5)
securecompare (1.0.0)
select2-rails (4.0.3)
thor (~> 0.14)
selectize-rails (0.12.4.1)
selenium-webdriver (3.8.0)
childprocess (~> 0.5)
rubyzip (~> 1.0)
sentry-raven (2.7.2)
sentry-raven (2.7.3)
faraday (>= 0.7.6, < 1.0)
sexp_processor (4.11.0)
shellany (0.0.1)
@ -695,8 +692,10 @@ GEM
rack (~> 2.0)
rack-protection (= 2.0.1)
tilt (~> 2.0)
skylight (1.6.1)
activesupport (>= 3.0.0)
skylight (2.0.1)
skylight-core (= 2.0.1)
skylight-core (2.0.1)
activesupport (>= 4.2.0)
smart_listing (1.2.2)
coffee-rails
jquery-rails
@ -743,12 +742,11 @@ GEM
unf (0.1.4)
unf_ext
unf_ext (0.0.7.5)
unicode-display_width (1.3.0)
unicode-display_width (1.3.2)
unicode_utils (1.4.0)
unicorn (5.4.0)
kgio (~> 2.6)
raindrops (~> 0.7)
url_safe_base64 (0.2.2)
validate_email (0.1.6)
activemodel (>= 3.0)
mail (>= 2.2.5)
@ -756,7 +754,7 @@ GEM
activemodel (>= 3.0.0)
addressable
vcr (4.0.0)
web-console (3.6.1)
web-console (3.6.2)
actionview (>= 5.0)
activemodel (>= 5.0)
bindex (>= 0.4.0)
@ -764,7 +762,7 @@ GEM
webfinger (1.1.0)
activesupport
httpclient (>= 2.4)
webmock (3.3.0)
webmock (3.4.1)
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff

View file

@ -19,17 +19,6 @@
margin-bottom: 2 * $default-padding;
}
.accompagnateur-header {
background-color: $light-grey;
padding-top: $default-padding;
margin-bottom: 3 * $default-spacer;
border-bottom: 1px solid $border-grey;
.container {
margin-bottom: -1px;
}
}
.mixed-buttons-bar {
flex-shrink: 0;

View file

@ -2,7 +2,7 @@
@import "fonts";
.new-header,
.accompagnateur-header,
.sub-header,
footer {
display: none;
}

View file

@ -0,0 +1,7 @@
@import "constants";
#services-index {
h1 {
margin-top: 2 * $default-padding;
}
}

View file

@ -0,0 +1,13 @@
@import "colors";
@import "constants";
.sub-header {
background-color: $light-grey;
padding-top: $default-padding;
margin-bottom: 3 * $default-spacer;
border-bottom: 1px solid $border-grey;
.container {
margin-bottom: -1px;
}
}

View file

@ -0,0 +1,9 @@
@import "constants";
.table-service {
.change {
text-align: center;
width: 200px;
padding-left: $default-padding;
}
}

View file

@ -63,11 +63,6 @@ class Admin::ProceduresController < AdminController
def hide
procedure = current_administrateur.procedures.find(params[:id])
procedure.hide!
# procedure should no longer be reachable so we delete its procedure_path
# that way it is also available for another procedure
# however, sometimes the path has already been deleted (ex: stolen by another procedure),
# so we're not certain the procedure has a procedure_path anymore
procedure.procedure_path.try(:destroy)
flash.notice = "Procédure supprimée, en cas d'erreur contactez nous : contact@demarches-simplifiees.fr"
redirect_to admin_procedures_draft_path
@ -232,15 +227,15 @@ class Admin::ProceduresController < AdminController
def path_list
json_path_list = ProcedurePath
.joins(', procedures')
.where("procedures.id = procedure_paths.procedure_id")
.where("procedures.archived_at" => nil)
.joins(:procedure)
.where(procedures: { archived_at: nil })
.where("path LIKE ?", "%#{params[:request]}%")
.order(:id)
.pluck(:path, :administrateur_id)
.map do |value|
.map do |path, administrateur_id|
{
label: value.first,
mine: value.second == current_administrateur.id
label: path,
mine: administrateur_id == current_administrateur.id
}
end.to_json

View file

@ -10,6 +10,7 @@ class ApplicationController < ActionController::Base
before_action :reject, if: -> { Flipflop.maintenance_mode? }
before_action :staging_authenticate
before_action :set_active_storage_host
def staging_authenticate
if StagingAuthService.enabled? && !authenticate_with_http_basic { |username, password| StagingAuthService.authenticate(username, password) }
@ -57,6 +58,10 @@ class ApplicationController < ActionController::Base
private
def set_active_storage_host
ActiveStorage::Current.host = request.base_url
end
def logged_users
@logged_users ||= [
current_user,

View file

@ -0,0 +1,92 @@
module NewAdministrateur
class ServicesController < AdministrateurController
def index
@services = services.ordered
@procedure = procedure
end
def new
@procedure = procedure
end
def create
new_service = Service.new(service_params)
new_service.administrateur = current_administrateur
if new_service.save
redirect_to services_path(procedure_id: params[:procedure_id]),
notice: "#{new_service.nom} créé"
else
flash[:alert] = new_service.errors.full_messages
render :new
end
end
def edit
@service = service
@procedure = procedure
end
def update
@service = service
if @service.update(service_params)
redirect_to services_path(procedure_id: params[:procedure_id]),
notice: "#{@service.nom} modifié"
else
flash[:alert] = @service.errors.full_messages
render :edit
end
end
def add_to_procedure
procedure = current_administrateur.procedures.find(procedure_params[:id])
service = services.find(procedure_params[:service_id])
procedure.update(service: service)
redirect_to admin_procedure_path(procedure.id),
notice: "service affecté : #{procedure.service.nom}"
end
def destroy
service_to_destroy = service
if service_to_destroy.procedures.present?
if service_to_destroy.procedures.count == 1
message = "la procédure #{service_to_destroy.procedures.first.libelle} utilise encore le service #{service_to_destroy.nom}. Veuillez l'affecter à un autre service avant de pouvoir le supprimer"
else
message = "les procédures #{service_to_destroy.procedures.map(&:libelle).join(', ')} utilisent encore le service #{service.nom}. Veuillez les affecter à un autre service avant de pouvoir le supprimer"
end
flash[:alert] = message
redirect_to services_path(procedure_id: params[:procedure_id])
else
service_to_destroy.destroy
redirect_to services_path(procedure_id: params[:procedure_id]),
notice: "#{service_to_destroy.nom} est supprimé"
end
end
private
def service_params
params.require(:service).permit(:nom, :organisme, :type_organisme, :email, :telephone, :horaires, :adresse)
end
def service
services.find(params[:id])
end
def services
current_administrateur.services
end
def procedure_params
params.require(:procedure).permit(:id, :service_id)
end
def procedure
current_administrateur.procedures.find(params[:procedure_id])
end
end
end

View file

@ -41,28 +41,34 @@ class Users::DossiersController < UsersController
array: true
end
def commencer_test
procedure_path = ProcedurePath.find_by(path: params[:procedure_path])
procedure = procedure_path.test_procedure
if procedure.present?
redirect_to new_users_dossier_path(procedure_id: procedure.id)
else
flash.alert = "Procédure inconnue"
redirect_to root_path
end
end
def commencer
if params[:procedure_path].present?
procedure_path = ProcedurePath.where(path: params[:procedure_path]).last
procedure_path = ProcedurePath.find_by(path: params[:procedure_path])
procedure = procedure_path.procedure
if procedure_path.nil? || procedure_path.procedure.nil?
flash.alert = "Procédure inconnue"
return redirect_to root_path
if procedure.present?
if procedure.archivee?
@dossier = Dossier.new(procedure: procedure)
render 'commencer/archived'
else
procedure = procedure_path.procedure
redirect_to new_users_dossier_path(procedure_id: procedure.id)
end
else
flash.alert = "Procédure inconnue"
redirect_to root_path
end
if procedure.archivee?
@dossier = Dossier.new(procedure: procedure)
return render 'commencer/archived'
end
redirect_to new_users_dossier_path(procedure_id: procedure.id)
rescue ActiveRecord::RecordNotFound
error_procedure
end
def new

View file

@ -12,7 +12,6 @@ class ProcedureDashboard < Administrate::BaseDashboard
types_de_champ: TypesDeChampCollectionField,
path: ProcedureLinkField,
dossiers: Field::HasMany,
procedure_path: Field::HasOne,
administrateur: Field::BelongsTo,
id: Field::Number,
libelle: Field::String,

View file

@ -2,25 +2,19 @@ module Carto
module GeoAPI
class Driver
def self.regions
call regions_url
url = [API_GEO_URL, "regions"].join("/")
call(url)
end
def self.departements
call departements_url
url = [API_GEO_URL, "departements"].join("/")
call(url)
end
def self.pays
File.open('app/lib/carto/geo_api/pays.json').read
end
def self.departements_url
'https://geo.api.gouv.fr/departements'
end
def self.regions_url
'https://geo.api.gouv.fr/regions'
end
private
def self.call(api_url)

View file

@ -3,13 +3,13 @@ class CARTO::SGMAP::API
end
def self.search_qp(geojson)
endpoint = "/quartiers-prioritaires/search"
call(base_url + endpoint, { geojson: geojson.to_s })
url = [API_CARTO_URL, "quartiers-prioritaires", "search"].join("/")
call(url, { geojson: geojson.to_s })
end
def self.search_cadastre(geojson)
endpoint = "/cadastre/geometrie"
call(base_url + endpoint, { geojson: geojson.to_s })
url = [API_CARTO_URL, "cadastre", "geometrie"].join("/")
call(url, { geojson: geojson.to_s })
end
private
@ -25,8 +25,4 @@ class CARTO::SGMAP::API
rescue RestClient::InternalServerError
raise RestClient::ResourceNotFound
end
def self.base_url
'https://apicarto.sgmap.fr'
end
end

View file

@ -9,6 +9,7 @@ class Administrateur < ApplicationRecord
has_many :procedures
has_many :administrateurs_procedures
has_many :admin_procedures, through: :administrateurs_procedures, source: :procedure
has_many :services
before_validation -> { sanitize_email(:email) }
before_save :ensure_api_token

View file

@ -4,13 +4,12 @@ class Procedure < ApplicationRecord
has_many :types_de_champ_private, -> { private_only }, class_name: 'TypeDeChamp', dependent: :destroy
has_many :dossiers
has_one :procedure_path, dependent: :destroy
has_one :module_api_carto, dependent: :destroy
has_one :attestation_template, dependent: :destroy
belongs_to :administrateur
belongs_to :parent_procedure, class_name: 'Procedure'
belongs_to :service
has_many :assign_to, dependent: :destroy
has_many :administrateurs_procedures
@ -45,7 +44,6 @@ class Procedure < ApplicationRecord
validates :libelle, presence: true, allow_blank: false, allow_nil: false
validates :description, presence: true, allow_blank: false, allow_nil: false
validates :organisation, presence: true, allow_blank: false, allow_nil: false
# Warning: dossier after_save build_default_champs must be removed
# to save a dossier created from this method
@ -61,10 +59,15 @@ class Procedure < ApplicationRecord
Dossier.new(procedure: self, champs: champs, champs_private: champs_private)
end
def procedure_path
ProcedurePath.find_with_procedure(self)
end
def hide!
now = DateTime.now
self.update(hidden_at: now, aasm_state: :hidden)
self.dossiers.update_all(hidden_at: now)
update(hidden_at: now, aasm_state: :hidden)
procedure_path&.hide!(self)
dossiers.update_all(hidden_at: now)
end
def path
@ -135,6 +138,16 @@ class Procedure < ApplicationRecord
procedure.logo_secure_token = nil
procedure.remote_logo_url = self.logo_url
if notice.attached?
response = Typhoeus.get(notice.service_url, timeout: 5)
if response.success?
procedure.notice.attach(
io: StringIO.new(response.body),
filename: notice.filename
)
end
end
procedure.administrateur = admin
procedure.initiated_mail = initiated_mail.try(:dup)
procedure.received_mail = received_mail.try(:dup)

View file

@ -3,6 +3,23 @@ class ProcedurePath < ApplicationRecord
validates :administrateur_id, presence: true, allow_blank: false, allow_nil: false
validates :procedure_id, presence: true, allow_blank: false, allow_nil: false
belongs_to :test_procedure, class_name: 'Procedure'
belongs_to :procedure
belongs_to :administrateur
def self.find_with_procedure(procedure)
where(procedure: procedure).or(where(test_procedure: procedure)).last
end
def hide!(procedure)
if self.procedure == procedure
update(procedure: nil)
end
if self.test_procedure == procedure
update(test_procedure: nil)
end
if procedure.nil? && test_procedure.nil?
destroy
end
end
end

27
app/models/service.rb Normal file
View file

@ -0,0 +1,27 @@
class Service < ApplicationRecord
has_many :procedures
belongs_to :administrateur
scope :ordered, -> { order(nom: :asc) }
enum type_organisme: {
administration_centrale: 'administration_centrale',
association: 'association',
commune: 'commune',
departement: 'departement',
etablissement_enseignement: 'etablissement_enseignement',
prefecture: 'prefecture',
region: 'region',
autre: 'autre'
}
validates :nom, presence: { message: 'doit être renseigné' }, allow_nil: false
validates :nom, uniqueness: { scope: :administrateur, message: 'existe déjà' }
validates :organisme, presence: { message: 'doit être renseigné' }, allow_nil: false
validates :type_organisme, presence: { message: 'doit être renseigné' }, allow_nil: false
validates :email, presence: { message: 'doit être renseigné' }, allow_nil: false
validates :telephone, presence: { message: 'doit être renseigné' }, allow_nil: false
validates :horaires, presence: { message: 'doivent être renseignés' }, allow_nil: false
validates :adresse, presence: { message: 'doit être renseignée' }, allow_nil: false
validates :administrateur, presence: { message: 'doit être renseigné' }, allow_nil: false
end

View file

@ -2,19 +2,24 @@
.alert.alert-info
Cette procédure est publiée, certains éléments de la description ne sont plus modifiables
- { libelle: 'Libellé*', description: 'Description*', organisation: 'Organisme*', direction: 'Direction', lien_site_web: 'Lien site internet', web_hook_url: 'Lien de rappel HTTP' }.each do |key, value|
- if key != :web_hook_url || Flipflop.web_hook?
.form-group
%h4
= value
- if key == :web_hook_url
%p
Un lien de rappel HTTP (aussi appelé webhook) est utilisé pour notifier un service tiers du changement de l'état dun dossier sur demarches-simplifiees.fr. À chaque changement détat d'un dossier, notre site va effectuer une requête sur le lien renseigné avec en paramètres : le nouvel état du dossier, lidentifiant de la procédure, l'identifiant dossier et la date du changement. Vous pourrez alors utiliser notre API pour récupérer les nouvelles informations du dossier concerné.
- if key == :description
= f.text_area key, rows: '6', placeholder: 'Description du projet', class: 'form-control'
.form-group
%h4 Libellé*
= f.text_field :libelle, class: 'form-control', placeholder: 'Libellé de la procédure'
- else
= f.text_field key, class: 'form-control', placeholder: value
.form-group
%h4 Description*
= f.text_area :description, rows: '6', placeholder: 'Description du projet', class: 'form-control'
.form-group
%h4 Lien site internet
= f.text_field :lien_site_web, class: 'form-control', placeholder: 'https://www.exemple.fr/'
- if Flipflop.web_hook?
.form-group
%h4 Lien de rappel HTTP
%p
Un lien de rappel HTTP (aussi appelé webhook) est utilisé pour notifier un service tiers du changement de l'état dun dossier sur demarches-simplifiees.fr. À chaque changement détat d'un dossier, notre site va effectuer une requête sur le lien renseigné avec en paramètres : le nouvel état du dossier, lidentifiant de la procédure, l'identifiant dossier et la date du changement. Vous pourrez alors utiliser notre API pour récupérer les nouvelles informations du dossier concerné.
= f.text_field :web_hook_url, class: 'form-control', placeholder: 'https://callback.exemple.fr/'
.form-group
%h4 Notice explicative de la procédure

View file

@ -1,9 +1,16 @@
- procedure = @facade.procedure
= render partial: 'admin/closed_mail_template_attestation_inconsistency_alert'
.row.white-back
#procedure_show
- if @facade.procedure.brouillon?
- if @facade.procedure.gestionnaires.size == 0
%a.action_button.btn.btn-success#publish-procedure{ style: 'float: right; margin-top: 10px;', disabled: 'disabled', 'data-toggle' => :tooltip, title: 'Vous ne pouvez pas publier une procédure sans qu\'aucun accompagnateur ne soit affecté à celle-ci.' }
- if procedure.brouillon?
- if procedure.gestionnaires.empty? || procedure.service.nil?
- message = ''
- if procedure.gestionnaires.empty?
- message += 'Affectez des accompagnateurs à votre procédure.'
- if procedure.service.nil?
- message += 'Affectez un service à votre procédure.'
%a.action_button.btn.btn-success#publish-procedure{ style: 'float: right; margin-top: 10px;', disabled: 'disabled', 'data-toggle' => :tooltip, title: message }
%i.fa.fa-eraser
Publier
- else
@ -19,15 +26,15 @@
= render partial: '/admin/procedures/modal_transfer'
- if @facade.procedure.archivee?
- if procedure.archivee?
%a#reenable.btn.btn-small.btn-default.text-info{ "data-target" => "#publish-modal", "data-toggle" => "modal", :type => "button", style: 'float: right; margin-top: 10px;' }
%i.fa.fa-eraser
Réactiver
= render partial: '/admin/procedures/modal_publish'
- elsif @facade.procedure.publiee?
= form_tag admin_procedure_archive_path(procedure_id: @facade.procedure.id, archive: !@facade.procedure.archivee?), method: :put, style: 'float: right; margin-top: 10px;' do
- elsif procedure.publiee?
= form_tag admin_procedure_archive_path(procedure_id: procedure.id, archive: !procedure.archivee?), method: :put, style: 'float: right; margin-top: 10px;' do
%button#archive.btn.btn-small.btn-default.text-info{ type: :button }
%i.fa.fa-eraser
Archiver
@ -39,7 +46,7 @@
%i.fa.fa-remove
Annuler
- if @facade.procedure.locked?
- if procedure.locked?
#procedure_locked
.alert.alert-info
Cette procédure a été publiée, certains éléments ne peuvent plus être modifiés.
@ -47,8 +54,8 @@
%div
%h3 Lien procédure
%div{ style: 'margin-left: 3%;' }
- if @facade.procedure.publiee_ou_archivee?
= link_to @facade.procedure.lien, sanitize_url(@facade.procedure.lien), target: :blank
- if procedure.publiee_ou_archivee?
= link_to procedure.lien, sanitize_url(procedure.lien), target: :blank
- else
%b
Cette procédure n'a pas encore été publiée et n'est donc pas accessible par le public.
@ -59,34 +66,34 @@
.row{ style: 'margin-right: 3%; margin-left: 3%;' }
.description.col-xs-6.col-md-3.procedure-description
%h4.text-info
= @facade.procedure.libelle
= procedure.libelle
= h sanitize(@facade.procedure.description)
= h sanitize(procedure.description)
.champs.col-xs-6.col-md-3
%h4.text-info
Champs
.badge.progress-bar-info
= @facade.procedure.types_de_champ.size
= procedure.types_de_champ.size
%ul
- @facade.procedure.types_de_champ.order(:order_place).each do |champ|
- procedure.types_de_champ.order(:order_place).each do |champ|
%li= champ.libelle
.champs_private.col-xs-6.col-md-3
%h4.text-info
Annotations privées
.badge.progress-bar-info
= @facade.procedure.types_de_champ_private.size
= procedure.types_de_champ_private.size
%ul
- @facade.procedure.types_de_champ_private.order(:order_place).each do |champ|
- procedure.types_de_champ_private.order(:order_place).each do |champ|
%li= champ.libelle
.pieces-justificatives.col-xs-6.col-md-3
%h4.text-info
Pièces jointes
.badge.progress-bar-info
= @facade.procedure.types_de_piece_justificative.size
- @facade.procedure.types_de_piece_justificative.each do |piece_justificative|
= procedure.types_de_piece_justificative.size
- procedure.types_de_piece_justificative.each do |piece_justificative|
= piece_justificative.libelle
%br
%br
@ -123,19 +130,19 @@
- else
= pie_chart @facade.dossiers_for_pie_highchart
- if @facade.procedure.publiee_ou_archivee?
- if procedure.publiee_ou_archivee?
%h3 Supprimer la procédure
.alert.alert-danger
%p
Attention : la suppression d'une procédure est définitive.
- dossiers_count = @facade.procedure.dossiers.count
- dossiers_count = procedure.dossiers.count
- if dossiers_count > 0
%p
= pluralize(dossiers_count, "dossier est rattaché", "dossiers sont rattachés")
à cette procédure, la suppression de cette procédure entrainera également leur suppression.
%p.text-right
= link_to "J'ai compris, je supprime la procédure",
hide_admin_procedure_path(@facade.procedure),
hide_admin_procedure_path(procedure),
method: :post,
class: "btn btn-danger",
data: { confirm: "Voulez-vous supprimer la procédure ?", disable_with: "Suppression..." }

View file

@ -16,7 +16,7 @@ Vous pouvez me joindre au numéro suivant : 01 76 42 02 87.
%br
%br
Je vous invite également à consulter notre site de documentation qui regroupe l'ensemble des informations relatives à demarches-simplifiees.fr ainsi que des tutoriels dutilisation :
= link_to('https://demarches-simplifiees.gitbook.io/demarches-simplifiees/', 'https://demarches-simplifiees.gitbook.io/demarches-simplifiees/')
= link_to(DOC_URL, DOC_URL)
%br
%br
= render partial: "layouts/mailers/bizdev_signature"

View file

@ -10,7 +10,7 @@ Votre compte a été créé pour l'adresse email #{@gestionnaire.email}. Pour l
%br
%br
Par ailleurs, notre site de documentation qui regroupe l'ensemble des informations relatives à demarches-simplifiees.fr ainsi que des tutoriels dutilisation est à votre disposition : 
= link_to('https://demarches-simplifiees.gitbook.io/demarches-simplifiees/', 'https://demarches-simplifiees.gitbook.io/demarches-simplifiees/')
= link_to(DOC_URL, DOC_URL)
%br
%br
Bonne journée,

View file

@ -24,7 +24,7 @@
%li.footer-link
= link_to "CGU", CGU_URL, :class => "footer-link", :target => "_blank", rel: "noopener noreferrer"
%li.footer-link
= link_to "Mentions légales", "https://demarches-simplifiees.gitbook.io/demarches-simplifiees/cgu#4.-mentions-legales", :class => "footer-link", :target => "_blank", rel: "noopener noreferrer"
= link_to "Mentions légales", MENTIONS_LEGALES_URL, :class => "footer-link", :target => "_blank", rel: "noopener noreferrer"
%li.footer-column
%ul.footer-links
@ -33,10 +33,10 @@
"mailto:#{t('dynamics.contact_email')}",
:class => "footer-link"
%li.footer-link
= link_to "Documentation", "https://demarches-simplifiees.gitbook.io/demarches-simplifiees/", :class => "footer-link", :target => "_blank", rel: "noopener noreferrer"
= link_to "Documentation", DOC_URL, :class => "footer-link", :target => "_blank", rel: "noopener noreferrer"
%li.footer-link
= link_to "Documentation de l'API", "/docs", :class => "footer-link", :target => "_blank", rel: "noopener noreferrer"
%li.footer-link
= link_to "FAQ", "http://demarches-simplifiees.helpscoutdocs.com/", :class => "footer-link", :target => "_blank", rel: "noopener noreferrer"
= link_to "FAQ", FAQ_URL, :class => "footer-link", :target => "_blank", rel: "noopener noreferrer"
%li.footer-link
= link_to "Accessibilité", accessibilite_index_path, :class => "footer-link"

View file

@ -10,38 +10,42 @@
#menu-block
.split-hr-left
#procedure-list
%a#onglet-infos{ :href => "#{url_for admin_procedure_path(@procedure)}" }
%a#onglet-infos{ href: url_for(admin_procedure_path(@procedure)) }
.procedure-list-element{ class: ('active' if active == 'Informations') }
Informations
%a#onglet-accompagnateurs{ :href => "#{url_for admin_procedure_accompagnateurs_path(@procedure)}" }
%a#onglet-services{ href: current_administrateur.services.present? ? url_for(services_path(procedure_id: @procedure.id)) : url_for(new_service_path(procedure_id: @procedure.id)) }
.procedure-list-element
Services
%a#onglet-accompagnateurs{ href: url_for(admin_procedure_accompagnateurs_path(@procedure)) }
.procedure-list-element{ class: ('active' if active == 'Accompagnateurs') }
= t('dynamics.admin.procedure.onglets.accompagnateurs')
%a#onglet-description{ :href => "#{url_for edit_admin_procedure_path(@procedure)}" }
%a#onglet-description{ href: url_for(edit_admin_procedure_path(@procedure)) }
.procedure-list-element{ class: ('active' if active == 'Description') }
Description
- if !@procedure.locked?
%a#onglet-champs{ :href => "#{url_for admin_procedure_types_de_champ_path(@procedure)}" }
%a#onglet-champs{ href: url_for(admin_procedure_types_de_champ_path(@procedure)) }
.procedure-list-element{ class: ('active' if active == 'Champs') }
Champs
- if !@procedure.locked?
%a#onglet-pieces{ :href => "#{url_for admin_procedure_pieces_justificatives_path(@procedure)}" }
%a#onglet-pieces{ href: url_for(admin_procedure_pieces_justificatives_path(@procedure)) }
.procedure-list-element{ class: ('active' if active == 'Pieces') }
Pièces jointes
- if !@procedure.locked?
%a#onglet-private-champs{ :href => "#{url_for admin_procedure_types_de_champ_private_path(@procedure)}" }
%a#onglet-private-champs{ href: url_for(admin_procedure_types_de_champ_private_path(@procedure)) }
.procedure-list-element{ class: ('active' if active == 'Annotations privées') }
Annotations privées
%a#onglet-inemailsfos{ :href => "#{url_for admin_procedure_mail_templates_path(@procedure)}" }
%a#onglet-inemailsfos{ href: url_for(admin_procedure_mail_templates_path(@procedure)) }
.procedure-list-element{ class: ('active' if active == 'E-mails') }
E-mails
%a#onglet-preview{ :href => "#{url_for admin_procedure_previsualisation_path(@procedure)}" }
%a#onglet-preview{ href: url_for(admin_procedure_previsualisation_path(@procedure)) }
.procedure-list-element{ class: ('active' if active == 'Prévisualisation') }
Prévisualisation

View file

@ -0,0 +1,5 @@
.sub-header
.container
%ul.breadcrumbs
- steps.each do |step|
%li= step

View file

@ -1,4 +1,4 @@
.dossiers-headers.accompagnateur-header
.dossiers-headers.sub-header
.container
%h1.page-title Prévisualisation de la procédure #{@dossier.procedure.libelle}

View file

@ -0,0 +1,43 @@
= form_for service, html: { class: 'form' } do |f|
= f.label :nom do
Nom
%span.mandatory *
= f.text_field :nom, placeholder: 'service jeunesse et prévention, direction des affaires maritimes', required: true
= f.label :organisme do
Organisme
%span.mandatory *
= f.text_field :organisme, placeholder: "mairie de Mours, préfecture de l'Oise, ministère de la Culture", required: true
= f.label :type_organisme do
Type dorganisme
%span.mandatory *
= f.select :type_organisme, Service.type_organismes.keys.map { |key| [ I18n.t("type_organisme.#{key}"), key] }
= f.label :email do
Courriel
%span.mandatory *
= f.email_field :email, placeholder: 'contact@mon-service.fr', required: true
= f.label :telephone do
Numéro de téléphone
%span.mandatory *
= f.telephone_field :telephone, placeholder: '04 12 24 42 37', required: true
= f.label :horaires do
Horaires
%span.mandatory *
= f.text_area :horaires, placeholder: "Du lundi au vendredi de 9 h 30 à 17 h 30\nLe samedi de 9 h 30 à 12 h", required: true
= f.label :adresse do
Adresse
%span.mandatory *
= f.text_area :adresse, placeholder: "20 avenue de Ségur\n75007 Paris", required: true
- if procedure_id.present?
= hidden_field_tag :procedure_id, procedure_id
.send-wrapper
= f.submit "Valider", class: 'button send'

View file

@ -0,0 +1,11 @@
= render partial: 'new_administrateur/breadcrumbs',
locals: { steps: [link_to('Procedures', admin_procedures_path),
link_to(@procedure.libelle, admin_procedure_path(@procedure)),
link_to('choix du service', services_path(procedure_id: @procedure.id)),
'modifier le service'] }
.container
%h1 Modifier le service
= render partial: 'form',
locals: { service: @service, procedure_id: @procedure.id }

View file

@ -0,0 +1,39 @@
= render partial: 'new_administrateur/breadcrumbs',
locals: { steps: [link_to('Procedures', admin_procedures_path),
link_to(@procedure.libelle, admin_procedure_path(@procedure)),
'choix du service'] }
#services-index.container
%h1 Choix du service pour la procédure
= form_for @procedure, url: { controller: "new_administrateur/services", action: :add_to_procedure } , html: { class: 'form' } do |f|
= f.label :service_id, "La procédure #{@procedure.libelle} est affectée au service"
= f.select :service_id,
current_administrateur.services.map { |s| [ s.nom, s.id ] },
{ prompt: 'choisir un service', selected: @procedure.service&.id },
required: true
= f.hidden_field :id
= f.submit 'valider', class: 'button primary'
%h1 Liste des Services
%table.table.table-service.hoverable
%thead
%tr
%th
nom
%th.change
= link_to('Nouveau service', new_service_path(procedure_id: @procedure.id), class: 'button')
%tbody
- @services.each do |service|
%tr
%td
= service.nom
%td.change
= link_to('modifier', edit_service_path(service, procedure_id: @procedure.id))
= link_to 'supprimer',
service_path(service, procedure_id: @procedure.id),
method: :delete,
data: { confirm: "Confirmez vous la suppression de #{service.nom}" }

View file

@ -0,0 +1,11 @@
= render partial: 'new_administrateur/breadcrumbs',
locals: { steps: [link_to('Procedures', admin_procedures_path),
link_to(@procedure.libelle, admin_procedure_path(@procedure)),
link_to('choix du service', services_path(procedure_id: @procedure.id)),
'nouveau service'] }
.container
%h1 Nouveau Service
= render partial: 'form',
locals: { service: Service.new, procedure_id: @procedure.id }

View file

@ -1,4 +1,4 @@
.accompagnateur-header
.sub-header
.container
%ul.breadcrumbs
%li= link_to('Avis', gestionnaire_avis_index_path)

View file

@ -1,7 +1,7 @@
- avis_statut = (@statut == NewGestionnaire::AvisController::A_DONNER_STATUS) ? 'à donner' : 'rendus'
- content_for(:title, "Avis #{avis_statut}")
.accompagnateur-header
.sub-header
.container.flex
.width-100
%h1.tab-title Avis

View file

@ -1,4 +1,4 @@
.accompagnateur-header
.sub-header
.container
.flex.justify-between
%ul.breadcrumbs

View file

@ -1,7 +1,7 @@
- content_for(:title, "#{@procedure.libelle}")
#procedure-show
.accompagnateur-header
.sub-header
.container.flex
.procedure-logo{ style: @procedure.logo.present? ? "background-image: url(#{@procedure.logo.url})" : nil,

View file

@ -1,4 +1,4 @@
.dossiers-headers.accompagnateur-header
.dossiers-headers.sub-header
.container
%h1.page-title Les dossiers

View file

@ -51,7 +51,7 @@
class: "role-panel-button-primary"
= link_to "Voir les démarches disponibles",
"https://demarches-simplifiees.gitbook.io/demarches-simplifiees/listes-des-demarches",
LISTE_DES_DEMARCHES_URL,
target: "_blank",
rel: "noopener noreferrer",
class: "role-panel-button-secondary"
@ -74,7 +74,7 @@
onclick: "javascript: ga('send', 'pageview', '/demander-une-demo')"
= link_to "Voir la documentation",
"https://demarches-simplifiees.gitbook.io/demarches-simplifiees/",
DOC_URL,
target: "_blank",
rel: "noopener noreferrer",
class: "role-panel-button-secondary"

View file

@ -131,7 +131,7 @@
%td Table Data 3
%h1 Header
.accompagnateur-header
.sub-header
.container
Titre
%ul.tabs

3
bin/rspec Executable file
View file

@ -0,0 +1,3 @@
#!/usr/bin/env ruby
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
load Gem.bin_path('rspec-core', 'rspec')

View file

@ -1,10 +1,9 @@
#!/usr/bin/env ruby
require 'pathname'
require 'fileutils'
include FileUtils
# path to your application root.
APP_ROOT = Pathname.new File.expand_path('../', __dir__)
APP_ROOT = File.expand_path('..', __dir__)
def system!(*args)
system(*args) || abort("\n== Command #{args} failed ==")
@ -18,8 +17,11 @@ chdir APP_ROOT do
system! 'gem install bundler --conservative'
system('bundle check') || system!('bundle install')
# Install JavaScript dependencies if using Yarn
# system('bin/yarn')
# puts "\n== Copying sample files =="
# if !File.exist?('config/database.yml')
# unless File.exist?('config/database.yml')
# cp 'config/database.yml.sample', 'config/database.yml'
# end

View file

@ -1,10 +1,9 @@
#!/usr/bin/env ruby
require 'pathname'
require 'fileutils'
include FileUtils
# path to your application root.
APP_ROOT = Pathname.new File.expand_path('../', __dir__)
APP_ROOT = File.expand_path('..', __dir__)
def system!(*args)
system(*args) || abort("\n== Command #{args} failed ==")
@ -18,6 +17,9 @@ chdir APP_ROOT do
system! 'gem install bundler --conservative'
system('bundle check') || system!('bundle install')
# Install JavaScript dependencies if using Yarn
# system('bin/yarn')
puts "\n== Updating database =="
system! 'bin/rails db:migrate'

11
bin/yarn Executable file
View file

@ -0,0 +1,11 @@
#!/usr/bin/env ruby
APP_ROOT = File.expand_path('..', __dir__)
Dir.chdir(APP_ROOT) do
begin
exec "yarnpkg", *ARGV
rescue Errno::ENOENT
warn "Yarn executable was not detected in the system."
warn "Download Yarn at https://yarnpkg.com/en/docs/install"
exit 1
end
end

View file

@ -1 +0,0 @@
CGU_URL = "https://demarches-simplifiees.gitbook.io/demarches-simplifiees/cgu"

View file

@ -1,3 +1,14 @@
API_CARTO_URL = "https://apicarto.sgmap.fr"
API_ENTREPRISE_URL = 'https://entreprise.api.gouv.fr/v2'
API_GEO_URL = "https://geo.api.gouv.fr"
PIPEDRIVE_API_URL = 'https://api.pipedrive.com/v1'
DOC_URL = "https://doc.demarches-simplifiees.fr"
LISTE_DES_DEMARCHES_URL = [DOC_URL, "listes-des-demarches"].join("/")
CGU_URL = [DOC_URL, "cgu"].join("/")
MENTIONS_LEGALES_URL = [CGU_URL, "4-mentions-legales"].join("#")
FAQ_URL = "https://faq.demarches-simplifiees.fr"

View file

@ -0,0 +1,10 @@
# These translations are used in the manager interface, which is in English,
# so we use English translations
fr:
flipflop:
title: "%{application} features"
feature_states:
enabled: "On"
disabled: "Off"

View file

@ -0,0 +1,10 @@
fr:
type_organisme:
administration_centrale: 'administration centrale'
association: 'association'
commune: 'commune'
departement: 'département'
etablissement_enseignement: 'établissement denseignement'
prefecture: 'préfecture'
region: 'région'
autre: 'autre'

View file

@ -211,6 +211,7 @@ Rails.application.routes.draw do
end
namespace :commencer do
get '/test/:procedure_path' => '/users/dossiers#commencer_test', as: :test
get '/:procedure_path' => '/users/dossiers#commencer'
end
@ -286,6 +287,12 @@ Rails.application.routes.draw do
get 'apercu'
end
end
resources :services, except: [:show] do
collection do
patch 'add_to_procedure'
end
end
end
apipie

View file

@ -0,0 +1,10 @@
class CreateServices < ActiveRecord::Migration[5.2]
def change
create_table :services do |t|
t.string :type_organisme, null: false
t.string :nom, null: false
t.timestamps
end
end
end

View file

@ -0,0 +1,5 @@
class AddServiceToProcedures < ActiveRecord::Migration[5.2]
def change
add_reference :procedures, :service, foreign_key: true
end
end

View file

@ -0,0 +1,5 @@
class AddAdministrateurToServices < ActiveRecord::Migration[5.2]
def change
add_reference :services, :administrateur, foreign_key: true
end
end

View file

@ -0,0 +1,5 @@
class AddUniqueIndexToServices < ActiveRecord::Migration[5.2]
def change
add_index :services, [:administrateur_id, :nom], unique: true
end
end

View file

@ -0,0 +1,9 @@
class AddColumnsToService < ActiveRecord::Migration[5.2]
def change
add_column :services, :organisme, :string
add_column :services, :email, :string
add_column :services, :telephone, :string
add_column :services, :horaires, :text
add_column :services, :adresse, :text
end
end

View file

@ -0,0 +1,5 @@
class AllowProcedureOrganismeToBeNull < ActiveRecord::Migration[5.2]
def change
change_column_null :procedures, :organisation, true
end
end

View file

@ -0,0 +1,5 @@
class AddTestProcedureToProcedurePaths < ActiveRecord::Migration[5.2]
def change
add_reference :procedure_paths, :test_procedure
end
end

View file

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2018_05_15_135415) do
ActiveRecord::Schema.define(version: 2018_05_16_155238) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -425,7 +425,9 @@ ActiveRecord::Schema.define(version: 2018_05_15_135415) do
t.integer "administrateur_id"
t.datetime "created_at"
t.datetime "updated_at"
t.bigint "test_procedure_id"
t.index ["path"], name: "index_procedure_paths_on_path"
t.index ["test_procedure_id"], name: "index_procedure_paths_on_test_procedure_id"
end
create_table "procedure_presentations", id: :serial, force: :cascade do |t|
@ -441,7 +443,7 @@ ActiveRecord::Schema.define(version: 2018_05_15_135415) do
create_table "procedures", id: :serial, force: :cascade do |t|
t.string "libelle"
t.string "description"
t.string "organisation", null: false
t.string "organisation"
t.string "direction"
t.string "lien_demarche"
t.datetime "created_at", null: false
@ -466,8 +468,10 @@ ActiveRecord::Schema.define(version: 2018_05_15_135415) do
t.bigint "parent_procedure_id"
t.datetime "test_started_at"
t.string "aasm_state", default: "brouillon"
t.bigint "service_id"
t.index ["hidden_at"], name: "index_procedures_on_hidden_at"
t.index ["parent_procedure_id"], name: "index_procedures_on_parent_procedure_id"
t.index ["service_id"], name: "index_procedures_on_service_id"
end
create_table "quartier_prioritaires", id: :serial, force: :cascade do |t|
@ -511,6 +515,21 @@ ActiveRecord::Schema.define(version: 2018_05_15_135415) do
t.index ["entreprise_id"], name: "index_rna_informations_on_entreprise_id"
end
create_table "services", force: :cascade do |t|
t.string "type_organisme", null: false
t.string "nom", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.bigint "administrateur_id"
t.string "organisme"
t.string "email"
t.string "telephone"
t.text "horaires"
t.text "adresse"
t.index ["administrateur_id", "nom"], name: "index_services_on_administrateur_id_and_nom", unique: true
t.index ["administrateur_id"], name: "index_services_on_administrateur_id"
end
create_table "types_de_champ", id: :serial, force: :cascade do |t|
t.string "libelle"
t.string "type_champ"
@ -576,8 +595,10 @@ ActiveRecord::Schema.define(version: 2018_05_15_135415) do
add_foreign_key "procedure_paths", "administrateurs"
add_foreign_key "procedure_paths", "procedures"
add_foreign_key "procedure_presentations", "assign_tos"
add_foreign_key "procedures", "services"
add_foreign_key "received_mails", "procedures"
add_foreign_key "refused_mails", "procedures"
add_foreign_key "services", "administrateurs"
add_foreign_key "without_continuation_mails", "procedures"
create_view "searches", sql_definition: <<-SQL

View file

@ -455,10 +455,15 @@ describe Admin::ProceduresController, type: :controller do
end
describe 'PUT #clone' do
let!(:procedure) { create(:procedure, administrateur: admin) }
let!(:procedure) { create(:procedure, :with_notice, administrateur: admin) }
let(:params) { { procedure_id: procedure.id } }
subject { put :clone, params: params }
before do
response = Typhoeus::Response.new(code: 200, body: 'Hello world')
Typhoeus.stub(/active_storage\/disk/).and_return(response)
end
it { expect { subject }.to change(Procedure, :count).by(1) }
context 'when admin is the owner of the procedure' do
@ -466,7 +471,8 @@ describe Admin::ProceduresController, type: :controller do
it 'creates a new procedure and redirect to it' do
expect(response).to redirect_to edit_admin_procedure_path(id: Procedure.last.id)
expect(Procedure.last.cloned_from_library).to be(false)
expect(Procedure.last.cloned_from_library).to be_falsey
expect(Procedure.last.notice.attached?).to be_truthy
expect(flash[:notice]).to have_content 'Procédure clonée'
end
@ -541,7 +547,7 @@ describe Admin::ProceduresController, type: :controller do
end
end
describe 'POST transfer' do
describe 'POST #transfer' do
let!(:procedure) { create :procedure, administrateur: admin }
subject { post :transfer, params: { email_admin: email_admin, procedure_id: procedure.id } }
@ -581,17 +587,17 @@ describe Admin::ProceduresController, type: :controller do
end
end
describe "POST hide" do
describe "POST #hide" do
subject { post :hide, params: { id: procedure.id } }
context "when procedure is not owned by administrateur" do
let!(:procedure) { create :procedure, administrateur: create(:administrateur) }
let(:procedure) { create :procedure, administrateur: create(:administrateur) }
it { expect{ subject }.to raise_error(ActiveRecord::RecordNotFound) }
end
context "when procedure is owned by administrateur" do
let!(:procedure) { create :procedure, :published, administrateur: admin }
let(:procedure) { create :procedure, :published, administrateur: admin }
before do
subject
@ -599,11 +605,11 @@ describe Admin::ProceduresController, type: :controller do
end
it { expect(procedure.hidden_at).not_to be_nil }
it { expect(procedure.procedure_path).to be_nil }
it { expect(procedure.procedure_path.procedure).to be_nil }
end
context "when procedure has no path" do
let!(:procedure) { create :procedure, administrateur: admin }
let(:procedure) { create :procedure, administrateur: admin }
it { expect{ subject }.not_to raise_error }
it do

View file

@ -186,7 +186,7 @@ describe API::V1::DossiersController do
describe 'first type de piece justificative' do
subject { super().first }
it { expect(subject.keys.include?(:id)).to be_truthy }
it { expect(subject.key?(:id)).to be_truthy }
it { expect(subject[:libelle]).to eq('RIB') }
it { expect(subject[:description]).to eq('Releve identité bancaire') }
end
@ -200,11 +200,11 @@ describe API::V1::DossiersController do
let(:field_list) { [:url, :created_at, :type_de_piece_justificative_id] }
subject { super()[:pieces_justificatives].first }
it { expect(subject.keys.include?(:content_url)).to be_truthy }
it { expect(subject.key?(:content_url)).to be_truthy }
it { expect(subject[:created_at]).not_to be_nil }
it { expect(subject[:type_de_piece_justificative_id]).not_to be_nil }
it { expect(subject.keys.include?(:user)).to be_truthy }
it { expect(subject.key?(:user)).to be_truthy }
describe 'user' do
subject { super()[:user] }
@ -222,8 +222,8 @@ describe API::V1::DossiersController do
describe 'first champs' do
subject { super().first }
it { expect(subject.keys.include?(:value)).to be_truthy }
it { expect(subject.keys.include?(:type_de_champ)).to be_truthy }
it { expect(subject.key?(:value)).to be_truthy }
it { expect(subject.key?(:type_de_champ)).to be_truthy }
describe 'type de champ' do
let(:field_list) {
@ -237,10 +237,10 @@ describe API::V1::DossiersController do
}
subject { super()[:type_de_champ] }
it { expect(subject.keys.include?(:id)).to be_truthy }
it { expect(subject.key?(:id)).to be_truthy }
it { expect(subject[:libelle]).to include('Libelle du champ') }
it { expect(subject[:description]).to include('description du champ') }
it { expect(subject.keys.include?(:order_place)).to be_truthy }
it { expect(subject.key?(:order_place)).to be_truthy }
it { expect(subject[:type_champ]).to eq('text') }
end
end
@ -295,8 +295,8 @@ describe API::V1::DossiersController do
describe 'first champs' do
subject { super().first }
it { expect(subject.keys.include?(:value)).to be_truthy }
it { expect(subject.keys.include?(:type_de_champ)).to be_truthy }
it { expect(subject.key?(:value)).to be_truthy }
it { expect(subject.key?(:type_de_champ)).to be_truthy }
describe 'type de champ' do
let(:field_list) {
@ -310,10 +310,10 @@ describe API::V1::DossiersController do
}
subject { super()[:type_de_champ] }
it { expect(subject.keys.include?(:id)).to be_truthy }
it { expect(subject.key?(:id)).to be_truthy }
it { expect(subject[:libelle]).to include('Libelle champ privé') }
it { expect(subject[:description]).to include('description du champ privé') }
it { expect(subject.keys.include?(:order_place)).to be_truthy }
it { expect(subject.key?(:order_place)).to be_truthy }
it { expect(subject[:type_champ]).to eq('text') }
end
end

View file

@ -0,0 +1,137 @@
describe NewAdministrateur::ServicesController, type: :controller do
let(:admin) { create(:administrateur) }
describe '#create' do
before do
sign_in admin
post :create, params: params
end
context 'when submitting a new service' do
let(:params) do
{
service: {
nom: 'super service',
organisme: 'organisme',
type_organisme: 'region',
email: 'email@toto.com',
telephone: '1234',
horaires: 'horaires',
adresse: 'adresse'
},
procedure_id: 12
}
end
it { expect(flash.alert).to be_nil }
it { expect(flash.notice).to eq('super service créé') }
it { expect(Service.last.nom).to eq('super service') }
it { expect(Service.last.organisme).to eq('organisme') }
it { expect(Service.last.type_organisme).to eq('region') }
it { expect(Service.last.email).to eq('email@toto.com') }
it { expect(Service.last.telephone).to eq('1234') }
it { expect(Service.last.horaires).to eq('horaires') }
it { expect(Service.last.adresse).to eq('adresse') }
it { expect(response).to redirect_to(services_path(procedure_id: 12)) }
end
context 'when submitting an invalid service' do
let(:params) { { service: { nom: 'super service' } } }
it { expect(flash.alert).not_to be_nil }
it { expect(response).to render_template(:new) }
end
end
describe '#update' do
let!(:service) { create(:service, administrateur: admin) }
let(:service_params) { { nom: 'nom', type_organisme: 'region' } }
before do
sign_in admin
params = {
id: service.id,
service: service_params,
procedure_id: 12
}
patch :update, params: params
end
context 'when updating a service' do
it { expect(flash.alert).to be_nil }
it { expect(flash.notice).to eq('nom modifié') }
it { expect(Service.last.nom).to eq('nom') }
it { expect(Service.last.type_organisme).to eq('region') }
it { expect(response).to redirect_to(services_path(procedure_id: 12)) }
end
context 'when updating a service with invalid data' do
let(:service_params) { { nom: '', type_organisme: 'region' } }
it { expect(flash.alert).not_to be_nil }
it { expect(response).to render_template(:edit) }
end
end
describe '#add_to_procedure' do
let!(:procedure) { create(:procedure, administrateur: admin) }
let!(:service) { create(:service, administrateur: admin) }
def post_add_to_procedure
sign_in admin
params = {
procedure: {
id: procedure.id,
service_id: service.id
}
}
patch :add_to_procedure, params: params
procedure.reload
end
context 'when adding a service to a procedure' do
before { post_add_to_procedure }
it { expect(flash.alert).to be_nil }
it { expect(flash.notice).to eq("service affecté : #{service.nom}") }
it { expect(procedure.service_id).to eq(service.id) }
it { expect(response).to redirect_to(admin_procedure_path(procedure.id)) }
end
context 'when stealing a service to add it to a procedure' do
let!(:service) { create(:service) }
it { expect { post_add_to_procedure }.to raise_error(ActiveRecord::RecordNotFound) }
end
end
describe '#destroy' do
let!(:service) { create(:service, administrateur: admin) }
context 'when a service has no related procedure' do
before do
sign_in admin
delete :destroy, params: { id: service.id, procedure_id: 12 }
end
it { expect{ service.reload }.to raise_error(ActiveRecord::RecordNotFound) }
it { expect(flash.alert).to be_nil }
it { expect(flash.notice).to eq("#{service.nom} est supprimé") }
it { expect(response).to redirect_to(services_path(procedure_id: 12)) }
end
context 'when a service still has some related procedures' do
let!(:procedure) { create(:procedure, service: service) }
before do
sign_in admin
delete :destroy, params: { id: service.id, procedure_id: 12 }
end
it { expect(service.reload).not_to be_nil }
it { expect(flash.alert).to eq("la procédure #{procedure.libelle} utilise encore le service service. Veuillez l'affecter à un autre service avant de pouvoir le supprimer") }
it { expect(flash.notice).to be_nil }
it { expect(response).to redirect_to(services_path(procedure_id: 12)) }
end
end
end

View file

@ -111,6 +111,15 @@ FactoryBot.define do
end
end
trait :with_notice do
after(:create) do |procedure, _evaluator|
procedure.notice.attach(
io: StringIO.new('Hello World'),
filename: 'hello.txt'
)
end
end
trait :with_all_champs_mandatory do
after(:build) do |procedure, _evaluator|
tdcs = []

12
spec/factories/service.rb Normal file
View file

@ -0,0 +1,12 @@
FactoryBot.define do
factory :service do
nom 'service'
organisme 'organisme'
type_organisme 'commune'
administrateur { create(:administrateur) }
email 'email@toto.com'
telephone '1234'
horaires 'de 9 h à 18 h'
adresse 'adresse'
end
end

View file

@ -14,7 +14,6 @@ feature 'As an administrateur I wanna clone a procedure', js: true do
page.find_by_id('from-scratch').click
fill_in 'procedure_libelle', with: 'libelle de la procedure'
page.execute_script("$('#procedure_description').val('description de la procedure')")
fill_in 'procedure_organisation', with: 'organisme de la procedure'
page.find_by_id('save-procedure').click
end

View file

@ -39,7 +39,6 @@ feature 'As an administrateur I wanna create a new procedure', js: true do
page.find_by_id('flash_message').visible?
fill_in 'procedure_libelle', with: 'libelle de la procedure'
page.execute_script("$('#procedure_description').val('description de la procedure')")
fill_in 'procedure_organisation', with: 'organisme de la procedure'
page.find_by_id('save-procedure').click
expect(page).to have_current_path(admin_procedure_types_de_champ_path(Procedure.first.id.to_s))
end
@ -51,8 +50,10 @@ feature 'As an administrateur I wanna create a new procedure', js: true do
page.find_by_id('from-scratch').click
fill_in 'procedure_libelle', with: 'libelle de la procedure'
page.execute_script("$('#procedure_description').val('description de la procedure')")
fill_in 'procedure_organisation', with: 'organisme de la procedure'
page.find_by_id('save-procedure').click
procedure = Procedure.last
procedure.update(service: create(:service))
end
scenario 'Add champ, add file, visualize them in procedure preview' do

View file

@ -18,16 +18,4 @@ describe Carto::GeoAPI::Driver do
it { is_expected.to eq File.open('app/lib/carto/geo_api/pays.json').read }
end
describe '.departements_url' do
subject { described_class.departements_url }
it { is_expected.to eq 'https://geo.api.gouv.fr/departements' }
end
describe '.regions_url' do
subject { described_class.regions_url }
it { is_expected.to eq 'https://geo.api.gouv.fr/regions' }
end
end

View file

@ -171,8 +171,6 @@ describe Procedure do
end
context 'organisation' do
it { is_expected.not_to allow_value(nil).for(:organisation) }
it { is_expected.not_to allow_value('').for(:organisation) }
it { is_expected.to allow_value('URRSAF').for(:organisation) }
end
end
@ -262,7 +260,8 @@ describe Procedure do
describe 'clone' do
let(:archived_at) { nil }
let(:published_at) { nil }
let(:procedure) { create(:procedure, archived_at: archived_at, published_at: published_at, received_mail: received_mail) }
let!(:service) { create(:service) }
let(:procedure) { create(:procedure, archived_at: archived_at, published_at: published_at, received_mail: received_mail, service: service) }
let!(:type_de_champ_0) { create(:type_de_champ, procedure: procedure, order_place: 0) }
let!(:type_de_champ_1) { create(:type_de_champ, procedure: procedure, order_place: 1) }
let!(:type_de_champ_2) { create(:type_de_champ_drop_down_list, procedure: procedure, order_place: 2) }
@ -328,6 +327,10 @@ describe Procedure do
it { expect(subject.cloned_from_library).to be(true) }
end
it 'should keep service_id' do
expect(subject.service).to eq(service)
end
it 'should duplicate existing mail_templates' do
expect(subject.received_mail.attributes.except("id", "procedure_id", "created_at", "updated_at")).to eq procedure.received_mail.attributes.except("id", "procedure_id", "created_at", "updated_at")
expect(subject.received_mail.id).not_to eq procedure.received_mail.id

View file

@ -0,0 +1,51 @@
describe Service, type: :model do
describe 'validation' do
let(:administrateur) { create(:administrateur) }
let(:params) do
{
nom: 'service des jardins',
organisme: 'mairie des iles',
type_organisme: 'commune',
email: 'super@email.com',
telephone: '1212202',
horaires: 'du lundi au vendredi',
adresse: '12 rue des schtroumpfs',
administrateur_id: administrateur.id
}
end
it { expect(Service.new(params).valid?).to be_truthy }
context 'when a first service exists' do
before { Service.create(params) }
context 'checks uniqueness of administrateur, name couple' do
it { expect(Service.create(params).valid?).to be_falsey }
end
end
context 'of type_organisme' do
it 'should be set' do
expect(Service.new(params.except(:type_organisme)).valid?).to be_falsey
end
end
context 'of nom' do
it 'should be set' do
expect(Service.new(params.except(:nom)).valid?).to be_falsey
end
end
context 'of administrateur' do
it 'should be set' do
expect(Service.new(params.except(:administrateur_id)).valid?).to be_falsey
end
end
context 'of type_organisme' do
it 'should belong to the enum' do
expect{ Service.new(params.merge(type_organisme: 'choucroute')) }.to raise_error(ArgumentError)
end
end
end
end

View file

@ -64,6 +64,7 @@ VCR.configure do |c|
c.hook_into :webmock
c.cassette_library_dir = 'spec/fixtures/cassettes'
c.configure_rspec_metadata!
c.ignore_hosts 'test.host'
end
DatabaseCleaner.strategy = :transaction
@ -119,6 +120,8 @@ RSpec.configure do |config|
config.before(:all) {
Warden.test_mode!
Typhoeus::Expectation.clear
if Flipflop.remote_storage?
VCR.use_cassette("ovh_storage_init") do
CarrierWave.configure do |config|