From fe4837394323bddb6a0436855b155b6623e54d97 Mon Sep 17 00:00:00 2001 From: Bryce Covert Date: Wed, 17 Nov 2021 21:50:12 -0800 Subject: [PATCH] avoids duplicate invoices atomic, prevents query that causes warnings. --- src/clj/auto_ap/datomic/migrate.clj | 26 +++++++++++- src/clj/auto_ap/routes/invoices.clj | 42 +++++++++---------- .../views/pages/transactions/table.cljs | 35 +++++++++------- src/cljs/auto_ap/views/utils.cljs | 13 ++++++ 4 files changed, 79 insertions(+), 37 deletions(-) diff --git a/src/clj/auto_ap/datomic/migrate.clj b/src/clj/auto_ap/datomic/migrate.clj index fe030f15..007194df 100644 --- a/src/clj/auto_ap/datomic/migrate.clj +++ b/src/clj/auto_ap/datomic/migrate.clj @@ -79,6 +79,24 @@ (seq vs) (conj {:db/id e a vs})))})}]]) + +(defn propose-invoice-fn [conn] + [[{:db/ident :propose-invoice + :db/doc "Adds an invoice if it's not found" + :db/fn (d/function '{:lang "clojure" + :params [db invoice] + :code (let [existing? (boolean (seq (d/query {:query {:find ['?i] + :in ['$ '?invoice-number '?client '?vendor] + :where ['[?i :invoice/invoice-number ?invoice-number] + '[?i :invoice/client ?client] + '[?i :invoice/vendor ?vendor] + '(not [?i :invoice/status :invoice-status/voided]) + ]} + :args [db (:invoice/invoice-number invoice) (:invoice/client invoice) (:invoice/vendor invoice)]})))] + (if existing? + [] + [invoice]))})}]]) + (defn add-include-in-reports [conn] (let [existing-accounts (->> (d/query {:query {:find ['?e] :in ['$] @@ -335,7 +353,13 @@ :db/cardinality :db.cardinality/one}]]} :auto-ap/add-power-user-schema {:txes [[{:db/ident :user-role/power-user}]]} :auto-ap/add-transaction-date-index {:txes [[{:db/ident :transaction/date - :db/index true}]]}} + :db/index true}]]} + :auto-ap/add-invoice-index {:txes [[{:db/ident :invoice/invoice-number + :db/index true}]] + :depends-on [:auto-ap/base-schema]} + + :auto-ap/add-propose-invoice {:txes-fn `propose-invoice-fn + :depends-on [:auto-ap/base-schema]}} diff --git a/src/clj/auto_ap/routes/invoices.clj b/src/clj/auto_ap/routes/invoices.clj index e4d1a01d..cf3e5067 100644 --- a/src/clj/auto_ap/routes/invoices.clj +++ b/src/clj/auto_ap/routes/invoices.clj @@ -182,7 +182,7 @@ :status :payment-status/cleared :date (:invoice/date invoice)})} )] - [invoice payment]))) + [[:propose-invoice invoice] payment]))) (filter identity) (map remove-nils) )) @@ -280,26 +280,26 @@ result :else - (conj result (cond-> (remove-nils #:invoice {:invoice/client (:db/id matching-client) - :invoice/client-identifier customer-identifier - :invoice/vendor (:db/id matching-vendor) - :invoice/invoice-number invoice-number - :invoice/total (Double/parseDouble total) - :invoice/date (to-date date) - :invoice/import-status :import-status/pending - :invoice/outstanding-balance (or existing-outstanding-balance (Double/parseDouble total)) - :invoice/status (or existing-status :invoice-status/unpaid) - :invoice/expense-accounts (when-not existing-id [#:invoice-expense-account {:account (d-vendors/account-for-client-id matching-vendor (:db/id matching-client)) - :location matching-location - :amount (Double/parseDouble total)}]) - :db/id existing-id - }) - (:vendor/terms matching-vendor) (assoc :invoice/due (coerce/to-date - (time/plus date (time/days (d-vendors/terms-for-client-id matching-vendor (:db/id matching-client)))))) - (boolean (automatically-paid-for (:db/id matching-client))) (assoc :invoice/scheduled-payment (coerce/to-date - (time/plus date (time/days (d-vendors/terms-for-client-id matching-vendor (:db/id matching-client)))))) - schedule-payment-dom (assoc :invoice/scheduled-payment (to-date - (next-dom date schedule-payment-dom)))))) + (conj result [:propose-invoice (cond-> (remove-nils #:invoice {:invoice/client (:db/id matching-client) + :invoice/client-identifier customer-identifier + :invoice/vendor (:db/id matching-vendor) + :invoice/invoice-number invoice-number + :invoice/total (Double/parseDouble total) + :invoice/date (to-date date) + :invoice/import-status :import-status/pending + :invoice/outstanding-balance (or existing-outstanding-balance (Double/parseDouble total)) + :invoice/status (or existing-status :invoice-status/unpaid) + :invoice/expense-accounts (when-not existing-id [#:invoice-expense-account {:account (d-vendors/account-for-client-id matching-vendor (:db/id matching-client)) + :location matching-location + :amount (Double/parseDouble total)}]) + :db/id existing-id + }) + (:vendor/terms matching-vendor) (assoc :invoice/due (coerce/to-date + (time/plus date (time/days (d-vendors/terms-for-client-id matching-vendor (:db/id matching-client)))))) + (boolean (automatically-paid-for (:db/id matching-client))) (assoc :invoice/scheduled-payment (coerce/to-date + (time/plus date (time/days (d-vendors/terms-for-client-id matching-vendor (:db/id matching-client)))))) + schedule-payment-dom (assoc :invoice/scheduled-payment (to-date + (next-dom date schedule-payment-dom))))])) )) [] imports)] diff --git a/src/cljs/auto_ap/views/pages/transactions/table.cljs b/src/cljs/auto_ap/views/pages/transactions/table.cljs index d417e0f9..ede317e6 100644 --- a/src/cljs/auto_ap/views/pages/transactions/table.cljs +++ b/src/cljs/auto_ap/views/pages/transactions/table.cljs @@ -8,7 +8,7 @@ [auto-ap.views.pages.transactions.form :as edit] [auto-ap.views.utils :refer - [action-cell-width date->str dispatch-event dispatch-event-with-propagation nf pretty]] + [action-cell-width date->str dispatch-event dispatch-event-with-propagation nf pretty with-role]] [goog.string :as gstring] [re-frame.core :as re-frame] [auto-ap.views.components.buttons :as buttons] @@ -32,24 +32,29 @@ (re-frame/reg-event-fx ::intend-to-edit - (fn [{:keys [db]} [_ which]] + [with-role] + (fn [{:keys [db role]} [_ which]] {:graphql {:token (-> db :user) :owns-state {:multi ::edits :which (:id which)} - :query-obj {:venia/queries (into [{:query/data [:potential-payment-matches - {:transaction_id (:id which)} - [:id :memo :check-number [:vendor [:name]]]]} - {:query/data [:potential-autopay-invoices-matches - {:transaction_id (:id which)} - [:id :invoice-number :total :date :scheduled-payment [:vendor [:name]]]]} - {:query/data [:potential-unpaid-invoices-matches - {:transaction_id (:id which)} - [:id :invoice-number :total :date :scheduled-payment [:vendor [:name]]]]}] - (when @(re-frame/subscribe [::subs/is-admin?]) - [{:query/data [:potential-transaction-rule-matches - {:transaction_id (:id which)} - [:id :note]]}]))} + :query-obj {:venia/queries + (cond-> [{:query/data [:potential-payment-matches + {:transaction_id (:id which)} + [:id :memo :check-number [:vendor [:name]]]]}] + (or (= "admin" role) + (= "power-user" role)) + + (into [{:query/data [:potential-autopay-invoices-matches + {:transaction_id (:id which)} + [:id :invoice-number :total :date :scheduled-payment [:vendor [:name]]]]} + {:query/data [:potential-unpaid-invoices-matches + {:transaction_id (:id which)} + [:id :invoice-number :total :date :scheduled-payment [:vendor [:name]]]]}]) + (= "admin" role) + (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]}})) diff --git a/src/cljs/auto_ap/views/utils.cljs b/src/cljs/auto_ap/views/utils.cljs index b9ce56df..12b29232 100644 --- a/src/cljs/auto_ap/views/utils.cljs +++ b/src/cljs/auto_ap/views/utils.cljs @@ -466,6 +466,19 @@ (-> context (assoc-in [:coeffects :user] (get-in context [:coeffects :db :user])))))) +(def with-role + (re-frame/->interceptor + :id :with-role + :before (fn [context] + (-> context + (assoc-in [:coeffects :role] (-> (get-in context [:coeffects :db :user]) + (str/split #"\.") + second + (base64/decodeString ) + (#(.parse js/JSON % )) + (js->clj :keywordize-keys true) + :user/role)))))) + (def with-is-admin? (re-frame/->interceptor :id :with-is-admin?