----------------------------------------------------------------------------- -- -- Module : Qifer -- Copyright : (c) Ingolf Wagner -- License : BSD3 -- -- Maintainer : Ingolf Wagner -- Stability : unstable -- Portability : -- -- | -- ----------------------------------------------------------------------------- module Qifer where import Data.List import Text.Regex.TDFA type CSV = [Row] type Row = [Column] type Column = String data Transaction = Transaction { date :: String , description :: String , text :: String , balance :: String } deriving (Eq,Show) type Position = Int data Rule = Rule { dateField :: Position , descField :: [Position] , textField :: [Position] , balanceField :: Position } deriving (Show) highestPosition :: Rule -> Position highestPosition (Rule dF tF ltF bF) = maximum . concat $ [[dF],tF,ltF,[bF]] toTransactions :: Rule -> CSV -> [Transaction] toTransactions _ [] = [] toTransactions rule (c:sv) | (highestPosition rule) >= (length c) = stepDeeper | otherwise = transform : stepDeeper where pick n = (c !! (n rule)) pock n = concat . intersperse " " . map (\k -> c !! k ) $ (n rule) stepDeeper = toTransactions rule sv transform = (Transaction (pick dateField) (pock descField) (pock textField) (pick balanceField)) qifHeader :: String qifHeader = "!Type:Bank" toQif :: Transaction -> [String] toQif trans = ["P" ++ d, "T" ++ money, "D" ++ time, "M" ++ msg] where d = (description trans) money = (balance trans) time = (date trans) msg = (text trans) transToQif :: [Transaction] -> [String] transToQif trans = qifHeader : (foo trans) where foo [] = [] foo (t:ts) = (toQif t) ++ ["^"] ++ (foo ts) -- | updates a Transaction if regex works updateTransaction :: String -> String -> Transaction -> Transaction updateTransaction regex replacement transaction = transaction { description = updateDesc } where updateDesc = if matches then replacement else (description transaction) matches = (description transaction) =~ regex :: Bool -- | very inefficient but better than nothing update :: [(String,String)] -> [Transaction] -> [Transaction] update _ [] = [] update regex (t:ts) = (updateSingle regex t) : (update regex ts) where updateSingle [] r = r updateSingle ((rgx,replacement):rest) transaction = if updatedTrans == transaction then updateSingle rest transaction else updatedTrans where updatedTrans = updateTransaction rgx replacement transaction