Splits out by legal entity
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user