journal: account types: add Cash, tweak fallback regexp, rewrite docs
This commit is contained in:
		
							parent
							
								
									30f02b0882
								
							
						
					
					
						commit
						fd9171df07
					
				| @ -296,29 +296,6 @@ journalAccountNameTree = accountNameTreeFrom . journalAccountNames | ||||
| 
 | ||||
| -- queries for standard account types | ||||
| 
 | ||||
| -- | Get a query for accounts of a certain type (Asset, Liability..) in this journal. | ||||
| -- The query will match all accounts which were declared as that type by account directives, | ||||
| -- plus all their subaccounts which have not been declared as a different type. | ||||
| -- If no accounts were declared as this type, the query will instead match accounts | ||||
| -- with names matched by the provided case-insensitive regular expression. | ||||
| journalAccountTypeQuery :: AccountType -> Regexp -> Journal -> Query | ||||
| journalAccountTypeQuery atype fallbackregex j = | ||||
|   case M.lookup atype (jdeclaredaccounttypes j) of | ||||
|     Nothing -> Acct fallbackregex | ||||
|     Just as -> | ||||
|       -- XXX Query isn't able to match account type since that requires extra info from the journal. | ||||
|       -- So we do a hacky search by name instead. | ||||
|       And [ | ||||
|          Or $ map (Acct . accountNameToAccountRegex) as | ||||
|         ,Not $ Or $ map (Acct . accountNameToAccountRegex) differentlytypedsubs | ||||
|         ] | ||||
|       where | ||||
|         differentlytypedsubs = concat | ||||
|           [subs | (t,bs) <- M.toList (jdeclaredaccounttypes j) | ||||
|               , t /= atype | ||||
|               , let subs = [b | b <- bs, any (`isAccountNamePrefixOf` b) as] | ||||
|           ] | ||||
| 
 | ||||
| -- | A query for accounts in this journal which have been | ||||
| -- declared as Asset by account directives, or otherwise for | ||||
| -- accounts with names matched by the case-insensitive regular expression | ||||
| @ -369,12 +346,43 @@ journalProfitAndLossAccountQuery j = Or [journalRevenueAccountQuery j | ||||
|                                         ,journalExpenseAccountQuery j | ||||
|                                         ] | ||||
| 
 | ||||
| -- | A query for Cash (-equivalent) accounts in this journal (ie, | ||||
| -- accounts which appear on the cashflow statement.)  This is currently | ||||
| -- hard-coded to be all the Asset accounts except for those with names | ||||
| -- containing the case-insensitive regular expression @(receivable|:A/R|:fixed)@. | ||||
| -- | A query for "Cash" (liquid asset) accounts in this journal (ie, | ||||
| -- accounts which appear on the cashflow statement.) This is the | ||||
| -- accounts declared to be Cash type, or if none of these are | ||||
| -- declared, the Asset accounts whose names do not contain the | ||||
| -- case-insensitive regular expression @(investment|receivable|:A/R|:fixed)@. | ||||
| journalCashAccountQuery  :: Journal -> Query | ||||
| journalCashAccountQuery j = And [journalAssetAccountQuery j, Not $ Acct "(receivable|:A/R|:fixed)"] | ||||
| journalCashAccountQuery j = | ||||
|   case M.lookup Cash (jdeclaredaccounttypes j) of | ||||
|     Just _  -> journalAccountTypeQuery Cash notused j | ||||
|       where notused = error' "journalCashAccountQuery: this should not have happened!" | ||||
|     Nothing -> And | ||||
|                [journalAssetAccountQuery j | ||||
|                ,Not $ Acct "(investment|receivable|:A/R|:fixed)" | ||||
|                ] | ||||
| 
 | ||||
| -- | Get a query for accounts of a certain type (Asset, Liability..) in this journal. | ||||
| -- The query will match all accounts which were declared as that type by account directives, | ||||
| -- plus all their subaccounts which have not been declared as a different type. | ||||
| -- If no accounts were declared as this type, the query will instead match accounts | ||||
| -- with names matched by the provided case-insensitive regular expression. | ||||
| journalAccountTypeQuery :: AccountType -> Regexp -> Journal -> Query | ||||
| journalAccountTypeQuery atype fallbackregex j = | ||||
|   case M.lookup atype (jdeclaredaccounttypes j) of | ||||
|     Nothing -> Acct fallbackregex | ||||
|     Just as -> | ||||
|       -- XXX Query isn't able to match account type since that requires extra info from the journal. | ||||
|       -- So we do a hacky search by name instead. | ||||
|       And [ | ||||
|          Or $ map (Acct . accountNameToAccountRegex) as | ||||
|         ,Not $ Or $ map (Acct . accountNameToAccountRegex) differentlytypedsubs | ||||
|         ] | ||||
|       where | ||||
|         differentlytypedsubs = concat | ||||
|           [subs | (t,bs) <- M.toList (jdeclaredaccounttypes j) | ||||
|               , t /= atype | ||||
|               , let subs = [b | b <- bs, any (`isAccountNamePrefixOf` b) as] | ||||
|           ] | ||||
| 
 | ||||
| -- Various kinds of filtering on journals. We do it differently depending | ||||
| -- on the command. | ||||
|  | ||||
| @ -121,6 +121,7 @@ data AccountType = | ||||
|   | Equity | ||||
|   | Revenue | ||||
|   | Expense | ||||
|   | Cash  -- ^ a subtype of Asset - liquid assets to show in cashflow report | ||||
|   deriving (Show,Eq,Ord,Data,Generic) | ||||
| 
 | ||||
| instance NFData AccountType | ||||
|  | ||||
| @ -380,10 +380,12 @@ parseAccountTypeCode s = | ||||
|     "r"         -> Right Revenue | ||||
|     "expense"   -> Right Expense | ||||
|     "x"         -> Right Expense | ||||
|     "cash"      -> Right Cash | ||||
|     "c"         -> Right Cash | ||||
|     _           -> Left err | ||||
|   where | ||||
|     err = "invalid account type code "++T.unpack s++", should be one of " ++ | ||||
|           (intercalate ", " $ ["A","L","E","R","X","ASSET","LIABILITY","EQUITY","REVENUE","EXPENSE"]) | ||||
|           (intercalate ", " $ ["A","L","E","R","X","C","Asset","Liability","Equity","Revenue","Expense","Cash"]) | ||||
| 
 | ||||
| -- Add an account declaration to the journal, auto-numbering it. | ||||
| addAccountDeclaration :: (AccountName,Text,[Tag]) -> JournalParser m () | ||||
|  | ||||
| @ -1087,37 +1087,88 @@ account ACCTNAME  [ACCTTYPE] [;COMMENT] | ||||
| 
 | ||||
| #### Account types | ||||
| 
 | ||||
| hledger recognises five types (or classes) of account: Asset, Liability, Equity, Revenue, Expense. | ||||
| This is used by a few accounting-aware reports such as [balancesheet][], [incomestatement][] and [cashflow][]. | ||||
| hledger recognises five main types of account, | ||||
| corresponding to the account classes in the [accounting equation][]: | ||||
| 
 | ||||
| [balancesheet]: hledger.html#balancesheet | ||||
| [cashflow]: hledger.html#cashflow | ||||
| [incomestatement]: hledger.html#incomestatement | ||||
| `Asset`, `Liability`, `Equity`, `Revenue`, `Expense`. | ||||
| 
 | ||||
| ##### Auto-detected account types | ||||
| These account types are important for controlling which accounts | ||||
| appear in the [balancesheet][], [balancesheetequity][], | ||||
| [incomestatement][] reports (and probably for other things in future). | ||||
| 
 | ||||
| If you name your top-level accounts with some variation of | ||||
| `assets`, `liabilities`/`debts`, `equity`, `revenues`/`income`, or `expenses`, | ||||
| their types are detected automatically. | ||||
| There is also the `Cash` type, which is a subtype of `Asset`, | ||||
| and which causes accounts to appear in the [cashflow][] report. | ||||
| ("Cash" here means [liquid assets][CCE], eg typically bank balances | ||||
| but not investments or receivables.) | ||||
| 
 | ||||
| ##### Account types declared with tags | ||||
| ##### Declaring account types | ||||
| 
 | ||||
| Generally, to make these reports work you should declare your | ||||
| top-level accounts and their types,  | ||||
| using [account directives](#declaring-accounts)  | ||||
| with `type:` [tags](journal.html#tags). | ||||
| 
 | ||||
| The tag's value should be one of: | ||||
| `Asset`, `Liability`, `Equity`, `Revenue`, `Expense`, `Cash`, | ||||
| `A`, `L`, `E`, `R`, `X`, `C` (all case insensitive). | ||||
| The type is inherited by all subaccounts except where they override it. | ||||
| Here's a complete example: | ||||
| 
 | ||||
| More generally, you can declare an account's type with an account directive, | ||||
| by writing a `type:` [tag](journal.html#tags) in a comment, followed by one of the words | ||||
| `Asset`, `Liability`, `Equity`, `Revenue`, `Expense`, | ||||
| or one of the letters `ALERX` (case insensitive): | ||||
| ```journal | ||||
| account assets       ; type: Asset | ||||
| account assets:bank  ; type: Cash | ||||
| account assets:cash  ; type: Cash | ||||
| account liabilities  ; type: Liability | ||||
| account equity       ; type: Equity | ||||
| account revenues     ; type: Revenue | ||||
| account expenses     ; type: Expense | ||||
| ``` | ||||
| 
 | ||||
| ##### Account types declared with account type codes | ||||
| ##### Auto-detected account types | ||||
| 
 | ||||
| If you happen to use common english top-level account names, you may | ||||
| not need to declare account types, as they will be detected | ||||
| automatically using the following rules: | ||||
| 
 | ||||
| | If name matches [regular expression][]: | account type is: | ||||
| |-----------------------------------------|----------------- | ||||
| | `^assets?(:|$)`                         | `Asset` | ||||
| | `^(debts?|liabilit(y|ies))(:|$)`        | `Liability` | ||||
| | `^equity(:|$)`                          | `Equity` | ||||
| | `^(income|revenue)s?(:|$)`              | `Revenue` | ||||
| | `^expenses?(:|$)`                       | `Expense` | ||||
| 
 | ||||
| | If account type is `Asset` and name does not contain regular expression: | account type is: | ||||
| |--------------------------------------------------------------------------|----------------- | ||||
| | `(investment|receivable|:A/R|:fixed)`                                    | `Cash` | ||||
| 
 | ||||
| Even so, explicit declarations may be a good idea, for clarity and | ||||
| predictability.  | ||||
| 
 | ||||
| ##### Interference from auto-detected account types | ||||
| 
 | ||||
| If you assign any account type, it's a good idea to assign all of | ||||
| them, to prevent any confusion from mixing declared and auto-detected | ||||
| types. Although it's unlikely to happen in real life, here's an | ||||
| example: with the following journal, `balancesheetequity` shows | ||||
| "liabilities" in both Liabilities and Equity sections. Declaring another | ||||
| account as `type:Liability` would fix it: | ||||
| 
 | ||||
| ```journal | ||||
| account liabilities  ; type:Equity | ||||
| 
 | ||||
| 2020-01-01 | ||||
|   assets        1 | ||||
|   liabilities   1 | ||||
|   equity       -2 | ||||
| ``` | ||||
| 
 | ||||
| ##### Old account type syntax | ||||
| 
 | ||||
| In some hledger journals you might instead see this old syntax (the | ||||
| letters ALERX, separated from the account name by two or more spaces); | ||||
| this is deprecated and may be removed soon: | ||||
| 
 | ||||
| Or, you can write one of those letters separated from the account name by two or more spaces, | ||||
| but this should probably be considered deprecated as of hledger 1.13: | ||||
| ```journal | ||||
| account assets       A | ||||
| account liabilities  L | ||||
| @ -1126,18 +1177,15 @@ account revenues     R | ||||
| account expenses     X | ||||
| ``` | ||||
| 
 | ||||
| ##### Overriding auto-detected types | ||||
| 
 | ||||
| If you ever override the types of those auto-detected english account names mentioned above, | ||||
| you might need to help the reports a bit. Eg: | ||||
| ```journal | ||||
| ; make "liabilities" not have the liability type - who knows why | ||||
| account liabilities  ; type:E | ||||
| [balancesheet]: hledger.html#balancesheet | ||||
| [balancesheetequity]: hledger.html#balancesheetequity | ||||
| [cashflow]: hledger.html#cashflow | ||||
| [incomestatement]: hledger.html#incomestatement | ||||
| [CCE]: https://en.wikipedia.org/wiki/Cash_and_cash_equivalents | ||||
| [regular expression]: hledger.html#regular-expressions | ||||
| [account equation]: https://en.wikipedia.org/wiki/Accounting_equation | ||||
| 
 | ||||
| ; we need to ensure some other account has the liability type, | ||||
| ; otherwise balancesheet would still show "liabilities" under Liabilities | ||||
| account -            ; type:L | ||||
| ``` | ||||
| 
 | ||||
| #### Account display order | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user