2019-08-06 11:02:54 +02:00
class Instructeur < ApplicationRecord
2019-09-17 10:16:52 +02:00
self . ignored_columns = [ 'features' , 'encrypted_password' , 'reset_password_token' , 'reset_password_sent_at' , 'remember_created_at' , 'sign_in_count' , 'current_sign_in_at' , 'last_sign_in_at' , 'current_sign_in_ip' , 'last_sign_in_ip' , 'failed_attempts' , 'unlock_token' , 'locked_at' ]
2018-03-14 17:25:43 +01:00
include EmailSanitizableConcern
2016-05-20 15:39:17 +02:00
has_and_belongs_to_many :administrateurs
2015-11-16 18:08:19 +01:00
2018-03-14 17:25:43 +01:00
before_validation - > { sanitize_email ( :email ) }
2016-06-20 17:37:04 +02:00
has_many :assign_to , dependent : :destroy
2019-08-20 16:47:41 +02:00
has_many :groupe_instructeurs , through : :assign_to
2019-09-18 11:46:28 +02:00
has_many :procedures , - > { distinct } , through : :groupe_instructeurs
2019-03-18 14:43:05 +01:00
2019-08-06 11:02:54 +02:00
has_many :assign_to_with_email_notifications , - > { with_email_notifications } , class_name : 'AssignTo' , inverse_of : :instructeur
2019-08-22 17:58:31 +02:00
has_many :groupe_instructeur_with_email_notifications , through : :assign_to_with_email_notifications , source : :groupe_instructeur
2019-03-18 14:43:05 +01:00
2019-08-22 17:58:31 +02:00
has_many :dossiers , - > { state_not_brouillon } , through : :groupe_instructeurs
2019-08-06 11:02:54 +02:00
has_many :follows , - > { active } , inverse_of : :instructeur
has_many :previous_follows , - > { inactive } , class_name : 'Follow' , inverse_of : :instructeur
2018-01-23 18:23:07 +01:00
has_many :followed_dossiers , through : :follows , source : :dossier
2019-06-07 14:59:49 +02:00
has_many :previously_followed_dossiers , - > { distinct } , through : :previous_follows , source : :dossier
2017-04-25 12:09:11 +02:00
has_many :avis
2018-01-16 09:23:20 +01:00
has_many :dossiers_from_avis , through : :avis , source : :dossier
2019-02-01 18:11:55 +01:00
has_many :trusted_device_tokens
2016-03-14 16:49:12 +01:00
2019-08-08 16:49:40 +02:00
has_one :user
2017-07-17 11:28:14 +02:00
def follow ( dossier )
2019-04-09 11:00:13 +02:00
begin
followed_dossiers << dossier
2019-06-07 14:59:14 +02:00
# If the user tries to follow a dossier she already follows,
# we just fail silently: it means the goal is already reached.
2019-04-09 11:00:13 +02:00
rescue ActiveRecord :: RecordNotUnique
2019-06-07 14:59:14 +02:00
# Database uniqueness constraint
rescue ActiveRecord :: RecordInvalid = > e
# ActiveRecord validation
2019-08-06 11:02:54 +02:00
raise unless e . record . errors . details . dig ( :instructeur_id , 0 , :error ) == :taken
2019-04-09 11:00:13 +02:00
end
2017-07-17 11:28:14 +02:00
end
2017-10-05 14:10:49 +02:00
def unfollow ( dossier )
2019-06-07 14:59:49 +02:00
f = follows . find_by ( dossier : dossier )
if f . present?
f . update ( unfollowed_at : Time . zone . now )
end
2017-10-05 14:10:49 +02:00
end
2017-07-17 13:13:20 +02:00
def follow? ( dossier )
followed_dossiers . include? ( dossier )
2016-07-18 18:24:29 +02:00
end
2016-08-02 14:49:41 +02:00
2018-02-19 11:20:57 +01:00
def assign_to_procedure ( procedure )
2018-02-20 11:24:32 +01:00
begin
2019-08-20 16:59:45 +02:00
assign_to . create ( {
procedure : procedure ,
groupe_instructeur : procedure . defaut_groupe_instructeur
} )
2018-02-20 11:24:32 +01:00
true
rescue ActiveRecord :: RecordNotUnique
false
end
2018-02-19 11:20:57 +01:00
end
def remove_from_procedure ( procedure )
2019-08-20 18:03:33 +02:00
! ! ( procedure . defaut_groupe_instructeur . in? ( groupe_instructeurs ) && groupe_instructeurs . destroy ( procedure . defaut_groupe_instructeur ) )
2018-02-19 11:20:57 +01:00
end
2017-05-12 16:47:18 +02:00
def last_week_overview
2018-10-25 15:07:15 +02:00
start_date = Time . zone . now . beginning_of_week
2017-05-12 16:47:18 +02:00
active_procedure_overviews = procedures
2018-01-15 19:34:08 +01:00
. publiees
. map { | procedure | procedure . procedure_overview ( start_date ) }
2019-09-12 11:26:22 +02:00
. filter ( & :had_some_activities? )
2017-05-12 16:47:18 +02:00
2017-06-27 18:00:05 +02:00
if active_procedure_overviews . count == 0
2017-05-12 16:47:18 +02:00
nil
else
{
start_date : start_date ,
2018-10-01 14:06:08 +02:00
procedure_overviews : active_procedure_overviews
2017-05-12 16:47:18 +02:00
}
end
end
2018-10-23 11:39:54 +02:00
def procedure_presentation_and_errors_for_procedure_id ( procedure_id )
2019-08-26 16:17:25 +02:00
assign_to . joins ( :groupe_instructeur ) . find_by ( groupe_instructeurs : { procedure_id : procedure_id } ) . procedure_presentation_or_default_and_errors
2017-10-02 17:03:38 +02:00
end
2017-10-05 16:10:00 +02:00
def notifications_for_dossier ( dossier )
follow = Follow
. includes ( dossier : [ :champs , :avis , :commentaires ] )
2019-08-06 11:02:54 +02:00
. find_by ( instructeur : self , dossier : dossier )
2017-10-05 16:10:00 +02:00
if follow . present?
2019-07-29 12:13:01 +02:00
demande = follow . dossier . champs . updated_since? ( follow . demande_seen_at ) . any?
2017-10-05 16:10:00 +02:00
2019-06-07 14:41:24 +02:00
annotations_privees = follow . dossier . champs_private . updated_since? ( follow . annotations_privees_seen_at ) . any?
2017-10-05 16:10:00 +02:00
2019-06-07 14:41:24 +02:00
avis_notif = follow . dossier . avis . updated_since? ( follow . avis_seen_at ) . any?
2017-10-05 16:10:00 +02:00
2019-06-07 14:41:24 +02:00
messagerie = dossier . commentaires
2019-06-07 17:09:19 +02:00
. where . not ( email : OLD_CONTACT_EMAIL )
. where . not ( email : CONTACT_EMAIL )
. updated_since? ( follow . messagerie_seen_at ) . any?
2017-10-05 16:10:00 +02:00
annotations_hash ( demande , annotations_privees , avis_notif , messagerie )
else
annotations_hash ( false , false , false , false )
end
end
2019-09-20 10:35:44 +02:00
def notifications_for_procedure ( procedure , state )
2018-02-20 12:09:25 +01:00
dossiers = case state
2019-09-20 10:35:44 +02:00
when :en_cours
procedure . defaut_groupe_instructeur . dossiers . en_cours
2018-02-20 12:09:25 +01:00
when :termine
2019-08-22 17:58:31 +02:00
procedure . defaut_groupe_instructeur . dossiers . termine
2018-02-20 12:09:25 +01:00
when :not_archived
2019-08-22 17:58:31 +02:00
procedure . defaut_groupe_instructeur . dossiers . not_archived
2019-04-17 15:20:10 +02:00
when :all
2019-08-22 17:58:31 +02:00
procedure . defaut_groupe_instructeur . dossiers
2018-10-23 18:45:21 +02:00
end
2017-10-05 16:10:00 +02:00
dossiers_id_with_notifications ( dossiers )
end
2019-09-20 10:35:44 +02:00
def notifications_per_procedure ( state )
2018-02-20 12:09:25 +01:00
dossiers = case state
2019-09-20 10:35:44 +02:00
when :en_cours
Dossier . en_cours
2018-02-20 12:09:25 +01:00
when :termine
Dossier . termine
when :not_archived
Dossier . not_archived
2018-10-23 18:45:21 +02:00
end
2017-10-05 16:10:00 +02:00
2019-08-22 17:58:31 +02:00
Dossier . joins ( :groupe_instructeur ) . where ( id : dossiers_id_with_notifications ( dossiers ) ) . group ( 'groupe_instructeurs.procedure_id' ) . count
2017-10-05 16:10:00 +02:00
end
def dossiers_id_with_notifications ( dossiers )
2018-10-23 18:45:21 +02:00
dossiers = dossiers . followed_by ( self )
2019-09-20 08:51:54 +02:00
# Relations passed to #or must be “structurally compatible”, i.e. query the same tables.
joined_dossiers = dossiers
. left_outer_joins ( :champs , :champs_private , :avis , :commentaires )
updated_demandes = joined_dossiers
2017-10-05 16:10:00 +02:00
. where ( 'champs.updated_at > follows.demande_seen_at' )
2019-09-20 08:51:54 +02:00
# We join `:champs` twice, the second time with `has_many :champs_privates`. ActiveRecord generates the SQL: 'LEFT OUTER JOIN "champs" "champs_privates_dossiers" ON …'. We can then use this `champs_privates_dossiers` alias to disambiguate the table in this WHERE clause.
updated_annotations = joined_dossiers
. where ( 'champs_privates_dossiers.updated_at > follows.annotations_privees_seen_at' )
2017-10-05 16:10:00 +02:00
2019-09-20 08:51:54 +02:00
updated_avis = joined_dossiers
2017-10-05 16:10:00 +02:00
. where ( 'avis.updated_at > follows.avis_seen_at' )
2019-09-20 08:51:54 +02:00
updated_messagerie = joined_dossiers
2017-10-05 16:10:00 +02:00
. where ( 'commentaires.updated_at > follows.messagerie_seen_at' )
2018-05-31 15:43:57 +02:00
. where . not ( commentaires : { email : OLD_CONTACT_EMAIL } )
. where . not ( commentaires : { email : CONTACT_EMAIL } )
2017-10-05 16:10:00 +02:00
2019-09-20 08:51:54 +02:00
updated_demandes . or ( updated_annotations ) . or ( updated_avis ) . or ( updated_messagerie ) . ids
2017-10-05 16:10:00 +02:00
end
2018-10-23 18:46:45 +02:00
def mark_tab_as_seen ( dossier , tab )
attributes = { }
2018-10-25 15:07:15 +02:00
attributes [ " #{ tab } _seen_at " ] = Time . zone . now
2019-08-06 11:02:54 +02:00
Follow . where ( instructeur : self , dossier : dossier ) . update_all ( attributes )
2018-10-23 18:46:45 +02:00
end
2019-03-13 17:59:33 +01:00
def email_notification_data
2019-08-22 17:58:31 +02:00
groupe_instructeur_with_email_notifications
. reduce ( [ ] ) do | acc , groupe |
procedure = groupe . procedure
2019-03-13 17:59:33 +01:00
h = {
2019-08-22 17:58:31 +02:00
nb_en_construction : groupe . dossiers . en_construction . count ,
2019-04-17 15:20:10 +02:00
nb_notification : notifications_for_procedure ( procedure , :all ) . count
2019-03-13 17:59:33 +01:00
}
if h [ :nb_en_construction ] > 0 || h [ :nb_notification ] > 0
h [ :procedure_id ] = procedure . id
h [ :procedure_libelle ] = procedure . libelle
acc << h
end
acc
end
end
2019-09-20 10:41:47 +02:00
def create_trusted_device_token
trusted_device_token = trusted_device_tokens . create
trusted_device_token . token
end
def young_login_token?
trusted_device_token = trusted_device_tokens . order ( created_at : :desc ) . first
trusted_device_token & . token_young?
end
2018-10-23 18:46:45 +02:00
private
def annotations_hash ( demande , annotations_privees , avis , messagerie )
{
demande : demande ,
annotations_privees : annotations_privees ,
avis : avis ,
messagerie : messagerie
}
end
2015-09-22 10:15:12 +02:00
end