2021-04-21 12:02:57 +02:00
class DossierProjectionService
2022-11-21 18:08:34 +01:00
class DossierProjection < Struct . new ( :dossier_id , :state , :archived , :hidden_by_user_at , :hidden_by_administration_at , :batch_operation_id , :columns )
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' }
2022-11-21 18:08:34 +01:00
( [ state_field , archived_field , hidden_by_user_at_field , hidden_by_administration_at_field , batch_operation_field ] + 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
)
2021-09-07 14:07:55 +02:00
. select ( :dossier_id , :value , :type_de_champ_id , :stable_id , :type , :external_id , :data ) # 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 |
2022-11-21 18:08:34 +01:00
if [ state_field , archived_field , hidden_by_user_at_field , hidden_by_administration_at_field , batch_operation_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
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
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 ] ,
2022-11-21 18:08:34 +01:00
batch_operation_field [ :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