Makes testing of transaction rules work
This commit is contained in:
@@ -41,6 +41,7 @@
|
||||
wrap-entity
|
||||
wrap-form-4xx-2
|
||||
wrap-schema-decode]]
|
||||
[auto-ap.time :as atime]
|
||||
[auto-ap.utils :refer [dollars=]]
|
||||
[bidi.bidi :as bidi]
|
||||
[clojure.string :as str]
|
||||
@@ -258,33 +259,31 @@
|
||||
(set))
|
||||
bank-account-id))
|
||||
|
||||
(defn validate-transaction-rule [form-params]
|
||||
(doseq [[{:transaction-rule-account/keys [account location]} i] (map vector (:transaction-rule/accounts form-params) (range))
|
||||
:let [account-location (pull-attr (dc/db conn) :account/location account)]
|
||||
:when (and account-location (not= account-location location))]
|
||||
(field-validation-error (str "must be " account-location)
|
||||
[:transaction-rule/accounts i :transaction-rule-account/location]
|
||||
:form form-params))
|
||||
|
||||
(let [total (reduce + 0.0 (map :transaction-rule-account/percentage (:transaction-rule/accounts form-params)))]
|
||||
(when-not (dollars= 1.0 total)
|
||||
(form-validation-error (format "Expense accounts total (%d%%) must add to 100%%" (int (* 100.0 total)))
|
||||
:form form-params)))
|
||||
|
||||
(when (and (:transaction-rule/bank-account form-params)
|
||||
(not (bank-account-belongs-to-client? (:transaction-rule/bank-account form-params)
|
||||
(:transaction-rule/client form-params))))
|
||||
(field-validation-error "does not belong to client"
|
||||
[:transaction-rule/bank-account]
|
||||
:form form-params)))
|
||||
|
||||
(defn transaction-rule-save [{:keys [form-params request-method identity] :as request}]
|
||||
(validate-transaction-rule form-params)
|
||||
(let [entity (cond-> form-params
|
||||
(= :post request-method) (assoc :db/id "new")
|
||||
true (assoc :transaction-rule/note (entity->note form-params)))
|
||||
_ (doseq [[{:transaction-rule-account/keys [account location]} i] (map vector (:transaction-rule/accounts entity) (range))
|
||||
:let [account-location (pull-attr (dc/db conn) :account/location account)]
|
||||
:when (and account-location (not= account-location location))]
|
||||
(field-validation-error (str "must be " account-location)
|
||||
[:transaction-rule/accounts i :transaction-rule-account/location]
|
||||
:form form-params))
|
||||
|
||||
total (reduce +
|
||||
0.0
|
||||
(map :transaction-rule-account/percentage
|
||||
(:transaction-rule/accounts entity)))
|
||||
_ (when-not (dollars= 1.0 total)
|
||||
(form-validation-error (format "Expense accounts total (%d%%) must add to 100%%" (int (* 100.0 total)))
|
||||
:form form-params))
|
||||
|
||||
_ (when (and (:transaction-rule/bank-account entity)
|
||||
(not (bank-account-belongs-to-client? (:transaction-rule/bank-account entity)
|
||||
(:transaction-rule/client entity))))
|
||||
(field-validation-error "does not belong to client"
|
||||
[:transaction-rule/bank-account]
|
||||
:form form-params))
|
||||
|
||||
|
||||
{:keys [tempids]} (audit-transact [[:upsert-entity entity]]
|
||||
(:identity request))
|
||||
updated-rule (dc/pull (dc/db conn)
|
||||
@@ -295,7 +294,112 @@
|
||||
:headers (cond-> {"hx-trigger" "modalclose"}
|
||||
(= :post request-method) (assoc "hx-retarget" "#entity-table tbody"
|
||||
"hx-reswap" "afterbegin")
|
||||
(= :put request-method) (assoc "hx-retarget" (format "#entity-table tr[data-id=\"%d\"]" (:db/id updated-rule)))))))
|
||||
(= :put request-method) (assoc "hx-retarget" (format "#entity-table tr[data-id=\"%d\"]" (:db/id updated-rule))
|
||||
"hx-reswap" "outerHTML")))))
|
||||
|
||||
|
||||
|
||||
(def transaction-read '[{:transaction/client [:client/name]
|
||||
:transaction/bank-account [:bank-account/name]}
|
||||
:transaction/description-original
|
||||
[:transaction/date :xform clj-time.coerce/from-date]])
|
||||
|
||||
(defn transaction-rule-test [{:keys [form-params request-method identity] :as request
|
||||
{:transaction-rule/keys [description client bank-account amount-lte amount-gte dom-lte dom-gte yodlee-merchant]} :form-params}]
|
||||
(validate-transaction-rule form-params)
|
||||
(let [valid-clients (extract-client-ids (:clients request)
|
||||
client)
|
||||
query (cond-> {:query {:find ['(pull ?e read)]
|
||||
:in ['$ 'read]
|
||||
:where []}
|
||||
:args [(dc/db conn) transaction-read]}
|
||||
description
|
||||
(merge-query {:query {:in ['?descr]
|
||||
:where ['[(iol-ion.query/->pattern ?descr) ?description-regex]]}
|
||||
:args [description]})
|
||||
|
||||
valid-clients
|
||||
(merge-query {:query {:in ['[?xx ...]]
|
||||
:where ['[?e :transaction/client ?xx]]}
|
||||
:args [(set valid-clients)]})
|
||||
|
||||
bank-account
|
||||
(merge-query {:query {:in ['?bank-account-id]
|
||||
:where ['[?e :transaction/bank-account ?bank-account-id]]}
|
||||
:args [bank-account]})
|
||||
|
||||
description
|
||||
(merge-query {:query {:where ['[?e :transaction/description-original ?do]
|
||||
'[(re-find ?description-regex ?do)]]}})
|
||||
|
||||
amount-gte
|
||||
(merge-query {:query {:in ['?amount-gte]
|
||||
:where ['[?e :transaction/amount ?ta]
|
||||
'[(>= ?ta ?amount-gte)]]}
|
||||
:args [amount-gte]})
|
||||
|
||||
amount-lte
|
||||
(merge-query {:query {:in ['?amount-lte]
|
||||
:where ['[?e :transaction/amount ?ta]
|
||||
'[(<= ?ta ?amount-lte)]]}
|
||||
:args [amount-lte]})
|
||||
|
||||
dom-lte
|
||||
(merge-query {:query {:in ['?dom-lte]
|
||||
:where ['[?e :transaction/date ?transaction-date]
|
||||
'[(iol-ion.query/dom ?transaction-date) ?dom]
|
||||
'[(<= ?dom ?dom-lte)]]}
|
||||
:args [dom-lte]})
|
||||
|
||||
dom-gte
|
||||
(merge-query {:query {:in ['?dom-gte]
|
||||
:where ['[?e :transaction/date ?transaction-date]
|
||||
'[(iol-ion.query/dom ?transaction-date) ?dom]
|
||||
'[(>= ?dom ?dom-gte)]]}
|
||||
:args [dom-gte]})
|
||||
|
||||
client
|
||||
(merge-query {:query {:in ['?client-id]
|
||||
:where ['[?e :transaction/client ?client-id]]}
|
||||
:args [client]})
|
||||
|
||||
|
||||
true
|
||||
(merge-query {:query {:where ['[?e :transaction/id]]}}))
|
||||
results (->>
|
||||
(query2 query)
|
||||
(map first))]
|
||||
|
||||
(html-response
|
||||
(com/modal-card {:class "fade-in transition duration-300"}
|
||||
[:div.p-2.flex.space-x-4 [:div "Transaction Rule"] [:div ">"] [:div "Results"] [:div.ml-4.relative (com/badge {} (count results))]]
|
||||
(com/data-grid
|
||||
{:headers [(com/data-grid-header {} "Client")
|
||||
(com/data-grid-header {} "Bank")
|
||||
(com/data-grid-header {} "Date")
|
||||
(com/data-grid-header {} "Description")]}
|
||||
(for [r (take 15 results)]
|
||||
(com/data-grid-row
|
||||
{}
|
||||
(com/data-grid-cell {} (-> r :transaction/client :client/name))
|
||||
(com/data-grid-cell {} (-> r :transaction/bank-account :bank-account/name))
|
||||
(com/data-grid-cell {} (some-> r :transaction/date (atime/unparse-local atime/normal-date)))
|
||||
(com/data-grid-cell {} (some-> r :transaction/description-original )))))
|
||||
[:div
|
||||
(com/button (cond-> {:color :primary
|
||||
:hx-vals (hx/json (:raw-form-params request))
|
||||
}
|
||||
(:db/id form-params) (assoc :hx-put (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-save))
|
||||
(not (:db/id form-params)) (assoc :hx-post (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-save)))
|
||||
"Save")
|
||||
(com/button {:hx-vals (hx/json (:raw-form-params request))
|
||||
:hx-put (bidi/path-for ssr-routes/only-routes
|
||||
:admin-transaction-rule-filled-account
|
||||
)} "Back")
|
||||
])
|
||||
:headers (-> {}
|
||||
(assoc "hx-retarget" ".modal-card")
|
||||
(assoc "hx-reswap" "outerHTML")))))
|
||||
|
||||
|
||||
|
||||
@@ -366,6 +470,7 @@
|
||||
:x-data (hx/json {:location (fc/field-value)})}
|
||||
[:div {:hx-trigger "changed"
|
||||
:hx-target "next *"
|
||||
:hx-swap "outerHTML"
|
||||
:hx-vals (format "js:{name: '%s', 'client-id': event.detail.clientId || '', 'account-id': event.detail.accountId || '', value: event.detail.location}" (fc/field-name) )
|
||||
:hx-get (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-location-select)
|
||||
:x-init "$watch('clientId', cid => $dispatch('changed', $data)); $watch('accountId', cid => $dispatch('changed', $data) )"}]
|
||||
@@ -554,7 +659,11 @@
|
||||
]]
|
||||
[:div
|
||||
(com/form-errors {:errors (:errors fc/*form-errors*)})
|
||||
(com/validated-save-button {:errors form-errors} "Save rule")])])))
|
||||
(com/validated-save-button {:errors form-errors} "Save rule")
|
||||
(com/validated-save-button {:errors form-errors :color :secondary
|
||||
:hx-post (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-test)}
|
||||
|
||||
"Test rule")])])))
|
||||
|
||||
|
||||
(defn new-account [{{:keys [client-id index]} :query-params}]
|
||||
@@ -607,6 +716,7 @@
|
||||
[:transaction-rule-account/percentage percentage])]]))
|
||||
|
||||
(defn transaction-dialog [{:keys [entity form-params form-errors]}]
|
||||
(clojure.pprint/pprint form-params)
|
||||
(modal-response (dialog* {:entity entity
|
||||
:form-params (or (when (seq form-params)
|
||||
form-params)
|
||||
@@ -649,6 +759,19 @@
|
||||
(wrap-nested-form-params)
|
||||
(wrap-form-4xx-2 (-> transaction-dialog
|
||||
(wrap-entity [:form-params :db/id] default-read))))
|
||||
|
||||
:admin-transaction-rule-test (-> transaction-rule-test
|
||||
(wrap-entity [:form-params :db/id] default-read)
|
||||
(wrap-schema-decode :form-schema form-schema)
|
||||
(wrap-nested-form-params)
|
||||
(wrap-form-4xx-2 (-> transaction-dialog
|
||||
(wrap-entity [:form-params :db/id] default-read))))
|
||||
:admin-transaction-rule-filled-account (-> transaction-dialog
|
||||
(wrap-entity [:form-params :db/id] default-read)
|
||||
(wrap-schema-decode :form-schema form-schema)
|
||||
(wrap-nested-form-params)
|
||||
(wrap-form-4xx-2 (-> transaction-dialog
|
||||
(wrap-entity [:form-params :db/id] default-read))))
|
||||
:admin-transaction-rule-edit-dialog (-> transaction-dialog
|
||||
(wrap-entity [:route-params :db/id] default-read)
|
||||
(wrap-schema-decode :route-schema [:map [:db/id entity-id]]))
|
||||
|
||||
Reference in New Issue
Block a user