working on UI.

This commit is contained in:
Bryce Covert
2021-01-09 00:09:52 -08:00
parent c6dd929c86
commit d3232c70b2
8 changed files with 242 additions and 117 deletions

View File

@@ -506,10 +506,15 @@
:cash_flow {:type :cash_flow_result :cash_flow {:type :cash_flow_result
:args {:client_id {:type :id}} :args {:client_id {:type :id}}
:resolve :get-cash-flow} :resolve :get-cash-flow}
:potential_payment_matches {:type '(list :payment) :potential_payment_matches {:type '(list :payment)
:args {:transaction_id {:type :id}} :args {:transaction_id {:type :id}}
:resolve :get-potential-payments} :resolve :get-potential-payments}
:potential_autopay_invoices_matches {:type '(list (list :invoice))
:args {:transaction_id {:type :id}}
:resolve :get-potential-autopay-invoices-matches}
:potential_transaction_rule_matches {:type '(list :transaction_rule) :potential_transaction_rule_matches {:type '(list :transaction_rule)
:args {:transaction_id {:type :id}} :args {:transaction_id {:type :id}}
:resolve :get-transaction-rule-matches} :resolve :get-transaction-rule-matches}
@@ -964,6 +969,11 @@
:payment_id {:type :id}} :payment_id {:type :id}}
:resolve :mutation/match-transaction} :resolve :mutation/match-transaction}
:match_transaction_autopay_invoices {:type :transaction
:args {:transaction_id {:type :id}
:autopay_invoice_ids {:type '(list :id)}}
:resolve :mutation/match-transaction-autopay-invoices}
:match_transaction_rules {:type '(list :transaction) :match_transaction_rules {:type '(list :transaction)
:args {:transaction_ids {:type '(list :id)} :args {:transaction_ids {:type '(list :id)}
:all {:type 'Boolean} :all {:type 'Boolean}
@@ -1222,6 +1232,7 @@
:get-all-sales-orders get-all-sales-orders :get-all-sales-orders get-all-sales-orders
:get-payment-page gq-checks/get-payment-page :get-payment-page gq-checks/get-payment-page
:get-potential-payments gq-checks/get-potential-payments :get-potential-payments gq-checks/get-potential-payments
:get-potential-autopay-invoices-matches gq-transactions/get-potential-autopay-invoices-matches
:get-accounts gq-accounts/get-accounts :get-accounts gq-accounts/get-accounts
:get-transaction-page gq-transactions/get-transaction-page :get-transaction-page gq-transactions/get-transaction-page
:get-ledger-page gq-ledger/get-ledger-page :get-ledger-page gq-ledger/get-ledger-page
@@ -1254,6 +1265,7 @@
:test-transaction-rule gq-transaction-rules/test-transaction-rule :test-transaction-rule gq-transaction-rules/test-transaction-rule
:run-transaction-rule gq-transaction-rules/run-transaction-rule :run-transaction-rule gq-transaction-rules/run-transaction-rule
:mutation/match-transaction gq-transactions/match-transaction :mutation/match-transaction gq-transactions/match-transaction
:mutation/match-transaction-autopay-invoices gq-transactions/match-transaction-autopay-invoices
:mutation/match-transaction-rules gq-transactions/match-transaction-rules :mutation/match-transaction-rules gq-transactions/match-transaction-rules
:mutation/edit-client gq-clients/edit-client :mutation/edit-client gq-clients/edit-client
:mutation/upsert-vendor gq-vendors/upsert-vendor :mutation/upsert-vendor gq-vendors/upsert-vendor

View File

@@ -22,7 +22,8 @@
[clojure.set :as set] [clojure.set :as set]
[clojure.string :as str] [clojure.string :as str]
[clojure.tools.logging :as log] [clojure.tools.logging :as log]
[datomic.api :as d])) [datomic.api :as d]
[auto-ap.datomic.invoices :as d-invoices]))
(def approval-status->graphql (ident->enum-f :transaction/approval-status)) (def approval-status->graphql (ident->enum-f :transaction/approval-status))
@@ -81,6 +82,16 @@
(:id context)) (:id context))
{:message (str "Succesfully deleted " (count all-ids) " transactions.")})) {:message (str "Succesfully deleted " (count all-ids) " transactions.")}))
(defn get-potential-autopay-invoices-matches [context args value]
(assert-admin (:id context))
(let [transaction (d-transactions/get-by-id (:transaction_id args))]
(let [matches-set (auto-ap.yodlee.import/match-transaction-to-unfulfilled-autopayments (:transaction/amount transaction)
(:db/id (:transaction/client transaction)))]
(->graphql (for [matches matches-set]
(for [[_ invoice-id ] matches]
(d-invoices/get-by-id invoice-id)))))))
(defn unlink-transaction [context args value] (defn unlink-transaction [context args value]
(let [_ (assert-admin (:id context)) (let [_ (assert-admin (:id context))
args (assoc args :id (:id context)) args (assoc args :id (:id context))
@@ -270,6 +281,23 @@
approval-status->graphql approval-status->graphql
->graphql)) ->graphql))
(defn match-transaction-autopay-invoices [context {:keys [transaction_id payment_id]} value]
(let [_ (assert-admin (:id context))
transaction (d-transactions/get-by-id transaction_id)
payment (d-checks/get-by-id payment_id)
_ (assert-can-see-client (:id context) (:transaction/client transaction) )
_ (assert-can-see-client (:id context) (:payment/client payment) )]
(when (not= (:db/id (:transaction/client transaction))
(:db/id (:payment/client payment)))
(throw (ex-info "Clients don't match" {:validation-error "Payment and client do not match."})))
(when-not (dollars= (- (:transaction/amount transaction))
(:payment/amount payment))
(throw (ex-info "Amounts don't match" {:validation-error "Amounts don't match"}))))
(-> (d-transactions/get-by-id transaction_id)
approval-status->graphql
->graphql))
(defn match-transaction-rules [context {:keys [transaction_ids transaction_rule_id all]} value] (defn match-transaction-rules [context {:keys [transaction_ids transaction_rule_id all]} value]
(let [_ (assert-admin (:id context)) (let [_ (assert-admin (:id context))
transaction_ids (if all transaction_ids (if all

View File

@@ -81,6 +81,11 @@
(- amount))] (- amount))]
consideration)] consideration)]
(log/info "Found " (count considerations) "considerations for transaction of" amount) (log/info "Found " (count considerations) "considerations for transaction of" amount)
considerations
))
(defn match-transaction-to-single-unfulfilled-autopayments [amount client-id]
(let [considerations (match-transaction-to-unfulfilled-autopayments amount client-id)]
(if (= 1 (count considerations)) (if (= 1 (count considerations))
(first considerations) (first considerations)
[]))) [])))
@@ -159,7 +164,7 @@
)] )]
(let [existing-check (transaction->existing-payment transaction check-number client-id bank-account-id amount id) (let [existing-check (transaction->existing-payment transaction check-number client-id bank-account-id amount id)
invoices-matches (when-not existing-check invoices-matches (when-not existing-check
(match-transaction-to-unfulfilled-autopayments amount client-id ))] (match-transaction-to-single-unfulfilled-autopayments amount client-id ))]
(cond-> (cond->
[#:transaction [#:transaction
{:post-date (coerce/to-date (time/parse post-date "YYYY-MM-dd")) {:post-date (coerce/to-date (time/parse post-date "YYYY-MM-dd"))

View File

@@ -47,6 +47,12 @@
:else :else
false)) false))
(defn disabled-if-any [states]
(if (some #(= :loading (:state %))
(vals states))
true
false))
(re-frame/reg-sub (re-frame/reg-sub
::multi ::multi

View File

@@ -94,25 +94,23 @@
[grid/header-cell {:style {:width (action-cell-width 3)}} ]]] [grid/header-cell {:style {:width (action-cell-width 3)}} ]]]
[grid/body [grid/body
(for [{:keys [id name accounts status detailed-status last-updated clients] :as c} (:data page)] (for [{:keys [id name accounts status detailed-status last-updated clients] :as c} (:data page)]
(do ^{:key (str name "-" id )}
(println c) [grid/row {:class (:class c) :id id}
^{:key (str name "-" id )} [grid/cell {} id]
[grid/row {:class (:class c) :id id} [grid/cell {} status]
[grid/cell {} id] [grid/cell {} detailed-status]
[grid/cell {} status] [grid/cell {} (date->str last-updated)]
[grid/cell {} detailed-status] [grid/cell {}
[grid/cell {} (date->str last-updated)] [:ul
[grid/cell {} (for [a accounts]
[:ul ^{:key (:id a)}
(for [a accounts] [:li (:name a) " - " (:number a) [:div.tag (->$ (:available-balance a))]])]]
^{:key (:id a)} [grid/cell {}
[:li (:name a) " - " (:number a) [:div.tag (->$ (:available-balance a))]])]] [:div.buttons
[grid/cell {} [buttons/fa-icon {:event [::form/editing c]
[:div.buttons :icon "fa-pencil"}]
[buttons/fa-icon {:event [::form/editing c] [buttons/fa-icon {:event [::request-refresh (:id c) (:id (:client c))]
:icon "fa-pencil"}] :class (status/class-for (get statuses (:id c)))
[buttons/fa-icon {:event [::request-refresh (:id c) (:id (:client c))] :icon "fa-refresh"}]
:class (status/class-for (get statuses (:id c))) [buttons/fa-icon {:event [::delete-requested (:id c)]
:icon "fa-refresh"}] :icon "fa-times"}]]]])]]]))
[buttons/fa-icon {:event [::delete-requested (:id c)]
:icon "fa-times"}]]]]))]]]))

View File

@@ -1,15 +1,22 @@
(ns auto-ap.views.pages.transactions.form (ns auto-ap.views.pages.transactions.form
(:require [auto-ap.forms :as forms] (:require [auto-ap.forms :as forms]
[auto-ap.subs :as subs] [auto-ap.subs :as subs]
[auto-ap.views.components.layouts :as layouts]
[auto-ap.views.components.typeahead :refer [typeahead typeahead-entity]]
[auto-ap.views.components.button-radio :refer [button-radio]] [auto-ap.views.components.button-radio :refer [button-radio]]
[auto-ap.views.components.expense-accounts-field :refer [expense-accounts-field] :as expense-accounts-field] [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-entity]]
[auto-ap.views.pages.transactions.common :refer [transaction-read]] [auto-ap.views.pages.transactions.common :refer [transaction-read]]
[auto-ap.views.utils :refer [bind-field dispatch-event with-user]] [auto-ap.views.utils :refer [->$ date->str dispatch-event with-user]]
[re-frame.core :as re-frame]
[clojure.string :as str] [clojure.string :as str]
[clojure.set :as set])) [re-frame.core :as re-frame]
[auto-ap.status :as status]
[reagent.core :as r]
[react :as react]
[reagent.core :as reagent]))
;; SUBS ;; SUBS
(re-frame/reg-sub (re-frame/reg-sub
@@ -45,7 +52,7 @@
(re-frame/reg-event-db (re-frame/reg-event-db
::editing ::editing
(fn [db [_ which potential-payment-matches potential-transaction-rule-matches]] (fn [db [_ which potential-payment-matches potential-autopay-invoices-matches potential-transaction-rule-matches]]
(let [locations @(re-frame/subscribe [::subs/locations-for-client (:id (:client which))]) (let [locations @(re-frame/subscribe [::subs/locations-for-client (:id (:client which))])
accounts-by-id @(re-frame/subscribe [::subs/accounts-by-id (:client which)])] accounts-by-id @(re-frame/subscribe [::subs/accounts-by-id (:client which)])]
(forms/start-form db ::form (forms/start-form db ::form
@@ -62,6 +69,9 @@
(assoc :potential-transaction-rule-matches (if (:matched-rule which) (assoc :potential-transaction-rule-matches (if (:matched-rule which)
nil nil
potential-transaction-rule-matches)) potential-transaction-rule-matches))
(assoc :potential-autopay-invoices-matches (if (:matched-rule which)
nil
potential-autopay-invoices-matches))
(update :accounts expense-accounts-field/from-graphql accounts-by-id (:amount which) locations)))))) (update :accounts expense-accounts-field/from-graphql accounts-by-id (:amount which) locations))))))
(re-frame/reg-event-db (re-frame/reg-event-db
@@ -91,7 +101,7 @@
(re-frame/reg-event-fx (re-frame/reg-event-fx
::matching ::matching-payment
[with-user (forms/triggers-loading ::form) (forms/in-form ::form)] [with-user (forms/triggers-loading ::form) (forms/in-form ::form)]
(fn [{{{:keys [id]} :data} :db user :user} [_ payment-id]] (fn [{{{:keys [id]} :data} :db user :user} [_ payment-id]]
{:graphql {:graphql
@@ -106,6 +116,23 @@
[::edited (:match-transaction result)]) [::edited (:match-transaction result)])
:on-error [::forms/save-error ::form]}})) :on-error [::forms/save-error ::form]}}))
(re-frame/reg-event-fx
::matching-autopay-invoices
[with-user (forms/triggers-loading ::form) (forms/in-form ::form)]
(fn [{{{:keys [id]} :data} :db user :user} [_ invoice-ids]]
{:graphql
{:token user
:query-obj {:venia/operation {:operation/type :mutation
:operation/name "MatchTransactionAutopayInvoices"}
:venia/queries [{:query/data [:match-transaction-autopay-invoices
{:transaction_id id
:autopay-invoice-ids invoice-ids}
transaction-read]}]}
:owns-state {:multi ::matching
:which [:autopay-invoices invoice-ids]}
:on-success (fn [result]
[::edited (:match-transaction-autopay-invoices result)])}}))
(re-frame/reg-event-fx (re-frame/reg-event-fx
::matching-rule ::matching-rule
[with-user (forms/triggers-loading ::form) (forms/in-form ::form)] [with-user (forms/triggers-loading ::form) (forms/in-form ::form)]
@@ -164,40 +191,99 @@
:id ::form})) :id ::form}))
(defn potential-transaction-rule-matches-box [{:keys [potential-transaction-rule-matches] :as params}] (defn potential-transaction-rule-matches-box [{:keys [potential-transaction-rule-matches] :as params}]
[:div.box (let [states @(re-frame/subscribe [::status/multi ::matching])]
[:div.columns [:div.box
[:div.column [:div.columns
[:h1.subtitle.is-5 "Matching Rules:"]] [:div.column
[:div.column.is-narrow [:h1.subtitle.is-5 "Matching Rules:"]]]
[:a.delete {:on-click (dispatch-event [::transaction-rule-closed])} ]]]
[:table.table.compact.is-borderless
[:table.table.compact.is-borderless (for [{:keys [note id]} potential-transaction-rule-matches]
(for [{:keys [note id]} potential-transaction-rule-matches] ^{:key id}
^{:key id} [:tr
[:tr [:td.no-border note]
[:td.no-border note] [:td.no-border
[:td.no-border [:a.button.is-primary.is-small {:on-click (dispatch-event [::matching-rule id])
[:a.button.is-primary.is-small {:on-click (dispatch-event [::matching-rule id])} :class (status/class-for (get states [:transaction-rule id]))
"Use this rule"]]])]]) :disabled (status/disabled-if-any states)}
"Use this rule"]]])]]))
(defn potential-payment-matches-box [{:keys [potential-payment-matches] :as params}] (defn potential-payment-matches-box [{:keys [potential-payment-matches] :as params}]
[:div.box (let [states @(re-frame/subscribe [::status/multi ::matching])]
[:div.columns [:div
[:div.column [:h1.subtitle.is-5 "Potentially matching payments:"]
[:h1.subtitle.is-5 "Potentially matching payments:"]]
[:div.column.is-narrow [:table.table.compact.is-borderless
[:a.delete {:on-click (dispatch-event [::manual-match])} ]]] (list
(for [{:keys [memo check-number vendor id]} potential-payment-matches]
[:table.table.compact.is-borderless [:tr
(list [:td.no-border (:name vendor)]
(for [{:keys [memo check-number vendor id]} potential-payment-matches] [:td.no-border (when check-number (str "Check " check-number " ")) memo]
[:tr [:td.no-border
[:td.no-border (:name vendor)] [:a.button.is-primary.is-small {:on-click (dispatch-event [::matching-payment id])
[:td.no-border (when check-number (str "Check " check-number " ")) memo] :class (status/class-for (get states [:payment id]))
[:td.no-border :disabled (status/disabled-if-any states)}
[:a.button.is-primary.is-small {:on-click (dispatch-event [::matching id])} "Match"]]]))]]))
"Match"]]]))]])
(defn potential-autopay-invoices-matches-box [{:keys [potential-autopay-invoices-matches] :as params}]
(let [states @(re-frame/subscribe [::status/multi ::matching])]
[:div
[:div.notification.is-light.is-info "This transaction may match the following autopay invoice(s)."]
[:table.table.grid.is-fullwidth
(list
(for [invoices potential-autopay-invoices-matches]
^{:key (str invoices)}
[:tr
[:td {:style {:width "30%"}} (:name (:vendor (first invoices)))]
[:td {:style {:overflow "visible" :width "60%"}} [:span.has-tooltip-arrow.has-tooltip-bottom {:data-tooltip (str/join "\n"
(for [i invoices]
(str (:invoice-number i) " (" (->$ (:total i)) ")"))
)}
(count invoices) " invoices" (if (> (count invoices) 1)
(str " from " (date->str (:date (first invoices))) " - " (date->str (:date (last invoices))))
(str " on " (date->str (:date (first invoices)))))]]
[:td {:style {:width "6em"}}
[:a.button.is-primary.is-small {:on-click (dispatch-event [::matching-autopay-invoices (map :id invoices)])
:class (status/class-for (get states [:autopay-invoices (map :id invoices)]))
:disabled (status/disabled-if-any states)}
"Match"]]]))]]))
(defonce ^js/React.Context current-tab-context ( react/createContext "default"))
(def ^js/React.Provider CurrentTabProvider (. current-tab-context -Provider))
#_(println "Provider is" Provider)
(def ^js/React.Consumer CurrentTabConsumer (. current-tab-context -Consumer))
(defn tabs [props & children]
(let [current-tab (r/atom (:default-tab props))]
(fn [props & children]
(let [current-tab-v @current-tab]
(r/create-element CurrentTabProvider #js {:value #js {:current-tab current-tab-v
:on-tab-clicked (fn [new]
(reset! current-tab new))}}
(r/as-element
[:<>
[:div.tabs
(into [:ul]
(r/children (r/current-component)))]
(into [:div]
(->> (r/children (r/current-component))
(filter identity)
(filter #(= (doto (:key (second %)) println) current-tab-v) )
first
(drop 2)))]))))))
(defn tab [props & children]
[:> CurrentTabConsumer {}
(fn [consume]
(let [{:strs [current-tab on-tab-clicked]} (js->clj consume)]
(r/as-element
[:li (if (= (:key props)
current-tab)
{:class "is-active"})
[:a {:on-click (fn [] (on-tab-clicked (:key props)))} (:title props)]])))])
(defn form [_] (defn form [_]
@@ -208,7 +294,9 @@
{:keys [form-inline form field raw-field error-notification submit-button ]} transaction-form {:keys [form-inline form field raw-field error-notification submit-button ]} transaction-form
is-admin? @(re-frame/subscribe [::subs/is-admin?]) is-admin? @(re-frame/subscribe [::subs/is-admin?])
should-disable-for-client? (and (not is-admin?) should-disable-for-client? (and (not is-admin?)
(not= :requires-feedback (:original-status data)))] (not= :requires-feedback (:original-status data)))
is-already-matched? (or (:matched-rule data)
(:payment data))]
(form-inline {:title "Transaction"} (form-inline {:title "Transaction"}
[:<> [:<>
@@ -235,27 +323,37 @@
[:input.input {:type "text" [:input.input {:type "text"
:field [:description-original] :field [:description-original]
:disabled "disabled"}]) :disabled "disabled"}])
(when (and (:payment data) (when (and (:payment data)
is-admin?) is-admin?)
[:p.notification.is-info.is-light>div.level>div.level-left [:p.notification.is-info.is-light>div.level>div.level-left
[:div.level-item "This transaction is linked to a payment "] [:div.level-item "This transaction is linked to a payment "]
[:div.level-item [:button.button.is-warning {:on-click (dispatch-event [::unlink])} "Unlink"]]]) [:div.level-item [:button.button.is-warning {:on-click (dispatch-event [::unlink])} "Unlink"]]])
(cond [tabs {:default-tab :details}
(and (seq (:potential-transaction-rule-matches data)) (when
(not (:matched-rule data)) (and (seq (:potential-transaction-rule-matches data))
(not (:payment data)) (not is-already-matched?)
is-admin?) is-admin?)
[potential-transaction-rule-matches-box {:potential-transaction-rule-matches (:potential-transaction-rule-matches data)}] [tab {:title "Transaction Rule" :key :transaction-rule}
[potential-transaction-rule-matches-box {:potential-transaction-rule-matches (:potential-transaction-rule-matches data)}]])
(when
(and (seq (:potential-autopay-invoices-matches data))
(not is-already-matched?)
is-admin?)
[tab {:title "Autopay invoices" :key :autopay-invoices}
[potential-autopay-invoices-matches-box {:potential-autopay-invoices-matches (:potential-autopay-invoices-matches data)}]])
(when
(and (seq (:potential-payment-matches data))
(not is-already-matched?)
[tab {:title "Payment" :key :payment}
[potential-payment-matches-box {:potential-payment-matches (:potential-payment-matches data)}]]))
(and (seq (:potential-payment-matches data)) [tab {:title "Details" :key :details}
(not (:payment data))
is-admin?)
[potential-payment-matches-box {:potential-payment-matches (:potential-payment-matches data)}]
(and (not (seq (:potential-payment-matches data)))
(not (seq (:potential-transaction-rule-matches data))))
[:div [:div
(field "Vendor" (field "Vendor"
[typeahead-entity {:matches @(re-frame/subscribe [::subs/vendors]) [typeahead-entity {:matches @(re-frame/subscribe [::subs/vendors])
@@ -293,33 +391,6 @@
:match->text :identifier :match->text :identifier
:type "typeahead-entity" :type "typeahead-entity"
:field [:forecast-match]}]) :field [:forecast-match]}])
(error-notification) (error-notification)
(when-not should-disable-for-client? (when-not should-disable-for-client?
(submit-button "Save"))] (submit-button "Save"))]]]]))])
:else
[:div
(field "Approval Status"
[button-radio
{:type "button-radio"
:field [:approval-status]
:options [[:unapproved "Unapproved"]
[:requires-feedback "Client Review"]
[:approved "Approved"]
[:excluded "Excluded from Ledger"]]
:disabled should-disable-for-client?}])
(field "Forecasted-transaction"
[typeahead-entity {:matches (doto @(re-frame/subscribe [::subs/forecasted-transactions-for-client (:id (:client data))]) println)
:match->text :identifier
:type "typeahead-entity"
:field [:forecast-match]}])
(error-notification)
(when-not should-disable-for-client?
(submit-button "Save"))])]))])

View File

@@ -19,7 +19,7 @@
::editing-matches-found ::editing-matches-found
(fn [{:keys [db]} [_ which matches]] (fn [{:keys [db]} [_ which matches]]
{:dispatch {:dispatch
[::edit/editing which (:potential-payment-matches matches) (:potential-transaction-rule-matches matches)]})) [::edit/editing which (:potential-payment-matches matches) (:potential-autopay-invoices-matches matches) (:potential-transaction-rule-matches matches)]}))
(re-frame/reg-event-fx (re-frame/reg-event-fx
::editing-matches-failed ::editing-matches-failed
@@ -36,7 +36,10 @@
:which (:id which)} :which (:id which)}
:query-obj {:venia/queries (into [{:query/data [:potential-payment-matches :query-obj {:venia/queries (into [{:query/data [:potential-payment-matches
{:transaction_id (:id which)} {:transaction_id (:id which)}
[:id :memo :check-number [:vendor [:name]]]]}] [: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]]]]}]
(when @(re-frame/subscribe [::subs/is-admin?]) (when @(re-frame/subscribe [::subs/is-admin?])
[{:query/data [:potential-transaction-rule-matches [{:query/data [:potential-transaction-rule-matches
{:transaction_id (:id which)} {:transaction_id (:id which)}

View File

@@ -174,6 +174,8 @@
(:transaction/approval-status transaction-tx)) (:transaction/approval-status transaction-tx))
(str "Should have approved transaction " transaction-tx)) (str "Should have approved transaction " transaction-tx))
(t/is (= #:payment{:status :payment-status/cleared (t/is (= #:payment{:status :payment-status/cleared
:type :payment-type/debit
:date (:transaction/date transaction-tx)
:client client-id :client client-id
:bank-account bank-account-id :bank-account bank-account-id
:vendor vendor-id :vendor vendor-id
@@ -437,7 +439,7 @@
:transaction/matched-rule)))))))) :transaction/matched-rule))))))))
(t/deftest match-transaction-to-unfulfilled-payments (t/deftest match-transaction-to-single-unfulfilled-payments
(t/testing "Auto-pay Invoices" (t/testing "Auto-pay Invoices"
(let [{:strs [vendor1-id vendor2-id]} (->> [#:vendor {:name "Autopay vendor 1" (let [{:strs [vendor1-id vendor2-id]} (->> [#:vendor {:name "Autopay vendor 1"
:db/id "vendor1-id"} :db/id "vendor1-id"}
@@ -458,7 +460,7 @@
(d/transact (d/connect uri)) (d/transact (d/connect uri))
deref deref
:tempids) :tempids)
invoices-matches (sut/match-transaction-to-unfulfilled-autopayments -30.0 client-id)] invoices-matches (sut/match-transaction-to-single-unfulfilled-autopayments -30.0 client-id)]
(t/is (= 1 (count invoices-matches))) (t/is (= 1 (count invoices-matches)))
)) ))
@@ -473,7 +475,7 @@
(d/transact (d/connect uri)) (d/transact (d/connect uri))
deref deref
:tempids) :tempids)
invoices-matches (sut/match-transaction-to-unfulfilled-autopayments -30.0 client-id)] invoices-matches (sut/match-transaction-to-single-unfulfilled-autopayments -30.0 client-id)]
(t/is (= [] invoices-matches)))) (t/is (= [] invoices-matches))))
@@ -489,7 +491,7 @@
(d/transact (d/connect uri)) (d/transact (d/connect uri))
deref deref
:tempids) :tempids)
invoices-matches (sut/match-transaction-to-unfulfilled-autopayments -30.0 client-id)] invoices-matches (sut/match-transaction-to-single-unfulfilled-autopayments -30.0 client-id)]
(t/is (= [] invoices-matches)))) (t/is (= [] invoices-matches))))
@@ -508,7 +510,7 @@
(d/transact (d/connect uri)) (d/transact (d/connect uri))
deref deref
:tempids) :tempids)
invoices-matches (sut/match-transaction-to-unfulfilled-autopayments -30.0 invoices-matches (sut/match-transaction-to-single-unfulfilled-autopayments -30.0
client-id)] client-id)]
(t/is (= [] invoices-matches)))) (t/is (= [] invoices-matches))))
(t/testing "Should match multiple invoices for same vendor that total to transaction amount" (t/testing "Should match multiple invoices for same vendor that total to transaction amount"
@@ -530,7 +532,7 @@
(d/transact (d/connect uri)) (d/transact (d/connect uri))
deref deref
:tempids) :tempids)
invoices-matches (sut/match-transaction-to-unfulfilled-autopayments -30.0 client-id)] invoices-matches (sut/match-transaction-to-single-unfulfilled-autopayments -30.0 client-id)]
(t/is (= 2 (count invoices-matches)) (t/is (= 2 (count invoices-matches))
(str "Expected " (vec invoices-matches) " to have a singular match of two invoices.")))) (str "Expected " (vec invoices-matches) " to have a singular match of two invoices."))))
(t/testing "Should not match if there are multiple candidate matches" (t/testing "Should not match if there are multiple candidate matches"
@@ -552,7 +554,7 @@
(d/transact (d/connect uri)) (d/transact (d/connect uri))
deref deref
:tempids) :tempids)
invoices-matches (sut/match-transaction-to-unfulfilled-autopayments -30.0 client-id)] invoices-matches (sut/match-transaction-to-single-unfulfilled-autopayments -30.0 client-id)]
(t/is (= 0 (count invoices-matches)) (t/is (= 0 (count invoices-matches))
(str "Expected " (vec invoices-matches) " to not match due to multiple possibilities.")))) (str "Expected " (vec invoices-matches) " to not match due to multiple possibilities."))))
@@ -575,7 +577,7 @@
(d/transact (d/connect uri)) (d/transact (d/connect uri))
deref deref
:tempids) :tempids)
invoices-matches (sut/match-transaction-to-unfulfilled-autopayments -30.0 client-id)] invoices-matches (sut/match-transaction-to-single-unfulfilled-autopayments -30.0 client-id)]
(t/is (= 0 (count invoices-matches)) (t/is (= 0 (count invoices-matches))
(str "Expected " (vec invoices-matches) " to only consider invoices for the same vendor.")))) (str "Expected " (vec invoices-matches) " to only consider invoices for the same vendor."))))
@@ -605,7 +607,7 @@
(d/transact (d/connect uri)) (d/transact (d/connect uri))
deref deref
:tempids)] :tempids)]
(t/is (= 2 (count (sut/match-transaction-to-unfulfilled-autopayments -40.0 client-id))) (t/is (= 2 (count (sut/match-transaction-to-single-unfulfilled-autopayments -40.0 client-id)))
(str "Expected to match with the chronologically adjacent invoice-1 and invoice-3.")) (str "Expected to match with the chronologically adjacent invoice-1 and invoice-3."))
(t/is (= [] (sut/match-transaction-to-unfulfilled-autopayments -31.0 client-id)) (t/is (= [] (sut/match-transaction-to-single-unfulfilled-autopayments -31.0 client-id))
(str "Expected to not match, because there is invoice-3 is between invoice-1 and invoice-2."))))))) (str "Expected to not match, because there is invoice-3 is between invoice-1 and invoice-2.")))))))