Splits out by legal entity

This commit is contained in:
2022-03-17 12:49:09 -07:00
parent 77455f6ef6
commit 6e41ada061

View File

@@ -57,18 +57,24 @@
:periods
(mapcat :accounts)
(filter (comp in-range? :numeric-code))
(group-by :location)
(group-by (juxt :client-id :location))
(filter (fn [[k as]]
(not (dollars-0? (reduce + 0 (map :amount as))))))
(mapcat second)
(map :location)
(map not-empty)
(map (fn [a]
(if (or (not (:client-id a))
(empty? (:location a)))
nil
[(:client-id a)
(:location a)])))
(filter identity)
(set)
(sort-by (fn [x] (if (= x "HQ" )
"ZZZZZZ"
x))))))
(sort-by (fn [x]
[(:client-id x)
(if (= (:location x) "HQ" )
"ZZZZZZ"
(:location x))])))))
(re-frame/reg-sub
::multi-client?
@@ -119,13 +125,15 @@
(map #(update % :amount js/parseFloat) a))))
(defn filter-accounts [accounts period [from to] only-location]
(defn filter-accounts [accounts period [from to] only-client only-location]
(->> (get accounts period)
vals
(filter (fn [{:keys [location numeric-code]}]
(filter (fn [{:keys [location client-id numeric-code]}]
(and (or (nil? only-location)
(= only-location location))
(or (nil? only-client)
(= only-client client-id))
(<= from numeric-code to))))
(sort-by :numeric-code)))
@@ -140,7 +148,7 @@
(comp
(map parse-amounts)
(map #(->> (:accounts %)
(group-by (juxt :numeric-code :location))
(group-by (juxt :numeric-code :client-id :location))
(map (fn [[k v]]
[k
(reduce (fn [a n]
@@ -420,17 +428,18 @@
["97000 Taxes" 97000 97999]
["98000 Other Expenses" 98000 98999]]})
(defn percent-of-sales [amount accounts which location]
(let [sales (aggregate-accounts (filter-accounts accounts which (get ranges :sales) location))]
(defn percent-of-sales [amount accounts which client-id location]
(let [sales (aggregate-accounts (filter-accounts accounts which (get ranges :sales) client-id location))]
(if (not (dollars-0? sales))
(/ amount
sales)
0.0)))
(defn used-accounts [accounts [from to] location]
(defn used-accounts [accounts [from to] client-id location]
(->> accounts
(mapcat vals)
(filter #(<= from (:numeric-code %) to))
(filter #(= client-id (:client-id %)))
(filter #(= location (:location %)))
(map #(select-keys % [:numeric-code :name]))
(set)
@@ -448,17 +457,15 @@
{:key (str "between-" i)}))]))
;; TODO Allow choosing more than one client
;; TODO allow "sandwhiching" clients data
;; TODO do we need squashing locations?
(defn grouping [{:keys [header type groupings location periods all-accounts]}]
(defn grouping [{:keys [header type groupings client-id location periods all-accounts]}]
(let [include-deltas @(re-frame/subscribe [::include-deltas])
multi-client? @(re-frame/subscribe [::multi-client?])]
[:<>
(doall
(for [[grouping-name from to] groupings
:let [account-codes (used-accounts all-accounts [from to] location)]
:let [account-codes (used-accounts all-accounts [from to] client-id location)]
:when (seq account-codes)]
^{:key grouping-name}
[:<>
@@ -479,17 +486,17 @@
[:td name]
(map-periods
(fn [i]
(let [amount (get-in all-accounts [i [numeric-code location] :amount] 0.0)]
(let [amount (get-in all-accounts [i [numeric-code client-id location] :amount] 0.0)]
[:<>
[:td.has-text-right (if multi-client?
[:span (->$ amount)]
[:a {:on-click (dispatch-event [::investigate-clicked location numeric-code numeric-code i :current])
:disabled (boolean multi-client?)}
(->$ amount)])]
[:td.has-text-right (->% (percent-of-sales amount all-accounts i location))]]))
[:td.has-text-right (->% (percent-of-sales amount all-accounts i client-id location))]]))
(fn [i]
[:td.has-text-right (->$ (- (get-in all-accounts [i [numeric-code location] :amount] 0.0)
(get-in all-accounts [(dec i) [numeric-code location] :amount] 0.0)))])
[:td.has-text-right (->$ (- (get-in all-accounts [i [numeric-code client-id location] :amount] 0.0)
(get-in all-accounts [(dec i) [numeric-code client-id location] :amount] 0.0)))])
periods
include-deltas)])]
@@ -497,22 +504,22 @@
[:th]
(map-periods
(fn [i]
(let [amount (aggregate-accounts (filter-accounts all-accounts i [from to] location))]
(let [amount (aggregate-accounts (filter-accounts all-accounts i [from to] client-id location))]
[:<>
[:th.has-text-right.total (if multi-client?
[:span (->$ amount)]
[:a {:on-click (dispatch-event [::investigate-clicked location from to i])}
(->$ amount)])]
[:th.has-text-right.total (->% (percent-of-sales amount all-accounts i location))]]))
[:th.has-text-right.total (->% (percent-of-sales amount all-accounts i client-id location))]]))
(fn [i]
[:th.has-text-right.total (->$ (- (aggregate-accounts (filter-accounts all-accounts i [from to] location))
(aggregate-accounts (filter-accounts all-accounts (dec i) [from to] location))))])
[:th.has-text-right.total (->$ (- (aggregate-accounts (filter-accounts all-accounts i [from to] client-id location))
(aggregate-accounts (filter-accounts all-accounts (dec i) [from to] client-id location))))])
periods
include-deltas)]]))]))
(defn overall-grouping [type title location]
(defn overall-grouping [type title client-id location]
(let [all-accounts @(re-frame/subscribe [::all-accounts])
periods @(re-frame/subscribe [::periods])
[min-numeric-code max-numeric-code] (ranges type)
@@ -522,6 +529,7 @@
[:tr [:th.is-size-5 title]]
[grouping {:location location
:client-id client-id
:groupings (type groupings)
:periods periods
:all-accounts all-accounts}]
@@ -529,43 +537,44 @@
[:tr [:th.is-size-5 title]
(map-periods
(fn [i]
(let [amount (aggregate-accounts (filter-accounts all-accounts i [min-numeric-code max-numeric-code] location))]
(let [amount (aggregate-accounts (filter-accounts all-accounts i [min-numeric-code max-numeric-code] client-id location))]
[:<>
[:th.has-text-right (if multi-client?
[:span (->$ amount)]
[:a
{:on-click (dispatch-event [::investigate-clicked location min-numeric-code max-numeric-code i])}
(->$ amount)])]
[:th.has-text-right (->% (percent-of-sales amount all-accounts i location))]
[:th.has-text-right (->% (percent-of-sales amount all-accounts i client-id location))]
]))
(fn [i]
[:th.has-text-right (->$ (- (aggregate-accounts (filter-accounts all-accounts i [min-numeric-code max-numeric-code] location))
(aggregate-accounts (filter-accounts all-accounts (dec i) [min-numeric-code max-numeric-code] location))))])
[:th.has-text-right (->$ (- (aggregate-accounts (filter-accounts all-accounts i [min-numeric-code max-numeric-code] client-id location))
(aggregate-accounts (filter-accounts all-accounts (dec i) [min-numeric-code max-numeric-code] client-id location))))])
periods
include-deltas)]]))
(defn subtotal [types negs title location]
(defn subtotal [types negs title client-id location]
(let [all-accounts @(re-frame/subscribe [::all-accounts])
periods @(re-frame/subscribe [::periods])
include-deltas @(re-frame/subscribe [::include-deltas])]
(println title client-id)
[:tr [:th.is-size-5 title]
(map-periods
(fn [i]
(let [amount (aggregate-accounts (mapcat (fn [t]
(cond->> (filter-accounts all-accounts i (ranges t) location)
(cond->> (filter-accounts all-accounts i (ranges t) client-id location)
(negs t) (map #(update % :amount -))))
types))]
[:<>
[:td.has-text-right [:span (->$ amount)]]
[:td.has-text-right (->% (percent-of-sales amount all-accounts i location))]]))
[:td.has-text-right (->% (percent-of-sales amount all-accounts i client-id location))]]))
(fn [i]
[:td.has-text-right (->$ (- (aggregate-accounts (mapcat (fn [t]
(cond->> (filter-accounts all-accounts i (ranges t) location)
(cond->> (filter-accounts all-accounts i (ranges t) client-id location)
(negs t) (map #(update % :amount -))))
types))
(aggregate-accounts (mapcat (fn [t]
(cond->> (filter-accounts all-accounts (dec i) (ranges t) location)
(cond->> (filter-accounts all-accounts (dec i) (ranges t) client-id location)
(negs t) (map #(update % :amount -))))
types))))])
periods
@@ -600,22 +609,22 @@
periods
include-deltas)]])
(defn location-rows [location]
(defn location-rows [client-id location]
[:<>
[overall-grouping :sales (str location " Sales") location]
[overall-grouping :cogs (str location " COGS") location]
[overall-grouping :payroll (str location " Payroll") location]
[subtotal [:payroll :cogs] #{} (str location " Prime Costs") location]
[subtotal [:sales :payroll :cogs] #{:payroll :cogs} (str location " Gross Profits") location]
[overall-grouping :controllable (str location " Controllable Expenses") location]
[overall-grouping :fixed-overhead (str location " Fixed Overhead") location]
[overall-grouping :ownership-controllable (str location " Ownership Controllable") location]
[subtotal [:controllable :fixed-overhead :ownership-controllable] #{} (str location " Overhead") location]
[subtotal [:sales :cogs :payroll :controllable :fixed-overhead :ownership-controllable] #{:cogs :payroll :controllable :fixed-overhead :ownership-controllable} (str location " Net Income") location]
[subtotal [:sales :cogs :payroll :controllable :fixed-overhead :ownership-controllable] #{:cogs :payroll :controllable :fixed-overhead :ownership-controllable} "Net Income" nil]])
[overall-grouping :sales (str location " Sales") client-id location]
[overall-grouping :cogs (str location " COGS") client-id location]
[overall-grouping :payroll (str location " Payroll") client-id location]
[subtotal [:payroll :cogs] #{} (str location " Prime Costs") client-id location]
[subtotal [:sales :payroll :cogs] #{:payroll :cogs} (str location " Gross Profits") client-id location]
[overall-grouping :controllable (str location " Controllable Expenses") client-id location]
[overall-grouping :fixed-overhead (str location " Fixed Overhead") client-id location]
[overall-grouping :ownership-controllable (str location " Ownership Controllable") client-id location]
[subtotal [:controllable :fixed-overhead :ownership-controllable] #{} (str location " Overhead") client-id location]
[subtotal [:sales :cogs :payroll :controllable :fixed-overhead :ownership-controllable] #{:cogs :payroll :controllable :fixed-overhead :ownership-controllable} (str location " Net Income") client-id location]
[subtotal [:sales :cogs :payroll :controllable :fixed-overhead :ownership-controllable] #{:cogs :payroll :controllable :fixed-overhead :ownership-controllable} "Net Income" client-id nil]])
(defn location-summary [location include-deltas]
(defn location-summary [client-id location include-deltas]
(let [periods @(re-frame/subscribe [::periods])]
[:div
[:h2.title.is-4.mb-4 location " Summary"]
@@ -625,12 +634,12 @@
:periods periods}]
[subtotal [:sales ] #{} "Sales" location]
[subtotal [:cogs ] #{} "Cogs" location]
[subtotal [:payroll ]#{} "Payroll" location]
[subtotal [:sales :payroll :cogs] #{:payroll :cogs} "Gross Profits" location]
[subtotal [:controllable :fixed-overhead :ownership-controllable] #{} "Overhead" location]
[subtotal [:sales :cogs :payroll :controllable :fixed-overhead :ownership-controllable] #{:cogs :payroll :controllable :fixed-overhead :ownership-controllable} "Net Income" location]]]]))
[subtotal [:sales ] #{} "Sales" client-id location]
[subtotal [:cogs ] #{} "Cogs" client-id location]
[subtotal [:payroll ]#{} "Payroll" client-id location]
[subtotal [:sales :payroll :cogs] #{:payroll :cogs} "Gross Profits" client-id location]
[subtotal [:controllable :fixed-overhead :ownership-controllable] #{} "Overhead" client-id location]
[subtotal [:sales :cogs :payroll :controllable :fixed-overhead :ownership-controllable] #{:cogs :payroll :controllable :fixed-overhead :ownership-controllable} "Net Income" client-id location]]]]))
(re-frame/reg-sub
::can-submit
@@ -876,6 +885,7 @@
(defn profit-and-loss-content []
(let [status @(re-frame/subscribe [::status/single ::page])
unresolved-accounts @(re-frame/subscribe [::uncategorized-accounts])
clients-by-id @(re-frame/subscribe [::subs/clients-by-id])
{:keys [data report active? error id]} @(re-frame/subscribe [::forms/form ::form])
{:keys [form-inline field raw-field error-notification submit-button ]} pnl-form
periods (:periods data)]
@@ -899,9 +909,9 @@
(:location %)))
unresolved-accounts))])
[:<>
(for [location @(re-frame/subscribe [::locations])]
^{:key (str location "-summary")}
[location-summary location (:include-deltas data)]
(for [[client-id location] @(re-frame/subscribe [::locations])]
^{:key (str client-id "-" location "-summary")}
[location-summary client-id location (:include-deltas data)]
)]
[:h2.title.is-4 {:style {:margin-bottom "1rem"}} "Detail"]
[:table.table.compact.balance-sheet
@@ -910,9 +920,11 @@
:periods periods}]
[:<>
(for [location @(re-frame/subscribe [::locations])]
^{:key location}
[location-rows location])]]]])])))
(for [[client-id location] @(re-frame/subscribe [::locations])]
^{:key (str client-id "-" location)}
[:<>
[:tr [:th.is-size-3 (:name (clients-by-id client-id))]]
[location-rows client-id location]])]]]])])))
(re-frame/reg-event-fx
::unmounted-pnl