From 38ed981cba634ef0dfbfbb290bb72d76ae22482c Mon Sep 17 00:00:00 2001 From: Bryce Date: Sat, 8 Feb 2025 22:14:24 -0800 Subject: [PATCH] Recalculates running balance as report is run --- src/clj/auto_ap/ledger.clj | 135 +++++++++--------- src/clj/auto_ap/ssr/ledger/balance_sheet.clj | 8 +- .../auto_ap/ssr/ledger/profit_and_loss.clj | 6 +- 3 files changed, 79 insertions(+), 70 deletions(-) diff --git a/src/clj/auto_ap/ledger.clj b/src/clj/auto_ap/ledger.clj index 3eb9a3e9..7c714426 100644 --- a/src/clj/auto_ap/ledger.clj +++ b/src/clj/auto_ap/ledger.clj @@ -352,18 +352,23 @@ (do (println (count a)) (count a))))) -(defn clients-needing-refresh [db] - (->> - (dc/q '[:find (pull ?c [:client/code :db/id :client/ledger-last-change :client/last-running-balance]) - :in $ - :where - [?c :client/code] - [(get-else $ ?c :client/ledger-last-change #inst "2040-01-01") ?last-change] - [(get-else $ ?c :client/last-running-balance #inst "2000-01-01") ?last-running-balance] - [(> ?last-change ?last-running-balance)] ] - db) - (map (fn [[client]] - client)))) +(defn clients-needing-refresh [db available] + (let [clients (->> + (dc/q '[:find (pull ?c [:client/code :db/id :client/ledger-last-change :client/last-running-balance]) + :in $ + :where + [?c :client/code] + [(get-else $ ?c :client/ledger-last-change #inst "2040-01-01") ?last-change] + [(get-else $ ?c :client/last-running-balance #inst "2000-01-01") ?last-running-balance] + [(> ?last-change ?last-running-balance)]] + db) + (map (fn [[client]] + client)))] + (if (and (set? available) (seq available)) + (filter (comp available :db/id) clients) + clients))) + +#_(clients-needing-refresh (dc/db conn) #{ 17592273679867}) #_(comment [17592334354011 #inst "0024-08-03T07:52:58.000-00:00"] [17592302554688 #inst "0023-07-20T07:52:58.000-00:00"] @@ -422,58 +427,60 @@ :bank-account/current-balance running-balance}]))))))) ;; TODO using iol-ion query as the base, building running balance sets -(defn upsert-running-balance [] - (mu/with-context {:service "upsert-running-balance" - :source "upsert-running-balance" } - (mu/trace ::updating-balance - [:service "upsert-running-balance" - :source "upsert-running-balance" ] - (let [db (dc/db conn) - starting-at (c/to-date (t/now)) - clients (clients-needing-refresh db) - _ (alog/info ::clients-needing-update :clients clients :count (count clients)) - client-change-stats (atom {}) - changes (for [c clients - :let [client-id (:db/id c) - account-lookup (build-account-lookup client-id)] - running-balance-set (account-sets db client-id) - running-balance-change (->> running-balance-set - (reduce - (fn [{:keys [changes last-running-balance]} - ^Line line-item] - #_(if (= 0 (rand-int 1000)) - (println (.-account-id line-item) (.-debit line-item) (.-credit line-item))) - (let [delta (if (#{:account-type/asset - :account-type/dividend - :account-type/expense} (:account_type (account-lookup (.-account-id line-item)))) - (- (or (.-debit line-item) 0.0) (or (.-credit line-item) 0.0)) - (- (or (.-credit line-item) 0.0) (or (.-debit line-item) 0.0))) - correct-running-balance (+ last-running-balance delta) - running-balance-changed? (not (dollars= correct-running-balance (or (.-running-balance line-item) 0.0)))] - (when running-balance-changed? - (swap! client-change-stats update (:client/code c) (fnil inc 0))) - (cond-> {:last-account-lookup account-lookup - :last-running-balance correct-running-balance - :changes changes} - - running-balance-changed? - (update :changes conj {:db/id (.-id line-item) - :journal-entry-line/running-balance correct-running-balance})))) - {:last-running-balance 0.0}) - :changes)] - running-balance-change)] - - (mu/trace ::update-running-balance [] - (auto-ap.datomic/audit-transact-batch changes - {:user/name "running balance updater"})) - (auto-ap.datomic/audit-transact (mapv (fn [c] - {:db/id (:db/id c) - :client/last-running-balance starting-at}) - clients) - {:user/name "running balance updater"}) - (alog/info ::change-stats :stats @client-change-stats) - (refresh-bank-account-balances (map :db/id clients)) - (count changes))))) +(defn upsert-running-balance + ([] (upsert-running-balance nil)) + ([clients] + (mu/with-context {:service "upsert-running-balance" + :source "upsert-running-balance"} + (mu/trace ::updating-balance + [:service "upsert-running-balance" + :source "upsert-running-balance"] + (let [db (dc/db conn) + starting-at (c/to-date (t/now)) + clients (clients-needing-refresh db clients) + _ (alog/info ::clients-needing-update :clients clients :count (count clients)) + client-change-stats (atom {}) + changes (for [c clients + :let [client-id (:db/id c) + account-lookup (build-account-lookup client-id)] + running-balance-set (account-sets db client-id) + running-balance-change (->> running-balance-set + (reduce + (fn [{:keys [changes last-running-balance]} + ^Line line-item] + #_(if (= 0 (rand-int 1000)) + (println (.-account-id line-item) (.-debit line-item) (.-credit line-item))) + (let [delta (if (#{:account-type/asset + :account-type/dividend + :account-type/expense} (:account_type (account-lookup (.-account-id line-item)))) + (- (or (.-debit line-item) 0.0) (or (.-credit line-item) 0.0)) + (- (or (.-credit line-item) 0.0) (or (.-debit line-item) 0.0))) + correct-running-balance (+ last-running-balance delta) + running-balance-changed? (not (dollars= correct-running-balance (or (.-running-balance line-item) 0.0)))] + (when running-balance-changed? + (swap! client-change-stats update (:client/code c) (fnil inc 0))) + (cond-> {:last-account-lookup account-lookup + :last-running-balance correct-running-balance + :changes changes} + + running-balance-changed? + (update :changes conj {:db/id (.-id line-item) + :journal-entry-line/running-balance correct-running-balance})))) + {:last-running-balance 0.0}) + :changes)] + running-balance-change)] + + (mu/trace ::update-running-balance [] + (auto-ap.datomic/audit-transact-batch changes + {:user/name "running balance updater"})) + (auto-ap.datomic/audit-transact (mapv (fn [c] + {:db/id (:db/id c) + :client/last-running-balance starting-at}) + clients) + {:user/name "running balance updater"}) + (alog/info ::change-stats :stats @client-change-stats) + (refresh-bank-account-balances (map :db/id clients)) + (count changes)))))) (comment (pull-id (dc/db conn) [:client/code "SCCB"]) diff --git a/src/clj/auto_ap/ssr/ledger/balance_sheet.clj b/src/clj/auto_ap/ssr/ledger/balance_sheet.clj index 5b25664a..185faba3 100644 --- a/src/clj/auto_ap/ssr/ledger/balance_sheet.clj +++ b/src/clj/auto_ap/ssr/ledger/balance_sheet.clj @@ -4,7 +4,7 @@ [auto-ap.datomic :refer [conn pull-many]] [auto-ap.graphql.utils :refer [assert-can-see-client]] - [auto-ap.ledger :refer [build-account-lookup]] + [auto-ap.ledger :refer [build-account-lookup upsert-running-balance]] [auto-ap.ledger.reports :as l-reports] [auto-ap.logging :as alog] [auto-ap.pdf.ledger :refer [table->pdf]] @@ -72,6 +72,8 @@ _ (doseq [client-id client-ids] (assert-can-see-client (:identity request) client-id)) + _ (upsert-running-balance (into #{} client-ids)) + lookup-account (->> client-ids (map (fn build-lookup [client-id] [client-id (build-account-lookup client-id)])) @@ -184,10 +186,10 @@ (defn make-balance-sheet-pdf [request report] - (let [ output-stream (ByteArrayOutputStream.) + (let [output-stream (ByteArrayOutputStream.) client-count (count (or (seq (:client (:query-params request))) (seq (:client (:form-params request))))) - date (:date (:query-params request))] + date (:date (:query-params request)) ] (pdf/pdf (-> [{:left-margin 10 :right-margin 10 :top-margin 15 :bottom-margin 15 :size :letter diff --git a/src/clj/auto_ap/ssr/ledger/profit_and_loss.clj b/src/clj/auto_ap/ssr/ledger/profit_and_loss.clj index 4580ca79..30e33fe3 100644 --- a/src/clj/auto_ap/ssr/ledger/profit_and_loss.clj +++ b/src/clj/auto_ap/ssr/ledger/profit_and_loss.clj @@ -4,7 +4,7 @@ [auto-ap.datomic :refer [conn pull-many]] [auto-ap.graphql.utils :refer [assert-can-see-client]] - [auto-ap.ledger :refer [build-account-lookup]] + [auto-ap.ledger :refer [build-account-lookup upsert-running-balance]] [auto-ap.ledger.reports :as l-reports] [auto-ap.logging :as alog] [auto-ap.pdf.ledger :refer [table->pdf]] @@ -33,8 +33,7 @@ [config.core :refer [env] :as env] [datomic.api :as dc] [iol-ion.utils :refer [by]] - [malli.core :as mc] - [medley.core :refer [map-vals]]) + [malli.core :as mc]) (:import [java.util UUID] [org.apache.commons.io.output ByteArrayOutputStream])) @@ -76,6 +75,7 @@ (when (and (seq periods) client) (let [client (if (= :all client) (take 5 (:clients request)) client) client-ids (map :db/id client) + _ (upsert-running-balance (into #{} client-ids)) _ (doseq [client-id client-ids] (assert-can-see-client (:identity request) client-id))