2015-08-10 11:05:06 +02:00
|
|
|
class Dossier < ActiveRecord::Base
|
2016-11-07 17:23:58 +01:00
|
|
|
include SpreadsheetArchitect
|
2016-02-19 16:59:18 +01:00
|
|
|
|
2015-11-02 11:23:55 +01:00
|
|
|
enum state: {draft: 'draft',
|
2015-11-02 15:46:43 +01:00
|
|
|
initiated: 'initiated',
|
2016-08-11 15:27:35 +02:00
|
|
|
replied: 'replied', #action utilisateur demandé
|
2016-10-07 14:58:45 +02:00
|
|
|
updated: 'updated', #etude par l'administration en cours
|
2016-08-11 15:27:35 +02:00
|
|
|
received: 'received',
|
|
|
|
closed: 'closed',
|
|
|
|
refused: 'refused',
|
|
|
|
without_continuation: 'without_continuation'
|
|
|
|
}
|
2015-09-22 18:30:20 +02:00
|
|
|
|
2015-09-24 11:45:00 +02:00
|
|
|
has_one :etablissement, dependent: :destroy
|
|
|
|
has_one :entreprise, dependent: :destroy
|
2016-08-30 11:18:43 +02:00
|
|
|
has_one :individual, dependent: :destroy
|
2016-03-16 15:34:35 +01:00
|
|
|
has_many :cerfa, dependent: :destroy
|
2016-01-18 16:20:51 +01:00
|
|
|
|
2015-09-24 11:45:00 +02:00
|
|
|
has_many :pieces_justificatives, dependent: :destroy
|
2016-08-08 12:52:30 +02:00
|
|
|
has_many :champs, class_name: 'ChampPublic', dependent: :destroy
|
|
|
|
has_many :champs_private, class_name: 'ChampPrivate', dependent: :destroy
|
2015-11-24 10:02:55 +01:00
|
|
|
has_many :quartier_prioritaires, dependent: :destroy
|
2016-01-18 12:03:18 +01:00
|
|
|
has_many :cadastres, dependent: :destroy
|
2016-01-18 16:20:51 +01:00
|
|
|
has_many :commentaires, dependent: :destroy
|
2016-02-08 18:16:18 +01:00
|
|
|
has_many :invites, dependent: :destroy
|
2016-09-14 16:36:01 +02:00
|
|
|
has_many :invites_user, class_name: 'InviteUser', dependent: :destroy
|
2016-07-18 18:24:29 +02:00
|
|
|
has_many :follows
|
2016-12-21 17:26:31 +01:00
|
|
|
has_many :notifications, dependent: :destroy
|
2016-01-18 16:20:51 +01:00
|
|
|
|
2015-09-21 17:59:03 +02:00
|
|
|
belongs_to :procedure
|
2015-09-23 12:16:21 +02:00
|
|
|
belongs_to :user
|
2015-08-12 10:09:52 +02:00
|
|
|
|
2016-08-30 11:18:43 +02:00
|
|
|
accepts_nested_attributes_for :individual
|
|
|
|
|
2015-08-13 15:55:19 +02:00
|
|
|
delegate :siren, to: :entreprise
|
2015-12-03 12:00:22 +01:00
|
|
|
delegate :siret, to: :etablissement, allow_nil: true
|
2015-09-21 17:59:03 +02:00
|
|
|
delegate :types_de_piece_justificative, to: :procedure
|
2015-11-05 11:21:44 +01:00
|
|
|
delegate :types_de_champ, to: :procedure
|
2016-08-01 18:10:32 +02:00
|
|
|
delegate :france_connect_information, to: :user
|
2015-08-13 15:55:19 +02:00
|
|
|
|
2017-03-01 09:51:55 +01:00
|
|
|
before_validation :update_state_dates, if: -> { state_changed? }
|
|
|
|
|
2015-11-03 15:27:49 +01:00
|
|
|
after_save :build_default_champs, if: Proc.new { procedure_id_changed? }
|
2016-08-30 11:18:43 +02:00
|
|
|
after_save :build_default_individual, if: Proc.new { procedure.for_individual? }
|
2015-08-24 15:23:07 +02:00
|
|
|
|
2015-09-24 11:17:17 +02:00
|
|
|
validates :user, presence: true
|
2015-08-21 11:37:13 +02:00
|
|
|
|
2016-10-05 16:45:51 +02:00
|
|
|
BROUILLON = %w(draft)
|
2016-08-11 15:27:35 +02:00
|
|
|
NOUVEAUX = %w(initiated)
|
2016-11-10 15:57:14 +01:00
|
|
|
OUVERT = %w(updated replied)
|
2016-08-11 15:27:35 +02:00
|
|
|
WAITING_FOR_GESTIONNAIRE = %w(updated)
|
2017-02-23 17:54:11 +01:00
|
|
|
WAITING_FOR_USER = %w(replied)
|
2016-10-19 17:25:24 +02:00
|
|
|
EN_CONSTRUCTION = %w(initiated updated replied)
|
2017-02-23 17:54:11 +01:00
|
|
|
EN_INSTRUCTION = %w(received)
|
2016-08-11 15:27:35 +02:00
|
|
|
A_INSTRUIRE = %w(received)
|
|
|
|
TERMINE = %w(closed refused without_continuation)
|
2017-02-23 17:54:11 +01:00
|
|
|
ALL_STATE = %w(initiated updated replied received closed refused without_continuation)
|
2015-11-19 18:04:09 +01:00
|
|
|
|
2017-01-02 16:45:03 +01:00
|
|
|
def unreaded_notifications
|
|
|
|
@unreaded_notif ||= notifications.where(already_read: false)
|
|
|
|
end
|
|
|
|
|
|
|
|
def first_unread_notification
|
|
|
|
unreaded_notifications.order("created_at ASC").first
|
|
|
|
end
|
|
|
|
|
2016-03-17 14:50:10 +01:00
|
|
|
def retrieve_last_piece_justificative_by_type(type)
|
2015-09-24 18:12:08 +02:00
|
|
|
pieces_justificatives.where(type_de_piece_justificative_id: type).last
|
|
|
|
end
|
|
|
|
|
2016-03-17 14:50:10 +01:00
|
|
|
def retrieve_all_piece_justificative_by_type(type)
|
2016-03-22 17:36:36 +01:00
|
|
|
pieces_justificatives.where(type_de_piece_justificative_id: type).order(created_at: :DESC)
|
2015-09-24 18:12:08 +02:00
|
|
|
end
|
|
|
|
|
2015-11-03 15:27:49 +01:00
|
|
|
def build_default_champs
|
2015-11-05 11:21:44 +01:00
|
|
|
procedure.types_de_champ.each do |type_de_champ|
|
2016-08-08 12:52:30 +02:00
|
|
|
ChampPublic.create(type_de_champ_id: type_de_champ.id, dossier_id: id)
|
|
|
|
end
|
|
|
|
|
|
|
|
procedure.types_de_champ_private.each do |type_de_champ|
|
|
|
|
ChampPrivate.create(type_de_champ_id: type_de_champ.id, dossier_id: id)
|
2015-11-03 15:27:49 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-08-30 11:18:43 +02:00
|
|
|
def build_default_individual
|
2016-12-21 15:39:41 +01:00
|
|
|
if Individual.where(dossier_id: self.id).count == 0
|
|
|
|
Individual.create(dossier: self)
|
|
|
|
end
|
2016-08-30 11:18:43 +02:00
|
|
|
end
|
|
|
|
|
2015-11-04 11:14:07 +01:00
|
|
|
def ordered_champs
|
2016-06-21 12:41:28 +02:00
|
|
|
champs.joins(', types_de_champ').where("champs.type_de_champ_id = types_de_champ.id AND types_de_champ.procedure_id = #{procedure.id}").order('order_place')
|
2016-08-08 12:52:30 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
def ordered_champs_private
|
|
|
|
champs_private.joins(', types_de_champ').where("champs.type_de_champ_id = types_de_champ.id AND types_de_champ.procedure_id = #{procedure.id}").order('order_place')
|
2015-11-04 11:14:07 +01:00
|
|
|
end
|
|
|
|
|
2016-10-07 15:16:03 +02:00
|
|
|
def ordered_pieces_justificatives
|
|
|
|
champs.joins(', types_de_piece_justificative').where("pieces_justificatives.type_de_piece_justificative_id = types_de_piece_justificative.id AND types_de_piece_justificative.procedure_id = #{procedure.id}").order('order_place ASC')
|
|
|
|
end
|
|
|
|
|
2015-11-04 11:14:07 +01:00
|
|
|
def ordered_commentaires
|
|
|
|
commentaires.order(created_at: :desc)
|
|
|
|
end
|
|
|
|
|
2015-09-24 18:12:08 +02:00
|
|
|
def next_step! role, action
|
2017-02-23 17:54:11 +01:00
|
|
|
unless %w(initiate follow update comment receive refuse without_continuation close).include?(action)
|
2015-09-24 18:12:08 +02:00
|
|
|
fail 'action is not valid'
|
|
|
|
end
|
|
|
|
|
2015-10-05 16:42:29 +02:00
|
|
|
unless %w(user gestionnaire).include?(role)
|
2015-09-24 18:12:08 +02:00
|
|
|
fail 'role is not valid'
|
|
|
|
end
|
|
|
|
|
|
|
|
if role == 'user'
|
|
|
|
case action
|
2015-11-02 15:31:15 +01:00
|
|
|
when 'initiate'
|
2015-09-24 18:12:08 +02:00
|
|
|
if draft?
|
2015-11-02 15:31:15 +01:00
|
|
|
initiated!
|
2015-09-24 18:12:08 +02:00
|
|
|
end
|
|
|
|
when 'update'
|
2015-11-02 11:33:00 +01:00
|
|
|
if replied?
|
2015-09-24 18:12:08 +02:00
|
|
|
updated!
|
|
|
|
end
|
|
|
|
when 'comment'
|
2015-11-02 11:33:00 +01:00
|
|
|
if replied?
|
2015-09-24 18:12:08 +02:00
|
|
|
updated!
|
|
|
|
end
|
|
|
|
end
|
|
|
|
elsif role == 'gestionnaire'
|
|
|
|
case action
|
|
|
|
when 'comment'
|
|
|
|
if updated?
|
2015-11-02 11:33:00 +01:00
|
|
|
replied!
|
2015-11-02 15:31:15 +01:00
|
|
|
elsif initiated?
|
2015-11-02 11:33:00 +01:00
|
|
|
replied!
|
2015-09-24 18:12:08 +02:00
|
|
|
end
|
2016-09-09 15:55:03 +02:00
|
|
|
when 'follow'
|
|
|
|
if initiated?
|
|
|
|
updated!
|
|
|
|
end
|
2016-08-25 15:21:25 +02:00
|
|
|
when 'close'
|
|
|
|
if received?
|
2015-11-02 15:00:28 +01:00
|
|
|
closed!
|
2015-09-24 18:12:08 +02:00
|
|
|
end
|
2016-08-25 17:46:26 +02:00
|
|
|
when 'refuse'
|
|
|
|
if received?
|
|
|
|
refused!
|
|
|
|
end
|
|
|
|
when 'without_continuation'
|
|
|
|
if received?
|
|
|
|
without_continuation!
|
|
|
|
end
|
2015-09-24 18:12:08 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
state
|
|
|
|
end
|
|
|
|
|
2016-10-05 16:45:51 +02:00
|
|
|
def brouillon?
|
|
|
|
BROUILLON.include?(state)
|
|
|
|
end
|
|
|
|
|
2016-10-24 16:00:03 +02:00
|
|
|
def self.all_state order = 'ASC'
|
|
|
|
where(state: ALL_STATE, archived: false).order("updated_at #{order}")
|
|
|
|
end
|
|
|
|
|
2016-10-05 16:45:51 +02:00
|
|
|
def self.brouillon order = 'ASC'
|
|
|
|
where(state: BROUILLON, archived: false).order("updated_at #{order}")
|
|
|
|
end
|
|
|
|
|
2016-08-11 15:27:35 +02:00
|
|
|
def self.nouveaux order = 'ASC'
|
|
|
|
where(state: NOUVEAUX, archived: false).order("updated_at #{order}")
|
|
|
|
end
|
|
|
|
|
2015-11-30 15:56:06 +01:00
|
|
|
def self.waiting_for_gestionnaire order = 'ASC'
|
|
|
|
where(state: WAITING_FOR_GESTIONNAIRE, archived: false).order("updated_at #{order}")
|
2015-09-24 18:12:08 +02:00
|
|
|
end
|
|
|
|
|
2015-11-30 15:56:06 +01:00
|
|
|
def self.waiting_for_user order = 'ASC'
|
|
|
|
where(state: WAITING_FOR_USER, archived: false).order("updated_at #{order}")
|
2015-09-24 18:12:08 +02:00
|
|
|
end
|
|
|
|
|
2016-10-19 17:25:24 +02:00
|
|
|
def self.en_construction order = 'ASC'
|
|
|
|
where(state: EN_CONSTRUCTION, archived: false).order("updated_at #{order}")
|
2016-08-22 16:10:48 +02:00
|
|
|
end
|
|
|
|
|
2016-11-10 15:57:14 +01:00
|
|
|
def self.ouvert order = 'ASC'
|
|
|
|
where(state: OUVERT, archived: false).order("updated_at #{order}")
|
|
|
|
end
|
|
|
|
|
2016-08-11 15:27:35 +02:00
|
|
|
def self.a_instruire order = 'ASC'
|
|
|
|
where(state: A_INSTRUIRE, archived: false).order("updated_at #{order}")
|
|
|
|
end
|
|
|
|
|
2016-08-12 13:56:10 +02:00
|
|
|
def self.en_instruction order = 'ASC'
|
|
|
|
where(state: EN_INSTRUCTION, archived: false).order("updated_at #{order}")
|
|
|
|
end
|
|
|
|
|
2015-11-30 15:56:06 +01:00
|
|
|
def self.termine order = 'ASC'
|
|
|
|
where(state: TERMINE, archived: false).order("updated_at #{order}")
|
2015-09-24 18:12:08 +02:00
|
|
|
end
|
|
|
|
|
2016-02-02 18:37:38 +01:00
|
|
|
def cerfa_available?
|
2016-03-16 15:34:35 +01:00
|
|
|
procedure.cerfa_flag? && cerfa.size != 0
|
2016-02-02 18:37:38 +01:00
|
|
|
end
|
|
|
|
|
2016-11-14 17:43:34 +01:00
|
|
|
def convert_specific_hash_values_to_string(hash_to_convert)
|
2016-11-08 11:48:36 +01:00
|
|
|
hash = {}
|
|
|
|
hash_to_convert.each do |key, value|
|
2016-11-14 17:25:17 +01:00
|
|
|
value = value.to_s if !value.kind_of?(Time) && !value.nil?
|
|
|
|
hash.store(key, value)
|
2016-11-08 11:48:36 +01:00
|
|
|
end
|
|
|
|
return hash
|
|
|
|
end
|
|
|
|
|
2016-11-14 17:43:34 +01:00
|
|
|
def convert_specific_array_values_to_string(array_to_convert)
|
|
|
|
array = []
|
|
|
|
array_to_convert.each do |value|
|
|
|
|
value = value.to_s if !value.kind_of?(Time) && !value.nil?
|
|
|
|
array << value
|
|
|
|
end
|
|
|
|
return array
|
|
|
|
end
|
|
|
|
|
2016-11-09 15:36:18 +01:00
|
|
|
def export_entreprise_data
|
2016-10-07 15:34:10 +02:00
|
|
|
unless entreprise.nil?
|
2016-11-07 17:23:58 +01:00
|
|
|
etablissement_attr = EtablissementCsvSerializer.new(self.etablissement).attributes.map { |k, v| ["etablissement.#{k}".parameterize.underscore.to_sym, v] }.to_h
|
|
|
|
entreprise_attr = EntrepriseSerializer.new(self.entreprise).attributes.map { |k, v| ["entreprise.#{k}".parameterize.underscore.to_sym, v] }.to_h
|
|
|
|
else
|
|
|
|
etablissement_attr = EtablissementSerializer.new(Etablissement.new).attributes.map { |k, v| ["etablissement.#{k}".parameterize.underscore.to_sym, v] }.to_h
|
|
|
|
entreprise_attr = EntrepriseSerializer.new(Entreprise.new).attributes.map { |k, v| ["entreprise.#{k}".parameterize.underscore.to_sym, v] }.to_h
|
2016-10-07 15:34:10 +02:00
|
|
|
end
|
2016-11-14 17:43:34 +01:00
|
|
|
return convert_specific_hash_values_to_string(etablissement_attr.merge(entreprise_attr))
|
2016-11-09 15:36:18 +01:00
|
|
|
end
|
2016-10-07 15:34:10 +02:00
|
|
|
|
2016-11-09 15:36:18 +01:00
|
|
|
def export_default_columns
|
|
|
|
dossier_attr = DossierSerializer.new(self).attributes
|
2016-11-14 17:43:34 +01:00
|
|
|
dossier_attr = convert_specific_hash_values_to_string(dossier_attr)
|
2016-11-09 15:36:18 +01:00
|
|
|
dossier_attr = dossier_attr.merge(self.export_entreprise_data)
|
|
|
|
return dossier_attr
|
2016-02-19 16:59:18 +01:00
|
|
|
end
|
2016-06-20 13:57:57 +02:00
|
|
|
|
2016-11-07 17:23:58 +01:00
|
|
|
def spreadsheet_columns
|
2016-11-09 09:19:57 +01:00
|
|
|
self.export_default_columns.to_a
|
|
|
|
end
|
|
|
|
|
2016-11-14 10:41:56 +01:00
|
|
|
def data_with_champs
|
2016-11-14 16:37:58 +01:00
|
|
|
serialized_dossier = DossierProcedureSerializer.new(self)
|
|
|
|
data = serialized_dossier.attributes.values
|
|
|
|
data += self.champs.order('type_de_champ_id ASC').map(&:value)
|
|
|
|
data += self.export_entreprise_data.values
|
|
|
|
return data
|
|
|
|
end
|
|
|
|
|
|
|
|
def export_headers
|
|
|
|
serialized_dossier = DossierProcedureSerializer.new(self)
|
|
|
|
headers = serialized_dossier.attributes.keys
|
|
|
|
headers += self.procedure.types_de_champ.order('id ASC').map { |types_de_champ| types_de_champ.libelle.parameterize.underscore.to_sym }
|
|
|
|
headers += self.export_entreprise_data.keys
|
|
|
|
return headers
|
2016-11-14 10:41:56 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
def self.export_full_generation(dossiers, format)
|
2017-01-03 15:50:44 +01:00
|
|
|
if dossiers && !dossiers.empty?
|
|
|
|
data = []
|
|
|
|
headers = dossiers.first.export_headers
|
|
|
|
dossiers.each do |dossier|
|
|
|
|
data << dossier.convert_specific_array_values_to_string(dossier.data_with_champs)
|
|
|
|
end
|
|
|
|
if ["csv"].include?(format)
|
|
|
|
return SpreadsheetArchitect.to_csv(data: data, headers: headers)
|
|
|
|
elsif ["xlsx"].include?(format)
|
|
|
|
return SpreadsheetArchitect.to_xlsx(data: data, headers: headers)
|
|
|
|
elsif ["ods"].include?(format)
|
|
|
|
return SpreadsheetArchitect.to_ods(data: data, headers: headers)
|
|
|
|
end
|
2016-11-09 09:19:57 +01:00
|
|
|
end
|
2016-11-07 17:23:58 +01:00
|
|
|
end
|
|
|
|
|
2017-01-26 17:54:04 +01:00
|
|
|
def followers_gestionnaires_emails
|
|
|
|
follows.includes(:gestionnaire).map { |f| f.gestionnaire }.pluck(:email).join(' ')
|
|
|
|
end
|
|
|
|
|
2016-06-20 13:57:57 +02:00
|
|
|
def reset!
|
2016-10-05 14:28:10 +02:00
|
|
|
etablissement.destroy
|
2016-10-05 15:01:31 +02:00
|
|
|
entreprise.destroy
|
2016-06-20 13:57:57 +02:00
|
|
|
|
|
|
|
update_attributes(autorisation_donnees: false)
|
|
|
|
end
|
2016-07-19 16:44:26 +02:00
|
|
|
|
|
|
|
def total_follow
|
|
|
|
follows.size
|
|
|
|
end
|
2016-07-22 15:06:30 +02:00
|
|
|
|
2016-09-13 12:17:56 +02:00
|
|
|
def read_only?
|
2017-02-21 18:05:48 +01:00
|
|
|
received? || closed? || refused? || without_continuation?
|
2016-09-13 12:17:56 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
def owner? email
|
|
|
|
user.email == email
|
|
|
|
end
|
2016-09-14 16:36:01 +02:00
|
|
|
|
|
|
|
def invite_by_user? email
|
|
|
|
(invites_user.pluck :email).include? email
|
|
|
|
end
|
2017-03-01 09:51:55 +01:00
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def update_state_dates
|
|
|
|
if initiated? && !self.initiated_at
|
|
|
|
self.initiated_at = DateTime.now
|
|
|
|
elsif received? && !self.received_at
|
|
|
|
self.received_at = DateTime.now
|
|
|
|
elsif TERMINE.include?(state)
|
|
|
|
self.processed_at = DateTime.now
|
|
|
|
end
|
|
|
|
end
|
2015-08-10 11:05:06 +02:00
|
|
|
end
|