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