diff --git a/src/clj/auto_ap/datomic/ledger.clj b/src/clj/auto_ap/datomic/ledger.clj index 8ba44350..17281ba2 100644 --- a/src/clj/auto_ap/datomic/ledger.clj +++ b/src/clj/auto_ap/datomic/ledger.clj @@ -39,14 +39,43 @@ :where ['[?e :journal-entry/client ?client-id]]} :args [(:client-id args)]}) - (:date-before args) - (merge-query {:query {:in ['?date-before] + (:to-date args) + (merge-query {:query {:in ['?to-date] :where ['[?e :journal-entry/date ?d] - '[(<= ?d ?date-before)]]} - :args [(:date-before args)]}) + '[(<= ?d ?to-date)]]} + :args [(c/to-date (:to-date args))]}) + + (:from-date args) + (merge-query {:query {:in ['?from-date] + :where ['[?e :journal-entry/date ?d] + '[(>= ?d ?from-date)]]} + :args [(c/to-date (:from-date args))]}) + + (:from-numeric-code args) + (merge-query {:query {:in ['?from-numeric-code] + :where ['[?e :journal-entry/line-items ?li] + '[?li :journal-entry-line/account ?a] + '[?a :account/numeric-code ?c] + '[(>= ?c ?from-numeric-code)]]} + :args [(:from-numeric-code args)]}) + + (:to-numeric-code args) + (merge-query {:query {:in ['?to-numeric-code] + :where ['[?e :journal-entry/line-items ?li] + '[?li :journal-entry-line/account ?a] + '[?a :account/numeric-code ?c] + '[(<= ?c ?to-numeric-code)]]} + :args [(:to-numeric-code args)]}) + + (:location args) + (merge-query {:query {:in ['?location] + :where ['[?e :journal-entry/line-items ?li] + '[?li :journal-entry-line/location ?location]]} + :args [(:location args)]}) true (merge-query {:query {:find ['?e] :where ['[?e :journal-entry/date]]}}))] + (println query) (cond->> query true (d/query) (:sort-by args) (apply-sort-2 args) @@ -57,9 +86,7 @@ :journal-entry/vendor [:vendor/name :db/id] :journal-entry/line-items [* {:journal-entry-line/account [* {:account/type [*]} - {:bank-account/type [*]}]}] - - }] + {:bank-account/type [*]}]}]}] ids) (map #(update % :journal-entry/date c/from-date)) (apply-sort args (some-> (:sort-by args) sort-fn)))) diff --git a/src/clj/auto_ap/graphql.clj b/src/clj/auto_ap/graphql.clj index 348cc095..3c16a157 100644 --- a/src/clj/auto_ap/graphql.clj +++ b/src/clj/auto_ap/graphql.clj @@ -10,6 +10,7 @@ [auto-ap.graphql.utils :refer [assert-admin can-see-client? assert-can-see-client]] [auto-ap.datomic :refer [uri merge-query]] [datomic.api :as d] + [clj-time.coerce :as coerce] [auto-ap.datomic.clients :as d-clients] [auto-ap.datomic.checks :as d-checks] [auto-ap.datomic.users :as d-users] @@ -23,6 +24,7 @@ [auto-ap.graphql.checks :as gq-checks] [auto-ap.graphql.invoices :as gq-invoices] [auto-ap.graphql.transactions :as gq-transactions] + [auto-ap.time :as time] [clojure.walk :as walk] [clojure.string :as str]) (:import @@ -31,11 +33,12 @@ (def integreat-schema { - :scalars {:id { - :parse (schema/as-conformer #(when % (Long/parseLong %))) + :scalars {:id {:parse (schema/as-conformer #(when % (Long/parseLong %))) :serialize (schema/as-conformer #(.toString %))} :ident {:parse (schema/as-conformer (fn [x] {:db/ident x})) - :serialize (schema/as-conformer #(or (:ident %) (:db/ident %) %))}} + :serialize (schema/as-conformer #(or (:ident %) (:db/ident %) %))} + :iso_date {:parse (schema/as-conformer #(coerce/to-date-time %)) + :serialize (schema/as-conformer #(time/unparse % time/iso-date))}} :objects { :client @@ -331,6 +334,11 @@ :ledger_page {:type :ledger_page :args {:client_id {:type :id} :bank_account_id {:type :id} + :from_date {:type :iso_date} + :to_date {:type :iso_date} + :location {:type 'String} + :from_numeric_code {:type 'Int} + :to_numeric_code {:type 'Int} :start {:type 'Int} :sort_by {:type 'String} :asc {:type 'Boolean}} diff --git a/src/clj/auto_ap/graphql/ledger.clj b/src/clj/auto_ap/graphql/ledger.clj index 31db0364..3a6c9f1d 100644 --- a/src/clj/auto_ap/graphql/ledger.clj +++ b/src/clj/auto_ap/graphql/ledger.clj @@ -72,35 +72,33 @@ (:db/ident (:bank-account/type account)))) :amount (reduce + 0 (map (fn [line-item] - (doto - (cond - (and (credit-account? account) (:journal-entry-line/debit line-item)) - (- (:journal-entry-line/debit line-item)) + (cond + (and (credit-account? account) (:journal-entry-line/debit line-item)) + (- (:journal-entry-line/debit line-item)) - (and (credit-account? account) (:journal-entry-line/credit line-item)) - (:journal-entry-line/credit line-item) + (and (credit-account? account) (:journal-entry-line/credit line-item)) + (:journal-entry-line/credit line-item) - (and (debit-account? account) (:journal-entry-line/debit line-item)) - (:journal-entry-line/debit line-item) + (and (debit-account? account) (:journal-entry-line/debit line-item)) + (:journal-entry-line/debit line-item) - (and (debit-account? account) (:journal-entry-line/credit line-item)) - (- (:journal-entry-line/credit line-item)) + (and (debit-account? account) (:journal-entry-line/credit line-item)) + (- (:journal-entry-line/credit line-item)) - :else - 0.0) - println)) + :else + 0.0)) line-items))})) []))) (defn get-balance-sheet [context args value] (let [args (assoc args :id (:id context)) [results] (l/get-graphql {:client-id (:client_id args) - :date-before (coerce/to-date (:date args)) + :to-date (coerce/to-date (:date args)) :count Integer/MAX_VALUE}) - _ (println (roll-up results)) + [comparable-results] (l/get-graphql {:client-id (:client_id args) - :date-before (coerce/to-date (time/minus (parse (:date args) iso-date) (time/years 1))) + :to-date (coerce/to-date (time/minus (parse (:date args) iso-date) (time/years 1))) :count Integer/MAX_VALUE})] (->graphql {:balance-sheet-accounts (roll-up results) @@ -111,10 +109,10 @@ (let [args (assoc args :id (:id context)) pnl (fn [from-date to-date] (let [[starting-results] (l/get-graphql {:client-id (:client_id args) - :date-before from-date + :to-date from-date :count Integer/MAX_VALUE}) [ending-results] (l/get-graphql {:client-id (:client_id args) - :date-before to-date + :to-date to-date :count Integer/MAX_VALUE}) starting-accounts (by :id (roll-up starting-results)) ending-accounts (by :id (roll-up ending-results))] diff --git a/src/cljs/auto_ap/views/pages/ledger/profit_and_loss.cljs b/src/cljs/auto_ap/views/pages/ledger/profit_and_loss.cljs index 6b798396..de8c1ea2 100644 --- a/src/cljs/auto_ap/views/pages/ledger/profit_and_loss.cljs +++ b/src/cljs/auto_ap/views/pages/ledger/profit_and_loss.cljs @@ -1,6 +1,7 @@ (ns auto-ap.views.pages.ledger.profit-and-loss (:require [auto-ap.subs :as subs] - [auto-ap.views.components.layouts :refer [side-bar-layout]] + [auto-ap.views.components.layouts :refer [side-bar-layout appearing-side-bar]] + [auto-ap.views.pages.ledger.table :refer [table]] [goog.string :as gstring] [auto-ap.utils :refer [dollars-0? by ]] [auto-ap.views.pages.ledger.side-bar :refer [ledger-side-bar]] @@ -8,6 +9,7 @@ [cljs-time.core :as t] [re-frame.core :as re-frame])) +;; SUBS (re-frame/reg-sub ::locations (fn [db] @@ -27,11 +29,31 @@ (fn [db] (-> db ::report))) +(re-frame/reg-sub + ::ledger-list-active? + (fn [db] + (-> db ::ledger-list-active?))) + (re-frame/reg-sub ::loading (fn [db] (-> db ::loading))) +(re-frame/reg-sub + ::ledger-list-loading + (fn [db] + (-> db ::ledger-list-loading))) + +(re-frame/reg-sub + ::ledger-list + (fn [db] + (-> db ::ledger-list :ledger-page))) + +(re-frame/reg-sub + ::ledger-params + (fn [db] + (-> db (::ledger-params {}) ))) + (re-frame/reg-sub ::accounts (fn [db [_ type only-location]] @@ -46,6 +68,7 @@ + (re-frame/reg-sub ::accounts-by-id (fn [db [_ type only-location]] @@ -82,6 +105,20 @@ (fn [db] (-> db ::params))) +;; EVENTS + +(re-frame/reg-event-db + ::ledger-list-closing + (fn [db] + (assoc db ::ledger-list-active? false))) + +(re-frame/reg-event-db + ::ledger-list-received + (fn [db [_ ledger-list]] + (assoc db + ::ledger-list ledger-list + ::ledger-list-loading false))) + (re-frame/reg-event-fx ::params-change (fn [cofx [_ params]] @@ -111,6 +148,43 @@ :from-date from :to-date to :selected selected)]})) + +(re-frame/reg-event-fx + ::investigate-clicked + (fn [{:keys [db] } [_ location from-numeric-code to-numeric-code which]] + {:db (assoc db + ::ledger-list-active? true + ::ledger-list-loading true) + :graphql {:token (-> db :user) + :query-obj {:venia/queries [[:ledger-page + {:client-id (:id @(re-frame/subscribe [::subs/client])) + :from-numeric-code from-numeric-code + :to-numeric-code to-numeric-code + :location location + :from-date (if (= :current which) + (:from-date (::params db)) + (date->str (t/minus (str->date (:from-date (::params db)) standard) (t/years 1)) + standard)) + :to-date (if (= :current which) + (:to-date (::params db)) + (date->str (t/minus (str->date (:to-date (::params db)) standard) (t/years 1)) + standard))} + [[:journal-entries [:id + :source + :amount + [:vendor + [:name :id]] + [:client + [:name :id]] + [:line-items + [:id :debit :credit :location + [:account [:id :name]]]] + :date]] + :total + :start + :end]]]} + :on-success [::ledger-list-received]}})) + (def groupings {:expense [["1100 Cash and Bank Accounts" 1100 1199] @@ -159,9 +233,7 @@ ["9800 Other Expenses" 9800 9899] ["9900 Tax Only Expenses" 9900 9999]]}) -(defn grouping [{:keys [header accounts comparable-accounts groupings]}] - - +(defn grouping [{:keys [header accounts comparable-accounts groupings location]}] (for [[grouping-name from to] groupings :let [matching-accounts (filter #(<= from (:numeric-code %) to) @@ -176,14 +248,20 @@ ] (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 [:a {:on-click (dispatch-event [::investigate-clicked location (:numeric-code account) (:numeric-code account) :current])} + (->$ (:amount account))]] + [:td.has-text-right [:a {:on-click (dispatch-event [::investigate-clicked location (:numeric-code account) (:numeric-code account) :comparable])} + (->$ (: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 [:a + {:on-click (dispatch-event [::investigate-clicked location from to :current])} + (->$ (reduce + 0 (map :amount + matching-accounts)))] ] + [:th.has-text-right.total [:a + {:on-click (dispatch-event [::investigate-clicked location from to :comparable])} + (->$ (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)))] @@ -197,12 +275,17 @@ [:td] [:td]] (grouping {:accounts @(re-frame/subscribe [::accounts type location]) + :location location :groupings (type groupings) :comparable-accounts @(re-frame/subscribe [::comparable-accounts-by-id type location]) }) [:tr [:th.has-text-centered title] - [:th.has-text-right (->$ (reduce + 0 (map :amount @(re-frame/subscribe [::accounts type location]))))] - [:th.has-text-right (->$ (reduce + 0 (map :amount (vals @(re-frame/subscribe [::comparable-accounts-by-id type location])))))] + [:th.has-text-right [:a + {:on-click (dispatch-event [::investigate-clicked location nil nil :current])} + (->$ (reduce + 0 (map :amount @(re-frame/subscribe [::accounts type location]))))]] + [:th.has-text-right [:a + {:on-click (dispatch-event [::investigate-clicked location nil nil :comparable])} + (->$ (reduce + 0 (map :amount (vals @(re-frame/subscribe [::comparable-accounts-by-id type location])))))]] [:th.has-text-right (->$ (- (reduce + 0 (map :amount @(re-frame/subscribe [::accounts type location]))) (reduce + 0 (map :amount (vals @(re-frame/subscribe [::comparable-accounts-by-id type location]))))))]])) @@ -318,7 +401,23 @@ {:component-will-mount #(re-frame/dispatch-sync [::params-change {:from-date (date->str (t/minus (local-now) (t/period :years 1)) standard) :to-date (date->str (local-now) standard)}]) })) + + +(defn ledger-list [_ ] + (let [ledger-page (re-frame/subscribe [::ledger-list])] + [:div [:a.delete.is-pulled-right {:on-click (dispatch-event [::ledger-list-closing])}] + [:div + [:h1.title "Ledger entries"] + [table {:ledger-page ledger-page + :status? false + :status (re-frame/subscribe [::ledger-list-loading]) + :params (re-frame/subscribe [::ledger-params])} ]]])) + (defn profit-and-loss-page [] - [side-bar-layout - {:side-bar [ledger-side-bar] - :main [profit-and-loss-content]}]) + (let [ledger-list-active? @(re-frame/subscribe [::ledger-list-active?])] + [side-bar-layout + {:side-bar [ledger-side-bar] + :main [profit-and-loss-content] + :right-side-bar [appearing-side-bar + {:visible? ledger-list-active?} + [ledger-list]]}])) diff --git a/src/cljs/auto_ap/views/pages/ledger/table.cljs b/src/cljs/auto_ap/views/pages/ledger/table.cljs index 0c8c023d..7d660020 100644 --- a/src/cljs/auto_ap/views/pages/ledger/table.cljs +++ b/src/cljs/auto_ap/views/pages/ledger/table.cljs @@ -9,7 +9,8 @@ (defn table [{:keys [id ledger-page status on-params-change vendors params check-boxes checked on-check-changed expense-event]}] (let [opc (fn [p] (on-params-change (merge @params p )))] - (fn [{:keys [id ledger-page status on-params-change vendors checked]}] + (fn [{:keys [id ledger-page status on-params-change vendors checked status?] + :or {status? true}}] (let [{:keys [sort-by asc]} @params {:keys [journal-entries start end count total]} @ledger-page selected-client @(re-frame/subscribe [::subs/client]) @@ -70,13 +71,14 @@ "Credit"] + (when status? - [sorted-column {:on-sort opc - :style {:width "8em" :cursor "pointer"} - :sort-key "status" - :sort-by sort-by - :asc asc} - "Status"]]] + [sorted-column {:on-sort opc + :style {:width "8em" :cursor "pointer"} + :sort-key "status" + :sort-by sort-by + :asc asc} + "Status"])]] [:tbody (if (:loading @status) [:tr @@ -98,7 +100,8 @@ [:td.has-text-right (nf amount )] [:td.has-text-right (nf amount )] - [:td status]]] + (when status? + [:td status])]] (for [{:keys [debit credit location account]} line-items] [:tr {:class (:class i)} (when-not selected-client @@ -112,7 +115,8 @@ [:td.has-text-right (when debit (nf debit ))] [:td.has-text-right (when credit (nf credit ))] - [:td status]] + (when status? + [:td status])] ))) (mapcat identity)))]]]))))