packages feed

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 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