Merge pull request #4922 from betagouv/4896-extend-dossier-before-deletion

#4896 Extend dossier en construction before deletion
This commit is contained in:
Keirua 2020-03-24 18:20:11 +01:00 committed by GitHub
commit ea3022a292
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 131 additions and 1 deletions

View file

@ -166,6 +166,12 @@ module Users
end
end
def extend_conservation
dossier.update(en_construction_conservation_extension: dossier.en_construction_conservation_extension + 1.month)
flash[:notice] = 'Votre dossier sera conservé un mois supplémentaire'
redirect_to dossier_path(@dossier)
end
def modifier
@dossier = dossier_with_champs
end

View file

@ -172,7 +172,7 @@ class Dossier < ApplicationRecord
scope :en_construction_close_to_expiration, -> do
en_construction
.joins(:procedure)
.where("dossiers.en_construction_at + (duree_conservation_dossiers_dans_ds * interval '1 month') - INTERVAL '1 month' <= now()")
.where("dossiers.en_construction_at + dossiers.en_construction_conservation_extension + (duree_conservation_dossiers_dans_ds * interval '1 month') - INTERVAL '1 month' <= now()")
end
scope :en_instruction_close_to_expiration, -> do
en_instruction
@ -310,6 +310,10 @@ class Dossier < ApplicationRecord
instruction_commencee? && retention_end_date <= Time.zone.now
end
def en_construction_close_to_expiration?
Dossier.en_construction_close_to_expiration.where(id: self).present?
end
def assign_to_groupe_instructeur(groupe_instructeur, author = nil)
if groupe_instructeur.procedure == procedure && groupe_instructeur != self.groupe_instructeur
if update(groupe_instructeur: groupe_instructeur, groupe_instructeur_updated_at: Time.zone.now)

View file

@ -22,6 +22,16 @@
%li
= link_to "Tout le dossier", dossier_path(dossier, format: :pdf), target: "_blank", rel: "noopener", class: "menu-item menu-link"
- if dossier.en_construction_close_to_expiration?
.card.warning
.card-title Votre dossier va expirer
%p
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 ladministration.
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.
%br
= button_to 'Repousser sa suppression', users_dossier_repousser_expiration_path(dossier), class: 'button secondary'
%ul.tabs
= dynamic_tab_item('Résumé', dossier_path(dossier))
= dynamic_tab_item('Demande', [demande_dossier_path(dossier), modifier_dossier_path(dossier)])

View file

@ -0,0 +1,94 @@
# frozen_string_literal: true
# from https://gist.github.com/Envek/7077bfc36b17233f60ad
# PostgreSQL interval data type support from https://github.com/rails/rails/pull/16919
# Works with both Rails 5.2 and 6.0
# Place this file to config/initializers/
require "active_support/duration"
# activerecord/lib/active_record/connection_adapters/postgresql/oid/interval.rb
module ActiveRecord
module ConnectionAdapters
module PostgreSQL
module OID # :nodoc:
class Interval < Type::Value # :nodoc:
def type
:interval
end
def cast_value(value)
case value
when ::ActiveSupport::Duration
value
when ::String
begin
::ActiveSupport::Duration.parse(value)
rescue ::ActiveSupport::Duration::ISO8601Parser::ParsingError
nil
end
else
super
end
end
def serialize(value)
case value
when ::ActiveSupport::Duration
value.iso8601(precision: self.precision)
when ::Numeric
# Sometimes operations on Times returns just float number of seconds so we need to handle that.
# Example: Time.current - (Time.current + 1.hour) # => -3600.000001776 (Float)
value.seconds.iso8601(precision: self.precision)
else
super
end
end
def type_cast_for_schema(value)
serialize(value).inspect
end
end
end
end
end
end
# activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
require 'active_record/connection_adapters/postgresql_adapter'
PostgreSQLAdapterWithInterval = Module.new do
def initialize_type_map(m = type_map)
super
m.register_type "interval" do |*_args, sql_type|
precision = extract_precision(sql_type)
::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::OID::Interval.new(precision: precision)
end
end
def configure_connection
super
execute('SET intervalstyle = iso_8601', 'SCHEMA')
end
ActiveRecord::Type.register(:interval, ::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::OID::Interval, adapter: :postgresql)
end
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.prepend(PostgreSQLAdapterWithInterval)
# activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
require 'active_record/connection_adapters/postgresql/schema_statements'
module SchemaStatementsWithInterval
def type_to_sql(type, limit: nil, precision: nil, scale: nil, array: nil, **)
case type.to_s
when 'interval'
case precision
when nil; "interval"
when 0..6; "interval(#{precision})"
else raise(ActiveRecordError, "No interval type has precision of #{precision}. The allowed range of precision is from 0 to 6")
end
else
super
end
end
end
ActiveRecord::ConnectionAdapters::PostgreSQL::SchemaStatements.prepend(SchemaStatementsWithInterval)

View file

@ -146,6 +146,7 @@ Rails.application.routes.draw do
post '/carte/zones' => 'carte#zones'
get '/carte' => 'carte#show'
post '/carte' => 'carte#save'
post '/repousser-expiration' => 'dossiers#extend_conservation'
end
# Redirection of legacy "/users/dossiers" route to "/dossiers"

View file

@ -0,0 +1,5 @@
class AddEnConstructionConservationExtensionToDossiers < ActiveRecord::Migration[5.2]
def change
add_column :dossiers, :en_construction_conservation_extension, :interval, :default => 0.days
end
end

View file

@ -255,6 +255,7 @@ ActiveRecord::Schema.define(version: 2020_03_19_103836) do
t.datetime "en_construction_close_to_expiration_notice_sent_at"
t.index "to_tsvector('french'::regconfig, (search_terms || private_search_terms))", name: "index_dossiers_on_search_terms_private_search_terms", using: :gin
t.index "to_tsvector('french'::regconfig, search_terms)", name: "index_dossiers_on_search_terms", using: :gin
t.interval "en_construction_conservation_extension", default: "00:00:00"
t.index ["archived"], name: "index_dossiers_on_archived"
t.index ["groupe_instructeur_id"], name: "index_dossiers_on_groupe_instructeur_id"
t.index ["hidden_at"], name: "index_dossiers_on_hidden_at"

View file

@ -77,6 +77,15 @@ describe Dossier do
is_expected.to include(just_expired_dossier)
is_expected.to include(long_expired_dossier)
end
context 'does not include an expiring dossier that has been postponed' do
before do
expiring_dossier.update(en_construction_conservation_extension: 1.month)
expiring_dossier.reload
end
it { is_expected.not_to include(expiring_dossier) }
end
end
describe 'en_instruction_close_to_expiration' do