started work on bank comparisons.
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -215,6 +215,11 @@
|
|||||||
:db/cardinality #:db{:ident :db.cardinality/one},
|
:db/cardinality #:db{:ident :db.cardinality/one},
|
||||||
:db/doc "A precomputed balance for the account",
|
:db/doc "A precomputed balance for the account",
|
||||||
:db/ident :bank-account/current-balance}
|
:db/ident :bank-account/current-balance}
|
||||||
|
{:db/valueType #:db{:ident :db.type/instant},
|
||||||
|
:db/noHistory true,
|
||||||
|
:db/cardinality #:db{:ident :db.cardinality/one},
|
||||||
|
:db/doc "A precomputed balance for the account",
|
||||||
|
:db/ident :bank-account/current-balance-synced}
|
||||||
{:db/valueType #:db{:ident :db.type/long},
|
{:db/valueType #:db{:ident :db.type/long},
|
||||||
:db/cardinality #:db{:ident :db.cardinality/one},
|
:db/cardinality #:db{:ident :db.cardinality/one},
|
||||||
:db/doc "The numeric code for the balance sheet",
|
:db/doc "The numeric code for the balance sheet",
|
||||||
@@ -1619,6 +1624,11 @@
|
|||||||
:db/cardinality #:db{:ident :db.cardinality/one},
|
:db/cardinality #:db{:ident :db.cardinality/one},
|
||||||
:db/doc "Yodlee account id",
|
:db/doc "Yodlee account id",
|
||||||
:db/ident :yodlee-account/id}
|
:db/ident :yodlee-account/id}
|
||||||
|
{:db/valueType #:db{:ident :db.type/instant},
|
||||||
|
:db/noHistory true,
|
||||||
|
:db/cardinality #:db{:ident :db.cardinality/one},
|
||||||
|
:db/doc "A precomputed balance for the account",
|
||||||
|
:db/ident :yodlee-account/last-synced}
|
||||||
{:db/valueType #:db{:ident :db.type/string},
|
{:db/valueType #:db{:ident :db.type/string},
|
||||||
:db/cardinality #:db{:ident :db.cardinality/one},
|
:db/cardinality #:db{:ident :db.cardinality/one},
|
||||||
:db/doc "account name",
|
:db/doc "account name",
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
[auto-ap.graphql.utils
|
[auto-ap.graphql.utils
|
||||||
:refer [->graphql <-graphql assert-admin attach-tracing-resolvers
|
:refer [->graphql <-graphql assert-admin attach-tracing-resolvers
|
||||||
can-see-client? is-admin? result->page]]
|
can-see-client? is-admin? result->page]]
|
||||||
|
[clj-time.coerce :as c]
|
||||||
|
[clj-time.core :as time]
|
||||||
[clojure.set :as set]
|
[clojure.set :as set]
|
||||||
[com.brunobonacci.mulog :as mu]
|
[com.brunobonacci.mulog :as mu]
|
||||||
[datomic.api :as dc]))
|
[datomic.api :as dc]))
|
||||||
@@ -13,24 +15,27 @@
|
|||||||
(let [db (dc/db conn)
|
(let [db (dc/db conn)
|
||||||
clients (dc/q '[:find (pull ?c [:db/id :client/code {:client/bank-accounts [:db/id :bank-account/code]}])
|
clients (dc/q '[:find (pull ?c [:db/id :client/code {:client/bank-accounts [:db/id :bank-account/code]}])
|
||||||
:where [?c :client/code]]
|
:where [?c :client/code]]
|
||||||
db )]
|
db)]
|
||||||
(doseq [[{client :db/id code :client/code bank-accounts :client/bank-accounts}] clients
|
(doseq [[{client :db/id code :client/code bank-accounts :client/bank-accounts}] clients
|
||||||
{bank-account :db/id bac :bank-account/code} bank-accounts]
|
{bank-account :db/id bac :bank-account/code} bank-accounts]
|
||||||
@(dc/transact conn [{:db/id bank-account
|
@(dc/transact conn [{:db/id bank-account
|
||||||
:bank-account/current-balance
|
:bank-account/current-balance-synced (c/to-date (time/now))
|
||||||
(or
|
:bank-account/current-balance
|
||||||
(->> (dc/index-pull db
|
(or
|
||||||
{:index :avet
|
(->> (dc/index-pull db
|
||||||
: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]}]
|
{:index :avet
|
||||||
:start [:journal-entry-line/client+account+location+date [client bank-account "A" #inst "2030-01-01"]]
|
: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]}]
|
||||||
:reverse true
|
:start [:journal-entry-line/client+account+location+date [client bank-account "A" #inst "2030-01-01"]]
|
||||||
})
|
:reverse true})
|
||||||
(filter (fn [{[c b] :journal-entry-line/client+account+location+date}]
|
(take 3)
|
||||||
(and (= c client)
|
|
||||||
(= b bank-account))))
|
(filter (fn [{[c b] :journal-entry-line/client+account+location+date}]
|
||||||
(map :journal-entry-line/running-balance)
|
(and (= c client)
|
||||||
(first))
|
(= b bank-account))))
|
||||||
0.0)}])))))
|
|
||||||
|
(map :journal-entry-line/running-balance)
|
||||||
|
(first))
|
||||||
|
0.0)}])))))
|
||||||
|
|
||||||
(defn get-client [context _ _]
|
(defn get-client [context _ _]
|
||||||
(->graphql
|
(->graphql
|
||||||
|
|||||||
@@ -96,4 +96,3 @@
|
|||||||
:intuit-bank-account/last-synced (coerce/to-date (:last-updated ba))
|
:intuit-bank-account/last-synced (coerce/to-date (:last-updated ba))
|
||||||
:intuit-bank-account/current-balance (:current-balance ba)}))
|
:intuit-bank-account/current-balance (:current-balance ba)}))
|
||||||
bank-accounts))))
|
bank-accounts))))
|
||||||
|
|
||||||
|
|||||||
@@ -35,5 +35,39 @@
|
|||||||
|
|
||||||
(require 'auto-ap.time_reader)
|
(require 'auto-ap.time_reader)
|
||||||
|
|
||||||
|
(let [start #clj-time/date-time "2024-02-01"
|
||||||
|
end #clj-time/date-time "2024-04-01"]
|
||||||
|
(for [[ib ba c] (seq (get-intuit-bank-accounts (dc/db conn) "BCFM"))
|
||||||
|
:let [raw-transactions (i/get-transactions (atime/unparse-local start atime/iso-date)
|
||||||
|
(atime/unparse-local end atime/iso-date)
|
||||||
|
ib)
|
||||||
|
ideal-transactions (intuits->transactions raw-transactions ba c)
|
||||||
|
|
||||||
|
found-transactions (when (seq ideal-transactions)
|
||||||
|
(into {} (dc/q '[:find ?si (count ?t)
|
||||||
|
:in $ [?eid ...]
|
||||||
|
:where
|
||||||
|
[?t :transaction/id ?eid]
|
||||||
|
[?t :transaction/approval-status ?s]
|
||||||
|
[?s :db/ident ?si]]
|
||||||
|
(dc/db conn)
|
||||||
|
(map :transaction/id ideal-transactions))))
|
||||||
|
|
||||||
|
missing-transaction-ids (when (seq ideal-transactions)
|
||||||
|
(->>
|
||||||
|
(dc/q '[:find ?eid
|
||||||
|
:in $ [?eid ...]
|
||||||
|
:where (not [_ :transaction/id ?eid])]
|
||||||
|
(dc/db conn)
|
||||||
|
(map :transaction/id ideal-transactions))
|
||||||
|
(map first)
|
||||||
|
(into #{})))
|
||||||
|
missing-transactions (filter (comp missing-transaction-ids :transaction/id) ideal-transactions)]]
|
||||||
|
{:bank-account/name (pull-attr (dc/db conn) :bank-account/name ba)
|
||||||
|
:external-transaction-count (count raw-transactions)
|
||||||
|
:integreat-transaction-count (reduce + 0 (vals found-transactions))
|
||||||
|
:approved-count (:transaction-approval-status/approved found-transactions 0)
|
||||||
|
:unapproved-count (:transaction-approval-status/unapproved found-transactions 0)
|
||||||
|
:requires-feedback-count (:transaction-approval-status/requires-feedback found-transactions 0)
|
||||||
|
:missing-transactions missing-transactions}))
|
||||||
|
|
||||||
|
|||||||
@@ -575,7 +575,6 @@
|
|||||||
(refresh-running-balance-accounts accounts-needing-rebuild clients c i db)
|
(refresh-running-balance-accounts accounts-needing-rebuild clients c i db)
|
||||||
(mu/log ::client-completed))))))))
|
(mu/log ::client-completed))))))))
|
||||||
|
|
||||||
|
|
||||||
;; TODO only enable once IOL is set up in clod
|
;; TODO only enable once IOL is set up in clod
|
||||||
#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
|
#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
|
||||||
(mount/defstate running-balance-cache-worker
|
(mount/defstate running-balance-cache-worker
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
[auto-ap.ssr.admin.transaction-rules :as admin-rules]
|
[auto-ap.ssr.admin.transaction-rules :as admin-rules]
|
||||||
[auto-ap.ssr.admin.vendors :as admin-vendors]
|
[auto-ap.ssr.admin.vendors :as admin-vendors]
|
||||||
[auto-ap.ssr.auth :as auth]
|
[auto-ap.ssr.auth :as auth]
|
||||||
|
[auto-ap.ssr.dashboard :as dashboard]
|
||||||
[auto-ap.ssr.company :as company]
|
[auto-ap.ssr.company :as company]
|
||||||
[auto-ap.ssr.company-dropdown :as company-dropdown]
|
[auto-ap.ssr.company-dropdown :as company-dropdown]
|
||||||
[auto-ap.ssr.company.company-1099 :as company-1099]
|
[auto-ap.ssr.company.company-1099 :as company-1099]
|
||||||
@@ -98,6 +99,7 @@
|
|||||||
(into admin-vendors/key->handler)
|
(into admin-vendors/key->handler)
|
||||||
(into admin-clients/key->handler)
|
(into admin-clients/key->handler)
|
||||||
(into admin-rules/key->handler)
|
(into admin-rules/key->handler)
|
||||||
|
(into dashboard/key->handler)
|
||||||
(into indicators/key->handler)
|
(into indicators/key->handler)
|
||||||
(into payments/key->handler)
|
(into payments/key->handler)
|
||||||
(into oin/route->handler)))
|
(into oin/route->handler)))
|
||||||
|
|||||||
73
src/clj/auto_ap/ssr/dashboard.clj
Normal file
73
src/clj/auto_ap/ssr/dashboard.clj
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
(ns auto-ap.ssr.dashboard
|
||||||
|
(:require [auto-ap.datomic :refer [conn]]
|
||||||
|
[auto-ap.routes.dashboard :as d-routes]
|
||||||
|
[auto-ap.routes.utils :refer [wrap-admin
|
||||||
|
wrap-client-redirect-unauthenticated]]
|
||||||
|
[auto-ap.ssr-routes :as ssr-routes]
|
||||||
|
[auto-ap.ssr.components :as com]
|
||||||
|
[auto-ap.ssr.ui :refer [base-page]]
|
||||||
|
[auto-ap.ssr.utils :refer [apply-middleware-to-all-handlers]]
|
||||||
|
[bidi.bidi :as bidi]
|
||||||
|
[datomic.api :as dc]
|
||||||
|
[auto-ap.time :as atime]))
|
||||||
|
|
||||||
|
(defn- page-contents [request]
|
||||||
|
[:div
|
||||||
|
[:h1.text-2xl.font-bold "Bank Accounts"]
|
||||||
|
(com/card {:class "inline-block"}
|
||||||
|
[:div.inline-flex.flex-wrap
|
||||||
|
(for [c (:clients request)
|
||||||
|
b (:client/bank-accounts (dc/pull (dc/db conn) '[{ :client/bank-accounts
|
||||||
|
[:bank-account/current-balance
|
||||||
|
[ :bank-account/current-balance-synced :xform clj-time.coerce/from-date]
|
||||||
|
:bank-account/name
|
||||||
|
{:bank-account/intuit-bank-account [:intuit-bank-account/current-balance
|
||||||
|
[ :intuit-bank-account/last-synced :xform clj-time.coerce/from-date]]}
|
||||||
|
{:bank-account/yodlee-account [:yodlee-account/available-balance
|
||||||
|
[:yodlee-account/last-synced :xform clj-time.coerce/from-date]]}]}]
|
||||||
|
(:db/id c)))]
|
||||||
|
[:div.flex.flex-col.p-4.border-l-2
|
||||||
|
[:div (:client/name c)]
|
||||||
|
[:div (:bank-account/name b)]
|
||||||
|
[:div.inline-flex.justify-between [:div "Ledger Balance"] (format "$%,.2f" (or (:bank-account/current-balance b) 0.0)) ]
|
||||||
|
[:div.inline-flex.justify-end.text-xs.text-gray-400.it (some-> (:bank-account/current-balance-synced b)
|
||||||
|
(atime/unparse-local atime/standard-time)
|
||||||
|
(#(str "Synced " %))) ]
|
||||||
|
[:div.inline-flex.justify-between [:div "Source Balance"] (format "$%,.2f" (or (-> b :bank-account/intuit-bank-account :intuit-bank-account/current-balance)
|
||||||
|
(-> b :bank-account/yodlee-account :yodlee-account/available-balance)
|
||||||
|
0.0))]
|
||||||
|
[:div.inline-flex.justify-end.text-xs.text-gray-400.it (or (some-> (:bank-account/intuit-bank-account b)
|
||||||
|
(:intuit-bank-account/last-synced)
|
||||||
|
(atime/unparse-local atime/standard-time)
|
||||||
|
(#(str "Synced " %)))
|
||||||
|
(some-> (:bank-account/yodlee-account b)
|
||||||
|
(:yodlee-account/last-synced)
|
||||||
|
(atime/unparse-local atime/standard-time)
|
||||||
|
(#(str "Synced " %))))]])]) ])
|
||||||
|
|
||||||
|
(defn page [request]
|
||||||
|
(base-page
|
||||||
|
request
|
||||||
|
(com/page {:nav com/main-aside-nav
|
||||||
|
:client-selection (:client-selection request)
|
||||||
|
:clients (:clients request)
|
||||||
|
:client (:client request)
|
||||||
|
:identity (:identity request)
|
||||||
|
:app-params {:hx-get (bidi/path-for ssr-routes/only-routes
|
||||||
|
::d-routes/page)
|
||||||
|
:hx-trigger "clientSelected from:body"
|
||||||
|
:hx-select "#app-contents"
|
||||||
|
:hx-swap "outerHTML swap:300ms"}
|
||||||
|
|
||||||
|
:request request}
|
||||||
|
(com/breadcrumbs {}
|
||||||
|
[:a {:href (bidi/path-for ssr-routes/only-routes ::d-routes/page)}
|
||||||
|
"Dashboard"])
|
||||||
|
(page-contents request))
|
||||||
|
"Dashboard"))
|
||||||
|
|
||||||
|
(def key->handler
|
||||||
|
( apply-middleware-to-all-handlers
|
||||||
|
{::d-routes/page page}
|
||||||
|
(fn [h]
|
||||||
|
(wrap-client-redirect-unauthenticated (wrap-admin h)))))
|
||||||
3
src/cljc/auto_ap/routes/dashboard.cljc
Normal file
3
src/cljc/auto_ap/routes/dashboard.cljc
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
(ns auto-ap.routes.dashboard)
|
||||||
|
(def routes {""
|
||||||
|
{:get ::page }})
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
[auto-ap.routes.admin.vendors :as v-routes]
|
[auto-ap.routes.admin.vendors :as v-routes]
|
||||||
[auto-ap.routes.outgoing-invoice :as oi-routes]
|
[auto-ap.routes.outgoing-invoice :as oi-routes]
|
||||||
[auto-ap.routes.payments :as p-routes]
|
[auto-ap.routes.payments :as p-routes]
|
||||||
|
[auto-ap.routes.dashboard :as d-routes]
|
||||||
[auto-ap.routes.invoice :as i-routes]
|
[auto-ap.routes.invoice :as i-routes]
|
||||||
[auto-ap.routes.admin.clients :as ac-routes]
|
[auto-ap.routes.admin.clients :as ac-routes]
|
||||||
[auto-ap.routes.admin.sales-summaries :as ss-routes]
|
[auto-ap.routes.admin.sales-summaries :as ss-routes]
|
||||||
@@ -16,6 +17,7 @@
|
|||||||
"search" :search
|
"search" :search
|
||||||
"indicators" indicator-routes/routes
|
"indicators" indicator-routes/routes
|
||||||
|
|
||||||
|
"dashboard" {:get ::d-routes/page}
|
||||||
"account" {"/search" {:get :account-search}}
|
"account" {"/search" {:get :account-search}}
|
||||||
"admin" {"" :auto-ap.routes.admin/page
|
"admin" {"" :auto-ap.routes.admin/page
|
||||||
"/client" ac-routes/routes
|
"/client" ac-routes/routes
|
||||||
|
|||||||
Reference in New Issue
Block a user