emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: Stefan Huchler <stefan.huchler@mail.de>
To: emacs-orgmode@gnu.org
Subject: org-capture template to type in bills from shops in ledger format
Date: Sun, 02 Jun 2019 02:05:04 +0200	[thread overview]
Message-ID: <87woi4rgwf.fsf@mail.de> (raw)

I wrote this template to capture my bills from mostly one shop, but it
has support for multiple shops and the important feature is that it
suggests previous item names and remembers last prices, that gives you
lot's of autocompletion if you repetetivly buy often the same stuff over
and over again.

#+begin_src emacs-lisp
%(let* ((default-directory (file-name-directory "%F"))
	(map-file "shop-items.txt"))
   (load-file "helper.el")
   (require 'dash)
   (let* ((shops (if (file-exists-p map-file)
		     (read-from-file map-file) '()))
	  (names (mapcar 'car shops))
	  (shop-name (ido-completing-read "Shop: " names nil nil nil))
	  (new-prices) (new-names) (new-amounts)
	  (products (assoc-default shop-name shops)))
     (while (let* ((names (mapcar 'car products))
     		   (name (ido-completing-read "Name: " names))
       		   (amount (read-number "Amount: " 1))
     		   (item (alist-get name products))
     		   (item (if (stringp item) (string-to-number item) item))
       		   (price (read-number "Price: " (or item 2.00))))
     	      (setq new-names (append new-names (list name)))
     	      (setq new-prices (append new-prices (list price)))	   
     	      (setq new-amounts (append new-amounts (list amount)))
     	      (y-or-n-p "More items? ")))
     (let* ((-compare-fn (lambda (x y) (equal (car x) (car y))))
     	    (new-products (mapcar* 'cons new-names new-prices))
     	    (combined-products (-distinct (append new-products products)))
	    (combined-shops (-distinct (append `((,shop-name . ,combined-products)) shops)))
     	    (format-string "      expenses:food:%s \t\t%s St @ =€%s")
     	    (format-function (lambda (name amount price)
     			       (format format-string name amount price)))
	    (product-lines (mapcar* format-function new-names
     					     new-amounts new-prices))
     	    (shopping-items (s-join "\n" product-lines))
     	    (total (reduce '+ (mapcar* '* new-amounts new-prices))))
       (print-to-file map-file combined-shops)
       (concat (format "  %(org-read-date nil nil) * %s\n%s"
     		       shop-name shopping-items)
     	       (format "\n      assets:bank:chequing\t\t€-%s"
       		       (read-string "Total: " (format "%.2f" total)))))))
#+end_src

Any thoughts? It's supposed to output into a org file with a embeded
ledger src block so you would have to check the alignment if you would
want to output to a normal ledger file.

here are the 2 functions from helper.el:

#+begin_src emacs-lisp
(defun print-to-file (filename data)
  (with-temp-file filename
    (let* ((print-length 5000))
      (prin1 data (current-buffer)))))

(defun read-from-file (filename)
  (with-temp-buffer
    (insert-file-contents filename)
    (cl-assert (eq (point) (point-min)))
    (read (current-buffer))))
#+end_src

Maybe that's useful for somebody else or somebody wants to suggest other
features or something. The only thing I would maybe consider to switch
is to use a json format for the shop-items.txt for the prices for easier
manual editing.

that's how I set it up:

#+begin_src emacs-lisp
("s" "(S)hopping" plain
	 (file+function "path/finances.org"
			(lambda () ""
			  (progn (org-babel-goto-named-src-block "balance")   
				 (org-babel-goto-src-block-head)(forward-line))))
	 "%[~/capture-templates/template-name]" 
	 :jump-to-captured t
	 :empty-lines-after 1
	 :immediate-finish nil)
#+end_src         

             reply	other threads:[~2019-06-02  0:17 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-06-02  0:05 Stefan Huchler [this message]
2019-06-02 13:37 ` org-capture template to type in bills from shops in ledger format Michael Welle
2019-06-04 16:42   ` Stefan Huchler
2019-06-22 14:14 ` Stefan Huchler

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.orgmode.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87woi4rgwf.fsf@mail.de \
    --to=stefan.huchler@mail.de \
    --cc=emacs-orgmode@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).