From be9c7890035b0f5b51de84749f1d6d53e51efd8d Mon Sep 17 00:00:00 2001 From: Bryce Covert Date: Fri, 31 Jul 2020 18:26:57 -0700 Subject: [PATCH] lots of QOL improvements. --- src/clj/auto_ap/background/invoices.clj | 29 ++++ src/clj/auto_ap/datomic/invoices.clj | 32 +++-- src/clj/auto_ap/parse/templates.clj | 7 +- src/clj/auto_ap/routes/invoices.clj | 11 +- src/clj/auto_ap/server.clj | 2 + src/cljc/auto_ap/utils.cljc | 9 ++ .../views/components/invoice_table.cljs | 19 +-- .../views/components/invoices/side_bar.cljs | 126 ++++++------------ .../auto_ap/views/pages/import_invoices.cljs | 70 ++++++---- .../auto_ap/views/pages/ledger/side_bar.cljs | 28 +++- src/cljs/auto_ap/views/pages/payments.cljs | 2 +- .../views/pages/payments/side_bar.cljs | 114 +++++----------- .../auto_ap/views/pages/transactions.cljs | 5 +- .../views/pages/transactions/side_bar.cljs | 119 +++++++++-------- .../auto_ap/views/pages/unpaid_invoices.cljs | 11 +- 15 files changed, 302 insertions(+), 282 deletions(-) create mode 100644 src/clj/auto_ap/background/invoices.clj diff --git a/src/clj/auto_ap/background/invoices.clj b/src/clj/auto_ap/background/invoices.clj new file mode 100644 index 00000000..46e4f383 --- /dev/null +++ b/src/clj/auto_ap/background/invoices.clj @@ -0,0 +1,29 @@ +(ns auto-ap.background.invoices + (:require [auto-ap.datomic.invoices :as d-invoices] + [auto-ap.datomic :refer [uri]] + [datomic.api :as d] + [auto-ap.time :as time] + [clj-time.coerce :as coerce])) + +(def break (atom false)) + +(defn close-auto-invoices [] + (while (and (not @break) + (not (Thread/interrupted))) + (println "Clearing automatic invoices") + (try + (->> (d/query {:query {:find ['?e] + :in ['$ '?today] + :where ['[?e :invoice/automatically-paid-when-due true] + '[?e :invoice/status :invoice-status/unpaid] + '[?e :invoice/due ?d] + '[(<= ?d ?today)]]} + :args [(d/db (d/connect uri)) (coerce/to-date (time/local-now))]}) + (mapv (fn [[i]] {:db/id i + :invoice/outstanding-balance 0.0 + :invoice/status :invoice-status/paid})) + (d/transact (d/connect uri)) + deref) + (Thread/sleep (* 1000 60 60)) + (catch Exception e + (println (.toString e)))))) diff --git a/src/clj/auto_ap/datomic/invoices.clj b/src/clj/auto_ap/datomic/invoices.clj index fae52eeb..46ae7fdb 100644 --- a/src/clj/auto_ap/datomic/invoices.clj +++ b/src/clj/auto_ap/datomic/invoices.clj @@ -194,15 +194,27 @@ (defn get-existing-set [] - (d/query - (cond-> {:query {:find ['?vendor '?client '?invoice-number] - :in ['$] - :where '[[?e :invoice/invoice-number ?invoice-number] - [?e :invoice/vendor ?vendor] - [?e :invoice/client ?client] - (not [?e :invoice/status :invoice-status/voided]) - ]} - - :args [(d/db (d/connect uri))]}))) + (let [vendored-results (set (d/query {:query {:find ['?vendor '?client '?invoice-number] + :in ['$] + :where '[[?e :invoice/invoice-number ?invoice-number] + [?e :invoice/vendor ?vendor] + [?e :invoice/client ?client] + (not [?e :invoice/status :invoice-status/voided]) + ]} + + :args [(d/db (d/connect uri))]})) + vendorless-results (->> (d/query {:query {:find ['?client '?invoice-number] + :in ['$] + :where '[[?e :invoice/invoice-number ?invoice-number] + (not [?e :invoice/vendor]) + [?e :invoice/client ?client] + (not [?e :invoice/status :invoice-status/voided]) + ]} + + :args [(d/db (d/connect uri))]}) + (mapv (fn [[client invoice-number]] + [nil client invoice-number]) ) + set)] + (into vendored-results vendorless-results))) diff --git a/src/clj/auto_ap/parse/templates.clj b/src/clj/auto_ap/parse/templates.clj index 32b70bbf..7a195271 100644 --- a/src/clj/auto_ap/parse/templates.clj +++ b/src/clj/auto_ap/parse/templates.clj @@ -107,9 +107,12 @@ :extract {:date #"INVOICE DATE(?s:.*)(?= (?:[0-9]+/[0-9]+/[0-9]+)\s+([0-9]+/[0-9]+/[0-9]+)) " :customer-identifier #"SOLD TO:(?:.*)(?=\n)\n(.*)(?=\s{2,})" ;; ([\S ]+)\s{2,} :invoice-number #"INVOICE\n(?:.*?)(?=\d{4,})(\d+)" - :total #"PAY THIS AMOUNT(?s:.*)(?= ([0-9,]+\.[0-9]{2}))"} + :total #"PAY THIS AMOUNT(?s:.*)(?= ([0-9,]+\.[0-9]{2}))" + :account-number #"ACCOUNT #.*\n.*\n\s+(\d+)"} :parser {:date [:clj-time "MM/dd/yy"] - :total [:trim-commas nil]}} + :total [:trim-commas nil]} + :multi #"\f" + :multi-match? #"PAY THIS AMOUNT"} ;; GOLDEN BRANDS {:vendor "Golden Brands San Jose" diff --git a/src/clj/auto_ap/routes/invoices.clj b/src/clj/auto_ap/routes/invoices.clj index fe544515..1c3297bb 100644 --- a/src/clj/auto_ap/routes/invoices.clj +++ b/src/clj/auto_ap/routes/invoices.clj @@ -64,6 +64,9 @@ (defn parse-vendor-id [{:keys [vendor]}] (:db/id vendor)) +(defn parse-automatically-paid-when-due [{:keys [vendor client-id]}] + (boolean ((set (map :db/id (:vendor/automatically-paid-when-due vendor))) client-id))) + (defn parse-amount [i] (try (Double/parseDouble (str/replace (or (second @@ -121,6 +124,7 @@ (map (parse-or-error :client-id #(parse-client % all-clients))) (map (parse-or-error :vendor #(parse-vendor % all-vendors))) (map (parse-or-error :vendor-id #(parse-vendor-id %))) + (map (parse-or-error :automatically-paid-when-due #(parse-automatically-paid-when-due %))) (map (parse-or-error :account-id parse-account-numeric-code)) (map (parse-or-error :invoice-number parse-invoice-number)) (map (parse-or-error :total parse-amount)) @@ -131,13 +135,14 @@ (defn invoice-rows->transaction [rows] (->> rows - (mapcat (fn [{:keys [vendor-id total client-id amount date invoice-number default-location account-id check vendor]}] + (mapcat (fn [{:keys [vendor-id total client-id amount date invoice-number default-location account-id check vendor automatically-paid-when-due]}] (let [invoice (cond-> #:invoice {:db/id (.toString (java.util.UUID/randomUUID)) :vendor vendor-id :client client-id :default-location default-location :import-status :import-status/imported + :automatically-paid-when-due automatically-paid-when-due #_#_:default-expense-account default-expense-account :total total :outstanding-balance (if (= "Cash" check) @@ -245,7 +250,8 @@ ". " (.toString e)) {:args [ invoice-number matching-vendor (:db/id matching-client)]}))) - ))] + )) + automatically-paid-for (set (map :db/id (:vendor/automatically-paid-when-due matching-vendor)))] (cond (not (and matching-location matching-client)) @@ -259,6 +265,7 @@ :invoice/client-identifier customer-identifier :invoice/vendor (:db/id matching-vendor) :invoice/invoice-number invoice-number + :invoice/automatically-paid-when-due (boolean (automatically-paid-for (:db/id matching-client))) :invoice/total (Double/parseDouble total) :invoice/date (to-date date) :invoice/import-status :import-status/pending diff --git a/src/clj/auto_ap/server.clj b/src/clj/auto_ap/server.clj index 4317a9f7..191bf404 100644 --- a/src/clj/auto_ap/server.clj +++ b/src/clj/auto_ap/server.clj @@ -3,6 +3,7 @@ [auto-ap.handler :refer [app]] [auto-ap.ledger :refer [process-all keep-up-to-date]] [auto-ap.yodlee.core :refer [load-in-memory-cache]] + [auto-ap.background.invoices :refer [close-auto-invoices]] [nrepl.server :refer [start-server stop-server]] [config.core :refer [env]] [ring.adapter.jetty :refer [run-jetty]]) @@ -18,5 +19,6 @@ (future (process-all)) (future (load-in-memory-cache)) (future (keep-up-to-date)) + (future (close-auto-invoices)) #_(future (always-process-sqs)) (run-jetty app {:port port :join? false}))) diff --git a/src/cljc/auto_ap/utils.cljc b/src/cljc/auto_ap/utils.cljc index 6aa6b3c7..57484026 100644 --- a/src/cljc/auto_ap/utils.cljc +++ b/src/cljc/auto_ap/utils.cljc @@ -36,3 +36,12 @@ (defn dollars= [amt1 amt2] (dollars-0? (- amt1 amt2) )) + +(defn deep-merge [v & vs] + (letfn [(rec-merge [v1 v2] + (if (and (map? v1) (map? v2)) + (merge-with deep-merge v1 v2) + v2))] + (if (some identity vs) + (reduce #(rec-merge %1 %2) v vs) + (last vs)))) diff --git a/src/cljs/auto_ap/views/components/invoice_table.cljs b/src/cljs/auto_ap/views/components/invoice_table.cljs index 7ff4e79b..b2bb69dc 100644 --- a/src/cljs/auto_ap/views/components/invoice_table.cljs +++ b/src/cljs/auto_ap/views/components/invoice_table.cljs @@ -50,7 +50,7 @@ (-> params (assoc :client-id (:id @(re-frame/subscribe [::subs/client])))) - [[:invoices [:id :total :outstanding-balance :invoice-number :date :due :status :client-identifier + [[:invoices [:id :total :outstanding-balance :invoice-number :date :due :status :client-identifier :automatically-paid-when-due [:vendor [:name :id]] [:expense_accounts [:amount :id :location [:account [:id ]]]] @@ -81,17 +81,20 @@ {:db (merge table-params params)})) (defn row [{:keys [invoice check-boxes checked on-check-changed selected-client overrides expense-event on-edit-invoice on-void-invoice on-unvoid-invoice]}] - (let [{:keys [client payments expense-accounts invoice-number date due total outstanding-balance id vendor] :as i} invoice + (let [{:keys [client payments expense-accounts invoice-number date due total outstanding-balance id vendor checkable?] :as i} invoice accounts-by-id @(re-frame/subscribe [::subs/accounts-by-id client]) account->name #(:name (accounts-by-id (:id %)))] [:tr {:class (:class i)} (when check-boxes - [:td [:input.checkbox {:type "checkbox" - :checked (if (get checked id) - "checked" - "") - :on-change (fn [x e] (when on-check-changed - (on-check-changed id i)))} ]]) + [:td.expandable + [:input.checkbox (cond-> {:type "checkbox" + + :checked (if (get checked id) + "checked" + "") + :on-change (fn [x e] (when on-check-changed + (on-check-changed id i)))} + (boolean? checkable?) (assoc :disabled (not checkable?))) ]]) (when-not selected-client [:td (if-let [client-override (:client overrides)] (client-override i) diff --git a/src/cljs/auto_ap/views/components/invoices/side_bar.cljs b/src/cljs/auto_ap/views/components/invoices/side_bar.cljs index 88ada957..d4eec58c 100644 --- a/src/cljs/auto_ap/views/components/invoices/side_bar.cljs +++ b/src/cljs/auto_ap/views/components/invoices/side_bar.cljs @@ -6,11 +6,12 @@ [cljs-time.core :as c] [goog.string :as gstring] [bidi.bidi :as bidi] + [auto-ap.utils :refer [deep-merge ]] [auto-ap.routes :as routes] [auto-ap.views.components.date-range-filter :refer [date-range-filter]] [auto-ap.views.components.number-filter :refer [number-filter]] [auto-ap.views.components.typeahead :refer [typeahead-entity]] - [auto-ap.views.utils :refer [active-when dispatch-event bind-field horizontal-field date->str str->date pretty standard query-params]] + [auto-ap.views.utils :refer [active-when dispatch-event bind-field horizontal-field date->str str->date pretty standard query-params dispatch-value-change]] [auto-ap.subs :as subs] [auto-ap.events :as events])) @@ -25,7 +26,6 @@ :<- [::subs/vendors-by-id] :<- [::subs/query-params] (fn [[specific-filters vendors-by-id query-params] ] - (println "Q:UERY" query-params) (let [url-filters (-> query-params (select-keys #{:vendor-id :date-range @@ -37,16 +37,13 @@ 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...")}) - :date-range {:raw (:date-range url-filters) - :settled (:date-range url-filters)} + :date-range (:date-range url-filters) :due-range (:due-range url-filters) - :amount-range {:raw {:amount-gte (:amount-gte url-filters) - :amount-lte (:amount-lte url-filters)} - :settled {:amount-gte (:amount-gte url-filters) - :amount-lte (:amount-lte url-filters)}} - :invoice-number-like {:raw (str (:invoice-number-like url-filters)) - :settled (str (:invoice-number-like url-filters))}}] - (merge url-filters specific-filters )))) + :amount-range {:amount-gte (:amount-gte url-filters) + :amount-lte (:amount-lte url-filters)} + :invoice-number-like (str (:invoice-number-like url-filters))}] + + (deep-merge url-filters (or specific-filters {}) )))) (re-frame/reg-sub ::filter @@ -54,24 +51,34 @@ (fn [filters [_ which]] (get filters which))) +(re-frame/reg-sub + ::settled-filters + (fn [db ] + (::settled-filters db))) + (re-frame/reg-sub ::filter-params + :<- [::settled-filters] :<- [::filters] :<- [::subs/active-page] - - (fn [[filters ap ]] - {:vendor-id (:id (:vendor filters)) - :date-range (:settled (:date-range filters)) - :due-range (:due-range filters) - :amount-gte (:amount-gte (:settled (:amount-range filters))) - :amount-lte (:amount-lte (:settled (:amount-range filters))) - :invoice-number-like (:settled (:invoice-number-like filters)) - :status (condp = ap - :invoices nil - :unpaid-invoices :unpaid - :paid-invoices :paid - :voided-invoices :voided)})) + (fn [[settled-filters filters ap ]] + (let [filters (or settled-filters filters)] + {:vendor-id (:id (:vendor filters)) + :date-range (:date-range filters) + :due-range (:due-range filters) + :amount-gte (:amount-gte (:amount-range filters)) + :amount-lte (:amount-lte (:amount-range filters)) + :invoice-number-like (:invoice-number-like filters) + :status (condp = ap + :invoices nil + :unpaid-invoices :unpaid + :paid-invoices :paid + :voided-invoices :voided)}))) +(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 @@ -80,66 +87,17 @@ [which val] (if (= 3 (count params)) [(into [a] b) c] [[a] b])] - {:db (assoc-in db (into [::filters] which) val)}))) - -(re-frame/reg-event-fx - ::invoice-number-like-settled - [(re-frame/path [::filters :invoice-number-like])] - (fn [{:keys [db]} [_ invoice-number-like]] - {:db (assoc db :settled invoice-number-like) - :dispatch [::filter-changed :invoice-number-like [:settled] invoice-number-like]})) - -(re-frame/reg-event-fx - ::amount-range-settled - [(re-frame/path [::filters :amount-range])] - (fn [{:keys [db]} [_ which value]] - {:db (assoc-in db [:settled which] value) - :dispatch [::filter-changed :amount-range [:settled] (assoc (:settled db) which value)]})) - -(re-frame/reg-event-fx - ::invoice-number-like-changed - [(re-frame/path [::filters :invoice-number-like])] - (fn [{:keys [db]} [_ invoice-number-like]] - {:dispatch-debounce {:event [::invoice-number-like-settled invoice-number-like] - :time 500 - :key ::invoice-number-like} - :db (assoc db :raw invoice-number-like)})) - -(re-frame/reg-event-fx - ::amount-range-changed - [(re-frame/path [::filters :amount-range])] - (fn [{:keys [db]} [_ [which] value]] - {:dispatch-debounce - {:event [::amount-range-settled which value] - :time 500 - :key ::amount-range} - :db (assoc-in db [:raw which] value)})) - -(re-frame/reg-event-fx - ::date-range-settled - [(re-frame/path [::filters :date-range])] - (fn [{:keys [db]} [_ which value]] - {:db (assoc-in db [:settled which] value) - :dispatch [::filter-changed :date-range [:settled] (assoc (:settled db) which value)]})) - -;; TODO for some reason reloading is borken, and typing will unset stuff, has nothing to do with it being debounced -(re-frame/reg-event-fx - ::date-range-changed - [(re-frame/path [::filters :date-range])] - (fn [{:keys [db]} [_ [which] value]] - (println which value) - {:dispatch-debounce - {:event [::date-range-settled which value] - :time 1000 - :key ::date-range} - :db (assoc-in db [:raw which] value)})) + {:db (assoc-in db (into [::filters] which) val) + :dispatch-debounce + {:event [::filters-settled] + :time 800 + :key ::filters}}))) (defn invoice-number-filter [] [:div.field [:div.control [:input.input {:placeholder "AP-123" - :value (:raw @(re-frame/subscribe [::filter :invoice-number-like])) - :on-change (fn [x] - (re-frame/dispatch [::invoice-number-like-changed (.. x -target -value) ]))} ]]]) + :value @(re-frame/subscribe [::filter :invoice-number-like]) + :on-change (dispatch-value-change [::filter-changed :invoice-number-like ])} ]]]) (defn invoices-side-bar [params] (let [ap @(re-frame/subscribe [::subs/active-page]) @@ -191,8 +149,8 @@ [:p.menu-label "Date Range"] [:div [date-range-filter - {:on-change-event [::date-range-changed] - :value (:raw @(re-frame/subscribe [::filter :date-range]))}]] + {:on-change-event [::filter-changed :date-range] + :value @(re-frame/subscribe [::filter :date-range])}]] [:p.menu-label "Due Range"] [:div @@ -203,8 +161,8 @@ [:p.menu-label "Amount"] [:div [number-filter - {:on-change-event [::amount-range-changed] - :value (:raw @(re-frame/subscribe [::filter :amount-range]))}]] + {:on-change-event [::filter-changed :amount-range] + :value @(re-frame/subscribe [::filter :amount-range])}]] [:p.menu-label "Invoice #"] [:div diff --git a/src/cljs/auto_ap/views/pages/import_invoices.cljs b/src/cljs/auto_ap/views/pages/import_invoices.cljs index cc363a23..02e4c3ce 100644 --- a/src/cljs/auto_ap/views/pages/import_invoices.cljs +++ b/src/cljs/auto_ap/views/pages/import_invoices.cljs @@ -7,14 +7,15 @@ [auto-ap.entities.clients :as client] [auto-ap.views.components.layouts :refer [side-bar-layout]] [auto-ap.views.components.invoices.side-bar :refer [invoices-side-bar]] - [auto-ap.views.utils :refer [dispatch-event bind-field]] + [auto-ap.views.utils :refer [dispatch-event bind-field with-user]] [auto-ap.utils :refer [by]] [auto-ap.entities.vendors :as vendor] [auto-ap.views.components.typeahead :refer [typeahead-entity]] [auto-ap.views.components.invoice-table :refer [invoice-table] :as invoice-table] [cljsjs.dropzone :as dropzone] [cljs.reader :as edn] - [clojure.string :as str])) + [clojure.string :as str] + [vimsical.re-frame.cofx.inject :as inject])) (defn dropzone [] (let [client (re-frame/subscribe [::subs/client]) token (re-frame/subscribe [::subs/token]) @@ -75,10 +76,6 @@ (fn [db] (-> db ::error))) -(re-frame/reg-sub - ::params - (fn [db] - (-> db (::params {})))) (re-frame/reg-sub ::batch @@ -98,16 +95,36 @@ :db (-> (:db cofx) (update ::batch inc))})) +(re-frame/reg-sub + ::last-params + (fn [db] + (-> db ::last-params))) + +(re-frame/reg-sub + ::params + :<- [::last-params] + :<- [::subs/client] + :<- [::invoice-table/table-params] + (fn [[last-params client table-params]] + (println "RE-EVALUATING") + (let [params (cond-> {:import-status "pending"} + client (assoc :client-id (:id client)) + (seq table-params) (merge table-params))] + (when (not= params last-params) + (re-frame/dispatch [::params-change])) + params))) + (re-frame/reg-event-fx ::params-change - (fn [cofx [_ params]] + [with-user (re-frame/inject-cofx ::inject/sub [::params])] + (fn [{:keys [db user] ::keys [params]} [_]] - {:db (-> (:db cofx) + {:db (-> db (dissoc ::error) (assoc-in [:status :loading] true) - (assoc-in [::params] params)) - :graphql {:token (-> cofx :db :user) - :query-obj (invoice-table/query (assoc params :import-status "pending")) + (assoc-in [::last-params] params)) + :graphql {:token user + :query-obj (invoice-table/query params) :on-success [::received]}})) (re-frame/reg-event-db @@ -210,6 +227,7 @@ status (re-frame/subscribe [::subs/status]) error (re-frame/subscribe [::error]) batch (re-frame/subscribe [::batch]) + params @(re-frame/subscribe [::params]) client (:id @(re-frame/subscribe [::subs/client]))] ^{:key (str client "-" @batch)} [:div @@ -227,24 +245,18 @@ [:span {:class "card-header-title"} "Found Invoices"]] [:div {:class "card-content"} [approve-reject-button (:checked @invoice-page)] - (if (:loading @status) - [:h1.title - [:i.fa.fa-spin.fa-spinner]] - (if (seq (:invoices @invoice-page)) - [invoice-table {:id :approved - :invoice-page invoice-page - :overrides {:client (fn [row] - [:p (:name (:client row)) - [:p [:i.is-size-7 (:client-identifier row)]]])} - :check-boxes true - :checked (:checked @invoice-page) - :on-check-changed (fn [which invoice] - (re-frame/dispatch [::toggle-check which invoice])) - :status (re-frame/subscribe [::subs/status]) - :params (re-frame/subscribe [::params]) - :on-params-change (fn [params] - (re-frame/dispatch [::params-change params])) }] - [:span "No pending invoices"]))]]])) + (if (seq (:invoices @invoice-page)) + [invoice-table {:id :approved + :invoice-page invoice-page + :overrides {:client (fn [row] + [:p (:name (:client row)) + [:p [:i.is-size-7 (:client-identifier row)]]])} + :check-boxes true + :checked (:checked @invoice-page) + :on-check-changed (fn [which invoice] + (re-frame/dispatch [::toggle-check which invoice])) + :status (re-frame/subscribe [::subs/status])}] + [:span "No pending invoices"])]]])) {:component-will-mount (fn [] (re-frame/dispatch-sync [::invalidated]))})) 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 07439d89..9f1060dc 100644 --- a/src/cljs/auto_ap/views/pages/ledger/side_bar.cljs +++ b/src/cljs/auto_ap/views/pages/ledger/side_bar.cljs @@ -13,6 +13,11 @@ (fn [db ] (::filters db {}))) +(re-frame/reg-sub + ::settled-filters + (fn [db ] + (::settled-filters db))) + (re-frame/reg-sub ::filters :<- [::specific-filters] @@ -38,7 +43,6 @@ :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)}] - (println url-filters specific-filters) (merge url-filters specific-filters )))) (re-frame/reg-sub @@ -49,13 +53,19 @@ (re-frame/reg-sub ::filter-params + :<- [::settled-filters] :<- [::filters] - (fn [filters] - {:vendor-id (:id (:vendor filters)) - :account-id (:id (:account filters)) - :date-range (:date-range filters) - :bank-account-id (:id (:bank-account 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 @@ -64,7 +74,11 @@ [which val] (if (= 3 (count params)) [(into [a] b) c] [[a] b])] - {:db (assoc-in db (into [::filters] which) val)}))) + {:db (assoc-in db (into [::filters] which) val) + :dispatch-debounce + {:event [::filters-settled] + :time 800 + :key ::filters}}))) (defn ledger-side-bar [] (let [ap @(re-frame/subscribe [::subs/active-page]) diff --git a/src/cljs/auto_ap/views/pages/payments.cljs b/src/cljs/auto_ap/views/pages/payments.cljs index f1eb03bb..0b8c8423 100644 --- a/src/cljs/auto_ap/views/pages/payments.cljs +++ b/src/cljs/auto_ap/views/pages/payments.cljs @@ -105,7 +105,7 @@ (re-frame/reg-event-fx ::unmounted (fn [{:keys [db]} _] - {:db (dissoc db ::last-params ::table/table-params ::side-bar/filters ::payment-page)})) + {:db (dissoc db ::last-params ::table/table-params ::side-bar/filters ::side-bar/settled-filters ::payment-page)})) (defn content [] (let [params @(re-frame/subscribe [::params])] diff --git a/src/cljs/auto_ap/views/pages/payments/side_bar.cljs b/src/cljs/auto_ap/views/pages/payments/side_bar.cljs index f085afa7..7732bf81 100644 --- a/src/cljs/auto_ap/views/pages/payments/side_bar.cljs +++ b/src/cljs/auto_ap/views/pages/payments/side_bar.cljs @@ -1,7 +1,7 @@ (ns auto-ap.views.pages.payments.side-bar (:require [auto-ap.routes :as routes] [auto-ap.subs :as subs] - [auto-ap.views.utils :refer [active-when]] + [auto-ap.views.utils :refer [active-when dispatch-value-change]] [auto-ap.views.components.vendor-filter :refer [vendor-filter]] [auto-ap.views.components.date-range-filter :refer [date-range-filter]] [auto-ap.views.components.number-filter :refer [number-filter]] @@ -15,6 +15,11 @@ (fn [db ] (::filters db {}))) +(re-frame/reg-sub + ::settled-filters + (fn [db ] + (::settled-filters db))) + (re-frame/reg-sub ::filters :<- [::specific-filters] @@ -32,15 +37,11 @@ {:id (str vendor-id) :name (get-in vendors-by-id [(str vendor-id) :name] "Loading...")}) :date-range (:date-range url-filters) - :amount-range {:raw {:amount-gte (:amount-gte url-filters) - :amount-lte (:amount-lte url-filters)} - :settled {:amount-gte (:amount-gte url-filters) - :amount-lte (:amount-lte url-filters)}} - :check-number-like {:raw (:check-number-like url-filters) - :settled (:check-number-like url-filters)} - :invoice-number {:raw (:invoice-number url-filters) - :settled (:invoice-number url-filters)}}] - (println "URL filters" url-filters) + :amount-range {:amount-gte (:amount-gte url-filters) + :amount-lte (:amount-lte url-filters)} + :check-number-like (:check-number-like url-filters) + :invoice-number (:invoice-number url-filters)}] + (merge url-filters specific-filters )))) (re-frame/reg-sub @@ -51,15 +52,22 @@ (re-frame/reg-sub ::filter-params + :<- [::settled-filters] :<- [::filters] - (fn [filters] - {:vendor-id (:id (:vendor filters)) - :date-range (:date-range filters) - :amount-gte (:amount-gte (:settled (:amount-range filters))) - :amount-lte (:amount-lte (:settled (:amount-range filters))) - :check-number-like (:settled (:check-number-like filters)) - :invoice-number (:settled (:invoice-number filters))})) + (fn [[settled-filters filters]] + (let [filters (or settled-filters filters)] + {:vendor-id (:id (:vendor filters)) + :date-range (:date-range filters) + :amount-gte (:amount-gte (:amount-range filters)) + :amount-lte (:amount-lte (:amount-range filters)) + :check-number-like (:check-number-like filters) + :invoice-number (:invoice-number 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 @@ -68,72 +76,23 @@ [which val] (if (= 3 (count params)) [(into [a] b) c] [[a] b])] - {:db (assoc-in db (into [::filters] which) val)}))) - -(re-frame/reg-event-fx - ::check-number-like-settled - [(re-frame/path [::filters :check-number-like])] - (fn [{:keys [db]} [_ description]] - {:db (assoc db :settled description) - :dispatch [::filter-changed :check-number-like [:settled] description]})) - -(re-frame/reg-event-fx - ::invoice-number-settled - [(re-frame/path [::filters :invoice-number])] - (fn [{:keys [db]} [_ description]] - {:db (assoc db :settled description) - :dispatch [::filter-changed :invoice-number [:settled] description]})) - -(re-frame/reg-event-fx - ::amount-range-settled - [(re-frame/path [::filters :amount-range])] - (fn [{:keys [db]} [_ which value]] - {:db (assoc-in db [:settled which] value) - :dispatch [::filter-changed :amount-range [:settled] (assoc (:settled db) which value)]})) - -(re-frame/reg-event-fx - ::check-number-like-changed - [(re-frame/path [::filters :check-number-like])] - (fn [{:keys [db]} [_ description]] - {:dispatch-debounce - {:event [::check-number-like-settled description] - :time 500 - :key ::check-number-like} - :db (assoc db :raw description)})) - -(re-frame/reg-event-fx - ::invoice-number-changed - [(re-frame/path [::filters :invoice-number])] - (fn [{:keys [db]} [_ description]] - {:dispatch-debounce - {:event [::invoice-number-settled description] - :time 500 - :key ::invoice-number} - :db (assoc db :raw description)})) - -(re-frame/reg-event-fx - ::amount-range-changed - [(re-frame/path [::filters :amount-range])] - (fn [{:keys [db]} [_ [which] value]] - {:dispatch-debounce - {:event [::amount-range-settled which value] - :time 500 - :key ::amount-range} - :db (assoc-in db [:raw which] value)})) + {:db (assoc-in db (into [::filters] which) val) + :dispatch-debounce + {:event [::filters-settled] + :time 800 + :key ::filters}}))) (defn check-number-filter [] [:div.field [:div.control [:input.input {:placeholder "10001" - :value (:raw @(re-frame/subscribe [::filter :check-number-like])) - :on-change (fn [x] - (re-frame/dispatch [::check-number-like-changed (.. x -target -value) ]))} ]]]) + :value @(re-frame/subscribe [::filter :check-number-like]) + :on-change (dispatch-value-change [::filter-changed :check-number-like])} ]]]) (defn invoice-number-filter [] [:div.field [:div.control [:input.input {:placeholder "SJ-12345" - :value (:raw @(re-frame/subscribe [::filter :invoice-number])) - :on-change (fn [x] - (re-frame/dispatch [::invoice-number-changed (.. x -target -value) ]))} ]]]) + :value @(re-frame/subscribe [::filter :invoice-number]) + :on-change (dispatch-value-change [::filter-changed :invoice-number])} ]]]) (defn side-bar [] (let [ap @(re-frame/subscribe [::subs/active-page]) @@ -156,10 +115,9 @@ [:p.menu-label "Amount"] [:div - (println (:raw @(re-frame/subscribe [::filter :amount-range]))) [number-filter - {:on-change-event [::amount-range-changed] - :value (:raw @(re-frame/subscribe [::filter :amount-range]))}]] + {:on-change-event [::filter-changed :amount-range] + :value @(re-frame/subscribe [::filter :amount-range])}]] [:p.menu-label "Check #"] [:div [check-number-filter]] diff --git a/src/cljs/auto_ap/views/pages/transactions.cljs b/src/cljs/auto_ap/views/pages/transactions.cljs index b2395540..1a7f5578 100644 --- a/src/cljs/auto_ap/views/pages/transactions.cljs +++ b/src/cljs/auto_ap/views/pages/transactions.cljs @@ -82,7 +82,8 @@ :total :start :end]]]} - :on-success [::received]}})) + :on-success [::received]} + :set-uri-params (dissoc params :status :client-id)})) (re-frame/reg-event-fx ::unapprove-all @@ -106,7 +107,7 @@ (re-frame/reg-event-fx ::unmounted (fn [{:keys [db]} _] - {:db (dissoc db ::last-params ::table/table-params ::side-bar/filters ::transaction-page)})) + {:db (dissoc db ::last-params ::table/table-params ::side-bar/filters ::side-bar/settled-filters ::transaction-page)})) (re-frame/reg-event-db ::received diff --git a/src/cljs/auto_ap/views/pages/transactions/side_bar.cljs b/src/cljs/auto_ap/views/pages/transactions/side_bar.cljs index 9860c055..f2a3ea5b 100644 --- a/src/cljs/auto_ap/views/pages/transactions/side_bar.cljs +++ b/src/cljs/auto_ap/views/pages/transactions/side_bar.cljs @@ -1,7 +1,7 @@ (ns auto-ap.views.pages.transactions.side-bar (:require [auto-ap.routes :as routes] [auto-ap.subs :as subs] - [auto-ap.views.utils :refer [active-when]] + [auto-ap.views.utils :refer [active-when dispatch-value-change]] [auto-ap.views.components.date-range-filter :refer [date-range-filter]] [auto-ap.views.components.number-filter :refer [number-filter]] [auto-ap.views.components.bank-account-filter :refer [bank-account-filter]] @@ -9,33 +9,72 @@ [bidi.bidi :as bidi] [re-frame.core :as re-frame])) (re-frame/reg-sub - ::filters + ::specific-filters (fn [db ] (::filters db {}))) +(re-frame/reg-sub + ::filters + :<- [::specific-filters] + :<- [::subs/vendors-by-id] + :<- [::subs/bank-accounts-by-id] + :<- [::subs/query-params] + (fn [[specific-filters vendors-by-id bank-accounts-by-id query-params] ] + + + (let [url-filters (-> query-params + (select-keys #{:vendor-id + :bank-account-id + :date-range + :description + :amount-gte + :amount-lte})) + 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...")}) + :amount-range {:amount-gte (:amount-gte url-filters) + :amount-lte (:amount-lte url-filters)} + :description (:description url-filters) + :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 + ::settled-filters + (fn [db ] + (::settled-filters db))) + (re-frame/reg-sub ::filter-params + :<- [::settled-filters] :<- [::filters] :<- [::subs/active-page] - (fn [[filters ap]] - {:vendor-id (:id (:vendor filters)) - :date-range (:date-range filters) - :bank-account-id (:id (:bank-account filters)) - :amount-gte (:amount-gte (:settled (:amount-range filters))) - :amount-lte (:amount-lte (:settled (:amount-range filters))) - :description (:settled (:description filters)) - :approval-status (condp = ap - :transactions nil - :unapproved-transactions :unapproved - :requires-feedback-transactions :requires-feedback - :excluded-transactions :excluded - :approved-transactions :approved)})) + (fn [[settled-filters filters ap]] + (let [filters (or settled-filters filters)] + {:vendor-id (:id (:vendor filters)) + :date-range (:date-range filters) + :bank-account-id (:id (:bank-account filters)) + :amount-gte (:amount-gte (:amount-range filters)) + :amount-lte (:amount-lte (:amount-range filters)) + :description (:description filters) + :approval-status (condp = ap + :transactions nil + :unapproved-transactions :unapproved + :requires-feedback-transactions :requires-feedback + :excluded-transactions :excluded + :approved-transactions :approved)}))) +(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 @@ -45,42 +84,11 @@ [which val] (if (= 3 (count params)) [(into [a] b) c] [[a] b])] - {:db (assoc-in db (into [::filters] which) val)}))) - -(re-frame/reg-event-fx - ::description-settled - [(re-frame/path [::filters :description])] - (fn [{:keys [db]} [_ description]] - {:db (assoc db :settled description) - :dispatch [::filter-changed :description [:settled] description]})) - - -(re-frame/reg-event-fx - ::description-changed - [(re-frame/path [::filters :description])] - (fn [{:keys [db]} [_ description]] - {:dispatch-debounce - {:event [::description-settled description] - :time 500 - :key ::description} - :db (assoc db :raw description)})) - -(re-frame/reg-event-fx - ::amount-range-settled - [(re-frame/path [::filters :amount-range])] - (fn [{:keys [db]} [_ which value]] - {:db (assoc-in db [:settled which] value) - :dispatch [::filter-changed :amount-range [:settled] (assoc (:settled db) which value)]})) - -(re-frame/reg-event-fx - ::amount-range-changed - [(re-frame/path [::filters :amount-range])] - (fn [{:keys [db]} [_ [which] value]] - {:dispatch-debounce - {:event [::amount-range-settled which value] - :time 500 - :key ::amount-range} - :db (assoc-in db [:raw which] value)})) + {:db (assoc-in db (into [::filters] which) val) + :dispatch-debounce + {:event [::filters-settled] + :time 800 + :key ::filters}}))) (defn side-bar [] (let [ap @(re-frame/subscribe [::subs/active-page]) @@ -136,8 +144,8 @@ [:p.menu-label "Amount"] [:div [number-filter - {:on-change-event [::amount-range-changed] - :value (:raw @(re-frame/subscribe [::filter :amount-range]))}]] + {:on-change-event [::filter-changed :amount-range] + :value @(re-frame/subscribe [::filter :amount-range])}]] [:p.menu-label "Vendor"] [:div @@ -151,7 +159,6 @@ [:div [:div.field [:div.control [:input.input {:placeholder "CHECK 123 ABC" - :value (:raw @(re-frame/subscribe [::filter :description])) - :on-change (fn [e] - (re-frame/dispatch [::description-changed (.. e -target -value) ]))} ]]]]])) + :value @(re-frame/subscribe [::filter :description]) + :on-change (dispatch-value-change [::filter-changed :description])} ]]]]])) diff --git a/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs b/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs index 0ab55eb0..47f26d5a 100644 --- a/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs +++ b/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs @@ -38,7 +38,13 @@ (re-frame/reg-sub ::invoice-page (fn [db] - (-> db ::invoice-page))) + (-> (::invoice-page db) + (update :invoices + (fn [is] + (mapv + (fn [i] + (assoc i :checkable? (not (:automatically-paid-when-due i)))) + is)))))) (re-frame/reg-sub ::invoice @@ -112,8 +118,7 @@ (re-frame/reg-event-fx ::unmounted (fn [{:keys [db]} _] - (println "UNMOUNTING?") - {:db (dissoc db ::invoice-page ::table/table-params ::side-bar/filters ::last-params)})) + {:db (dissoc db ::invoice-page ::table/table-params ::side-bar/filters ::side-bar/settled-filters ::last-params)})) (re-frame/reg-event-db ::received