zebra striping + single table for column-per-location

This commit is contained in:
2022-04-04 15:27:56 -07:00
parent 52bd8b5671
commit 982a0f3bed
3 changed files with 139 additions and 81 deletions

View File

@@ -41,7 +41,8 @@
(= :dollar (:format cell)) (assoc :align :right) (= :dollar (:format cell)) (assoc :align :right)
(= :percent (:format cell)) (assoc :align :right) (= :percent (:format cell)) (assoc :align :right)
(:bold cell) (assoc-in [:ttf-name] "fonts/calibri-bold.ttf") (:bold cell) (assoc-in [:ttf-name] "fonts/calibri-bold.ttf")
(:color cell) (assoc :color (:color cell))) (:color cell) (assoc :color (:color cell))
(:bg-color cell) (assoc :background-color (:bg-color cell)))
cell-contents cell-contents
])) ]))
@@ -195,7 +196,7 @@
report (l-reports/summarize-pnl pnl-data) report (l-reports/summarize-pnl pnl-data)
output-stream (ByteArrayOutputStream.)] output-stream (ByteArrayOutputStream.)]
(pdf/pdf (pdf/pdf
(-> [{:left-margin 10 :right-margin 10 :top-margin 15 :bottom-margin 15 (-> [{:left-margin 10 :right-margin 10 :top-margin 5 :bottom-margin 15
:size (cond :size (cond
(and (>= (count (-> pnl-data :args :periods)) 8 ) (and (>= (count (-> pnl-data :args :periods)) 8 )
(-> pnl-data :args :include-deltas)) (-> pnl-data :args :include-deltas))

View File

@@ -177,6 +177,11 @@
(update :filters (fn [f] (update :filters (fn [f]
(assoc f :date-range period))))) (assoc f :date-range period)))))
(defn zebra [pnl-data i]
(if (odd? i)
(assoc-in pnl-data [:cell-args :bg-color] [240 240 240])
pnl-data))
(defn negate [pnl-data types] (defn negate [pnl-data types]
@@ -208,6 +213,7 @@
:value (aggregate-accounts p) :value (aggregate-accounts p)
:filters (when (:from-numeric-code (:filters p)) ;; don't allow filtering when you don't at least filter numeric codes :filters (when (:from-numeric-code (:filters p)) ;; don't allow filtering when you don't at least filter numeric codes
(:filters p))} (:filters p))}
(:cell-args p)
cell-args)) cell-args))
pnl-datas))) pnl-datas)))
@@ -221,10 +227,18 @@
(map (map
(fn [v s] (fn [v s]
{:border (:border v) {:border (:border v)
:format :percent :bg-color (:bg-color v)
:format (if (string? (:value v))
:text
:percent)
:color [128 128 128] :color [128 128 128]
:value (if (dollars-0? s) :value (cond
(string? (:value v))
""
(dollars-0? s)
0.0 0.0
:else
(/ (:value v) s))}) (/ (:value v) s))})
values sales)))))) values sales))))))
@@ -234,10 +248,16 @@
(->> values (->> values
(partition 2 1) (partition 2 1)
(map (fn [[a b]] (map (fn [[a b]]
(if (or (string? (:value b))
(string? (:value a)))
{:value ""
:format :text
:bg-color (:bg-color b)}
{:border (:border b) {:border (:border b)
:format :dollar :format :dollar
:value (- (:value b) :value (- (:value b)
(:value a))}))))))) (:value a))
:bg-color (:bg-color b)}))))))))
(defn combine-tables (defn combine-tables
([[pnl-data] table percent-of-sales deltas] ([[pnl-data] table percent-of-sales deltas]
@@ -259,11 +279,10 @@
deltas))) deltas)))
(defn headers [[pnl-data :as pnl-datas] header-title] (defn headers [[pnl-data :as pnl-datas] header-title]
(let [ (let [big-header (into [{:value header-title
big-header (into [{:value header-title
:bold true}] :bold true}]
(map (fn [p] (map-indexed (fn [i p]
{:value (cond-> {:value
(str (date->str (:start p)) (str (date->str (:start p))
" - " " - "
(date->str (:end p))) (date->str (:end p)))
@@ -278,27 +297,35 @@
:else :else
2) 2)
:align :center :align :center
:bold true}) :bold true}
(odd? i) (assoc :bg-color [240 240 240])))
(:periods (:args pnl-data)))) (:periods (:args pnl-data))))
sub-header (into [{:value ""}] sub-header (into [{:value ""}]
(if (-> pnl-data :args :column-per-location) (if (-> pnl-data :args :column-per-location)
(mapcat (mapcat
(fn [p] (fn [p]
(cond-> [{:value (-> p :filters :location) (cond-> [(merge {:value (or (
-> p :filters :location) "Total")
:align :right} :align :right}
{:value "%" (:cell-args p))
:align :right}] (merge {:value "%"
(-> pnl-data :args :include-deltas) (conj {:value "+/-" :align :right}
:align :right}))) (:cell-args p))]
(-> pnl-data :args :include-deltas) (conj (merge {:value "+/-"
:align :right}
(:cell-args p)))))
pnl-datas) pnl-datas)
(mapcat (mapcat
(fn [_] (fn [p]
(cond-> [{:value "Amt" (cond-> [(merge {:value "Amt"
:align :right} :align :right}
{:value "%" (:cell-args p))
:align :right}] (merge {:value "%"
(-> pnl-data :args :include-deltas) (conj {:value "+/-" :align :right}
:align :right}))) (:cell-args p))]
(-> pnl-data :args :include-deltas) (conj (merge {:value "+/-"
:align :right}
(:cell-args p)))))
pnl-datas)))] pnl-datas)))]
[big-header [big-header
sub-header])) sub-header]))
@@ -343,25 +370,36 @@
pnl-datas) pnl-datas)
account-codes (used-accounts pnl-datas)] account-codes (used-accounts pnl-datas)]
:when (seq account-codes) :when (seq account-codes)
row (-> [[{:value (str "---" grouping-name "---")}]] row (-> [(into [{:value (str "---" grouping-name "---")}]
(map
(fn [p]
(assoc (:cell-args p) :value "" :format ""))
pnl-datas)
)]
(into (for [{:keys [numeric-code name]} account-codes] (into (for [{:keys [numeric-code name]} account-codes]
(into [{:value name}] (into [{:value name}]
(map (map
(fn [p] (fn [p]
(let [pnl-data (-> p (filter-numeric-code numeric-code numeric-code))] (let [pnl-data (-> p (filter-numeric-code numeric-code numeric-code))]
(merge
{:format :dollar {:format :dollar
:filters (:filters pnl-data) :filters (:filters pnl-data)
:value (aggregate-accounts pnl-data)})) :value (aggregate-accounts pnl-data)}
(:cell-args p))))
pnl-datas)))) pnl-datas))))
(conj (subtotal-by-column-row pnl-datas "" {:border [:top]})))] (conj (subtotal-by-column-row pnl-datas "" {:border [:top]})))]
row)] row)]
(-> [[{:value title (-> [(into [{:value title
:bold true}]] :bold true}]
(map
(fn [p]
(assoc (:cell-args p) :value "" :format ""))
pnl-datas))]
(into individual-accounts) (into individual-accounts)
(conj (subtotal-by-column-row pnl-datas title))))) (conj (subtotal-by-column-row pnl-datas title)))))
(defn location-detail-table [pnl-datas client-data title prefix] (defn location-detail-table [pnl-datas client-datas title prefix]
(let [table (-> [] (let [table (-> []
(into (detail-rows pnl-datas (into (detail-rows pnl-datas
:sales :sales
@@ -399,11 +437,14 @@
(filter-categories [:sales :cogs :payroll :controllable :fixed-overhead :ownership-controllable]) (filter-categories [:sales :cogs :payroll :controllable :fixed-overhead :ownership-controllable])
(negate #{:cogs :payroll :controllable :fixed-overhead :ownership-controllable})) (negate #{:cogs :payroll :controllable :fixed-overhead :ownership-controllable}))
pnl-datas) pnl-datas)
(str prefix " Net Income"))) (str prefix " Net Income"))))
(conj (subtotal-by-column-row (-> client-data table (if (seq client-datas)
(conj table (subtotal-by-column-row (map #(-> %
(filter-categories [:sales :cogs :payroll :controllable :fixed-overhead :ownership-controllable]) (filter-categories [:sales :cogs :payroll :controllable :fixed-overhead :ownership-controllable])
(negate #{:cogs :payroll :controllable :fixed-overhead :ownership-controllable})) (negate #{:cogs :payroll :controllable :fixed-overhead :ownership-controllable}))
"All Location Net Income"))) client-datas)
"All Location Net Income"))
table)
percent-of-sales (calc-percent-of-sales table pnl-datas) percent-of-sales (calc-percent-of-sales table pnl-datas)
deltas (into [] (calc-deltas table))] deltas (into [] (calc-deltas table))]
{:header (headers pnl-datas title) {:header (headers pnl-datas title)
@@ -427,45 +468,52 @@
{:warning (warning-message pnl-data) {:warning (warning-message pnl-data)
:summaries :summaries
(if (-> pnl-data :args :column-per-location) (if (-> pnl-data :args :column-per-location)
(for [client-id (set (map first (client-locations pnl-data)))] [(location-summary-table (mapcat identity (for [[period i] (map vector (-> pnl-data :args :periods ) (range))]
(location-summary-table (for [period (-> pnl-data :args :periods ) (concat
location (locations pnl-data)] (for [location (set (map second (client-locations pnl-data)))]
(-> pnl-data (-> pnl-data
(filter-client client-id)
(filter-location location) (filter-location location)
(filter-period period))) (filter-period period)
(str (-> pnl-data :clients-by-id (get client-id)) " Summary"))) (zebra i)))
[(zebra (filter-period pnl-data period) i)])))
"All location Summary")]
(for [[client-id location] (client-locations pnl-data)] (for [[client-id location] (client-locations pnl-data)]
(location-summary-table (for [period (-> pnl-data :args :periods )] (location-summary-table (for [[period i] (map vector (-> pnl-data :args :periods ) (range))]
(-> pnl-data (-> pnl-data
(filter-client client-id) (filter-client client-id)
(filter-location location) (filter-location location)
(filter-period period))) (filter-period period)
(zebra i)))
(str (-> pnl-data :clients-by-id (get client-id)) " (" location ") Summary")))) (str (-> pnl-data :clients-by-id (get client-id)) " (" location ") Summary"))))
:details :details
(doall (if (-> pnl-data :args :column-per-location) (doall (if (-> pnl-data :args :column-per-location)
(for [client-id (set (map first (client-locations pnl-data)))] [(location-detail-table (mapcat identity (for [[period i] (map vector (-> pnl-data :args :periods ) (range))]
(location-detail-table (for [period (-> pnl-data :args :periods ) (concat
location (locations pnl-data)] (for [location (set (map second (client-locations pnl-data)))]
(-> pnl-data (-> pnl-data
(filter-client client-id)
(filter-location location) (filter-location location)
(filter-period period))) (filter-period period)
(-> pnl-data (zebra i)))
(filter-client client-id)) [(-> pnl-data
(str (-> pnl-data :clients-by-id (get client-id)) " Detail") (filter-period period)
"")) (zebra i))])))
nil
"All location Detail"
"")]
(for [[client-id location] (client-locations pnl-data)] (for [[client-id location] (client-locations pnl-data)]
(location-detail-table (for [period (-> pnl-data :args :periods )] (location-detail-table (for [[period i] (map vector (-> pnl-data :args :periods ) (range))]
(-> pnl-data (-> pnl-data
(filter-client client-id) (filter-client client-id)
(filter-location location) (filter-location location)
(filter-period period))) (filter-period period)
(zebra i)))
(for [[period i] (map vector (-> pnl-data :args :periods ) (range))]
(-> pnl-data (-> pnl-data
(filter-client client-id)) (filter-client client-id)
(filter-period period)
(zebra i)))
(str (-> pnl-data :clients-by-id (get client-id)) " (" location ") Detail") (str (-> pnl-data :clients-by-id (get client-id)) " (" location ") Detail")
location)))) location))))})
})
(defn balance-sheet-headers [pnl-data] (defn balance-sheet-headers [pnl-data]
@@ -483,8 +531,7 @@
(:value b))})])))) (:value b))})]))))
(defn summarize-balance-sheet [pnl-data] (defn summarize-balance-sheet [pnl-data]
(let [ (let [pnl-datas (map (fn [p]
pnl-datas (map (fn [p]
(filter-period pnl-data p)) (filter-period pnl-data p))
(:periods (:args pnl-data))) (:periods (:args pnl-data)))
table (-> [] table (-> []
@@ -502,7 +549,6 @@
(filter-categories [:sales :cogs :payroll :controllable :fixed-overhead :ownership-controllable]) (filter-categories [:sales :cogs :payroll :controllable :fixed-overhead :ownership-controllable])
(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 (:include-comparison (:args pnl-data)) table (if (:include-comparison (:args pnl-data))
(append-deltas table) (append-deltas table)

View File

@@ -38,6 +38,10 @@
(:color c) (assoc-in [:style :color] (str "rgb(" (:color c) (assoc-in [:style :color] (str "rgb("
(str/join "," (str/join ","
(:color c)) (:color c))
")"))
(:bg-color c) (assoc-in [:style :background-color] (str "rgb("
(str/join ","
(:bg-color c))
")"))) ")")))
cell-contents])) cell-contents]))
@@ -68,7 +72,14 @@
(for [[i row] (map vector (range) (:rows table))] (for [[i row] (map vector (range) (:rows table))]
^{:key i} ^{:key i}
[:tr [:tr
(for [[i c] (map vector (range) (take cell-count (concat row (repeat nil))))] (for [[i c] (map vector (range) (take cell-count
(reduce
(fn [[acc cnt] cur]
(if (>= (+ cnt (:colspan cur 1)) cell-count)
(reduced (conj acc cur))
[(conj acc cur) (+ cnt (:colspan cur 1))]))
[[] 0]
(concat row (repeat nil)))))]
^{:key i} ^{:key i}
[cell {:click-event click-event} c])])) [cell {:click-event click-event} c])]))
(conj ^{:key "last"} (conj ^{:key "last"}