Sisällytä erittelyt siirtoihin

This commit is contained in:
Saku Laesvuori 2025-07-19 13:12:22 +03:00
parent f03829a294
commit 0b5dbbd133
Signed by: slaesvuo
GPG Key ID: 257D284A2A1D3A32
2 changed files with 97 additions and 91 deletions

View File

@ -1,5 +1,6 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE NamedFieldPuns #-}
module Data.TITO.Parser where
@ -143,84 +144,89 @@ titoRoot = record "00" $ do
return TITORoot {..}
titoRecord :: Parser TITORecord
titoRecord = P.try (transaction' False)
<|> P.try (transactionDetail' False)
titoRecord = P.try (transaction False)
<|> 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 (transaction True)
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 :: Bool -> Parser TITORecord
transaction = fmap . TransactionRecord <*> transaction' 0
transactionDetail' :: Bool -> Parser TITORecord
transaction' :: Int -> Bool -> Parser Transaction
transaction' minimumDepth isInformational = do
(depth, transaction) <- 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 <- 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' isInformational
itemisation <- P.many $ P.try $ transaction' (depth + 1) isInformational
pure $ transaction {details, itemisation}
transactionDetail' :: Bool -> Parser TransactionDetail
transactionDetail' isInformational =
record' (if isInformational 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" -> 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
balance :: Parser TITORecord
balance = record "40" $ do

View File

@ -34,31 +34,9 @@ data TITORoot = TITORoot -- T00
, ibanAndBic :: Maybe (Text, Text)
} deriving (Show, Eq)
data TITORecord = Transaction -- T80 if isInformational, else T10
data TITORecord = TransactionRecord -- 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
, transaction :: Transaction
}
| Balance -- T40
{ date :: Day
@ -91,6 +69,28 @@ data TITORecord = Transaction -- T80 if isInformational, else T10
}
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
| Invoice -- 02