-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathLoan.hs
170 lines (143 loc) · 4.67 KB
/
Loan.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
{-# LANGUAGE Arrows #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module OpalLib.Loan where
import Prelude hiding (null)
import Control.Arrow (returnA)
import Control.Lens (makeLenses,(^.),(.~),(%~),to,_1)
import Control.Monad (void)
import Data.Time (UTCTime)
import Data.Profunctor.Product.TH (makeAdaptorAndInstance)
import Opaleye
import Opaleye.Classy
import OpalLib.Ids
import OpalLib.Date
import OpalLib.Accession
import OpalLib.Person
import OpalLib.Book
data Loan' a b c d e f = Loan
{ _loanId :: a
, _loanPersonId :: b
, _loanAccessionId :: c
, _loanBorrowed :: d
, _loanDue :: e
, _loanReturned :: f
} deriving Show
makeLenses ''Loan'
makeAdaptorAndInstance "pLoan" ''Loan'
type LoanColumns = Loan'
LoanIdColumn
PersonIdColumn
AccessionIdColumn
(Column PGTimestamptz)
(Column PGTimestamptz)
(Column (Nullable PGTimestamptz))
type LoanInsertColumns = Loan'
LoanIdColumnMaybe
PersonIdColumn
AccessionIdColumn
(Column PGTimestamptz)
(Column PGTimestamptz)
(Column (Nullable PGTimestamptz))
type Loan = Loan'
LoanId
PersonId
AccessionId
UTCTime
UTCTime
(Maybe UTCTime)
type LoanColumnsNullable = Loan'
LoanIdColumnNullable
PersonIdColumnNullable
AccessionIdColumnNullable
(Column (Nullable PGTimestamptz))
(Column (Nullable PGTimestamptz))
(Column (Nullable PGTimestamptz))
type FullLoanColumns =
(LoanColumns,AccessionIdColumn,BookColumns,PersonColumns)
type FullLoan = (Loan,AccessionId,Book,Person)
loanTable :: Table LoanInsertColumns LoanColumns
loanTable = Table "loan" $ pLoan Loan
{ _loanId = pLoanId . LoanId $ optional "id"
, _loanPersonId = pPersonId . PersonId $ required "person_id"
, _loanAccessionId = pAccessionId . AccessionId $ required "accession_id"
, _loanBorrowed = required "borrowed"
, _loanDue = required "due"
, _loanReturned = required "returned"
}
loanQuery :: Query LoanColumns
loanQuery = queryTable loanTable
loansAll :: CanOpaleye c e m => m [Loan]
loansAll = liftQuery loanQuery
loanPersonQuery :: QueryArr LoanColumns PersonColumns
loanPersonQuery = proc (l) -> do
p <- personQuery -< ()
restrict -< l^.loanPersonId.to unPersonId .== p^.personId.to unPersonId
returnA -< p
loanAccessionQuery :: QueryArr LoanColumns (AccessionIdColumn,BookColumns)
loanAccessionQuery = proc (l) -> do
t <- accessionsWithBookQuery -< ()
restrict -< l^.loanAccessionId.to unAccessionId .== t^._1.to unAccessionId
returnA -< t
fullLoanQuery :: Query FullLoanColumns
fullLoanQuery = proc () -> do
l <- loanQuery -< ()
p <- loanPersonQuery -< l
(aId,b) <- loanAccessionQuery -< l
returnA -< (l,aId,b,p)
findLoanByLoanIdQuery :: LoanIdColumn -> Query FullLoanColumns
findLoanByLoanIdQuery lId = proc () -> do
t <- fullLoanQuery -< ()
restrict -< t^._1.loanId.to unLoanId .== unLoanId lId
returnA -< t
findLoanByLoanId
:: CanOpaleye c e m
=> LoanId
-> m (Maybe FullLoan)
findLoanByLoanId = liftQueryFirst . findLoanByLoanIdQuery . constant
borrow
:: CanOpaleye c e m
=> AccessionId
-> PersonId
-> UTCTime
-> UTCTime
-> m LoanId
borrow aId pId b d =
fmap head $ liftInsertReturning loanTable (^.loanId) $ Loan
{ _loanId = LoanId Nothing
, _loanPersonId = constant pId
, _loanAccessionId = constant aId
, _loanBorrowed = constant b
, _loanDue = constant d
, _loanReturned = null
}
loanOutstanding :: LoanColumns -> Column PGBool
loanOutstanding l = l^.loanReturned.to isNull
restrictLoansCurrent :: QueryArr LoanColumns ()
restrictLoansCurrent = proc (l) -> do
restrict -< loanOutstanding l
loansOutstandingQuery :: Query FullLoanColumns
loansOutstandingQuery = proc () -> do
t <- fullLoanQuery -< ()
restrictLoansCurrent -< t^._1
returnA -< t
loansOutstanding :: CanOpaleye c e m => m [FullLoan]
loansOutstanding = liftQuery loansOutstandingQuery
loansOverdueQuery :: Query FullLoanColumns
loansOverdueQuery = proc () -> do
t <- fullLoanQuery -< ()
restrictLoansCurrent -< t^._1
restrict -< t^._1.loanDue .<= now
returnA -< t
loansOverdue :: CanOpaleye c e m => m [FullLoan]
loansOverdue = liftQuery loansOverdueQuery
loanReturn :: CanOpaleye c e m => LoanId -> UTCTime -> m ()
loanReturn lId r = void $ liftUpdate loanTable
( (loanId %~ pLoanId (LoanId Just))
. (loanReturned .~ toNullable (constant r))
)
(\ l -> l^.loanId.to unLoanId .== unLoanId (constant lId))