Compare commits
8 Commits
a22ebd1835
...
24fe93cd90
Author | SHA1 | Date | |
---|---|---|---|
24fe93cd90 | |||
710ff26f50 | |||
1a9d7e37ae | |||
6b399c80eb | |||
0b5dbbd133 | |||
f03829a294 | |||
fc607b763f | |||
bf06f917a6 |
@ -1,4 +1,4 @@
|
||||
(channel
|
||||
(version 0)
|
||||
(url "https://git.olarinmaensamoojat.fi/OMS/haskell-tito")
|
||||
(url "https://git.olarinmaensamoojat.fi/OMS/tito")
|
||||
(directory ".guix/modules"))
|
||||
|
61
README.md
Normal file
61
README.md
Normal file
@ -0,0 +1,61 @@
|
||||
# TITO
|
||||
|
||||
::: {lang=eo}
|
||||
*Ĉi tiu pakaĵo enhavas datumstrukturoj kaj sintaksa analizilo por TITO, maljuna
|
||||
finna normo por cifera konteltiroj. Ĉar ĝi kredeble estas senutila ekster
|
||||
Finnujo, la dokumentaro estas skribita en la finna lingvo.*
|
||||
::: {lang=eo}
|
||||
|
||||
::: {lang=en}
|
||||
*This package provides data types and a parser for TITO, an old Finnish
|
||||
standard for digital bank account statements. It is most likely useful only in
|
||||
Finland and thus the documentation is in Finnish.*
|
||||
::: {lang=en}
|
||||
|
||||
Tito on Haskell-kirjasto TITO-muotoisten tiliotteiden lukemiseen. Moduuli
|
||||
`Data.TITO` sisältää ylätason funktiot tiliotteen tulkitsemiseen,
|
||||
`Data.TITO.Types` määrittää tiliotteen tietorakenteen ja `Data.TITO.Parser`
|
||||
ohjeet sen tekstimuodon tulkitsemisen. Kaikki moduulien nimet on suunniteltu
|
||||
tuotavaksi omaan nimiavaruuteensa, mutta vain `Data.TITO.readFile` menee
|
||||
päällekkäin `Prelude`:n nimen kanssa.
|
||||
|
||||
## Asentaminen
|
||||
|
||||
Lisää tämä git-tietovaranto [Guixin kanavalistaan][guix-channels]
|
||||
seuraavankaltaisella pätkällä:
|
||||
|
||||
[guix-channels]: https://guix.gnu.org/manual/devel/en/guix.html#Specifying-Additional-Channels
|
||||
|
||||
```lisp
|
||||
(channel
|
||||
(name 'ghc-tito)
|
||||
(url "https://git.olarinmaensamoojat.fi/OMS/tito")
|
||||
(branch "main")
|
||||
(introduction
|
||||
(make-channel-introduction
|
||||
"a793f511921f1e962ca0fdc9d988dfe26b4dc6b4"
|
||||
(openpgp-fingerprint
|
||||
"A0C9 1947 734F 076F 5F08 E9FF 257D 284A 2A1D 3A32"))))
|
||||
```
|
||||
|
||||
Tämän jälkeen Tito on saatavilla `ghc-tito`-nimisenä pakettina kaikkialla
|
||||
Guixissa.
|
||||
|
||||
## Kehittäminen
|
||||
|
||||
Kehitysympäristön saat helposti Guixilla ajamalla komennon [`guix
|
||||
shell`][guix-shell] tässä hakemistossa. Muutoksia, vikailmoituksia ja
|
||||
kehitysideoita voi jättää Giteassa tai sähköpostilla osoitteeseen
|
||||
<saku@laesvuori.fi>. Tarkista, että Tito kääntyy vielä muutostesi jälkeen
|
||||
ajamalla komento `guix time-machine -C channels.scm -- build -f guix.scm`.
|
||||
|
||||
[guix-shell]: https://guix.gnu.org/manual/devel/en/guix.html#Invoking-guix-shell
|
||||
|
||||
## Kopioiminen
|
||||
|
||||
Laskutin on [GNU AGPL lisenssin version kolme](COPYING.md), tai valintasi
|
||||
mukaan minkä tahansa myöhemmän [Free Software Foundationin julkaiseman
|
||||
version][fsf-agpl], alainen vapaa ohjelma, eli se kunniottaa käyttäjiensä
|
||||
vapautta päättää itse omasta tietojenkäsittelystään ja auttaa toisiaan.
|
||||
|
||||
[fsf-agpl]: https://www.gnu.org/licenses/agpl-3.0.html
|
11
channels.scm
Normal file
11
channels.scm
Normal file
@ -0,0 +1,11 @@
|
||||
(list (channel
|
||||
(name 'guix)
|
||||
(url "https://git.guix.gnu.org/guix.git")
|
||||
(branch "master")
|
||||
(commit
|
||||
"502ad9da2a7da064aef6a6dcdada3c92ae90aa72")
|
||||
(introduction
|
||||
(make-channel-introduction
|
||||
"9edb3f66fd807b096b48283debdcddccfea34bad"
|
||||
(openpgp-fingerprint
|
||||
"BBB0 2DDF 2CEA F6A8 0D1D E643 A2A0 6DF2 A33A 54FA")))))
|
@ -1,2 +1,18 @@
|
||||
module Data.TITO where
|
||||
|
||||
import Control.Exception
|
||||
|
||||
import qualified Data.ByteString as BS
|
||||
import qualified Text.Megaparsec as P
|
||||
|
||||
import Data.TITO.Parser
|
||||
import Data.TITO.Types
|
||||
|
||||
decode :: BS.ByteString -> Either ParseErrors AccountStatement
|
||||
decode = P.parse accountStatement ""
|
||||
|
||||
readFile :: FilePath -> IO AccountStatement
|
||||
readFile fp =
|
||||
BS.readFile fp
|
||||
>>= either (throwIO . ErrorCall . P.errorBundlePretty) pure
|
||||
. P.parse accountStatement fp
|
||||
|
@ -1,5 +1,6 @@
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE RecordWildCards #-}
|
||||
{-# LANGUAGE NamedFieldPuns #-}
|
||||
|
||||
module Data.TITO.Parser where
|
||||
|
||||
@ -93,8 +94,8 @@ transactionType = do
|
||||
case n of
|
||||
1 -> pure Deposit
|
||||
2 -> pure Withdrawal
|
||||
3 -> pure DepositFix
|
||||
4 -> pure WithdrawalFix
|
||||
3 -> pure DepositCorrection
|
||||
4 -> pure WithdrawalCorrection
|
||||
9 -> pure Declined
|
||||
_ -> P.failure Nothing mempty -- TODO: proper error message
|
||||
|
||||
@ -117,119 +118,125 @@ nameSource = do
|
||||
"A" -> pure Customer
|
||||
_ -> P.failure Nothing mempty -- TODO: proper error message
|
||||
|
||||
tito :: Parser TITO
|
||||
tito = TITO <$> titoRoot <*> P.many titoRecord <* P.eof
|
||||
accountStatement :: Parser AccountStatement
|
||||
accountStatement = do
|
||||
tito <- record "00" $ do
|
||||
P.string "100" -- version number
|
||||
account <- alphaNumeric 14
|
||||
statementNumber <- alphaNumeric 3
|
||||
startDate <- date
|
||||
endDate <- date
|
||||
created <- timestamp
|
||||
customer <- alphaNumeric 17
|
||||
startBalanceDate <- date
|
||||
startBalance <- money
|
||||
_records <- optional' numeric 6
|
||||
currency <- optional' alphaNumeric 3
|
||||
accountName <- optional' alphaNumeric 30
|
||||
accountLimit <- fmap Money <$> optional' numeric 18
|
||||
accountOwnerName <- alphaNumeric 35
|
||||
bankName <- alphaNumeric 40
|
||||
contactInformation <- optional' alphaNumeric 40
|
||||
bankSpecific <- optional' alphaNumeric 30
|
||||
ibanAndBic <- fmap (fmap $ T.break isSpace) $ optional' alphaNumeric 30 -- FI1234567 XXXXX
|
||||
return AccountStatement {events = [], ..}
|
||||
events <- P.many titoRecord <* P.eof
|
||||
pure $ tito {events}
|
||||
|
||||
titoRoot :: Parser TITORoot
|
||||
titoRoot = record "00" $ do
|
||||
P.string "100" -- version number
|
||||
account <- alphaNumeric 14
|
||||
statementNumber <- alphaNumeric 3
|
||||
startDate <- date
|
||||
endDate <- date
|
||||
created <- timestamp
|
||||
customer <- alphaNumeric 17
|
||||
startBalanceDate <- date
|
||||
startBalance <- money
|
||||
_records <- optional' numeric 6
|
||||
currency <- optional' alphaNumeric 3
|
||||
accountName <- optional' alphaNumeric 30
|
||||
accountLimit <- fmap Money <$> optional' numeric 18
|
||||
accountOwnerName <- alphaNumeric 35
|
||||
bankName <- alphaNumeric 40
|
||||
contactInformation <- optional' alphaNumeric 40
|
||||
bankSpecific <- optional' alphaNumeric 30
|
||||
ibanAndBic <- fmap (fmap $ T.break isSpace) $ optional' alphaNumeric 30 -- FI1234567 XXXXX
|
||||
return TITORoot {..}
|
||||
|
||||
titoRecord :: Parser TITORecord
|
||||
titoRecord = P.try (transaction' False)
|
||||
<|> P.try (transactionDetail' False)
|
||||
titoRecord :: Parser Event
|
||||
titoRecord = P.try transaction
|
||||
<|> P.try balance
|
||||
<|> P.try summary
|
||||
<|> P.try fixSummary
|
||||
<|> P.try special
|
||||
<|> P.try info
|
||||
<|> P.try (transaction' True)
|
||||
<|> P.try (transactionDetail' True)
|
||||
<|> P.try correctionSummary
|
||||
<|> P.try bankSpecific
|
||||
<|> P.try message
|
||||
<|> P.try transactionNotification
|
||||
|
||||
transaction' :: Bool -> Parser TITORecord
|
||||
transaction' isInformational = record (if isInformational then "80" else "10") $ do
|
||||
transactionNumber <- numeric 6
|
||||
archiveId <- optional' alphaNumeric 18
|
||||
parsedDate <- date
|
||||
valueDate <- optional 6 date
|
||||
paymentDate <- optional 6 date
|
||||
transactionType <- transactionType
|
||||
descriptionCode <- alphaNumeric 3
|
||||
descriptionText <- alphaNumeric 35
|
||||
amount <- money
|
||||
receiptCode <- alphaNumeric 1
|
||||
transferMethod <- alphaNumeric 1
|
||||
payeeName <- optional' alphaNumeric 35
|
||||
nameSource <- optional 1 nameSource
|
||||
recipientAccount <- optional' alphaNumeric 14
|
||||
accountChanged <- optional' alphaNumeric 1
|
||||
reference <- optional' numeric 20
|
||||
formNumber <- optional' alphaNumeric 8
|
||||
depth <- alphaNumeric 1
|
||||
return Transaction {date = parsedDate, ..}
|
||||
transaction, transactionNotification :: Parser Event
|
||||
transaction = BasicTransaction <$> transaction' 0 False
|
||||
transactionNotification = TransactionNotification <$> transaction' 0 True
|
||||
|
||||
transactionDetail' :: Bool -> Parser TITORecord
|
||||
transactionDetail' isInformational =
|
||||
record' (if isInformational then "81" else "11") $ \recordLength -> do
|
||||
transaction' :: Int -> Bool -> Parser Transaction
|
||||
transaction' minimumDepth isNotification = do
|
||||
(depth, transaction) <- record (if isNotification then "80" else "10") $ do
|
||||
transactionNumber <- numeric 6
|
||||
archiveId <- optional' alphaNumeric 18
|
||||
parsedDate <- date
|
||||
valueDate <- optional 6 date
|
||||
paymentDate <- optional 6 date
|
||||
transactionType <- transactionType
|
||||
descriptionCode <- alphaNumeric 3
|
||||
descriptionText <- alphaNumeric 35
|
||||
amount <- money
|
||||
receiptCode <- alphaNumeric 1
|
||||
transferMethod <- alphaNumeric 1
|
||||
payeeName <- optional' alphaNumeric 35
|
||||
nameSource <- optional 1 nameSource
|
||||
recipientAccount <- optional' alphaNumeric 14
|
||||
accountChanged <- optional' alphaNumeric 1
|
||||
reference <- optional' numeric 20
|
||||
formNumber <- optional' alphaNumeric 8
|
||||
depth <- fromIntegral <$> numeric 1 <|> const 0 <$> P.char 32 -- space
|
||||
guard $ depth >= minimumDepth
|
||||
return (depth, Transaction {details = [], itemisation = [], date = parsedDate, ..})
|
||||
details <- P.many $ P.try $ transactionDetail' isNotification
|
||||
itemisation <- P.many $ P.try $ transaction' (depth + 1) isNotification
|
||||
pure $ transaction {details, itemisation}
|
||||
|
||||
transactionDetail' :: Bool -> Parser TransactionDetail
|
||||
transactionDetail' isNotification =
|
||||
record' (if isNotification then "81" else "11") $ \recordLength -> do
|
||||
let detailLength = recordLength - 8
|
||||
detailType <- optional' alphaNumeric 2
|
||||
detail <- case detailType of
|
||||
Just "00" -> do
|
||||
first <- alphaNumeric 35
|
||||
rest <- P.count' 0 11 (optional' alphaNumeric 35)
|
||||
pure $ Freeform $ first :| catMaybes rest
|
||||
Just "01" -> Number <$> numeric 8
|
||||
Just "02" -> do
|
||||
customer <- alphaNumeric 10
|
||||
alphaNumeric 1
|
||||
invoice <- alphaNumeric 15
|
||||
alphaNumeric 1
|
||||
date <- date
|
||||
pure Invoice {..}
|
||||
Just "03" -> Card <$> alphaNumeric 19 <* alphaNumeric 1 <*> optional' alphaNumeric 14
|
||||
Just "04" -> Fix <$> alphaNumeric 18
|
||||
Just "05" -> do
|
||||
foreignAmount <- money
|
||||
alphaNumeric 1
|
||||
currency <- alphaNumeric 3
|
||||
alphaNumeric 1
|
||||
exchangeRate <- numeric 11
|
||||
exchangeReference <- optional' alphaNumeric 6
|
||||
pure ForeignCurrency {..}
|
||||
Just "06" -> fmap Notes $ (:|) <$> alphaNumeric 35 <*> (maybeToList <$> optional' alphaNumeric 35)
|
||||
Just "07" -> do
|
||||
first <- alphaNumeric 35
|
||||
rest <- P.count' 0 11 (optional' alphaNumeric 35)
|
||||
pure $ BankFreeform $ first :| catMaybes rest
|
||||
Just "08" -> PaymentSubject <$> numeric 3 <* alphaNumeric 1 <*> alphaNumeric 31
|
||||
Just "09" -> Name <$> alphaNumeric 35
|
||||
Just "11" -> do
|
||||
payersReference <- optional' alphaNumeric 35
|
||||
payeeIBAN <- optional' alphaNumeric 35
|
||||
payeeBIC <- optional' alphaNumeric 35
|
||||
payeeName <- optional' alphaNumeric 70
|
||||
payerName <- optional' alphaNumeric 70
|
||||
payerId <- optional' alphaNumeric 35
|
||||
archiveId <- optional' alphaNumeric 35
|
||||
pure SEPA {..}
|
||||
_ -> Unknown <$> alphaNumeric detailLength
|
||||
pure TransactionDetail {..}
|
||||
case detailType of
|
||||
Just "00" -> do
|
||||
first <- alphaNumeric 35
|
||||
rest <- P.count' 0 11 (optional' alphaNumeric 35)
|
||||
pure $ Freeform $ first :| catMaybes rest
|
||||
Just "01" -> Number <$> numeric 8
|
||||
Just "02" -> do
|
||||
customer <- alphaNumeric 10
|
||||
alphaNumeric 1
|
||||
invoice <- alphaNumeric 15
|
||||
alphaNumeric 1
|
||||
date <- date
|
||||
pure Invoice {..}
|
||||
Just "03" -> Card <$> alphaNumeric 19 <* alphaNumeric 1 <*> optional' alphaNumeric 14
|
||||
Just "04" -> Correction <$> alphaNumeric 18
|
||||
Just "05" -> do
|
||||
foreignAmount <- money
|
||||
alphaNumeric 1
|
||||
currency <- alphaNumeric 3
|
||||
alphaNumeric 1
|
||||
exchangeRate <- numeric 11
|
||||
exchangeReference <- optional' alphaNumeric 6
|
||||
pure ForeignCurrency {..}
|
||||
Just "06" -> fmap Notes $ (:|) <$> alphaNumeric 35 <*> (maybeToList <$> optional' alphaNumeric 35)
|
||||
Just "07" -> do
|
||||
first <- alphaNumeric 35
|
||||
rest <- P.count' 0 11 (optional' alphaNumeric 35)
|
||||
pure $ BankFreeform $ first :| catMaybes rest
|
||||
Just "08" -> PaymentSubject <$> numeric 3 <* alphaNumeric 1 <*> alphaNumeric 31
|
||||
Just "09" -> Name <$> alphaNumeric 35
|
||||
Just "11" -> do
|
||||
payersReference <- optional' alphaNumeric 35
|
||||
payeeIBAN <- optional' alphaNumeric 35
|
||||
payeeBIC <- optional' alphaNumeric 35
|
||||
payeeName <- optional' alphaNumeric 70
|
||||
payerName <- optional' alphaNumeric 70
|
||||
payerId <- optional' alphaNumeric 35
|
||||
archiveId <- optional' alphaNumeric 35
|
||||
pure SEPA {..}
|
||||
_ -> Unknown <$> alphaNumeric detailLength
|
||||
|
||||
balance :: Parser TITORecord
|
||||
balance :: Parser Event
|
||||
balance = record "40" $ do
|
||||
date <- date
|
||||
endBalance <- money
|
||||
usableBalance <- optional 19 money
|
||||
pure Balance {..}
|
||||
|
||||
summary :: Parser TITORecord
|
||||
summary :: Parser Event
|
||||
summary = record "50" $ do
|
||||
period <- period
|
||||
date <- date
|
||||
@ -239,22 +246,22 @@ summary = record "50" $ do
|
||||
withdrawalsTotal <- money
|
||||
pure Summary {..}
|
||||
|
||||
fixSummary :: Parser TITORecord
|
||||
fixSummary = record "51" $ do
|
||||
correctionSummary :: Parser Event
|
||||
correctionSummary = record "51" $ do
|
||||
period <- period
|
||||
date <- date
|
||||
depositFixes <- numeric 8
|
||||
depositFixesTotal <- money
|
||||
withdrawalFixes <- numeric 8
|
||||
withdrawalFixesTotal <- money
|
||||
pure FixSummary {..}
|
||||
depositCorrections <- numeric 8
|
||||
depositCorrectionsTotal <- money
|
||||
withdrawalCorrections <- numeric 8
|
||||
withdrawalCorrectionsTotal <- money
|
||||
pure CorrectionSummary {..}
|
||||
|
||||
special :: Parser TITORecord
|
||||
special = record' "60" $ \recordLength -> do
|
||||
bankSpecific :: Parser Event
|
||||
bankSpecific = record' "60" $ \recordLength -> do
|
||||
BankSpecific <$> alphaNumeric 3 <*> P.takeP Nothing (recordLength - 9)
|
||||
|
||||
info :: Parser TITORecord
|
||||
info = record' "70" $ \recordLength -> do
|
||||
message :: Parser Event
|
||||
message = record' "70" $ \recordLength -> do
|
||||
bankId <- alphaNumeric 3
|
||||
info <- T.unlines . T.chunksOf 80 <$> alphaNumeric (recordLength - 9)
|
||||
pure Info {..}
|
||||
message <- T.unlines . T.chunksOf 80 <$> alphaNumeric (recordLength - 9)
|
||||
pure Message {..}
|
||||
|
@ -8,14 +8,7 @@ import Data.Text (Text)
|
||||
import Data.Time (Day, LocalTime)
|
||||
import Data.List.NonEmpty (NonEmpty)
|
||||
|
||||
data TITO = TITO
|
||||
{ root :: TITORoot
|
||||
, records :: [TITORecord]
|
||||
} deriving (Show, Eq)
|
||||
|
||||
newtype Money = Money Integer deriving (Eq, Show)
|
||||
|
||||
data TITORoot = TITORoot -- T00
|
||||
data AccountStatement = AccountStatement
|
||||
{ account :: Text
|
||||
, statementNumber :: Text
|
||||
, startDate :: Day
|
||||
@ -32,64 +25,65 @@ data TITORoot = TITORoot -- T00
|
||||
, contactInformation :: Maybe Text
|
||||
, bankSpecific :: Maybe Text
|
||||
, ibanAndBic :: Maybe (Text, Text)
|
||||
, events :: [Event]
|
||||
} deriving (Show, Eq)
|
||||
|
||||
data TITORecord = Transaction -- T80 if isInformational, else T10
|
||||
{ isInformational :: Bool
|
||||
, transactionNumber :: Integer
|
||||
, archiveId :: Maybe Text
|
||||
, date :: Day
|
||||
, valueDate :: Maybe Day
|
||||
, paymentDate :: Maybe Day
|
||||
, transactionType :: TransactionType
|
||||
, descriptionCode :: Text
|
||||
, descriptionText :: Text
|
||||
, amount :: Money
|
||||
, receiptCode :: Text
|
||||
, transferMethod :: Text
|
||||
, payeeName :: Maybe Text
|
||||
, nameSource :: Maybe NameSource
|
||||
, recipientAccount :: Maybe Text
|
||||
, accountChanged :: Maybe Text
|
||||
, reference :: Maybe Integer
|
||||
, formNumber :: Maybe Text
|
||||
, depth :: Text
|
||||
}
|
||||
| TransactionDetail -- T81 if isInformational, else T11
|
||||
{ isInformational :: Bool
|
||||
, detailType :: Maybe Text
|
||||
, detail :: TransactionDetail
|
||||
}
|
||||
| Balance -- T40
|
||||
{ date :: Day
|
||||
, endBalance :: Money
|
||||
, usableBalance :: Maybe Money
|
||||
}
|
||||
| Summary -- T50
|
||||
{ period :: Period
|
||||
, date :: Day
|
||||
, deposits :: Integer
|
||||
, depositsTotal :: Money
|
||||
, withdrawals :: Integer
|
||||
, withdrawalsTotal :: Money
|
||||
}
|
||||
| FixSummary -- T51
|
||||
{ period :: Period
|
||||
, date :: Day
|
||||
, depositFixes :: Integer
|
||||
, depositFixesTotal :: Money
|
||||
, withdrawalFixes :: Integer
|
||||
, withdrawalFixesTotal :: Money
|
||||
}
|
||||
| BankSpecific -- T60
|
||||
{ bankId :: Text
|
||||
, rawData :: ByteString
|
||||
}
|
||||
| Info -- T70
|
||||
{ bankId :: Text
|
||||
, info :: Text
|
||||
}
|
||||
deriving (Show, Eq)
|
||||
newtype Money = Money Integer deriving (Eq, Show)
|
||||
|
||||
data Event = BasicTransaction Transaction -- T10
|
||||
| TransactionNotification Transaction -- T80
|
||||
| Balance -- T40
|
||||
{ date :: Day
|
||||
, endBalance :: Money
|
||||
, usableBalance :: Maybe Money
|
||||
}
|
||||
| Summary -- T50
|
||||
{ period :: Period
|
||||
, date :: Day
|
||||
, deposits :: Integer
|
||||
, depositsTotal :: Money
|
||||
, withdrawals :: Integer
|
||||
, withdrawalsTotal :: Money
|
||||
}
|
||||
| CorrectionSummary -- T51
|
||||
{ period :: Period
|
||||
, date :: Day
|
||||
, depositCorrections :: Integer
|
||||
, depositCorrectionsTotal :: Money
|
||||
, withdrawalCorrections :: Integer
|
||||
, withdrawalCorrectionsTotal :: Money
|
||||
}
|
||||
| BankSpecific -- T60
|
||||
{ bankId :: Text
|
||||
, rawData :: ByteString
|
||||
}
|
||||
| Message -- T70
|
||||
{ bankId :: Text
|
||||
, message :: Text
|
||||
}
|
||||
deriving (Show, Eq)
|
||||
|
||||
data Transaction = Transaction
|
||||
{ transactionNumber :: Integer
|
||||
, archiveId :: Maybe Text
|
||||
, date :: Day
|
||||
, valueDate :: Maybe Day
|
||||
, paymentDate :: Maybe Day
|
||||
, transactionType :: TransactionType
|
||||
, descriptionCode :: Text
|
||||
, descriptionText :: Text
|
||||
, amount :: Money
|
||||
, receiptCode :: Text
|
||||
, transferMethod :: Text
|
||||
, payeeName :: Maybe Text
|
||||
, nameSource :: Maybe NameSource
|
||||
, recipientAccount :: Maybe Text
|
||||
, accountChanged :: Maybe Text
|
||||
, reference :: Maybe Integer
|
||||
, formNumber :: Maybe Text
|
||||
, details :: [TransactionDetail]
|
||||
, itemisation :: [Transaction]
|
||||
} deriving (Show, Eq)
|
||||
|
||||
data TransactionDetail = Freeform (NonEmpty Text) -- 00
|
||||
| Number Integer -- 01
|
||||
@ -102,8 +96,8 @@ data TransactionDetail = Freeform (NonEmpty Text) -- 00
|
||||
{ cardNumber :: Text
|
||||
, merchantsReference :: Maybe Text
|
||||
}
|
||||
| Fix -- 04
|
||||
{ fixedTransaction :: Text}
|
||||
| Correction -- 04
|
||||
{ correctedTransaction :: Text}
|
||||
| ForeignCurrency -- 05
|
||||
{ foreignAmount :: Money
|
||||
, currency :: Text
|
||||
@ -129,7 +123,11 @@ data TransactionDetail = Freeform (NonEmpty Text) -- 00
|
||||
| Unknown Text -- all others
|
||||
deriving (Eq, Show)
|
||||
|
||||
data TransactionType = Deposit | Withdrawal | DepositFix | WithdrawalFix | Declined deriving (Show, Eq)
|
||||
data TransactionType = Deposit
|
||||
| Withdrawal
|
||||
| DepositCorrection
|
||||
| WithdrawalCorrection
|
||||
| Declined deriving (Show, Eq)
|
||||
|
||||
data Period = Day | Statement | Month | Year deriving (Show, Eq)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user