demarches-normaliennes/app/models/instructeur.rb

213 lines
7.1 KiB
Ruby
Raw Normal View History

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']
include EmailSanitizableConcern
has_and_belongs_to_many :administrateurs
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
has_many :procedures, -> { distinct }, through: :groupe_instructeurs
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-08-22 17:58:31 +02:00
has_many :dossiers, -> { state_not_brouillon }, through: :groupe_instructeurs
has_many :follows, -> { active }, inverse_of: :instructeur
has_many :previous_follows, -> { inactive }, class_name: 'Follow', inverse_of: :instructeur
has_many :followed_dossiers, through: :follows, source: :dossier
has_many :previously_followed_dossiers, -> { distinct }, through: :previous_follows, source: :dossier
2017-04-25 12:09:11 +02:00
has_many :avis
has_many :dossiers_from_avis, through: :avis, source: :dossier
2019-02-01 18:11:55 +01:00
has_many :trusted_device_tokens
2019-08-08 16:49:40 +02:00
has_one :user
def follow(dossier)
begin
followed_dossiers << dossier
# If the user tries to follow a dossier she already follows,
# we just fail silently: it means the goal is already reached.
rescue ActiveRecord::RecordNotUnique
# Database uniqueness constraint
rescue ActiveRecord::RecordInvalid => e
# ActiveRecord validation
raise unless e.record.errors.details.dig(:instructeur_id, 0, :error) == :taken
end
end
2017-10-05 14:10:49 +02:00
def unfollow(dossier)
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)
end
def assign_to_procedure(procedure)
2018-02-20 11:24:32 +01:00
begin
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
end
def remove_from_procedure(procedure)
!!(procedure.defaut_groupe_instructeur.in?(groupe_instructeurs) && groupe_instructeurs.destroy(procedure.defaut_groupe_instructeur))
end
def last_week_overview
2018-10-25 15:07:15 +02:00
start_date = Time.zone.now.beginning_of_week
active_procedure_overviews = procedures
.publiees
.map { |procedure| procedure.procedure_overview(start_date) }
2019-09-12 11:26:22 +02:00
.filter(&:had_some_activities?)
if active_procedure_overviews.count == 0
nil
else
{
start_date: start_date,
procedure_overviews: active_procedure_overviews
}
end
end
def procedure_presentation_and_errors_for_procedure_id(procedure_id)
assign_to.joins(:groupe_instructeur).find_by(groupe_instructeurs: { procedure_id: procedure_id }).procedure_presentation_or_default_and_errors
end
def notifications_for_dossier(dossier)
follow = Follow
.includes(dossier: [:champs, :avis, :commentaires])
.find_by(instructeur: self, dossier: dossier)
if follow.present?
demande = follow.dossier.champs.updated_since?(follow.demande_seen_at).any?
annotations_privees = follow.dossier.champs_private.updated_since?(follow.annotations_privees_seen_at).any?
avis_notif = follow.dossier.avis.updated_since?(follow.avis_seen_at).any?
messagerie = dossier.commentaires
.where.not(email: OLD_CONTACT_EMAIL)
.where.not(email: CONTACT_EMAIL)
.updated_since?(follow.messagerie_seen_at).any?
annotations_hash(demande, annotations_privees, avis_notif, messagerie)
else
annotations_hash(false, false, false, false)
end
end
def notifications_for_procedure(procedure, state = :en_cours)
dossiers = case state
when :termine
2019-08-22 17:58:31 +02:00
procedure.defaut_groupe_instructeur.dossiers.termine
when :not_archived
2019-08-22 17:58:31 +02:00
procedure.defaut_groupe_instructeur.dossiers.not_archived
when :all
2019-08-22 17:58:31 +02:00
procedure.defaut_groupe_instructeur.dossiers
else
2019-08-22 17:58:31 +02:00
procedure.defaut_groupe_instructeur.dossiers.en_cours
end
dossiers_id_with_notifications(dossiers)
end
def notifications_per_procedure(state = :en_cours)
dossiers = case state
when :termine
Dossier.termine
when :not_archived
Dossier.not_archived
else
Dossier.en_cours
end
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
end
def create_trusted_device_token
2019-02-01 18:11:55 +01:00
trusted_device_token = trusted_device_tokens.create
trusted_device_token.token
end
def dossiers_id_with_notifications(dossiers)
dossiers = dossiers.followed_by(self)
# 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
.where('champs.updated_at > follows.demande_seen_at')
# 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')
updated_avis = joined_dossiers
.where('avis.updated_at > follows.avis_seen_at')
updated_messagerie = joined_dossiers
.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 })
updated_demandes.or(updated_annotations).or(updated_avis).or(updated_messagerie).ids
end
def mark_tab_as_seen(dossier, tab)
attributes = {}
2018-10-25 15:07:15 +02:00
attributes["#{tab}_seen_at"] = Time.zone.now
Follow.where(instructeur: self, dossier: dossier).update_all(attributes)
end
def young_login_token?
2019-02-01 18:11:55 +01:00
trusted_device_token = trusted_device_tokens.order(created_at: :desc).first
2019-02-04 11:04:55 +01:00
trusted_device_token&.token_young?
end
def email_notification_data
2019-08-22 17:58:31 +02:00
groupe_instructeur_with_email_notifications
.reduce([]) do |acc, groupe|
procedure = groupe.procedure
h = {
2019-08-22 17:58:31 +02:00
nb_en_construction: groupe.dossiers.en_construction.count,
nb_notification: notifications_for_procedure(procedure, :all).count
}
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
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