diff --git a/src/clj/auto_ap/ssr/ledger/common.clj b/src/clj/auto_ap/ssr/ledger/common.clj index 62863789..1bebd5cd 100644 --- a/src/clj/auto_ap/ssr/ledger/common.clj +++ b/src/clj/auto_ap/ssr/ledger/common.clj @@ -203,6 +203,39 @@ result)) results)) +(defn- entries-off-reports + "Journal entries with a line posted to one of `clients`' bank accounts flagged + `:bank-account/include-in-reports` false, or nil when there are none. + + The GraphQL ledger page has always dropped these (see + auto-ap.datomic.ledger/graphql-results), so the register has to agree -- + otherwise the same entry is visible on one ledger page and missing from the + other. Resolved up front off VAET, which is ~150 entries db-wide and costs + ~2ms; excluding them inside the query with a not-join instead measured ~10x + the cost of the whole scan on a wide date range." + [db clients] + (when-let [off-reports (seq (dc/q '[:find [?ba ...] + + :in $ [?client ...] + + :where + [?client :client/bank-accounts ?ba] + [?ba :bank-account/include-in-reports false]] + db clients))] + (set (dc/q '[:find [?e ...] + + :in $ [?ba ...] + + :where + [?li :journal-entry-line/account ?ba] + [?e :journal-entry/line-items ?li]] + db off-reports)))) + +(defn- apply-include-in-reports [db clients results] + (if-let [hidden (entries-off-reports db clients)] + (remove (comp hidden last) results) + results)) + ;; TODO ;; 1. Sorting in investigate dialog ;; 2. actual date range filtering in investigate dialog @@ -375,6 +408,7 @@ (merge-query {:query {:find ['?sort-default '?e]}})))] (->> (observable-query query) + (apply-include-in-reports db valid-clients) (apply-sort-4 (assoc query-params :default-asc? true)) (apply-only-unbalanced query-params) (apply-pagination query-params)))) diff --git a/test/clj/auto_ap/ssr/ledger_test.clj b/test/clj/auto_ap/ssr/ledger_test.clj index 7454c00e..13974993 100644 --- a/test/clj/auto_ap/ssr/ledger_test.clj +++ b/test/clj/auto_ap/ssr/ledger_test.clj @@ -797,3 +797,85 @@ [:journal-entry/external-id (external-id "ext-good-1")])] (is (= 100.0 (:journal-entry/amount entry))) (is (= 2 (count (:journal-entry/line-items entry)))))))))))) + +(deftest fetch-ids-include-in-reports-test + (testing "Should leave an entry out of the register when a line posts to a bank account off reports" + (let [{:strs [reports-client shown-entry]} + (setup-test-data [(test-bank-account :db/id "shown-bank" + :bank-account/name "Shown Bank" + :bank-account/numeric-code 11000 + :bank-account/include-in-reports true) + (test-bank-account :db/id "hidden-bank" + :bank-account/name "Hidden Bank" + :bank-account/numeric-code 11001 + :bank-account/include-in-reports false) + (test-client :db/id "reports-client" + :client/code "REPORTS-TEST" + :client/locations ["HQ"] + :client/bank-accounts ["shown-bank" "hidden-bank"]) + {:db/id "reports-expense" + :account/name "Expense" + :account/numeric-code 60000 + :account/account-set "default"} + {:db/id "shown-entry" + :journal-entry/client "reports-client" + :journal-entry/date #inst "2024-03-01" + :journal-entry/amount 100.0 + :journal-entry/source "transaction" + :journal-entry/line-items + [{:journal-entry-line/account "shown-bank" + :journal-entry-line/credit 100.0} + {:journal-entry-line/account "reports-expense" + :journal-entry-line/debit 100.0}]} + {:db/id "hidden-entry" + :journal-entry/client "reports-client" + :journal-entry/date #inst "2024-03-02" + :journal-entry/amount 50.0 + :journal-entry/source "transaction" + :journal-entry/line-items + [{:journal-entry-line/account "hidden-bank" + :journal-entry-line/credit 50.0} + {:journal-entry-line/account "reports-expense" + :journal-entry-line/debit 50.0}]}]) + request {:client-id reports-client + :clients [reports-client] + :route-params {} + :query-params {}} + result (common/fetch-ids (dc/db conn) request)] + + (is (= [shown-entry] (vec (:all-ids result)))) + (is (= [shown-entry] (vec (:ids result)))) + (testing "and counts it out of the total, so the page is not silently short" + (is (= 1 (:count result)))))) + + (testing "Should keep every entry when no bank account is off reports" + (let [{:strs [open-client open-entry]} + (setup-test-data [(test-bank-account :db/id "open-bank" + :bank-account/name "Open Bank" + :bank-account/numeric-code 11002 + :bank-account/include-in-reports true) + (test-client :db/id "open-client" + :client/code "REPORTS-OPEN" + :client/locations ["HQ"] + :client/bank-accounts ["open-bank"]) + {:db/id "open-expense" + :account/name "Expense" + :account/numeric-code 60001 + :account/account-set "default"} + {:db/id "open-entry" + :journal-entry/client "open-client" + :journal-entry/date #inst "2024-03-01" + :journal-entry/amount 100.0 + :journal-entry/source "transaction" + :journal-entry/line-items + [{:journal-entry-line/account "open-bank" + :journal-entry-line/credit 100.0} + {:journal-entry-line/account "open-expense" + :journal-entry-line/debit 100.0}]}]) + result (common/fetch-ids (dc/db conn) {:client-id open-client + :clients [open-client] + :route-params {} + :query-params {}})] + + (is (= [open-entry] (vec (:all-ids result)))) + (is (= 1 (:count result))))))