Browse Source

Merge branch 'split-sub-transactions' into 'master'

Let the user split sub-transactions

See merge request nico/elbank!9
custom-labels
Nicolas Petton 3 years ago
parent
commit
817047305e
2 changed files with 103 additions and 19 deletions
  1. +30
    -19
      elbank-report.el
  2. +73
    -0
      test/elbank-report-test.el

+ 30
- 19
elbank-report.el View File

@ -26,6 +26,8 @@
(require 'seq)
(require 'map)
(require 'subr-x)
(require 'cl-lib)
(require 'button)
(require 'elbank-common)
@ -350,29 +352,38 @@ point."
(elbank-write-data elbank-data)
(elbank-report-refresh))
(defun elbank-report-split-transaction ()
"Split the transaction at point.
(defun elbank-report--split-amount (amount)
"Split amount into a list of (CATEGORY-NAME . AMOUNT)."
(let ((amount-left amount)
(categories (list)))
(while (not (zerop amount-left))
(let ((sub-label (completing-read "Category: "
(map-keys elbank-categories)))
(sub-amount (read-from-minibuffer
(format "Amount (%s left): " amount-left)
(number-to-string amount-left))))
(push (cons sub-label sub-amount) categories)
(setq amount-left (/ (round (* 100 (- amount-left
(string-to-number sub-amount))))
100.0))))
categories))
(defun elbank-report-split-transaction (&optional transaction)
"Split TRANSACTION, transaction at point if nil.
Splitting is done by assigning multiple categories to
transaction, each one with an amount."
(interactive)
(let* ((trans (elbank-report--transaction-at-point))
(amount-left (string-to-number
(elbank-transaction-elt trans 'amount)))
(categories '()))
(when (elbank-sub-transaction-p trans)
(user-error "Cannot split sub transactions"))
(while (not (zerop amount-left))
(let ((label (completing-read "Category: "
(map-keys elbank-categories)))
(amount (read-from-minibuffer
(format "Amount (%s left): " amount-left)
(number-to-string amount-left))))
(push (cons label amount) categories)
(setq amount-left (/ (round (* 100 (- amount-left
(string-to-number amount))))
100.0 ))))
(elbank-report-set-category categories)))
(let* ((trans (or transaction (elbank-report--transaction-at-point)))
(amount (elbank-transaction-elt trans 'amount)))
(if (elbank-sub-transaction-p trans)
(let* ((main-transaction (elbank-transaction-elt trans 'split-from))
(sub-category (map-elt trans 'category))
(all-categories (map-elt main-transaction 'category))
(other-categories (cl-remove (cons sub-category amount) all-categories :count 1 :test #'equal))
(new-sub-categories (elbank-report--split-amount (string-to-number amount))))
(elbank-report-set-category (append other-categories new-sub-categories) main-transaction))
(elbank-report-set-category (elbank-report--split-amount (string-to-number amount)) trans))))
(defun elbank-report-unsplit-transaction ()
"Unsplit the parent of the sub transaction at point.


+ 73
- 0
test/elbank-report-test.el View File

@ -0,0 +1,73 @@
;;; elbank-report-test.el --- Unit tests for elbank-report.el -*- lexical-binding: t; -*-
;; Copyright (C) 2017-2018 Nicolas Petton
;; Author: Nicolas Petton <nicolas@petton.fr>
;; Keywords: test
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;; Tests for elbank-report.el
;;; Code:
(require 'buttercup)
(require 'elbank-report)
(describe "Splitting transaction"
(spy-on 'elbank-report-set-category)
(spy-on 'elbank-report--split-amount :and-return-value '(("foo" . "1500") ("bar" . "500")))
(describe "should split a non-splitted transaction"
(it "with a category"
(let* ((transaction '((amount . "2000") (category . "Expenses"))))
(elbank-report-split-transaction transaction)
(expect 'elbank-report-set-category
:to-have-been-called-with '(("foo" . "1500") ("bar" . "500")) transaction)))
(it "with no category"
(let* ((transaction '((amount . "2000"))))
(elbank-report-split-transaction transaction)
(expect 'elbank-report-set-category
:to-have-been-called-with '(("foo" . "1500") ("bar" . "500")) transaction))))
(describe "should split a sub-transaction"
(it "with different categories"
(let* ((main-transaction '((amount . "3000")
(category . (("cat1" . "1000") ("cat2" . "2000")))))
(sub-transaction `((amount . "2000")
(category . "cat2")
(split-from . ,main-transaction))))
(elbank-report-split-transaction sub-transaction)
(expect 'elbank-report-set-category
:to-have-been-called-with '(("cat1" . "1000")
("foo" . "1500")
("bar" . "500")) main-transaction))))
(it "with 2 identical sub-transactions"
(let* ((main-transaction '((amount . "4000")
(category . (("cat1" . "2000") ("cat1" . "2000")))))
(sub-transaction `((amount . "2000")
(category . "cat1")
(split-from . ,main-transaction))))
(elbank-report-split-transaction sub-transaction)
(expect 'elbank-report-set-category
:to-have-been-called-with '(("cat1" . "2000")
("foo" . "1500")
("bar" . "500")) main-transaction))))
(provide 'elbank-report-test)
;;; elbank-report-test.el ends here

Loading…
Cancel
Save