5 Commits

Author SHA1 Message Date
Bryce
b02aec3546 Move sales summaries from admin to pos menu
- Move SSR handler from auto-ap.ssr.admin.sales-summaries to auto-ap.ssr.pos.sales-summaries
- Move route namespace from auto-ap.routes.admin.sales-summaries to auto-ap.routes.pos.sales-summaries
- Update nav to use main-aside-nav with POS breadcrumbs
- Use pos.common date-range-field* filter component
- Remove wrap-admin/wrap-client-redirect-unauthenticated from middleware
- Add Summaries to Sales sidebar menu
2026-05-16 00:13:42 -07:00
Bryce
5a39a0c762 fixes for sales summaries being automatic. 2026-05-15 23:22:38 -07:00
95f12a6072 refactor: remove dead calc-aggregate-totals and unused schema attributes
The 13 sales-summary/total-* attributes were computed and stored but never
read — the only consumer (get-debits) was commented out. Active display code
computes totals on-the-fly from the items list instead.
2026-05-15 23:22:38 -07:00
0e76506c22 consolidate sales summary ledger entry creation into upsert-sales-summary tx
Move journal entry calculation and creation from the reconcile-ledger
background job into the upsert-sales-summary tx function. Now any save
of a sales summary (job recalculation, admin edit wizard, or manual
touch) automatically creates the journal entry if balanced with all
accounts mapped, or retracts it if conditions no longer hold. Eliminates
the need for a separate upsert-sales-summary-ledger call and the
reconcile ledger pass for sales summaries.
2026-05-15 23:22:38 -07:00
baf8cfff97 feat: complete automatic sales summary calculations and ledger posting 2026-05-15 23:22:38 -07:00
7 changed files with 230 additions and 328 deletions

File diff suppressed because one or more lines are too long

View File

@@ -178,8 +178,7 @@
(conj (conj
(table->pdf report (table->pdf report
(cond-> (into [30 ] (repeat client-count 13)) (cond-> (into [30 ] (repeat client-count 13))
(:include-comparison args) (into (repeat (* 2 client-count) 13)) (:include-comparison args) (into (repeat (* 2 client-count) 13))))))
(and (> client-count 1) (not (:include-comparison args))) (conj 13)))))
output-stream) output-stream)
(.toByteArray output-stream))) (.toByteArray output-stream)))

View File

@@ -120,8 +120,7 @@
(list (list
[:div.text-2xl.font-bold.text-gray-600 (str "Balance Sheet - " (str/join ", " (map :client/name client))) ] [:div.text-2xl.font-bold.text-gray-600 (str "Balance Sheet - " (str/join ", " (map :client/name client))) ]
(rtable/table {:widths (cond-> (into [30 ] (repeat 13 client-count)) (rtable/table {:widths (cond-> (into [30 ] (repeat 13 client-count))
(> (count date) 1) (into (repeat 13 (* 2 client-count (dec (count date))))) (> (count date) 1) (into (repeat 13 (* 2 client-count (dec (count date))))))
(and (> client-count 1) (= (count date) 1)) (conj 13))
:investigate-url (bidi.bidi/path-for ssr-routes/only-routes ::route/investigate) :investigate-url (bidi.bidi/path-for ssr-routes/only-routes ::route/investigate)
:table report :table report
:warning (not-empty (str/join "\n " (filter not-empty [warning (:warning report)])))} ))))]) :warning (not-empty (str/join "\n " (filter not-empty [warning (:warning report)])))} ))))])
@@ -203,8 +202,7 @@
(conj (conj
(table->pdf report (table->pdf report
(cond-> (into [30 ] (repeat client-count 13)) (cond-> (into [30 ] (repeat client-count 13))
(> (count date) 1) (into (repeat (* 2 client-count (dec (count date))) 13 )) (> (count date) 1) (into (repeat (* 2 client-count (dec (count date))) 13 ))))))
(and (> client-count 1) (= (count date) 1)) (conj 13)))))
output-stream) output-stream)
(.toByteArray output-stream))) (.toByteArray output-stream)))

View File

@@ -6,12 +6,10 @@
[auto-ap.datomic.accounts :as d-accounts] [auto-ap.datomic.accounts :as d-accounts]
[auto-ap.graphql.utils :refer [extract-client-ids]] [auto-ap.graphql.utils :refer [extract-client-ids]]
[auto-ap.query-params :refer [wrap-copy-qp-pqp]] [auto-ap.query-params :refer [wrap-copy-qp-pqp]]
[auto-ap.client-routes :as client-routes]
[auto-ap.routes.pos.sales-summaries :as route] [auto-ap.routes.pos.sales-summaries :as route]
[auto-ap.ssr-routes :as ssr-routes] [auto-ap.ssr-routes :as ssr-routes]
[auto-ap.ssr.common-handlers :refer [add-new-entity-handler]] [auto-ap.ssr.common-handlers :refer [add-new-entity-handler]]
[auto-ap.ssr.components :as com] [auto-ap.ssr.components :as com]
[auto-ap.ssr.components.link-dropdown :refer [link-dropdown]]
[auto-ap.ssr.components.multi-modal :as mm] [auto-ap.ssr.components.multi-modal :as mm]
[auto-ap.ssr.form-cursor :as fc] [auto-ap.ssr.form-cursor :as fc]
[auto-ap.ssr.grid-page-helper :as helper :refer [wrap-apply-sort]] [auto-ap.ssr.grid-page-helper :as helper :refer [wrap-apply-sort]]
@@ -29,7 +27,7 @@
[clojure.string :as str] [clojure.string :as str]
[datomic.api :as dc] [datomic.api :as dc]
[hiccup.util :as hu] [hiccup.util :as hu]
[iol-ion.query :refer [dollars= dollars-0?]] [iol-ion.query :refer [dollars=]]
[malli.core :as mc] [malli.core :as mc]
[malli.util :as mut])) [malli.util :as mut]))
@@ -57,14 +55,15 @@
* *
[:sales-summary/date :xform clj-time.coerce/from-date] [:sales-summary/date :xform clj-time.coerce/from-date]
{:sales-summary/client [:client/code :client/name :db/id]} {:sales-summary/client [:client/code :client/name :db/id]}
{:sales-summary/items [{[:ledger-mapped/ledger-side :xform iol-ion.query/ident] [:db/ident]} {:sales-summary/items [{[:ledger-mapped/ledger-side :xform iol-ion.query/ident] [:db/ident]
}
:ledger-mapped/account :ledger-mapped/account
:ledger-mapped/amount :ledger-mapped/amount
:sales-summary-item/category :sales-summary-item/category
:sales-summary-item/sort-order :sales-summary-item/sort-order
:db/id :db/id
:sales-summary-item/manual?]} :sales-summary-item/manual?]
{:journal-entry/original-entity [:db/id]}]) } ])
(defn fetch-ids [db request] (defn fetch-ids [db request]
(let [query-params (:query-params request) (let [query-params (:query-params request)
@@ -91,6 +90,7 @@
:where [[(< ?d ?end-date)]]} :where [[(< ?d ?end-date)]]}
:args [(-> query-params :end-date c/to-date)]}) :args [(-> query-params :end-date c/to-date)]})
true true
(merge-query {:query {:find ['?sort-default '?e] (merge-query {:query {:find ['?sort-default '?e]
:where ['[?e :sales-summary/date ?sort-default]]}}))] :where ['[?e :sales-summary/date ?sort-default]]}}))]
@@ -116,6 +116,9 @@
(defn sort-items [ss] (defn sort-items [ss]
(sort-by (juxt :ledger-mapped/ledger-side :sales-summary-item/sort-order :sales-summary-item/category) ss)) (sort-by (juxt :ledger-mapped/ledger-side :sales-summary-item/sort-order :sales-summary-item/category) ss))
(defn total-debits [items] (defn total-debits [items]
(->> items (->> items
(filter #(= :ledger-side/debit (:ledger-mapped/ledger-side %))) (filter #(= :ledger-side/debit (:ledger-mapped/ledger-side %)))
@@ -128,11 +131,6 @@
(map #(:ledger-mapped/amount % 0.0)) (map #(:ledger-mapped/amount % 0.0))
(reduce + 0.0))) (reduce + 0.0)))
(defn truncate [s max-len]
(if (> (count s) max-len)
(str (subs s 0 (- max-len 3)) "...")
s))
(def grid-page (def grid-page
(helper/build {:id "entity-table" (helper/build {:id "entity-table"
:id-fn :db/id :id-fn :db/id
@@ -165,100 +163,46 @@
(= (count (:clients args)) 1)) (= (count (:clients args)) 1))
:render #(-> % :sales-summary/client :client/code)} :render #(-> % :sales-summary/client :client/code)}
{:key "date" {:key "date"
:name "Date" :name "Date"
:sort-key "date" :sort-key "date"
:render #(some-> % :sales-summary/date (atime/unparse-local atime/normal-date))} :render #(some-> % :sales-summary/date (atime/unparse-local atime/normal-date))}
{:key "debits" {:key "debits"
:name "Debits" :name "debits"
:sort-key "debits" :sort-key "debits"
:class "w-72 align-top"
:render (fn [ss] :render (fn [ss]
(let [items (:sales-summary/items ss) (let [total-debits (total-debits (:sales-summary/items ss))
debit-items (filter #(= :ledger-side/debit (:ledger-mapped/ledger-side %)) (sort-items items)) total-credits (total-credits (:sales-summary/items ss))]
credit-count (count (filter #(= :ledger-side/credit (:ledger-mapped/ledger-side %)) items)) [:ul
total-debits (total-debits items)] (for [si (sort-items (:sales-summary/items ss))
[:div.flex.flex-col.h-full :when (= :ledger-side/debit (:ledger-mapped/ledger-side si))]
[:ul.flex-grow [:li (:sales-summary-item/category si) ": " (format "$%,.2f" (:ledger-mapped/amount si))
(for [si debit-items]
[:li.flex.items-baseline.gap-2.py-0.5.text-sm.text-gray-700
[:span.flex-1.min-w-0.truncate.text-gray-600
(:sales-summary-item/category si)]
(when-not (:ledger-mapped/account si) (when-not (:ledger-mapped/account si)
[:span.shrink-0 (com/pill {:color :red} "?")]) [:span.pl-4 (com/pill {:color :red}
[:span.shrink-0.font-mono.tabular-nums.text-right.text-gray-900.whitespace-nowrap "missing account")])]
(format "$%,.2f" (:ledger-mapped/amount si))]]) )
(for [_ (range (max 0 (- credit-count (count debit-items))))] [:li (com/pill {:color (if (dollars= total-debits total-credits)
[:li.py-0.5.text-sm " "])] :primary
[:div.border-t-2.border-gray-300.mt-1.pt-1.flex.justify-between.items-baseline :red)} "Total: " (format "$%,.2f" total-debits))]]))}
[:span.text-xs.uppercase.tracking-wider.font-semibold.text-gray-500 "Total"]
[:span.font-mono.tabular-nums.font-bold.text-gray-900
(format "$%,.2f" total-debits)]]]))}
{:key "credits" {:key "credits"
:name "Credits" :name "credits"
:sort-key "credits" :sort-key "credits"
:class "w-72 align-top"
:render (fn [ss] :render (fn [ss]
(let [items (:sales-summary/items ss) (let [total-debits (total-debits (:sales-summary/items ss))
credit-items (filter #(= :ledger-side/credit (:ledger-mapped/ledger-side %)) (sort-items items)) total-credits (total-credits (:sales-summary/items ss))]
debit-count (count (filter #(= :ledger-side/debit (:ledger-mapped/ledger-side %)) items)) [:ul
total-credits (total-credits items)] (for [si (sort-items (:sales-summary/items ss))
[:div.flex.flex-col.h-full :when (= :ledger-side/credit (:ledger-mapped/ledger-side si))]
[:ul.flex-grow [:li (:sales-summary-item/category si) ": " (format "$%,.2f" (:ledger-mapped/amount si))
(for [si credit-items]
[:li.flex.items-baseline.gap-2.py-0.5.text-sm.text-gray-700
[:span.flex-1.min-w-0.truncate.text-gray-600
(:sales-summary-item/category si)]
(when-not (:ledger-mapped/account si) (when-not (:ledger-mapped/account si)
[:span.shrink-0 (com/pill {:color :red} "?")]) [:span.pl-4 (com/pill {:color :red}
[:span.shrink-0.font-mono.tabular-nums.text-right.text-gray-900.whitespace-nowrap "missing account")])])
(format "$%,.2f" (:ledger-mapped/amount si))]]) [:li (com/pill {:color (if (dollars= total-debits total-credits)
(for [_ (range (max 0 (- debit-count (count credit-items))))] :primary
[:li.py-0.5.text-sm " "])] :red)} "Total: " (format "$%,.2f" total-credits))]]))}]}))
[:div.border-t-2.border-gray-300.mt-1.pt-1.flex.justify-between.items-baseline
[:span.text-xs.uppercase.tracking-wider.font-semibold.text-gray-500 "Total"]
[:span.font-mono.tabular-nums.font-bold.text-gray-900
(format "$%,.2f" total-credits)]]]))}
{:key "balance"
:name "Status"
:sort-key "balance"
:class "w-28 align-top"
:render (fn [ss]
(let [items (:sales-summary/items ss)
total-debits (total-debits items)
total-credits (total-credits items)
delta (- total-debits total-credits)
balanced? (dollars= total-debits total-credits)
missing-account? (some #(not (:ledger-mapped/account %)) items)]
[:div.flex.flex-col.items-center.gap-1.pt-2
(when missing-account?
[:span.inline-block.text-xs.font-semibold.uppercase.tracking-wider.text-amber-800.bg-amber-100.border.border-amber-300.rounded-sm.px-1.5.py-0.5
"Missing acct"])
(if balanced?
(when-not missing-account?
[:span.inline-block.text-xs.font-semibold.uppercase.tracking-wider.text-emerald-800.bg-emerald-100.border.border-emerald-300.rounded-sm.px-1.5.py-0.5
"Balanced"])
[:div.flex.flex-col.items-center
[:span.font-mono.tabular-nums.text-red-700.font-bold.text-sm
(format "$%,.2f" (Math/abs delta))]
[:span.text-xs.uppercase.tracking-wider.text-red-600.font-medium.mt-0.5
(if (> total-debits total-credits) "Debit over" "Credit over")]])]))}
{:key "links"
:name "Links"
:show-starting "lg"
:class "w-8"
:render (fn [ss]
(let [ledger-entry (:journal-entry/original-entity ss)]
(when (seq ledger-entry)
(link-dropdown
[{:link (hu/url (bidi/path-for client-routes/routes :ledger)
{:exact-match-id (:db/id (first ledger-entry))})
:color :yellow
:content "Ledger entry"}]))))}]}))
(def row* (partial helper/row* grid-page)) (def row* (partial helper/row* grid-page))
(def table* (partial helper/table* grid-page)) (def table* (partial helper/table* grid-page))
@@ -291,6 +235,7 @@
(not (and (:credit x) (not (and (:credit x)
(:debit x))))]]]] ]) (:debit x))))]]]] ])
(defn summary-total-row* [request] (defn summary-total-row* [request]
(let [total-credits (-> request (let [total-credits (-> request
:multi-form-state :multi-form-state
@@ -304,22 +249,16 @@
(total-debits))] (total-debits))]
(com/data-grid-row {:id "total-row" (com/data-grid-row {:id "total-row"
:class "bg-slate-50 border-t-2 border-slate-300"
:hx-trigger "change from:closest form target:.amount-field" :hx-trigger "change from:closest form target:.amount-field"
:hx-put (bidi.bidi/path-for ssr-routes/only-routes ::route/expense-account-total) :hx-put (bidi.bidi/path-for ssr-routes/only-routes ::route/expense-account-total)
:hx-target "this" :hx-target "this"
:hx-swap "innerHTML"} :hx-swap "innerHTML"}
(com/data-grid-cell {}) (com/data-grid-cell {})
(com/data-grid-cell {:class "text-right"} [:span.font-bold.text-right "TOTAL"])
(com/data-grid-cell {:class "text-right"} (com/data-grid-cell {:class "text-right"}
[:span.text-xs.uppercase.tracking-wider.font-semibold.text-slate-600 (format "$%,.2f" total-debits))
"Total"])
(com/data-grid-cell {:class "text-right"} (com/data-grid-cell {:class "text-right"}
[:span.font-mono.tabular-nums.font-bold.text-slate-900 (format "$%,.2f" total-credits)))))
(format "$%,.2f" total-debits)])
(com/data-grid-cell {:class "text-right"}
[:span.font-mono.tabular-nums.font-bold.text-slate-900
(format "$%,.2f" total-credits)])
(com/data-grid-cell {}))))
(defn unbalanced-row* [request] (defn unbalanced-row* [request]
(let [total-credits (-> request (let [total-credits (-> request
@@ -331,31 +270,25 @@
:multi-form-state :multi-form-state
:step-params :step-params
:sales-summary/items :sales-summary/items
(total-debits)) (total-debits))]
unbalanced? (not (dollars= total-credits total-debits))
debit-over? (and unbalanced? (> total-debits total-credits))
credit-over? (and unbalanced? (> total-credits total-debits))]
(com/data-grid-row {:id "unbalanced-row" (com/data-grid-row {:id "total-row"
:class (when unbalanced? "bg-red-50 border-t border-red-200")
:hx-trigger "change from:closest form target:.amount-field" :hx-trigger "change from:closest form target:.amount-field"
:hx-put (bidi.bidi/path-for ssr-routes/only-routes ::route/expense-account-total) :hx-put (bidi.bidi/path-for ssr-routes/only-routes ::route/expense-account-total)
:hx-target "this" :hx-target "this"
:hx-swap "innerHTML"} :hx-swap "innerHTML"}
(com/data-grid-cell {}) (com/data-grid-cell {})
(com/data-grid-cell {:class "text-right"} [:span.font-bold.text-right "UNBALANCED"])
(com/data-grid-cell {:class "text-right"} (com/data-grid-cell {:class "text-right"}
(when unbalanced? (when (and
[:span.text-xs.uppercase.tracking-wider.font-semibold.text-red-700 (not (dollars= total-credits total-debits))
"Out of balance"])) (> total-debits total-credits))
(format "$%,.2f" (- total-debits total-credits))))
(com/data-grid-cell {:class "text-right"} (com/data-grid-cell {:class "text-right"}
(when debit-over? (when
[:span.font-mono.tabular-nums.font-bold.text-red-700 (and (not (dollars= total-credits total-debits))
(format "$%,.2f" (- total-debits total-credits))])) (> total-credits total-debits))
(com/data-grid-cell {:class "text-right"} (format "$%,.2f" (- total-credits total-debits)))))))
(when credit-over?
[:span.font-mono.tabular-nums.font-bold.text-red-700
(format "$%,.2f" (- total-credits total-debits))]))
(com/data-grid-cell {}))))
(defn- account-typeahead* (defn- account-typeahead*
[{:keys [name value client-id]}] [{:keys [name value client-id]}]
@@ -373,9 +306,7 @@
(defn sales-summary-item-row* [{:keys [value client-id]}] (defn sales-summary-item-row* [{:keys [value client-id]}]
(let [manual? (fc/field-value (:sales-summary-item/manual? value))] (let [manual? (fc/field-value (:sales-summary-item/manual? value))]
(com/data-grid-row (cond-> {:x-ref "p" (com/data-grid-row (cond-> {:x-ref "p"
:x-data (hx/json {}) :x-data (hx/json {})}
:class (when manual?
"bg-indigo-50/40 border-l-2 border-indigo-300")}
(fc/field-value (:new? value)) (hx/htmx-transition-appear )) (fc/field-value (:new? value)) (hx/htmx-transition-appear ))
(fc/with-field :db/id (fc/with-field :db/id
(com/hidden {:name (fc/field-name) (com/hidden {:name (fc/field-name)
@@ -384,7 +315,7 @@
(fc/with-field :sales-summary-item/manual? (fc/with-field :sales-summary-item/manual?
(com/hidden {:name (fc/field-name) (com/hidden {:name (fc/field-name)
:value true}))) :value true})))
(com/data-grid-cell {:class "align-top"} (com/data-grid-cell {}
(fc/with-field :sales-summary-item/category (fc/with-field :sales-summary-item/category
(if manual? (if manual?
(com/validated-field {:errors (fc/field-errors)} (com/validated-field {:errors (fc/field-errors)}
@@ -395,38 +326,35 @@
(list (list
(com/hidden {:name (fc/field-name) (com/hidden {:name (fc/field-name)
:value (fc/field-value)}) :value (fc/field-value)})
[:span.text-sm.text-gray-700 (fc/field-value (:sales-summary-item/category value))))))
(fc/field-value (:sales-summary-item/category value))])))) (com/data-grid-cell {}
(com/data-grid-cell {:class "align-top"}
(fc/with-field :ledger-mapped/account (fc/with-field :ledger-mapped/account
(com/validated-field {:errors (fc/field-errors)} (com/validated-field {:errors (fc/field-errors)}
(account-typeahead* {:value (fc/field-value) (account-typeahead* {:value (fc/field-value)
:client-id client-id :client-id client-id
:name (fc/field-name)})))) :name (fc/field-name)}))))
(com/data-grid-cell {:class "text-right align-top"} (com/data-grid-cell {:class "text-right"}
(if manual? (if manual?
(fc/with-field :debit (fc/with-field :debit
(com/validated-field {:errors (fc/field-errors)} (com/validated-field {:errors (fc/field-errors)}
(com/money-input {:class "w-24 text-right font-mono tabular-nums" (com/money-input {:class "w-24"
:name (fc/field-name) :name (fc/field-name)
:value (fc/field-value)}))) :value (fc/field-value)})))
(when (= (fc/field-value (:ledger-mapped/ledger-side value)) (when (= (fc/field-value (:ledger-mapped/ledger-side value))
:ledger-side/debit) :ledger-side/debit)
[:span.font-mono.tabular-nums.text-gray-900.text-sm.whitespace-nowrap (format "$%,.2f" (fc/field-value (:ledger-mapped/amount value))))))
(format "$%,.2f" (fc/field-value (:ledger-mapped/amount value)))]))) (com/data-grid-cell {:class "text-right"}
(com/data-grid-cell {:class "text-right align-top"}
(if manual? (if manual?
(fc/with-field :credit (fc/with-field :credit
(com/validated-field {:errors (fc/field-errors)} (com/validated-field {:errors (fc/field-errors)}
(com/money-input {:class "w-24 text-right font-mono tabular-nums" (com/money-input {:class "w-24"
:name (fc/field-name) :name (fc/field-name)
:value (fc/field-value)}))) :value (fc/field-value)})))
(when (= (fc/field-value (:ledger-mapped/ledger-side value)) (when (= (fc/field-value (:ledger-mapped/ledger-side value))
:ledger-side/credit) :ledger-side/credit)
[:span.font-mono.tabular-nums.text-gray-900.text-sm.whitespace-nowrap (format "$%,.2f" (fc/field-value (:ledger-mapped/amount value))))))
(format "$%,.2f" (fc/field-value (:ledger-mapped/amount value)))])))
(com/data-grid-cell {:class "align-top"} (com/data-grid-cell {:class "align-top"}
(when manual? (when manual?
(com/a-icon-button {"@click.prevent.stop" "$refs.p.remove()"} svg/x)))))) (com/a-icon-button {"@click.prevent.stop" "$refs.p.remove()"} svg/x))))))
@@ -477,7 +405,7 @@
:footer :footer
(mm/default-step-footer linear-wizard this :validation-route ::route/edit-wizard-navigate) (mm/default-step-footer linear-wizard this :validation-route ::route/edit-wizard-navigate)
:validation-route ::route/edit-wizard-navigate :validation-route ::route/edit-wizard-navigate
:width-height-class "lg:w-[920px] lg:h-[640px]"))) :width-height-class "lg:w-[850px] lg:h-[900px]")))
(defn attach-ledger [i] (defn attach-ledger [i]
(cond-> i (cond-> i
@@ -522,7 +450,8 @@
(if (:sales-summary-item/manual? i) (if (:sales-summary-item/manual? i)
(attach-ledger i) (attach-ledger i)
{:db/id (:db/id i) {:db/id (:db/id i)
:ledger-mapped/account (:ledger-mapped/account i)})) :ledger-mapped/account (:ledger-mapped/account i)
}))
(:sales-summary/items result))}]] (:sales-summary/items result))}]]
(clojure.pprint/pprint (:sales-summary/items result)) (clojure.pprint/pprint (:sales-summary/items result))
@(dc/transact conn [ transaction]) @(dc/transact conn [ transaction])

View File

@@ -798,23 +798,20 @@
(defn balance-sheet-headers [pnl-data] (defn balance-sheet-headers [pnl-data]
(let [period-count (count (:periods (:args pnl-data))) (let [period-count (count (:periods (:args pnl-data)))]
client-ids (set (map :client-id (:data pnl-data)))
client-count (count client-ids)
show-total? (and (> client-count 1) (= 1 period-count))]
(cond-> [] (cond-> []
(> client-count 1) (> (count (set (map :client-id (:data pnl-data)))) 1)
(conj (cond-> (into [{:value "Client"}] (conj (into [{:value "Client"}]
(mapcat identity
(for [client client-ids]
(cond-> [{:value (str (-> pnl-data :client-codes (get client)))}]
(> period-count 1)
(into (apply concat (repeat (dec period-count) ["" ""])))))))
show-total? (conj {:value "Total" :bold true :border [:left]})))
(mapcat identity
(for [client (set (map :client-id (:data pnl-data))) ]
(cond-> [{:value (str (-> pnl-data :client-codes (get client)))}]
(> period-count 1)
(into (apply concat (repeat (dec period-count) ["" ""]))))))))
true true
(conj (cond-> (into [{:value "Period Ending"}] (conj (into [{:value "Period Ending"}]
(for [client client-ids (for [client (set (map :client-id (:data pnl-data)))
[index p] (map vector (range) (:periods (:args pnl-data))) [index p] (map vector (range) (:periods (:args pnl-data)))
:let [is-first? (= 0 index) :let [is-first? (= 0 index)
period-date (date->str p) period-date (date->str p)
@@ -824,8 +821,7 @@
[{:value period-date} [{:value period-date}
{:value "+/-"}])] {:value "+/-"}])]
header period-headers] header period-headers]
header)) header))))))
show-total? (conj {:value (date->str (first (:periods (:args pnl-data)))) :border [:left]}))))))
(defn append-deltas [table] (defn append-deltas [table]
(->> table (->> table
@@ -894,33 +890,12 @@
:rows table}))) :rows table})))
) )
(defn add-total-border [rows]
(map (fn [row]
(let [last-idx (dec (count row))]
(map-indexed
(fn [i cell]
(if (= i last-idx)
(let [borders (or (:border cell) [])]
(assoc cell :border (conj borders :left)))
cell))
row)))
rows))
(defn summarize-balance-sheet [pnl-data] (defn summarize-balance-sheet [pnl-data]
(let [client-ids (set (map :client-id (:data pnl-data))) (let [pnl-datas (for [client-id (set (map :client-id (:data pnl-data)))
client-count (count client-ids)
period-count (count (:periods (:args pnl-data)))
show-total? (and (> client-count 1) (= 1 period-count))
pnl-datas (for [client-id client-ids
p (:periods (:args pnl-data))] p (:periods (:args pnl-data))]
(-> pnl-data (-> pnl-data
(filter-client client-id) (filter-client client-id)
(filter-period p))) (filter-period p)))]
total-data (when show-total?
(-> pnl-data
(filter-period (first (:periods (:args pnl-data))))
(assoc :cell-args {:bold true})))
pnl-datas (concat pnl-datas (when total-data [total-data]))]
(let [table (-> [] (let [table (-> []
(into (detail-rows pnl-datas (into (detail-rows pnl-datas
:assets :assets
@@ -937,11 +912,10 @@
(negate #{:cogs :payroll :controllable :fixed-overhead :ownership-controllable})) (negate #{:cogs :payroll :controllable :fixed-overhead :ownership-controllable}))
pnl-datas) pnl-datas)
"Retained Earnings"))) "Retained Earnings")))
table (if (and (> period-count 1) table (if (and (> (count (:periods (:args pnl-data))) 1)
(:include-deltas (:args pnl-data))) (:include-deltas (:args pnl-data)))
(append-deltas table) (append-deltas table)
table) table)]
table (if show-total? (add-total-border table) table)]
{:warning (warning-message pnl-data) {:warning (warning-message pnl-data)
:header (balance-sheet-headers pnl-data) :header (balance-sheet-headers pnl-data)
:rows table})) :rows table}))

View File

@@ -265,8 +265,7 @@ NOTE: Please review the transactions we may have question for you here: https://
[:div.notification.is-warning.is-light [:div.notification.is-warning.is-light
(:warning report)]) (:warning report)])
[rtable/table {:widths (cond-> (into [30 ] (repeat 13 client-count)) [rtable/table {:widths (cond-> (into [30 ] (repeat 13 client-count))
(:include-comparison args) (into (repeat 13 (* 2 client-count))) (:include-comparison args) (into (repeat 13 (* 2 client-count))))
(and (> client-count 1) (not (:include-comparison args))) (conj 13))
:click-event ::investigate-clicked :click-event ::investigate-clicked
:table report}]])) :table report}]]))

View File

@@ -1,2 +1,5 @@
#!/bin/bash #!/bin/bash
sudo docker run --rm -ti -v ~/dev/integreat/data/solr:/var/solr --network=bridge -p 8983:8983 679918342773.dkr.ecr.us-east-1.amazonaws.com/integreat-solr sudo docker run --rm -ti -v ~/dev/integreat/data/solr:/var/solr --network=bridge -p 8983:8983 bryce-solr
#sudo podman container run --user 1000 --privileged --volume /home/notid/dev/integreat/data/solr:/var/solr -p 8983:8983 bryce-solr