fix(reports): collapse accounts sharing a numeric code to one row
A client's bank account and the financial account it posts to carry the same numeric code. Reports keyed their detail rows on [code, name], so the pair rendered as two rows — one labelled for the bank account, one for the financial account. The amount was duplicated too, not just the label: the row's figure is filtered by code alone, so both rows printed the whole code's total. The group subtotal counts the code once, so a section's visible rows stopped footing to their own subtotal. Penelope's Coffee and Tea overshot the 2000 Accounts Payable subtotal by $251,751.80 this way. Resolve it in two places: - build-account-lookup now maps every account at a shared code down to the bank account's name, per client. Where a client has two bank accounts on one code, lowest :bank-account/sort-order wins, then lowest :db/id, so the label is stable across runs. - used-accounts now keys rows on the code alone. Across a multi-client report the clients can still disagree, since only some of them have a bank account at the code; a bank-sourced name wins there, which the new :bank_account_name? flag carries through from the lookup. Rows are code-keyed now, so detail-rows decides whether to print a figure by asking whether the client has data at the code rather than under the winning name — otherwise a client reaching a code under a name another client won would blank out. Balance sheet, profit and loss and cash flows all route through used-accounts and are all fixed. The GraphQL and cljs balance sheets pick up the unified name through build-account-lookup. A sweep of all 146 clients with bank accounts finds duplicate rows on 8 of them before this change and none after, with every section total unchanged.
This commit is contained in:
@@ -1,10 +1,98 @@
|
||||
(ns auto-ap.ledger-test
|
||||
(:require
|
||||
[auto-ap.integration.util :refer [wrap-setup]]
|
||||
[clojure.test :as t]))
|
||||
[auto-ap.datomic :refer [conn]]
|
||||
[auto-ap.integration.util :refer [test-account test-bank-account test-client
|
||||
wrap-setup]]
|
||||
[auto-ap.ledger :refer [build-account-lookup]]
|
||||
[clojure.test :as t]
|
||||
[datomic.api :as dc]))
|
||||
|
||||
(t/use-fixtures :each wrap-setup)
|
||||
|
||||
(t/deftest build-account-lookup-prefers-the-bank-account-name
|
||||
(t/testing "a bank account and the financial account sharing its code resolve to one name"
|
||||
(let [{:strs [client bank financial]}
|
||||
(:tempids @(dc/transact conn
|
||||
[(test-account :db/id "financial"
|
||||
:account/name "Accounts Payable 10"
|
||||
:account/numeric-code 21010
|
||||
:account/type :account-type/liability)
|
||||
(test-client :db/id "client"
|
||||
:client/bank-accounts
|
||||
[(test-bank-account :db/id "bank"
|
||||
:bank-account/name "Capital One CC - 3196"
|
||||
:bank-account/numeric-code 21010
|
||||
:bank-account/type :bank-account-type/credit)])]))
|
||||
lookup (build-account-lookup client)]
|
||||
|
||||
(t/is (= "Capital One CC - 3196" (:name (lookup bank))))
|
||||
(t/is (= "Capital One CC - 3196" (:name (lookup financial)))
|
||||
"the financial account takes the bank account's name, so reports render one row")
|
||||
|
||||
(t/testing "and both are flagged as bank-named for downstream report labelling"
|
||||
(t/is (true? (:bank_account_name? (lookup bank))))
|
||||
(t/is (true? (:bank_account_name? (lookup financial)))))
|
||||
|
||||
(t/testing "without changing the code or the account type"
|
||||
(t/is (= 21010 (:numeric_code (lookup bank))))
|
||||
(t/is (= 21010 (:numeric_code (lookup financial))))
|
||||
(t/is (= :account-type/liability (:account_type (lookup financial))))))))
|
||||
|
||||
(t/deftest build-account-lookup-leaves-unshared-codes-alone
|
||||
(t/testing "an account with no bank account at its code keeps its own name"
|
||||
(let [{:strs [client financial]}
|
||||
(:tempids @(dc/transact conn
|
||||
[(test-account :db/id "financial"
|
||||
:account/name "Sales Taxes Payable"
|
||||
:account/numeric-code 23000
|
||||
:account/type :account-type/liability)
|
||||
(test-client :db/id "client"
|
||||
:client/bank-accounts
|
||||
[(test-bank-account :db/id "bank"
|
||||
:bank-account/name "Capital One CC - 3196"
|
||||
:bank-account/numeric-code 21010
|
||||
:bank-account/type :bank-account-type/credit)])]))
|
||||
lookup (build-account-lookup client)]
|
||||
(t/is (= "Sales Taxes Payable" (:name (lookup financial))))
|
||||
(t/is (false? (:bank_account_name? (lookup financial))))))
|
||||
|
||||
(t/testing "another client's bank account never renames this client's accounts"
|
||||
(let [{:strs [mine financial]}
|
||||
(:tempids @(dc/transact conn
|
||||
[(test-account :db/id "financial"
|
||||
:account/name "Accounts Payable 10"
|
||||
:account/numeric-code 21010
|
||||
:account/type :account-type/liability)
|
||||
(test-client :db/id "mine")
|
||||
(test-client :db/id "theirs"
|
||||
:client/bank-accounts
|
||||
[(test-bank-account :db/id "bank"
|
||||
:bank-account/name "Capital One CC - 3196"
|
||||
:bank-account/numeric-code 21010
|
||||
:bank-account/type :bank-account-type/credit)])]))
|
||||
lookup (build-account-lookup mine)]
|
||||
(t/is (= "Accounts Payable 10" (:name (lookup financial))))
|
||||
(t/is (false? (:bank_account_name? (lookup financial)))))))
|
||||
|
||||
(t/deftest build-account-lookup-breaks-ties-between-bank-accounts
|
||||
(t/testing "two bank accounts on one code resolve deterministically by sort-order"
|
||||
(let [{:strs [client first-bank second-bank]}
|
||||
(:tempids @(dc/transact conn
|
||||
[(test-client :db/id "client"
|
||||
:client/bank-accounts
|
||||
[(test-bank-account :db/id "second-bank"
|
||||
:bank-account/name "US Bank 2974"
|
||||
:bank-account/numeric-code 13101
|
||||
:bank-account/sort-order 3)
|
||||
(test-bank-account :db/id "first-bank"
|
||||
:bank-account/name "Fremont Gyro HB Main 8576"
|
||||
:bank-account/numeric-code 13101
|
||||
:bank-account/sort-order 0)])]))
|
||||
lookup (build-account-lookup client)]
|
||||
(t/is (= "Fremont Gyro HB Main 8576"
|
||||
(:name (lookup first-bank))
|
||||
(:name (lookup second-bank)))))))
|
||||
|
||||
(t/deftest entity-change->ledger
|
||||
#_(t/testing "Should code an expected deposit"
|
||||
(let [{:strs [ed ccp receipts-split client]}
|
||||
|
||||
Reference in New Issue
Block a user