You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
141 lines
3.7 KiB
141 lines
3.7 KiB
class Entry < ApplicationRecord
|
|
|
|
require 'csv'
|
|
|
|
belongs_to :user
|
|
|
|
validates :date, presence: true
|
|
validates :hours, numericality: { only_integer: true, greater_than_or_equal_to: 0 }, unless: -> { start_time.present? && end_time.nil? }
|
|
validates :minutes, numericality: { only_integer: true, greater_than_or_equal_to: 0, less_than: 60 }, unless: -> { start_time.present? && end_time.nil? }
|
|
|
|
before_save :normalize_time
|
|
|
|
PRAKTIKUMSTYPEN = %w[propädeutikum fachspezifikum]
|
|
ENTRY_ARTEN = %w[Praktikum Selbsterfahrung Supervision Fortbildung Semesterkosten]
|
|
|
|
validates :praktikums_typ, inclusion: { in: PRAKTIKUMSTYPEN }
|
|
validates :entry_art, inclusion: { in: ENTRY_ARTEN }
|
|
validates :distance_km, numericality: { only_integer: true, greater_than_or_equal_to: 0 }
|
|
|
|
after_initialize :set_default_date, if: :new_record?
|
|
|
|
def set_default_date
|
|
self.date ||= Date.today
|
|
end
|
|
|
|
def kilometer_pauschale
|
|
return 0 unless distance_km.present?
|
|
distance_km * 0.42
|
|
end
|
|
|
|
def self.total_kilometer_cost_by_year(user)
|
|
where(user: user)
|
|
.where.not(distance_km: nil)
|
|
.group(Arel.sql("DATE_PART('year', date)"))
|
|
.order(Arel.sql("DATE_PART('year', date) DESC"))
|
|
.pluck(
|
|
Arel.sql("DATE_PART('year', date)::int"),
|
|
Arel.sql("SUM(distance_km * 2 * 0.42)")
|
|
).to_h
|
|
end
|
|
|
|
def self.total_fortbildungskosten_by_year(user)
|
|
where(user: user, entry_art: 'Fortbildung')
|
|
.where.not(kosten: nil)
|
|
.group(Arel.sql("DATE_PART('year', date)"))
|
|
.order(Arel.sql("DATE_PART('year', date) DESC"))
|
|
.pluck(Arel.sql("DATE_PART('year', date)::int"), Arel.sql("SUM(kosten)"))
|
|
.to_h
|
|
end
|
|
|
|
def self.total_selbsterfahrungskosten_by_year(user)
|
|
where(user: user, entry_art: 'Selbsterfahrung')
|
|
.where.not(kosten: nil)
|
|
.group(Arel.sql("DATE_PART('year', date)"))
|
|
.order(Arel.sql("DATE_PART('year', date) DESC"))
|
|
.pluck(Arel.sql("DATE_PART('year', date)::int"), Arel.sql("SUM(kosten)"))
|
|
.to_h
|
|
end
|
|
|
|
def self.total_selbsterfahrungskosten_by_year(user)
|
|
where(user: user, entry_art: 'Selbsterfahrung')
|
|
.where.not(kosten: nil)
|
|
.group(Arel.sql("DATE_PART('year', date)"))
|
|
.order(Arel.sql("DATE_PART('year', date) DESC"))
|
|
.pluck(Arel.sql("DATE_PART('year', date)::int"), Arel.sql("SUM(kosten)"))
|
|
.to_h
|
|
end
|
|
|
|
def self.total_supervision_by_year(user)
|
|
where(user: user, entry_art: 'Supervision')
|
|
.where.not(kosten: nil)
|
|
.group(Arel.sql("DATE_PART('year', date)"))
|
|
.order(Arel.sql("DATE_PART('year', date) DESC"))
|
|
.pluck(Arel.sql("DATE_PART('year', date)::int"), Arel.sql("SUM(kosten)"))
|
|
.to_h
|
|
end
|
|
|
|
def self.total_semesterkosten_by_year(user)
|
|
where(user: user)
|
|
.where.not(kosten: nil)
|
|
.group(Arel.sql("DATE_PART('year', date)"))
|
|
.order(Arel.sql("DATE_PART('year', date) DESC"))
|
|
.pluck(Arel.sql("DATE_PART('year', date)::int"), Arel.sql("SUM(kosten)"))
|
|
.to_h
|
|
end
|
|
|
|
def jahr
|
|
date.year
|
|
end
|
|
|
|
def total_minutes
|
|
hours * 60 + minutes
|
|
end
|
|
|
|
def self.to_csv
|
|
CSV.generate(headers: true, col_sep: ";") do |csv|
|
|
csv << %w[Datum Stunden Minuten Typ Art Kilometer User]
|
|
|
|
all.each do |entry|
|
|
csv << [
|
|
entry.date,
|
|
entry.hours,
|
|
entry.minutes,
|
|
entry.praktikums_typ,
|
|
entry.entry_art,
|
|
entry.distance_km,
|
|
entry.beschreibung,
|
|
entry.kosten,
|
|
entry.user.email
|
|
]
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
def total_minutes_including_break
|
|
return nil unless start_time && end_time
|
|
minutes = ((end_time - start_time) / 60).to_i
|
|
minutes -= lunch_break_minutes.to_i
|
|
minutes = 0 if minutes < 0
|
|
minutes
|
|
end
|
|
|
|
def hours_and_minutes
|
|
mins = total_minutes_including_break
|
|
return [0, 0] unless mins
|
|
[mins / 60, mins % 60]
|
|
end
|
|
|
|
private
|
|
|
|
def normalize_time
|
|
|
|
self.minutes ||= 0
|
|
self.hours ||= 0
|
|
|
|
self.hours += minutes / 60
|
|
self.minutes = minutes % 60
|
|
end
|
|
end
|