notes: backlog updates
This commit is contained in:
		
							parent
							
								
									03f6119a8d
								
							
						
					
					
						commit
						ba207ce391
					
				
							
								
								
									
										842
									
								
								NOTES.org
									
									
									
									
									
								
							
							
						
						
									
										842
									
								
								NOTES.org
									
									
									
									
									
								
							| @ -1,5 +1,9 @@ | ||||
| hledger project notes | ||||
| 
 | ||||
| *We are all wandering the orderly halls of Castle Haskell.* | ||||
| 
 | ||||
| *This whole plain is gunpowder a mile deep.* | ||||
| 
 | ||||
| * about | ||||
| This emacs org-mode outline contains Simon's project backlog, activity | ||||
| log, and random developer notes.  Currently only I use this file, but | ||||
| @ -16,11 +20,9 @@ assuming 4 hours in day, 5 days in a week, and 4 weeks in a month. | ||||
| At some point there might be a process to aggregate estimates, log them | ||||
| (including deleted items as 0) on commit, and make burndown charts. | ||||
| 
 | ||||
| 
 | ||||
| * routines | ||||
| standard procedures/checklists for various activities | ||||
| 
 | ||||
| 
 | ||||
| * misc | ||||
| ** inspiration | ||||
| "...simplicity of design was the most essential, guiding principle. | ||||
| @ -2118,150 +2120,421 @@ move *FromOpts into toOpts | ||||
| *** 6/30 announce, notes | ||||
| *** 7/1 notes | ||||
| 
 | ||||
| 
 | ||||
| * in progress | ||||
| 
 | ||||
| * next up | ||||
| ** web: code review/refactor | ||||
| ** web: use bootstrap | ||||
| ** more powerful csv conversion | ||||
| ** formats: ofx reader | ||||
| *** clint's code | ||||
| Date: Sun, 18 Sep 2011 12:26:16 -0400 | ||||
| From: Clint Adams <clint@softwarefreedom.org> | ||||
| To: hledger@googlegroups.com | ||||
| Subject: OFX conversion | ||||
| Message-ID: <20110918162616.GA18874@softwarefreedom.org> | ||||
| MIME-Version: 1.0 | ||||
| User-Agent: Mutt/1.5.20 (2009-06-14) | ||||
| X-Original-Sender: clint@softwarefreedom.org | ||||
| X-Original-Authentication-Results: gmr-mx.google.com; spf=pass (google.com: | ||||
|  domain of clint@softwarefreedom.org designates 216.27.154.199 as permitted | ||||
|  sender) smtp.mail=clint@softwarefreedom.org | ||||
| Reply-To: hledger@googlegroups.com | ||||
| Precedence: list | ||||
| Mailing-list: list hledger@googlegroups.com; contact hledger+owners@googlegroups.com | ||||
| List-ID: <hledger.googlegroups.com> | ||||
| X-Google-Group-Id: 895107692464 | ||||
| List-Post: <http://groups.google.com/group/hledger/post?hl=en_US>, <mailto:hledger@googlegroups.com> | ||||
| List-Help: <http://groups.google.com/support/?hl=en_US>, <mailto:hledger+help@googlegroups.com> | ||||
| List-Archive: <http://groups.google.com/group/hledger?hl=en_US> | ||||
| Sender: hledger@googlegroups.com | ||||
| List-Subscribe: <http://groups.google.com/group/hledger/subscribe?hl=en_US>, <mailto:hledger+subscribe@googlegroups.com> | ||||
| List-Unsubscribe: <http://groups.google.com/group/hledger/subscribe?hl=en_US>, <mailto:hledger+unsubscribe@googlegroups.com> | ||||
| Content-Type: text/plain; charset=iso-8859-1 | ||||
| Content-Disposition: inline | ||||
| Content-Transfer-Encoding: 8bit | ||||
| 
 | ||||
| This is definitely suboptimal but it seems to work on | ||||
| the OFX 1.0.2 output from AmEx. | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| {-# LANGUAGE Arrows, NoMonomorphismRestriction #-} | ||||
| import Text.XML.HXT.Core | ||||
| import Text.Printf (printf) | ||||
| 
 | ||||
| import Data.List (groupBy) | ||||
| import Data.List.Split (splitOn) | ||||
| 
 | ||||
| import Data.Maybe (fromMaybe) | ||||
| 
 | ||||
| import Data.Time.Calendar (Day (ModifiedJulianDay)) | ||||
| import Data.Time.Format (formatTime) | ||||
| import Data.Time.LocalTime (LocalTime (LocalTime), TimeOfDay (TimeOfDay)) | ||||
| import Data.Time.Parse (strptime) | ||||
| 
 | ||||
| import System.Locale (defaultTimeLocale) | ||||
| import System.Process (readProcessWithExitCode) | ||||
| 
 | ||||
| import Hledger.Cli.Format (FormatString (FormatField), Field (FieldNo)) | ||||
| import Hledger.Cli.Convert | ||||
| 
 | ||||
| normAmount :: String -> String | ||||
| normAmount amt | amt == "" = "" | ||||
|     | otherwise = printf "%.2f" (read amt :: Double) | ||||
| 
 | ||||
| compressWhitespace :: String -> String | ||||
| compressWhitespace x = map head $ groupSpaces x | ||||
|         where groupSpaces "" = [""] | ||||
|               groupSpaces x = groupBy (\x y -> x==' ' && y==' ') x | ||||
| 
 | ||||
| data Transaction = Transaction | ||||
|   { trnType, dtUser, dtPosted, trnAmt, fitId, refNum, name, memo :: String } | ||||
|   deriving (Show, Eq) | ||||
| 
 | ||||
| -- this doesn't get the timezone right | ||||
| ofxDateParse :: String -> String | ||||
| ofxDateParse x = formatTime defaultTimeLocale "%Y-%m-%d" (fst (fromMaybe (LocalTime (ModifiedJulianDay 100) (TimeOfDay 0 0 0), "") (strptime "%Y%m%d%H%M%S.%OS" x))) | ||||
| 
 | ||||
| parseFakeXML string = readString [ withValidate no | ||||
|                              , withRemoveWS yes | ||||
|                              ] string | ||||
| 
 | ||||
| atTag tag = deep (isElem >>> hasName tag) | ||||
| text = getChildren >>> getText | ||||
| textAtTag tag = atTag tag >>> text | ||||
| 
 | ||||
| getTransactions = atTag "STMTTRN" >>> | ||||
|   proc l -> do | ||||
|     trnType  <- textAtTag "TRNTYPE" -< l | ||||
|     dtUser   <- textAtTag "DTUSER"         -< l | ||||
|     dtPosted <- textAtTag "DTPOSTED" -< l | ||||
|     trnAmt <- textAtTag "TRNAMT" -< l | ||||
|     fitId <- textAtTag "FITID" -< l | ||||
|     refNum <- textAtTag "REFNUM" -< l | ||||
|     name <- textAtTag "NAME" -< l | ||||
|     memo <- textAtTag "MEMO" -< l | ||||
|     returnA -< Transaction | ||||
|       { trnType   = trnType, | ||||
|         dtUser = ofxDateParse dtUser, | ||||
|         dtPosted = ofxDateParse dtPosted, | ||||
|         trnAmt     = trnAmt, | ||||
|         fitId     = fitId, | ||||
|         refNum     = refNum, | ||||
|         name     = name, | ||||
|         memo  = memo } | ||||
| 
 | ||||
| ofxrules = CsvRules { | ||||
|       dateField=Just 0, | ||||
|       dateFormat=Nothing, | ||||
|       statusField=Nothing, | ||||
|       codeField=Nothing, | ||||
|       descriptionField=[FormatField False Nothing Nothing (FieldNo 2)], | ||||
|       amountField=Just 1, | ||||
|       inField=Nothing, | ||||
|       outField=Nothing, | ||||
|       currencyField=Nothing, | ||||
|       baseCurrency=Nothing, | ||||
|       accountField=Nothing, | ||||
|       account2Field=Nothing, | ||||
|       effectiveDateField=Nothing, | ||||
|       baseAccount="Liabilities:American Express", | ||||
|       accountRules=[] | ||||
| } | ||||
| 
 | ||||
| txnToCsvRecord :: Transaction -> CsvRecord | ||||
| txnToCsvRecord x = [dtUser x, normAmount (trnAmt x), compressWhitespace (name x) ++ "(" ++ refNum x ++ ")", fitId x, memo x] | ||||
| 
 | ||||
| printTxnWithComment :: CsvRecord -> IO () | ||||
| printTxnWithComment x = putStrLn ("; " ++ x !! 3 ++ " - " ++ x !! 4) >> printTxn False ofxrules x | ||||
| 
 | ||||
| main = do | ||||
|   filecontents <- readFile "/tmp/ofx.ofx" | ||||
|   let splitfilecontents = splitOn "\n\n" filecontents | ||||
|   let ofxheader = head splitfilecontents | ||||
|   let ofxsgml = splitfilecontents !! 1 | ||||
|   (_, fakexml, _) <- readProcessWithExitCode "/usr/bin/sgml2xml" [] ofxsgml | ||||
| 
 | ||||
|   transes <- runX (parseFakeXML fakexml >>> getTransactions) | ||||
| 
 | ||||
|   let records = map txnToCsvRecord transes | ||||
|   mapM_ (printTxnWithComment) records | ||||
| 
 | ||||
| 
 | ||||
| * backlog | ||||
| ** Archive                                                          :ARCHIVE: | ||||
| *** DONE 98: build issue due to missing template files | ||||
|     CLOSED: [2013-01-24 Thu 09:30] | ||||
|     :PROPERTIES: | ||||
|     :ARCHIVE_TIME: 2013-01-24 Thu 09:30 | ||||
|     :END: | ||||
| **** test fix | ||||
| **** publish patch | ||||
| **** close issue | ||||
| **** improve clean build testing, possibly with cabal-dev | ||||
| *** DONE fix/explain build errors | ||||
|     CLOSED: [2013-02-08 Fri 09:05] | ||||
|     :PROPERTIES: | ||||
|     :ARCHIVE_TIME: 2013-02-11 Mon 12:44 | ||||
|     :END: | ||||
| *** DONE add: djp/sm enhancements | ||||
|     CLOSED: [2013-03-15 Fri 18:35] | ||||
|     :PROPERTIES: | ||||
|     :ARCHIVE_TIME: 2013-03-15 Fri 18:35 | ||||
|     :END: | ||||
| **** DONE cleanups | ||||
|      CLOSED: [2013-02-25 Mon 16:38] | ||||
| **** DONE 52 show added txn | ||||
|      CLOSED: [2013-02-25 Mon 16:38] | ||||
| **** DONE 47 do-over | ||||
|      CLOSED: [2013-02-25 Mon 16:38] | ||||
| **** DONE 96 command-line defaults | ||||
|      CLOSED: [2013-02-25 Mon 16:38] | ||||
| **** DONE 45 allow comment/tag entry | ||||
|      CLOSED: [2013-02-25 Mon 16:38] | ||||
| ***** allow DESC ;COMMENT | ||||
| ***** allow AMOUNT ;COMMENT | ||||
| **** DONE allow DATE CODE | ||||
|      CLOSED: [2013-02-25 Mon 16:38] | ||||
| **** DONE confirm before adding txn | ||||
|      CLOSED: [2013-02-25 Mon 16:39] | ||||
| **** DONE don't die after data entry if a partial date was provided on command line | ||||
|       CLOSED: [2013-03-04 Mon 18:09] | ||||
| 
 | ||||
| **** DONE decide how to wind this up, complete/announce bounty | ||||
|      CLOSED: [2013-03-09 Sat 07:57] | ||||
| **** DONE add to release notes | ||||
|      CLOSED: [2013-03-09 Sat 07:57] | ||||
| 
 | ||||
| ** TODO more powerful csv reading | ||||
| *** DONE v2 rules file mockup showing new syntax | ||||
|     CLOSED: [2013-01-11 Fri 20:27] | ||||
| *** DONE write down pseudo grammar | ||||
|     CLOSED: [2013-01-11 Fri 20:27] | ||||
| *** DONE review status | ||||
|     CLOSED: [2013-01-11 Fri 20:47] | ||||
| *** DONE parse basic directives & assignments | ||||
|     CLOSED: [2013-01-12 Sat 09:12] | ||||
| *** DONE apply basic directives & assignments | ||||
|     CLOSED: [2013-01-13 Sun 11:01] | ||||
| **** DONE directives | ||||
|      CLOSED: [2013-01-13 Sun 10:58] | ||||
| **** DONE field assignments | ||||
|      CLOSED: [2013-01-13 Sun 10:58] | ||||
| ***** DONE code review | ||||
|       CLOSED: [2013-01-12 Sat 09:41] | ||||
| ***** DONE code cleanup | ||||
|       CLOSED: [2013-01-12 Sat 11:40] | ||||
| ****** DONE conform to new naming | ||||
|        CLOSED: [2013-01-12 Sat 11:40] | ||||
| ****** DONE clarify rules type | ||||
|        CLOSED: [2013-01-12 Sat 10:57] | ||||
| ****** DONE simplify | ||||
|        CLOSED: [2013-01-12 Sat 11:40] | ||||
| ******* DONE get it parsing test rules again | ||||
|         CLOSED: [2013-01-12 Sat 11:05] | ||||
| ******* DONE get it printing correct parsed value | ||||
|         CLOSED: [2013-01-12 Sat 11:05] | ||||
| ******* DONE cleanup | ||||
|         CLOSED: [2013-01-12 Sat 11:40] | ||||
| ***** DONE generate field values from templates | ||||
|       CLOSED: [2013-01-13 Sun 10:58] | ||||
| ****** DONE date-format & date | ||||
|        CLOSED: [2013-01-13 Sun 01:00] | ||||
| ****** DONE other fields | ||||
|        CLOSED: [2013-01-13 Sun 10:58] | ||||
| *** DONE 1-based field numbering | ||||
|     CLOSED: [2013-01-13 Sun 11:01] | ||||
| *** DONE conditional assignments | ||||
|     CLOSED: [2013-01-26 Sat 05:47] | ||||
| **** DONE parsing | ||||
|      CLOSED: [2013-01-14 Mon 07:27] | ||||
| ***** DONE review doc | ||||
|       CLOSED: [2013-01-13 Sun 11:37] | ||||
| ***** DONE update grammar | ||||
|       CLOSED: [2013-01-13 Sun 11:39] | ||||
| ***** DONE multiple assignments | ||||
|       CLOSED: [2013-01-13 Sun 12:55] | ||||
| ***** DONE multiple patterns | ||||
|       CLOSED: [2013-01-13 Sun 13:36] | ||||
| ***** DONE clarify syntax | ||||
|       CLOSED: [2013-01-13 Sun 14:20] | ||||
| ***** DONE update grammar | ||||
|       CLOSED: [2013-01-14 Mon 07:13] | ||||
| ***** DONE clarify backwards compatibility | ||||
|       CLOSED: [2013-01-14 Mon 07:13] | ||||
| ***** DONE lighter conditional syntax (omit field name) | ||||
|       CLOSED: [2013-01-14 Mon 07:27] | ||||
| 
 | ||||
| **** DONE functionality | ||||
|      CLOSED: [2013-01-26 Sat 05:47] | ||||
| ***** DONE clarify spec | ||||
|       CLOSED: [2013-01-14 Mon 09:33] | ||||
| ***** DONE implement | ||||
|       CLOSED: [2013-01-14 Mon 09:33] | ||||
| 
 | ||||
| ***** DONE test | ||||
|       CLOSED: [2013-01-26 Sat 05:47] | ||||
| ****** DONE fix speed | ||||
|        CLOSED: [2013-01-26 Sat 05:46] | ||||
| ******* DONE review/try regex libs | ||||
|         CLOSED: [2013-01-26 Sat 05:29] | ||||
| ******* DONE profile different variants | ||||
|         CLOSED: [2013-01-26 Sat 05:29] | ||||
| ******* DONE handle malformed regexps as well as before | ||||
|         CLOSED: [2013-01-26 Sat 05:46] | ||||
| *** DONE fix warnings | ||||
|     CLOSED: [2013-01-26 Sat 15:03] | ||||
| *** DONE field name list | ||||
|     CLOSED: [2013-01-26 Sat 15:03] | ||||
| **** DONE implement assignment by field name list | ||||
|      CLOSED: [2013-01-26 Sat 14:58] | ||||
| ***** DONE add a date field assignment per its position | ||||
|       CLOSED: [2013-01-26 Sat 14:39] | ||||
| 
 | ||||
| ***** DONE refactor | ||||
|       CLOSED: [2013-01-26 Sat 14:51] | ||||
| ***** DONE add multiple fields without hard coding | ||||
|       CLOSED: [2013-01-26 Sat 14:58] | ||||
| ***** DONE add all the right fields | ||||
|       CLOSED: [2013-01-26 Sat 14:58] | ||||
| *** DONE skip | ||||
|     CLOSED: [2013-01-26 Sat 15:38] | ||||
| *** DONE set currency from csv | ||||
|     CLOSED: [2013-03-19 Tue 06:17] | ||||
| *** DONE set amount sign based on another field's content (type=debit|credit) | ||||
|     CLOSED: [2013-01-26 Sat 16:57] | ||||
| *** DONE set amount based on two fields (amount in, amount out) | ||||
|     CLOSED: [2013-03-19 Tue 06:17] | ||||
| 
 | ||||
| *** DONE parse parenthesised amounts as negative | ||||
|     CLOSED: [2013-01-27 Sun 17:32] | ||||
| *** DONE user friendliness | ||||
|     CLOSED: [2013-02-11 Mon 12:43] | ||||
| **** DONE robust parsing | ||||
|      CLOSED: [2013-01-27 Sun 07:32] | ||||
| **** DONE clear-ish errors | ||||
|      CLOSED: [2013-02-11 Mon 10:16] | ||||
| ***** DONE catalog errors | ||||
|       CLOSED: [2013-02-09 Sat 15:18] | ||||
| ***** DONE missing date/amount rule error | ||||
|       CLOSED: [2013-02-09 Sat 09:32] | ||||
| ***** DONE better amount parse errors | ||||
|       CLOSED: [2013-02-09 Sat 10:12] | ||||
| ****** DONE clean up csv parsing/validation | ||||
|        CLOSED: [2013-01-28 Mon 08:50] | ||||
| ****** DONE clean up rules parsing/validation | ||||
|        CLOSED: [2013-01-28 Mon 08:50] | ||||
| 
 | ||||
| ****** DONE no amount assignment | ||||
|        CLOSED: [2013-01-29 Tue 06:50] | ||||
| ****** DONE amount field unparseable | ||||
|        CLOSED: [2013-02-09 Sat 10:12] | ||||
| ****** DONE confusing amount parse error for header line | ||||
|        CLOSED: [2013-02-09 Sat 11:47] | ||||
| hledgerdev:  | ||||
| Error, could not parse amount "" ((line 1, column 1): | ||||
| unexpected end of input | ||||
| expecting left-symbol amount, right-symbol amount or no-symbol amount) | ||||
| in ["Date","Details","Debit","Credit","Balance"] | ||||
| 
 | ||||
| rules: | ||||
| # | ||||
| 
 | ||||
| ****** DONE could not parse amount in (data line) | ||||
|        CLOSED: [2013-02-09 Sat 11:48] | ||||
| hledgerdev: Error, could not parse amount "" ((line 1, column 1): | ||||
| unexpected end of input expecting left-symbol amount, right-symbol | ||||
| amount or no-symbol amount) in ["07/12/2012","LODGMENT | ||||
| 529898","","10.0","131.21"] | ||||
| 
 | ||||
| rules: | ||||
| ****** DONE poor error on empty amount csv field | ||||
|        CLOSED: [2013-02-09 Sat 14:03] | ||||
| ***** DONE better date parse errors | ||||
|       CLOSED: [2013-02-09 Sat 11:26] | ||||
| ****** DONE don't silently misparse d/m/y | ||||
|        CLOSED: [2013-02-09 Sat 13:34] | ||||
| ***** DONE why x rule triggering ? | ||||
|       CLOSED: [2013-02-09 Sat 17:28] | ||||
| ***** DONE unclear error when conditional block assignment has no field name | ||||
|       CLOSED: [2013-02-09 Sat 17:40] | ||||
| 
 | ||||
| **** show what's happening | ||||
| *** DONE fix parsing of %10 and fields: ...amount... as %1 in .wepay-in.csv.rules | ||||
|     CLOSED: [2013-03-14 Thu 16:19] | ||||
| *** DONE interpolate by name | ||||
|     CLOSED: [2013-03-14 Thu 17:33] | ||||
| *** DONE skip-lines -> skip | ||||
|      CLOSED: [2013-03-14 Thu 17:36] | ||||
| *** DONE amount-in/out | ||||
|     CLOSED: [2013-03-15 Fri 17:45] | ||||
| *** DONE value-less skip | ||||
|     CLOSED: [2013-03-15 Fri 17:45] | ||||
| *** DONE make if operator optional | ||||
|     CLOSED: [2013-03-19 Tue 06:47] | ||||
| *** DONE docs | ||||
|     CLOSED: [2013-03-29 Fri 15:20] | ||||
| **** DONE reorganize file format docs | ||||
|      CLOSED: [2013-02-11 Mon 12:45] | ||||
| **** DONE review/record writing tips | ||||
|      CLOSED: [2013-03-14 Thu 16:28] | ||||
| **** DONE csv introduction | ||||
|      CLOSED: [2013-03-14 Thu 17:54] | ||||
| **** DONE convert to hakyll 4 | ||||
|      CLOSED: [2013-03-14 Thu 17:54] | ||||
| **** DONE serve manual from hub | ||||
|      CLOSED: [2013-03-13 Wed 11:03] | ||||
| **** DONE rewrite intro | ||||
|      CLOSED: [2013-03-17 Sun 16:15] | ||||
| **** DONE rewrite rules reference | ||||
|      CLOSED: [2013-03-19 Tue 06:15] | ||||
| **** DONE update manual | ||||
|      CLOSED: [2013-03-29 Fri 14:06] | ||||
| **** DONE update grammar | ||||
|      CLOSED: [2013-03-29 Fri 14:37] | ||||
| **** DONE clarify csv / journal entry / transaction terminology | ||||
|      CLOSED: [2013-03-19 Tue 06:15] | ||||
| **** DONE clarify directives / assignments / rules terminology | ||||
|      CLOSED: [2013-03-29 Fri 15:16] | ||||
| **** DONE clarify account directives | ||||
|      CLOSED: [2013-03-29 Fri 15:16] | ||||
| **** DONE clarify optional syntax (:, if, fields) | ||||
|      CLOSED: [2013-03-29 Fri 15:16] | ||||
| **** clarify upgrade process | ||||
| ***** base-currency -> default-currency | ||||
| ***** base-account -> default-account1 | ||||
| ***** FIELDNAME-field N -> FIELDNAME %N+1 | ||||
| ***** update each account-assigning rule | ||||
| ****** add a line containing ~ before the regexps | ||||
| ****** add account2: before the account name | ||||
| **** set up versioned manual | ||||
| **** update/add examples | ||||
|      https://gist.github.com/simonmichael/5153401 bofi example | ||||
| 
 | ||||
| ***** no rules file example | ||||
| ***** rules file example | ||||
| ***** how to archive/import the journal data more permanently | ||||
| *** DONE update default rules | ||||
|     CLOSED: [2013-03-29 Fri 15:19] | ||||
| *** DONE testing | ||||
|     CLOSED: [2013-03-29 Fri 15:51] | ||||
| **** DONE wells fargo checking | ||||
|      CLOSED: [2013-01-27 Sun 17:25] | ||||
| **** DONE western federal | ||||
|      CLOSED: [2013-01-27 Sun 18:51] | ||||
| **** DONE b of i | ||||
|      CLOSED: [2013-03-19 Tue 06:17] | ||||
| **** DONE wepay | ||||
|      CLOSED: [2013-03-19 Tue 06:17] | ||||
| **** DONE paypal | ||||
|      CLOSED: [2013-03-29 Fri 15:24] | ||||
| **** DONE mint | ||||
|      CLOSED: [2013-03-29 Fri 15:39] | ||||
| **** DONE ynab | ||||
|      CLOSED: [2013-03-29 Fri 15:46] | ||||
| **** wescom | ||||
| *** DONE commits | ||||
|     CLOSED: [2013-03-29 Fri 16:10] | ||||
| *** TODO auto skip csv header lines | ||||
| *** TODO use csv header as initial field name list | ||||
| *** TODO skip (& other directives ?) in conditional blocks | ||||
| *** TODO match on individual fields | ||||
| *** TODO else | ||||
| *** TODO don't automatically write rules files | ||||
| *** TODO sign flipping aid: parse --AMT, -(AMT) as AMT ? | ||||
| *** TODO interpolation enhancements | ||||
| *** TODO entry templates | ||||
| **ENTRY TEMPLATES** give most flexibility, defining the entire | ||||
|     journal entry at once. They look like a standard journal entry, but | ||||
|     with CSV field references instead of values, beginning with `%date` | ||||
|     on the first line. Eg, this builds an entry with an extra virtual | ||||
|     posting: | ||||
| 
 | ||||
|          %date %description | ||||
|            %account                   %amount | ||||
|            %default-account | ||||
|            (some special account)     %amount | ||||
| 
 | ||||
| 
 | ||||
| thai | ||||
| expenses:food:dining | ||||
| 
 | ||||
| desc~thai | ||||
| account=expenses:food:dining | ||||
| 
 | ||||
| desc~thai | ||||
| [date] [description] | ||||
|   ; original-description: [2] | ||||
|   expenses:food:dining  [amount] | ||||
|   [base-account] | ||||
| *** TODO command-line rules | ||||
| *** TODO smarter default rules | ||||
| *** TODO generalise rules to non csv ? | ||||
| 
 | ||||
| ** TODO issue tracking/roadmap cleanup | ||||
| *** clarify wish tracking, project hosting | ||||
| *** clean up wrong/missing issue fields | ||||
| **** component | ||||
| **** type | ||||
| *** prune/update field values | ||||
| *** link useful tracker views | ||||
| **** issues by type grid            https://code.google.com/p/hledger/issues/list?q=&colspec=ID+Type+Status+Summary+Reporter+Opened+Stars&sort=&groupby=&mode=grid&y=Type&x=Status&cells=tiles&nobtn=Update | ||||
| **** enhancements by component grid https://code.google.com/p/hledger/issues/list?can=2&q=type%3Aenhancement&colspec=ID+Type+Status+Summary+Reporter+Opened+Stars&sort=&groupby=&mode=grid&y=Component&x=Status&cells=tiles&nobtn=Update | ||||
| **** enhancements by reporter grid  https://code.google.com/p/hledger/issues/list?can=2&q=type%3Aenhancement&colspec=ID+Type+Status+Summary+Reporter+Opened+Stars&sort=&groupby=&mode=grid&y=Reporter&x=Status&cells=tiles&nobtn=Update | ||||
| *** try trello boards | ||||
| 
 | ||||
| ** TODO fix tests | ||||
| *** unit | ||||
| *** func | ||||
| ** TODO use readFile' everywhere | ||||
| *** clean up readFile situation | ||||
| **** drop UTF8IOCompat ? | ||||
| ***** TODO research | ||||
| 
 | ||||
| ** TODO release | ||||
| ** advertise hledger-irr etc. better | ||||
| ** extra -> hledger-contrib ? | ||||
| ** my personal user wishlist | ||||
| *** better csv reading | ||||
| **** more powerful hints | ||||
| ***** rewrite account names | ||||
| ***** select one or both accounts, generate three or more postings, or generate full transactions | ||||
| ***** based on any field | ||||
| ***** set secondary date from date in description | ||||
| **** simpler syntax | ||||
| ***** list-of-field-names  | ||||
| ***** simplify redundant directives | ||||
| ****** currency -> default-commodity ? | ||||
| **** better rules file handling | ||||
| ***** share hints among different files - include ? | ||||
| ***** literal --rules option | ||||
| ***** don't auto-create missing rules file | ||||
| ****** by default use (and log) simple default rules | ||||
| ****** on command, generate | ||||
| ******* guess fields from data | ||||
| ******* show all directives | ||||
| 
 | ||||
| *** balance assertions | ||||
| *** secure portable/remote access | ||||
| *** better web ui | ||||
| **** more speed | ||||
| ***** show page render time | ||||
| ***** profile | ||||
| **** ability to reduce detail in sidebar | ||||
| **** bootstrap styling | ||||
| **** steady, quick evolution | ||||
| 
 | ||||
| *** phone-based data entry | ||||
| **** ixpenseit | ||||
| **** ynab | ||||
| 
 | ||||
| ** errors | ||||
| *** add: should not accept . as an amount | ||||
| *** add: default amount adds one decimal place when journal contains no decimals  2d | ||||
| *** add: excessive precision in default balancing amount  1d | ||||
| **** shelltest tests/add.test -- -t10 | ||||
| **** find original justification or drop | ||||
| *** add: learn decimal point/thousands separator from the journal and/or add session ?  2d | ||||
| Eg: comma is already used as thousands separator in the journal, but add | ||||
| interprets it as decimal point giving a wrong default for amount 2 (though | ||||
| the correct journal transaction is written in this case) | ||||
| 
 | ||||
| $ hledger -f t add | ||||
| Adding transactions to journal file "t". | ||||
| To complete a transaction, enter . (period) at an account prompt. | ||||
| To stop adding transactions, enter . at a date prompt, or control-d/control-c. | ||||
| date, or . to end [2011/09/30]:  | ||||
| description []: z | ||||
| account 1: a | ||||
| amount  1: 1,000 | ||||
| account 2: b | ||||
| amount  2 [-1,0]:  | ||||
| account 3, or . to record: . | ||||
| date, or . to end [2011/09/30]: . | ||||
| $ cat t | ||||
| ; journal created 2011-09-30 by hledger | ||||
| 
 | ||||
| 2011/09/30 | ||||
|     a  $1,000,000.00 | ||||
|     b | ||||
| 
 | ||||
| 2011/09/30 x | ||||
|     a          $1,2 | ||||
|     b | ||||
| 
 | ||||
| 2011/09/30 y | ||||
|     a          $1.2 | ||||
|     b | ||||
| 
 | ||||
| 2011/09/30 z | ||||
|     a         1,000 | ||||
|     b | ||||
| 
 | ||||
| *** web: unknown flag --port | ||||
| $ hledger web --port=5001 -f all.journal paypal | ||||
| hledger: Unknown flag: --port | ||||
| *** print: virtual posting parentheses throwing off layout | ||||
| *** bal: should --flat show inclusive or exclusive balances ?? | ||||
| *** double quote matches everything ?  1 | ||||
| *** web: stray bracket in journal edit form title  1 | ||||
| *** web: enter doesn't work in add form completing fields  1d | ||||
| @ -2319,52 +2592,30 @@ hledger: could not parse journal data in t.j | ||||
| unexpected "b" | ||||
| expecting comment or new-line | ||||
| 
 | ||||
| *** add: default amount adds one decimal place when journal contains no decimals  2d | ||||
| *** add: excessive precision in default balancing amount  1d | ||||
| **** shelltest tests/add.test -- -t10 | ||||
| **** find original justification or drop | ||||
| *** add: learn decimal point/thousands separator from the journal and/or add session ?  2d | ||||
| Eg: comma is already used as thousands separator in the journal, but add | ||||
| interprets it as decimal point giving a wrong default for amount 2 (though | ||||
| the correct journal transaction is written in this case) | ||||
| 
 | ||||
| $ hledger -f t add | ||||
| Adding transactions to journal file "t". | ||||
| To complete a transaction, enter . (period) at an account prompt. | ||||
| To stop adding transactions, enter . at a date prompt, or control-d/control-c. | ||||
| date, or . to end [2011/09/30]:  | ||||
| description []: z | ||||
| account 1: a | ||||
| amount  1: 1,000 | ||||
| account 2: b | ||||
| amount  2 [-1,0]:  | ||||
| account 3, or . to record: . | ||||
| date, or . to end [2011/09/30]: . | ||||
| $ cat t | ||||
| ; journal created 2011-09-30 by hledger | ||||
| 
 | ||||
| 2011/09/30 | ||||
|     a  $1,000,000.00 | ||||
|     b | ||||
| 
 | ||||
| 2011/09/30 x | ||||
|     a          $1,2 | ||||
|     b | ||||
| 
 | ||||
| 2011/09/30 y | ||||
|     a          $1.2 | ||||
|     b | ||||
| 
 | ||||
| 2011/09/30 z | ||||
|     a         1,000 | ||||
|     b | ||||
| 
 | ||||
| *** convert: 49 convert should report rules file parse errors better  1d | ||||
| *** not: does not work with date: etc. | ||||
| *** 25 hledger in windows console does not print non-ascii characters  3d | ||||
| http://stackoverflow.com/questions/10779149/unicode-console-i-o-in-haskell-on-windows | ||||
| http://hackage.haskell.org/trac/ghc/ticket/4471 | ||||
| *** journalAddFile is called in reverse order of includes  2 | ||||
| ** documentation, marketing | ||||
| *** cli: short flags not passed through to subcommand | ||||
| *** irr: flags require preceding -- | ||||
| ** documentation | ||||
| *** hledger intro tutorial: | ||||
| **** what problem did ledger solve when I started ? | ||||
| ***** I needed to track my time at work | ||||
| ***** I needed a transparent, open, future-proof data format | ||||
| ***** I needed simple, reliable, fixable software with no lock-in | ||||
| ***** I wanted an accounting tool without distracting/frustrating unfixable usability/functionality bugs | ||||
| **** what problem did hledger solve when I started ? | ||||
| ***** I neededed a better implementation of ledger (for me; that meant ie more installable, intuitive, documented, bug free, easy to hack on and extend) | ||||
| ***** I needed to make consistent bookkeeping more fun and motivating | ||||
| ***** I wanted a not-too-demanding learn haskell project | ||||
| ***** I wanted reusable accounting libraries available in haskell for experiments | ||||
| ***** I wanted to explore making an easy accounting app I could sell | ||||
| **** what problem is hledger solving now ? | ||||
| ***** same as above ? | ||||
| *** doc: manual rewrites | ||||
| *** developer notes | ||||
| **** 2012/7 cleanup | ||||
| ***** quick cleanup finance onwards  2 | ||||
| @ -2602,9 +2853,11 @@ binaries for all platforms | ||||
| 
 | ||||
| *** internal code docs | ||||
| *** live demos/talks | ||||
| ** marketing | ||||
| *** reference | ||||
| http://www.geekwire.com/2013/marketing-advice-startups/ | ||||
| ** finance | ||||
| *** develop funding process | ||||
| **** license change ? | ||||
| **** donate button, see chimoo guy | ||||
| **** funding document 2009/01 | ||||
| ***** text | ||||
| @ -2805,6 +3058,7 @@ competitors/fellow niche inhabitants | ||||
| ****** gwern | ||||
|        most haskellers have never heard of hledger, sounds arrogant or hubristic to talk of charging for it | ||||
| 
 | ||||
| **** license change ? | ||||
| **** home edition | ||||
| **** real-time project ledger | ||||
| **** in-place transaction editing fund drive | ||||
| @ -2959,6 +3213,8 @@ $ ledger -V -f test.dat --no-rounding bal | ||||
| Is there something off with how the data aboce is set up?  Should I be  | ||||
| using be more place holders?  | ||||
| *** performance | ||||
| **** reference | ||||
| http://stackoverflow.com/questions/3276240/tools-for-analyzing-performance-of-a-haskell-program/3276557#3276557 | ||||
| **** speed, benchmark tests | ||||
| **** memory usage | ||||
| *** build & packaging | ||||
| @ -2989,6 +3245,7 @@ using be more place holders? | ||||
| ***** easy installer | ||||
| ***** easy startup | ||||
| ** refactoring | ||||
| *** clarify need for & usage of primary/secondary/transaction/posting dates | ||||
| *** makefile cleanups | ||||
| *** make shell tests version independent | ||||
| tests/no-such-file.test: rm -f $$; bin/hledger register -f $$; rm -f $$ | ||||
| @ -3045,11 +3302,33 @@ http://ajaxcssblog.com/jquery/url-read-request-variables/ | ||||
| **** unix/windows/mac platform | ||||
| *** inspiration | ||||
| http://community.haskell.org/~ndm/downloads/paper-hoogle_overview-19_nov_2008.pdf -> Design Guidelines | ||||
| ** features | ||||
| *** add: don't offer record txn option in account N prompt if it's not balanced yet | ||||
| *** add: rewrite a short description (trader) to the full description from the matched txn (trader joe's) ? | ||||
| *** add: try wizards, vty-ui libs ? | ||||
| *** add: would be nice to create the journal file only if a txn is actually recorded | ||||
| *** perf tuning experiments | ||||
| **** string -> text | ||||
| **** strict data fields | ||||
| **** more profiling | ||||
| **** faster parsec alternative | ||||
| *** web: code/ui review/refactor | ||||
| **** convert all to HTF ? | ||||
| ** new features | ||||
| *** add: more enhancements | ||||
| **** display default after accepting it ? | ||||
| ***** try haskeline's defaults | ||||
| **** use previous values as defaults after restart | ||||
| **** stop after single txn if 2 or more args | ||||
| **** be non-interactive if 5 or more args | ||||
| **** use command-line args as inputs not just defaults | ||||
| **** don't add space after tab-completing account | ||||
| expenses:personal:health:personal care  | ||||
| 
 | ||||
| **** refactor | ||||
| ***** split into entry & append internally | ||||
| ***** get* -> input* | ||||
| ***** askFor -> input | ||||
| ***** expose entry & append in ui | ||||
| **** don't offer record txn option in account N prompt if it's not balanced yet | ||||
| **** rewrite a short description (trader) to the full description from the matched txn (trader joe's) ? | ||||
| **** try wizards, vty-ui libs ? | ||||
| **** would be nice to create the journal file only if a txn is actually recorded | ||||
| 
 | ||||
| *** balance: --depth with --flat should show aggregate balances including the non-displayed deeper accounts | ||||
| *** balance: try indenting amounts | ||||
| @ -3134,6 +3413,12 @@ hledger -f demo.journal reg inacct:expenses:food:pets date:2010/8/25 | ||||
| 2010/08/25 catfood              expenses:food:pets           $10.00       $10.00 | ||||
|                                 assets:cash                 $-10.00            0 | ||||
| 
 | ||||
| *** cli: better error message for malformed dates | ||||
| $ 2012 bal -e 'home care' | ||||
| hledger: could not parse end date: (line 1, column 1): | ||||
| unexpected "h" | ||||
| expecting digit, "january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december", "jan", "feb", "mar", "apr", "jun", "jul", "aug", "sep", "oct", "nov", "dec", "today", "yesterday", "tomorrow", "last", "this" or "next" (run with --help for usage) | ||||
| 
 | ||||
| *** docs: --help-web and web ui help links that go to online help, with paragraph comments & chat | ||||
| cf clients & profits interactive user guide, php.net, realworldhaskell etc. | ||||
| *** docs: better intro, less wall-of-text, separate tutorial & reference sections | ||||
| @ -3242,7 +3527,6 @@ dataType = do string "Cash" | ||||
| 
 | ||||
| transaction :: GenParser Char st [TransactionDetail] | ||||
| 
 | ||||
| 
 | ||||
| *** parsing: accept all real-world ledger files | ||||
| As far as I know it currently accepts all ledger 2.6-era files. | ||||
| Add support for ledger 3 file format as/when that stabilises. | ||||
| @ -3277,6 +3561,7 @@ $ hledger -f time.journal bal -p aug -B | ||||
|                    1 | ||||
|               17.75h | ||||
| 
 | ||||
| *** parsing: better date tag syntax errors | ||||
| *** parsing: canonicalise account names to be case-insensitive ? | ||||
| *** parsing: end directive may also be spelled end account; or end ends last directive | ||||
| *** parsing: enforce positive price amounts, like ledger | ||||
| @ -3328,11 +3613,13 @@ eg support -p 'from 1/1 to 2/1 weekly' | ||||
| 
 | ||||
| *** print: shouldn't support -M and --depth ? | ||||
| 
 | ||||
| *** queries: tag value queries | ||||
| *** register: for the love of god, show full descriptions | ||||
| 
 | ||||
| *** web: api | ||||
| *** web: auto-complete accounts & amount as well as description | ||||
| *** web: auto-complete from substrings, not just prefixes | ||||
| *** web: balance chart should end at query end date not last txn date | ||||
| *** web: better web ui/gui | ||||
| *** web: completes one account name component in add form account fields | ||||
| *** web: how to find out net worth, /register?q=assets+liabilities shows nothing | ||||
| @ -3646,3 +3933,174 @@ gather data on real-world installation & usage issues | ||||
| simplify bug reporting/handling | ||||
| improve reliability | ||||
| *** upload feature | ||||
| *** ofx reader | ||||
| **** clint's code | ||||
| Date: Sun, 18 Sep 2011 12:26:16 -0400 | ||||
| From: Clint Adams <clint@softwarefreedom.org> | ||||
| To: hledger@googlegroups.com | ||||
| Subject: OFX conversion | ||||
| Message-ID: <20110918162616.GA18874@softwarefreedom.org> | ||||
| MIME-Version: 1.0 | ||||
| User-Agent: Mutt/1.5.20 (2009-06-14) | ||||
| X-Original-Sender: clint@softwarefreedom.org | ||||
| X-Original-Authentication-Results: gmr-mx.google.com; spf=pass (google.com: | ||||
|  domain of clint@softwarefreedom.org designates 216.27.154.199 as permitted | ||||
|  sender) smtp.mail=clint@softwarefreedom.org | ||||
| Reply-To: hledger@googlegroups.com | ||||
| Precedence: list | ||||
| Mailing-list: list hledger@googlegroups.com; contact hledger+owners@googlegroups.com | ||||
| List-ID: <hledger.googlegroups.com> | ||||
| X-Google-Group-Id: 895107692464 | ||||
| List-Post: <http://groups.google.com/group/hledger/post?hl=en_US>, <mailto:hledger@googlegroups.com> | ||||
| List-Help: <http://groups.google.com/support/?hl=en_US>, <mailto:hledger+help@googlegroups.com> | ||||
| List-Archive: <http://groups.google.com/group/hledger?hl=en_US> | ||||
| Sender: hledger@googlegroups.com | ||||
| List-Subscribe: <http://groups.google.com/group/hledger/subscribe?hl=en_US>, <mailto:hledger+subscribe@googlegroups.com> | ||||
| List-Unsubscribe: <http://groups.google.com/group/hledger/subscribe?hl=en_US>, <mailto:hledger+unsubscribe@googlegroups.com> | ||||
| Content-Type: text/plain; charset=iso-8859-1 | ||||
| Content-Disposition: inline | ||||
| Content-Transfer-Encoding: 8bit | ||||
| 
 | ||||
| This is definitely suboptimal but it seems to work on | ||||
| the OFX 1.0.2 output from AmEx. | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| {-# LANGUAGE Arrows, NoMonomorphismRestriction #-} | ||||
| import Text.XML.HXT.Core | ||||
| import Text.Printf (printf) | ||||
| 
 | ||||
| import Data.List (groupBy) | ||||
| import Data.List.Split (splitOn) | ||||
| 
 | ||||
| import Data.Maybe (fromMaybe) | ||||
| 
 | ||||
| import Data.Time.Calendar (Day (ModifiedJulianDay)) | ||||
| import Data.Time.Format (formatTime) | ||||
| import Data.Time.LocalTime (LocalTime (LocalTime), TimeOfDay (TimeOfDay)) | ||||
| import Data.Time.Parse (strptime) | ||||
| 
 | ||||
| import System.Locale (defaultTimeLocale) | ||||
| import System.Process (readProcessWithExitCode) | ||||
| 
 | ||||
| import Hledger.Cli.Format (FormatString (FormatField), Field (FieldNo)) | ||||
| import Hledger.Cli.Convert | ||||
| 
 | ||||
| normAmount :: String -> String | ||||
| normAmount amt | amt == "" = "" | ||||
|     | otherwise = printf "%.2f" (read amt :: Double) | ||||
| 
 | ||||
| compressWhitespace :: String -> String | ||||
| compressWhitespace x = map head $ groupSpaces x | ||||
|         where groupSpaces "" = [""] | ||||
|               groupSpaces x = groupBy (\x y -> x==' ' && y==' ') x | ||||
| 
 | ||||
| data Transaction = Transaction | ||||
|   { trnType, dtUser, dtPosted, trnAmt, fitId, refNum, name, memo :: String } | ||||
|   deriving (Show, Eq) | ||||
| 
 | ||||
| -- this doesn't get the timezone right | ||||
| ofxDateParse :: String -> String | ||||
| ofxDateParse x = formatTime defaultTimeLocale "%Y-%m-%d" (fst (fromMaybe (LocalTime (ModifiedJulianDay 100) (TimeOfDay 0 0 0), "") (strptime "%Y%m%d%H%M%S.%OS" x))) | ||||
| 
 | ||||
| parseFakeXML string = readString [ withValidate no | ||||
|                              , withRemoveWS yes | ||||
|                              ] string | ||||
| 
 | ||||
| atTag tag = deep (isElem >>> hasName tag) | ||||
| text = getChildren >>> getText | ||||
| textAtTag tag = atTag tag >>> text | ||||
| 
 | ||||
| getTransactions = atTag "STMTTRN" >>> | ||||
|   proc l -> do | ||||
|     trnType  <- textAtTag "TRNTYPE" -< l | ||||
|     dtUser   <- textAtTag "DTUSER"         -< l | ||||
|     dtPosted <- textAtTag "DTPOSTED" -< l | ||||
|     trnAmt <- textAtTag "TRNAMT" -< l | ||||
|     fitId <- textAtTag "FITID" -< l | ||||
|     refNum <- textAtTag "REFNUM" -< l | ||||
|     name <- textAtTag "NAME" -< l | ||||
|     memo <- textAtTag "MEMO" -< l | ||||
|     returnA -< Transaction | ||||
|       { trnType   = trnType, | ||||
|         dtUser = ofxDateParse dtUser, | ||||
|         dtPosted = ofxDateParse dtPosted, | ||||
|         trnAmt     = trnAmt, | ||||
|         fitId     = fitId, | ||||
|         refNum     = refNum, | ||||
|         name     = name, | ||||
|         memo  = memo } | ||||
| 
 | ||||
| ofxrules = CsvRules { | ||||
|       dateField=Just 0, | ||||
|       dateFormat=Nothing, | ||||
|       statusField=Nothing, | ||||
|       codeField=Nothing, | ||||
|       descriptionField=[FormatField False Nothing Nothing (FieldNo 2)], | ||||
|       amountField=Just 1, | ||||
|       inField=Nothing, | ||||
|       outField=Nothing, | ||||
|       currencyField=Nothing, | ||||
|       baseCurrency=Nothing, | ||||
|       accountField=Nothing, | ||||
|       account2Field=Nothing, | ||||
|       effectiveDateField=Nothing, | ||||
|       baseAccount="Liabilities:American Express", | ||||
|       accountRules=[] | ||||
| } | ||||
| 
 | ||||
| txnToCsvRecord :: Transaction -> CsvRecord | ||||
| txnToCsvRecord x = [dtUser x, normAmount (trnAmt x), compressWhitespace (name x) ++ "(" ++ refNum x ++ ")", fitId x, memo x] | ||||
| 
 | ||||
| printTxnWithComment :: CsvRecord -> IO () | ||||
| printTxnWithComment x = putStrLn ("; " ++ x !! 3 ++ " - " ++ x !! 4) >> printTxn False ofxrules x | ||||
| 
 | ||||
| main = do | ||||
|   filecontents <- readFile "/tmp/ofx.ofx" | ||||
|   let splitfilecontents = splitOn "\n\n" filecontents | ||||
|   let ofxheader = head splitfilecontents | ||||
|   let ofxsgml = splitfilecontents !! 1 | ||||
|   (_, fakexml, _) <- readProcessWithExitCode "/usr/bin/sgml2xml" [] ofxsgml | ||||
| 
 | ||||
|   transes <- runX (parseFakeXML fakexml >>> getTransactions) | ||||
| 
 | ||||
|   let records = map txnToCsvRecord transes | ||||
|   mapM_ (printTxnWithComment) records | ||||
| 
 | ||||
| *** gnucash reader | ||||
| *** accounts: list account names by type, optionally filtered | ||||
| hledger accounts | ||||
|  -B|--balancesheet|-I|--incomestatement|-C|--cashflow| | ||||
|  -a|--assets|-l|--liabilities|-i|--income|-e|--expenses|-q|--equity | ||||
| *** config: save config properties | ||||
| hledger config accounts.asset Asset | ||||
| *** checkup: check journal for common issues | ||||
| **** parseable ? | ||||
| **** transactions balanced ? | ||||
| **** balance assertions ? | ||||
| **** balance sheet zeroed out each year ? | ||||
| **** consistent/recent entry activity ? | ||||
| *** summary: show overview report by period | ||||
|                       week               month             quarter             year | ||||
|                  this last average  this last average  this last average  this last average | ||||
| 
 | ||||
| you have        (assets) | ||||
| you almost have (receivables) | ||||
| you owe now     (payables)    | ||||
| you owe later   (liabilities) | ||||
| revenues                      | ||||
| expenses | ||||
| cash in | ||||
| cash out | ||||
| 
 | ||||
| 
 | ||||
| *** filter by commodity | ||||
| comm:EUR | ||||
| curr:USD | ||||
| c:$ | ||||
| *** parsing: ignore missing included files | ||||
| $ hledger -f .paypal.journal print | ||||
| hledger: "/Users/simon/.sm/personal/.paypal.journal" (line 2, column 1) reading /Users/simon/.sm/personal/paypal-2001.journal: | ||||
| /Users/simon/.sm/personal/paypal-2001.journal: openFile: does not exist (No such file or directory) | ||||
| 
 | ||||
| *** lift "At most one alias directive and one alias option will be applied to each account name." restriction | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user