zebra striping + single table for column-per-location
This commit is contained in:
@@ -41,7 +41,8 @@
|
||||
(= :dollar (:format cell)) (assoc :align :right)
|
||||
(= :percent (:format cell)) (assoc :align :right)
|
||||
(: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
|
||||
]))
|
||||
@@ -195,7 +196,7 @@
|
||||
report (l-reports/summarize-pnl pnl-data)
|
||||
output-stream (ByteArrayOutputStream.)]
|
||||
(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
|
||||
(and (>= (count (-> pnl-data :args :periods)) 8 )
|
||||
(-> pnl-data :args :include-deltas))
|
||||
|
||||
@@ -177,6 +177,11 @@
|
||||
(update :filters (fn [f]
|
||||
(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]
|
||||
@@ -208,6 +213,7 @@
|
||||
: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 p))}
|
||||
(:cell-args p)
|
||||
cell-args))
|
||||
pnl-datas)))
|
||||
|
||||
@@ -221,10 +227,18 @@
|
||||
(map
|
||||
(fn [v s]
|
||||
{:border (:border v)
|
||||
:format :percent
|
||||
:bg-color (:bg-color v)
|
||||
:format (if (string? (:value v))
|
||||
:text
|
||||
:percent)
|
||||
:color [128 128 128]
|
||||
:value (if (dollars-0? s)
|
||||
:value (cond
|
||||
(string? (:value v))
|
||||
""
|
||||
|
||||
(dollars-0? s)
|
||||
0.0
|
||||
:else
|
||||
(/ (:value v) s))})
|
||||
values sales))))))
|
||||
|
||||
@@ -234,10 +248,16 @@
|
||||
(->> values
|
||||
(partition 2 1)
|
||||
(map (fn [[a b]]
|
||||
{:border (:border b)
|
||||
:format :dollar
|
||||
:value (- (:value b)
|
||||
(:value a))})))))))
|
||||
(if (or (string? (:value b))
|
||||
(string? (:value a)))
|
||||
{:value ""
|
||||
:format :text
|
||||
:bg-color (:bg-color b)}
|
||||
{:border (:border b)
|
||||
:format :dollar
|
||||
:value (- (:value b)
|
||||
(:value a))
|
||||
:bg-color (:bg-color b)}))))))))
|
||||
|
||||
(defn combine-tables
|
||||
([[pnl-data] table percent-of-sales deltas]
|
||||
@@ -259,46 +279,53 @@
|
||||
deltas)))
|
||||
|
||||
(defn headers [[pnl-data :as pnl-datas] header-title]
|
||||
(let [
|
||||
big-header (into [{:value header-title
|
||||
(let [big-header (into [{:value header-title
|
||||
:bold true}]
|
||||
(map (fn [p]
|
||||
{:value
|
||||
(str (date->str (:start p))
|
||||
" - "
|
||||
(date->str (:end p)))
|
||||
:colspan (cond
|
||||
(-> pnl-data :args :include-deltas)
|
||||
3
|
||||
(map-indexed (fn [i p]
|
||||
(cond-> {:value
|
||||
(str (date->str (:start p))
|
||||
" - "
|
||||
(date->str (:end p)))
|
||||
:colspan (cond
|
||||
(-> pnl-data :args :include-deltas)
|
||||
3
|
||||
|
||||
(-> pnl-data :args :column-per-location)
|
||||
(* 2 (/ (count pnl-datas)
|
||||
(count (-> pnl-data :args :periods))))
|
||||
(-> pnl-data :args :column-per-location)
|
||||
(* 2 (/ (count pnl-datas)
|
||||
(count (-> pnl-data :args :periods))))
|
||||
|
||||
:else
|
||||
2)
|
||||
:align :center
|
||||
:bold true})
|
||||
:else
|
||||
2)
|
||||
:align :center
|
||||
:bold true}
|
||||
(odd? i) (assoc :bg-color [240 240 240])))
|
||||
(:periods (:args pnl-data))))
|
||||
sub-header (into [{:value ""}]
|
||||
(if (-> pnl-data :args :column-per-location)
|
||||
(mapcat
|
||||
(fn [p]
|
||||
(cond-> [{:value (-> p :filters :location)
|
||||
:align :right}
|
||||
{:value "%"
|
||||
:align :right}]
|
||||
(-> pnl-data :args :include-deltas) (conj {:value "+/-"
|
||||
:align :right})))
|
||||
(cond-> [(merge {:value (or (
|
||||
-> p :filters :location) "Total")
|
||||
:align :right}
|
||||
(:cell-args p))
|
||||
(merge {:value "%"
|
||||
:align :right}
|
||||
(:cell-args p))]
|
||||
(-> pnl-data :args :include-deltas) (conj (merge {:value "+/-"
|
||||
:align :right}
|
||||
(:cell-args p)))))
|
||||
pnl-datas)
|
||||
(mapcat
|
||||
(fn [_]
|
||||
(cond-> [{:value "Amt"
|
||||
:align :right}
|
||||
{:value "%"
|
||||
:align :right}]
|
||||
(-> pnl-data :args :include-deltas) (conj {:value "+/-"
|
||||
:align :right})))
|
||||
(fn [p]
|
||||
(cond-> [(merge {:value "Amt"
|
||||
:align :right}
|
||||
(:cell-args p))
|
||||
(merge {:value "%"
|
||||
:align :right}
|
||||
(:cell-args p))]
|
||||
(-> pnl-data :args :include-deltas) (conj (merge {:value "+/-"
|
||||
:align :right}
|
||||
(:cell-args p)))))
|
||||
pnl-datas)))]
|
||||
[big-header
|
||||
sub-header]))
|
||||
@@ -343,25 +370,36 @@
|
||||
pnl-datas)
|
||||
account-codes (used-accounts pnl-datas)]
|
||||
: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 [{:value name}]
|
||||
(map
|
||||
(fn [p]
|
||||
(let [pnl-data (-> p (filter-numeric-code numeric-code numeric-code))]
|
||||
{:format :dollar
|
||||
:filters (:filters pnl-data)
|
||||
:value (aggregate-accounts pnl-data)}))
|
||||
(merge
|
||||
{:format :dollar
|
||||
:filters (:filters pnl-data)
|
||||
:value (aggregate-accounts pnl-data)}
|
||||
(:cell-args p))))
|
||||
|
||||
pnl-datas))))
|
||||
(conj (subtotal-by-column-row pnl-datas "" {:border [:top]})))]
|
||||
row)]
|
||||
(-> [[{:value title
|
||||
:bold true}]]
|
||||
(-> [(into [{:value title
|
||||
:bold true}]
|
||||
(map
|
||||
(fn [p]
|
||||
(assoc (:cell-args p) :value "" :format ""))
|
||||
pnl-datas))]
|
||||
(into individual-accounts)
|
||||
(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 (-> []
|
||||
(into (detail-rows pnl-datas
|
||||
:sales
|
||||
@@ -399,11 +437,14 @@
|
||||
(filter-categories [:sales :cogs :payroll :controllable :fixed-overhead :ownership-controllable])
|
||||
(negate #{:cogs :payroll :controllable :fixed-overhead :ownership-controllable}))
|
||||
pnl-datas)
|
||||
(str prefix " Net Income")))
|
||||
(conj (subtotal-by-column-row (-> client-data
|
||||
(filter-categories [:sales :cogs :payroll :controllable :fixed-overhead :ownership-controllable])
|
||||
(negate #{:cogs :payroll :controllable :fixed-overhead :ownership-controllable}))
|
||||
"All Location Net Income")))
|
||||
(str prefix " Net Income"))))
|
||||
table (if (seq client-datas)
|
||||
(conj table (subtotal-by-column-row (map #(-> %
|
||||
(filter-categories [:sales :cogs :payroll :controllable :fixed-overhead :ownership-controllable])
|
||||
(negate #{:cogs :payroll :controllable :fixed-overhead :ownership-controllable}))
|
||||
client-datas)
|
||||
"All Location Net Income"))
|
||||
table)
|
||||
percent-of-sales (calc-percent-of-sales table pnl-datas)
|
||||
deltas (into [] (calc-deltas table))]
|
||||
{:header (headers pnl-datas title)
|
||||
@@ -427,45 +468,52 @@
|
||||
{:warning (warning-message pnl-data)
|
||||
:summaries
|
||||
(if (-> pnl-data :args :column-per-location)
|
||||
(for [client-id (set (map first (client-locations pnl-data)))]
|
||||
(location-summary-table (for [period (-> pnl-data :args :periods )
|
||||
location (locations pnl-data)]
|
||||
(-> pnl-data
|
||||
(filter-client client-id)
|
||||
(filter-location location)
|
||||
(filter-period period)))
|
||||
(str (-> pnl-data :clients-by-id (get client-id)) " Summary")))
|
||||
[(location-summary-table (mapcat identity (for [[period i] (map vector (-> pnl-data :args :periods ) (range))]
|
||||
(concat
|
||||
(for [location (set (map second (client-locations pnl-data)))]
|
||||
(-> pnl-data
|
||||
(filter-location location)
|
||||
(filter-period period)
|
||||
(zebra i)))
|
||||
[(zebra (filter-period pnl-data period) i)])))
|
||||
"All location Summary")]
|
||||
(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
|
||||
(filter-client client-id)
|
||||
(filter-location location)
|
||||
(filter-period period)))
|
||||
(filter-period period)
|
||||
(zebra i)))
|
||||
(str (-> pnl-data :clients-by-id (get client-id)) " (" location ") Summary"))))
|
||||
:details
|
||||
(doall (if (-> pnl-data :args :column-per-location)
|
||||
(for [client-id (set (map first (client-locations pnl-data)))]
|
||||
(location-detail-table (for [period (-> pnl-data :args :periods )
|
||||
location (locations pnl-data)]
|
||||
(-> pnl-data
|
||||
(filter-client client-id)
|
||||
(filter-location location)
|
||||
(filter-period period)))
|
||||
(-> pnl-data
|
||||
(filter-client client-id))
|
||||
(str (-> pnl-data :clients-by-id (get client-id)) " Detail")
|
||||
""))
|
||||
[(location-detail-table (mapcat identity (for [[period i] (map vector (-> pnl-data :args :periods ) (range))]
|
||||
(concat
|
||||
(for [location (set (map second (client-locations pnl-data)))]
|
||||
(-> pnl-data
|
||||
(filter-location location)
|
||||
(filter-period period)
|
||||
(zebra i)))
|
||||
[(-> pnl-data
|
||||
(filter-period period)
|
||||
(zebra i))])))
|
||||
nil
|
||||
"All location Detail"
|
||||
"")]
|
||||
(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
|
||||
(filter-client client-id)
|
||||
(filter-location location)
|
||||
(filter-period period)))
|
||||
(-> pnl-data
|
||||
(filter-client client-id))
|
||||
(filter-period period)
|
||||
(zebra i)))
|
||||
(for [[period i] (map vector (-> pnl-data :args :periods ) (range))]
|
||||
(-> pnl-data
|
||||
(filter-client client-id)
|
||||
(filter-period period)
|
||||
(zebra i)))
|
||||
(str (-> pnl-data :clients-by-id (get client-id)) " (" location ") Detail")
|
||||
location))))
|
||||
})
|
||||
location))))})
|
||||
|
||||
|
||||
(defn balance-sheet-headers [pnl-data]
|
||||
@@ -483,8 +531,7 @@
|
||||
(:value b))})]))))
|
||||
|
||||
(defn summarize-balance-sheet [pnl-data]
|
||||
(let [
|
||||
pnl-datas (map (fn [p]
|
||||
(let [pnl-datas (map (fn [p]
|
||||
(filter-period pnl-data p))
|
||||
(:periods (:args pnl-data)))
|
||||
table (-> []
|
||||
@@ -502,7 +549,6 @@
|
||||
(filter-categories [:sales :cogs :payroll :controllable :fixed-overhead :ownership-controllable])
|
||||
(negate #{:cogs :payroll :controllable :fixed-overhead :ownership-controllable}))
|
||||
pnl-datas)
|
||||
|
||||
"Retained Earnings")))
|
||||
table (if (:include-comparison (:args pnl-data))
|
||||
(append-deltas table)
|
||||
|
||||
@@ -38,6 +38,10 @@
|
||||
(:color c) (assoc-in [:style :color] (str "rgb("
|
||||
(str/join ","
|
||||
(:color c))
|
||||
")"))
|
||||
(:bg-color c) (assoc-in [:style :background-color] (str "rgb("
|
||||
(str/join ","
|
||||
(:bg-color c))
|
||||
")")))
|
||||
|
||||
cell-contents]))
|
||||
@@ -68,7 +72,14 @@
|
||||
(for [[i row] (map vector (range) (:rows table))]
|
||||
^{:key i}
|
||||
[: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}
|
||||
[cell {:click-event click-event} c])]))
|
||||
(conj ^{:key "last"}
|
||||
|
||||
Reference in New Issue
Block a user