Splits out multiple tables when too wide

This commit is contained in:
2022-03-22 08:06:10 -07:00
parent be6be38c34
commit 4c0fcf3718

View File

@@ -188,73 +188,65 @@
(defn combine-tables [pnl-data table percent-of-sales deltas] (defn combine-tables [pnl-data table percent-of-sales deltas]
(map (fn [[title & row] percent-of-sales deltas ] (map (fn [[title & row] percent-of-sales deltas ]
(let [deltas (cons nil deltas)] (let [deltas (cons "-" deltas)]
(into [title] (into [title]
(filter identity (mapcat
(mapcat (fn [v p d]
(fn [v p d] [v p d])
[v p d]) row
row percent-of-sales
percent-of-sales deltas))
deltas)))
)) ))
table table
percent-of-sales percent-of-sales
deltas)) deltas))
(defn headers [pnl-data header-title] (defn headers [pnl-data header-title]
(let [deltas (cons nil (repeat "Change")) (let [big-header (into [{:value header-title
big-header (into [{:value header-title
:bold true}] :bold true}]
(map-indexed (fn [i p] (map-indexed (fn [i p]
{:value {:value
(str (date->str (:start p)) (str (date->str (:start p))
" - " " - "
(date->str (:end p))) (date->str (:end p)))
:colspan (if (= 0 i) :colspan 3
2
3)
:align :center :align :center
:bold true}) :bold true})
(:periods (:args pnl-data)))) (:periods (:args pnl-data))))
sub-header (into [{:value ""}] sub-header (into [{:value ""}]
(filter identity (mapcat
(mapcat (fn [_]
(fn [v p d] [{:value "Amount"
[{:value "Amount" :align :right
:align :right :bold true}
:bold true} {:value "% Sales"
{:value "% Sales" :align :right
:align :right :bold true}
:bold true} {:value "Change"
(when d :align :right
{:value d :bold true}])
:align :right (:periods (:args pnl-data))))]
:bold true})])
(:periods (:args pnl-data))
(:periods (:args pnl-data))
deltas)))]
[big-header [big-header
sub-header])) sub-header]))
(defn location-summary-table [pnl-data title] (defn location-summary-table [pnl-data title]
(let [table [(subtotal-row (filter-categories pnl-data [:sales]) "Sales") (let [table [(subtotal-row (filter-categories pnl-data [:sales]) "Sales")
(subtotal-row (filter-categories pnl-data [:cogs ]) "Cogs") (subtotal-row (filter-categories pnl-data [:cogs ]) "Cogs")
(subtotal-row (filter-categories pnl-data [:payroll ]) "Payroll") (subtotal-row (filter-categories pnl-data [:payroll ]) "Payroll")
(subtotal-row (-> pnl-data (subtotal-row (-> pnl-data
(filter-categories [:sales :payroll :cogs]) (filter-categories [:sales :payroll :cogs])
(negate #{:payroll :cogs})) (negate #{:payroll :cogs}))
"Gross Profits") "Gross Profits")
(subtotal-row (filter-categories pnl-data [:controllable :fixed-overhead :ownership-controllable]) (subtotal-row (filter-categories pnl-data [:controllable :fixed-overhead :ownership-controllable])
"Overhead") "Overhead")
(subtotal-row (-> pnl-data (subtotal-row (-> pnl-data
(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}))
"Net Income")] "Net Income")]
percent-of-sales (calc-percent-of-sales table pnl-data) percent-of-sales (calc-percent-of-sales table pnl-data)
deltas (calc-deltas table)] deltas (calc-deltas table)]
{:header (headers pnl-data title) {:header (headers pnl-data title)
@@ -317,9 +309,6 @@
(conj (subtotal-row (-> pnl-data (conj (subtotal-row (-> pnl-data
(filter-categories [:controllable :fixed-overhead :ownership-controllable])) (filter-categories [:controllable :fixed-overhead :ownership-controllable]))
(str (:prefix pnl-data) " Overhead"))) (str (:prefix pnl-data) " Overhead")))
(conj (subtotal-row (-> pnl-data
(filter-categories [:controllable :fixed-overhead :ownership-controllable]))
(str (:prefix pnl-data) " Overhead")))
(conj (subtotal-row (-> pnl-data (conj (subtotal-row (-> pnl-data
(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}))
@@ -357,7 +346,7 @@
(:colspan cell) (assoc :colspan (:colspan cell))) (:colspan cell) (assoc :colspan (:colspan cell)))
(cond (= :dollar (:format cell)) (cond (= :dollar (:format cell))
(.format (DecimalFormat. "$###,###.00") (:value cell)) (.format (DecimalFormat. "$###,##0.00") (:value cell))
(= :percent (:format cell)) (= :percent (:format cell))
(.format (DecimalFormat. "0%") (:value cell)) (.format (DecimalFormat. "0%") (:value cell))
@@ -365,14 +354,34 @@
:else :else
(str (:value cell)))]) (str (:value cell)))])
(defn cell-count [table]
(let [counts (map count (:rows table))]
(if (seq counts)
(apply max counts)
0)))
(defn table->pdf [table] (defn table->pdf [table]
(let [cell-count (apply max (map count (:rows table)))] (let [cell-count (cell-count table)]
(-> [:pdf-table {:header (mapv (-> [:pdf-table {:header (mapv
(fn [header] (fn [header]
(map cell->pdf header)) (map cell->pdf header))
(:header table)) (:header table))
:cell-border false} :cell-border false
(into [70] (take (dec cell-count) (repeat 20)))] :width-percent (cond (= 5 cell-count)
50
(= 6 cell-count)
60
(= 7 cell-count)
70
(= 8 cell-count)
80
:else
100)}
(into [20] (take (dec cell-count) (repeat 10)))]
(into (into
(for [row (:rows table)] (for [row (:rows table)]
@@ -381,6 +390,63 @@
(cell->pdf cell) (cell->pdf cell)
)))) ))))
(conj (take cell-count (repeat (cell->pdf {:value " "}))))))) (conj (take cell-count (repeat (cell->pdf {:value " "})))))))
(defn split-table [table n]
(let [cell-count (cell-count table)]
(if (<= cell-count n)
[table]
(let [new-table (-> table
(update :rows (fn [rows]
(map
(fn [[header & rest]]
(into [header]
(take (dec n) rest)))
rows)))
(update :header (fn [headers]
(map
(fn [[title & header]]
(first
(reduce
(fn [[so-far a] next]
(let [new-a (+ a (or (:colspan next)
1))]
(if (<= new-a n)
[(conj so-far next) new-a]
[so-far new-a])))
[[title] 1]
header)))
headers))))
remaining (-> table
(update :rows (fn [rows]
(map
(fn [[header & rest]]
(into [header]
(drop (dec n) rest)))
rows)))
(update :header (fn [headers]
(map
(fn [[title & header]]
(first
(reduce
(fn [[so-far a] next]
(let [new-a (+ a (or (:colspan next)
1))]
(if (> new-a n)
[(conj so-far next) new-a]
[so-far new-a])))
[[title] 1]
header)))
headers))))]
(into [new-table]
(split-table remaining n))))))
(defn break-apart-tables [tables]
(for [table tables
table (split-table table 10)]
table))
(defn make-pnl [args data] (defn make-pnl [args data]
(let [data (<-graphql data) (let [data (<-graphql data)
@@ -399,13 +465,14 @@
report (summarize-pnl (PNLData. (assoc args :deltas true) data (by :db/id clients))) report (summarize-pnl (PNLData. (assoc args :deltas true) data (by :db/id clients)))
output-stream (ByteArrayOutputStream.)] output-stream (ByteArrayOutputStream.)]
(pdf/pdf (pdf/pdf
[{:left-margin 15 :right-margin 15 :top-margin 15 :bottom-margin 15 :size :letter (into
:font {:size 8}} [{:left-margin 10 :right-margin 10 :top-margin 15 :bottom-margin 15 :size :letter
[:heading (str "Profit and Loss - " (str/join ", " (map :client/name clients)))] :orientation :landscape
(into [:paragraph] :font {:size 8}}
(map table->pdf (:summaries report))) [:heading (str "Profit and Loss - " (str/join ", " (map :client/name clients)))]]
(into [:paragraph] (for [table (break-apart-tables (concat (:summaries report)
(map table->pdf (:details report)))] (:details report)))]
(table->pdf table)))
output-stream) output-stream)
(.toByteArray output-stream))) (.toByteArray output-stream)))