.gitignore
[comptalang.git] / cli / Hcompta / CLI / Command / GL.hs
index e6073c71b2117e3f269a0f1f831c43708bdb74b5..a7eb53528732c47d4cbde2a674d2c2e61e381c33 100644 (file)
+{-# LANGUAGE ExistentialQuantification #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE NamedFieldPuns #-}
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE Rank2Types #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TupleSections #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
 module Hcompta.CLI.Command.GL where
 
-import           Control.Monad (liftM)
+import           Control.Applicative (Const(..), (<$>))
+import           Control.Arrow (first, (+++))
+import           Control.Monad (Monad(..), liftM, mapM)
 import           Control.Monad.IO.Class (liftIO)
-import           Control.Monad.Trans.Except (runExceptT)
-import qualified Data.Either
-import qualified Data.Foldable
-import           Data.Functor.Compose (Compose(..))
-import qualified Data.List
-import qualified Data.Map.Strict as Data.Map
-import           Data.Monoid ((<>))
-import qualified Data.Sequence
-import qualified Data.Text as Text
-import qualified Data.Text.Lazy as TL
-import           Prelude hiding (foldr)
+import           Data.Bool
+import           Data.Decimal (Decimal)
+import           Data.Either (Either(..), partitionEithers)
+import           Data.Foldable (Foldable(..))
+import           Data.Function (($), (.), on, id, flip)
+import           Data.Functor (Functor(..))
+import           Data.List ((++), repeat)
+import           Data.Map.Strict (Map)
+import qualified Data.Map.Strict as Map
+import           Data.Maybe (Maybe(..))
+import           Data.Monoid (Monoid(..))
+import           Data.Ord (Ord)
+import qualified Data.Sequence as Seq
+import qualified Data.Strict.Maybe as Strict
+import           Data.String (String)
+import           Data.Text (Text)
+import           Prelude (Bounded(..), unlines, zipWith)
 import           System.Console.GetOpt
                  ( ArgDescr(..)
                  , OptDescr(..)
                  , usageInfo
                  )
 import           System.Environment as Env (getProgName)
-import           System.Exit (exitWith, ExitCode(..))
+import           System.Exit (exitSuccess)
 import qualified System.IO as IO
+import           System.IO (FilePath, IO)
 
-import           Hcompta.Account (Account)
-import           Hcompta.Amount (Amount)
-import qualified Hcompta.Amount as Amount
-import qualified Hcompta.Amount.Write as Amount.Write
+import qualified Hcompta.Account as Account
 import qualified Hcompta.CLI.Args as Args
-import qualified Hcompta.CLI.Context as Context
-import qualified Hcompta.CLI.Format.Ledger as CLI.Ledger
+import qualified Hcompta.CLI.Context as C
+import qualified Hcompta.CLI.Env as CLI.Env
+import           Hcompta.CLI.Format.Ledger ()
+import           Hcompta.CLI.Format.JCC ()
 import qualified Hcompta.CLI.Lang as Lang
-import qualified Hcompta.CLI.Lib.Leijen.Table as Table
+import qualified Hcompta.CLI.Lib.Leijen.Table as Leijen.Table
 import qualified Hcompta.CLI.Write as Write
+import qualified Hcompta.Chart as Chart
 import           Hcompta.Date (Date)
-import qualified Hcompta.Date.Write as Date.Write
 import qualified Hcompta.Filter as Filter
 import qualified Hcompta.Filter.Read as Filter.Read
-import qualified Hcompta.Filter.Reduce as Filter.Reduce
+import qualified Hcompta.Format.JCC as JCC
 import qualified Hcompta.Format.Ledger as Ledger
-import qualified Hcompta.Format.Ledger.Journal as Ledger.Journal
-import qualified Hcompta.Format.Ledger.Read as Ledger.Read
-import qualified Hcompta.Format.Ledger.Write as Ledger.Write
+import qualified Hcompta.GL as GL
 import           Hcompta.Lib.Leijen (toDoc, ToDoc(..))
+import qualified Hcompta.Lib.TreeMap as TreeMap
+import           Hcompta.Polarize (Polarized)
+import qualified Hcompta.Polarize as Polarize
+import qualified Hcompta.Posting as Posting
+import qualified Hcompta.Filter.Amount as Filter.Amount
+import           Hcompta.CLI.Format (Format(..), Formats)
+import qualified Hcompta.CLI.Format as Format
 import qualified Hcompta.Lib.Leijen as W
-import qualified Hcompta.Lib.TreeMap as Lib.TreeMap
-import           Hcompta.GL (GL(..))
-import qualified Hcompta.GL as GL
+import qualified Hcompta.Lib.Parsec as R
+import qualified Hcompta.Unit as Unit
+import qualified Hcompta.Quantity as Quantity
 
-data Ctx
- =   Ctx
- { ctx_input              :: [FilePath]
- , ctx_filter_transaction :: Filter.Simplified
-                             (Filter.Test_Bool
-                             (Filter.Test_Transaction
-                             Ledger.Transaction))
- , ctx_filter_posting     :: Filter.Simplified
-                             (Filter.Test_Bool
-                             (Filter.Test_Posting
-                             Ledger.Posting))
- , ctx_filter_gl          :: Filter.Simplified
-                             (Filter.Test_Bool
-                             (Filter.Test_GL
-                             ( Account
-                             , Date
-                             , Amount.Sum Amount
-                             , Amount.Sum Amount )))
+data Context
+ =   Context
+ { ctx_filter_transaction :: forall t.
+                             ( Filter.Transaction t
+                             , Filter.Amount_Quantity
+                               (Posting.Posting_Amount
+                               (Filter.Transaction_Posting t))
+                               ~ Filter.Amount.Quantity
+                             ) => Filter.Simplified
+                                  (Filter.Filter_Bool
+                                  (Filter.Filter_Transaction t))
+ , ctx_filter_gl          :: forall b.
+                             ( Filter.GL b
+                             , Filter.Amount_Quantity
+                               (Filter.GL_Amount b)
+                               ~ Filter.Amount.Quantity
+                             ) => Filter.Simplified
+                                  (Filter.Filter_Bool
+                                  (Filter.Filter_GL b))
+ , ctx_input              :: [FilePath]
+ , ctx_input_format       :: Formats
+ , ctx_output             :: [(Write.Mode, FilePath)]
+ , ctx_output_format      :: Maybe Formats
+
+ -- , ctx_filter_gl          :: Filter.Simplified
+ --                             (Filter.Filter_Bool
+ --                             (Filter.Filter_GL
+ --                             ( (Account_Tags, Ledger.Account)
+ --                             , Date
+ --                             , (Ledger.Unit, Polarize.Polarized Ledger.Quantity)
+ --                             , (Ledger.Unit, Polarize.Polarized Ledger.Quantity) )))
+ -- , ctx_filter_posting     :: Filter.Simplified
+ --                             (Filter.Filter_Bool
+ --                             (Filter.Filter_Posting
+ --                             (Ledger.Charted Ledger.Posting)))
  , ctx_reduce_date        :: Bool
- } deriving (Show)
-
-nil :: Ctx
-nil =
-       Ctx
-        { ctx_filter_gl          = mempty
-        , ctx_filter_posting     = mempty
-        , ctx_filter_transaction = mempty
+ } -- deriving (Show)
+
+context :: Context
+context =
+       Context
+        { ctx_filter_gl          = Filter.Simplified $ Right True
+        -- , ctx_filter_posting     = Filter.Simplified $ Right True
+        , ctx_filter_transaction = Filter.Simplified $ Right True
         , ctx_input              = []
+        , ctx_input_format       = mempty
+        , ctx_output             = []
+        , ctx_output_format      = mempty
         , ctx_reduce_date        = True
         }
 
-usage :: IO String
-usage = do
+usage :: C.Context -> IO String
+usage = do
        bin <- Env.getProgName
        return $ unlines $
-               [ "SYNTAX "
-               , "  "++bin++" gl"
-               , " [-t TRANSACTION_FILTER]"
-               , " [-p POSTING_FILTER]"
-               , " [-g GL_FILTER]"
-               , " JOURNAL_FILE [...]"
+               [ C.translate c Lang.Section_Description
+               , "  "++C.translate c Lang.Help_Command_General_Ledger
                , ""
-               , usageInfo "OPTIONS" options
+               , C.translate c Lang.Section_Syntax
+               , "  "++bin++" gl ["++C.translate c Lang.Type_Option++"] [...]"++
+                               " ["++C.translate c Lang.Type_File_Journal++"] [...]"
+               , ""
+               , usageInfo (C.translate c Lang.Section_Options) (options c)
                ]
 
-options :: Args.Options Ctx
-options =
+options :: C.Context -> Args.Options Context
+options =
        [ Option "g" ["filter-gl"]
-        (ReqArg (\s context ctx -> do
-               ctx_filter_gl <-
-                       liftM (\t -> (<>) (ctx_filter_gl ctx)
-                        (Filter.simplify t (Nothing::Maybe ( Account
-                                                           , Date
-                                                           , Amount.Sum Amount
-                                                           , Amount.Sum Amount )))) $
-                               liftIO $ Filter.Read.read Filter.Read.test_gl s
-                               >>= \f -> case f of
-                                Left  ko -> Write.fatal context $ ko
-                                Right ok -> return ok
-               return $ ctx{ctx_filter_gl}) "FILTER")
-        "filter at general ledger level, multiple uses are merged with a logical AND"
-       , Option "p" ["filter-posting"]
-        (ReqArg (\s context ctx -> do
+        (ReqArg (\s ctx -> do
+               filter <-
+                       R.runParserT_with_Error
+                        Filter.Read.filter_gl
+                        Filter.Read.context "" s
+               case filter of
+                Left (ko::[R.Error Filter.Read.Error]) -> Write.fatal c ko
+                Right flt ->
+                       return $
+                               ctx{ctx_filter_gl =
+                                       Filter.and (ctx_filter_gl ctx) $
+                                       (Filter.simplify $
+                                               Filter.Read.get_Forall_Filter_GL_Decimal <$> flt)
+                                }) $
+               C.translate c Lang.Type_Filter_General_Ledger) $
+               C.translate c Lang.Help_Option_Filter_General_Ledger
+       {-, Option "p" ["filter-posting"]
+        (ReqArg (\s ctx -> do
                ctx_filter_posting <-
-                       liftM (\t -> (<>) (ctx_filter_posting ctx)
-                        (Filter.simplify t (Nothing::Maybe Ledger.Posting))) $
-                       liftIO $ Filter.Read.read Filter.Read.test_posting s
+                       liftM ((ctx_filter_posting ctx <>) . Filter.simplify) $
+                       liftIO $ Filter.Read.read Filter.Read.filter_posting s
                        >>= \f -> case f of
-                        Left  ko -> Write.fatal context $ ko
+                        Left  ko -> Write.fatal c $ ko
                         Right ok -> return ok
-               return $ ctx{ctx_filter_posting}) "FILTER")
-        "filter at posting level, multiple uses are merged with a logical AND"
+               return $ ctx{ctx_filter_posting}) $
+               C.translate c Lang.Type_Filter_Posting) $
+               C.translate c Lang.Help_Option_Filter_Posting
+       -}
        , Option "t" ["filter-transaction"]
-        (ReqArg (\s context ctx -> do
-               ctx_filter_transaction <-
-                       liftM (\t -> (<>) (ctx_filter_transaction ctx)
-                        (Filter.simplify t (Nothing::Maybe Ledger.Transaction))) $
-                       liftIO $ Filter.Read.read Filter.Read.test_transaction s
-                       >>= \f -> case f of
-                        Left  ko -> Write.fatal context $ ko
-                        Right ok -> return ok
-               return $ ctx{ctx_filter_transaction}) "FILTER")
-        "filter at transaction level, multiple uses are merged with a logical AND"
+        (ReqArg (\s ctx -> do
+               filter <-
+                       R.runParserT_with_Error
+                        Filter.Read.filter_transaction
+                        Filter.Read.context "" s
+               case filter of
+                Left ko -> Write.fatal c ko
+                Right flt ->
+                       return $
+                               ctx{ctx_filter_transaction =
+                                       Filter.and (ctx_filter_transaction ctx) $
+                                       (Filter.simplify $
+                                               Filter.Read.get_Forall_Filter_Transaction_Decimal <$> flt)
+                                }) $
+               C.translate c Lang.Type_Filter_Transaction) $
+               C.translate c Lang.Help_Option_Filter_Transaction
        , Option "h" ["help"]
-        (NoArg (\_context _ctx -> do
-               usage >>= IO.hPutStr IO.stderr
-               exitWith ExitSuccess))
-        "show this help"
+        (NoArg (\_ctx -> do
+               usage >>= IO.hPutStr IO.stderr
+               exitSuccess)) $
+               C.translate c Lang.Help_Option_Help
        , Option "i" ["input"]
-        (ReqArg (\s _context ctx -> do
-               return $ ctx{ctx_input=s:ctx_input ctx}) "JOURNAL_FILE")
-        "read data from given file, multiple uses merge the data as would a concatenation do"
+        (ReqArg (\s ctx -> do
+               return $ ctx{ctx_input=s:ctx_input ctx}) $
+               C.translate c Lang.Type_File_Journal) $
+               C.translate c Lang.Help_Option_Input
+       , Option "f" ["input-format"]
+        (OptArg (\arg ctx -> do
+               ctx_input_format <- case arg of
+                Nothing       -> return $ Format_JCC ()
+                Just "jcc"    -> return $ Format_JCC ()
+                Just "ledger" -> return $ Format_Ledger ()
+                Just _        -> Write.fatal c $
+                       W.text "--input-format option expects \"jcc\", or \"ledger\" as value"
+               return $ ctx{ctx_input_format})
+         "[jcc|ledger]")
+         "input format"
+       , Option "o" ["output"]
+        (ReqArg (\s ctx -> do
+               return $ ctx{ctx_output=(Write.Mode_Append, s):ctx_output ctx}) $
+               C.translate c Lang.Type_File) $
+               C.translate c Lang.Help_Option_Output
+       , Option "F" ["output-format"]
+        (ReqArg (\arg ctx -> do
+               ctx_output_format <- case arg of
+                "jcc"    -> return $ Just $ Format_JCC ()
+                "ledger" -> return $ Just $ Format_Ledger ()
+                _        -> Write.fatal c $
+                       W.text "--output-format option expects \"jcc\", or \"ledger\" as value"
+               return $ ctx{ctx_output_format})
+         "[jcc|ledger]") $
+               "output format"
+       , Option "O" ["overwrite"]
+        (ReqArg (\s ctx -> do
+               return $ ctx{ctx_output=(Write.Mode_Over, s):ctx_output ctx}) $
+               C.translate c Lang.Type_File) $
+               C.translate c Lang.Help_Option_Overwrite
+       {- NOTE: not used so far.
        , Option "" ["reduce-date"]
-        (OptArg (\arg context ctx -> do
+        (OptArg (\arg c ctx -> do
                ctx_reduce_date <- case arg of
                 Nothing    -> return $ True
                 Just "yes" -> return $ True
                 Just "no"  -> return $ False
-                Just _     -> Write.fatal context $
+                Just _     -> Write.fatal c $
                        W.text "--reduce-date option expects \"yes\", or \"no\" as value"
                return $ ctx{ctx_reduce_date})
          "[yes|no]")
         "use advanced date reducer to speed up filtering"
+       -}
        ]
 
-run :: Context.Context -> [String] -> IO ()
-run context args = do
-       (ctx, inputs) <- Args.parse context usage options (nil, args)
-       read_journals <- do
-               CLI.Ledger.paths context $ ctx_input ctx ++ inputs
+run :: C.Context -> [String] -> IO ()
+run c args = do
+       (ctx, inputs) <-
+               first (\x ->
+                       case ctx_output x of
+                        [] -> x{ctx_output=[(Write.Mode_Append, "-")]}
+                        _  -> x) <$>
+               Args.parse c usage options (context, args)
+       input_paths <- CLI.Env.paths c $ ctx_input ctx ++ inputs
+       read_journals <- mapM (liftIO . journal_read ctx) input_paths
+       case partitionEithers read_journals of
+        (errs@(_:_), _journals) -> Write.fatals c errs
+        ([], (journals::[Forall_Journal_GL])) -> do
+               let gl =
+                       mconcat $
+                       fmap Format.journal_flatten $
+                       case ctx_output_format ctx of
+                        Just f -> Format.journal_empty f:journals
+                        Nothing -> journals
+               with_color <- Write.with_color c IO.stdout
+               W.displayIO IO.stdout $
+                       W.renderPretty with_color 1.0 maxBound $
+                       toDoc () $ Leijen.Table.table_of (c, ctx) gl
+               {-
+               Write.debug c $ "filter: transaction: " ++ show (ctx_filter_transaction ctx)
+               Write.debug c $ "filter: posting: " ++ show (ctx_filter_posting ctx)
+               Write.debug c $ "filter: balance: " ++ show (ctx_filter_balance ctx)
+               -}
+
+instance Leijen.Table.Table_of (C.Context, Context) Forall_Journal_GL where
+       table_of (c, ctx) gl =
+               let lang = C.lang c in
+               zipWith id
+                [ Leijen.Table.column (Lang.translate lang Lang.Title_Account)         Leijen.Table.Align_Left
+                , Leijen.Table.column (Lang.translate lang Lang.Title_Date)            Leijen.Table.Align_Left
+                , Leijen.Table.column (Lang.translate lang Lang.Title_Debit)           Leijen.Table.Align_Right
+                , Leijen.Table.column (Lang.translate lang Lang.Title_Credit)          Leijen.Table.Align_Right
+                , Leijen.Table.column (Lang.translate lang Lang.Title_Running_debit)   Leijen.Table.Align_Right
+                , Leijen.Table.column (Lang.translate lang Lang.Title_Running_credit)  Leijen.Table.Align_Right
+                , Leijen.Table.column (Lang.translate lang Lang.Title_Running_balance) Leijen.Table.Align_Right
+                , Leijen.Table.column (Lang.translate lang Lang.Title_Description)     Leijen.Table.Align_Left
+                ] $
+               Format.journal_leijen_table_cells
+                (Format.journal_filter ctx $
+                       (Const::x -> Const x ()) gl) $
+               repeat []
+
+
+-- * 'GL.GL'
+
+-- ** Type 'Format_GL'
+
+type Format_Journal_GL
+ = Format
+   (   JCC.Journal GL_JCC)
+   (Ledger.Journal GL_Ledger)
+
+-- JCC
+type GL_JCC
+ = GL.GL (JCC.Charted JCC.Transaction)
+ -- = GL.GL JCC.Transaction
+instance Format.Journal (JCC.Journal GL_JCC) where
+       type Journal_Format   (JCC.Journal GL_JCC)
+        = Format_Journal_GL
+       journal_format = Format_JCC
+
+-- Ledger
+type GL_Ledger
+ -- = GL.GL Ledger.Transaction
+ = GL.GL (Ledger.Charted Ledger.Transaction)
+instance Format.Journal (Ledger.Journal GL_Ledger) where
+       type Journal_Format   (Ledger.Journal GL_Ledger)
+        = Format_Journal_GL
+       journal_format = Format_Ledger
+
+-- ** Class 'Journal'
+
+class
+ ( Format.Journal_Read j
+ , Ord (Account.Account_Section (Format.Journal_Account j))
+ , Leijen.Table.Cell_of_forall_param j
+    (TreeMap.Path (Account.Account_Section
+     (GL.Posting_Account (Format.Journal_Posting j))))
+ , Leijen.Table.Cell_of_forall_param j
+    (Format.Journal_Unit j, Format.Journal_Quantity j)
+ , Leijen.Table.Cell_of_forall_param j
+    (TreeMap.Path (Account.Account_Section (GL.Posting_Account
+     (Chart.Charted (Format.Journal_Account j)
+      (Format.Journal_Posting j)))))
+ , Polarize.Polarizable (Format.Journal_Quantity j)
+ ) => Journal j
+ where
+       journal_transaction_wording
+        :: forall m. j m
+        -> Format.Journal_Transaction j
+        -> Text
+       journal_posting_amounts
+        :: forall m. j m
+        -> Format.Journal_Posting j
+        -> Map (Format.Journal_Unit j)
+               (Format.Journal_Quantity j)
+       journal_posting_amounts_set
+        :: forall m. j m
+        -> Map (Format.Journal_Unit j)
+               (Format.Journal_Quantity j)
+        -> Format.Journal_Posting j
+        -> Format.Journal_Posting j
+
+instance Journal JCC.Journal
+ where
+       journal_transaction_wording _j = JCC.transaction_wording
+       journal_posting_amounts     _j = JCC.posting_amounts
+       journal_posting_amounts_set _j posting_amounts p =
+               p { JCC.posting_amounts }
+instance Journal Ledger.Journal
+ where
+       journal_transaction_wording _j = Ledger.transaction_wording
+       journal_posting_amounts     _j = Ledger.posting_amounts
+       journal_posting_amounts_set _j posting_amounts p =
+               p { Ledger.posting_amounts }
+
+-- ** Class 'Journal_GL'
+
+class
+ ( Format.Journal (j m)
+ , Format.Journal_Format (j m) ~ Format_Journal_GL
+ , Format.Journal_Read j
+ , Format.Journal_Monoid (j m)
+ , Format.Journal_Leijen_Table_Cells j m
+ , Format.Journal_Filter Context j m
+ ) => Journal_GL j m
+
+instance Journal_GL JCC.Journal    GL_JCC
+instance Journal_GL Ledger.Journal GL_Ledger
+
+-- ** Type 'Forall_Journal_GL'
+
+data    Forall_Journal_GL
+ = forall j m. Journal_GL  j m
+ =>     Forall_Journal_GL (j m)
+
+instance Format.Journal Forall_Journal_GL where
+       type Journal_Format   Forall_Journal_GL = Format_Journal_GL
+       journal_format
+        (Forall_Journal_GL j) =
+               Format.journal_format j
+instance Format.Journal_Empty Forall_Journal_GL where
+       journal_empty f =
+               case f of
+                Format_JCC    () -> Forall_Journal_GL (mempty::JCC.Journal GL_JCC)
+                Format_Ledger () -> Forall_Journal_GL (mempty::Ledger.Journal GL_Ledger)
+instance Format.Journal_Monoid Forall_Journal_GL where
+       journal_flatten
+        (Forall_Journal_GL j) =
+               Forall_Journal_GL $
+               Format.journal_flatten j
+       journal_fold f (Forall_Journal_GL j) =
+               Format.journal_fold (f . Forall_Journal_GL) j
+instance Monoid Forall_Journal_GL where
+       mempty = Forall_Journal_GL (mempty::JCC.Journal GL_JCC)
+       mappend x y =
+               case (mappend `on` Format.journal_format) x y of
+                Format_JCC    j -> Forall_Journal_GL j
+                Format_Ledger j -> Forall_Journal_GL j
+       mconcat js =
+               case js of
+                [] -> mempty
+                j:jn -> foldl' mappend j jn
+
+
+-- *** 'journal_read'
+
+type Journal_Filter_Simplified transaction
+ = Filter.Simplified
+   (Filter.Filter_Bool
+   (Filter.Filter_Transaction transaction))
+type Journal_Read_Cons txn
+ = txn -> Filter.Filtered (Journal_Filter_Simplified txn) txn
+journal_read
+ :: Context -> FilePath
+ -> IO (Either (Format.Message W.Doc) Forall_Journal_GL)
+journal_read ctx =
+       case ctx_input_format ctx of
+        Format_JCC () ->
+               let wrap (j::JCC.Journal GL_JCC)
+                        = Forall_Journal_GL j in
+               let cons :: Journal_Read_Cons (JCC.Charted JCC.Transaction)
+                        = Filter.Filtered (ctx_filter_transaction ctx) in
+               liftM ((+++) Format.Message wrap) .
+               Format.journal_read cons
+        Format_Ledger () ->
+               let wrap (j::Ledger.Journal GL_Ledger)
+                        = Forall_Journal_GL j in
+               let cons :: Journal_Read_Cons (Ledger.Charted Ledger.Transaction)
+                        = Filter.Filtered (ctx_filter_transaction ctx) in
+               liftM ((+++) Format.Message wrap) .
+               Format.journal_read cons
+
+
+-- Instances 'Format.Journal_Filter'
+
+instance
+ ( Functor j
+ , Format.Journal_Chart j
+ , Journal j
+ , Journal_GL j (GL.GL t)
+ , GL.Transaction t
+ , Format.Journal_Account_Section j ~ Text
+ , GL.Transaction_Posting t
+   ~ Chart.Charted (Format.Journal_Account j)
+                   (Format.Journal_Posting j)
+ , GL.Posting_Quantity (GL.Transaction_Posting t)
+   ~ Map (Format.Journal_Unit j)
+         (Polarized (Format.Journal_Quantity j))
+ , Format.Journal_Quantity j ~ Decimal
+ , Format.Journal_Account_Section j
+   ~ Account.Account_Section (GL.Posting_Account (GL.Transaction_Posting t))
+ , Ord (Format.Journal_Unit j)
+ , Unit.Unit (Format.Journal_Unit j)
+ ) => Format.Journal_Filter Context j (GL.GL t) where
+       journal_filter ctx j =
+               GL.GL .
+               TreeMap.map_Maybe_with_Path
+                (\acct expanded_lines ->
+                       let chart = Format.journal_chart j in
+                       case Map.mapMaybeWithKey
+                        (\date seq_lines ->
+                               case foldMap
+                                (\line@GL.GL_Line
+                                { GL.gl_line_transaction = _t
+                                , GL.gl_line_posting     = p
+                                , GL.gl_line_sum         = s
+                                } ->
+                                       Map.foldlWithKey
+                                        (\acc unit qty ->
+                                               let sqty = (Map.!) s unit in
+                                               if Filter.test (ctx_filter_gl ctx)
+                                                ( (Chart.account_tags acct chart, acct)
+                                                , date
+                                                , (unit, Polarize.polarize qty)
+                                                , (unit, sqty)
+                                                )
+                                               then (Seq.|>) acc line
+                                                { GL.gl_line_posting =
+                                                       journal_posting_amounts_set j
+                                                        (Map.singleton unit qty) <$> p
+                                                , GL.gl_line_sum = Map.singleton unit sqty
+                                                }
+                                               else acc
+                                        )
+                                        Seq.empty
+                                        (journal_posting_amounts j $ Chart.charted p)
+                                ) seq_lines
+                                of
+                                m | Seq.null m -> Nothing
+                                m -> Just m
+                        )
+                        (GL.inclusive expanded_lines)
+                        of
+                               m | Map.null m -> Strict.Nothing
+                               m -> Strict.Just m
+                ) .
+               (\(GL.Expanded gl) -> gl) .
+               GL.expanded <$> j
+instance Format.Journal_Filter Context (Const Forall_Journal_GL) () where
+       journal_filter ctx
+        (Const (Forall_Journal_GL j)) =
+               Const $ Forall_Journal_GL $
+               Format.journal_filter ctx j
+
+-- Instances 'Format.Journal_Leijen_Table_Cells'
+
+instance
+ ( Format.Journal_Content j
+ , Journal j
+ , Quantity.Addable (Format.Journal_Quantity j)
+ , GL.Transaction_Posting t
+   ~ Chart.Charted (Format.Journal_Account j)
+                   (Format.Journal_Posting j)
+ , Format.Journal_Transaction j ~ GL.Transaction_Line t
+ , GL.Posting_Quantity (Chart.Charted (Format.Journal_Account j)
+                       (Format.Journal_Posting j))
+   ~ Map (Format.Journal_Unit j)
+         (Polarized (Format.Journal_Quantity j))
+ , GL.Posting_Quantity (Format.Journal_Posting j)
+   ~ Map (Format.Journal_Unit j)
+         (Polarized (Format.Journal_Quantity j))
+ -- , GL.Posting_Account t ~ Format.Journal_Account j
+ -- , Leijen.Table.Cell_of_forall_param j (TreeMap.Path as)
+ , Leijen.Table.Cell_of_forall_param j Date
+ , Leijen.Table.Cell_of_forall_param j Text
+ , Ord (Format.Journal_Unit j)
+ , GL.Transaction t
+ ) => Format.Journal_Leijen_Table_Cells j (GL.GL t) where
+       journal_leijen_table_cells jnl =
+               flip (TreeMap.foldr_with_Path
+                (\account ->
+                       flip $ Map.foldrWithKey
+                        (\date ->
+                               flip $ foldr
+                                (\GL.GL_Line
+                                        { GL.gl_line_transaction = t
+                                        , GL.gl_line_posting     = p
+                                        , GL.gl_line_sum         = s
+                                        } ->
+                                       flip (Map.foldrWithKey
+                                        (\unit qty ->
+                                               let ms = Map.lookup unit s in
+                                               zipWith (:)
+                                                [ cell_of account
+                                                , cell_of date
+                                                , cell_of $ (unit,) <$> Polarize.polarizable_positive qty
+                                                , cell_of $ (unit,) <$> Polarize.polarizable_negative qty
+                                                , cell_of $ (unit,) <$> (ms >>= Polarize.polarized_positive)
+                                                , cell_of $ (unit,) <$> (ms >>= Polarize.polarized_negative)
+                                                , cell_of $ (unit,) . Polarize.depolarize <$> ms
+                                                , cell_of $ journal_transaction_wording jnl t
+                                                ]
+                                        ))
+                                        (journal_posting_amounts jnl $ Chart.charted p)
+                                )
+                        )
+                )) $
+                (\(GL.GL x) -> x)
+                (Format.journal_content jnl)
+               where
+                       cell_of :: Leijen.Table.Cell_of_forall_param j x => x -> Leijen.Table.Cell
+                       cell_of = Leijen.Table.cell_of_forall_param jnl
+
+instance Format.Journal_Leijen_Table_Cells (Const Forall_Journal_GL) () where
+       journal_leijen_table_cells
+        (Const (Forall_Journal_GL j)) =
+               Format.journal_leijen_table_cells j
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{-
+-- Instances GL.GL -> GL.Expanded
+
+instance
+ ( Functor j
+ , Journal_GL_Expanded j (GL.Expanded t)
+ -- NOTE: constraint from GL.expanded
+ , GL.Transaction t
+ ) => Format.Journal_Wrap (j (GL.GL t))
+                          Forall_Journal_GL_Expanded where
+       journal_wrap =
+               Forall_Journal_GL_Expanded .
+               fmap GL.expanded
+
+instance Format.Journal_Wrap Forall_Journal_GL
+                             Forall_Journal_GL_Expanded where
+       journal_wrap (Forall_Journal_GL j) = Format.journal_wrap j
+-}
+{-
+-- * 'GL.GL_Expanded'
+
+-- ** Type 'Format_GL_Expanded'
+
+type Format_Journal_GL_Expanded
+ = Format
+   (   JCC.Journal GL_Expanded_JCC)
+   (Ledger.Journal GL_Expanded_Ledger)
+
+-- JCC
+type GL_Expanded_JCC
+ = GL.Expanded (JCC.Charted JCC.Transaction)
+instance Format.Journal (JCC.Journal GL_Expanded_JCC) where
+       type Journal_Format   (JCC.Journal GL_Expanded_JCC)
+        = Format_Journal_GL_Expanded
+       journal_format = Format_JCC
+
+-- Ledger
+type GL_Expanded_Ledger
+ = GL.Expanded (Ledger.Charted Ledger.Transaction)
+instance Format.Journal (Ledger.Journal GL_Expanded_Ledger) where
+       type Journal_Format   (Ledger.Journal GL_Expanded_Ledger)
+        = Format_Journal_GL_Expanded
+       journal_format = Format_Ledger
+
+-- ** Class 'Journal_GL_Expanded'
+
+class
+ ( Format.Journal (j m)
+ , Format.Journal_Format (j m) ~ Format_Journal_GL_Expanded
+ -- , Format.Journal_Leijen_Table_Cells j m
+ , Format.Journal_Filter Context j m
+ ) => Journal_GL_Expanded j m where
+       journal_posting_amounts
+        :: j m
+        -> Format.Journal_Posting j
+        -> Map (Format.Journal_Unit j)
+               (Format.Journal_Quantity j)
+       journal_posting_amounts_set
+        :: j m
+        -> Map (Format.Journal_Unit j)
+               (Format.Journal_Quantity j)
+        -> Format.Journal_Posting j
+        -> Format.Journal_Posting j
+
+instance Journal_GL_Expanded    JCC.Journal GL_Expanded_JCC
+ where
+       journal_posting_amounts     _j = JCC.posting_amounts
+       journal_posting_amounts_set _j posting_amounts p =
+               p { JCC.posting_amounts }
+instance Journal_GL_Expanded Ledger.Journal GL_Expanded_Ledger
+ where
+       journal_posting_amounts     _j = Ledger.posting_amounts
+       journal_posting_amounts_set _j posting_amounts p =
+               p { Ledger.posting_amounts }
+
+-- ** Type 'Forall_Journal_GL_Expanded'
+
+data    Forall_Journal_GL_Expanded
+ = forall j m. Journal_GL_Expanded  j m
+ =>     Forall_Journal_GL_Expanded (j m)
+
+instance Format.Journal Forall_Journal_GL_Expanded where
+       type Journal_Format   Forall_Journal_GL_Expanded = Format_Journal_GL_Expanded
+       journal_format
+        (Forall_Journal_GL_Expanded j) =
+               Format.journal_format j
+
+-- Instances 'Format.Journal_Filter'
+
+instance
+ ( Functor j
+ , Format.Journal_Chart j
+ , Journal_GL_Expanded j (GL.Expanded t)
+ , GL.Transaction t
+ , Format.Journal_Account_Section j ~ Text
+ , GL.Transaction_Posting t ~ Chart.Charted (Format.Journal_Account j) (Format.Journal_Posting j)
+ , GL.Posting_Quantity (GL.Transaction_Posting t)
+   ~ Map (Format.Journal_Unit j) (Polarized (Format.Journal_Quantity j))
+ , Format.Journal_Quantity j ~ Decimal
+ , Format.Journal_Account_Section j
+   ~ Account.Account_Section (GL.Posting_Account (GL.Transaction_Posting t))
+ , Ord (Format.Journal_Unit j)
+ , Unit.Unit (Format.Journal_Unit j)
+ ) => Format.Journal_Filter Context j (GL.Expanded t) where
+       journal_filter ctx j =
+               GL.Expanded .
+               TreeMap.map_Maybe_with_Path
+                (\acct expanded_lines ->
+                       let chart = Format.journal_chart j in
+                       case Map.mapMaybeWithKey
+                        (\date seq_lines ->
+                               case foldMap
+                                (\line@GL.GL_Line
+                                { GL.gl_line_transaction = _t
+                                , GL.gl_line_posting     = Chart.Charted ch p
+                                , GL.gl_line_sum         = s
+                                } ->
+                                       Map.foldlWithKey
+                                        (\acc unit qty ->
+                                               let sqty = (Map.!) s unit in
+                                               if Filter.test (ctx_filter_gl ctx)
+                                                ( (Chart.account_tags acct chart, acct)
+                                                , date
+                                                , (unit, Polarize.polarize qty)
+                                                , (unit, sqty)
+                                                )
+                                               then (Seq.|>) acc line
+                                                { GL.gl_line_posting =
+                                                       Chart.Charted ch $
+                                                       journal_posting_amounts_set j
+                                                        (Map.singleton unit qty) p
+                                                , GL.gl_line_sum = Map.singleton unit sqty
+                                                }
+                                               else acc
+                                        )
+                                        Seq.empty
+                                        (journal_posting_amounts j p)
+                                ) seq_lines
+                                of
+                                m | Seq.null m -> Nothing
+                                m -> Just m
+                        )
+                        (GL.inclusive expanded_lines)
+                        of
+                               m | Map.null m -> Strict.Nothing
+                               m -> Strict.Just $ expanded_lines { GL.inclusive=m }
+                ) .
+               (\(GL.Expanded gl) -> gl) <$> j
+
+instance Format.Journal_Filter Context (Const Forall_Journal_GL_Expanded) () where
+       journal_filter ctx
+        (Const (Forall_Journal_GL_Expanded j)) =
+               Const $ Forall_Journal_GL_Expanded $
+               Format.journal_filter ctx j
+-}
+
+{-
+run :: C.Context -> [String] -> IO ()
+run c args = do
+       (ctx, inputs) <-
+               first (\x ->
+                       case ctx_output x of
+                        [] -> x{ctx_output=[(Write.Mode_Append, "-")]}
+                        _  -> x) <$>
+               Args.parse c usage options (context, args)
+       read_journals <-
+               liftM partitionEithers $ do
+               CLI.Env.paths c $ ctx_input ctx ++ inputs
                >>= do
                        mapM $ \path -> do
-                               liftIO $ runExceptT $ Ledger.Read.file path
+                               liftIO $ runExceptT $ Ledger.Read.file
+                                (Ledger.Read.context ( ctx_filter_transaction ctx
+                                                     , ctx_filter_posting     ctx )
+                                                     Ledger.journal)
+                                path
                                >>= \x -> case x of
                                 Left  ko -> return $ Left (path, ko)
                                 Right ok -> return $ Right ok
-               >>= return . Data.Either.partitionEithers
        case read_journals of
         (errs@(_:_), _journals) ->
-               (flip mapM_) errs $ \(_path, err) -> do
-                       Write.fatal context $ err
+               forM_ errs $ \(_path, err) -> do
+                       Write.fatal c $ err
         ([], journals) -> do
-               Write.debug context $ "filter: transaction: " ++ show (ctx_filter_transaction ctx)
-               Write.debug context $ "filter: posting: " ++ show (ctx_filter_posting ctx)
-               Write.debug context $ "filter: gl: " ++ show (ctx_filter_gl ctx)
-               let gl = ledger_gl ctx journals
-               style_color <- Write.with_color context IO.stdout
-               W.displayIO IO.stdout $
-                W.renderPretty style_color 1.0 maxBound $ do
-                       toDoc () $
-                               let title =
-                                       TL.toStrict . W.displayT .
-                                       W.renderCompact False .
-                                       toDoc (Context.lang context) in
-                               zipWith id
-                               [ Table.column (title Lang.Message_Account)         Table.Align_Left
-                               , Table.column (title Lang.Message_Date)            Table.Align_Left
-                               , Table.column (title Lang.Message_Debit)           Table.Align_Right
-                               , Table.column (title Lang.Message_Credit)          Table.Align_Right
-                               , Table.column (title Lang.Message_Running_debit)   Table.Align_Right
-                               , Table.column (title Lang.Message_Running_credit)  Table.Align_Right
-                               , Table.column (title Lang.Message_Running_balance) Table.Align_Right
-                               , Table.column (title Lang.Message_Description)     Table.Align_Left
-                               ] $
-                               write_gl gl (repeat [])
+               Write.debug c $ "filter: transaction: " ++ show (ctx_filter_transaction ctx)
+               Write.debug c $ "filter: posting: " ++ show (ctx_filter_posting ctx)
+               Write.debug c $ "filter: gl: " ++ show (ctx_filter_gl ctx)
+               let (amount_styles, gl) = ledger_gl ctx journals
+               let lang = C.lang c
+               Write.write c Write.style (ctx_output ctx) $ do
+               toDoc () $ do
+               zipWith id
+                [ Table.column (Lang.translate lang Lang.Title_Account)         Table.Align_Left
+                , Table.column (Lang.translate lang Lang.Title_Date)            Table.Align_Left
+                , Table.column (Lang.translate lang Lang.Title_Debit)           Table.Align_Right
+                , Table.column (Lang.translate lang Lang.Title_Credit)          Table.Align_Right
+                , Table.column (Lang.translate lang Lang.Title_Running_debit)   Table.Align_Right
+                , Table.column (Lang.translate lang Lang.Title_Running_credit)  Table.Align_Right
+                , Table.column (Lang.translate lang Lang.Title_Running_balance) Table.Align_Right
+                , Table.column (Lang.translate lang Lang.Title_Description)     Table.Align_Left
+                ] $ do
+               write_gl amount_styles gl (repeat [])
+-}
 
+{-
 ledger_gl
- :: Ctx
- -> [Ledger.Journal]
- -> GL Ledger.Transaction
+ :: Context
+ -> [ Ledger.Journal (GL.GL (Ledger.Charted Ledger.Transaction)) ]
+ -> ( Ledger.Amount.Styles
+    , GL (Ledger.Charted Ledger.Transaction)
+    )
 ledger_gl ctx journals =
-       let reducer_date =
-               if ctx_reduce_date ctx
-               then Filter.Reduce.bool_date <$> ctx_filter_transaction ctx
-               else mempty in
-       let gl =
-               Data.Foldable.foldl'
-                (flip $ Ledger.Journal.fold
-                        (\Ledger.Journal{Ledger.journal_transactions=ts} ->
-                               flip (Data.Foldable.foldl'
-                                (flip $ (\t ->
-                                       case Filter.test (ctx_filter_transaction ctx) t of
-                                        False -> id
-                                        True ->
-                                               GL.general_ledger
-                                                t{ Ledger.transaction_postings =
-                                                       Data.Map.map
-                                                        (Data.Foldable.foldMap
-                                                                (\p ->
-                                                                       Data.Map.foldrWithKey
-                                                                        (\u a -> (:) p{Ledger.posting_amounts=Data.Map.singleton u a})
-                                                                        []
-                                                                        (Ledger.posting_amounts p)
-                                                                )
-                                                        ) $
-                                                       Data.Map.mapMaybe
-                                                        (\ps -> case Data.List.filter
-                                                                (Filter.test $ ctx_filter_posting ctx) ps of
-                                                                [] -> Nothing
-                                                                x  -> Just x)
-                                                        (Ledger.transaction_postings t)
-                                                }
-                                ))) $ Compose $ Compose $
-                               case Filter.simplified reducer_date of
-                                Left reducer -> do
-                                       let (ts_reduced, _date_sieve) = Filter.Reduce.map_date reducer ts
-                                       ts_reduced
-                                Right True  -> ts:[]
-                                Right False -> []
-                        )
-                )
-                GL.nil
-                journals in
+       let (_chart, amount_styles, gl) =
+               foldl'
+                (flip (\j ->
+                       flip mappend $
+                       ( Ledger.journal_chart j
+                       , Ledger.journal_amount_styles j
+                       , ) $
+                       Ledger.Journal.fold
+                        (\Ledger.Journal
+                                { Ledger.journal_sections=g
+                                } -> mappend g
+                        ) j mempty
+                ))
+                mempty journals in
+       (amount_styles,) $
        GL.GL $
-       Lib.TreeMap.map_Maybe_with_Path
+       TreeMap.map_Maybe_with_Path
         (\acct expanded_lines ->
-               case Data.Map.mapMaybeWithKey
+               case Map.mapMaybeWithKey
                 (\date seq_lines ->
-                       case Data.Foldable.foldMap
+                       case foldMap
                         (\line@GL.GL_Line
                         { GL.gl_line_transaction = _t
-                        , GL.gl_line_posting     = p
+                        , GL.gl_line_posting     = Ledger.Charted c p
                         , GL.gl_line_sum         = s
                         } ->
-                               if Filter.test (ctx_filter_gl ctx)
-                                ( acct
-                                , date
-                                , Amount.sum $ snd $ Data.Map.elemAt 0 $ Ledger.posting_amounts p
-                                , snd . Data.Map.elemAt 0 <$> s
+                               Map.foldlWithKey
+                                (\acc unit qty ->
+                                       let sqty = (Map.!) s unit in
+                                       if Filter.test (ctx_filter_gl ctx)
+                                        ( (Chart.account_tags acct c, acct)
+                                        , date
+                                        , (unit, Polarize.polarize qty)
+                                        , (unit, sqty)
+                                        )
+                                       then (Seq.|>) acc line
+                                        { GL.gl_line_posting = Ledger.Charted c p
+                                                { Ledger.posting_amounts = Map.singleton unit qty }
+                                        , GL.gl_line_sum = Map.singleton unit sqty
+                                        }
+                                       else acc
                                 )
-                               then Data.Sequence.singleton line
-                               else Data.Sequence.empty
+                                Seq.empty
+                                (Ledger.posting_amounts p)
                         ) seq_lines of
-                        m | Data.Sequence.null m -> Nothing
+                        m | Seq.null m -> Nothing
                         m -> Just m
                 )
                 (GL.inclusive expanded_lines) of
-                       m | Data.Map.null m -> Nothing
-                       m -> Just m
+                       m | Map.null m -> Strict.Nothing
+                       m -> Strict.Just m
                ) $
        GL.expanded gl
 
 write_gl
- :: GL Ledger.Transaction
+ :: Ledger.Amount.Styles
+ -> GL (Ledger.Charted Ledger.Transaction)
  -> [[Table.Cell]]
  -> [[Table.Cell]]
-write_gl (GL gl) =
-       flip (Lib.TreeMap.foldr_with_Path
+write_gl amount_styles (GL gl) =
+       flip (TreeMap.foldr_with_Path
         (\acct ->
-               flip $ Data.Map.foldrWithKey
+               flip $ Map.foldrWithKey
                 (\date ->
-                       flip (Data.Foldable.foldr
+                       flip (foldr
                         (\GL.GL_Line
-                                { GL.gl_line_transaction = t
-                                , GL.gl_line_posting     = p
+                                { GL.gl_line_transaction = Ledger.Charted _ t
+                                , GL.gl_line_posting     = Ledger.Charted _ p
                                 , GL.gl_line_sum         = s
                                 } ->
-                               flip (Data.Map.foldrWithKey
-                                (\unit amt -> do
-                                       let ptype = Ledger.Posting_Type_Regular
-                                       let descr = Ledger.transaction_description t
+                               flip (Map.foldrWithKey
+                                (\unit qty ->
+                                       let ms = Map.lookup unit s in
                                        zipWith (:)
-                                               [ Table.cell
-                                                { Table.cell_content = Ledger.Write.account        ptype acct
-                                                , Table.cell_width   = Ledger.Write.account_length ptype acct
-                                                }
+                                               [ let ptype = Ledger.Posting_Type_Regular in
+                                                       Table.cell
+                                                        { Table.cell_content = Ledger.Write.account        ptype acct
+                                                        , Table.cell_width   = Ledger.Write.account_length ptype acct
+                                                        }
                                                , Table.cell
                                                 { Table.cell_content = Date.Write.date        date
                                                 , Table.cell_width   = Date.Write.date_length date
                                                 }
-                                               , Table.cell
-                                                { Table.cell_content = maybe W.empty Amount.Write.amount        (Amount.sumable_positive amt)
-                                                , Table.cell_width   = maybe 0       Amount.Write.amount_length (Amount.sumable_positive amt)
-                                                }
-                                               , Table.cell
-                                                { Table.cell_content = maybe W.empty Amount.Write.amount        (Amount.sumable_negative amt)
-                                                , Table.cell_width   = maybe 0       Amount.Write.amount_length (Amount.sumable_negative amt)
-                                                }
-                                               , Table.cell
-                                                { Table.cell_content = maybe W.empty Amount.Write.amount        (maybe Nothing (Data.Map.lookup unit) $ Amount.sum_positive s)
-                                                , Table.cell_width   = maybe 0       Amount.Write.amount_length (maybe Nothing (Data.Map.lookup unit) $ Amount.sum_positive s)
-                                                }
-                                               , Table.cell
-                                                { Table.cell_content = maybe W.empty Amount.Write.amount        (maybe Nothing (Data.Map.lookup unit) $ Amount.sum_negative s)
-                                                , Table.cell_width   = maybe 0       Amount.Write.amount_length (maybe Nothing (Data.Map.lookup unit) $ Amount.sum_negative s)
-                                                }
-                                               , Table.cell
-                                                { Table.cell_content = maybe W.empty Amount.Write.amount        (Data.Map.lookup unit $ Amount.sum_balance s)
-                                                , Table.cell_width   = maybe 0       Amount.Write.amount_length (Data.Map.lookup unit $ Amount.sum_balance s)
-                                                }
-                                               , Table.cell
-                                                { Table.cell_content = toDoc ()    descr
-                                                , Table.cell_width   = Text.length descr
-                                                }
+                                               , cell_amount unit (Polarize.polarizable_positive qty)
+                                               , cell_amount unit (Polarize.polarizable_negative qty)
+                                               , cell_amount unit (ms >>= Polarize.polarized_positive)
+                                               , cell_amount unit (ms >>= Polarize.polarized_negative)
+                                               , cell_amount unit (liftM Polarize.depolarize ms)
+                                               , let descr = Ledger.transaction_wording t in
+                                                       Table.cell
+                                                        { Table.cell_content = toDoc ()    descr
+                                                        , Table.cell_width   = Text.length descr
+                                                        }
                                                ]
                                 ))
                                 (Ledger.posting_amounts p)
@@ -332,3 +910,16 @@ write_gl (GL gl) =
                 )
         ))
         gl
+       where
+               cell_amount :: Ledger.Unit -> Maybe Ledger.Quantity -> Table.Cell
+               cell_amount unit mq =
+                       case mq of
+                        Nothing -> Table.cell
+                        Just q ->
+                               let a  = Ledger.Amount.Amount unit q in
+                               let sa = Ledger.Amount.style amount_styles a in
+                               Table.cell
+                                { Table.cell_content = Amount.Write.amount        sa
+                                , Table.cell_width   = Amount.Write.amount_length sa
+                                }
+-}