UWMGUJOW5X5HQTS76T2FD7MNAJF7SESPQVU5FDIZO52V75TT2X6AC ZKFETYRKPM2BYO47I4B7ZTZZNIGTUKKYX2KK27KUETVJXUV5O65AC 7OTVLW6G7IIAJE2Q4PX53DEXQYY6CPNZJVUJO2ELGGAJKQLXQ7FQC DJATFGIC75CQDWMFHIWOKFXF26GKPINREMP6FNNTLF75JZZ3EQEQC YWNTVA7PN7MC3HNTER3OCFHQAVKNJUK7KRQDZYFK24S5JLWHNU4AC EFSXYZPOGA5M4DN65IEIDO7JK6U34DMQELAPHOIL2UAT6HRC66BAC LTSVBVA235BQAIU3SQURKSRHIAL33K47G4J6TSEP2K353OCHNJEAC IPG33FAWXGEQ2PO6OXRT2PWWXHRNMPVUKKADL6UKKN5GD2CNZ25AC LAROLAYUGJ4Q5AEFV5EJMIA2ZKBNCBWHHHPCJ3CKCNIUIYUKRFVQC SEWTRB6S5PO5MQBLCPVBD7XT2BDYNZUE2RO6Z2XENZRIOCN6OZJAC JFOEOFGA4CQR2LW43IVQGDZSPVJAD4KDN2DZMZXGM2QDIUD7AVCAC DFOBMSAODB3NKW37B272ZXA2ML5HMIH3N3C4GT2DPEQS7ZFK4SNAC AL37SVTCKRSG4HG2PCYK5Z7QSIZZH5JHH4Q2VLMXFAXSAQRFFG4QC B6HWAPDPXIWH7CHK5VLMWLL6EQN6NOFZEFYO47BPUY2ZO4SL7VDAC NEDDHXUK3GNFMOFO3KLU7NRIHCTYNWBT3D6HTKZAOXFDE6HMDZ6AC IZEVQF627FA7VV25KJAWYWGGC35LZUUBBQRPN5ZAINTQLPEDRTEAC A6HKMINBNGQLLX4QJMYWKQ4JAEHVJ4HIRVDKPPDI3FJUO2AAB7OQC AWWC6P5ZVFDQHX3EAYDG4DKTUZ6A5LHQAV3NIUO3VP6FM7JKPK5AC HMDM3B557TO5RYP2IGFFC2C2VN6HYZTDQ47CJY2O37BW55DSMFZAC J6S23MDGHVSCVVIRB6XRNSY3EGTDNWFJHV7RYLIEHBUK5KU63CFQC RN7EI6INGUUHGMNY5RU3NH56WPLRZY5ZMYDNFMNE3TGV4ESFLQIAC QMRKFEPGFBCEWAIXPEIG5ILKAJ2JH5L3TOITHR4HNJXK5FN3KXBQC 64C6AWH66FDKU6UE6Z6JPX2J2GBM2JOPTH2GL6LHKAIUBGNGDZ5AC 2J37EVJMX255K3XEJHTZGRPEIRMAQ62JQWOA7JU3YTZUB6PUPWVQC RSF6UAJKG7CEKILSVXI6C4YZXY7PIYZM2EMA2IXKQ7SADKNVSH7QC 73NDXDEZRMK672GHSTC3CI6YHXFZ2GGJI5IKQGHKFDZKTNSQXLLQC FXJQACESPGTLPG5ELXBU3M3OQXUZQQIR7HPIEHQ3FNUTMWVH4WBAC W35DDBFYF6Z4ZPCFEO5RPAONZLYCSNTXUSTS6FIUUVZHCI6Q7GHAC ZIG57EE6RB22JGB3CT33EN2HVYCHCXBT5GROBTBMBLEMDTGQOOBQC ASF3UPJLCX7KIUCNJD5KAXSPDXCUEJHLL4HBRTRUBPCW73IXOCWQC O5FVTOM6YFBLEPF3S576K6IMT6ZZ5VQCSB3YVXNS4CKBITKCRZ7AC O227CEAV7BTKSE3SSC7XHC5IWEBXZL2AOOKJMBMOOFNTLINBLQMAC 4R7XIYK3BP664CO3YJ2VM64ES2JYN27UTQG5KS34OTEPAIODSZLQC BSIUHCGFDFDFGWYMHZB7OVU3Z3IHPEUXRISIOPGZI2RUXZFDS2EQC Q5X5RYQLP5K7REYD6VLHOKC4W36ZELJYA45V6YFKTD5S6MPN3NDQC WZFQDWW4XK6M4A4PQ7WQJUTZUPRGQR7V7ZVZY5ZTL5AMGIFMHB2QC POX3UAMTGCNS3SU5I6IKDNCCSHEAUSFBZ3WCMQ3EXKPNXETOI6BAC NVOCQVASZWTKQJG7GPH7KHKZZR7NUG4WLV5YY4KAIRPCJRWCZPIAC RPAJLHMTUJU4AYNBOHVGHGGB4NY2NLY3BVPYN5FMWB3ZIMAUQHCQC TLQ72DSJD7GGPWN6HGBHAVPBRQFKEQ6KSK43U7JWWID4ZWAF47JAC SLL7262CJUE7TZDDZZXFROHCVVDA527WA4PHXCKEGZUJF2EN5MQAC GCVQD44VRPQVKPZEPIC4AOIXLJIG2ZMV3QI2Y7KALUT6NVUBSGSAC P6NR2CGXCWAW6GXXSIXCGOBIRAS2BM4LEM6D5ADPN4IL7TMW6UVAC EMVTF2IWNQGRL44FC4JNG5FYYQTZSFPNM6SOM7IAEH6T7PPK2NVAC Y35QCWYW2OTZ27ZVTH2BA3XJTUCJ2WMLKU32ZCOCDY3AW7TIZXRAC 4QX5E5ACVN57KJLCWOM4JEI6JSV4XZNCWVYPOTKSOMUW3SOMCNJAC 7HPY3QPFPN35PSPUBVNW2GTFB3CBQZBST4J2BAVJ7QMXLIUN52JAC 7KZP4RHZ3QSYTPPQ257A65Z5UPX44TF2LAI2U5EMULQCLDCEUK2AC 5DRIWGLUKMQZU2ZPBXSTLAWJKAMOD5YXAHM5LEDQHDFGYYLHWCDQC KNSI575VAW6HRCZYXOEPQ4DTSML4EORML5MV4DJBRKE7TXCPS4EAC SCXG6TJWYIPRUMT27KGKIIF6FYKTUTY74UNZ2FQTT63XZ6HIF3AAC 2KZPOGRBY6KBMO76F55ZKIVOLSG3O63VP3RHRZVANXYT3OLZ3OWQC 7DBNV3GV773FH5ZLQWFX4RBOS4Q3CIK2RYZNNABY3ZOETYZCXRNQC 2OIPAQCBDIUJBXB4K2QVP3IEBIUOCQHSWSWFVMVSVZC7GHX2VK7AC HALRDT2F22DAQ54M334YSKD2XJCAXDXEZPDKGMOWKH7XELBAS6MAC NJNMO72S7VIUV22JXB4IFPZMHWTJAOTP6EC6Z4QSKYIROSXT52MQC I2KHGVD44KT4MQJXGCTVSQKMBO6TVCY72F26TLXGWRL6PHGF6RNQC PT4276XCOP5NJ3GRFJLIBZKVNVAOATAY5PLWV7FWK6RZW5FTEP5AC NLZ3JXLOOIL37O3RRQWXHNPNSNEOOLPD6MCB754BEBECQB3KGR2AC PBD7LZYQHXAA3KLH2ZUX5GW4UFML6BQ32KXZF4KZ6OYFASUYFJ5QC BROSTG5KP3NUNLSYPVQID254TE47E5RKQAKLPIY7PGWETE6JNMTAC 2XQD6KKKD6QVHFHAEMVE3XXY7X2T7BLTLL7XIILZAXNJJH2YONUQC Z24SZOGZJLDTDTGWH7M25RYQ7MYSU52ZLFWJ2PSQFTMK4J35PIWAC QMEYU4MWLTSWPWEEOFRLK2IKE64BY3V5X73323WPLCGPP3TPDYGAC ADMKQQGCGVSHHIMVQ4XFRDCG544SBJCYALSKZV45CQQBZ4ACUH2AC GMYPBCWEB6NKURRILAHR3TJUKDOGR2ZMK5I6MS6P5G2LAGH36P3QC MGOF7IUFGXYQKZOKMM2GGULFFVAULEHLZDSHMUW6B5DBKVXXR74AC RFYEVKZQLOOQP536GRZOROSQW2O7TEHJ2HZDRVVUSBKLY5FBEO3QC UUR6SMCAJMA7O3ZFUCQMPZFDDIPUVQ5IHUAC5F252YVD6H3JIKPQC LHJ2HFXVUQ4VG25I7DADWU73G5K5WNZBDQ3SVNKFYLZ5BEYM4XCQC EQXRXRZDYCM7BDAVBOXQYPG6C7IJT3OFGNIXCDAHJJBRKAXNGL7AC import Control.Monad.Trans.Except ( withExceptT)import Control.Monad.Trans.Reader ( mapReaderT)
import Control.Monad.Trans.Except ( withExceptT )import Control.Monad.Trans.Reader ( mapReaderT )
{-- A stream of dates upon which the specified subscription- should be billed, beginning with the first day of the- subscription.-}
-- | A stream of dates upon which the specified subscription-- should be billed, beginning with the first day of the-- subscription.
next :: Maybe T.Day -> Maybe (T.Day, Maybe T.Day)next d = dod' <- dif (all (d' <) subEndDay) then Just (d', nextRecurrence rec d') else Nothing
next :: Maybe T.Day -> Maybe (T.Day, Maybe T.Day)next d = dod' <- dif (all (d' <) subEndDay) then Just (d', nextRecurrence rec d') else Nothing
let err = returnError ConversionFailedf("could not deserialize value " <> T.unpack fieldValue <>" to a valid BTC address for network " <> show n)
let err = returnErrorConversionFailedf( "could not deserialize value "<> T.unpack fieldValue<> " to a valid BTC address for network "<> show n)
whereparser :: Text -> RowParser (CreditTo (NetworkId, Address))parser = \case"credit_to_address" -> CreditToCurrency <$> (addressParser mode <* nullField <* nullField)"credit_to_user" -> CreditToUser <$> (nullField *> nullField *> idParser UserId <* nullField)"credit_to_project" -> CreditToProject <$> (nullField *> nullField *> nullField *> idParser ProjectId)_ -> empty
whereparser :: Text -> RowParser (CreditTo (NetworkId, Address))parser = \case"credit_to_address" ->CreditToCurrency <$> (addressParser mode <* nullField <* nullField)"credit_to_user" ->CreditToUser <$> (nullField *> nullField *> idParser UserId <* nullField)"credit_to_project" ->CreditToProject<$> (nullField *> nullField *> nullField *> idParser ProjectId)_ -> empty
CreateUser ::BTCUser -> DBOp UserIdFindUser ::UserId -> DBOp (Maybe BTCUser)FindUserByName ::UserName -> DBOp (Maybe (UserId, BTCUser))
CreateUser :: BTCUser -> DBOp UserIdFindUser :: UserId -> DBOp (Maybe BTCUser)FindUserByName :: UserName -> DBOp (Maybe (UserId, BTCUser))
CreateProject ::Project -> DBOp ProjectIdFindProject ::ProjectId -> DBOp (Maybe Project)ListProjects ::DBOp [ProjectId]FindSubscribers ::ProjectId -> DBOp [UserId]FindUserProjects ::UserId -> DBOp [(ProjectId, Project)]AddUserToProject ::ProjectId -> InvitingUID -> InvitedUID -> DBOp ()CreateInvitation ::ProjectId -> InvitingUID -> Email -> C.UTCTime -> DBOp InvitationCodeFindInvitation ::InvitationCode -> DBOp (Maybe Invitation)AcceptInvitation ::UserId -> InvitationCode -> C.UTCTime -> DBOp ()
CreateProject :: Project -> DBOp ProjectIdFindProject :: ProjectId -> DBOp (Maybe Project)ListProjects :: DBOp [ProjectId]FindSubscribers :: ProjectId -> DBOp [UserId]FindUserProjects :: UserId -> DBOp [(ProjectId, Project)]AddUserToProject :: ProjectId -> InvitingUID -> InvitedUID -> DBOp ()CreateInvitation :: ProjectId -> InvitingUID -> Email -> C.UTCTime -> DBOp InvitationCodeFindInvitation :: InvitationCode -> DBOp (Maybe Invitation)AcceptInvitation :: UserId -> InvitationCode -> C.UTCTime -> DBOp ()
CreateEvent ::ProjectId -> UserId -> LogEntry BTCNet -> DBOp EventIdAmendEvent ::EventId -> EventAmendment BTCNet -> DBOp AmendmentIdFindEvent ::EventId -> DBOp (Maybe (KeyedLogEntry BTCNet))FindEvents ::ProjectId -> UserId -> RangeQuery -> Word32 -> DBOp [LogEntry BTCNet]ReadWorkIndex ::ProjectId -> DBOp (WorkIndex BTCNet)
CreateEvent :: ProjectId -> UserId -> LogEntry BTCNet -> DBOp EventIdAmendEvent :: EventId -> EventAmendment BTCNet -> DBOp AmendmentIdFindEvent :: EventId -> DBOp (Maybe (KeyedLogEntry BTCNet))FindEvents :: ProjectId -> UserId -> RangeQuery -> Word32 -> DBOp [LogEntry BTCNet]ReadWorkIndex :: ProjectId -> DBOp (WorkIndex BTCNet)
CreateAuction ::Auction -> DBOp AuctionIdFindAuction ::AuctionId -> DBOp (Maybe Auction)CreateBid ::AuctionId -> Bid -> DBOp BidIdFindBids ::AuctionId -> DBOp [(BidId, Bid)]
CreateAuction :: Auction -> DBOp AuctionIdFindAuction :: AuctionId -> DBOp (Maybe Auction)CreateBid :: AuctionId -> Bid -> DBOp BidIdFindBids :: AuctionId -> DBOp [(BidId, Bid)]
CreateBillable ::UserId -> Billable -> DBOp BillableIdFindBillable ::BillableId -> DBOp (Maybe Billable)FindBillables ::ProjectId -> DBOp [(BillableId, Billable)]
CreateBillable :: UserId -> Billable -> DBOp BillableIdFindBillable :: BillableId -> DBOp (Maybe Billable)FindBillables :: ProjectId -> DBOp [(BillableId, Billable)]
CreateSubscription ::UserId -> BillableId -> T.Day -> DBOp SubscriptionIdFindSubscription ::SubscriptionId -> DBOp (Maybe Subscription)FindSubscriptions ::UserId -> ProjectId -> DBOp [(SubscriptionId, Subscription)]
CreateSubscription :: UserId -> BillableId -> T.Day -> DBOp SubscriptionIdFindSubscription :: SubscriptionId -> DBOp (Maybe Subscription)FindSubscriptions :: UserId -> ProjectId -> DBOp [(SubscriptionId, Subscription)]
CreatePaymentRequest ::PaymentRequest -> DBOp PaymentRequestIdFindPaymentRequests ::SubscriptionId -> DBOp [(PaymentRequestId, PaymentRequest)]FindUnpaidRequests ::SubscriptionId -> DBOp [BillDetail]FindPaymentRequest ::PaymentKey -> DBOp (Maybe (PaymentRequestId, PaymentRequest))FindPaymentRequestId ::PaymentRequestId -> DBOp (Maybe PaymentRequest)
CreatePaymentRequest :: PaymentRequest -> DBOp PaymentRequestIdFindPaymentRequests :: SubscriptionId -> DBOp [(PaymentRequestId, PaymentRequest)]FindUnpaidRequests :: SubscriptionId -> DBOp [BillDetail]FindPaymentRequest :: PaymentKey -> DBOp (Maybe (PaymentRequestId, PaymentRequest))FindPaymentRequestId :: PaymentRequestId -> DBOp (Maybe PaymentRequest)
workIndexJSON nmode (WorkIndex widx) =v2 $ obj ["workIndex" .= fmap widxRec (MS.assocs widx)]wherewidxRec :: (CreditTo (NetworkId, Address), NonEmpty Interval) -> ValuewidxRec (c, l) = object[ "creditTo" .= creditToJSON nmode c, "intervals" .= (intervalJSON <$> L.toList l)]
workIndexJSON nmode (WorkIndex widx) = v2$ obj ["workIndex" .= fmap widxRec (MS.assocs widx)]wherewidxRec :: (CreditTo (NetworkId, Address), NonEmpty Interval) -> ValuewidxRec (c, l) = object[ "creditTo" .= creditToJSON nmode c, "intervals" .= (intervalJSON <$> L.toList l)]
import Control.Error.Util (maybeT)import Control.Lens (makeClassy, makeClassyPrisms, review,view, (%~), (^.), traverseOf)
import Control.Error.Util ( maybeT )import Control.Lens ( makeClassy, makeClassyPrisms, review, view, (%~), (^.), traverseOf)
import Control.Monad.Except (MonadError, throwError)import qualified Crypto.PubKey.RSA.Types as RSA (Error (..), PrivateKey)import Crypto.Random.Types (MonadRandom, getRandomBytes)
import Control.Monad.Except ( MonadError, throwError)import qualified Crypto.PubKey.RSA.Types as RSA( Error(..), PrivateKey)import Crypto.Random.Types ( MonadRandom, getRandomBytes)
import qualified Bippy as Bimport qualified Bippy.Proto as Pimport qualified Bippy.Types as BTimport Haskoin.Address (Address(..))import Haskoin.Address.Base58 (encodeBase58Check)import Haskoin.Script (ScriptOutput (..))
import qualified Bippy as Bimport qualified Bippy.Proto as Pimport qualified Bippy.Types as BTimport Haskoin.Address ( Address(..) )import Haskoin.Address.Base58 ( encodeBase58Check )import Haskoin.Script ( ScriptOutput(..) )
createPaymentRequests :: ( MonadRandom m, MonadReader r m, HasPaymentsConfig r, MonadError e m, AsPaymentError e, MonadDB m)=> BillingOps m -- ^ generators for payment request components-> C.UTCTime -- ^ timestamp for payment request creation-> UserId -- ^ customer responsible for payment-> ProjectId -- ^ project whose worklog is to be paid-> m [PaymentRequestId]
createPaymentRequests:: ( MonadRandom m, MonadReader r m, HasPaymentsConfig r, MonadError e m, AsPaymentError e, MonadDB m)=> BillingOps m -- ^ generators for payment request components-> C.UTCTime -- ^ timestamp for payment request creation-> UserId -- ^ customer responsible for payment-> ProjectId -- ^ project whose worklog is to be paid-> m [PaymentRequestId]
createSubscriptionPaymentRequests ::( MonadRandom m, MonadReader r m, HasPaymentsConfig r, MonadError e m, AsPaymentError e
createSubscriptionPaymentRequests:: ( MonadRandom m, MonadReader r m, HasPaymentsConfig r, MonadError e m, AsPaymentError e
billableSub <- maybeT (raiseSubjectNotFound . FindBillable $ sub ^. billable) pure $traverseOf billable findBillable sub
billableSub <-maybeT (raiseSubjectNotFound . FindBillable $ sub ^. billable) pure$ traverseOf billable findBillable sub
billableDates <- findUnbilledDates now (view billable billableSub) paymentRequests $takeWhile (< view _utctDay now) $ billingSchedule billableSub
billableDates <-findUnbilledDates now (view billable billableSub) paymentRequests$ takeWhile (< view _utctDay now)$ billingSchedule billableSub
createPaymentRequest ::( MonadRandom m, MonadReader r m, HasPaymentsConfig r, MonadError e m, AsPaymentError e
createPaymentRequest:: ( MonadRandom m, MonadReader r m, HasPaymentsConfig r, MonadError e m, AsPaymentError e
findUnbilledDates :: (MonadDB m, MonadError e m, AsPaymentError e)=> C.UTCTime -- ^ the date against which payment request expiration should be checked-> Billable-> [(PaymentRequestId, PaymentRequest)] -- ^ the list of existing payment requests-> [T.Day] -- ^ the list of expected billing days-> m [T.Day] -- ^ the list of billing days for which no payment request existsfindUnbilledDates now b (px @ (p : ps)) (dx @ (d : ds)) =
findUnbilledDates:: (MonadDB m, MonadError e m, AsPaymentError e)=> C.UTCTime -- ^ the date against which payment request expiration should be checked-> Billable-> [(PaymentRequestId, PaymentRequest)] -- ^ the list of existing payment requests-> [T.Day] -- ^ the list of expected billing days-> m [T.Day] -- ^ the list of billing days for which no payment request existsfindUnbilledDates now b (px@(p : ps)) (dx@(d : ds)) =
Expired r -> if view _utctDay now > addDays (view gracePeriod b) (view billingDate r)then throwError (review _Overdue (r ^. subscription))else fmap (d :) $ findUnbilledDates now b px dx -- d will be rebilled_ -> findUnbilledDates now b ps ds -- if paid or unpaid, nothing to do
Expired r ->if view _utctDay now > addDays (view gracePeriod b) (view billingDate r)then throwError (review _Overdue (r ^. subscription))else fmap (d :) $ findUnbilledDates now b px dx -- d will be rebilled_ -> findUnbilledDates now b ps ds -- if paid or unpaid, nothing to do
getRequestStatus :: (MonadDB m)=> C.UTCTime -- ^ the date against which request expiration should be checked-> (PaymentRequestId, PaymentRequest) -- ^ the request for which to find a payment-> m PaymentRequestStatus
getRequestStatus:: (MonadDB m)=> C.UTCTime -- ^ the date against which request expiration should be checked-> (PaymentRequestId, PaymentRequest) -- ^ the request for which to find a payment-> m PaymentRequestStatus
pure $ B.createPaymentDetails(toNetwork (cfg ^. networkMode) BTC)outputs(T.fromThyme billingTime)expiry memo uri payloadwherepayoutTime = T.mkUTCTime payoutDate (fromInteger 0)
pure $ B.createPaymentDetails (toNetwork (cfg ^. networkMode) BTC)outputs(T.fromThyme billingTime)expirymemouripayloadwhere payoutTime = T.mkUTCTime payoutDate (fromInteger 0)
join <$> (traverse checkAccess $ filter (not . isExpired now . view _2) requests)wherefindOp = FindUnpaidRequests sidcheckAccess d =if view (_3 . customer) d == uidthen pure [d]else raiseOpForbidden uid (UserNotSubscriber sid) findOp
join<$> (traverse checkAccess $ filter (not . isExpired now . view _2) requests)wherefindOp = FindUnpaidRequests sidcheckAccess d = if view (_3 . customer) d == uidthen pure [d]else raiseOpForbidden uid (UserNotSubscriber sid) findOp
( LogEntry(..), creditTo, event, eventMeta, CreditTo(..), _CreditToCurrency, _CreditToUser, _CreditToProject, creditToName, LogEvent(..), eventName, nameEvent, eventTime, WorkIndex(WorkIndex), _WorkIndex, workIndex, DepF, toDepF, EventId(EventId), _EventId, ModTime(ModTime), _ModTime
( LogEntry(..), creditTo, event, eventMeta, CreditTo(..), _CreditToCurrency, _CreditToUser, _CreditToProject, creditToName, LogEvent(..), eventName, nameEvent, eventTime, WorkIndex(WorkIndex), _WorkIndex, workIndex, DepF, toDepF, EventId(EventId), _EventId, ModTime(ModTime), _ModTime
import Data.Eq (Eq, (==))import Data.Either (Either(..), rights)import Data.Foldable as Fimport Data.Function (($), (.), id)import Data.Functor (fmap)import Data.Heap as Himport Data.List.NonEmpty as Limport Data.Maybe (Maybe(..))import Data.Map.Strict as MSimport Data.Ord (Ord(..), Ordering(..))import Data.Ratio (Rational)import Data.Text (Text)import Data.Thyme.Clock as C
import Data.Eq ( Eq, (==))import Data.Either ( Either(..), rights)import Data.Foldable as Fimport Data.Function ( ($), (.), id)import Data.Functor ( fmap )import Data.Heap as Himport Data.List.NonEmpty as Limport Data.Maybe ( Maybe(..) )import Data.Map.Strict as MSimport Data.Ord ( Ord(..), Ordering(..))import Data.Ratio ( Rational )import Data.Text ( Text )import Data.Thyme.Clock as C
let combine (StartWork t) (StopWork t') | t' > t = Right $ Interval t t'combine (e1 @ (StartWork _)) (e2 @ (StartWork _)) = Left $ max e1 e2 -- ignore redundant startscombine (e1 @ (StopWork _)) (e2 @ (StopWork _)) = Left $ min e1 e2 -- ignore redundant endscombine _ e2 = Left e2
let combine :: LogEvent -> LogEvent -> Either LogEvent Intervalcombine (StartWork t) (StopWork t') | t' > t = Right $ Interval t t'combine (e1@(StartWork _)) (e2@(StartWork _)) = Left $ max e1 e2 -- ignore redundant startscombine (e1@(StopWork _)) (e2@(StopWork _)) = Left $ min e1 e2 -- ignore redundant endscombine _ e2 = Left e2
linearDepreciation :: Months -- ^ The number of initial months during which no depreciation occurs-> Months -- ^ The number of months over which each logged interval will be depreciated-> DepF -- ^ The resulting configured depreciation function.
linearDepreciation:: Months -- ^ The number of initial months during which no depreciation occurs-> Months -- ^ The number of months over which each logged interval will be depreciated-> DepF -- ^ The resulting configured depreciation function.
depPct dt =if dt < monthsLength undepLength then 1else toSeconds (max zeroV (maxDepreciable ^-^ dt)) / toSeconds maxDepreciable
depPct dt = if dt < monthsLength undepLengththen 1else toSeconds (max zeroV (maxDepreciable ^-^ dt))/ toSeconds maxDepreciable
req <- getRequestrawHeader <- maybe (throwMissingAuth ()) pure $ getHeader "Authorization" req
req <- getRequestrawHeader <- maybe (throwMissingAuth ()) pure $ getHeader "Authorization" req
credentials <- caseA.eitherDecode requestBody >>= A.parseEither parseLoginRequestofLeft _ -> snapError 400 $ "Unable to parse login credentials object."
credentials <-case A.eitherDecode requestBody >>= A.parseEither parseLoginRequest ofLeft _ -> snapError 400 $ "Unable to parse login credentials object."
authResult <- with auth $ AU.loginByUsername (loginUser credentials) (AU.ClearText (encodeUtf8 $ loginPass credentials)) False
authResult <- with auth $ AU.loginByUsername(loginUser credentials)(AU.ClearText (encodeUtf8 $ loginPass credentials))False
keyedLogEntryJSON :: NetworkMode -> (EventId, KeyedLogEntry (NetworkId, Address)) -> A.ValuekeyedLogEntryJSON nmode (eid, (pid, uid, ev)) = v2 . obj $[ "eventId" .= idValue _EventId eid, "projectId" .= idValue _ProjectId pid, "loggedBy" .= idValue _UserId uid] <> logEntryFields nmode ev
keyedLogEntryJSON:: NetworkMode -> (EventId, KeyedLogEntry (NetworkId, Address)) -> A.ValuekeyedLogEntryJSON nmode (eid, (pid, uid, ev)) =v2. obj$ [ "eventId" .= idValue _EventId eid, "projectId" .= idValue _ProjectId pid, "loggedBy" .= idValue _UserId uid]<> logEntryFields nmode ev
auctionRoute =serveJSON auctionJSON $ method GET auctionGetHandlerauctionBidRoute =serveJSON bidIdJSON $ method POST auctionBidHandler
auctionRoute = serveJSON auctionJSON $ method GET auctionGetHandlerauctionBidRoute = serveJSON bidIdJSON $ method POST auctionBidHandler
, ("login" , loginRoute), ("login" , xhrLoginRoute), ("logout" , logoutRoute), ("login/check" , checkLoginRoute), ("register" , registerRoute), ("accept_invitation" , acceptInviteRoute)
, ("login" , loginRoute), ("login" , xhrLoginRoute), ("logout" , logoutRoute), ("login/check", checkLoginRoute), ("register" , registerRoute), ( "accept_invitation", acceptInviteRoute)
, ("user/projects/:projectId/logStart" , logWorkRoute StartWork), ("user/projects/:projectId/logEnd" , logWorkRoute StopWork), ("user/projects/:projectId/events" , userEventsRoute), ("user/projects/:projectId/workIndex" , userWorkIndexRoute), ("projects/:projectId/workIndex" , projectWorkIndexRoute), ("projects/:projectId/auctions" , auctionCreateRoute) -- <|> auctionListRoute), ("projects/:projectId/billables" , billableCreateRoute <|> billableListRoute), ("projects/:projectId/payouts" , projectPayoutsRoute), ("projects/:projectId/invite" , inviteRoute), ("projects/:projectId" , projectRoute), ("projects" , projectCreateRoute <|> projectListRoute)
, ("user/projects/:projectId/logStart" , logWorkRoute StartWork), ("user/projects/:projectId/logEnd" , logWorkRoute StopWork), ("user/projects/:projectId/events" , userEventsRoute), ("user/projects/:projectId/workIndex", userWorkIndexRoute), ("projects/:projectId/workIndex" , projectWorkIndexRoute), ( "projects/:projectId/auctions", auctionCreateRoute) -- <|> auctionListRoute), ( "projects/:projectId/billables", billableCreateRoute <|> billableListRoute), ("projects/:projectId/payouts", projectPayoutsRoute), ("projects/:projectId/invite" , inviteRoute), ("projects/:projectId" , projectRoute), ("projects" , projectCreateRoute <|> projectListRoute)