feat(dossiers/show): enhance header with expirations message/banner. also ensure consistent design between dossier states
fix(spec): broken due to last refactoring spec(dossier.extend_conservation): add system spec lint(ruby): still not yet ready for auto lint in IDE...
This commit is contained in:
parent
2a87b9bf89
commit
b6adf5fc72
13 changed files with 164 additions and 38 deletions
|
@ -98,6 +98,11 @@ module DossierHelper
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def safe_expiration_date(dossier)
|
||||||
|
date = dossier.expiration_date.presence || dossier.approximative_expiration_date
|
||||||
|
l(date, format: '%d/%m/%Y')
|
||||||
|
end
|
||||||
|
|
||||||
def annuaire_link(siren)
|
def annuaire_link(siren)
|
||||||
base_url = "https://annuaire-entreprises.data.gouv.fr"
|
base_url = "https://annuaire-entreprises.data.gouv.fr"
|
||||||
return base_url if siren.blank?
|
return base_url if siren.blank?
|
||||||
|
|
|
@ -539,20 +539,32 @@ class Dossier < ApplicationRecord
|
||||||
!brouillon? && !user_deleted? && !archived
|
!brouillon? && !user_deleted? && !archived
|
||||||
end
|
end
|
||||||
|
|
||||||
def close_to_expiration_at
|
def expirable?
|
||||||
|
[brouillon?, en_construction?, termine?].any?
|
||||||
|
end
|
||||||
|
|
||||||
|
def approximative_expiration_date_reference
|
||||||
if brouillon?
|
if brouillon?
|
||||||
created_at
|
created_at
|
||||||
elsif en_construction?
|
elsif en_construction?
|
||||||
en_construction_at
|
en_construction_at
|
||||||
elsif en_instruction?
|
elsif termine?
|
||||||
en_instruction_at
|
|
||||||
else
|
|
||||||
processed_at
|
processed_at
|
||||||
end + conservation_extension + procedure.duree_conservation_dossiers_dans_ds.months - REMAINING_WEEKS_BEFORE_EXPIRATION.weeks
|
else
|
||||||
|
fail "approximative_expiration_date_reference should not be called in state #{self.state}"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def duration_after_notice
|
def approximative_expiration_date
|
||||||
MONTHS_AFTER_EXPIRATION.month + DAYS_AFTER_EXPIRATION.days
|
[
|
||||||
|
approximative_expiration_date_reference,
|
||||||
|
conservation_extension,
|
||||||
|
procedure.duree_conservation_dossiers_dans_ds.months
|
||||||
|
].sum - REMAINING_WEEKS_BEFORE_EXPIRATION.weeks
|
||||||
|
end
|
||||||
|
|
||||||
|
def close_to_expiration?
|
||||||
|
approximative_expiration_date < Time.zone.now
|
||||||
end
|
end
|
||||||
|
|
||||||
def expiration_date
|
def expiration_date
|
||||||
|
@ -565,12 +577,8 @@ class Dossier < ApplicationRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def close_to_expiration?
|
def duration_after_notice
|
||||||
!en_instruction? && close_to_expiration_at < Time.zone.now
|
MONTHS_AFTER_EXPIRATION.month + DAYS_AFTER_EXPIRATION.days
|
||||||
end
|
|
||||||
|
|
||||||
def close_to_expiration_notice_sent?
|
|
||||||
expiration_date.present?
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def expiration_can_be_extended?
|
def expiration_can_be_extended?
|
||||||
|
|
17
app/views/shared/dossiers/_expiration_banner.html.haml
Normal file
17
app/views/shared/dossiers/_expiration_banner.html.haml
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
- if dossier.expirable? && dossier.close_to_expiration?
|
||||||
|
.card.warning.mt-2.mb-3
|
||||||
|
.card-title Votre dossier va expirer
|
||||||
|
%p
|
||||||
|
- if dossier.brouillon?
|
||||||
|
Votre dossier est en brouillon, mais va bientôt expirer. Cela signifie qu’il va bientôt être supprimé sans avoir été déposé.
|
||||||
|
Si vous souhaitez le conserver afin de poursuivre la démarche, vous pouvez le conserver
|
||||||
|
un mois de plus en cliquant sur le bouton ci-dessous.
|
||||||
|
- elsif dossier.en_construction?
|
||||||
|
Votre dossier est en attente de prise en charge par l'administration. Le delais de prise en charge maximale est de 6 mois. Vous pouvez toutefois entendre cette durée d'un mois en cliquant sur le bouton suivant.
|
||||||
|
- elsif dossier.termine?
|
||||||
|
Le traitement de votre dossier est terminé, mais il va bientôt expirer. Cela signifie qu’il va bientôt être supprimé.
|
||||||
|
Si vous souhaitez conserver une trace, vous pouvez le télécharger au format PDF.
|
||||||
|
|
||||||
|
- if dossier.expiration_can_be_extended?
|
||||||
|
%br
|
||||||
|
= button_to 'Repousser sa suppression', users_dossier_repousser_expiration_path(dossier), class: 'button secondary mt-2'
|
|
@ -1,6 +1,14 @@
|
||||||
%h1
|
= status_badge(dossier.state)
|
||||||
= procedure_libelle(dossier.procedure)
|
.title-container
|
||||||
|
%span.icon.folder
|
||||||
|
%h1= procedure_libelle(dossier.procedure)
|
||||||
|
%h2
|
||||||
|
= t('views.users.dossiers.show.header.dossier_number', dossier_id: dossier.id)
|
||||||
|
= t('views.users.dossiers.show.header.created_date', date_du_dossier: I18n.l(dossier.created_at))
|
||||||
|
|
||||||
.dossier-form-actions
|
= render(partial: 'shared/dossiers/short_expires_message', locals: {dossier: dossier})
|
||||||
|
|
||||||
|
.header-actions
|
||||||
- if current_user.owns?(dossier)
|
- if current_user.owns?(dossier)
|
||||||
= render partial: 'invites/dropdown', locals: { dossier: dossier }
|
= render partial: 'invites/dropdown', locals: { dossier: dossier }
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
- if dossier.expirable?
|
||||||
|
%p.expires_at
|
||||||
|
%small= t("shared.dossiers.header.expires_at.#{dossier.state}", date: safe_expiration_date(dossier))
|
||||||
|
- else
|
||||||
|
%p.expires_at_en_instruction
|
||||||
|
%small= t("shared.dossiers.header.expires_at.en_instruction")
|
||||||
|
|
||||||
|
|
||||||
|
= render(partial: 'shared/dossiers/expiration_banner', locals: {dossier: dossier})
|
|
@ -10,6 +10,9 @@
|
||||||
- if dossier.en_construction_at.present?
|
- if dossier.en_construction_at.present?
|
||||||
= t('views.users.dossiers.show.header.submit_date', date_du_dossier: I18n.l(dossier.en_construction_at))
|
= t('views.users.dossiers.show.header.submit_date', date_du_dossier: I18n.l(dossier.en_construction_at))
|
||||||
|
|
||||||
|
= render(partial: 'shared/dossiers/short_expires_message', locals: {dossier: dossier})
|
||||||
|
|
||||||
|
|
||||||
- if current_user.owns?(dossier)
|
- if current_user.owns?(dossier)
|
||||||
.header-actions
|
.header-actions
|
||||||
= render partial: 'invites/dropdown', locals: { dossier: dossier }
|
= render partial: 'invites/dropdown', locals: { dossier: dossier }
|
||||||
|
@ -22,25 +25,6 @@
|
||||||
%li
|
%li
|
||||||
= link_to t('views.users.dossiers.show.header.print_dossier'), dossier_path(dossier, format: :pdf), target: "_blank", rel: "noopener", class: "menu-item menu-link"
|
= link_to t('views.users.dossiers.show.header.print_dossier'), dossier_path(dossier, format: :pdf), target: "_blank", rel: "noopener", class: "menu-item menu-link"
|
||||||
|
|
||||||
- if dossier.close_to_expiration?
|
|
||||||
.card.warning
|
|
||||||
.card-title Votre dossier va expirer
|
|
||||||
%p
|
|
||||||
- if dossier.brouillon?
|
|
||||||
Votre dossier est en brouillon, mais va bientôt expirer. Cela signifie qu’il va bientôt être supprimé sans avoir été déposé.
|
|
||||||
Si vous souhaitez le conserver afin de poursuivre la démarche, vous pouvez le conserver
|
|
||||||
un mois de plus en cliquant sur le bouton ci-dessous.
|
|
||||||
- elsif dossier.termine?
|
|
||||||
Le traitement de votre dossier est terminé, mais il va bientôt expirer. Cela signifie qu’il va bientôt être supprimé.
|
|
||||||
Si vous souhaitez conserver une trace, vous pouvez le télécharger au format PDF.
|
|
||||||
- else
|
|
||||||
Votre dossier a été déposé, mais va bientôt expirer. Cela signifie qu’il va bientôt être supprimé sans avoir été traité par l’administration.
|
|
||||||
Si vous souhaitez le conserver afin de poursuivre la démarche, vous pouvez le conserver
|
|
||||||
un mois de plus en cliquant sur le bouton ci-dessous.
|
|
||||||
|
|
||||||
- if dossier.expiration_can_be_extended?
|
|
||||||
%br
|
|
||||||
= button_to 'Repousser sa suppression', users_dossier_repousser_expiration_path(dossier), class: 'button secondary'
|
|
||||||
|
|
||||||
%ul.tabs
|
%ul.tabs
|
||||||
= dynamic_tab_item(t('views.users.dossiers.show.header.summary'), dossier_path(dossier))
|
= dynamic_tab_item(t('views.users.dossiers.show.header.summary'), dossier_path(dossier))
|
||||||
|
|
|
@ -160,6 +160,7 @@ en:
|
||||||
request: "Request"
|
request: "Request"
|
||||||
mailbox: "Mailbox"
|
mailbox: "Mailbox"
|
||||||
dossier_number: "File n. %{dossier_id}"
|
dossier_number: "File n. %{dossier_id}"
|
||||||
|
created_date: "- Draft on %{date_du_dossier}"
|
||||||
submit_date: "- Submit on %{date_du_dossier}"
|
submit_date: "- Submit on %{date_du_dossier}"
|
||||||
print: "print"
|
print: "print"
|
||||||
print_dossier: "All the file"
|
print_dossier: "All the file"
|
||||||
|
|
|
@ -156,6 +156,7 @@ fr:
|
||||||
request: "Demande"
|
request: "Demande"
|
||||||
mailbox: "Messagerie"
|
mailbox: "Messagerie"
|
||||||
dossier_number: "Dossier nº %{dossier_id}"
|
dossier_number: "Dossier nº %{dossier_id}"
|
||||||
|
created_date: "- En brouillon depuis le %{date_du_dossier}"
|
||||||
submit_date: "- Déposé le %{date_du_dossier}"
|
submit_date: "- Déposé le %{date_du_dossier}"
|
||||||
print: "imprimer"
|
print: "imprimer"
|
||||||
print_dossier: "Tout le dossier"
|
print_dossier: "Tout le dossier"
|
||||||
|
|
|
@ -7,6 +7,14 @@ en:
|
||||||
numero_allocataire_notice: It is usually composed of 7 digits.
|
numero_allocataire_notice: It is usually composed of 7 digits.
|
||||||
code_postal_label: postal code
|
code_postal_label: postal code
|
||||||
code_postal_notice: It is usually composed of 5 digits.
|
code_postal_notice: It is usually composed of 5 digits.
|
||||||
|
header:
|
||||||
|
expires_at:
|
||||||
|
brouillon: "Expires at %{date}"
|
||||||
|
en_construction: "Expires at %{date}"
|
||||||
|
en_instruction: "This file is being instructed, the administration will answer as soon as possible"
|
||||||
|
accepte: "Expires at %{date}"
|
||||||
|
refuse: "Expires at %{date}"
|
||||||
|
sans_suite: "Expires at %{date}"
|
||||||
champs:
|
champs:
|
||||||
cnaf:
|
cnaf:
|
||||||
show:
|
show:
|
||||||
|
|
|
@ -7,6 +7,14 @@ fr:
|
||||||
numero_allocataire_notice: Il est généralement composé de 7 chiffres.
|
numero_allocataire_notice: Il est généralement composé de 7 chiffres.
|
||||||
code_postal_label: Le code postal
|
code_postal_label: Le code postal
|
||||||
code_postal_notice: Il est généralement composé de 5 chiffres.
|
code_postal_notice: Il est généralement composé de 5 chiffres.
|
||||||
|
header:
|
||||||
|
expires_at:
|
||||||
|
brouillon: "Expirera le %{date}"
|
||||||
|
en_construction: "Expirera le %{date}"
|
||||||
|
en_instruction: "Ce dossier est en instruction, il n'expirera pas"
|
||||||
|
accepte: "Expirera le %{date}"
|
||||||
|
refuse: "Expirera le %{date}"
|
||||||
|
sans_suite: "Expirera le %{date}"
|
||||||
champs:
|
champs:
|
||||||
cnaf:
|
cnaf:
|
||||||
show:
|
show:
|
||||||
|
|
|
@ -9,7 +9,7 @@ end
|
||||||
|
|
||||||
Capybara.register_driver :headless_chrome do |app|
|
Capybara.register_driver :headless_chrome do |app|
|
||||||
options = Selenium::WebDriver::Chrome::Options.new
|
options = Selenium::WebDriver::Chrome::Options.new
|
||||||
options.add_argument('--headless')
|
options.add_argument('--headless') unless ENV['NO_HEADLESS']
|
||||||
options.add_argument('--window-size=1440,900')
|
options.add_argument('--window-size=1440,900')
|
||||||
|
|
||||||
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
|
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
|
||||||
|
|
|
@ -165,6 +165,27 @@ describe 'The user' do
|
||||||
expect(page).to have_current_path(merci_dossier_path(user_dossier))
|
expect(page).to have_current_path(merci_dossier_path(user_dossier))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
scenario 'extends dossier experation date more than one time, ', js: true do
|
||||||
|
user_old_dossier = create(:dossier,
|
||||||
|
procedure: simple_procedure,
|
||||||
|
created_at: simple_procedure.duree_conservation_dossiers_dans_ds.month.ago,
|
||||||
|
user: user)
|
||||||
|
login_as(user, scope: :user)
|
||||||
|
visit brouillon_dossier_path(user_old_dossier)
|
||||||
|
|
||||||
|
expect(page).to have_css('.card-title', text: 'Votre dossier va expirer', visible: true)
|
||||||
|
click_on "Repousser sa suppression"
|
||||||
|
expect(page).not_to have_button("Repousser sa suppression")
|
||||||
|
|
||||||
|
Timecop.freeze(1.month.from_now) do
|
||||||
|
visit brouillon_dossier_path(user_old_dossier)
|
||||||
|
|
||||||
|
expect(page).to have_css('.card-title', text: 'Votre dossier va expirer', visible: true)
|
||||||
|
click_on "Repousser sa suppression"
|
||||||
|
expect(page).not_to have_button("Repousser sa suppression")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
let(:procedure_with_pj) do
|
let(:procedure_with_pj) do
|
||||||
tdcs = [build(:type_de_champ_piece_justificative, mandatory: true, libelle: 'Pièce justificative')]
|
tdcs = [build(:type_de_champ_piece_justificative, mandatory: true, libelle: 'Pièce justificative')]
|
||||||
create(:procedure, :published, :for_individual, types_de_champ: tdcs)
|
create(:procedure, :published, :for_individual, types_de_champ: tdcs)
|
||||||
|
|
56
spec/views/shared/dossiers/_header.html.haml_spec.rb
Normal file
56
spec/views/shared/dossiers/_header.html.haml_spec.rb
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
describe 'shared/dossiers/short_expires_message.html.haml', type: :view do
|
||||||
|
include DossierHelper
|
||||||
|
let(:dossier) do
|
||||||
|
build(:dossier, state, attributes.merge(id: 1, state: state))
|
||||||
|
end
|
||||||
|
let(:i18n_key_state) { state }
|
||||||
|
subject do
|
||||||
|
render('shared/dossiers/short_expires_message.html.haml',
|
||||||
|
dossier: dossier,
|
||||||
|
current_user: build(:user))
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with dossier.brouillon?' do
|
||||||
|
let(:attributes) { { created_at: 6.months.ago } }
|
||||||
|
let(:state) { :brouillon }
|
||||||
|
|
||||||
|
it 'render estimated expiration date' do
|
||||||
|
expect(subject).to have_selector('.expires_at',
|
||||||
|
text: I18n.t("shared.dossiers.header.expires_at.#{i18n_key_state}",
|
||||||
|
date: safe_expiration_date(dossier)))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with dossier.en_construction?' do
|
||||||
|
let(:attributes) { { en_construction_at: 6.months.ago } }
|
||||||
|
let(:state) { :en_construction }
|
||||||
|
|
||||||
|
it 'render estimated expiration date' do
|
||||||
|
expect(subject).to have_selector('.expires_at',
|
||||||
|
text: I18n.t("shared.dossiers.header.expires_at.#{i18n_key_state}",
|
||||||
|
date: safe_expiration_date(dossier)))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with dossier.en_instruction?' do
|
||||||
|
let(:state) { :en_instruction }
|
||||||
|
let(:attributes) { {} }
|
||||||
|
|
||||||
|
it 'render estimated expiration date' do
|
||||||
|
expect(subject).to have_selector('p.expires_at_en_instruction',
|
||||||
|
text: I18n.t("shared.dossiers.header.expires_at.#{i18n_key_state}"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with dossier.en_processed_at?' do
|
||||||
|
let(:state) { :accepte }
|
||||||
|
let(:attributes) { {} }
|
||||||
|
|
||||||
|
it 'render estimated expiration date' do
|
||||||
|
allow(dossier).to receive(:processed_at).and_return(6.months.ago)
|
||||||
|
expect(subject).to have_selector('.expires_at',
|
||||||
|
text: I18n.t("shared.dossiers.header.expires_at.#{i18n_key_state}",
|
||||||
|
date: safe_expiration_date(dossier)))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue