diff --git a/src/clj/auto_ap/datomic/ledger.clj b/src/clj/auto_ap/datomic/ledger.clj index b6f4816f..34c8c491 100644 --- a/src/clj/auto_ap/datomic/ledger.clj +++ b/src/clj/auto_ap/datomic/ledger.clj @@ -62,6 +62,18 @@ '[(>= ?c ?from-numeric-code)]]} :args [(:from-numeric-code args)]}) + (:amount-gte args) + (merge-query {:query {:in ['?amount-gte] + :where ['[?e :journal-entry/amount ?a] + '[(>= ?a ?amount-gte)]]} + :args [(:amount-gte args)]}) + + (:amount-lte args) + (merge-query {:query {:in ['?amount-lte] + :where ['[?e :journal-entry/amount ?a] + '[(<= ?a ?amount-lte)]]} + :args [(:amount-lte args)]}) + (:bank-account-id args) (merge-query {:query {:in ['?a] :where ['[?e :journal-entry/line-items ?li] diff --git a/src/clj/auto_ap/graphql.clj b/src/clj/auto_ap/graphql.clj index 5e5fd9c7..2afc00c4 100644 --- a/src/clj/auto_ap/graphql.clj +++ b/src/clj/auto_ap/graphql.clj @@ -517,6 +517,8 @@ :args {:client_id {:type :id} :vendor_id {:type :id} :account_id {:type :id} + :amount_lte {:type :money} + :amount_gte {:type :money} :bank_account_id {:type :id} :date_range {:type :date_range} :location {:type 'String} diff --git a/src/cljs/auto_ap/views/pages/ledger.cljs b/src/cljs/auto_ap/views/pages/ledger.cljs index 780d0a1e..e072c328 100644 --- a/src/cljs/auto_ap/views/pages/ledger.cljs +++ b/src/cljs/auto_ap/views/pages/ledger.cljs @@ -20,36 +20,29 @@ [re-frame.core :as re-frame] [reagent.core :as reagent] [auto-ap.status :as status] - [vimsical.re-frame.fx.track :as track])) - - -(re-frame/reg-sub - ::ledger-page - (fn [db] - (-> db ::ledger-page))) - - - -(re-frame/reg-sub - ::params - :<- [::subs/client] - :<- [::side-bar/filter-params] - :<- [::table/table-params] - (fn [[client filter-params table-params]] - (cond-> {} - client (assoc :client-id (:id client)) - (seq filter-params) (merge filter-params) - (seq table-params) (merge table-params)))) + [vimsical.re-frame.fx.track :as track] + [auto-ap.views.pages.data-page :as data-page] + [clojure.set :as set])) +(defn data-params->query-params [params] + {:start (:start params 0) + :sort (:sort params) + :client-id (:id @(re-frame/subscribe [::subs/client])) + :vendor-id (:id (:vendor params)) + :date-range (:date-range params) + :account-id (:id (:account params)) + :bank-account-id (:id (:bank-account params)) + :amount-gte (:amount-gte (:amount-range params)) + :amount-lte (:amount-lte (:amount-range params))}) (re-frame/reg-event-fx ::params-change [with-user] (fn [{:keys [user db]} [_ params]] {:graphql {:token user - :owns-state {:single ::page} + :owns-state {:single [::data-page/page ::page]} :query-obj {:venia/queries [[:ledger-page - params + (data-params->query-params params) [[:journal-entries [:id :source :amount @@ -66,35 +59,30 @@ :total :start :end]]]} - :on-success [::received]} - :set-uri-params (dissoc params :status :client-id)})) + :on-success (fn [result] + [::data-page/received ::page (set/rename-keys (:ledger-page result) + {:journal-entries :data})])}})) (re-frame/reg-event-fx ::unmounted (fn [{:keys [db]} _] - {:db (dissoc db ::table/table-params ::side-bar/filters ::ledger-page) - ::track/dispose {:id ::params}})) + {::track/dispose {:id ::params}})) (re-frame/reg-event-fx ::mounted (fn [{:keys [db]} _] {::track/register {:id ::params - :subscription [::params] + :subscription [::data-page/params ::page] :event-fn (fn [params] [::params-change params])}})) -(re-frame/reg-event-db - ::received - (fn [db [_ data]] - (-> db - (assoc ::ledger-page (:ledger-page data))))) + (defn ledger-content [] (let [current-client @(re-frame/subscribe [::subs/client])] [:div [:h1.title "Ledger"] [table/table {:id :ledger - :ledger-page @(re-frame/subscribe [::ledger-page]) - :status @(re-frame/subscribe [::status/single ::page])}]])) + :data-page ::page}]])) (defn ledger-page [] @@ -106,9 +94,8 @@ :reagent-render (fn [] (if (not= "manager" (:user/role @user)) - (let [params @(re-frame/subscribe [::params])] - [side-bar-layout - {:side-bar [ledger-side-bar] - :main [ledger-content]}]) + [side-bar-layout + {:side-bar [ledger-side-bar {:data-page ::page}] + :main [ledger-content]}] [:div "Not authorized"]))}))) diff --git a/src/cljs/auto_ap/views/pages/ledger/side_bar.cljs b/src/cljs/auto_ap/views/pages/ledger/side_bar.cljs index 9f1060dc..6f27d953 100644 --- a/src/cljs/auto_ap/views/pages/ledger/side_bar.cljs +++ b/src/cljs/auto_ap/views/pages/ledger/side_bar.cljs @@ -1,86 +1,15 @@ (ns auto-ap.views.pages.ledger.side-bar (:require [auto-ap.routes :as routes] [auto-ap.subs :as subs] - [auto-ap.views.utils :refer [active-when]] [auto-ap.views.components.date-range-filter :refer [date-range-filter]] - [auto-ap.views.components.bank-account-filter :refer [bank-account-filter]] + [auto-ap.views.components.number-filter :refer [number-filter]] [auto-ap.views.components.typeahead :refer [typeahead-entity]] + [auto-ap.views.pages.data-page :as data-page] + [auto-ap.views.utils :refer [active-when]] [bidi.bidi :as bidi] [re-frame.core :as re-frame])) -(re-frame/reg-sub - ::specific-filters - (fn [db ] - (::filters db {}))) - -(re-frame/reg-sub - ::settled-filters - (fn [db ] - (::settled-filters db))) - -(re-frame/reg-sub - ::filters - :<- [::specific-filters] - :<- [::subs/vendors-by-id] - :<- [::subs/bank-accounts-by-id] - :<- [::subs/accounts-by-id] - :<- [::subs/query-params] - (fn [[specific-filters vendors-by-id bank-accounts-by-id accounts-by-id query-params] ] - (let [url-filters (-> query-params - (select-keys #{:vendor-id - :bank-account-id - :account-id - :date-range})) - url-filters {:vendor (when-let [vendor-id (:vendor-id url-filters)] - {:id (str vendor-id) - :name (get-in vendors-by-id [(str vendor-id) :name] "Loading...")}) - :bank-account (when-let [bank-account-id (:bank-account-id url-filters)] - {:id (str bank-account-id) - :name (get-in bank-accounts-by-id [(str bank-account-id) :name] "Loading...")}) - - :account (when-let [account-id (:account-id url-filters)] - {:id (str account-id) - :numeric-code (get-in accounts-by-id [(str account-id) :numeric-code] "Loading...") - :name (get-in accounts-by-id [(str account-id) :name] "Loading...")}) - :date-range (:date-range url-filters)}] - (merge url-filters specific-filters )))) - -(re-frame/reg-sub - ::filter - :<- [::filters] - (fn [filters [_ which]] - (filters which))) - -(re-frame/reg-sub - ::filter-params - :<- [::settled-filters] - :<- [::filters] - (fn [[settled-filters filters]] - (let [filters (or settled-filters filters)] - {:vendor-id (:id (:vendor filters)) - :account-id (:id (:account filters)) - :date-range (:date-range filters) - :bank-account-id (:id (:bank-account filters))}))) - -(re-frame/reg-event-fx - ::filters-settled - (fn [{:keys [db]} [_ & params]] - {:db (assoc db ::settled-filters @(re-frame/subscribe [::filters]))})) - -(re-frame/reg-event-fx - ::filter-changed - (fn [{:keys [db]} [_ & params]] - (let [[a b c] params - [which val] (if (= 3 (count params)) - [(into [a] b) c] - [[a] b])] - {:db (assoc-in db (into [::filters] which) val) - :dispatch-debounce - {:event [::filters-settled] - :time 800 - :key ::filters}}))) - -(defn ledger-side-bar [] +(defn ledger-side-bar [{:keys [data-page]}] (let [ap @(re-frame/subscribe [::subs/active-page]) user @(re-frame/subscribe [::subs/user]) accounts @(re-frame/subscribe [::subs/accounts])] @@ -115,29 +44,36 @@ [:div [typeahead-entity {:matches @(re-frame/subscribe [::subs/bank-accounts]) :match->text :name + :include-keys [:name :id] :type "typeahead-entity" - :on-change #(re-frame/dispatch [::filter-changed :bank-account %]) - :value @(re-frame/subscribe [::filter :bank-account])}]] + :on-change #(re-frame/dispatch [::data-page/filter-changed data-page :bank-account %]) + :value @(re-frame/subscribe [::data-page/filter data-page :bank-account])}]] [:p.menu-label "Vendor"] [:div [typeahead-entity {:matches @(re-frame/subscribe [::subs/vendors]) - :on-change #(re-frame/dispatch [::filter-changed :vendor %]) + :on-change #(re-frame/dispatch [::data-page/filter-changed data-page :vendor %]) + :include-keys [:name :id] :match->text :name :type "typeahead-entity" - :value @(re-frame/subscribe [::filter :vendor])}]] + :value @(re-frame/subscribe [::data-page/filter data-page :vendor])}]] [:p.menu-label "Account"] [:div [typeahead-entity {:matches accounts :match->text (fn [x ] (str (:numeric-code x) " - " (:name x))) + :include-keys [:name :id :numeric-code] :type "typeahead-entity" - :on-change #(re-frame/dispatch [::filter-changed :account %]) - :value @(re-frame/subscribe [::filter :account])}]] + :on-change #(re-frame/dispatch [::data-page/filter-changed data-page :account %]) + :value @(re-frame/subscribe [::data-page/filter data-page :account])}]] + [:p.menu-label "Amount"] + [:div + [number-filter + {:on-change-event [::data-page/filter-changed data-page :amount-range] + :value @(re-frame/subscribe [::data-page/filter data-page :amount-range])}]] + [:p.menu-label "Date Range"] [:div [date-range-filter - {:on-change-event [::filter-changed :date-range] - :value @(re-frame/subscribe [::filter :date-range])}]]]) - - ]])) + {:on-change-event [::data-page/filter-changed data-page :date-range] + :value @(re-frame/subscribe [::data-page/filter data-page :date-range])}]]])]])) diff --git a/src/cljs/auto_ap/views/pages/ledger/table.cljs b/src/cljs/auto_ap/views/pages/ledger/table.cljs index 623acb3f..93327940 100644 --- a/src/cljs/auto_ap/views/pages/ledger/table.cljs +++ b/src/cljs/auto_ap/views/pages/ledger/table.cljs @@ -6,18 +6,8 @@ [auto-ap.views.utils :refer [date->str dispatch-event nf]] [goog.string :as gstring] [re-frame.core :as re-frame] - [auto-ap.views.components.grid :as grid])) - -(re-frame/reg-sub - ::table-params - (fn [db] - (::table-params db))) - -(re-frame/reg-event-fx - ::params-changed - [(re-frame/path [::table-params])] - (fn [{table-params :db} [_ params :as z]] - {:db (merge table-params params)})) + [auto-ap.views.components.grid :as grid] + [auto-ap.views.pages.data-page :as data-page])) (defn ledger-row [{{:keys [client vendor status date amount id line-items] :as i} :row :keys [selected-client accounts-by-id bank-accounts-by-id]}] @@ -48,35 +38,29 @@ [grid/cell {:class "has-text-right"} (when debit (nf debit ))] [grid/cell {:class "has-text-right"} (when credit (nf credit ))]])]]) -(defn table [{:keys [id ledger-page status vendors check-boxes checked on-check-changed expense-event]}] - (fn [{:keys [id ledger-page status vendors checked status?] - :or {status? true}}] - (let [{:keys [sort]} @(re-frame/subscribe [::table-params]) - selected-client @(re-frame/subscribe [::subs/client]) - accounts-by-id @(re-frame/subscribe [::subs/accounts-by-id selected-client]) - bank-accounts-by-id @(re-frame/subscribe [::subs/bank-accounts-by-id])] - [grid/grid {:on-params-change (fn [e] - (re-frame/dispatch [::params-changed e])) - :params @(re-frame/subscribe [::table-params]) - :status status - :column-count (if selected-client 5 6)} - [grid/controls ledger-page] - [grid/table {:fullwidth true :class ["wrappable"]} - [grid/header - [grid/row {} - (when-not selected-client - [grid/sortable-header-cell {:sort-key "client" :sort-name "Client"} "Client"]) - [grid/sortable-header-cell {:sort-key "vendor" :sort-name "Vendor"} "Vendor"] - [grid/sortable-header-cell {:sort-key "date" :sort-name "Date" :style {:width "8em"}} "Date"] - [grid/header-cell {} "Account"] - [grid/sortable-header-cell {:sort-key "amount" :sort-name "Amount" :class "has-text-right" :style {:width "7em"}} "Debit"] - [grid/sortable-header-cell {:sort-key "amount" :sort-name "Amount" :class "has-text-right" :style {:width "7em"}} "Credit"]]] - [grid/body - (for [{:keys [client vendor status date amount id line-items] :as i} (:journal-entries ledger-page)] - ^{:key id} - [ledger-row {:row i - :selected-client selected-client - :accounts-by-id accounts-by-id - :bank-accounts-by-id bank-accounts-by-id}] - )]]]))) +(defn table [{:keys [id data-page status vendors on-check-changed expense-event]}] + (let [{:keys [data status]} @(re-frame/subscribe [::data-page/page data-page]) + selected-client @(re-frame/subscribe [::subs/client]) + accounts-by-id @(re-frame/subscribe [::subs/accounts-by-id selected-client]) + bank-accounts-by-id @(re-frame/subscribe [::subs/bank-accounts-by-id])] + [grid/grid {:data-page data-page + :column-count (if selected-client 5 6)} + [grid/controls data] + [grid/table {:fullwidth true :class ["wrappable"]} + [grid/header + [grid/row {} + (when-not selected-client + [grid/sortable-header-cell {:sort-key "client" :sort-name "Client"} "Client"]) + [grid/sortable-header-cell {:sort-key "vendor" :sort-name "Vendor"} "Vendor"] + [grid/sortable-header-cell {:sort-key "date" :sort-name "Date" :style {:width "8em"}} "Date"] + [grid/header-cell {} "Account"] + [grid/sortable-header-cell {:sort-key "amount" :sort-name "Amount" :class "has-text-right" :style {:width "7em"}} "Debit"] + [grid/sortable-header-cell {:sort-key "amount" :sort-name "Amount" :class "has-text-right" :style {:width "7em"}} "Credit"]]] + [grid/body + (for [{:keys [client vendor status date amount id line-items] :as i} (:data data)] + ^{:key id} + [ledger-row {:row i + :selected-client selected-client + :accounts-by-id accounts-by-id + :bank-accounts-by-id bank-accounts-by-id}])]]])) diff --git a/src/cljs/auto_ap/views/pages/transactions.cljs b/src/cljs/auto_ap/views/pages/transactions.cljs index 414f195c..c5a07795 100644 --- a/src/cljs/auto_ap/views/pages/transactions.cljs +++ b/src/cljs/auto_ap/views/pages/transactions.cljs @@ -103,34 +103,21 @@ (defn content [] - (let [notification (re-frame/subscribe [::notification]) - user @(re-frame/subscribe [::subs/user]) + (let [user @(re-frame/subscribe [::subs/user]) params @(re-frame/subscribe [::data-page/params ::page])] [:div [:h1.title "Transactions"] [status/status-notification {:statuses [[::status/single ::unapprove-all] [::status/single ::manual-import]]}] (when (= "admin" (:user/role user)) - [:div - (when (:message @notification) - (list - [:div.notification - (:message @notification)] - (when (seq (:errors @notification)) - [:div.notification.is-danger - [:h3 (count (:errors @notification)) " errors:"] - [:ul - (for [transaction (:errors @notification) - error (:errors transaction)] - [:li (:description-original transaction) "-" (:details error)])]]))) - [:div.is-pulled-right - [:div.buttons - [:button.button.is-outlined.is-primary {:on-click (dispatch-event [::manual/opening])} - "Manual Yodlee Import"] - [:button.button.is-outlined.is-danger {:on-click (dispatch-event [::unapprove-all params]) - :class (status/class-for @(re-frame/subscribe [::status/single ::unapprove-all])) - :disabled (status/disabled-for @(re-frame/subscribe [::status/single ::unapprove-all]))} - "Unapprove all"]]]]) + [:div.is-pulled-right + [:div.buttons + [:button.button.is-outlined.is-primary {:on-click (dispatch-event [::manual/opening])} + "Manual Yodlee Import"] + [:button.button.is-outlined.is-danger {:on-click (dispatch-event [::unapprove-all params]) + :class (status/class-for @(re-frame/subscribe [::status/single ::unapprove-all])) + :disabled (status/disabled-for @(re-frame/subscribe [::status/single ::unapprove-all]))} + "Unapprove all"]]]) [table/table {:id :transactions :data-page ::page}]]))