Makes new balance sheet page. It's much faster.
This commit is contained in:
@@ -164,63 +164,91 @@
|
||||
(defn ident [x]
|
||||
(:db/ident x))
|
||||
|
||||
(deftype Line [^Long id ^Long client-id ^Long account-id ^String location ^java.util.Date date ^Double debit ^Double credit ^Double running-balance])
|
||||
|
||||
(defn ->line [{[current-client current-account current-location current-date debit credit running-balance]
|
||||
:v
|
||||
id :e}]
|
||||
(Line. id current-client current-account current-location current-date debit credit running-balance)
|
||||
)
|
||||
|
||||
(defn compare-account [^Line l1 ^Line l2]
|
||||
|
||||
(let [a (compare (.-date l1) (.-date l2))]
|
||||
(if (not= 0 a)
|
||||
a
|
||||
(compare (.-id l1) (.-id l2)))))
|
||||
|
||||
(defn account-sets [db client-id]
|
||||
(for [running-balance-set (->> (dc/index-range db :journal-entry-line/running-balance-tuple [client-id] [(inc client-id)])
|
||||
(seq)
|
||||
(partition-by (fn [{[current-client current-account current-location current-date debit credit running-balance]
|
||||
:v}]
|
||||
[current-client current-account current-location]))) ]
|
||||
(map ->line)
|
||||
(partition-by (fn set-partition [^Line l]
|
||||
[(.-account-id l) (.-location l)]))) ]
|
||||
(->> running-balance-set
|
||||
(sort-by (fn [{id :e [_ _ _ current-date] :v}]
|
||||
[current-date id])))))
|
||||
(sort compare-account))))
|
||||
|
||||
(defn account-snapshot [db client-id end]
|
||||
(defn account-snapshot [db client-id ^java.util.Date end]
|
||||
(for [running-balance-set (account-sets db client-id)
|
||||
:let [{id :e [client-id account-id location date _ _ current-balance] :v}
|
||||
(->> running-balance-set
|
||||
(take-while (fn [{id :e [_ _ _ current-date] :v}]
|
||||
(<= (.compareTo current-date end) 0)))
|
||||
(take-while (fn until-date [^Line l]
|
||||
(let [^java.util.Date d (.-date l)]
|
||||
(<= (.compareTo ^java.util.Date d end) 0))))
|
||||
last)]
|
||||
:when id]
|
||||
[client-id account-id location date current-balance]))
|
||||
|
||||
(defn detailed-account-snapshot [db client-id end]
|
||||
|
||||
(defn detailed-account-snapshot [db client-id ^java.util.Date end]
|
||||
(for [running-balance-set (account-sets db client-id)
|
||||
:let [{:keys [account-id client-id location current-balance debits credits count]}
|
||||
(->> running-balance-set
|
||||
|
||||
(take-while (fn [{id :e [_ _ _ current-date] :v}]
|
||||
(<= (.compareTo current-date end) 0)))
|
||||
(take-while (fn until-date [^Line l]
|
||||
(let [^java.util.Date d (.-date l)]
|
||||
(<= (.compareTo ^java.util.Date d end) 0))))
|
||||
(reduce
|
||||
(fn [acc {id :e [current-client current-account current-location current-date debit credit balance] :v}]
|
||||
(-> acc
|
||||
(update :count inc)
|
||||
(update :debits + (or debit 0.0))
|
||||
(update :credits + (or credit 0.0))
|
||||
(assoc :current-balance balance
|
||||
:account-id current-account
|
||||
:client-id current-client
|
||||
:location current-location)))
|
||||
{:count 0
|
||||
:debits 0.0
|
||||
:credits 0.0
|
||||
:current-balance 0.0}))]
|
||||
(fn step [acc ^Line l]
|
||||
(assoc! acc
|
||||
:count (unchecked-inc (:count acc))
|
||||
:debits (unchecked-add (:debits acc) (or (.-debit l) 0.0))
|
||||
:credits (unchecked-add (:credits acc) (or (.-credit l) 0.0))
|
||||
:current-balance (.-running-balance l)
|
||||
:account-id (.-account-id l)
|
||||
:client-id (.-client-id l)
|
||||
:location (.-location l)))
|
||||
(transient {:count 0
|
||||
:debits 0.0
|
||||
:credits 0.0
|
||||
:current-balance 0.0})))]
|
||||
:when client-id]
|
||||
[client-id account-id location debits credits current-balance count]))
|
||||
|
||||
|
||||
|
||||
(comment
|
||||
(detailed-account-snapshot (dc/db auto-ap.datomic/conn)
|
||||
(auto-ap.datomic/pull-id (dc/db auto-ap.datomic/conn)
|
||||
[:client/code "NGOP"])
|
||||
#inst "2024-01-01")
|
||||
#inst "2020-01-01")
|
||||
|
||||
(account-snapshot (dc/db auto-ap.datomic/conn)
|
||||
(auto-ap.datomic/pull-id (dc/db auto-ap.datomic/conn)
|
||||
[:client/code "NGOP"])
|
||||
#inst "2022-01-01")
|
||||
|
||||
(def orig (into [] (take 5000 (mapcat (fn [ls]
|
||||
(map #(.-id %) ls)) (account-sets (dc/db auto-ap.datomic/conn)
|
||||
(auto-ap.datomic/pull-id (dc/db auto-ap.datomic/conn)
|
||||
[:client/code "NGOP"]))))))
|
||||
|
||||
(def n (into [] (take 5000 (mapcat (fn [ls]
|
||||
(map #(.-id %) ls)) (account-sets (dc/db auto-ap.datomic/conn)
|
||||
(auto-ap.datomic/pull-id (dc/db auto-ap.datomic/conn)
|
||||
[:client/code "NGOP"]))))))
|
||||
|
||||
(= orig n)
|
||||
|
||||
#_(seq (dc/q '[:find ?c ?a ?l ?date ?balance
|
||||
:in $
|
||||
:where [?c :client/code "NGOP"]
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -465,8 +465,6 @@
|
||||
(refresh-bank-account-balances (map :db/id clients))
|
||||
(count changes)))))
|
||||
|
||||
|
||||
|
||||
(comment
|
||||
(pull-id (dc/db conn) [:client/code "SCCB"])
|
||||
|
||||
|
||||
@@ -56,7 +56,6 @@
|
||||
|
||||
(defn table->pdf [table widths]
|
||||
(let [cell-count (cell-count table)]
|
||||
|
||||
(-> [:pdf-table {:header (mapv
|
||||
(fn [header]
|
||||
(map cell->pdf header))
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
"sales"
|
||||
(#{::payment-routes/all-page ::payment-routes/pending-page ::payment-routes/cleared-page ::payment-routes/voided-page} (:matched-route request))
|
||||
"payments"
|
||||
(#{::ledger-routes/all-page ::ledger-routes/external-page ::ledger-routes/external-import-page} (:matched-route request))
|
||||
(#{::ledger-routes/all-page ::ledger-routes/external-page ::ledger-routes/external-import-page ::ledger-routes/balance-sheet} (:matched-route request))
|
||||
"ledger"
|
||||
:else
|
||||
nil)]
|
||||
@@ -303,8 +303,20 @@
|
||||
:profit-and-loss-detail)} "Profit & Loss Detail")
|
||||
(menu-button- {:href (bidi/path-for client-routes/routes
|
||||
:cash-flows)} "Cash Flows")
|
||||
(menu-button- {:href (bidi/path-for client-routes/routes
|
||||
:balance-sheet)} "Balance Sheet")
|
||||
|
||||
(if (is-admin? (:identity request))
|
||||
(menu-button- {:href (hu/url (bidi/path-for ssr-routes/only-routes
|
||||
::ledger-routes/balance-sheet))
|
||||
:active? (= ::ledger-routes/balance-sheet (:matched-route request))
|
||||
:hx-boost "true"}
|
||||
[:div.flex.gap-2
|
||||
"Balance Sheet"
|
||||
(tags/pill- {:color :secondary} "WIP")])
|
||||
(menu-button- {:href (bidi/path-for client-routes/routes
|
||||
:balance-sheet)} "Balance Sheet"))
|
||||
(when (is-admin? (:identity request))
|
||||
(menu-button- {:href (bidi/path-for client-routes/routes
|
||||
:balance-sheet)} "Old Balance Sheet"))
|
||||
(when (can? (:identity request)
|
||||
{:subject :ledger
|
||||
:activity :import})
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
(ns auto-ap.ssr.components.inputs
|
||||
(:require
|
||||
[hiccup2.core :as hiccup]
|
||||
[auto-ap.ssr.hiccup-helper :as hh]
|
||||
[clojure.string :as str]
|
||||
[auto-ap.ssr.svg :as svg]
|
||||
[auto-ap.ssr.components.tags :as tags]
|
||||
[auto-ap.ssr.hx :as hx]))
|
||||
(:require [auto-ap.ssr.components.buttons :as buttons]
|
||||
[auto-ap.ssr.components.tags :as tags]
|
||||
[auto-ap.ssr.hiccup-helper :as hh]
|
||||
[auto-ap.ssr.hx :as hx]
|
||||
[auto-ap.ssr.svg :as svg]
|
||||
[clojure.string :as str]
|
||||
[hiccup2.core :as hiccup]))
|
||||
|
||||
|
||||
(def default-input-classes
|
||||
@@ -169,17 +169,31 @@
|
||||
"x-bind:value" "v"
|
||||
))]]
|
||||
[:div.flex.w-full.justify-items-stretch
|
||||
[:span.flex-grow.text-left [:span {"x-text" "value.size"} ]
|
||||
" selected"]
|
||||
|
||||
[:div.flex-grow.flex
|
||||
[:template {:x-if "value.size > 0"}
|
||||
[:a.bg-blue-100.rounded-full.px-3 {:x-data "popper()"}
|
||||
[:span.text-left {:x-ref "source"}
|
||||
[:span {"x-text" "value.size"}]
|
||||
" selected"]
|
||||
(buttons/tooltip- {:x-bind "tooltip" }
|
||||
[:div.flex.flex-wrap.gap-4.w-64
|
||||
[:template {:x-for "v in Array.from(value.values())"}
|
||||
[:div.bg-green-50.rounded-full.px-3.text-ellipsis.whitespace-nowrap.shrink.overflow-hidden.text-green-800 {:x-text "lookup[v]"}]]])]]
|
||||
[:template {:x-if "value.size == 0"}
|
||||
[:span.text-left.text-gray-400 "None selected"]]
|
||||
|
||||
[:div {:class "w-4 h-4 ml-2 inline text-gray-500 self-center rounded-full bg-gray-100 text-gray-500"
|
||||
"@click.prevent.stop" "value = new Set([])"
|
||||
:x-show "value.size > 0"}
|
||||
svg/x]]
|
||||
[:div {:class "w-3 h-3 m-1 inline ml-1 justify-self-end text-gray-500 self-center"}
|
||||
svg/drop-down]
|
||||
[:div {:x-show "value.warning"
|
||||
:x-ref "warning_badge"
|
||||
:x-effect "if (value.warning) { $nextTick(()=> warning_badge.update()) }"}
|
||||
(tags/badge- {:class "peer"} "!")
|
||||
|
||||
|
||||
|
||||
|
||||
[:div {:x-show "value.warning"
|
||||
:x-ref "warning_pop"
|
||||
:class "hidden peer-hover:block bg-red-50 dark:bg-gray-600 rounded-lg shadow-2xl w-max z-50 p-4"
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
(ns auto-ap.ssr.ledger.balance-sheet
|
||||
(:require [auto-ap.datomic
|
||||
(:require [amazonica.aws.s3 :as s3]
|
||||
[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.reports :as l-reports]
|
||||
[auto-ap.logging :as alog]
|
||||
[auto-ap.pdf.ledger :refer [table->pdf]]
|
||||
[auto-ap.permissions :refer [wrap-must]]
|
||||
[auto-ap.routes.ledger :as route]
|
||||
[auto-ap.routes.utils
|
||||
@@ -13,19 +15,25 @@
|
||||
[auto-ap.ssr.components :as com]
|
||||
[auto-ap.ssr.form-cursor :as fc]
|
||||
[auto-ap.ssr.hx :as hx]
|
||||
[auto-ap.ssr.svg :as svg]
|
||||
[auto-ap.ssr.ui :refer [base-page]]
|
||||
[auto-ap.ssr.utils
|
||||
:refer [apply-middleware-to-all-handlers clj-date-schema
|
||||
field-validation-error html-response wrap-form-4xx-2
|
||||
wrap-merge-prior-hx wrap-schema-decode
|
||||
wrap-schema-enforce]]
|
||||
html-response modal-response wrap-form-4xx-2
|
||||
wrap-merge-prior-hx wrap-schema-enforce]]
|
||||
[auto-ap.time :as atime]
|
||||
[bidi.bidi :as bidi]
|
||||
[clj-pdf.core :as pdf]
|
||||
[clj-time.coerce :as coerce]
|
||||
[clj-time.core :as t]
|
||||
[clojure.java.io :as io]
|
||||
[clojure.string :as str]
|
||||
[config.core :refer [env] :as env]
|
||||
[datomic.api :as dc]
|
||||
[iol-ion.utils :refer [by]]
|
||||
[malli.core :as mc]))
|
||||
[malli.core :as mc])
|
||||
(:import [java.util UUID]
|
||||
[org.apache.commons.io.output ByteArrayOutputStream]))
|
||||
|
||||
|
||||
|
||||
@@ -193,126 +201,134 @@
|
||||
;; 3. General cleanup of the patterns in run-balance-sheet
|
||||
;; 4. Review ledger dialog
|
||||
|
||||
(defn get-report [{ {:keys [date comparison-date include-comparison client] :as qp} :query-params :as request}]
|
||||
(when (and date client)
|
||||
(let [client-ids (map :db/id client)
|
||||
_ (doseq [client-id client-ids]
|
||||
(assert-can-see-client (:identity request) client-id))
|
||||
|
||||
end-date (coerce/to-date date)
|
||||
comparable-date (coerce/to-date comparison-date)
|
||||
lookup-account (->> client-ids
|
||||
(map (fn build-lookup [client-id]
|
||||
[client-id (build-account-lookup client-id)]))
|
||||
(into {}))
|
||||
data (cond-> {:balance-sheet-accounts (into []
|
||||
(mapcat
|
||||
(fn calculate-accounts [client-id ]
|
||||
(for [
|
||||
[client-id account-id location debits credits balance count] (iol-ion.query/detailed-account-snapshot (dc/db conn) client-id end-date)
|
||||
:let [account ( (or (lookup-account client-id) {}) account-id)]]
|
||||
{:client-id client-id
|
||||
:account-id account-id
|
||||
:location location
|
||||
:debits debits
|
||||
:credits credits
|
||||
:count count
|
||||
:amount balance
|
||||
:account-type (:account_type account)
|
||||
:numeric-code (:numeric_code account)
|
||||
:name (:name account) }))
|
||||
|
||||
client-ids))}
|
||||
(and include-comparison comparison-date)
|
||||
(assoc :comparable-balance-sheet-accounts
|
||||
(into []
|
||||
(mapcat
|
||||
(fn calculate-accounts [client-id ]
|
||||
(for [
|
||||
[client-id account-id location debits credits balance count] (iol-ion.query/detailed-account-snapshot (dc/db conn) client-id comparable-date)
|
||||
:let [account ( (or (lookup-account client-id) {}) account-id)]]
|
||||
{:client-id client-id
|
||||
:account-id account-id
|
||||
:location location
|
||||
:debits debits
|
||||
:credits credits
|
||||
:count count
|
||||
:amount balance
|
||||
:account-type (:account_type account)
|
||||
:numeric-code (:numeric_code account)
|
||||
:name (:name account) }))
|
||||
|
||||
client-ids)))
|
||||
)
|
||||
args (assoc (:query-params request)
|
||||
:periods (filter identity (cond-> [date]
|
||||
include-comparison (conj comparison-date))))
|
||||
clients (pull-many (dc/db conn) [:client/code :client/name :db/id] client-ids)
|
||||
|
||||
data (concat (->> (:balance-sheet-accounts data)
|
||||
(map (fn [b]
|
||||
(assoc b
|
||||
:period (:date args)))))
|
||||
(->> (:comparable-balance-sheet-accounts data)
|
||||
(map (fn [b]
|
||||
(assoc b
|
||||
:period (:comparison-date args))))))
|
||||
pnl-data (l-reports/->PNLData args data (by :db/id :client/code clients))
|
||||
report (l-reports/summarize-balance-sheet pnl-data) ]
|
||||
(alog/info ::balance-sheet :params args)
|
||||
{:data report
|
||||
:report report})))
|
||||
|
||||
(defn balance-sheet* [{ {:keys [date comparison-date include-comparison client] } :query-params :as request}]
|
||||
[:div#report
|
||||
(when (and date client)
|
||||
(let [client-ids (map :db/id client)
|
||||
|
||||
_ (doseq [client-id client-ids]
|
||||
(assert-can-see-client (:identity request) client-id))
|
||||
|
||||
end-date (coerce/to-date date)
|
||||
comparable-date (coerce/to-date comparison-date)
|
||||
lookup-account (->> client-ids
|
||||
(map (fn build-lookup [client-id]
|
||||
[client-id (build-account-lookup client-id)]))
|
||||
(into {}))
|
||||
data (cond-> {:balance-sheet-accounts (into []
|
||||
(mapcat
|
||||
(fn calculate-accounts [client-id ]
|
||||
(for [
|
||||
[client-id account-id location debits credits balance count] (iol-ion.query/detailed-account-snapshot (dc/db conn) client-id end-date)
|
||||
:let [account ( (or (lookup-account client-id) {}) account-id)]]
|
||||
{:client-id client-id
|
||||
:account-id account-id
|
||||
:location location
|
||||
:debits debits
|
||||
:credits credits
|
||||
:count count
|
||||
:amount balance
|
||||
:account-type (:account_type account)
|
||||
:numeric-code (:numeric_code account)
|
||||
:name (:name account) }))
|
||||
|
||||
client-ids))}
|
||||
(and include-comparison comparison-date)
|
||||
(assoc :comparable-balance-sheet-accounts
|
||||
(into []
|
||||
(mapcat
|
||||
(fn calculate-accounts [client-id ]
|
||||
(for [
|
||||
[client-id account-id location debits credits balance count] (iol-ion.query/detailed-account-snapshot (dc/db conn) client-id comparable-date)
|
||||
:let [account ( (or (lookup-account client-id) {}) account-id)]]
|
||||
{:client-id client-id
|
||||
:account-id account-id
|
||||
:location location
|
||||
:debits debits
|
||||
:credits credits
|
||||
:count count
|
||||
:amount balance
|
||||
:account-type (:account_type account)
|
||||
:numeric-code (:numeric_code account)
|
||||
:name (:name account) }))
|
||||
|
||||
client-ids)))
|
||||
)
|
||||
args (assoc (:query-params request)
|
||||
:periods (filter identity (cond-> [date]
|
||||
include-comparison (conj comparison-date))))
|
||||
clients (pull-many (dc/db conn) [:client/code :client/name :db/id] client-ids)
|
||||
|
||||
data (concat (->> (:balance-sheet-accounts data)
|
||||
(map (fn [b]
|
||||
(assoc b
|
||||
:period (:date args)))))
|
||||
(->> (:comparable-balance-sheet-accounts data)
|
||||
(map (fn [b]
|
||||
(assoc b
|
||||
:period (:comparison-date args))))))
|
||||
pnl-data (l-reports/->PNLData args data (by :db/id :client/code clients))
|
||||
client-count (count (set (map :client-id (:data pnl-data))))
|
||||
report (l-reports/summarize-balance-sheet pnl-data) ]
|
||||
(alog/info ::balance-sheet :params args)
|
||||
(let [{:keys [data report]} (get-report request)
|
||||
client-count (count (set (map :client-id (:data data)))) ]
|
||||
(list
|
||||
[:div.text-2xl.font-bold.text-gray-600 (str "Balance Sheet - " (str/join ", " (map :client/name clients))) ]
|
||||
[:div.text-2xl.font-bold.text-gray-600 (str "Balance Sheet - " (str/join ", " (map :client/name client))) ]
|
||||
(table {:widths (cond-> (into [30 ] (repeat 13 client-count))
|
||||
(:include-comparison args) (into (repeat 13 (* 2 client-count))))
|
||||
(:include-comparison (:args data)) (into (repeat 13 (* 2 client-count))))
|
||||
:click-event ::investigate-clicked
|
||||
:table report} ))))])
|
||||
|
||||
(defn form* [request]
|
||||
|
||||
(let [params (merge (:query-params request) (:form-params request) {})]
|
||||
(fc/start-form
|
||||
|
||||
params
|
||||
(:form-errors request)
|
||||
[:div#balance-sheet-form.flex.flex-col.gap-4.mt-4
|
||||
[:form {:hx-get (bidi.bidi/path-for ssr-routes/only-routes ::route/run-balance-sheet)
|
||||
:hx-target "#balance-sheet-form"
|
||||
:hx-swap "outerHTML"}
|
||||
[:div.flex.gap-8 {:x-data (hx/json {:comparison (boolean (:include-comparison params))})}
|
||||
(fc/with-field :client
|
||||
(com/validated-inline-field
|
||||
{:label "Customers" :errors (fc/field-errors)}
|
||||
(com/multi-typeahead {:name (fc/field-name)
|
||||
:class "w-64"
|
||||
:id "client"
|
||||
:url (bidi/path-for ssr-routes/only-routes :company-search)
|
||||
:value (fc/field-value)
|
||||
:value-fn :db/id
|
||||
:content-fn :client/name})))
|
||||
(fc/with-field :date
|
||||
(com/validated-inline-field {:label "Date"
|
||||
:errors (fc/field-errors)}
|
||||
(com/date-input {:placeholder "12/21/2020"
|
||||
:name (fc/field-name)
|
||||
:value (some-> (fc/field-value)
|
||||
(atime/unparse-local atime/normal-date))})))
|
||||
(fc/with-field :include-comparison
|
||||
(com/toggle {:x-model "comparison" :name (fc/field-name) :checked (boolean (fc/field-value))} "Compare"))
|
||||
[:div (hx/alpine-appear {:x-show "comparison"})
|
||||
(fc/with-field :comparison-date
|
||||
(com/validated-inline-field {:label "Previous Date"
|
||||
:errors (fc/field-errors)}
|
||||
|
||||
(com/date-input {:placeholder "12/21/2020"
|
||||
:name (fc/field-name)
|
||||
:value (some-> (fc/field-value)
|
||||
(atime/unparse-local atime/normal-date))})))]
|
||||
(com/button {:color :primary :class "w-32"}
|
||||
"Run")]]
|
||||
[:div.flex.gap-8
|
||||
[:form {:hx-get (bidi.bidi/path-for ssr-routes/only-routes ::route/run-balance-sheet)
|
||||
:hx-target "#balance-sheet-form"
|
||||
:hx-swap "outerHTML"
|
||||
:hx-disabled-elt "find fieldset"}
|
||||
[:fieldset
|
||||
[:div.flex.gap-8 {:x-data (hx/json {:comparison (boolean (:include-comparison params))})}
|
||||
(fc/with-field :client
|
||||
(com/validated-inline-field
|
||||
{:label "Customers" :errors (fc/field-errors)}
|
||||
(com/multi-typeahead {:name (fc/field-name)
|
||||
:class "w-64"
|
||||
:id "client"
|
||||
:url (bidi/path-for ssr-routes/only-routes :company-search)
|
||||
:value (or (fc/field-value)
|
||||
(take 5 (:clients request)))
|
||||
:value-fn :db/id
|
||||
:content-fn :client/name})))
|
||||
(fc/with-field :date
|
||||
(com/validated-inline-field {:label "Date"
|
||||
:errors (fc/field-errors)}
|
||||
(com/date-input {:placeholder "12/21/2020"
|
||||
:name (fc/field-name)
|
||||
:value (some->
|
||||
(or (fc/field-value) (t/now))
|
||||
(atime/unparse-local atime/normal-date))})))
|
||||
(fc/with-field :include-comparison
|
||||
(com/toggle {:x-model "comparison" :name (fc/field-name) :checked (boolean (fc/field-value))} "Compare"))
|
||||
[:div (hx/alpine-appear {:x-show "comparison"})
|
||||
(fc/with-field :comparison-date
|
||||
(com/validated-inline-field {:label "Previous Date"
|
||||
:errors (fc/field-errors)}
|
||||
|
||||
(com/date-input {:placeholder "12/21/2020"
|
||||
:name (fc/field-name)
|
||||
:value (some-> (or (fc/field-value) (t/plus (t/now) (t/years -1)))
|
||||
(atime/unparse-local atime/normal-date))})))]
|
||||
(com/button {:color :primary :class "w-32"}
|
||||
"Run")
|
||||
(com/button {:formaction (bidi.bidi/path-for ssr-routes/only-routes ::route/export-balance-sheet) } "Export PDF")]]] ]
|
||||
(balance-sheet* request)])))
|
||||
|
||||
(defn form [request]
|
||||
@@ -335,6 +351,71 @@
|
||||
(form* request))
|
||||
"Balance Sheet"))
|
||||
|
||||
(defn make-balance-sheet-pdf [request report]
|
||||
|
||||
(let [ output-stream (ByteArrayOutputStream.)
|
||||
client-count (count (or (seq (:client (:query-params request)))
|
||||
(seq (:client (:form-params request)))))]
|
||||
(pdf/pdf
|
||||
(-> [{:left-margin 10 :right-margin 10 :top-margin 15 :bottom-margin 15
|
||||
:size :letter
|
||||
:font {:size 6
|
||||
:ttf-name "fonts/calibri-light.ttf"}}
|
||||
[:heading (str "Balance Sheet - " (str/join ", " (map :client/name (or (seq (:client (:query-params request)))
|
||||
(seq (:client (:form-params request)))))))]]
|
||||
|
||||
(conj [:paragraph {:color [128 0 0] :size 9} (:warning report)])
|
||||
(conj
|
||||
(table->pdf report
|
||||
(cond-> (into [30 ] (repeat client-count 13))
|
||||
(or (:include-comparison (:query-params request))
|
||||
(:include-comparison (:form-params request))) (into (repeat (* 2 client-count) 13))))))
|
||||
output-stream)
|
||||
(.toByteArray output-stream)))
|
||||
|
||||
(defn print-balance-sheet [request]
|
||||
(let [uuid (str (UUID/randomUUID))
|
||||
pdf-data (make-balance-sheet-pdf request (:report (get-report request)))
|
||||
name "test" #_(balance-sheet-args->name args)
|
||||
key (str "reports/balance-sheet/" uuid "/" name ".pdf")
|
||||
url (str "https://" (:data-bucket env) "/" key)]
|
||||
(s3/put-object :bucket-name (:data-bucket env/env)
|
||||
:key key
|
||||
:input-stream (io/make-input-stream pdf-data {})
|
||||
:metadata {:content-length (count pdf-data)
|
||||
:content-type "application/pdf"})
|
||||
@(dc/transact conn
|
||||
[{:report/name name
|
||||
:report/client (map :db/id (:client (:query-params request)))
|
||||
:report/key key
|
||||
:report/url url
|
||||
:report/creator (:user (:identity request))
|
||||
:report/created (java.util.Date.)}])
|
||||
{:report/name name
|
||||
:report/url url }))
|
||||
|
||||
(defn export [request]
|
||||
(modal-response
|
||||
(com/modal {}
|
||||
(com/modal-card
|
||||
{}
|
||||
"Ready!"
|
||||
(com/modal-body {}
|
||||
[:div.flex.flex-col.mt-4.space-y-4.items-center
|
||||
[:a {:href (:report/url (print-balance-sheet request))}
|
||||
[:div.w-24.h-24.bg-green-50.rounded-full.p-4.text-green-300 {:class " hover:scale-110 transition duration-100"}
|
||||
|
||||
svg/download]]
|
||||
[:span.text-gray-800
|
||||
"Click "
|
||||
(com/link {:href (:report/url (print-balance-sheet request))} "here")
|
||||
" to download"]
|
||||
])
|
||||
nil))
|
||||
:headers (-> {}
|
||||
(assoc "hx-retarget" ".modal-stack")
|
||||
(assoc "hx-reswap" "beforeend"))))
|
||||
|
||||
(def key->handler
|
||||
(apply-middleware-to-all-handlers
|
||||
(->
|
||||
@@ -343,7 +424,11 @@
|
||||
(wrap-form-4xx-2 balance-sheet))
|
||||
::route/run-balance-sheet (-> form
|
||||
(wrap-schema-enforce :query-schema query-schema)
|
||||
(wrap-form-4xx-2 form))})
|
||||
(wrap-form-4xx-2 form))
|
||||
::route/export-balance-sheet (-> export
|
||||
(wrap-schema-enforce :query-schema query-schema)
|
||||
(wrap-form-4xx-2 form))}
|
||||
)
|
||||
(fn [h]
|
||||
(-> h
|
||||
(wrap-merge-prior-hx)
|
||||
|
||||
@@ -8,4 +8,5 @@
|
||||
"/table" ::table
|
||||
"/bank-account-filter" ::bank-account-filter
|
||||
"/reports/balance-sheet" {"" ::balance-sheet
|
||||
"run" ::run-balance-sheet}})
|
||||
"/run" ::run-balance-sheet
|
||||
"/export" ::export-balance-sheet}})
|
||||
Reference in New Issue
Block a user