Begin implementation of billing event persistence.
[?]
Jan 20, 2017, 5:31 AM
73NDXDEZRMK672GHSTC3CI6YHXFZ2GGJI5IKQGHKFDZKTNSQXLLQCDependencies
- [2]
5ZSKPQ3KAdd created_at and auction_start timestamps to auction - [3]
DFOBMSAOInitial work on payments API - [4]
3QVT6MA6Add database support for event amend operations. - [5]
7KZP4RHZSwitch from Data.Time to Data.Thyme - [6]
RPAJLHMTChange to use UUIDs instead of ints for primary keys. - [7]
IZEVQF62Work in progress replacing sqlite with postgres. - [8]
GCVQD44VCreate amends endpoint, switch to UUID primary keys - [9]
7HPY3QPFFix linting errors. (yay hlint!) - [10]
ZP62WC47Begin conversion to build with stack. - [11]
EKY7U7SKFinish conversion to stack. - [12]
NEDDHXUKReformat via stylish-haskell - [13]
O5FVTOM6Undo JSON silliness, enable a couple more routes. - [14]
2G3GNDDUEvent logging is now functioning in postgres. - [15]
XTBSG4C7Adding serveJSON combinator to eliminate some boilerplate from handlers. - [16]
KEP5WUFJConvert project to stack-based build. - [17]
NLZ3JXLOFix formatting with stylish-haskell. - [18]
LD4GLVSFMore database stuff. - [19]
M4KM76DGMerge branch 'stackify' - [20]
QMRKFEPGRefactor QDB to use a free monad algebra instead. - [21]
ZITLSTYXFix problems with SQL queries & depreciation function parsing. - [22]
RN7EI6INUpdate database layer to use CreditTo - [23]
NAS4BFL4Trivial stylish-haskell reformat. - [24]
2XQD6KKKAdd invitation logic and clean up DBProg error handling. - [25]
5OI44E4EAdd authentication to auction search. - [26]
FD7SV5I6Fix handling of event_t columns. - [27]
A6HKMINBAttempting to improve JSON handling. - [28]
HALRDT2FAdded initial auction create route. - [29]
TNR3TEHKSwitch to Postgres + snaplet arch compiles. - [30]
Z7KS5XHHVery WIP. Wow. - [*]
64C6AWH6Rename Ananke -> Quixotic, project reboot. - [*]
BROSTG5KBeginning of modularization of server.
Change contents
- replacement in lib/Aftok/Billables.hs at line 7
import Control.Lens (makeLenses)import Control.Lens (makeLenses, makePrisms) - edit in lib/Aftok/Billables.hs at line 11
import Aftok.Project (ProjectId)import Aftok (UserId)import Aftok.Types (Satoshi) - replacement in lib/Aftok/Billables.hs at line 16
makePrisms ''BillableId - replacement in lib/Aftok/Billables.hs at line 18
data BillingFrequencydata Recurrence - edit in lib/Aftok/Billables.hs at line 23
makeLenses ''BillingFrequencydata Recurrence= Recurring { _frequency :: BillingFrequency } - replacement in lib/Aftok/Billables.hs at line 26
data Billable (p :: *) (c :: *) = BillablerecurrenceName :: Recurrence -> TextrecurrenceName Annually = "annually"recurrenceName (Monthly _) = "monthly"recurrenceName SemiMonthly = "semimonthly"recurrenceName (Weekly _) = "weekly"recurrenceName OneTime = "onetime"recurrenceCount :: Recurrence -> Maybe IntrecurrenceCount Annually = NothingrecurrenceCount (Monthly i) = Just irecurrenceCount SemiMonthly = NothingrecurrenceCount (Weekly i) = Just irecurrenceCount OneTime = Nothingdata Billable' (p :: *) (u :: *) (c :: *) = Billable - edit in lib/Aftok/Billables.hs at line 42
, _creator :: u - replacement in lib/Aftok/Billables.hs at line 49
makeLenses ''BillablemakeLenses ''Billable'type Billable = Billable' ProjectId UserId Satoshi - replacement in lib/Aftok/Billables.hs at line 53
monthly :: BillingFrequencymonthly :: Recurrence - replacement in lib/Aftok/Billables.hs at line 56
bimonthly :: BillingFrequencybimonthly :: Recurrence - replacement in lib/Aftok/Billables.hs at line 59
quarterly :: BillingFrequencyquarterly :: Recurrence - replacement in lib/Aftok/Billables.hs at line 62
seminannually :: BillingFrequencyseminannually :: Recurrence - replacement in lib/Aftok/Billables.hs at line 65
annually :: BillingFrequencyannually :: Recurrence - edit in lib/Aftok/Billables.hs at line 68[3.1730]
newtype SubscriptionId = SubscriptionId UUID deriving (Show, Eq) - replacement in lib/Aftok/Database/PostgreSQL.hs at line 17
import Database.PostgreSQL.Simple.FromFieldimport Database.PostgreSQL.Simple.FromField - replacement in lib/Aftok/Database/PostgreSQL.hs at line 24
import Aftok.Auction as Aimport qualified Aftok.Auction as Aimport qualified Aftok.Billables as BI - replacement in lib/Aftok/Database/PostgreSQL.hs at line 28
import Aftok.Project as Pimport qualified Aftok.Project as Pimport Aftok.Time (Days(..), _Days) - replacement in lib/Aftok/Database/PostgreSQL.hs at line 45
pidParser :: FieldParser ProjectIdpidParser f v = ProjectId <$> fromField f vpidParser :: FieldParser P.ProjectIdpidParser f v = P.ProjectId <$> fromField f v - edit in lib/Aftok/Database/PostgreSQL.hs at line 77
recurrenceParser :: RowParser BI.RecurrencerecurrenceParser =let prec :: Text -> RowParser BI.Recurrenceprec "annually" = nullField *> pure BI.Annuallyprec "monthly" = BI.Monthly <$> fieldprec "semimonthly" = nullField *> pure BI.SemiMonthlyprec "weekly" = BI.Weekly <$> fieldprec "onetime" = nullField *> pure BI.OneTimeprec _ = emptyin field >>= prec - replacement in lib/Aftok/Database/PostgreSQL.hs at line 91[4.213]→[4.213:243](∅→∅),[4.243]→[3.2364:2765](∅→∅),[3.2765]→[4.533:607](∅→∅),[4.533]→[4.533:607](∅→∅),[4.607]→[3.2766:3131](∅→∅),[3.3131]→[4.863:892](∅→∅),[4.863]→[4.863:892](∅→∅)
case tn of"event_t" ->let err = UnexpectedNull { errSQLType = B.unpack tn, errSQLTableOid = tableOid f, errSQLField = maybe "" B.unpack (name f), errHaskellType = "UTCTime -> LogEvent", errMessage = "columns of type event_t should not contain null values"}in maybe (conversionError err) (nameEvent . decodeUtf8) v_ ->let err = Incompatible { errSQLType = B.unpack tn, errSQLTableOid = tableOid f, errSQLField = maybe "" B.unpack (name f), errHaskellType = "UTCTime -> LogEvent", errMessage = "column was not of type event_t"}in conversionError errif tn /= "event_t"then returnError Incompatible f "column was not of type event_t"else maybe (returnError UnexpectedNull f "event type may not be null") (nameEvent . decodeUtf8) v - replacement in lib/Aftok/Database/PostgreSQL.hs at line 96[4.944]→[4.944:1043](∅→∅),[4.1043]→[4.596:638](∅→∅),[4.638]→[4.1086:1409](∅→∅),[4.1086]→[4.1086:1409](∅→∅)
creditToParser f v = dotn <- typename flet parser :: Text -> Conversion (RowParser CreditTo)parser tname = pure $ case tname of"credit_to_btc_addr" -> CreditToAddress <$> (fieldWith btcAddrParser <* nullField <* nullField)"credit_to_user" -> CreditToUser <$> (nullField *> fieldWith uidParser <* nullField)"credit_to_project" -> CreditToProject <$> (nullField *> nullField *> fieldWith pidParser)_ -> emptycreditToParser f v =let parser :: Text -> RowParser CreditToparser "credit_to_btc_addr" = CreditToAddress <$> (fieldWith btcAddrParser <* nullField <* nullField)parser "credit_to_user" = CreditToUser <$> (nullField *> fieldWith uidParser <* nullField)parser "credit_to_project" = CreditToProject <$> (nullField *> nullField *> fieldWith pidParser)parser _ = emptyin dotn <- typename fif tn /= "credit_to_t"then returnError Incompatible f "column was not of type credit_to_t"else maybe empty (pure . parser . decodeUtf8) v - edit in lib/Aftok/Database/PostgreSQL.hs at line 108[4.1410]→[4.1410:1480](∅→∅),[4.1480]→[4.639:685](∅→∅),[4.685]→[4.1528:1679](∅→∅),[4.1528]→[4.1528:1679](∅→∅),[4.1679]→[4.686:687](∅→∅),[4.687]→[4.1682:1683](∅→∅),[4.1682]→[4.1682:1683](∅→∅)
case tn of"credit_to_t" -> maybe empty (parser . decodeUtf8) v_ -> conversionError $Incompatible(B.unpack tn)(tableOid f)(maybe "" B.unpack (name f))"RowParser CreditTo""column was not of type event_t" - replacement in lib/Aftok/Database/PostgreSQL.hs at line 120
auctionParser :: RowParser AuctionauctionParser :: RowParser A.Auction - replacement in lib/Aftok/Database/PostgreSQL.hs at line 122[4.2039]→[4.109:177](∅→∅),[4.177]→[2.187:221](∅→∅),[4.177]→[4.275:309](∅→∅),[2.221]→[4.275:309](∅→∅),[4.275]→[4.275:309](∅→∅),[4.309]→[2.222:256](∅→∅),[4.47]→[4.2144:2178](∅→∅),[4.156]→[4.2144:2178](∅→∅),[2.256]→[4.2144:2178](∅→∅),[4.309]→[4.2144:2178](∅→∅),[4.662]→[4.2144:2178](∅→∅),[4.2144]→[4.2144:2178](∅→∅)
Auction <$> fieldWith pidParser<*> fieldWith uidParser<*> fieldWith utcParser<*> fieldWith btcParser<*> fieldWith utcParser<*> fieldWith utcParserA.Auction <$> fieldWith pidParser<*> fieldWith uidParser<*> fieldWith utcParser<*> fieldWith btcParser<*> fieldWith utcParser<*> fieldWith utcParser - replacement in lib/Aftok/Database/PostgreSQL.hs at line 129
bidParser :: RowParser BidbidParser :: RowParser A.Bid - replacement in lib/Aftok/Database/PostgreSQL.hs at line 131
Bid <$> fieldWith uidParser<*> fieldWith secondsParser<*> fieldWith btcParser<*> fieldWith utcParserA.Bid <$> fieldWith uidParser<*> fieldWith secondsParser<*> fieldWith btcParser<*> fieldWith utcParser - replacement in lib/Aftok/Database/PostgreSQL.hs at line 147
projectParser :: RowParser ProjectprojectParser :: RowParser P.Project - replacement in lib/Aftok/Database/PostgreSQL.hs at line 149[4.2224]→[4.2224:2278](∅→∅),[4.2275]→[4.1210:1244](∅→∅),[4.2278]→[4.1210:1244](∅→∅),[4.1210]→[4.1210:1244](∅→∅),[4.1244]→[4.422:460](∅→∅)
Project <$> field<*> fieldWith utcParser<*> fieldWith uidParser<*> fieldWith fromJSONFieldP.Project <$> field<*> fieldWith utcParser<*> fieldWith uidParser<*> fieldWith fromJSONField - replacement in lib/Aftok/Database/PostgreSQL.hs at line 154
invitationParser :: RowParser InvitationinvitationParser :: RowParser P.Invitation - replacement in lib/Aftok/Database/PostgreSQL.hs at line 156
Invitation <$> fieldWith pidParser<*> fieldWith uidParser<*> fieldWith emailParser<*> fieldWith utcParser<*> fmap (fmap toThyme) fieldP.Invitation <$> fieldWith pidParser<*> fieldWith uidParser<*> fieldWith emailParser<*> fieldWith utcParser<*> fmap (fmap toThyme) field - edit in lib/Aftok/Database/PostgreSQL.hs at line 166
billableParser :: RowParser BI.BillablebillableParser =BI.Billable <$> fieldWith pidParser<*> fieldWith uidParser<*> field<*> field<*> recurrenceParser<*> fieldWith btcParser<*> (Days <$> field) - replacement in lib/Aftok/Database/PostgreSQL.hs at line 198[4.1362]→[4.581:608](∅→∅),[4.608]→[4.4:75](∅→∅),[4.75]→[4.688:732](∅→∅),[4.732]→[4.121:182](∅→∅),[4.121]→[4.121:182](∅→∅),[4.182]→[4.1732:1885](∅→∅),[4.1885]→[4.316:341](∅→∅),[4.316]→[4.316:341](∅→∅),[4.341]→[3.3184:3302](∅→∅)
instance DBEval QDBM wheredbEval (CreateEvent (ProjectId pid) (UserId uid) (LogEntry c e m)) =case c ofCreditToAddress addr ->pinsert EventId"INSERT INTO work_events \\(project_id, user_id, credit_to_type, credit_to_btc_addr, event_type, event_time, event_metadata) \\VALUES (?, ?, ?, ?, ?, ?, ?) \\RETURNING id"( pid, uid, creditToName c, addr ^. _BtcAddr . to addrToBase58, eventName e, fromThyme $ e ^. eventTime, m)storeEvent :: DBOp a -> Maybe (QDBM EventId)storeEvent (CreateBillable _) = error "Not implemented"storeEvent (CreateSubscription _ _) = error "Not implemented"storeEvent (CreatePaymentRequest _) = error "Not implemented"storeEvent (CreatePayment _) = error "Not implemented"storeEvent _ = Nothing - replacement in lib/Aftok/Database/PostgreSQL.hs at line 205[4.426]→[4.1987:2017](∅→∅),[4.2017]→[4.455:516](∅→∅),[4.455]→[4.455:516](∅→∅),[4.516]→[4.2018:2173](∅→∅),[4.2173]→[4.652:677](∅→∅),[4.652]→[4.652:677](∅→∅),[4.677]→[4.2174:2276](∅→∅)
CreditToProject pid' ->pinsert EventId"INSERT INTO work_events \\(project_id, user_id, credit_to_type, credit_to_project_id, event_type, event_time, event_metadata) \\VALUES (?, ?, ?, ?, ?, ?, ?) \\RETURNING id"( pid, uid, creditToName c, pid' ^. _ProjectId, eventName e, fromThyme $ e ^. eventTime, m)updateCache :: DBOp a -> QDBM aupdateCache (CreateEvent (P.ProjectId pid) (UserId uid) (LogEntry c e m)) =case c ofCreditToAddress addr ->pinsert EventId"INSERT INTO work_events \\(project_id, user_id, credit_to_type, credit_to_btc_addr, event_type, event_time, event_metadata) \\VALUES (?, ?, ?, ?, ?, ?, ?) \\RETURNING id"( pid, uid, creditToName c, addr ^. _BtcAddr . to addrToBase58, eventName e, fromThyme $ e ^. eventTime, m) - replacement in lib/Aftok/Database/PostgreSQL.hs at line 216[4.763]→[4.2277:2304](∅→∅),[4.2304]→[4.789:850](∅→∅),[4.789]→[4.789:850](∅→∅),[4.850]→[4.2305:2457](∅→∅),[4.2457]→[4.983:1008](∅→∅),[4.983]→[4.983:1008](∅→∅),[4.1008]→[4.2458:2557](∅→∅)
CreditToUser uid' ->pinsert EventId"INSERT INTO work_events \\(project_id, user_id, credit_to_type, credit_to_user_id, event_type, event_time, event_metadata) \\VALUES (?, ?, ?, ?, ?, ?, ?) \\RETURNING id"( pid, uid, creditToName c, uid' ^. _UserId, eventName e, fromThyme $ e ^. eventTime, m)CreditToProject pid' ->pinsert EventId"INSERT INTO work_events \\(project_id, user_id, credit_to_type, credit_to_project_id, event_type, event_time, event_metadata) \\VALUES (?, ?, ?, ?, ?, ?, ?) \\RETURNING id"( pid, uid, creditToName c, pid' ^. P._ProjectId, eventName e, fromThyme $ e ^. eventTime, m) - replacement in lib/Aftok/Database/PostgreSQL.hs at line 224[4.1808]→[4.2552:2589](∅→∅),[4.2589]→[4.236:277](∅→∅),[4.236]→[4.236:277](∅→∅),[4.277]→[4.2558:2746](∅→∅),[4.2746]→[4.1162:1200](∅→∅),[4.1162]→[4.1162:1200](∅→∅)
dbEval (FindEvent (EventId eid)) =headMay <$> pquery qdbLogEntryParser"SELECT project_id, user_id, \\credit_to_type, credit_to_btc_addr, credit_to_user_id, credit_to_project_id, \\event_type, event_time, event_metadata FROM work_events \\WHERE id = ?"(Only eid)CreditToUser uid' ->pinsert EventId"INSERT INTO work_events \\(project_id, user_id, credit_to_type, credit_to_user_id, event_type, event_time, event_metadata) \\VALUES (?, ?, ?, ?, ?, ?, ?) \\RETURNING id"( pid, uid, creditToName c, uid' ^. _UserId, eventName e, fromThyme $ e ^. eventTime, m) - replacement in lib/Aftok/Database/PostgreSQL.hs at line 232[4.3406]→[4.1231:1289](∅→∅),[4.1289]→[4.278:323](∅→∅),[4.323]→[4.1323:1409](∅→∅),[4.1323]→[4.1323:1409](∅→∅),[4.1409]→[4.2590:2659](∅→∅),[4.2659]→[4.2802:2836](∅→∅),[4.1479]→[4.2802:2836](∅→∅),[4.2836]→[4.324:371](∅→∅),[4.371]→[4.1548:1684](∅→∅),[4.1548]→[4.1548:1684](∅→∅),[4.1684]→[4.2660:2712](∅→∅),[4.2712]→[4.2837:2884](∅→∅),[4.1737]→[4.2837:2884](∅→∅),[4.2884]→[4.372:416](∅→∅),[4.416]→[4.1815:1901](∅→∅),[4.1815]→[4.1815:1901](∅→∅),[4.1901]→[4.2713:2782](∅→∅),[4.2782]→[4.2885:2919](∅→∅),[4.1971]→[4.2885:2919](∅→∅),[4.2919]→[4.417:432](∅→∅)
dbEval (FindEvents (ProjectId pid) (UserId uid) ival) =let q (Before e) = pquery logEntryParser"SELECT btc_addr, event_type, event_time, event_metadata FROM work_events \\WHERE project_id = ? AND user_id = ? AND event_time <= ?"(pid, uid, fromThyme e)q (During s e) = pquery logEntryParser"SELECT btc_addr, event_type, event_time, event_metadata FROM work_events \\WHERE project_id = ? AND user_id = ? \\AND event_time >= ? AND event_time <= ?"(pid, uid, fromThyme s, fromThyme e)q (After s) = pquery logEntryParser"SELECT btc_addr, event_type, event_time, event_metadata FROM work_events \\WHERE project_id = ? AND user_id = ? AND event_time >= ?"(pid, uid, fromThyme s)in q ivalupdateCache (FindEvent (EventId eid)) =headMay <$> pquery qdbLogEntryParser"SELECT project_id, user_id, \\credit_to_type, credit_to_btc_addr, credit_to_user_id, credit_to_project_id, \\event_type, event_time, event_metadata FROM work_events \\WHERE id = ?"(Only eid) - replacement in lib/Aftok/Database/PostgreSQL.hs at line 240[4.1084]→[4.2783:2839](∅→∅),[4.2839]→[4.2092:2116](∅→∅),[4.2092]→[4.2092:2116](∅→∅),[4.2116]→[4.1091:1216](∅→∅),[4.1216]→[4.2221:2276](∅→∅),[4.2221]→[4.2221:2276](∅→∅)
dbEval (AmendEvent (EventId eid) (TimeChange mt t)) =pinsert AmendmentId"INSERT INTO event_time_amendments \\(event_id, amended_at, event_time) \\VALUES (?, ?, ?) RETURNING id"( eid, fromThyme $ mt ^. _ModTime, fromThyme t )updateCache (FindEvents (P.ProjectId pid) (UserId uid) ival) =let q (Before e) = pquery logEntryParser"SELECT btc_addr, event_type, event_time, event_metadata FROM work_events \\WHERE project_id = ? AND user_id = ? AND event_time <= ?"(pid, uid, fromThyme e)q (During s e) = pquery logEntryParser"SELECT btc_addr, event_type, event_time, event_metadata FROM work_events \\WHERE project_id = ? AND user_id = ? \\AND event_time >= ? AND event_time <= ?"(pid, uid, fromThyme s, fromThyme e)q (After s) = pquery logEntryParser"SELECT btc_addr, event_type, event_time, event_metadata FROM work_events \\WHERE project_id = ? AND user_id = ? AND event_time >= ?"(pid, uid, fromThyme s)in q ival - replacement in lib/Aftok/Database/PostgreSQL.hs at line 256[4.1952]→[4.2747:2821](∅→∅),[4.2821]→[4.1305:1532](∅→∅),[4.1305]→[4.1305:1532](∅→∅),[4.1532]→[3.3303:3401](∅→∅)
dbEval (AmendEvent (EventId eid) (CreditToChange mt c)) =case c ofCreditToAddress addr ->pinsert AmendmentId"INSERT INTO event_credit_to_amendments \\(event_id, amended_at, credit_to_type, credit_to_btc_addr) \\VALUES (?, ?, ?, ?) RETURNING id"( eid, fromThyme $ mt ^. _ModTime, creditToName c, addr ^. _BtcAddr . to addrToBase58 )updateCache (AmendEvent (EventId eid) (TimeChange mt t)) =pinsert AmendmentId"INSERT INTO event_time_amendments \\(event_id, amended_at, event_time) \\VALUES (?, ?, ?) RETURNING id"( eid, fromThyme $ mt ^. _ModTime, fromThyme t ) - replacement in lib/Aftok/Database/PostgreSQL.hs at line 263
CreditToProject pid ->pinsert AmendmentId"INSERT INTO event_credit_to_amendments \\(event_id, amended_at, credit_to_type, credit_to_project_id) \\VALUES (?, ?, ?, ?) RETURNING id"( eid, fromThyme $ mt ^. _ModTime, creditToName c, pid ^. _ProjectId )updateCache (AmendEvent (EventId eid) (CreditToChange mt c)) =case c ofCreditToAddress addr ->pinsert AmendmentId"INSERT INTO event_credit_to_amendments \\(event_id, amended_at, credit_to_type, credit_to_btc_addr) \\VALUES (?, ?, ?, ?) RETURNING id"( eid, fromThyme $ mt ^. _ModTime, creditToName c, addr ^. _BtcAddr . to addrToBase58 ) - replacement in lib/Aftok/Database/PostgreSQL.hs at line 272[4.1933]→[4.733:759](∅→∅),[4.759]→[4.2985:3013](∅→∅),[4.1960]→[4.2985:3013](∅→∅),[4.3013]→[4.1960:2128](∅→∅),[4.1960]→[4.1960:2128](∅→∅),[4.2128]→[4.3014:3092](∅→∅)
CreditToUser uid ->pinsert AmendmentId"INSERT INTO event_credit_to_amendments \\(event_id, amended_at, credit_to_type, credit_to_user_id) \\VALUES (?, ?, ?, ?) RETURNING id"( eid, fromThyme $ mt ^. _ModTime, creditToName c, uid ^. _UserId )CreditToProject pid ->pinsert AmendmentId"INSERT INTO event_credit_to_amendments \\(event_id, amended_at, credit_to_type, credit_to_project_id) \\VALUES (?, ?, ?, ?) RETURNING id"( eid, fromThyme $ mt ^. _ModTime, creditToName c, pid ^. P._ProjectId ) - replacement in lib/Aftok/Database/PostgreSQL.hs at line 279[4.2209]→[4.2904:2964](∅→∅),[4.2904]→[4.2904:2964](∅→∅),[4.2964]→[4.2589:2613](∅→∅),[4.2589]→[4.2589:2613](∅→∅),[4.2613]→[4.2210:2343](∅→∅),[4.2343]→[4.2720:2764](∅→∅),[4.2720]→[4.2720:2764](∅→∅)
dbEval (AmendEvent (EventId eid) (MetadataChange mt v)) =pinsert AmendmentId"INSERT INTO event_metadata_amendments \\(event_id, amended_at, event_metadata) \\VALUES (?, ?, ?) RETURNING id"( eid, fromThyme $ mt ^. _ModTime, v)CreditToUser uid ->pinsert AmendmentId"INSERT INTO event_credit_to_amendments \\(event_id, amended_at, credit_to_type, credit_to_user_id) \\VALUES (?, ?, ?, ?) RETURNING id"( eid, fromThyme $ mt ^. _ModTime, creditToName c, uid ^. _UserId ) - replacement in lib/Aftok/Database/PostgreSQL.hs at line 286[4.4598]→[4.2920:2966](∅→∅),[4.2966]→[4.2799:2839](∅→∅),[4.2799]→[4.2799:2839](∅→∅),[4.2839]→[4.2965:3067](∅→∅),[4.3067]→[4.433:450](∅→∅),[4.2942]→[4.433:450](∅→∅),[4.450]→[4.2966:2998](∅→∅),[4.2986]→[4.2966:2998](∅→∅),[4.2966]→[4.2966:2998](∅→∅)
dbEval (ReadWorkIndex (ProjectId pid)) = dologEntries <- pquery logEntryParser"SELECT btc_addr, event_type, event_time, event_metadata FROM work_events WHERE project_id = ?"(Only pid)pure $ workIndex logEntriesupdateCache (AmendEvent (EventId eid) (MetadataChange mt v)) =pinsert AmendmentId"INSERT INTO event_metadata_amendments \\(event_id, amended_at, event_metadata) \\VALUES (?, ?, ?) RETURNING id"( eid, fromThyme $ mt ^. _ModTime, v) - replacement in lib/Aftok/Database/PostgreSQL.hs at line 293[4.4862]→[4.178:209](∅→∅),[4.209]→[4.3035:3057](∅→∅),[4.3103]→[4.3035:3057](∅→∅),[4.3035]→[4.3035:3057](∅→∅),[4.3057]→[4.310:427](∅→∅),[4.427]→[4.210:252](∅→∅),[4.252]→[4.453:492](∅→∅),[4.453]→[4.453:492](∅→∅),[4.492]→[3.3402:3441](∅→∅),[3.3441]→[4.536:585](∅→∅),[4.536]→[4.536:585](∅→∅)
dbEval (CreateAuction auc) =pinsert AuctionId"INSERT INTO auctions (project_id, user_id, raise_amount, end_time) \\VALUES (?, ?, ?, ?) RETURNING id"( auc ^. (A.projectId . _ProjectId), auc ^. (A.initiator . _UserId), auc ^. (raiseAmount . satoshi), auc ^. (auctionEnd.to fromThyme))updateCache (ReadWorkIndex (P.ProjectId pid)) = dologEntries <- pquery logEntryParser"SELECT btc_addr, event_type, event_time, event_metadata FROM work_events WHERE project_id = ?"(Only pid)pure $ workIndex logEntries - replacement in lib/Aftok/Database/PostgreSQL.hs at line 299[4.5183]→[4.3104:3135](∅→∅),[4.3135]→[4.574:611](∅→∅),[4.574]→[4.574:611](∅→∅),[4.611]→[2.257:372](∅→∅),[2.372]→[4.3377:3412](∅→∅),[4.3201]→[4.3377:3412](∅→∅),[4.3377]→[4.3377:3412](∅→∅)
dbEval (FindAuction aucId) =headMay <$> pquery auctionParser"SELECT project_id, initiator_id, created_at, raise_amount, start_time, end_time FROM auctions WHERE id = ?"(Only (aucId ^. _AuctionId))updateCache (CreateAuction auc) =pinsert A.AuctionId"INSERT INTO auctions (project_id, user_id, raise_amount, end_time) \\VALUES (?, ?, ?, ?) RETURNING id"( auc ^. (A.projectId . P._ProjectId), auc ^. (A.initiator . _UserId), auc ^. (A.raiseAmount . satoshi), auc ^. (A.auctionEnd . to fromThyme)) - replacement in lib/Aftok/Database/PostgreSQL.hs at line 309[4.5425]→[4.3202:3247](∅→∅),[4.3247]→[4.3487:3634](∅→∅),[4.3487]→[4.3487:3634](∅→∅),[4.3634]→[4.3248:3262](∅→∅),[4.3262]→[4.3649:3733](∅→∅),[4.3649]→[4.3649:3733](∅→∅),[4.803]→[4.49:49](∅→∅),[4.3733]→[3.3442:3479](∅→∅),[4.49]→[4.3080:3118](∅→∅),[4.297]→[4.3080:3118](∅→∅),[4.800]→[4.3080:3118](∅→∅),[4.803]→[4.3080:3118](∅→∅),[3.3479]→[4.3080:3118](∅→∅),[4.3768]→[4.3080:3118](∅→∅),[4.3118]→[4.3791:3799](∅→∅),[4.3791]→[4.3791:3799](∅→∅)
dbEval (CreateBid (AuctionId aucId) bid) =pinsert BidId"INSERT INTO bids (auction_id, bidder_id, bid_seconds, bid_amount, bid_time) \\VALUES (?, ?, ?, ?, ?) RETURNING id"( aucId, bid ^. (bidUser._UserId), case bid ^. bidSeconds of (Seconds i) -> i, bid ^. (bidAmount . satoshi), bid ^. (bidTime.to fromThyme))updateCache (FindAuction aucId) =headMay <$> pquery auctionParser"SELECT project_id, initiator_id, created_at, raise_amount, start_time, end_time FROM auctions WHERE id = ?"(Only (aucId ^. A._AuctionId)) - replacement in lib/Aftok/Database/PostgreSQL.hs at line 314[4.5525]→[4.3263:3291](∅→∅),[4.3291]→[4.3829:3939](∅→∅),[4.3829]→[4.3829:3939](∅→∅),[4.3939]→[4.612:647](∅→∅)
dbEval (ReadBids aucId) =pquery bidParser"SELECT user_id, bid_seconds, bid_amount, bid_time FROM bids WHERE auction_id = ?"(Only (aucId ^. _AuctionId))updateCache (CreateBid (A.AuctionId aucId) bid) =pinsert A.BidId"INSERT INTO bids (auction_id, bidder_id, bid_seconds, bid_amount, bid_time) \\VALUES (?, ?, ?, ?, ?) RETURNING id"( aucId, bid ^. (A.bidUser . _UserId), case bid ^. A.bidSeconds of (Seconds i) -> i, bid ^. (A.bidAmount . satoshi), bid ^. (A.bidTime . to fromThyme)) - replacement in lib/Aftok/Database/PostgreSQL.hs at line 325[4.668]→[4.3292:3322](∅→∅),[4.3322]→[3.3480:3620](∅→∅),[3.3620]→[4.4027:4109](∅→∅),[4.4027]→[4.4027:4109](∅→∅),[4.4109]→[3.3621:3717](∅→∅)
dbEval (CreateUser user') =let addrMay :: Maybe ByteStringaddrMay = user' ^? (userAddress . traverse . _BtcAddr . to addrToBase58)in pinsert UserId"INSERT INTO users (handle, btc_addr, email) VALUES (?, ?, ?) RETURNING id"( user' ^. (username._UserName), addrMay, user' ^. userEmail._Email)updateCache (ReadBids aucId) =pquery bidParser"SELECT user_id, bid_seconds, bid_amount, bid_time FROM bids WHERE auction_id = ?"(Only (aucId ^. A._AuctionId)) - replacement in lib/Aftok/Database/PostgreSQL.hs at line 330[4.705]→[4.3323:3358](∅→∅),[4.3358]→[4.684:718](∅→∅),[4.684]→[4.684:718](∅→∅),[4.718]→[4.4270:4350](∅→∅),[4.4270]→[4.4270:4350](∅→∅)
dbEval (FindUser (UserId uid)) =headMay <$> pquery userParser"SELECT handle, btc_addr, email FROM users WHERE id = ?"(Only uid)updateCache (CreateUser user') =let addrMay :: Maybe ByteStringaddrMay = user' ^? (userAddress . traverse . _BtcAddr . to addrToBase58)in pinsert UserId"INSERT INTO users (handle, btc_addr, email) VALUES (?, ?, ?) RETURNING id"( user' ^. (username._UserName), addrMay, user' ^. userEmail._Email) - replacement in lib/Aftok/Database/PostgreSQL.hs at line 340[4.1369]→[4.3359:3400](∅→∅),[4.3400]→[4.761:798](∅→∅),[4.761]→[4.761:798](∅→∅),[4.798]→[4.4454:4540](∅→∅),[4.4454]→[4.4454:4540](∅→∅)
dbEval (FindUserByName (UserName h)) =headMay <$> pquery qdbUserParser"SELECT id, handle, btc_addr, email FROM users WHERE handle = ?"(Only h)updateCache (FindUser (UserId uid)) =headMay <$> pquery userParser"SELECT handle, btc_addr, email FROM users WHERE id = ?"(Only uid) - replacement in lib/Aftok/Database/PostgreSQL.hs at line 345
dbEval (CreateInvitation (ProjectId pid) (UserId uid) (Email e) t) = doinvCode <- liftIO randomInvCodevoid $ pexec"INSERT INTO invitations (project_id, invitor_id, invitee_email, invitation_key, invitation_time) \\VALUES (?, ?, ?, ?, ?)"(pid, uid, e, renderInvCode invCode, fromThyme t)pure invCodeupdateCache (FindUserByName (UserName h)) =headMay <$> pquery qdbUserParser"SELECT id, handle, btc_addr, email FROM users WHERE handle = ?"(Only h)updateCache (CreateInvitation (P.ProjectId pid) (UserId uid) (Email e) t) = doinvCode <- liftIO P.randomInvCodevoid $ pexec"INSERT INTO invitations (project_id, invitor_id, invitee_email, invitation_key, invitation_time) \\VALUES (?, ?, ?, ?, ?)"(pid, uid, e, P.renderInvCode invCode, fromThyme t)pure invCodeupdateCache (FindInvitation ic) =headMay <$> pquery invitationParser"SELECT project_id, invitor_id, invitee_email, invitation_time, acceptance_time \\FROM invitations WHERE invitation_key = ?"(Only $ P.renderInvCode ic) - replacement in lib/Aftok/Database/PostgreSQL.hs at line 364[4.3742]→[4.3401:3432](∅→∅),[4.3432]→[4.831:871](∅→∅),[4.831]→[4.831:871](∅→∅),[4.871]→[4.3634:3804](∅→∅),[4.3634]→[4.3634:3804](∅→∅)
dbEval (FindInvitation ic) =headMay <$> pquery invitationParser"SELECT project_id, invitor_id, invitee_email, invitation_time, acceptance_time \\FROM invitations WHERE invitation_key = ?"(Only $ renderInvCode ic)updateCache (AcceptInvitation (UserId uid) ic t) = transactQDBM $ dovoid $ pexec"UPDATE invitations SET acceptance_time = ? WHERE invitation_key = ?"(fromThyme t, P.renderInvCode ic)void $ pexec"INSERT INTO project_companions (project_id, user_id, invited_by, joined_at) \\SELECT i.project_id, ?, i.invitor_id, ? \\FROM invitations i \\WHERE i.invitation_key = ?"(uid, fromThyme t, P.renderInvCode ic) - replacement in lib/Aftok/Database/PostgreSQL.hs at line 375
dbEval (AcceptInvitation (UserId uid) ic t) = transactQDBM $ dovoid $ pexec"UPDATE invitations SET acceptance_time = ? WHERE invitation_key = ?"(fromThyme t, renderInvCode ic)void $ pexec"INSERT INTO project_companions (project_id, user_id, invited_by, joined_at) \\SELECT i.project_id, ?, i.invitor_id, ? \\FROM invitations i \\WHERE i.invitation_key = ?"(uid, fromThyme t, renderInvCode ic)updateCache (CreateProject p) =pinsert P.ProjectId"INSERT INTO projects (project_name, inception_date, initiator_id, depreciation_fn) \\VALUES (?, ?, ?, ?) RETURNING id"(p ^. P.projectName, p ^. (P.inceptionDate . to fromThyme), p ^. (P.initiator . _UserId), toJSON $ p ^. P.depf) - replacement in lib/Aftok/Database/PostgreSQL.hs at line 381[4.4291]→[4.3433:3462](∅→∅),[4.3462]→[4.4596:4751](∅→∅),[4.4596]→[4.4596:4751](∅→∅),[4.4751]→[4.586:696](∅→∅)
dbEval (CreateProject p) =pinsert ProjectId"INSERT INTO projects (project_name, inception_date, initiator_id, depreciation_fn) \\VALUES (?, ?, ?, ?) RETURNING id"(p ^. projectName, p ^. (inceptionDate.to fromThyme), p ^. (P.initiator . _UserId), toJSON $ p ^. depf)updateCache (FindProject (P.ProjectId pid)) =headMay <$> pquery projectParser"SELECT project_name, inception_date, initiator_id, depreciation_fn FROM projects WHERE id = ?"(Only pid) - replacement in lib/Aftok/Database/PostgreSQL.hs at line 386[4.947]→[4.3463:3504](∅→∅),[4.3504]→[4.914:951](∅→∅),[4.914]→[4.914:951](∅→∅),[4.951]→[4.4:106](∅→∅),[4.4924]→[4.4:106](∅→∅),[4.106]→[4.5009:5026](∅→∅),[4.5009]→[4.5009:5026](∅→∅)
dbEval (FindProject (ProjectId pid)) =headMay <$> pquery projectParser"SELECT project_name, inception_date, initiator_id, depreciation_fn FROM projects WHERE id = ?"(Only pid)updateCache (FindUserProjects (UserId uid)) =pquery qdbProjectParser"SELECT p.id, p.project_name, p.inception_date, p.initiator_id, p.depreciation_fn \\FROM projects p LEFT OUTER JOIN project_companions pc ON pc.project_id = p.id \\WHERE pc.user_id = ? \\OR p.initiator_id = ?"(uid, uid) - replacement in lib/Aftok/Database/PostgreSQL.hs at line 394[4.1014]→[4.3505:3548](∅→∅),[4.3548]→[4.5099:5127](∅→∅),[4.5099]→[4.5099:5127](∅→∅),[4.5127]→[4.107:284](∅→∅),[4.284]→[4.3549:3579](∅→∅),[4.3579]→[4.315:345](∅→∅),[4.315]→[4.315:345](∅→∅),[4.345]→[4.5448:5465](∅→∅),[4.5448]→[4.5448:5465](∅→∅)
dbEval (FindUserProjects (UserId uid)) =pquery qdbProjectParser"SELECT p.id, p.project_name, p.inception_date, p.initiator_id, p.depreciation_fn \\FROM projects p LEFT OUTER JOIN project_companions pc ON pc.project_id = p.id \\WHERE pc.user_id = ? \\OR p.initiator_id = ?"(uid, uid)updateCache (AddUserToProject pid current new) = void $pexec"INSERT INTO project_companions (project_id, user_id, invited_by) VALUES (?, ?, ?)"(pid ^. P._ProjectId, new ^. _UserId, current ^. _UserId) - replacement in lib/Aftok/Database/PostgreSQL.hs at line 399[4.1043]→[4.3580:3633](∅→∅),[4.3633]→[4.1006:1016](∅→∅),[4.1006]→[4.1006:1016](∅→∅),[4.1016]→[4.5532:5684](∅→∅),[4.5532]→[4.5532:5684](∅→∅)
dbEval (AddUserToProject pid current new) = void $pexec"INSERT INTO project_companions (project_id, user_id, invited_by) VALUES (?, ?, ?)"(pid ^. _ProjectId, new ^. _UserId, current ^. _UserId)updateCache dbop @ (CreateBillable b) = doeventId <- requireEventId dboppinsert BI.BillableId"INSERT INTO billables \\(project_id, event_id, name, description, recurrence_type, recurrence_count, billing_amount, grace_period_days)\\VALUES (?, ?, ?, ?, ?, ?, ?, ?) RETURNING id"( b ^. (BI.project . P._ProjectId), eventId ^. _EventId, b ^. BI.name, b ^. BI.description, b ^. (BI.recurrence . to BI.recurrenceName), b ^. (BI.recurrence . to BI.recurrenceCount), b ^. (BI.amount . satoshi), b ^. (BI.gracePeriod . _Days)) - replacement in lib/Aftok/Database/PostgreSQL.hs at line 415
dbEval (CreateBillable _) = error "Not implemented"dbEval (ReadBillable _) = error "Not implemented"dbEval (CreatePaymentRequest _ _) = error "Not implemented"dbEval (CreatePayment _ ) = error "Not implemented"updateCache (ReadBillable bid) =headMay <$> pquery billableParser"SELECT b.project_id, e.created_by, b.name, b.description, b.recurrence_type, b.recurrence_count, \\ b.billing_amount, b.grace_period_days \\FROM billables b JOIN aftok_events e ON e.id = b.event_id \\WHERE b.id = ?"(Only (bid ^. BI._BillableId)) - edit in lib/Aftok/Database/PostgreSQL.hs at line 423
updateCache (CreateSubscription _ _) = error "Not implemented"updateCache (CreatePaymentRequest _) = error "Not implemented"updateCache (CreatePayment _ ) = error "Not implemented" - replacement in lib/Aftok/Database/PostgreSQL.hs at line 427
dbEval (RaiseDBError err _) = QDBM . lift $ left errupdateCache (RaiseDBError err _) = raiseError err - edit in lib/Aftok/Database/PostgreSQL.hs at line 429
requireEventId :: DBOp a -> QDBM EventIdrequireEventId = maybe (raiseError EventStorageFailed) id . storeEvent - edit in lib/Aftok/Database/PostgreSQL.hs at line 432
raiseError :: DBError -> QDBM araiseError = QDBM . lift . left - edit in lib/Aftok/Database/PostgreSQL.hs at line 435[3.3947]
instance DBEval QDBM wheredbEval e = updateCache e - edit in lib/Aftok/Database.hs at line 19
import Aftok.Types - replacement in lib/Aftok/Database.hs at line 53
CreateBillable :: Billable ProjectId Satoshi -> DBOp BillableIdReadBillable :: BillableId -> DBOp (Maybe (Billable ProjectId Satoshi))CreateBillable :: Billable -> DBOp BillableIdReadBillable :: BillableId -> DBOp (Maybe Billable)CreateSubscription :: UserId -> BillableId -> DBOp SubscriptionId - replacement in lib/Aftok/Database.hs at line 58
CreatePaymentRequest :: UserId -> PaymentRequest ProjectId BillableId -> DBOp PaymentRequestIdCreatePayment :: Payment PaymentRequestId UserId -> DBOp PaymentIdCreatePaymentRequest :: PaymentRequest SubscriptionId -> DBOp PaymentRequestIdCreatePayment :: Payment PaymentRequestId -> DBOp PaymentId - edit in lib/Aftok/Database.hs at line 72
| EventStorageFailed - replacement in lib/Aftok/Database.hs at line 177
createBillable :: UserId -> Billable ProjectId Satoshi -> DBProg BillableIdcreateBillable uid b = withProjectAuth (b ^. B.project) uid $ CreateBillable bcreateBillable :: Billable -> DBProg BillableIdcreateBillable b = withProjectAuth (b ^. B.project) (b ^. B.creator) $ CreateBillable b - replacement in lib/Aftok/Database.hs at line 180
readBillable :: BillableId -> DBProg (Maybe (Billable ProjectId Satoshi))readBillable :: BillableId -> DBProg (Maybe Billable) - replacement in lib/Aftok/Database.hs at line 188
readPaymentHistory :: UserId -> DBProg [Payment PaymentRequestId UserId]readPaymentHistory :: UserId -> DBProg [Payment PaymentRequestId] - replacement in lib/Aftok/Payments.hs at line 18
data PaymentRequest (p :: *) (b :: *) = PaymentRequest{ _project :: pdata PaymentRequest (s :: *) = PaymentRequest{ _subscription :: s - edit in lib/Aftok/Payments.hs at line 22
, _billable :: b - replacement in lib/Aftok/Payments.hs at line 25
data Payment r u = Paymentdata Payment (r :: *) = Payment - edit in lib/Aftok/Payments.hs at line 29
, _payor :: u - edit in lib/Aftok/Time.hs at line 1
{-# LANGUAGE TemplateHaskell #-} - edit in lib/Aftok/Time.hs at line 5
import Control.Lens (makePrisms) - edit in lib/Aftok/Time.hs at line 8
makePrisms ''Days - edit in migrations/2016-12-31_03-45-17_create-payments.txt at line 26
created_by uuid references users(id) null, - edit in server/Aftok/Snaplet.hs at line 43
handleDBError (EventStorageFailed) =snapError 500 "The event submitted could not be saved to the log."