-- SPDX-FileCopyrightText: 2023 Steffen Jost -- -- SPDX-License-Identifier: AGPL-3.0-or-later {-# OPTIONS_GHC -fno-warn-unused-top-binds #-} module Utils.Print.RenewQualification 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') import Handler.Utils.Qualification (computeNewValidDate) defaultNotice :: Lang -> Bool -> Maybe Int -> Text -> Text -> Text -> [Text] defaultNotice l renewAuto elimit qualName qualShort newExpire = [intro <> renewal <> bequick <> outro, still_needed, switch_lang] -- list of separate paragraphs where intro :: Text | isDe l = [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. |] | otherwise = [st|A certificate for your records can only be generated immediately after a successful test. The certificate will be issued for the user login. The certificate and this letter may then prove that you have passed. |] renewal :: Text | not renewAuto = mempty | isDe l = [st|Bei erfolgreichem Abschluss der Schulung verlängert sich das Ablaufdatum automatisch auf den #{newExpire}. |] | otherwise = [st|Upon successful completion of the training, the expiry date will automatically be extended until #{newExpire}. |] bequick :: Text | isDe l = "Wir empfehlen die Schulung zeitnah durchzuführen. " | otherwise = "We recommend completing the training as soon as possible. " limit :: Text | Just n <- elimit, n > 0, isDe l = [st|innerhalb von #{n} Versuchen |] | Just n <- elimit, n > 0 = [st|within #{n} attempts |] | otherwise = mempty praxis :: Text | renewAuto = mempty | isDe l = "der Praxisteil und " | otherwise = "the practical part and " outro :: Text | isDe l = [st|Sollte bis zum Ablaufdatum #{praxis}das E-Learning nicht #{limit}erfolgreich abgeschlossen sein, muss zur Wiedererlangung der Fahrberechtigung „#{qualShort}“ ein Grundkurs #{qualName} bei der Fraport Fahrerausbildung absolviert werden.|] | otherwise = [st|The licence irrevocably expires, if #{praxis}the e-learning is not successfully completed #{limit}by the expiry date. In this case, regaining licence "#{qualShort}" requires the completing of a normal training course #{qualName} again, as if no prior experience existed.|] still_needed :: Text | isDe l = "Benötigen Sie die Fahrberechtigung nicht mehr, informieren Sie bitte die Fraport Fahrerausbildung." | otherwise = "Please inform us, if this driving licence is no longer required." switch_lang :: Text | isDe l = "(Please contact us if you prefer letters in English.)" | otherwise = "(Kontaktieren Sie uns bitte, um zukünftige Briefe von uns in deutscher Sprache zu erhalten.)" isAnyDrivingLicence :: Text -> Maybe Text -- isAnyDrivingLicence = firstJust (Text.stripSuffix "führerschein") . Text.words . Text.replace "-" " " . Text.replace "+" "" isAnyDrivingLicence = firstJust (Text.stripSuffix "führerschein") . Text.words . Text.map anyNonAlphaToBlank anyNonAlphaToBlank :: Char -> Char anyNonAlphaToBlank c | Char.isAlpha c = c | otherwise = ' ' qualificationText :: Lang -> Text -> Text -> (Text, Text, Text) -- (qarea, qformal, qlicence) i.e. (Rollfeld, Rollfeldfahrberechtigung, Rollfeldführerschein) translated qualificationText l _qName "GSS" | isDe l = ("Gabelstapler", "Fahrberechtigung Gabelstapler", "Gabelstaplerführerschein") | otherwise = ("forklift", "forklift driving licence", "forklift driving licence") qualificationText l qName@(isAnyDrivingLicence -> Just qPrefix) qShort | isDe l = (qPrefix, [st|Fahrberechtigung „#{qShort}“|], qName) | qShort == "F" = ("apron", [st|driving licence "#{qShort}"|], "apron driving licence") | Text.isPrefixOf "R" qShort = ("maneuvering area", [st|driving licence "#{qShort}"|], "maneuvering area driving licence") | otherwise = (qPrefix, qPrefix <> " driving licence", qName) qualificationText l qName qShort | isDe l = (qShort, [st|Fahrberechtigung „#{qShort}“|], qName) | otherwise = (qShort, [st|driving licence "#{qShort}"|], qName) data LetterRenewQualification = LetterRenewQualification { lmsLogin :: LmsIdent , lmsPin :: Text , qualHolderID :: UserId , qualHolderDN :: UserDisplayName , qualHolderSN :: UserSurname , qualExpiry :: Day , qualId :: QualificationId , qualName :: Text , qualShort :: Text , qualSchool :: SchoolId , qualDuration :: Maybe Int , qualRenewAuto :: Bool , qualELimit :: 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 LetterRenewQualificationData = LetterRenewQualificationData { lmsUrl, lmsUrlLogin, lmsUrlPassword, lmsIdent :: Text } deriving (Eq, Show) letterRenewalQualificationFData :: LetterRenewQualification -> LetterRenewQualificationData letterRenewalQualificationFData LetterRenewQualification{lmsLogin, lmsPin} = LetterRenewQualificationData{..} where lmsUrl = "drive.fraport.de" lmsUrlLogin = "https://" <> lmsUrl <> "/?username=" <> lmsIdent lmsUrlPassword = lmsUrlLogin <> "&password=" <> lmsPin lmsIdent = getLmsIdent lmsLogin instance MDLetter LetterRenewQualification where encryptPDFfor _ = PasswordUnderling getLetterKind _ = PinLetter getLetterEnvelope l = 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@LetterRenewQualification{..} = Just $ \DateTimeFormatter{ format } -> let LetterRenewQualificationData{..} = letterRenewalQualificationFData l in $(ihamletFile "templates/mail/body/qualificationRenewal.hamlet") letterMeta l@LetterRenewQualification{..} DateTimeFormatter{ format } lang Entity{entityKey=rcvrId, entityVal=User{userDisplayName}} = let LetterRenewQualificationData{..} = letterRenewalQualificationFData l isSupervised = rcvrId /= qualHolderID newExpire = computeNewValidDate (fromMaybe 0 qualDuration) qualExpiry (qArea, qFormal, qLicence) = qualificationText lang qualName qualShort in mkMeta $ guardMonoid isSupervised [ toMeta "supervisor" userDisplayName ] <> guardMonoid isReminder [ toMeta "reminder" ("reminder"::Text) ] <> guardMonoid (not qualRenewAuto) [ toMeta "practical" True -- note: definied or undefined matters, bool value is unimportant ] <> [ 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" lmsUrlPassword -- ok for PDF, since it contains the PIN already , toMeta "notice" $ defaultNotice lang qualRenewAuto qualELimit qualName qualShort $ format SelFormatDate newExpire , toMeta "de-subject" [st|Verlängerung Fahrberechtigung „#{qualShort}“ (#{qualName})|] , toMeta "en-subject" [st|Renewal of driving licence "#{qualShort}" (#{qualName})|] , toMeta "de-opening" $ bool [st|Guten Tag #{qualHolderDN},|] [st|Guten Tag #{userDisplayName},|] isSupervised , toMeta "en-opening" $ bool [st|Dear #{qualHolderDN},|] [st|Dear #{userDisplayName},|] isSupervised , toMeta "qarea" qArea , toMeta "qformal" qFormal , toMeta "qlicence" qLicence ] -- NOTE: use [st|some simple text with interpolation|] getPJId LetterRenewQualification{..} = PrintJobIdentification { pjiName = bool "Renewal" "Renewal Reminder" isReminder , pjiApcAcknowledge = "lms-" <> getLmsIdent lmsLogin , pjiRecipient = Nothing -- to be filled later , pjiSender = Nothing , pjiAffected = Just qualHolderID , 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]) }