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