2 changed files with 703 additions and 127 deletions
@ -1,91 +1,413 @@ |
|||||
class User < ApplicationRecord |
class User < ApplicationRecord |
||||
# Include default devise modules. Others available are: |
# Include default devise modules. Others available are: |
||||
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable |
# :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 |
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 = [ |
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? |
after_initialize :set_default, if: :new_record? |
||||
|
|
||||
|
# ------------------------------------------------------------ |
||||
|
# Allgemein |
||||
|
# ------------------------------------------------------------ |
||||
|
|
||||
def praepedeutikum_abgeschlossen? |
def praepedeutikum_abgeschlossen? |
||||
praepedeutikum_done |
praepedeutikum_done |
||||
end |
end |
||||
|
|
||||
def is_admin? |
def is_admin? |
||||
self.email =="christoph@marzell.net" |
|
||||
|
email == "christoph@marzell.net" |
||||
end |
end |
||||
|
|
||||
|
def self.entry_arten_for(typ) |
||||
|
ENTRY_ARTEN_BY_TYP[typ.to_s] || ENTRY_ARTEN |
||||
|
end |
||||
|
|
||||
|
# ------------------------------------------------------------ |
||||
|
# Matrizen aktualisieren |
||||
|
# ------------------------------------------------------------ |
||||
|
|
||||
def update_required_matrices! |
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| |
PRAKTIKUMSTYPEN.each do |typ| |
||||
required_hours_matrix[typ] ||= {} |
|
||||
weekly_target_matrix[typ] ||= {} |
|
||||
|
required[typ] ||= {} |
||||
|
weekly[typ] ||= {} |
||||
|
|
||||
ENTRY_ARTEN.each do |art| |
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 |
||||
end |
end |
||||
|
|
||||
|
self.required_hours_matrix = required |
||||
|
self.weekly_target_matrix = weekly |
||||
|
|
||||
save! |
save! |
||||
end |
end |
||||
|
|
||||
|
# ------------------------------------------------------------ |
||||
|
# Default-Wochenziele |
||||
|
# ------------------------------------------------------------ |
||||
|
|
||||
def default_weekly_target_for(typ, art) |
def default_weekly_target_for(typ, art) |
||||
|
typ = typ.to_s |
||||
|
art = canonical_entry_art(art) |
||||
|
|
||||
case [typ, 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"], |
when ["propädeutikum", "Selbsterfahrung"], |
||||
["fachspezifikum", "Selbsterfahrung"], |
["fachspezifikum", "Selbsterfahrung"], |
||||
["fachspezifikum", "Gruppenselbsterfahrung"] then 0.25 |
|
||||
|
["fachspezifikum", "Gruppenselbsterfahrung"] |
||||
|
0.25 |
||||
|
|
||||
when ["propädeutikum", "Supervision"], |
when ["propädeutikum", "Supervision"], |
||||
["fachspezifikum", "Supervision"], |
["fachspezifikum", "Supervision"], |
||||
["fachspezifikum", "Peergruppensupervision"], |
["fachspezifikum", "Peergruppensupervision"], |
||||
["fachspezifikum", "Einzel-/Kleingruppensupervision"] then 0.25 |
|
||||
when ["fachspezifikum", "Eigenständige Tätigkeit"] then 10 |
|
||||
else 0 |
|
||||
|
["fachspezifikum", "Einzel-/Kleingruppensupervision"] |
||||
|
0.25 |
||||
|
|
||||
|
when ["fachspezifikum", "Eigenständige Tätigkeit"] |
||||
|
10 |
||||
|
|
||||
|
# 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 |
end |
||||
end |
end |
||||
|
|
||||
|
# ------------------------------------------------------------ |
||||
|
# Default-Sollstunden / Einheiten |
||||
|
# ------------------------------------------------------------ |
||||
|
|
||||
def set_default |
|
||||
self.required_hours_matrix = PRAKTIKUMSTYPEN.to_h do |typ| |
|
||||
[typ, ENTRY_ARTEN.to_h { |art| [art, default_hours_for(typ, art)] }] |
|
||||
|
def default_hours_for(typ, art) |
||||
|
typ = typ.to_s |
||||
|
art = canonical_entry_art(art) |
||||
|
|
||||
|
case [typ, art] |
||||
|
# ---------------------------------------------------------- |
||||
|
# 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 |
||||
self.weekly_target_matrix = { |
|
||||
"propädeutikum" => { "Praktikum" => 12, "Selbsterfahrung" => 0.25, "Supervision" => 0.25 }, |
|
||||
"fachspezifikum" => { "Praktikum" => 10, "Selbsterfahrung" => 0.25, "Supervision" => 0.25 } |
|
||||
} |
|
||||
end |
end |
||||
|
|
||||
|
# ------------------------------------------------------------ |
||||
|
# Sollwert aus persönlicher Matrix |
||||
|
# ------------------------------------------------------------ |
||||
|
|
||||
def default_hours_for(typ, 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 |
|
||||
|
def required_hours_for(typ, art) |
||||
|
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 |
||||
end |
end |
||||
|
|
||||
def required_hours_for(typ, art) |
|
||||
required_hours_matrix.dig(typ, art) || 0 |
|
||||
|
# ------------------------------------------------------------ |
||||
|
# Alte Bezeichnungen normalisieren |
||||
|
# ------------------------------------------------------------ |
||||
|
|
||||
|
def canonical_entry_art(art) |
||||
|
case art.to_s |
||||
|
when "Peergroup", "Peer-Gruppe" |
||||
|
"Peergruppenarbeit" |
||||
|
else |
||||
|
art.to_s |
||||
|
end |
||||
end |
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