journal: account directives can declare account types
Previously you had to use one of the standard english account names (assets, liabilities..) for top-level accounts, if you wanted to use the bs/bse/cf/is commands. Now, account directives can specify which of the big five categories an account belongs to - asset, liability, equity, revenue or expense - by writing one of the letters A, L, E, R or X two or more spaces after the account name (where the numeric account code used to be). This might change. Some thoughts influencing the current syntax: - easy to type and read - does not require multiple lines - does not depend on any particular account numbering scheme - allows more types later if needed - still anglocentric, but only a little - could be treated as syntactic sugar for account tags later - seems to be compatible with (ignored by) current Ledger The current design permits unlimited account type declarations anywhere in the account tree. So you could declare a liability account somewhere under assets, and maybe a revenue account under that, and another asset account even further down. In such cases you start to see oddities like accounts appearing in multiple places in a tree-mode report. In theory the reports will still behave reasonably, but this has not been tested too hard. In any case this is clearly too much freedom. I have left it this way, for now, in case it helps with: - modelling contra accounts ? - multiple files. I suspect the extra expressiveness may come in handy when combining multiple files with account type declarations, rewriting account names, apply parent accounts etc. If we only allowed type declarations on top-level accounts, or only allowed a single account of each type, complications seem likely.
This commit is contained in:
		
							parent
							
								
									678e8c28e4
								
							
						
					
					
						commit
						c1236fa6e9
					
				| @ -162,16 +162,17 @@ instance Sem.Semigroup Journal where | |||||||
|     ,jparseparentaccounts       = jparseparentaccounts       j2 |     ,jparseparentaccounts       = jparseparentaccounts       j2 | ||||||
|     ,jparsealiases              = jparsealiases              j2 |     ,jparsealiases              = jparsealiases              j2 | ||||||
|     -- ,jparsetransactioncount     = jparsetransactioncount     j1 +  jparsetransactioncount     j2 |     -- ,jparsetransactioncount     = jparsetransactioncount     j1 +  jparsetransactioncount     j2 | ||||||
|     ,jparsetimeclockentries = jparsetimeclockentries j1 <> jparsetimeclockentries j2 |     ,jparsetimeclockentries     = jparsetimeclockentries j1 <> jparsetimeclockentries j2 | ||||||
|     ,jincludefilestack          = jincludefilestack          j2 |     ,jincludefilestack          = jincludefilestack          j2 | ||||||
|     ,jdeclaredaccounts                  = jdeclaredaccounts                  j1 <> jdeclaredaccounts                  j2 |     ,jdeclaredaccounts          = jdeclaredaccounts          j1 <> jdeclaredaccounts          j2 | ||||||
|  |     ,jdeclaredaccounttypes      = jdeclaredaccounttypes      j1 <> jdeclaredaccounttypes      j2 | ||||||
|     ,jcommodities               = jcommodities               j1 <> jcommodities               j2 |     ,jcommodities               = jcommodities               j1 <> jcommodities               j2 | ||||||
|     ,jinferredcommodities       = jinferredcommodities       j1 <> jinferredcommodities       j2 |     ,jinferredcommodities       = jinferredcommodities       j1 <> jinferredcommodities       j2 | ||||||
|     ,jmarketprices              = jmarketprices              j1 <> jmarketprices              j2 |     ,jmarketprices              = jmarketprices              j1 <> jmarketprices              j2 | ||||||
|     ,jtxnmodifiers              = jtxnmodifiers              j1 <> jtxnmodifiers              j2 |     ,jtxnmodifiers              = jtxnmodifiers              j1 <> jtxnmodifiers              j2 | ||||||
|     ,jperiodictxns              = jperiodictxns              j1 <> jperiodictxns              j2 |     ,jperiodictxns              = jperiodictxns              j1 <> jperiodictxns              j2 | ||||||
|     ,jtxns                      = jtxns                      j1 <> jtxns                      j2 |     ,jtxns                      = jtxns                      j1 <> jtxns                      j2 | ||||||
|     ,jfinalcommentlines         = jfinalcommentlines         j2 |     ,jfinalcommentlines         = jfinalcommentlines         j2  -- XXX discards j1's ? | ||||||
|     ,jfiles                     = jfiles                     j1 <> jfiles                     j2 |     ,jfiles                     = jfiles                     j1 <> jfiles                     j2 | ||||||
|     ,jlastreadtime              = max (jlastreadtime j1) (jlastreadtime j2) |     ,jlastreadtime              = max (jlastreadtime j1) (jlastreadtime j2) | ||||||
|     } |     } | ||||||
| @ -193,8 +194,9 @@ nulljournal = Journal { | |||||||
|   ,jparsetimeclockentries     = [] |   ,jparsetimeclockentries     = [] | ||||||
|   ,jincludefilestack          = [] |   ,jincludefilestack          = [] | ||||||
|   ,jdeclaredaccounts          = [] |   ,jdeclaredaccounts          = [] | ||||||
|   ,jcommodities               = M.fromList [] |   ,jdeclaredaccounttypes      = M.empty | ||||||
|   ,jinferredcommodities       = M.fromList [] |   ,jcommodities               = M.empty | ||||||
|  |   ,jinferredcommodities       = M.empty | ||||||
|   ,jmarketprices              = [] |   ,jmarketprices              = [] | ||||||
|   ,jtxnmodifiers              = [] |   ,jtxnmodifiers              = [] | ||||||
|   ,jperiodictxns              = [] |   ,jperiodictxns              = [] | ||||||
|  | |||||||
| @ -113,7 +113,26 @@ instance Default Interval where def = NoInterval | |||||||
| instance NFData Interval | instance NFData Interval | ||||||
| 
 | 
 | ||||||
| type AccountName = Text | type AccountName = Text | ||||||
| type AccountCode = Int | 
 | ||||||
|  | data AccountType = | ||||||
|  |     Asset | ||||||
|  |   | Liability | ||||||
|  |   | Equity | ||||||
|  |   | Revenue | ||||||
|  |   | Expense | ||||||
|  |   deriving (Show,Eq,Ord,Data,Generic) | ||||||
|  | 
 | ||||||
|  | instance NFData AccountType | ||||||
|  | 
 | ||||||
|  | -- not worth the trouble, letters defined in accountdirectivep for now | ||||||
|  | --instance Read AccountType | ||||||
|  | --  where | ||||||
|  | --    readsPrec _ ('A' : xs) = [(Asset,     xs)] | ||||||
|  | --    readsPrec _ ('L' : xs) = [(Liability, xs)] | ||||||
|  | --    readsPrec _ ('E' : xs) = [(Equity,    xs)] | ||||||
|  | --    readsPrec _ ('R' : xs) = [(Revenue,   xs)] | ||||||
|  | --    readsPrec _ ('X' : xs) = [(Expense,   xs)] | ||||||
|  | --    readsPrec _ _ = [] | ||||||
| 
 | 
 | ||||||
| data AccountAlias = BasicAlias AccountName AccountName | data AccountAlias = BasicAlias AccountName AccountName | ||||||
|                   | RegexAlias Regexp Replacement |                   | RegexAlias Regexp Replacement | ||||||
| @ -369,6 +388,7 @@ data Journal = Journal { | |||||||
|   ,jincludefilestack      :: [FilePath] |   ,jincludefilestack      :: [FilePath] | ||||||
|   -- principal data |   -- principal data | ||||||
|   ,jdeclaredaccounts      :: [AccountName]                          -- ^ Accounts declared by account directives, in parse order (after journal finalisation)  |   ,jdeclaredaccounts      :: [AccountName]                          -- ^ Accounts declared by account directives, in parse order (after journal finalisation)  | ||||||
|  |   ,jdeclaredaccounttypes  :: M.Map AccountType [AccountName]        -- ^ Accounts whose type has been declared in account directives (usually 5 top-level accounts)  | ||||||
|   ,jcommodities           :: M.Map CommoditySymbol Commodity        -- ^ commodities and formats declared by commodity directives |   ,jcommodities           :: M.Map CommoditySymbol Commodity        -- ^ commodities and formats declared by commodity directives | ||||||
|   ,jinferredcommodities   :: M.Map CommoditySymbol AmountStyle      -- ^ commodities and formats inferred from journal amounts  TODO misnamed - jusedstyles |   ,jinferredcommodities   :: M.Map CommoditySymbol AmountStyle      -- ^ commodities and formats inferred from journal amounts  TODO misnamed - jusedstyles | ||||||
|   ,jmarketprices          :: [MarketPrice] |   ,jmarketprices          :: [MarketPrice] | ||||||
|  | |||||||
| @ -43,6 +43,7 @@ module Hledger.Read.Common ( | |||||||
|   getDefaultAmountStyle, |   getDefaultAmountStyle, | ||||||
|   getAmountStyle, |   getAmountStyle, | ||||||
|   pushDeclaredAccount, |   pushDeclaredAccount, | ||||||
|  |   addDeclaredAccountType, | ||||||
|   pushParentAccount, |   pushParentAccount, | ||||||
|   popParentAccount, |   popParentAccount, | ||||||
|   getParentAccount, |   getParentAccount, | ||||||
| @ -311,6 +312,10 @@ getAmountStyle commodity = do | |||||||
| pushDeclaredAccount :: AccountName -> JournalParser m () | pushDeclaredAccount :: AccountName -> JournalParser m () | ||||||
| pushDeclaredAccount acct = modify' (\j -> j{jdeclaredaccounts = acct : jdeclaredaccounts j}) | pushDeclaredAccount acct = modify' (\j -> j{jdeclaredaccounts = acct : jdeclaredaccounts j}) | ||||||
| 
 | 
 | ||||||
|  | addDeclaredAccountType :: AccountName -> AccountType -> JournalParser m () | ||||||
|  | addDeclaredAccountType acct atype =  | ||||||
|  |   modify' (\j -> j{jdeclaredaccounttypes = M.insertWith (++) atype [acct] (jdeclaredaccounttypes j)}) | ||||||
|  | 
 | ||||||
| pushParentAccount :: AccountName -> JournalParser m () | pushParentAccount :: AccountName -> JournalParser m () | ||||||
| pushParentAccount acct = modify' (\j -> j{jparseparentaccounts = acct : jparseparentaccounts j}) | pushParentAccount acct = modify' (\j -> j{jparseparentaccounts = acct : jparseparentaccounts j}) | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -69,6 +69,7 @@ import Control.Monad | |||||||
| import Control.Monad.Except (ExceptT(..)) | import Control.Monad.Except (ExceptT(..)) | ||||||
| import Control.Monad.State.Strict | import Control.Monad.State.Strict | ||||||
| import Data.Bifunctor (first) | import Data.Bifunctor (first) | ||||||
|  | import Data.Maybe | ||||||
| import qualified Data.Map.Strict as M | import qualified Data.Map.Strict as M | ||||||
| import Data.Text (Text) | import Data.Text (Text) | ||||||
| import Data.String | import Data.String | ||||||
| @ -257,10 +258,29 @@ accountdirectivep :: JournalParser m () | |||||||
| accountdirectivep = do | accountdirectivep = do | ||||||
|   string "account" |   string "account" | ||||||
|   lift (skipSome spacenonewline) |   lift (skipSome spacenonewline) | ||||||
|   acct <- modifiedaccountnamep  -- account directives can be modified by alias/apply account |   -- the account name, possibly modified by preceding alias or apply account directives | ||||||
|   _ :: Maybe String <- (optional $ lift $ skipSome spacenonewline >> some digitChar)  -- compatibility: ignore account codes supported in 1.9/1.10 |   acct <- modifiedaccountnamep | ||||||
|  |   -- and maybe something else after two or more spaces ? | ||||||
|  |   matype :: Maybe AccountType <- lift $ fmap (fromMaybe Nothing) $ optional $ do | ||||||
|  |     skipSome spacenonewline -- at least one more space in addition to the one consumed by modifiedaccountp  | ||||||
|  |     choice [ | ||||||
|  |       -- a numeric account code, as supported in 1.9-1.10 ? currently ignored | ||||||
|  |        some digitChar >> return Nothing | ||||||
|  |       -- a letter account type code (ALERX), as added in 1.11 ? | ||||||
|  |       ,char 'A' >> return (Just Asset)  | ||||||
|  |       ,char 'L' >> return (Just Liability)  | ||||||
|  |       ,char 'E' >> return (Just Equity)  | ||||||
|  |       ,char 'R' >> return (Just Revenue)  | ||||||
|  |       ,char 'X' >> return (Just Expense)  | ||||||
|  |       ] | ||||||
|   newline |   newline | ||||||
|  |   -- Ledger-style indented subdirectives on following lines ? ignore | ||||||
|   skipMany indentedlinep |   skipMany indentedlinep | ||||||
|  | 
 | ||||||
|  |   -- update the journal | ||||||
|  |   case matype of | ||||||
|  |     Nothing    -> return () | ||||||
|  |     Just atype -> addDeclaredAccountType acct atype | ||||||
|   pushDeclaredAccount acct |   pushDeclaredAccount acct | ||||||
| 
 | 
 | ||||||
| indentedlinep :: JournalParser m String | indentedlinep :: JournalParser m String | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user