2020-08-06 16:35:45 +02:00
# == Schema Information
#
# Table name: dossiers
#
# id :integer not null, primary key
2021-02-04 19:23:40 +01:00
# api_entreprise_job_exceptions :string is an Array
2020-08-06 16:35:45 +02:00
# archived :boolean default(FALSE)
# autorisation_donnees :boolean
# brouillon_close_to_expiration_notice_sent_at :datetime
2021-05-05 21:05:33 +02:00
# conservation_extension :interval default(0 seconds)
2021-06-04 12:03:31 +02:00
# declarative_triggered_at :datetime
2021-05-01 12:20:24 +02:00
# deleted_user_email_never_send :string
2021-11-24 12:27:32 +01:00
# depose_at :datetime
2020-08-06 16:35:45 +02:00
# en_construction_at :datetime
# en_construction_close_to_expiration_notice_sent_at :datetime
# en_instruction_at :datetime
# groupe_instructeur_updated_at :datetime
# hidden_at :datetime
2021-12-21 12:44:57 +01:00
# hidden_by_administration_at :datetime
2022-02-08 10:47:43 +01:00
# hidden_by_reason :string
2021-11-10 17:36:24 +01:00
# hidden_by_user_at :datetime
2021-10-04 10:03:06 +02:00
# identity_updated_at :datetime
2020-08-06 16:35:45 +02:00
# last_avis_updated_at :datetime
# last_champ_private_updated_at :datetime
# last_champ_updated_at :datetime
# last_commentaire_updated_at :datetime
# motivation :text
# private_search_terms :text
# processed_at :datetime
# search_terms :text
# state :string
# termine_close_to_expiration_notice_sent_at :datetime
# created_at :datetime
# updated_at :datetime
2021-09-07 10:36:09 +02:00
# dossier_transfer_id :bigint
2020-08-06 16:35:45 +02:00
# groupe_instructeur_id :bigint
# revision_id :bigint
# user_id :integer
#
2018-03-06 13:44:29 +01:00
class Dossier < ApplicationRecord
2021-05-04 16:29:29 +02:00
self . ignored_columns = [ :en_construction_conservation_extension ]
2019-02-27 12:03:53 +01:00
include DossierFilteringConcern
2021-10-13 14:41:05 +02:00
include DossierRebaseConcern
2019-02-27 12:03:53 +01:00
2020-02-05 16:09:03 +01:00
include Discard :: Model
self . discard_column = :hidden_at
default_scope - > { kept }
2017-05-26 18:27:51 +02:00
enum state : {
2017-12-04 20:23:57 +01:00
brouillon : 'brouillon' ,
en_construction : 'en_construction' ,
en_instruction : 'en_instruction' ,
accepte : 'accepte' ,
refuse : 'refuse' ,
sans_suite : 'sans_suite'
2017-05-26 18:27:51 +02:00
}
2015-09-22 18:30:20 +02:00
2018-08-28 14:10:55 +02:00
EN_CONSTRUCTION_OU_INSTRUCTION = [ states . fetch ( :en_construction ) , states . fetch ( :en_instruction ) ]
TERMINE = [ states . fetch ( :accepte ) , states . fetch ( :refuse ) , states . fetch ( :sans_suite ) ]
INSTRUCTION_COMMENCEE = TERMINE + [ states . fetch ( :en_instruction ) ]
2018-01-18 11:39:05 +01:00
SOUMIS = EN_CONSTRUCTION_OU_INSTRUCTION + TERMINE
2017-05-26 18:22:31 +02:00
2020-05-13 20:45:21 +02:00
TAILLE_MAX_ZIP = 100 . megabytes
2019-07-18 16:47:59 +02:00
2020-03-25 04:09:14 +01:00
REMAINING_DAYS_BEFORE_CLOSING = 2
2020-03-25 10:38:17 +01:00
INTERVAL_BEFORE_CLOSING = " #{ REMAINING_DAYS_BEFORE_CLOSING } days "
2021-11-17 10:53:43 +01:00
REMAINING_WEEKS_BEFORE_EXPIRATION = 2
INTERVAL_BEFORE_EXPIRATION = " #{ REMAINING_WEEKS_BEFORE_EXPIRATION } weeks "
MONTHS_AFTER_EXPIRATION = 1
DAYS_AFTER_EXPIRATION = 5
INTERVAL_EXPIRATION = " #{ MONTHS_AFTER_EXPIRATION } month #{ DAYS_AFTER_EXPIRATION } days "
2020-02-05 22:10:22 +01:00
2015-09-24 11:45:00 +02:00
has_one :etablissement , dependent : :destroy
2020-01-07 16:36:04 +01:00
has_one :individual , validate : false , dependent : :destroy
2018-11-28 16:13:58 +01:00
has_one :attestation , dependent : :destroy
2016-01-18 16:20:51 +01:00
2021-04-13 20:24:02 +02:00
# FIXME: some dossiers have more than one attestation
has_many :attestations , dependent : :destroy
2019-02-18 17:52:15 +01:00
has_one_attached :justificatif_motivation
2021-04-01 17:22:47 +02:00
has_many :champs , - > { root . public_ordered } , inverse_of : false , dependent : :destroy
has_many :champs_private , - > { root . private_ordered } , class_name : 'Champ' , inverse_of : false , dependent : :destroy
2019-05-29 18:28:27 +02:00
has_many :commentaires , inverse_of : :dossier , dependent : :destroy
2016-02-08 18:16:18 +01:00
has_many :invites , dependent : :destroy
2019-06-12 19:10:53 +02:00
has_many :follows , - > { active } , inverse_of : :dossier
has_many :previous_follows , - > { inactive } , class_name : 'Follow' , inverse_of : :dossier
2019-08-06 11:02:54 +02:00
has_many :followers_instructeurs , through : :follows , source : :instructeur
has_many :previous_followers_instructeurs , - > { distinct } , through : :previous_follows , source : :instructeur
2019-05-29 18:28:27 +02:00
has_many :avis , inverse_of : :dossier , dependent : :destroy
2021-02-25 10:10:24 +01:00
has_many :experts , through : :avis
2021-08-18 11:19:19 +02:00
has_many :traitements , - > { order ( :processed_at ) } , inverse_of : :dossier , dependent : :destroy do
2021-11-14 18:43:45 +01:00
def passer_en_construction ( instructeur : nil , processed_at : Time . zone . now )
2021-11-04 19:05:04 +01:00
build ( state : Dossier . states . fetch ( :en_construction ) ,
2021-11-14 18:43:45 +01:00
instructeur_email : instructeur & . email ,
2021-11-04 19:05:04 +01:00
processed_at : processed_at )
end
2021-11-14 18:43:45 +01:00
def passer_en_instruction ( instructeur : nil , processed_at : Time . zone . now )
2021-11-04 19:05:04 +01:00
build ( state : Dossier . states . fetch ( :en_instruction ) ,
2021-11-14 18:43:45 +01:00
instructeur_email : instructeur & . email ,
2021-11-04 19:05:04 +01:00
processed_at : processed_at )
end
2021-08-18 11:19:19 +02:00
def accepter_automatiquement ( processed_at : Time . zone . now )
build ( state : Dossier . states . fetch ( :accepte ) ,
processed_at : processed_at )
end
def accepter ( motivation : nil , instructeur : nil , processed_at : Time . zone . now )
build ( state : Dossier . states . fetch ( :accepte ) ,
instructeur_email : instructeur & . email ,
motivation : motivation ,
processed_at : processed_at )
end
def refuser ( motivation : nil , instructeur : nil , processed_at : Time . zone . now )
build ( state : Dossier . states . fetch ( :refuse ) ,
instructeur_email : instructeur & . email ,
motivation : motivation ,
processed_at : processed_at )
end
def classer_sans_suite ( motivation : nil , instructeur : nil , processed_at : Time . zone . now )
build ( state : Dossier . states . fetch ( :sans_suite ) ,
instructeur_email : instructeur & . email ,
motivation : motivation ,
processed_at : processed_at )
end
end
2021-11-04 19:05:04 +01:00
has_one :traitement , - > { order ( processed_at : :desc ) } , inverse_of : false
2016-01-18 16:20:51 +01:00
2020-11-17 13:46:13 +01:00
has_many :dossier_operation_logs , - > { order ( :created_at ) } , inverse_of : :dossier
2018-11-23 21:02:18 +01:00
2021-03-09 11:21:30 +01:00
belongs_to :groupe_instructeur , optional : true
2020-08-27 19:55:10 +02:00
belongs_to :revision , class_name : 'ProcedureRevision' , optional : false
2021-05-11 17:49:29 +02:00
belongs_to :user , optional : true
2021-05-12 19:04:31 +02:00
has_one :france_connect_information , through : :user
2015-08-12 10:09:52 +02:00
2020-08-27 19:55:10 +02:00
has_one :procedure , through : :revision
has_many :types_de_champ , through : :revision
has_many :types_de_champ_private , through : :revision
2021-10-06 13:16:25 +02:00
belongs_to :transfer , class_name : 'DossierTransfer' , foreign_key : 'dossier_transfer_id' , optional : true , inverse_of : :dossiers
2021-09-07 10:36:09 +02:00
has_many :transfer_logs , class_name : 'DossierTransferLog' , dependent : :destroy
2017-08-02 14:56:08 +02:00
accepts_nested_attributes_for :champs
2017-08-02 15:33:23 +02:00
accepts_nested_attributes_for :champs_private
2017-08-02 14:56:08 +02:00
2019-07-02 15:38:23 +02:00
include AASM
aasm whiny_persistence : true , column : :state , enum : true do
state :brouillon , initial : true
state :en_construction
state :en_instruction
state :accepte
state :refuse
state :sans_suite
event :passer_en_construction , after : :after_passer_en_construction do
transitions from : :brouillon , to : :en_construction
end
event :passer_en_instruction , after : :after_passer_en_instruction do
transitions from : :en_construction , to : :en_instruction
end
event :passer_automatiquement_en_instruction , after : :after_passer_automatiquement_en_instruction do
transitions from : :en_construction , to : :en_instruction
end
event :repasser_en_construction , after : :after_repasser_en_construction do
transitions from : :en_instruction , to : :en_construction
end
event :accepter , after : :after_accepter do
transitions from : :en_instruction , to : :accepte
end
event :accepter_automatiquement , after : :after_accepter_automatiquement do
transitions from : :en_construction , to : :accepte
end
event :refuser , after : :after_refuser do
transitions from : :en_instruction , to : :refuse
end
event :classer_sans_suite , after : :after_classer_sans_suite do
transitions from : :en_instruction , to : :sans_suite
end
event :repasser_en_instruction , after : :after_repasser_en_instruction do
2021-05-01 12:20:24 +02:00
transitions from : :refuse , to : :en_instruction , guard : :can_repasser_en_instruction?
transitions from : :sans_suite , to : :en_instruction , guard : :can_repasser_en_instruction?
transitions from : :accepte , to : :en_instruction , guard : :can_repasser_en_instruction?
2019-07-02 15:38:23 +02:00
end
end
2018-08-28 14:10:55 +02:00
scope :state_brouillon , - > { where ( state : states . fetch ( :brouillon ) ) }
scope :state_not_brouillon , - > { where . not ( state : states . fetch ( :brouillon ) ) }
scope :state_en_construction , - > { where ( state : states . fetch ( :en_construction ) ) }
scope :state_en_instruction , - > { where ( state : states . fetch ( :en_instruction ) ) }
2017-07-11 16:09:03 +02:00
scope :state_en_construction_ou_instruction , - > { where ( state : EN_CONSTRUCTION_OU_INSTRUCTION ) }
2018-06-13 17:32:50 +02:00
scope :state_instruction_commencee , - > { where ( state : INSTRUCTION_COMMENCEE ) }
2017-07-11 16:09:03 +02:00
scope :state_termine , - > { where ( state : TERMINE ) }
2021-11-10 17:36:24 +01:00
scope :state_not_termine , - > { where . not ( state : TERMINE ) }
2017-05-26 18:23:16 +02:00
2017-06-01 11:05:51 +02:00
scope :archived , - > { where ( archived : true ) }
scope :not_archived , - > { where ( archived : false ) }
2022-01-05 10:41:02 +01:00
scope :hidden_by_user , - > { where . not ( hidden_by_user_at : nil ) }
2021-12-21 12:44:57 +01:00
scope :hidden_by_administration , - > { where . not ( hidden_by_administration_at : nil ) }
2022-01-05 10:41:02 +01:00
scope :visible_by_user , - > { where ( hidden_by_user_at : nil ) }
2022-01-13 12:35:07 +01:00
scope :visible_by_administration , - > { where ( " hidden_by_administration_at IS NULL AND NOT (hidden_by_user_at IS NOT NULL AND dossiers.state = 'en_construction') " ) }
2017-05-26 18:23:16 +02:00
scope :order_by_updated_at , - > ( order = :desc ) { order ( updated_at : order ) }
2021-12-06 15:49:17 +01:00
scope :order_by_created_at , - > ( order = :asc ) { order ( depose_at : order , created_at : order , id : order ) }
2019-09-26 14:57:58 +02:00
scope :updated_since , - > ( since ) { where ( 'dossiers.updated_at >= ?' , since ) }
2021-12-06 15:49:17 +01:00
scope :created_since , - > ( since ) { where ( 'dossiers.depose_at >= ?' , since ) }
2017-05-26 18:23:16 +02:00
2020-10-30 15:01:13 +01:00
scope :with_type_de_champ , - > ( stable_id ) {
joins ( 'INNER JOIN champs ON champs.dossier_id = dossiers.id INNER JOIN types_de_champ ON types_de_champ.id = champs.type_de_champ_id' )
. where ( 'types_de_champ.private = FALSE AND types_de_champ.stable_id = ?' , stable_id )
}
scope :with_type_de_champ_private , - > ( stable_id ) {
joins ( 'INNER JOIN champs ON champs.dossier_id = dossiers.id INNER JOIN types_de_champ ON types_de_champ.id = champs.type_de_champ_id' )
. where ( 'types_de_champ.private = TRUE AND types_de_champ.stable_id = ?' , stable_id )
}
2017-09-27 11:51:31 +02:00
scope :all_state , - > { not_archived . state_not_brouillon }
2017-12-05 16:14:02 +01:00
scope :en_construction , - > { not_archived . state_en_construction }
2017-09-27 11:51:31 +02:00
scope :en_instruction , - > { not_archived . state_en_instruction }
scope :termine , - > { not_archived . state_termine }
2021-11-26 15:06:32 +01:00
2021-04-29 17:29:47 +02:00
scope :processed_in_month , - > ( month ) do
state_termine
. joins ( :traitements )
. where ( traitements : { processed_at : month . beginning_of_month .. month . end_of_month } )
end
scope :downloadable_sorted , - > {
2019-07-30 15:39:20 +02:00
state_not_brouillon
2022-01-05 10:41:02 +01:00
. visible_by_administration
2019-07-30 15:39:20 +02:00
. includes (
:user ,
:individual ,
2019-08-06 11:02:54 +02:00
:followers_instructeurs ,
2021-11-04 19:05:04 +01:00
:traitement ,
2021-03-25 12:56:42 +01:00
:groupe_instructeur ,
procedure : [
:groupe_instructeurs ,
:draft_types_de_champ ,
:draft_types_de_champ_private ,
:published_types_de_champ ,
:published_types_de_champ_private
] ,
avis : [ :claimant , :expert ] ,
2021-10-20 16:52:38 +02:00
etablissement : :champ
2021-12-06 15:49:17 +01:00
) . order ( depose_at : 'asc' )
2019-07-30 15:39:20 +02:00
}
2017-09-27 11:51:31 +02:00
scope :en_cours , - > { not_archived . state_en_construction_ou_instruction }
2017-10-10 18:35:00 +02:00
scope :without_followers , - > { left_outer_joins ( :follows ) . where ( follows : { id : nil } ) }
2018-08-30 11:51:35 +02:00
scope :with_champs , - > { includes ( champs : :type_de_champ ) }
2018-11-01 14:04:32 +01:00
scope :for_api , - > {
2019-06-25 17:12:44 +02:00
includes ( commentaires : { piece_jointe_attachment : :blob } ,
2018-11-01 14:04:32 +01:00
champs : [
:geo_areas ,
:etablissement ,
2019-07-11 10:28:44 +02:00
piece_justificative_file_attachment : :blob ,
champs : [
piece_justificative_file_attachment : :blob
]
2018-11-01 14:04:32 +01:00
] ,
champs_private : [
:geo_areas ,
:etablissement ,
2019-07-11 10:28:44 +02:00
piece_justificative_file_attachment : :blob ,
champs : [
piece_justificative_file_attachment : :blob
]
2018-11-01 14:04:32 +01:00
] ,
2019-07-31 16:09:28 +02:00
justificatif_motivation_attachment : :blob ,
attestation : [ ] ,
avis : { piece_justificative_file_attachment : :blob } ,
2021-11-04 19:05:04 +01:00
traitement : [ ] ,
2018-11-01 14:04:32 +01:00
etablissement : [ ] ,
individual : [ ] ,
user : [ ] )
}
2021-02-04 12:59:10 +01:00
scope :with_notifiable_procedure , - > ( opts = { notify_on_closed : false } ) do
states = opts [ :notify_on_closed ] ? [ :publiee , :close , :depubliee ] : [ :publiee , :depubliee ]
2020-03-24 12:50:59 +01:00
joins ( :procedure )
2020-04-29 19:18:12 +02:00
. where ( procedures : { aasm_state : states } )
2021-05-01 12:20:24 +02:00
. where . not ( user_id : nil )
2020-03-24 12:50:59 +01:00
end
2021-11-19 14:07:47 +01:00
scope :interval_brouillon_close_to_expiration , - > do
2021-11-19 14:34:20 +01:00
state_brouillon . where ( " dossiers.created_at + dossiers.conservation_extension + (duree_conservation_dossiers_dans_ds * INTERVAL '1 month') - INTERVAL :expires_in < :now " , { now : Time . zone . now , expires_in : INTERVAL_BEFORE_EXPIRATION } )
2021-11-19 14:07:47 +01:00
end
scope :interval_en_construction_close_to_expiration , - > do
2021-11-19 14:34:20 +01:00
state_en_construction . where ( " dossiers.en_construction_at + dossiers.conservation_extension + (duree_conservation_dossiers_dans_ds * INTERVAL '1 month') - INTERVAL :expires_in < :now " , { now : Time . zone . now , expires_in : INTERVAL_BEFORE_EXPIRATION } )
2021-11-19 14:07:47 +01:00
end
2021-11-19 14:34:20 +01:00
scope :interval_termine_close_to_expiration , - > do
2021-11-30 14:47:19 +01:00
state_termine
2021-12-02 14:21:39 +01:00
. where ( procedures : { procedure_expires_when_termine_enabled : true } )
2021-11-30 14:47:19 +01:00
. where ( " dossiers.processed_at + dossiers.conservation_extension + (duree_conservation_dossiers_dans_ds * INTERVAL '1 month') - INTERVAL :expires_in < :now " , { now : Time . zone . now , expires_in : INTERVAL_BEFORE_EXPIRATION } )
2021-11-19 14:07:47 +01:00
end
2021-11-19 14:34:20 +01:00
scope :brouillon_close_to_expiration , - > do
joins ( :procedure ) . interval_brouillon_close_to_expiration
end
scope :en_construction_close_to_expiration , - > do
joins ( :procedure ) . interval_en_construction_close_to_expiration
end
2021-11-19 14:07:47 +01:00
scope :termine_close_to_expiration , - > do
2021-11-19 14:34:20 +01:00
joins ( :procedure ) . interval_termine_close_to_expiration
2020-02-26 17:36:24 +01:00
end
2021-11-19 12:36:03 +01:00
2021-11-19 14:28:54 +01:00
scope :close_to_expiration , - > do
joins ( :procedure ) . scoping do
2021-11-19 14:34:20 +01:00
interval_brouillon_close_to_expiration
. or ( interval_en_construction_close_to_expiration )
. or ( interval_termine_close_to_expiration )
2021-11-19 14:28:54 +01:00
end
2020-04-02 15:04:12 +02:00
end
2020-02-26 17:36:24 +01:00
2021-12-01 17:39:47 +01:00
scope :termine_or_en_construction_close_to_expiration , - > do
joins ( :procedure ) . scoping do
interval_en_construction_close_to_expiration
. or ( interval_termine_close_to_expiration )
end
end
2020-03-24 12:50:59 +01:00
scope :brouillon_expired , - > do
state_brouillon
2020-03-25 10:38:17 +01:00
. where ( " brouillon_close_to_expiration_notice_sent_at + INTERVAL :expires_in < :now " , { now : Time . zone . now , expires_in : INTERVAL_EXPIRATION } )
2020-03-24 12:50:59 +01:00
end
scope :en_construction_expired , - > do
state_en_construction
2020-03-25 10:38:17 +01:00
. where ( " en_construction_close_to_expiration_notice_sent_at + INTERVAL :expires_in < :now " , { now : Time . zone . now , expires_in : INTERVAL_EXPIRATION } )
2020-03-24 12:50:59 +01:00
end
2020-04-02 15:04:12 +02:00
scope :termine_expired , - > do
state_termine
. where ( " termine_close_to_expiration_notice_sent_at + INTERVAL :expires_in < :now " , { now : Time . zone . now , expires_in : INTERVAL_EXPIRATION } )
end
2020-02-26 17:36:24 +01:00
scope :without_brouillon_expiration_notice_sent , - > { where ( brouillon_close_to_expiration_notice_sent_at : nil ) }
scope :without_en_construction_expiration_notice_sent , - > { where ( en_construction_close_to_expiration_notice_sent_at : nil ) }
2020-04-02 15:04:12 +02:00
scope :without_termine_expiration_notice_sent , - > { where ( termine_close_to_expiration_notice_sent_at : nil ) }
2019-12-03 10:31:10 +01:00
2022-01-11 15:20:23 +01:00
scope :discarded_expired , - > { discarded . where ( 'dossiers.hidden_at < ?' , 1 . week . ago ) }
scope :discarded_by_user_expired , - > { discarded . where ( 'dossiers.hidden_by_user_at < ?' , 1 . week . ago ) }
scope :discarded_by_administration_expired , - > { discarded . where ( 'dossiers.hidden_by_administration_at < ?' , 1 . week . ago ) }
2020-03-19 13:11:45 +01:00
scope :discarded_brouillon_expired , - > do
with_discarded
. state_brouillon
2022-01-11 15:20:23 +01:00
. discarded_expired
. or ( state_brouillon . discarded_by_user_expired )
2020-03-19 13:11:45 +01:00
end
scope :discarded_en_construction_expired , - > do
with_discarded
. state_en_construction
2022-01-11 15:20:23 +01:00
. discarded_expired
. or ( state_en_construction . discarded_by_user_expired )
2020-11-26 15:13:32 +01:00
end
scope :discarded_termine_expired , - > do
with_discarded
. state_termine
2022-01-11 15:20:23 +01:00
. discarded_expired
. or ( state_termine . discarded_by_user_expired . discarded_by_administration_expired )
2020-03-19 13:11:45 +01:00
end
2020-03-25 04:09:14 +01:00
scope :brouillon_near_procedure_closing_date , - > do
2020-02-05 22:10:22 +01:00
# select users who have submitted dossier for the given 'procedures.id'
users_who_submitted =
state_not_brouillon
2021-03-09 11:21:25 +01:00
. joins ( :revision )
. where ( " procedure_revisions.procedure_id = procedures.id " )
2020-02-05 22:10:22 +01:00
. select ( :user_id )
# select dossier in brouillon where procedure closes in two days and for which the user has not submitted a Dossier
2020-04-29 19:18:12 +02:00
state_brouillon
. with_notifiable_procedure
2020-03-25 10:38:17 +01:00
. where ( " procedures.auto_archive_on - INTERVAL :before_closing = :now " , { now : Time . zone . today , before_closing : INTERVAL_BEFORE_CLOSING } )
2020-02-05 22:10:22 +01:00
. where . not ( user : users_who_submitted )
end
2021-11-04 19:05:04 +01:00
scope :for_api_v2 , - > { includes ( procedure : [ :administrateurs , :attestation_template ] , etablissement : [ ] , individual : [ ] , traitement : [ ] ) }
2019-09-18 13:07:30 +02:00
2020-09-18 15:40:26 +02:00
scope :with_notifications , - > do
2020-07-30 11:05:39 +02:00
joins ( :follows )
. where ( 'last_champ_updated_at > follows.demande_seen_at' \
2021-10-04 10:05:27 +02:00
' OR identity_updated_at > follows.demande_seen_at' \
2020-07-30 11:05:39 +02:00
' OR groupe_instructeur_updated_at > follows.demande_seen_at' \
' OR last_champ_private_updated_at > follows.annotations_privees_seen_at' \
' OR last_avis_updated_at > follows.avis_seen_at' \
' OR last_commentaire_updated_at > follows.messagerie_seen_at' )
. distinct
2019-09-23 14:38:12 +02:00
end
2016-08-30 11:18:43 +02:00
accepts_nested_attributes_for :individual
2018-04-23 11:57:38 +02:00
delegate :siret , :siren , to : :etablissement , allow_nil : true
2021-05-12 19:04:31 +02:00
delegate :france_connect_information , to : :user , allow_nil : true
2015-08-13 15:55:19 +02:00
2021-03-09 11:21:25 +01:00
before_save :build_default_champs , if : Proc . new { revision_id_was . nil? }
2018-07-25 19:34:06 +02:00
before_save :update_search_terms
2017-03-01 09:51:55 +01:00
2018-03-01 17:04:05 +01:00
after_save :send_web_hook
2020-09-28 17:38:49 +02:00
after_create_commit :send_draft_notification_email
2015-08-24 15:23:07 +02:00
2021-05-11 17:49:29 +02:00
validates :user , presence : true , if : - > { deleted_user_email_never_send . nil? }
2020-08-27 19:55:10 +02:00
validates :individual , presence : true , if : - > { revision . procedure . for_individual? }
2021-03-09 11:21:30 +01:00
validates :groupe_instructeur , presence : true , if : - > { ! brouillon? }
2015-08-21 11:37:13 +02:00
2021-10-20 16:52:38 +02:00
EXPORT_BATCH_SIZE = 5000
def self . downloadable_sorted_batch
dossiers = downloadable_sorted . to_a
( dossiers . size . to_f / EXPORT_BATCH_SIZE ) . ceil . times do | i |
start_index = i * EXPORT_BATCH_SIZE
end_index = start_index + EXPORT_BATCH_SIZE - 1
load_champs ( dossiers [ start_index .. end_index ] )
end
dossiers
end
def self . load_champs ( dossiers )
:: ActiveRecord :: Associations :: Preloader . new . preload ( dossiers , {
champs : {
type_de_champ : [ ] ,
etablissement : :champ ,
piece_justificative_file_attachment : :blob ,
champs : [
type_de_champ : [ ] ,
piece_justificative_file_attachment : :blob
]
} ,
champs_private : {
type_de_champ : [ ] ,
etablissement : :champ ,
piece_justificative_file_attachment : :blob ,
champs : [
type_de_champ : [ ] ,
piece_justificative_file_attachment : :blob
]
}
} )
end
2021-05-01 12:20:24 +02:00
def user_deleted?
2021-09-08 09:21:06 +02:00
persisted? && user_id . nil?
2021-05-01 12:20:24 +02:00
end
def user_email_for ( use )
if user_deleted?
if use == :display
deleted_user_email_never_send
else
raise " Can not send email to discarded user "
end
else
user . email
end
end
2020-07-02 11:02:50 +02:00
def motivation
return nil if ! termine?
2021-11-04 19:05:04 +01:00
traitement & . motivation || read_attribute ( :motivation )
2020-07-02 11:02:50 +02:00
end
2018-07-25 19:34:06 +02:00
def update_search_terms
self . search_terms = [
user & . email ,
2018-08-22 17:48:25 +02:00
* champs . flat_map ( & :search_terms ) ,
2018-07-25 19:34:06 +02:00
* etablissement & . search_terms ,
individual & . nom ,
individual & . prenom
] . compact . join ( ' ' )
2018-08-22 17:48:25 +02:00
self . private_search_terms = champs_private . flat_map ( & :search_terms ) . compact . join ( ' ' )
2018-07-25 19:34:06 +02:00
end
2015-11-03 15:27:49 +01:00
def build_default_champs
2020-08-27 19:55:10 +02:00
revision . build_champs . each do | champ |
2019-01-30 16:14:15 +01:00
champs << champ
2018-08-22 17:16:06 +02:00
end
2020-08-27 19:55:10 +02:00
revision . build_champs_private . each do | champ |
2019-02-07 10:44:15 +01:00
champs_private << champ
2015-11-03 15:27:49 +01:00
end
end
2016-08-30 11:18:43 +02:00
def build_default_individual
2020-01-07 17:59:11 +01:00
if procedure . for_individual? && individual . blank?
self . individual = if france_connect_information . present?
Individual . from_france_connect ( france_connect_information )
else
Individual . new
end
2016-12-21 15:39:41 +01:00
end
2016-08-30 11:18:43 +02:00
end
2017-07-11 15:58:31 +02:00
def en_construction_ou_instruction?
EN_CONSTRUCTION_OU_INSTRUCTION . include? ( state )
end
def termine?
TERMINE . include? ( state )
end
2018-06-13 13:58:14 +02:00
def instruction_commencee?
INSTRUCTION_COMMENCEE . include? ( state )
end
2016-06-20 13:57:57 +02:00
def reset!
2016-10-05 14:28:10 +02:00
etablissement . destroy
2016-06-20 13:57:57 +02:00
2018-02-08 17:13:15 +01:00
update_columns ( autorisation_donnees : false )
2016-06-20 13:57:57 +02:00
end
2016-07-19 16:44:26 +02:00
2016-09-13 12:17:56 +02:00
def read_only?
2017-12-04 20:23:57 +01:00
en_instruction? || accepte? || refuse? || sans_suite?
2016-09-13 12:17:56 +02:00
end
2018-06-25 18:07:16 +02:00
def can_transition_to_en_construction?
2019-12-04 15:45:06 +01:00
brouillon? && procedure . dossier_can_transition_to_en_construction?
2018-06-25 18:07:16 +02:00
end
2021-05-01 12:20:24 +02:00
def can_repasser_en_instruction?
termine? && ! user_deleted?
end
2019-02-06 18:20:35 +01:00
def can_be_updated_by_user?
2018-06-08 15:51:46 +02:00
brouillon? || en_construction?
end
2019-02-06 19:11:55 +01:00
def can_be_deleted_by_user?
2021-12-07 15:38:37 +01:00
brouillon? || en_construction? || termine?
2019-02-06 19:11:55 +01:00
end
2022-01-05 10:41:02 +01:00
def can_be_hidden_by_user?
en_construction? || termine?
end
2019-03-12 15:41:47 +01:00
def messagerie_available?
2021-05-01 12:20:24 +02:00
! brouillon? && ! user_deleted? && ! archived
2019-03-12 15:41:47 +01:00
end
2021-11-22 14:51:52 +01:00
def expirable?
2021-11-30 14:47:19 +01:00
[
brouillon? ,
en_construction? ,
termine? && procedure . procedure_expires_when_termine_enabled
] . any?
2021-11-22 14:51:52 +01:00
end
def approximative_expiration_date_reference
2021-11-17 10:53:43 +01:00
if brouillon?
created_at
elsif en_construction?
2021-11-18 18:15:57 +01:00
en_construction_at
2021-11-22 14:51:52 +01:00
elsif termine?
2021-11-17 10:53:43 +01:00
processed_at
2021-11-22 14:51:52 +01:00
else
fail " approximative_expiration_date_reference should not be called in state #{ self . state } "
end
2021-05-04 16:29:29 +02:00
end
2021-11-22 14:51:52 +01:00
def approximative_expiration_date
[
approximative_expiration_date_reference ,
conservation_extension ,
procedure . duree_conservation_dossiers_dans_ds . months
2021-12-07 13:32:39 +01:00
] . sum - REMAINING_WEEKS_BEFORE_EXPIRATION . weeks
2021-11-22 14:51:52 +01:00
end
def close_to_expiration?
2021-12-07 13:32:27 +01:00
return false if en_instruction?
approximative_expiration_date < Time . zone . now
2021-11-17 10:53:43 +01:00
end
def expiration_date
if brouillon? && brouillon_close_to_expiration_notice_sent_at . present?
brouillon_close_to_expiration_notice_sent_at + duration_after_notice
elsif en_construction? && en_construction_close_to_expiration_notice_sent_at . present?
en_construction_close_to_expiration_notice_sent_at + duration_after_notice
elsif termine? && termine_close_to_expiration_notice_sent_at . present?
termine_close_to_expiration_notice_sent_at + duration_after_notice
end
2021-05-04 16:29:29 +02:00
end
2021-11-22 14:51:52 +01:00
def duration_after_notice
MONTHS_AFTER_EXPIRATION . month + DAYS_AFTER_EXPIRATION . days
2021-11-17 10:53:43 +01:00
end
def expiration_can_be_extended?
brouillon? || en_construction?
2020-03-19 14:47:09 +01:00
end
2021-03-03 18:21:00 +01:00
def show_groupe_instructeur_details?
2021-03-09 11:21:30 +01:00
procedure . routee? && groupe_instructeur . present? && ( ! procedure . feature_enabled? ( :procedure_routage_api ) || ! defaut_groupe_instructeur? )
2021-03-03 18:21:00 +01:00
end
def show_groupe_instructeur_selector?
procedure . routee? && ! procedure . feature_enabled? ( :procedure_routage_api )
end
2020-02-26 12:30:52 +01:00
def assign_to_groupe_instructeur ( groupe_instructeur , author = nil )
2021-03-09 11:21:25 +01:00
if ( groupe_instructeur . nil? || groupe_instructeur . procedure == procedure ) && self . groupe_instructeur != groupe_instructeur
2020-02-26 22:17:55 +01:00
if update ( groupe_instructeur : groupe_instructeur , groupe_instructeur_updated_at : Time . zone . now )
2020-02-26 12:30:52 +01:00
unfollow_stale_instructeurs
if author . present?
log_dossier_operation ( author , :changer_groupe_instructeur , self )
end
true
end
else
false
end
end
2020-09-09 15:04:58 +02:00
def archiver! ( author )
update! ( archived : true )
log_dossier_operation ( author , :archiver )
end
def desarchiver! ( author )
update! ( archived : false )
log_dossier_operation ( author , :desarchiver )
end
2017-04-18 17:31:01 +02:00
def text_summary
if brouillon?
parts = [
2018-09-05 14:48:42 +02:00
" Dossier en brouillon répondant à la démarche " ,
2017-04-18 17:31:01 +02:00
procedure . libelle ,
2017-05-02 09:48:25 +02:00
" gérée par l'organisme " ,
2019-02-05 11:29:49 +01:00
procedure . organisation_name
2017-04-18 17:31:01 +02:00
]
else
parts = [
" Dossier déposé le " ,
2021-12-06 15:49:17 +01:00
depose_at . strftime ( " %d/%m/%Y " ) ,
2018-09-05 14:48:42 +02:00
" sur la démarche " ,
2017-04-18 17:31:01 +02:00
procedure . libelle ,
2017-05-02 09:48:25 +02:00
" gérée par l'organisme " ,
2019-02-05 11:29:49 +01:00
procedure . organisation_name
2017-04-18 17:31:01 +02:00
]
end
parts . join
end
2021-12-02 16:19:17 +01:00
def duree_totale_conservation_in_months
procedure . duree_conservation_dossiers_dans_ds + ( conservation_extension / 1 . month . to_i )
end
2021-02-25 10:10:24 +01:00
def avis_for_instructeur ( instructeur )
2019-08-06 11:02:54 +02:00
if instructeur . dossiers . include? ( self )
2017-09-08 11:52:20 +02:00
avis . order ( created_at : :asc )
else
avis
. where ( confidentiel : false )
2021-04-07 19:53:18 +02:00
. or ( avis . where ( claimant : instructeur ) )
2017-09-08 11:52:20 +02:00
. order ( created_at : :asc )
end
end
2021-02-25 10:10:24 +01:00
def avis_for_expert ( expert )
2021-05-19 15:41:12 +02:00
Avis
. where ( dossier_id : id , confidentiel : false )
2021-05-20 16:15:59 +02:00
. or ( Avis . where ( id : expert . avis , dossier_id : id ) )
2021-05-19 15:41:12 +02:00
. order ( created_at : :asc )
2021-02-25 10:10:24 +01:00
end
2017-11-17 23:40:51 +01:00
def owner_name
2018-04-23 11:57:38 +02:00
if etablissement . present?
etablissement . entreprise_raison_sociale
2017-11-17 23:40:51 +01:00
elsif individual . present?
" #{ individual . nom } #{ individual . prenom } "
end
end
2020-03-24 12:50:59 +01:00
def log_operations?
2021-10-05 16:03:56 +02:00
! procedure . brouillon? && ! brouillon?
2020-03-24 12:50:59 +01:00
end
def keep_track_on_deletion?
2021-10-27 10:02:56 +02:00
! procedure . brouillon? && ! brouillon?
2020-03-24 12:50:59 +01:00
end
2021-12-16 11:25:44 +01:00
def hidden_by_user?
hidden_by_user_at . present?
end
2021-12-21 12:44:57 +01:00
def hidden_by_administration?
hidden_by_administration_at . present?
2021-12-16 11:25:44 +01:00
end
2021-12-10 17:13:26 +01:00
def deleted_by_instructeur_and_user?
2021-12-21 12:44:57 +01:00
termine? && hidden_by_administration? && hidden_by_user?
2021-12-16 11:25:44 +01:00
end
2018-10-31 13:28:39 +01:00
def expose_legacy_carto_api?
procedure . expose_legacy_carto_api?
end
2018-10-10 19:58:51 +02:00
def geo_position
if etablissement . present?
2020-01-14 19:00:17 +01:00
point = Geocoder . search ( etablissement . geo_adresse ) . first
2018-10-10 19:58:51 +02:00
end
2020-04-16 10:22:07 +02:00
lon = Champs :: CarteChamp :: DEFAULT_LON . to_s
lat = Champs :: CarteChamp :: DEFAULT_LAT . to_s
2018-10-10 19:58:51 +02:00
zoom = " 13 "
if point . present?
2020-01-14 19:00:17 +01:00
lat , lon = point . coordinates . map ( & :to_s )
2018-10-10 19:58:51 +02:00
end
{ lon : lon , lat : lat , zoom : zoom }
end
2022-02-02 16:10:29 +01:00
def attestation_template
revision . attestation_template
end
2022-01-25 18:26:34 +01:00
2022-02-02 16:10:29 +01:00
def unspecified_attestation_champs
2018-04-06 16:21:48 +02:00
if attestation_template & . activated?
2018-04-06 13:09:37 +02:00
attestation_template . unspecified_champs_for_dossier ( self )
else
[ ]
end
end
2017-06-08 14:04:47 +02:00
def build_attestation
2022-02-02 16:10:29 +01:00
if attestation_template & . activated?
attestation_template . attestation_for ( self )
2017-06-08 14:04:47 +02:00
end
end
2021-10-27 10:02:56 +02:00
def expired_keep_track_and_destroy!
transaction do
if keep_track_on_deletion?
DeletedDossier . create_from_dossier ( self , :expired )
2021-11-04 19:04:04 +01:00
dossier_operation_logs . destroy_all
2021-10-27 10:02:56 +02:00
log_automatic_dossier_operation ( :supprimer , self )
end
destroy!
2020-03-24 12:50:59 +01:00
end
2021-10-27 10:02:56 +02:00
true
rescue
false
2020-03-19 11:53:25 +01:00
end
2018-07-23 15:06:06 +02:00
2022-01-05 10:41:02 +01:00
def author_is_user ( author )
author . is_a? ( User )
end
def author_is_administration ( author )
author . is_a? ( Instructeur ) || author . is_a? ( Administrateur ) || author . is_a? ( SuperAdmin )
end
def restore_dossier_and_destroy_deleted_dossier ( author )
2022-02-08 10:47:43 +01:00
if deleted_dossier . present?
deleted_dossier & . destroy!
end
2022-01-05 10:41:02 +01:00
log_dossier_operation ( author , :restaurer , self )
end
2021-12-10 17:13:26 +01:00
2022-01-05 10:41:02 +01:00
def discard_and_keep_track! ( author , reason )
if termine? && author_is_administration ( author )
2022-02-08 10:47:43 +01:00
update ( hidden_by_administration_at : Time . zone . now , hidden_by_reason : reason )
2021-12-10 17:13:26 +01:00
end
2022-01-05 10:41:02 +01:00
if can_be_hidden_by_user? && author_is_user ( author )
2022-02-08 10:47:43 +01:00
update ( hidden_by_user_at : Time . zone . now , dossier_transfer_id : nil , hidden_by_reason : reason )
2021-12-10 17:13:26 +01:00
end
2021-10-27 10:02:56 +02:00
transaction do
2022-01-11 15:20:23 +01:00
if deleted_by_instructeur_and_user? || en_construction? || brouillon?
2021-12-16 11:25:44 +01:00
if keep_track_on_deletion?
log_dossier_operation ( author , :supprimer , self )
end
2021-10-27 10:02:56 +02:00
2022-01-05 10:41:02 +01:00
if ! ( en_construction? && author_is_user ( author ) )
discard!
end
2021-12-10 17:13:26 +01:00
end
2021-10-27 10:02:56 +02:00
end
2020-11-17 13:25:35 +01:00
2022-02-08 10:47:43 +01:00
if en_construction?
update ( hidden_by_reason : reason )
administration_emails = followers_instructeurs . present? ? followers_instructeurs . map ( & :email ) : procedure . administrateurs . map ( & :email )
administration_emails . each do | email |
DossierMailer . notify_en_construction_deletion_to_administration ( self , email ) . deliver_later
2021-10-27 10:02:56 +02:00
end
2018-07-23 15:06:06 +02:00
end
2018-05-30 11:36:48 +02:00
end
2021-10-27 10:02:56 +02:00
def restore ( author )
2020-03-26 17:35:50 +01:00
if discarded?
2021-10-27 10:02:56 +02:00
transaction do
2022-01-05 10:41:02 +01:00
if author_is_administration ( author ) && hidden_by_administration?
2021-12-21 12:44:57 +01:00
update ( hidden_by_administration_at : nil )
2022-01-05 10:41:02 +01:00
end
if undiscard && keep_track_on_deletion?
restore_dossier_and_destroy_deleted_dossier ( author )
end
end
elsif author_is_user ( author ) && hidden_by_user?
transaction do
update ( hidden_by_user_at : nil )
2022-02-08 10:47:43 +01:00
! hidden_by_administration? && update ( hidden_by_reason : nil )
2022-01-05 10:41:02 +01:00
if en_construction?
restore_dossier_and_destroy_deleted_dossier ( author )
2020-03-26 17:35:50 +01:00
end
end
2022-01-27 17:01:27 +01:00
elsif author_is_administration ( author ) && hidden_by_administration?
transaction do
update ( hidden_by_administration_at : nil )
2022-02-08 10:47:43 +01:00
! hidden_by_user? && update ( hidden_by_reason : nil )
2022-01-27 17:01:27 +01:00
end
2020-03-26 17:35:50 +01:00
end
end
2021-12-08 11:23:03 +01:00
def attestation_activated?
termine? && procedure . attestation_template & . activated?
end
2020-07-01 17:31:08 +02:00
def after_passer_en_construction
2021-11-04 19:05:04 +01:00
self . conservation_extension = 0 . days
2021-11-24 12:27:32 +01:00
self . depose_at = self . en_construction_at = self . traitements
2021-11-04 19:05:04 +01:00
. passer_en_construction
. processed_at
save!
2020-07-01 17:31:08 +02:00
end
2021-11-26 12:19:40 +01:00
def after_passer_en_instruction ( h )
instructeur = h [ :instructeur ]
disable_notification = h . fetch ( :disable_notification , false )
2019-08-06 11:02:54 +02:00
instructeur . follow ( self )
2018-11-26 21:29:06 +01:00
2021-11-04 19:05:04 +01:00
self . en_construction_close_to_expiration_notice_sent_at = nil
self . conservation_extension = 0 . days
self . en_instruction_at = self . traitements
2021-11-14 18:43:45 +01:00
. passer_en_instruction ( instructeur : instructeur )
2021-11-04 19:05:04 +01:00
. processed_at
save!
2021-09-01 15:11:11 +02:00
if ! procedure . declarative_accepte? && ! disable_notification
NotificationMailer . send_en_instruction_notification ( self ) . deliver_later
end
2019-08-06 11:02:54 +02:00
log_dossier_operation ( instructeur , :passer_en_instruction )
2018-11-26 19:12:56 +01:00
end
2019-07-02 15:38:23 +02:00
def after_passer_automatiquement_en_instruction
2021-11-04 19:05:04 +01:00
self . en_construction_close_to_expiration_notice_sent_at = nil
self . conservation_extension = 0 . days
self . en_instruction_at = self . declarative_triggered_at = self . traitements
. passer_en_instruction
. processed_at
2021-06-04 12:03:31 +02:00
save!
2019-05-02 16:22:16 +02:00
log_automatic_dossier_operation ( :passer_en_instruction )
2019-01-10 17:23:48 +01:00
end
2019-08-06 11:02:54 +02:00
def after_repasser_en_construction ( instructeur )
2021-11-24 11:54:18 +01:00
create_missing_traitemets
2021-11-04 19:05:04 +01:00
self . en_construction_close_to_expiration_notice_sent_at = nil
self . conservation_extension = 0 . days
self . en_construction_at = self . traitements
2021-11-14 18:43:45 +01:00
. passer_en_construction ( instructeur : instructeur )
2021-11-04 19:05:04 +01:00
. processed_at
save!
2019-08-06 11:02:54 +02:00
log_dossier_operation ( instructeur , :repasser_en_construction )
2018-11-26 19:12:56 +01:00
end
2021-11-26 12:19:40 +01:00
def after_repasser_en_instruction ( h )
instructeur = h [ :instructeur ]
disable_notification = h . fetch ( :disable_notification , false )
2021-11-24 11:54:18 +01:00
create_missing_traitemets
2021-12-16 11:25:44 +01:00
self . hidden_by_user_at = nil
2020-05-12 19:01:25 +02:00
self . archived = false
2021-11-04 19:05:04 +01:00
self . termine_close_to_expiration_notice_sent_at = nil
self . conservation_extension = 0 . days
self . en_instruction_at = self . traitements
2021-11-14 18:43:45 +01:00
. passer_en_instruction ( instructeur : instructeur )
2021-11-04 19:05:04 +01:00
. processed_at
2019-07-01 17:45:03 +02:00
attestation & . destroy
2019-07-02 15:38:23 +02:00
save!
2021-09-01 15:11:11 +02:00
if ! disable_notification
DossierMailer . notify_revert_to_instruction ( self ) . deliver_later
end
2019-08-06 11:02:54 +02:00
log_dossier_operation ( instructeur , :repasser_en_instruction )
2019-07-01 17:45:03 +02:00
end
2021-11-26 12:19:40 +01:00
def after_accepter ( h )
instructeur = h [ :instructeur ]
motivation = h [ :motivation ]
justificatif = h [ :justificatif ]
disable_notification = h . fetch ( :disable_notification , false )
2021-11-04 19:05:04 +01:00
self . processed_at = self . traitements
. accepter ( motivation : motivation , instructeur : instructeur )
. processed_at
save!
2019-07-02 15:38:23 +02:00
2019-02-18 17:52:15 +01:00
if justificatif
self . justificatif_motivation . attach ( justificatif )
end
2018-11-26 19:12:56 +01:00
if attestation . nil?
2019-07-02 15:38:23 +02:00
self . attestation = build_attestation
2018-11-26 19:12:56 +01:00
end
2019-07-02 15:38:23 +02:00
save!
2020-12-08 15:57:48 +01:00
remove_titres_identite!
2021-09-01 15:11:11 +02:00
if ! disable_notification
NotificationMailer . send_accepte_notification ( self ) . deliver_later
end
2021-04-09 09:55:36 +02:00
send_dossier_decision_to_experts ( self )
2019-08-06 11:02:54 +02:00
log_dossier_operation ( instructeur , :accepter , self )
2018-11-26 19:12:56 +01:00
end
2019-07-02 15:38:23 +02:00
def after_accepter_automatiquement
2021-11-04 19:05:04 +01:00
self . processed_at = self . en_instruction_at = self . declarative_triggered_at = self . traitements
. accepter_automatiquement
. processed_at
save!
2019-01-16 11:00:25 +01:00
if attestation . nil?
2019-07-02 15:38:23 +02:00
self . attestation = build_attestation
2019-01-16 11:00:25 +01:00
end
2019-07-02 15:38:23 +02:00
save!
2020-12-08 15:57:48 +01:00
remove_titres_identite!
2021-04-29 19:10:22 +02:00
NotificationMailer . send_accepte_notification ( self ) . deliver_later
2019-05-02 16:22:16 +02:00
log_automatic_dossier_operation ( :accepter , self )
2019-01-16 11:00:25 +01:00
end
2021-11-26 12:19:40 +01:00
def after_refuser ( h )
instructeur = h [ :instructeur ]
motivation = h [ :motivation ]
justificatif = h [ :justificatif ]
disable_notification = h . fetch ( :disable_notification , false )
2021-11-04 19:05:04 +01:00
self . processed_at = self . traitements
. refuser ( motivation : motivation , instructeur : instructeur )
. processed_at
save!
2019-07-02 15:38:23 +02:00
2019-02-18 17:52:15 +01:00
if justificatif
self . justificatif_motivation . attach ( justificatif )
end
2018-11-26 19:12:56 +01:00
2019-07-02 15:38:23 +02:00
save!
2020-12-08 15:57:48 +01:00
remove_titres_identite!
2021-09-01 15:11:11 +02:00
if ! disable_notification
NotificationMailer . send_refuse_notification ( self ) . deliver_later
end
2021-04-09 09:55:36 +02:00
send_dossier_decision_to_experts ( self )
2019-08-06 11:02:54 +02:00
log_dossier_operation ( instructeur , :refuser , self )
2018-11-26 19:12:56 +01:00
end
2021-11-26 12:19:40 +01:00
def after_classer_sans_suite ( h )
instructeur = h [ :instructeur ]
motivation = h [ :motivation ]
justificatif = h [ :justificatif ]
disable_notification = h . fetch ( :disable_notification , false )
2021-11-04 19:05:04 +01:00
self . processed_at = self . traitements
. classer_sans_suite ( motivation : motivation , instructeur : instructeur )
. processed_at
save!
2019-07-02 15:38:23 +02:00
2019-02-18 17:52:15 +01:00
if justificatif
self . justificatif_motivation . attach ( justificatif )
end
2018-11-26 19:12:56 +01:00
2019-07-02 15:38:23 +02:00
save!
2020-12-08 15:57:48 +01:00
remove_titres_identite!
2021-09-01 15:11:11 +02:00
if ! disable_notification
NotificationMailer . send_sans_suite_notification ( self ) . deliver_later
end
2021-04-09 09:55:36 +02:00
send_dossier_decision_to_experts ( self )
2019-08-06 11:02:54 +02:00
log_dossier_operation ( instructeur , :classer_sans_suite , self )
2018-11-26 19:12:56 +01:00
end
2020-12-08 15:57:48 +01:00
def remove_titres_identite!
champs . filter ( & :titre_identite? ) . map ( & :piece_justificative_file ) . each ( & :purge_later )
end
2019-01-30 16:14:15 +01:00
def check_mandatory_champs
2019-09-12 11:26:22 +02:00
( champs + champs . filter ( & :repetition? ) . flat_map ( & :champs ) )
. filter ( & :mandatory_and_blank? )
2019-01-30 16:14:15 +01:00
. map do | champ |
" Le champ #{ champ . libelle . truncate ( 200 ) } doit être rempli. "
end
end
2020-07-28 14:22:56 +02:00
def log_modifier_annotations! ( instructeur )
2019-09-12 11:26:22 +02:00
champs_private . filter ( & :value_previously_changed? ) . each do | champ |
2019-08-06 11:02:54 +02:00
log_dossier_operation ( instructeur , :modifier_annotation , champ )
2019-05-02 16:23:47 +02:00
end
end
2019-05-02 16:24:24 +02:00
2020-07-28 18:16:03 +02:00
def log_modifier_annotation! ( champ , instructeur )
log_dossier_operation ( instructeur , :modifier_annotation , champ )
end
2019-05-02 16:24:24 +02:00
def demander_un_avis! ( avis )
log_dossier_operation ( avis . claimant , :demander_un_avis , avis )
end
2021-06-22 10:17:10 +02:00
def spreadsheet_columns_csv ( types_de_champ : )
spreadsheet_columns ( with_etablissement : true , types_de_champ : types_de_champ )
2019-11-06 15:55:01 +01:00
end
2021-06-22 10:17:10 +02:00
def spreadsheet_columns_xlsx ( types_de_champ : )
spreadsheet_columns ( types_de_champ : types_de_champ )
2019-11-06 15:55:01 +01:00
end
2021-06-22 10:17:10 +02:00
def spreadsheet_columns_ods ( types_de_champ : )
spreadsheet_columns ( types_de_champ : types_de_champ )
2019-11-06 15:55:01 +01:00
end
2021-06-22 10:17:10 +02:00
def spreadsheet_columns ( with_etablissement : false , types_de_champ : )
2019-09-18 21:09:52 +02:00
columns = [
2019-04-03 14:29:30 +02:00
[ 'ID' , id . to_s ] ,
2021-05-01 12:20:24 +02:00
[ 'Email' , user_email_for ( :display ) ]
2019-10-31 14:14:14 +01:00
]
if procedure . for_individual?
columns += [
[ 'Civilité' , individual & . gender ] ,
[ 'Nom' , individual & . nom ] ,
2020-05-13 15:57:56 +02:00
[ 'Prénom' , individual & . prenom ]
2019-10-31 14:14:14 +01:00
]
2020-05-13 15:57:56 +02:00
if procedure . ask_birthday
columns += [ [ 'Date de naissance' , individual & . birthdate ] ]
end
2019-11-06 15:55:01 +01:00
elsif with_etablissement
columns += [
[ 'Établissement SIRET' , etablissement & . siret ] ,
[ 'Établissement siège social' , etablissement & . siege_social ] ,
[ 'Établissement NAF' , etablissement & . naf ] ,
[ 'Établissement libellé NAF' , etablissement & . libelle_naf ] ,
[ 'Établissement Adresse' , etablissement & . adresse ] ,
[ 'Établissement numero voie' , etablissement & . numero_voie ] ,
[ 'Établissement type voie' , etablissement & . type_voie ] ,
[ 'Établissement nom voie' , etablissement & . nom_voie ] ,
[ 'Établissement complément adresse' , etablissement & . complement_adresse ] ,
[ 'Établissement code postal' , etablissement & . code_postal ] ,
[ 'Établissement localité' , etablissement & . localite ] ,
[ 'Établissement code INSEE localité' , etablissement & . code_insee_localite ] ,
[ 'Entreprise SIREN' , etablissement & . entreprise_siren ] ,
[ 'Entreprise capital social' , etablissement & . entreprise_capital_social ] ,
[ 'Entreprise numero TVA intracommunautaire' , etablissement & . entreprise_numero_tva_intracommunautaire ] ,
[ 'Entreprise forme juridique' , etablissement & . entreprise_forme_juridique ] ,
[ 'Entreprise forme juridique code' , etablissement & . entreprise_forme_juridique_code ] ,
[ 'Entreprise nom commercial' , etablissement & . entreprise_nom_commercial ] ,
[ 'Entreprise raison sociale' , etablissement & . entreprise_raison_sociale ] ,
[ 'Entreprise SIRET siège social' , etablissement & . entreprise_siret_siege_social ] ,
[ 'Entreprise code effectif entreprise' , etablissement & . entreprise_code_effectif_entreprise ] ,
[ 'Entreprise date de création' , etablissement & . entreprise_date_creation ] ,
[ 'Entreprise nom' , etablissement & . entreprise_nom ] ,
[ 'Entreprise prénom' , etablissement & . entreprise_prenom ] ,
[ 'Association RNA' , etablissement & . association_rna ] ,
[ 'Association titre' , etablissement & . association_titre ] ,
[ 'Association objet' , etablissement & . association_objet ] ,
[ 'Association date de création' , etablissement & . association_date_creation ] ,
[ 'Association date de déclaration' , etablissement & . association_date_declaration ] ,
[ 'Association date de publication' , etablissement & . association_date_publication ]
]
2019-10-31 14:14:14 +01:00
else
columns << [ 'Entreprise raison sociale' , etablissement & . entreprise_raison_sociale ]
end
columns += [
2019-04-03 14:29:30 +02:00
[ 'Archivé' , :archived ] ,
2021-05-10 11:00:57 +02:00
[ 'État du dossier' , Dossier . human_attribute_name ( " state. #{ state } " ) ] ,
2019-04-03 14:29:30 +02:00
[ 'Dernière mise à jour le' , :updated_at ] ,
2021-12-06 15:49:17 +01:00
[ 'Déposé le' , :depose_at ] ,
2019-07-04 15:02:25 +02:00
[ 'Passé en instruction le' , :en_instruction_at ] ,
2019-04-03 14:29:30 +02:00
[ 'Traité le' , :processed_at ] ,
[ 'Motivation de la décision' , :motivation ] ,
2019-08-06 11:02:54 +02:00
[ 'Instructeurs' , followers_instructeurs . map ( & :email ) . join ( ' ' ) ]
2019-09-18 21:09:52 +02:00
]
if procedure . routee?
columns << [ 'Groupe instructeur' , groupe_instructeur . label ]
end
2021-10-22 12:18:43 +02:00
columns + self . class . champs_for_export ( champs + champs_private , types_de_champ )
2019-04-03 14:29:30 +02:00
end
2021-10-22 12:18:43 +02:00
def self . champs_for_export ( champs , types_de_champ )
2020-09-08 15:53:07 +02:00
# Index values by stable_id
2021-10-22 12:18:43 +02:00
values = champs . reject ( & :exclude_from_export? )
2021-08-18 14:02:40 +02:00
. index_by ( & :stable_id )
. transform_values ( & :for_export )
2020-09-08 15:53:07 +02:00
# Get all the champs values for the types de champ in the final list.
# Dossier might not have corresponding champ – display nil.
2021-08-18 14:02:40 +02:00
types_de_champ . flat_map do | type_de_champ |
2021-08-18 14:13:10 +02:00
Array . wrap ( values [ type_de_champ . stable_id ] || [ nil ] ) . map . with_index do | champ_value , index |
[ type_de_champ . libelle_for_export ( index ) , champ_value ]
2021-08-18 14:02:40 +02:00
end
2019-04-03 14:29:30 +02:00
end
end
2021-05-04 10:31:13 +02:00
def export_and_attachments_downloadable?
PiecesJustificativesService . pieces_justificatives_total_size ( self ) < Dossier :: TAILLE_MAX_ZIP
2019-07-01 15:55:37 +02:00
end
2021-02-25 10:10:24 +01:00
def linked_dossiers_for ( instructeur_or_expert )
2021-06-10 15:24:15 +02:00
dossier_ids = champs . filter ( & :dossier_link? ) . filter_map ( & :value )
2021-02-25 10:10:24 +01:00
instructeur_or_expert . dossiers . where ( id : dossier_ids )
2020-02-05 17:38:24 +01:00
end
2019-11-28 18:03:23 +01:00
def hash_for_deletion_mail
{ id : self . id , procedure_libelle : self . procedure . libelle }
end
2020-04-30 15:49:43 +02:00
def geo_data?
geo_areas . present?
end
def to_feature_collection
{
type : 'FeatureCollection' ,
id : id ,
bbox : bounding_box ,
features : geo_areas . map ( & :to_feature )
}
end
2021-02-04 19:24:52 +01:00
def log_api_entreprise_job_exception ( exception )
exceptions = self . api_entreprise_job_exceptions || = [ ]
exceptions << exception . inspect
update_column ( :api_entreprise_job_exceptions , exceptions )
end
2021-09-01 18:17:26 +02:00
def user_locale
user & . locale || I18n . default_locale
end
2022-02-08 10:47:43 +01:00
def purge_discarded
2021-10-21 13:29:47 +02:00
transaction do
2022-02-08 10:47:43 +01:00
if keep_track_on_deletion?
DeletedDossier . create_from_dossier ( self , hidden_by_reason )
end
2021-10-21 13:29:47 +02:00
2022-02-08 10:47:43 +01:00
dossier_operation_logs . not_deletion . destroy_all
destroy
2021-10-21 13:29:47 +02:00
end
end
2022-02-08 10:47:43 +01:00
def self . purge_discarded
discarded_brouillon_expired . find_each ( & :purge_discarded )
discarded_en_construction_expired . find_each ( & :purge_discarded )
discarded_termine_expired . find_each ( & :purge_discarded )
end
2017-12-05 17:43:32 +01:00
private
2021-11-24 11:54:18 +01:00
def create_missing_traitemets
if en_construction_at . present? && traitements . en_construction . empty?
self . traitements . passer_en_construction ( processed_at : en_construction_at )
2021-11-24 12:27:32 +01:00
self . depose_at || = en_construction_at
2021-11-24 11:54:18 +01:00
end
if en_instruction_at . present? && traitements . en_instruction . empty?
self . traitements . passer_en_instruction ( processed_at : en_instruction_at )
end
end
2021-10-27 10:02:56 +02:00
def deleted_dossier
@deleted_dossier || = DeletedDossier . find_by ( dossier_id : id )
end
2021-03-03 18:21:00 +01:00
def defaut_groupe_instructeur?
groupe_instructeur == procedure . defaut_groupe_instructeur
end
2020-04-30 15:49:43 +02:00
def geo_areas
champs . includes ( :geo_areas ) . flat_map ( & :geo_areas ) + champs_private . includes ( :geo_areas ) . flat_map ( & :geo_areas )
end
def bounding_box
factory = RGeo :: Geographic . simple_mercator_factory
bounding_box = RGeo :: Cartesian :: BoundingBox . new ( factory )
2021-06-10 15:24:15 +02:00
geo_areas . filter_map ( & :rgeo_geometry ) . each do | geometry |
2020-05-05 10:26:13 +02:00
bounding_box . add ( geometry )
2020-04-30 15:49:43 +02:00
end
[ bounding_box . max_point , bounding_box . min_point ] . compact . flat_map ( & :coordinates )
end
2019-05-02 16:22:16 +02:00
def log_dossier_operation ( author , operation , subject = nil )
2020-03-24 12:50:59 +01:00
if log_operations?
DossierOperationLog . create_and_serialize (
dossier : self ,
operation : DossierOperationLog . operations . fetch ( operation ) ,
author : author ,
subject : subject
)
end
2018-11-26 21:29:06 +01:00
end
2019-05-02 16:22:16 +02:00
def log_automatic_dossier_operation ( operation , subject = nil )
2020-03-24 12:50:59 +01:00
if log_operations?
DossierOperationLog . create_and_serialize (
dossier : self ,
operation : DossierOperationLog . operations . fetch ( operation ) ,
automatic_operation : true ,
subject : subject
)
end
2019-02-13 16:13:37 +01:00
end
2017-10-11 15:36:40 +02:00
def send_draft_notification_email
2019-05-23 14:28:14 +02:00
if brouillon? && ! procedure . declarative?
2018-11-20 11:50:25 +01:00
DossierMailer . notify_new_draft ( self ) . deliver_later
2017-10-11 15:36:40 +02:00
end
end
2018-03-01 17:04:05 +01:00
def send_web_hook
2020-09-22 17:03:19 +02:00
if saved_change_to_state? && ! brouillon? && procedure . web_hook_url . present?
2018-03-01 17:04:05 +01:00
WebHookJob . perform_later (
procedure ,
self
)
end
end
2019-12-03 10:31:10 +01:00
2020-02-25 15:51:30 +01:00
def unfollow_stale_instructeurs
2020-02-26 12:30:52 +01:00
followers_instructeurs . each do | instructeur |
if instructeur . groupe_instructeurs . exclude? ( groupe_instructeur )
instructeur . unfollow ( self )
2020-04-01 11:10:25 +02:00
if kept?
DossierMailer . notify_groupe_instructeur_changed ( instructeur , self ) . deliver_later
end
2020-02-25 15:51:30 +01:00
end
end
end
2020-02-05 22:10:22 +01:00
def self . notify_draft_not_submitted
2020-03-25 04:09:14 +01:00
brouillon_near_procedure_closing_date
. includes ( :user )
2020-02-05 22:10:22 +01:00
. find_each do | dossier |
2020-03-19 03:46:12 +01:00
DossierMailer . notify_brouillon_not_submitted ( dossier ) . deliver_later
2020-02-05 22:10:22 +01:00
end
end
2021-04-09 09:55:36 +02:00
def send_dossier_decision_to_experts ( dossier )
avis_experts_procedures_ids = Avis
. joins ( :experts_procedure )
. where ( dossier : dossier , experts_procedures : { allow_decision_access : true } )
. with_answer
. distinct
. pluck ( 'avis.id, experts_procedures.id' )
# rubocop:disable Lint/UnusedBlockArgument
avis_ids = avis_experts_procedures_ids
. uniq { | ( avis_id , experts_procedures_id ) | experts_procedures_id }
. map { | ( avis_id , _ ) | avis_id }
# rubocop:enable Lint/UnusedBlockArgument
avis_ids . each { | avis_id | ExpertMailer . send_dossier_decision ( avis_id ) . deliver_later }
end
2015-08-10 11:05:06 +02:00
end