Merge branch 'staging'

This commit is contained in:
Xavier J 2016-06-29 13:33:21 +02:00
commit e82a2b82aa
135 changed files with 5086 additions and 499 deletions

View file

@ -22,6 +22,8 @@ gem 'jbuilder', '~> 2.0'
# bundle exec rake doc:rails generates the API under doc/api.
gem 'sdoc', '~> 0.4.0', group: :doc
# Enable deep clone of active record models
gem 'deep_cloneable', '~> 2.2.1'
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'

View file

@ -119,6 +119,8 @@ GEM
sprockets (>= 2.0.0)
database_cleaner (1.4.1)
debug_inspector (0.0.2)
deep_cloneable (2.2.1)
activerecord (>= 3.1.0, < 5.2.0)
devise (3.4.1)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
@ -634,6 +636,7 @@ DEPENDENCIES
coffee-rails (~> 4.1.0)
css_splitter
database_cleaner
deep_cloneable (~> 2.2.1)
devise
draper
factory_girl
@ -690,4 +693,4 @@ DEPENDENCIES
will_paginate-bootstrap
BUNDLED WITH
1.11.2
1.12.5

BIN
app/assets/images/edit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -0,0 +1,22 @@
function address_type_init() {
display = 'label';
var bloodhound = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace(display),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: '/ban/search?request=%QUERY',
wildcard: '%QUERY'
}
});
bloodhound.initialize();
$("input[type='address']").typeahead({
minLength: 1
}, {
display: display,
source: bloodhound,
limit: 5
});
}

View file

@ -29,8 +29,7 @@
//= require franceconnect
//= require bootstrap-wysihtml5
//= require bootstrap-wysihtml5/locales/fr-FR
//= require typeahead.bundle
$(document).on('page:load', scroll_to);
$(document).ready(scroll_to);

View file

@ -14,6 +14,17 @@ function initCarto() {
layers: [OSM]
});
icon = L.icon({
iconUrl: '/assets/marker-icon.png',
//shadowUrl: 'leaf-shadow.png',
iconSize: [34.48, 40], // size of the icon
//shadowSize: [50, 64], // size of the shadow
iconAnchor: [20, 20] // point of the icon which will correspond to marker's location
//shadowAnchor: [4, 62], // the same for the shadow
//popupAnchor: [-3, -76] // point from which the popup should open relative to the iconAnchor
});
if (qp_active())
display_qp(JSON.parse($("#quartier_prioritaires").val()));
@ -39,6 +50,7 @@ function initCarto() {
map.setView(new L.LatLng(position.lat, position.lon), position.zoom);
add_event_freeDraw();
add_event_search_address();
}
function default_gestionnaire_position() {
@ -81,22 +93,30 @@ function add_event_freeDraw() {
freeDraw.on('markers', function (e) {
$("#json_latlngs").val(JSON.stringify(e.latLngs));
add_event_edit();
get_external_data(e.latLngs);
});
$("#map").on('click', function(){
freeDraw.setMode(L.FreeDraw.MODES.VIEW);
});
$("#new").on('click', function (e) {
freeDraw.setMode(L.FreeDraw.MODES.CREATE);
});
$("#edit").on('click', function (e) {
freeDraw.setMode(L.FreeDraw.MODES.EDIT);
});
$("#delete").on('click', function (e) {
freeDraw.setMode(L.FreeDraw.MODES.DELETE);
});
}
function add_event_edit (){
$(".leaflet-container g path").on('click', function (e) {
setTimeout(function(){freeDraw.setMode(L.FreeDraw.MODES.EDIT | L.FreeDraw.MODES.DELETE)}, 50);
});
}
function get_position() {
var position;
@ -111,8 +131,32 @@ function get_position() {
return position;
}
function get_address_point(request) {
$.ajax({
url: '/ban/address_point?request=' + request,
dataType: 'json',
async: true
}).done(function (data) {
if (data.lat != null) {
map.setView(new L.LatLng(data.lat, data.lon), data.zoom);
//L.marker([data.lat, data.lon], {icon: icon}).addTo(map);
}
});
}
function jsObject_to_array(qp_list) {
return Object.keys(qp_list).map(function (v) {
return qp_list[v];
});
}
function add_event_search_address() {
$("#search_by_address input[type='address']").bind('typeahead:select', function (ev, seggestion) {
get_address_point(seggestion['label']);
});
$("#search_by_address input[type='address']").keypress(function (e) {
if (e.which == 13)
get_address_point($(this).val());
});
}

View file

@ -0,0 +1,47 @@
$(document).on('page:load', action_type_de_champs);
$(document).ready(action_type_de_champs);
function action_type_de_champs() {
$("input[type='email']").on('change', function () {
toggleErrorClass(this, validateEmail($(this).val()));
});
$("input[type='phone']").on('change', function () {
val = $(this).val();
val = val.replace(/[ ]/g, '');
toggleErrorClass(this, validatePhone(val));
});
$("#liste_champs input").on('focus', function (){
$("#description_"+this.id).slideDown();
});
$("#liste_champs input").on('blur', function (){
$("#description_"+this.id).slideUp();
});
address_type_init();
}
function toggleErrorClass(node, boolean) {
if (boolean)
$(node).removeClass('input-error');
else
$(node).addClass('input-error');
}
function validatePhone(phone) {
var re = /^(0|(\+[1-9]{2})|(00[1-9]{2}))[1-9][0-9]{8}$/;
return validateInput(phone, re)
}
function validateEmail(email) {
var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return validateInput(email, re)
}
function validateInput(input, regex) {
return regex.test(input);
}

View file

@ -0,0 +1,34 @@
$(document).on('page:load', the_terms);
$(document).ready(the_terms);
function the_terms() {
var the_terms = $("#dossier_autorisation_donnees");
if(the_terms.size() == 0)
return;
check_value (the_terms);
the_terms.click(function () {
check_value (the_terms);
});
function check_value (the_terms){
if (the_terms.is(":checked")) {
$("#etape_suivante").removeAttr("disabled");
} else {
$("#etape_suivante").attr("disabled", "disabled");
}
}
}
function error_form_siret(invalid_siret){
$("input[type='submit']").removeClass('btn-success').addClass('btn-danger').val('Erreur SIRET');
$("#dossier_siret").addClass('input-error').val(invalid_siret).on('input', reset_form_siret);
}
function reset_form_siret(){
$("input[type='submit']").removeClass('btn-danger').addClass('btn-success').val('Valider');
$("#dossier_siret").removeClass('input-error');
}

View file

@ -182,7 +182,12 @@ div.pagination {
text-align: center;
}
.alert.alert-success.move_up {
.alert{
margin-bottom: 0px;
}
.alert.alert-success.move_up,
.alert.alert-danger.siret{
position: absolute;
top: 0px;
left: 0;

View file

@ -12,12 +12,16 @@ table {
@extend .col-md-12;
@extend .col-lg-12;
margin-left: 15px;
width: 90%;
height: 600px;
}
#map.qp, #map.cadastre {
@extend .col-md-9;
@extend .col-lg-9;
width: 70%;
}
.list {
@ -35,6 +39,10 @@ table {
}
}
.leaflet-container path {
cursor: url('/assets/edit.png'), default !important;
}
#infos_dossier {
#map.mini {
height: 300px;
@ -42,8 +50,6 @@ table {
}
}
#map section.overlay {
position: absolute;
top: 0;
@ -56,7 +62,7 @@ table {
}
#map.mode-create {
cursor: crosshair !important;
cursor: url('/assets/pencil.png'), crosshair !important;
}
#map g path.tracer {

View file

@ -7,6 +7,11 @@
}
}
.input-error {
color: darkred !important;
border-color: darkred !important
}
.type_champ-text {
@extend .col-md-6;
@extend .col-lg-6;
@ -16,6 +21,43 @@
}
}
.type_champ-address {
@extend .col-md-6;
@extend .col-lg-6;
input[type='address'] {
width: 100%;
}
}
.type_champ-email {
@extend .col-md-4;
@extend .col-lg-4;
input[type='email'] {
width: 100%;
}
}
.type_champ-civilite {
@extend .col-md-3;
@extend .col-lg-3;
}
.type_champ-phone {
@extend .col-md-2;
@extend .col-lg-2;
input[type='phone'] {
width: 100%;
}
}
.datepicker-switch {
color: #0086b3;
text-decoration: underline;
}
.type_champ-textarea {
@extend .col-md-8;
@extend .col-lg-8;
@ -35,11 +77,27 @@
}
}
.type_champ-datetime {
.type_champ-date {
@extend .col-md-2;
@extend .col-lg-2;
input[type='number']{
width: 100%;
input[type='date'] {
width: 120px;
}
}
.type_champ-datetime {
@extend .col-md-4;
@extend .col-lg-4;
input[type='datetime'] {
width: 120px;
}
}
.description_div {
margin-top: 5px;
margin-left: 5px;
color: dimgrey;
display: none;
}

View file

@ -0,0 +1,29 @@
.etapes_menu{
h3 {
margin-left: 3%;
}
padding-right: 0 !important;
}
.etapes_informations {
padding-left: 0 !important;
}
.etape{
margin-bottom: 0px;
}
.etape_2{
.etapes_menu{
#dossier_siret{
width: 200px;
}
button{
margin-top: 8px;
}
}
.etapes_informations{
padding-top: 15px;
}
}

View file

@ -6,13 +6,6 @@
display: none;
}
#dossier_siret {
margin-bottom: 10px;
margin-left: auto;
margin-right: auto;
width: 200px;
}
#titre_procedure {
margin-top: 3%;
margin-bottom: 2%;

View file

@ -0,0 +1,35 @@
.tt-menu {
width: 555px;
padding: 8px 0;
background-color: #fff;
border: 1px solid #ccc;
border: 1px solid rgba(0, 0, 0, 0.2);
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
border-radius: 8px;
-webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
-moz-box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
}
.tt-suggestion {
padding: 3px 20px;
font-size: 18px;
line-height: 24px;
}
.twitter-typeahead {
width: 555px;
}
.tt-suggestion:hover {
cursor: pointer;
color: #fff;
background-color: #0097cf;
}
.tt-suggestion.tt-cursor {
color: #fff;
background-color: #0097cf;
}

View file

@ -22,6 +22,23 @@ class Admin::PiecesJustificativesController < AdminController
def update_params
params
.require(:procedure)
.permit(types_de_piece_justificative_attributes: [:libelle, :description, :id])
.permit(types_de_piece_justificative_attributes: [:libelle, :description, :id, :order_place])
end
def move_up
index = params[:index].to_i - 1
if @procedure.switch_types_de_piece_justificative index
render 'show', format: :js
else
render json: {}, status: 400
end
end
def move_down
if @procedure.switch_types_de_piece_justificative params[:index].to_i
render 'show', format: :js
else
render json: {}, status: 400
end
end
end

View file

@ -0,0 +1,13 @@
class Admin::PrevisualisationsController < AdminController
before_action :retrieve_procedure
def show
@procedure
@dossier = Dossier.new(id: 0, procedure: @procedure)
PrevisualisationService.destroy_all_champs @dossier
@dossier.build_default_champs
@champs = @dossier.ordered_champs
end
end

View file

@ -7,7 +7,7 @@ class Admin::ProceduresController < AdminController
def index
@procedures = smart_listing_create :procedures,
current_administrateur.procedures.where(archived: false),
current_administrateur.procedures.where(published: true, archived: false).order(created_at: :desc),
partial: "admin/procedures/list",
array: true
@ -16,7 +16,7 @@ class Admin::ProceduresController < AdminController
def archived
@procedures = smart_listing_create :procedures,
current_administrateur.procedures.where(archived: true),
current_administrateur.procedures.where(archived: true).order(created_at: :desc),
partial: "admin/procedures/list",
array: true
@ -25,6 +25,18 @@ class Admin::ProceduresController < AdminController
render 'index'
end
def draft
@procedures = smart_listing_create :procedures,
current_administrateur.procedures.where(published: false, archived: false).order(created_at: :desc),
partial: "admin/procedures/list",
array: true
draft_class
render 'index'
end
def show
@facade = AdminProceduresShowFacades.new @procedure.decorate
end
@ -33,6 +45,17 @@ class Admin::ProceduresController < AdminController
end
def destroy
procedure = Procedure.find(params[:id])
return render json: {}, status: 401 if procedure.published? || procedure.archived?
procedure.destroy
flash.notice = 'Procédure supprimée'
redirect_to admin_procedures_draft_path
end
def new
@procedure ||= Procedure.new
@procedure.module_api_carto ||= ModuleAPICarto.new
@ -60,15 +83,28 @@ class Admin::ProceduresController < AdminController
end
flash.notice = 'Préocédure modifiée'
redirect_to admin_procedures_path
redirect_to edit_admin_procedure_path(id: @procedure.id)
end
def publish
change_status({published: true})
end
def archive
@procedure = current_administrateur.procedures.find(params[:procedure_id])
@procedure.update_attributes({archived: params[:archive]})
change_status({archived: params[:archive]})
end
flash.notice = 'Procédure éditée'
redirect_to admin_procedures_path
def clone
@procedure = current_administrateur.procedures.find(params[:procedure_id])
new_procedure = @procedure.clone
if new_procedure
flash.notice = 'Procédure clonée'
redirect_to edit_admin_procedure_path(id: new_procedure.id)
else
flash.now.alert = @procedure.errors.full_messages.join('<br />').html_safe
render 'index'
end
rescue ActiveRecord::RecordNotFound
flash.alert = 'Procédure inéxistante'
@ -83,6 +119,10 @@ class Admin::ProceduresController < AdminController
@archived_class = 'active'
end
def draft_class
@draft_class = 'active'
end
private
def create_procedure_params
@ -92,4 +132,16 @@ class Admin::ProceduresController < AdminController
def create_module_api_carto_params
params.require(:procedure).require(:module_api_carto_attributes).permit(:id, :use_api_carto, :quartiers_prioritaires, :cadastre)
end
def change_status(status_options)
@procedure = current_administrateur.procedures.find(params[:procedure_id])
@procedure.update_attributes(status_options)
flash.notice = 'Procédure éditée'
redirect_to admin_procedures_path
rescue ActiveRecord::RecordNotFound
flash.alert = 'Procédure inéxistante'
redirect_to admin_procedures_path
end
end

View file

@ -19,7 +19,9 @@ class Admin::TypesDeChampController < AdminController
end
def update_params
params.require(:procedure).permit(types_de_champ_attributes: [:libelle, :description, :order_place, :type_champ, :id, :mandatory])
params
.require(:procedure)
.permit(types_de_champ_attributes: [:libelle, :description, :order_place, :type_champ, :id, :mandatory])
end
def move_up

View file

@ -0,0 +1,20 @@
class Ban::SearchController < ApplicationController
def get
request = params[:request]
render json: Carto::Bano::AddressRetriever.new(request).list.inject([]) {
|acc, value| acc.push({label: value})
}.to_json
end
def get_address_point
point = Carto::Geocodeur.convert_adresse_to_point(params[:request])
unless point.nil?
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

View file

@ -22,10 +22,11 @@ class CommentairesController < ApplicationController
end
@commentaire.body = params['texte_commentaire']
@commentaire.save unless flash.alert
saved = false
saved = @commentaire.save unless flash.alert
if is_gestionnaire?
NotificationMailer.new_answer(@commentaire.dossier).deliver_now!
NotificationMailer.new_answer(@commentaire.dossier).deliver_now! if saved
redirect_to url_for(controller: 'backoffice/dossiers', action: :show, id: params['dossier_id'])
elsif current_user.email != @commentaire.dossier.user.email
invite = Invite.where(dossier: @commentaire.dossier, user: current_user).first

View file

@ -6,7 +6,7 @@ class DemoController < ApplicationController
return redirect_to root_path if Rails.env.production?
smart_listing_create :procedures,
Procedure.where(archived: false),
Procedure.where(archived: false, published: true),
partial: "demo/list",
array: true
end

View file

@ -0,0 +1,32 @@
class Gestionnaires::PasswordsController < Devise::PasswordsController
# GET /resource/password/new
# def new
# super
# end
# POST /resource/password
# def create
# super
# end
# GET /resource/password/edit?reset_password_token=abcdef
# def edit
# super
# end
# PUT /resource/password
# def update
# super
# end
# protected
# def after_resetting_password_path_for(resource)
# super(resource)
# end
# The path used after sending reset password instructions
# def after_sending_reset_password_instructions_path_for(resource_name)
# super(resource_name)
# end
end

View file

@ -46,6 +46,14 @@ class Users::DescriptionController < UsersController
@dossier.champs.each do |champ|
champ.value = params[:champs]["'#{champ.id}'"]
if champ.type_champ == 'datetime'
champ.value = params[:champs]["'#{champ.id}'"]+
' ' +
params[:time_hour]["'#{champ.id}'"] +
':' +
params[:time_minute]["'#{champ.id}'"]
end
if champ.mandatory? && (champ.value.nil? || champ.value.blank?)
flash.now.alert = "Le champ #{champ.libelle} doit être rempli."
return render 'show'
@ -94,6 +102,6 @@ class Users::DescriptionController < UsersController
private
def create_params
params.permit(:nom_projet, :description)
params.permit(:nom_projet)
end
end

View file

@ -3,7 +3,7 @@ class Users::DossiersController < UsersController
helper SmartListing::Helper
before_action :authenticate_user!
before_action :check_siret, only: :create
before_action :check_siret, only: :siret_informations
before_action only: [:show] do
authorized_routes? self.class
@ -23,52 +23,55 @@ class Users::DossiersController < UsersController
end
def new
procedure = Procedure.where(archived: false).find(params[:procedure_id])
procedure = Procedure.where(archived: false, published: true).find(params[:procedure_id])
@dossier = Dossier.new(procedure: procedure)
@siret = params[:siret] || current_user.siret
dossier = Dossier.create(procedure: procedure, user: current_user, state: 'draft')
siret = params[:siret] || current_user.siret
update_current_user_siret! siret unless siret.nil?
redirect_to users_dossier_path(id: dossier.id)
rescue ActiveRecord::RecordNotFound
error_procedure
end
def show
@facade = DossierFacades.new params[:id], current_user.email
@facade = facade
@siret = current_user.siret unless current_user.siret.nil?
rescue ActiveRecord::RecordNotFound
flash.alert = t('errors.messages.dossier_not_found')
redirect_to url_for users_dossiers_path
end
def create
entreprise_adapter = SIADE::EntrepriseAdapter.new(siren)
def siret_informations
@facade = facade params[:dossier_id]
dossier = Dossier.create(user: current_user,
state: 'draft',
procedure_id: create_params[:procedure_id],
mandataire_social: mandataire_social?(entreprise_adapter.mandataires_sociaux))
update_current_user_siret! siret
entreprise = dossier.create_entreprise(entreprise_adapter.to_params)
DossierService.new(@facade.dossier, siret, current_user.france_connect_information).dossier_informations!
entreprise.create_rna_information(SIADE::RNAAdapter.new(siret).to_params)
etablissement = dossier.create_etablissement(SIADE::EtablissementAdapter.new(siret).to_params
.merge({entreprise_id: entreprise.id}))
etablissement.exercices.create(SIADE::ExercicesAdapter.new(siret).to_params)
redirect_to url_for(controller: :dossiers, action: :show, id: dossier.id)
@facade = facade params[:dossier_id]
render '/dossiers/new_siret', formats: 'js'
rescue RestClient::ResourceNotFound
errors_valid_siret
rescue ActiveRecord::RecordNotFound
flash.alert = t('errors.messages.dossier_not_found')
redirect_to url_for(controller: :siret)
redirect_to url_for users_dossiers_path
end
def change_siret
Dossier.find(params[:dossier_id]).reset!
@facade = facade params[:dossier_id]
render '/dossiers/new_siret', formats: :js
end
def update
@facade = DossierFacades.new params[:id], current_user.email
@facade = facade params[:dossier][:id]
if checked_autorisation_donnees?
@facade.dossier.update_attributes(update_params)
@ -79,8 +82,8 @@ class Users::DossiersController < UsersController
redirect_to url_for(controller: :description, action: :show, dossier_id: @facade.dossier.id)
end
else
flash.now.alert = 'Les conditions sont obligatoires.'
render 'show'
flash.alert = 'Les conditions sont obligatoires.'
redirect_to users_dossier_path(id: @facade.dossier.id)
end
end
@ -132,7 +135,9 @@ class Users::DossiersController < UsersController
def errors_valid_siret
flash.alert = t('errors.messages.invalid_siret')
redirect_to url_for new_users_dossiers_path(procedure_id: create_params[:procedure_id])
@facade = facade params[:dossier_id]
render '/dossiers/new_siret', formats: :js, locals: {invalid_siret: siret}
end
def update_params
@ -147,28 +152,21 @@ class Users::DossiersController < UsersController
create_params[:siret]
end
def siren
siret[0..8]
end
def create_params
params.require(:dossier).permit(:siret, :procedure_id)
params.require(:dossier).permit(:siret)
end
def error_procedure
flash.alert = t('errors.messages.procedure_not_found')
redirect_to url_for users_dossiers_path
end
def mandataire_social? mandataires_list
unless current_user.france_connect_information.nil?
mandataires_list.each do |mandataire|
return true if mandataire[:nom].upcase == current_user.family_name.upcase &&
mandataire[:prenom].upcase == current_user.given_name.upcase &&
mandataire[:date_naissance_timestamp] == current_user.birthdate.to_time.to_i
end
def update_current_user_siret! siret
current_user.update_attributes(siret: siret)
end
false
def facade id = params[:id]
DossierFacades.new id, current_user.email
end
end

View file

@ -12,7 +12,7 @@ class Users::SessionsController < Sessions::SessionsController
# GET /resource/sign_in
def new
unless user_return_to_procedure_id.nil?
@dossier = Dossier.new(procedure: Procedure.not_archived(user_return_to_procedure_id))
@dossier = Dossier.new(procedure: Procedure.active(user_return_to_procedure_id))
end
@user = User.new

View file

@ -2,7 +2,7 @@ class CommentaireDecorator < Draper::Decorator
delegate_all
def created_at_fr
created_at.to_datetime.strftime('%d/%m/%Y - %H:%M')
created_at.localtime.strftime('%d/%m/%Y - %H:%M')
rescue
'dd/mm/YYYY - HH:MM'
end

View file

@ -3,7 +3,7 @@ class DossierDecorator < Draper::Decorator
delegate_all
def display_date
date_previsionnelle.to_date.strftime('%d/%m/%Y')
date_previsionnelle.localtime.strftime('%d/%m/%Y')
rescue
'dd/mm/YYYY'
end

View file

@ -5,6 +5,10 @@ class ProcedureDecorator < Draper::Decorator
h.new_users_dossiers_url(procedure_id: id)
end
def created_at_fr
created_at.localtime.strftime('%d/%m/%Y %H:%M')
end
def logo_img
return 'logo-tps.png' if logo.blank?
logo

View file

@ -0,0 +1,37 @@
class TypeDePieceJustificativeDecorator < Draper::Decorator
delegate_all
def button_up params
h.link_to '', params[:url], class: up_classes, id: "btn_up_#{params[:index]}", remote: true, method: :post if display_up_button?(params[:index])
end
def button_down params
h.link_to '', params[:url], class: down_classes, id: "btn_down_#{params[:index]}", remote: true, method: :post if display_down_button?(params[:index])
end
private
def up_classes
base_classes << 'fa-chevron-up'
end
def down_classes
base_classes << 'fa-chevron-down'
end
def base_classes
%w(btn btn-default form-control fa)
end
def display_up_button?(index)
!(index == 0 || count_type_de_piece_justificative < 2)
end
def display_down_button?(index)
(index + 1) < count_type_de_piece_justificative
end
def count_type_de_piece_justificative
@count_type_de_piece_justificative ||= procedure.types_de_piece_justificative.count
end
end

View file

@ -15,7 +15,7 @@ class DossierFacades
end
def entreprise
@dossier.entreprise.decorate
@dossier.entreprise.decorate unless @dossier.entreprise.nil?
end
def etablissement

View file

@ -2,9 +2,35 @@ class Champ < ActiveRecord::Base
belongs_to :dossier
belongs_to :type_de_champ
delegate :libelle, :type_champ, :order_place, :mandatory, to: :type_de_champ
delegate :libelle, :type_champ, :order_place, :mandatory, :description, to: :type_de_champ
def mandatory?
mandatory
end
def data_provide
return 'datepicker' if type_champ == 'datetime' || type_champ == 'date'
return 'typeahead' if type_champ == 'address'
end
def data_date_format
('dd/mm/yyyy' if type_champ == 'datetime' || type_champ == 'date')
end
def same_hour? num
same_date? num, '%H'
end
def same_minute? num
same_date? num, '%M'
end
def same_date? num, compare
if type_champ == 'datetime' && !value.nil?
if value.to_datetime.strftime(compare) == num
return true
end
end
false
end
end

View file

@ -30,7 +30,6 @@ class Dossier < ActiveRecord::Base
after_save :build_default_champs, if: Proc.new { procedure_id_changed? }
validates :nom_projet, presence: true, allow_blank: false, allow_nil: true
validates :description, presence: true, allow_blank: false, allow_nil: true
validates :user, presence: true
WAITING_FOR_GESTIONNAIRE = %w(initiated updated submitted)
@ -52,7 +51,7 @@ class Dossier < ActiveRecord::Base
end
def ordered_champs
champs.joins(', types_de_champ').where('champs.type_de_champ_id = types_de_champ.id').order('order_place')
champs.joins(', types_de_champ').where("champs.type_de_champ_id = types_de_champ.id AND types_de_champ.procedure_id = #{procedure.id}").order('order_place')
end
def ordered_commentaires
@ -194,4 +193,10 @@ class Dossier < ActiveRecord::Base
entreprise_attr = EntrepriseSerializer.new(self.entreprise).attributes.map {|k, v| ["entreprise.#{k}", v] }.to_h
dossier_attr.merge(etablissement_attr).merge(entreprise_attr)
end
def reset!
entreprise.destroy unless entreprise.nil?
update_attributes(autorisation_donnees: false)
end
end

View file

@ -1,5 +1,5 @@
class Entreprise < ActiveRecord::Base
belongs_to :dossier
has_one :etablissement
has_one :rna_information
has_one :etablissement, dependent: :destroy
has_one :rna_information, dependent: :destroy
end

View file

@ -2,7 +2,7 @@ class Etablissement < ActiveRecord::Base
belongs_to :dossier
belongs_to :entreprise
has_many :exercices
has_many :exercices, dependent: :destroy
def geo_adresse
[numero_voie, type_voie, nom_voie, complement_adresse, code_postal, localite].join(' ')

View file

@ -4,7 +4,7 @@ class Gestionnaire < ActiveRecord::Base
has_and_belongs_to_many :administrateurs
has_many :assign_to
has_many :assign_to, dependent: :destroy
has_many :procedures, through: :assign_to
has_many :dossiers, through: :procedures

View file

@ -5,7 +5,7 @@ class PieceJustificative < ActiveRecord::Base
belongs_to :user
delegate :api_entreprise, :libelle, to: :type_de_piece_justificative
delegate :api_entreprise, :libelle, :order_place, to: :type_de_piece_justificative
alias_attribute :type, :type_de_piece_justificative_id
@ -38,7 +38,9 @@ class PieceJustificative < ActiveRecord::Base
application/vnd.openxmlformats-officedocument.presentationml.presentation,
application/vnd.oasis.opendocument.text,
application/vnd.oasis.opendocument.presentation,
application/vnd.oasis.opendocument.spreadsheet
application/vnd.oasis.opendocument.spreadsheet,
image/png,
image/jpeg
"
end
end

View file

@ -1,13 +1,13 @@
class Procedure < ActiveRecord::Base
has_many :types_de_piece_justificative, dependent: :destroy
has_many :types_de_champ, dependent: :destroy
has_many :dossiers, dependent: :destroy
has_many :dossiers
has_one :module_api_carto, dependent: :destroy
belongs_to :administrateur
has_many :assign_to
has_many :assign_to, dependent: :destroy
has_many :gestionnaires, through: :assign_to
delegate :use_api_carto, to: :module_api_carto
@ -25,22 +25,44 @@ class Procedure < ActiveRecord::Base
types_de_champ.order(:order_place)
end
def types_de_piece_justificative_ordered
types_de_piece_justificative.order(:order_place)
end
def self.not_archived id
Procedure.where(archived: false).find(id)
end
def self.active id
Procedure.where(archived: false, published: true).find(id)
end
def switch_types_de_champ index_of_first_element
switch_list_order(types_de_champ_ordered, index_of_first_element)
end
def switch_types_de_piece_justificative index_of_first_element
switch_list_order(types_de_piece_justificative_ordered, index_of_first_element)
end
def switch_list_order(list, index_of_first_element)
return false if index_of_first_element < 0
types_de_champ_tmp = types_de_champ_ordered
nb_types_de_champ = types_de_champ_tmp.count
return false if index_of_first_element == nb_types_de_champ - 1
return false if types_de_champ_ordered.count < 1
types_de_champ_tmp[index_of_first_element].update_attributes(order_place: index_of_first_element + 1)
types_de_champ_tmp[index_of_first_element + 1].update_attributes(order_place: index_of_first_element)
return false if index_of_first_element == list.count - 1
return false if list.count < 1
list[index_of_first_element].update_attributes(order_place: index_of_first_element + 1)
list[index_of_first_element + 1].update_attributes(order_place: index_of_first_element)
true
end
def locked?
dossiers.where.not(state: :draft).count > 0
published?
end
def clone
procedure = self.deep_clone(include: [ :types_de_piece_justificative, :types_de_champ, :module_api_carto ])
procedure.archived = false
procedure.published = false
return procedure if procedure.save
end
end

View file

@ -1,9 +1,15 @@
class TypeDeChamp < ActiveRecord::Base
enum type_champs: {text: 'text',
enum type_champs: {
text: 'text',
textarea: 'textarea',
date: 'date',
datetime: 'datetime',
number: 'number',
checkbox: 'checkbox'
checkbox: 'checkbox',
civilite: 'civilite',
email: 'email',
phone: 'phone',
address: 'address'
}
belongs_to :procedure

View file

@ -1,7 +1,6 @@
class DossierSerializer < ActiveModel::Serializer
attributes :id,
:nom_projet,
:description,
:created_at,
:updated_at,
:archived,

View file

@ -1,6 +1,6 @@
class TypeDePieceJustificativeSerializer < ActiveModel::Serializer
attributes :id,
:libelle,
:description
:description,
:order_place
end

View file

@ -0,0 +1,48 @@
class DossierService
def initialize dossier, siret, france_connect_information
@dossier = dossier
@siret = siret
@france_connect_information = france_connect_information
end
def dossier_informations!
@entreprise_adapter = SIADE::EntrepriseAdapter.new(DossierService.siren @siret)
@dossier.create_entreprise(@entreprise_adapter.to_params)
@etablissement_adapter = SIADE::EtablissementAdapter.new(@siret)
@dossier.create_etablissement(@etablissement_adapter.to_params)
@rna_adapter = SIADE::RNAAdapter.new(@siret)
@dossier.entreprise.create_rna_information(@rna_adapter.to_params)
@exercices_adapter = SIADE::ExercicesAdapter.new(@siret)
@dossier.etablissement.exercices.create(@exercices_adapter.to_params)
@dossier.update_attributes(mandataire_social: mandataire_social?(@entreprise_adapter.mandataires_sociaux))
@dossier.etablissement.update_attributes(entreprise: @dossier.entreprise)
@dossier
end
def self.siren siret
siret[0..8]
end
private
def mandataire_social? mandataires_list
unless @france_connect_information.nil?
mandataires_list.each do |mandataire|
return true if mandataire[:nom].upcase == @france_connect_information.family_name.upcase &&
mandataire[:prenom].upcase == @france_connect_information.given_name.upcase &&
mandataire[:date_naissance_timestamp] == @france_connect_information.birthdate.to_time.to_i
end
end
false
end
end

View file

@ -0,0 +1,5 @@
class PrevisualisationService
def self.destroy_all_champs dossier
Champ.where(dossier_id: dossier.id, type_de_champ_id: dossier.procedure.types_de_champ.ids).destroy_all
end
end

View file

@ -29,7 +29,7 @@ class CerfaUploader < CarrierWave::Uploader::Base
# Add a white list of extensions which are allowed to be uploaded.
# For images you might use something like this:
def extension_white_list
%w(pdf doc docx xls xlsx ppt pptx odt ods odp)
%w(pdf doc docx xls xlsx ppt pptx odt ods odp jpg jpeg png)
end
def filename

View file

@ -29,7 +29,7 @@ class PieceJustificativeUploader < CarrierWave::Uploader::Base
# Add a white list of extensions which are allowed to be uploaded.
# For images you might use something like this:
def extension_white_list
%w(pdf doc docx xls xlsx ppt pptx odt ods odp)
%w(pdf doc docx xls xlsx ppt pptx odt ods odp jpg jpeg png)
end
def filename

View file

@ -40,7 +40,7 @@ class ProcedureLogoUploader < CarrierWave::Uploader::Base
if Features.remote_storage
filename = "#{model.class.to_s.underscore}-#{secure_token}.#{file.extension.downcase}"
else
filename = "logo.#{file.extension.downcase}"
filename = "logo-#{secure_token}.#{file.extension.downcase}"
end
end
filename

View file

@ -1,9 +1,4 @@
%h2.text-info
=@procedure.libelle
%br
%ul.nav.nav-tabs
= render partial: 'admin/procedures/navbar', locals: {active: 'Accompagnateurs'}
=render partial: 'admin/procedures/head', locals: {active: 'Accompagnateurs'}
#accompagnateur_form
.row

View file

@ -1,14 +1,21 @@
= f.fields_for :types_de_piece_justificative, types_de_piece_justificative do |ff|
= f.fields_for :types_de_piece_justificative, types_de_piece_justificative, remote: true do |ff|
.form-inline
.form-group
%h4 Libellé
=ff.text_field :libelle, class: 'form-control libelle', placeholder: 'Libellé'
.form-group
%h4 Description
=ff.text_area :description, class: 'form-control description', placeholder: 'Description'
.form-group
= ff.hidden_field :order_place, value: ff.index
= ff.hidden_field :id
- unless ff.object.id.nil?
.form-group
%br &nbsp;
= ff.object.button_up(index: ff.index, url: move_up_admin_procedure_pieces_justificatives_path(@procedure, ff.index))
= ff.object.button_down(index: ff.index, url: move_down_admin_procedure_pieces_justificatives_path(@procedure, ff.index))
.form-group
%br &nbsp;

View file

@ -1,8 +1,7 @@
= form_for [:admin, @procedure], url: admin_procedure_pieces_justificatives_path(@procedure) , remote: true do |f|
#liste_piece_justificative
= render partial: 'fields', locals:{ types_de_piece_justificative: @procedure.types_de_piece_justificative, f: f }
= render partial: 'fields', locals:{ types_de_piece_justificative: @procedure.types_de_piece_justificative_ordered.decorate, f: f }
= f.submit "Enregistrer", class: 'btn btn-success', id: :save
%hr
#new_type_de_piece_justificative
= render partial: 'fields', locals:{ types_de_piece_justificative: TypeDePieceJustificative.new, f: f }
= render partial: 'fields', locals:{ types_de_piece_justificative: TypeDePieceJustificative.new.decorate, f: f }

View file

@ -1,9 +1,4 @@
%h2.text-info
=@procedure.libelle
%br
%ul.nav.nav-tabs
= render partial: 'admin/procedures/navbar', locals: {active: 'Pieces'}
=render partial: 'admin/procedures/head', locals: {active: 'Pieces'}
#piece_justificative_form
= render 'form'

View file

@ -0,0 +1,4 @@
=render partial: 'admin/procedures/head', locals: {active: 'Prévisualisation'}
#previsualisation
=render 'users/description/show'

View file

@ -0,0 +1,8 @@
%h2.text-info
-unless @procedure.logo.blank?
= image_tag @procedure.logo, style: 'width: 30px'
=@procedure.libelle
%br
%ul.nav.nav-tabs
= render partial: 'admin/procedures/navbar', locals: {active: active}

View file

@ -14,7 +14,9 @@
.row
.col-md-6.col-lg-6
%h4 Logo de la procédure
= f.file_field(:logo, accept: 'image/png, image/jpg,image/jpeg')
- unless @procedure.logo.blank?
= image_tag @procedure.logo, {style: 'height: 40px; display: inline; margin-right: 6px', id: 'preview_procedure_logo'}
= f.file_field(:logo, accept: 'image/png, image/jpg, image/jpeg', style: 'display:inline')
%div{style:'margin-top:5px'}
%i

View file

@ -3,7 +3,10 @@
%thead
%th#ID= smart_listing.sortable 'ID', 'id'
%th#libelle= smart_listing.sortable 'Libellé', 'libelle'
- unless @draft_class
%th#lien Lien
%th#created_at= smart_listing.sortable 'Date création', 'created_at'
%th#lien Actions
- @procedures.each do |procedure|
- procedure = procedure.decorate
@ -11,7 +14,14 @@
%td.col-md-1.col-lg-1= procedure.id
%td.col-md-6.col-lg-6
= link_to(procedure.libelle, "/admin/procedures/#{procedure.id}")
- unless @draft_class
%td= link_to procedure.lien, procedure.lien
%td
= procedure.created_at_fr
%td
= link_to('Cloner', admin_procedure_clone_path(procedure.id), 'data-method' => :put, class: 'btn-sm btn-primary')
- unless procedure.published? || procedure.archived?
= link_to('X', url_for(controller: 'admin/procedures', action: :destroy, id: procedure.id), 'data-method' => :delete, class: 'btn-sm btn-danger')
= smart_listing.paginate
= smart_listing.pagination_per_page_links

View file

@ -15,3 +15,6 @@
%li{ class: ('disabled' if @procedure.locked?) || ('active' if active == 'Pieces') }
= link_to_unless(@procedure.locked?, 'Pièces justificatives', admin_procedure_pieces_justificatives_path(@procedure)) do
= link_to('Pièces justificatives', '#')
%li{ class: ('active' if active == 'Prévisualisation'), style: 'float:right' }
= link_to('Prévisualisation', admin_procedure_previsualisation_path(@procedure), {style: 'font-style: italic;'})

View file

@ -1,5 +1,10 @@
#onglets
%ul.nav.nav-tabs
%li{class: @draft_class}
%a{:href => "#{url_for :admin_procedures_draft}"}
%h5.text-primary
="Brouillons"
%li{class: @active_class}
%a{:href => "#{url_for :admin_procedures}"}
%h5.text-success

View file

@ -1,9 +1,4 @@
%h2.text-info
=@procedure.libelle
%br
%ul.nav.nav-tabs
= render partial: 'navbar', locals: {active: 'Description'}
= render partial: 'head', locals: {active: 'Description'}
#procedure_new.section.section-label
= form_for @procedure, url: url_for({controller: 'admin/procedures', action: :update, id: @procedure.id}), multipart: true do |f|

View file

@ -4,3 +4,6 @@
= form_for @procedure, url: {controller: 'admin/procedures', action: :create}, multipart: true do |f|
=render partial: 'informations', locals: {f: f}
=f.submit 'Valider', class: 'btn btn-info', style: 'float:right'
%br
%br
%br

View file

@ -1,36 +1,48 @@
#procedure_show
%h2.text-info
=@facade.procedure.libelle
%br
=render partial: 'head', locals: {active: 'Informations'}
%ul.nav.nav-tabs
= render partial: 'navbar', locals: {active: 'Informations'}
-if ! @facade.procedure.published?
= form_tag admin_procedure_publish_path(procedure_id: @facade.procedure.id, publish: true), method: :put, style:'float: right; margin-top: 10px' do
%button#archive.btn.btn-small.btn-success.text-info{type: :button}
%i.fa.fa-eraser
Publier
#confirm
%button#valid.btn.btn-small.btn-success{type: :submit}
%i.fa.fa-check
Valider
%button#cancel.btn.btn-small.btn-danger{type: :button}
%i.fa.fa-remove
Annuler
%li{style:'float:right'}
= form_tag admin_procedure_archive_path(procedure_id: @facade.procedure.id, archive: !@facade.procedure.archived?), method: :put do
%button#archive.btn.btn-nav.text-info{type: :button}
-else
= form_tag admin_procedure_archive_path(procedure_id: @facade.procedure.id, archive: !@facade.procedure.archived?), method: :put, style:'float: right; margin-top: 10px' do
%button#archive.btn.btn-small.btn-default.text-info{type: :button}
%i.fa.fa-eraser
- if @facade.procedure.archived
= 'Réactiver'
- else
= 'Archiver'
#confirm
%button#valid.btn.btn-nav.text-success{type: :submit}
%button#valid.btn.btn-small.btn-success{type: :submit}
%i.fa.fa-check
Valider
%button#cancel.btn.btn-nav.text-danger{type: :button}
%button#cancel.btn.btn-small.btn-danger{type: :button}
%i.fa.fa-remove
Annuler
- if @facade.procedure.locked?
#procedure_locked.center
%h5
.label.label-info La procédure ne peut plus être modifiée car un usagé a déjà déposé un dossier
.label.label-info La procédure ne peut plus être modifiée car elle a été publiée
%div
%h3 Lien procédure
%div{style:'margin-left:3%'}
-if @facade.procedure.published?
= @facade.procedure.lien
-else
%b
Cette procédure n'a pas encore été publiée et n'est donc pas accessible par le public.
%br
%h3 Détails

View file

@ -1,9 +1,4 @@
%h2.text-info
=@procedure.libelle
%br
%ul.nav.nav-tabs
= render partial: 'admin/procedures/navbar', locals: {active: 'Champs'}
=render partial: 'admin/procedures/head', locals: {active: 'Champs'}
#liste_champ
= render partial: 'form'

View file

@ -6,9 +6,6 @@
%h4
= @facade.dossier.procedure.libelle
.description
= h @facade.dossier.description.html_safe
- if @facade.dossier.mandataire_social && gestionnaire_signed_in?
.mandataire_social.text-success.center
%br

View file

@ -1,13 +1,21 @@
.container#recap_info_entreprise
%h2 Récapitulatif de vos informations <em id="insee_infogreffe" class='small'>(récupérées auprès de l'INSEE et d'INFOGREFFE)</em>
%br
#users_siret_index
.row.etape.etape_1
= render partial: '/dossiers/etapes/etape1'
.row.etape.etape_2
= render partial: '/dossiers/etapes/etape2'
-#- if @facade.procedure.module_api_carto.use_api_carto?
-# .row.etape.etape_3
-# .etape.etapes_menu.col-md-3.col-lg-3
-# %h3
-# 3 - Ma zone d'intervention
-# .etape.etapes_informations.col-md-9.col-lg-9
-#
-#.row.etape.etape_4
-# .etape.etapes_menu.col-md-3.col-lg-3
-# %h3
-# = "#{@facade.procedure.module_api_carto.use_api_carto? ? '4' : '3'} - Mon dossier"
-# .etape.etapes_informations.col-md-9.col-lg-9
%div.row
= render partial: '/dossiers/infos_entreprise'
%br
= form_for @facade.dossier, url: { controller: '/users/dossiers', action: :update } do |f|
%label{ style:'font-weight:normal' }
= f.check_box :autorisation_donnees
J'autorise les décideurs publics à vérifier les informations de mon organisation auprès des administrations concernées. Ces informations resteront strictement confidentielles.
%br
= f.submit 'Etape suivante', class: "btn btn btn-info", style: 'float:right', id: 'etape_suivante'

View file

@ -0,0 +1,19 @@
.etape.etapes_menu.col-md-3.col-lg-3
%h3
Ma procédure
%br
.center
- if @facade.procedure.euro_flag
#euro_flag.flag
=image_tag('drapeau_europe.png')
#logo_procedure.flag
=image_tag( @facade.procedure.decorate.logo_img )
.etape.etapes_informations.col-md-9.col-lg-9
.row
%h2#titre_procedure.text-info
= @facade.procedure.libelle
%p{style:'width: 95%;'}
= h @facade.procedure.description.html_safe

View file

@ -0,0 +1,39 @@
.etape.etapes_menu.col-md-3.col-lg-3
%h3
Mes informations
%br
- unless @facade.entreprise.nil?
.center{style:'margin-left: -5%'}
Vous êtes authentifié avec le SIRET
%h3.text-success
= @facade.etablissement.siret
= form_for @facade.dossier, url: users_dossier_change_siret_path(dossier_id: @facade.dossier.id), method: :put, remote: true do |f|
= f.submit 'Changer de SIRET', class: %w(btn btn-xs btn-primary)
.etape.etapes_informations.col-md-9.col-lg-9
.row
- if @facade.entreprise.nil?
#new_siret{style:'margin-left: 20%; margin-top: 5%'}
= form_for @facade.dossier, html: {class: 'form-inline'}, url: users_dossier_siret_informations_path(dossier_id: @facade.dossier.id), method: :post, remote: true do |f|
.form-group.form-group-lg
= f.text_field :siret, class: "form-control", placeholder: "Entrez votre Siret", value: @siret
= f.hidden_field :dossier_id, value: @facade.dossier.id
= f.submit 'Valider', class: %w(btn btn-lg btn-success), data: { disable_with: "Recherche en cours ..." }
- else
#recap_info_entreprise
= render partial: '/dossiers/infos_entreprise'
%p#insee_infogreffe{style:'color:grey; float:right'}
%i
Informations récupérées auprès de l'INSEE et d'INFOGREFFE
%br
= form_for @facade.dossier, url: { controller: '/users/dossiers', action: :update } do |f|
= f.hidden_field :id
%label{ style:'font-weight:normal' }
= f.check_box :autorisation_donnees
J'autorise les décideurs publics à vérifier les informations de mon organisation auprès des administrations concernées. Ces informations resteront strictement confidentielles.
%br
= f.submit 'Etape suivante', class: "btn btn btn-info", style: 'float:right', id: 'etape_suivante', disabled: :disabled

View file

@ -0,0 +1,7 @@
$('.row.etape.etape_2').html("<%= escape_javascript(render partial: '/dossiers/etapes/etape2', locals: { facade: @facade } ) %>");
the_terms();
<% unless flash.empty? %>
error_form_siret('<%= invalid_siret %>');
<% end %>
<% flash.clear %>

View file

@ -0,0 +1,31 @@
= devise_error_messages!
#form_login
= image_tag('logo-tps.png')
%br
%h2#gestionnaire_login Changement de mot de passe
%br
%br
#new_user
= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f|
= f.hidden_field :reset_password_token
%h4
= f.label 'Nouveau mot de passe'
.input-group
.input-group-addon
%span.glyphicon.glyphicon-asterisk
= f.password_field :password, autofocus: true, autocomplete: "off", class: 'form-control'
%br
%h4
= f.label 'Retaper le mot de passe'
.input-group
.input-group-addon
%span.glyphicon.glyphicon-asterisk
= f.password_field :password_confirmation, autocomplete: "off", class: 'form-control'
%br
%br
.actions
= f.submit "Changer", class:'btn btn-primary'
%br

View file

@ -0,0 +1,22 @@
= devise_error_messages!
#form_login
= image_tag('logo-tps.png')
%br
%h2#gestionnaire_login Mot de passe oublié
%br
%br
#new_user
= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f|
%h4
= f.label :email
.input-group
.input-group-addon
%span.glyphicon.glyphicon-user
= f.email_field :email, class: 'form-control', placeholder: 'Email'
%br
%br
.actions
= f.submit "Renvoyer", class:'btn btn-primary'
%br

View file

@ -26,3 +26,4 @@
.actions
= f.submit "Se connecter", class:'btn btn-primary'
%br
= render "gestionnaires/shared/links"

View file

@ -0,0 +1,2 @@
<%= link_to "Mot de passe oublié ?", new_password_path(resource_name) %><br />

View file

@ -0,0 +1,33 @@
#beta
Beta
= image_tag('marianne_small.png', class: 'logo')
%a{href: '/'}
= image_tag('logo-tps.png', class: 'logo')
%a{href: '/', class: 'btn btn-md'}
-if gestionnaire_signed_in? || user_signed_in?
Mes Dossiers
-elsif administrateur_signed_in?
Mes Procédures
#sign_out
-if gestionnaire_signed_in?
= render partial: 'gestionnaires/login_banner'
-elsif administrateur_signed_in?
= render partial: 'administrateurs/login_banner'
- elsif user_signed_in?
%div.user
-if current_user.loged_in_with_france_connect?
%div{ id: "fconnect-profile", "data-fc-logout-url" => '/users/sign_out" data-method="delete' }
%a.text-info{ href: "#" }
= "#{current_user.given_name} #{current_user.family_name}"
= link_to "", '/users/sign_out', method: :delete, :class => 'btn fa fa-power-off off-fc-link'
-else
%i.fa.fa-user
= current_user.email
= link_to "Déconnexion", '/users/sign_out', method: :delete, :class => 'btn btn-md'
- else
= link_to "Utilisateur", '/users/sign_in', method: :get, :class => 'btn btn-md'
= link_to "Accompagnateur", '/gestionnaires/sign_in', method: :get, :class => 'btn btn-md'
= link_to "Administrateur", '/administrateurs/sign_in', method: :get, :class => 'btn btn-md'

View file

@ -12,36 +12,7 @@
%body
%div#wrap
%div#header.navbar
#beta
Beta
= image_tag('marianne_small.png', class: 'logo')
%a{href: '/'}
= image_tag('logo-tps.png', class: 'logo')
#sign_out
-if gestionnaire_signed_in?
= render partial: 'gestionnaires/login_banner'
-elsif administrateur_signed_in?
= render partial: 'administrateurs/login_banner'
- elsif user_signed_in?
%div.user
-if current_user.loged_in_with_france_connect?
%div{ id: "fconnect-profile", "data-fc-logout-url" => '/users/sign_out" data-method="delete' }
%a.text-info{ href: "#" }
= "#{current_user.given_name} #{current_user.family_name}"
= link_to "", '/users/sign_out', method: :delete, :class => 'btn fa fa-power-off off-fc-link'
-else
%i.fa.fa-user
= current_user.email
= link_to "Déconnexion", '/users/sign_out', method: :delete, :class => 'btn btn-md'
- else
= link_to "Utilisateur", '/users/sign_in', method: :get, :class => 'btn btn-md'
= link_to "Accompagnateur", '/gestionnaires/sign_in', method: :get, :class => 'btn btn-md'
= link_to "Administrateur", '/administrateurs/sign_in', method: :get, :class => 'btn btn-md'
=render partial: "layouts/navbar"
#flash_message.center
- if flash.notice
@ -50,7 +21,6 @@
- if flash.alert
.alert.alert-danger
= flash.alert
#main_div.main_div
= yield

View file

@ -58,6 +58,10 @@
.row.word.news
.latest_release.col-md-7.col-lg-7
- if @latest_release.nil?
%p
Erreur dans la récupération des données
-else
%h3.text-info
= "Dernière version (#{@latest_release.tag_name} - #{@latest_release.published_at})"
.body

View file

@ -1,14 +1,20 @@
%h2
='Localisation de votre demande'
='Localisation'
%h4.text-primary
Positionnez-vous et dessinez sur la carte la zone d'action de votre demande.
%br
.content{style:'margin-bottom:60px'}
%button#new.btn.btn-sm.btn-success{type:'button'} Nouveau
\-
%button#edit.btn.btn-sm.btn-info{type:'button'} Editer
\-
%button#delete.btn.btn-sm.btn-danger{type:'button'} Supprimer
%button#new.btn.btn-md.btn-success{type:'button'}
%i.fa.fa-pencil
Ajouter une zone
-#\-
-#%button#edit.btn.btn-sm.btn-info{type:'button'} Editer
-#\-
-#%button#delete.btn.btn-sm.btn-danger{type:'button'} Supprimer
%span#search_by_address{style: 'margin-left: 20px'}
%input.form-control{type: :address, placeholder: 'Rechercher une adresse'}
%br
%br
#carte_page.row
@ -24,7 +30,6 @@
%h3.text-warning Cadastres
%ul
= form_tag(url_for({controller: :carte, action: :save, dossier_id: @dossier.id}), class: 'form-inline', method: 'POST') do
%br
%input{type: 'hidden', value: "#{@dossier.json_latlngs}", name: 'json_latlngs', id: 'json_latlngs'}

View file

@ -0,0 +1,38 @@
-@champs.each do |champ|
.row
%div{class: "type_champ-#{champ.type_champ}"}
-if champ.type_champ == 'checkbox'
%h4{style:'margin-left:15px;'}
= champ.libelle
- if champ.mandatory?
= '*'
%input{type: 'hidden', name:"champs['#{champ.id}']", id: "champs_#{champ.id}", value: ''}
%input{type: 'checkbox', style:'margin-left: 15px;', name:"champs['#{champ.id}']", id: "champs_#{champ.id}", checked: ('checked' if champ.value == 'on')}
-else
%h4
= champ.libelle
- if champ.mandatory?
= '*'
-if champ.type_champ == 'textarea'
=render partial: 'users/description/champs/textarea', locals: {champ: champ}
-elsif champ.type_champ == 'civilite'
=render partial: 'users/description/champs/civilite', locals: {champ: champ}
- elsif champ.type_champ == 'datetime'
=render partial: 'users/description/champs/datetime', locals: {champ: champ}
-else
%input.form-control{name:"champs['#{champ.id}']",
placeholder: champ.libelle,
id: "champs_#{champ.id}",
value: champ.value,
type: champ.type_champ,
'data-provide' => champ.data_provide,
'data-date-format' => champ.data_date_format}
- unless champ.description.empty?
.row
.col-lg-8.col-md-8{class: 'description_div', id:"description_champs_#{champ.id}"}
= champ.description

View file

@ -0,0 +1,45 @@
.container#description_page
%h2
= @dossier.procedure.libelle
%h3 Votre dossier
%br
-#TODO use form_for
= form_tag(url_for({controller: 'users/description', action: :create, dossier_id: @dossier.id}), class: 'form-inline', method: 'POST', multipart: true) do
%div
.row
.col-md-12
%h4 Libellé pour votre dossier *
= text_field_tag :nom_projet, @dossier.nom_projet, placeholder: 'Nom du projet', class: 'form-control'
#liste_champs
-unless @champs.nil?
=render partial: 'users/description/champs'
-if !@procedure.lien_demarche.blank? || @procedure.cerfa_flag || @dossier.types_de_piece_justificative.size > 0
%br
%h3 Documents administratifs
-unless @procedure.lien_demarche.blank?
%p
Formulaire / documentation de la démarche :
%a{style:'font-size:0.9em; padding-left:3px', id: 'lien_cerfa' ,href: "#{@procedure.lien_demarche}", :target => '_blank'} Accéder
%br
//TODO a refactorer
= render partial: 'users/description/pieces_justificatives'
- if user_signed_in?
%div{style: 'text-align:right'}
%h6 Tous les champs portant un * sont obligatoires.
-if !@dossier.draft?
=render partial: '/layouts/modifications_terminees'
-else
= submit_tag 'Soumettre mon dossier', id: 'suivant', class: %w(btn btn btn-success), style: 'float:right', data: { disable_with: 'Soumettre votre dossier', submit: true}
%br
%br

View file

@ -0,0 +1,7 @@
%label.radio-inline
= radio_button_tag "champs['#{champ.id}']", "M.", champ.value == 'Mme' ? false : true
Monsieur
%label.radio-inline
= radio_button_tag "champs['#{champ.id}']", "Mme", champ.value == 'Mme'
Madame

View file

@ -0,0 +1,21 @@
%input.form-control{name:"champs['#{champ.id}']",
placeholder: champ.libelle,
id: "champs_#{champ.id}",
value: (champ.value.split(/[ ][0-9]*:[0-9]*/).first unless champ.value.nil?),
type: champ.type_champ,
'data-provide' => champ.data_provide,
'data-date-format' => champ.data_date_format}
%select.form-control{name:"time_hour['#{champ.id}']", style: 'margin-left: 5px', id:"time_hour_#{champ.id}"}
- (0..23).each do |num|
- num = "%.2i" %num
%option{value: num, selected: (:selected if champ.same_hour?(num))}
= num
h
%select.form-control{name:"time_minute['#{champ.id}']", id:"time_minute_#{champ.id}"}
- (0..59).each do |num|
- num = "%.2i" %num
- if num.to_i%5 == 0
%option{value: num, selected: (:selected if champ.same_minute?(num))}
= num
min

View file

@ -0,0 +1,5 @@
%textarea.form-control.wysihtml5{name:"champs['#{champ.id}']",
placeholder: champ.description,
id: "champs_#{champ.id}",
row: '6'}
=champ.value

View file

@ -1,76 +1 @@
.container#description_page
%h2
= @dossier.procedure.libelle
%h3 Votre dossier
%br
-#TODO use form_for
= form_tag(url_for({controller: :description, action: :create, dossier_id: @dossier.id}), class: 'form-inline', method: 'POST', multipart: true) do
%div
.row
.col-md-12
%h4 Libellé pour votre dossier *
= text_field_tag :nom_projet, @dossier.nom_projet, placeholder: 'Nom du projet', class: 'form-control'
%br
.row
.col-md-12
%h4 Description *
= text_area_tag :description, @dossier.description, rows: '6', placeholder: 'Description du projet', class: 'form-control wysihtml5'
#liste_champs
-unless @champs.nil?
-@champs.each do |champ|
.row
%div{class: "type_champ-#{champ.type_champ}"}
-if champ.type_champ == 'checkbox'
%h4{style:'margin-left:15px;'}
= champ.libelle
- if champ.mandatory?
= '*'
%input{type: 'hidden', name:"champs['#{champ.id}']", id: "champs_#{champ.id}", value: ''}
%input{type: 'checkbox', style:'margin-left: 15px;', name:"champs['#{champ.id}']", id: "champs_#{champ.id}", checked: ('checked' if champ.value == 'on')}
-else
%h4
= champ.libelle
- if champ.mandatory?
= '*'
-if champ.type_champ == 'textarea'
%textarea.form-control{name:"champs['#{champ.id}']",
placeholder: champ.libelle,
id: "champs_#{champ.id}"}
=champ.value
-else
%input.form-control{name:"champs['#{champ.id}']",
placeholder: champ.libelle,
id: "champs_#{champ.id}",
value: champ.value,
type:"#{champ.type_champ}",
'data-provide' => ('datepicker' if champ.type_champ == 'datetime'),
'data-date-format' => ('dd/mm/yyyy' if champ.type_champ == 'datetime')}
-if !@procedure.lien_demarche.blank? || @procedure.cerfa_flag || @dossier.pieces_justificatives.size > 1
%br
%h3 Documents administratifs
-unless @procedure.lien_demarche.blank?
%p
Formulaire / documentation de la démarche :
%a{style:'font-size:0.9em; padding-left:3px', id: 'lien_cerfa' ,href: "#{@procedure.lien_demarche}", :target => '_blank'} Accéder
%br
//TODO a refactorer
= render partial: 'pieces_justificatives'
%div{style: 'text-align:right'}
%h6 Tous les champs portant un * sont obligatoires.
-if !@dossier.draft?
=render partial: '/layouts/modifications_terminees'
-else
= submit_tag 'Soumettre mon dossier', id: 'suivant', class: %w(btn btn btn-success), style: 'float:right', data: { disable_with: 'Soumettre votre dossier', submit: true}
%br
%br
= render partial: 'show'

View file

@ -1,11 +0,0 @@
- if @dossier.procedure.euro_flag
#euro_flag.flag
=image_tag('drapeau_europe.png')
#logo_procedure.flag
=image_tag( @dossier.procedure.decorate.logo_img )
%h2#titre_procedure.text-info
= @dossier.procedure.libelle
%p
= h @dossier.procedure.description.html_safe

View file

@ -1,11 +0,0 @@
.container.center#users_siret_index
.row
%p.lead{id: 'pro_section', style:'padding-top: 120px'}
= render partial: 'title_procedure'
%br
= form_for @dossier, url: {controller: 'users/dossiers', action: :create}, method: :post do |f|
.form-group.form-group-lg
= f.text_field :siret, class: "form-control", placeholder: "Entrez votre Siret", value: @siret
= f.hidden_field :procedure_id
= f.submit 'Commencer', class: %w(btn btn-lg btn-success), style: 'margin-top:20px;'

View file

@ -2,7 +2,20 @@
%br
- if @dossier
= link_to 'X', users_no_procedure_url, class: 'btn btn-xs', style:'float: right'
= render partial: 'users/dossiers/title_procedure'
- if @dossier.procedure.euro_flag
#euro_flag.flag
=image_tag('drapeau_europe.png')
#logo_procedure.flag
=image_tag( @dossier.procedure.decorate.logo_img )
%h2#titre_procedure.text-info
= @dossier.procedure.libelle
%p
= h @dossier.procedure.description.html_safe
- else
= image_tag('logo-tps.png', {id: 'logo_tps'})
%br

View file

@ -63,6 +63,7 @@ set :shared_paths, [
'public/system',
'public/uploads',
'config/database.yml',
"config/fog_credentials.yml",
'config/initializers/secret_token.rb',
"config/environments/#{ENV['to']}.rb",
"config/initializers/token.rb",

View file

@ -9,8 +9,9 @@ Rails.application.routes.draw do
}, skip: [:password, :registrations]
devise_for :gestionnaires, controllers: {
sessions: 'gestionnaires/sessions'
}, skip: [:password, :registrations]
sessions: 'gestionnaires/sessions',
passwords: 'gestionnaires/passwords'
}, skip: [:registrations]
devise_for :users, controllers: {
sessions: 'users/sessions',
@ -25,6 +26,8 @@ Rails.application.routes.draw do
devise_scope :gestionnaire do
get '/gestionnaires/sign_in/demo' => 'gestionnaires/sessions#demo'
get '/gestionnaires/edit' => 'gestionnaires/registrations#edit', :as => 'edit_gestionnaires_registration'
put '/gestionnaires' => 'gestionnaires/registrations#update', :as => 'gestionnaires_registration'
end
devise_scope :administrateur do
@ -73,6 +76,9 @@ Rails.application.routes.draw do
post '/carte' => 'carte#save'
put '/archive' => 'dossiers#archive'
post '/siret_informations' => 'dossiers#siret_informations'
put '/change_siret' => 'dossiers#change_siret'
end
resource :dossiers
end
@ -82,6 +88,7 @@ Rails.application.routes.draw do
namespace :admin do
get 'sign_in' => '/administrateurs/sessions#new'
get 'procedures/archived' => 'procedures#archived'
get 'procedures/draft' => 'procedures#draft'
get 'profile' => 'profile#show', as: :profile
resources :procedures do
@ -89,11 +96,18 @@ Rails.application.routes.draw do
post '/:index/move_up' => 'types_de_champ#move_up', as: :move_up
post '/:index/move_down' => 'types_de_champ#move_down', as: :move_down
end
resource :pieces_justificatives, only: [:show, :update] do
post '/:index/move_up' => 'pieces_justificatives#move_up', as: :move_up
post '/:index/move_down' => 'pieces_justificatives#move_down', as: :move_down
end
put 'archive' => 'procedures#archive', as: :archive
put 'publish' => 'procedures#publish', as: :publish
put 'clone' => 'procedures#clone', as: :clone
resource :accompagnateurs, only: [:show, :update]
resource :previsualisation, only: [:show]
resources :types_de_champ, only: [:destroy]
resource :pieces_justificatives, only: [:show, :update]
@ -107,6 +121,11 @@ Rails.application.routes.draw do
resources :gestionnaires, only: [:index, :create, :destroy]
end
namespace :ban do
get 'search' => 'search#get'
get 'address_point' => 'search#get_address_point'
end
get 'backoffice' => 'backoffice#index'
namespace :backoffice do

View file

@ -0,0 +1,9 @@
class AddOrderPlaceInTypeDePieceJustificative < ActiveRecord::Migration
def up
add_column :types_de_piece_justificative, :order_place, :integer
end
def down
remove_column :types_de_piece_justificative, :order_place
end
end

View file

@ -0,0 +1,12 @@
class AddProcedureStatus < ActiveRecord::Migration
class Procedure < ActiveRecord::Base
end
def change
add_column :procedures, :published, :boolean, default: false, null: false
Procedure.all.each do |procedure|
procedure.published = true
procedure.save!
end
end
end

View file

@ -0,0 +1,64 @@
class DeleteDefaultDescriptionToDossier < ActiveRecord::Migration
class Dossier < ActiveRecord::Base
end
class Champ < ActiveRecord::Base
end
class Procedure < ActiveRecord::Base
end
class TypeDeChamp < ActiveRecord::Base
end
def up
Procedure.all.each do |procedure|
#change all type_de_champ place_order by +1 to insert new type_de_champ description on first place
TypeDeChamp.where(procedure_id: procedure.id).each do |type_de_champ|
type_de_champ.order_place += 1
type_de_champ.save
end
#insert type_de_champ description on first place
TypeDeChamp.create(libelle: 'Description', description: 'Description de votre demande', type_champ: 'textarea', order_place: 0, procedure_id: procedure.id, mandatory: true)
end
Dossier.all.each do |dossier|
#get the new type de champ
new_type_de_champ = TypeDeChamp.where(libelle: 'Description', type_champ: 'textarea', order_place: 0, procedure_id: dossier.procedure_id, mandatory: true)
#create a new champ with the actual description value
Champ.create(value: dossier.description, type_de_champ_id: new_type_de_champ.first.id, dossier_id: dossier.id)
end
remove_column :dossiers, :description
end
def down
add_column :dossiers, :description, :text
Champ.destroy_all(dossier_id: 0)
TypeDeChamp.where(libelle: 'Description', type_champ: 'textarea', order_place: 0, mandatory: true).each do |type_de_champ|
Champ.where(type_de_champ_id: type_de_champ.id).each do |champ|
dossier = Dossier.find(champ.dossier_id)
dossier.description = champ.value
dossier.save
champ.delete
end
procedure_id = type_de_champ.procedure_id
type_de_champ.delete
TypeDeChamp.where(procedure_id: procedure_id).each do |type_de_champ_2|
type_de_champ_2.order_place -= 1
type_de_champ_2.save
end
end
end
end

View file

@ -0,0 +1,15 @@
class ConvertAllDatetimeToDateOnDatabase < ActiveRecord::Migration
class TypeDeChamp < ActiveRecord::Base
end
def change
TypeDeChamp.all.each do |type_de_champ|
if type_de_champ.type_champ == 'datetime'
type_de_champ.type_champ = 'date'
type_de_champ.save
end
end
end
end

View file

@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20160524093540) do
ActiveRecord::Schema.define(version: 20160622081321) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -113,7 +113,6 @@ ActiveRecord::Schema.define(version: 20160524093540) do
add_index "commentaires", ["dossier_id"], name: "index_commentaires_on_dossier_id", using: :btree
create_table "dossiers", force: :cascade do |t|
t.string "description"
t.boolean "autorisation_donnees"
t.string "nom_projet"
t.integer "procedure_id"
@ -242,6 +241,7 @@ ActiveRecord::Schema.define(version: 20160524093540) do
t.string "logo"
t.boolean "cerfa_flag", default: false
t.string "logo_secure_token"
t.boolean "published", default: false, null: false
end
create_table "quartier_prioritaires", force: :cascade do |t|
@ -278,6 +278,7 @@ ActiveRecord::Schema.define(version: 20160524093540) do
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "procedure_id"
t.integer "order_place"
end
create_table "users", force: :cascade do |t|

View file

@ -0,0 +1,36 @@
module Carto
module Bano
# input : address
# output : Array List label address
class AddressRetriever
def initialize(address)
@address = address
end
def list
@list ||= convert_driver_result_to_full_address
end
private
def driver
@driver ||= Carto::Bano::Driver.new @address, 5
end
def convert_driver_result_to_full_address
result = JSON.parse(driver.call)
if result['features'].size == 0
Rails.logger.error "unable to find location for address #{@address}"
return []
end
result['features'].inject([]) do |acc, feature|
acc.push feature['properties']['label']
end
rescue TypeError, JSON::ParserError
[]
end
end
end
end

View file

@ -3,12 +3,15 @@ module Carto
# input : string (address)
# output : json
class Driver
def initialize(address)
def initialize(address, limit = 1)
@address = address
@limit = limit
end
def call
RestClient.get api_url, params: { q: @address, limit: 1 }
RestClient.get api_url, params: { q: @address, limit: @limit }
rescue RestClient::ServiceUnavailable
nil
end
def api_url

View file

@ -12,7 +12,9 @@ class Github::API
def self.call(end_point, params = {})
RestClient::Resource.new(
base_uri+end_point
base_uri+end_point, timeout: 5
).get(params: params)
rescue RestClient::Forbidden
nil
end
end

View file

@ -1,9 +1,11 @@
class Github::Releases
def self.latest
release = Hashie::Mash.new JSON.parse(Github::API.latest_release)
release.published_at = release.published_at.to_date.strftime('%d/%m/%Y')
latest_release = Github::API.latest_release
return nil if latest_release.nil?
release = Hashie::Mash.new JSON.parse(latest_release)
release.published_at = release.published_at.to_date.strftime('%d/%m/%Y')
release
end
end

View file

@ -2,12 +2,13 @@ require 'spec_helper'
describe Admin::PiecesJustificativesController, type: :controller do
let(:admin) { create(:administrateur) }
let(:published) { false }
let(:procedure) { create(:procedure, administrateur: admin, published: published) }
before do
sign_in admin
end
describe 'GET #show' do
let(:procedure) { create(:procedure, administrateur: admin) }
let(:procedure_id) { procedure.id }
subject { get :show, procedure_id: procedure_id }
@ -17,8 +18,8 @@ describe Admin::PiecesJustificativesController, type: :controller do
it { expect(subject.status).to eq(404) }
end
context 'when procedure have at least a file' do
let!(:dossier) { create(:dossier, procedure: procedure, state: :initiated) }
context 'when procedure is published' do
let(:published) { true }
it { is_expected.to redirect_to admin_procedure_path id: procedure_id }
end
@ -30,7 +31,6 @@ describe Admin::PiecesJustificativesController, type: :controller do
end
describe 'PUT #update' do
let(:procedure) { create(:procedure, administrateur: admin) }
let(:procedure_id) { procedure.id }
let(:libelle) { 'RIB' }
let(:description) { "relevé d'identité bancaire" }
@ -72,7 +72,6 @@ describe Admin::PiecesJustificativesController, type: :controller do
end
describe 'DELETE #destroy' do
let(:procedure) { create(:procedure, administrateur: admin) }
let!(:pj) { create(:type_de_piece_justificative, procedure: procedure) }
let(:procedure_id) { procedure.id }
let(:pj_id) { pj.id }
@ -97,4 +96,76 @@ describe Admin::PiecesJustificativesController, type: :controller do
it { expect{ subject }.to change(TypeDePieceJustificative, :count).by(-1) }
end
end
describe 'POST #move_up' do
subject { post :move_up, procedure_id: procedure.id, index: index, format: :js }
context 'when procedure have no type de champ' do
let(:index) { 0 }
it { expect(subject.status).to eq(400) }
end
context 'when procedure have only one type de champ' do
let(:index) { 1 }
let!(:type_de_piece_justificative) { create(:type_de_piece_justificative, procedure: procedure) }
it { expect(subject.status).to eq(400) }
end
context 'when procedure have tow type de champs' do
context 'when index == 0' do
let(:index) { 0 }
let!(:type_de_piece_justificative_1) { create(:type_de_piece_justificative, procedure: procedure) }
let!(:type_de_piece_justificative_2) { create(:type_de_piece_justificative, procedure: procedure) }
it { expect(subject.status).to eq(400) }
end
context 'when index > 0' do
let(:index) { 1 }
let!(:type_de_piece_justificative_0) { create(:type_de_piece_justificative, procedure: procedure, order_place: 0) }
let!(:type_de_piece_justificative_1) { create(:type_de_piece_justificative, procedure: procedure, order_place: 1) }
it { expect(subject.status).to eq(200) }
it { expect(subject).to render_template('show') }
it 'changes order places' do
post :move_up, procedure_id: procedure.id, index: index, format: :js
type_de_piece_justificative_0.reload
type_de_piece_justificative_1.reload
expect(type_de_piece_justificative_0.order_place).to eq(1)
expect(type_de_piece_justificative_1.order_place).to eq(0)
end
end
end
end
describe 'POST #move_down' do
let(:request) { post :move_down, procedure_id: procedure.id, index: index, format: :js }
let(:index) { 0 }
subject { request }
context 'when procedure have no type de champ' do
it { expect(subject.status).to eq(400) }
end
context 'when procedure have only one type de champ' do
let!(:type_de_piece_justificative_0) { create(:type_de_piece_justificative, procedure: procedure) }
it { expect(subject.status).to eq(400) }
end
context 'when procedure have 2 type de champ' do
let!(:type_de_piece_justificative_0) { create(:type_de_piece_justificative, procedure: procedure, order_place: 0) }
let!(:type_de_piece_justificative_1) { create(:type_de_piece_justificative, procedure: procedure, order_place: 1) }
context 'when index represent last type_de_piece_justificative' do
let(:index) { 1 }
it { expect(subject.status).to eq(400) }
end
context 'when index does not represent last type_de_piece_justificative' do
let(:index) { 0 }
it { expect(subject.status).to eq(200) }
it { expect(subject).to render_template('show') }
it 'changes order place' do
request
type_de_piece_justificative_0.reload
type_de_piece_justificative_1.reload
expect(type_de_piece_justificative_0.order_place).to eq(1)
expect(type_de_piece_justificative_1.order_place).to eq(0)
end
end
end
end
end

View file

@ -0,0 +1,16 @@
require 'spec_helper'
describe Admin::PrevisualisationsController, type: :controller do
let(:admin) { create(:administrateur) }
let(:procedure) { create :procedure, administrateur: admin }
before do
sign_in admin
end
describe 'GET #show' do
subject { get :show, procedure_id: procedure.id }
it { expect(subject.status).to eq(200) }
end
end

View file

@ -46,8 +46,56 @@ describe Admin::ProceduresController, type: :controller do
it { expect(response.status).to eq(200) }
end
describe 'GET #published' do
subject { get :published }
it { expect(response.status).to eq(200) }
end
describe 'DELETE #destroy' do
let(:procedure_draft) { create :procedure, published: false, archived: false }
let(:procedure_published) { create :procedure, published: true, archived: false }
let(:procedure_archived) { create :procedure, published: false, archived: true }
subject { delete :destroy, id: procedure.id }
context 'when procedure is draft' do
let!(:procedure) { procedure_draft }
describe 'tech params' do
before do
subject
end
it { expect(subject.status).to eq 302 }
it { expect(flash[:notice]).to be_present }
end
it 'destroy procedure is call' do
expect_any_instance_of(Procedure).to receive(:destroy)
subject
end
it { expect { subject }.to change{Procedure.count}.by(-1) }
end
context 'when procedure is published' do
let(:procedure) { procedure_published }
it { expect(subject.status).to eq 401 }
end
context 'when procedure is archived' do
let(:procedure) { procedure_published }
it { expect(subject.status).to eq 401 }
end
end
describe 'GET #edit' do
let(:procedure) { create(:procedure, administrateur: admin) }
let(:published) { false }
let(:procedure) { create(:procedure, administrateur: admin, published: published) }
let(:procedure_id) { procedure.id }
subject { get :edit, id: procedure_id }
@ -66,8 +114,8 @@ describe Admin::ProceduresController, type: :controller do
it { expect(subject).to have_http_status(:success) }
end
context 'when procedure have at least a file' do
let!(:dossier) { create(:dossier, procedure: procedure, state: :initiated) }
context 'when procedure is published' do
let(:published) { true }
it { is_expected.to redirect_to admin_procedure_path id: procedure_id }
end
@ -192,7 +240,7 @@ describe Admin::ProceduresController, type: :controller do
it { expect(subject.cadastre).to be_truthy }
end
it { expect(subject).to redirect_to(admin_procedures_path) }
it { expect(subject).to redirect_to(edit_admin_procedure_path id: procedure.id) }
it { expect(flash[:notice]).to be_present }
end
@ -258,4 +306,35 @@ describe Admin::ProceduresController, type: :controller do
it { expect(flash[:alert]).to have_content 'Procédure inéxistante' }
end
end
describe 'PUT #clone' do
let!(:procedure) { create(:procedure, administrateur: admin) }
subject { put :clone, procedure_id: procedure.id }
it { expect { subject }.to change(Procedure, :count).by(1) }
context 'when admin is the owner of the procedure' do
before do
subject
end
it 'creates a new procedure and redirect to it' do
expect(response).to redirect_to edit_admin_procedure_path(id: Procedure.last.id)
expect(flash[:notice]).to have_content 'Procédure clonée'
end
end
context 'when admin is not the owner of the procedure' do
let(:admin_2) { create(:administrateur) }
before do
sign_out admin
sign_in admin_2
subject
end
it { expect(response).to redirect_to :admin_procedures }
it { expect(flash[:alert]).to have_content 'Procédure inéxistante' }
end
end
end

View file

@ -9,7 +9,8 @@ describe Admin::TypesDeChampController, type: :controller do
end
describe 'GET #show' do
let(:procedure) { create(:procedure, administrateur: admin) }
let(:published) { false }
let(:procedure) { create(:procedure, administrateur: admin, published: published) }
let(:procedure_id) { procedure.id }
subject { get :show, procedure_id: procedure_id }
@ -19,8 +20,8 @@ describe Admin::TypesDeChampController, type: :controller do
it { expect(subject.status).to eq(404) }
end
context 'when procedure have at least a file' do
let!(:dossier) { create(:dossier, procedure: procedure, state: :initiated) }
context 'when procedure is published' do
let(:published) { true }
it { is_expected.to redirect_to admin_procedure_path id: procedure_id }
end

View file

@ -116,7 +116,7 @@ describe API::V1::DossiersController do
let!(:dossier) { Timecop.freeze(date_creation) { create(:dossier, :with_entreprise, procedure: procedure) } }
let(:dossier_id) { dossier.id }
let(:body) { JSON.parse(retour.body, symbolize_names: true) }
let(:field_list) { [:id, :nom_projet, :created_at, :updated_at, :description, :archived, :mandataire_social, :entreprise, :etablissement, :cerfa, :types_de_piece_justificative, :pieces_justificatives, :champs, :commentaires] }
let(:field_list) { [:id, :nom_projet, :created_at, :updated_at, :archived, :mandataire_social, :entreprise, :etablissement, :cerfa, :types_de_piece_justificative, :pieces_justificatives, :champs, :commentaires] }
subject { body[:dossier] }
it 'return REST code 200', :show_in_doc do
@ -126,7 +126,6 @@ describe API::V1::DossiersController do
it { expect(subject[:nom_projet]).to eq(dossier.nom_projet) }
it { expect(subject[:created_at]).to eq('2008-09-01T08:05:00.000Z') }
it { expect(subject[:updated_at]).to eq('2008-09-01T08:05:00.000Z') }
it { expect(subject[:description]).to eq(dossier.description) }
it { expect(subject[:archived]).to eq(dossier.archived) }
it { expect(subject[:mandataire_social]).to eq(dossier.mandataire_social) }

View file

@ -91,5 +91,17 @@ describe Backoffice::CommentairesController, type: :controller do
end
end
end
describe 'comment cannot be saved' do
before do
allow_any_instance_of(Commentaire).to receive(:save).and_return(false)
end
it 'Notification email is not sent' do
expect(NotificationMailer).not_to receive(:new_answer)
expect(NotificationMailer).not_to receive(:deliver_now!)
post :create, dossier_id: dossier_id, texte_commentaire: texte_commentaire
end
end
end
end

Some files were not shown because too many files have changed in this diff Show more