Merge branch 'dev'

This commit is contained in:
gregoirenovel 2018-03-29 18:02:22 +02:00
commit 279d4c1631
89 changed files with 527 additions and 153 deletions

View file

@ -2,6 +2,36 @@ $(document).on('turbolinks:load', wysihtml5_active);
function wysihtml5_active (){
$('.wysihtml5').each(function(i, elem) {
$(elem).wysihtml5({ toolbar:{ "fa": true, "link": false, "color": false }, "locale": "fr-FR" });
$(elem).wysihtml5({
toolbar: {
"fa": true,
"link": false,
"color": false
},
parserRules: {
tags: {
p: {},
h1: {},
h2: {},
h3: {},
h4: {},
h5: {},
h6: {},
b: {},
i: {},
u: {},
small: {},
blockquote: {},
ul: {},
ol: {},
li: {},
img: {},
code: {
unwrap: 1
}
}
},
"locale": "fr-FR"
});
});
}

View file

@ -66,6 +66,10 @@
}
}
.updated-at-col {
width: 110px;
}
.follow-col {
width: 200px;
text-align: right;

View file

@ -1,6 +1,8 @@
module NewUser
class DossiersController < UserController
before_action :ensure_ownership!
before_action :ensure_ownership!, except: [:index, :modifier, :update]
before_action :ensure_ownership_or_invitation!, only: [:modifier, :update]
before_action :forbid_invite_submission!, only: [:update]
def attestation
send_data(dossier.attestation.pdf.read, filename: 'attestation.pdf', type: 'application/pdf')
@ -67,15 +69,14 @@ module NewUser
elsif draft?
flash.now.notice = 'Votre brouillon a bien été sauvegardé.'
render :modifier
elsif @dossier.brouillon?
@dossier.en_construction!
NotificationMailer.send_notification(@dossier, @dossier.procedure.initiated_mail_template).deliver_now!
redirect_to merci_dossier_path(@dossier)
elsif owns_dossier?
redirect_to users_dossier_recapitulatif_path(@dossier)
else
if @dossier.brouillon?
@dossier.en_construction!
NotificationMailer.send_notification(@dossier, @dossier.procedure.initiated_mail_template).deliver_now!
redirect_to merci_dossier_path(@dossier)
else
@dossier.en_construction!
redirect_to users_dossier_recapitulatif_path(@dossier)
end
redirect_to users_dossiers_invite_path(@dossier.invite_for_user(current_user))
end
end
@ -83,6 +84,10 @@ module NewUser
@dossier = current_user.dossiers.includes(:procedure).find(params[:id])
end
def index
@dossiers = current_user.dossiers.includes(:procedure).page([params[:page].to_i, 1].max)
end
private
# FIXME: require(:dossier) when all the champs are united
@ -95,16 +100,32 @@ module NewUser
end
def dossier_with_champs
@dossier_with_champs ||= current_user.dossiers.with_ordered_champs.find(params[:id])
@dossier_with_champs ||= Dossier.with_ordered_champs.find(params[:id])
end
def ensure_ownership!
if dossier.user_id != current_user.id
flash[:alert] = "Vous n'avez pas accès à ce dossier"
redirect_to root_path
if !owns_dossier?
forbidden!
end
end
def ensure_ownership_or_invitation!
if !dossier.owner_or_invite?(current_user)
forbidden!
end
end
def forbid_invite_submission!
if passage_en_construction? && !owns_dossier?
forbidden!
end
end
def forbidden!
flash[:alert] = "Vous n'avez pas accès à ce dossier"
redirect_to root_path
end
def individual_params
params.require(:individual).permit(:gender, :nom, :prenom, :birthdate)
end
@ -113,6 +134,14 @@ module NewUser
params.require(:dossier).permit(:autorisation_donnees)
end
def owns_dossier?
dossier.user_id == current_user.id
end
def passage_en_construction?
dossier.brouillon? && !draft?
end
def draft?
params[:submit_action] == 'draft'
end

View file

@ -10,9 +10,11 @@ class UsersController < ApplicationController
dossier = Dossier.find(dossier_id)
return dossier if dossier.owner?(current_user.email) || dossier.invite_by_user?(current_user.email)
if !dossier.owner_or_invite?(current_user)
raise ActiveRecord::RecordNotFound
end
raise ActiveRecord::RecordNotFound
dossier
end
def authorized_routes?(controller)

View file

@ -1,6 +1,6 @@
class ApiEntreprise::Adapter
def initialize(siret_or_siren, procedure_id)
@siret_or_siren = siret_or_siren
def initialize(siret, procedure_id)
@siret = siret
@procedure_id = procedure_id
end

View file

@ -2,7 +2,8 @@ class ApiEntreprise::EntrepriseAdapter < ApiEntreprise::Adapter
private
def get_resource
ApiEntreprise::API.entreprise(@siret_or_siren, @procedure_id)
siren = @siret[0..8]
ApiEntreprise::API.entreprise(siren, @procedure_id)
end
def process_params

View file

@ -2,7 +2,7 @@ class ApiEntreprise::EtablissementAdapter < ApiEntreprise::Adapter
private
def get_resource
ApiEntreprise::API.etablissement(@siret_or_siren, @procedure_id)
ApiEntreprise::API.etablissement(@siret, @procedure_id)
end
def process_params

View file

@ -2,7 +2,7 @@ class ApiEntreprise::ExercicesAdapter < ApiEntreprise::Adapter
private
def get_resource
ApiEntreprise::API.exercices(@siret_or_siren, @procedure_id)
ApiEntreprise::API.exercices(@siret, @procedure_id)
end
def process_params

View file

@ -2,7 +2,7 @@ class ApiEntreprise::RNAAdapter < ApiEntreprise::Adapter
private
def get_resource
ApiEntreprise::API.rna(@siret_or_siren, @procedure_id)
ApiEntreprise::API.rna(@siret, @procedure_id)
end
def process_params

View file

@ -1,6 +1,4 @@
class Champ < ApplicationRecord
self.inheritance_column = :_type_disabled
belongs_to :dossier, touch: true
belongs_to :type_de_champ, inverse_of: :champ
has_many :commentaires

View file

@ -0,0 +1,2 @@
class Champs::AddressChamp < Champs::TextChamp
end

View file

@ -0,0 +1,2 @@
class Champs::CheckboxChamp < Champ
end

View file

@ -0,0 +1,2 @@
class Champs::CiviliteChamp < Champ
end

View file

@ -0,0 +1,2 @@
class Champs::DateChamp < Champ
end

View file

@ -0,0 +1,2 @@
class Champs::DatetimeChamp < Champ
end

View file

@ -0,0 +1,2 @@
class Champs::DepartementChamp < Champs::TextChamp
end

View file

@ -0,0 +1,2 @@
class Champs::DossierLinkChamp < Champ
end

View file

@ -0,0 +1,2 @@
class Champs::DropDownListChamp < Champ
end

View file

@ -0,0 +1,2 @@
class Champs::EmailChamp < Champs::TextChamp
end

View file

@ -0,0 +1,2 @@
class Champs::EngagementChamp < Champs::CheckboxChamp
end

View file

@ -0,0 +1,2 @@
class Champs::ExplicationChamp < Champs::TextChamp
end

View file

@ -0,0 +1,2 @@
class Champs::HeaderSectionChamp < Champ
end

View file

@ -0,0 +1,2 @@
class Champs::MultipleDropDownListChamp < Champ
end

View file

@ -0,0 +1,2 @@
class Champs::NumberChamp < Champ
end

View file

@ -0,0 +1,2 @@
class Champs::PaysChamp < Champs::TextChamp
end

View file

@ -0,0 +1,2 @@
class Champs::PhoneChamp < Champs::TextChamp
end

View file

@ -0,0 +1,2 @@
class Champs::PieceJustificativeChamp < Champ
end

View file

@ -0,0 +1,2 @@
class Champs::RegionChamp < Champs::TextChamp
end

View file

@ -0,0 +1,2 @@
class Champs::TextChamp < Champ
end

View file

@ -0,0 +1,2 @@
class Champs::TextareaChamp < Champs::TextChamp
end

View file

@ -0,0 +1,2 @@
class Champs::YesNoChamp < Champs::CheckboxChamp
end

View file

@ -190,12 +190,12 @@ class Dossier < ApplicationRecord
en_instruction? || accepte? || refuse? || sans_suite?
end
def owner?(email)
user.email == email
def owner_or_invite?(user)
self.user == user || invite_for_user(user).present?
end
def invite_by_user?(email)
(invites_user.pluck :email).include? email
def invite_for_user(user)
invites_user.find_by(user_id: user.id)
end
def can_be_en_construction?

View file

@ -1,6 +1,4 @@
class TypeDeChamp < ApplicationRecord
self.inheritance_column = :_type_disabled
enum type_champs: {
text: 'text',
textarea: 'textarea',

View file

@ -0,0 +1,2 @@
class TypesDeChamp::AddressTypeDeChamp < TypesDeChamp::TextTypeDeChamp
end

View file

@ -0,0 +1,2 @@
class TypesDeChamp::CheckboxTypeDeChamp < TypeDeChamp
end

View file

@ -0,0 +1,2 @@
class TypesDeChamp::CiviliteTypeDeChamp < TypeDeChamp
end

View file

@ -0,0 +1,2 @@
class TypesDeChamp::DateTypeDeChamp < TypeDeChamp
end

View file

@ -0,0 +1,2 @@
class TypesDeChamp::DatetimeTypeDeChamp < TypeDeChamp
end

View file

@ -0,0 +1,2 @@
class TypesDeChamp::DepartementTypeDeChamp < TypesDeChamp::TextTypeDeChamp
end

View file

@ -0,0 +1,2 @@
class TypesDeChamp::DossierLinkTypeDeChamp < TypeDeChamp
end

View file

@ -0,0 +1,2 @@
class TypesDeChamp::DropDownListTypeDeChamp < TypeDeChamp
end

View file

@ -0,0 +1,2 @@
class TypesDeChamp::EmailTypeDeChamp < TypesDeChamp::TextTypeDeChamp
end

View file

@ -0,0 +1,2 @@
class TypesDeChamp::EngagementTypeDeChamp < TypesDeChamp::CheckboxTypeDeChamp
end

View file

@ -0,0 +1,2 @@
class TypesDeChamp::ExplicationTypeDeChamp < TypesDeChamp::TextTypeDeChamp
end

View file

@ -0,0 +1,2 @@
class TypesDeChamp::HeaderSectionTypeDeChamp < TypeDeChamp
end

View file

@ -0,0 +1,2 @@
class TypesDeChamp::MultipleDropDownListTypeDeChamp < TypeDeChamp
end

View file

@ -0,0 +1,2 @@
class TypesDeChamp::NumberTypeDeChamp < TypeDeChamp
end

View file

@ -0,0 +1,2 @@
class TypesDeChamp::PaysTypeDeChamp < TypesDeChamp::TextTypeDeChamp
end

View file

@ -0,0 +1,2 @@
class TypesDeChamp::PhoneTypeDeChamp < TypesDeChamp::TextTypeDeChamp
end

View file

@ -0,0 +1,2 @@
class TypesDeChamp::PieceJustificativeTypeDeChamp < TypeDeChamp
end

View file

@ -0,0 +1,2 @@
class TypesDeChamp::RegionTypeDeChamp < TypesDeChamp::TextTypeDeChamp
end

View file

@ -0,0 +1,2 @@
class TypesDeChamp::TextTypeDeChamp < TypeDeChamp
end

View file

@ -0,0 +1,2 @@
class TypesDeChamp::TextareaTypeDeChamp < TypesDeChamp::TextTypeDeChamp
end

View file

@ -0,0 +1,2 @@
class TypesDeChamp::YesNoTypeDeChamp < TypesDeChamp::CheckboxTypeDeChamp
end

View file

@ -3,7 +3,7 @@ class SIRETService
procedure_id = dossier&.procedure_id
etablissement_params = ApiEntreprise::EtablissementAdapter.new(siret, procedure_id).to_params
entreprise_params = ApiEntreprise::EntrepriseAdapter.new(siren(siret), procedure_id).to_params
entreprise_params = ApiEntreprise::EntrepriseAdapter.new(siret, procedure_id).to_params
if etablissement_params.present? && entreprise_params.present?
association_params = ApiEntreprise::RNAAdapter.new(siret, procedure_id).to_params
@ -23,10 +23,6 @@ class SIRETService
end
end
def self.siren(siret)
siret[0..8]
end
def self.handle_legacy_models!(params, entreprise_params, dossier, association_params)
params[:entreprise_attributes] = entreprise_params.merge(
{

View file

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

View file

@ -1,5 +1,5 @@
- if !@facade.dossier.read_only?
- if user_signed_in? && (@facade.dossier.owner?(current_user.email) || @facade.dossier.invite_by_user?(current_user.email))
- if user_signed_in? && (@facade.dossier.owner_or_invite?(current_user))
= 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
= "éditer".upcase

View file

@ -1,5 +1,5 @@
- if !@facade.dossier.read_only?
- if user_signed_in? && (@facade.dossier.owner?(current_user.email) || @facade.dossier.invite_by_user?(current_user.email))
- if user_signed_in? && (@facade.dossier.owner_or_invite?(current_user))
- 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
%a#maj_pj.action{ "data-target" => "#upload-pj-modal",

View file

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

View file

@ -110,7 +110,7 @@
%td.status-col
= link_to(gestionnaire_dossier_path(@procedure, dossier), class: 'cell-link') do
= render partial: 'status', locals: { dossier: dossier }
= render partial: 'shared/dossiers/status', locals: { dossier: dossier }
%td.follow-col= render partial: 'dossier_actions', locals: { procedure: @procedure, dossier: dossier, dossier_is_followed: @followed_dossiers_id.include?(dossier.id) }
= paginate @dossiers
- else

View file

@ -29,6 +29,6 @@
%td= link_to(dossier.user.email, dossier_linked_path(current_gestionnaire, dossier), class: 'cell-link')
%td.status-col
= link_to(dossier_linked_path(current_gestionnaire, dossier), class: 'cell-link') do
= render partial: 'new_gestionnaire/procedures/status', locals: { dossier: dossier }
= render partial: 'shared/dossiers/status', locals: { dossier: dossier }
- else
%h2 Aucun dossier correspondant à votre recherche n'a été trouvé

View file

@ -0,0 +1,31 @@
.container
%h1.page-title Mes dossiers
%table.table.dossiers-table.hoverable
%thead
%tr
%th
%th.number-col Nº dossier
%th Procédure
%th.status-col Statut
%th.updated-at-col Mis à jour
%tbody
- @dossiers.each do |dossier|
%tr
%td.folder-col
= link_to(modifier_dossier_path(dossier), class: 'cell-link') do
%span.icon.folder
%td.number-col
= link_to(modifier_dossier_path(dossier), class: 'cell-link') do
= dossier.id
%td
= link_to(modifier_dossier_path(dossier), class: 'cell-link') do
= dossier.procedure.libelle
%td.status-col
= link_to(modifier_dossier_path(dossier), class: 'cell-link') do
= render partial: 'shared/dossiers/status', locals: { dossier: dossier }
%td.updated-at-col
= link_to(modifier_dossier_path(dossier), class: 'cell-link') do
= dossier.updated_at.localtime.strftime("%d/%m/%Y")
= paginate(@dossiers)

View file

@ -52,9 +52,10 @@
class: 'button send',
data: { action: 'draft', disable_with: 'Envoi...' }
= f.button 'Soumettre le dossier',
class: 'button send primary',
data: { action: 'submit', disable_with: 'Envoi...' }
- if @dossier.user == current_user
= f.button 'Soumettre le dossier',
class: 'button send primary',
data: { action: 'submit', disable_with: 'Envoi...' }
- else
= f.button 'Modifier le dossier',

View file

@ -60,6 +60,7 @@
%h1 Labels
%span.label .label
%span.label.brouillon .label.brouillon
%span.label.instruction .label.instruction
%span.label.construction .label.construction
%span.label.accepted .label.accepted

View file

@ -1,3 +1,5 @@
- if dossier.brouillon?
%span.label.brouillon brouillon
- if dossier.en_instruction?
%span.label.instruction en instruction
- elsif dossier.en_construction?

View file

@ -206,7 +206,7 @@ Rails.application.routes.draw do
get "patron" => "root#patron"
scope module: 'new_user' do
resources :dossiers, only: [:update] do
resources :dossiers, only: [:index, :update] do
member do
get 'identite'
patch 'update_identite'

View file

@ -0,0 +1,18 @@
namespace :'2018_03_29_remove_code_tags_from_mail_templates' do
task clean: :environment do
remove_code_tag_from_body(Mails::ClosedMail)
remove_code_tag_from_body(Mails::InitiatedMail)
remove_code_tag_from_body(Mails::ReceivedMail)
remove_code_tag_from_body(Mails::RefusedMail)
remove_code_tag_from_body(Mails::WithoutContinuationMail)
end
def remove_code_tag_from_body(model_class)
mails = model_class.where("body LIKE ?", "%<code>%")
puts "#{mails.count} #{model_class.name} to clean"
mails.each do |m|
puts "cleaning #{model_class.name} ##{m.id}"
m.update(body: m.body.gsub("<code>", "").gsub("</code>", ""))
end
end
end

View file

@ -369,11 +369,11 @@ describe NewGestionnaire::DossiersController, type: :controller do
describe "#update_annotations" do
let(:champ_multiple_drop_down_list) do
create(:type_de_champ, :private, type_champ: 'multiple_drop_down_list', libelle: 'libelle').champ.create
create(:type_de_champ_multiple_drop_down_list, :private, libelle: 'libelle').champ.create
end
let(:champ_datetime) do
create(:type_de_champ, :private, type_champ: 'datetime', libelle: 'libelle').champ.create
create(:type_de_champ_datetime, :private, libelle: 'libelle').champ.create
end
let(:dossier) do

View file

@ -3,44 +3,96 @@ require 'spec_helper'
describe NewUser::DossiersController, type: :controller do
let(:user) { create(:user) }
describe 'before_action: ensure_ownership!' do
it 'is present' do
describe 'before_actions' do
it 'are present' do
before_actions = NewUser::DossiersController
._process_action_callbacks
.find_all{ |process_action_callbacks| process_action_callbacks.kind == :before }
.map(&:filter)
expect(before_actions).to include(:ensure_ownership!)
expect(before_actions).to include(:ensure_ownership!, :ensure_ownership_or_invitation!, :forbid_invite_submission!)
end
end
describe 'ensure_ownership!' do
shared_examples_for 'does not redirect nor flash' do
before { @controller.send(ensure_authorized) }
it { expect(@controller).not_to have_received(:redirect_to) }
it { expect(flash.alert).to eq(nil) }
end
shared_examples_for 'redirects and flashes' do
before { @controller.send(ensure_authorized) }
it { expect(@controller).to have_received(:redirect_to).with(root_path) }
it { expect(flash.alert).to eq("Vous n'avez pas accès à ce dossier") }
end
describe '#ensure_ownership!' do
let(:user) { create(:user) }
let(:asked_dossier) { create(:dossier) }
let(:ensure_authorized) { :ensure_ownership! }
before do
@controller.params = @controller.params.merge(dossier_id: asked_dossier.id)
expect(@controller).to receive(:current_user).and_return(user)
allow(@controller).to receive(:redirect_to)
@controller.send(:ensure_ownership!)
end
context 'when a user asks for its dossier' do
context 'when a user asks for their own dossier' do
let(:asked_dossier) { create(:dossier, user: user) }
it 'does not redirects nor flash' do
expect(@controller).not_to have_received(:redirect_to)
expect(flash.alert).to eq(nil)
end
it_behaves_like 'does not redirect nor flash'
end
context 'when a user asks for another dossier' do
let(:asked_dossier) { create(:dossier) }
it_behaves_like 'redirects and flashes'
end
it 'redirects and flash' do
expect(@controller).to have_received(:redirect_to).with(root_path)
expect(flash.alert).to eq("Vous n'avez pas accès à ce dossier")
end
context 'when an invite asks for a dossier where they were invited' do
before { create(:invite, dossier: asked_dossier, user: user, type: 'InviteUser') }
it_behaves_like 'redirects and flashes'
end
context 'when an invite asks for another dossier' do
before { create(:invite, dossier: create(:dossier), user: user, type: 'InviteUser') }
it_behaves_like 'redirects and flashes'
end
end
describe '#ensure_ownership_or_invitation!' do
let(:user) { create(:user) }
let(:asked_dossier) { create(:dossier) }
let(:ensure_authorized) { :ensure_ownership_or_invitation! }
before do
@controller.params = @controller.params.merge(dossier_id: asked_dossier.id)
expect(@controller).to receive(:current_user).and_return(user)
allow(@controller).to receive(:redirect_to)
end
context 'when a user asks for their own dossier' do
let(:asked_dossier) { create(:dossier, user: user) }
it_behaves_like 'does not redirect nor flash'
end
context 'when a user asks for another dossier' do
it_behaves_like 'redirects and flashes'
end
context 'when an invite asks for a dossier where they were invited' do
before { create(:invite, dossier: asked_dossier, user: user, type: 'InviteUser') }
it_behaves_like 'does not redirect nor flash'
end
context 'when an invite asks for another dossier' do
before { create(:invite, dossier: create(:dossier), user: user, type: 'InviteUser') }
it_behaves_like 'redirects and flashes'
end
end
@ -242,5 +294,43 @@ describe NewUser::DossiersController, type: :controller do
expect(response).to redirect_to(merci_dossier_path(dossier))
end
end
context 'when the user has an invitation but is not the owner' do
let(:dossier) { create(:dossier) }
let!(:invite) { create(:invite, dossier: dossier, user: user, type: 'InviteUser') }
context 'and the invite saves a draft' do
let(:payload) { submit_payload.merge(submit_action: 'draft') }
before do
first_champ.type_de_champ.update(mandatory: true, libelle: 'l')
allow(PiecesJustificativesService).to receive(:missing_pj_error_messages).and_return(['pj'])
subject
end
it { expect(response).to render_template(:modifier) }
it { expect(flash.notice).to eq('Votre brouillon a bien été sauvegardé.') }
it { expect(dossier.reload.state).to eq('brouillon') }
end
context 'and the invite tries to submit the dossier' do
before { subject }
it { expect(response).to redirect_to(root_path) }
it { expect(flash.alert).to eq("Vous n'avez pas accès à ce dossier") }
end
context 'and the invite updates a dossier en constructions' do
before do
dossier.en_construction!
subject
end
it { expect(first_champ.reload.value).to eq('beautiful value') }
it { expect(dossier.reload.state).to eq('en_construction') }
it { expect(response).to redirect_to(users_dossiers_invite_path(invite)) }
end
end
end
end

View file

@ -1,7 +1,7 @@
require 'spec_helper'
describe ChampDecorator do
let(:type_de_champ) { create(:type_de_champ, type_champ: type_champ) }
let(:type_de_champ) { create(:type_de_champ) }
let(:champ) { type_de_champ.champ.create }
let(:decorator) { champ.decorate }
@ -9,7 +9,7 @@ describe ChampDecorator do
subject { decorator.value }
describe 'for a checkbox' do
let(:type_champ) { :checkbox }
let(:type_de_champ) { create(:type_de_champ_checkbox) }
context 'when value is on' do
before { champ.update value: 'on' }
@ -22,7 +22,7 @@ describe ChampDecorator do
end
describe 'for a engagement' do
let(:type_champ) { :engagement }
let(:type_de_champ) { create(:type_de_champ_engagement) }
context 'when value is on' do
before { champ.update value: 'on' }
@ -35,7 +35,7 @@ describe ChampDecorator do
end
describe 'for a multiple_drop_down_list' do
let(:type_champ) { :multiple_drop_down_list }
let(:type_de_champ) { create(:type_de_champ_multiple_drop_down_list) }
context 'when value is an array' do
before { champ.update value: '["1", "2"]' }
@ -49,7 +49,7 @@ describe ChampDecorator do
end
describe "for a date" do
let(:type_champ) { :date }
let(:type_de_champ) { create(:type_de_champ_date) }
context "when value is an ISO date" do
before { champ.update value: "2017-12-31" }
@ -67,7 +67,7 @@ describe ChampDecorator do
subject { decorator.date_for_input }
describe "for a date" do
let(:type_champ) { :date }
let(:type_de_champ) { create(:type_de_champ_date) }
context "when value is an ISO date" do
before { champ.update value: "2017-12-31" }
@ -81,7 +81,7 @@ describe ChampDecorator do
end
describe "for a datetime" do
let(:type_champ) { :date }
let(:type_de_champ) { create(:type_de_champ_date) }
context "when value is an formatted datetime" do
before { champ.update value: "2017-12-30 23:17" }

View file

@ -1,21 +1,21 @@
FactoryBot.define do
factory :champ do
type_de_champ { FactoryBot.create(:type_de_champ) }
type_de_champ { create(:type_de_champ) }
trait :checkbox do
type_de_champ { FactoryBot.create(:type_de_champ, :checkbox) }
type_de_champ { create(:type_de_champ_checkbox) }
end
trait :header_section do
type_de_champ { FactoryBot.create(:type_de_champ, :header_section) }
type_de_champ { create(:type_de_champ_header_section) }
end
trait :explication do
type_de_champ { FactoryBot.create(:type_de_champ, :explication) }
type_de_champ { create(:type_de_champ_explication) }
end
trait :dossier_link do
type_de_champ { FactoryBot.create(:type_de_champ, :type_dossier_link) }
type_de_champ { create(:type_de_champ_dossier_link) }
end
end
end

View file

@ -67,7 +67,7 @@ FactoryBot.define do
trait :with_datetime do
after(:build) do |procedure, _evaluator|
type_de_champ = create(:type_de_champ, mandatory: true, type_champ: :datetime)
type_de_champ = create(:type_de_champ_datetime, mandatory: true)
procedure.types_de_champ << type_de_champ
end
@ -75,7 +75,7 @@ FactoryBot.define do
trait :with_dossier_link do
after(:build) do |procedure, _evaluator|
type_de_champ = create(:type_de_champ, :type_dossier_link)
type_de_champ = create(:type_de_champ_dossier_link)
procedure.types_de_champ << type_de_champ
end
@ -83,7 +83,7 @@ FactoryBot.define do
trait :with_yes_no do
after(:build) do |procedure, _evaluator|
type_de_champ = create(:type_de_champ, :type_yes_no)
type_de_champ = create(:type_de_champ_yes_no)
procedure.types_de_champ << type_de_champ
end
@ -114,27 +114,26 @@ FactoryBot.define do
trait :with_all_champs_mandatory do
after(:build) do |procedure, _evaluator|
tdcs = []
tdcs << create(:type_de_champ, type_champ: 'text', mandatory: true, libelle: 'text')
tdcs << create(:type_de_champ, type_champ: 'textarea', mandatory: true, libelle: 'textarea')
tdcs << create(:type_de_champ, type_champ: 'date', mandatory: true, libelle: 'date')
tdcs << create(:type_de_champ, type_champ: 'datetime', mandatory: true, libelle: 'datetime')
tdcs << create(:type_de_champ, type_champ: 'number', mandatory: true, libelle: 'number')
tdcs << create(:type_de_champ, type_champ: 'checkbox', mandatory: true, libelle: 'checkbox')
tdcs << create(:type_de_champ, type_champ: 'civilite', mandatory: true, libelle: 'civilite')
tdcs << create(:type_de_champ, type_champ: 'email', mandatory: true, libelle: 'email')
tdcs << create(:type_de_champ, type_champ: 'phone', mandatory: true, libelle: 'phone')
tdcs << create(:type_de_champ, type_champ: 'yes_no', mandatory: true, libelle: 'yes_no')
tdcs << create(:type_de_champ, :type_drop_down_list, mandatory: true, libelle: 'simple_drop_down_list')
tdcs << create(:type_de_champ, :type_drop_down_list, type_champ: 'multiple_drop_down_list', mandatory: true, libelle: 'multiple_drop_down_list')
tdcs << create(:type_de_champ, type_champ: 'pays', mandatory: true, libelle: 'pays')
tdcs << create(:type_de_champ, type_champ: 'regions', mandatory: true, libelle: 'regions')
tdcs << create(:type_de_champ, type_champ: 'departements', mandatory: true, libelle: 'departements')
tdcs << create(:type_de_champ, type_champ: 'engagement', mandatory: true, libelle: 'engagement')
tdcs << create(:type_de_champ, type_champ: 'header_section', mandatory: true, libelle: 'header_section')
tdcs << create(:type_de_champ, type_champ: 'explication', mandatory: true, libelle: 'explication')
tdcs << create(:type_de_champ, :type_dossier_link, mandatory: true, libelle: 'dossier_link')
tdcs << create(:type_de_champ, type_champ: 'piece_justificative', mandatory: true, libelle: 'piece_justificative')
tdcs << create(:type_de_champ, mandatory: true, libelle: 'text')
tdcs << create(:type_de_champ_textarea, mandatory: true, libelle: 'textarea')
tdcs << create(:type_de_champ_date, mandatory: true, libelle: 'date')
tdcs << create(:type_de_champ_datetime, mandatory: true, libelle: 'datetime')
tdcs << create(:type_de_champ_number, mandatory: true, libelle: 'number')
tdcs << create(:type_de_champ_checkbox, mandatory: true, libelle: 'checkbox')
tdcs << create(:type_de_champ_civilite, mandatory: true, libelle: 'civilite')
tdcs << create(:type_de_champ_email, mandatory: true, libelle: 'email')
tdcs << create(:type_de_champ_phone, mandatory: true, libelle: 'phone')
tdcs << create(:type_de_champ_yes_no, mandatory: true, libelle: 'yes_no')
tdcs << create(:type_de_champ_drop_down_list, mandatory: true, libelle: 'simple_drop_down_list')
tdcs << create(:type_de_champ_multiple_drop_down_list, mandatory: true, libelle: 'multiple_drop_down_list')
tdcs << create(:type_de_champ_pays, mandatory: true, libelle: 'pays')
tdcs << create(:type_de_champ_regions, mandatory: true, libelle: 'regions')
tdcs << create(:type_de_champ_departements, mandatory: true, libelle: 'departements')
tdcs << create(:type_de_champ_engagement, mandatory: true, libelle: 'engagement')
tdcs << create(:type_de_champ_header_section, mandatory: true, libelle: 'header_section')
tdcs << create(:type_de_champ_explication, mandatory: true, libelle: 'explication')
tdcs << create(:type_de_champ_dossier_link, mandatory: true, libelle: 'dossier_link')
tdcs << create(:type_de_champ_piece_justificative, mandatory: true, libelle: 'piece_justificative')
procedure.types_de_champ = tdcs
end
end

View file

@ -1,5 +1,5 @@
FactoryBot.define do
factory :type_de_champ do
factory :type_de_champ, class: 'TypesDeChamp::TextTypeDeChamp' do
private false
sequence(:libelle) { |n| "Libelle du champ #{n}" }
sequence(:description) { |n| "description du champ #{n}" }
@ -7,33 +7,74 @@ FactoryBot.define do
order_place 1
mandatory false
trait :checkbox do
factory :type_de_champ_text, class: 'TypesDeChamp::TextTypeDeChamp' do
type_champ 'text'
end
factory :type_de_champ_textarea, class: 'TypesDeChamp::TextareaTypeDeChamp' do
type_champ 'textarea'
end
factory :type_de_champ_number, class: 'TypesDeChamp::NumberTypeDeChamp' do
type_champ 'number'
end
factory :type_de_champ_checkbox, class: 'TypesDeChamp::CheckboxTypeDeChamp' do
type_champ 'checkbox'
end
trait :header_section do
type_champ 'header_section'
factory :type_de_champ_civilite, class: 'TypesDeChamp::CiviliteTypeDeChamp' do
type_champ 'civilite'
end
trait :explication do
type_champ 'explication'
factory :type_de_champ_email, class: 'TypesDeChamp::EmailTypeDeChamp' do
type_champ 'email'
end
trait :type_dossier_link do
libelle 'Référence autre dossier'
type_champ 'dossier_link'
factory :type_de_champ_phone, class: 'TypesDeChamp::PhoneTypeDeChamp' do
type_champ 'phone'
end
trait :type_yes_no do
factory :type_de_champ_address, class: 'TypesDeChamp::AddressTypeDeChamp' do
type_champ 'address'
end
factory :type_de_champ_yes_no, class: 'TypesDeChamp::YesNoTypeDeChamp' do
libelle 'Yes/no'
type_champ 'yes_no'
end
trait :type_drop_down_list do
factory :type_de_champ_date, class: 'TypesDeChamp::DateTypeDeChamp' do
type_champ 'date'
end
factory :type_de_champ_datetime, class: 'TypesDeChamp::DatetimeTypeDeChamp' do
type_champ 'datetime'
end
factory :type_de_champ_drop_down_list, class: 'TypesDeChamp::DropDownListTypeDeChamp' do
libelle 'Menu déroulant'
type_champ 'drop_down_list'
drop_down_list { create(:drop_down_list) }
end
factory :type_de_champ_multiple_drop_down_list, class: 'TypesDeChamp::MultipleDropDownListTypeDeChamp' do
type_champ 'multiple_drop_down_list'
drop_down_list { create(:drop_down_list) }
end
factory :type_de_champ_pays, class: 'TypesDeChamp::PaysTypeDeChamp' do
type_champ 'pays'
end
factory :type_de_champ_regions, class: 'TypesDeChamp::RegionTypeDeChamp' do
type_champ 'regions'
end
factory :type_de_champ_departements, class: 'TypesDeChamp::DepartementTypeDeChamp' do
type_champ 'departements'
end
factory :type_de_champ_engagement, class: 'TypesDeChamp::EngagementTypeDeChamp' do
type_champ 'engagement'
end
factory :type_de_champ_header_section, class: 'TypesDeChamp::HeaderSectionTypeDeChamp' do
type_champ 'header_section'
end
factory :type_de_champ_explication, class: 'TypesDeChamp::ExplicationTypeDeChamp' do
type_champ 'explication'
end
factory :type_de_champ_dossier_link, class: 'TypesDeChamp::DossierLinkTypeDeChamp' do
libelle 'Référence autre dossier'
type_champ 'dossier_link'
end
factory :type_de_champ_piece_justificative, class: 'TypesDeChamp::PieceJustificativeTypeDeChamp' do
type_champ 'piece_justificative'
end
trait :private do
private true

View file

@ -84,7 +84,7 @@ feature 'The user' do
end
let(:simple_procedure) do
tdcs = [create(:type_de_champ, type_champ: 'text', mandatory: true, libelle: 'text')]
tdcs = [create(:type_de_champ, mandatory: true, libelle: 'text')]
create(:procedure, :published, :for_individual, types_de_champ: tdcs)
end

View file

@ -2,7 +2,7 @@ require 'spec_helper'
describe '2018_03_06_clean_html_textareas#clean' do
let(:procedure) { create(:procedure) }
let(:type_champ) { create(:type_de_champ, procedure: procedure, type_champ: :textarea) }
let(:type_champ) { create(:type_de_champ_textarea, procedure: procedure) }
let(:champ) { type_champ.champ.create(value: "<p>Gnahar<br>greu bouahaha</p>") }
let(:champ_date) { Time.local(1995) }
let(:rake_date) { Time.local(2018) }

View file

@ -0,0 +1,31 @@
require 'spec_helper'
describe '2018_03_29_remove_code_tags_from_mail_templates#clean' do
let(:rake_task) { Rake::Task['2018_03_29_remove_code_tags_from_mail_templates:clean'] }
let!(:dirty_closed_mail) { create(:closed_mail, body: "<h1>Salut</h1><br>Voici ton email avec une balise <code>--balise--</code>") }
let!(:dirty_initiated_mail) { create(:initiated_mail, body: "<h1>Salut</h1><br>Voici ton email avec une balise <code>--balise--</code>") }
let!(:dirty_received_mail) { create(:received_mail, body: "<h1>Salut</h1><br>Voici ton email avec une balise <code>--balise--</code>") }
let!(:dirty_refused_mail) { create(:refused_mail, body: "<h1>Salut</h1><br>Voici ton email avec une balise <code>--balise--</code>") }
let!(:dirty_without_continuation_mail) { create(:without_continuation_mail, body: "<h1>Salut</h1><br>Voici ton email avec une balise <code>--balise--</code>") }
before do
TPS::Application.load_tasks
rake_task.invoke
dirty_closed_mail.reload
dirty_initiated_mail.reload
dirty_received_mail.reload
dirty_refused_mail.reload
dirty_without_continuation_mail.reload
end
after { rake_task.reenable }
it 'cleans up code tags' do
expect(dirty_closed_mail.body).to eq("<h1>Salut</h1><br>Voici ton email avec une balise --balise--")
expect(dirty_initiated_mail.body).to eq("<h1>Salut</h1><br>Voici ton email avec une balise --balise--")
expect(dirty_received_mail.body).to eq("<h1>Salut</h1><br>Voici ton email avec une balise --balise--")
expect(dirty_refused_mail.body).to eq("<h1>Salut</h1><br>Voici ton email avec une balise --balise--")
expect(dirty_without_continuation_mail.body).to eq("<h1>Salut</h1><br>Voici ton email avec une balise --balise--")
end
end

View file

@ -33,7 +33,7 @@ shared_examples 'champ_spec' do
end
context "when type_champ=date" do
let(:type_de_champ) { create(:type_de_champ, type_champ: "date") }
let(:type_de_champ) { create(:type_de_champ_date) }
let(:champ) { type_de_champ.champ.create }
it "should convert %d/%m/%Y format to ISO" do

View file

@ -23,7 +23,7 @@ describe Champ do
end
describe '#format_datetime' do
let(:type_de_champ) { build(:type_de_champ, type_champ: 'datetime') }
let(:type_de_champ) { build(:type_de_champ_datetime) }
let(:champ) { type_de_champ.champ.build(value: value) }
before { champ.save }
@ -42,7 +42,7 @@ describe Champ do
end
describe '#multiple_select_to_string' do
let(:type_de_champ) { build(:type_de_champ, type_champ: 'multiple_drop_down_list') }
let(:type_de_champ) { build(:type_de_champ_multiple_drop_down_list) }
let(:champ) { type_de_champ.champ.build(value: value) }
before { champ.save }
@ -80,27 +80,26 @@ describe Champ do
end
describe 'for_export' do
let(:type_de_champ) { create(:type_de_champ, type_champ: type_champ) }
let(:type_de_champ) { create(:type_de_champ) }
let(:champ) { type_de_champ.champ.build(value: value) }
before { champ.save }
context 'when type_de_champ is text' do
let(:type_champ) { 'text' }
let(:value) { '123' }
it { expect(champ.for_export).to eq('123') }
end
context 'when type_de_champ is textarea' do
let(:type_champ) { 'textarea' }
let(:type_de_champ) { create(:type_de_champ_textarea) }
let(:value) { '<b>gras<b>' }
it { expect(champ.for_export).to eq('gras') }
end
context 'when type_de_champ is yes_no' do
let(:type_champ) { 'yes_no' }
let(:type_de_champ) { create(:type_de_champ_yes_no) }
context 'if yes' do
let(:value) { 'true' }
@ -122,11 +121,9 @@ describe Champ do
end
context 'when type_de_champ is multiple_drop_down_list' do
let(:type_champ) { 'multiple_drop_down_list' }
let(:type_de_champ) { create(:type_de_champ_multiple_drop_down_list) }
let(:value) { '["Crétinier", "Mousserie"]' }
before { type_de_champ.drop_down_list = create(:drop_down_list) }
it { expect(champ.for_export).to eq('Crétinier, Mousserie') }
end
end

View file

@ -161,8 +161,8 @@ describe TagsSubstitutionConcern, type: :model do
context 'when the procedure has 2 types de champ date and datetime' do
let(:types_de_champ) do
[
create(:type_de_champ, libelle: 'date', type_champ: 'date'),
create(:type_de_champ, libelle: 'datetime', type_champ: 'datetime')
create(:type_de_champ_date, libelle: 'date'),
create(:type_de_champ_datetime, libelle: 'datetime')
]
end

View file

@ -404,28 +404,39 @@ describe Dossier do
end
end
describe '#invite_by_user?' do
let(:dossier) { create :dossier }
let(:invite_user) { create :user, email: user_invite_email }
let(:invite_gestionnaire) { create :user, email: gestionnaire_invite_email }
let(:user_invite_email) { 'plup@plop.com' }
let(:gestionnaire_invite_email) { 'plap@plip.com' }
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, email: invite_user.email, type: 'InviteUser'
create :invite, dossier: dossier, user: invite_gestionnaire, email: invite_gestionnaire.email, type: 'InviteGestionnaire'
create(:invite, dossier: dossier, user: invite_user, type: 'InviteUser')
create(:invite, dossier: dossier, user: invite_gestionnaire, type: 'InviteGestionnaire')
end
subject { dossier.invite_by_user? email }
subject { dossier.owner_or_invite?(user) }
context 'when email is present on invite list' do
let(:email) { user_invite_email }
context 'when user is owner' do
let(:user) { owner }
it { is_expected.to be_truthy }
end
context 'when email is present on invite list' do
let(:email) { gestionnaire_invite_email }
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

View file

@ -47,14 +47,14 @@ describe DropDownList do
end
context 'when multiple' do
let(:type_de_champ) { build(:type_de_champ, type_champ: 'multiple_drop_down_list') }
let(:type_de_champ) { build(:type_de_champ_multiple_drop_down_list) }
let(:champ) { type_de_champ.champ.build(value: '["1","2"]').decorate }
it { expect(dropdownlist.selected_options(champ)).to match(['1', '2']) }
end
context 'when simple' do
let(:type_de_champ) { build(:type_de_champ, type_champ: 'drop_down_list') }
let(:type_de_champ) { build(:type_de_champ_drop_down_list) }
let(:champ) { type_de_champ.champ.build(value: '1').decorate }
it { expect(dropdownlist.selected_options(champ)).to match(['1']) }

View file

@ -155,10 +155,10 @@ describe Procedure do
let(:procedure) { create(:procedure, archived_at: archived_at, published_at: published_at, received_mail: received_mail) }
let!(:type_de_champ_0) { create(:type_de_champ, procedure: procedure, order_place: 0) }
let!(:type_de_champ_1) { create(:type_de_champ, procedure: procedure, order_place: 1) }
let!(:type_de_champ_2) { create(:type_de_champ, :type_drop_down_list, procedure: procedure, order_place: 2) }
let!(:type_de_champ_2) { create(:type_de_champ_drop_down_list, procedure: procedure, order_place: 2) }
let!(:type_de_champ_private_0) { create(:type_de_champ, :private, procedure: procedure, order_place: 0) }
let!(:type_de_champ_private_1) { create(:type_de_champ, :private, procedure: procedure, order_place: 1) }
let!(:type_de_champ_private_2) { create(:type_de_champ, :private, :type_drop_down_list, procedure: procedure, order_place: 2) }
let!(:type_de_champ_private_2) { create(:type_de_champ_drop_down_list, :private, procedure: procedure, order_place: 2) }
let!(:piece_justificative_0) { create(:type_de_piece_justificative, procedure: procedure, order_place: 0) }
let!(:piece_justificative_1) { create(:type_de_piece_justificative, procedure: procedure, order_place: 1) }
let(:received_mail){ create(:received_mail) }

View file

@ -15,6 +15,16 @@ shared_examples 'type_de_champ_spec' do
it { is_expected.to allow_value('datetime').for(:type_champ) }
it { is_expected.to allow_value('number').for(:type_champ) }
it { is_expected.to allow_value('checkbox').for(:type_champ) }
it do
TypeDeChamp.type_champs.each do |(type_champ, _)|
type_de_champ = create(:"type_de_champ_#{type_champ}")
champ = type_de_champ.champ.create
expect(type_de_champ.class.name).to match(/^TypesDeChamp::/)
expect(champ.class.name).to match(/^Champs::/)
end
end
end
context 'order_place' do

View file

@ -3,7 +3,7 @@ require 'spec_helper'
describe ChampsService do
let(:type_de_champ) { create(:type_de_champ) }
let(:type_de_champ_mandatory) { create(:type_de_champ, libelle: 'mandatory', mandatory: true) }
let(:type_de_champ_datetime) { create(:type_de_champ, type_champ: :datetime) }
let(:type_de_champ_datetime) { create(:type_de_champ_datetime) }
let!(:champ) { type_de_champ.champ.create(value: 'toto') }
let!(:champ_mandatory_empty) { type_de_champ_mandatory.champ.create }
let!(:champ_datetime) { type_de_champ_datetime.champ.create }

View file

@ -1,7 +1,7 @@
require 'spec_helper'
describe 'users/description/champs/date.html.haml', type: :view do
let(:type_champ) { create(:type_de_champ, type_champ: :date) }
let(:type_champ) { create(:type_de_champ_date) }
before do
render 'users/description/champs/date.html.haml', champ: champ

View file

@ -1,7 +1,7 @@
require 'spec_helper'
describe 'users/description/champs/dossier_link.html.haml', type: :view do
let(:type_champ) { create(:type_de_champ, type_champ: :dossier_link) }
let(:type_champ) { create(:type_de_champ_dossier_link) }
before do
render 'users/description/champs/dossier_link.html.haml', champ: champ

View file

@ -1,7 +1,7 @@
require 'spec_helper'
describe 'users/description/champs/engagement.html.haml', type: :view do
let(:type_champ) { create(:type_de_champ, type_champ: :engagement) }
let(:type_champ) { create(:type_de_champ_engagement) }
subject { render 'users/description/champs/engagement.html.haml', champ: champ }

View file

@ -1,5 +1,5 @@
describe 'users/description/champs/render_list_champs.html.haml', type: :view do
let(:type_champ) { create(:type_de_champ, :checkbox) }
let(:type_champ) { create(:type_de_champ_checkbox) }
context "with any champ" do
let!(:champ) { create(:champ, type_de_champ: type_champ, value: nil) }
@ -40,7 +40,7 @@ describe 'users/description/champs/render_list_champs.html.haml', type: :view do
end
context 'with a dossier_link' do
let(:type_champ) { create(:type_de_champ, type_champ: :dossier_link) }
let(:type_champ) { create(:type_de_champ_dossier_link) }
let!(:champ) { create(:champ, type_de_champ: type_champ, value: nil) }
before do

View file

@ -1,7 +1,7 @@
require 'spec_helper'
describe 'users/description/champs/yes_no.html.haml', type: :view do
let(:type_champ) { create(:type_de_champ, type_champ: :yes_no) }
let(:type_champ) { create(:type_de_champ_yes_no) }
before do
render 'users/description/champs/yes_no.html.haml', champ: champ