Merge branch 'dev'

This commit is contained in:
Frederic Merizen 2018-05-31 17:07:02 +02:00
commit d28d467aea
34 changed files with 402 additions and 124 deletions

View file

@ -217,6 +217,15 @@ class Admin::ProceduresController < AdminController
render json: json_path_list render json: json_path_list
end end
def delete_deliberation
procedure = Procedure.find(params[:id])
procedure.deliberation.purge_later
flash.notice = 'la délibération a bien été supprimée'
redirect_to edit_admin_procedure_path(procedure)
end
private private
def cloned_from_library? def cloned_from_library?
@ -224,7 +233,7 @@ class Admin::ProceduresController < AdminController
end end
def procedure_params def procedure_params
editable_params = [:libelle, :description, :organisation, :direction, :lien_site_web, :notice, :web_hook_url, :euro_flag, :logo, :auto_archive_on] editable_params = [:libelle, :description, :organisation, :direction, :lien_site_web, :cadre_juridique, :deliberation, :notice, :web_hook_url, :euro_flag, :logo, :auto_archive_on]
if @procedure&.locked? if @procedure&.locked?
params.require(:procedure).permit(*editable_params) params.require(:procedure).permit(*editable_params)
else else

View file

@ -0,0 +1,4 @@
module Manager
class DossiersController < Manager::ApplicationController
end
end

View file

@ -0,0 +1,4 @@
module Manager
class GestionnairesController < Manager::ApplicationController
end
end

View file

@ -0,0 +1,4 @@
module Manager
class UsersController < Manager::ApplicationController
end
end

View file

@ -73,7 +73,7 @@ module NewUser
@dossier.en_construction! @dossier.en_construction!
NotificationMailer.send_initiated_notification(@dossier).deliver_later NotificationMailer.send_initiated_notification(@dossier).deliver_later
redirect_to merci_dossier_path(@dossier) redirect_to merci_dossier_path(@dossier)
elsif owns_dossier? elsif current_user.owns?(dossier)
redirect_to users_dossier_recapitulatif_path(@dossier) redirect_to users_dossier_recapitulatif_path(@dossier)
else else
redirect_to users_dossiers_invite_path(@dossier.invite_for_user(current_user)) redirect_to users_dossiers_invite_path(@dossier.invite_for_user(current_user))
@ -142,19 +142,19 @@ module NewUser
end end
def ensure_ownership! def ensure_ownership!
if !owns_dossier? if !current_user.owns?(dossier)
forbidden! forbidden!
end end
end end
def ensure_ownership_or_invitation! def ensure_ownership_or_invitation!
if !dossier.owner_or_invite?(current_user) if !current_user.owns_or_invite?(dossier)
forbidden! forbidden!
end end
end end
def forbid_invite_submission! def forbid_invite_submission!
if passage_en_construction? && !owns_dossier? if passage_en_construction? && !current_user.owns?(dossier)
forbidden! forbidden!
end end
end end
@ -172,10 +172,6 @@ module NewUser
params.require(:dossier).permit(:autorisation_donnees) params.require(:dossier).permit(:autorisation_donnees)
end end
def owns_dossier?
dossier.user_id == current_user.id
end
def passage_en_construction? def passage_en_construction?
dossier.brouillon? && !draft? dossier.brouillon? && !draft?
end end

View file

@ -10,7 +10,7 @@ class UsersController < ApplicationController
dossier = Dossier.find(dossier_id) dossier = Dossier.find(dossier_id)
if !dossier.owner_or_invite?(current_user) if !current_user.owns_or_invite?(dossier)
raise ActiveRecord::RecordNotFound raise ActiveRecord::RecordNotFound
end end

View file

@ -0,0 +1,54 @@
require "administrate/base_dashboard"
class DossierDashboard < Administrate::BaseDashboard
# ATTRIBUTE_TYPES
# a hash that describes the type of each of the model's fields.
#
# Each different type represents an Administrate::Field object,
# which determines how the attribute is displayed
# on pages throughout the dashboard.
ATTRIBUTE_TYPES = {
id: Field::Number,
procedure: Field::HasOne,
state: Field::String,
text_summary: Field::String,
created_at: Field::DateTime,
updated_at: Field::DateTime,
types_de_champ: TypesDeChampCollectionField,
}.freeze
# COLLECTION_ATTRIBUTES
# an array of attributes that will be displayed on the model's index page.
#
# By default, it's limited to four items to reduce clutter on index pages.
# Feel free to add, remove, or rearrange items.
COLLECTION_ATTRIBUTES = [
:id,
:procedure,
:created_at,
:state
].freeze
# SHOW_PAGE_ATTRIBUTES
# an array of attributes that will be displayed on the model's show page.
SHOW_PAGE_ATTRIBUTES = [
:text_summary,
:state,
:procedure,
:types_de_champ,
:created_at,
:updated_at,
].freeze
# FORM_ATTRIBUTES
# an array of attributes that will be displayed
# on the model's form (`new` and `edit`) pages.
FORM_ATTRIBUTES = [].freeze
# Overwrite this method to customize how users are displayed
# across all pages of the admin dashboard.
#
# def display_resource(user)
# "User ##{user.id}"
# end
end

View file

@ -0,0 +1,50 @@
require "administrate/base_dashboard"
class GestionnaireDashboard < Administrate::BaseDashboard
# ATTRIBUTE_TYPES
# a hash that describes the type of each of the model's fields.
#
# Each different type represents an Administrate::Field object,
# which determines how the attribute is displayed
# on pages throughout the dashboard.
ATTRIBUTE_TYPES = {
id: Field::Number,
email: Field::String,
created_at: Field::DateTime,
updated_at: Field::DateTime,
current_sign_in_at: Field::DateTime,
dossiers: Field::HasMany,
}.freeze
# COLLECTION_ATTRIBUTES
# an array of attributes that will be displayed on the model's index page.
#
# By default, it's limited to four items to reduce clutter on index pages.
# Feel free to add, remove, or rearrange items.
COLLECTION_ATTRIBUTES = [
:email,
:created_at,
].freeze
# SHOW_PAGE_ATTRIBUTES
# an array of attributes that will be displayed on the model's show page.
SHOW_PAGE_ATTRIBUTES = [
:dossiers,
:id,
:email,
:current_sign_in_at,
:created_at,
].freeze
# FORM_ATTRIBUTES
# an array of attributes that will be displayed
# on the model's form (`new` and `edit`) pages.
FORM_ATTRIBUTES = [].freeze
# Overwrite this method to customize how users are displayed
# across all pages of the admin dashboard.
#
def display_resource(gestionnaire)
gestionnaire.email
end
end

View file

@ -74,7 +74,7 @@ class ProcedureDashboard < Administrate::BaseDashboard
# Overwrite this method to customize how procedures are displayed # Overwrite this method to customize how procedures are displayed
# across all pages of the admin dashboard. # across all pages of the admin dashboard.
# #
# def display_resource(procedure) def display_resource(procedure)
# "Procedure ##{procedure.id}" "#{procedure.libelle} ##{procedure.id}"
# end end
end end

View file

@ -0,0 +1,50 @@
require "administrate/base_dashboard"
class UserDashboard < Administrate::BaseDashboard
# ATTRIBUTE_TYPES
# a hash that describes the type of each of the model's fields.
#
# Each different type represents an Administrate::Field object,
# which determines how the attribute is displayed
# on pages throughout the dashboard.
ATTRIBUTE_TYPES = {
id: Field::Number,
email: Field::String,
created_at: Field::DateTime,
updated_at: Field::DateTime,
current_sign_in_at: Field::DateTime,
dossiers: Field::HasMany,
}.freeze
# COLLECTION_ATTRIBUTES
# an array of attributes that will be displayed on the model's index page.
#
# By default, it's limited to four items to reduce clutter on index pages.
# Feel free to add, remove, or rearrange items.
COLLECTION_ATTRIBUTES = [
:email,
:created_at,
].freeze
# SHOW_PAGE_ATTRIBUTES
# an array of attributes that will be displayed on the model's show page.
SHOW_PAGE_ATTRIBUTES = [
:dossiers,
:id,
:email,
:current_sign_in_at,
:created_at,
].freeze
# FORM_ATTRIBUTES
# an array of attributes that will be displayed
# on the model's form (`new` and `edit`) pages.
FORM_ATTRIBUTES = [].freeze
# Overwrite this method to customize how users are displayed
# across all pages of the admin dashboard.
#
def display_resource(user)
user.email
end
end

View file

@ -16,10 +16,12 @@ module DossierHelper
end end
def delete_dossier_confirm(dossier) def delete_dossier_confirm(dossier)
message = "Vous vous apprêtez à supprimer votre dossier ainsi que les informations quil contient. " message = ["Vous vous apprêtez à supprimer votre dossier ainsi que les informations quil contient."]
if dossier.en_construction_ou_instruction? if dossier.en_construction_ou_instruction?
message += "Nous vous rappelons que toute suppression entraine lannulation de la démarche en cours. " message << "Nous vous rappelons que toute suppression entraine lannulation de la démarche en cours."
end end
message += "Confirmer la suppression ?" message << "Confirmer la suppression ?"
message.join(" ")
end end
end end

View file

@ -163,10 +163,6 @@ class Dossier < ApplicationRecord
en_instruction? || accepte? || refuse? || sans_suite? en_instruction? || accepte? || refuse? || sans_suite?
end end
def owner_or_invite?(user)
self.user == user || invite_for_user(user).present?
end
def invite_for_user(user) def invite_for_user(user)
invites_user.find_by(user_id: user.id) invites_user.find_by(user_id: user.id)
end end

View file

@ -24,6 +24,7 @@ class Procedure < ApplicationRecord
has_one :without_continuation_mail, class_name: "Mails::WithoutContinuationMail", dependent: :destroy has_one :without_continuation_mail, class_name: "Mails::WithoutContinuationMail", dependent: :destroy
has_one_attached :notice has_one_attached :notice
has_one_attached :deliberation
delegate :use_api_carto, to: :module_api_carto delegate :use_api_carto, to: :module_api_carto
@ -45,6 +46,7 @@ class Procedure < ApplicationRecord
validates :libelle, presence: true, allow_blank: false, allow_nil: false validates :libelle, presence: true, allow_blank: false, allow_nil: false
validates :description, presence: true, allow_blank: false, allow_nil: false validates :description, presence: true, allow_blank: false, allow_nil: false
validate :check_juridique
include AASM include AASM
@ -198,15 +200,7 @@ class Procedure < ApplicationRecord
procedure.logo_secure_token = nil procedure.logo_secure_token = nil
procedure.remote_logo_url = self.logo_url procedure.remote_logo_url = self.logo_url
if notice.attached? %i(notice deliberation).each { |attachment| clone_attachment(procedure, attachment) }
response = Typhoeus.get(notice.service_url, timeout: 5)
if response.success?
procedure.notice.attach(
io: StringIO.new(response.body),
filename: notice.filename
)
end
end
procedure.administrateur = admin procedure.administrateur = admin
procedure.initiated_mail = initiated_mail&.dup procedure.initiated_mail = initiated_mail&.dup
@ -349,6 +343,25 @@ class Procedure < ApplicationRecord
private private
def clone_attachment(cloned_procedure, attachment_symbol)
attachment = send(attachment_symbol)
if attachment.attached?
response = Typhoeus.get(attachment.service_url, timeout: 5)
if response.success?
cloned_procedure.send(attachment_symbol).attach(
io: StringIO.new(response.body),
filename: attachment.filename
)
end
end
end
def check_juridique
if cadre_juridique.blank? && !deliberation.attached?
errors.add(:cadre_juridique, " : veuillez remplir le texte de loi ou la délibération")
end
end
def field_hash(label, table, column) def field_hash(label, table, column)
{ {
'label' => label, 'label' => label,

View file

@ -38,7 +38,15 @@ class User < ApplicationRecord
loged_in_with_france_connect.present? loged_in_with_france_connect.present?
end end
def owns?(dossier)
dossier.user_id == id
end
def invite?(dossier_id) def invite?(dossier_id)
invites.pluck(:dossier_id).include?(dossier_id.to_i) invites.pluck(:dossier_id).include?(dossier_id.to_i)
end end
def owns_or_invite?(dossier)
owns?(dossier) || invite?(dossier.id)
end
end end

View file

@ -21,6 +21,27 @@
Un lien de rappel HTTP (aussi appelé webhook) est utilisé pour notifier un service tiers du changement de l'état dun dossier sur demarches-simplifiees.fr. À chaque changement détat d'un dossier, notre site va effectuer une requête sur le lien renseigné avec en paramètres : le nouvel état du dossier, lidentifiant de la procédure, l'identifiant dossier et la date du changement. Vous pourrez alors utiliser notre API pour récupérer les nouvelles informations du dossier concerné. Un lien de rappel HTTP (aussi appelé webhook) est utilisé pour notifier un service tiers du changement de l'état dun dossier sur demarches-simplifiees.fr. À chaque changement détat d'un dossier, notre site va effectuer une requête sur le lien renseigné avec en paramètres : le nouvel état du dossier, lidentifiant de la procédure, l'identifiant dossier et la date du changement. Vous pourrez alors utiliser notre API pour récupérer les nouvelles informations du dossier concerné.
= f.text_field :web_hook_url, class: 'form-control', placeholder: 'https://callback.exemple.fr/' = f.text_field :web_hook_url, class: 'form-control', placeholder: 'https://callback.exemple.fr/'
.form-group
%h4 Cadre juridique *
%p Indiquez la référence ou l'URL du texte juridique ou chargez la délibération qui justifie cette procédure
= f.label :cadre_juridique, 'Référence ou texte de loi'
= f.text_field :cadre_juridique, class: 'form-control', placeholder: 'https://www.legifrance.gouv.fr/'
= f.label :deliberation, 'Délibération'
- deliberation = @procedure.deliberation
- if !deliberation.attached?
= f.file_field :deliberation,
direct_upload: true
- else
%a{ href: url_for(deliberation), target: '_blank' }
= deliberation.filename.to_s
= link_to 'supprimer', delete_deliberation_admin_procedure_path(@procedure),
method: :delete
%br
Modifier :
= f.file_field :deliberation,
direct_upload: true
.form-group .form-group
%h4 Notice explicative de la procédure %h4 Notice explicative de la procédure
- notice = @procedure.notice - notice = @procedure.notice

View file

@ -1,5 +1,5 @@
- if !@facade.dossier.read_only? - if !@facade.dossier.read_only?
- if user_signed_in? && (@facade.dossier.owner_or_invite?(current_user)) - if user_signed_in? && (current_user.owns_or_invite?(@facade.dossier))
%a#maj_carte.action{ href: "/users/dossiers/#{@facade.dossier.id}/carte" } %a#maj_carte.action{ href: "/users/dossiers/#{@facade.dossier.id}/carte" }
.col-lg-2.col-md-2.col-sm-2.col-xs-2.action .col-lg-2.col-md-2.col-sm-2.col-xs-2.action
= 'ÉDITER' = 'ÉDITER'

View file

@ -1,5 +1,5 @@
- if !@facade.dossier.read_only? - if !@facade.dossier.read_only?
- if user_signed_in? && (@facade.dossier.owner_or_invite?(current_user)) - if user_signed_in? && (current_user.owns_or_invite?(@facade.dossier))
= link_to modifier_dossier_path(@facade.dossier), class: 'action', id: 'maj_infos' do = link_to modifier_dossier_path(@facade.dossier), class: 'action', id: 'maj_infos' do
#edit-dossier.col-lg-2.col-md-2.col-sm-2.col-xs-2.action #edit-dossier.col-lg-2.col-md-2.col-sm-2.col-xs-2.action
= "ÉDITER" = "ÉDITER"

View file

@ -1,5 +1,5 @@
- if !@facade.dossier.read_only? - if !@facade.dossier.read_only?
- if user_signed_in? && (@facade.dossier.owner_or_invite?(current_user)) - if user_signed_in? && (current_user.owns_or_invite?(@facade.dossier))
- if @facade.procedure.cerfa_flag? || @facade.dossier.types_de_piece_justificative.size > 0 - if @facade.procedure.cerfa_flag? || @facade.dossier.types_de_piece_justificative.size > 0
.col-lg-4.col-md-4.col-sm-4.col-xs-4.action .col-lg-4.col-md-4.col-sm-4.col-xs-4.action
%a#maj_pj.action{ "data-target" => "#upload-pj-modal", %a#maj_pj.action{ "data-target" => "#upload-pj-modal",

View file

@ -101,7 +101,7 @@
Pièce non fournie Pièce non fournie
- if !@facade.dossier.read_only? - if !@facade.dossier.read_only?
- if user_signed_in? && (@facade.dossier.owner_or_invite?(current_user)) - if user_signed_in? && (current_user.owns_or_invite?(@facade.dossier))
- if @facade.procedure.cerfa_flag? || @facade.dossier.types_de_piece_justificative.size > 0 - if @facade.procedure.cerfa_flag? || @facade.dossier.types_de_piece_justificative.size > 0
.row .row
.col-xs-4 .col-xs-4

View file

@ -14,7 +14,7 @@
.dossier-state= @facade.dossier.display_state .dossier-state= @facade.dossier.display_state
.split-hr-left .split-hr-left
- if @facade.dossier.user == current_user - if current_user.owns?(@facade.dossier)
.text-center.mt-1 .text-center.mt-1
= link_to ask_deletion_dossier_path(@facade.dossier), method: :post, class: "btn btn-danger", data: { confirm: delete_dossier_confirm(@facade.dossier) } do = link_to ask_deletion_dossier_path(@facade.dossier), method: :post, class: "btn btn-danger", data: { confirm: delete_dossier_confirm(@facade.dossier) } do
Supprimer définitivement Supprimer définitivement

View file

@ -12,7 +12,8 @@ as defined by the routes in the `admin/` namespace
<hr /> <hr />
<% Administrate::Namespace.new(namespace).resources.each do |resource| %> <% Administrate::Namespace.new(namespace).resources.reject { |resource| resource.resource == 'dossiers'}.each do |resource| %>
<%= link_to( <%= link_to(
display_resource_name(resource), display_resource_name(resource),
[namespace, resource.path], [namespace, resource.path],

View file

@ -58,7 +58,7 @@
class: 'button send', class: 'button send',
data: { action: 'draft', disable_with: 'Envoi...' } data: { action: 'draft', disable_with: 'Envoi...' }
- if dossier.user == current_user - if current_user.owns?(dossier)
= f.button 'Soumettre le dossier', = f.button 'Soumettre le dossier',
class: 'button send primary', class: 'button send primary',
data: { action: 'submit', disable_with: 'Envoi...' } data: { action: 'submit', disable_with: 'Envoi...' }

View file

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

View file

@ -11,6 +11,10 @@ Rails.application.routes.draw do
put 'enable_feature', on: :member put 'enable_feature', on: :member
end end
resources :users, only: [:index, :show]
resources :gestionnaires, only: [:index, :show]
resources :dossiers, only: [:show]
resources :demandes, only: [:index] resources :demandes, only: [:index]
post 'demandes/create_administrateur' post 'demandes/create_administrateur'
post 'demandes/refuse_administrateur' post 'demandes/refuse_administrateur'
@ -143,6 +147,7 @@ Rails.application.routes.draw do
member do member do
post :hide post :hide
delete :delete_deliberation
end end
resources :types_de_champ, only: [:destroy] resources :types_de_champ, only: [:destroy]

View file

@ -0,0 +1,5 @@
class AddCadreJuridiqueToProcedure < ActiveRecord::Migration[5.2]
def change
add_column :procedures, :cadre_juridique, :string
end
end

View file

@ -481,6 +481,7 @@ ActiveRecord::Schema.define(version: 2018_05_30_095508) do
t.bigint "service_id" t.bigint "service_id"
t.integer "duree_conservation_dossiers_dans_ds" t.integer "duree_conservation_dossiers_dans_ds"
t.integer "duree_conservation_dossiers_hors_ds" t.integer "duree_conservation_dossiers_hors_ds"
t.string "cadre_juridique"
t.index ["hidden_at"], name: "index_procedures_on_hidden_at" t.index ["hidden_at"], name: "index_procedures_on_hidden_at"
t.index ["parent_procedure_id"], name: "index_procedures_on_parent_procedure_id" t.index ["parent_procedure_id"], name: "index_procedures_on_parent_procedure_id"
t.index ["service_id"], name: "index_procedures_on_service_id" t.index ["service_id"], name: "index_procedures_on_service_id"

View file

@ -15,6 +15,7 @@ describe Admin::ProceduresController, type: :controller do
let(:quartiers_prioritaires) { '0' } let(:quartiers_prioritaires) { '0' }
let(:cadastre) { '0' } let(:cadastre) { '0' }
let(:cerfa_flag) { true } let(:cerfa_flag) { true }
let(:cadre_juridique) { 'cadre juridique' }
let(:procedure_params) { let(:procedure_params) {
{ {
@ -24,6 +25,7 @@ describe Admin::ProceduresController, type: :controller do
direction: direction, direction: direction,
lien_demarche: lien_demarche, lien_demarche: lien_demarche,
cerfa_flag: cerfa_flag, cerfa_flag: cerfa_flag,
cadre_juridique: cadre_juridique,
module_api_carto_attributes: { module_api_carto_attributes: {
use_api_carto: use_api_carto, use_api_carto: use_api_carto,
quartiers_prioritaires: quartiers_prioritaires, quartiers_prioritaires: quartiers_prioritaires,
@ -471,7 +473,7 @@ describe Admin::ProceduresController, type: :controller do
end end
describe 'PUT #clone' do describe 'PUT #clone' do
let!(:procedure) { create(:procedure, :with_notice, administrateur: admin) } let!(:procedure) { create(:procedure, :with_notice, :with_deliberation, administrateur: admin) }
let(:params) { { procedure_id: procedure.id } } let(:params) { { procedure_id: procedure.id } }
subject { put :clone, params: params } subject { put :clone, params: params }
@ -489,6 +491,7 @@ describe Admin::ProceduresController, type: :controller do
expect(response).to redirect_to edit_admin_procedure_path(id: Procedure.last.id) expect(response).to redirect_to edit_admin_procedure_path(id: Procedure.last.id)
expect(Procedure.last.cloned_from_library).to be_falsey expect(Procedure.last.cloned_from_library).to be_falsey
expect(Procedure.last.notice.attached?).to be_truthy expect(Procedure.last.notice.attached?).to be_truthy
expect(Procedure.last.deliberation.attached?).to be_truthy
expect(flash[:notice]).to have_content 'Procédure clonée' expect(flash[:notice]).to have_content 'Procédure clonée'
end end
@ -634,4 +637,16 @@ describe Admin::ProceduresController, type: :controller do
end end
end end
end end
describe "DELETE #delete_deliberation" do
let(:procedure) { create(:procedure, :with_deliberation) }
before do
delete :delete_deliberation, params: { id: procedure.id }
procedure.reload
end
it { expect(procedure.deliberation.attached?).to eq(false) }
it { expect(response).to redirect_to(edit_admin_procedure_path(procedure)) }
end
end end

View file

@ -6,6 +6,7 @@ FactoryBot.define do
description "Demande de subvention à l'intention des associations" description "Demande de subvention à l'intention des associations"
organisation "Orga DINSIC" organisation "Orga DINSIC"
direction "direction DINSIC" direction "direction DINSIC"
cadre_juridique "un cadre juridique important"
published_at nil published_at nil
cerfa_flag false cerfa_flag false
administrateur { create(:administrateur) } administrateur { create(:administrateur) }
@ -134,6 +135,15 @@ FactoryBot.define do
end end
end end
trait :with_deliberation do
after(:create) do |procedure, _evaluator|
procedure.deliberation.attach(
io: StringIO.new('Hello World'),
filename: 'hello.txt'
)
end
end
trait :with_all_champs_mandatory do trait :with_all_champs_mandatory do
after(:build) do |procedure, _evaluator| after(:build) do |procedure, _evaluator|
tdcs = [] tdcs = []

View file

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

View file

@ -32,13 +32,14 @@ feature 'As an administrateur I wanna create a new procedure', js: true do
expect(page).to have_current_path(new_admin_procedure_path) expect(page).to have_current_path(new_admin_procedure_path)
end end
scenario 'Finding save button for new procedure, libelle and description required' do scenario 'Finding save button for new procedure, libelle, description and cadre_juridique required' do
page.find_by_id('new-procedure').click page.find_by_id('new-procedure').click
page.find_by_id('from-scratch').click page.find_by_id('from-scratch').click
page.find_by_id('save-procedure').click page.find_by_id('save-procedure').click
page.find_by_id('flash_message').visible? page.find_by_id('flash_message').visible?
fill_in 'procedure_libelle', with: 'libelle de la procedure' fill_in 'procedure_libelle', with: 'libelle de la procedure'
page.execute_script("$('#procedure_description').val('description de la procedure')") page.execute_script("$('#procedure_description').val('description de la procedure')")
fill_in 'procedure_cadre_juridique', with: 'cadre juridique'
page.find_by_id('save-procedure').click page.find_by_id('save-procedure').click
expect(page).to have_current_path(admin_procedure_types_de_champ_path(Procedure.first.id.to_s)) expect(page).to have_current_path(admin_procedure_types_de_champ_path(Procedure.first.id.to_s))
end end
@ -50,6 +51,7 @@ feature 'As an administrateur I wanna create a new procedure', js: true do
page.find_by_id('from-scratch').click page.find_by_id('from-scratch').click
fill_in 'procedure_libelle', with: 'libelle de la procedure' fill_in 'procedure_libelle', with: 'libelle de la procedure'
page.execute_script("$('#procedure_description').val('description de la procedure')") page.execute_script("$('#procedure_description').val('description de la procedure')")
fill_in 'procedure_cadre_juridique', with: 'cadre juridique'
page.find_by_id('save-procedure').click page.find_by_id('save-procedure').click
procedure = Procedure.last procedure = Procedure.last

View file

@ -397,44 +397,6 @@ describe Dossier do
end end
end end
describe '#owner_or_invite?' do
let(:owner) { create(:user) }
let(:dossier) { create(:dossier, user: owner) }
let(:invite_user) { create(:user) }
let(:invite_gestionnaire) { create(:user) }
before do
create(:invite, dossier: dossier, user: invite_user, type: 'InviteUser')
create(:invite, dossier: dossier, user: invite_gestionnaire, type: 'InviteGestionnaire')
end
subject { dossier.owner_or_invite?(user) }
context 'when user is owner' do
let(:user) { owner }
it { is_expected.to be_truthy }
end
context 'when user was invited by user' do
let(:user) { invite_user }
it { is_expected.to be_truthy }
end
context 'when user was invited by gestionnaire (legacy, no new invitations happen)' do
let(:user) { invite_gestionnaire }
it { is_expected.to be_falsey }
end
context 'when user is quidam' do
let(:user) { create(:user) }
it { is_expected.to be_falsey }
end
end
describe "#text_summary" do describe "#text_summary" do
let(:procedure) { create(:procedure, libelle: "Procédure", organisation: "Organisme") } let(:procedure) { create(:procedure, libelle: "Procédure", organisation: "Organisme") }

View file

@ -173,6 +173,26 @@ describe Procedure do
context 'organisation' do context 'organisation' do
it { is_expected.to allow_value('URRSAF').for(:organisation) } it { is_expected.to allow_value('URRSAF').for(:organisation) }
end end
context 'juridique' do
it { is_expected.not_to allow_value(nil).for(:cadre_juridique) }
it { is_expected.to allow_value('text').for(:cadre_juridique) }
context 'with deliberation' do
let(:procedure) { build(:procedure, cadre_juridique: nil) }
it { expect(procedure.valid?).to eq(false) }
context 'when the deliberation is uploaded ' do
before do
allow(procedure).to receive(:deliberation)
.and_return(double('attached?': true))
end
it { expect(procedure.valid?).to eq(true) }
end
end
end
end end
describe '#types_de_champ_ordered' do describe '#types_de_champ_ordered' do

View file

@ -31,6 +31,37 @@ describe User, type: :model do
end end
end end
describe '#owns?' do
let(:owner) { create(:user) }
let(:dossier) { create(:dossier, user: owner) }
let(:invite_user) { create(:user) }
let(:invite_gestionnaire) { create(:user) }
subject { user.owns?(dossier) }
context 'when user is owner' do
let(:user) { owner }
it { is_expected.to be_truthy }
end
context 'when user was invited by user' do
before do
create(:invite, dossier: dossier, user: invite_user, type: 'InviteUser')
end
let(:user) { invite_user }
it { is_expected.to be_falsy }
end
context 'when user is quidam' do
let(:user) { create(:user) }
it { is_expected.to be_falsey }
end
end
describe '#invite?' do describe '#invite?' do
let(:dossier) { create :dossier } let(:dossier) { create :dossier }
let(:user) { dossier.user } let(:user) { dossier.user }
@ -50,6 +81,37 @@ describe User, type: :model do
end end
end end
describe '#owns_or_invite?' do
let(:owner) { create(:user) }
let(:dossier) { create(:dossier, user: owner) }
let(:invite_user) { create(:user) }
let(:invite_gestionnaire) { create(:user) }
subject { user.owns_or_invite?(dossier) }
context 'when user is owner' do
let(:user) { owner }
it { is_expected.to be_truthy }
end
context 'when user was invited by user' do
before do
create(:invite, dossier: dossier, user: invite_user, type: 'InviteUser')
end
let(:user) { invite_user }
it { is_expected.to be_truthy }
end
context 'when user is quidam' do
let(:user) { create(:user) }
it { is_expected.to be_falsey }
end
end
context 'unified login' do context 'unified login' do
it 'syncs credentials to associated gestionnaire' do it 'syncs credentials to associated gestionnaire' do
user = create(:user) user = create(:user)

View file

@ -72,61 +72,30 @@ describe 'users/recapitulatif/show.html.haml', type: :view do
end end
context 'when invite is logged' do context 'when invite is logged' do
context 'when invite is by Gestionnaire' do let!(:invite_user) { create(:user, email: 'invite@octo.com') }
let!(:invite_user) { create(:user, email: 'invite@octo.com') }
before do before do
create(:invite) { create(:invite, email: invite_user.email, user: invite_user, dossier: dossier) } create(:invite) { create(:invite, email: invite_user.email, user: invite_user, dossier: dossier, type: 'InviteUser') }
sign_out dossier.user sign_out dossier.user
sign_in invite_user sign_in invite_user
render render
end
describe 'les liens de modifications' do
it 'describe link is not present' do
expect(rendered).not_to have_css('#maj_infos')
end
it 'map link is not present' do
expect(rendered).not_to have_css('#maj_carte')
end
it 'PJ link is not present' do
expect(rendered).not_to have_css('#maj_pj')
end
it 'archive link is not present' do
expect(rendered).not_to have_content('Archiver')
end
end
end end
context 'invite is by User' do describe 'les liens de modifications' do
let!(:invite_user) { create(:user, email: 'invite@octo.com') } it 'describe link is not present' do
expect(rendered).to have_css('#maj_infos')
before do
create(:invite) { create(:invite, email: invite_user.email, user: invite_user, dossier: dossier, type: 'InviteUser') }
sign_out dossier.user
sign_in invite_user
render
end end
describe 'les liens de modifications' do it 'map link is present' do
it 'describe link is not present' do expect(rendered).to have_css('#maj_carte')
expect(rendered).to have_css('#maj_infos') end
end
it 'map link is present' do it 'PJ link is present' do
expect(rendered).to have_css('#maj_carte') expect(rendered).to have_css('#maj_pj')
end end
it 'PJ link is present' do it 'archive link is present' do
expect(rendered).to have_css('#maj_pj') expect(rendered).not_to have_content('Archiver')
end
it 'archive link is present' do
expect(rendered).not_to have_content('Archiver')
end
end end
end end
end end