Avoid divisions by zero & display depreciated time shares.

[?]
Feb 20, 2021, 3:32 AM
4WBBSPHBORAQYMQYVKVO4SLPUD5R2TI2WWIMRYMARNTWP5CQU22AC

Dependencies

  • [2] W3S6D7LU Fix sample paths in DEVELOPMENT.md
  • [3] ZHV75AEN basic cleanup
  • [4] ZEAH247R Show all project contributors, not just those with a revenue share.
  • [5] Z5KNL332 Add skeleton of project overview HTML.
  • [6] DZ7G36NC Allow first-revenue cutoff for depreciation.
  • [7] PBD7LZYQ Postgres & auth are beginning to function.
  • [8] NJNMO72S Add zcash.com submodule and update client to modern halogen.
  • [9] 7TQPQW3N Begin adding parsing for project detail.
  • [10] HMDM3B55 Implement core of payments/billing infrastructure.
  • [11] NAFJ6RB3 Minor module reorg.
  • [12] M4PWY5RU Preliminary work to add support for Zcash payments.
  • [13] EMVTF2IW WIP moving back to snap.
  • [14] UWMGUJOW Autoformat sources.
  • [15] 46PUXHTY Implement project invitations.
  • [16] APOATM4X Add getProjectDetail call to project API
  • [17] 3GLHIR4F Add migrate script for prod system.
  • [18] W3PIWHDK Fix logged hours display error.
  • [19] PPW6ROC5 Render project data
  • [20] 4QX5E5AC Initial compilation of payouts function succeeds.
  • [21] NSRSSSTR Update nginx.conf, make aftok host configurable for cli scripts.
  • [22] XXJFUZOV Add first revenue date to project payout computation.
  • [23] 7HPY3QPF Fix linting errors. (yay hlint!)
  • [24] U7YAT2ZK Add error reporting to signup form.
  • [25] CI4OPKQM Add payouts spec.
  • [26] X3ES7NUA Fine. I'll use ormolu. At least it doesn't break the code.
  • [27] IR75ZMX3 Return actual events for interval ends, not just timestamps.
  • [28] GMYPBCWE Make docker-compose work.
  • [29] 7KZP4RHZ Switch from Data.Time to Data.Thyme
  • [*] QAC2QJ32 Add project overview page to client.
  • [*] E2KOBKIJ Add setup script detailing the setup of the docker host.
  • [*] NVOCQVAS Initial failing tests.

Change contents

  • replacement in DEVELOPMENT.md at line 115
    [2.123][5.1143:1260](),[5.1143][5.1143:1260]()
    following commands to initialize the database. The postgres user's password is
    specified in the docker-compose file.
    [2.123]
    [5.1260]
    `deploy/dbinit.sh` script to initialize the database. The postgres user's password
    can be specified in the docker-compose file.
  • replacement in DEVELOPMENT.md at line 119
    [5.1269][5.1269:1370](),[5.1370][2.124:197]()
    createuser -h localhost -U postgres -W -P aftok
    createdb -h localhost -U postgres -W -O aftok aftok
    psql -h localhost -U aftok -W aftok < local/postgres/db-dumps/aftok.dump
    [5.1269]
    [5.1434]
    ./deploy/dbinit.sh local/postgres/db-dumps/aftok.dump
  • replacement in client/src/Aftok/Api/Project.purs at line 104
    [5.311][5.2771:2796]()
    , timeDevoted :: Hours
    [5.311]
    [5.1635]
    , loggedHours :: Hours
    , depreciatedHours :: Hours
  • replacement in client/src/Aftok/Api/Project.purs at line 128
    [5.3033][5.3033:3081]()
    timeDevoted <- Hours <$> x .: "timeDevoted"
    [5.3033]
    [5.1761]
    loggedHours <- Hours <$> x .: "loggedHours"
    depreciatedHours <- Hours <$> x .: "depreciatedHours"
  • replacement in client/src/Aftok/Api/Project.purs at line 135
    [5.1837][5.3227:3303](),[5.3227][5.3227:3303]()
    pure $ Contributor' { userId, handle, joinedOn, timeDevoted, revShare }
    [5.1837]
    [5.381]
    pure $ Contributor' { userId, handle, joinedOn, loggedHours, depreciatedHours, revShare }
  • replacement in client/src/Aftok/Overview.purs at line 177
    [5.5678][3.165:273]()
    , colmd3 (Just "Contributed Hours")
    , colmd3 (Just "Current Revenue Share")
    [5.5678]
    [5.5786]
    , colmd2 (Just "Contributed")
    , colmd3 (Just "After Depreciation")
    , colmd3 (Just "Revenue Share")
  • replacement in client/src/Aftok/Overview.purs at line 230
    [5.6331][3.391:447]()
    , colmd3 (Just $ show (unwrap pud.timeDevoted))
    [5.6331]
    [3.447]
    , colmd2 (Just $ show (unwrap pud.loggedHours) <> " hours")
    , colmd3 (Just $ show (unwrap pud.depreciatedHours) <> " hours")
  • replacement in client/src/Aftok/Overview.purs at line 298
    [5.12101][5.12101:12152]()
    , timeDevoted: Hours 100.0
    [5.12101]
    [5.12152]
    , loggedHours: Hours 100.0
    , depreciatedHours: Hours 75.0
  • file addition: dbinit.sh (---r------)
    [32.1]
    #!/bin/bash
    createuser -h localhost -U postgres -W -P aftok
    createdb -h localhost -U postgres -W -O aftok aftok
    psql -h localhost -U postgres -W aftok \
    -c 'CREATE EXTENSION IF NOT EXISTS "uuid-ossp" WITH SCHEMA public;'
    if [ -n "$1" ]; then
    psql -h localhost -U aftok -W aftok < $1
    fi
  • replacement in docker-compose.yml at line 81
    [5.24621][5.24621:24648]()
    source: aftok-data
    [5.24621]
    [5.24648]
    source: v_aftok-data
  • replacement in docker-compose.yml at line 109
    [5.24731][5.24731:24745]()
    aftok-data:
    [5.24731]
    [5.10495]
    v_aftok-data:
  • edit in lib/Aftok/TimeLog.hs at line 114
    [5.22764]
    [5.52471]
    deriving (Show, Eq)
  • edit in lib/Aftok/TimeLog.hs at line 123
    [5.22918]
    [5.22918]
    deriving (Show, Eq)
  • replacement in lib/Aftok/TimeLog.hs at line 171
    [5.1194][5.1194:1289]()
    else max 0 (1 - (C.toSeconds (intervalAge ^-^ undepLength) / C.toSeconds depLength))
    [5.1194]
    [5.1032]
    else
    if depLength == 0
    then 0
    else max 0 (1 - (C.toSeconds (intervalAge ^-^ undepLength) / C.toSeconds depLength))
  • replacement in lib/Aftok/TimeLog.hs at line 202
    [5.1402][5.23587:23689]()
    withShareFraction t = t & wsShare .~ (C.toSeconds (t ^. wsDepreciated) / C.toSeconds totalTime)
    [5.1402]
    [5.23689]
    withShareFraction t =
    t & wsShare .~ (
    if totalTime == 0
    then 0
    else (C.toSeconds (t ^. wsDepreciated) / C.toSeconds totalTime)
    )
  • edit in server/Aftok/Snaplet/Projects.hs at line 39
    [5.24770]
    [5.24770]
    wsDepreciated,
  • replacement in server/Aftok/Snaplet/Projects.hs at line 72
    [5.25060][5.25060:25091]()
    _timeDevoted :: Hours,
    [5.25060]
    [5.25091]
    _loggedHours :: Hours,
    _depreciatedHours :: Hours,
  • edit in server/Aftok/Snaplet/Projects.hs at line 120
    [5.1756][4.66:67]()
  • replacement in server/Aftok/Snaplet/Projects.hs at line 127
    [4.312][4.312:403]()
    _timeDevoted = Hours . (`div` 3600) . round . C.toSeconds' $ ws ^. wsLogged,
    [4.312]
    [4.403]
    _loggedHours = Hours . (`div` 3600) . round . C.toSeconds' $ ws ^. wsLogged,
    _depreciatedHours = Hours . (`div` 3600) . round . C.toSeconds' $ ws ^. wsDepreciated,
  • edit in server/Aftok/Snaplet/Projects.hs at line 131
    [4.461][4.461:462]()
  • replacement in server/Aftok/Snaplet/Projects.hs at line 133
    [4.585][4.585:644]()
    zeroContrib = Contributor uid' h t (Hours 0) 0
    [4.585]
    [4.644]
    zeroContrib = Contributor uid' h t (Hours 0) (Hours 0) 0
  • replacement in server/Aftok/Snaplet/Projects.hs at line 303
    [5.27701][5.27701:27760]()
    "timeDevoted" .= (c ^. timeDevoted . (to fromEnum)),
    [5.27701]
    [5.27760]
    "loggedHours" .= (c ^. loggedHours . (to fromEnum)),
    "depreciatedHours" .= (c ^. depreciatedHours . (to fromEnum)),
  • replacement in test/Aftok/TimeLogSpec.hs at line 15
    [5.82762][5.1008:1068]()
    import Aftok.Types (DepreciationFunction (..), UserId (..))
    [5.82762]
    [5.1068]
    import Aftok.Types (DepreciationFunction (..), DepreciationRules (..), UserId (..))
  • edit in test/Aftok/TimeLogSpec.hs at line 25
    [5.2043]
    [5.82920]
    import qualified Data.UUID as U
  • replacement in test/Aftok/TimeLogSpec.hs at line 129
    [5.2877][5.2877:2931]()
    depf = toDepF $ LinearDepreciation 180 1800
    [5.2877]
    [5.2931]
    depf = toDepF $ DepreciationRules (LinearDepreciation 180 1800) Nothing
  • edit in test/Aftok/TimeLogSpec.hs at line 136
    [5.3406]
    [5.2853]
    it "correctly handles fully depreciated work intervals" $ do
    now <- C.getCurrentTime
    let depf = toDepF $ DepreciationRules (LinearDepreciation 6 2) Nothing
    raw = [
    ("b3ff64b7-6699-45f2-acee-38751325bf46", StartWork, "2021-02-09T15:52:13.434308+00"),
    ("b3ff64b7-6699-45f2-acee-38751325bf46", StopWork, "2021-02-09T16:12:32.936579+00"),
    ("d56ae5bd-8892-44c6-9a02-f6a8aca8636e", StartWork, "2021-02-09T16:23:10.637749+00"),
    ("d56ae5bd-8892-44c6-9a02-f6a8aca8636e", StopWork, "2021-02-09T16:27:00.082747+00"),
    ("d56ae5bd-8892-44c6-9a02-f6a8aca8636e", StartWork, "2021-02-09T16:29:10.119337+00"),
    ("d56ae5bd-8892-44c6-9a02-f6a8aca8636e", StopWork, "2021-02-09T18:54:26.778107+00")]
    toEvent :: (String, C.UTCTime -> LogEvent, String) -> Maybe LogEntry
    toEvent (uuid, f, t) =
    LogEntry <$> (CreditToUser . UserId <$> U.fromString uuid)
    <*> (f . C.toThyme <$> parseISO8601 t)
    <*> pure Nothing
    events = catMaybes $ fmap toEvent raw
    widx = workIndex (view event) events
    p = payouts depf now widx
    p `shouldBe` WorkShares 0 M.empty
  • replacement in test/Aftok/TimeLogSpec.hs at line 159
    [5.2937][5.2937:2980]()
    let depf = linearDepreciation 10 100
    [5.2937]
    [5.2980]
    let depf fr = linearDepreciation fr 10 100