fradrive/src/Handler/Allocation/EditUser.hs
2021-06-15 13:55:37 +02:00

149 lines
6.4 KiB
Haskell

module Handler.Allocation.EditUser
( getAEditUserR, postAEditUserR
, getADelUserR, postADelUserR
) where
import Import
import Handler.Allocation.Application
import Handler.Allocation.UserForm
import Handler.Utils
import qualified Data.Map.Strict as Map
import qualified Data.Set as Set
import qualified Data.Conduit.Combinators as C
import Handler.Utils.Delete
import qualified Database.Esqueleto as E
getAEditUserR, postAEditUserR :: TermId -> SchoolId -> AllocationShorthand -> CryptoUUIDUser -> Handler Html
getAEditUserR = postAEditUserR
postAEditUserR tid ssh ash cID = do
(Entity _ Allocation{..}, User{..}, (editUserAct, editUserForm, editUserEnctype)) <- runDB $ do
uid <- decrypt cID
user <- get404 uid
alloc@(Entity aId _) <- getBy404 $ TermSchoolAllocationShort tid ssh ash
Entity auId AllocationUser{..} <- getBy404 $ UniqueAllocationUser aId uid
((editUserRes, editUserForm), editUserEnctype) <- runFormPost . renderAForm FormStandard $
allocationUserForm aId $ Just AllocationUserForm
{ aauUser = uid
, aauTotalCourses = allocationUserTotalCourses
, aauPriority = allocationUserPriority
, aauApplications = Map.empty -- form collects existing applications itself
}
editUserAct <- formResultMaybe editUserRes $ \AllocationUserForm{..} -> Just <$> do
now <- liftIO getCurrentTime
replace auId AllocationUser
{ allocationUserAllocation = aId
, allocationUserUser = aauUser
, allocationUserTotalCourses = aauTotalCourses
, allocationUserPriority = aauPriority
}
audit $ TransactionAllocationUserEdited aauUser aId
oldApps <- selectList [CourseApplicationUser ==. aauUser, CourseApplicationAllocation ==. Just aId] []
forM_ oldApps $ \(Entity appId CourseApplication{..}) -> do
deleteWhere [ CourseApplicationFileApplication ==. appId ]
delete appId
unless (courseApplicationCourse `Map.member` aauApplications) $
audit $ TransactionCourseApplicationDeleted courseApplicationCourse courseApplicationUser appId
iforM_ aauApplications $ \cId ApplicationForm{..} -> maybeT_ $ do
prio <- hoistMaybe afPriority
let rated = afRatingVeto || is _Just afRatingPoints
appId <- lift $ insert CourseApplication
{ courseApplicationCourse = cId
, courseApplicationUser = aauUser
, courseApplicationText = afText
, courseApplicationRatingVeto = afRatingVeto
, courseApplicationRatingPoints = afRatingPoints
, courseApplicationRatingComment = afRatingComment
, courseApplicationAllocation = Just aId
, courseApplicationAllocationPriority = Just prio
, courseApplicationTime = now
, courseApplicationRatingTime = guardOn rated now
}
lift . runConduit $ transPipe liftHandler (sequence_ afFiles) .| C.mapM_ (insert_ . review _FileReference . (, CourseApplicationFileResidual appId))
lift . audit $ TransactionCourseApplicationEdit cId aauUser appId
return $ do
addMessageI Success MsgAllocationEditUserUserEdited
redirect $ AllocationR tid ssh ash AUsersR
return (alloc, user, (editUserAct, editUserForm, editUserEnctype))
sequence_ editUserAct
MsgRenderer mr <- getMsgRenderer
let title = MsgAllocationEditUserTitle (mr . ShortTermIdentifier $ unTermKey allocationTerm) (unSchoolKey allocationSchool) allocationShorthand userDisplayName
shortTitle = MsgAllocationEditUserShortTitle allocationTerm allocationSchool allocationShorthand userDisplayName
siteLayoutMsg title $ do
setTitleI shortTitle
wrapForm editUserForm FormSettings
{ formMethod = POST
, formAction = Just . SomeRoute . AllocationR tid ssh ash $ AEditUserR cID
, formEncoding = editUserEnctype
, formAttrs = []
, formSubmit = FormSubmit
, formAnchor = Nothing :: Maybe Text
}
getADelUserR, postADelUserR :: TermId -> SchoolId -> AllocationShorthand -> CryptoUUIDUser -> Handler Html
getADelUserR = postADelUserR
postADelUserR tid ssh ash cID = do
uid <- decrypt cID
(aId, auId) <- runDB . maybeT notFound $ do
aId <- MaybeT . getKeyBy $ TermSchoolAllocationShort tid ssh ash
auId <- MaybeT . getKeyBy $ UniqueAllocationUser aId uid
return (aId, auId)
deleteR DeleteRoute
{ drRecords = Set.singleton auId
, drGetInfo = \(allocationUser `E.InnerJoin` user) -> do
E.on $ allocationUser E.^. AllocationUserUser E.==. user E.^. UserId
let appsCount = E.subSelectCount . E.from $ \courseApplication ->
E.where_ $ courseApplication E.^. CourseApplicationUser E.==. allocationUser E.^. AllocationUserUser
E.&&. courseApplication E.^. CourseApplicationAllocation E.==. E.just (allocationUser E.^. AllocationUserAllocation)
allocsCount = E.subSelectCount . E.from $ \courseParticipant ->
E.where_ $ courseParticipant E.^. CourseParticipantUser E.==. allocationUser E.^. AllocationUserUser
E.&&. courseParticipant E.^. CourseParticipantAllocated E.==. E.just (allocationUser E.^. AllocationUserAllocation)
return ( ( user E.^. UserDisplayName, user E.^. UserSurname )
, appsCount :: E.SqlExpr (E.Value Word64)
, allocsCount :: E.SqlExpr (E.Value Word64)
)
, drUnjoin = \(allocationUser `E.InnerJoin` _user) -> allocationUser
, drRenderRecord = \((E.Value dName, E.Value sName), E.Value (assertM' (> 0) -> appsCount), E.Value (assertM' (> 0) -> allocsCount)) -> return
[whamlet|
$newline never
^{nameWidget dName sName}
$if is _Just appsCount || is _Just allocsCount
\ (
$maybe c <- appsCount
_{MsgAllocationApplicationsCount c}
$if is _Just appsCount || is _Just allocsCount
, #
$maybe c <- appsCount
_{MsgAllocationAllocationsCount c}
)
|]
, drRecordConfirmString = \((E.Value dName, _), _, _) -> return [st|#{dName}|]
, drFormMessage = \_ -> return Nothing
, drCaption = SomeMessage MsgAllocationUserDeleteQuestion
, drSuccessMessage = SomeMessage MsgAllocationUserDeleted
, drAbort = SomeRoute . AllocationR tid ssh ash $ AEditUserR cID
, drSuccess = SomeRoute $ AllocationR tid ssh ash AUsersR
, drDelete = \_k doDelete -> do
res <- doDelete
audit $ TransactionAllocationUserDeleted uid aId
return res
}