diff --git a/app/controllers/users/dossiers_controller.rb b/app/controllers/users/dossiers_controller.rb index e5bf6a48c..4193859c9 100644 --- a/app/controllers/users/dossiers_controller.rb +++ b/app/controllers/users/dossiers_controller.rb @@ -84,8 +84,12 @@ class Users::DossiersController < UsersController @facade = facade params[:dossier][:id] if checked_autorisation_donnees? - @facade.dossier.update_attributes(update_params) - + begin + @facade.dossier.update_attributes!(update_params) + rescue + flash.now.alert = @facade.dossier.errors.full_messages.join('
').html_safe + return render 'show' + end if @facade.dossier.procedure.module_api_carto.use_api_carto redirect_to url_for(controller: :carte, action: :show, dossier_id: @facade.dossier.id) else @@ -117,7 +121,7 @@ class Users::DossiersController < UsersController end def update_params - params.require(:dossier).permit(:autorisation_donnees) + params.require(:dossier).permit(:id, :autorisation_donnees, individual_attributes: [:nom, :prenom, :birthdate]) end def checked_autorisation_donnees? diff --git a/app/decorators/entreprise_decorator.rb b/app/decorators/entreprise_decorator.rb index fe34dbace..6db7236fe 100644 --- a/app/decorators/entreprise_decorator.rb +++ b/app/decorators/entreprise_decorator.rb @@ -2,7 +2,7 @@ class EntrepriseDecorator < Draper::Decorator delegate_all def raison_sociale_or_name - raison_sociale.nil? ? nom + ' ' + prenom : raison_sociale + raison_sociale.blank? ? nom + ' ' + prenom : raison_sociale end def effectif diff --git a/app/facades/dossier_facades.rb b/app/facades/dossier_facades.rb index 059462848..f44f1a9e5 100644 --- a/app/facades/dossier_facades.rb +++ b/app/facades/dossier_facades.rb @@ -50,6 +50,10 @@ class DossierFacades @dossier.ordered_champs_private end + def individual + @dossier.individual + end + def commentaires_files PieceJustificative.where(dossier_id: @dossier.id, type_de_piece_justificative_id: nil) end diff --git a/app/models/dossier.rb b/app/models/dossier.rb index ccae17f45..623cb9515 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -14,6 +14,7 @@ class Dossier < ActiveRecord::Base has_one :etablissement, dependent: :destroy has_one :entreprise, dependent: :destroy + has_one :individual, dependent: :destroy has_many :cerfa, dependent: :destroy has_many :pieces_justificatives, dependent: :destroy @@ -28,6 +29,8 @@ class Dossier < ActiveRecord::Base belongs_to :procedure belongs_to :user + accepts_nested_attributes_for :individual + delegate :siren, to: :entreprise delegate :siret, to: :etablissement, allow_nil: true delegate :types_de_piece_justificative, to: :procedure @@ -35,6 +38,7 @@ class Dossier < ActiveRecord::Base delegate :france_connect_information, to: :user after_save :build_default_champs, if: Proc.new { procedure_id_changed? } + after_save :build_default_individual, if: Proc.new { procedure.for_individual? } validates :user, presence: true @@ -66,6 +70,12 @@ class Dossier < ActiveRecord::Base end end + def build_default_individual + Individual.new(dossier_id: id).save(validate: false) + Entreprise.new(dossier_id: id).save(validate: false) + Etablissement.new(dossier_id: id, entreprise_id: entreprise.id).save(validate: false) + end + def ordered_champs champs.joins(', types_de_champ').where("champs.type_de_champ_id = types_de_champ.id AND types_de_champ.procedure_id = #{procedure.id}").order('order_place') end diff --git a/app/models/entreprise.rb b/app/models/entreprise.rb index ad3a8ee9b..8218f75e4 100644 --- a/app/models/entreprise.rb +++ b/app/models/entreprise.rb @@ -4,4 +4,10 @@ class Entreprise < ActiveRecord::Base has_one :rna_information, dependent: :destroy validates_presence_of :siren + + before_save :default_values + + def default_values + self.raison_sociale ||= '' + end end diff --git a/app/models/individual.rb b/app/models/individual.rb new file mode 100644 index 000000000..324438c48 --- /dev/null +++ b/app/models/individual.rb @@ -0,0 +1,9 @@ +class Individual < ActiveRecord::Base + belongs_to :dossier + + validates_uniqueness_of :dossier_id + + validates :nom, presence: true, allow_nil: false, allow_blank: false + validates :prenom, presence: true, allow_nil: false, allow_blank: false + validates :birthdate, presence: true, allow_nil: false, allow_blank: false +end diff --git a/app/views/backoffice/dossiers/show.html.haml b/app/views/backoffice/dossiers/show.html.haml index 6a99e2f16..6eaa95dde 100644 --- a/app/views/backoffice/dossiers/show.html.haml +++ b/app/views/backoffice/dossiers/show.html.haml @@ -7,8 +7,8 @@ = @facade.dossier.display_state = render partial: 'follow_action' - - = render partial: '/dossiers/infos_entreprise' + - unless @facade.procedure.for_individual? + = render partial: '/dossiers/infos_entreprise' = render partial: '/dossiers/infos_dossier' %br diff --git a/app/views/dossiers/etapes/_etape2.html.haml b/app/views/dossiers/etapes/_etape2.html.haml index 2e8f161e9..3f36a3c2a 100644 --- a/app/views/dossiers/etapes/_etape2.html.haml +++ b/app/views/dossiers/etapes/_etape2.html.haml @@ -1,40 +1,4 @@ -.etape.etapes_menu.col-md-3.col-lg-3 - %h3 - Mes informations - %br - - unless @facade.entreprise.nil? - .center{style:'margin-left: -5%'} - Vous êtes authentifié avec le SIRET - - %h3.text-success - = @facade.etablissement.siret - = form_for @facade.dossier, url: users_dossier_change_siret_path(dossier_id: @facade.dossier.id), method: :put, remote: true do |f| - = f.submit 'Changer de SIRET', class: %w(btn btn-xs btn-primary) - - -.etape.etapes_informations.col-md-9.col-lg-9 - .row - - if @facade.entreprise.nil? - #new_siret{style:'margin-left: 20%; margin-top: 5%'} - = form_for @facade.dossier, html: {class: 'form-inline'}, url: users_dossier_siret_informations_path(dossier_id: @facade.dossier.id), method: :post, remote: true do |f| - .form-group.form-group-lg - = f.text_field :siret, class: "form-control", placeholder: "Entrez votre Siret", value: @siret - = f.hidden_field :dossier_id, value: @facade.dossier.id - = f.submit 'Valider', class: %w(btn btn-lg btn-success), data: { disable_with: "Recherche en cours ..." } - - else - %br - #recap_info_entreprise - = render partial: '/dossiers/infos_entreprise' - - %p#insee_infogreffe{style:'color:grey; float:right'} - %i - Informations récupérées auprès de l'INSEE et d'INFOGREFFE - - %br - = form_for @facade.dossier, url: { controller: '/users/dossiers', action: :update } do |f| - = f.hidden_field :id - %label{ style:'font-weight:normal' } - = f.check_box :autorisation_donnees - J'autorise les décideurs publics à vérifier les informations de mon organisation auprès des administrations concernées. Ces informations resteront strictement confidentielles. - %br - = f.submit 'Etape suivante', class: "btn btn btn-info", style: 'float:right', id: 'etape_suivante', disabled: :disabled +- if @facade.procedure.for_individual? + = render partial: 'dossiers/etapes/etape_2/individual' +- else + = render partial: 'dossiers/etapes/etape_2/entreprise' \ No newline at end of file diff --git a/app/views/dossiers/etapes/etape_2/_entreprise.html.haml b/app/views/dossiers/etapes/etape_2/_entreprise.html.haml new file mode 100644 index 000000000..2e8f161e9 --- /dev/null +++ b/app/views/dossiers/etapes/etape_2/_entreprise.html.haml @@ -0,0 +1,40 @@ +.etape.etapes_menu.col-md-3.col-lg-3 + %h3 + Mes informations + %br + - unless @facade.entreprise.nil? + .center{style:'margin-left: -5%'} + Vous êtes authentifié avec le SIRET + + %h3.text-success + = @facade.etablissement.siret + = form_for @facade.dossier, url: users_dossier_change_siret_path(dossier_id: @facade.dossier.id), method: :put, remote: true do |f| + = f.submit 'Changer de SIRET', class: %w(btn btn-xs btn-primary) + + +.etape.etapes_informations.col-md-9.col-lg-9 + .row + - if @facade.entreprise.nil? + #new_siret{style:'margin-left: 20%; margin-top: 5%'} + = form_for @facade.dossier, html: {class: 'form-inline'}, url: users_dossier_siret_informations_path(dossier_id: @facade.dossier.id), method: :post, remote: true do |f| + .form-group.form-group-lg + = f.text_field :siret, class: "form-control", placeholder: "Entrez votre Siret", value: @siret + = f.hidden_field :dossier_id, value: @facade.dossier.id + = f.submit 'Valider', class: %w(btn btn-lg btn-success), data: { disable_with: "Recherche en cours ..." } + - else + %br + #recap_info_entreprise + = render partial: '/dossiers/infos_entreprise' + + %p#insee_infogreffe{style:'color:grey; float:right'} + %i + Informations récupérées auprès de l'INSEE et d'INFOGREFFE + + %br + = form_for @facade.dossier, url: { controller: '/users/dossiers', action: :update } do |f| + = f.hidden_field :id + %label{ style:'font-weight:normal' } + = f.check_box :autorisation_donnees + J'autorise les décideurs publics à vérifier les informations de mon organisation auprès des administrations concernées. Ces informations resteront strictement confidentielles. + %br + = f.submit 'Etape suivante', class: "btn btn btn-info", style: 'float:right', id: 'etape_suivante', disabled: :disabled diff --git a/app/views/dossiers/etapes/etape_2/_individual.html.haml b/app/views/dossiers/etapes/etape_2/_individual.html.haml new file mode 100644 index 000000000..0b1c37ece --- /dev/null +++ b/app/views/dossiers/etapes/etape_2/_individual.html.haml @@ -0,0 +1,40 @@ +.etape.etapes_menu.col-md-3.col-lg-3 + %h3 + Mes informations + %br + %p.center + Les informations de bases + %br + vous concernant. + +.etape.etapes_informations.col-md-9.col-lg-9 + .row + = form_for @facade.dossier, url: { controller: '/users/dossiers', action: :update } do |f| + = f.hidden_field :id + + = f.fields_for :individual, @facade.individual do |ff| + .form-group + %label + %h4 + Nom + = ff.text_field :nom, {class: 'form-control'} + .form-group + %label + %h4 + Prénom + = ff.text_field :prenom, {class: 'form-control'} + .form-group + %label + %h4 + Date de naissance + = ff.text_field :birthdate, {class: 'form-control', 'data-provide' => 'datepicker', 'data-date-format' => 'dd/mm/yyyy'} + + %p + %label{ style:'font-weight:normal' } + = f.check_box :autorisation_donnees + = " ".html_safe + Vos informations personnelles ne seront jamais utilisées dans un but lucratif ou commercial. Elles ne pourront être communiquées à de tiers personnes sans votre accord préalable. Elles pourront en revanche être communiquées aux administrations compétentes afin d'instruire votre dossier, conformément à la déclaration CNIL effectué par le service TPS. + =link_to 'en savoir plus', cgu_path, target: '_blank' + + %br + = f.submit 'Etape suivante', class: "btn btn btn-info", style: 'float:right', id: 'etape_suivante' diff --git a/app/views/users/dossiers/_list.html.haml b/app/views/users/dossiers/_list.html.haml index 3f788cee0..e8bdcc86d 100644 --- a/app/views/users/dossiers/_list.html.haml +++ b/app/views/users/dossiers/_list.html.haml @@ -1,8 +1,8 @@ - unless smart_listing.empty? %table.table %thead - %th.col-md-4.col-lg-4= smart_listing.sortable 'Procédure', 'procedure.libelle' - %th.col-md-4.col-lg-4= smart_listing.sortable 'Raison sociale', 'entreprise.raison_sociale' + %th.col-md-1.col-lg-1= smart_listing.sortable 'Numéro', 'id' + %th.col-md-5.col-lg-5= smart_listing.sortable 'Procédure', 'procedure.libelle' %th.col-md-2.col-lg-2= smart_listing.sortable 'État', 'state' %th.col-md-2.col-lg-2= smart_listing.sortable 'Date de mise à jour', 'updated_at' - @dossiers.each do |dossier| @@ -12,11 +12,11 @@ - else - dossier = dossier.decorate %tr + %td.center + = dossier.id %td - = dossier.procedure.libelle - %td - = link_to(dossier.entreprise.raison_sociale, users_dossiers_invite_path(id: invite.id)) unless invite.nil? - = link_to(dossier.entreprise.raison_sociale, users_dossier_recapitulatif_path(dossier)) if invite.nil? + = link_to(dossier.procedure.libelle, users_dossiers_invite_path(id: invite.id)) unless invite.nil? + = link_to(dossier.procedure.libelle, users_dossier_recapitulatif_path(dossier)) if invite.nil? %td{id: "dossier_#{dossier.id}_state"}= dossier.display_state %td= dossier.last_update diff --git a/app/views/users/registrations/new.html.haml b/app/views/users/registrations/new.html.haml index 4e780d97f..17054c523 100644 --- a/app/views/users/registrations/new.html.haml +++ b/app/views/users/registrations/new.html.haml @@ -29,6 +29,7 @@ = devise_error_messages! #form_login + %br = image_tag('logo-tps.png') %br %h2#gestionnaire_login Inscription diff --git a/config/locales/models/individual/fr.yml b/config/locales/models/individual/fr.yml new file mode 100644 index 000000000..88aba8e77 --- /dev/null +++ b/config/locales/models/individual/fr.yml @@ -0,0 +1,19 @@ +fr: + activerecord: + attributes: + individual: + nom: Nom + prenom: Prénom + birthdate: Date de naissance + errors: + models: + individual: + attributes: + nom: + blank: 'doit être rempli' + prenom: + blank: 'doit être rempli' + birthdate: + blank: 'doit être rempli' + + diff --git a/db/migrate/20160829114646_create_individual_table.rb b/db/migrate/20160829114646_create_individual_table.rb new file mode 100644 index 000000000..f93c6a8ca --- /dev/null +++ b/db/migrate/20160829114646_create_individual_table.rb @@ -0,0 +1,11 @@ +class CreateIndividualTable < ActiveRecord::Migration + def change + create_table :individuals do |t| + t.string :nom + t.string :prenom + t.string :birthdate + end + + add_belongs_to :individuals, :dossier + end +end diff --git a/db/schema.rb b/db/schema.rb index c06938ac8..5cb43da5e 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160829094658) do +ActiveRecord::Schema.define(version: 20160829114646) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -213,6 +213,13 @@ ActiveRecord::Schema.define(version: 20160829094658) do add_index "gestionnaires", ["email"], name: "index_gestionnaires_on_email", unique: true, using: :btree add_index "gestionnaires", ["reset_password_token"], name: "index_gestionnaires_on_reset_password_token", unique: true, using: :btree + create_table "individuals", force: :cascade do |t| + t.string "nom" + t.string "prenom" + t.string "birthdate" + t.integer "dossier_id" + end + create_table "invites", force: :cascade do |t| t.string "email" t.string "email_sender" diff --git a/spec/features/backoffice/navigate_to_dossier_spec.rb b/spec/features/backoffice/navigate_to_dossier_spec.rb index 8f29befa2..972c70f58 100644 --- a/spec/features/backoffice/navigate_to_dossier_spec.rb +++ b/spec/features/backoffice/navigate_to_dossier_spec.rb @@ -29,5 +29,21 @@ feature 'on backoffice page' do expect(page).to have_css('#backoffice_dossier_show') end end + + context 'when gestionnaire have enterprise and individual dossier in his inbox' do + let!(:procedure_individual) { create :procedure, libelle: 'procedure individual', administrateur: administrateur, for_individual: true } + let!(:dossier_individual) { create :dossier, procedure: procedure_individual, state: 'updated' } + + before do + create :assign_to, gestionnaire: gestionnaire, procedure: procedure_individual + + visit backoffice_path + page.click_on dossier_individual.id + end + + scenario 'it redirect to dossier page' do + expect(page).to have_css('#backoffice_dossier_show') + end + end end end \ No newline at end of file diff --git a/spec/features/users/list_dossiers_spec.rb b/spec/features/users/list_dossiers_spec.rb index acf68a384..85fdc963f 100644 --- a/spec/features/users/list_dossiers_spec.rb +++ b/spec/features/users/list_dossiers_spec.rb @@ -9,8 +9,8 @@ feature 'user access to the list of his dossier' do before do dossier1.update_column(:updated_at, "19/07/2052 15:35".to_time) - dossier1.entreprise.update_column(:raison_sociale, 'PLOP') - last_updated_dossier.entreprise.update_column(:raison_sociale, 'PLIP') + dossier1.procedure.update_column(:libelle, 'PLOP') + last_updated_dossier.procedure.update_column(:libelle, 'PLIP') visit new_user_session_path within('#new_user') do @@ -20,12 +20,12 @@ feature 'user access to the list of his dossier' do end end scenario 'the list of dossier is displayed' do - expect(page).to have_content(dossier1.entreprise.raison_sociale) - expect(page).not_to have_content(dossier2.entreprise.raison_sociale) + expect(page).to have_content(dossier1.procedure.libelle) + expect(page).not_to have_content(dossier2.procedure.libelle) end scenario 'the list must be order by last updated' do - expect(page.body).to match(/#{last_updated_dossier.entreprise.raison_sociale}.*#{dossier1.entreprise.raison_sociale}/m) + expect(page.body).to match(/#{last_updated_dossier.procedure.libelle}.*#{dossier1.procedure.libelle}/m) end scenario 'the state of dossier is displayed' do @@ -34,7 +34,7 @@ feature 'user access to the list of his dossier' do context 'when user clicks on a projet in list' do before do - page.click_on dossier1.entreprise.raison_sociale + page.click_on dossier1.procedure.libelle end scenario 'user is redirected to dossier page' do expect(page).to have_css('#recap_dossier') diff --git a/spec/mailers/notification_mailer_spec.rb b/spec/mailers/notification_mailer_spec.rb index 48a3e25e5..44f5d68ea 100644 --- a/spec/mailers/notification_mailer_spec.rb +++ b/spec/mailers/notification_mailer_spec.rb @@ -19,7 +19,7 @@ RSpec.describe NotificationMailer, type: :mailer do subject(:subject) { described_class.dossier_validated(dossier) } it { expect(subject.body).to match("Votre dossier N°#{dossier.id} a été validé par votre accompagnateur.") } - it { expect(subject.body).to include("Afin de finaliser son dépot, merci de vous rendre sur #{users_dossier_recapitulatif_url(dossier_id: dossier.id)}") } + it { expect(subject.body).to include("Afin de finaliser son dépôt, merci de vous rendre sur #{users_dossier_recapitulatif_url(dossier_id: dossier.id)}") } it { expect(subject.subject).to eq("Votre dossier TPS N°#{dossier.id} a été validé") } end @@ -30,7 +30,7 @@ RSpec.describe NotificationMailer, type: :mailer do subject(:subject) { described_class.dossier_submitted(dossier) } it { expect(subject.body).to match("Nous vous confirmons que votre dossier N°#{dossier.id} a été déposé") } - it { expect(subject.body).to match("aurpès de #{dossier.procedure.organisation} avec succès") } + it { expect(subject.body).to match("auprès de #{dossier.procedure.organisation} avec succès") } it { expect(subject.body).to match("ce jour à #{dossier.updated_at}.") } it { expect(subject.subject).to eq("Votre dossier TPS N°#{dossier.id} a été déposé") } end diff --git a/spec/models/dossier_spec.rb b/spec/models/dossier_spec.rb index 19c46a4f1..583a47410 100644 --- a/spec/models/dossier_spec.rb +++ b/spec/models/dossier_spec.rb @@ -23,6 +23,7 @@ describe Dossier do it { is_expected.to have_many(:cerfa) } it { is_expected.to have_one(:etablissement) } it { is_expected.to have_one(:entreprise) } + it { is_expected.to have_one(:individual) } it { is_expected.to belong_to(:user) } it { is_expected.to have_many(:invites) } it { is_expected.to have_many(:follows) } @@ -105,6 +106,24 @@ describe Dossier do end end + describe '#build_default_individual' do + context 'when dossier is linked to a procedure with for_individual attr false' do + let(:dossier) { create(:dossier, user: user) } + + it 'have no object created' do + expect(dossier.individual).to be_nil + end + end + + context 'when dossier is linked to a procedure with for_individual attr true' do + let(:dossier) { create(:dossier, user: user, procedure: (create :procedure, for_individual: true)) } + + it 'have no object created' do + expect(dossier.individual).not_to be_nil + end + end + end + describe '#save' do subject { build(:dossier, procedure: procedure, user: user) } let!(:procedure) { create(:procedure) } diff --git a/spec/models/individual_spec.rb b/spec/models/individual_spec.rb new file mode 100644 index 000000000..e0d02e03b --- /dev/null +++ b/spec/models/individual_spec.rb @@ -0,0 +1,8 @@ +require 'spec_helper' + +describe Individual do + it { is_expected.to have_db_column(:nom) } + it { is_expected.to have_db_column(:prenom) } + it { is_expected.to have_db_column(:birthdate) } + it { is_expected.to belong_to(:dossier) } +end diff --git a/spec/views/users/dossiers/index_html.haml_spec.rb b/spec/views/users/dossiers/index_html.haml_spec.rb index c6424b4d0..617cb3276 100644 --- a/spec/views/users/dossiers/index_html.haml_spec.rb +++ b/spec/views/users/dossiers/index_html.haml_spec.rb @@ -15,15 +15,6 @@ describe 'users/dossiers/index.html.haml', type: :view do let!(:decorate_dossier_invite) { create(:dossier, :with_entreprise, user: create(:user), state: 'initiated').decorate } before do - decorate_dossier_replied.entreprise.update_column(:raison_sociale, 'plap') - decorate_dossier_updated.entreprise.update_column(:raison_sociale, 'plep') - decorate_dossier_validated.entreprise.update_column(:raison_sociale, 'plip') - decorate_dossier_submitted.entreprise.update_column(:raison_sociale, 'plop') - decorate_dossier_received.entreprise.update_column(:raison_sociale, 'plup') - decorate_dossier_closed.entreprise.update_column(:raison_sociale, 'plyp') - decorate_dossier_refused.entreprise.update_column(:raison_sociale, 'plzp') - decorate_dossier_without_continuation.entreprise.update_column(:raison_sociale, 'plnp') - create :invite, dossier: decorate_dossier_invite, user: user end @@ -42,8 +33,8 @@ describe 'users/dossiers/index.html.haml', type: :view do subject { rendered } describe 'columns' do + it { is_expected.to have_content(decorate_dossier_at_check.id) } it { is_expected.to have_content(decorate_dossier_at_check.procedure.libelle) } - it { is_expected.to have_content(decorate_dossier_at_check.entreprise.raison_sociale) } it { is_expected.to have_content(decorate_dossier_at_check.display_state) } it { is_expected.to have_content(decorate_dossier_at_check.last_update) } end