adds profit and loss snapshot.
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -190,6 +190,22 @@
|
|||||||
client-ids))
|
client-ids))
|
||||||
true ->graphql)))
|
true ->graphql)))
|
||||||
|
|
||||||
|
(defn get-profit-and-loss-raw [client-ids periods]
|
||||||
|
(let [ all-ledger-entries (->> client-ids
|
||||||
|
(map (fn [client-id]
|
||||||
|
[client-id (full-ledger-for-client client-id)]))
|
||||||
|
(into {}))
|
||||||
|
lookup-account (->> client-ids
|
||||||
|
(map (fn [client-id]
|
||||||
|
[client-id (build-account-lookup client-id)]))
|
||||||
|
(into {}))]
|
||||||
|
(->graphql {:periods
|
||||||
|
(->> periods
|
||||||
|
(mapv (fn [{:keys [start end]}]
|
||||||
|
{:accounts (mapcat
|
||||||
|
#(roll-up-until (lookup-account %) (all-ledger-entries %) (coerce/to-date end) (coerce/to-date start) )
|
||||||
|
client-ids)})))})))
|
||||||
|
|
||||||
(defn get-profit-and-loss [context args _]
|
(defn get-profit-and-loss [context args _]
|
||||||
(let [client-id (:client_id args)
|
(let [client-id (:client_id args)
|
||||||
client-ids (or (some-> client-id vector)
|
client-ids (or (some-> client-id vector)
|
||||||
@@ -200,22 +216,10 @@
|
|||||||
(assert-can-see-client (:id context) client-id))
|
(assert-can-see-client (:id context) client-id))
|
||||||
_ (when (and (:include_deltas args)
|
_ (when (and (:include_deltas args)
|
||||||
(:column_per_location args))
|
(:column_per_location args))
|
||||||
(throw (ex-info "Please select one of 'Include deltas' or 'Column per location'" {:validation-error "Please select one of 'Include deltas' or 'Column per location'"})))
|
(throw (ex-info "Please select one of 'Include deltas' or 'Column per location'" {:validation-error "Please select one of 'Include deltas' or 'Column per location'"}))) ]
|
||||||
all-ledger-entries (->> client-ids
|
(get-profit-and-loss-raw client-ids (:periods args))))
|
||||||
(map (fn [client-id]
|
|
||||||
[client-id (full-ledger-for-client client-id)]))
|
|
||||||
(into {}))
|
|
||||||
lookup-account (->> client-ids
|
|
||||||
(map (fn [client-id]
|
|
||||||
[client-id (build-account-lookup client-id)]))
|
|
||||||
(into {}))]
|
|
||||||
(->graphql
|
|
||||||
{:periods
|
|
||||||
(->> (:periods args)
|
|
||||||
(mapv (fn [{:keys [start end]}]
|
|
||||||
{:accounts (mapcat
|
|
||||||
#(roll-up-until (lookup-account %) (all-ledger-entries %) (coerce/to-date end) (coerce/to-date start) )
|
|
||||||
client-ids)})))})))
|
|
||||||
|
|
||||||
|
|
||||||
;; profit and loss based off of index
|
;; profit and loss based off of index
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
(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.graphql.ledger :refer [get-profit-and-loss-raw]]
|
||||||
|
[auto-ap.graphql.utils :refer [<-graphql extract-client-ids]]
|
||||||
|
[auto-ap.ledger.reports :as r]
|
||||||
[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]]
|
||||||
@@ -91,8 +93,8 @@ valid-clients (extract-client-ids (:clients request)
|
|||||||
[?e :sales-order/total ?total]]
|
[?e :sales-order/total ?total]]
|
||||||
(dc/db conn)
|
(dc/db conn)
|
||||||
[valid-clients
|
[valid-clients
|
||||||
(coerce/to-date (time/plus (time/now) (time/days -14)))
|
(coerce/to-date (time/with-time-at-start-of-day (time/plus (time/now) (time/days -14))))
|
||||||
(coerce/to-date (time/now))])
|
(coerce/to-date (time/with-time-at-start-of-day (time/plus (time/now) (time/days 1))))])
|
||||||
(sort-by first))]
|
(sort-by first))]
|
||||||
(com/card {:class "w-full h-full p-4"}
|
(com/card {:class "w-full h-full p-4"}
|
||||||
[:h1.text-2xl.font-bold.text-slate-700 "Gross sales, last 14 days"]
|
[:h1.text-2xl.font-bold.text-slate-700 "Gross sales, last 14 days"]
|
||||||
@@ -100,12 +102,13 @@ valid-clients (extract-client-ids (:clients request)
|
|||||||
[:canvas.w-full.h-full.p-8 {:x-data (hx/json {:chart nil
|
[:canvas.w-full.h-full.p-8 {:x-data (hx/json {:chart nil
|
||||||
:labels (map first totals)
|
:labels (map first totals)
|
||||||
:data (map second totals)})
|
:data (map second totals)})
|
||||||
:x-init " new Chart($el, {
|
:x-init
|
||||||
|
"new Chart($el, {
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
data: {
|
data: {
|
||||||
labels: labels,
|
labels: labels,
|
||||||
datasets: [{
|
datasets: [{
|
||||||
label: 'Total invoice spend',
|
label: 'Gross sales',
|
||||||
data: data,
|
data: data,
|
||||||
borderWidth: 1
|
borderWidth: 1
|
||||||
}]
|
}]
|
||||||
@@ -138,8 +141,8 @@ valid-clients (extract-client-ids (:clients request)
|
|||||||
[?ea :account/name ?an]]
|
[?ea :account/name ?an]]
|
||||||
(dc/db conn)
|
(dc/db conn)
|
||||||
[valid-clients
|
[valid-clients
|
||||||
(coerce/to-date (time/plus (time/now) (time/months -1)))
|
(coerce/to-date (time/with-time-at-start-of-day (time/plus (time/now) (time/months -1))))
|
||||||
(coerce/to-date (time/now))])
|
(coerce/to-date (time/plus (time/with-time-at-start-of-day (time/now)) (time/days 1)))])
|
||||||
(sort-by last)
|
(sort-by last)
|
||||||
(reverse)
|
(reverse)
|
||||||
(take 5))]
|
(take 5))]
|
||||||
@@ -155,7 +158,7 @@ valid-clients (extract-client-ids (:clients request)
|
|||||||
data: {
|
data: {
|
||||||
labels: labels,
|
labels: labels,
|
||||||
datasets: [{
|
datasets: [{
|
||||||
label: 'Gross Sales',
|
label: 'Total invoices',
|
||||||
data: data,
|
data: data,
|
||||||
borderWidth: 1
|
borderWidth: 1
|
||||||
}]
|
}]
|
||||||
@@ -167,6 +170,55 @@ valid-clients (extract-client-ids (:clients request)
|
|||||||
}
|
}
|
||||||
});"}]])))
|
});"}]])))
|
||||||
|
|
||||||
|
(defn pnl-card [request]
|
||||||
|
(com/card {:class "w-full h-full p-4"}
|
||||||
|
[:h1.text-2xl.font-bold.text-gray-700
|
||||||
|
"Profit and Loss"
|
||||||
|
]
|
||||||
|
(let [all-clients (extract-client-ids (:clients request)
|
||||||
|
(:client-id request)
|
||||||
|
(when (:client-code request)
|
||||||
|
[:client/code (:client-code request)]))
|
||||||
|
clients (take 10 all-clients)
|
||||||
|
data (<-graphql (get-profit-and-loss-raw clients
|
||||||
|
[{:start (time/plus (time/now) (time/days -90))
|
||||||
|
:end (time/now)}]))
|
||||||
|
data (r/->PNLData {} (:accounts (first (:periods data))) {})
|
||||||
|
sales (r/aggregate-accounts (r/filter-categories data [ :sales]))
|
||||||
|
expenses (r/aggregate-accounts (r/filter-categories data [ :cogs :payroll :controllable :fixed-overhead :ownership-controllable ]))]
|
||||||
|
(list
|
||||||
|
(when (not= (count all-clients) (count clients))
|
||||||
|
[:div.bg-yellow-100.rounded-lg.p-4.my-2.text-yellow-900 "Warning: Too many clients are selected. This report only shows 10 of the selected clients."])
|
||||||
|
[:canvas.w-full.h-full.p-8 {:x-data (hx/json {:chart nil
|
||||||
|
:labels [(format "Income $%,.2f" sales) (format "Expenses $%,.2f" expenses)]
|
||||||
|
:data [sales expenses]})
|
||||||
|
:x-init
|
||||||
|
"new Chart($el, {
|
||||||
|
type: 'bar',
|
||||||
|
data: {
|
||||||
|
labels: labels,
|
||||||
|
datasets: [{
|
||||||
|
label: 'Dollars',
|
||||||
|
data: data,
|
||||||
|
borderWidth: 1
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
indexAxis: 'y',
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
scales: {
|
||||||
|
x: {
|
||||||
|
beginAtZero: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});"}]
|
||||||
|
[:div
|
||||||
|
"Income: " (format "$%,.2f" sales)]
|
||||||
|
[:div
|
||||||
|
"Expenses: " (format "$%,.2f" expenses)]))))
|
||||||
|
|
||||||
(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 auto-rows-fr max-h-[970px]"}
|
[:div {:class "grid grid-cols-1 lg:grid-cols-2 2xl:grid-cols-3 gap-4 auto-rows-fr max-h-[970px]"}
|
||||||
@@ -180,9 +232,8 @@ valid-clients (extract-client-ids (:clients request)
|
|||||||
[:div
|
[:div
|
||||||
(sales-chart-card request)]
|
(sales-chart-card request)]
|
||||||
[:div
|
[:div
|
||||||
(com/card {:class "w-full h-full p-4"}
|
(pnl-card request)
|
||||||
[:h1.text-2xl.font-bold.text-gray-700
|
|
||||||
"Tasks"])
|
|
||||||
]
|
]
|
||||||
] ])
|
] ])
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user