Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3b0029ba04 | |||
| e554048f5a | |||
| e59fff352f | |||
| e9d4174b83 | |||
| 90613faf72 | |||
| 6a070a6775 | |||
| ea113cf57a | |||
| 6ffc49ae0e | |||
| ab8b17229a | |||
| 74f7633837 |
@ -2,6 +2,14 @@
|
|||||||
|
|
||||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||||
|
|
||||||
|
## [27.4.79](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v27.4.78...v27.4.79) (2024-09-10)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **notifications:** fix [#180](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/issues/180) qualification expiry notification are sent only once ([74f7633](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/74f7633837870448f7cab1013719f42ab49941fe))
|
||||||
|
* **supervision:** fix [#181](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/issues/181) by unifying deletion of supervision ([6a070a6](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/6a070a67756bd4ef4b9b5efc176f34c7ed183f1a))
|
||||||
|
|
||||||
## [27.4.78](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v27.4.77...v27.4.78) (2024-09-05)
|
## [27.4.78](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v27.4.77...v27.4.78) (2024-09-05)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
# SPDX-FileCopyrightText: 2023 Steffen Jost <s.jost@fraport.de>
|
# SPDX-FileCopyrightText: 2023-24 Steffen Jost <s.jost@fraport.de>
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
@ -15,11 +15,15 @@ FirmActionInfo: Betrifft alle Firmenangehörigen unter Ihrer Aufsicht.
|
|||||||
FirmActNotify: Mitteilung versenden
|
FirmActNotify: Mitteilung versenden
|
||||||
FirmActResetSupervision: Ansprechpartner für alle Firmenangehörigen zurücksetzen
|
FirmActResetSupervision: Ansprechpartner für alle Firmenangehörigen zurücksetzen
|
||||||
FirmActResetSuperKeep: Bisherige Ansprechpartner der Firmenangehörigen zusätzlich beibehalten?
|
FirmActResetSuperKeep: Bisherige Ansprechpartner der Firmenangehörigen zusätzlich beibehalten?
|
||||||
|
FirmActRemoveSupers: Alle rein firmenbezogenen Ansprechpartnerbeziehungen für diese Personen entfernen?
|
||||||
FirmActResetMutualSupervision: Ansprechpartner beaufsichtigen sich gegenseitig
|
FirmActResetMutualSupervision: Ansprechpartner beaufsichtigen sich gegenseitig
|
||||||
|
FirmActResetSupersKeepAll: Alle behalten
|
||||||
|
FirmActResetSupersRemoveAps: Nur Standardansprechpartner entfernen
|
||||||
|
FirmActResetSupersRemoveAll: Alle entfernen
|
||||||
FirmActAddSupervisors: Ansprechpartner hinzufügen
|
FirmActAddSupervisors: Ansprechpartner hinzufügen
|
||||||
FirmActAddSupersEmpty: Es konnten keine Ansprechpartner hinzugefügt werden
|
FirmActAddSupersEmpty: Es konnten keine Ansprechpartner hinzugefügt werden
|
||||||
FirmActAddSupersSet n@Int64 postal@(Maybe Bool): #{n} Standardansprechpartner geändert #{maybeBoolMessage postal "" "und auf Briefversand geschaltet" "und Benachrichtigungen per Email gesetzt"}, aber nicht nicht aktiviert.
|
FirmActAddSupersSet n@Int64 postal@(Maybe Bool): #{n} Standardansprechpartner geändert #{maybeBoolMessage postal "" "und auf Briefversand geschaltet" "und Benachrichtigungen per Email gesetzt"}, aber nicht nicht aktiviert.
|
||||||
RemoveSupervisors ndef@Int64 nact@Int64: #{ndef} Standard Ansprechpartner entfernt#{bool ", aber keine aktiven Ansprechpartnerbeziehungen wurden deaktiviert" (", " <> tshow nact <> " aktive Ansprechpartnerbeziehungen gelöscht") (nact > 0)}
|
RemoveSupervisors ndef@Int64: #{ndef} Standardansprechpartner entfernt.
|
||||||
FirmActChangeContactUser: Kontaktinformationen von allen Firmenangehörigen ändern
|
FirmActChangeContactUser: Kontaktinformationen von allen Firmenangehörigen ändern
|
||||||
FirmActChangeContactFirm: Kontaktinformationen der Firma ändern
|
FirmActChangeContactFirm: Kontaktinformationen der Firma ändern
|
||||||
FirmActChangeContactFirmInfo: Firmenkontaktinformationen werden nur für neue Firmenangehörige verwendet, für die sonst keine Kontaktinformationen vorliegen.
|
FirmActChangeContactFirmInfo: Firmenkontaktinformationen werden nur für neue Firmenangehörige verwendet, für die sonst keine Kontaktinformationen vorliegen.
|
||||||
@ -33,7 +37,8 @@ FirmUserActRemove: Firmenassoziation entfernen
|
|||||||
FirmUserActMkSuper: Zum Firmenansprechpartner ernennen
|
FirmUserActMkSuper: Zum Firmenansprechpartner ernennen
|
||||||
FirmUserActChangeDetailsResult n@Int64 t@Int64: Firmenassoziation von #{n}/#{t} #{pluralDE n "Firmenangehörigen" "Firmenangehörige"} wurden aktualisiert
|
FirmUserActChangeDetailsResult n@Int64 t@Int64: Firmenassoziation von #{n}/#{t} #{pluralDE n "Firmenangehörigen" "Firmenangehörige"} wurden aktualisiert
|
||||||
FirmUserActChangeResult n@Int64 t@Int64: Benachrichtigungseinstellung für #{n}/#{t} #{pluralDE n "Firmenangehörigen" "Firmenangehörige"} wurden geändert
|
FirmUserActChangeResult n@Int64 t@Int64: Benachrichtigungseinstellung für #{n}/#{t} #{pluralDE n "Firmenangehörigen" "Firmenangehörige"} wurden geändert
|
||||||
FirmuserActRemoveResult uc@Int64 sup@Int64 sub@Int64: #{uc} #{pluralDE uc "Firmenassoziation" "Firmenassoziationen"} entfernt. #{noneMoreDE sup "" (tshow sup <> "Ansprechpartnerbeziehungen wegen entferntem Ansprechpartner gelöschtt. ")} #{noneMoreDE sub "" (tshow sup <> "Ansprechpartnerbeziehungen wegen entfernten Angesprochenen gelöscht.")}
|
FirmUserActRemoveResult uc@Int64: #{uc} #{pluralDE uc "Firmenassoziation" "Firmenassoziationen"} entfernt.
|
||||||
|
FirmRemoveSupervision sup@Int64 sub@Int64: #{noneMoreDE sup "" (tshow sup <> " Ansprechpartnerbeziehungen wegen entferntem Ansprechpartner gelöscht. ")} #{noneOneMoreDE sub "Keine Ansprechpartnerbeziehung" "Eine Ansprechpartnerbeziehung" (tshow sup <> " Ansprechpartnerbeziehungen")} wegen entferntem Angesprochenem gelöscht.
|
||||||
FirmNewSupervisor: Neue individuelle Ansprechpartner hinzufügen
|
FirmNewSupervisor: Neue individuelle Ansprechpartner hinzufügen
|
||||||
FirmSetSupervisor: Existierende Ansprechpartner hinzufügen
|
FirmSetSupervisor: Existierende Ansprechpartner hinzufügen
|
||||||
FirmSetSupersReport nusr@Int64 nspr@Int64 nrem@Int64: Für #{nusr} Firmenangehörige wurden #{nspr} individuelle Ansprechpartner eingetragen#{bool "." (" und " <> tshow nrem <> " individuelle Ansprechpartnerbeziehungen gelöscht.") (nrem >0)}
|
FirmSetSupersReport nusr@Int64 nspr@Int64 nrem@Int64: Für #{nusr} Firmenangehörige wurden #{nspr} individuelle Ansprechpartner eingetragen#{bool "." (" und " <> tshow nrem <> " individuelle Ansprechpartnerbeziehungen gelöscht.") (nrem >0)}
|
||||||
@ -42,7 +47,7 @@ FirmSuperActNotify: Mitteilung versenden
|
|||||||
FirmSuperActSwitchSuper: Standard Firmenansprechpartner abändern
|
FirmSuperActSwitchSuper: Standard Firmenansprechpartner abändern
|
||||||
FirmSuperActSwitchSuperInfo: Betrifft keine firmenfremden Ansprechpartner und ändert keine aktiven individuellen Ansprechpartnerbeziehungen. Gegebenfalls im Anschluss die Funktion "Ansprechpartner auf Firmenstandard zurücksetzen" nutzen.
|
FirmSuperActSwitchSuperInfo: Betrifft keine firmenfremden Ansprechpartner und ändert keine aktiven individuellen Ansprechpartnerbeziehungen. Gegebenfalls im Anschluss die Funktion "Ansprechpartner auf Firmenstandard zurücksetzen" nutzen.
|
||||||
FirmSuperActRMSuperDef: Firmenansprechpartner entfernen
|
FirmSuperActRMSuperDef: Firmenansprechpartner entfernen
|
||||||
FirmSuperActRMSuperActive: Auch aktive Ansprechpartnerbeziehungen innerhalb dieser Firma beenden
|
FirmSuperActRMSuperActive: Aktive Ansprechpartnerbeziehungen innerhalb dieser Firma beenden?
|
||||||
FirmsNotification: Firmen E-Mail versenden
|
FirmsNotification: Firmen E-Mail versenden
|
||||||
FirmNotification fsh@CompanyShorthand: E-Mail an #{fsh} senden
|
FirmNotification fsh@CompanyShorthand: E-Mail an #{fsh} senden
|
||||||
FirmsNotificationTitle: Firmen benachrichtigen
|
FirmsNotificationTitle: Firmen benachrichtigen
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
# SPDX-FileCopyrightText: 2023 Steffen Jost <s.jost@fraport.de>
|
# SPDX-FileCopyrightText: 2023-24 Steffen Jost <s.jost@fraport.de>
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
@ -15,11 +15,15 @@ FirmActionInfo: Affects alle company associates under your supervision.
|
|||||||
FirmActNotify: Send message
|
FirmActNotify: Send message
|
||||||
FirmActResetSupervision: Reset supervisors for all company associates
|
FirmActResetSupervision: Reset supervisors for all company associates
|
||||||
FirmActResetSuperKeep: Additionally keep existing supervisors of company associates?
|
FirmActResetSuperKeep: Additionally keep existing supervisors of company associates?
|
||||||
|
FirmActRemoveSupers: Terminate all company related supervisonships?
|
||||||
FirmActResetMutualSupervision: Supervisors supervise each other
|
FirmActResetMutualSupervision: Supervisors supervise each other
|
||||||
|
FirmActResetSupersKeepAll: Keep all
|
||||||
|
FirmActResetSupersRemoveAps: Remove default supervisors only
|
||||||
|
FirmActResetSupersRemoveAll: Remove all
|
||||||
FirmActAddSupervisors: Add supervisors
|
FirmActAddSupervisors: Add supervisors
|
||||||
FirmActAddSupersEmpty: No supervisors added
|
FirmActAddSupersEmpty: No supervisors added
|
||||||
FirmActAddSupersSet n postal: #{n} default company supervisors changed #{maybeBoolMessage postal "" "and switched to postal notifications" "and switched to email notifications"}, but not yet activated.
|
FirmActAddSupersSet n postal: #{n} default company supervisors changed #{maybeBoolMessage postal "" "and switched to postal notifications" "and switched to email notifications"}, but not yet activated.
|
||||||
RemoveSupervisors ndef nact: #{ndef} default supervisors removed#{bool ", but no active supervisions were deactivated" (" and " <> tshow nact <> " active supervisions terminated") (nact > 0)}
|
RemoveSupervisors ndef: #{ndef} default supervisors removed.
|
||||||
FirmActChangeContactUser: Change contact data for all company associates
|
FirmActChangeContactUser: Change contact data for all company associates
|
||||||
FirmActChangeContactFirm: Change company contact data
|
FirmActChangeContactFirm: Change company contact data
|
||||||
FirmActChangeContactFirmInfo: The company contact data is only used for new company associates that would habe no contact information of their own otherwise.
|
FirmActChangeContactFirmInfo: The company contact data is only used for new company associates that would habe no contact information of their own otherwise.
|
||||||
@ -33,7 +37,8 @@ FirmUserActRemove: Delete company association
|
|||||||
FirmUserActMkSuper: Mark as company supervisor
|
FirmUserActMkSuper: Mark as company supervisor
|
||||||
FirmUserActChangeDetailsResult n t: #{n}/#{t} #{pluralENs n "company association"} updated
|
FirmUserActChangeDetailsResult n t: #{n}/#{t} #{pluralENs n "company association"} updated
|
||||||
FirmUserActChangeResult n t: Notification settings changed for #{n}/#{t} company #{pluralENs n "associate"}
|
FirmUserActChangeResult n t: Notification settings changed for #{n}/#{t} company #{pluralENs n "associate"}
|
||||||
FirmuserActRemoveResult uc sup sub: #{pluralENsN uc "Company association"} deleted. #{noneMoreEN sup "" ((pluralENsN sup "supervision") <> " removed due to eliminated supervisors.")} #{noneMoreEN sub "" ((pluralENsN sub "supervision") <> " removed due to eliminated supervisees.")}
|
FirmUserActRemoveResult uc: #{pluralENsN uc "Company association"} deleted.
|
||||||
|
FirmRemoveSupervision sup sub: #{noneMoreEN sup "" ((pluralENsN sup "supervision") <> " removed due to eliminated supervisors.")} #{noneMoreEN sub "No supervision" (pluralENsN sub "supervision")} removed due to eliminated supervisees.
|
||||||
FirmNewSupervisor: Appoint new individual supervisors
|
FirmNewSupervisor: Appoint new individual supervisors
|
||||||
FirmSetSupervisor: Add existing supervisors
|
FirmSetSupervisor: Add existing supervisors
|
||||||
FirmSetSupersReport nusr nspr nrem: #{nspr} individual supervisors set for #{nusr} company associates#{bool "." (" and " <> tshow nrem <> " other individual supervisions terminated.") (nrem >0)}
|
FirmSetSupersReport nusr nspr nrem: #{nspr} individual supervisors set for #{nusr} company associates#{bool "." (" and " <> tshow nrem <> " other individual supervisions terminated.") (nrem >0)}
|
||||||
@ -42,7 +47,7 @@ FirmSuperActNotify: Send message
|
|||||||
FirmSuperActSwitchSuper: Change default company supervisor
|
FirmSuperActSwitchSuper: Change default company supervisor
|
||||||
FirmSuperActSwitchSuperInfo: Does not affect company-external supervisors and does not change any active individual supervisions. Additionally use reset action, if desired.
|
FirmSuperActSwitchSuperInfo: Does not affect company-external supervisors and does not change any active individual supervisions. Additionally use reset action, if desired.
|
||||||
FirmSuperActRMSuperDef: Remove default supervisor
|
FirmSuperActRMSuperDef: Remove default supervisor
|
||||||
FirmSuperActRMSuperActive: Also remove active supervisions within this company
|
FirmSuperActRMSuperActive: Terminate active supervisions within this company?
|
||||||
FirmsNotification: Send company notification e-mail
|
FirmsNotification: Send company notification e-mail
|
||||||
FirmNotification fsh: Send e-mail to #{fsh}
|
FirmNotification fsh: Send e-mail to #{fsh}
|
||||||
FirmsNotificationTitle: Company notification
|
FirmsNotificationTitle: Company notification
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"version": "27.4.78"
|
"version": "27.4.79"
|
||||||
}
|
}
|
||||||
|
|||||||
2
package-lock.json
generated
2
package-lock.json
generated
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "uni2work",
|
"name": "uni2work",
|
||||||
"version": "27.4.78",
|
"version": "27.4.79",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "uni2work",
|
"name": "uni2work",
|
||||||
"version": "27.4.78",
|
"version": "27.4.79",
|
||||||
"description": "",
|
"description": "",
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "",
|
"author": "",
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
name: uniworx
|
name: uniworx
|
||||||
version: 27.4.78
|
version: 27.4.79
|
||||||
dependencies:
|
dependencies:
|
||||||
- base
|
- base
|
||||||
- yesod
|
- yesod
|
||||||
|
|||||||
25
src/Audit.hs
25
src/Audit.hs
@ -1,7 +1,9 @@
|
|||||||
-- SPDX-FileCopyrightText: 2023 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Steffen Jost <s.jost@fraport.de>
|
-- SPDX-FileCopyrightText: 2023-24 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Steffen Jost <s.jost@fraport.de>
|
||||||
--
|
--
|
||||||
-- SPDX-License-Identifier: AGPL-3.0-or-later
|
-- SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
{-# LANGUAGE TypeApplications #-}
|
||||||
|
|
||||||
module Audit
|
module Audit
|
||||||
( module Audit.Types
|
( module Audit.Types
|
||||||
, AuditException(..)
|
, AuditException(..)
|
||||||
@ -17,6 +19,8 @@ import Import.NoModel
|
|||||||
import Settings
|
import Settings
|
||||||
import Model
|
import Model
|
||||||
import Database.Persist.Sql
|
import Database.Persist.Sql
|
||||||
|
import qualified Database.Esqueleto.Experimental as E -- needs TypeApplications Lang-Pragma
|
||||||
|
import qualified Database.Esqueleto.Utils as E
|
||||||
import Audit.Types
|
import Audit.Types
|
||||||
|
|
||||||
import qualified Data.Text as Text
|
import qualified Data.Text as Text
|
||||||
@ -129,7 +133,7 @@ logInterface :: ( AuthId (HandlerSite m) ~ Key User
|
|||||||
-> Text -- ^ Any additional information
|
-> Text -- ^ Any additional information
|
||||||
-> ReaderT (YesodPersistBackend (HandlerSite m)) m ()
|
-> ReaderT (YesodPersistBackend (HandlerSite m)) m ()
|
||||||
-- ^ Log a transaction using information available from `HandlerT`, also calls `audit`
|
-- ^ Log a transaction using information available from `HandlerT`, also calls `audit`
|
||||||
logInterface interfaceLogInterface interfaceLogSubtype interfaceLogSuccess interfaceLogRows interfaceLogInfo = do
|
logInterface interfaceLogInterface interfaceLogSubtype interfaceLogSuccess interfaceLogRows interfaceLogInfo = do
|
||||||
interfaceLogWrite <- (methodGet /=) . Wai.requestMethod . reqWaiRequest <$> getRequest
|
interfaceLogWrite <- (methodGet /=) . Wai.requestMethod . reqWaiRequest <$> getRequest
|
||||||
logInterface' interfaceLogInterface interfaceLogSubtype interfaceLogWrite interfaceLogSuccess interfaceLogRows interfaceLogInfo
|
logInterface' interfaceLogInterface interfaceLogSubtype interfaceLogWrite interfaceLogSuccess interfaceLogRows interfaceLogInfo
|
||||||
|
|
||||||
@ -173,20 +177,25 @@ logInterface' (Text.strip -> interfaceLogInterface) (Text.strip -> interfaceLogS
|
|||||||
|
|
||||||
reportAdminProblem :: ( IsSqlBackend (YesodPersistBackend (HandlerSite m))
|
reportAdminProblem :: ( IsSqlBackend (YesodPersistBackend (HandlerSite m))
|
||||||
, SqlBackendCanWrite (YesodPersistBackend (HandlerSite m))
|
, SqlBackendCanWrite (YesodPersistBackend (HandlerSite m))
|
||||||
, MonadHandler m
|
, MonadHandler m
|
||||||
-- , HasCallStack
|
-- , HasCallStack
|
||||||
)
|
)
|
||||||
=> AdminProblem -- ^ Problem to record
|
=> AdminProblem -- ^ Problem to record
|
||||||
-> ReaderT (YesodPersistBackend (HandlerSite m)) m ()
|
-> ReaderT (YesodPersistBackend (HandlerSite m)) m ()
|
||||||
-- ^ Log a problem that needs interventions by admins
|
-- ^ Log a problem that needs interventions by admins, provided this problem has not already been reported and is still unsolved
|
||||||
--
|
--
|
||||||
-- - `problemLogTime` is now
|
-- - `problemLogTime` is now
|
||||||
-- - `problemSolver` is Nothing, we do not record the person who caused it
|
-- - `problemSolver` is Nothing, we do not record the person who caused it
|
||||||
reportAdminProblem problem@(toJSON -> problemLogInfo) = do
|
reportAdminProblem problem = do
|
||||||
problemLogTime <- liftIO getCurrentTime
|
|
||||||
let problemLogSolved = Nothing
|
let problemLogSolved = Nothing
|
||||||
problemLogSolver = Nothing
|
problemLogSolver = Nothing
|
||||||
insert_ ProblemLog{..}
|
problemLogInfo = toJSON problem
|
||||||
|
problemLogTime <- liftIO getCurrentTime
|
||||||
|
isKnown <- E.selectExists $ do
|
||||||
|
pl <- E.from $ E.table @ProblemLog
|
||||||
|
E.where_ $ E.isNothing (pl E.^. ProblemLogSolved)
|
||||||
|
E.&&. E.val problemLogInfo E.==. pl E.^. ProblemLogInfo
|
||||||
|
unless isKnown $ insert_ ProblemLog{..}
|
||||||
$logWarnS "Problem" $ Text.filter (/= '\n') $ tshow problem -- <> " - " <> pack (prettyCallStack callStack)
|
$logWarnS "Problem" $ Text.filter (/= '\n') $ tshow problem -- <> " - " <> pack (prettyCallStack callStack)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -34,7 +34,7 @@ dummyForm = do
|
|||||||
mr <- getMessageRender
|
mr <- getMessageRender
|
||||||
wreq (ciField & addDatalist userList) (fslpI MsgDummyIdent (mr MsgDummyIdentPlaceholder) & addAttr "autocomplete" "username" & addName PostLoginDummy) Nothing
|
wreq (ciField & addDatalist userList) (fslpI MsgDummyIdent (mr MsgDummyIdentPlaceholder) & addAttr "autocomplete" "username" & addName PostLoginDummy) Nothing
|
||||||
where
|
where
|
||||||
userList = fmap mkOptionList . runDB $ withReaderT projectBackend (map toOption <$> selectList [] [Asc UserIdent] :: ReaderT SqlBackend _ [Option UserIdent])
|
userList = fmap mkOptionList . runDB $ withReaderT projectBackend (map toOption <$> selectList [UserId <=. UserKey 12] [Asc UserIdent] :: ReaderT SqlBackend _ [Option UserIdent])
|
||||||
toOption (Entity _ User{..}) = Option userDisplayName userIdent (CI.original userIdent)
|
toOption (Entity _ User{..}) = Option userDisplayName userIdent (CI.original userIdent)
|
||||||
|
|
||||||
apDummy :: Text
|
apDummy :: Text
|
||||||
|
|||||||
@ -55,6 +55,7 @@ module Database.Esqueleto.Utils
|
|||||||
, day, day', dayMaybe, interval, diffDays, diffTimes
|
, day, day', dayMaybe, interval, diffDays, diffTimes
|
||||||
, exprLift
|
, exprLift
|
||||||
, explicitUnsafeCoerceSqlExprValue
|
, explicitUnsafeCoerceSqlExprValue
|
||||||
|
, psqlVersion_
|
||||||
, truncateTable
|
, truncateTable
|
||||||
, module Database.Esqueleto.Utils.TH
|
, module Database.Esqueleto.Utils.TH
|
||||||
) where
|
) where
|
||||||
@ -814,6 +815,8 @@ instance (PersistField a1, PersistField a2, PersistField b, Finite a1, Finite a2
|
|||||||
]
|
]
|
||||||
(E.else_ $ E.else_ $ E.veryUnsafeCoerceSqlExprValue (E.nothing :: E.SqlExpr (E.Value (Maybe ()))))
|
(E.else_ $ E.else_ $ E.veryUnsafeCoerceSqlExprValue (E.nothing :: E.SqlExpr (E.Value (Maybe ()))))
|
||||||
|
|
||||||
|
psqlVersion_ :: E.SqlExpr (E.Value Text)
|
||||||
|
psqlVersion_ = E.unsafeSqlFunction "VERSION" ()
|
||||||
|
|
||||||
-- Suspected to cause trouble. Needs more testing!
|
-- Suspected to cause trouble. Needs more testing!
|
||||||
-- truncateTable :: (MonadIO m, BackendCompatible SqlBackend backend, PersistEntity record)
|
-- truncateTable :: (MonadIO m, BackendCompatible SqlBackend backend, PersistEntity record)
|
||||||
|
|||||||
@ -283,7 +283,7 @@ postAdminAvsR = do
|
|||||||
(f_set , fs_size) = showLics AvsLicenceVorfeld
|
(f_set , fs_size) = showLics AvsLicenceVorfeld
|
||||||
(revoke , rv_size) = showLics AvsNoLicence
|
(revoke , rv_size) = showLics AvsNoLicence
|
||||||
return $ Just [whamlet|
|
return $ Just [whamlet|
|
||||||
<h2>Licence check differences:
|
<h2>Licence check AVS-ID differences:
|
||||||
<dl .deflist>
|
<dl .deflist>
|
||||||
<dt .deflist__dt>Grant R (#{rg_size}):
|
<dt .deflist__dt>Grant R (#{rg_size}):
|
||||||
<dd .deflist__dd>#{r_grant}
|
<dd .deflist__dd>#{r_grant}
|
||||||
@ -308,7 +308,7 @@ postAdminAvsR = do
|
|||||||
let showApids apids
|
let showApids apids
|
||||||
| null apids = "[ ]"
|
| null apids = "[ ]"
|
||||||
| otherwise = Text.intercalate ", " (tshow <$> Set.toList apids)
|
| otherwise = Text.intercalate ", " (tshow <$> Set.toList apids)
|
||||||
procLic :: AvsLicence -> Bool -> Set AvsPersonId -> Html
|
procLic :: (Ord a, Show a) => AvsLicence -> Bool -> Set a -> Html
|
||||||
procLic aLic up apids
|
procLic aLic up apids
|
||||||
| n <- Set.size apids, n > 0 =
|
| n <- Set.size apids, n > 0 =
|
||||||
let subtype = Text.cons (bool '↧' '↥' up) $ Text.singleton $ licence2char aLic
|
let subtype = Text.cons (bool '↧' '↥' up) $ Text.singleton $ licence2char aLic
|
||||||
@ -349,18 +349,43 @@ postAdminAvsR = do
|
|||||||
l2 = guardMonoid (synchLevel >= 2) $ procLic AvsLicenceVorfeld True $ fltrIds avsLicenceDiffGrantVorfeld --grant Vorfeld
|
l2 = guardMonoid (synchLevel >= 2) $ procLic AvsLicenceVorfeld True $ fltrIds avsLicenceDiffGrantVorfeld --grant Vorfeld
|
||||||
l3 = guardMonoid (synchLevel >= 3) $ procLic AvsLicenceVorfeld False $ fltrIds avsLicenceDiffRevokeRollfeld --downgrade Rollfeld -> Vorfeld
|
l3 = guardMonoid (synchLevel >= 3) $ procLic AvsLicenceVorfeld False $ fltrIds avsLicenceDiffRevokeRollfeld --downgrade Rollfeld -> Vorfeld
|
||||||
l4 = guardMonoid (synchLevel >= 4) $ procLic AvsLicenceRollfeld True $ fltrIds avsLicenceDiffGrantRollfeld --grant Rollfeld
|
l4 = guardMonoid (synchLevel >= 4) $ procLic AvsLicenceRollfeld True $ fltrIds avsLicenceDiffGrantRollfeld --grant Rollfeld
|
||||||
return $ Just [shamlet|
|
avsIdChanges = [shamlet|
|
||||||
<h3>
|
<h3>
|
||||||
Next automatic AVS licence synchronisation:
|
Next automatic AVS-ID licence synchronisation:
|
||||||
<dl .deflist>
|
<dl .deflist>
|
||||||
^{l4}
|
^{l4}
|
||||||
^{l3}
|
^{l3}
|
||||||
^{l2}
|
^{l2}
|
||||||
^{l1}
|
^{l1}
|
||||||
$maybe reason <- reasonFilter
|
$maybe reason <- reasonFilter
|
||||||
<dt .deflist__dt>Filtered "#{reason}" (#{Set.size reasonFltrdIds}):
|
<dt .deflist__dt>Filtered "#{reason}" (#{Set.size reasonFltrdIds}):
|
||||||
<dd .deflist__dd>#{showApids reasonFltrdIds}
|
<dd .deflist__dd>#{showApids reasonFltrdIds}
|
||||||
|]
|
|]
|
||||||
|
----------------------------------------------------
|
||||||
|
-- translate AVS-IDs to AVS-NOs for convenience only
|
||||||
|
avsidnos <- runDBRead $ E.select $ do
|
||||||
|
ua <- X.from $ E.table @UserAvs
|
||||||
|
E.where_ $ ua E.^. UserAvsPersonId `E.in_` E.vals (Set.unions [avsLicenceDiffRevokeAll, avsLicenceDiffRevokeRollfeld, avsLicenceDiffGrantVorfeld, avsLicenceDiffGrantRollfeld]) -- , reasonFltrdIds])
|
||||||
|
return (ua E.^. UserAvsPersonId, ua E.^. UserAvsNoPerson)
|
||||||
|
let id2no = Map.fromList $ $(E.unValueN 2) <$> avsidnos
|
||||||
|
translate = setMapMaybe (`Map.lookup` id2no)
|
||||||
|
l1' = guardMonoid (synchLevel >= 1) $ procLic AvsNoLicence False $ translate $ fltrIds avsLicenceDiffRevokeAll --revoke Vorfeld and maybe also Rollfeld
|
||||||
|
l2' = guardMonoid (synchLevel >= 2) $ procLic AvsLicenceVorfeld True $ translate $ fltrIds avsLicenceDiffGrantVorfeld --grant Vorfeld
|
||||||
|
l3' = guardMonoid (synchLevel >= 3) $ procLic AvsLicenceVorfeld False $ translate $ fltrIds avsLicenceDiffRevokeRollfeld --downgrade Rollfeld -> Vorfeld
|
||||||
|
l4' = guardMonoid (synchLevel >= 4) $ procLic AvsLicenceRollfeld True $ translate $ fltrIds avsLicenceDiffGrantRollfeld --grant Rollfeld
|
||||||
|
autoNoDiffs = [shamlet|
|
||||||
|
<h3>
|
||||||
|
Next automatic licence changes translated to human readable AVS-Numbers, if known:
|
||||||
|
<dl .deflist>
|
||||||
|
^{l4'}
|
||||||
|
^{l3'}
|
||||||
|
^{l2'}
|
||||||
|
^{l1'}
|
||||||
|
$maybe reason <- reasonFilter
|
||||||
|
<dt .deflist__dt>Filtered "#{reason}" (#{Set.size reasonFltrdIds}):
|
||||||
|
<dd .deflist__dd>#{showApids $ translate reasonFltrdIds}
|
||||||
|
|]
|
||||||
|
return $ Just $ avsIdChanges <> autoNoDiffs
|
||||||
return (basediffs, autoDiffs)
|
return (basediffs, autoDiffs)
|
||||||
|
|
||||||
-- (Just BtnSynchLicences) -> do
|
-- (Just BtnSynchLicences) -> do
|
||||||
|
|||||||
@ -28,7 +28,9 @@ import Text.Hamlet
|
|||||||
-- import Handler.Utils.I18n
|
-- import Handler.Utils.I18n
|
||||||
|
|
||||||
import Handler.Admin.Test.Download (testDownload)
|
import Handler.Admin.Test.Download (testDownload)
|
||||||
|
import qualified Database.Esqueleto.Experimental as E (selectOne, unValue)
|
||||||
|
import qualified Database.Esqueleto.PostgreSQL as E (now_)
|
||||||
|
import qualified Database.Esqueleto.Utils as E (psqlVersion_)
|
||||||
|
|
||||||
-- BEGIN - Buttons needed only here
|
-- BEGIN - Buttons needed only here
|
||||||
data ButtonCreate = CreateMath | CreateInf | CrashApp -- Dummy for Example
|
data ButtonCreate = CreateMath | CreateInf | CrashApp -- Dummy for Example
|
||||||
@ -226,6 +228,9 @@ postAdminTestR = do
|
|||||||
|
|
||||||
UniWorX{ appSettings' = AppSettings{..} } <- getYesod
|
UniWorX{ appSettings' = AppSettings{..} } <- getYesod
|
||||||
|
|
||||||
|
psqlVersion <- runDBRead $ E.selectOne $ return E.psqlVersion_
|
||||||
|
dbTime <- runDBRead $ E.selectOne $ return E.now_
|
||||||
|
|
||||||
let locallyDefinedPageHeading = [whamlet|Admin TestPage for Uni2work|]
|
let locallyDefinedPageHeading = [whamlet|Admin TestPage for Uni2work|]
|
||||||
siteLayout locallyDefinedPageHeading $ do
|
siteLayout locallyDefinedPageHeading $ do
|
||||||
-- defaultLayout $ do
|
-- defaultLayout $ do
|
||||||
@ -327,6 +332,17 @@ postAdminTestR = do
|
|||||||
<dd .deflist__dd>#{tshow appSynchroniseAvsUsersWithin}
|
<dd .deflist__dd>#{tshow appSynchroniseAvsUsersWithin}
|
||||||
|]
|
|]
|
||||||
|
|
||||||
|
[whamlet|
|
||||||
|
<section>
|
||||||
|
<h2> PostgreSQL Information
|
||||||
|
<dl .deflist>
|
||||||
|
$maybe pver <- psqlVersion
|
||||||
|
<dt .deflist__dt>DB Version
|
||||||
|
<dd .deflist__dd>#{E.unValue pver}
|
||||||
|
$maybe ptme <- dbTime
|
||||||
|
<dt .deflist__dt>DB Time
|
||||||
|
<dd .deflist__dd>#{tshow (E.unValue ptme)}
|
||||||
|
|]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -742,29 +742,28 @@ embedRenderMessage ''UniWorX ''FirmUserAction id
|
|||||||
|
|
||||||
data FirmUserActionData = FirmUserActNotifyData
|
data FirmUserActionData = FirmUserActNotifyData
|
||||||
| FirmUserActResetSupervisionData
|
| FirmUserActResetSupervisionData
|
||||||
{ firmUserActResetKeepOldSupers :: Maybe Bool
|
{ firmUserActResetSupers :: Maybe Bool
|
||||||
-- , firmUserActResetMutualSupervision :: Maybe Bool
|
|
||||||
}
|
}
|
||||||
| FirmUserActSetSupervisorData
|
| FirmUserActSetSupervisorData
|
||||||
{ firmUserActSetSuperNames :: Maybe (Set Text)
|
{ firmUserActSetSuperNames :: Maybe (Set Text)
|
||||||
, firmUserActSetSuperIds :: Maybe [UserId]
|
, firmUserActSetSuperIds :: Maybe [UserId]
|
||||||
, firmUserActSetSuperReason :: Maybe Text
|
, firmUserActSetSuperReason :: Maybe Text
|
||||||
, firmUserActSetSuperReroute :: Bool
|
, firmUserActSetSuperReroute :: Bool
|
||||||
, firmUserActSetSuperKeep :: Bool
|
, firmUserActResetSupers :: Maybe Bool
|
||||||
}
|
}
|
||||||
| FirmUserActMkSuperData
|
| FirmUserActMkSuperData
|
||||||
{ firmUserActMkSuperReroute :: Maybe Bool }
|
{ firmUserActMkSuperReroute :: Maybe Bool }
|
||||||
| FirmUserActChangeDetailsData
|
| FirmUserActChangeDetailsData
|
||||||
{ firmUserActDetailPriority :: Maybe Int
|
{ firmUserActDetailPriority :: Maybe Int
|
||||||
, firmUserActDetailReason :: Maybe Text
|
, firmUserActDetailReason :: Maybe Text
|
||||||
}
|
}
|
||||||
| FirmUserActChangeContactData
|
| FirmUserActChangeContactData
|
||||||
{ firmUserActPostalAddr :: Maybe StoredMarkup
|
{ firmUserActPostalAddr :: Maybe StoredMarkup
|
||||||
, firmUserActUseCompanyPostal :: Maybe Bool
|
, firmUserActUseCompanyPostal :: Maybe Bool
|
||||||
, firmUserActPostalPref :: Maybe Bool
|
, firmUserActPostalPref :: Maybe Bool
|
||||||
}
|
}
|
||||||
| FirmUserActRemoveData
|
| FirmUserActRemoveData
|
||||||
{ firmUserActRemoveKeepSuper :: Bool
|
{ firmUserActRemoveSupers :: Bool
|
||||||
}
|
}
|
||||||
deriving (Eq, Ord, Show, Generic)
|
deriving (Eq, Ord, Show, Generic)
|
||||||
|
|
||||||
@ -968,25 +967,24 @@ mkFirmUserTable isAdmin cid = do
|
|||||||
acts = mconcat
|
acts = mconcat
|
||||||
[ guardMonoid isAdmin $ singletonMap FirmUserActNotify $ pure FirmUserActNotifyData
|
[ guardMonoid isAdmin $ singletonMap FirmUserActNotify $ pure FirmUserActNotifyData
|
||||||
, singletonMap FirmUserActResetSupervision $ FirmUserActResetSupervisionData
|
, singletonMap FirmUserActResetSupervision $ FirmUserActResetSupervisionData
|
||||||
<$> aopt (boolField . Just $ SomeMessage MsgBoolIrrelevant) (fslI MsgFirmActResetSuperKeep) (Just $ Just False)
|
<$> aopt (boolFieldCustom (SomeMessage MsgFirmActResetSupersRemoveAll) (SomeMessage MsgFirmActResetSupersRemoveAps) $ Just $ SomeMessage MsgFirmActResetSupersKeepAll) (fslI MsgFirmActResetSuperKeep) (Just $ Just False)
|
||||||
-- <*> aopt checkBoxField (fslI MsgFirmActResetMutualSupervision) (Just $ Just True )
|
|
||||||
, singletonMap FirmUserActSetSupervisor $ FirmUserActSetSupervisorData
|
, singletonMap FirmUserActSetSupervisor $ FirmUserActSetSupervisorData
|
||||||
<$> aopt (textField & cfAnySeparatedSet) (fslI MsgFirmNewSupervisor & setTooltip MsgCourseParticipantsRegisterUsersFieldTip) Nothing
|
<$> aopt (textField & cfAnySeparatedSet) (fslI MsgFirmNewSupervisor & setTooltip MsgCourseParticipantsRegisterUsersFieldTip) Nothing
|
||||||
<*> aopt supervisorsField (fslI MsgFirmSetSupervisor & setTooltip MsgMultiSelectTip) Nothing
|
<*> aopt supervisorsField (fslI MsgFirmSetSupervisor & setTooltip MsgMultiSelectTip) Nothing
|
||||||
<*> aopt (textField & cfStrip & addDatalist superReasons) (fslI MsgUserSupervisorReason & setTooltip MsgUserSupervisorReasonTooltip) Nothing
|
<*> aopt (textField & cfStrip & addDatalist superReasons) (fslI MsgUserSupervisorReason & setTooltip MsgUserSupervisorReasonTooltip) Nothing
|
||||||
<*> areq (boolField . Just $ SomeMessage MsgBoolIrrelevant) (fslI MsgMailSupervisorReroute & setTooltip MsgMailSupervisorRerouteTooltip) (Just False)
|
<*> areq boolField' (fslI MsgMailSupervisorReroute & setTooltip MsgMailSupervisorRerouteTooltip) (Just False)
|
||||||
<*> areq (boolField . Just $ SomeMessage MsgBoolIrrelevant) (fslI MsgFirmActResetSuperKeep) (Just False)
|
<*> aopt (boolFieldCustom (SomeMessage MsgFirmActResetSupersRemoveAll) (SomeMessage MsgFirmActResetSupersRemoveAps) $ Just $ SomeMessage MsgFirmActResetSupersKeepAll) (fslI MsgFirmActResetSuperKeep) (Just $ Just False)
|
||||||
, singletonMap FirmUserActMkSuper $ FirmUserActMkSuperData
|
, singletonMap FirmUserActMkSuper $ FirmUserActMkSuperData
|
||||||
<$> aopt checkBoxField (fslI MsgTableIsDefaultReroute) (Just $ Just True)
|
<$> aopt checkBoxField (fslI MsgTableIsDefaultReroute) (Just $ Just True)
|
||||||
, singletonMap FirmUserActChangeDetails $ FirmUserActChangeDetailsData
|
|
||||||
<$> aopt intField (fslI MsgCompanyUserPriority & setTooltip MsgCompanyUserPriorityTip) Nothing
|
|
||||||
<*> aopt (textField & cfStrip & addDatalist userReasons) (fslI MsgUserCompanyReason & setTooltip (SomeMessages [SomeMessage MsgUserCompanyReasonTooltip, SomeMessage MsgNullDeletes])) Nothing
|
|
||||||
, singletonMap FirmUserActChangeContact $ FirmUserActChangeContactData
|
, singletonMap FirmUserActChangeContact $ FirmUserActChangeContactData
|
||||||
<$> aopt htmlField (fslI MsgPostAddress & setTooltip (SomeMessages [SomeMessage MsgPostAddressTip, SomeMessage MsgUtilEmptyNoChangeTip])) Nothing
|
<$> aopt htmlField (fslI MsgPostAddress & setTooltip (SomeMessages [SomeMessage MsgPostAddressTip, SomeMessage MsgUtilEmptyNoChangeTip])) Nothing
|
||||||
<*> aopt boolField' (fslI MsgCompanyUserUseCompanyAddress & setTooltip MsgCompanyUserUseCompanyAddressTip) Nothing
|
<*> aopt boolField' (fslI MsgCompanyUserUseCompanyAddress & setTooltip MsgCompanyUserUseCompanyAddressTip) Nothing
|
||||||
<*> aopt postalEmailField (fslI MsgFormFieldPostal & setTooltip MsgFormFieldPostalTip) Nothing
|
<*> aopt postalEmailField (fslI MsgFormFieldPostal & setTooltip MsgFormFieldPostalTip) Nothing
|
||||||
|
, singletonMap FirmUserActChangeDetails $ FirmUserActChangeDetailsData
|
||||||
|
<$> aopt intField (fslI MsgCompanyUserPriority & setTooltip MsgCompanyUserPriorityTip) Nothing
|
||||||
|
<*> aopt (textField & cfStrip & addDatalist userReasons) (fslI MsgUserCompanyReason & setTooltip (SomeMessages [SomeMessage MsgUserCompanyReasonTooltip, SomeMessage MsgNullDeletes])) Nothing
|
||||||
, singletonMap FirmUserActRemove $ FirmUserActRemoveData
|
, singletonMap FirmUserActRemove $ FirmUserActRemoveData
|
||||||
<$> areq (boolField . Just $ SomeMessage MsgBoolIrrelevant) (fslI MsgFirmActResetSuperKeep) (Just False)
|
<$> areq boolField' (fslI MsgFirmActRemoveSupers) (Just True)
|
||||||
]
|
]
|
||||||
dbtParams = DBParamsForm
|
dbtParams = DBParamsForm
|
||||||
{ dbParamsFormMethod = POST
|
{ dbParamsFormMethod = POST
|
||||||
@ -1053,6 +1051,10 @@ postFirmUsersR fsh = do
|
|||||||
-- return usr
|
-- return usr
|
||||||
<*> mkFirmUserTable isAdmin cid
|
<*> mkFirmUserTable isAdmin cid
|
||||||
|
|
||||||
|
let resetSupers :: Maybe Bool -> NonEmpty UserId -> DB Int64
|
||||||
|
resetSupers Nothing _ = return 0
|
||||||
|
resetSupers (Just False) uids = deleteDefaultSupervisorsForUsers [] [] uids
|
||||||
|
resetSupers (Just True ) uids = deleteWhereCount [UserSupervisorUser <-. toList uids]
|
||||||
formResult fusrRes $ \case
|
formResult fusrRes $ \case
|
||||||
(_, uids) | null uids -> addMessageI Error MsgUtilEmptyChoice
|
(_, uids) | null uids -> addMessageI Error MsgUtilEmptyChoice
|
||||||
(FirmUserActNotifyData , uids) -> do
|
(FirmUserActNotifyData , uids) -> do
|
||||||
@ -1060,9 +1062,7 @@ postFirmUsersR fsh = do
|
|||||||
redirect (FirmCommR fsh, [(toPathPiece GetRecipient, toPathPiece cID) | cID <- cuids])
|
redirect (FirmCommR fsh, [(toPathPiece GetRecipient, toPathPiece cID) | cID <- cuids])
|
||||||
(FirmUserActResetSupervisionData{..}, set2NonEmpty (error "Unexpected empty user list in getFirmUserR action handler.") -> uids) -> do -- set guaranteed to be non-empty due to first case clause
|
(FirmUserActResetSupervisionData{..}, set2NonEmpty (error "Unexpected empty user list in getFirmUserR action handler.") -> uids) -> do -- set guaranteed to be non-empty due to first case clause
|
||||||
runDB $ do
|
runDB $ do
|
||||||
delSupers <- if firmUserActResetKeepOldSupers == Just False
|
delSupers <- resetSupers firmUserActResetSupers uids
|
||||||
then deleteDefaultSupervisorsForUsers [] [] uids
|
|
||||||
else return 0
|
|
||||||
newSupers <- addDefaultSupervisors Nothing cid uids
|
newSupers <- addDefaultSupervisors Nothing cid uids
|
||||||
addMessageI Info $ MsgFirmResetSupervision delSupers newSupers
|
addMessageI Info $ MsgFirmResetSupervision delSupers newSupers
|
||||||
reloadKeepGetParams $ FirmUsersR fsh -- reload to reflect changes
|
reloadKeepGetParams $ FirmUsersR fsh -- reload to reflect changes
|
||||||
@ -1081,8 +1081,7 @@ postFirmUsersR fsh = do
|
|||||||
<li>#{usr}
|
<li>#{usr}
|
||||||
|]
|
|]
|
||||||
in addMessageModal Error (i18n . MsgCourseParticipantsRegisterNotFoundInAvs $ length usersNotFound) (Right msgContent)
|
in addMessageModal Error (i18n . MsgCourseParticipantsRegisterNotFoundInAvs $ length usersNotFound) (Right msgContent)
|
||||||
delSupers <- runDB
|
delSupers <- runDB $ resetSupers firmUserActResetSupers uids
|
||||||
$ bool (deleteDefaultSupervisorsForUsers [cid] [] uids) (return 0) firmUserActSetSuperKeep
|
|
||||||
<* putMany [UserSupervisor s u firmUserActSetSuperReroute (Just cid) firmUserActSetSuperReason | u <- toList uids, s <- newSupers]
|
<* putMany [UserSupervisor s u firmUserActSetSuperReroute (Just cid) firmUserActSetSuperReason | u <- toList uids, s <- newSupers]
|
||||||
addMessageI Success $ MsgFirmSetSupersReport nrUsers nrSupers delSupers
|
addMessageI Success $ MsgFirmSetSupersReport nrUsers nrSupers delSupers
|
||||||
reloadKeepGetParams $ FirmUsersR fsh -- reload to reflect changes
|
reloadKeepGetParams $ FirmUsersR fsh -- reload to reflect changes
|
||||||
@ -1119,11 +1118,15 @@ postFirmUsersR fsh = do
|
|||||||
allok = bool Warning Success $ nrChanged == total
|
allok = bool Warning Success $ nrChanged == total
|
||||||
addMessageI allok $ MsgFirmUserActChangeResult nrChanged total
|
addMessageI allok $ MsgFirmUserActChangeResult nrChanged total
|
||||||
reloadKeepGetParams $ FirmUsersR fsh -- reload to reflect changes
|
reloadKeepGetParams $ FirmUsersR fsh -- reload to reflect changes
|
||||||
(FirmUserActRemoveData{}, Set.toList -> uids) -> do
|
(FirmUserActRemoveData{..}, Set.toList -> uids) -> do
|
||||||
(nrUc, nrSuper, nrSubs) <- runDB $ deleteCompanyUser cid uids
|
let optRemove = if firmUserActRemoveSupers then id else const $ return 0
|
||||||
|
(nrUc, nrSuper, nrSubs) <- runDB $ (,,)
|
||||||
|
<$> deleteWhereCount [UserCompanyCompany ==. cid, UserCompanyUser <-. uids]
|
||||||
|
<*> optRemove (deleteWhereCount [UserSupervisorCompany ==. Just cid, UserSupervisorSupervisor <-. uids])
|
||||||
|
<*> optRemove (deleteWhereCount [UserSupervisorCompany ==. Just cid, UserSupervisorUser <-. uids])
|
||||||
let total = fromIntegral $ length uids
|
let total = fromIntegral $ length uids
|
||||||
allok = bool Warning Success $ nrUc == total
|
allok = bool Warning Success $ total == nrUc
|
||||||
addMessageI allok $ MsgFirmuserActRemoveResult nrUc nrSuper nrSubs
|
addMessageI allok $ someMessages [MsgFirmUserActRemoveResult nrUc, MsgFirmRemoveSupervision nrSuper nrSubs]
|
||||||
reloadKeepGetParams $ FirmUsersR fsh -- reload to reflect changes
|
reloadKeepGetParams $ FirmUsersR fsh -- reload to reflect changes
|
||||||
|
|
||||||
formFirmAction <- runFirmActionFormPost cid (FirmUsersR fsh) isAdmin [FirmActNotify, FirmActResetSupervision, FirmActAddSupervisors, FirmActChangeContactFirm, FirmActChangeContactUser]
|
formFirmAction <- runFirmActionFormPost cid (FirmUsersR fsh) isAdmin [FirmActNotify, FirmActResetSupervision, FirmActAddSupervisors, FirmActChangeContactFirm, FirmActChangeContactUser]
|
||||||
@ -1153,7 +1156,7 @@ data FirmSuperActionData = FirmSuperActNotifyData
|
|||||||
, firmSuperActSwitchReroute :: Maybe Bool
|
, firmSuperActSwitchReroute :: Maybe Bool
|
||||||
}
|
}
|
||||||
| FirmSuperActRMSuperDefData
|
| FirmSuperActRMSuperDefData
|
||||||
{ firmSuperActRMSuperActive :: Maybe Bool }
|
{ firmSuperActRMSuperActive :: Bool }
|
||||||
|
|
||||||
deriving (Eq, Ord, Show, Generic)
|
deriving (Eq, Ord, Show, Generic)
|
||||||
|
|
||||||
@ -1296,11 +1299,11 @@ mkFirmSuperTable isAdmin cid = do
|
|||||||
acts = mconcat
|
acts = mconcat
|
||||||
[ guardMonoid isAdmin $ singletonMap FirmSuperActNotify $ pure FirmSuperActNotifyData
|
[ guardMonoid isAdmin $ singletonMap FirmSuperActNotify $ pure FirmSuperActNotifyData
|
||||||
, singletonMap FirmSuperActSwitchSuper $ FirmSuperActSwitchSuperData
|
, singletonMap FirmSuperActSwitchSuper $ FirmSuperActSwitchSuperData
|
||||||
<$> aopt (boolField . Just $ SomeMessage MsgBoolIrrelevant) (fslI MsgFirmSuperDefault) (Just $ Just True)
|
<$> aopt boolField' (fslI MsgFirmSuperDefault) (Just $ Just True)
|
||||||
<*> aopt (boolField . Just $ SomeMessage MsgBoolIrrelevant) (fslI MsgTableIsDefaultReroute) Nothing
|
<*> aopt boolField' (fslI MsgTableIsDefaultReroute) Nothing
|
||||||
<* aformMessage msgSupervisorUnchanged
|
<* aformMessage msgSupervisorUnchanged
|
||||||
, singletonMap FirmSuperActRMSuperDef $ FirmSuperActRMSuperDefData
|
, singletonMap FirmSuperActRMSuperDef $ FirmSuperActRMSuperDefData
|
||||||
<$> aopt checkBoxField (fslI MsgFirmSuperActRMSuperActive) (Just $ Just True)
|
<$> areq boolField' (fslI MsgFirmSuperActRMSuperActive) (Just True)
|
||||||
]
|
]
|
||||||
dbtParams = DBParamsForm
|
dbtParams = DBParamsForm
|
||||||
{ dbParamsFormMethod = POST
|
{ dbParamsFormMethod = POST
|
||||||
@ -1344,19 +1347,14 @@ postFirmSupersR fsh = do
|
|||||||
formResult fsprRes $ \case
|
formResult fsprRes $ \case
|
||||||
(_, uids) | null uids -> addMessageI Error MsgUtilEmptyChoice
|
(_, uids) | null uids -> addMessageI Error MsgUtilEmptyChoice
|
||||||
(FirmSuperActRMSuperDefData{..}, Set.toList -> uids) -> do
|
(FirmSuperActRMSuperDefData{..}, Set.toList -> uids) -> do
|
||||||
(nrRmSuper,nrRmActual) <- runDB $ (,)
|
let optRemove = if firmSuperActRMSuperActive then id else const $ return 0
|
||||||
|
(nrRmSuper,nrRmSupers,nrRmSubs) <- runDB $ (,,)
|
||||||
<$> updateWhereCount [UserCompanyUser <-. uids, UserCompanyCompany ==. cid] [UserCompanySupervisor =. False, UserCompanySupervisorReroute =. False]
|
<$> updateWhereCount [UserCompanyUser <-. uids, UserCompanyCompany ==. cid] [UserCompanySupervisor =. False, UserCompanySupervisorReroute =. False]
|
||||||
<*> if firmSuperActRMSuperActive /= Just True
|
<*> optRemove (deleteWhereCount [UserSupervisorCompany ==. Just cid, UserSupervisorSupervisor <-. uids])
|
||||||
then return 0
|
<*> optRemove (deleteWhereCount [UserSupervisorCompany ==. Just cid, UserSupervisorUser <-. uids])
|
||||||
else E.deleteCount $ do
|
let total = fromIntegral $ length uids
|
||||||
spr <- E.from $ E.table @UserSupervisor
|
allok = bool Warning Success $ total == nrRmSuper
|
||||||
E.where_ $ spr E.^. UserSupervisorSupervisor `E.in_` E.vals uids
|
addMessageI allok $ someMessages [MsgRemoveSupervisors nrRmSuper, MsgFirmRemoveSupervision nrRmSupers nrRmSubs]
|
||||||
E.&&. E.exists (do
|
|
||||||
usr <- E.from $ E.table @UserCompany
|
|
||||||
E.where_ $ usr E.^. UserCompanyCompany E.==. E.val cid
|
|
||||||
E.&&. usr E.^. UserCompanyUser E.==. spr E.^. UserSupervisorUser
|
|
||||||
)
|
|
||||||
addMessageI Info $ MsgRemoveSupervisors nrRmSuper nrRmActual
|
|
||||||
reloadKeepGetParams $ FirmUsersR fsh -- reload to reflect changes
|
reloadKeepGetParams $ FirmUsersR fsh -- reload to reflect changes
|
||||||
(FirmSuperActSwitchSuperData{..}, Set.toList -> uids) -> do
|
(FirmSuperActSwitchSuperData{..}, Set.toList -> uids) -> do
|
||||||
let (fltrSpr, changes) = case (firmSuperActSwitchSuper, firmSuperActSwitchReroute) of
|
let (fltrSpr, changes) = case (firmSuperActSwitchSuper, firmSuperActSwitchReroute) of
|
||||||
|
|||||||
@ -20,6 +20,9 @@ import Control.Concurrent.STM.Delay
|
|||||||
|
|
||||||
import System.Environment (lookupEnv) -- while git version number is not working
|
import System.Environment (lookupEnv) -- while git version number is not working
|
||||||
|
|
||||||
|
import qualified Database.Esqueleto.Experimental as E
|
||||||
|
import qualified Database.Esqueleto.PostgreSQL as E (now_)
|
||||||
|
|
||||||
-- import Data.FileEmbed (embedStringFile)
|
-- import Data.FileEmbed (embedStringFile)
|
||||||
|
|
||||||
getHealthR :: Handler TypedContent
|
getHealthR :: Handler TypedContent
|
||||||
@ -114,10 +117,16 @@ getInstanceR = do
|
|||||||
getStatusR :: Handler Html
|
getStatusR :: Handler Html
|
||||||
getStatusR = do
|
getStatusR = do
|
||||||
starttime <- getsYesod appStartTime
|
starttime <- getsYesod appStartTime
|
||||||
(currtime, env_version) <- liftIO $ (,) <$> getCurrentTime <*> lookupEnv "VERSION_NR"
|
dbTime <- runDBRead $ E.selectOne $ return E.now_
|
||||||
|
(currtime,env_version) <- liftIO $ (,) <$> getCurrentTime <*> lookupEnv "VERSION_NR"
|
||||||
-- ft <- formatTime' "%Y-%m-%d %H:%M:%S" currtime
|
-- ft <- formatTime' "%Y-%m-%d %H:%M:%S" currtime
|
||||||
let diffTime :: UTCTime -> Text
|
let diffTime :: UTCTime -> Text
|
||||||
diffTime = pack . iso8601Show . calendarTimeTime . fromIntegral . truncate . diffUTCTime currtime
|
diffTime t =
|
||||||
|
let tdiff = diffUTCTime currtime t
|
||||||
|
in if 64 > abs tdiff
|
||||||
|
then tshow tdiff
|
||||||
|
else pack . iso8601Show . calendarTimeTime . fromIntegral $ truncate tdiff
|
||||||
|
|
||||||
withUrlRenderer
|
withUrlRenderer
|
||||||
[hamlet|
|
[hamlet|
|
||||||
$doctype 5
|
$doctype 5
|
||||||
@ -129,8 +138,13 @@ getStatusR = do
|
|||||||
<p>
|
<p>
|
||||||
Environment version #{env_ver}
|
Environment version #{env_ver}
|
||||||
<p>
|
<p>
|
||||||
Current Time <br>
|
Current Application Time <br>
|
||||||
#{show currtime} <br>
|
#{show currtime} <br>
|
||||||
|
$maybe dbtval <- dbTime
|
||||||
|
$with dbt <- E.unValue dbtval
|
||||||
|
Current Database Time <br>
|
||||||
|
#{show dbt} #
|
||||||
|
Difference: #{diffTime dbt} <br>
|
||||||
<p>
|
<p>
|
||||||
Instance Start <br>
|
Instance Start <br>
|
||||||
#{show starttime} #
|
#{show starttime} #
|
||||||
|
|||||||
@ -96,12 +96,12 @@ mkQualificationAllTable isAdmin = do
|
|||||||
maybeCell (qualificationDescription quali) markupCellLargeModal
|
maybeCell (qualificationDescription quali) markupCellLargeModal
|
||||||
, sortable Nothing (i18nCell MsgQualificationValidDuration & cellTooltip MsgTableDiffDaysTooltip) $
|
, sortable Nothing (i18nCell MsgQualificationValidDuration & cellTooltip MsgTableDiffDaysTooltip) $
|
||||||
foldMap (textCell . formatCalendarDiffDays . fromMonths) . view (resultAllQualification . _qualificationValidDuration)
|
foldMap (textCell . formatCalendarDiffDays . fromMonths) . view (resultAllQualification . _qualificationValidDuration)
|
||||||
|
, sortable Nothing (i18nCell MsgQualificationRefreshWithin & cellTooltips [SomeMessage MsgQualificationRefreshWithinTooltip , SomeMessage MsgTableDiffDaysTooltip]) $
|
||||||
|
foldMap (textCell . formatCalendarDiffDays ) . view (resultAllQualification . _qualificationRefreshWithin)
|
||||||
, sortable (Just "qelearning") (i18nCell MsgTableLmsElearning & cellTooltip MsgQualificationElearningStart) $ \row ->
|
, sortable (Just "qelearning") (i18nCell MsgTableLmsElearning & cellTooltip MsgQualificationElearningStart) $ \row ->
|
||||||
let elearnstart = row ^. resultAllQualification . _qualificationElearningStart
|
let elearnstart = row ^. resultAllQualification . _qualificationElearningStart
|
||||||
reminder = row ^. resultAllQualification . _qualificationRefreshReminder
|
reminder = row ^. resultAllQualification . _qualificationRefreshReminder
|
||||||
in tickmarkCell $ elearnstart && isJust reminder
|
in tickmarkCell $ elearnstart && isJust reminder
|
||||||
, sortable Nothing (i18nCell MsgQualificationRefreshWithin & cellTooltips [SomeMessage MsgQualificationRefreshWithinTooltip , SomeMessage MsgTableDiffDaysTooltip]) $
|
|
||||||
foldMap (textCell . formatCalendarDiffDays ) . view (resultAllQualification . _qualificationRefreshWithin)
|
|
||||||
, sortable Nothing (i18nCell MsgQualificationRefreshReminder & cellTooltips [SomeMessage MsgQualificationRefreshReminderTooltip, SomeMessage MsgTableDiffDaysTooltip]) $
|
, sortable Nothing (i18nCell MsgQualificationRefreshReminder & cellTooltips [SomeMessage MsgQualificationRefreshReminderTooltip, SomeMessage MsgTableDiffDaysTooltip]) $
|
||||||
foldMap (textCell . formatCalendarDiffDays ) . view (resultAllQualification . _qualificationRefreshReminder)
|
foldMap (textCell . formatCalendarDiffDays ) . view (resultAllQualification . _qualificationRefreshReminder)
|
||||||
, sortable (Just "noteexpiry") (i18nCell MsgQualificationExpiryNotification & cellTooltip MsgQualificationExpiryNotificationTooltip)
|
, sortable (Just "noteexpiry") (i18nCell MsgQualificationExpiryNotification & cellTooltip MsgQualificationExpiryNotificationTooltip)
|
||||||
@ -543,7 +543,7 @@ postQualificationR sid qsh = do
|
|||||||
Ex.groupBy (qblock Ex.^. QualificationUserBlockReason)
|
Ex.groupBy (qblock Ex.^. QualificationUserBlockReason)
|
||||||
let countRows' :: Ex.SqlExpr (Ex.Value Int64) = Ex.countRows
|
let countRows' :: Ex.SqlExpr (Ex.Value Int64) = Ex.countRows
|
||||||
Ex.orderBy [Ex.desc countRows']
|
Ex.orderBy [Ex.desc countRows']
|
||||||
Ex.limit 7
|
Ex.limit 9
|
||||||
pure (qblock Ex.^. QualificationUserBlockReason)
|
pure (qblock Ex.^. QualificationUserBlockReason)
|
||||||
mkOption :: Ex.Value Text -> Option Text
|
mkOption :: Ex.Value Text -> Option Text
|
||||||
mkOption (Ex.unValue -> t) = Option{ optionDisplay = t, optionInternalValue = t, optionExternalValue = toPathPiece t }
|
mkOption (Ex.unValue -> t) = Option{ optionDisplay = t, optionInternalValue = t, optionExternalValue = toPathPiece t }
|
||||||
|
|||||||
@ -191,18 +191,19 @@ postUsersR = do
|
|||||||
fmap (setOf $ folded . _Value . _Just) . Ex.select . Ex.distinct $ do
|
fmap (setOf $ folded . _Value . _Just) . Ex.select . Ex.distinct $ do
|
||||||
usrc <- Ex.from $ Ex.table @UserSupervisor
|
usrc <- Ex.from $ Ex.table @UserSupervisor
|
||||||
E.where_ $ E.isJust (usrc E.^. UserSupervisorReason)
|
E.where_ $ E.isJust (usrc E.^. UserSupervisorReason)
|
||||||
|
Ex.limit 9
|
||||||
return $ usrc E.^. UserSupervisorReason
|
return $ usrc E.^. UserSupervisorReason
|
||||||
acts :: Map UserAction (AForm Handler UserActionData)
|
acts :: Map UserAction (AForm Handler UserActionData)
|
||||||
acts = mconcat
|
acts = mconcat
|
||||||
[ singletonMap UserLdapSync $ pure UserLdapSyncData
|
[ singletonMap UserLdapSync $ pure UserLdapSyncData
|
||||||
, singletonMap UserAvsSync $ pure UserAvsSyncData
|
, singletonMap UserAvsSync $ pure UserAvsSyncData
|
||||||
, singletonMap UserAddSupervisor $ UserAddSupervisorData
|
, singletonMap UserAddSupervisor $ UserAddSupervisorData
|
||||||
<$> apopt (textField & cfAnySeparatedSet) (fslI MsgTableSupervisor & setTooltip MsgCourseParticipantsRegisterUsersFieldTip) Nothing
|
<$> apopt (textField & cfAnySeparatedSet) (fslI MsgTableSupervisor & setTooltip MsgCourseParticipantsRegisterUsersFieldTip) Nothing
|
||||||
<*> apopt (boolField . Just $ SomeMessage MsgBoolIrrelevant) (fslI MsgMailSupervisorReroute & setTooltip MsgMailSupervisorRerouteTooltip) (Just True)
|
<*> apopt boolField' (fslI MsgMailSupervisorReroute & setTooltip MsgMailSupervisorRerouteTooltip) (Just False)
|
||||||
<*> aopt (textField & cfStrip & addDatalist superReasons) (fslI MsgUserSupervisorReason & setTooltip MsgUserSupervisorReasonTooltip) Nothing
|
<*> aopt (textField & cfStrip & addDatalist superReasons) (fslI MsgUserSupervisorReason & setTooltip MsgUserSupervisorReasonTooltip) Nothing
|
||||||
, singletonMap UserSetSupervisor $ UserSetSupervisorData
|
, singletonMap UserSetSupervisor $ UserSetSupervisorData
|
||||||
<$> apopt (textField & cfAnySeparatedSet) (fslI MsgTableSupervisor & setTooltip MsgCourseParticipantsRegisterUsersFieldTip) Nothing
|
<$> apopt (textField & cfAnySeparatedSet) (fslI MsgTableSupervisor & setTooltip MsgCourseParticipantsRegisterUsersFieldTip) Nothing
|
||||||
<*> apopt (boolField . Just $ SomeMessage MsgBoolIrrelevant) (fslI MsgMailSupervisorReroute & setTooltip MsgMailSupervisorRerouteTooltip) (Just True)
|
<*> apopt boolField' (fslI MsgMailSupervisorReroute & setTooltip MsgMailSupervisorRerouteTooltip) (Just False)
|
||||||
<*> aopt (textField & cfStrip & addDatalist superReasons) (fslI MsgUserSupervisorReason & setTooltip MsgUserSupervisorReasonTooltip) Nothing
|
<*> aopt (textField & cfStrip & addDatalist superReasons) (fslI MsgUserSupervisorReason & setTooltip MsgUserSupervisorReasonTooltip) Nothing
|
||||||
, singletonMap UserRemoveSupervisor $ pure UserRemoveSupervisorData
|
, singletonMap UserRemoveSupervisor $ pure UserRemoveSupervisorData
|
||||||
, singletonMap UserRemoveSubordinates $ pure UserRemoveSubordinatesData
|
, singletonMap UserRemoveSubordinates $ pure UserRemoveSubordinatesData
|
||||||
|
|||||||
@ -329,6 +329,8 @@ updateAvsUserByADC newAvsDataContact@(AvsDataContact apid newAvsPersonInfo newAv
|
|||||||
let usrId = userAvsUser usravs
|
let usrId = userAvsUser usravs
|
||||||
usr <- MaybeT $ get usrId
|
usr <- MaybeT $ get usrId
|
||||||
lift $ do -- maybeT no longer needed from here onwards
|
lift $ do -- maybeT no longer needed from here onwards
|
||||||
|
uuid :: CryptoUUIDUser <- encrypt usrId
|
||||||
|
$logInfoS "AVS" [st|updateAvsUserByADC: #{tshow uuid}|]
|
||||||
let oldAvsPersonInfo = userAvsLastPersonInfo usravs -- Nothing is ok here
|
let oldAvsPersonInfo = userAvsLastPersonInfo usravs -- Nothing is ok here
|
||||||
oldAvsFirmInfo = userAvsLastFirmInfo usravs -- Nothing is ok here
|
oldAvsFirmInfo = userAvsLastFirmInfo usravs -- Nothing is ok here
|
||||||
oldAvsCardNo = userAvsLastCardNo usravs & fmap Just
|
oldAvsCardNo = userAvsLastCardNo usravs & fmap Just
|
||||||
@ -380,72 +382,73 @@ updateAvsUserByADC newAvsDataContact@(AvsDataContact apid newAvsPersonInfo newAv
|
|||||||
, UserAvsLastCardNo =. newAvsCardNo
|
, UserAvsLastCardNo =. newAvsCardNo
|
||||||
]
|
]
|
||||||
|
|
||||||
-- update company association & supervision
|
usr_up2 <- guardMonoidM (oldAvsFirmInfo /= Just newAvsFirmInfo) $ do
|
||||||
newCompanyEnt@Entity{entityKey=newCompanyId} <- upsertAvsCompany newAvsFirmInfo oldAvsFirmInfo
|
-- update company association & supervision
|
||||||
oldCompanyEnt <- getAvsCompany `traverseJoin` oldAvsFirmInfo
|
newCompanyEnt@Entity{entityKey=newCompanyId} <- upsertAvsCompany newAvsFirmInfo oldAvsFirmInfo
|
||||||
primaryCompanyId <- userCompanyCompany <<$>> getUserPrimaryCompany usrId
|
upsertCompanySuperior newCompanyEnt newAvsFirmInfo oldAvsFirmInfo usrId -- ensure firmInfo superior is supervisor for this user
|
||||||
let oldCompanyId = entityKey <$> oldCompanyEnt
|
oldCompanyEnt <- getAvsCompany `traverseJoin` oldAvsFirmInfo
|
||||||
-- oldCompanyMb = entityVal <$> oldCompanyEnt
|
primaryCompanyId <- userCompanyCompany <<$>> getUserPrimaryCompany usrId
|
||||||
-- pst_up = if
|
let oldCompanyId = entityKey <$> oldCompanyEnt
|
||||||
-- -- | isNothing oldCompanyMb || oldCompanyId == primaryCompanyId -- refactor could replace next 4 lines
|
-- oldCompanyMb = entityVal <$> oldCompanyEnt
|
||||||
-- -- -> mkUpdate' usr newCompany oldCompanyMb $ CheckUpdate UserPrefersPostal _companyPrefersPostal -- always update if company association is fresh (case should not occur in practice though)
|
-- pst_up = if
|
||||||
-- | isNothing oldCompanyMb
|
-- -- | isNothing oldCompanyMb || oldCompanyId == primaryCompanyId -- refactor could replace next 4 lines
|
||||||
-- -> mkUpdateDirect usr newCompany $ CheckUpdate UserPrefersPostal _companyPrefersPostal -- always update if company association is fresh (case should not occur in practice though)
|
-- -- -> mkUpdate' usr newCompany oldCompanyMb $ CheckUpdate UserPrefersPostal _companyPrefersPostal -- always update if company association is fresh (case should not occur in practice though)
|
||||||
-- | oldCompanyId == primaryCompanyId -- && isJust oldCompanyId -- is ensured by previous line
|
-- | isNothing oldCompanyMb
|
||||||
-- -> mkUpdate usr newCompany oldCompanyMb $ CheckUpdate UserPrefersPostal _companyPrefersPostal -- possibly change postal preference
|
-- -> mkUpdateDirect usr newCompany $ CheckUpdate UserPrefersPostal _companyPrefersPostal -- always update if company association is fresh (case should not occur in practice though)
|
||||||
-- | otherwise
|
-- | oldCompanyId == primaryCompanyId -- && isJust oldCompanyId -- is ensured by previous line
|
||||||
-- -> Nothing
|
-- -> mkUpdate usr newCompany oldCompanyMb $ CheckUpdate UserPrefersPostal _companyPrefersPostal -- possibly change postal preference
|
||||||
superReasonComDef = tshow SupervisorReasonCompanyDefault
|
-- | otherwise
|
||||||
newUserComp = UserCompany usrId newCompanyId False False 1 True Nothing -- default value for new company insertion, if no update can be done
|
-- -> Nothing
|
||||||
|
superReasonComDef = tshow SupervisorReasonCompanyDefault
|
||||||
|
newUserComp = UserCompany usrId newCompanyId False False 1 True Nothing -- default value for new company insertion, if no update can be done
|
||||||
|
|
||||||
usr_up2 <- case oldAvsFirmInfo of
|
case oldAvsFirmInfo of
|
||||||
_ | Just newCompanyId == oldCompanyId -- company unchanged entirely
|
_ | Just newCompanyId == oldCompanyId -- company unchanged entirely
|
||||||
-> return mempty -- => do nothing
|
-> return mempty -- => do nothing
|
||||||
(Just oafi) | isJust (view _avsFirmPostAddressSimple oafi)
|
(Just oafi) | isJust (view _avsFirmPostAddressSimple oafi)
|
||||||
&& ((==) `on` view _avsFirmPostAddressSimple) oafi newAvsFirmInfo -- non-empty company address unchanged OR
|
&& ((==) `on` view _avsFirmPostAddressSimple) oafi newAvsFirmInfo -- non-empty company address unchanged OR
|
||||||
|| isJust (view _avsFirmPrimaryEmail oafi)
|
|| isJust (view _avsFirmPrimaryEmail oafi)
|
||||||
&& ((==) `on` view _avsFirmPrimaryEmail) oafi newAvsFirmInfo -- non-empty company primary email unchanged
|
&& ((==) `on` view _avsFirmPrimaryEmail) oafi newAvsFirmInfo -- non-empty company primary email unchanged
|
||||||
-> do -- => just update user company association, keeping supervision privileges
|
-> do -- => just update user company association, keeping supervision privileges
|
||||||
case oldCompanyId of
|
case oldCompanyId of
|
||||||
Nothing -> void $ insertUnique newUserComp -- it's ok if this already exists
|
Nothing -> void $ insertUnique newUserComp -- it's ok if this already exists
|
||||||
Just ocid -> do
|
Just ocid -> do
|
||||||
void $ upsertBySafe (UniqueUserCompany usrId ocid) newUserComp (_userCompanyCompany .~ newCompanyId) -- keep default supervisor settings
|
void $ upsertBySafe (UniqueUserCompany usrId ocid) newUserComp (_userCompanyCompany .~ newCompanyId) -- keep default supervisor settings
|
||||||
void $ updateWhere [ UserSupervisorSupervisor ==. usrId -- update company-related supervisions
|
void $ updateWhere [ UserSupervisorSupervisor ==. usrId -- update company-related supervisions
|
||||||
, UserSupervisorCompany ==. Just ocid -- to new company, regardless of
|
, UserSupervisorCompany ==. Just ocid -- to new company, regardless of
|
||||||
, UserSupervisorReason ==. Just superReasonComDef] -- user
|
, UserSupervisorReason ==. Just superReasonComDef] -- user
|
||||||
[ UserSupervisorCompany =. Just newCompanyId]
|
[ UserSupervisorCompany =. Just newCompanyId]
|
||||||
return mempty
|
return mempty
|
||||||
_ | Just newCompanyId == primaryCompanyId -- old primaryCompany is now also AVS-company
|
_ | Just newCompanyId == primaryCompanyId -- old primaryCompany is now also AVS-company
|
||||||
-> do
|
-> do
|
||||||
whenIsJust oldCompanyId $ \oldCid -> do
|
whenIsJust oldCompanyId $ \oldCid -> do
|
||||||
deleteBy $ UniqueUserCompany usrId oldCid
|
deleteBy $ UniqueUserCompany usrId oldCid
|
||||||
deleteWhere $ (UserSupervisorUser ==. usrId):(UserSupervisorCompany ==. oldCompanyId):(UserSupervisorReason ~=. superReasonComDef)
|
deleteWhere $ (UserSupervisorUser ==. usrId):(UserSupervisorCompany ==. oldCompanyId):(UserSupervisorReason ~=. superReasonComDef)
|
||||||
return mempty
|
return mempty
|
||||||
_ -- company changed completely
|
_ -- company changed completely
|
||||||
-> do
|
-> do
|
||||||
(pst_up, problems) <- switchAvsUserCompany False False usrId newCompanyId
|
(pst_up, problems) <- switchAvsUserCompany False False usrId newCompanyId
|
||||||
mapM_ reportAdminProblem problems
|
mapM_ reportAdminProblem problems
|
||||||
-- Following line does not type, hence additional parameter needed
|
-- Following line does not type, hence additional parameter needed
|
||||||
-- return [ u | u@Update{updateField=f} <- pst_up, f /= UserPostAddress ] -- already computed in frm_up above, duplicate update must be prevented (version above accounts for legacy updates)
|
-- return [ u | u@Update{updateField=f} <- pst_up, f /= UserPostAddress ] -- already computed in frm_up above, duplicate update must be prevented (version above accounts for legacy updates)
|
||||||
return pst_up
|
return pst_up
|
||||||
-- SPECIALISED CODE, PROBABLY DEPRECATED
|
-- SPECIALISED CODE, PROBABLY DEPRECATED
|
||||||
-- switch user company, keeping old priority
|
-- switch user company, keeping old priority
|
||||||
-- (getBy . UniqueUserCompany usrId) `traverseJoin` oldCompanyId >>= \case
|
-- (getBy . UniqueUserCompany usrId) `traverseJoin` oldCompanyId >>= \case
|
||||||
-- Nothing ->
|
-- Nothing ->
|
||||||
-- void $ insertUnique newUserComp
|
-- void $ insertUnique newUserComp
|
||||||
-- Just Entity{entityKey=ucidOld, entityVal=UserCompany{userCompanyCompany, userCompanySupervisor, userCompanySupervisorReroute, userCompanyPriority}} -> do
|
-- Just Entity{entityKey=ucidOld, entityVal=UserCompany{userCompanyCompany, userCompanySupervisor, userCompanySupervisorReroute, userCompanyPriority}} -> do
|
||||||
-- when userCompanySupervisor $ reportAdminProblem $ AdminProblemSupervisorNewCompany usrId userCompanyCompany newCompanyId userCompanySupervisorReroute
|
-- when userCompanySupervisor $ reportAdminProblem $ AdminProblemSupervisorNewCompany usrId userCompanyCompany newCompanyId userCompanySupervisorReroute
|
||||||
-- delete ucidOld
|
-- delete ucidOld
|
||||||
-- void $ insertUnique newUserComp{userCompanyPriority} -- keep priority, if insert succeeds
|
-- void $ insertUnique newUserComp{userCompanyPriority} -- keep priority, if insert succeeds
|
||||||
-- -- adjust supervison
|
-- -- adjust supervison
|
||||||
-- let oldCompDefSuperFltr = mconcat [UserSupervisorCompany ~~. oldCompanyId, UserSupervisorReason ~=. superReasonComDef]
|
-- let oldCompDefSuperFltr = mconcat [UserSupervisorCompany ~~. oldCompanyId, UserSupervisorReason ~=. superReasonComDef]
|
||||||
-- deleteWhere $ (UserSupervisorSupervisor ==. usrId) : oldCompDefSuperFltr
|
-- deleteWhere $ (UserSupervisorSupervisor ==. usrId) : oldCompDefSuperFltr
|
||||||
-- oldAPs <- deleteWhereCount $ (UserSupervisorUser ==. usrId) : oldCompDefSuperFltr
|
-- oldAPs <- deleteWhereCount $ (UserSupervisorUser ==. usrId) : oldCompDefSuperFltr
|
||||||
-- addDefaultSupervisors' newCompanyId $ singleton usrId
|
-- addDefaultSupervisors' newCompanyId $ singleton usrId
|
||||||
-- newAPs <- count $ (UserSupervisorUser ==. usrId) : (UserSupervisorCompany ==. Just newCompanyId) : (UserSupervisorReason ~=. superReasonComDef)
|
-- newAPs <- count $ (UserSupervisorUser ==. usrId) : (UserSupervisorCompany ==. Just newCompanyId) : (UserSupervisorReason ~=. superReasonComDef)
|
||||||
-- when (oldAPs > 0 && newAPs <= 0) $ reportAdminProblem $ AdminProblemNewlyUnsupervised usrId oldCompanyId newCompanyId
|
-- when (oldAPs > 0 && newAPs <= 0) $ reportAdminProblem $ AdminProblemNewlyUnsupervised usrId oldCompanyId newCompanyId
|
||||||
-- return pst_up
|
-- return pst_up
|
||||||
upsertCompanySuperior newCompanyEnt newAvsFirmInfo oldAvsFirmInfo [usrId] -- ensure firmInfo superior is supervisor for this user
|
|
||||||
update usrId usr_up2 -- update user by company switch first (due to possible conflicts with usr_up2)
|
update usrId usr_up2 -- update user by company switch first (due to possible conflicts with usr_up2)
|
||||||
update usrId usr_up1 -- update user eventually
|
update usrId usr_up1 -- update user eventually
|
||||||
update uaId avs_ups -- update stored avsinfo for future updates
|
update uaId avs_ups -- update stored avsinfo for future updates
|
||||||
@ -585,16 +588,18 @@ getAvsCompany afi =
|
|||||||
|
|
||||||
-- | insert a company from AVS firm info or update an existing one based on previous values
|
-- | insert a company from AVS firm info or update an existing one based on previous values
|
||||||
upsertAvsCompany :: AvsFirmInfo -> Maybe AvsFirmInfo -> DB (Entity Company)
|
upsertAvsCompany :: AvsFirmInfo -> Maybe AvsFirmInfo -> DB (Entity Company)
|
||||||
|
-- upsertAvsCompany newAvsFirmInfo (Just oldAvsFirmInfo)
|
||||||
|
-- | newAvsFirmInfo == oldAvsFirmInfo = maybeM (upsertAvsCompany newAvsFirmInfo Nothing) pure $ getAvsCompany newAvsFirmInfo -- firmInfo unchanged, shortcircuit; SHORTCIRCUIT no longer needed, checked at call-site due to result not being wrapped in Maybe
|
||||||
upsertAvsCompany newAvsFirmInfo mbOldAvsFirmInfo = do
|
upsertAvsCompany newAvsFirmInfo mbOldAvsFirmInfo = do
|
||||||
mbFirmEnt <- getAvsCompany newAvsFirmInfo -- primarily by AvsId, then Shorthand, then name
|
mbFirmEnt <- getAvsCompany newAvsFirmInfo -- primarily by AvsId, then Shorthand, then name
|
||||||
$logInfoS "AVS" [st|upsertAvsCompany: old #{tshow mbFirmEnt} new #{tshow newAvsFirmInfo}|]
|
$logInfoS "AVS" [st|upsertAvsCompany: old #{tshow mbOldAvsFirmInfo} new #{tshow newAvsFirmInfo} ent-new #{tshow mbFirmEnt}|]
|
||||||
case (mbFirmEnt, mbOldAvsFirmInfo) of
|
case mbFirmEnt of
|
||||||
(Nothing, _) -> do -- insert new company, neither AvsId nor Shorthand exist in DB
|
Nothing -> do -- insert new company, neither AvsId nor Shorthand exist in DB
|
||||||
afn <- if 0 < newAvsFirmInfo ^. _avsFirmFirmNo
|
afn <- if 0 < newAvsFirmInfo ^. _avsFirmFirmNo
|
||||||
then return $ newAvsFirmInfo ^. _avsFirmFirmNo
|
then return $ newAvsFirmInfo ^. _avsFirmFirmNo
|
||||||
else maybe (-1) (pred . companyAvsId . entityVal) <$> selectMaybe [CompanyAvsId <. 0] [Asc CompanyAvsId]
|
else maybe (-1) (pred . companyAvsId . entityVal) <$> selectMaybe [CompanyAvsId <. 0] [Asc CompanyAvsId]
|
||||||
let upd = flip updateRecord newAvsFirmInfo
|
let upd = flip updateRecord newAvsFirmInfo
|
||||||
dmy = Company -- mostly dummy, values are actually prodcued through firmInfo2company below for consistency
|
dmy = Company -- mostly dummy, values are actually produced through firmInfo2company below for consistency
|
||||||
{ companyName = newAvsFirmInfo ^. _avsFirmFirm . from _CI
|
{ companyName = newAvsFirmInfo ^. _avsFirmFirm . from _CI
|
||||||
, companyShorthand = newAvsFirmInfo ^. _avsFirmAbbreviation . from _CI
|
, companyShorthand = newAvsFirmInfo ^. _avsFirmAbbreviation . from _CI
|
||||||
, companyAvsId = afn
|
, companyAvsId = afn
|
||||||
@ -606,11 +611,12 @@ upsertAvsCompany newAvsFirmInfo mbOldAvsFirmInfo = do
|
|||||||
$logInfoS "AVS" $ "Insert new company: " <> tshow cmp
|
$logInfoS "AVS" $ "Insert new company: " <> tshow cmp
|
||||||
newCmp <- insertEntity cmp
|
newCmp <- insertEntity cmp
|
||||||
reportAdminProblem $ AdminProblemNewCompany $ entityKey newCmp
|
reportAdminProblem $ AdminProblemNewCompany $ entityKey newCmp
|
||||||
$logInfoS "AVS" "Insert new company completed."
|
|
||||||
return newCmp
|
return newCmp
|
||||||
|
|
||||||
(Just Entity{entityKey=firmid, entityVal=firm}, oldAvsFirmInfo) -> do -- possibly update existing company, if isJust oldAvsFirmInfo and changed occurred
|
(Just Entity{entityKey=firmid, entityVal=firm}) -> do -- possibly update existing company, if isJust oldAvsFirmInfo and identical AvsFirmNo and changes occurred
|
||||||
let cmp_ups = mapMaybe (mkUpdate' firm newAvsFirmInfo oldAvsFirmInfo) firmInfo2company
|
let oldHasSameFirmNo = Just (newAvsFirmInfo ^. _avsFirmFirmNo) == (mbOldAvsFirmInfo ^? _Just . _avsFirmFirmNo)
|
||||||
|
oldAvsFirmInfo = guardOnM oldHasSameFirmNo mbOldAvsFirmInfo
|
||||||
|
cmp_ups = mapMaybe (mkUpdate' firm newAvsFirmInfo oldAvsFirmInfo) firmInfo2company
|
||||||
key_ups = mkUpdate' firm newAvsFirmInfo oldAvsFirmInfo firmInfo2key
|
key_ups = mkUpdate' firm newAvsFirmInfo oldAvsFirmInfo firmInfo2key
|
||||||
uniq_ups <- mkUpdateCheckUnique' firm newAvsFirmInfo oldAvsFirmInfo firmInfo2companyNo
|
uniq_ups <- mkUpdateCheckUnique' firm newAvsFirmInfo oldAvsFirmInfo firmInfo2companyNo
|
||||||
$logInfoS "AVS" [st|Update company #{companyShorthand firm}: #{tshow (length cmp_ups)}, #{tshow (length key_ups)}, #{tshow (length uniq_ups)} for #{tshow oldAvsFirmInfo}|]
|
$logInfoS "AVS" [st|Update company #{companyShorthand firm}: #{tshow (length cmp_ups)}, #{tshow (length key_ups)}, #{tshow (length uniq_ups)} for #{tshow oldAvsFirmInfo}|]
|
||||||
@ -629,7 +635,7 @@ upsertAvsCompany newAvsFirmInfo mbOldAvsFirmInfo = do
|
|||||||
| otherwise -> $logInfoS "AVS" $ "Update company shorthand failed for " <> ciOriginal cmp_key <> " and " <> ciOriginal alt_key
|
| otherwise -> $logInfoS "AVS" $ "Update company shorthand failed for " <> ciOriginal cmp_key <> " and " <> ciOriginal alt_key
|
||||||
maybeM (return res_cmp) return $ getBy uniq_cmp
|
maybeM (return res_cmp) return $ getBy uniq_cmp
|
||||||
_otherwise -> return res_cmp
|
_otherwise -> return res_cmp
|
||||||
$logInfoS "AVS" "Update company completed."
|
$logInfoS "AVS" [st|Update company #{companyShorthand firm} completed.|]
|
||||||
return res_cmp2
|
return res_cmp2
|
||||||
where
|
where
|
||||||
firmInfo2key =
|
firmInfo2key =
|
||||||
@ -645,8 +651,8 @@ upsertAvsCompany newAvsFirmInfo mbOldAvsFirmInfo = do
|
|||||||
|
|
||||||
|
|
||||||
-- | adjust superiors, assumes that CompanyUser exists for all usrs for given company; does not work otherwise
|
-- | adjust superiors, assumes that CompanyUser exists for all usrs for given company; does not work otherwise
|
||||||
upsertCompanySuperior :: Entity Company -> AvsFirmInfo -> Maybe AvsFirmInfo -> [UserId] -> DB () -- may return superior (Maybe UserId), but currently not needed
|
upsertCompanySuperior :: Entity Company -> AvsFirmInfo -> Maybe AvsFirmInfo -> UserId -> DB () -- may return superior (Maybe UserId), but currently not needed
|
||||||
upsertCompanySuperior Entity{entityKey=cid, entityVal=Company{}} newAfi oldAfi usrs =
|
upsertCompanySuperior Entity{entityKey=cid, entityVal=Company{}} newAfi oldAfi usrId =
|
||||||
let reasonSuperior = Just $ tshow SupervisorReasonAvsSuperior
|
let reasonSuperior = Just $ tshow SupervisorReasonAvsSuperior
|
||||||
getInsertUid eml = altM (guessUserByEmail $ stripCI eml) (catchAll2log' $ Just . entityKey <$> ldapLookupAndUpsert eml)
|
getInsertUid eml = altM (guessUserByEmail $ stripCI eml) (catchAll2log' $ Just . entityKey <$> ldapLookupAndUpsert eml)
|
||||||
newAvsNo = newAfi ^. _avsFirmFirmNo
|
newAvsNo = newAfi ^. _avsFirmFirmNo
|
||||||
@ -655,22 +661,26 @@ upsertCompanySuperior Entity{entityKey=cid, entityVal=Company{}} newAfi oldAfi u
|
|||||||
mbOldEmail = oldAfi ^? _Just . _avsFirmEMailSuperior . _Just
|
mbOldEmail = oldAfi ^? _Just . _avsFirmEMailSuperior . _Just
|
||||||
getSupId = getInsertUid `traverseJoin` mbSupEmail
|
getSupId = getInsertUid `traverseJoin` mbSupEmail
|
||||||
getOldId = (guessUserByEmail . stripCI) `traverseJoin` mbOldEmail
|
getOldId = (guessUserByEmail . stripCI) `traverseJoin` mbOldEmail
|
||||||
unchangedCompany = oldAvsNo == Just newAvsNo
|
getSupervision :: Maybe UserId -> DB (Maybe (Entity UserSupervisor))
|
||||||
changedSuperior = mbSupEmail /= mbOldEmail -- beware, both could be Nothing
|
getSupervision = traverseJoin (getBy . flip UniqueUserSupervisor usrId)
|
||||||
|
unchangedCompany = oldAvsNo == Just newAvsNo
|
||||||
|
changedSuperior = mbSupEmail /= mbOldEmail -- beware we only have AvsFirmInfo for one user; also both could be Nothing
|
||||||
-- 1. not unchangedCompany: do not delete, but ensure that superior supervision is set, since it could be a just a single user company change
|
-- 1. not unchangedCompany: do not delete, but ensure that superior supervision is set, since it could be a just a single user company change
|
||||||
-- 2. unchangedCompany && not changedSuperior: superior must already been set, short-circuit
|
-- 2. unchangedCompany && not changedSuperior: superior must already been set, short-circuit
|
||||||
-- 3. unchangedCompany && changedSuperior: update superior for all users
|
-- 3. unchangedCompany && changedSuperior: update superior for all users
|
||||||
in unless (unchangedCompany && not changedSuperior) $ do -- do nothing if (unchangedCompany && not changedSuperior).
|
in unless (unchangedCompany && not changedSuperior) $ do -- do nothing if (unchangedCompany && not changedSuperior).
|
||||||
mbSupId <- getSupId
|
mbSupId <- getSupId
|
||||||
|
mbUsrSup <- getSupervision mbSupId
|
||||||
-- delete old superiors, if any
|
-- delete old superiors, if any
|
||||||
when (unchangedCompany && changedSuperior) $
|
when (unchangedCompany && changedSuperior) $
|
||||||
deleteWhere $ mcons ((UserSupervisorSupervisor !=.) <$> mbSupId)
|
deleteWhere $ mcons ((UserSupervisorSupervisor !=.) <$> mbSupId)
|
||||||
[ UserSupervisorCompany ==. Just cid, UserSupervisorReason ==. reasonSuperior ]
|
[ UserSupervisorCompany ==. Just cid, UserSupervisorReason ==. reasonSuperior ]
|
||||||
unless unchangedCompany $
|
unless unchangedCompany $
|
||||||
deleteWhere [ UserSupervisorReason ==. reasonSuperior, UserSupervisorUser <-. usrs ]
|
deleteWhere [ UserSupervisorReason ==. reasonSuperior, UserSupervisorUser ==. usrId ]
|
||||||
-- ensure superior supervision
|
-- ensure superior supervision
|
||||||
case mbSupId of
|
case (mbSupId, mbUsrSup) of
|
||||||
Just supId -> do
|
(_ , Just _) -> return () -- supId is already supervisor for uid for any reason
|
||||||
|
(Just supId, Nothing) -> do
|
||||||
-- ensure association between company and superior at equal-to-top priority
|
-- ensure association between company and superior at equal-to-top priority
|
||||||
prio <- getCompanyUserMaxPrio supId
|
prio <- getCompanyUserMaxPrio supId
|
||||||
void $ insertUnique (UserCompany supId cid False False prio True reasonSuperior) -- superior is not a supervisor, do not change existing user company associations
|
void $ insertUnique (UserCompany supId cid False False prio True reasonSuperior) -- superior is not a supervisor, do not change existing user company associations
|
||||||
@ -702,7 +712,7 @@ upsertCompanySuperior Entity{entityKey=cid, entityVal=Company{}} newAfi oldAfi u
|
|||||||
when (unchangedCompany && changedSuperior) $ do
|
when (unchangedCompany && changedSuperior) $ do
|
||||||
oldSupId <- getOldId
|
oldSupId <- getOldId
|
||||||
reportAdminProblem $ AdminProblemCompanySuperiorChange supId cid oldSupId
|
reportAdminProblem $ AdminProblemCompanySuperiorChange supId cid oldSupId
|
||||||
Nothing ->
|
(Nothing, Nothing) ->
|
||||||
when (unchangedCompany && changedSuperior) $ do
|
when (unchangedCompany && changedSuperior) $ do
|
||||||
oldSupId <- getOldId
|
oldSupId <- getOldId
|
||||||
reportAdminProblem $ AdminProblemCompanySuperiorNotFound mbSupEmail cid oldSupId
|
reportAdminProblem $ AdminProblemCompanySuperiorNotFound mbSupEmail cid oldSupId
|
||||||
|
|||||||
@ -222,7 +222,8 @@ defaultSupervisorReasonFilter :: [Filter UserSupervisor]
|
|||||||
defaultSupervisorReasonFilter =
|
defaultSupervisorReasonFilter =
|
||||||
[UserSupervisorReason ==. Nothing]
|
[UserSupervisorReason ==. Nothing]
|
||||||
||. [UserSupervisorReason ==. Just (tshow SupervisorReasonCompanyDefault)]
|
||. [UserSupervisorReason ==. Just (tshow SupervisorReasonCompanyDefault)]
|
||||||
-- ||. [UserSupervisorReason <-. [Just $ tshow r | r <- [SupervisorReasonCompanyDefault, SupervisorReasonAvsSuperior]]]
|
||. [UserSupervisorReason ==. Just (tshow SupervisorReasonAvsSuperior )]
|
||||||
|
-- ||. [UserSupervisorReason <-. Nothing : [Just $ tshow r | r <- [SupervisorReasonCompanyDefault, SupervisorReasonAvsSuperior]]] -- Does <-. work with Nothing?
|
||||||
|
|
||||||
-- | remove supervisors for given users; maybe restricted to those linked to given companies or supervisors
|
-- | remove supervisors for given users; maybe restricted to those linked to given companies or supervisors
|
||||||
deleteDefaultSupervisorsForUsers :: [CompanyId] -> [UserId] -> NonEmpty UserId -> DB Int64
|
deleteDefaultSupervisorsForUsers :: [CompanyId] -> [UserId] -> NonEmpty UserId -> DB Int64
|
||||||
@ -232,14 +233,6 @@ deleteDefaultSupervisorsForUsers cids sprs usrs =
|
|||||||
$ bcons (notNull sprs) (UserSupervisorSupervisor <-. sprs)
|
$ bcons (notNull sprs) (UserSupervisorSupervisor <-. sprs)
|
||||||
$ (UserSupervisorUser <-. toList usrs) : defaultSupervisorReasonFilter
|
$ (UserSupervisorUser <-. toList usrs) : defaultSupervisorReasonFilter
|
||||||
|
|
||||||
-- | deletes user company association and all company related supervision
|
|
||||||
-- WARNING: does not check for admin problems!
|
|
||||||
deleteCompanyUser :: CompanyId -> [UserId] -> DB (Int64, Int64, Int64)
|
|
||||||
deleteCompanyUser cid uids = (,,)
|
|
||||||
<$> deleteWhereCount [UserCompanyCompany ==. cid, UserCompanyUser <-. uids]
|
|
||||||
<*> deleteWhereCount ((UserSupervisorCompany ==. Just cid):(UserSupervisorSupervisor <-. uids) : defaultSupervisorReasonFilter)
|
|
||||||
<*> deleteWhereCount ((UserSupervisorCompany ==. Just cid):(UserSupervisorUser <-. uids) : defaultSupervisorReasonFilter)
|
|
||||||
|
|
||||||
-- | retrieve maximum company user priority fo a user
|
-- | retrieve maximum company user priority fo a user
|
||||||
getCompanyUserMaxPrio :: UserId -> DB Int
|
getCompanyUserMaxPrio :: UserId -> DB Int
|
||||||
getCompanyUserMaxPrio uid = do
|
getCompanyUserMaxPrio uid = do
|
||||||
|
|||||||
@ -67,7 +67,7 @@ dispatchJobLmsEnqueue qid = JobHandlerAtomic act
|
|||||||
now <- liftIO getCurrentTime
|
now <- liftIO getCurrentTime
|
||||||
let nowaday = utctDay now
|
let nowaday = utctDay now
|
||||||
-- send second reminders first, before enqueing even more, but only for users with currently open LMS and still valid Qualificiations
|
-- send second reminders first, before enqueing even more, but only for users with currently open LMS and still valid Qualificiations
|
||||||
ifNothingM (qualificationRefreshReminder quali) () $ \remindPeriod -> do
|
whenIsJust (qualificationRefreshReminder quali) $ \remindPeriod -> do
|
||||||
let remindDate = addGregorianDurationClip remindPeriod nowaday
|
let remindDate = addGregorianDurationClip remindPeriod nowaday
|
||||||
reminders <- E.select $ do
|
reminders <- E.select $ do
|
||||||
(luser :& quser) <- E.from $ E.table @LmsUser `E.innerJoin` E.table @QualificationUser
|
(luser :& quser) <- E.from $ E.table @LmsUser `E.innerJoin` E.table @QualificationUser
|
||||||
@ -91,33 +91,40 @@ dispatchJobLmsEnqueue qid = JobHandlerAtomic act
|
|||||||
, jNotification = NotificationQualificationRenewal { nQualification = qid, nReminder = True }
|
, jNotification = NotificationQualificationRenewal { nQualification = qid, nReminder = True }
|
||||||
}
|
}
|
||||||
_ -> return ()
|
_ -> return ()
|
||||||
|
-- send initial reminders
|
||||||
ifNothingM (qualificationRefreshWithin quali) () $ \renewalPeriod -> do -- no refreshWithin, no first reminders
|
whenIsJust (qualificationRefreshWithin quali) $ \renewalPeriod -> do -- no refreshWithin, no first reminders
|
||||||
let renewalDate = addGregorianDurationClip renewalPeriod nowaday
|
let renewalDate = addGregorianDurationClip renewalPeriod nowaday
|
||||||
renewalUsers <- E.select $ do
|
renewalUsers <- E.select $ do
|
||||||
quser <- E.from $ E.table @QualificationUser
|
quser <- E.from $ E.table @QualificationUser
|
||||||
E.where_ $ quser E.^. QualificationUserQualification E.==. E.val qid
|
E.where_ $ quser E.^. QualificationUserQualification E.==. E.val qid
|
||||||
E.&&. quser E.^. QualificationUserScheduleRenewal
|
E.&&. quser E.^. QualificationUserScheduleRenewal
|
||||||
E.&&. quser E.^. QualificationUserValidUntil E.<=. E.val renewalDate
|
E.&&. quser E.^. QualificationUserValidUntil E.<=. E.val renewalDate
|
||||||
E.&&. (quser `qualificationValid` now)
|
E.&&. (quser `qualificationValid` now)
|
||||||
E.&&. E.notExists (do
|
E.&&. E.notExists (do
|
||||||
luser <- E.from $ E.table @LmsUser
|
luser <- E.from $ E.table @LmsUser
|
||||||
E.where_ $ luser E.^. LmsUserQualification E.==. E.val qid
|
E.where_ $ luser E.^. LmsUserQualification E.==. E.val qid
|
||||||
E.&&. luser E.^. LmsUserUser E.==. quser E.^. QualificationUserUser
|
E.&&. luser E.^. LmsUserUser E.==. quser E.^. QualificationUserUser
|
||||||
E.&&. E.isNothing (luser E.^. LmsUserEnded)
|
E.&&. E.isNothing (luser E.^. LmsUserEnded)
|
||||||
)
|
)
|
||||||
pure quser
|
pure quser
|
||||||
let usr_job :: Entity QualificationUser -> Job
|
let usr_job :: Entity QualificationUser -> Maybe Job
|
||||||
usr_job quser =
|
usr_job quser =
|
||||||
let uid = quser ^. _entityVal . _qualificationUserUser
|
let uid = quser ^. _entityVal . _qualificationUserUser
|
||||||
uex = quser ^. _entityVal . _qualificationUserValidUntil
|
uex = quser ^. _entityVal . _qualificationUserValidUntil
|
||||||
in if qualificationElearningStart quali
|
unf = quser ^. _entityVal . _qualificationUserLastNotified
|
||||||
then JobLmsEnqueueUser { jQualification = qid, jUser = uid }
|
nfy_cutoff = addGregorianDurationClip renewalPeriod $ utctDay unf
|
||||||
else JobUserNotification { jRecipient = uid, jNotification =
|
do_notify = uex > nfy_cutoff || (uex == nfy_cutoff && utctDayTime now >= utctDayTime unf)
|
||||||
NotificationQualificationExpiry { nQualification = qid, nExpiry = uex }
|
in if
|
||||||
}
|
| qualificationElearningStart quali -- repetition avoided since LmsUser does not exist
|
||||||
forM_ renewalUsers (queueDBJob . usr_job)
|
-> Just $ JobLmsEnqueueUser { jQualification = qid, jUser = uid }
|
||||||
logInterface "LMS" (qshort <> "-enq") True (Just $ length renewalUsers) ""
|
| do_notify -- repetition avoided by QualificationUserLastNotified
|
||||||
|
-> Just $ JobUserNotification
|
||||||
|
{ jRecipient = uid
|
||||||
|
, jNotification = NotificationQualificationExpiry { nQualification = qid, nExpiry = uex }
|
||||||
|
}
|
||||||
|
| otherwise -> Nothing
|
||||||
|
forM_ renewalUsers (flip whenIsJust queueDBJob . usr_job)
|
||||||
|
logInterface "LMS" (qshort <> "-enq") True (Just $ length renewalUsers) ""
|
||||||
|
|
||||||
dispatchJobLmsEnqueueUser :: QualificationId -> UserId -> JobHandler UniWorX
|
dispatchJobLmsEnqueueUser :: QualificationId -> UserId -> JobHandler UniWorX
|
||||||
dispatchJobLmsEnqueueUser qid uid = JobHandlerAtomic act
|
dispatchJobLmsEnqueueUser qid uid = JobHandlerAtomic act
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
-- SPDX-FileCopyrightText: 2022-23 Steffen Jost <jost@tcs.ifi.lmu.de>
|
-- SPDX-FileCopyrightText: 2022-24 Steffen Jost <jost@tcs.ifi.lmu.de>,Steffen Jost <s.jost@fraport.de>
|
||||||
--
|
--
|
||||||
-- SPDX-License-Identifier: AGPL-3.0-or-later
|
-- SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
@ -22,24 +22,22 @@ import Text.Hamlet
|
|||||||
|
|
||||||
|
|
||||||
dispatchNotificationQualificationExpiry :: QualificationId -> Day -> UserId -> Handler ()
|
dispatchNotificationQualificationExpiry :: QualificationId -> Day -> UserId -> Handler ()
|
||||||
dispatchNotificationQualificationExpiry nQualification dExpiry jRecipient = userMailT jRecipient $ do
|
dispatchNotificationQualificationExpiry nQualification dExpiry jRecipient = do
|
||||||
(recipient@User{..}, Qualification{..}) <- liftHandler . runDB $ (,)
|
now <- liftIO getCurrentTime
|
||||||
|
encRecipient :: CryptoUUIDUser <- liftHandler $ encrypt jRecipient
|
||||||
|
(recipient@User{..}, Qualification{..}) <- runDB $ (,)
|
||||||
<$> getJust jRecipient
|
<$> getJust jRecipient
|
||||||
<*> getJust nQualification
|
<*> getJust nQualification
|
||||||
|
|
||||||
encRecipient :: CryptoUUIDUser <- liftHandler $ encrypt jRecipient
|
|
||||||
let entRecipient = Entity jRecipient recipient
|
let entRecipient = Entity jRecipient recipient
|
||||||
qname = CI.original qualificationName
|
qname = CI.original qualificationName
|
||||||
expiryDate <- formatTimeUser SelFormatDate dExpiry $ Just entRecipient
|
userMailT jRecipient $ do
|
||||||
|
expiryDate <- formatTimeUser SelFormatDate dExpiry $ Just entRecipient
|
||||||
$logDebugS "LMS" $ "Notify " <> tshow encRecipient <> " about expiry of qualification " <> qname
|
replaceMailHeader "Auto-Submitted" $ Just "auto-generated"
|
||||||
|
setSubjectI $ MsgMailSubjectQualificationExpiry qname
|
||||||
replaceMailHeader "Auto-Submitted" $ Just "auto-generated"
|
editNotifications <- mkEditNotifications jRecipient
|
||||||
setSubjectI $ MsgMailSubjectQualificationExpiry qname
|
addHtmlMarkdownAlternatives $(ihamletFile "templates/mail/qualificationExpiry.hamlet")
|
||||||
|
runDB $ updateBy (UniqueQualificationUser nQualification jRecipient) [QualificationUserLastNotified =. now]
|
||||||
editNotifications <- mkEditNotifications jRecipient
|
$logDebugS "LMS" $ "Notified " <> tshow encRecipient <> " about soonish expiry of qualification " <> qname
|
||||||
|
|
||||||
addHtmlMarkdownAlternatives $(ihamletFile "templates/mail/qualificationExpiry.hamlet")
|
|
||||||
|
|
||||||
|
|
||||||
dispatchNotificationQualificationExpired :: QualificationId -> UserId -> Handler ()
|
dispatchNotificationQualificationExpired :: QualificationId -> UserId -> Handler ()
|
||||||
@ -81,7 +79,7 @@ dispatchNotificationQualificationExpired nQualification jRecipient = do
|
|||||||
$logInfoS "LMS" $ "Notified " <> tshow encRecipient <> " about expired qualification " <> qname
|
$logInfoS "LMS" $ "Notified " <> tshow encRecipient <> " about expired qualification " <> qname
|
||||||
else
|
else
|
||||||
$logErrorS "LMS" $ "Failed to notify " <> tshow encRecipient <> " about expired qualification " <> qname
|
$logErrorS "LMS" $ "Failed to notify " <> tshow encRecipient <> " about expired qualification " <> qname
|
||||||
else $logInfoS "LMS" $ "Suppressed repeated notification " <> tshow encRecipient <> " about expired qualification " <> qname
|
else $logInfoS "LMS" $ "Suppressed repeated notification " <> tshow encRecipient <> " about expired qualification " <> qname -- should no longer happen to using quserToNotify filter in Jobs.Handler.Lms, but sometimes does after restarts
|
||||||
_ -> $logErrorS "LMS" $ "Failed to notify " <> tshow encRecipient <> " about expired qualification " <> tshow nQualification
|
_ -> $logErrorS "LMS" $ "Failed to notify " <> tshow encRecipient <> " about expired qualification " <> tshow nQualification
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -122,11 +122,11 @@ dispatchJobSynchroniseAvsQueue = JobHandlerException $ do
|
|||||||
-- E.truncateTable $ AvsSync (error "truncateTable: AvsSyncUser not needed") now Nothing
|
-- E.truncateTable $ AvsSync (error "truncateTable: AvsSyncUser not needed") now Nothing
|
||||||
-- return jobs
|
-- return jobs
|
||||||
let (unlinked, linked) = foldl' discernJob mempty jobs
|
let (unlinked, linked) = foldl' discernJob mempty jobs
|
||||||
$logInfoS "SynchronisAvs" [st|AVS synch performing for #{length linked} AVS linked users and #{length unlinked} unlinked users|]
|
$logInfoS "SynchronisAvs" [st|AVS synch start for #{length linked} AVS linked users and #{length unlinked} unlinked users|]
|
||||||
void $ updateAvsUserByIds linked
|
void $ updateAvsUserByIds linked
|
||||||
void $ linktoAvsUserByUIDs unlinked
|
void $ linktoAvsUserByUIDs unlinked
|
||||||
runDB $ deleteWhere [AvsSyncUser <-. (E.unValue . fst3 <$> jobs)]
|
runDB $ deleteWhere [AvsSyncUser <-. (E.unValue . fst3 <$> jobs)]
|
||||||
$logInfoS "SynchronisAvs" [st|AVS synch performed for #{length linked} AVS linked users and #{length unlinked} unlinked users|]
|
$logInfoS "SynchronisAvs" [st|AVS synch end for #{length linked} AVS linked users and #{length unlinked} unlinked users|]
|
||||||
-- we do not reschedule failed synchs here in order to avoid a loop
|
-- we do not reschedule failed synchs here in order to avoid a loop
|
||||||
where
|
where
|
||||||
discernJob accs ( _ , E.Value (Just api), E.Value True ) = accs & over _2 (Set.insert api)
|
discernJob accs ( _ , E.Value (Just api), E.Value True ) = accs & over _2 (Set.insert api)
|
||||||
@ -146,8 +146,7 @@ dispatchJobSynchroniseAvsLicences = JobHandlerException $ do -- when (synchLevel
|
|||||||
, avsLicenceSynchMaxChanges = maxChanges
|
, avsLicenceSynchMaxChanges = maxChanges
|
||||||
} <- getsYesod $ view _appAvsLicenceSynchConf
|
} <- getsYesod $ view _appAvsLicenceSynchConf
|
||||||
|
|
||||||
let -- TODO: enable a cron job by setting
|
let procLic :: AvsLicence -> Bool -> Set AvsPersonId -> Handler ()
|
||||||
procLic :: AvsLicence -> Bool -> Set AvsPersonId -> Handler ()
|
|
||||||
procLic aLic up apids
|
procLic aLic up apids
|
||||||
| n <- Set.size apids, n > 0 =
|
| n <- Set.size apids, n > 0 =
|
||||||
let subtype = Text.cons (bool '↧' '↥' up) $ Text.singleton $ licence2char aLic
|
let subtype = Text.cons (bool '↧' '↥' up) $ Text.singleton $ licence2char aLic
|
||||||
|
|||||||
@ -5,10 +5,15 @@ $#
|
|||||||
$# SPDX-License-Identifier: AGPL-3.0-or-later
|
$# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
Bitte beachten, dass Ansprechpartner-Beziehung unabhängig von Firmenzugehörigkeit zwischen Einzelpersonen bestehen.
|
<p>
|
||||||
Daraus folgt zum Beispiel, dass wenn <em>x</em> ein Standard-Ansprechpartner für Firma <em>a</em> ist
|
Bitte beachten: Ansprechpartner-Beziehung bestehen unabhängig von Firmenzugehörigkeit zwischen Einzelpersonen! #
|
||||||
und wenn <em>y</em> sowohl Firma <em>a</em> als auch <em>b</em> angehört,
|
|
||||||
dass dann <em>x</em> als firmenfremd in der Liste der Ansprechpartner von Firma <em>b</em> angezeigt wird.
|
<p>
|
||||||
|
Daraus folgt zum Beispiel, dass wenn <em>x</em> ein Standard-Ansprechpartner für Firma <em>a</em> ist #
|
||||||
|
und wenn <em>y</em> sowohl Firma <em>a</em> als auch <em>b</em> angehört, #
|
||||||
|
dass <em>x</em> als firmenfremd in der Liste der Ansprechpartner von Firma <em>b</em> angezeigt wird. #
|
||||||
|
Dies kann hier mit der Aktion "Firmenansprechpartner entfernen" nicht geändert werden, #
|
||||||
|
da die Ansprechpartnerbeziehung ja über eine andere Firma weiter existiert.
|
||||||
|
|
||||||
^{firmContactInfo}
|
^{firmContactInfo}
|
||||||
|
|
||||||
|
|||||||
@ -5,9 +5,12 @@ $#
|
|||||||
$# SPDX-License-Identifier: AGPL-3.0-or-later
|
$# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
Note that supervision is company independent.
|
<p>
|
||||||
For example, if <em>x</em> is a regular supervisor for company <em>a</em> and <em>y</em> belongs to companies <em>a</em> and <em>b</em>,
|
Note that supervisionship is company independent! #
|
||||||
then <em>x</em> will be listed as a foreign supervisor for company <em>b</em>.
|
<p>
|
||||||
|
For example, if <em>x</em> is a regular supervisor for company <em>a</em> and <em>y</em> belongs to companies <em>a</em> and <em>b</em>, #
|
||||||
|
then <em>x</em> will be listed as a foreign supervisor for company <em>b</em>. #
|
||||||
|
This cannot be changed through action "Remove default supervisor" here, since the external supervisionship persists.
|
||||||
|
|
||||||
^{firmContactInfo}
|
^{firmContactInfo}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user