module Penny.Brenner.Util where
import Control.Monad.Exception.Synchronous as Ex
import qualified Penny.Brenner.Types as Y
import qualified Data.ByteString as BS
import qualified System.IO.Error as IOE
import qualified Data.Serialize as S
import qualified Data.Text as X
import qualified Penny.Copper.Parsec as CP
import qualified Text.Parsec as P
import qualified Penny.Lincoln as L
loadDb
:: Y.AllowNew
-> Y.DbLocation
-> IO Y.DbList
loadDb (Y.AllowNew allowNew) (Y.DbLocation dbLoc) = do
eiStr <- IOE.tryIOError (BS.readFile . X.unpack $ dbLoc)
case eiStr of
Left e ->
if allowNew && IOE.isDoesNotExistError e
then return []
else IOE.ioError e
Right g -> case readDbTuple g of
Ex.Exception e -> fail e
Ex.Success good -> return good
version :: Int
version = 0
brenner :: String
brenner = "penny.brenner"
readDbTuple
:: BS.ByteString
-> Ex.Exceptional String Y.DbList
readDbTuple bs = do
(s, v, ls) <- Ex.fromEither $ S.decode bs
Ex.assert "database file format not recognized." $ s == brenner
Ex.assert "wrong database version." $ v == version
return ls
saveDbTuple :: Y.DbList -> BS.ByteString
saveDbTuple ls = S.encode (brenner, version, ls)
saveDb :: Y.DbLocation -> Y.DbList -> IO ()
saveDb (Y.DbLocation p) = BS.writeFile (X.unpack p) . saveDbTuple
parseQty :: Y.Amount -> L.Qty
parseQty a = case P.parse CP.quantity "" (Y.unAmount a) of
Left e -> error $ "could not parse quantity from string: "
++ (X.unpack . Y.unAmount $ a) ++ ": " ++ show e
Right g -> g
label :: String -> X.Text -> String
label s x = s ++ ": " ++ X.unpack x ++ "\n"
showPosting :: Y.Posting -> String
showPosting (Y.Posting dt dc nc am py fd) =
label "Date" (X.pack . show . Y.unDate $ dt)
++ label "Description" (Y.unDesc dc)
++ label "Type" (X.pack $ case nc of
Y.Increase -> "increase"
Y.Decrease -> "decrease")
++ label "Amount" (Y.unAmount am)
++ label "Payee" (Y.unPayee py)
++ label "Financial institution ID" (Y.unFitId fd)
++ "\n"
showDbPair :: (Y.UNumber, Y.Posting) -> String
showDbPair (Y.UNumber u, p) =
label "U number" (X.pack . show $ u)
++ showPosting p