bgmax 0.1.0.1 → 0.2.0.0
raw patch · 5 files changed
+422/−381 lines, 5 filesdep ~attoparsecdep ~basedep ~bytestringPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: attoparsec, base, bytestring, time
API changes (from Hackage documentation)
- Finance.BgMax.Parser: instance N Int
- Finance.BgMax.Parser: instance N Integer
- Finance.BgMax.Parser: parseBgMax :: Parser [Post]
- Finance.BgMax.TK: D :: DepositType
- Finance.BgMax.TK: EUR :: Currency
- Finance.BgMax.TK: K :: DepositType
- Finance.BgMax.TK: P :: TestMark
- Finance.BgMax.TK: Ref :: Int -> ByteString -> Reference
- Finance.BgMax.TK: Ref0 :: Reference
- Finance.BgMax.TK: Ref1 :: Reference
- Finance.BgMax.TK: Ref2 :: Integer -> Reference
- Finance.BgMax.TK: Ref3 :: ByteString -> Reference
- Finance.BgMax.TK: Ref4 :: ByteString -> Reference
- Finance.BgMax.TK: Ref5 :: ByteString -> Reference
- Finance.BgMax.TK: S :: DepositType
- Finance.BgMax.TK: SEK :: Currency
- Finance.BgMax.TK: T :: TestMark
- Finance.BgMax.TK: TK :: Int -> Post
- Finance.BgMax.TK: TK01 :: TK01_t -> Post
- Finance.BgMax.TK: TK01_t :: ByteString -> Int -> LocalTime -> TestMark -> TK01_t
- Finance.BgMax.TK: TK05 :: TK05_t -> Post
- Finance.BgMax.TK: TK05_t :: Integer -> Maybe Integer -> Currency -> TK05_t
- Finance.BgMax.TK: TK15 :: TK15_t -> Post
- Finance.BgMax.TK: TK15_t :: Integer -> Day -> Int -> Integer -> Currency -> Int -> Maybe DepositType -> TK15_t
- Finance.BgMax.TK: TK20 :: TK20_t -> Post
- Finance.BgMax.TK: TK20_t :: Transaction -> TK20_t
- Finance.BgMax.TK: TK21 :: TK21_t -> Post
- Finance.BgMax.TK: TK21_t :: Transaction -> Int -> TK21_t
- Finance.BgMax.TK: TK22 :: TK22_t -> Post
- Finance.BgMax.TK: TK22_t :: Transaction -> TK22_t
- Finance.BgMax.TK: TK23 :: TK23_t -> Post
- Finance.BgMax.TK: TK23_t :: Transaction -> TK23_t
- Finance.BgMax.TK: TK25 :: TK25_t -> Post
- Finance.BgMax.TK: TK25_t :: ByteString -> TK25_t
- Finance.BgMax.TK: TK26 :: TK26_t -> Post
- Finance.BgMax.TK: TK26_t :: ByteString -> ByteString -> TK26_t
- Finance.BgMax.TK: TK27 :: TK27_t -> Post
- Finance.BgMax.TK: TK27_t :: ByteString -> ByteString -> TK27_t
- Finance.BgMax.TK: TK28 :: TK28_t -> Post
- Finance.BgMax.TK: TK28_t :: ByteString -> ByteString -> ByteString -> TK28_t
- Finance.BgMax.TK: TK29 :: TK29_t -> Post
- Finance.BgMax.TK: TK29_t :: Integer -> TK29_t
- Finance.BgMax.TK: TK70 :: TK70_t -> Post
- Finance.BgMax.TK: TK70_t :: Int -> Int -> Int -> Int -> TK70_t
- Finance.BgMax.TK: Transaction :: Integer -> Reference -> Integer -> Int -> Integer -> Int -> Transaction
- Finance.BgMax.TK: address :: TK27_t -> ByteString
- Finance.BgMax.TK: ammount :: Transaction -> Integer
- Finance.BgMax.TK: bcgNo :: Transaction -> Integer
- Finance.BgMax.TK: city :: TK28_t -> ByteString
- Finance.BgMax.TK: country :: TK28_t -> ByteString
- Finance.BgMax.TK: countryCode :: TK28_t -> ByteString
- Finance.BgMax.TK: currency :: TK05_t -> Currency
- Finance.BgMax.TK: data Currency
- Finance.BgMax.TK: data DepositType
- Finance.BgMax.TK: data Post
- Finance.BgMax.TK: data Reference
- Finance.BgMax.TK: data TK01_t
- Finance.BgMax.TK: data TK05_t
- Finance.BgMax.TK: data TK15_t
- Finance.BgMax.TK: data TK20_t
- Finance.BgMax.TK: data TK21_t
- Finance.BgMax.TK: data TK22_t
- Finance.BgMax.TK: data TK23_t
- Finance.BgMax.TK: data TK25_t
- Finance.BgMax.TK: data TK26_t
- Finance.BgMax.TK: data TK27_t
- Finance.BgMax.TK: data TK28_t
- Finance.BgMax.TK: data TK29_t
- Finance.BgMax.TK: data TK70_t
- Finance.BgMax.TK: data TestMark
- Finance.BgMax.TK: data Transaction
- Finance.BgMax.TK: deduction :: TK21_t -> Transaction
- Finance.BgMax.TK: deductionCode :: TK21_t -> Int
- Finance.BgMax.TK: deductionsCount :: TK70_t -> Int
- Finance.BgMax.TK: depositAmmount :: TK15_t -> Integer
- Finance.BgMax.TK: depositCount :: TK70_t -> Int
- Finance.BgMax.TK: depositCurrency :: TK15_t -> Currency
- Finance.BgMax.TK: depositNo :: TK15_t -> Int
- Finance.BgMax.TK: depositType :: TK15_t -> Maybe DepositType
- Finance.BgMax.TK: extraName :: TK26_t -> ByteString
- Finance.BgMax.TK: extraReferenceCount :: TK70_t -> Int
- Finance.BgMax.TK: imageMark :: Transaction -> Int
- Finance.BgMax.TK: information :: TK25_t -> ByteString
- Finance.BgMax.TK: instance Show Currency
- Finance.BgMax.TK: instance Show DepositType
- Finance.BgMax.TK: instance Show Post
- Finance.BgMax.TK: instance Show Reference
- Finance.BgMax.TK: instance Show TK01_t
- Finance.BgMax.TK: instance Show TK05_t
- Finance.BgMax.TK: instance Show TK15_t
- Finance.BgMax.TK: instance Show TK20_t
- Finance.BgMax.TK: instance Show TK21_t
- Finance.BgMax.TK: instance Show TK22_t
- Finance.BgMax.TK: instance Show TK23_t
- Finance.BgMax.TK: instance Show TK25_t
- Finance.BgMax.TK: instance Show TK26_t
- Finance.BgMax.TK: instance Show TK27_t
- Finance.BgMax.TK: instance Show TK28_t
- Finance.BgMax.TK: instance Show TK29_t
- Finance.BgMax.TK: instance Show TK70_t
- Finance.BgMax.TK: instance Show TestMark
- Finance.BgMax.TK: instance Show Transaction
- Finance.BgMax.TK: layoutName :: TK01_t -> ByteString
- Finance.BgMax.TK: layoutVersion :: TK01_t -> Int
- Finance.BgMax.TK: name :: TK26_t -> ByteString
- Finance.BgMax.TK: negativeReference :: TK23_t -> Transaction
- Finance.BgMax.TK: orgNo :: TK29_t -> Integer
- Finance.BgMax.TK: payment :: TK20_t -> Transaction
- Finance.BgMax.TK: paymentChannel :: Transaction -> Int
- Finance.BgMax.TK: paymentDate :: TK15_t -> Day
- Finance.BgMax.TK: paymentDeductionCount :: TK15_t -> Int
- Finance.BgMax.TK: paymentsCount :: TK70_t -> Int
- Finance.BgMax.TK: positiveReference :: TK22_t -> Transaction
- Finance.BgMax.TK: recipientAccount :: TK15_t -> Integer
- Finance.BgMax.TK: recipientBG :: TK05_t -> Integer
- Finance.BgMax.TK: recipientPG :: TK05_t -> Maybe Integer
- Finance.BgMax.TK: reference :: Transaction -> Reference
- Finance.BgMax.TK: senderBG :: Transaction -> Integer
- Finance.BgMax.TK: testMark :: TK01_t -> TestMark
- Finance.BgMax.TK: timeStamp :: TK01_t -> LocalTime
- Finance.BgMax.TK: zipCode :: TK27_t -> ByteString
+ BankGiro.BgMax: Address :: Maybe ByteString -> Maybe ByteString -> Maybe ByteString -> Maybe ByteString -> Maybe ByteString -> Address
+ BankGiro.BgMax: BgMax :: Int -> LocalTime -> TestMark -> Integer -> Integer -> Integer -> Integer -> [Section] -> BgMax
+ BankGiro.BgMax: Blank :: Reference
+ BankGiro.BgMax: BlankNoUB :: Reference
+ BankGiro.BgMax: CorrectOCR :: Integer -> Centi -> Reference
+ BankGiro.BgMax: CorrectUB :: ByteString -> Centi -> Reference
+ BankGiro.BgMax: D :: DepositType
+ BankGiro.BgMax: Deduction :: DeductionCode -> EntryType
+ BankGiro.BgMax: DeductionCodeReserved :: Int -> DeductionCode
+ BankGiro.BgMax: ElectronicAG :: PaymentChannel
+ BankGiro.BgMax: ElectronicBank :: PaymentChannel
+ BankGiro.BgMax: ElectronicLB :: PaymentChannel
+ BankGiro.BgMax: Entry :: EntryType -> Sender -> [Reference] -> Centi -> PaymentChannel -> Integer -> Image -> [ByteString] -> Entry
+ BankGiro.BgMax: ExtendedRef :: Int -> ByteString -> Reference
+ BankGiro.BgMax: Image :: Image
+ BankGiro.BgMax: ImageReserved :: Int -> Image
+ BankGiro.BgMax: IncorrectOCR :: ByteString -> Reference
+ BankGiro.BgMax: IncorrectUB :: ByteString -> Reference
+ BankGiro.BgMax: K :: DepositType
+ BankGiro.BgMax: NoImage :: Image
+ BankGiro.BgMax: P :: TestMark
+ BankGiro.BgMax: Paper :: PaymentChannel
+ BankGiro.BgMax: PartialFinal :: DeductionCode
+ BankGiro.BgMax: PartialRest :: DeductionCode
+ BankGiro.BgMax: Payment :: EntryType
+ BankGiro.BgMax: PaymentChannelReserved :: Int -> PaymentChannel
+ BankGiro.BgMax: S :: DepositType
+ BankGiro.BgMax: SEK :: Currency
+ BankGiro.BgMax: Section :: Integer -> Maybe Integer -> Integer -> Day -> Integer -> Centi -> Integer -> Maybe DepositType -> Currency -> [Entry] -> Section
+ BankGiro.BgMax: Sender :: Integer -> Maybe (ByteString, ByteString) -> Address -> Maybe Integer -> Sender
+ BankGiro.BgMax: T :: TestMark
+ BankGiro.BgMax: WholeNoRest :: DeductionCode
+ BankGiro.BgMax: [address] :: Sender -> Address
+ BankGiro.BgMax: [ammount] :: Entry -> Centi
+ BankGiro.BgMax: [bgSerialNo] :: Entry -> Integer
+ BankGiro.BgMax: [city] :: Address -> Maybe ByteString
+ BankGiro.BgMax: [countryCode] :: Address -> Maybe ByteString
+ BankGiro.BgMax: [country] :: Address -> Maybe ByteString
+ BankGiro.BgMax: [currency] :: Section -> Currency
+ BankGiro.BgMax: [depositAmmount] :: Section -> Centi
+ BankGiro.BgMax: [depositDay] :: Section -> Day
+ BankGiro.BgMax: [depositNo] :: Section -> Integer
+ BankGiro.BgMax: [depositType] :: Section -> Maybe DepositType
+ BankGiro.BgMax: [entries] :: Section -> [Entry]
+ BankGiro.BgMax: [entryType] :: Entry -> EntryType
+ BankGiro.BgMax: [image] :: Entry -> Image
+ BankGiro.BgMax: [info] :: Entry -> [ByteString]
+ BankGiro.BgMax: [noDeductions] :: BgMax -> Integer
+ BankGiro.BgMax: [noDeposits] :: BgMax -> Integer
+ BankGiro.BgMax: [noExtraReferences] :: BgMax -> Integer
+ BankGiro.BgMax: [noPayments] :: BgMax -> Integer
+ BankGiro.BgMax: [orgNo] :: Sender -> Maybe Integer
+ BankGiro.BgMax: [paymentChannel] :: Entry -> PaymentChannel
+ BankGiro.BgMax: [recipientAccount] :: Section -> Integer
+ BankGiro.BgMax: [recipientBankGiro] :: Section -> Integer
+ BankGiro.BgMax: [recipientPostGiro] :: Section -> Maybe Integer
+ BankGiro.BgMax: [reference] :: Entry -> [Reference]
+ BankGiro.BgMax: [sNoPayments] :: Section -> Integer
+ BankGiro.BgMax: [sections] :: BgMax -> [Section]
+ BankGiro.BgMax: [senderBankGiro] :: Sender -> Integer
+ BankGiro.BgMax: [senderName] :: Sender -> Maybe (ByteString, ByteString)
+ BankGiro.BgMax: [sender] :: Entry -> Sender
+ BankGiro.BgMax: [street] :: Address -> Maybe ByteString
+ BankGiro.BgMax: [testMark] :: BgMax -> TestMark
+ BankGiro.BgMax: [version] :: BgMax -> Int
+ BankGiro.BgMax: [writeDay] :: BgMax -> LocalTime
+ BankGiro.BgMax: [zipCode] :: Address -> Maybe ByteString
+ BankGiro.BgMax: addressPostOne :: Parser (ByteString, ByteString)
+ BankGiro.BgMax: addressPostTwo :: Parser (ByteString, ByteString, ByteString)
+ BankGiro.BgMax: assert :: Bool -> String -> Parser ()
+ BankGiro.BgMax: bgMax :: Parser BgMax
+ BankGiro.BgMax: common :: Parser ([ByteString], Maybe (ByteString, ByteString), Address, Maybe Integer)
+ BankGiro.BgMax: data Address
+ BankGiro.BgMax: data BgMax
+ BankGiro.BgMax: data Currency
+ BankGiro.BgMax: data DeductionCode
+ BankGiro.BgMax: data DepositType
+ BankGiro.BgMax: data Entry
+ BankGiro.BgMax: data EntryType
+ BankGiro.BgMax: data Image
+ BankGiro.BgMax: data PaymentChannel
+ BankGiro.BgMax: data Reference
+ BankGiro.BgMax: data Section
+ BankGiro.BgMax: data Sender
+ BankGiro.BgMax: data TestMark
+ BankGiro.BgMax: dateStamp :: Parser Day
+ BankGiro.BgMax: deduction :: Parser Entry
+ BankGiro.BgMax: deductionPost :: Parser (Integer, ByteString, Centi, Int, PaymentChannel, Integer, Image, DeductionCode)
+ BankGiro.BgMax: depositPost :: Parser (Integer, Day, Integer, Centi, Currency, Integer, Maybe DepositType)
+ BankGiro.BgMax: dummyLine :: ByteString -> Parser ()
+ BankGiro.BgMax: endPost :: Parser (Integer, Integer, Integer, Integer)
+ BankGiro.BgMax: entry :: Parser Entry
+ BankGiro.BgMax: extraReferenceNumberPost :: Integer -> Centi -> PaymentChannel -> Integer -> Image -> Parser Reference
+ BankGiro.BgMax: extraReferenceNumberPostNegative :: Integer -> Centi -> PaymentChannel -> Integer -> Image -> Parser Reference
+ BankGiro.BgMax: informationPost :: Parser ByteString
+ BankGiro.BgMax: instance GHC.Classes.Eq BankGiro.BgMax.Image
+ BankGiro.BgMax: instance GHC.Classes.Eq BankGiro.BgMax.PaymentChannel
+ BankGiro.BgMax: instance GHC.Read.Read BankGiro.BgMax.DepositType
+ BankGiro.BgMax: instance GHC.Show.Show BankGiro.BgMax.Address
+ BankGiro.BgMax: instance GHC.Show.Show BankGiro.BgMax.BgMax
+ BankGiro.BgMax: instance GHC.Show.Show BankGiro.BgMax.Currency
+ BankGiro.BgMax: instance GHC.Show.Show BankGiro.BgMax.DeductionCode
+ BankGiro.BgMax: instance GHC.Show.Show BankGiro.BgMax.DepositType
+ BankGiro.BgMax: instance GHC.Show.Show BankGiro.BgMax.Entry
+ BankGiro.BgMax: instance GHC.Show.Show BankGiro.BgMax.EntryType
+ BankGiro.BgMax: instance GHC.Show.Show BankGiro.BgMax.Image
+ BankGiro.BgMax: instance GHC.Show.Show BankGiro.BgMax.PaymentChannel
+ BankGiro.BgMax: instance GHC.Show.Show BankGiro.BgMax.Reference
+ BankGiro.BgMax: instance GHC.Show.Show BankGiro.BgMax.Section
+ BankGiro.BgMax: instance GHC.Show.Show BankGiro.BgMax.Sender
+ BankGiro.BgMax: instance GHC.Show.Show BankGiro.BgMax.TestMark
+ BankGiro.BgMax: isEndOfLine :: Char -> Bool
+ BankGiro.BgMax: maybeP :: Parser a -> Parser (Maybe a)
+ BankGiro.BgMax: mkDeductionCode :: Int -> DeductionCode
+ BankGiro.BgMax: mkImage :: Int -> Image
+ BankGiro.BgMax: mkPaymentChannel :: Int -> PaymentChannel
+ BankGiro.BgMax: mkReference :: Int -> ByteString -> Centi -> Reference
+ BankGiro.BgMax: myTake :: Int -> Parser ByteString
+ BankGiro.BgMax: namePost :: Parser (ByteString, ByteString)
+ BankGiro.BgMax: openingPost :: Parser (Integer, Maybe Integer, Currency)
+ BankGiro.BgMax: orgNoPost :: Parser Integer
+ BankGiro.BgMax: pCurrency :: Parser Currency
+ BankGiro.BgMax: pTestMark :: Parser TestMark
+ BankGiro.BgMax: payment :: Parser Entry
+ BankGiro.BgMax: paymentPost :: Parser (Integer, ByteString, Centi, Int, PaymentChannel, Integer, Image)
+ BankGiro.BgMax: referenceCommon :: Bool -> Integer -> Centi -> PaymentChannel -> Integer -> Image -> Parser Reference
+ BankGiro.BgMax: section :: Parser Section
+ BankGiro.BgMax: startPost :: Parser (Int, LocalTime, TestMark)
+ BankGiro.BgMax: takeRead :: Read a => Int -> Parser a
+ BankGiro.BgMax: takeReadMaybe :: Read a => Int -> Parser (Maybe a)
+ BankGiro.BgMax: takeT :: Int -> Parser ByteString
+ BankGiro.BgMax: takeTab :: ByteString -> Int -> Int -> Parser ByteString
+ BankGiro.BgMax: tillEol :: Parser String
+ BankGiro.BgMax: timeStamp :: Parser LocalTime
Files
- bgmax.cabal +19/−11
- changelog.md +3/−0
- src/BankGiro/BgMax.hs +400/−0
- src/Finance/BgMax/Parser.hs +0/−185
- src/Finance/BgMax/TK.hs +0/−185
bgmax.cabal view
@@ -1,5 +1,5 @@ name: bgmax-version: 0.1.0.1+version: 0.2.0.0 synopsis: Parse BgMax-files homepage: http://github.com/jonpetterbergman/bgmax bug-reports: http://github.com/jonpetterbergman/bgmax/issues@@ -14,20 +14,28 @@ cabal-version: >=1.10 extra-source-files: changelog.md description: - A low-level parser for - <http://www.bgc.se/upload/Gemensamt/Trycksaker/Manualer/BG6040.pdf BgMax>- -files from <http://www.bgc.se Bankgirocentralen> (BGC).+ A parser for + <http://www.autogiro.se/globalassets/dokument/tekniska-manualer/bankgiroinbetalningar_tekniskmanual_sv.pdf BgMax>+ -files from <http://www.autogiro.se BankGirot>. It is able to parse all of the - <http://www.bgc.se/templates/Iframe____3125.aspx example files> from BGC.+ <http://www.autogiro.se/tjanster/inbetalningar/bankgiro-inbetalningar/teknisk-information/ example files> from BGC.+source-repository head+ type: git+ location: http://github.com/jonpetterbergman/bgmax +source-repository this+ type: git+ location: http://github.com/jonpetterbergman/bgmax+ tag: v0.2.0.0+ library- exposed-modules: Finance.BgMax.TK - Finance.BgMax.Parser+ exposed-modules: BankGiro.BgMax -- other-modules: other-extensions: OverloadedStrings- build-depends: base >=4.7 && <4.8,- time >=1.2 && <1.5,- bytestring >=0.9 && <10.3,- attoparsec >=0.10 && <0.13+ build-depends: + base >= 4.9 && < 4.10,+ time >= 1.6 && < 1.7,+ bytestring >= 0.10.8.1 && < 0.11,+ attoparsec >= 0.13.1.0 && < 0.14 hs-source-dirs: src default-language: Haskell2010
changelog.md view
@@ -1,3 +1,6 @@+# Version 0.2.0.0+ - Complete rewrite, more complete higher level parser+ # Version 0.1.0.1 - Cleaned up build-depends. - Moved to github.
+ src/BankGiro/BgMax.hs view
@@ -0,0 +1,400 @@+{-# LANGUAGE OverloadedStrings #-}+module BankGiro.BgMax where++import Control.Applicative ((<|>))+import Control.Monad (guard)+import Data.Attoparsec.ByteString (Parser, eitherP, endOfInput,+ many', many1, option,+ parseOnly, (<?>))+import qualified Data.Attoparsec.ByteString as Atto+import Data.Attoparsec.ByteString.Char8 (IResult (..), anyChar,+ endOfLine, manyTill, parse,+ string, takeTill)+import Data.ByteString (ByteString)+import qualified Data.ByteString as BS+import Data.ByteString.Char8 (snoc, unpack)+import Data.Fixed (Centi, Fixed (..))+import Data.Time (Day, LocalTime)+import Data.Time.Format (defaultTimeLocale,+ parseTimeM)++data PaymentChannel =+ ElectronicBank+ | ElectronicLB+ | Paper+ | ElectronicAG+ | PaymentChannelReserved Int deriving (Show,Eq)++data Image =+ NoImage+ | Image+ | ImageReserved Int deriving (Show,Eq)++data Address =+ Address {+ street :: Maybe ByteString+ , zipCode :: Maybe ByteString+ , city :: Maybe ByteString+ , country :: Maybe ByteString+ , countryCode :: Maybe ByteString } deriving Show++data Sender =+ Sender {+ senderBankGiro :: Integer+ , senderName :: Maybe (ByteString,ByteString)+ , address :: Address+ , orgNo :: Maybe Integer } deriving Show++data Reference =+ Blank+ | BlankNoUB+ | CorrectOCR Integer Centi+ | IncorrectOCR ByteString+ | CorrectUB ByteString Centi+ | IncorrectUB ByteString+ | ExtendedRef Int ByteString deriving Show++mkReference :: Int -> ByteString -> Centi -> Reference+mkReference 0 _ _ = Blank+mkReference 1 _ _ = BlankNoUB+mkReference 2 bs x = CorrectOCR (read $ unpack bs) x+mkReference 3 bs _ = IncorrectOCR bs+mkReference 4 bs x = CorrectUB bs x+mkReference 5 bs _ = IncorrectUB bs+mkReference n bs _ = ExtendedRef n bs++data DeductionCode =+ WholeNoRest+ | PartialRest+ | PartialFinal+ | DeductionCodeReserved Int deriving Show++mkDeductionCode :: Int -> DeductionCode+mkDeductionCode 1 = WholeNoRest+mkDeductionCode 2 = PartialRest+mkDeductionCode 3 = PartialFinal+mkDeductionCode n = DeductionCodeReserved n++data EntryType =+ Payment+ | Deduction DeductionCode deriving Show++data Entry =+ Entry {+ entryType :: EntryType+ , sender :: Sender+ , reference :: [Reference]+ , ammount :: Centi+ , paymentChannel :: PaymentChannel+ , bgSerialNo :: Integer+ , image :: Image+ , info :: [ByteString] } deriving Show++data Currency = SEK deriving Show++data DepositType = K | D | S deriving (Show,Read)++data Section =+ Section {+ recipientBankGiro :: Integer+ , recipientPostGiro :: Maybe Integer+ , recipientAccount :: Integer+ , depositDay :: Day+ , depositNo :: Integer+ , depositAmmount :: Centi+ , sNoPayments :: Integer+ , depositType :: Maybe DepositType+ , currency :: Currency+ , entries :: [Entry] } deriving Show++data TestMark = T | P deriving Show++data BgMax =+ BgMax {+ version :: Int+ , writeDay :: LocalTime+ , testMark :: TestMark+ , noPayments :: Integer+ , noDeductions :: Integer+ , noExtraReferences :: Integer+ , noDeposits :: Integer+ , sections :: [Section] } deriving Show++mkPaymentChannel :: Int -> PaymentChannel+mkPaymentChannel 1 = ElectronicBank+mkPaymentChannel 2 = ElectronicLB+mkPaymentChannel 3 = Paper+mkPaymentChannel 4 = ElectronicAG+mkPaymentChannel n = PaymentChannelReserved n++mkImage :: Int -> Image+mkImage 0 = NoImage+mkImage 1 = Image+mkImage n = ImageReserved n+++assert :: Bool -> String -> Parser ()+assert cond msg | cond = return ()+ | otherwise = fail msg++bgMax :: Parser BgMax+bgMax =+ do+ (v,ts,tm) <- startPost+ sects <- many1 section+ (noPayments,noDeductions,noExtraReferences,noDeposits) <- endPost+ return $ BgMax v ts tm noPayments noDeductions noExtraReferences noDeposits sects++isEndOfLine :: Char -> Bool+isEndOfLine '\n' = True+isEndOfLine '\r' = True+isEndOfLine _ = False++dummyLine :: ByteString -> Parser ()+dummyLine x = string x >> tillEol >> return ()++tillEol :: Parser String+tillEol = manyTill anyChar (endOfLine <|> endOfInput)++takeTab :: ByteString -> Int -> Int -> Parser ByteString+takeTab acc _ 0 = return acc+takeTab acc tabLen n | n > 0 =+ do+ c <- anyChar+ takeTab (acc `snoc` c) tabLen (n - (if (c == '\t') then tabLen else 1))+ | otherwise = mempty++myTake :: Int -> Parser ByteString+myTake n = takeTab "" 6 n++takeT :: Int -> Parser ByteString+takeT n =+ do+ c <- myTake n+ return c++takeReadMaybe :: Read a => Int -> Parser (Maybe a)+takeReadMaybe n =+ do+ c <- myTake n+ case reads $ unpack c of+ [(x,_)] -> return $ Just x+ _ -> return Nothing++takeRead :: Read a => Int -> Parser a+takeRead n =+ do+ it <- takeReadMaybe n+ maybe mempty return it++pTestMark :: Parser TestMark+pTestMark = (string "P" >> return P) <|> (string "T" >> return T)++pCurrency :: Parser Currency+pCurrency = string "SEK" >> return SEK++timeStamp :: Parser LocalTime+timeStamp =+ do+ str <- fmap unpack $ myTake 20+ parseTimeM False defaultTimeLocale "%_Y%m%d%H%M%S%q" $ str ++ "000000"++dateStamp :: Parser Day+dateStamp =+ do+ str <- fmap unpack $ myTake 8+ parseTimeM False defaultTimeLocale "%_Y%m%d" str+++startPost :: Parser (Int,LocalTime,TestMark)+startPost =+ (do+ string "01BGMAX "+ v <- takeRead 2+ ts <- timeStamp+ tm <- pTestMark+ tillEol+ return (v,ts,tm)) <?> "startPost"++endPost :: Parser (Integer,Integer,Integer,Integer)+endPost =+ (do+ string "70"+ noPayments <- takeRead 8+ noDeductions <- takeRead 8+ noExtraReferences <- takeRead 8+ noDeposits <- takeRead 8+ tillEol+ return (noPayments,noDeductions,noExtraReferences,noDeposits)) <?> "endPost"++openingPost :: Parser (Integer,Maybe Integer,Currency)+openingPost =+ (do+ string "05"+ bgNo <- takeRead 10+ pgNo <- (fmap Just $ takeRead 10) <|> (myTake 10 >> return Nothing)+ c <- pCurrency+ tillEol+ return (bgNo,pgNo,c)) <?> "openingPost"++depositPost :: Parser (Integer,Day,Integer,Centi,Currency,Integer,Maybe DepositType)+depositPost =+ (do+ string "15"+ accNo <- takeRead 35+ payDay <- dateStamp+ depositNo <- takeRead 5+ amm <- fmap MkFixed $ takeRead 18+ c <- pCurrency+ noPayments <- takeRead 8+ depositType <- takeReadMaybe 1+ tillEol+ return (accNo,payDay,depositNo,amm,c,noPayments,depositType)) <?> "depositPost"++section :: Parser Section+section =+ (do+ (rBgNo,rPgNo,c) <- openingPost+ ents <- many1 entry+ (accNo,payDay,depositNo,amm,c',noPayments,depositType) <- depositPost+ return $ Section rBgNo rPgNo accNo payDay depositNo amm noPayments depositType c ents) <?> "section"++entry :: Parser Entry+entry = deduction <|> payment++maybeP :: Parser a -> Parser (Maybe a)+maybeP p = option Nothing $ fmap Just p++common :: Parser ([ByteString],+ Maybe (ByteString,ByteString),+ Address,+ Maybe Integer)+common =+ do+ info <- many' informationPost+ names <- maybeP namePost+ (street,zipCode) <- fmap (maybe (Nothing,Nothing) $ \(a,b) -> (Just a,Just b)) $ maybeP addressPostOne+ (city,country,countryCode) <- fmap (maybe (Nothing,Nothing,Nothing) $ \(a,b,c) -> (Just a,Just b,Just c)) $ maybeP addressPostTwo+ orgNo <- maybeP orgNoPost+ return (info,names,Address street zipCode city country countryCode,orgNo)++payment :: Parser Entry+payment =+ do+ (bg,ref,amm,refc,payc,bgcno,im) <- paymentPost+ er <- many' (extraReferenceNumberPost bg 0 payc bgcno im <|>+ extraReferenceNumberPostNegative bg 0 payc bgcno im)+ (info,names,addr,orgNo) <- common+ return $ Entry Payment (Sender bg names addr orgNo) (mkReference refc ref amm:er) amm payc bgcno im info++deduction :: Parser Entry+deduction =+ do+ (bg,ref,amm,refc,payc,bgcno,im,dedc) <- deductionPost+ er <- many' (extraReferenceNumberPost bg 0 payc bgcno im <|>+ extraReferenceNumberPostNegative bg 0 payc bgcno im)+ (info,names,addr,orgNo) <- common+ return $ Entry (Deduction dedc) (Sender bg names addr orgNo) (mkReference refc ref amm:er) amm payc bgcno im info++paymentPost :: Parser (Integer,ByteString,Centi,Int,PaymentChannel,Integer,Image)+paymentPost =+ (do+ string "20"+ bgNo <- takeRead 10+ ref <- myTake 25+ amm <- fmap MkFixed $ takeRead 18+ refc <- takeRead 1+ payc <- fmap mkPaymentChannel $ takeRead 1+ bgcNo <- takeRead 12+ im <- fmap mkImage $ takeRead 1+ tillEol+ return (bgNo,ref,amm,refc,payc,bgcNo,im)) <?> "paymentPost"++deductionPost :: Parser (Integer,ByteString,Centi,Int,PaymentChannel,Integer,Image,DeductionCode)+deductionPost =+ (do+ string "21"+ bgNo <- takeRead 10+ ref <- myTake 25+ amm <- fmap MkFixed $ takeRead 18+ refc <- takeRead 1+ payc <- fmap mkPaymentChannel $ takeRead 1+ bgcNo <- takeRead 12+ im <- fmap mkImage $ takeRead 1+ dedc <- fmap mkDeductionCode $ takeRead 1+ tillEol+ return (bgNo,ref,amm,refc,payc,bgcNo,im,dedc)) <?> "deductionPost"++referenceCommon :: Bool -> Integer -> Centi -> PaymentChannel -> Integer -> Image -> Parser Reference+referenceCommon isNeg bgNo' amm' payc' bgcNo' im' =+ do+ bgNo <- takeRead 10+ ref <- takeT 25+ amm <- fmap MkFixed $ takeRead 18+ refc <- takeRead 1+ payc <- fmap mkPaymentChannel $ takeRead 1+ bgcNo <- takeRead 12+ im <- fmap mkImage $ takeRead 1+ tillEol+ assert (bgNo' == bgNo) "bgNo doesn't match"+ assert (payc' == payc) "payc doesn't match"+ assert (bgcNo' == bgcNo) "bgcNo doesn't match"+ assert (im' == im) "im doesn't match"+ return $ mkReference refc ref (if isNeg then 0 - amm else amm)++extraReferenceNumberPost :: Integer -> Centi -> PaymentChannel -> Integer -> Image -> Parser Reference+extraReferenceNumberPost bgNo amm payc bgcNo im =+ (do+ string "22"+ referenceCommon False bgNo amm payc bgcNo im) <?> "extraReferenceNumberPost"++extraReferenceNumberPostNegative :: Integer -> Centi -> PaymentChannel -> Integer -> Image -> Parser Reference+extraReferenceNumberPostNegative bgNo amm payc bgcNo im =+ (do+ string "23"+ referenceCommon True bgNo amm payc bgcNo im) <?> "extraReferenceNumberPostNegative"++informationPost :: Parser ByteString+informationPost =+ (do+ string "25"+ info <- takeT 50+ tillEol+ return info) <?> "informationPost"++namePost :: Parser (ByteString,ByteString)+namePost =+ (do+ string "26"+ name <- takeT 35+ extraName <- takeT 35+ tillEol+ return (name,extraName)) <?> "namePost"++addressPostOne :: Parser (ByteString,ByteString)+addressPostOne =+ (do+ string "27"+ street <- takeT 35+ zipCode <- takeT 9+ tillEol+ return (street,zipCode)) <?> "addressPostOne"++addressPostTwo :: Parser (ByteString,ByteString,ByteString)+addressPostTwo =+ (do+ string "28"+ city <- takeT 35+ country <- takeT 35+ countryCode <- takeT 2+ tillEol+ return (city,country,countryCode)) <?> "addressPostTwo"++orgNoPost :: Parser Integer+orgNoPost =+ (do+ string "29"+ orgNo <- takeRead 12+ tillEol+ return orgNo) <?> "orgNoPost"+
− src/Finance/BgMax/Parser.hs
@@ -1,185 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{- |-Module : $Header$-Description : Parser for the BgMax file format-Copyright : (c) Petter Bergman-License : BSD3--Maintainer : jon.petter.bergman@gmail.com-Stability : experimental-Portability : non-portable (OverloadedStrings)--This module contains a Parser for the -<http://www.bgc.se/upload/Gemensamt/Trycksaker/Manualer/BG6040.pdf BgMax>-format.--The parser tries to be forgiving with input it doesn't understand.--}-module Finance.BgMax.Parser(parseBgMax) where-import Finance.BgMax.TK-import Data.ByteString.Char8(ByteString,dropWhile,reverse,readInt,readInteger,null,replicate)-import Data.Time(LocalTime(..),Day,TimeOfDay(..),fromGregorian)-import Data.Char(isSpace)-import Data.Attoparsec.ByteString.Char8(Parser,take,endOfLine,sepBy,string,skipWhile,notInClass)-import Prelude hiding (take,dropWhile,reverse,null,replicate)-import Control.Applicative((<|>),(*>),(<*>),(<$>),(<*))-import Data.Fixed(Pico)--class N a where- readN :: ByteString -> Maybe (a,ByteString)--instance N Int where- readN = readInt--instance N Integer where- readN = readInteger- -readFullN :: N a => ByteString -> Parser a-readFullN bs = - case readN bs of- Nothing -> fail $ "could not read as Int: " ++ show bs- Just (x,bs') | null bs' -> return x- | otherwise -> fail $ "could not read all characters as Int: " ++ show bs'--n' :: N a => ByteString -> Parser a-n' = readFullN--n :: N a => Int -> Parser a-n c = take c >>= n'--nhb' :: N a => ByteString -> Parser a-nhb' = readFullN . dropWhile isSpace--nhb :: N a => Int -> Parser a-nhb c = take c >>= nhb'--orBlank :: (Int -> Parser a) -> Int -> Parser (Maybe a)-orBlank p c = (fmap Just $ p c) <|> (string (replicate c ' ') *> (return Nothing))--avb' :: ByteString -> ByteString-avb' = reverse . dropWhile isSpace . reverse--avb :: Int -> Parser ByteString-avb = fmap avb' . take--ab' :: ByteString -> ByteString-ab' = dropWhile isSpace--ab :: Int -> Parser ByteString-ab = fmap ab' . take--pOrT :: Parser TestMark-pOrT =- "T" *> return T <|>- "P" *> return P--parseCurrency :: Parser Currency-parseCurrency =- "EUR" *> return EUR <|>- "SEK" *> return SEK--makeReference :: Int -> ByteString -> Parser Reference-makeReference 0 _ = return Ref0-makeReference 1 _ = return Ref1-makeReference 2 bs = fmap Ref2 $ nhb' bs-makeReference 3 bs = return $ Ref3 $ ab' bs-makeReference 4 bs = return $ Ref4 $ avb' bs-makeReference 5 bs = return $ Ref5 $ ab' bs-makeReference i bs = return $ Ref i bs--parseDepositType :: Parser DepositType-parseDepositType = "K" *> return K <|>- "D" *> return D <|>- "S" *> return S--parseDay :: Parser Day-parseDay = fromGregorian <$> n 4 <*> n 2 <*> n 2--parseMicroseconds :: Parser Pico-parseMicroseconds =- do- second <- n 2- microsecond <- n 6- return $ (fromInteger second) + ((fromInteger microsecond) / 1000000)--parseTimeOfDay :: Parser TimeOfDay-parseTimeOfDay = TimeOfDay <$> n 2 <*> n 2 <*> parseMicroseconds--localTime :: Parser LocalTime-localTime = LocalTime <$> parseDay <*> parseTimeOfDay--parseTransaction :: Parser Transaction-parseTransaction = - do- sBG <- n 10- ref' <- take 25- amm <- n 18- refCode <- n 1- chan <- n 1- bglNo <- n 12- imag <- n 1- ref <- makeReference refCode ref'- return $ Transaction sBG ref amm chan bglNo imag--parsePost :: Parser a -> Parser b -> Parser b-parsePost code make = code *> make <* skipWhile (== ' ')--tk01 :: Parser Post-tk01 = fmap TK01 $ parsePost "01" $ TK01_t <$> avb 20 <*> n 2 <*> localTime <*> pOrT--tk05 :: Parser Post-tk05 = fmap TK05 $ parsePost "05" $ TK05_t <$> n 10 <*> orBlank n 10 <*> parseCurrency--tk20 :: Parser Post-tk20 = fmap TK20 $ parsePost "20" $ TK20_t <$> parseTransaction--tk21 :: Parser Post-tk21 = fmap TK21 $ parsePost "21" $ TK21_t <$> parseTransaction <*> n 1--tk22 :: Parser Post-tk22 = fmap TK22 $ parsePost "22" $ TK22_t <$> parseTransaction--tk23 :: Parser Post-tk23 = fmap TK23 $ parsePost "23" $ TK23_t <$> parseTransaction--tk25 :: Parser Post-tk25 = fmap TK25 $ parsePost "25" $ TK25_t <$> ab 50--tk26 :: Parser Post-tk26 = fmap TK26 $ parsePost "26" $ TK26_t <$> avb 35 <*> avb 35--tk27 :: Parser Post-tk27 = fmap TK27 $ parsePost "27" $ TK27_t <$> avb 35 <*> avb 9--tk28 :: Parser Post-tk28 = fmap TK28 $ parsePost "28" $ TK28_t <$> avb 35 <*> avb 35 <*> avb 2--tk29 :: Parser Post-tk29 = fmap TK29 $ parsePost "29" $ TK29_t <$> n 12--tk15 :: Parser Post-tk15 = fmap TK15 $ parsePost "15" $ TK15_t <$> n 35 <*> parseDay <*> n 5 <*> n 18 <*> parseCurrency <*> n 8 <*> orBlank (const parseDepositType) 1--tk70 :: Parser Post-tk70 = fmap TK70 $ parsePost "70" $ TK70_t <$> n 8 <*> n 8 <*> n 8 <*> n 8--tk :: Parser Post-tk = (TK <$> n 2) <* skipWhile (notInClass "\n\r")---- | Parser for BgMax posts.-parseBgMax :: Parser [Post]-parseBgMax = sepBy go endOfLine - where go = tk01 <|> - tk05 <|> - tk20 <|> - tk21 <|> - tk22 <|> - tk23 <|> - tk25 <|>- tk26 <|>- tk27 <|>- tk28 <|>- tk29 <|>- tk15 <|> - tk70 <|>- tk
− src/Finance/BgMax/TK.hs
@@ -1,185 +0,0 @@-{- |-Module : $Header$-Description : Datatypes for the BgMax file format-Copyright : (c) Petter Bergman-License : BSD3--Maintainer : jon.petter.bergman@gmail.com-Stability : experimental-Portability : portable--This module contain data definitions for the different types of "Posts" or -"Transaction Codes" that may occur in a BgMax file, as well as auxiliary-data types. --The datatypes should map in a straightforward way to the -documentation from <http://www.bgc.se/upload/Gemensamt/Trycksaker/Manualer/BG6040.pdf Bankgirocentralen>.--}-module Finance.BgMax.TK where-import Data.Time(LocalTime(..),Day)-import Data.ByteString(ByteString)---- | Testmark-data TestMark = - T -- ^ Test file - | P -- ^ Production file - deriving Show---- | BankGirot currently only supports EUR and SEK-data Currency = EUR | SEK deriving Show---- | Reference.--- The references correspond to the reference codes defined in--- <http://www.bgc.se/upload/Gemensamt/Trycksaker/Manualer/BG6040.pdf the BgMax documentation>.-data Reference = - -- | No reference.- Ref0- -- | No reference. - | Ref1 - -- | Reference is correct OCR-no.- | Ref2 Integer- -- | One or more references.- | Ref3 ByteString- -- | One reference.- | Ref4 ByteString- -- | Incorrect reference.- | Ref5 ByteString- -- | Reserved for future use.- | Ref Int ByteString - deriving Show---- | Deposit type.--- Deposit type according to bank agreement.-data DepositType = K | D | S deriving Show---- | Transaction type reused in TK 20,21,22,23.-data Transaction = - Transaction {- senderBG :: Integer,- reference :: Reference,- ammount :: Integer,- -- | See the BGC documentation for the meaning of payment channel code.- paymentChannel :: Int,- bcgNo :: Integer,- -- | See the BGC documentation for the meaning of the image mark.- imageMark :: Int } - deriving Show---- | Start post.-data TK01_t =- TK01_t {- layoutName :: ByteString,- layoutVersion :: Int,- timeStamp :: LocalTime,- testMark :: TestMark } - deriving Show---- | Opening post.-data TK05_t =- TK05_t {- recipientBG :: Integer,- recipientPG :: Maybe Integer,- currency :: Currency } - deriving Show---- | Payment post.-data TK20_t =- TK20_t {- payment :: Transaction } - deriving Show---- | Deduction post.-data TK21_t =- TK21_t {- deduction :: Transaction,- -- | See the BGC documentation for the meaning of the deduction code.- deductionCode :: Int } - deriving Show---- | Extra reference post.-data TK22_t =- TK22_t {- positiveReference :: Transaction } - deriving Show---- | Extra reference post (negative ammount).-data TK23_t =- TK23_t {- negativeReference :: Transaction } - deriving Show---- | Information post.-data TK25_t =- TK25_t {- information :: ByteString } - deriving Show---- | Name post.-data TK26_t =- TK26_t {- name :: ByteString,- extraName :: ByteString } - deriving Show---- | Address 1 post.-data TK27_t =- TK27_t {- address :: ByteString,- zipCode :: ByteString } - deriving Show---- | Address 2 post.-data TK28_t =- TK28_t {- city :: ByteString,- country :: ByteString,- countryCode :: ByteString } - deriving Show---- | Organisation-number post.-data TK29_t = - TK29_t {- orgNo :: Integer } - deriving Show---- | Deposit post.-data TK15_t =- TK15_t {- recipientAccount :: Integer,- paymentDate :: Day,- depositNo :: Int,- depositAmmount :: Integer,- depositCurrency :: Currency,- paymentDeductionCount :: Int,- depositType :: Maybe DepositType } - deriving Show---- | End post-data TK70_t =- TK70_t {- paymentsCount :: Int,- deductionsCount :: Int,- extraReferenceCount :: Int,- depositCount :: Int } - deriving Show---- | Sum type for posts.-data Post =- TK01 TK01_t- | TK05 TK05_t- | TK20 TK20_t- | TK21 TK21_t- | TK22 TK22_t- | TK23 TK23_t- | TK25 TK25_t- | TK26 TK26_t- | TK27 TK27_t- | TK28 TK28_t- | TK29 TK29_t- | TK15 TK15_t- | TK70 TK70_t- -- | The BGC documentation states that implementations should ignore posts - -- they don't understand, they will be instead be recorded using this - -- constructor.- | TK Int - deriving Show