refactor(letter): first test version of new letters

This commit is contained in:
Steffen Jost 2024-05-23 18:18:13 +02:00
parent 9451d90a9e
commit 9814712c61
9 changed files with 470 additions and 2156 deletions

View File

@ -25,7 +25,8 @@ import qualified Database.Esqueleto.Legacy as E
import qualified Database.Esqueleto.Utils as E
import Database.Esqueleto.Utils.TH
import Utils.Print
import Utils.Print hiding (LetterRenewQualificationF)
import Utils.Print.RenewQualification
import qualified Data.Aeson as Aeson
-- import qualified Data.Text as Text
@ -82,7 +83,7 @@ lrqf2letter LRQF{..}
usr <- getUser lrqfUser
rcvr <- mapM getUser lrqfSuper
now <- liftIO getCurrentTime
let letter = LetterRenewQualificationF
let letter = LetterRenewQualification
{ lmsLogin = lrqfIdent
, lmsPin = lrqfPin
, qualHolderID = usr ^. _entityKey

View File

@ -23,6 +23,7 @@ module Utils.Print
-- , MDLetter
, SomeLetter(..)
, LetterRenewQualificationF(..)
-- , LetterRenewQualification(..)
, LetterExpireQualification(..)
-- , LetterCourseCertificate()
, makeCourseCertificates
@ -59,7 +60,8 @@ import Jobs.Handler.SendNotification.Utils
import Utils.Print.Instances ()
import Utils.Print.Letters
import Utils.Print.SomeLetter
import Utils.Print.RenewQualification
import Utils.Print.RenewQualificationF
import Utils.Print.RenewQualification()
import Utils.Print.ExpireQualification
import Utils.Print.CourseCertificate

View File

@ -129,6 +129,7 @@ defWriterOpts t = def { P.writerExtensions = P.pandocExtensions, P.writerTemplat
data LetterKind = Din5008 -- scrlttr2: Standard postal letter with address field, expects peprinted FraportLogo
| PinLetter -- Like Din5008, but for special paper with a protected pin field
| PinNew -- New Variant for Pin Letters for R. TODO: Remove/rename/replace PinLetter
| Plain -- scrartcl: Empty, expects empty paper with no preprints
| PlainLogo -- Like plain, but expects to be printed on paper with Logo
-- | Logo -- Like plain, but prints Fraport Logo in the upper right corner
@ -139,15 +140,18 @@ templateLatex =
let
tDin5008 = decodeUtf8 $(Data.FileEmbed.embedFile "templates/letter/din5008.latex")
tPinLetter = decodeUtf8 $(Data.FileEmbed.embedFile "templates/letter/din5008with_pin.latex")
tPinNew = decodeUtf8 $(Data.FileEmbed.embedFile "templates/letter/din5008with_pin_new.latex")
tPlain = decodeUtf8 $(Data.FileEmbed.embedFile "templates/letter/plain_article.latex")
in \case
PinLetter -> tPinLetter
PinNew -> tPinNew
Din5008 -> tDin5008
PlainLogo -> tPlain
Plain -> tPlain
paperKind :: LetterKind -> Text -- Muss genau 5 Zeichen haben!
paperKind PinLetter = "a4pin" -- Pin-Brief
paperKind PinNew = "a4pin" -- Pin-Brief
paperKind Plain = "a4wht" -- Ohne Logo
paperKind Din5008 = "a4log" -- Mit Logo
paperKind PlainLogo = "a4log"

View File

@ -19,7 +19,7 @@ import Utils.Print.Letters
import Handler.Utils.Widgets (nameHtml) -- , nameHtml')
data LetterRenewQualificationF = LetterRenewQualificationF
data LetterRenewQualification = LetterRenewQualification
{ lmsLogin :: LmsIdent
, lmsPin :: Text
, qualHolderID :: UserId
@ -37,30 +37,31 @@ data LetterRenewQualificationF = LetterRenewQualificationF
-- this datatype is specific to this letter only, and just to avoid code duplication for derived data or constants
data LetterRenewQualificationFData = LetterRenewQualificationFData { lmsUrl, lmsUrlLogin, lmsIdent :: Text }
data LetterRenewQualificationData = LetterRenewQualificationData { lmsUrl, lmsUrlLogin, lmsIdent :: Text }
deriving (Eq, Show)
letterRenewalQualificationFData :: LetterRenewQualificationF -> LetterRenewQualificationFData
letterRenewalQualificationFData LetterRenewQualificationF{lmsLogin} = LetterRenewQualificationFData{..}
letterRenewalQualificationFData :: LetterRenewQualification -> LetterRenewQualificationData
letterRenewalQualificationFData LetterRenewQualification{lmsLogin} = LetterRenewQualificationData{..}
where
lmsUrl = "https://drive.fraport.de"
lmsUrlLogin = lmsUrl <> "/?login=" <> lmsIdent
lmsUrl = "drive.fraport.de"
lmsUrlLogin = "https://" <> lmsUrl <> "/?login=" <> lmsIdent
lmsIdent = getLmsIdent lmsLogin
instance MDLetter LetterRenewQualificationF where
instance MDLetter LetterRenewQualification where
encryptPDFfor _ = PasswordUnderling
getLetterKind _ = PinLetter
getLetterKind _ = PinNew
getLetterEnvelope _ = 'f' -- maybe 'q' (Char.toLower . fst) $ Text.uncons (qualShort l)
getTemplate _ = decodeUtf8 $(Data.FileEmbed.embedFile "templates/letter/fraport_renewal.md")
getTemplate _ = decodeUtf8 $(Data.FileEmbed.embedFile "templates/letter/fraport_renewal_new.md")
getMailSubject l = SomeMessage $ MsgMailSubjectQualificationRenewal $ qualShort l
getMailBody l@LetterRenewQualificationF{..} = Just $ \DateTimeFormatter{ format } ->
let LetterRenewQualificationFData{..} = letterRenewalQualificationFData l
getMailBody l@LetterRenewQualification{..} = Just $ \DateTimeFormatter{ format } ->
let LetterRenewQualificationData{..} = letterRenewalQualificationFData l
in $(ihamletFile "templates/mail/body/qualificationRenewal.hamlet")
letterMeta l@LetterRenewQualificationF{..} DateTimeFormatter{ format } lang Entity{entityKey=rcvrId, entityVal=User{userDisplayName}} =
let LetterRenewQualificationFData{..} = letterRenewalQualificationFData l
letterMeta l@LetterRenewQualification{..} DateTimeFormatter{ format } lang Entity{entityKey=rcvrId, entityVal=User{userDisplayName}} =
let LetterRenewQualificationData{..} = letterRenewalQualificationFData l
isSupervised = rcvrId /= qualHolderID
newExpire = addDays (fromIntegral $ fromMaybe 0 qualDuration) qualExpiry
in mkMeta $
guardMonoid isSupervised
[ toMeta "supervisor" userDisplayName
@ -79,10 +80,15 @@ instance MDLetter LetterRenewQualificationF where
, mbMeta "validduration" (show <$> qualDuration)
, toMeta "url-text" lmsUrl
, toMeta "url" lmsUrlLogin
, toMeta "notice" [ [st|Ein Zertifikat für Ihre Unterlagen kann nur direkt nach dem erfolgreichen Test erstellt werden. Das Zertifikat wird auf die Benutzerkennung ausgestellt. Zusammen mit diesem Schreiben können Sie Ihrem Arbeitgeber zeigen, dass Sie bestanden haben. Bei erfolgreichem Abschluss der Schulung verlängert sich das Ablaufdatum automatisch auf den #{format SelFormatDate newExpire}. Wir empfehlen die Schulung zeitnah durchzuführen. Sollte bis zum Ablaufdatum das E-Learning nicht erfolgreich abgeschlossen sein oder der Test nach 5 Versuchen nicht bestanden werden, muss zur Wiedererlangung der Fahrberechtigung #{qualShort} ein Grundkurs #{qualName} bei der Fahrerausbildung absolviert werden.|]
, "Benötigen Sie die Fahrberechtigung nicht mehr, informieren Sie bitte die Fahrerausbildung."::Text
, "(Please contact us if you prefer letters in English.)"
]
, toMeta "de-subject" [st|Verlängerung Fahrberechtigung #{qualShort} (#{qualName})|]
, toMeta "en-subject" [st|Renewal of driving licence #{qualShort} (#{qualName})|]
] -- TODO use [st|some simple text with interpolation|]
]
getPJId LetterRenewQualificationF{..} =
getPJId LetterRenewQualification{..} =
PrintJobIdentification
{ pjiName = bool "Renewal" "Renewal Reminder" isReminder
, pjiApcAcknowledge = "lms-" <> getLmsIdent lmsLogin

View File

@ -0,0 +1,100 @@
-- SPDX-FileCopyrightText: 2023 Steffen Jost <jost@tcs.ifi.lmu.de>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later
{-# OPTIONS_GHC -fno-warn-unused-top-binds #-}
module Utils.Print.RenewQualificationF where
import Import
import Text.Hamlet
-- import Data.Char as Char
-- import qualified Data.Text as Text
import qualified Data.CaseInsensitive as CI
import Data.FileEmbed (embedFile)
import Utils.Print.Letters
import Handler.Utils.Widgets (nameHtml) -- , nameHtml')
data LetterRenewQualificationF = LetterRenewQualificationF
{ lmsLogin :: LmsIdent
, lmsPin :: Text
, qualHolderID :: UserId
, qualHolderDN :: UserDisplayName
, qualHolderSN :: UserSurname
, qualExpiry :: Day
, qualId :: QualificationId
, qualName :: Text
, qualShort :: Text
, qualSchool :: SchoolId
, qualDuration :: Maybe Int
, isReminder :: Bool
}
deriving (Eq, Show)
-- this datatype is specific to this letter only, and just to avoid code duplication for derived data or constants
data LetterRenewQualificationFData = LetterRenewQualificationFData { lmsUrl, lmsUrlLogin, lmsIdent :: Text }
deriving (Eq, Show)
letterRenewalQualificationFData :: LetterRenewQualificationF -> LetterRenewQualificationFData
letterRenewalQualificationFData LetterRenewQualificationF{lmsLogin} = LetterRenewQualificationFData{..}
where
lmsUrl = "https://drive.fraport.de"
lmsUrlLogin = lmsUrl <> "/?login=" <> lmsIdent
lmsIdent = getLmsIdent lmsLogin
instance MDLetter LetterRenewQualificationF where
encryptPDFfor _ = PasswordUnderling
getLetterKind _ = PinLetter
getLetterEnvelope _ = 'f' -- maybe 'q' (Char.toLower . fst) $ Text.uncons (qualShort l)
getTemplate _ = decodeUtf8 $(Data.FileEmbed.embedFile "templates/letter/fraport_renewal.md")
getMailSubject l = SomeMessage $ MsgMailSubjectQualificationRenewal $ qualShort l
getMailBody l@LetterRenewQualificationF{..} = Just $ \DateTimeFormatter{ format } ->
let LetterRenewQualificationFData{..} = letterRenewalQualificationFData l
in $(ihamletFile "templates/mail/body/qualificationRenewal.hamlet")
letterMeta l@LetterRenewQualificationF{..} DateTimeFormatter{ format } lang Entity{entityKey=rcvrId, entityVal=User{userDisplayName}} =
let LetterRenewQualificationFData{..} = letterRenewalQualificationFData l
isSupervised = rcvrId /= qualHolderID
in mkMeta $
guardMonoid isSupervised
[ toMeta "supervisor" userDisplayName
, toMeta "de-opening" ("Sehr geehrte Damen und Herren,"::Text)
, toMeta "en-opening" ("Dear Sir or Madam,"::Text)
] <>
guardMonoid isReminder
[ toMeta "reminder" ("reminder"::Text)
] <>
[ toMeta "lang" lang
, toMeta "login" lmsIdent
, toMeta "pin" lmsPin
, toMeta "examinee" qualHolderDN
, toMeta "subject-meta" qualHolderDN
, toMeta "expiry" (format SelFormatDate qualExpiry)
, mbMeta "validduration" (show <$> qualDuration)
, toMeta "url-text" lmsUrl
, toMeta "url" lmsUrlLogin
]
getPJId LetterRenewQualificationF{..} =
PrintJobIdentification
{ pjiName = bool "Renewal" "Renewal Reminder" isReminder
, pjiApcAcknowledge = "lms-" <> getLmsIdent lmsLogin
, pjiRecipient = Nothing -- to be filled later
, pjiSender = Nothing
, pjiCourse = Nothing
, pjiQualification = Just qualId
, pjiLmsUser = Just lmsLogin
, pjiFileName = "renew_" <> CI.original (unSchoolKey qualSchool) <> "-" <> qualShort <> "_" <> qualHolderSN
-- let nameRecipient = abbrvName <$> recipient
-- nameSender = abbrvName <$> sender
-- nameCourse = CI.original . courseShorthand <$> course
-- nameQuali = CI.original . qualificationShorthand <$> quali
-- in .. = T.replace " " "-" (T.intercalate "_" . catMaybes $ [Just printJobName, nameQuali, nameCourse, nameSender, nameRecipient])
}

View File

@ -0,0 +1,206 @@
%Based upon https://github.com/benedictdudel/pandoc-letter-din5008
\documentclass[
paper=A4,
foldmarks=BTm, % show foldmarks top, middle, bottom
foldmarks=false, % don't print foldmarks
fromalign=left, % letter head on the right
fromphone=true, % show phone number
fromemail=true, % show email
fromlogo=false, % don't show logo in letter head
version=last, % latest version of KOMA letter
pagenumber=botright, % show pagenumbers on bottom right
firstfoot=false % first-page footer
]{scrlttr2}
\PassOptionsToPackage{hyphens}{url}
\PassOptionsToPackage{unicode$for(hyperrefoptions)$,$hyperrefoptions$$endfor$}{hyperref}
\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available
\IfFileExists{bookmark.sty}{\usepackage{bookmark}}{\usepackage{hyperref}}
\hypersetup{
$if(subject-meta)$
pdfsubject={$subject-meta$},
$endif$
$if(author-meta)$
pdfauthor={$author-meta$},
$endif$
$if(lang)$
pdflang={$lang$},
$endif$
$if(is-de)$
$if(de-subject)$
pdftitle={$de-subject$},
$endif$
$else$
$if(en-subject)$
pdftitle={$en-subject$},
$endif$
$endif$
$if(apc-ident)$
pdfkeywords={$apc-ident$},
$endif$
}
\usepackage{url}
\usepackage{iftex}
%\usepackage[ngerman]{babel}
$if(lang)$
\ifLuaTeX
\usepackage[bidi=basic]{babel}
\else
\usepackage[bidi=default]{babel}
\fi
\babelprovide[main,import]{$babel-lang$}
$for(babel-otherlangs)$
\babelprovide[import]{$babel-otherlangs$}
$endfor$
% get rid of language-specific shorthands (see #6817):
\let\LanguageShortHands\languageshorthands
\def\languageshorthands#1{}
$endif$
\ifLuaTeX
\usepackage{selnolig} % disable illegal ligatures
\fi
\usepackage[sfdefault]{roboto}
\ifPDFTeX
\usepackage[$if(fontenc)$$fontenc$$else$T1$endif$]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{textcomp} % provide euro and other symbols
% \usepackage{DejaVuSansMono} % better monofont
\else
% if luatex or xetex
\usepackage{fontspec}
% \setmonofont{DejaVu Sans Mono}
\fi
\renewcommand{\familydefault}{\sfdefault}
$if(mathspec)$
\ifXeTeX
\usepackage{mathspec}
\else
\usepackage{unicode-math}
\fi
$else$
\usepackage{unicode-math}
$endif$
%\usepackage[a4paper, bottom=8cm, top=3cm]{geometry} %%% THIS HAD NO EFFECT AT ALL
\usepackage{parskip}% might be useful for pandoc tightlist
\usepackage{graphics}
\usepackage{xcolor}
\usepackage{booktabs}
\usepackage{longtable}
\usepackage[right]{eurosym}
\usepackage{enumitem}
\makeatletter
\setplength{firstheadvpos}{1.8cm}
\setplength{toaddrvpos}{5.5cm}
\setlength{\@tempskipa}{-1.2cm}%
\@addtoplength{toaddrheight}{\@tempskipa}
\makeatother
\setlength{\oddsidemargin}{\useplength{toaddrhpos}}
\addtolength{\oddsidemargin}{-1in}
\setlength{\textwidth}{\useplength{firstheadwidth}}
\usepackage[absolute,quiet,overlay]{textpos}%,showboxes
\setlength{\TPHorizModule}{1mm}
\setlength{\TPVertModule}{1mm}
\providecommand{\tightlist}{%
\setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}
\begin{document}%
\setkomavar{fromname}{$author$}%
\renewcommand*{\raggedsignature}{\raggedright}%
\setkomavar{fromaddress}{%
$for(return-address)$%
$return-address$$sep$\\
$endfor$
}
\setkomavar{fromphone}{$phone$}
\setkomavar{fromemail}{$email$}
%if there is a handwritten signature
%\setkomavar{signature}{$author$}
%if there is no handwritten signature
\setkomavar{signature}{}
\setplength{sigbeforevskip}{-\baselineskip}
\setkomavar{date}{$date$}
\setkomavar{place}{$place$}
$if(is-de)$
\setkomavar{subject}{$de-subject$}
$else$
\setkomavar{subject}{$en-subject$}
$endif$
\begin{letter}{%
$for(address)$
$address$$sep$\\
$endfor$
}
$if(apc-ident)$
\begin{textblock}{200}(5,5)%hpos,vpos
\textcolor{white!0}{$apc-ident$}%
\end{textblock}%
$endif$
$if(is-de)$
\opening{$de-opening$}
$else$
\opening{$en-opening$}
$endif$
\begin{textblock}{65}(84,232)%hpos,vpos
\textcolor{black!39}{
\begin{labeling}{Password:}%Achtung! Die Position des Logins muss sprachunabhängig immer an der gleichen Position sein, sonst kannn die Rückmeldung der Druckerei den Ident nicht mehr identifizieren!
$if(is-de)$
\item[Benutzer:] \texttt{$login$}
\item[Passwort:] \texttt{$pin$}
$else$
\item[User:] \texttt{$login$}
\item[Password:] \texttt{$pin$}
$endif$
\end{labeling}
~}
\end{textblock}
$body$
$if(is-de)$
\closing{$de-closing$}
$else$
\closing{$en-closing$}
$endif$
%\ps $postskriptum$
$if(encludes)$
\setkomavar*{enclseparator}{Anlage}
\encl{$encludes$}
$endif$
$if(notice)$
\begin{textblock}{170}(20,258)%hpos,vpos
\scriptsize
\textbf{Hinweise für den Schulungsteilnehmer:}
\newline
$for(notice)$
$notice$
$sep$\newline
$endfor$
\end{textblock}
$endif$
\end{letter}
\end{document}

View File

@ -86,6 +86,8 @@ $else$
$endif$
Die Durchführung des Lernprogramms und des Abschlusstests dauert etwa 2,5h.
This is the new version
Fahrberechtigungsinhaber
: $examinee$

View File

@ -0,0 +1,130 @@
---
### Metadaten, welche hier eingestellt werden:
# Absender
de-subject: 'Verlängerung Fahrberechtigung "F" (Vorfeldführerschein)'
en-subject: Renewal of apron driving license
author: Fraport AG - Fahrerausbildung (AVN-AR)
phone: +49 69 690-30306
email: fahrerausbildung@fraport.de
place: Frankfurt am Main
return-address:
- 60547 Frankfurt
de-opening: Liebe Fahrberechtigungsinhaber,
en-opening: Dear driver,
de-closing: |
Mit freundlichen Grüßen,
Ihre Fraport Fahrerausbildung
en-closing: |
With kind regards,
Your Fraport Driver Training
encludes:
hyperrefoptions: hidelinks
### Metadaten, welche automatisch ersetzt werden:
url-text: 'drive.fraport.de'
url: 'https://drive.fraport.de'
date: 11.11.1111
expiry: 00.00.0000
lang: de-de
is-de: true
login: 123456
pin: abcdef
paper: pin
# Emfpänger
examinee: P. Rüfling
address:
- E. M. Pfänger
- Musterfirma GmbH
- Musterstraße 11
- 12345 Musterstadt
...
$if(titleblock)$
$titleblock$
$endif$
$for(header-includes)$
$header-includes$
$endfor$
$for(include-before)$
$include-before$
$endfor$
$if(is-de)$
<!-- deutsche Version des Briefes -->
um die Rollfeldfahrberechtigung von \textbf{$examinee$} zu erhalten, benötigen wir bis zum $date$ den Nachweis, dass die theoretische und praktische flughafenspezifische Rollfeld Recurrent Schulung der Fraport AG gemäß Verordnung der Europäische Union Nr. 139/2014 absolviert wurde.
Die Online-Schulung der Fraport AG ist erreichbar unter folgendem Link:
[$url-text$]($url$)
Der erforderliche Benutzername und das Passwort für die Fraport Online-Schulung finden Sie untenstehend. Die Weitergabe der persönlichen Benutzerdaten an Dritte ist untersagt. Ausschließlich Sie sind berechtigt, die Benutzerdaten an den Schulungsteilnehmer auszuhändigen.
Für die Absolvierung der Schulungsmaßnahme werden 1-2 Stunden benötigt. Der Abschluss der Schulung wird automatisch an das System der Fahrerausbildung übermittelt.
Nach erfolgreichem Abschluss der Online-Schulung muss \textbf{$examinee$} sich von Ihrer Firma zum praktischen Teil der Schulung einplanen lassen. Im Rahmen der 3--4-stündigen praktischen Auffrischung erfolgen Funkübungen sowie die Durchführung einer Übungsfahrt mit Prüfungscharakter im Start-/Landebahnsystem.
$else$
<!-- englische Version des Briefes -->
$if(reminder)$
this is a last **reminder**: as of $date$,
$if(supervisor)$
$examinee$ has
$else$
you have
$endif$
not yet completed the below detailed elearning.
The qualification will expire automatically,
if the elearning is not concluded in time!
$else$
$if(supervisor)$
the apron diving license of $examinee$
$else$
your apron diving license
$endif$
is about to expire soon.
$endif$
The validity will be extended
$if(validduration)$
by $validduration$ months
$endif$
by successfully participating in
an elearning.
$if(supervisor)$
Supervisors are kindly requested to forward the login data
below confidentially to the examinee.
$else$
Please use the login data from the protected area below.
$endif$
Reserve 2.5h for the entire e-learning, including the exam.
Examinee
: $examinee$
Expiry
: $expiry$
E-learning website
: [$url-text$]($url$)
If the apron driving license expires before completing this e-learning,
$if(supervisor)$
the examinee has to participate in a basic training course again to regain
to regain the apron driving licence.
$else$
you have to participate in a basic training course again to regain
your apron driving licence.
$endif$
Please contact the Fraport driving school team, if you need any assistance.
(Kontaktieren Sie uns bitte, wenn Sie zukünftige Briefe in deutscher Sprache bevorzugen.)
$endif$

File diff suppressed because it is too large Load Diff