diff --git a/src/clj/auto_ap/datomic/vendors.clj b/src/clj/auto_ap/datomic/vendors.clj index 09899c38..0e3c7bed 100644 --- a/src/clj/auto_ap/datomic/vendors.clj +++ b/src/clj/auto_ap/datomic/vendors.clj @@ -1,8 +1,10 @@ (ns auto-ap.datomic.vendors - (:require [datomic.api :as d] - [auto-ap.graphql.utils :refer [limited-clients ]] + (:require + [auto-ap.datomic :refer [conn merge-query uri add-sorter-fields apply-pagination merge-query apply-sort-3]] + [auto-ap.graphql.utils :refer [limited-clients]] + [clojure.string :as str] + [datomic.api :as d])) - [auto-ap.datomic :refer [uri conn merge-query]])) (defn <-datomic [a] (cond-> a (:vendor/legal-entity-tin-type a) (update :vendor/legal-entity-tin-type :db/ident) @@ -58,6 +60,30 @@ (update usages v (fnil conj []) {:client-id c :count cnt})) {}))) +(defn raw-graphql-ids [db args] + (let [query (cond-> {:query {:find [] + :in ['$] + :where []} + :args [db]} + (:sort args) (add-sorter-fields {"name" ['[?e :vendor/name ?sort-name]]} + args) + + (not (str/blank? (:name-like args))) + (merge-query {:query {:in ['?name-like] + :where ['[?e :vendor/name ?n] + '[(re-find ?name-like ?n)]]} + :args [(re-pattern (str "(?i)" (:name-like args)))]}) + + true + (merge-query {:query {:find ['?e] + :where ['[?e :vendor/name]]}}))] + + + (cond->> query + true (d/query) + true (apply-sort-3 args) + true (apply-pagination args)))) + (defn trim-usage [v limited-clients] (->> (if limited-clients (update v :usage (fn [usages] @@ -73,17 +99,23 @@ )) +(defn graphql-results [ids db args] + (let [results (->> (d/pull-many db default-read ids) + (group-by :db/id)) + vendors (->> ids + (map results) + (map first) + (map #(cleanse (:id args) %)) + (map <-datomic))] + vendors)) + (defn get-graphql [args] - (->> (cond-> {:query {:find [(list 'pull '?e default-read)] - :in ['$] - :where ['[?e :vendor/name]]} - :args [(d/db (d/connect uri))]}) - (d/query) - (map first) - (map #(cleanse (:id args) %)) - (map <-datomic) - (map #(trim-usage % (limited-clients (:id args)))) - #_(map #(assoc % :usage (get usages (:db/id %)))))) + (let [db (d/db conn) + {ids-to-retrieve :ids matching-count :count} (raw-graphql-ids db args)] + [(->> (graphql-results ids-to-retrieve db args)) + matching-count]) + + ) (defn get-graphql-by-id [args id] (->> (cond-> {:query {:find [(list 'pull '?e default-read)] diff --git a/src/clj/auto_ap/graphql.clj b/src/clj/auto_ap/graphql.clj index 20192cdb..60f9b147 100644 --- a/src/clj/auto_ap/graphql.clj +++ b/src/clj/auto_ap/graphql.clj @@ -294,11 +294,17 @@ :sales_order_total {:type :money} :sales_order_tax {:type :money}}} + :vendor_page {:fields {:vendors {:type '(list :vendor)} + :count {:type 'Int} + :total {:type 'Int} + :start {:type 'Int} + :end {:type 'Int}}} + :reminder_page {:fields {:reminders {:type '(list :reminder)} - :count {:type 'Int} - :total {:type 'Int} - :start {:type 'Int} - :end {:type 'Int}}} + :count {:type 'Int} + :total {:type 'Int} + :start {:type 'Int} + :end {:type 'Int}}} :check_result {:fields {:invoices {:type '(list :invoice)} :pdf_url {:type 'String}}} @@ -398,9 +404,13 @@ - :vendor {:type '(list :vendor) + :vendor {:type :vendor_page + :args {:name_like {:type 'String} + :start {:type 'Int} + :per_page {:type 'Int} + :sort {:type '(list :sort_item)}} :resolve :get-vendor} - :user {:type '(list :user) + :user {:type '(list :user) :resolve :get-user} :vendor_by_id {:type :vendor :args {:id {:type :id}} @@ -708,7 +718,7 @@ '[(get-else $ ?je :journal-entry-line/debit 0.0) ?debit] '[(get-else $ ?je :journal-entry-line/credit 0.0) ?credit]]} :args [(d/db (d/connect uri)) client_id]})) - bills-due-soon (d/query {:query {:find '[?due ?outstanding ?invoice-number ?vendor-id] + bills-due-soon (d/query {:query {:find '[?due ?outstanding ?invoice-number ?vendor-id ?vendor-name] :in '[$ ?client ?due-before] :where ['[?i :invoice/client ?client] '[?i :invoice/status :invoice-status/unpaid] @@ -716,7 +726,8 @@ '[(<= ?due ?due-before)] '[?i :invoice/outstanding-balance ?outstanding] '[?i :invoice/invoice-number ?invoice-number] - '[?i :invoice/vendor ?vendor-id]]} + '[?i :invoice/vendor ?vendor-id] + '[?vendor-id :vendor/name ?vendor-name]]} :args [(d/db (d/connect uri)) client_id (coerce/to-date (t/plus (time/local-now) (t/days 180)))]}) outstanding-checks (reduce + @@ -754,10 +765,10 @@ {:beginning_balance total-cash :outstanding_payments outstanding-checks - :invoices_due_soon (mapv (fn [[due outstanding invoice-number vendor-id]] + :invoices_due_soon (mapv (fn [[due outstanding invoice-number vendor-id vendor-name]] {:due (coerce/to-date-time due) :invoice_number invoice-number - :vendor {:id vendor-id} + :vendor {:id vendor-id :name vendor-name} :outstanding_balance outstanding}) bills-due-soon) :upcoming_credits (into (mapv diff --git a/src/clj/auto_ap/graphql/transactions.clj b/src/clj/auto_ap/graphql/transactions.clj index ed234116..91e8c19b 100644 --- a/src/clj/auto_ap/graphql/transactions.clj +++ b/src/clj/auto_ap/graphql/transactions.clj @@ -134,13 +134,18 @@ (defn bulk-code-transactions [context args _] (assert-admin (:id context)) + (when-not (:client_id args) + (throw (ex-info "Client is required" + {:validation-error "client is required"}))) (let [args (assoc args :id (:id context)) locations (:client/locations (d/pull (d/db conn) [:client/locations] - (:client_id (:filters args)))) + (:client_id args))) all-ids (all-ids-not-locked (get-ids-matching-filters args)) transactions (d/pull-many (d/db conn) '[:db/id :transaction/amount] (vec all-ids)) account-total (reduce + 0 (map (fn [x] (:percentage x)) (:accounts args)))] + (log/info "client is" locations) + (when (and (seq (:accounts args)) @@ -149,14 +154,13 @@ (throw (ex-info error {:validation-error error})))) (doseq [a (:accounts args) - :let [{:keys [:account/location :account/name]} (d/entity (d/db conn) (:account_id a)) - client (d/entity (d/db conn) (:client_id (:filters args)))]] + :let [{:keys [:account/location :account/name]} (d/entity (d/db conn) (:account_id a))]] (when (and location (not= location (:location a))) (let [err (str "Account " name " uses location " (:location a) ", but is supposed to be " location)] (throw (ex-info err {:validation-error err}) ))) (when (and (not location) - (not (get (into #{"Shared"} (:client/locations client)) + (not (get (into #{"Shared"} locations) (:location a)))) (let [err (str "Account " name " uses location " (:location a) ", but doesn't belong to the client.")] (throw (ex-info err {:validation-error err}) )))) @@ -599,6 +603,7 @@ :resolve :mutation/bulk-change-transaction-status} :bulk_code_transactions {:type :message :args {:filters {:type :transaction_filters} + :client_id {:type :id} :vendor {:type :id} :approval_status {:type :transaction_approval_status} :accounts {:type '(list :edit_percentage_account)} diff --git a/src/clj/auto_ap/graphql/vendors.clj b/src/clj/auto_ap/graphql/vendors.clj index 037d3e09..62820f8f 100644 --- a/src/clj/auto_ap/graphql/vendors.clj +++ b/src/clj/auto_ap/graphql/vendors.clj @@ -1,13 +1,11 @@ (ns auto-ap.graphql.vendors - (:require [auto-ap.graphql.utils :refer [->graphql assert-can-see-client assert-admin is-admin? enum->keyword]] - [auto-ap.datomic.vendors :as d-vendors] - [auto-ap.time :refer [parse iso-date]] - [datomic.api :as d] - [auto-ap.datomic :refer [uri remove-nils audit-transact conn]] - [clj-time.coerce :as coerce] - [clojure.set :as set] - [clojure.tools.logging :as log])) - + (:require + [auto-ap.datomic :refer [audit-transact conn remove-nils]] + [auto-ap.datomic.vendors :as d-vendors] + [auto-ap.graphql.utils + :refer [->graphql <-graphql assert-admin enum->keyword is-admin? result->page]] + [clojure.tools.logging :as log] + [datomic.api :as d])) (defn upsert-vendor [context {{:keys [id name hidden terms code print_as primary_contact secondary_contact address default_account_id invoice_reminder_schedule schedule_payment_dom terms_overrides account_overrides] :as in} :vendor} value] (when id @@ -114,10 +112,16 @@ (audit-transact transaction (:id context)) to)) -(defn get-graphql [context args value] +#_(defn get-graphql [context args value] (->graphql (d-vendors/get-graphql (assoc args :id (:id context))))) +(defn get-graphql [context args _] + (assert-admin (:id context)) + (let [args (assoc args :id (:id context)) + [vendors vendors-count ] (d-vendors/get-graphql (<-graphql args))] + (result->page vendors vendors-count :vendors args))) + (defn get-by-id [context args value] (->graphql (d-vendors/get-graphql-by-id (assoc args :id (:id context)) diff --git a/src/cljs/auto_ap/events.cljs b/src/cljs/auto_ap/events.cljs index 837dcb62..8ec5dd6d 100644 --- a/src/cljs/auto_ap/events.cljs +++ b/src/cljs/auto_ap/events.cljs @@ -13,20 +13,6 @@ (defn jwt->data [token] (js->clj (.parse js/JSON (b64/decodeString (second (str/split token #"\." )))))) -(def vendor-query - [:id :name :hidden :terms [:default-account [:name :id :location]] - [:account-overrides [[:client [:id :name]] :id [:account [:id :numeric-code :name]]]] - [:automatically-paid-when-due [:id :name]] - [:terms-overrides [[:client [:id :name]] :id :terms]] - [:schedule-payment-dom [[:client [:id :name]] :id :dom]] - [:usage [:client-id :count]] - [:primary-contact [:name :phone :email :id]] - [:secondary-contact [:id :name :phone :email]] - :print-as :invoice-reminder-schedule :code - :legal-entity-first-name :legal-entity-middle-name :legal-entity-last-name - :legal-entity-tin :legal-entity-tin-type - :legal-entity-1099-type - [:address [:street1 :street2 :city :state :zip]]]) (defn client-query [token] (cond-> [:id :name :signature-file :code :email :matches :week-a-debits :week-a-credits :week-b-debits :week-b-credits :locations :locked-until :square-auth-token @@ -45,7 +31,7 @@ (re-frame/reg-event-fx ::initialize-db - (fn [{:keys [db]} [_ token]] + (fn [{:keys [_]} [_ token]] (let [handler (:handler (bidi/match-route routes/routes (.. js/window -location -pathname)))] (cond (= :login handler) @@ -79,8 +65,7 @@ :query-obj {:venia/queries [[:client (client-query token)] - [:vendor - vendor-query] + [:accounts [:numeric-code :location :name :type :account_set :applicability :id [:client-overrides [:name :id [:client [:name :id]]]]]]]} :on-success [::received-initial] :on-error [::failed-initial]}})))) @@ -97,8 +82,7 @@ {:graphql {:token token :query-obj {:venia/queries [[:client (client-query token)] - [:vendor - vendor-query] + [:accounts [:numeric-code :name :location :type :account_set :applicability :id [:client-overrides [:name [:client [:name :id]]]]]]]} :on-success [::received-initial] @@ -109,11 +93,10 @@ (re-frame/reg-event-fx ::received-initial - (fn [{:keys [db]} [_ {accounts :accounts clients :client vendors :vendor :as x}]] + (fn [{:keys [db]} [_ {accounts :accounts clients :client}]] {:db (-> db (assoc :clients (by :id clients) ) - (assoc :vendors (by :id vendors) ) (assoc :is-initial-loading? false) (assoc :accounts accounts ) (assoc :client (or (when (= 1 (count clients)) (->> clients first :id )) @@ -178,36 +161,6 @@ :auto-ap.forms/forms nil) (auto-ap.views.pages.data-page/dispose-all))}))) -(re-frame/reg-event-db - ::imported-invoices - (fn [db [_ new-invoices]] - (assoc-in db [:invoices :pending] new-invoices))) - -(re-frame/reg-event-fx - ::view-pending-invoices - (fn [cofx []] - {:db (assoc-in (:db cofx) [:status :loading] true) - :graphql {:token (-> cofx :db :user) - :query-obj {:venia/queries [[:invoice - {:imported false :client_id (:id @(re-frame/subscribe [::subs/client]))} - [:id :total :invoice-number :date [:vendor [:name :id]] [:client [:name :id]]]]]} - - :on-success [::received-invoices :pending]}})) - -(re-frame/reg-event-fx - ::view-unpaid-invoices - (fn [cofx []] - {:db (assoc-in (:db cofx) [:status :loading] true) - :graphql {:token (-> cofx :db :user) - :query-obj {:venia/queries [[:invoice - {:imported true :client_id (:id @(re-frame/subscribe [::subs/client]))} - [:id :total :invoice-number :date [:vendor [:name :id]] [:client [:name :id]]]]]} - :on-success [::received-invoices :unpaid]}})) - -(re-frame/reg-event-db - ::submitted-new-invoice - (fn [db [_ invoice]] - (assoc db :new-invoice {}))) (re-frame/reg-event-fx ::logout @@ -218,48 +171,6 @@ :redirect (bidi/path-for routes/routes :login) :set-local-storage ["jwt" nil]})) -(re-frame/reg-event-fx - ::submit-new-invoice - (fn [{:keys [db]} [_ invoice]] - {:http {:method :post - :token (-> db :user) - :uri "/api/invoices" - :body (pr-str {:rows [(assoc invoice :imported true)]}) - :headers {"Content-Type" "application/edn"} - :on-success [::submitted-new-invoice]} - :db (assoc-in db [:new-invoice :loading?] true)})) - -(re-frame/reg-event-db - ::received-invoices - (fn [db [_ type result]] - (let [new-invoices (if (:invoice result) - (:invoice result) - result)] - (-> db - (assoc-in [:invoices type] new-invoices) - (assoc-in [:status :loading] false))))) - -(re-frame/reg-event-db - ::change-form-state - (fn [db [_ target value]] - (assoc-in db target value))) - -(re-frame/reg-event-db - ::change-nested-form-state - (fn [db [_ form more value]] - (update-in db form - (fn [x] - (assoc-in x more value))))) - - - -(re-frame/reg-event-db - ::page-failed - (fn [db [_ result]] - (println "Page failure" result) - (assoc db :page-failure result - :status nil))) - (re-frame/reg-event-db ::yodlee-merchants-received diff --git a/src/cljs/auto_ap/subs.cljs b/src/cljs/auto_ap/subs.cljs index f3ddba56..912590ae 100644 --- a/src/cljs/auto_ap/subs.cljs +++ b/src/cljs/auto_ap/subs.cljs @@ -195,102 +195,6 @@ (fn [db] (:user db))) -(re-frame/reg-sub - ::vendors - :<- [::is-admin?] - :<- [::all-vendors] - (fn [[is-admin all-vendors]] - (filter #(or (not (:hidden %)) - is-admin) all-vendors))) - -(re-frame/reg-sub - ::searchable-vendors - :<- [::is-admin?] - :<- [::client] - :<- [::all-vendors] - (fn [[is-admin client all-vendors]] - (cond is-admin - all-vendors - - client - (filter (fn [{:keys [hidden usage]}] - (or (not hidden) - (-> (first (filter #(= (:client-id %) - (:id client)) - usage)) - (:count 0) - (> 0)))) - all-vendors) - - - :else - - - (filter #(not (:hidden %)) all-vendors)))) - -(re-frame/reg-sub - ::searchable-vendors-index - :<- [::searchable-vendors] - (fn [searchable-vendors] - (doto (MiniSearch. #js {:fields #js ["name" "content"] - :storeFields #js ["id" "name" "content" "usage"]}) - (.addAll (clj->js (map (fn [v] {:id (:id v) - :name (:name v) - :content (:name v) - :usage (:usage v)}) - searchable-vendors)))))) - -(re-frame/reg-sub - ::all-vendors-index - :<- [::all-vendors] - (fn [all-vendors] - (doto (MiniSearch. #js {:fields #js ["name" "content"] - :storeFields #js ["id" "name" "content" "usage"]}) - (.addAll (clj->js (map (fn [v] {:id (:id v) - :name (:name v) - :content (:name v) - :usage (:usage v)}) - all-vendors)))))) - -(re-frame/reg-sub - ::all-vendors - (fn [db] - (vals (:vendors db)))) - -(re-frame/reg-sub - ::vendors-by-id - (fn [db] - (:vendors db))) - -(re-frame/reg-sub - ::vendor-default-account - (fn [db [_ v client]] - (let [accounts (accounts-by-id (:accounts db) client) - vendor (if (map? v) - v - (-> (:vendors db) (get v))) - client-override (->> (:account-overrides vendor) - (filter #(= (:id (:client %)) (:id client)) - ) - first - :account - :id) - default-id (:id (:default-account vendor)) - i (or client-override default-id)] - (accounts i)))) - -(re-frame/reg-sub - ::sorted-vendors - :<- [::vendors] - (fn [vendors] - (sort-by :name vendors))) - -(re-frame/reg-sub - ::sorted-all-vendors - :<- [::all-vendors] - (fn [all-vendors] - (sort-by :name all-vendors))) - (re-frame/reg-sub ::admin (fn [db] diff --git a/src/cljs/auto_ap/views/components/vendor_dialog.cljs b/src/cljs/auto_ap/views/components/vendor_dialog.cljs index f8d0e4e4..acbd7ad3 100644 --- a/src/cljs/auto_ap/views/components/vendor_dialog.cljs +++ b/src/cljs/auto_ap/views/components/vendor_dialog.cljs @@ -1,19 +1,24 @@ (ns auto-ap.views.components.vendor-dialog - (:require [re-frame.core :as re-frame] - [auto-ap.views.utils :refer [dispatch-event horizontal-field bind-field with-user with-is-admin? active-when account->match-text]] - [auto-ap.views.components.address :refer [address-field]] - [auto-ap.views.components.typeahead :refer [typeahead-v3]] - [auto-ap.views.components.dropdown :refer [drop-down drop-down-contents]] - [auto-ap.events :as events] - [clj-fuzzy.metrics :refer [jaccard jaro-winkler]] - [clojure.spec.alpha :as s] - [clojure.string :as str] - [auto-ap.entities.vendors :as entity] - [auto-ap.entities.contact :as contact] - [auto-ap.subs :as subs] - [auto-ap.forms :as forms] - [auto-ap.views.components.modal :as modal] - [auto-ap.status :as status])) + (:require + [auto-ap.entities.contact :as contact] + [auto-ap.entities.vendors :as entity] + [auto-ap.forms :as forms] + [auto-ap.status :as status] + [auto-ap.subs :as subs] + [auto-ap.views.components.address :refer [address-field]] + [auto-ap.views.components.modal :as modal] + [auto-ap.views.components.typeahead :refer [typeahead-v3]] + [auto-ap.views.pages.admin.vendors.common :as common] + [auto-ap.views.utils + :refer [account->match-text + bind-field + dispatch-event + horizontal-field + with-is-admin? + with-user]] + [clojure.spec.alpha :as s] + [clojure.string :as str] + [re-frame.core :as re-frame])) (re-frame/reg-sub ::can-submit @@ -28,25 +33,8 @@ (re-frame/reg-event-db ::settled [(forms/in-form ::vendor-form)] - (fn [{:keys [data] :as form} _] - form - #_(let [vendors @(re-frame/subscribe [::subs/vendors]) - text (.toLowerCase (:name data "")) - matching-vendor (when (> (count text) 5) - (->> vendors - (filter #(not= (:id %) (:id data))) - (map :name) - (mapcat - (fn [v] (mapv - (fn [n] [v (jaro-winkler text n ) n text]) - (ngrams v (count text))))) - (filter #(> (second %) 0.9)) - - (map first) - first))] - (if matching-vendor - (assoc form :warning (str "Are you sure you don't mean " matching-vendor "?")) - (dissoc form :warning))))) + (fn [form _] + form)) (re-frame/reg-event-db ::removed-override @@ -83,15 +71,13 @@ (re-frame/reg-event-fx ::save-complete [(forms/triggers-stop ::vendor-form)] - (fn [{:keys [db]} [_ {vendor :upsert-vendor} ]] - {:dispatch [::modal/modal-closed ] - :db (-> db (assoc-in [:vendors (:id vendor)] vendor))})) + (fn [_ [_ _ ]] + {:dispatch [::modal/modal-closed ]})) (re-frame/reg-event-fx ::save [with-user with-is-admin? (forms/triggers-loading ::vendor-form) (forms/in-form ::vendor-form)] (fn [{:keys [user is-admin?] {{:keys [name hidden print-as terms invoice-reminder-schedule primary-contact automatically-paid-when-due schedule-payment-dom secondary-contact address default-account terms-overrides account-overrides id legal-entity-tin legal-entity-tin-type legal-entity-first-name legal-entity-last-name legal-entity-middle-name legal-entity-1099-type] :as data} :data} :db} _] - (println data) (when (s/valid? ::entity/vendor data) { :graphql {:token user @@ -137,7 +123,7 @@ :legal-entity-1099-type (some-> legal-entity-1099-type clojure.core/name not-empty keyword) )) println)} - events/vendor-query]}]} + common/default-read]}]} :on-success [::save-complete]}}))) (defn client-list [{:keys [override-key override-value-key change-event default-key data]} template] @@ -472,7 +458,6 @@ (defn vendor-dialog [{:keys [save-event] }] (let [clients @(re-frame/subscribe [::subs/clients]) - all-vendors @(re-frame/subscribe [::subs/vendors]) {:keys [data error warning] :as f} @(re-frame/subscribe [::forms/form ::vendor-form]) change-event [::changed]] [:div diff --git a/src/cljs/auto_ap/views/pages/admin/accounts/side_bar.cljs b/src/cljs/auto_ap/views/pages/admin/accounts/side_bar.cljs index 592713ec..6e8fee87 100644 --- a/src/cljs/auto_ap/views/pages/admin/accounts/side_bar.cljs +++ b/src/cljs/auto_ap/views/pages/admin/accounts/side_bar.cljs @@ -13,9 +13,8 @@ (re-frame/reg-sub ::filters :<- [::specific-filters] - :<- [::subs/vendors-by-id] :<- [::subs/query-params] - (fn [[specific-filters vendors-by-id query-params] ] + (fn [[specific-filters query-params] ] (let [url-filters (-> query-params (select-keys #{:name-like :code-like}) (update :name-like #(some-> % str)) diff --git a/src/cljs/auto_ap/views/pages/admin/rules.cljs b/src/cljs/auto_ap/views/pages/admin/rules.cljs index e2081d54..fbf5e642 100644 --- a/src/cljs/auto_ap/views/pages/admin/rules.cljs +++ b/src/cljs/auto_ap/views/pages/admin/rules.cljs @@ -1,26 +1,22 @@ (ns auto-ap.views.pages.admin.rules - (:require [auto-ap.forms :as forms] - [auto-ap.subs :as subs] - [auto-ap.views.components.admin.side-bar :refer [admin-side-bar]] - [auto-ap.views.pages.admin.rules.side-bar :as side-bar] - [auto-ap.views.components.layouts :refer [appearing-side-bar side-bar-layout]] - [auto-ap.views.pages.admin.rules.table :as table] - [auto-ap.views.pages.admin.rules.results-modal :as results-modal] - [auto-ap.views.pages.admin.rules.form :as form] - [auto-ap.views.pages.admin.rules.common :refer [default-read]] - [auto-ap.views.utils :refer [dispatch-event with-user]] - [vimsical.re-frame.cofx.inject :as inject] - [vimsical.re-frame.fx.track :as track] - [auto-ap.events :as events] - [auto-ap.utils :refer [replace-by merge-by]] - [re-frame.core :as re-frame] - [auto-ap.status :as status] - [auto-ap.effects.forward :as forward] - [auto-ap.views.pages.data-page :as data-page] - [clojure.set :as set] - [auto-ap.views.components.buttons :as buttons])) - - + (:require + [auto-ap.effects.forward :as forward] + [auto-ap.events :as events] + [auto-ap.forms :as forms] + [auto-ap.subs :as subs] + [auto-ap.views.components.admin.side-bar :refer [admin-side-bar]] + [auto-ap.views.components.buttons :as buttons] + [auto-ap.views.components.layouts + :refer [appearing-side-bar side-bar-layout]] + [auto-ap.views.pages.admin.rules.common :refer [default-read]] + [auto-ap.views.pages.admin.rules.form :as form] + [auto-ap.views.pages.admin.rules.side-bar :as side-bar] + [auto-ap.views.pages.admin.rules.table :as table] + [auto-ap.views.pages.data-page :as data-page] + [auto-ap.views.utils :refer [dispatch-event with-user]] + [clojure.set :as set] + [re-frame.core :as re-frame] + [vimsical.re-frame.fx.track :as track])) ;; EVENTS @@ -29,7 +25,7 @@ (re-frame/reg-event-fx ::params-change [with-user ] - (fn [{:keys [db user] :as cofx} [_ params]] + (fn [{:keys [user]} [_ params]] {:graphql {:token user :owns-state {:single [::data-page/page ::page]} :query-obj {:venia/queries [{:query/data [:transaction_rule_page @@ -52,13 +48,13 @@ (re-frame/reg-event-fx ::new-rule-clicked - (fn [{:keys [db]} _] + (fn [_ _] {:dispatch [::form/adding {:client @(re-frame/subscribe [::subs/client])}]})) (re-frame/reg-event-fx ::mounted - (fn [{:keys [db]}] + (fn [_] {:dispatch-n [[::events/yodlee-merchants-needed]] ::forward/register [{:id ::page :events #{::form/updated} @@ -75,7 +71,7 @@ (re-frame/reg-event-fx ::unmounted - (fn [{:keys [db]}] + (fn [_] {:dispatch [::data-page/dispose ::page] ::forward/dispose [{:id ::page} {:id ::deleted-transaction-rule}] @@ -85,8 +81,7 @@ (def rules-content (with-meta (fn [] - (let [current-client @(re-frame/subscribe [::subs/client]) - user @(re-frame/subscribe [::subs/user])] + (let [user @(re-frame/subscribe [::subs/user])] [:div [:h1.title "Transaction Rules"] (when (= "admin" (:user/role user)) diff --git a/src/cljs/auto_ap/views/pages/admin/rules/table.cljs b/src/cljs/auto_ap/views/pages/admin/rules/table.cljs index f3265b44..509522ca 100644 --- a/src/cljs/auto_ap/views/pages/admin/rules/table.cljs +++ b/src/cljs/auto_ap/views/pages/admin/rules/table.cljs @@ -1,20 +1,17 @@ (ns auto-ap.views.pages.admin.rules.table - (:require [auto-ap.subs :as subs] - [auto-ap.views.utils :refer [dispatch-event ->$ with-user action-cell-width]] - [auto-ap.views.pages.admin.rules.form :as form] - [auto-ap.views.components.paginator :refer [paginator]] - [auto-ap.views.components.sort-by-list :refer [sort-by-list]] - [auto-ap.views.pages.admin.rules.results-modal :as results-modal] - [auto-ap.views.components.sorter :refer [sorted-column toggle-sort-by sort-icon]] - [auto-ap.views.components.buttons :as buttons] - [auto-ap.views.components.grid :as grid] - [auto-ap.events :as events] - [auto-ap.status :as status] - [re-frame.core :as re-frame] - [reagent.core :as reagent] - [reagent.core :as r] - [auto-ap.views.components.modal :as modal] - [auto-ap.views.pages.data-page :as data-page])) + (:require + [auto-ap.status :as status] + [auto-ap.subs :as subs] + [auto-ap.views.components.buttons :as buttons] + [auto-ap.views.components.grid :as grid] + [auto-ap.views.components.modal :as modal] + [auto-ap.views.pages.admin.rules.form :as form] + [auto-ap.views.pages.admin.rules.results-modal :as results-modal] + [auto-ap.views.pages.data-page :as data-page] + [auto-ap.views.utils + :refer [->$ action-cell-width dispatch-event with-user]] + [re-frame.core :as re-frame] + [reagent.core :as r])) (re-frame/reg-event-fx ::run-clicked diff --git a/src/cljs/auto_ap/views/pages/admin/vendors.cljs b/src/cljs/auto_ap/views/pages/admin/vendors.cljs index 6e77e8e7..6413d4d4 100644 --- a/src/cljs/auto_ap/views/pages/admin/vendors.cljs +++ b/src/cljs/auto_ap/views/pages/admin/vendors.cljs @@ -1,93 +1,76 @@ (ns auto-ap.views.pages.admin.vendors - (:require [re-frame.core :as re-frame] - [reagent.core :as reagent] - [clojure.string :as str] - [auto-ap.views.components.buttons :as buttons] - [auto-ap.views.pages.admin.vendors.side-bar :as side-bar] - [auto-ap.subs :as subs] - [auto-ap.events :as events] - [auto-ap.forms :as forms] - [auto-ap.utils :refer [by]] - [auto-ap.entities.vendors :as entity] - [auto-ap.views.components.address :refer [address-field]] - [auto-ap.views.components.grid :as grid] - [auto-ap.views.components.admin.side-bar :refer [admin-side-bar]] - [auto-ap.views.components.layouts :refer [side-bar-layout]] - [clojure.spec.alpha :as s] - [auto-ap.views.utils :refer [login-url dispatch-value-change dispatch-event bind-field horizontal-field action-cell-width]] - [auto-ap.views.pages.admin.vendors.table :as table] - [auto-ap.views.pages.admin.vendors.merge-dialog :as merge-dialog] - [cljs.reader :as edn] - [auto-ap.routes :as routes] - [bidi.bidi :as bidi] - [auto-ap.status :as status] - [vimsical.re-frame.fx.track :as track] - [auto-ap.effects.forward :as forward]) - (:require-macros [cljs.core.async.macros :refer [go]] - [auto-ap.entities.vendors :as vendor])) + (:require + [auto-ap.effects.forward :as forward] + [auto-ap.subs :as subs] + [auto-ap.views.components.admin.side-bar :refer [admin-side-bar]] + [auto-ap.views.components.layouts :refer [side-bar-layout]] + [auto-ap.views.pages.admin.vendors.merge-dialog :as merge-dialog] + [auto-ap.views.pages.admin.vendors.side-bar :as side-bar] + [auto-ap.views.pages.admin.vendors.table :as table] + [auto-ap.views.pages.data-page :as data-page] + [auto-ap.views.utils :refer [dispatch-event with-user]] + [clojure.set :as set] + [re-frame.core :as re-frame] + [vimsical.re-frame.fx.track :as track] + [auto-ap.views.components.vendor-dialog :as vendor-dialog])) - -(re-frame/reg-event-fx - ::invalidated - (fn [{:keys [db]}] - {:graphql {:token (:user db) - :owns-state {:single ::vendor-page} - :query-obj {:venia/queries [[:vendor events/vendor-query]]} - :on-success [::received-vendors]}})) - -(re-frame/reg-event-fx - ::mounted - (fn [{:keys [db]} _] - {:dispatch [::invalidated] - ::track/register {:id ::params - :subscription [::params] - :event-fn (fn [params] [::params-change params])} - ::forward/register {:id ::merge-complete - :events #{::merge-dialog/complete} - :event-fn (fn [_] - [::invalidated])}})) - -(re-frame/reg-event-db - ::received-vendors - (fn [db [_ vendors]] - (assoc db :vendors (by :id (:vendor vendors ))))) - - -(re-frame/reg-event-fx - ::unmounted - (fn [{:keys [db]} _] - {:db (dissoc db ::table/params ::side-bar/filter-params) - ::forward/dispose {:id ::merge-complete} - ::track/dispose {:id ::params}})) - -(re-frame/reg-sub - ::params - :<- [::side-bar/filter-params] - :<- [::table/params] - (fn [[filter-params table-params]] - (cond-> {} - (seq filter-params) (merge filter-params) - (seq table-params) (merge table-params)))) +(def default-read [:id :name :hidden :terms [:default-account [:name :id :location]] + [:account-overrides [[:client [:id :name]] :id [:account [:id :numeric-code :name]]]] + [:automatically-paid-when-due [:id :name]] + [:terms-overrides [[:client [:id :name]] :id :terms]] + [:schedule-payment-dom [[:client [:id :name]] :id :dom]] + [:usage [:client-id :count]] + [:primary-contact [:name :phone :email :id]] + [:secondary-contact [:id :name :phone :email]] + :print-as :invoice-reminder-schedule :code + :legal-entity-first-name :legal-entity-middle-name :legal-entity-last-name + :legal-entity-tin :legal-entity-tin-type + :legal-entity-1099-type + [:address [:street1 :street2 :city :state :zip]]]) (re-frame/reg-event-fx ::params-change - (fn [_ [_ params]] - {:set-uri-params params})) - -(re-frame/reg-sub - ::vendor-page - :<- [::params] - :<- [::subs/sorted-all-vendors] - (fn [[params all-vendors]] - (let [matching-vendors (cond->> all-vendors - (:name-like params) (filter #(str/includes? (str/lower-case (or (:name %) "")) - (str/lower-case (:name-like params)))))] - (assoc (grid/virtual-paginate-controls (:start params ) (:per-page params) matching-vendors) - :data (grid/virtual-paginate (:start params) (:per-page params) matching-vendors))))) - - + [with-user] + (fn [{:keys [user]} [_ params]] + {:graphql {:token user + :owns-state {:single [::data-page/page ::page]} + :query-obj {:venia/queries [{:query/data [:vendor + {:sort (:sort params) + :start (:start params 0) + :per-page (:per-page params) + :name-like (:name-like params)} + [[:vendors default-read] + :total + :start + :end]] + :query/alias :result}]} + :on-success (fn [result] + [::data-page/received ::page + (set/rename-keys (:result result) + {:vendors :data})])}})) +(re-frame/reg-event-fx + ::mounted + (fn [_ _] + {::forward/register [{:id ::merge-complete + :events #{::merge-dialog/complete} + :event-fn (fn [_] + [::params-change {}])} + {:id ::save-complete + :events #{::vendor-dialog/save-complete} + :event-fn (fn [_] + [::params-change {}])}] + ::track/register {:id ::params + :subscription [::data-page/params ::page] + :event-fn (fn [params] + [::params-change params])}})) +(re-frame/reg-event-fx + ::unmounted + (fn [_ _] + {:dispatch [::data-page/dispose ::page] + ::forward/dispose [{:id ::merge-complete} {:id ::save-complete}] + ::track/dispose {:id ::params}})) (defn admin-vendors-content [] [(with-meta @@ -95,17 +78,15 @@ [:div.inbox-messages (when-let [banner (:banner @(re-frame/subscribe [::subs/admin]))] [:div.notification banner]) - (let [vendors (re-frame/subscribe [::subs/vendors]) - editing-vendor (:vendor @(re-frame/subscribe [::subs/admin]))] - [:div - [:h1.title "Vendors"] - [:div.is-pulled-right [:a.button.is-primary.is-outlined {:on-click (dispatch-event [::merge-dialog/show])} "Merge vendors"]] - [table/vendors-table {:page @(re-frame/subscribe [::vendor-page]) - :status @(re-frame/subscribe [::status/single ::vendor-page])}]])]) + [:div + [:h1.title "Vendors"] + [:div.is-pulled-right [:a.button.is-primary.is-outlined {:on-click (dispatch-event [::merge-dialog/show])} "Merge vendors"]] + [table/vendors-table {:id :vendors + :data-page ::page}]]]) {:component-did-mount #(re-frame/dispatch [::mounted]) :component-will-unmount #(re-frame/dispatch-sync [::unmounted])})]) (defn admin-vendors-page [] [side-bar-layout {:side-bar [admin-side-bar {} - [side-bar/vendor-side-bar]] + [side-bar/vendor-side-bar {:data-page ::page}]] :main [admin-vendors-content]}]) diff --git a/src/cljs/auto_ap/views/pages/admin/vendors/common.cljs b/src/cljs/auto_ap/views/pages/admin/vendors/common.cljs new file mode 100644 index 00000000..3aebce41 --- /dev/null +++ b/src/cljs/auto_ap/views/pages/admin/vendors/common.cljs @@ -0,0 +1,15 @@ +(ns auto-ap.views.pages.admin.vendors.common) + +(def default-read [:id :name :hidden :terms [:default-account [:name :id :location]] + [:account-overrides [[:client [:id :name]] :id [:account [:id :numeric-code :name]]]] + [:automatically-paid-when-due [:id :name]] + [:terms-overrides [[:client [:id :name]] :id :terms]] + [:schedule-payment-dom [[:client [:id :name]] :id :dom]] + [:usage [:client-id :count]] + [:primary-contact [:name :phone :email :id]] + [:secondary-contact [:id :name :phone :email]] + :print-as :invoice-reminder-schedule :code + :legal-entity-first-name :legal-entity-middle-name :legal-entity-last-name + :legal-entity-tin :legal-entity-tin-type + :legal-entity-1099-type + [:address [:street1 :street2 :city :state :zip]]]) diff --git a/src/cljs/auto_ap/views/pages/admin/vendors/side_bar.cljs b/src/cljs/auto_ap/views/pages/admin/vendors/side_bar.cljs index dda46698..25a2d5a9 100644 --- a/src/cljs/auto_ap/views/pages/admin/vendors/side_bar.cljs +++ b/src/cljs/auto_ap/views/pages/admin/vendors/side_bar.cljs @@ -2,69 +2,17 @@ (:require [re-frame.core :as re-frame] [auto-ap.subs :as subs] - [auto-ap.views.utils :refer [active-when dispatch-value-change]])) - -(re-frame/reg-sub - ::specific-filters - (fn [db ] - (::filters db nil))) - -(re-frame/reg-sub - ::filters - :<- [::specific-filters] - :<- [::subs/vendors-by-id] - :<- [::subs/query-params] - (fn [[specific-filters vendors-by-id query-params] ] - (let [url-filters (-> query-params - (select-keys #{:name-like}) - (update :name-like #(some-> % str)))] - (merge url-filters specific-filters )))) - -(re-frame/reg-sub - ::filter - :<- [::filters] - (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 [[settled-filters filters ap ]] - (let [filters (or settled-filters filters)] - {:name-like (:name-like 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}}))) + [auto-ap.views.utils :refer [dispatch-value-change]] + [auto-ap.views.pages.data-page :as data-page])) -(defn vendor-side-bar [] +(defn vendor-side-bar [{:keys [data-page]}] [:div [:p.menu-label "Name"] - - [:div.field - [:div.control [:input.input {:placeholder "Harry's Food Products" - :value @(re-frame/subscribe [::filter :name-like]) - :on-change (dispatch-value-change [::filter-changed :name-like])} ]]]]) + [:div + [:div.field + [:div.control [:input.input {:placeholder "HOME DEPOT" + :value @(re-frame/subscribe [::data-page/filter data-page :name-like]) + :on-change (dispatch-value-change [::data-page/filter-changed data-page :name-like])} ]]]]]) diff --git a/src/cljs/auto_ap/views/pages/admin/vendors/table.cljs b/src/cljs/auto_ap/views/pages/admin/vendors/table.cljs index 827e680b..994482f0 100644 --- a/src/cljs/auto_ap/views/pages/admin/vendors/table.cljs +++ b/src/cljs/auto_ap/views/pages/admin/vendors/table.cljs @@ -1,34 +1,21 @@ (ns auto-ap.views.pages.admin.vendors.table - (:require - [re-frame.core :as re-frame] - [reagent.core :as reagent] + (:require [auto-ap.subs :as subs] - [auto-ap.status :as status] - [auto-ap.views.components.vendor-dialog :refer [vendor-dialog] :as vendor-dialog] + [auto-ap.views.components.buttons :as buttons] [auto-ap.views.components.grid :as grid] - [auto-ap.views.utils :refer [login-url dispatch-value-change dispatch-event bind-field horizontal-field action-cell-width]] - [auto-ap.views.components.buttons :as buttons])) + [auto-ap.views.components.vendor-dialog :as vendor-dialog] + [auto-ap.views.pages.data-page :as data-page] + [auto-ap.views.utils :refer [action-cell-width]] + [re-frame.core :as re-frame])) -(re-frame/reg-event-fx - ::params-changed - (fn [{:keys [db]} [_ p]] - {:db (assoc db ::params p)})) - -(re-frame/reg-sub - ::params - (fn [db] - (-> db ::params))) - -(defn vendors-table [{:keys [status page]}] - (let [params @(re-frame/subscribe [::params]) +(defn vendors-table [{:keys [data-page]}] + (let [{:keys [data]} @(re-frame/subscribe [::data-page/page data-page]) accounts @(re-frame/subscribe [::subs/all-accounts-by-id])] + (println "DATA COUNT" (keys data)) - [grid/grid {:status status - :on-params-change (fn [p] - (re-frame/dispatch [::params-changed p])) - :params params + [grid/grid {:data-page data-page :column-count 4} - [grid/controls page] + [grid/controls data] [grid/table {:fullwidth true} [grid/header [grid/row {} @@ -37,7 +24,7 @@ [grid/header-cell {} "Default Account"] [grid/header-cell {:style {:width (action-cell-width 1)}}]]] [grid/body - (for [v (:data page)] + (for [v (:data data)] ^{:key (str (:id v))} [grid/row {:class (:class v) :id (:id v)} [grid/cell {} (:name v) diff --git a/src/cljs/auto_ap/views/pages/home.cljs b/src/cljs/auto_ap/views/pages/home.cljs index 3daefedc..d8cfa285 100644 --- a/src/cljs/auto_ap/views/pages/home.cljs +++ b/src/cljs/auto_ap/views/pages/home.cljs @@ -3,18 +3,17 @@ [auto-ap.subs :as subs] [auto-ap.views.components.grid :as grid] [auto-ap.views.components.layouts :refer [side-bar-layout]] - [auto-ap.views.components.typeahead :refer [typeahead-v3]] + [auto-ap.history :refer [history]] + [cemerick.url :as url] [auto-ap.views.utils :refer [->$ date->str days-until dispatch-event local-now standard]] [bidi.bidi :as bidi] [cljs-time.coerce :as coerce] [cljs-time.core :as t] - [clojure.string :as str] [pushy.core :as pushy] [re-frame.core :as re-frame] [recharts] - [downshift :as ds :refer [useCombobox]] [reagent.core :as r] [react])) @@ -39,7 +38,7 @@ :data data :dataKey "value" :inner-radius 20} - (map (fn [x y] + (map (fn [_ y] ^{:key y} [cell {:key y :fill (colors y)}]) data (range)) ] @@ -57,7 +56,7 @@ (defn make-cash-flow-chart [{:keys [width height data] }] (let [redirect-fn (fn [x] - (pushy/set-token! auto-ap.history/history (str (bidi/path-for routes/routes :unpaid-invoices) "?" (get (js->clj x) "query-params"))) + (pushy/set-token! history (str (bidi/path-for routes/routes :unpaid-invoices) "?" (get (js->clj x) "query-params"))) )] [bar-chart {:width width :height height :data data :fill "#FFFFFF" :stackOffset "sign"} [tool-tip] @@ -161,29 +160,29 @@ (fn [[{:keys [effective-balance credits-yesterday] } :as acc] day] (let [invoices-due-today (invoices-due-soon (date->str (t/plus start-date (t/days day))) 0.0) credits-due-today (upcoming-credits (date->str (t/plus start-date (t/days day))) 0.0) - debits-due-today (upcoming-debits (date->str (t/plus start-date (t/days day))) 0.0)] - (let [today (t/plus start-date (t/days day))] - (conj acc - {:name (date->str today) - :date today - :effective-balance (+ (- effective-balance invoices-due-today ) - debits-due-today - credits-yesterday) - :credits-yesterday credits-due-today - :credits credits-due-today - :debits debits-due-today - :invoices (- invoices-due-today) - :query-params (cemerick.url/map->query {:due-range {:start (date->str today standard) - :end (date->str today standard)}})})))) - (list {:name (date->str start-date) - :date start-date - :effective-balance effective-balance - :invoices (- (invoices-due-soon (date->str start-date) 0.0)) - :credits (upcoming-credits (date->str start-date) 0.0) - :credits-yesterday (upcoming-credits (date->str start-date) 0.0) - :debits (upcoming-debits (date->str start-date) 0.0) + debits-due-today (upcoming-debits (date->str (t/plus start-date (t/days day))) 0.0) + today (t/plus start-date (t/days day))] + (conj acc + {:name (date->str today) + :date today + :effective-balance (+ (- effective-balance invoices-due-today ) + debits-due-today + credits-yesterday) + :credits-yesterday credits-due-today + :credits credits-due-today + :debits debits-due-today + :invoices (- invoices-due-today) + :query-params (url/map->query {:due-range {:start (date->str today standard) + :end (date->str today standard)}})}))) + (list {:name (date->str start-date) + :date start-date + :effective-balance effective-balance + :invoices (- (invoices-due-soon (date->str start-date) 0.0)) + :credits (upcoming-credits (date->str start-date) 0.0) + :credits-yesterday (upcoming-credits (date->str start-date) 0.0) + :debits (upcoming-debits (date->str start-date) 0.0) :outstanding-payments (- outstanding-payments) - :query-params (cemerick.url/map->query {:due-range {:end (date->str start-date standard)}})}) + :query-params (url/map->query {:due-range {:end (date->str start-date standard)}})}) (condp = (:cash-flow-range chart-options) :seven-days (range 1 7) @@ -210,9 +209,8 @@ ::cash-flow-page :<- [::cash-flow-table-params] :<- [::cash-flow-data] - :<- [::subs/vendors-by-id] - (fn [[params cash-flow-data vendors-by-id]] - (let [ {:keys [outstanding-payments invoices-due-soon upcoming-credits upcoming-debits]} cash-flow-data + (fn [[params cash-flow-data]] + (let [ {:keys [invoices-due-soon upcoming-credits upcoming-debits]} cash-flow-data rows (concat (map (fn [c] {:date (:date c) :days-until (days-until (:date c)) @@ -230,7 +228,7 @@ {:date (:due c) :days-until (days-until (:due c)) :amount (:outstanding-balance c) - :name (str (:name (get vendors-by-id (:id (:vendor c)))) " (" (:invoice-number c) ")") + :name (str (:name (:vendor c)) " (" (:invoice-number c) ")") :type "Invoice"}) invoices-due-soon))] (assoc (grid/virtual-paginate-controls (:start params ) (:per-page params) rows) @@ -253,7 +251,7 @@ {:client-id (:id @(re-frame/subscribe [::subs/client]))} [:beginning-balance :outstanding-payments - [:invoices-due-soon [:due :outstanding-balance [:vendor [:id]] :invoice-number]] + [:invoices-due-soon [:due :outstanding-balance [:vendor [:id :name]] :invoice-number]] [:upcoming-credits [:date :amount :identifier]] [:upcoming-debits [:date :amount :identifier]]]]]} :on-success [::received]}})) @@ -300,8 +298,6 @@ (defn home-content [] (let [client-id (-> @(re-frame/subscribe [::subs/client]) :id) - accounts-by-id @(re-frame/subscribe [::subs/accounts-by-id]) - accounts-index @(re-frame/subscribe [::subs/accounts-index]) chart-options @(re-frame/subscribe [::chart-options])] ^{:key client-id} [side-bar-layout {:side-bar [:div diff --git a/src/cljs/auto_ap/views/pages/new_invoice.cljs b/src/cljs/auto_ap/views/pages/new_invoice.cljs deleted file mode 100644 index 3ac28955..00000000 --- a/src/cljs/auto_ap/views/pages/new_invoice.cljs +++ /dev/null @@ -1,75 +0,0 @@ -(ns auto-ap.views.pages.new-invoice - (:require [re-frame.core :as re-frame] - [auto-ap.subs :as subs] - [auto-ap.events :as events])) - -(defn new-invoice-page [] - (let [form-data (re-frame/subscribe [::subs/new-invoice-form])] - [:div - [:form - [:h1.title "New InvoiceR"] - [:div.field - [:label.label "Vendor"] - [:div.control - [:input.input {:type "text" - :auto-focus true - :placeholder "CINTAS" - :value (:vendor @form-data) - :on-change (fn [e] - (re-frame/dispatch [::events/change-form-state - [:new-invoice :vendor] - (.. e -target -value)]))}]]] - [:div.field - [:label.label "Customer"] - [:div.control - [:input.input {:type "text" - :placeholder "Brown Chicken Brown Cow" - :value (:client @form-data) - :on-change (fn [e] - (re-frame/dispatch [::events/change-form-state - [:new-invoice :client] - (.. e -target -value)]))}]]] - [:div.field - [:label.label "Invoice #"] - [:div.control - [:input.input {:type "text" - :placeholder "12345" - :value (:invoice-number @form-data) - :on-change (fn [e] - (re-frame/dispatch [::events/change-form-state - [:new-invoice :invoice-number] - (.. e -target -value)]))}]]] - [:div.field - [:label.label "Date"] - [:div.control - [:input.input {:type "text" - :placeholder "11/11/2011" - :value (:date @form-data) - :on-change (fn [e] - (re-frame/dispatch [::events/change-form-state - [:new-invoice :date] - (.. e -target -value)]))}]]] - [:div.field - [:label.label "Total"] - [:div.control - [:input.input {:type "text" - :placeholder "$14.50" - :value (:total @form-data) - :on-change (fn [e] - (re-frame/dispatch [::events/change-form-state - [:new-invoice :total] - (.. e -target -value)]))}]]] - [:div.control - [:submit.button.is-large.is-primary { - :disabled (if (and (:total @form-data) (:date @form-data) (:client @form-data) (:invoice-number @form-data) - (:vendor @form-data)) - "" - "disabled") - :on-click - (fn [x] - (.preventDefault x) - (re-frame/dispatch [::events/submit-new-invoice @form-data]))} - [:span - (when (:loading? @form-data) - [:i.fa.fa-spin.fa-spinner]) - "Save"]]]]])) diff --git a/src/cljs/auto_ap/views/pages/transactions/bulk_updates.cljs b/src/cljs/auto_ap/views/pages/transactions/bulk_updates.cljs index eefc3955..a8480993 100644 --- a/src/cljs/auto_ap/views/pages/transactions/bulk_updates.cljs +++ b/src/cljs/auto_ap/views/pages/transactions/bulk_updates.cljs @@ -8,13 +8,18 @@ :as expense-accounts-field :refer [expense-accounts-field]] [auto-ap.views.components.modal :as modal] - [auto-ap.views.components.typeahead :refer [typeahead-v3]] + [auto-ap.views.components.typeahead.vendor + :refer [search-backed-typeahead]] + [auto-ap.views.pages.data-page :as data-page] [auto-ap.views.pages.transactions.common :refer [data-params->query-params]] [auto-ap.views.utils :refer [dispatch-event with-user]] [clojure.string :as str] [re-frame.core :as re-frame] - [auto-ap.views.pages.data-page :as data-page])) + [reagent.core :as r] + [vimsical.re-frame.fx.track :as track] + [auto-ap.events :as events] + [vimsical.re-frame.cofx.inject :as inject])) (re-frame/reg-sub ::can-submit @@ -31,8 +36,8 @@ (re-frame/reg-event-fx ::code-selected - [with-user (forms/in-form ::form) ] - (fn [{:keys [user db]} [_ checked]] + [with-user (forms/in-form ::form) (re-frame/inject-cofx ::inject/sub [::subs/client])] + (fn [{:keys [user db] ::subs/keys [client]} [_ checked]] (let [checked-params (get checked "header") specific-transactions (map :id (vals (dissoc checked "header"))) data (:data db)] @@ -43,6 +48,7 @@ :operation/name "BulkCodeTransactions"} :venia/queries [[:bulk-code-transactions {:filters (some-> checked-params data-params->query-params) + :client_id (:id client) :ids specific-transactions :vendor (:id (:vendor data)) :approval-status (:transaction-approval-status data) @@ -67,33 +73,56 @@ ::changed (forms/change-handler ::form (fn [data field value] - (cond (and (= [:vendor] field) + (cond (and (= [:vendor-preferences] field) value) [[:accounts] (expense-accounts-field/default-account (:accounts data) - @(re-frame/subscribe [::subs/vendor-default-account (:id value) (:client data)]) + (:default-account value) (:total data) [])] :else [])))) +(re-frame/reg-event-fx + ::changed-vendor + [(forms/in-form ::form)] + (fn [{{{:keys [client]} :data} :db} [_ vendor]] + (when (and (:id client) (:id vendor)) + {:dispatch [::events/vendor-preferences-requested {:client-id (:id client) + :vendor-id (:id vendor) + :on-success [::changed [:vendor-preferences]] + :on-failure [:hello]}]}))) + +(re-frame/reg-event-fx + ::mounted + (fn [] + {::track/register {:id ::vendor-change + :subscription [::forms/field ::form [:vendor]] + :event-fn (fn [v] + [::changed-vendor v])}})) + +(re-frame/reg-event-fx + ::unmounted + (fn [] + {::track/dispose {:id ::vendor-change}})) + (def code-form (forms/vertical-form {:submit-event [::code-selected] - :change-event [::changed] - :can-submit [::can-submit] - :id ::form})) -(defn form [] + :change-event [::changed] + :can-submit [::can-submit] + :id ::form})) +(defn form-content [_] (let [{:keys [data]} @(re-frame/subscribe [::forms/form ::form]) - {:keys [form-inline field]} code-form - ] + {:keys [form-inline field]} code-form] (form-inline {} [:<> (field "Vendor" - [typeahead-v3 {:entities-by-id @(re-frame/subscribe [::subs/vendors-by-id]) - :entity-index @(re-frame/subscribe [::subs/searchable-vendors-index]) - :entity->text :name - :type "typeahead-v3" - :auto-focus true - :field [:vendor]}]) + [search-backed-typeahead {:search-query (fn [i] + [:search_vendor + {:query i} + [:name :id]]) + :type "typeahead-v3" + :auto-focus true + :field [:vendor]}]) (field "Approval Status" [button-radio @@ -115,6 +144,13 @@ :field [:accounts]}]) {:key (some-> data :vendor :id str)}) ]))) +(defn form [_] + (r/create-class + {:display-name "transaction-bulk-update-form" + :component-did-mount #(re-frame/dispatch [::mounted]) + :component-will-unmount #(re-frame/dispatch [::unmounted]) + :reagent-render (fn [p] + [form-content p])})) (re-frame/reg-event-fx ::code-requested diff --git a/src/cljs/auto_ap/views/pages/transactions/form.cljs b/src/cljs/auto_ap/views/pages/transactions/form.cljs index 2ed439ab..1d31071c 100644 --- a/src/cljs/auto_ap/views/pages/transactions/form.cljs +++ b/src/cljs/auto_ap/views/pages/transactions/form.cljs @@ -1,23 +1,25 @@ (ns auto-ap.views.pages.transactions.form - (:require [auto-ap.forms :as forms] - [auto-ap.status :as status] - [auto-ap.subs :as subs] - [auto-ap.views.components.button-radio :refer [button-radio]] - [auto-ap.views.components.expense-accounts-field - :as - expense-accounts-field - :refer - [expense-accounts-field]] - [auto-ap.views.components.layouts :as layouts] - [auto-ap.views.components.typeahead :refer [typeahead-v3]] - [auto-ap.views.pages.transactions.common :refer [transaction-read]] - [auto-ap.views.utils - :refer - [->$ date->str dispatch-event pretty with-user]] - [clojure.string :as str] - [re-frame.core :as re-frame] - [react :as react] - [reagent.core :as r])) + (:require + [auto-ap.forms :as forms] + [auto-ap.status :as status] + [auto-ap.subs :as subs] + [auto-ap.views.components.button-radio :refer [button-radio]] + [auto-ap.views.components.expense-accounts-field + :as expense-accounts-field + :refer [expense-accounts-field]] + [auto-ap.views.components.layouts :as layouts] + [auto-ap.views.components.typeahead :refer [typeahead-v3]] + [auto-ap.views.components.typeahead.vendor + :refer [search-backed-typeahead]] + [auto-ap.views.pages.transactions.common :refer [transaction-read]] + [auto-ap.views.utils + :refer [->$ date->str dispatch-event pretty with-user]] + [clojure.string :as str] + [re-frame.core :as re-frame] + [react :as react] + [reagent.core :as r] + [vimsical.re-frame.fx.track :as track] + [auto-ap.events :as events])) ;; SUBS (re-frame/reg-sub @@ -76,11 +78,11 @@ (forms/change-handler ::form (fn [data field value] (let [locations @(re-frame/subscribe [::subs/locations-for-client (:id (:client data))])] - (if (and (= [:vendor] field) + (if (and (= [:vendor-preferences] field) value (expense-accounts-field/can-replace-with-default? (:accounts data))) [[:accounts] (expense-accounts-field/default-account (:accounts data) - @(re-frame/subscribe [::subs/vendor-default-account (:id value) (:client data)]) + (:default-account (:vendor-preferences data)) (:amount data) locations)] []))))) @@ -185,17 +187,28 @@ {})) -(re-frame/reg-event-db - ::manual-match - [(forms/in-form ::form)] - (fn [edit-transaction] - (update-in edit-transaction [:data] dissoc :potential-payment-matches))) +(re-frame/reg-event-fx + ::changed-vendor + [(forms/in-form ::form)] + (fn [{{{:keys [client]} :data} :db} [_ vendor]] + (when (and (:id client) (:id vendor)) + {:dispatch [::events/vendor-preferences-requested {:client-id (:id client) + :vendor-id (:id vendor) + :on-success [::changed [:vendor-preferences]] + :on-failure [:hello]}]}))) -(re-frame/reg-event-db - ::transaction-rule-closed - [(forms/in-form ::form)] - (fn [edit-transaction] - (update-in edit-transaction [:data] dissoc :potential-transaction-rule-matches))) +(re-frame/reg-event-fx + ::mounted + (fn [] + {::track/register {:id ::vendor-change + :subscription [::forms/field ::form [:vendor]] + :event-fn (fn [v] + [::changed-vendor v])}})) + +(re-frame/reg-event-fx + ::unmounted + (fn [] + {::track/dispose {:id ::vendor-change}})) ;; VIEWS @@ -324,7 +337,7 @@ [:a {:on-click (fn [] (on-tab-clicked (:key props)))} (:title props)]])))]) -(defn form [_] +(defn form-content [_] [layouts/side-bar {:on-close (dispatch-event [::forms/form-closing ::form])} (let [{:keys [data] } @(re-frame/subscribe [::forms/form ::form]) locations @(re-frame/subscribe [::subs/locations-for-client (:id (:client data))]) @@ -404,14 +417,15 @@ [tab {:title "Details" :key :details} [:div (field "Vendor" - [typeahead-v3 {:entities-by-id @(re-frame/subscribe [::subs/vendors-by-id]) - :entity-index @(re-frame/subscribe [::subs/searchable-vendors-index]) - :entity->text :name - :type "typeahead-v3" - :auto-focus true - :field [:vendor] - :disabled (or (boolean (:payment data)) - should-disable-for-client?)}]) + [search-backed-typeahead {:search-query (fn [i] + [:search_vendor + {:query i} + [:name :id]]) + :type "typeahead-v3" + :auto-focus true + :field [:vendor] + :disabled (or (boolean (:payment data)) + should-disable-for-client?)}]) (with-meta (field nil [expense-accounts-field @@ -442,3 +456,11 @@ (when-not should-disable-for-client? (submit-button "Save"))]]]]) {:key (:id data)}))]) + +(defn form [_] + (r/create-class + {:display-name "transaction-form" + :component-did-mount #(re-frame/dispatch [::mounted]) + :component-will-unmount #(re-frame/dispatch [::unmounted]) + :reagent-render (fn [p] + [form-content p])})) diff --git a/src/cljs/auto_ap/views/pages/transactions/table.cljs b/src/cljs/auto_ap/views/pages/transactions/table.cljs index e1edf714..201a716b 100644 --- a/src/cljs/auto_ap/views/pages/transactions/table.cljs +++ b/src/cljs/auto_ap/views/pages/transactions/table.cljs @@ -40,6 +40,9 @@ :which (:id which)} :query-obj {:venia/queries (cond-> [{:query/data [:potential-payment-matches + {:transaction_id (:id which)} + [:id :memo :check-number [:vendor [:name]]]]} + {:query/data [:potential-payment-matches {:transaction_id (:id which)} [:id :memo :check-number [:vendor [:name]]]]}] (or (= "admin" role) @@ -55,8 +58,7 @@ (into [{:query/data [:potential-transaction-rule-matches {:transaction_id (:id which)} [:id :note]]}]))} - :on-success [::editing-matches-found which] - :on-error [::editing-matches-failed which]}})) + :on-success [::editing-matches-found which]}})) (re-frame/reg-sub ::table-params