(cloud) running balance update way more streamlined now
This commit is contained in:
@@ -170,77 +170,34 @@
|
||||
lms)))
|
||||
->graphql)))
|
||||
|
||||
(defn refresh-bank-account-current-balance [bank-account-id]
|
||||
(let [all-transactions (dc/q
|
||||
{:query {:find ['?e '?debit '?credit]
|
||||
:in ['$ '?bank-account-id]
|
||||
:where '[[?e :journal-entry-line/account ?bank-account-id]
|
||||
[(get-else $ ?e :journal-entry-line/debit 0.0) ?debit]
|
||||
[(get-else $ ?e :journal-entry-line/credit 0.0) ?credit]]}
|
||||
:args [(dc/db conn) bank-account-id]})
|
||||
debits (->> all-transactions
|
||||
(map (fn [[_ debit _]]
|
||||
debit))
|
||||
(reduce + 0.0))
|
||||
credits (->> all-transactions
|
||||
(map (fn [[_ _ credit]]
|
||||
credit))
|
||||
(reduce + 0.0))
|
||||
current-balance (if (= :bank-account-type/check (:db/ident (:bank-account/type (dc/pull (dc/db conn) [:bank-account/type] bank-account-id))))
|
||||
(- debits credits)
|
||||
(- credits debits))]
|
||||
(dc/transact conn {:tx-data [{:db/id bank-account-id
|
||||
:bank-account/current-balance current-balance}]})))
|
||||
|
||||
(defn bank-accounts-needing-refresh []
|
||||
(let [last-refreshed (->> (dc/q {:query {:find ['?ba '?tx]
|
||||
:in ['$ ]
|
||||
:where ['[?ba :bank-account/current-balance _ ?tx true]]}
|
||||
:args [(dc/history (dc/db conn))]})
|
||||
(group-by first)
|
||||
(map (fn [[ba balance-txes]]
|
||||
[ba (->> balance-txes
|
||||
(map second)
|
||||
(sort-by #(- %))
|
||||
first)])))
|
||||
has-newer-transaction (->> (dc/q
|
||||
{:query {:find ['?ba]
|
||||
:in '[$ [[?ba ?last-refreshed] ...] ]
|
||||
:where ['[_ :journal-entry-line/account ?ba ?tx]
|
||||
'[(>= ?tx ?last-refreshed)]]}
|
||||
:args [(dc/history (dc/db conn))
|
||||
last-refreshed]})
|
||||
(map first)
|
||||
(set))
|
||||
|
||||
no-current-balance (->> (dc/q {:query {:find ['?ba]
|
||||
:in '[$]
|
||||
:where ['[?ba :bank-account/code]
|
||||
'(not [?ba :bank-account/current-balance])
|
||||
]}
|
||||
:args [(dc/db conn)]})
|
||||
(map first))]
|
||||
(into has-newer-transaction no-current-balance)))
|
||||
|
||||
(defn build-current-balance [bank-accounts]
|
||||
(doseq [bank-account bank-accounts]
|
||||
(log/info "Refreshing bank account" (-> (dc/db conn) (dc/pull [:bank-account/code] bank-account)))
|
||||
(try
|
||||
(refresh-bank-account-current-balance bank-account)
|
||||
(catch Exception e
|
||||
(log/error "Can't refresh current balance" e)))))
|
||||
|
||||
#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
|
||||
(defn refresh-all-current-balance []
|
||||
(lc/with-context {:source "current-balance-cache"}
|
||||
(build-current-balance (->> (dc/q {:query {:find ['?ba]
|
||||
:in '[$]
|
||||
:where ['[?ba :bank-account/code]]}
|
||||
:args [(dc/db conn)]})
|
||||
(map first)))))
|
||||
|
||||
(defn refresh-current-balance []
|
||||
(build-current-balance (bank-accounts-needing-refresh)))
|
||||
(lc/with-context {:source "current-balance-refresh"}
|
||||
(let [db (dc/db conn)
|
||||
clients (dc/q '[:find (pull ?c [:db/id :client/code {:client/bank-accounts [:db/id :bank-account/code]}])
|
||||
:where [?c :client/code]]
|
||||
db )]
|
||||
(dc/transact conn
|
||||
{:tx-data
|
||||
(for [[{client :db/id code :client/code bank-accounts :client/bank-accounts}] clients
|
||||
{bank-account :db/id bac :bank-account/code} bank-accounts]
|
||||
{:db/id bank-account
|
||||
:bank-account/current-balance
|
||||
(or
|
||||
(->> (dc/index-pull db
|
||||
{:index :avet
|
||||
:selector [:db/id :journal-entry-line/location :journal-entry-line/account :journal-entry-line/running-balance :journal-entry-line/client+account+location+date {:journal-entry/_line-items [:journal-entry/date :journal-entry/client]}]
|
||||
:start [:journal-entry-line/client+account+location+date [client bank-account "A" #inst "2030-01-01"]]
|
||||
:limit 1
|
||||
:reverse true
|
||||
})
|
||||
(filter (fn [{[c b] :journal-entry-line/client+account+location+date}]
|
||||
(and (= c client)
|
||||
(= b bank-account))))
|
||||
(map :journal-entry-line/running-balance)
|
||||
(first))
|
||||
0.0)})})))
|
||||
)
|
||||
|
||||
(defn get-client [context _ _]
|
||||
(->graphql
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
[auto-ap.jobs.core :refer [execute]]))
|
||||
|
||||
(defn -main [& _]
|
||||
(execute "current-balance-cache" clients/refresh-current-balance))
|
||||
(execute "current-balance-cache" clients/refresh-all-current-balance))
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,13 +2,12 @@
|
||||
(:require
|
||||
[auto-ap.datomic
|
||||
:refer [audit-transact
|
||||
audit-transact-batch
|
||||
transact-with-backoff
|
||||
conn
|
||||
pull-id
|
||||
pull-ref
|
||||
remove-nils]]
|
||||
[auto-ap.utils :refer [by dollars-0? dollars=]]
|
||||
remove-nils
|
||||
transact-with-backoff]]
|
||||
[auto-ap.utils :refer [by dollars-0? dollars= heartbeat]]
|
||||
[clj-time.coerce :as c]
|
||||
[clj-time.core :as t]
|
||||
[clojure.tools.logging :as log]
|
||||
@@ -17,7 +16,9 @@
|
||||
[datomic.client.api :as dc]
|
||||
[iol-ion.tx :refer [upsert-ledger]]
|
||||
[manifold.deferred :as de]
|
||||
[manifold.stream :as s]))
|
||||
[manifold.stream :as s]
|
||||
[mount.core :as mount]
|
||||
[yang.scheduler :as scheduler]))
|
||||
|
||||
(defn datums->impacted-entity [db [e changes]]
|
||||
(let [entity (dc/pull db '[{:invoice/_expense-accounts [:db/id] :transaction/_accounts [:db/id]}] e)
|
||||
@@ -754,6 +755,6 @@
|
||||
|
||||
;; TODO only enable once IOL is set up in clod
|
||||
#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
|
||||
#_(mount/defstate running-balance-cache-worker
|
||||
(mount/defstate running-balance-cache-worker
|
||||
:start (scheduler/every (* 15 60 (+ 500 (rand-int 500))) (heartbeat refresh-running-balance-cache "running-balance-cache"))
|
||||
:stop (scheduler/stop running-balance-cache-worker))
|
||||
|
||||
Reference in New Issue
Block a user