diff --git a/src/clj/auto_ap/graphql.clj b/src/clj/auto_ap/graphql.clj index a4df9fee..6ac2b22e 100644 --- a/src/clj/auto_ap/graphql.clj +++ b/src/clj/auto_ap/graphql.clj @@ -468,6 +468,7 @@ :resolve :get-transaction-rule-matches} :balance_sheet {:type :balance_sheet :args {:client_id {:type :id} + :include_comparison {:type 'Boolean} :date {:type :iso_date}} :resolve :get-balance-sheet} diff --git a/src/clj/auto_ap/graphql/ledger.clj b/src/clj/auto_ap/graphql/ledger.clj index 650e5154..0f08684a 100644 --- a/src/clj/auto_ap/graphql/ledger.clj +++ b/src/clj/auto_ap/graphql/ledger.clj @@ -180,10 +180,11 @@ comparable-date (coerce/to-date (time/minus (:date args) (time/years 1))) all-ledger-entries (full-ledger-for-client client-id) lookup-account (build-account-lookup client-id)] + (log/info "Running balance sheet with " args) - (->graphql - {:balance-sheet-accounts (roll-up-until lookup-account all-ledger-entries end-date) - :comparable-balance-sheet-accounts (roll-up-until lookup-account all-ledger-entries comparable-date)}))) + (cond-> {:balance-sheet-accounts (roll-up-until lookup-account all-ledger-entries end-date)} + (:include_comparison args) (assoc :comparable-balance-sheet-accounts (roll-up-until lookup-account all-ledger-entries comparable-date)) + true ->graphql))) (defn get-profit-and-loss [context args value] (let [client-id (:client_id args) diff --git a/src/cljs/auto_ap/views/pages/ledger/balance_sheet.cljs b/src/cljs/auto_ap/views/pages/ledger/balance_sheet.cljs index f89b8f44..9bd55896 100644 --- a/src/cljs/auto_ap/views/pages/ledger/balance_sheet.cljs +++ b/src/cljs/auto_ap/views/pages/ledger/balance_sheet.cljs @@ -1,12 +1,14 @@ (ns auto-ap.views.pages.ledger.balance-sheet (:require [auto-ap.subs :as subs] [auto-ap.views.components.layouts :refer [side-bar-layout]] + [auto-ap.views.components.switch-field :refer [switch-field]] [goog.string :as gstring] [auto-ap.utils :refer [by]] - [auto-ap.views.pages.ledger.side-bar :refer [ledger-side-bar]] + [auto-ap.views.pages.ledger.side-bar :refer [ledger-side-bar]] [auto-ap.views.utils :refer [date->str date-picker bind-field local-now standard ->$ str->date]] [cljs-time.core :as t] - [re-frame.core :as re-frame])) + [re-frame.core :as re-frame] + [auto-ap.status :as status])) (re-frame/reg-sub ::report @@ -46,10 +48,6 @@ (= type account-type))) (by :id)))) -(re-frame/reg-sub - ::loading - (fn [db] - (-> db ::loading))) (def groupings {:asset [["1100 Cash and Bank Accounts" 11000 11999] @@ -73,20 +71,24 @@ ::received (fn [db [_ data]] (-> db - (assoc ::report (:balance-sheet data)) - (assoc-in [::loading] false)))) + (assoc ::report (:balance-sheet data))))) (re-frame/reg-sub ::params (fn [db] (-> db ::params))) +(re-frame/reg-sub + ::include-comparison + :<- [::params] + (fn [params] + (:include-comparison params))) + (re-frame/reg-event-fx ::params-change (fn [cofx [_ params]] {:db (-> (:db cofx) - (assoc-in [::error] nil) - (assoc-in [::loading] true) + (dissoc ::report) (assoc-in [::params] params)) :graphql {:token (-> cofx :db :user) :query-obj {:venia/queries [[:balance-sheet @@ -94,6 +96,8 @@ :client-id (:id @(re-frame/subscribe [::subs/client]))) [[:balance-sheet-accounts [:name :amount :account-type :id :numeric-code]] [:comparable-balance-sheet-accounts [:name :amount :account-type :id :numeric-code]]]]]} + + :owns-state {:single ::page} :on-success [::received]}})) (re-frame/reg-event-fx @@ -103,79 +107,104 @@ :date date)]})) +(re-frame/reg-event-fx + ::include-comparison-changed + (fn [cofx [_ include-comparison]] + {:dispatch [::params-change (assoc @(re-frame/subscribe [::params]) + :include-comparison + include-comparison)]})) + (defn grouping [{:keys [header accounts comparable-accounts groupings]}] - - (for [[grouping-name from to] groupings - :let [matching-accounts (filter - #(<= from (:numeric-code %) to) - accounts)] - :when (seq matching-accounts) + (let [include-comparison @(re-frame/subscribe [::include-comparison])] + + (for [[grouping-name from to] groupings + :let [matching-accounts (filter + #(<= from (:numeric-code %) to) + accounts)] + :when (seq matching-accounts) + ] + (list + [:tr [:th "---" grouping-name "---"] + [:td] + (when include-comparison + [:td]) + (when include-comparison + [:td]) ] - (list - [:tr [:th "---" grouping-name "---"] - [:td] - [:td] - [:td] - ] - (for [account matching-accounts] - [:tr [:td (:name account)] - [:td.has-text-right (->$ (:amount account))] - [:td.has-text-right (->$ (:amount (get comparable-accounts (:id account)) 0))] - [:td.has-text-right (->$ (- (:amount account ) (:amount (get comparable-accounts (:id account)) 0)))]]) - [:tr [:th "---" grouping-name "---"] - [:th.has-text-right.total (->$ (reduce + 0 (map :amount - matching-accounts))) ] - [:th.has-text-right.total (->$ (reduce + 0 (map #(:amount (get comparable-accounts (:id %)) 0) - matching-accounts)))] - [:th.has-text-right.total (->$ (reduce + 0 - (map #(- (:amount % ) (:amount (get comparable-accounts (:id %)) 0)) - matching-accounts)))] - [:td] - ]))) + (for [account matching-accounts] + [:tr [:td (:name account)] + [:td.has-text-right (->$ (:amount account))] + (when include-comparison + [:td.has-text-right (->$ (:amount (get comparable-accounts (:id account)) 0))]) + (when include-comparison + [:td.has-text-right (->$ (- (:amount account ) (:amount (get comparable-accounts (:id account)) 0)))])]) + [:tr [:th "---" grouping-name "---"] + [:th.has-text-right.total (->$ (reduce + 0 (map :amount + matching-accounts))) ] + (when include-comparison + [:th.has-text-right.total (->$ (reduce + 0 (map #(:amount (get comparable-accounts (:id %)) 0) + matching-accounts)))]) + (when include-comparison + [:th.has-text-right.total (->$ (reduce + 0 + (map #(- (:amount % ) (:amount (get comparable-accounts (:id %)) 0)) + matching-accounts)))]) + [:td] + ])))) (defn overall-grouping [type title] - (list - [:tr [:th.has-text-centered title] - [:td] - [:td] - [:td]] - (grouping {:accounts @(re-frame/subscribe [::accounts type]) - :groupings (type groupings) - :comparable-accounts @(re-frame/subscribe [::comparable-accounts-by-id type]) - }) - [:tr [:th.has-text-centered title] - [:th.has-text-right (->$ (reduce + 0 (map :amount @(re-frame/subscribe [::accounts type]))))] - [:th.has-text-right (->$ (reduce + 0 (map :amount (vals @(re-frame/subscribe [::comparable-accounts-by-id type])))))] - [:th.has-text-right (->$ (- (reduce + 0 (map :amount @(re-frame/subscribe [::accounts type]))) - (reduce + 0 (map :amount (vals @(re-frame/subscribe [::comparable-accounts-by-id type]))))))]])) + (let [include-comparison @(re-frame/subscribe [::include-comparison])] + (list + [:tr [:th.has-text-centered title] + [:td] + (when include-comparison + [:td]) + (when include-comparison + [:td])] + (grouping {:accounts @(re-frame/subscribe [::accounts type]) + :groupings (type groupings) + :comparable-accounts @(re-frame/subscribe [::comparable-accounts-by-id type]) + }) + [:tr [:th.has-text-centered title] + [:th.has-text-right (->$ (reduce + 0 (map :amount @(re-frame/subscribe [::accounts type]))))] + (when include-comparison + [:th.has-text-right (->$ (reduce + 0 (map :amount (vals @(re-frame/subscribe [::comparable-accounts-by-id type])))))]) + (when include-comparison + [:th.has-text-right (->$ (- (reduce + 0 (map :amount @(re-frame/subscribe [::accounts type]))) + (reduce + 0 (map :amount (vals @(re-frame/subscribe [::comparable-accounts-by-id type]))))))])]))) (defn retained-earnings [] - (list - - #_(grouping {:accounts @(re-frame/subscribe [::accounts type]) - :comparable-accounts @(re-frame/subscribe [::comparable-accounts-by-id type]) - }) - [:tr [:th.has-text-centered "Retained Earnings"] - [:th.has-text-right (->$ (- (reduce + 0 (map :amount @(re-frame/subscribe [::accounts :revenue]))) - (reduce + 0 (map :amount @(re-frame/subscribe [::accounts :expense])))))] - [:th.has-text-right (->$ (- (reduce + 0 (map :amount (vals @(re-frame/subscribe [::comparable-accounts-by-id :revenue])))) - (reduce + 0 (map :amount (vals @(re-frame/subscribe [::comparable-accounts-by-id :expense]))))))] - [:th.has-text-right (->$ (- (- (reduce + 0 (map :amount @(re-frame/subscribe [::accounts :revenue]))) - (reduce + 0 (map :amount @(re-frame/subscribe [::accounts :expense])))) - (- (reduce + 0 (map :amount (vals @(re-frame/subscribe [::comparable-accounts-by-id :revenue])))) - (reduce + 0 (map :amount (vals @(re-frame/subscribe [::comparable-accounts-by-id :expense])))))))]])) + (let [include-comparison @(re-frame/subscribe [::include-comparison])] + (list + + #_(grouping {:accounts @(re-frame/subscribe [::accounts type]) + :comparable-accounts @(re-frame/subscribe [::comparable-accounts-by-id type]) + }) + [:tr [:th.has-text-centered "Retained Earnings"] + [:th.has-text-right (->$ (- (reduce + 0 (map :amount @(re-frame/subscribe [::accounts :revenue]))) + (reduce + 0 (map :amount @(re-frame/subscribe [::accounts :expense])))))] + (when include-comparison + [:th.has-text-right (->$ (- (reduce + 0 (map :amount (vals @(re-frame/subscribe [::comparable-accounts-by-id :revenue])))) + (reduce + 0 (map :amount (vals @(re-frame/subscribe [::comparable-accounts-by-id :expense]))))))]) + (when include-comparison + [:th.has-text-right (->$ (- (- (reduce + 0 (map :amount @(re-frame/subscribe [::accounts :revenue]))) + (reduce + 0 (map :amount @(re-frame/subscribe [::accounts :expense])))) + (- (reduce + 0 (map :amount (vals @(re-frame/subscribe [::comparable-accounts-by-id :revenue])))) + (reduce + 0 (map :amount (vals @(re-frame/subscribe [::comparable-accounts-by-id :expense])))))))])]))) (def balance-sheet-content (with-meta (fn [] (let [current-client @(re-frame/subscribe [::subs/client]) + status @(re-frame/subscribe [::status/single ::page]) user @(re-frame/subscribe [::subs/user]) params @(re-frame/subscribe [::params])] (if current-client [:div.is-inline - [:h1.title "Balance Sheet"] + [:h1.title "Balance Sheet - " (:name current-client)] + [status/status-notification {:statuses [[::status/single ::page]]}] + [:div.report-controls [:p.help "Date"] [bind-field @@ -190,28 +219,35 @@ :field [:date] :event [::date-picked] :popper-props (clj->js {:placement "right"}) - :subscription params}]]] - (if @(re-frame/subscribe [::loading]) - [:div [:i.icon.fa.fa-spin.fa-spinner]] + :subscription params}]] + + [switch-field {:id "include-comparison" + :checked (boolean (:include-comparison params)) + :on-change (fn [e] + (re-frame/dispatch [::include-comparison-changed (.-checked (.-target e))])) + :label "Include comparison" + :type "checkbox"}]] + [status/big-loader status] + (when (not= :loading (:state status)) [:table.table.compact.balance-sheet [:tr [:td.has-text-right "Period ending"] - [:td.has-text-right (date->str (str->date (:date params) standard))] - [:td.has-text-right (when (:date params) - (date->str (t/minus (str->date (:date params) standard) (t/years 1))))] + (when (:include-comparison params) + [:td.has-text-right (date->str (str->date (:date params) standard))]) + (when (:include-comparison params) + [:td.has-text-right (when (:date params) + (date->str (t/minus (str->date (:date params) standard) (t/years 1))))]) [:td]] (list (overall-grouping :asset "Assets") (overall-grouping :liability "Liabilities" ) (overall-grouping :equity "Owner's Equity" ) - (retained-earnings))]) - - - ] + (retained-earnings))])] [:div [:h1.title "Balance sheet"] [:h2.subtitle "Please choose a client first"]]))) - {:component-will-mount #(re-frame/dispatch-sync [::params-change {:date (date->str (local-now) standard)}]) })) + {:component-will-mount #(re-frame/dispatch-sync [::params-change {:date (date->str (local-now) standard) + :include-comparison true}]) })) (defn balance-sheet-page [] (let [user (re-frame/subscribe [::subs/user])] diff --git a/src/cljs/auto_ap/views/pages/transactions/form.cljs b/src/cljs/auto_ap/views/pages/transactions/form.cljs index dab015c7..df9bca6e 100644 --- a/src/cljs/auto_ap/views/pages/transactions/form.cljs +++ b/src/cljs/auto_ap/views/pages/transactions/form.cljs @@ -235,6 +235,11 @@ [:input.input {:type "text" :field [:description-original] :disabled "disabled"}]) + (when (and (:payment data) + is-admin?) + [:p.notification.is-info.is-light>div.level>div.level-left + [:div.level-item "This transaction is linked to a payment "] + [:div.level-item [:button.button.is-warning {:on-click (dispatch-event [::unlink])} "Unlink"]]]) (cond (and (seq (:potential-transaction-rule-matches data)) @@ -289,11 +294,7 @@ :type "typeahead-entity" :field [:forecast-match]}]) - (when (and (:payment data) - is-admin?) - [:p.notification.is-info.is-light>div.level>div.level-left - [:div.level-item "This transaction is linked to a payment "] - [:div.level-item [:button.button.is-warning {:on-click (dispatch-event [::unlink])} "Unlink"]]]) + (error-notification)