(ns auto-ap.integration.graphql.ledger.running-balance (:require [auto-ap.datomic :refer [conn pull-attr]] [auto-ap.ledger :as sut] [iol-ion.tx :refer [upsert-ledger]] [auto-ap.integration.util :refer [wrap-setup]] [clojure.test :as t :refer [deftest is testing use-fixtures]] [datomic.api :as d])) (use-fixtures :each wrap-setup) (deftest running-balance (let [{:strs [test-account-1 test-account-2 test-client journal-entry-1 journal-entry-2 journal-entry-3 line-1-1 line-1-2 line-2-1 line-2-2 line-3-1 line-3-2]} (:tempids (d/transact conn [{:db/id "test-account-1" :account/type :account-type/asset} {:db/id "test-account-2" :account/type :account-type/equity} {:db/id "test-client" :client/code "TEST"} `(upsert-ledger {:db/id "journal-entry-1" :journal-entry/external-id "1" :journal-entry/date #inst "2022-01-01" :journal-entry/client "test-client" :journal-entry/line-items [{:db/id "line-1-1" :journal-entry-line/account "test-account-1" :journal-entry-line/location "A" :journal-entry-line/debit 10.0} {:db/id "line-1-2" :journal-entry-line/account "test-account-2" :journal-entry-line/location "A" :journal-entry-line/credit 10.0}]}) `(upsert-ledger {:db/id "journal-entry-2" :journal-entry/date #inst "2022-01-02" :journal-entry/external-id "2" :journal-entry/client "test-client" :journal-entry/line-items [{:db/id "line-2-1" :journal-entry-line/account "test-account-1" :journal-entry-line/location "A" :journal-entry-line/debit 50.0} {:db/id "line-2-2" :journal-entry-line/account "test-account-2" :journal-entry-line/location "A" :journal-entry-line/credit 50.0}]}) `(upsert-ledger {:db/id "journal-entry-3" :journal-entry/date #inst "2022-01-03" :journal-entry/external-id "3" :journal-entry/client "test-client" :journal-entry/line-items [{:db/id "line-3-1" :journal-entry-line/account "test-account-1" :journal-entry-line/location "A" :journal-entry-line/debit 150.0} {:db/id "line-3-2" :journal-entry-line/account "test-account-2" :journal-entry-line/location "A" :journal-entry-line/credit 150.0}]})]))] (testing "should set running-balance on ledger entries missing them" (sut/refresh-running-balance-cache) (println (d/pull (d/db conn) '[*] line-1-1)) (is (= [-10.0 -60.0 -210.0] (map #(pull-attr (d/db conn) :journal-entry-line/running-balance %) [line-1-1 line-2-1 line-3-1 ]))) (is (= [10.0 60.0 210.0] (map #(pull-attr (d/db conn) :journal-entry-line/running-balance %) [line-1-2 line-2-2 line-3-2])))) (testing "should recompute if the data is out of date" (d/transact conn [{:db/id line-1-1 :journal-entry-line/dirty true :journal-entry-line/running-balance 123810.23}]) (sut/refresh-running-balance-cache) (is (= [-10.0 -60.0 -210.0] (map #(pull-attr (d/db conn) :journal-entry-line/running-balance %) [line-1-1 line-2-1 line-3-1])))) (testing "should recompute every entry after the out of date one" (d/transact conn [{:db/id line-1-1 :journal-entry-line/dirty true :journal-entry-line/debit 70.0}]) (sut/refresh-running-balance-cache) (is (= [-70.0 -120.0 -270.0] (map #(pull-attr (d/db conn) :journal-entry-line/running-balance %) [line-1-1 line-2-1 line-3-1])))) (testing "should not recompute entries that aren't dirty" (d/transact conn [{:db/id line-1-1 :journal-entry-line/dirty false :journal-entry-line/debit 90.0}]) (sut/refresh-running-balance-cache) (is (= [-70.0 -120.0 -270.0] (map #(pull-attr (d/db conn) :journal-entry-line/running-balance %) [line-1-1 line-2-1 line-3-1]))) ) (testing "changing a ledger entry should mark the line items as dirty" (d/transact conn [`(upsert-ledger ~{:db/id journal-entry-2 :journal-entry/date #inst "2022-01-02" :journal-entry/client test-client :journal-entry/external-id "2" :journal-entry/line-items [{:db/id "line-2-1" :journal-entry-line/account test-account-1 :journal-entry-line/location "A" :journal-entry-line/debit 50.0} {:db/id "line-2-2" :journal-entry-line/account test-account-2 :journal-entry-line/location "A" :journal-entry-line/credit 50.0}]})]) (is (= [true true] (->> (d/pull (d/db conn) '[{:journal-entry/line-items [:journal-entry-line/dirty]}] journal-entry-2) (:journal-entry/line-items) (map :journal-entry-line/dirty)))) (testing "should also mark the next entry as dirty, so that if a ledger entry is changed, the old accounts get updated" (is (= [false false] (->> (d/pull (d/db conn) '[{:journal-entry/line-items [:journal-entry-line/dirty]}] journal-entry-1) (:journal-entry/line-items) (map :journal-entry-line/dirty)))) (is (= [true true] (->> (d/pull (d/db conn) '[{:journal-entry/line-items [:journal-entry-line/dirty]}] journal-entry-3) (:journal-entry/line-items) (map :journal-entry-line/dirty))))))))