diff options
Diffstat (limited to 'app/Import/Ing/CurrentAccountCsv.hs')
-rw-r--r-- | app/Import/Ing/CurrentAccountCsv.hs | 44 |
1 files changed, 22 insertions, 22 deletions
diff --git a/app/Import/Ing/CurrentAccountCsv.hs b/app/Import/Ing/CurrentAccountCsv.hs index bf28730..1456be1 100644 --- a/app/Import/Ing/CurrentAccountCsv.hs +++ b/app/Import/Ing/CurrentAccountCsv.hs | |||
@@ -17,12 +17,12 @@ import Data.Time.Zones (TZ, loadTZFromDB) | |||
17 | import Data.Vector qualified as V | 17 | import Data.Vector qualified as V |
18 | import Import.Ing.Shared | 18 | import Import.Ing.Shared |
19 | ( DebitCredit (Credit, Debit), | 19 | ( DebitCredit (Credit, Debit), |
20 | dateCP, | ||
21 | decimalCP, | ||
22 | ibanCP, | ||
23 | maybeCP, | 20 | maybeCP, |
21 | parseDateM, | ||
22 | parseDecimalM, | ||
23 | parseIbanM, | ||
24 | parseTimestampM, | ||
24 | scsvOptions, | 25 | scsvOptions, |
25 | timestampCP, | ||
26 | ) | 26 | ) |
27 | import System.IO (Handle) | 27 | import System.IO (Handle) |
28 | import Text.Regex.TDFA ((=~~)) | 28 | import Text.Regex.TDFA ((=~~)) |
@@ -155,7 +155,7 @@ maybeNotProvided :: T.Text -> Maybe T.Text | |||
155 | maybeNotProvided t = if t == "NOTPROVIDED" then Nothing else Just t | 155 | maybeNotProvided t = if t == "NOTPROVIDED" then Nothing else Just t |
156 | 156 | ||
157 | valueDateCP :: T.Text -> C.Parser Day | 157 | valueDateCP :: T.Text -> C.Parser Day |
158 | valueDateCP = dateCP "%d/%m/%Y" | 158 | valueDateCP = parseDateM "%d/%m/%Y" |
159 | 159 | ||
160 | data PartTx = PartTx !Day !TransactionType !DebitCredit | 160 | data PartTx = PartTx !Day !TransactionType !DebitCredit |
161 | 161 | ||
@@ -163,7 +163,7 @@ notificationsCP :: TZ -> PartTx -> T.Text -> C.Parser MoreData | |||
163 | notificationsCP _ (PartTx _ Transfer Credit) t = do | 163 | notificationsCP _ (PartTx _ Transfer Credit) t = do |
164 | let regex = "^Name: (.*) Description: (.*) IBAN: ([A-Z0-9]+) Reference: (.*) Value date: ([0-9]{2}/[0-9]{2}/[0-9]{4})$" :: String | 164 | let regex = "^Name: (.*) Description: (.*) IBAN: ([A-Z0-9]+) Reference: (.*) Value date: ([0-9]{2}/[0-9]{2}/[0-9]{4})$" :: String |
165 | (_, _, _, [name, desc, ibanTxt, ref, valDateTxt]) <- t =~~ regex :: C.Parser (T.Text, T.Text, T.Text, [T.Text]) | 165 | (_, _, _, [name, desc, ibanTxt, ref, valDateTxt]) <- t =~~ regex :: C.Parser (T.Text, T.Text, T.Text, [T.Text]) |
166 | iban <- ibanCP ibanTxt | 166 | iban <- parseIbanM ibanTxt |
167 | valDate <- valueDateCP valDateTxt | 167 | valDate <- valueDateCP valDateTxt |
168 | return $ | 168 | return $ |
169 | DepositTransferData | 169 | DepositTransferData |
@@ -185,7 +185,7 @@ notificationsCP _ (PartTx _ Transfer Debit) t = do | |||
185 | notificationsCP amsTz (PartTx _ PaymentTerminal Debit) t = do | 185 | notificationsCP amsTz (PartTx _ PaymentTerminal Debit) t = do |
186 | let regex = "^Card sequence no.: ([0-9]+) ? ([0-9]{2}/[0-9]{2}/[0-9]{4} [0-9]{2}:[0-9]{2}) Transaction: (.*) Term: ((.+) Google Pay|(.+)) Value date: ([0-9]{2}/[0-9]{2}/[0-9]{4})$" :: String | 186 | let regex = "^Card sequence no.: ([0-9]+) ? ([0-9]{2}/[0-9]{2}/[0-9]{4} [0-9]{2}:[0-9]{2}) Transaction: (.*) Term: ((.+) Google Pay|(.+)) Value date: ([0-9]{2}/[0-9]{2}/[0-9]{4})$" :: String |
187 | (_, _, _, [cardSeqNo, timestampTxt, transaction, _, gpayTerm, noGpayTerm, valDateTxt]) <- t =~~ regex :: C.Parser (T.Text, T.Text, T.Text, [T.Text]) | 187 | (_, _, _, [cardSeqNo, timestampTxt, transaction, _, gpayTerm, noGpayTerm, valDateTxt]) <- t =~~ regex :: C.Parser (T.Text, T.Text, T.Text, [T.Text]) |
188 | timestamp <- timestampCP "%d/%m/%Y %H:%M" amsTz timestampTxt | 188 | timestamp <- parseTimestampM "%d/%m/%Y %H:%M" amsTz timestampTxt |
189 | valDate <- valueDateCP valDateTxt | 189 | valDate <- valueDateCP valDateTxt |
190 | return $ | 190 | return $ |
191 | PaymentTerminalData | 191 | PaymentTerminalData |
@@ -199,7 +199,7 @@ notificationsCP amsTz (PartTx _ PaymentTerminal Debit) t = do | |||
199 | notificationsCP amsTz (PartTx _ PaymentTerminal Credit) t = do | 199 | notificationsCP amsTz (PartTx _ PaymentTerminal Credit) t = do |
200 | let regex = "^Card sequence no.: ([0-9]+) ? ([0-9]{2}/[0-9]{2}/[0-9]{4} [0-9]{2}:[0-9]{2}) Transaction: (.*) Term: (.*) Cashback transaction Value date: ([0-9]{2}/[0-9]{2}/[0-9]{4})$" :: String | 200 | let regex = "^Card sequence no.: ([0-9]+) ? ([0-9]{2}/[0-9]{2}/[0-9]{4} [0-9]{2}:[0-9]{2}) Transaction: (.*) Term: (.*) Cashback transaction Value date: ([0-9]{2}/[0-9]{2}/[0-9]{4})$" :: String |
201 | (_, _, _, [cardSeqNo, timestampTxt, transaction, term, valDateTxt]) <- t =~~ regex :: C.Parser (T.Text, T.Text, T.Text, [T.Text]) | 201 | (_, _, _, [cardSeqNo, timestampTxt, transaction, term, valDateTxt]) <- t =~~ regex :: C.Parser (T.Text, T.Text, T.Text, [T.Text]) |
202 | timestamp <- timestampCP "%d/%m/%Y %H:%M" amsTz timestampTxt | 202 | timestamp <- parseTimestampM "%d/%m/%Y %H:%M" amsTz timestampTxt |
203 | valDate <- valueDateCP valDateTxt | 203 | valDate <- valueDateCP valDateTxt |
204 | return $ | 204 | return $ |
205 | PaymentTerminalCashbackData | 205 | PaymentTerminalCashbackData |
@@ -212,8 +212,8 @@ notificationsCP amsTz (PartTx _ PaymentTerminal Credit) t = do | |||
212 | notificationsCP amsTz (PartTx _ OnlineBanking Credit) t = do | 212 | notificationsCP amsTz (PartTx _ OnlineBanking Credit) t = do |
213 | let regex = "^Name: (.*) Description: (.*) IBAN: ([A-Z0-9]+) Date/time: ([0-9]{2}-[0-9]{2}-[0-9]{4} [0-9]{2}:[0-9]{2}:[0-9]{2}) Value date: ([0-9]{2}/[0-9]{2}/[0-9]{4})$" :: String | 213 | let regex = "^Name: (.*) Description: (.*) IBAN: ([A-Z0-9]+) Date/time: ([0-9]{2}-[0-9]{2}-[0-9]{4} [0-9]{2}:[0-9]{2}:[0-9]{2}) Value date: ([0-9]{2}/[0-9]{2}/[0-9]{4})$" :: String |
214 | (_, _, _, [name, desc, ibanTxt, timestampTxt, valDateTxt]) <- t =~~ regex :: C.Parser (T.Text, T.Text, T.Text, [T.Text]) | 214 | (_, _, _, [name, desc, ibanTxt, timestampTxt, valDateTxt]) <- t =~~ regex :: C.Parser (T.Text, T.Text, T.Text, [T.Text]) |
215 | iban <- ibanCP ibanTxt | 215 | iban <- parseIbanM ibanTxt |
216 | timestamp <- timestampCP "%d-%m-%Y %H:%M:%S" amsTz timestampTxt | 216 | timestamp <- parseTimestampM "%d-%m-%Y %H:%M:%S" amsTz timestampTxt |
217 | valDate <- valueDateCP valDateTxt | 217 | valDate <- valueDateCP valDateTxt |
218 | return $ | 218 | return $ |
219 | OnlineBankingCredit | 219 | OnlineBankingCredit |
@@ -226,11 +226,11 @@ notificationsCP amsTz (PartTx _ OnlineBanking Credit) t = do | |||
226 | notificationsCP amsTz (PartTx _ OnlineBanking Debit) t = do | 226 | notificationsCP amsTz (PartTx _ OnlineBanking Debit) t = do |
227 | let regex = "^Name: (.*) Description: (.*) IBAN: ([A-Z0-9]+) (Date/time: ([0-9]{2}-[0-9]{2}-[0-9]{4} [0-9]{2}:[0-9]{2}:[0-9]{2}) )?Value date: ([0-9]{2}/[0-9]{2}/[0-9]{4})$" :: String | 227 | let regex = "^Name: (.*) Description: (.*) IBAN: ([A-Z0-9]+) (Date/time: ([0-9]{2}-[0-9]{2}-[0-9]{4} [0-9]{2}:[0-9]{2}:[0-9]{2}) )?Value date: ([0-9]{2}/[0-9]{2}/[0-9]{4})$" :: String |
228 | (_, _, _, [name, desc, ibanTxt, _, timestampTxt, valDateTxt]) <- t =~~ regex :: C.Parser (T.Text, T.Text, T.Text, [T.Text]) | 228 | (_, _, _, [name, desc, ibanTxt, _, timestampTxt, valDateTxt]) <- t =~~ regex :: C.Parser (T.Text, T.Text, T.Text, [T.Text]) |
229 | iban <- ibanCP ibanTxt | 229 | iban <- parseIbanM ibanTxt |
230 | timestamp <- | 230 | timestamp <- |
231 | if T.null timestampTxt | 231 | if T.null timestampTxt |
232 | then pure Nothing | 232 | then pure Nothing |
233 | else Just <$> timestampCP "%d-%m-%Y %H:%M:%S" amsTz timestampTxt | 233 | else Just <$> parseTimestampM "%d-%m-%Y %H:%M:%S" amsTz timestampTxt |
234 | valDate <- valueDateCP valDateTxt | 234 | valDate <- valueDateCP valDateTxt |
235 | return $ | 235 | return $ |
236 | OnlineBankingDebit | 236 | OnlineBankingDebit |
@@ -245,7 +245,7 @@ notificationsCP _ (PartTx date DirectDebit Debit) t = normalRecurrentDirectDebit | |||
245 | normalRecurrentDirectDebit = do | 245 | normalRecurrentDirectDebit = do |
246 | let regex = "^Name: (.*) Description: (.*) IBAN: ([A-Z0-9]+) Reference: (.*) Mandate ID: (.*) Creditor ID: (.*) Recurrent SEPA direct debit (Other party: (.*) )?Value date: ([0-9]{2}/[0-9]{2}/[0-9]{4})$" :: String | 246 | let regex = "^Name: (.*) Description: (.*) IBAN: ([A-Z0-9]+) Reference: (.*) Mandate ID: (.*) Creditor ID: (.*) Recurrent SEPA direct debit (Other party: (.*) )?Value date: ([0-9]{2}/[0-9]{2}/[0-9]{4})$" :: String |
247 | (_, _, _, [name, desc, ibanTxt, ref, mandateId, creditorId, _, otherParty, valDateTxt]) <- t =~~ regex :: C.Parser (T.Text, T.Text, T.Text, [T.Text]) | 247 | (_, _, _, [name, desc, ibanTxt, ref, mandateId, creditorId, _, otherParty, valDateTxt]) <- t =~~ regex :: C.Parser (T.Text, T.Text, T.Text, [T.Text]) |
248 | iban <- ibanCP ibanTxt | 248 | iban <- parseIbanM ibanTxt |
249 | valDate <- valueDateCP valDateTxt | 249 | valDate <- valueDateCP valDateTxt |
250 | return $ | 250 | return $ |
251 | RecurrentDirectDebitData | 251 | RecurrentDirectDebitData |
@@ -261,7 +261,7 @@ notificationsCP _ (PartTx date DirectDebit Debit) t = normalRecurrentDirectDebit | |||
261 | ingInsurancePayment = do | 261 | ingInsurancePayment = do |
262 | let regex = "^Name: (.* ING Verzekeren) Description: (.*) IBAN: ([A-Z0-9]+) Reference: (.*) Mandate ID: (.*) Creditor ID: (.*) Recurrent SEPA direct debit$" :: String | 262 | let regex = "^Name: (.* ING Verzekeren) Description: (.*) IBAN: ([A-Z0-9]+) Reference: (.*) Mandate ID: (.*) Creditor ID: (.*) Recurrent SEPA direct debit$" :: String |
263 | (_, _, _, [name, desc, ibanTxt, ref, mandateId, creditorId]) <- t =~~ regex :: C.Parser (T.Text, T.Text, T.Text, [T.Text]) | 263 | (_, _, _, [name, desc, ibanTxt, ref, mandateId, creditorId]) <- t =~~ regex :: C.Parser (T.Text, T.Text, T.Text, [T.Text]) |
264 | iban <- ibanCP ibanTxt | 264 | iban <- parseIbanM ibanTxt |
265 | return $ | 265 | return $ |
266 | RecurrentDirectDebitData | 266 | RecurrentDirectDebitData |
267 | { rddName = name, | 267 | { rddName = name, |
@@ -276,8 +276,8 @@ notificationsCP _ (PartTx date DirectDebit Debit) t = normalRecurrentDirectDebit | |||
276 | notificationsCP amsTz (PartTx _ Ideal Debit) t = do | 276 | notificationsCP amsTz (PartTx _ Ideal Debit) t = do |
277 | let regex = "^Name: (.*) Description: (.*) IBAN: ([A-Z0-9]+) Reference: ([0-9]{2}-[0-9]{2}-[0-9]{4} [0-9]{2}:[0-9]{2}) ([0-9]+) Value date: ([0-9]{2}/[0-9]{2}/[0-9]{4})$" :: String | 277 | let regex = "^Name: (.*) Description: (.*) IBAN: ([A-Z0-9]+) Reference: ([0-9]{2}-[0-9]{2}-[0-9]{4} [0-9]{2}:[0-9]{2}) ([0-9]+) Value date: ([0-9]{2}/[0-9]{2}/[0-9]{4})$" :: String |
278 | (_, _, _, [name, desc, ibanTxt, timestampTxt, ref, valDateTxt]) <- t =~~ regex :: C.Parser (T.Text, T.Text, T.Text, [T.Text]) | 278 | (_, _, _, [name, desc, ibanTxt, timestampTxt, ref, valDateTxt]) <- t =~~ regex :: C.Parser (T.Text, T.Text, T.Text, [T.Text]) |
279 | iban <- ibanCP ibanTxt | 279 | iban <- parseIbanM ibanTxt |
280 | timestamp <- timestampCP "%d-%m-%Y %H:%M" amsTz timestampTxt | 280 | timestamp <- parseTimestampM "%d-%m-%Y %H:%M" amsTz timestampTxt |
281 | valDate <- valueDateCP valDateTxt | 281 | valDate <- valueDateCP valDateTxt |
282 | return $ | 282 | return $ |
283 | IdealDebitData | 283 | IdealDebitData |
@@ -291,7 +291,7 @@ notificationsCP amsTz (PartTx _ Ideal Debit) t = do | |||
291 | notificationsCP _ (PartTx _ BatchPayment Credit) t = do | 291 | notificationsCP _ (PartTx _ BatchPayment Credit) t = do |
292 | let regex = "^Name: (.*) Description: (.*) IBAN: ([A-Z0-9]+) Reference: (.*) Value date: ([0-9]{2}/[0-9]{2}/[0-9]{4})$" :: String | 292 | let regex = "^Name: (.*) Description: (.*) IBAN: ([A-Z0-9]+) Reference: (.*) Value date: ([0-9]{2}/[0-9]{2}/[0-9]{4})$" :: String |
293 | (_, _, _, [name, desc, ibanTxt, ref, valDateTxt]) <- t =~~ regex :: C.Parser (T.Text, T.Text, T.Text, [T.Text]) | 293 | (_, _, _, [name, desc, ibanTxt, ref, valDateTxt]) <- t =~~ regex :: C.Parser (T.Text, T.Text, T.Text, [T.Text]) |
294 | iban <- ibanCP ibanTxt | 294 | iban <- parseIbanM ibanTxt |
295 | valDate <- valueDateCP valDateTxt | 295 | valDate <- valueDateCP valDateTxt |
296 | return $ | 296 | return $ |
297 | BatchPaymentData | 297 | BatchPaymentData |
@@ -310,7 +310,7 @@ debitCreditCP t = fail ("Unknown debit/credit value '" ++ T.unpack t ++ "'") | |||
310 | 310 | ||
311 | parseNamedRecord :: TZ -> C.NamedRecord -> C.Parser PrimTx | 311 | parseNamedRecord :: TZ -> C.NamedRecord -> C.Parser PrimTx |
312 | parseNamedRecord amsTz m = do | 312 | parseNamedRecord amsTz m = do |
313 | date <- m .: "Date" >>= dateCP "%0Y%m%d" | 313 | date <- m .: "Date" >>= parseDateM "%0Y%m%d" |
314 | debitCredit <- m .: "Debit/credit" >>= debitCreditCP | 314 | debitCredit <- m .: "Debit/credit" >>= debitCreditCP |
315 | codeText <- m .: "Code" | 315 | codeText <- m .: "Code" |
316 | tyText <- m .: "Transaction type" | 316 | tyText <- m .: "Transaction type" |
@@ -322,11 +322,11 @@ parseNamedRecord amsTz m = do | |||
322 | else | 322 | else |
323 | PrimTx date | 323 | PrimTx date |
324 | <$> (m .: "Name / Description" <&> maybeNotProvided) | 324 | <$> (m .: "Name / Description" <&> maybeNotProvided) |
325 | <*> (m .: "Account" >>= ibanCP) | 325 | <*> (m .: "Account" >>= parseIbanM) |
326 | <*> (m .: "Counterparty" >>= maybeCP ibanCP) | 326 | <*> (m .: "Counterparty" >>= maybeCP parseIbanM) |
327 | <*> pure debitCredit | 327 | <*> pure debitCredit |
328 | <*> (m .: "Amount (EUR)" >>= decimalCP) | 328 | <*> (m .: "Amount (EUR)" >>= parseDecimalM) |
329 | <*> (m .: "Resulting balance" >>= decimalCP) | 329 | <*> (m .: "Resulting balance" >>= parseDecimalM) |
330 | <*> m .: "Tag" | 330 | <*> m .: "Tag" |
331 | <*> (m .: "Notifications" >>= notificationsCP amsTz (PartTx date ty debitCredit)) | 331 | <*> (m .: "Notifications" >>= notificationsCP amsTz (PartTx date ty debitCredit)) |
332 | 332 | ||