Sales on page
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -109,6 +109,8 @@
|
|||||||
(alog/warn ::couldnt-upsert-accounts :error e))))
|
(alog/warn ::couldnt-upsert-accounts :error e))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defn import-plaid-int []
|
(defn import-plaid-int []
|
||||||
(let [_ (upsert-accounts)
|
(let [_ (upsert-accounts)
|
||||||
import-batch (t/start-import-batch :import-source/plaid "Automated plaid user")
|
import-batch (t/start-import-batch :import-source/plaid "Automated plaid user")
|
||||||
|
|||||||
@@ -1,83 +1,133 @@
|
|||||||
(ns auto-ap.ssr.dashboard
|
(ns auto-ap.ssr.dashboard
|
||||||
(:require [auto-ap.datomic :refer [conn]]
|
(:require [auto-ap.datomic :refer [conn]]
|
||||||
|
[auto-ap.graphql.utils :refer [extract-client-ids]]
|
||||||
[auto-ap.routes.dashboard :as d-routes]
|
[auto-ap.routes.dashboard :as d-routes]
|
||||||
[auto-ap.routes.utils :refer [wrap-admin
|
[auto-ap.routes.utils :refer [wrap-admin
|
||||||
wrap-client-redirect-unauthenticated]]
|
wrap-client-redirect-unauthenticated]]
|
||||||
[auto-ap.ssr-routes :as ssr-routes]
|
[auto-ap.ssr-routes :as ssr-routes]
|
||||||
[auto-ap.ssr.components :as com]
|
[auto-ap.ssr.components :as com]
|
||||||
|
[auto-ap.ssr.hx :as hx]
|
||||||
[auto-ap.ssr.ui :refer [base-page]]
|
[auto-ap.ssr.ui :refer [base-page]]
|
||||||
[auto-ap.ssr.utils :refer [apply-middleware-to-all-handlers]]
|
[auto-ap.ssr.utils :refer [apply-middleware-to-all-handlers]]
|
||||||
|
[auto-ap.time :as atime]
|
||||||
[bidi.bidi :as bidi]
|
[bidi.bidi :as bidi]
|
||||||
[datomic.api :as dc]
|
[clj-time.coerce :as coerce]
|
||||||
[auto-ap.time :as atime]))
|
[clj-time.core :as time]
|
||||||
|
[datomic.api :as dc]))
|
||||||
|
|
||||||
|
(defn bank-accounts-card [request]
|
||||||
|
(com/card {:class "inline-block"}
|
||||||
|
[:div.p-4
|
||||||
|
[:h1.text-2xl.font-bold "Bank Accounts"]
|
||||||
|
[:div {:class "max-h-[800px] overflow-scroll"}
|
||||||
|
(for [c (:clients request)
|
||||||
|
b (:client/bank-accounts (dc/pull (dc/db conn) '[{:client/bank-accounts
|
||||||
|
|
||||||
|
[:bank-account/current-balance
|
||||||
|
{[:bank-account/type :xform iol-ion.query/ident] [:db/ident]}
|
||||||
|
|
||||||
|
[: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]]}
|
||||||
|
{:bank-account/plaid-account [:plaid-account/balance
|
||||||
|
[:plaid-account/last-synced :xform clj-time.coerce/from-date]]}]}]
|
||||||
|
(:db/id c)))
|
||||||
|
:when (not= :bank-account-type/cash (:bank-account/type b))]
|
||||||
|
[:div.flex.flex-col.p-4.border-b-2.border-gray-200
|
||||||
|
[:div.font-bold.text-gray-700 (:client/name c)]
|
||||||
|
[:div (:bank-account/name b)]
|
||||||
|
[:div.grid.grid-cols-3.gap-x-2.items-baseline
|
||||||
|
[:div "Ledger Balance"]
|
||||||
|
[:div.text-right (format "$%,.2f" (or (:bank-account/current-balance b) 0.0))]
|
||||||
|
[:div.text-xs.text-gray-400.text-right (some-> (:bank-account/current-balance-synced b)
|
||||||
|
(atime/unparse-local atime/standard-time)
|
||||||
|
(#(str "Synced " %)))]
|
||||||
|
|
||||||
|
(when-let [n (cond (-> b :bank-account/intuit-bank-account)
|
||||||
|
"Intuit"
|
||||||
|
(-> b :bank-account/yodlee-account)
|
||||||
|
"Yodlee"
|
||||||
|
(-> b :bank-account/plaid-account)
|
||||||
|
"Plaid"
|
||||||
|
:else
|
||||||
|
nil)]
|
||||||
|
(list
|
||||||
|
[:div (str n " Balance")]
|
||||||
|
[:div.text-right (format "$%,.2f" (or (-> b :bank-account/intuit-bank-account :intuit-bank-account/current-balance)
|
||||||
|
(-> b :bank-account/yodlee-account :yodlee-account/available-balance)
|
||||||
|
(-> b :bank-account/plaid-account :plaid-account/balance)
|
||||||
|
0.0))]
|
||||||
|
[:div.text-xs.text-gray-400.text-right (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 " %)))
|
||||||
|
(some-> (:bank-account/plaid-account b)
|
||||||
|
(:plaid-account/last-synced)
|
||||||
|
(atime/unparse-local atime/standard-time)
|
||||||
|
(#(str "Synced " %))))]
|
||||||
|
[:div.inline-flex.justify-end.text-xs.text-gray-400.it]))
|
||||||
|
#_[:div.inline-flex.justify-between.items-baseline]]])]]))
|
||||||
|
|
||||||
|
(defn sales-chart-card [request]
|
||||||
|
(let [
|
||||||
|
valid-clients (extract-client-ids (:clients request)
|
||||||
|
(:client-id request)
|
||||||
|
(when (:client-code request)
|
||||||
|
[:client/code (:client-code request)]))
|
||||||
|
totals
|
||||||
|
(->> (dc/q '[:find ?sd (sum ?total)
|
||||||
|
:in $ [?clients ?start-date ?end-date]
|
||||||
|
:where [(iol-ion.query/scan-sales-orders $ ?clients ?start-date ?end-date) [[?e _ ?sort-default] ...]]
|
||||||
|
[?e :sales-order/date ?d]
|
||||||
|
[(iol-ion.query/iso-date ?d) ?sd]
|
||||||
|
[?e :sales-order/total ?total]]
|
||||||
|
(dc/db conn)
|
||||||
|
[valid-clients
|
||||||
|
(coerce/to-date (time/plus (time/now) (time/days -14)))
|
||||||
|
(coerce/to-date (time/now))])
|
||||||
|
(sort-by first))]
|
||||||
|
(com/card {:class "w-full h-full"}
|
||||||
|
[:canvas.w-full.h-full {:x-data (hx/json {:chart nil
|
||||||
|
:labels (map first totals)
|
||||||
|
:data (map second totals)})
|
||||||
|
:x-init " new Chart($el, {
|
||||||
|
type: 'bar',
|
||||||
|
data: {
|
||||||
|
labels: labels,
|
||||||
|
datasets: [{
|
||||||
|
label: 'Gross Sales',
|
||||||
|
data: data,
|
||||||
|
borderWidth: 1
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
scales: {
|
||||||
|
y: {
|
||||||
|
beginAtZero: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});"}])))
|
||||||
|
|
||||||
(defn- page-contents [request]
|
(defn- page-contents [request]
|
||||||
[:div
|
[:div
|
||||||
[:div {:class "grid grid-cols-1 lg:grid-cols-2 2xl:grid-cols-3 gap-4 overflow-scroll"}
|
[:div {:class "grid grid-cols-1 lg:grid-cols-2 2xl:grid-cols-3 gap-4 overflow-scroll auto-rows-fr"}
|
||||||
[:div.bg-blue-300.p-4.flex.flex-grow-0 "report-1"]
|
[:div (com/card {:class "w-full h-full"} [:div.w-full.h-full "report-1"])]
|
||||||
[:div.bg-red-300.p-4.flex.flex-grow-0 "hi"]
|
[:div "hi"]
|
||||||
[:div.row-span-2
|
[:div.row-span-2
|
||||||
(com/card {:class "inline-block"}
|
(bank-accounts-card request)]
|
||||||
[:div.p-4
|
|
||||||
|
|
||||||
[:h1.text-2xl.font-bold "Bank Accounts"]
|
|
||||||
[:div {:class "max-h-[800px] overflow-scroll"}
|
|
||||||
(for [c (:clients request)
|
|
||||||
b (:client/bank-accounts (dc/pull (dc/db conn) '[{ :client/bank-accounts
|
|
||||||
|
|
||||||
[:bank-account/current-balance
|
|
||||||
{[:bank-account/type :xform iol-ion.query/ident] [:db/ident]}
|
|
||||||
|
|
||||||
[: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]]}
|
|
||||||
{:bank-account/plaid-account [:plaid-account/balance
|
|
||||||
[:plaid-account/last-synced :xform clj-time.coerce/from-date]]}]}]
|
|
||||||
(:db/id c)))
|
|
||||||
:when (not= :bank-account-type/cash (:bank-account/type b))]
|
|
||||||
[:div.flex.flex-col.p-4.border-b-2.border-gray-200
|
|
||||||
[:div.font-bold.text-gray-700 (:client/name c)]
|
|
||||||
[:div (:bank-account/name b)]
|
|
||||||
[:div.grid.grid-cols-3.gap-x-2.items-baseline
|
|
||||||
[:div "Ledger Balance"]
|
|
||||||
[:div.text-right (format "$%,.2f" (or (:bank-account/current-balance b) 0.0))]
|
|
||||||
[:div.text-xs.text-gray-400.text-right (some-> (:bank-account/current-balance-synced b)
|
|
||||||
(atime/unparse-local atime/standard-time)
|
|
||||||
(#(str "Synced " %)))]
|
|
||||||
|
|
||||||
(when-let [n (cond (-> b :bank-account/intuit-bank-account)
|
|
||||||
"Intuit"
|
|
||||||
(-> b :bank-account/yodlee-account)
|
|
||||||
"Yodlee"
|
|
||||||
(-> b :bank-account/plaid-account)
|
|
||||||
"Plaid"
|
|
||||||
:else
|
|
||||||
nil)]
|
|
||||||
(list
|
|
||||||
[:div (str n " Balance")]
|
|
||||||
[:div.text-right (format "$%,.2f" (or (-> b :bank-account/intuit-bank-account :intuit-bank-account/current-balance)
|
|
||||||
(-> b :bank-account/yodlee-account :yodlee-account/available-balance)
|
|
||||||
(-> b :bank-account/plaid-account :plaid-account/balance)
|
|
||||||
0.0))]
|
|
||||||
[:div.text-xs.text-gray-400.text-right (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 " %)))
|
|
||||||
(some-> (:bank-account/plaid-account b)
|
|
||||||
(:plaid-account/last-synced)
|
|
||||||
(atime/unparse-local atime/standard-time)
|
|
||||||
(#(str "Synced " %))))]
|
|
||||||
[:div.inline-flex.justify-end.text-xs.text-gray-400.it ]))
|
|
||||||
#_[:div.inline-flex.justify-between.items-baseline]]])]])]
|
|
||||||
|
|
||||||
[:div.bg-purple-300.p-4 "hi"]
|
[:div.bg-purple-300.p-4
|
||||||
|
(sales-chart-card request)]
|
||||||
[:div.bg-slate-300.p-4 "hi"]
|
[:div.bg-slate-300.p-4 "hi"]
|
||||||
] ])
|
] ])
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,7 @@
|
|||||||
[:link {:rel "stylesheet" :href "https://cdn.jsdelivr.net/npm/choices.js@9.0.1/public/assets/styles/choices.min.css"}]
|
[:link {:rel "stylesheet" :href "https://cdn.jsdelivr.net/npm/choices.js@9.0.1/public/assets/styles/choices.min.css"}]
|
||||||
[:script {:src "https://cdn.jsdelivr.net/npm/choices.js@9.0.1/public/assets/scripts/choices.min.js"}]
|
[:script {:src "https://cdn.jsdelivr.net/npm/choices.js@9.0.1/public/assets/scripts/choices.min.js"}]
|
||||||
[:script {:src "https://unpkg.com/htmx.org/dist/ext/response-targets.js"}]
|
[:script {:src "https://unpkg.com/htmx.org/dist/ext/response-targets.js"}]
|
||||||
|
[:script {:src "https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.1/chart.umd.min.js" :integrity "sha512-CQBWl4fJHWbryGE+Pc7UAxWMUMNMWzWxF4SQo9CgkJIN1kx6djDQZjh3Y8SZ1d+6I+1zze6Z7kHXO7q3UyZAWw==" :crossorigin "anonymous" :referrerpolicy "no-referrer"}]
|
||||||
|
|
||||||
[:script {:src "https://unpkg.com/dropzone@5.9.3/dist/min/dropzone.min.js"}]
|
[:script {:src "https://unpkg.com/dropzone@5.9.3/dist/min/dropzone.min.js"}]
|
||||||
[:link {:rel "stylesheet" :href "https://unpkg.com/dropzone@5/dist/min/dropzone.min.css" :type "text/css"}]
|
[:link {:rel "stylesheet" :href "https://unpkg.com/dropzone@5/dist/min/dropzone.min.css" :type "text/css"}]
|
||||||
@@ -69,9 +70,9 @@ input::-webkit-inner-spin-button {
|
|||||||
input[type=number] {
|
input[type=number] {
|
||||||
-moz-appearance:textfield; /* Firefox */
|
-moz-appearance:textfield; /* Firefox */
|
||||||
} "]
|
} "]
|
||||||
[:body {:hx-ext "disable-submit, class-tools"
|
[:body {:hx-ext "disable-submit, class-tools"
|
||||||
:x-data (hx/json {:globalClientSelection (or (:client-selection request)
|
:x-data (hx/json {:globalClientSelection (or (:client-selection request)
|
||||||
:all )}) ;; TODO remove once session is used
|
:all)}) ;; TODO remove once session is used
|
||||||
:x-hx-header:x-clients "JSON.stringify(globalClientSelection)"}
|
:x-hx-header:x-clients "JSON.stringify(globalClientSelection)"}
|
||||||
contents
|
contents
|
||||||
[:script {:src "/js/flowbite.min.js"}]
|
[:script {:src "/js/flowbite.min.js"}]
|
||||||
|
|||||||
Reference in New Issue
Block a user