diff --git a/Gemfile b/Gemfile index c5a760d5e..7e40ba5ab 100644 --- a/Gemfile +++ b/Gemfile @@ -60,7 +60,6 @@ gem 'premailer-rails' gem 'puma' # Use Puma as the app server gem 'pundit' gem 'rack-attack' -gem 'rack-mini-profiler' gem 'rails' gem 'rails-i18n' # Locales par défaut gem 'rake-progressbar', require: false @@ -104,6 +103,7 @@ group :development do gem 'brakeman', require: false gem 'haml-lint' gem 'letter_opener_web' + gem 'rack-mini-profiler' gem 'rails-erd', require: false # generates `doc/database_models.pdf` gem 'rubocop', require: false gem 'rubocop-rails_config' diff --git a/app/assets/fonts/Muli-Bold.woff b/app/assets/fonts/Muli-Bold.woff index fc7a6fa82..32cd7c7b9 100644 Binary files a/app/assets/fonts/Muli-Bold.woff and b/app/assets/fonts/Muli-Bold.woff differ diff --git a/app/assets/fonts/Muli-Bold.woff2 b/app/assets/fonts/Muli-Bold.woff2 new file mode 100644 index 000000000..238cad90c Binary files /dev/null and b/app/assets/fonts/Muli-Bold.woff2 differ diff --git a/app/assets/fonts/Muli-Italic.woff b/app/assets/fonts/Muli-Italic.woff index 9358d8ea3..9780f52c7 100644 Binary files a/app/assets/fonts/Muli-Italic.woff and b/app/assets/fonts/Muli-Italic.woff differ diff --git a/app/assets/fonts/Muli-Italic.woff2 b/app/assets/fonts/Muli-Italic.woff2 new file mode 100644 index 000000000..13b30a7e1 Binary files /dev/null and b/app/assets/fonts/Muli-Italic.woff2 differ diff --git a/app/assets/fonts/Muli-Regular.woff b/app/assets/fonts/Muli-Regular.woff index f61ecf832..061938363 100644 Binary files a/app/assets/fonts/Muli-Regular.woff and b/app/assets/fonts/Muli-Regular.woff differ diff --git a/app/assets/fonts/Muli-Regular.woff2 b/app/assets/fonts/Muli-Regular.woff2 new file mode 100644 index 000000000..aabeed2ca Binary files /dev/null and b/app/assets/fonts/Muli-Regular.woff2 differ diff --git a/app/assets/images/footer/logo-dinum.png b/app/assets/images/footer/logo-dinum.png new file mode 100644 index 000000000..86c7d6902 Binary files /dev/null and b/app/assets/images/footer/logo-dinum.png differ diff --git a/app/assets/images/footer/logo-dinum.svg b/app/assets/images/footer/logo-dinum.svg deleted file mode 100644 index 096f4714b..000000000 --- a/app/assets/images/footer/logo-dinum.svg +++ /dev/null @@ -1 +0,0 @@ -BM_DINUM diff --git a/app/assets/images/logo-france-connect.png b/app/assets/images/logo-france-connect.png new file mode 100644 index 000000000..c33a34723 Binary files /dev/null and b/app/assets/images/logo-france-connect.png differ diff --git a/app/assets/images/marianne.png b/app/assets/images/marianne.png new file mode 100644 index 000000000..a84a7bc79 Binary files /dev/null and b/app/assets/images/marianne.png differ diff --git a/app/assets/stylesheets/new_design/fonts.scss b/app/assets/stylesheets/new_design/fonts.scss index 2e093a609..c315a61d8 100644 --- a/app/assets/stylesheets/new_design/fonts.scss +++ b/app/assets/stylesheets/new_design/fonts.scss @@ -1,20 +1,23 @@ @font-face { font-family: "Muli"; - src: asset-url("Muli-Regular.woff") format("woff"); + src: asset-url("Muli-Regular.woff2") format("woff2"), + asset-url("Muli-Regular.woff") format("woff"); font-weight: normal; font-style: normal; } @font-face { font-family: "Muli"; - src: asset-url("Muli-Bold.woff") format("woff"); + src: asset-url("Muli-Bold.woff2") format("woff2"), + asset-url("Muli-Bold.woff") format("woff"); font-weight: bold; font-style: normal; } @font-face { font-family: "Muli"; - src: asset-url("Muli-Italic.woff") format("woff"); + src: asset-url("Muli-Italic.woff2") format("woff2"), + asset-url("Muli-Italic.woff") format("woff"); font-weight: normal; font-style: italic; } diff --git a/app/assets/stylesheets/new_design/new_footer.scss b/app/assets/stylesheets/new_design/new_footer.scss index c64c24d50..ee726a9ef 100644 --- a/app/assets/stylesheets/new_design/new_footer.scss +++ b/app/assets/stylesheets/new_design/new_footer.scss @@ -61,7 +61,6 @@ footer { } .footer-text { - font-style: italic; margin-bottom: 14px; } @@ -70,10 +69,10 @@ footer { } .footer-logo-dinum { - @include ie-compatible-background-image("footer/logo-dinum.svg"); + @include ie-compatible-background-image("footer/logo-dinum.png"); - height: 104px; - width: 90px; + height: 150px; + width: 202px; margin-bottom: 14px; } diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 7ed38f687..4c795d27c 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -12,7 +12,6 @@ class ApplicationController < ActionController::Base before_action :load_navbar_left_pannel_partial_url before_action :set_raven_context before_action :redirect_if_untrusted - before_action :authorize_request_for_profiler before_action :reject, if: -> { feature_enabled?(:maintenance_mode) } before_action :staging_authenticate @@ -30,12 +29,6 @@ class ApplicationController < ActionController::Base end end - def authorize_request_for_profiler - if feature_enabled?(:mini_profiler) - Rack::MiniProfiler.authorize_request - end - end - def load_navbar_left_pannel_partial_url controller = request.controller_class method = params[:action] diff --git a/app/controllers/champs/siret_controller.rb b/app/controllers/champs/siret_controller.rb index 98ebb81ee..4e8ba19a2 100644 --- a/app/controllers/champs/siret_controller.rb +++ b/app/controllers/champs/siret_controller.rb @@ -16,7 +16,7 @@ class Champs::SiretController < ApplicationController begin etablissement = find_etablissement_with_siret - rescue ApiEntreprise::API::RequestFailed + rescue ApiEntreprise::API::RequestFailed, ApiEntreprise::API::ServiceUnavailable return siret_error(:network_error) end if etablissement.nil? diff --git a/app/controllers/instructeurs/procedures_controller.rb b/app/controllers/instructeurs/procedures_controller.rb index 5ab52a73c..67d13b647 100644 --- a/app/controllers/instructeurs/procedures_controller.rb +++ b/app/controllers/instructeurs/procedures_controller.rb @@ -98,6 +98,12 @@ module Instructeurs @archived_dossiers end + @has_en_cours_notifications = current_instructeur.notifications_for_procedure(@procedure, :en_cours).exists? + @has_termine_notifications = current_instructeur.notifications_for_procedure(@procedure, :termine).exists? + + @not_archived_notifications_dossier_ids = current_instructeur.notifications_for_procedure(@procedure, :not_archived).pluck(:id) + @counters = @procedure.dossiers_count_for_instructeur(current_instructeur) + sorted_ids = procedure_presentation.sorted_ids(@dossiers, current_instructeur) if @current_filters.count > 0 diff --git a/app/jobs/api_entreprise/attestation_sociale_job.rb b/app/jobs/api_entreprise/attestation_sociale_job.rb index 581ed8037..cdaad27d2 100644 --- a/app/jobs/api_entreprise/attestation_sociale_job.rb +++ b/app/jobs/api_entreprise/attestation_sociale_job.rb @@ -1,4 +1,6 @@ class ApiEntreprise::AttestationSocialeJob < ApiEntreprise::Job + retry_on ApiEntreprise::API::ServiceUnavailable, wait: 1.day + def perform(etablissement_id, procedure_id) etablissement = Etablissement.find(etablissement_id) etablissement_params = ApiEntreprise::AttestationSocialeAdapter.new(etablissement.siret, procedure_id).to_params diff --git a/app/lib/api_entreprise/api.rb b/app/lib/api_entreprise/api.rb index c953052ed..716c28f30 100644 --- a/app/lib/api_entreprise/api.rb +++ b/app/lib/api_entreprise/api.rb @@ -20,6 +20,9 @@ class ApiEntreprise::API class BadFormatRequest < StandardError end + class ServiceUnavailable < StandardError + end + def self.entreprise(siren, procedure_id) call(ENTREPRISE_RESOURCE_NAME, siren, procedure_id) end @@ -76,7 +79,9 @@ class ApiEntreprise::API elsif response.code&.between?(401, 499) raise ResourceNotFound, "url: #{url}" elsif response.code == 400 - raise BadFormatRequest, "url: #{url}" + raise BadFormatRequest, "url: #{url}" + elsif response.code == 503 + raise ServiceUnavailable, "url: #{url}" else raise RequestFailed, "HTTP Error Code: #{response.code} for #{url}\nheaders: #{response.headers}\nbody: #{response.body}" end diff --git a/app/models/procedure.rb b/app/models/procedure.rb index a54c42d33..11b87db3f 100644 --- a/app/models/procedure.rb +++ b/app/models/procedure.rb @@ -630,6 +630,46 @@ class Procedure < ApplicationRecord draft_revision.deep_clone(include: [:revision_types_de_champ, :revision_types_de_champ_private]) end + def dossiers_count_for_instructeur(instructeur) + query = <<-EOF + SELECT + COUNT(*) FILTER ( WHERE "dossiers"."state" in ('en_construction', 'en_instruction') and (("follows"."id" IS NULL) or ("follows"."instructeur_id" = :instructeur_id and "follows"."unfollowed_at" < :now)) and not "dossiers"."archived") AS a_suivre, + COUNT(*) FILTER ( WHERE "dossiers"."state" in ('en_construction', 'en_instruction') and "follows"."instructeur_id" = :instructeur_id and not "dossiers"."archived" and "follows"."unfollowed_at" IS NULL) AS suivis, + COUNT(*) FILTER ( WHERE "dossiers"."state" in ('accepte', 'refuse', 'sans_suite') and not "dossiers"."archived" ) AS termines, + COUNT(*) FILTER ( WHERE "dossiers"."state" != 'brouillon' and not "dossiers"."archived" ) AS total, + COUNT(*) FILTER ( WHERE "dossiers"."archived" ) AS archived + FROM + "dossiers" + INNER JOIN + "groupe_instructeurs" + ON "dossiers"."groupe_instructeur_id" = "groupe_instructeurs"."id" + INNER JOIN + "assign_tos" + ON "groupe_instructeurs"."id" = "assign_tos"."groupe_instructeur_id" + INNER JOIN + "procedures" + ON "groupe_instructeurs"."procedure_id" = "procedures"."id" + LEFT OUTER JOIN + "follows" + ON "follows"."dossier_id" = "dossiers"."id" + WHERE + "dossiers"."hidden_at" IS NULL + AND "assign_tos"."instructeur_id" = :instructeur_id + AND "procedures"."id" = :procedure_id + GROUP BY + groupe_instructeurs.procedure_id, procedures.libelle + EOF + + sanitized_query = ActiveRecord::Base.sanitize_sql([ + query, + instructeur_id: instructeur.id, + procedure_id: self.id, + now: Time.zone.now + ]) + + Procedure.connection.select_all(sanitized_query).first || { "a_suivre" => 0, "suivis" => 0, "termines" => 0, "total" => 0, "archived" => 0 } + end + private def before_publish diff --git a/app/models/procedure_presentation.rb b/app/models/procedure_presentation.rb index 82d8ca2dc..da3ede8ba 100644 --- a/app/models/procedure_presentation.rb +++ b/app/models/procedure_presentation.rb @@ -82,7 +82,6 @@ class ProcedurePresentation < ApplicationRecord end def displayed_field_values(dossier) - assert_matching_procedure(dossier) displayed_fields.map { |field| get_value(dossier, field['table'], field['column']) } end @@ -256,12 +255,6 @@ class ProcedurePresentation < ApplicationRecord end end - def assert_matching_procedure(dossier) - if dossier.procedure != procedure - raise "Procedure mismatch (expected #{procedure.id}, got #{dossier.procedure.id})" - end - end - def get_value(dossier, table, column) case table when 'self' diff --git a/app/views/dossiers/show.pdf.prawn b/app/views/dossiers/show.pdf.prawn index 36c1c6329..da7d7f360 100644 --- a/app/views/dossiers/show.pdf.prawn +++ b/app/views/dossiers/show.pdf.prawn @@ -188,6 +188,9 @@ prawn_document(page_size: "A4") do |pdf| add_title(pdf, "Identité du demandeur") + if @dossier.user.france_connect_information.present? + format_in_2_columns(pdf, 'Informations France Connect', "Le dossier a été déposé par le compte de #{@dossier.individual.prenom} #{@dossier.individual.nom}, authentifié par France Connect le #{@dossier.individual.updated_at.strftime('%d/%m/%Y')}") + end format_in_2_columns(pdf, "Email", @dossier.user.email) add_identite_individual(pdf, @dossier) if @dossier.individual.present? render_identite_etablissement(pdf, @dossier.etablissement) if @dossier.etablissement.present? diff --git a/app/views/instructeurs/procedures/show.html.haml b/app/views/instructeurs/procedures/show.html.haml index 520004861..b425fe13a 100644 --- a/app/views/instructeurs/procedures/show.html.haml +++ b/app/views/instructeurs/procedures/show.html.haml @@ -24,29 +24,29 @@ = tab_item('à suivre', instructeur_procedure_path(@procedure, statut: 'a-suivre'), active: @statut == 'a-suivre', - badge: number_with_html_delimiter(@a_suivre_dossiers.count)) + badge: number_with_html_delimiter(@counters['a_suivre'])) - = tab_item(t('pluralize.followed', count: @followed_dossiers.count), + = tab_item(t('pluralize.followed', count: @counters['suivis']), instructeur_procedure_path(@procedure, statut: 'suivis'), active: @statut == 'suivis', - badge: number_with_html_delimiter(@followed_dossiers.count), - notification: current_instructeur.notifications_for_procedure(@procedure, :en_cours).exists?) + badge: number_with_html_delimiter(@counters['suivis']), + notification: @has_en_cours_notifications) - = tab_item(t('pluralize.processed', count: @termines_dossiers.count), + = tab_item(t('pluralize.processed', count: @counters['termines']), instructeur_procedure_path(@procedure, statut: 'traites'), active: @statut == 'traites', - badge: number_with_html_delimiter(@termines_dossiers.count), - notification: current_instructeur.notifications_for_procedure(@procedure, :termine).exists?) + badge: number_with_html_delimiter(@counters['termines']), + notification: @has_termine_notifications) = tab_item('tous les dossiers', instructeur_procedure_path(@procedure, statut: 'tous'), active: @statut == 'tous', - badge: number_with_html_delimiter(@all_state_dossiers.count)) + badge: number_with_html_delimiter(@counters['total'])) = tab_item(t('pluralize.archived', count: @archived_dossiers.count), instructeur_procedure_path(@procedure, statut: 'archives'), active: @statut == 'archives', - badge: number_with_html_delimiter(@archived_dossiers.count)) + badge: number_with_html_delimiter(@counters['archived'])) .procedure-actions = render partial: "download_dossiers", @@ -135,7 +135,7 @@ %td.folder-col = link_to(instructeur_dossier_path(@procedure, dossier), class: 'cell-link') do %span.icon.folder - - if current_instructeur.notifications_for_procedure(@procedure, :not_archived).include?(dossier) + - if @not_archived_notifications_dossier_ids.include?(dossier.id) %span.notifications{ 'aria-label': 'notifications' } %td.number-col diff --git a/app/views/layouts/_new_header.haml b/app/views/layouts/_new_header.haml index 857aecffb..8bba0a619 100644 --- a/app/views/layouts/_new_header.haml +++ b/app/views/layouts/_new_header.haml @@ -20,7 +20,7 @@ - else - root_profile_link, root_profile_libelle = root_path_info_for_profile(nav_bar_profile) = link_to root_profile_link, class: 'header-logo justify-center', title: root_profile_libelle do - = image_tag 'marianne.svg', alt: 'Liberté, égalité, fraternité', width: '65' + = image_tag 'marianne.png', alt: 'Liberté, égalité, fraternité', width: '65', height: 56, loading: 'lazy' %span.big.site-title> = APPLICATION_NAME %span.small.site-title> diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 65e4c51e9..8383106fe 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -16,9 +16,8 @@ - packs = ['application', 'track', administrateur_signed_in? ? 'track-admin' : nil].compact = javascript_packs_with_chunks_tag *packs, defer: true - = preload_link_tag(asset_url("Muli-Regular.woff")) - = preload_link_tag(asset_url("Muli-Bold.woff")) - = preload_link_tag(asset_url("Muli-Italic.woff")) + = preload_link_tag(asset_url("Muli-Regular.woff2")) + = preload_link_tag(asset_url("Muli-Bold.woff2")) = stylesheet_link_tag 'new_design/new_application', media: 'all' = stylesheet_link_tag 'new_design/print', media: 'print' diff --git a/app/views/root/landing.html.haml b/app/views/root/landing.html.haml index 85568cee2..9aa9b3719 100644 --- a/app/views/root/landing.html.haml +++ b/app/views/root/landing.html.haml @@ -14,13 +14,13 @@ %em.hero-tagline-em en ligne .hero-illustration - %img{ :src => image_url("landing/hero/dematerialiser.svg"), alt: '' } + %img{ :src => image_url("landing/hero/dematerialiser.svg"), alt: '', width: 499, height: 280, loading: 'lazy' } .landing-panel.usagers-panel .container .role-panel-wrapper .role-panel-30.role-usagers-image - %img.role-image{ :src => image_url("landing/roles/usagers.svg"), alt: '' } + %img.role-image{ :src => image_url("landing/roles/usagers.svg"), alt: '', width: 176, height: 180, loading: 'lazy' } .role-panel-70 %h2.role-panel-title Vous souhaitez effectuer une demande auprès d'une administration ? diff --git a/app/views/shared/dossiers/_demande.html.haml b/app/views/shared/dossiers/_demande.html.haml index 55870541c..4328a907a 100644 --- a/app/views/shared/dossiers/_demande.html.haml +++ b/app/views/shared/dossiers/_demande.html.haml @@ -5,6 +5,8 @@ .tab-title Identité du demandeur .card + - if dossier.user.france_connect_information.present? + = render partial: "shared/dossiers/france_connect_informations", locals: { individual: dossier.individual } = render partial: "shared/dossiers/user_infos", locals: { user: dossier.user } - if dossier.etablissement.present? diff --git a/app/views/shared/dossiers/_edit.html.haml b/app/views/shared/dossiers/_edit.html.haml index a8a420e3f..a3db1492a 100644 --- a/app/views/shared/dossiers/_edit.html.haml +++ b/app/views/shared/dossiers/_edit.html.haml @@ -21,7 +21,8 @@ Votre dossier est enregistré automatiquement après chaque modification. Vous pouvez à tout moment fermer la fenêtre et reprendre plus tard là où vous en étiez. - else Pour enregistrer votre dossier et le reprendre plus tard, cliquez sur le bouton « Enregistrer le brouillon » en bas à gauche du formulaire. - + - if !apercu && dossier.user.france_connect_information.present? + = render partial: "shared/dossiers/france_connect_informations", locals: { individual: dossier.individual } - if notice_url(dossier.procedure).present? = link_to notice_url(dossier.procedure), target: '_blank', rel: 'noopener', class: 'button notice', title: "Pour vous aider à remplir votre dossier, vous pouvez consulter le guide de cette démarche." do %span.icon.info> diff --git a/app/views/shared/dossiers/_france_connect_informations.html.haml b/app/views/shared/dossiers/_france_connect_informations.html.haml new file mode 100644 index 000000000..125bbbb96 --- /dev/null +++ b/app/views/shared/dossiers/_france_connect_informations.html.haml @@ -0,0 +1,4 @@ +.card.featured + .flex.justify-center + = image_tag "logo-france-connect.png", alt: "France Connect logo", width: 200, class: "mb-2" + .card-title Le dossier a été déposé par le compte de #{individual.prenom} #{individual.nom}, authentifié par France Connect le #{individual.updated_at.strftime('%d/%m/%Y')}. diff --git a/app/views/shared/dossiers/editable_champs/_editable_champ.html.haml b/app/views/shared/dossiers/editable_champs/_editable_champ.html.haml index 0331de761..bb5100ae1 100644 --- a/app/views/shared/dossiers/editable_champs/_editable_champ.html.haml +++ b/app/views/shared/dossiers/editable_champs/_editable_champ.html.haml @@ -7,7 +7,6 @@ - elsif has_label?(champ) = render partial: 'shared/dossiers/editable_champs/champ_label', locals: { form: form, champ: champ, seen_at: defined?(seen_at) ? seen_at : nil } - if champ.type_champ == "titre_identite" - %p.notice Carte d'identité (uniquement le recto), passeport ou titre de séjour. Formats acceptés : jpg / png. - + %p.notice Carte nationale d’identité (uniquement le recto), passeport, titre de séjour ou autre justificatif d’identité. Formats acceptés : jpg/png = render partial: "shared/dossiers/editable_champs/#{champ.type_champ}", locals: { champ: champ, form: form } diff --git a/config/initializers/rack_mini_profiler.rb b/config/initializers/rack_mini_profiler.rb index 5065ab5cd..fc9414e45 100644 --- a/config/initializers/rack_mini_profiler.rb +++ b/config/initializers/rack_mini_profiler.rb @@ -1 +1,3 @@ -Rack::MiniProfiler.config.authorization_mode = :whitelist +if Rails.env.development? + Rack::MiniProfiler.config.authorization_mode = :whitelist +end diff --git a/spec/features/france_connect/france_connect_particulier_spec.rb b/spec/features/france_connect/france_connect_particulier_spec.rb index 123a10d7d..37a5171c3 100644 --- a/spec/features/france_connect/france_connect_particulier_spec.rb +++ b/spec/features/france_connect/france_connect_particulier_spec.rb @@ -68,6 +68,10 @@ feature 'France Connect Particulier Connexion' do scenario 'he is redirected to user dossiers page' do expect(page).to have_content('Dossiers') end + + scenario 'the updated_at date is well updated' do + expect(france_connect_information.updated_at).not_to eq(france_connect_information.created_at) + end end end diff --git a/spec/jobs/api_entreprise/attestation_sociale_job_spec.rb b/spec/jobs/api_entreprise/attestation_sociale_job_spec.rb index d68594ecf..5c89302a7 100644 --- a/spec/jobs/api_entreprise/attestation_sociale_job_spec.rb +++ b/spec/jobs/api_entreprise/attestation_sociale_job_spec.rb @@ -1,3 +1,5 @@ +include ActiveJob::TestHelper + RSpec.describe ApiEntreprise::AttestationSocialeJob, type: :job do let(:etablissement) { create(:etablissement, siret: siret) } let(:siret) { '41816609600069' } @@ -21,4 +23,20 @@ RSpec.describe ApiEntreprise::AttestationSocialeJob, type: :job do subject expect(Etablissement.find(etablissement.id).entreprise_attestation_sociale).to be_attached end + + context 'when ApiEntreprise::API::ServiceUnavailable is raised' do + # https://api.rubyonrails.org/classes/ActiveJob/Exceptions/ClassMethods.html#method-i-retry_on + # retry on will try 5 times and then bubble up the error + it 'makes 5 attempts' do + assert_performed_jobs 5 do + ServiceUnavailableJob.perform_later rescue ApiEntreprise::API::ServiceUnavailable + end + end + end + + class ServiceUnavailableJob < ApiEntreprise::AttestationSocialeJob + def perform + raise ApiEntreprise::API::ServiceUnavailable + end + end end diff --git a/spec/models/procedure_spec.rb b/spec/models/procedure_spec.rb index eda353e8c..9a309a43d 100644 --- a/spec/models/procedure_spec.rb +++ b/spec/models/procedure_spec.rb @@ -1023,4 +1023,136 @@ describe Procedure do it { is_expected.to be false } end end + + describe "#dossiers_count_for_instructeur" do + let(:instructeur) { create(:instructeur) } + let(:procedure) { create(:procedure, instructeurs: [instructeur]) } + let(:gi_2) { procedure.groupe_instructeurs.create(label: '2') } + let(:gi_3) { procedure.groupe_instructeurs.create(label: '3') } + + subject do + procedure.dossiers_count_for_instructeur(instructeur) + end + + context "when logged in, and belonging to gi_1, gi_2" do + before do + instructeur.groupe_instructeurs << gi_2 + end + + context "without any dossier" do + it { expect(subject['a_suivre']).to eq(0) } + it { expect(subject['suivis']).to eq(0) } + it { expect(subject['termines']).to eq(0) } + it { expect(subject['total']).to eq(0) } + it { expect(subject['archived']).to eq(0) } + end + + context 'with a new brouillon dossier' do + let!(:brouillon_dossier) { create(:dossier, procedure: procedure, state: Dossier.states.fetch(:brouillon)) } + + it { expect(subject['a_suivre']).to eq(0) } + it { expect(subject['suivis']).to eq(0) } + it { expect(subject['termines']).to eq(0) } + it { expect(subject['total']).to eq(0) } + it { expect(subject['archived']).to eq(0) } + end + + context 'with a new dossier without follower' do + let!(:new_unfollow_dossier) { create(:dossier, procedure: procedure, state: Dossier.states.fetch(:en_instruction)) } + + it { expect(subject['a_suivre']).to eq(1) } + it { expect(subject['suivis']).to eq(0) } + it { expect(subject['termines']).to eq(0) } + it { expect(subject['total']).to eq(1) } + it { expect(subject['archived']).to eq(0) } + + context 'and dossiers without follower on each of the others groups' do + let!(:new_unfollow_dossier_on_gi_2) { create(:dossier, groupe_instructeur: gi_2, state: Dossier.states.fetch(:en_instruction)) } + let!(:new_unfollow_dossier_on_gi_3) { create(:dossier, groupe_instructeur: gi_3, state: Dossier.states.fetch(:en_instruction)) } + + before { subject } + + it { expect(subject['a_suivre']).to eq(2) } + it { expect(subject['total']).to eq(2) } + end + end + + context 'with a new dossier with a follower' do + let!(:new_followed_dossier) { create(:dossier, procedure: procedure, state: Dossier.states.fetch(:en_instruction)) } + + before do + instructeur.followed_dossiers << new_followed_dossier + end + + it { expect(subject['a_suivre']).to eq(0) } + it { expect(subject['suivis']).to eq(1) } + it { expect(subject['termines']).to eq(0) } + it { expect(subject['total']).to eq(1) } + it { expect(subject['archived']).to eq(0) } + + context 'and dossier with a follower on each of the others groups' do + let!(:new_follow_dossier_on_gi_2) { create(:dossier, groupe_instructeur: gi_2, state: Dossier.states.fetch(:en_instruction)) } + let!(:new_follow_dossier_on_gi_3) { create(:dossier, groupe_instructeur: gi_3, state: Dossier.states.fetch(:en_instruction)) } + + before do + instructeur.followed_dossiers << new_follow_dossier_on_gi_2 << new_follow_dossier_on_gi_3 + end + + # followed dossiers on another groupe should not be displayed + it { expect(subject['suivis']).to eq(2) } + it { expect(subject['total']).to eq(2) } + end + + context 'and dossier with a follower is unfollowed' do + before do + instructeur.unfollow(new_followed_dossier) + end + + it { expect(subject['a_suivre']).to eq(1) } + it { expect(subject['suivis']).to eq(0) } + it { expect(subject['total']).to eq(1) } + end + end + + context 'with a termine dossier' do + let!(:termine_dossier) { create(:dossier, procedure: procedure, state: Dossier.states.fetch(:accepte)) } + + it { expect(subject['a_suivre']).to eq(0) } + it { expect(subject['suivis']).to eq(0) } + it { expect(subject['termines']).to eq(1) } + it { expect(subject['total']).to eq(1) } + it { expect(subject['archived']).to eq(0) } + + context 'and terminer dossiers on each of the others groups' do + let!(:termine_dossier_on_gi_2) { create(:dossier, groupe_instructeur: gi_2, state: Dossier.states.fetch(:accepte)) } + let!(:termine_dossier_on_gi_3) { create(:dossier, groupe_instructeur: gi_3, state: Dossier.states.fetch(:accepte)) } + + before { subject } + + it { expect(subject['a_suivre']).to eq(0) } + it { expect(subject['suivis']).to eq(0) } + it { expect(subject['termines']).to eq(2) } + it { expect(subject['total']).to eq(2) } + it { expect(subject['archived']).to eq(0) } + end + end + + context 'with an archived dossier' do + let!(:archived_dossier) { create(:dossier, procedure: procedure, state: Dossier.states.fetch(:en_instruction), archived: true) } + + it { expect(subject['a_suivre']).to eq(0) } + it { expect(subject['suivis']).to eq(0) } + it { expect(subject['termines']).to eq(0) } + it { expect(subject['total']).to eq(0) } + it { expect(subject['archived']).to eq(1) } + + context 'and terminer dossiers on each of the others groups' do + let!(:archived_dossier_on_gi_2) { create(:dossier, groupe_instructeur: gi_2, state: Dossier.states.fetch(:en_instruction), archived: true) } + let!(:archived_dossier_on_gi_3) { create(:dossier, groupe_instructeur: gi_3, state: Dossier.states.fetch(:en_instruction), archived: true) } + + it { expect(subject['archived']).to eq(2) } + end + end + end + end end diff --git a/spec/views/instructeur/dossiers/show.html.haml_spec.rb b/spec/views/instructeur/dossiers/show.html.haml_spec.rb index 25072b3e5..48863d240 100644 --- a/spec/views/instructeur/dossiers/show.html.haml_spec.rb +++ b/spec/views/instructeur/dossiers/show.html.haml_spec.rb @@ -18,4 +18,19 @@ describe 'instructeurs/dossiers/show.html.haml', type: :view do expect(rendered).to have_text('Identité') expect(rendered).to have_text('Demande') end + + context 'when the user is logged in with france connect' do + let(:france_connect_information) { build(:france_connect_information) } + let(:user) { build(:user, france_connect_information: france_connect_information) } + let(:procedure1) { create(:procedure, :with_type_de_champ, for_individual: true) } + let(:dossier) { create(:dossier, procedure: procedure1, user: user) } + + before do + render + end + + it 'fills the individual with the informations from France Connect' do + expect(rendered).to have_text("Le dossier a été déposé par le compte de #{dossier.individual.prenom} #{dossier.individual.nom}, authentifié par France Connect le #{dossier.individual.updated_at.strftime('%d/%m/%Y')}") + end + end end diff --git a/spec/views/users/dossiers/demande.html.haml_spec.rb b/spec/views/users/dossiers/demande.html.haml_spec.rb index 0a46903d4..a203fc83b 100644 --- a/spec/views/users/dossiers/demande.html.haml_spec.rb +++ b/spec/views/users/dossiers/demande.html.haml_spec.rb @@ -33,4 +33,19 @@ describe 'users/dossiers/demande.html.haml', type: :view do it { expect(rendered).not_to have_text('Déposé le') } end + + context 'when the user is logged in with france connect' do + let(:france_connect_information) { build(:france_connect_information) } + let(:user) { build(:user, france_connect_information: france_connect_information) } + let(:procedure1) { create(:procedure, :with_type_de_champ, for_individual: true) } + let(:dossier) { create(:dossier, procedure: procedure1, user: user) } + + before do + render + end + + it 'fills the individual with the informations from France Connect' do + expect(rendered).to have_text("Le dossier a été déposé par le compte de #{dossier.individual.prenom} #{dossier.individual.nom}, authentifié par France Connect le #{dossier.individual.updated_at.strftime('%d/%m/%Y')}") + end + end end