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,52 +188,44 @@
(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 [v p d] (fn [_]
[{:value "Amount" [{:value "Amount"
:align :right :align :right
:bold true} :bold true}
{:value "% Sales" {:value "% Sales"
:align :right :align :right
:bold true} :bold true}
(when d {:value "Change"
{:value d
:align :right :align :right
:bold true})]) :bold true}])
(:periods (:args pnl-data)) (:periods (:args pnl-data))))]
(:periods (:args pnl-data))
deltas)))]
[big-header [big-header
sub-header])) sub-header]))
@@ -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
[{:left-margin 10 :right-margin 10 :top-margin 15 :bottom-margin 15 :size :letter
:orientation :landscape
:font {:size 8}} :font {:size 8}}
[:heading (str "Profit and Loss - " (str/join ", " (map :client/name clients)))] [:heading (str "Profit and Loss - " (str/join ", " (map :client/name clients)))]]
(into [:paragraph] (for [table (break-apart-tables (concat (:summaries report)
(map table->pdf (:summaries report))) (:details report)))]
(into [:paragraph] (table->pdf table)))
(map table->pdf (:details report)))]
output-stream) output-stream)
(.toByteArray output-stream))) (.toByteArray output-stream)))