schild.rb 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674
  1. require 'schild/version'
  2. require 'sequel'
  3. ##
  4. # === Schild Basis-Modul
  5. # Das Schild Modul, das alle Klassen für die Datenbankanbindung bereitstellt.
  6. # Die zur Verfügung gestellten Klassen entsprechen dabei den Schild-Tabellen,
  7. # und den damit verbundenen Assoaziationen.
  8. #
  9. # Neben dem Zugriff aus Daten innerhalb einer Tabelle kann über die Schild-Klassen
  10. # auch auf weitere verknüpfte Tabellen zugegriffen werden. Dazu ein Beispiel:
  11. #
  12. # Schueler[0].name
  13. # => "Olsen"
  14. #
  15. # Schueler[0].abschnitte[0].jahr
  16. # => 2017
  17. #
  18. # Im ersten Beispiel wurde auf den ersten Schüler in der Datenbank ([0]) zugegriffen,
  19. # und der `name` ausgelesen.
  20. #
  21. # Im zweiten Beispiel wird auf den gleichen Schüler zugegriffen und dessen Abschnitt-Tabelle
  22. # ebenfalls abgefragt. D.h. es wird bereits auf die Abschnitte-Tabelle zugegriffen
  23. # und automatisch nur Abschnitte zurückgegeben, die zum Schüler gehören. Aus
  24. # dieser Menge wird ebenfalls der erste Abschnitt gewählt ([0]).
  25. #
  26. # Auf diesem Weg können beliebig verschachtelte Anfragen gestartet werden.
  27. #
  28. # Es wird empfohlen statt Schild das Modul SchildErweitert einzubinden. Es
  29. # beinhaltet neben den Assoaziationen auch weitere Methoden.
  30. # Weitere Erläuterungen dazu weiter im Modul.
  31. module Schild
  32. Sequel::Model.plugin :tactical_eager_loading
  33. # @db ist die Datenbank-Verbindung. Alle Daten können über diese Variable abgerufen werden
  34. @db = Sequel.connect("#{ENV['S_ADAPTER']}://#{ENV['S_HOST']}/#{ENV['S_DB']}?user=#{ENV['S_USER']}&password=#{ENV['S_PASSWORD']}&zeroDateTimeBehavior=convertToNull")
  35. begin
  36. retries ||= 0
  37. @db.test_connection
  38. rescue
  39. puts "Verbindung zum Server konnte nicht hergestellt werden"
  40. puts "#{retries += 1}. Verbindungsversuch in 5s (max 50 Versuche)"
  41. puts "Sie können mit Strg-c abbrechen."
  42. sleep 5
  43. retry if retries < 50
  44. end
  45. @db.extension(:freeze_datasets)
  46. @db.extension(:connection_validator)
  47. @db.extension(:null_dataset)
  48. # gibt die Datenbank zurück
  49. def self.db
  50. @db
  51. end
  52. # Stellt die Schüler-Tabelle mit Assoziationen bereit.
  53. # Die aufgeführten Instanzmethoden sind ausschließlich Assoaziationen.
  54. #
  55. # Tabellenname: schueler
  56. class Schueler < Sequel::Model(:schueler)
  57. # @!method fachklasse
  58. # @return [Fachklasse]
  59. many_to_one :fachklasse, :class => :Fachklasse
  60. # @!method abschnitte
  61. # @return [Array<Abschnitt>]
  62. one_to_many :abschnitte, :class => :Abschnitt
  63. # @!method bk_abschluss
  64. # @return [BKAbschluss]
  65. one_to_one :bk_abschluss, :class => :BKAbschluss
  66. # @!method bk_abschluss_leistungen
  67. # @return [Array<BKAbschlussFach>]
  68. one_to_many :bk_abschluss_leistungen, :class => :BKAbschlussFach
  69. # @!method abi_abschluss
  70. # @return [AbiAbschluss]
  71. one_to_one :abi_abschluss, :class => :AbiAbschluss
  72. # @!method abi_abschluss_leistungen
  73. # @return [Array<AbiAbschlussFach>]
  74. one_to_many :abi_abschluss_leistungen, :class => :AbiAbschlussFach
  75. # @!method fhr_abschluss
  76. # @return [FHRAbschluss]
  77. one_to_one :fhr_abschluss, :class => :FHRAbschluss
  78. # @!method fhr_abschluss_leistungen
  79. # @return [Array<FHRAbschlussFach>]
  80. one_to_many :fhr_abschluss_leistungen, :class => :FHRAbschlussFach
  81. # @!method vermerke
  82. # @return [Array<Vermerk>]
  83. one_to_many :vermerke, :class => :Vermerk
  84. # @!method schuelerfoto
  85. # @return [Schuelerfoto]
  86. one_to_one :schuelerfoto, :class => :Schuelerfoto
  87. # @!method sprachenfolgen
  88. # @return [Array<Sprachenfolge>]
  89. one_to_many :sprachenfolgen, :class => :Sprachenfolge
  90. end
  91. # Informationen zu Klassenbezeichnung und weiteren Daten über die jeweiligen
  92. # Bildungsgänge. Verfügbar als Assoziationen für Schüler.
  93. #
  94. # Tabellenname: eigeneschule_fachklassen
  95. class Fachklasse < Sequel::Model(:eigeneschule_fachklassen)
  96. end
  97. # Versetzungstabelle für Fachklassen. D.h. Klassenbezeichnungen für vorhergehende
  98. # und nachfolgende Klassen.
  99. #
  100. # Tabellenname: versetzung
  101. class Versetzung < Sequel::Model(:versetzung)
  102. # @!method fachklasse
  103. # @return [Fachklasse]
  104. many_to_one :fachklasse, :class => :Fachklasse
  105. end
  106. # Assoziation für Lehrer, hauptsächlich für Klassenlehrer
  107. #
  108. # Tabellenname: k_lehrer
  109. class Klassenlehrer < Sequel::Model(:k_lehrer)
  110. end
  111. # Ist die Assoziation, die Halbjahre, sog. Abschnitte zurückgibt.
  112. #
  113. # Tabellenname: schuelerlernabschnittsdaten
  114. class Abschnitt < Sequel::Model(:schuelerlernabschnittsdaten)
  115. # @!method noten
  116. # @return [Array<Note>]
  117. one_to_many :noten, :class => :Note
  118. # @!method fachklasse
  119. # @return [Fachklasse]
  120. many_to_one :fachklasse, :class => :Fachklasse
  121. # @!method klassenlehrer
  122. # @return [Klassenlehrer]
  123. many_to_one :klassenlehrer, :primary_key=>:Kuerzel, :key=>:KlassenLehrer, :class=>:Klassenlehrer
  124. end
  125. # Assoziation für Noten
  126. #
  127. # Tabellenname: schuelerleistungsdaten
  128. class Note < Sequel::Model(:schuelerleistungsdaten)
  129. # @!method fach
  130. # @return [Fach]
  131. many_to_one :fach, :class => :Fach
  132. end
  133. # Assoziation für Fächer
  134. #
  135. # Tabellenname: eigeneschule_faecher
  136. class Fach < Sequel::Model(:eigeneschule_faecher)
  137. # @!method sprachenfolge
  138. # @return [Sprachenfolge]
  139. one_to_one :sprachenfolge, :class => :Sprachenfolge, :key => :Fach_ID
  140. # @!method gliederungen
  141. # @return [Array<Fach_Gliederung>]
  142. one_to_many :gliederungen, :class => :Fach_Gliederung, :key => :Fach_ID
  143. end
  144. # Assoziation für BK-Abschluss des Schülers
  145. #
  146. # Tabellenname: schuelerbkabschluss
  147. class BKAbschluss < Sequel::Model(:schuelerbkabschluss)
  148. end
  149. # Assoziation für die Prüfungsfächer des Schülers
  150. #
  151. # Tabellenname: schuelerbkfaecher
  152. class BKAbschlussFach < Sequel::Model(:schuelerbkfaecher)
  153. # @!method fach
  154. # @return [Fach]
  155. many_to_one :fach, :class => :Fach
  156. end
  157. # Assoziation für Abi-Abschluss des Schülers
  158. #
  159. # Tabellenname: schuelerabitur
  160. class AbiAbschluss < Sequel::Model(:schuelerabitur)
  161. end
  162. # Assoziation für die Abifächer des Schülers
  163. #
  164. # Tabellenname: schuelerabifaecher
  165. class AbiAbschlussFach < Sequel::Model(:schuelerabifaecher)
  166. # @!method fach
  167. # @return [Fach]
  168. many_to_one :fach, :class => :Fach
  169. end
  170. # Assoziation für FHR-Abschluss des Schülers
  171. #
  172. # Tabellenname: schuelerfhr
  173. class FHRAbschluss < Sequel::Model(:schuelerfhr)
  174. end
  175. # Assoziation für die FHR-fächer des Schülers
  176. #
  177. # Tabellenname: schuelerfhrfaecher
  178. class FHRAbschlussFach < Sequel::Model(:schuelerfhrfaecher)
  179. # @!method fach
  180. # @return [Fach]
  181. many_to_one :fach, :class => :Fach
  182. end
  183. # Assoziation für die bisher erreichten Sprachniveaus
  184. #
  185. # Tabellenname: schuelersprachenfolge
  186. class Sprachenfolge < Sequel::Model(:schuelersprachenfolge)
  187. end
  188. # Besondere Facheinstellungen nach Fachklasse. Betrifft v.a. Sortierung,
  189. # Festlegungen über Prüfungsfächer etc.
  190. #
  191. # Tabellenname: fach_gliederungen
  192. class Fach_Gliederung < Sequel::Model(:fach_gliederungen)
  193. # @!method fachklasse
  194. # @return [Fachklasse]
  195. many_to_one :fachklasse, :class => :Fachklasse
  196. end
  197. # Vermerke von Schülern
  198. #
  199. # Tabellenname: schuelervermerke
  200. class Vermerk < Sequel::Model(:schuelervermerke)
  201. end
  202. # Schülerfotos als jpg
  203. #
  204. # Tabellenname: schuelerfotos
  205. class Schuelerfoto < Sequel::Model(:schuelerfotos)
  206. end
  207. # Schul-Tabelle
  208. #
  209. # Tabellenname: eigeneschule
  210. class Schule < Sequel::Model(:eigeneschule)
  211. end
  212. # Tabelle für Schild-Nutzer
  213. #
  214. # Tabellenname: users
  215. class Nutzer < Sequel::Model(:users)
  216. end
  217. end
  218. # ==SchildErweitert
  219. # Dieses Modul bindet das Schild-Modul ein und erweitert es mit zusätzlichen Methoden
  220. # zum einfachen Zugriff auf Schild-Methoden, die teilweise verschachtelt sind.
  221. # Ebenso bietet SchildErweitert alle Methoden mit Null-Objekten, d.h. es
  222. # gibt kein +nil+, nur Standardwerte.
  223. module SchildErweitert
  224. if Module.private_method_defined? :include
  225. # erst Ruby 2.1.0 macht include zu einer public-Methode
  226. class Module
  227. public :include
  228. end
  229. end
  230. # String und Symbol werden um snake_case ergänzt, das die Schild-Tabellen umbenennt
  231. # Legacy-Methoden aus alten Schild-Versionen wird teilweise auch unterstützt.
  232. module CoreExtensions
  233. # Patch für String
  234. module String
  235. # wandelt Strings in +Snake Case+ um.
  236. # Beispiel:
  237. # CamelCase.snake_case
  238. # => camel_case
  239. def snake_case
  240. return downcase if match(/\A[A-Z]+\z/)
  241. gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
  242. gsub(/([a-z])([A-Z])/, '\1_\2').
  243. downcase
  244. end
  245. end
  246. # Patch für Symbol
  247. module Symbol
  248. # snake_case für Symbol, verwandel Symbol in String
  249. def snake_case
  250. to_s.snake_case
  251. end
  252. end
  253. end
  254. # Schild hat teilweise nil in DB-Feldern. SchildTypeSaver gibt entweder einen
  255. # Leer-String zurück ("") oder bei strftime das 1899 Datum zurück.
  256. module SchildTypeSaver
  257. Symbol.include SchildErweitert::CoreExtensions::Symbol
  258. String.include CoreExtensions::String
  259. # es wird für jede Spalte in der Schild-Tabelle eine Ersatzmethode
  260. # erstellt, die bei nil ein Null-Objekt erstellt.
  261. # Dazu wird die neu angelegte Methode per MethodLogger gesichert.
  262. def self.included(klass)
  263. klass.columns.each do |column|
  264. name = column.snake_case
  265. MethodLogger::Methods.add(klass, name)
  266. # allow_nil ist als Argument optional und lässt bei +true+ alle Ergebnisse durch
  267. define_method(("_"+name.to_s).to_sym) {public_send(column)}
  268. define_method(name) do |allow_nil=false|
  269. ret = public_send(column)
  270. if allow_nil || ret
  271. ret = ret.strip if ret.class == String
  272. ret
  273. else
  274. create_null_object(klass, column)
  275. end
  276. end
  277. end
  278. end
  279. # Es wird ein Null-Objekt erstellt, das einen Standardwert zurückgibt.
  280. def create_null_object(klass, column)
  281. k = Sequel::Database::SCHEMA_TYPE_CLASSES[klass.db_schema[column][:type]]
  282. case
  283. # Sequel stellt :datetime als [Time, DateTime] dar, deswegen die Abfrage nach Array
  284. # Schild verwendet Time Objekte, wir machen das auch
  285. when k.class == Array then Time.new(1899)
  286. when k == Integer then 0
  287. when k == Float then 0.0
  288. # alle anderen types werden als Klasse zurückgegeben
  289. else k.new
  290. end
  291. end
  292. end
  293. # Halten wir Protokoll zu den erstellten Methoden
  294. # Ist brauchbar, wenn man z.B. noch extremer als der SchildTypeSaver arbeiten möchte
  295. module MethodLogger
  296. # Methoden-Klasse die alles Daten sammelt
  297. class Methods
  298. @@accessor_methods = {}
  299. # Eine Methode dem MethodLogger hinzufügen
  300. # @param [Class, method]
  301. def self.add(klass, meth)
  302. @@accessor_methods[klass] ||= []
  303. @@accessor_methods[klass] << meth
  304. end
  305. # Liste von Methoden für eine Klasse auslesen
  306. def self.list(klass=nil)
  307. klass ? @@accessor_methods[klass] : @@accessor_methods
  308. end
  309. end
  310. end
  311. # Mixin für Notenbezeichnungen
  312. module NotenHelfer
  313. # Noten können als Punkte abgerufen werden:
  314. # note[5] => "4-"
  315. # oder auch andersherum: note.index("4-") => 5
  316. @note = %w[6 5- 5 5+ 4- 4 4+ 3- 3 3+ 2- 2 2+ 1- 1 1+]
  317. # @param note [Integer]
  318. def self.punkte_aus_note(note)
  319. return if note.nil?
  320. @note.index(note)
  321. end
  322. # @param punkte [Integer]
  323. def self.note_aus_punkten(punkte)
  324. return unless punkte && punkte.to_i.between?(1,15) || punkte == "0"
  325. return punkte if ((punkte.to_i == 0) && (punkte.size > 1))
  326. return if (punkte.class == String) && punkte.empty?
  327. @note[punkte.to_i]
  328. end
  329. # Notenbezeichnung als String
  330. # @param ziffer [String]
  331. def note_s(ziffer)
  332. case ziffer
  333. when "1", "1+", "1-" then "sehr gut"
  334. when "2", "2+", "2-" then "gut"
  335. when "3", "3+", "3-" then "befriedigend"
  336. when "4", "4+", "4-" then "ausreichend"
  337. when "5", "5+", "5-" then "mangelhaft"
  338. when "6" then "ungenügend"
  339. when 'NB' then "––––––"
  340. when "E1" then "mit besonderem Erfolg teilgenommen"
  341. when "E2" then "mit Erfolg teilgenommen"
  342. when 'E3' then "teilgenommen"
  343. end
  344. end
  345. end
  346. # Klassen sind Konstanten. Deswegen alle auslesen, die Klassen behalten und
  347. # dynamisch neue Klassen mit gleichem Namen erstellen.
  348. # Automatisch SchildTypeSaver einbinden.
  349. #
  350. # Sollen zusätzliche Methoden eingebunden werden, muss - wie unten Schueler
  351. # und andere Klassen - die neu erstelle Klasse gepatcht werden.
  352. # Die alten Methoden bleiben erhalten, d.h. auch die TypeSaver-Methoden.
  353. Schild.constants.map {|name| Schild.const_get(name)}.select {|o| o.is_a?(Class)}.each do |klass|
  354. name = Schild.const_get(klass.to_s).name.split("::").last
  355. klass = Class.new(klass){include SchildTypeSaver}
  356. name = const_set(name, klass)
  357. end
  358. # Stellt die Schüler-Tabelle samt Assoziationen bereit.
  359. class Schueler
  360. # gibt das z.Zt. aktuelle Halbjahr zurück.
  361. def akt_halbjahr
  362. abschnitte.last
  363. end
  364. # gibt aus +jahr+ das Halbjahr +1+ oder +2+ zurück.
  365. def halbjahr(jahr, abschnitt)
  366. abschnitte_dataset.where(:jahr => jahr, :abschnitt => abschnitt).first
  367. end
  368. # gibt +Herr+ oder +Frau+ als Anrede für Schüler zurück.
  369. def anrede
  370. self.geschlecht == 3 ? "Herr" : "Frau"
  371. end
  372. # gibt die passende Bezeichnung zurück Schüler
  373. def schueler_in
  374. self.geschlecht == 3 ? "Schüler" : "Schülerin"
  375. end
  376. # gibt die passende Bezeichnung zurück Studierende
  377. def studierende_r
  378. self.geschlecht == 3 ? "Studierender" : "Studierende"
  379. end
  380. # gibt die jeweilige Berufsbezeichnung nach Geschlecht zurück.
  381. def berufsbezeichnung_mw
  382. return "Keine Fachklasse zugeordnet" if self.fachklasse.nil?
  383. self.geschlecht == 3 ? self.fachklasse.bezeichnung : self.fachklasse.beschreibung_w
  384. end
  385. # gibt +true+ zurück, wenn Schüler volljährig.
  386. def volljaehrig?
  387. self.volljaehrig == "+"
  388. end
  389. # gibt an, ob der Schüler zu einem Zeitpunkt *datum* volljährig war.
  390. def volljaehrig_bei?(datum)
  391. return false if datum.nil? || self.Geburtsdatum.nil?
  392. geb, datum = self.Geburtsdatum.to_date, datum.to_date
  393. (datum.year - geb.year - ((datum.month > geb.month || (datum.month == geb.month && datum.day >= geb.day)) ? 0 : 1)) >= 18
  394. end
  395. # fragt ab, ob in Schild ein Foto als hinterlegt eingetragen ist.
  396. def foto_vorhanden?
  397. !!(self.schuelerfoto && self.schuelerfoto.foto)
  398. end
  399. # gibt, wenn vorhanden, ein Foto als jpg-String zurück, ansonsten nil.
  400. def foto
  401. self.schuelerfoto.foto if self.foto_vorhanden?
  402. end
  403. end
  404. # Ist die Assoziation, die Halbjahre, sog. Abschnitte zurückgibt.
  405. class Abschnitt
  406. dataset_module do
  407. # filtert den Datensatz nach Jahr
  408. def jahr(i)
  409. where(:Jahr => i)
  410. end
  411. # filtert den Datensatz nach Halbjahr
  412. def halbjahr(i,j)
  413. jahr(i).where(:Abschnitt => j)
  414. end
  415. # filtert und gibt den Datensatz als Abschnitt des aktuellen Halbjahrs zurück
  416. def akt_halbjahr
  417. halbjahr(Time.new.year-1, 1).first
  418. end
  419. end
  420. # Hilfsmethode für die folgenden Methoden
  421. def faecher_nach_id(id)
  422. noten.select{ |n| n.fach.Fachgruppe_ID == id && n.AufZeugnis == '+' }.sort_by{ |n| n.fach.SortierungS2 }
  423. end
  424. # wählt alle berufsübergreifenden Fächer des gewählten Schülers in angegeben Halbjahr.
  425. def berufsuebergreifend
  426. faecher_nach_id 10
  427. end
  428. # wählt alle berufsbezogenen Fächer des gewählten Schülers in angegeben Halbjahr.
  429. def berufsbezogen
  430. faecher_nach_id 20
  431. end
  432. # wählt alle Fächer des Differenzierungsbreichs des gewählten Schülers in angegeben Halbjahr.
  433. def differenzierungsbereich
  434. faecher_nach_id 30
  435. end
  436. # wählt alle Fächergruppen aus.
  437. def faechergruppen
  438. [berufsuebergreifend, berufsbezogen, differenzierungsbereich]
  439. end
  440. # gibt den Namen des Klassenlehrers mit gekürztem Vornamen.
  441. def v_name_klassenlehrer
  442. return "Kein Klassenlehrer angelegt" if klassenlehrer.nil?
  443. v = klassenlehrer.vorname
  444. n = klassenlehrer.nachname
  445. "#{v[0]}. #{n}"
  446. end
  447. # gibt "Klassenlehrer" entsprechend Geschlecht zurück
  448. def klassenlehrer_in
  449. return "Kein Klassenlehrer angelegt" if klassenlehrer.nil?
  450. klassenlehrer.geschlecht == "3" ? "Klassenlehrer" : "Klassenlehrerin"
  451. end
  452. # gibt das aktuelle Schuljahr als String im Format "2014/15" zurück.
  453. def schuljahr
  454. jahr = self.jahr
  455. "#{jahr}/#{jahr-1999}"
  456. end
  457. end
  458. # Assoziation für Noten
  459. class Note
  460. include NotenHelfer
  461. # note in String umwandeln
  462. def note
  463. note_s self.noten_krz
  464. end
  465. # Bezeichnung des Fachs
  466. def bezeichnung
  467. fach.bezeichnung
  468. end
  469. # Die Fachgruppen-ID des Fachs
  470. def fachgruppe_ID
  471. fach.fachgruppe_id
  472. end
  473. end
  474. # Assoziation für BK-Abschlussdaten
  475. class BKAbschluss
  476. # Ist der Schüler zugelassen?
  477. def zulassung?
  478. self.Zulassung == "+"
  479. end
  480. # Ist der Schüler für den Berufsabschluss zugelassen?
  481. def zulassung_ba?
  482. self.ZulassungBA == "+"
  483. end
  484. # Hat der Schüler den Berufsabschluss bestanden?
  485. def bestanden_ba?
  486. self.BestandenBA == "+"
  487. end
  488. end
  489. # Assoziation für die jeweiligen BK-Prüfungsfächer
  490. class BKAbschlussFach
  491. include NotenHelfer
  492. # Wurde das Fach schriftlich geprüft?
  493. def fach_schriftlich?
  494. self.FachSchriftlich == "+"
  495. end
  496. # Wurde das Fach mündlich geprüft?
  497. def fach_muendlich?
  498. self.MdlPruefung == "+"
  499. end
  500. # holt die jeweilige Note aus der Tabelle.
  501. # Standard ist note_abschluss_ba, als Argument kann auch eine andere
  502. # verwendet werden (siehe Tabelle)
  503. def note(notenart=:note_abschluss_ba)
  504. note_s send(notenart)
  505. end
  506. end
  507. # Assoziation für Abi-Abschlussdaten
  508. class AbiAbschluss
  509. # Ist der Schüler zugelassen?
  510. def zulassung?
  511. self.Zugelassen == "+"
  512. end
  513. alias_method :zugelassen?, :zulassung?
  514. # Hat der Schüler die Abi-Prüfung bestanden?
  515. def bestanden_abi?
  516. self.PruefungBestanden == "+"
  517. end
  518. alias_method :pruefung_bestanden?, :bestanden_abi?
  519. # Latinum gemacht?
  520. def latinum?
  521. self.Latinum == "+"
  522. end
  523. # Kleines Latinum erreicht?
  524. def kl_latinum?
  525. self.KlLatinum == "+"
  526. end
  527. # Gräcum erreicht?
  528. def graecum?
  529. self.Graecum == "+"
  530. end
  531. # Hebraicum erreicht?
  532. def hebraicum?
  533. self.Hebraicum == "+"
  534. end
  535. end
  536. # Assoziation für die jeweiligen Abi-Prüfungsfächer
  537. class AbiAbschlussFach
  538. include NotenHelfer
  539. # Note aus Tebelle abfragen, Notenart angeben (siehe Tabelle)
  540. def note(notenart)
  541. note_s send(notenart)
  542. end
  543. end
  544. # Assoziation für die jeweiligen FHR-Prüfungsfächer
  545. class FHRAbschlussFach
  546. include NotenHelfer
  547. # Note aus Tebelle abfragen, Notenart angeben (siehe Tabelle)
  548. def note(notenart)
  549. note_s send(notenart)
  550. end
  551. end
  552. # Schul-Tabelle mit vereinfachtem Zugriff auf Datenfelder mittel class-Methoden
  553. class Schule
  554. # gibt die Schulnummer zurück
  555. def self.schulnummer
  556. self.first.schul_nr
  557. end
  558. # gibt den Namen des Schulleiters als V. Name zurück
  559. def self.v_name_schulleiter
  560. "#{self.first.schulleiter_vorname[0]}. #{self.first.schulleiter_name}"
  561. end
  562. # gibt die männliche bzw. weibliche Form des Schulleiters zurück
  563. def self.schulleiter_in
  564. self.first.schulleiter_geschlecht == 3 ? "Schulleiter" : "Schulleiterin"
  565. end
  566. # gibt den Ort der Schule zurück
  567. def self.ort
  568. self.first.ort
  569. end
  570. end
  571. # Tabelle der Schuld-Benutzer zum Abgleichen der Daten
  572. class Nutzer
  573. alias :name :us_name
  574. alias :login :us_login_name
  575. alias :passwort :us_password
  576. alias :password :passwort
  577. # prüft, ob das angegebene Passwort mit dem gespeicherten Passwort übereinstimmt
  578. def passwort?(passwort='')
  579. crypt(passwort) == self.passwort
  580. end
  581. alias :password? :passwort?
  582. # ver- bzw. entschlüsselt einen String mit dem Schild-Passwortalgorithmus
  583. def crypt(passwort)
  584. passwort.codepoints.map{|c| ((c/16)*32+15-c).chr}.join('')
  585. end
  586. end
  587. end