2018-03-06 13:44:29 +01:00
|
|
|
|
class Procedure < ApplicationRecord
|
2017-04-13 14:48:18 +02:00
|
|
|
|
has_many :types_de_piece_justificative, -> { order "order_place ASC" }, dependent: :destroy
|
2018-02-13 15:38:26 +01:00
|
|
|
|
has_many :types_de_champ, -> { public_only }, dependent: :destroy
|
|
|
|
|
has_many :types_de_champ_private, -> { private_only }, class_name: 'TypeDeChamp', dependent: :destroy
|
2016-06-20 17:37:04 +02:00
|
|
|
|
has_many :dossiers
|
2017-03-07 10:25:28 +01:00
|
|
|
|
|
2016-06-24 16:41:44 +02:00
|
|
|
|
has_one :procedure_path, dependent: :destroy
|
|
|
|
|
|
2016-01-18 16:20:51 +01:00
|
|
|
|
has_one :module_api_carto, dependent: :destroy
|
2017-06-08 14:16:48 +02:00
|
|
|
|
has_one :attestation_template, dependent: :destroy
|
2016-01-18 16:20:51 +01:00
|
|
|
|
|
|
|
|
|
belongs_to :administrateur
|
|
|
|
|
|
2016-06-20 17:37:04 +02:00
|
|
|
|
has_many :assign_to, dependent: :destroy
|
2018-03-23 11:39:36 +01:00
|
|
|
|
has_many :administrateurs_procedures
|
|
|
|
|
has_many :administrateurs, through: :administrateurs_procedures
|
2016-05-20 15:39:17 +02:00
|
|
|
|
has_many :gestionnaires, through: :assign_to
|
|
|
|
|
|
2017-05-26 21:55:19 +02:00
|
|
|
|
has_one :initiated_mail, class_name: "Mails::InitiatedMail", dependent: :destroy
|
|
|
|
|
has_one :received_mail, class_name: "Mails::ReceivedMail", dependent: :destroy
|
|
|
|
|
has_one :closed_mail, class_name: "Mails::ClosedMail", dependent: :destroy
|
|
|
|
|
has_one :refused_mail, class_name: "Mails::RefusedMail", dependent: :destroy
|
|
|
|
|
has_one :without_continuation_mail, class_name: "Mails::WithoutContinuationMail", dependent: :destroy
|
|
|
|
|
|
2018-04-11 14:35:52 +02:00
|
|
|
|
has_one_attached :notice
|
|
|
|
|
|
2016-01-25 15:54:21 +01:00
|
|
|
|
delegate :use_api_carto, to: :module_api_carto
|
|
|
|
|
|
2016-08-31 16:07:11 +02:00
|
|
|
|
accepts_nested_attributes_for :types_de_champ, :reject_if => proc { |attributes| attributes['libelle'].blank? }, :allow_destroy => true
|
2015-11-20 13:54:08 +01:00
|
|
|
|
accepts_nested_attributes_for :types_de_piece_justificative, :reject_if => proc { |attributes| attributes['libelle'].blank? }, :allow_destroy => true
|
2015-12-08 10:11:58 +01:00
|
|
|
|
accepts_nested_attributes_for :module_api_carto
|
2016-08-03 18:19:56 +02:00
|
|
|
|
accepts_nested_attributes_for :types_de_champ_private
|
2015-11-10 10:23:15 +01:00
|
|
|
|
|
2015-12-10 17:13:39 +01:00
|
|
|
|
mount_uploader :logo, ProcedureLogoUploader
|
|
|
|
|
|
2017-06-27 14:22:43 +02:00
|
|
|
|
default_scope { where(hidden_at: nil) }
|
2017-07-17 15:06:36 +02:00
|
|
|
|
scope :brouillons, -> { where(published_at: nil).where(archived_at: nil) }
|
|
|
|
|
scope :publiees, -> { where.not(published_at: nil).where(archived_at: nil) }
|
|
|
|
|
scope :archivees, -> { where.not(archived_at: nil) }
|
|
|
|
|
scope :publiees_ou_archivees, -> { where.not(published_at: nil) }
|
|
|
|
|
scope :by_libelle, -> { order(libelle: :asc) }
|
2017-05-26 21:30:11 +02:00
|
|
|
|
|
2015-09-22 11:21:52 +02:00
|
|
|
|
validates :libelle, presence: true, allow_blank: false, allow_nil: false
|
|
|
|
|
validates :description, presence: true, allow_blank: false, allow_nil: false
|
2017-11-23 11:37:41 +01:00
|
|
|
|
validates :organisation, presence: true, allow_blank: false, allow_nil: false
|
2015-11-17 15:30:03 +01:00
|
|
|
|
|
2017-06-27 14:22:43 +02:00
|
|
|
|
def hide!
|
2017-06-27 15:26:40 +02:00
|
|
|
|
now = DateTime.now
|
2018-03-02 16:27:03 +01:00
|
|
|
|
self.update(hidden_at: now)
|
2017-06-27 15:26:40 +02:00
|
|
|
|
self.dossiers.update_all(hidden_at: now)
|
2017-06-27 14:22:43 +02:00
|
|
|
|
end
|
|
|
|
|
|
2016-06-24 16:41:44 +02:00
|
|
|
|
def path
|
2018-01-11 19:04:39 +01:00
|
|
|
|
procedure_path.path if procedure_path.present?
|
2016-06-24 16:41:44 +02:00
|
|
|
|
end
|
|
|
|
|
|
2016-06-30 10:24:01 +02:00
|
|
|
|
def default_path
|
2017-04-14 11:34:53 +02:00
|
|
|
|
libelle.parameterize.first(50)
|
2016-06-30 10:24:01 +02:00
|
|
|
|
end
|
|
|
|
|
|
2015-11-17 15:30:03 +01:00
|
|
|
|
def types_de_champ_ordered
|
|
|
|
|
types_de_champ.order(:order_place)
|
|
|
|
|
end
|
2015-11-19 11:37:01 +01:00
|
|
|
|
|
2016-08-03 18:19:56 +02:00
|
|
|
|
def types_de_champ_private_ordered
|
|
|
|
|
types_de_champ_private.order(:order_place)
|
|
|
|
|
end
|
|
|
|
|
|
2018-02-09 17:38:30 +01:00
|
|
|
|
def all_types_de_champ
|
|
|
|
|
types_de_champ + types_de_champ_private
|
|
|
|
|
end
|
|
|
|
|
|
2018-03-20 17:47:37 +01:00
|
|
|
|
def self.active(id)
|
2017-07-11 15:52:06 +02:00
|
|
|
|
publiees.find(id)
|
2016-06-09 17:49:38 +02:00
|
|
|
|
end
|
|
|
|
|
|
2018-03-20 17:47:37 +01:00
|
|
|
|
def switch_types_de_champ(index_of_first_element)
|
2016-06-08 16:45:18 +02:00
|
|
|
|
switch_list_order(types_de_champ_ordered, index_of_first_element)
|
|
|
|
|
end
|
|
|
|
|
|
2018-03-20 17:47:37 +01:00
|
|
|
|
def switch_types_de_champ_private(index_of_first_element)
|
2016-08-03 18:19:56 +02:00
|
|
|
|
switch_list_order(types_de_champ_private_ordered, index_of_first_element)
|
|
|
|
|
end
|
|
|
|
|
|
2018-03-20 17:47:37 +01:00
|
|
|
|
def switch_types_de_piece_justificative(index_of_first_element)
|
2017-04-13 14:48:18 +02:00
|
|
|
|
switch_list_order(types_de_piece_justificative, index_of_first_element)
|
2016-06-08 16:45:18 +02:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def switch_list_order(list, index_of_first_element)
|
2017-05-26 21:43:44 +02:00
|
|
|
|
if index_of_first_element < 0 ||
|
|
|
|
|
index_of_first_element == list.count - 1 ||
|
|
|
|
|
list.count < 1
|
|
|
|
|
|
|
|
|
|
false
|
|
|
|
|
else
|
2018-03-02 16:27:03 +01:00
|
|
|
|
list[index_of_first_element].update(order_place: index_of_first_element + 1)
|
|
|
|
|
list[index_of_first_element + 1].update(order_place: index_of_first_element)
|
2017-05-26 21:43:44 +02:00
|
|
|
|
|
|
|
|
|
true
|
|
|
|
|
end
|
2015-11-19 11:37:01 +01:00
|
|
|
|
end
|
2015-12-21 14:40:28 +01:00
|
|
|
|
|
|
|
|
|
def locked?
|
2017-07-13 15:20:24 +02:00
|
|
|
|
publiee_ou_archivee?
|
2015-12-21 14:40:28 +01:00
|
|
|
|
end
|
2016-06-09 17:49:38 +02:00
|
|
|
|
|
2018-04-12 18:35:13 +02:00
|
|
|
|
def clone(admin, from_library)
|
2017-03-07 18:19:48 +01:00
|
|
|
|
procedure = self.deep_clone(include:
|
2017-06-26 17:18:47 +02:00
|
|
|
|
{
|
|
|
|
|
types_de_piece_justificative: nil,
|
|
|
|
|
module_api_carto: nil,
|
|
|
|
|
attestation_template: nil,
|
|
|
|
|
types_de_champ: :drop_down_list,
|
|
|
|
|
types_de_champ_private: :drop_down_list
|
|
|
|
|
})
|
2017-07-10 23:42:33 +02:00
|
|
|
|
procedure.archived_at = nil
|
2017-07-11 14:21:10 +02:00
|
|
|
|
procedure.published_at = nil
|
2016-09-02 17:10:55 +02:00
|
|
|
|
procedure.logo_secure_token = nil
|
|
|
|
|
procedure.remote_logo_url = self.logo_url
|
2017-03-07 18:19:48 +01:00
|
|
|
|
|
2018-01-08 14:44:15 +01:00
|
|
|
|
procedure.administrateur = admin
|
2017-05-27 01:08:01 +02:00
|
|
|
|
procedure.initiated_mail = initiated_mail.try(:dup)
|
|
|
|
|
procedure.received_mail = received_mail.try(:dup)
|
|
|
|
|
procedure.closed_mail = closed_mail.try(:dup)
|
|
|
|
|
procedure.refused_mail = refused_mail.try(:dup)
|
|
|
|
|
procedure.without_continuation_mail = without_continuation_mail.try(:dup)
|
2017-03-07 18:19:48 +01:00
|
|
|
|
|
2018-04-12 18:35:13 +02:00
|
|
|
|
procedure.cloned_from_library = from_library
|
|
|
|
|
|
2018-01-08 15:42:38 +01:00
|
|
|
|
procedure
|
2016-06-15 11:34:05 +02:00
|
|
|
|
end
|
|
|
|
|
|
2017-07-13 15:21:52 +02:00
|
|
|
|
def brouillon?
|
|
|
|
|
published_at.nil?
|
|
|
|
|
end
|
|
|
|
|
|
2016-07-12 15:20:10 +02:00
|
|
|
|
def publish!(path)
|
2018-03-02 16:27:03 +01:00
|
|
|
|
self.update!({ published_at: Time.now, archived_at: nil })
|
2016-06-24 16:41:44 +02:00
|
|
|
|
ProcedurePath.create!(path: path, procedure: self, administrateur: self.administrateur)
|
|
|
|
|
end
|
|
|
|
|
|
2017-07-13 15:14:28 +02:00
|
|
|
|
def publiee?
|
|
|
|
|
published_at.present? && archived_at.nil?
|
|
|
|
|
end
|
|
|
|
|
|
2016-06-24 16:41:44 +02:00
|
|
|
|
def archive
|
2018-03-02 16:27:03 +01:00
|
|
|
|
self.update!(archived_at: Time.now)
|
2017-07-10 23:42:33 +02:00
|
|
|
|
end
|
|
|
|
|
|
2017-07-13 15:09:25 +02:00
|
|
|
|
def archivee?
|
2017-07-13 15:20:24 +02:00
|
|
|
|
published_at.present? && archived_at.present?
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def publiee_ou_archivee?
|
|
|
|
|
publiee? || archivee?
|
2016-06-24 16:41:44 +02:00
|
|
|
|
end
|
|
|
|
|
|
2018-01-10 17:52:43 +01:00
|
|
|
|
def whitelisted?
|
|
|
|
|
whitelisted_at.present?
|
|
|
|
|
end
|
|
|
|
|
|
2016-07-22 15:06:30 +02:00
|
|
|
|
def total_dossier
|
2017-07-10 16:11:12 +02:00
|
|
|
|
self.dossiers.state_not_brouillon.size
|
2016-07-22 15:06:30 +02:00
|
|
|
|
end
|
2017-01-26 12:12:52 +01:00
|
|
|
|
|
2018-03-16 12:00:01 +01:00
|
|
|
|
def export_filename
|
|
|
|
|
procedure_identifier = procedure_path&.path || "procedure-#{id}"
|
|
|
|
|
"dossiers_#{procedure_identifier}_#{Time.now.strftime('%Y-%m-%d_%H-%M')}"
|
|
|
|
|
end
|
|
|
|
|
|
2017-04-05 11:34:16 +02:00
|
|
|
|
def generate_export
|
2017-12-01 12:24:41 +01:00
|
|
|
|
exportable_dossiers = dossiers.downloadable_sorted
|
2017-04-05 11:34:16 +02:00
|
|
|
|
|
|
|
|
|
headers = exportable_dossiers.any? ? exportable_dossiers.first.export_headers : []
|
2017-04-12 17:59:12 +02:00
|
|
|
|
data = exportable_dossiers.any? ? exportable_dossiers.map { |d| d.full_data_strings_array } : [[]]
|
2017-04-05 11:34:16 +02:00
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
headers: headers,
|
|
|
|
|
data: data
|
|
|
|
|
}
|
|
|
|
|
end
|
|
|
|
|
|
2017-06-27 18:00:05 +02:00
|
|
|
|
def procedure_overview(start_date)
|
|
|
|
|
ProcedureOverview.new(self, start_date)
|
2017-05-12 15:47:05 +02:00
|
|
|
|
end
|
2017-05-26 21:55:19 +02:00
|
|
|
|
|
2017-05-27 01:08:01 +02:00
|
|
|
|
def initiated_mail_template
|
2017-12-22 21:37:08 +01:00
|
|
|
|
initiated_mail || Mails::InitiatedMail.default_for_procedure(self)
|
2017-05-26 21:55:19 +02:00
|
|
|
|
end
|
|
|
|
|
|
2017-05-27 01:08:01 +02:00
|
|
|
|
def received_mail_template
|
2017-12-22 21:37:08 +01:00
|
|
|
|
received_mail || Mails::ReceivedMail.default_for_procedure(self)
|
2017-05-26 21:55:19 +02:00
|
|
|
|
end
|
|
|
|
|
|
2017-05-27 01:08:01 +02:00
|
|
|
|
def closed_mail_template
|
2017-12-22 21:37:08 +01:00
|
|
|
|
closed_mail || Mails::ClosedMail.default_for_procedure(self)
|
2017-05-26 21:55:19 +02:00
|
|
|
|
end
|
|
|
|
|
|
2017-05-27 01:08:01 +02:00
|
|
|
|
def refused_mail_template
|
2017-12-22 21:37:08 +01:00
|
|
|
|
refused_mail || Mails::RefusedMail.default_for_procedure(self)
|
2017-05-26 21:55:19 +02:00
|
|
|
|
end
|
|
|
|
|
|
2017-05-27 01:08:01 +02:00
|
|
|
|
def without_continuation_mail_template
|
2017-12-22 21:37:08 +01:00
|
|
|
|
without_continuation_mail || Mails::WithoutContinuationMail.default_for_procedure(self)
|
2017-05-26 21:55:19 +02:00
|
|
|
|
end
|
2017-10-02 17:03:38 +02:00
|
|
|
|
|
|
|
|
|
def fields
|
|
|
|
|
fields = [
|
|
|
|
|
field_hash('Créé le', 'self', 'created_at'),
|
|
|
|
|
field_hash('Mis à jour le', 'self', 'updated_at'),
|
|
|
|
|
field_hash('Demandeur', 'user', 'email')
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
fields << [
|
|
|
|
|
field_hash('Civilité (FC)', 'france_connect_information', 'gender'),
|
|
|
|
|
field_hash('Prénom (FC)', 'france_connect_information', 'given_name'),
|
|
|
|
|
field_hash('Nom (FC)', 'france_connect_information', 'family_name')
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
if !for_individual || (for_individual && individual_with_siret)
|
|
|
|
|
fields << [
|
|
|
|
|
field_hash('SIREN', 'entreprise', 'siren'),
|
|
|
|
|
field_hash('Forme juridique', 'entreprise', 'forme_juridique'),
|
|
|
|
|
field_hash('Nom commercial', 'entreprise', 'nom_commercial'),
|
|
|
|
|
field_hash('Raison sociale', 'entreprise', 'raison_sociale'),
|
|
|
|
|
field_hash('SIRET siège social', 'entreprise', 'siret_siege_social'),
|
|
|
|
|
field_hash('Date de création', 'entreprise', 'date_creation')
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
fields << [
|
|
|
|
|
field_hash('SIRET', 'etablissement', 'siret'),
|
2017-12-06 17:34:03 +01:00
|
|
|
|
field_hash('Libellé NAF', 'etablissement', 'libelle_naf'),
|
2017-10-02 17:03:38 +02:00
|
|
|
|
field_hash('Code postal', 'etablissement', 'code_postal')
|
|
|
|
|
]
|
|
|
|
|
end
|
|
|
|
|
|
2017-10-03 15:08:51 +02:00
|
|
|
|
types_de_champ
|
2018-01-15 22:10:46 +01:00
|
|
|
|
.reject { |tdc| ['header_section', 'explication'].include?(tdc.type_champ) }
|
2017-10-03 15:08:51 +02:00
|
|
|
|
.each do |type_de_champ|
|
|
|
|
|
|
2017-10-02 17:03:38 +02:00
|
|
|
|
fields << field_hash(type_de_champ.libelle, 'type_de_champ', type_de_champ.id.to_s)
|
|
|
|
|
end
|
|
|
|
|
|
2017-10-03 15:08:51 +02:00
|
|
|
|
types_de_champ_private
|
2018-01-15 22:10:46 +01:00
|
|
|
|
.reject { |tdc| ['header_section', 'explication'].include?(tdc.type_champ) }
|
2017-10-03 15:08:51 +02:00
|
|
|
|
.each do |type_de_champ|
|
|
|
|
|
|
2017-10-02 17:03:38 +02:00
|
|
|
|
fields << field_hash(type_de_champ.libelle, 'type_de_champ_private', type_de_champ.id.to_s)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
fields.flatten
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def fields_for_select
|
|
|
|
|
fields.map do |field|
|
|
|
|
|
[field['label'], "#{field['table']}/#{field['column']}"]
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2017-09-27 15:16:07 +02:00
|
|
|
|
def self.default_sort
|
|
|
|
|
{
|
|
|
|
|
'table' => 'self',
|
|
|
|
|
'column' => 'id',
|
|
|
|
|
'order' => 'desc'
|
|
|
|
|
}.to_json
|
|
|
|
|
end
|
|
|
|
|
|
2018-01-10 16:46:12 +01:00
|
|
|
|
def whitelist!
|
|
|
|
|
update_attribute('whitelisted_at', DateTime.now)
|
|
|
|
|
end
|
|
|
|
|
|
2018-04-03 11:33:11 +02:00
|
|
|
|
def closed_mail_template_attestation_inconsistency_state
|
|
|
|
|
# As an optimization, don’t check the predefined templates (they are presumed correct)
|
|
|
|
|
if closed_mail.present?
|
|
|
|
|
tag_present = closed_mail.body.include?("--lien attestation--")
|
|
|
|
|
if attestation_template&.activated? && !tag_present
|
|
|
|
|
:missing_tag
|
|
|
|
|
elsif !attestation_template&.activated? && tag_present
|
|
|
|
|
:extraneous_tag
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2017-10-02 17:03:38 +02:00
|
|
|
|
private
|
|
|
|
|
|
|
|
|
|
def field_hash(label, table, column)
|
|
|
|
|
{
|
|
|
|
|
'label' => label,
|
|
|
|
|
'table' => table,
|
|
|
|
|
'column' => column
|
|
|
|
|
}
|
|
|
|
|
end
|
2015-09-21 17:59:03 +02:00
|
|
|
|
end
|