neat/Handler/Wallet.hs

200 lines
8.9 KiB
Haskell
Raw Normal View History

2015-08-09 21:33:19 +00:00
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE OverloadedStrings #-}
2015-04-26 20:18:24 +00:00
module Handler.Wallet where
import Import
import Data.Time.Clock
import Text.Printf
2015-08-09 21:33:19 +00:00
import Database.Persist.Sql
data Profit = Profit
{ date :: Day
, buy :: Int64
, sell :: Int64
, profit :: Int64
, bf :: Int64
, tt :: Int64
} deriving (Show, Eq)
2015-09-06 13:53:09 +00:00
data ProfitSum = ProfitSum
{ psbuy :: Int64
, pssell :: Int64
, psprofit :: Int64
, psbf :: Int64
, pstt :: Int64
} deriving (Show, Eq)
2015-08-09 21:33:19 +00:00
instance RawSql Profit where
rawSqlCols _ _ = (6,[])
rawSqlColCountReason _ = "date, buy, sell, profit, bf, tt"
rawSqlProcessRow [PersistDay t, PersistInt64 b, PersistInt64 s,
PersistInt64 p, PersistInt64 bf, PersistInt64 tt] = Right (Profit t b s p bf tt)
rawSqlProcessRow a = Left ("Wrong kinds of Arguments:" <> (pack $ show a))
2015-07-24 19:12:18 +00:00
2015-08-09 00:06:32 +00:00
buttonIntervals :: [(Int64,String)]
buttonIntervals = [ (2,"2 hours")
, (6,"6 hours")
, (12,"12 hours")
, (24,"1 day")
, (48,"2 days")
, (7*24,"7 days")
, (31*24,"31 days")
]
2015-08-09 21:33:19 +00:00
profitIntervals :: [Int64]
profitIntervals = [7,14,31]
2015-04-26 20:18:24 +00:00
getWalletR :: Handler Html
getWalletR = getWalletDetailsR 6 7
getWalletDetailsR :: Int64 -> Int64 -> Handler Html
getWalletDetailsR hrs days = loginOrDo (\(uid,user) -> do
now <- liftIO getCurrentTime
trans <- runDB $ selectList [TransactionDateTime >. (addUTCTime ((fromIntegral $ -(hrs*3600)) :: NominalDiffTime) now)] [Desc TransactionDateTime]
2015-08-09 21:33:19 +00:00
let profitquery = "select \
min(date(date_time at time zone 'utc')) as date,\
sum(CASE WHEN NOT trans_is_sell THEN quantity*price_cents ELSE 0 END) :: bigint as buy,\
sum(CASE WHEN trans_is_sell THEN quantity*price_cents ELSE 0 END) :: bigint as sell,\
sum(COALESCE(profit,0)) :: bigint as profit,\
sum(fee) :: bigint as brokerfee,\
sum(tax) :: bigint as transactiontax \
from transaction \
where \
\"user\"=? \
and extract(day from (now() at time zone 'utc')-date(date_time at time zone 'utc')) < ? \
group by \
extract(day from (now() at time zone 'utc')-date(date_time at time zone 'utc')) \
order by \
extract(day from (now() at time zone 'utc')-date(date_time at time zone 'utc')) asc"
(profits :: [Profit]) <- runDB $ rawSql profitquery [toPersistValue uid, toPersistValue days]
2015-09-06 13:53:09 +00:00
let profitssum = foldl' addProfit (ProfitSum 0 0 0 0 0) profits
loginLayout user $ [whamlet|
2015-08-09 00:06:32 +00:00
<div .panel .panel-default>
<div .panel-heading>Transactions in the last #{hrs} hours:
<div .btn-group .btn-group-justified role="group">
$forall (hrs',cap) <- buttonIntervals
$if hrs == hrs'
<a href="@{WalletDetailsR hrs' days}" .btn .active role="button">#{cap}
$else
2015-08-09 00:06:32 +00:00
<a href="@{WalletDetailsR hrs' days}" .btn role="button">#{cap}
<table .table .table-condensed .small>
2015-08-09 00:06:32 +00:00
<tr>
<th .text-center>Time
<th .text-center>P/C
<th .text-center>B/S
<th .text-center>Item
<th .text-center>##
2015-08-09 00:06:32 +00:00
<th .text-center>ISK/Item
<th .text-center>ISK total
<th .text-center>ISK profit
<th .text-center>%
<th .text-center>Time
<th .text-center>Client
<th .text-center>Station
<th .text-center>?
<th .text-center>
$forall Entity _ t <- trans
<tr>
<td>#{showDateTime $ transactionDateTime $ t}
2015-08-09 00:06:32 +00:00
$if transactionTransForCorp t
<td .corpTransaction .text-center>C
$else
<td .personalTransaction .text-center>P
$if transactionTransIsSell t
<td .sellTransaction .text-center>S
$else
<td .buyTransaction .text-center>B
<td><a href="@{ItemR (transactionTypeId t)}">#{transactionTypeName t}</a>
<td .numeric>#{transactionQuantity t}
<td .numeric>#{prettyISK $ transactionPriceCents t}
<td .numeric>#{prettyISK $ transactionQuantity t * transactionPriceCents t}
2015-08-09 00:06:32 +00:00
$maybe profit <- transRealProfit t
$if (&&) (transactionTransIsSell t) (profit > 0)
<td .numeric .profit>
2015-08-09 00:06:32 +00:00
#{prettyISK $ profit}
$elseif (&&) (transactionTransIsSell t) (profit < 0)
<td .numeric .loss>
2015-08-09 00:06:32 +00:00
#{prettyISK $ profit}
$elseif not (transactionTransIsSell t)
<td .numeric .buyfee>
2015-08-09 00:06:32 +00:00
#{prettyISK $ profit}
$else
2015-08-18 00:46:13 +00:00
<td .numeric>
2015-08-09 00:06:32 +00:00
#{prettyISK $ profit}
<td .numeric>
2015-08-09 00:06:32 +00:00
#{profitPercent profit t}%
$nothing
<td>
-
<td>
<td .duration>
2015-08-09 00:06:32 +00:00
$maybe secs <- transactionSecondsToSell t
#{showSecsToSell secs}
$nothing
&nbsp;
<td>#{transactionClientName t}
<td>#{transactionStationName t}
<td>
<td>
2015-08-09 00:06:32 +00:00
<div .panel .panel-default>
<div .panel-heading>Statistices for the last #{days} days:
2015-08-09 21:33:19 +00:00
<div .btn-group .btn-group-justified role="group">
$forall days' <- profitIntervals
$if days == days'
<a href="@{WalletDetailsR hrs days'}" .btn .active role="button">#{days'} days
$else
<a href="@{WalletDetailsR hrs days'}" .btn role="button">#{days'} days
<table .table .table-condensed .small>
2015-08-09 00:06:32 +00:00
<tr>
2015-08-09 21:33:19 +00:00
<th .text-center>Date
<th .text-center>ISK Buy
<th .text-center>ISK Sell
<th .text-center>ISK Profit
<th .text-center>ISK Broker Fee
<th .text-center>ISK Transaction Tax
<th .text-center>Real Profit
<th .text-center>%
$forall (Profit t b s p bf tt) <- profits
<tr>
<td>#{show t}
<td .numeric>#{prettyISK b}
<td .numeric>#{prettyISK s}
<td .numeric>#{prettyISK p}
<td .numeric>#{prettyISK bf}
<td .numeric>#{prettyISK tt}
<td .numeric>#{transRealProfit' p bf tt}
<td .numeric>
$maybe pp <- profitPercent' p bf tt s
#{pp}
$nothing
&nbsp;
2015-09-06 13:53:09 +00:00
$with (ProfitSum b s p bf tt) <- profitssum
<tr .total>
<th .text-center>Total
<td .numeric>#{prettyISK b}
<td .numeric>#{prettyISK s}
<td .numeric>#{prettyISK p}
<td .numeric>#{prettyISK bf}
<td .numeric>#{prettyISK tt}
<td .numeric>#{transRealProfit' p bf tt}
<td .numeric>
$maybe pp <- profitPercent' p bf tt s
#{pp}
$nothing
&nbsp;
2015-07-24 19:12:18 +00:00
|]
)
2015-08-09 21:33:19 +00:00
transRealProfit' :: Int64 -> Int64 -> Int64 -> String
transRealProfit' p bf tt = prettyISK (p-bf-tt)
profitPercent' :: Int64 -> Int64 -> Int64 -> Int64 -> Maybe String
profitPercent' p bf tt s = if s == 0 then Nothing
else Just . printf "%.2f" $ 100*(fromIntegral (p - bf - tt) / fromIntegral s :: Double)
2015-09-06 13:53:09 +00:00
addProfit :: ProfitSum -> Profit -> ProfitSum
addProfit (ProfitSum b' s' p' bf' tt') (Profit _ b s p bf tt) = ProfitSum (b+b') (s+s') (p+p') (bf+bf') (tt+tt')