/
qualification.rb
150 lines (120 loc) · 4.48 KB
/
qualification.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# Copyright (c) 2012-2013, Jungwacht Blauring Schweiz. This file is part of
# hitobito and licensed under the Affero General Public License version 3
# or later. See the COPYING file at the top-level directory or at
# https://github.com/hitobito/hitobito.
# == Schema Information
#
# Table name: qualifications
#
# id :integer not null, primary key
# finish_at :date
# origin :string(255)
# start_at :date not null
# person_id :integer not null
# qualification_kind_id :integer not null
#
# Indexes
#
# index_qualifications_on_person_id (person_id)
# index_qualifications_on_qualification_kind_id (qualification_kind_id)
#
class Qualification < ActiveRecord::Base
attr_writer :first_of_kind
attr_accessor :open_training_days
### ASSOCIATIONS
belongs_to :person
belongs_to :qualification_kind
has_paper_trail meta: { main_id: ->(q) { q.person_id }, main_type: Person.sti_name }
### VALIDATIONS
before_validation :set_finish_at
validates_by_schema
validates :qualification_kind_id,
uniqueness: { scope: [:person_id, :start_at, :finish_at],
message: :exists_for_timeframe }
validates :start_at, :finish_at,
timeliness: { type: :date, allow_blank: true, before: Date.new(9999, 12, 31) }
delegate :cover?, :active?, to: :duration
class << self
def order_by_date
order(
Arel.sql('CASE WHEN finish_at IS NULL THEN 0 ELSE 1 END, finish_at DESC, start_at DESC')
)
end
def active(date = nil)
date ||= Time.zone.today
where('qualifications.start_at <= ?', date).
where('qualifications.finish_at >= ? OR qualifications.finish_at IS NULL', date)
end
def reactivateable(date = nil)
date ||= Time.zone.today
joins(:qualification_kind).
where('qualifications.start_at <= ?', date).
where('qualifications.finish_at IS NULL OR ' \
'(qualification_kinds.reactivateable IS NULL AND ' \
' qualifications.finish_at >= :date) OR ' \
'DATE_ADD(qualifications.finish_at, ' \
' INTERVAL qualification_kinds.reactivateable YEAR) >= :date',
date: date)
end
def only_reactivateable(date = nil)
date ||= Time.zone.today
joins(:qualification_kind).
where.not(finish_at: nil).
where.not(qualification_kinds: { reactivateable: nil }).
where('qualifications.finish_at < :date AND ' \
'DATE_ADD(qualifications.finish_at, ' \
' INTERVAL qualification_kinds.reactivateable YEAR) >= :date',
date: date)
end
def not_active(qualification_kind_ids = [], date = nil) # rubocop:disable Metrics/MethodLength
date ||= Time.zone.today
kind_condition =
if qualification_kind_ids.present?
'q2.qualification_kind_id IN (:qualification_kind_ids)'
else
'q2.qualification_kind_id = qualifications.qualification_kind_id'
end
where('NOT EXISTS (SELECT 1 FROM qualifications q2 ' \
'WHERE q2.person_id = qualifications.person_id ' \
"AND #{kind_condition} " \
'AND q2.start_at <= :date ' \
'AND (q2.finish_at IS NULL OR q2.finish_at >= :date))',
qualification_kind_ids: qualification_kind_ids, date: date)
end
end
def duration
@duration ||= Duration.new(start_at, finish_at)
end
def reactivateable_until
return unless finish_at
finish_at + qualification_kind.reactivateable.to_i.years
end
def reactivateable?(date = nil)
date ||= Time.zone.today
finish_at.nil? || (reactivateable_until && reactivateable_until >= date)
end
def first_of_kind?
@first_of_kind
end
def first_reactivateable?
first_of_kind? && reactivateable?
end
def to_s(format = :default)
I18n.t("activerecord.attributes.qualification.#{to_s_key(format)}",
kind: qualification_kind.to_s,
finish_at: finish_at? ? I18n.l(finish_at) : nil,
origin: origin)
end
private
def set_finish_at
if start_at? && qualification_kind && qualification_kind.validity
self.finish_at = (start_at + qualification_kind.validity.years).end_of_year
end
end
def to_s_key(format = :default)
cols = []
cols << :finish_at if finish_at?
cols << :origin if format == :long && origin?
['string', cols.join('_and_').presence].compact.join('_with_')
end
end