2 changed files with 703 additions and 127 deletions
@ -1,91 +1,413 @@ |
|||
class User < ApplicationRecord |
|||
# Include default devise modules. Others available are: |
|||
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable |
|||
devise :database_authenticatable, :registerable, |
|||
:recoverable, :rememberable, :validatable, :confirmable |
|||
devise :database_authenticatable, |
|||
:registerable, |
|||
:recoverable, |
|||
:rememberable, |
|||
:validatable, |
|||
:confirmable |
|||
|
|||
has_many :entries, dependent: :destroy |
|||
|
|||
PRAKTIKUMSTYPEN = %w[propädeutikum fachspezifikum mediation] |
|||
PRAKTIKUMSTYPEN = %w[ |
|||
propädeutikum |
|||
fachspezifikum |
|||
mediation |
|||
].freeze |
|||
|
|||
# ------------------------------------------------------------ |
|||
# Alle möglichen Entry-Arten |
|||
# ------------------------------------------------------------ |
|||
ENTRY_ARTEN = [ |
|||
"Praktikum", |
|||
"Selbsterfahrung", |
|||
"Supervision", |
|||
# Neue differenzierte Einträge (nur sichtbar im fachspezifikum-Kontext) |
|||
"Gruppenselbsterfahrung", # 64h |
|||
"Theorie/Methodikseminare", # 216h |
|||
"Peergruppensupervision", # 168h |
|||
"Einzel-/Kleingruppensupervision", # 40h |
|||
"Eigenständige Tätigkeit" |
|||
] |
|||
# Allgemein |
|||
"Praktikum", |
|||
"Selbsterfahrung", |
|||
"Supervision", |
|||
"Fortbildung", |
|||
"Semesterkosten", |
|||
|
|||
# Mediation |
|||
"Präsenzmodul", |
|||
"Peergruppenarbeit", |
|||
"Fallarbeit", |
|||
"Praxisseminare", |
|||
"Literatur- und Selbststudium", |
|||
|
|||
# Fachspezifikum |
|||
"Gruppenselbsterfahrung", |
|||
"Theorie/Methodikseminare", |
|||
"Peergruppensupervision", |
|||
"Einzel-/Kleingruppensupervision", |
|||
"Eigenständige Tätigkeit" |
|||
].freeze |
|||
|
|||
# ------------------------------------------------------------ |
|||
# Arten pro Ausbildung |
|||
# |
|||
# Kann im Frontend / Controller verwendet werden, damit nicht |
|||
# jede Entry-Art bei jedem Ausbildungstyp angezeigt wird. |
|||
# ------------------------------------------------------------ |
|||
ENTRY_ARTEN_BY_TYP = { |
|||
"propädeutikum" => [ |
|||
"Praktikum", |
|||
"Selbsterfahrung", |
|||
"Supervision", |
|||
"Fortbildung", |
|||
"Semesterkosten" |
|||
], |
|||
|
|||
"fachspezifikum" => [ |
|||
"Praktikum", |
|||
"Selbsterfahrung", |
|||
"Supervision", |
|||
"Fortbildung", |
|||
"Semesterkosten", |
|||
"Gruppenselbsterfahrung", |
|||
"Theorie/Methodikseminare", |
|||
"Peergruppensupervision", |
|||
"Einzel-/Kleingruppensupervision", |
|||
"Eigenständige Tätigkeit" |
|||
], |
|||
|
|||
"mediation" => [ |
|||
"Präsenzmodul", |
|||
"Selbsterfahrung", |
|||
"Supervision", |
|||
"Peergruppenarbeit", |
|||
"Fallarbeit", |
|||
"Praxisseminare", |
|||
"Literatur- und Selbststudium", |
|||
"Fortbildung", |
|||
"Semesterkosten" |
|||
] |
|||
}.freeze |
|||
|
|||
# ------------------------------------------------------------ |
|||
# Mediation – zusätzliche Anforderungen |
|||
# ------------------------------------------------------------ |
|||
|
|||
# Vorgabe des konkreten Lehrgangs |
|||
MEDIATION_PRAESENZMODULE_TAGE = 19 |
|||
|
|||
# ZivMediat-AV: |
|||
# Von den insgesamt 26 Supervisionseinheiten müssen mindestens |
|||
# 3 Einheiten Einzelsupervision sein. |
|||
MEDIATION_EINZELSUPERVISION_MINDESTENS = 3 |
|||
|
|||
after_initialize :set_default, if: :new_record? |
|||
|
|||
# ------------------------------------------------------------ |
|||
# Allgemein |
|||
# ------------------------------------------------------------ |
|||
|
|||
def praepedeutikum_abgeschlossen? |
|||
praepedeutikum_done |
|||
end |
|||
|
|||
def is_admin? |
|||
self.email =="christoph@marzell.net" |
|||
email == "christoph@marzell.net" |
|||
end |
|||
|
|||
def self.entry_arten_for(typ) |
|||
ENTRY_ARTEN_BY_TYP[typ.to_s] || ENTRY_ARTEN |
|||
end |
|||
|
|||
# ------------------------------------------------------------ |
|||
# Matrizen aktualisieren |
|||
# ------------------------------------------------------------ |
|||
|
|||
def update_required_matrices! |
|||
required = (required_hours_matrix || {}).deep_stringify_keys |
|||
weekly = (weekly_target_matrix || {}).deep_stringify_keys |
|||
|
|||
migrate_legacy_peer_group_key!( |
|||
required, |
|||
use_default_when_zero: true |
|||
) |
|||
|
|||
migrate_legacy_peer_group_key!( |
|||
weekly, |
|||
use_default_when_zero: false |
|||
) |
|||
|
|||
PRAKTIKUMSTYPEN.each do |typ| |
|||
required_hours_matrix[typ] ||= {} |
|||
weekly_target_matrix[typ] ||= {} |
|||
required[typ] ||= {} |
|||
weekly[typ] ||= {} |
|||
|
|||
ENTRY_ARTEN.each do |art| |
|||
required_hours_matrix[typ][art] ||= default_hours_for(typ, art) |
|||
weekly_target_matrix[typ][art] ||= default_weekly_target_for(typ, art) |
|||
unless required[typ].key?(art) |
|||
required[typ][art] = default_hours_for(typ, art) |
|||
end |
|||
|
|||
unless weekly[typ].key?(art) |
|||
weekly[typ][art] = default_weekly_target_for(typ, art) |
|||
end |
|||
end |
|||
end |
|||
|
|||
self.required_hours_matrix = required |
|||
self.weekly_target_matrix = weekly |
|||
|
|||
save! |
|||
end |
|||
|
|||
# ------------------------------------------------------------ |
|||
# Default-Wochenziele |
|||
# ------------------------------------------------------------ |
|||
|
|||
def default_weekly_target_for(typ, art) |
|||
typ = typ.to_s |
|||
art = canonical_entry_art(art) |
|||
|
|||
case [typ, art] |
|||
when ["propädeutikum", "Praktikum"] then 12 |
|||
when ["fachspezifikum", "Praktikum"] then 10 |
|||
when ["propädeutikum", "Praktikum"] |
|||
12 |
|||
|
|||
when ["fachspezifikum", "Praktikum"] |
|||
10 |
|||
|
|||
when ["propädeutikum", "Selbsterfahrung"], |
|||
["fachspezifikum", "Selbsterfahrung"], |
|||
["fachspezifikum", "Gruppenselbsterfahrung"] then 0.25 |
|||
["fachspezifikum", "Gruppenselbsterfahrung"] |
|||
0.25 |
|||
|
|||
when ["propädeutikum", "Supervision"], |
|||
["fachspezifikum", "Supervision"], |
|||
["fachspezifikum", "Peergruppensupervision"], |
|||
["fachspezifikum", "Einzel-/Kleingruppensupervision"] then 0.25 |
|||
when ["fachspezifikum", "Eigenständige Tätigkeit"] then 10 |
|||
else 0 |
|||
end |
|||
end |
|||
["fachspezifikum", "Einzel-/Kleingruppensupervision"] |
|||
0.25 |
|||
|
|||
when ["fachspezifikum", "Eigenständige Tätigkeit"] |
|||
10 |
|||
|
|||
def set_default |
|||
self.required_hours_matrix = PRAKTIKUMSTYPEN.to_h do |typ| |
|||
[typ, ENTRY_ARTEN.to_h { |art| [art, default_hours_for(typ, art)] }] |
|||
# Mediation findet typischerweise blockweise statt. |
|||
# Deshalb kein künstliches Wochenziel. |
|||
when ["mediation", "Präsenzmodul"], |
|||
["mediation", "Selbsterfahrung"], |
|||
["mediation", "Supervision"], |
|||
["mediation", "Peergruppenarbeit"], |
|||
["mediation", "Fallarbeit"], |
|||
["mediation", "Praxisseminare"], |
|||
["mediation", "Literatur- und Selbststudium"] |
|||
0 |
|||
|
|||
else |
|||
0 |
|||
end |
|||
self.weekly_target_matrix = { |
|||
"propädeutikum" => { "Praktikum" => 12, "Selbsterfahrung" => 0.25, "Supervision" => 0.25 }, |
|||
"fachspezifikum" => { "Praktikum" => 10, "Selbsterfahrung" => 0.25, "Supervision" => 0.25 } |
|||
} |
|||
end |
|||
|
|||
# ------------------------------------------------------------ |
|||
# Default-Sollstunden / Einheiten |
|||
# ------------------------------------------------------------ |
|||
|
|||
def default_hours_for(typ, art) |
|||
typ = typ.to_s |
|||
art = canonical_entry_art(art) |
|||
|
|||
case [typ, art] |
|||
when ["propädeutikum", "Praktikum"] then 480 |
|||
when ["propädeutikum", "Selbsterfahrung"] then 50 |
|||
when ["propädeutikum", "Supervision"] then 20 |
|||
when ["fachspezifikum", "Praktikum"] then 600 |
|||
when ["fachspezifikum", "Selbsterfahrung"] then 80 |
|||
when ["fachspezifikum", "Supervision"] then 40 |
|||
when ["fachspezifikum", "Eigenständige Tätigkeit"] then 600 |
|||
else 0 |
|||
# ---------------------------------------------------------- |
|||
# Propädeutikum |
|||
# ---------------------------------------------------------- |
|||
when ["propädeutikum", "Praktikum"] |
|||
480 |
|||
|
|||
when ["propädeutikum", "Selbsterfahrung"] |
|||
50 |
|||
|
|||
when ["propädeutikum", "Supervision"] |
|||
20 |
|||
|
|||
# ---------------------------------------------------------- |
|||
# Fachspezifikum |
|||
# ---------------------------------------------------------- |
|||
when ["fachspezifikum", "Praktikum"] |
|||
600 |
|||
|
|||
when ["fachspezifikum", "Selbsterfahrung"] |
|||
80 |
|||
|
|||
when ["fachspezifikum", "Supervision"] |
|||
40 |
|||
|
|||
when ["fachspezifikum", "Gruppenselbsterfahrung"] |
|||
64 |
|||
|
|||
when ["fachspezifikum", "Theorie/Methodikseminare"] |
|||
216 |
|||
|
|||
when ["fachspezifikum", "Peergruppensupervision"] |
|||
168 |
|||
|
|||
when ["fachspezifikum", "Einzel-/Kleingruppensupervision"] |
|||
40 |
|||
|
|||
when ["fachspezifikum", "Eigenständige Tätigkeit"] |
|||
600 |
|||
|
|||
# ---------------------------------------------------------- |
|||
# Mediation |
|||
# ---------------------------------------------------------- |
|||
|
|||
# Wird in Tagen und nicht in Stunden bewertet. |
|||
when ["mediation", "Präsenzmodul"] |
|||
0 |
|||
|
|||
# ZivMediat-AV Anlage 1 |
|||
when ["mediation", "Selbsterfahrung"] |
|||
40 |
|||
|
|||
when ["mediation", "Supervision"] |
|||
26 |
|||
|
|||
when ["mediation", "Peergruppenarbeit"] |
|||
24 |
|||
|
|||
when ["mediation", "Fallarbeit"] |
|||
17 |
|||
|
|||
when ["mediation", "Praxisseminare"] |
|||
58 |
|||
|
|||
# Zusätzliche Lehrgangsvorgabe |
|||
when ["mediation", "Literatur- und Selbststudium"] |
|||
150 |
|||
|
|||
else |
|||
0 |
|||
end |
|||
end |
|||
|
|||
# ------------------------------------------------------------ |
|||
# Sollwert aus persönlicher Matrix |
|||
# ------------------------------------------------------------ |
|||
|
|||
def required_hours_for(typ, art) |
|||
required_hours_matrix.dig(typ, art) || 0 |
|||
typ = typ.to_s |
|||
art = canonical_entry_art(art) |
|||
|
|||
value = required_hours_matrix&.dig(typ, art) |
|||
|
|||
value.nil? ? default_hours_for(typ, art) : value |
|||
end |
|||
|
|||
def weekly_target_for(typ, art) |
|||
typ = typ.to_s |
|||
art = canonical_entry_art(art) |
|||
|
|||
value = weekly_target_matrix&.dig(typ, art) |
|||
|
|||
value.nil? ? default_weekly_target_for(typ, art) : value |
|||
end |
|||
|
|||
# ------------------------------------------------------------ |
|||
# Mediation – Präsenztage |
|||
# ------------------------------------------------------------ |
|||
|
|||
def mediation_praesenzmodule_required |
|||
MEDIATION_PRAESENZMODULE_TAGE |
|||
end |
|||
|
|||
def mediation_praesenzmodule_completed |
|||
entries |
|||
.where( |
|||
praktikums_typ: "mediation", |
|||
entry_art: "Präsenzmodul" |
|||
) |
|||
.distinct |
|||
.count(:date) |
|||
end |
|||
|
|||
def mediation_praesenzmodule_remaining |
|||
[ |
|||
mediation_praesenzmodule_required - |
|||
mediation_praesenzmodule_completed, |
|||
0 |
|||
].max |
|||
end |
|||
|
|||
def mediation_praesenzmodule_completed? |
|||
mediation_praesenzmodule_completed >= |
|||
mediation_praesenzmodule_required |
|||
end |
|||
|
|||
# ------------------------------------------------------------ |
|||
# Mediation – besondere Vorgaben |
|||
# ------------------------------------------------------------ |
|||
|
|||
def mediation_einzelsupervision_required |
|||
MEDIATION_EINZELSUPERVISION_MINDESTENS |
|||
end |
|||
|
|||
private |
|||
|
|||
# ------------------------------------------------------------ |
|||
# Defaults für neuen User |
|||
# ------------------------------------------------------------ |
|||
|
|||
def set_default |
|||
self.required_hours_matrix ||= PRAKTIKUMSTYPEN.to_h do |typ| |
|||
[ |
|||
typ, |
|||
ENTRY_ARTEN.to_h do |art| |
|||
[art, default_hours_for(typ, art)] |
|||
end |
|||
] |
|||
end |
|||
|
|||
self.weekly_target_matrix ||= PRAKTIKUMSTYPEN.to_h do |typ| |
|||
[ |
|||
typ, |
|||
ENTRY_ARTEN.to_h do |art| |
|||
[art, default_weekly_target_for(typ, art)] |
|||
end |
|||
] |
|||
end |
|||
end |
|||
|
|||
# ------------------------------------------------------------ |
|||
# Alte Bezeichnungen normalisieren |
|||
# ------------------------------------------------------------ |
|||
|
|||
def canonical_entry_art(art) |
|||
case art.to_s |
|||
when "Peergroup", "Peer-Gruppe" |
|||
"Peergruppenarbeit" |
|||
else |
|||
art.to_s |
|||
end |
|||
end |
|||
|
|||
def migrate_legacy_peer_group_key!(matrix, use_default_when_zero:) |
|||
PRAKTIKUMSTYPEN.each do |typ| |
|||
values = matrix[typ] |
|||
next unless values.is_a?(Hash) |
|||
|
|||
legacy_value = nil |
|||
|
|||
if values.key?("Peergroup") |
|||
legacy_value = values.delete("Peergroup") |
|||
end |
|||
|
|||
if values.key?("Peer-Gruppe") |
|||
legacy_value ||= values.delete("Peer-Gruppe") |
|||
end |
|||
|
|||
next if legacy_value.nil? |
|||
next if values.key?("Peergruppenarbeit") |
|||
|
|||
if use_default_when_zero && |
|||
typ == "mediation" && |
|||
legacy_value.to_f.zero? |
|||
|
|||
values["Peergruppenarbeit"] = |
|||
default_hours_for( |
|||
"mediation", |
|||
"Peergruppenarbeit" |
|||
) |
|||
else |
|||
values["Peergruppenarbeit"] = legacy_value |
|||
end |
|||
end |
|||
end |
|||
end |
|||
Loading…
Reference in new issue