2021-04-21 12:02:57 +02:00
class DossierProjectionService
2023-12-11 17:06:12 +01:00
class DossierProjection < Struct . new ( :dossier_id , :state , :archived , :hidden_by_user_at , :hidden_by_administration_at , :for_tiers , :prenom , :nom , :batch_operation_id , :sva_svr_decision_on , :corrections , :columns ) do
2023-03-27 16:23:11 +02:00
def pending_correction?
2023-04-03 17:05:54 +02:00
return false if corrections . blank?
2023-03-27 16:23:11 +02:00
2023-04-03 17:05:54 +02:00
corrections . any? { _1 [ :resolved_at ] . nil? }
2023-03-27 16:23:11 +02:00
end
2024-01-24 17:01:59 +01:00
def resolved_corrections?
return false if corrections . blank?
corrections . all? { _1 [ :resolved_at ] . present? }
end
2023-03-27 16:23:11 +02:00
end
2021-04-21 12:02:57 +02:00
end
TABLE = 'table'
COLUMN = 'column'
# Returns [DossierProjection(dossier, columns)] ordered by dossiers_ids
# and the columns orderd by fields.
#
# It tries to be fast by using `pluck` (or at least `select`)
# to avoid deserializing entire records.
#
# It stores its intermediary queries results in an hash in the corresponding field.
# ex: field_email[:id_value_h] = { dossier_id_1: email_1, dossier_id_3: email_3 }
#
# Those hashes are needed because:
# - the order of the intermediary query results are unknown
# - some values can be missing (if a revision added or removed them)
def self . project ( dossiers_ids , fields )
2021-04-26 10:35:22 +02:00
state_field = { TABLE = > 'self' , COLUMN = > 'state' }
archived_field = { TABLE = > 'self' , COLUMN = > 'archived' }
2022-11-21 18:08:34 +01:00
batch_operation_field = { TABLE = > 'self' , COLUMN = > 'batch_operation_id' }
2021-11-24 10:35:19 +01:00
hidden_by_user_at_field = { TABLE = > 'self' , COLUMN = > 'hidden_by_user_at' }
2022-02-02 19:34:00 +01:00
hidden_by_administration_at_field = { TABLE = > 'self' , COLUMN = > 'hidden_by_administration_at' }
2023-12-11 17:06:12 +01:00
for_tiers_field = { TABLE = > 'self' , COLUMN = > 'for_tiers' }
individual_first_name = { TABLE = > 'individual' , COLUMN = > 'prenom' }
individual_last_name = { TABLE = > 'individual' , COLUMN = > 'nom' }
2023-06-07 17:25:41 +02:00
sva_svr_decision_on_field = { TABLE = > 'self' , COLUMN = > 'sva_svr_decision_on' }
2023-04-03 17:05:54 +02:00
dossier_corrections = { TABLE = > 'dossier_corrections' , COLUMN = > 'resolved_at' }
2023-12-11 17:06:12 +01:00
( [ state_field , archived_field , sva_svr_decision_on_field , hidden_by_user_at_field , hidden_by_administration_at_field , for_tiers_field , individual_first_name , individual_last_name , batch_operation_field , dossier_corrections ] + fields ) # the view needs state and archived dossier attributes
2021-04-22 22:27:38 +02:00
. each { | f | f [ :id_value_h ] = { } }
. group_by { | f | f [ TABLE ] } # one query per table
. each do | table , fields |
case table
when 'type_de_champ' , 'type_de_champ_private'
Champ
. includes ( :type_de_champ )
. where (
types_de_champ : { stable_id : fields . map { | f | f [ COLUMN ] } } ,
dossier_id : dossiers_ids
)
2023-04-03 16:05:18 +02:00
. select ( :dossier_id , :value , :type_de_champ_id , :stable_id , :type , :external_id , :data , :value_json ) # we cannot pluck :value, as we need the champ.to_s method
2021-04-22 22:27:38 +02:00
. group_by ( & :stable_id ) # the champs are redispatched to their respective fields
. map do | stable_id , champs |
field = fields . find { | f | f [ COLUMN ] == stable_id . to_s }
field [ :id_value_h ] = champs . to_h { | c | [ c . dossier_id , c . to_s ] }
end
2021-04-21 12:02:57 +02:00
when 'self'
Dossier
. where ( id : dossiers_ids )
2021-04-22 22:27:38 +02:00
. pluck ( :id , * fields . map { | f | f [ COLUMN ] . to_sym } )
2021-04-26 10:35:22 +02:00
. each do | id , * columns |
fields . zip ( columns ) . each do | field , value |
2023-12-11 17:06:12 +01:00
if [ state_field , archived_field , hidden_by_user_at_field , hidden_by_administration_at_field , for_tiers_field , batch_operation_field , sva_svr_decision_on_field ] . include? ( field )
2021-04-26 10:35:22 +02:00
field [ :id_value_h ] [ id ] = value
else
field [ :id_value_h ] [ id ] = value & . strftime ( '%d/%m/%Y' ) # other fields are datetime
end
end
end
2021-04-21 12:02:57 +02:00
when 'individual'
Individual
. where ( dossier_id : dossiers_ids )
2021-04-22 22:27:38 +02:00
. pluck ( :dossier_id , * fields . map { | f | f [ COLUMN ] . to_sym } )
. each { | id , * columns | fields . zip ( columns ) . each { | field , value | field [ :id_value_h ] [ id ] = value } }
2021-04-21 12:02:57 +02:00
when 'etablissement'
Etablissement
. where ( dossier_id : dossiers_ids )
2021-04-22 22:27:38 +02:00
. pluck ( :dossier_id , * fields . map { | f | f [ COLUMN ] . to_sym } )
. each { | id , * columns | fields . zip ( columns ) . each { | field , value | field [ :id_value_h ] [ id ] = value } }
when 'user'
fields [ 0 ] [ :id_value_h ] = Dossier # there is only one field available for user table
. joins ( :user )
. where ( id : dossiers_ids )
. pluck ( 'dossiers.id, users.email' )
2021-04-21 12:02:57 +02:00
. to_h
when 'groupe_instructeur'
2021-04-22 22:27:38 +02:00
fields [ 0 ] [ :id_value_h ] = Dossier
2021-04-21 12:02:57 +02:00
. joins ( :groupe_instructeur )
. where ( id : dossiers_ids )
. pluck ( 'dossiers.id, groupe_instructeurs.label' )
. to_h
2023-04-03 17:05:54 +02:00
when 'dossier_corrections'
2023-03-27 16:23:11 +02:00
columns = fields . map { _1 [ COLUMN ] . to_sym }
2023-04-03 17:05:54 +02:00
id_value_h = DossierCorrection . where ( dossier_id : dossiers_ids )
2023-03-27 16:23:11 +02:00
. pluck ( :dossier_id , * columns )
2023-04-03 17:05:54 +02:00
. group_by ( & :first ) # group corrections by dossier_id
. transform_values do | values | # build each correction has an hash column => value
2023-03-27 16:23:11 +02:00
values . map { Hash [ columns . zip ( _1 [ 1 .. - 1 ] ) ] }
end
fields [ 0 ] [ :id_value_h ] = id_value_h
2021-04-29 09:33:04 +02:00
when 'procedure'
Dossier
. joins ( :procedure )
. where ( id : dossiers_ids )
. pluck ( :id , * fields . map { | f | f [ COLUMN ] . to_sym } )
. each { | id , * columns | fields . zip ( columns ) . each { | field , value | field [ :id_value_h ] [ id ] = value } }
2021-04-21 12:02:57 +02:00
when 'followers_instructeurs'
2021-06-10 15:24:15 +02:00
# rubocop:disable Style/HashTransformValues
2021-04-22 22:27:38 +02:00
fields [ 0 ] [ :id_value_h ] = Follow
2021-04-21 12:02:57 +02:00
. active
. joins ( instructeur : :user )
. where ( dossier_id : dossiers_ids )
. pluck ( 'dossier_id, users.email' )
. group_by { | dossier_id , _ | dossier_id }
2021-05-04 15:41:38 +02:00
. to_h { | dossier_id , dossier_id_emails | [ dossier_id , dossier_id_emails . sort . map { | _ , email | email } & . join ( ', ' ) ] }
2021-06-10 15:24:15 +02:00
# rubocop:enable Style/HashTransformValues
2023-04-20 11:44:35 +02:00
when 'avis'
# rubocop:disable Style/HashTransformValues
fields [ 0 ] [ :id_value_h ] = Avis
. where ( dossier_id : dossiers_ids )
. pluck ( 'dossier_id' , 'question_answer' )
. group_by { | dossier_id , _ | dossier_id }
2023-04-25 14:24:37 +02:00
. to_h { | dossier_id , question_answer | [ dossier_id , question_answer . map { | _ , answer | answer } & . compact & . tally & . map { | k , v | I18n . t ( " helpers.label.question_answer_with_count. #{ k } " , count : v ) } & . join ( ' / ' ) ] }
2023-04-20 11:44:35 +02:00
# rubocop:enable Style/HashTransformValues
2021-04-21 12:02:57 +02:00
end
end
2021-04-26 10:35:22 +02:00
dossiers_ids . map do | dossier_id |
DossierProjection . new (
dossier_id ,
state_field [ :id_value_h ] [ dossier_id ] ,
archived_field [ :id_value_h ] [ dossier_id ] ,
2021-11-24 10:35:19 +01:00
hidden_by_user_at_field [ :id_value_h ] [ dossier_id ] ,
2022-02-02 19:34:00 +01:00
hidden_by_administration_at_field [ :id_value_h ] [ dossier_id ] ,
2023-12-11 17:06:12 +01:00
for_tiers_field [ :id_value_h ] [ dossier_id ] ,
individual_first_name [ :id_value_h ] [ dossier_id ] ,
individual_last_name [ :id_value_h ] [ dossier_id ] ,
2022-11-21 18:08:34 +01:00
batch_operation_field [ :id_value_h ] [ dossier_id ] ,
2023-06-07 17:25:41 +02:00
sva_svr_decision_on_field [ :id_value_h ] [ dossier_id ] ,
2023-04-03 17:05:54 +02:00
dossier_corrections [ :id_value_h ] [ dossier_id ] ,
2021-04-26 10:35:22 +02:00
fields . map { | f | f [ :id_value_h ] [ dossier_id ] }
)
2021-04-21 12:02:57 +02:00
end
end
end