Merge branch 'dev'

This commit is contained in:
gregoirenovel 2018-05-24 17:28:45 +02:00
commit 3e27b761ec
62 changed files with 553 additions and 315 deletions

View file

@ -10,15 +10,6 @@ class Admin::AccompagnateursController < AdminController
def show
assign_scope = @procedure.gestionnaires
# FIXME: remove this comment (no code to remove) when
# https://github.com/Sology/smart_listing/issues/134
# is fixed.
#
# No need to permit parameters for smart_listing, because
# there are no sortable columns
#
# END OF FIXME
@accompagnateurs_assign = smart_listing_create :accompagnateurs_assign,
assign_scope,
partial: "admin/accompagnateurs/list_assign",
@ -27,15 +18,6 @@ class Admin::AccompagnateursController < AdminController
not_assign_scope = current_administrateur.gestionnaires.where.not(id: assign_scope.ids)
not_assign_scope = not_assign_scope.where("email LIKE ?", "%#{params[:filter]}%") if params[:filter]
# FIXME: remove this comment (no code to remove) when
# https://github.com/Sology/smart_listing/issues/134
# is fixed.
#
# No need to permit parameters for smart_listing, because
# there are no sortable columns
#
# END OF FIXME
@accompagnateurs_not_assign = smart_listing_create :accompagnateurs_not_assign,
not_assign_scope,
partial: "admin/accompagnateurs/list_not_assign",

View file

@ -3,12 +3,6 @@ class Admin::GestionnairesController < AdminController
helper SmartListing::Helper
def index
# FIXME: remove when
# https://github.com/Sology/smart_listing/issues/134
# is fixed
permit_smart_listing_params
# END OF FIXME
@gestionnaires = smart_listing_create :gestionnaires,
current_administrateur.gestionnaires,
partial: "admin/gestionnaires/list",

View file

@ -5,12 +5,6 @@ class Admin::ProceduresController < AdminController
before_action :retrieve_procedure, only: [:show, :edit]
def index
# FIXME: remove when
# https://github.com/Sology/smart_listing/issues/134
# is fixed
permit_smart_listing_params
# END OF FIXME
@procedures = smart_listing_create :procedures,
current_administrateur.procedures.publiees.order(published_at: :desc),
partial: "admin/procedures/list",
@ -20,12 +14,6 @@ class Admin::ProceduresController < AdminController
end
def archived
# FIXME: remove when
# https://github.com/Sology/smart_listing/issues/134
# is fixed
permit_smart_listing_params
# END OF FIXME
@procedures = smart_listing_create :procedures,
current_administrateur.procedures.archivees.order(published_at: :desc),
partial: "admin/procedures/list",
@ -37,12 +25,6 @@ class Admin::ProceduresController < AdminController
end
def draft
# FIXME: remove when
# https://github.com/Sology/smart_listing/issues/134
# is fixed
permit_smart_listing_params
# END OF FIXME
@procedures = smart_listing_create :procedures,
current_administrateur.procedures.brouillons.order(created_at: :desc),
partial: "admin/procedures/list",
@ -127,22 +109,15 @@ class Admin::ProceduresController < AdminController
return redirect_to admin_procedures_path
end
procedure_path = ProcedurePath.find_by(path: params[:procedure_path])
if procedure_path
if procedure_path.administrateur_id == current_administrateur.id
procedure_path.procedure.archive
procedure_path.delete
else
@mine = false
return render '/admin/procedures/publish', formats: 'js'
end
end
if procedure.may_publish?(params[:procedure_path])
procedure.publish!(params[:procedure_path])
flash.notice = "Procédure publiée"
render js: "window.location = '#{admin_procedures_path}'"
redirect_to admin_procedures_path
else
@mine = false
render '/admin/procedures/publish', formats: 'js'
end
rescue ActiveRecord::RecordNotFound
flash.alert = 'Procédure inexistante'
redirect_to admin_procedures_path
@ -167,7 +142,7 @@ class Admin::ProceduresController < AdminController
def archive
procedure = current_administrateur.procedures.find(params[:procedure_id])
procedure.archive
procedure.archive!
flash.notice = "Procédure archivée"
redirect_to admin_procedures_path

View file

@ -56,6 +56,10 @@ class ApplicationController < ActionController::Base
end
end
def after_sign_out_path_for(_resource_or_scope)
stored_location_for(:user) || super
end
private
def set_active_storage_host
@ -113,37 +117,6 @@ class ApplicationController < ActionController::Base
end
end
def permit_smart_listing_params
# FIXME: remove when
# https://github.com/Sology/smart_listing/issues/134
# is fixed
self.params = params.permit(
# Dossiers
:liste,
dossiers_smart_listing:
[
:page,
:per_page,
{ sort: [:id, :'procedure.libelle', :state, :updated_at] }
],
# Gestionnaires
gestionnaires_smart_listing:
[
:page,
:per_page,
{ sort: [:email] }
],
# Procédures
procedures_smart_listing:
[
:page,
:per_page,
{ sort: [:id, :libelle, :published_at] }
]
)
# END OF FIXME
end
def reject
authorized_request =
request.path_info == '/' ||

View file

@ -0,0 +1,26 @@
class DemandesController < ApplicationController
layout "new_application"
def new
end
def create
PipedriveService.add_demande(
demande_params[:email],
demande_params[:phone],
demande_params[:name],
demande_params[:poste],
demande_params[:source],
demande_params[:organization_name],
demande_params[:address]
)
flash.notice = 'Votre demande a bien été enregistrée, nous vous contacterons rapidement.'
redirect_to root_path
end
private
def demande_params
params.permit(:organization_name, :poste, :name, :email, :phone, :source, :address)
end
end

View file

@ -15,6 +15,7 @@ class FranceConnect::ParticulierController < ApplicationController
if fci.user.nil?
user = User.find_or_create_by(email: fci.email_france_connect) do |new_user|
new_user.password = Devise.friendly_token[0, 20]
new_user.confirmed_at = DateTime.now
end
fci.update_attribute('user_id', user.id)

View file

@ -89,7 +89,7 @@ module NewGestionnaire
if gestionnaire.save
user = User.find_by(email: email)
if user.blank?
user = User.create(email: email, password: password)
user = User.create(email: email, password: password, confirmed_at: DateTime.now)
end
sign_in(user)

View file

@ -98,6 +98,13 @@ module NewUser
end
end
def ask_deletion
@dossier = current_user.dossiers.find(params[:id])
DossierMailer.ask_deletion(@dossier).deliver_later
flash.notice = 'Une demande de suppression de votre dossier a été envoyée, elle sera traitée dans les plus brefs délais.'
redirect_to users_dossier_recapitulatif_path(@dossier)
end
private
def page

View file

@ -0,0 +1,38 @@
# frozen_string_literal: true
class Users::ConfirmationsController < Devise::ConfirmationsController
# GET /resource/confirmation/new
# def new
# super
# end
# POST /resource/confirmation
# def create
# super
# end
# GET /resource/confirmation?confirmation_token=abcdef
# def show
# super
# end
protected
# The path used after resending confirmation instructions.
# def after_resending_confirmation_instructions_path_for(resource_name)
# super(resource_name)
# end
# The path used after confirmation.
def after_confirmation_path_for(resource_name, resource)
check_invite!(resource)
super(resource_name, resource)
end
private
def check_invite!(user)
Invite.where(email: user.email).update_all user_id: user.id
end
end

View file

@ -2,6 +2,9 @@ class Users::DossiersController < UsersController
include SmartListing::Helper::ControllerExtensions
helper SmartListing::Helper
SESSION_USER_RETURN_LOCATION = 'user_return_to'
before_action :store_user_location!, only: :new
before_action :authenticate_user!, except: :commencer
before_action :check_siret, only: :siret_informations
@ -29,12 +32,6 @@ class Users::DossiersController < UsersController
return redirect_to users_dossiers_path
end
# FIXME: remove when
# https://github.com/Sology/smart_listing/issues/134
# is fixed
permit_smart_listing_params
# END OF FIXME
@dossiers = smart_listing_create :dossiers,
@dossiers_filtered,
partial: "users/dossiers/list",
@ -43,7 +40,7 @@ class Users::DossiersController < UsersController
def commencer_test
procedure_path = ProcedurePath.find_by(path: params[:procedure_path])
procedure = procedure_path.test_procedure
procedure = procedure_path&.test_procedure
if procedure.present?
redirect_to new_users_dossier_path(procedure_id: procedure.id)
@ -55,7 +52,7 @@ class Users::DossiersController < UsersController
def commencer
procedure_path = ProcedurePath.find_by(path: params[:procedure_path])
procedure = procedure_path.procedure
procedure = procedure_path&.procedure
if procedure.present?
if procedure.archivee?
@ -72,6 +69,8 @@ class Users::DossiersController < UsersController
end
def new
erase_user_location!
procedure = Procedure.publiees.find(params[:procedure_id])
dossier = Dossier.create(procedure: procedure, user: current_user, state: 'brouillon')
@ -240,4 +239,12 @@ class Users::DossiersController < UsersController
def facade(id = params[:id])
DossierFacades.new id, current_user.email
end
def store_user_location!
store_location_for(:user, request.fullpath)
end
def erase_user_location!
session.delete(SESSION_USER_RETURN_LOCATION)
end
end

View file

@ -4,12 +4,9 @@ class Users::RegistrationsController < Devise::RegistrationsController
# before_action :configure_sign_up_params, only: [:create]
# before_action :configure_account_update_params, only: [:update]
def after_sign_up_path_for(resource_or_scope)
WelcomeMailer.welcome_email(resource_or_scope).deliver_now!
check_invite! resource_or_scope
super
end
# def after_sign_up_path_for(resource_or_scope)
# super
# end
# GET /resource/sign_up
# def new
@ -18,8 +15,15 @@ class Users::RegistrationsController < Devise::RegistrationsController
# POST /resource
def create
user = User.find_by(email: params[:user][:email])
if user.present?
UserMailer.new_account_warning(user).deliver
flash.notice = t('devise.registrations.signed_up_but_unconfirmed')
redirect_to root_path
else
super
end
end
# GET /resource/edit
# def edit
@ -66,10 +70,4 @@ class Users::RegistrationsController < Devise::RegistrationsController
# def after_inactive_sign_up_path_for(resource)
# super(resource)
# end
private
def check_invite!(user)
Invite.where(email: user.email).update_all user_id: user.id
end
end

View file

@ -7,7 +7,7 @@ class AutoArchiveProcedureJob < ApplicationJob
dossier.en_instruction!
end
procedure.archive
procedure.archive!
end
end
end

View file

@ -2,6 +2,7 @@ class Pipedrive::API
PIPEDRIVE_ALL_NOT_DELETED_DEALS = 'all_not_deleted'
PIPEDRIVE_DEALS_URL = [PIPEDRIVE_API_URL, 'deals'].join("/")
PIPEDRIVE_PEOPLE_URL = [PIPEDRIVE_API_URL, 'persons'].join("/")
PIPEDRIVE_ORGANIZATIONS_URL = [PIPEDRIVE_API_URL, 'organizations'].join("/")
def self.get_persons_owned_by_user(user_id)
url = PIPEDRIVE_PEOPLE_URL
@ -23,12 +24,24 @@ class Pipedrive::API
self.put(url, params)
end
def self.post_deal(params)
self.post(PIPEDRIVE_DEALS_URL, params)
end
def self.put_person(person_id, params)
url = [PIPEDRIVE_PEOPLE_URL, person_id].join("/")
self.put(url, params)
end
def self.post_person(params)
self.post(PIPEDRIVE_PEOPLE_URL, params)
end
def self.post_organization(params)
self.post(PIPEDRIVE_ORGANIZATIONS_URL, params)
end
private
def self.get(url, params)
@ -47,4 +60,10 @@ class Pipedrive::API
RestClient.put(url, params.to_json, { content_type: :json })
end
def self.post(url, params)
url = "#{url}?api_token=#{PIPEDRIVE_TOKEN}"
RestClient.post(url, params.to_json, { content_type: :json })
end
end

View file

@ -33,4 +33,15 @@ class Pipedrive::DealAdapter
Pipedrive::API.put_deal(deal_id, params)
end
def self.add_deal(organisation_id, person_id, title)
params = {
org_id: organisation_id,
person_id: person_id,
title: title,
user_id: Pipedrive::PersonAdapter::PIPEDRIVE_ROBOT_ID
}
Pipedrive::API.post_deal(params)
end
end

View file

@ -0,0 +1,13 @@
class Pipedrive::OrganizationAdapter
def self.add_organization(name, address)
params = {
name: name,
owner_id: Pipedrive::PersonAdapter::PIPEDRIVE_ROBOT_ID,
address: address
}
response = Pipedrive::API.post_organization(params)
JSON.parse(response.body)['data']['id']
end
end

View file

@ -1,5 +1,6 @@
class Pipedrive::PersonAdapter
PIPEDRIVE_POSTE_ATTRIBUTE_ID = '33a790746f1713d712fe97bcce9ac1ca6374a4d6'
PIPEDRIVE_SOURCE_ATTRIBUTE_ID = '2fa7864f467ffa97721cbcd08df5a3d591b15f50'
PIPEDRIVE_ROBOT_ID = '2748449'
def self.get_demandes_from_persons_owned_by_robot
@ -19,4 +20,20 @@ class Pipedrive::PersonAdapter
Pipedrive::API.put_person(person_id, params)
end
def self.add_person(email, phone, name, organization_id, poste, source)
params = {
email: email,
phone: phone,
name: name,
org_id: organization_id,
owner_id: PIPEDRIVE_ROBOT_ID,
"#{PIPEDRIVE_POSTE_ATTRIBUTE_ID}": poste,
"#{PIPEDRIVE_SOURCE_ATTRIBUTE_ID}": source
}
response = Pipedrive::API.post_person(params)
JSON.parse(response.body)['data']['id']
end
end

View file

@ -0,0 +1,6 @@
class DeviseUserMailer < Devise::Mailer
helper :application # gives access to all helpers defined within `application_helper`.
include Devise::Controllers::UrlHelpers # Optional. eg. `confirmation_url`
default template_path: 'devise/mailer' # to make sure that your mailer uses the devise views
layout 'mailers/layout'
end

View file

@ -0,0 +1,8 @@
class DossierMailer < ApplicationMailer
layout 'mailers/layout'
def ask_deletion(dossier)
@dossier = dossier
mail(to: "contact@demarches-simplifiees.fr", subject: "Demande de suppression de dossier")
end
end

View file

@ -0,0 +1,8 @@
class UserMailer < ApplicationMailer
layout 'mailers/layout'
def new_account_warning(user)
@user = user
mail(to: user.email, subject: "Création de compte")
end
end

View file

@ -1,8 +0,0 @@
class WelcomeMailer < ApplicationMailer
def welcome_email(user)
@user = user
mail(to: user.email,
subject: "Création de votre compte demarches-simplifiees.fr")
end
end

View file

@ -101,6 +101,10 @@ class Administrateur < ApplicationRecord
save
end
def owns?(procedure)
id == procedure.administrateur_id
end
private
def generate_api_token

View file

@ -45,6 +45,77 @@ class Procedure < ApplicationRecord
validates :libelle, presence: true, allow_blank: false, allow_nil: false
validates :description, presence: true, allow_blank: false, allow_nil: false
include AASM
aasm whiny_persistence: true do
state :brouillon, initial: true
state :publiee
state :archivee
state :hidden
event :publish, after: :after_publish, guard: :can_publish? do
transitions from: :brouillon, to: :publiee
transitions from: :archivee, to: :publiee
end
event :archive, after: :after_archive do
transitions from: :publiee, to: :archivee
end
event :hide, after: :after_hide do
transitions from: :brouillon, to: :hidden
transitions from: :publiee, to: :hidden
transitions from: :archivee, to: :hidden
end
end
def after_publish(path)
now = Time.now
update(
test_started_at: now,
archived_at: nil,
published_at: now
)
procedure_path = ProcedurePath.find_by(path: path)
if procedure_path.present?
if procedure_path.procedure != self
procedure_path.procedure.archive!
procedure_path.update(procedure: self)
end
else
ProcedurePath.create(procedure: self, administrateur: administrateur, path: path)
end
end
def after_archive
update(archived_at: Time.now)
end
def after_hide
now = Time.now
update(hidden_at: now)
procedure_path&.hide!(self)
dossiers.update_all(hidden_at: now)
end
def locked?
publiee_ou_archivee?
end
def publiee_ou_archivee?
publiee? || archivee?
end
def can_publish?(path)
procedure_path = ProcedurePath.find_by(path: path)
if procedure_path.present?
administrateur.owns?(procedure_path)
else
true
end
end
# Warning: dossier after_save build_default_champs must be removed
# to save a dossier created from this method
def new_dossier
@ -63,13 +134,6 @@ class Procedure < ApplicationRecord
ProcedurePath.find_with_procedure(self)
end
def hide!
now = DateTime.now
update(hidden_at: now, aasm_state: :hidden)
procedure_path&.hide!(self)
dossiers.update_all(hidden_at: now)
end
def path
procedure_path.path if procedure_path.present?
end
@ -120,10 +184,6 @@ class Procedure < ApplicationRecord
end
end
def locked?
publiee_ou_archivee?
end
def clone(admin, from_library)
procedure = self.deep_clone(include:
{
@ -161,32 +221,6 @@ class Procedure < ApplicationRecord
procedure
end
def brouillon?
published_at.nil?
end
def publish!(path)
now = Time.now
self.update!({ test_started_at: now, published_at: now, archived_at: nil, aasm_state: :publiee })
ProcedurePath.create!(path: path, procedure: self, administrateur: self.administrateur)
end
def publiee?
published_at.present? && archived_at.nil?
end
def archive
self.update!(archived_at: Time.now, aasm_state: :archivee)
end
def archivee?
published_at.present? && archived_at.present?
end
def publiee_ou_archivee?
publiee? || archivee?
end
def whitelisted?
whitelisted_at.present?
end

View file

@ -10,7 +10,7 @@ class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
:recoverable, :rememberable, :trackable, :validatable, :confirmable
has_many :dossiers, dependent: :destroy
has_many :invites, dependent: :destroy

View file

@ -14,4 +14,10 @@ class PipedriveService
def self.get_demandes
Pipedrive::PersonAdapter.get_demandes_from_persons_owned_by_robot
end
def self.add_demande(email, phone, name, poste, source, organization_name, address)
organization_id = Pipedrive::OrganizationAdapter.add_organization(organization_name, address)
person_id = Pipedrive::PersonAdapter.add_person(email, phone, name, organization_id, poste, source)
Pipedrive::DealAdapter.add_deal(organization_id, person_id, organization_name)
end
end

View file

@ -0,0 +1,43 @@
.container
%h1 Demande de compte administrateur
%p Pour obtenir un compte administrateur sur demarches-simplifiees.fr, veuillez remplir le formulaire ci-dessous et un membre de notre équipe vous contactera très prochainement.
%p Tous les champs sont obligatoires.
= form_tag({ controller: 'demandes', action: 'create' }, class: 'form') do
= label_tag :organization_name do
Quel est le nom de votre organisme ?
%span.mandatory *
= text_field_tag :organization_name, nil, placeholder: 'service jeunesse et prévention, direction des affaires maritimes', required: true
= label_tag :poste do
Quel est votre poste ?
%span.mandatory *
= text_field_tag :poste, nil, required: true
= label_tag :name do
Quel est votre prénom et votre nom ?
%span.mandatory *
= text_field_tag :name, nil, required: true
= label_tag :email do
Quelle est l'adresse email pour laquelle vous souhaitez un compte ?
%span.mandatory *
= email_field_tag :email, nil, required: true
= label_tag :phone do
Quel est votre numéro de téléphone ?
%span.mandatory *
= text_field_tag :phone, nil, required: true
= label_tag :source do
Comment avez-vous entendu parlé de demarches-simplifiees.fr ?
%span.mandatory *
= text_field_tag :source, nil, required: true
= label_tag :address do
Quel est le code postal de votre institution ?
%span.mandatory *
= text_field_tag :address, nil, required: true
= submit_tag 'Envoyer', class: 'button', data: { disable_with: "Envoi..." }

View file

@ -0,0 +1,10 @@
- content_for(:title, 'Activez votre compte')
%p Bonjour #{@user.email},
%p
Pour activer votre compte sur demarches-simplifiees.fr, veuillez cliquer sur le lien suivant :
= link_to(confirmation_url(@user, confirmation_token: @token), confirmation_url(@user, confirmation_token: @token))
%p Bonne journée,
%p L'équipe demarches-simplifiees.fr

View file

@ -0,0 +1,12 @@
- content_for(:title, 'Demande de suppression de dossier')
%h1 Bonjour
%p
Une demande de suppression a été effectuée pour le dossier
= @dossier.id
par l'utilisateur
= @dossier.user.email
\.
%p
Merci de le notifier quand cela est fait.

View file

@ -13,3 +13,9 @@
.split-hr-left
.dossier-state= @facade.dossier.display_state
.split-hr-left
.text-center.mt-1
= link_to ask_deletion_dossier_path(@facade.dossier), method: :post, class:"btn btn-danger", data: { confirm: "Confirmez-vous la demande de suppression de ce dossier ?" } do
Demander la suppression
%br
du dossier

View file

@ -67,7 +67,7 @@
%p.role-panel-explanation Créez des formulaires en ligne en quelques minutes et instruisez les demandes des usagers sur une plateforme dédiée
= link_to "Demander un compte",
"https://pipedrivewebforms.com/form/c4a5de08b0a1dcc92374e853aa11905a1871869",
new_demande_path,
class: "role-panel-button-primary",
target: "_blank",
rel: "noopener noreferrer",

View file

@ -0,0 +1,14 @@
- content_for(:title, 'Demande de création de compte')
%h1 Bonjour
%p Une demande de création de compte a été réalisée sur le site demarches-simplifiees.fr pour l'email #{@user.email}.
%p
Votre compte existe déjà. Si vous souhaitez changer votre mot de passe, veuillez suivre les instructions à l'adresse suivante
#{link_to(new_password_url(@user), new_password_url(@user))}.
%p Si vous n'êtes pas à l'origine de cette demande, vous pouvez ignorer ce mail.
%p
Cordialement,
%br
L'équipe demarches-simplifiees.fr

View file

@ -1,14 +0,0 @@
Bienvenue sur demarches-simplifiees.fr,
Nous vous remercions de vous être inscrit sur demarches-simplifiees.fr. Pour mémoire, voici quelques informations utiles :
URL : <%= root_url %>
Login : <%= @user.email %>
Oubli de mot de passe, pas de problème :
<%= new_user_password_url %>
Bonne journée,
L'équipe demarches-simplifiees.fr

View file

@ -13,7 +13,7 @@ Devise.setup do |config|
config.mailer_sender = "demarches-simplifiees.fr <#{I18n.t('dynamics.contact_email')}>"
# Configure the class responsible to send e-mails.
# config.mailer = 'Devise::Mailer'
config.mailer = 'DeviseUserMailer'
# ==> ORM configuration
# Load and configure the ORM. Supports :active_record (default) and
@ -70,7 +70,7 @@ Devise.setup do |config|
# It will change confirmation, password recovery and other workflows
# to behave the same regardless if the e-mail provided was right or wrong.
# Does not affect registerable.
# config.paranoid = true
config.paranoid = true
# By default Devise will store the user in session. You can skip storage for
# particular strategies by setting this option.
@ -119,7 +119,7 @@ Devise.setup do |config|
# initial account confirmation) to be applied. Requires additional unconfirmed_email
# db field (see migrations). Until confirmed, new email is stored in
# unconfirmed_email column, and copied to email column on successful confirmation.
config.reconfirmable = true
config.reconfirmable = false
# Defines which key will be used when confirming an account
# config.confirmation_keys = [ :email ]

View file

@ -86,6 +86,8 @@ fr:
delimiter: ''
activerecord:
errors:
messages:
blank: "doit être rempli"
models:
attestation_template:
attributes:

View file

@ -1,8 +0,0 @@
fr:
activerecord:
errors:
models:
administrateur:
attributes:
email:
blank: 'doit être rempli'

View file

@ -15,17 +15,3 @@ fr:
refuse: "Refusé"
sans_suite: "Sans suite"
autorisation_donnees: Acceptation des CGU
errors:
models:
dossier:
attributes:
mail_contact:
blank: 'doit être rempli'
invalid: 'est incorrect'
montant_projet:
blank: 'doit être rempli'
montant_aide_demande:
blank: 'doit être rempli'
date_previsionnelle:
blank: 'doit être remplie'

View file

@ -6,15 +6,3 @@ fr:
nom: Nom
prenom: Prénom
birthdate: Date de naissance
errors:
models:
individual:
attributes:
gender:
blank: 'doit être rempli'
nom:
blank: 'doit être rempli'
prenom:
blank: 'doit être rempli'
birthdate:
blank: 'doit être rempli'

View file

@ -3,15 +3,3 @@ fr:
attributes:
procedure:
organisation: Organisme
errors:
models:
procedure:
attributes:
libelle:
blank: Attribut manquant
description:
blank: Attribut manquant
lien_demarche:
blank: Attribut manquant
organisation:
blank: Attribut manquant

View file

@ -43,7 +43,8 @@ Rails.application.routes.draw do
devise_for :users, controllers: {
sessions: 'users/sessions',
registrations: 'users/registrations',
passwords: 'users/passwords'
passwords: 'users/passwords',
confirmations: 'users/confirmations'
}
devise_scope :user do
@ -68,6 +69,7 @@ Rails.application.routes.draw do
resources :stats, only: [:index]
resources :accessibilite, only: [:index]
resources :demandes, only: [:new, :create]
namespace :france_connect do
get 'particulier' => 'particulier#login'
@ -224,6 +226,7 @@ Rails.application.routes.draw do
patch 'update_identite'
get 'modifier'
get 'merci'
post 'ask_deletion'
end
get 'attestation'
end

View file

@ -0,0 +1,18 @@
class AddConfirmableToUserDevise < ActiveRecord::Migration[5.2]
def up
add_column :users, :confirmation_token, :string
add_column :users, :confirmed_at, :datetime
add_column :users, :confirmation_sent_at, :datetime
add_index :users, :confirmation_token, unique: true
# User.reset_column_information # Need for some types of updates, but not for update_all.
# To avoid a short time window between running the migration and updating all existing
# users as confirmed, do the following
User.all.update_all confirmed_at: DateTime.now
# All existing user accounts should be able to log in after this.
end
def down
remove_columns :users, :confirmation_token, :confirmed_at, :confirmation_sent_at
# remove_columns :users, :unconfirmed_email # Only if using reconfirmable
end
end

View file

@ -0,0 +1,6 @@
class AddRetentionTimesToProcedure < ActiveRecord::Migration[5.2]
def change
add_column :procedures, :duree_conservation_dossiers_dans_ds, :integer
add_column :procedures, :duree_conservation_dossiers_hors_ds, :integer
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_16_155238) do
ActiveRecord::Schema.define(version: 2018_05_22_142109) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -469,6 +469,8 @@ ActiveRecord::Schema.define(version: 2018_05_16_155238) do
t.datetime "test_started_at"
t.string "aasm_state", default: "brouillon"
t.bigint "service_id"
t.integer "duree_conservation_dossiers_dans_ds"
t.integer "duree_conservation_dossiers_hors_ds"
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"
@ -571,6 +573,10 @@ ActiveRecord::Schema.define(version: 2018_05_16_155238) do
t.datetime "updated_at"
t.string "siret"
t.string "loged_in_with_france_connect", default: "false"
t.string "confirmation_token"
t.datetime "confirmed_at"
t.datetime "confirmation_sent_at"
t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end

View file

@ -2,8 +2,7 @@ require 'spec_helper'
describe Admin::PiecesJustificativesController, type: :controller do
let(:admin) { create(:administrateur) }
let(:published_at) { nil }
let(:procedure) { create(:procedure, administrateur: admin, published_at: published_at) }
let(:procedure) { create(:procedure, administrateur: admin) }
before do
sign_in admin
end
@ -19,7 +18,7 @@ describe Admin::PiecesJustificativesController, type: :controller do
end
context 'when procedure is published' do
let(:published_at) { Time.now }
let(:procedure) { create(:procedure, :published, administrateur: admin) }
it { is_expected.to redirect_to admin_procedure_path id: procedure_id }
end

View file

@ -92,8 +92,8 @@ describe Admin::ProceduresController, type: :controller do
describe 'DELETE #destroy' do
let(:procedure_draft) { create :procedure, administrateur: admin, published_at: nil, archived_at: nil }
let(:procedure_published) { create :procedure, administrateur: admin, published_at: Time.now, archived_at: nil }
let(:procedure_archived) { create :procedure, administrateur: admin, published_at: nil, archived_at: Time.now }
let(:procedure_published) { create :procedure, administrateur: admin, aasm_state: :publiee, published_at: Time.now, archived_at: nil }
let(:procedure_archived) { create :procedure, administrateur: admin, aasm_state: :archivee, published_at: nil, archived_at: Time.now }
subject { delete :destroy, params: { id: procedure.id } }
@ -344,7 +344,7 @@ describe Admin::ProceduresController, type: :controller do
it 'publish the given procedure' do
expect(procedure.publiee?).to be_truthy
expect(procedure.path).to eq(procedure_path)
expect(response.status).to eq 200
expect(response.status).to eq 302
expect(flash[:notice]).to have_content 'Procédure publiée'
end
end
@ -355,7 +355,7 @@ describe Admin::ProceduresController, type: :controller do
it 'publish the given procedure' do
expect(procedure.publiee?).to be_truthy
expect(procedure.path).to eq(procedure_path)
expect(response.status).to eq 200
expect(response.status).to eq 302
expect(flash[:notice]).to have_content 'Procédure publiée'
end
@ -432,8 +432,8 @@ describe Admin::ProceduresController, type: :controller do
procedure.reload
end
it { expect(procedure.archivee?).to be_falsey }
it { expect(response.status).to eq 200 }
it { expect(procedure.publiee?).to be_truthy }
it { expect(response.status).to eq 302 }
it { expect(flash[:notice]).to have_content 'Procédure publiée' }
end
end

View file

@ -9,8 +9,7 @@ describe Admin::TypesDeChampController, type: :controller do
end
describe 'GET #show' do
let(:published_at) { nil }
let(:procedure) { create(:procedure, administrateur: admin, published_at: published_at) }
let(:procedure) { create(:procedure, :published, administrateur: admin) }
let(:procedure_id) { procedure.id }
subject { get :show, params: { procedure_id: procedure_id } }
@ -21,7 +20,6 @@ describe Admin::TypesDeChampController, type: :controller do
end
context 'when procedure is published' do
let(:published_at) { Time.now }
it { is_expected.to redirect_to admin_procedure_path id: procedure_id }
end

View file

@ -9,8 +9,7 @@ describe Admin::TypesDeChampPrivateController, type: :controller do
end
describe 'GET #show' do
let(:published_at) { nil }
let(:procedure) { create(:procedure, administrateur: admin, published_at: published_at) }
let(:procedure) { create(:procedure, :published, administrateur: admin) }
let(:procedure_id) { procedure.id }
subject { get :show, params: { procedure_id: procedure_id } }
@ -21,7 +20,6 @@ describe Admin::TypesDeChampPrivateController, type: :controller do
end
context 'when procedure is published' do
let(:published_at) { Time.now }
it { is_expected.to redirect_to admin_procedure_path id: procedure_id }
end

View file

@ -99,7 +99,7 @@ describe NewGestionnaire::ProceduresController, type: :controller do
context "with procedures assigned" do
let(:procedure1) { create(:procedure, :published) }
let(:procedure2) { create(:procedure, :published, :archived) }
let(:procedure2) { create(:procedure, :archived) }
let(:procedure3) { create(:procedure) }
before do

View file

@ -384,4 +384,33 @@ describe NewUser::DossiersController, type: :controller do
end
end
end
describe '#ask_deletion' do
before { sign_in(user) }
subject { post :ask_deletion, params: { id: dossier.id } }
context 'when dossier is owned by signed in user' do
let(:dossier) { create(:dossier, user: user, autorisation_donnees: true) }
it do
expect(DossierMailer).to receive(:ask_deletion).and_return(double(deliver_later: nil))
subject
end
it { is_expected.to redirect_to(users_dossier_recapitulatif_path(dossier)) }
end
context 'when dossier is not owned by signed in user' do
let(:user2) { create(:user) }
let(:dossier) { create(:dossier, user: user2, autorisation_donnees: true) }
it do
expect(DossierMailer).not_to receive(:ask_deletion)
subject
end
it { is_expected.to redirect_to(root_path) }
end
end
end

View file

@ -46,7 +46,6 @@ describe Users::CommentairesController, type: :controller do
it 'Notification email is not send' do
expect(NotificationMailer).not_to receive(:new_answer)
expect(WelcomeMailer).not_to receive(:deliver_now!)
subject
end

View file

@ -0,0 +1,23 @@
describe Users::ConfirmationsController, type: :controller do
let(:email) { 'mail@beta.gouv.fr' }
let(:user) do
create(:user,
email: email,
password: 'a good password',
confirmation_token: '123',
confirmed_at: nil)
end
before { @request.env["devise.mapping"] = Devise.mappings[:user] }
describe '#check_invite!' do
let!(:invite) { create(:invite, email: email) }
let!(:invite2) { create(:invite, email: email) }
before { get :show, params: { confirmation_token: user.confirmation_token } }
it 'the new user is connect at his two invite' do
expect(User.last.invites.size).to eq(2)
end
end
end

View file

@ -26,7 +26,7 @@ shared_examples 'description_controller_spec' do
context 'procedure is archived' do
render_views
let(:archived_at) { Time.now }
let(:archived) { true }
it { expect(response).to have_http_status(:success) }
it { expect(response.body).to_not have_content(I18n.t('errors.messages.procedure_archived')) }
@ -329,7 +329,7 @@ shared_examples 'description_controller_spec' do
end
context 'La procédure est archivée' do
let(:archived_at) { Time.now }
let(:archived) { true }
before do
post :update, params: { dossier_id: dossier.id }

View file

@ -5,10 +5,15 @@ require 'controllers/users/description_controller_shared_example'
describe Users::DescriptionController, type: :controller, vcr: { cassette_name: 'controllers_users_description_controller' } do
let(:owner_user) { create(:user) }
let(:invite_by_user) { create :user, email: 'invite@plop.com' }
let(:archived_at) { nil }
let(:archived) { false }
let(:state) { 'en_construction' }
let(:procedure) { create(:procedure, :with_two_type_de_piece_justificative, :with_type_de_champ, :with_datetime, cerfa_flag: true, published_at: Time.now, archived_at: archived_at) }
let(:procedure) do
if archived
create(:procedure, :archived, :with_two_type_de_piece_justificative, :with_type_de_champ, :with_datetime, cerfa_flag: true)
else
create(:procedure, :published, :with_two_type_de_piece_justificative, :with_type_de_champ, :with_datetime, cerfa_flag: true)
end
end
let(:dossier) { create(:dossier, procedure: procedure, user: owner_user, state: state) }
let(:dossier_id) { dossier.id }

View file

@ -152,23 +152,26 @@ describe Users::DossiersController, type: :controller do
end
describe 'GET #commencer' do
subject { get :commencer, params: { procedure_path: procedure.path } }
subject { get :commencer, params: { procedure_path: path } }
let(:path) { procedure.path }
it { expect(subject.status).to eq 302 }
it { expect(subject).to redirect_to new_users_dossier_path(procedure_id: procedure.id) }
context 'when procedure is archived' do
let(:procedure) { create(:procedure, :published, archived_at: Time.now) }
before do
procedure.update_column :archived_at, Time.now
end
let(:procedure) { create(:procedure, :archived) }
it { expect(subject.status).to eq 200 }
end
context 'when procedure is hidden' do
let(:procedure) { create(:procedure, :published, hidden_at: DateTime.now) }
let(:procedure) { create(:procedure, :hidden) }
it { expect(subject).to redirect_to(root_path) }
end
context 'when procedure path dose not exist' do
let(:path) { 'hello' }
it { expect(subject).to redirect_to(root_path) }
end

View file

@ -1,5 +1,3 @@
require 'spec_helper'
describe Users::RegistrationsController, type: :controller do
let(:email) { 'test@octo.com' }
let(:password) { 'password' }
@ -11,38 +9,40 @@ describe Users::RegistrationsController, type: :controller do
end
describe '#create' do
subject { post :create, params: { user: user } }
subject do
post :create, params: { user: user }
end
context 'when user is correct' do
it 'sends welcome email' do
expect(WelcomeMailer).to receive(:welcome_email).and_return(WelcomeMailer)
expect(WelcomeMailer).to receive(:deliver_now!)
it 'sends confirmation instruction' do
expect(DeviseUserMailer).to receive(:confirmation_instructions).and_return(DeviseUserMailer)
expect(DeviseUserMailer).to receive(:deliver)
subject
end
describe '#check_invite!' do
let!(:invite) { create :invite, email: email }
let!(:invite2) { create :invite, email: email }
before do
subject
end
it 'the new user is connect at his two invite' do
expect(User.last.invites.size).to eq 2
end
end
end
context 'when user is not correct' do
let(:user) { { email: '', password: password } }
it 'not sends welcome email' do
expect(WelcomeMailer).not_to receive(:welcome_email)
it 'not sends confirmation instruction' do
expect(DeviseUserMailer).not_to receive(:confirmation_instructions)
subject
end
end
context 'when the user already exists' do
let!(:existing_user) { create(:user, email: email, password: password) }
before do
allow(UserMailer).to receive(:new_account_warning).and_return(double(deliver: 'deliver'))
subject
end
it { expect(response).to redirect_to(root_path) }
it { expect(flash.notice).to eq(I18n.t('devise.registrations.signed_up_but_unconfirmed')) }
it { expect(UserMailer).to have_received(:new_account_warning) }
end
end
end

View file

@ -100,14 +100,22 @@ FactoryBot.define do
end
trait :published do
after(:create) do |procedure, _evaluator|
after(:build) do |procedure, _evaluator|
procedure.publish!(generate(:published_path))
end
end
trait :archived do
after(:build) do |procedure, _evaluator|
procedure.archived_at = Time.now
procedure.publish!(generate(:published_path))
procedure.archive!
end
end
trait :hidden do
after(:build) do |procedure, _evaluator|
procedure.publish!(generate(:published_path))
procedure.hide!
end
end

View file

@ -3,5 +3,6 @@ FactoryBot.define do
factory :user do
email { generate(:user_email) }
password 'password'
confirmed_at DateTime.now
end
end

View file

@ -1,10 +1,10 @@
require 'rails_helper'
RSpec.describe AutoArchiveProcedureJob, type: :job do
let!(:procedure) { create(:procedure, published_at: Time.now, archived_at: nil, auto_archive_on: nil) }
let!(:procedure_hier) { create(:procedure, published_at: Time.now, archived_at: nil, auto_archive_on: 1.day.ago) }
let!(:procedure_aujourdhui) { create(:procedure, published_at: Time.now, archived_at: nil, auto_archive_on: Date.today) }
let!(:procedure_demain) { create(:procedure, published_at: Time.now, archived_at: nil, auto_archive_on: 1.day.from_now) }
let!(:procedure) { create(:procedure, :published, auto_archive_on: nil) }
let!(:procedure_hier) { create(:procedure, :published, auto_archive_on: 1.day.ago) }
let!(:procedure_aujourdhui) { create(:procedure, :published, auto_archive_on: Date.today) }
let!(:procedure_demain) { create(:procedure, :published, auto_archive_on: 1.day.from_now) }
subject { AutoArchiveProcedureJob.new.perform }

View file

@ -0,0 +1,9 @@
class DeviseUserMailerPreview < ActionMailer::Preview
def confirmation_instructions
DeviseUserMailer.confirmation_instructions(User.first, "faketoken", {})
end
def reset_password_instructions
DeviseUserMailer.reset_password_instructions(User.first, "faketoken", {})
end
end

View file

@ -0,0 +1,5 @@
class UserPreview < ActionMailer::Preview
def new_account_warning
UserMailer.new_account_warning(User.first)
end
end

View file

@ -1,15 +0,0 @@
require 'spec_helper'
describe WelcomeMailer, type: :mailer do
describe ".welcome_email" do
let(:user) { create(:user) }
subject(:subject) { described_class.welcome_email(user) }
it { expect(subject.body).to match(root_url) }
it { expect(subject.body).to match(new_user_password_url) }
it { expect(subject.body).to match(user.email) }
it { expect(subject.body).to match('Bienvenue sur demarches-simplifiees.fr') }
it { expect(subject.body).to match('Nous vous remercions de vous être inscrit sur demarches-simplifiees.fr. Pour mémoire, voici quelques informations utiles :') }
it { expect(subject.subject).to eq("Création de votre compte demarches-simplifiees.fr") }
end
end

View file

@ -213,17 +213,17 @@ describe Procedure do
end
describe 'locked?' do
let(:procedure) { create(:procedure, published_at: published_at) }
let(:procedure) { create(:procedure, aasm_state: aasm_state) }
subject { procedure.locked? }
context 'when procedure is in draft status' do
let(:published_at) { nil }
context 'when procedure is in brouillon status' do
let(:aasm_state) { :brouillon }
it { is_expected.to be_falsey }
end
context 'when procedure is in draft status' do
let(:published_at) { Time.now }
context 'when procedure is in publiee status' do
let(:aasm_state) { :publiee }
it { is_expected.to be_truthy }
end
end
@ -379,8 +379,8 @@ describe Procedure do
describe "#brouillon?" do
let(:procedure_brouillon) { Procedure.new() }
let(:procedure_publiee) { Procedure.new(published_at: Time.now) }
let(:procedure_archivee) { Procedure.new(published_at: Time.now, archived_at: Time.now) }
let(:procedure_publiee) { Procedure.new(aasm_state: :publiee, published_at: Time.now) }
let(:procedure_archivee) { Procedure.new(aasm_state: :archivee, published_at: Time.now, archived_at: Time.now) }
it { expect(procedure_brouillon.brouillon?).to be_truthy }
it { expect(procedure_publiee.brouillon?).to be_falsey }
@ -389,8 +389,8 @@ describe Procedure do
describe "#publiee?" do
let(:procedure_brouillon) { Procedure.new() }
let(:procedure_publiee) { Procedure.new(published_at: Time.now) }
let(:procedure_archivee) { Procedure.new(published_at: Time.now, archived_at: Time.now) }
let(:procedure_publiee) { Procedure.new(aasm_state: :publiee, published_at: Time.now) }
let(:procedure_archivee) { Procedure.new(aasm_state: :archivee, published_at: Time.now, archived_at: Time.now) }
it { expect(procedure_brouillon.publiee?).to be_falsey }
it { expect(procedure_publiee.publiee?).to be_truthy }
@ -399,20 +399,18 @@ describe Procedure do
describe "#archivee?" do
let(:procedure_brouillon) { Procedure.new() }
let(:procedure_publiee) { Procedure.new(published_at: Time.now) }
let(:procedure_archivee) { Procedure.new(published_at: Time.now, archived_at: Time.now) }
let(:procedure_batarde) { Procedure.new(published_at: nil, archived_at: Time.now) }
let(:procedure_publiee) { Procedure.new(aasm_state: :publiee, published_at: Time.now) }
let(:procedure_archivee) { Procedure.new(aasm_state: :archivee, published_at: Time.now, archived_at: Time.now) }
it { expect(procedure_brouillon.archivee?).to be_falsey }
it { expect(procedure_publiee.archivee?).to be_falsey }
it { expect(procedure_archivee.archivee?).to be_truthy }
it { expect(procedure_batarde.archivee?).to be_falsey }
end
describe "#publiee_ou_archivee?" do
let(:procedure_brouillon) { Procedure.new() }
let(:procedure_publiee) { Procedure.new(published_at: Time.now) }
let(:procedure_archivee) { Procedure.new(published_at: Time.now, archived_at: Time.now) }
let(:procedure_publiee) { Procedure.new(aasm_state: :publiee, published_at: Time.now) }
let(:procedure_archivee) { Procedure.new(aasm_state: :archivee, published_at: Time.now, archived_at: Time.now) }
it { expect(procedure_brouillon.publiee_ou_archivee?).to be_falsey }
it { expect(procedure_publiee.publiee_ou_archivee?).to be_truthy }
@ -425,7 +423,7 @@ describe Procedure do
let(:now) { Time.now.beginning_of_minute }
before do
Timecop.freeze(now)
procedure.archive
procedure.archive!
procedure.reload
end
after { Timecop.return }

View file

@ -1,8 +1,7 @@
require 'spec_helper'
describe 'admin/_closed_mail_template_attestation_inconsistency_alert.html.haml', type: :view do
let(:procedure) { create(:procedure, closed_mail: closed_mail, published_at: published_at) }
let(:published_at) { nil }
let(:procedure) { create(:procedure, closed_mail: closed_mail) }
def alert
assign(:procedure, procedure)
@ -32,7 +31,7 @@ describe 'admin/_closed_mail_template_attestation_inconsistency_alert.html.haml'
it { expect(alert).to include(edit_admin_procedure_mail_template_path(procedure, Mails::ClosedMail::SLUG)) }
context 'when the procedure has been published, the attestation cannot be deactivated' do
let(:published_at) { Time.now }
let(:procedure) { create(:procedure, :published, closed_mail: closed_mail) }
it { expect(procedure.locked?).to be_truthy }
it { expect(alert).not_to include(edit_admin_procedure_attestation_template_path(procedure)) }

View file

@ -61,7 +61,7 @@ describe 'admin/procedures/show.html.haml', type: :view do
describe 'procedure is archived' do
before do
procedure.publish!('fake_path')
procedure.archive
procedure.archive!
procedure.reload
render
end