Add linking, location, import-batch, and potential-duplicates filters to SSR transactions
This commit is contained in:
@@ -42,8 +42,15 @@
|
|||||||
[:description {:optional true} [:maybe [:string {:decode/string strip}]]]
|
[:description {:optional true} [:maybe [:string {:decode/string strip}]]]
|
||||||
[:vendor {:optional true :default nil} [:maybe [:entity-map {:pull [:db/id :vendor/name]}]]]
|
[:vendor {:optional true :default nil} [:maybe [:entity-map {:pull [:db/id :vendor/name]}]]]
|
||||||
[:bank-account {:optional true :default nil} [:maybe [:entity-map {:pull [:db/id :bank-account/numeric-code]}]]]
|
[:bank-account {:optional true :default nil} [:maybe [:entity-map {:pull [:db/id :bank-account/numeric-code]}]]]
|
||||||
[:account {:optional true :default nil} [:maybe [:entity-map {:pull [:db/id :account/name]}]]]
|
[:account {:optional true :default nil} [:maybe [:entity-map {:pull [:db/id :account/name]}]]]
|
||||||
#_[:status {:optional true} [:maybe (ref->enum-schema "transaction-status")]]
|
[:linked-to {:optional true} [:maybe [:enum "payment" "expected-deposit" "invoice" "none"]]]
|
||||||
|
[:location {:optional true} [:maybe [:string {:decode/string strip}]]]
|
||||||
|
[:potential-duplicates {:optional true}
|
||||||
|
[:maybe [:boolean {:decode/string {:enter #(cond (= % "on") true
|
||||||
|
(= % "") false
|
||||||
|
:else
|
||||||
|
(boolean %))}}]]]
|
||||||
|
#_[:status {:optional true} [:maybe (ref->enum-schema "transaction-status")]]
|
||||||
[:exact-match-id {:optional true} [:maybe entity-id]]
|
[:exact-match-id {:optional true} [:maybe entity-id]]
|
||||||
[:all-selected {:optional true :default nil} [:maybe :boolean]]
|
[:all-selected {:optional true :default nil} [:maybe :boolean]]
|
||||||
[:selected {:optional true :default nil} [:maybe [:vector {:coerce? true}
|
[:selected {:optional true :default nil} [:maybe [:vector {:coerce? true}
|
||||||
@@ -167,13 +174,59 @@
|
|||||||
:where ['[?import-batch-id :import-batch/entry ?e]]}
|
:where ['[?import-batch-id :import-batch/entry ?e]]}
|
||||||
:args [(:import-batch-id args)]})
|
:args [(:import-batch-id args)]})
|
||||||
|
|
||||||
(:unresolved args)
|
(:unresolved args)
|
||||||
(merge-query {:query {:where ['[?e :transaction/date]
|
(merge-query {:query {:where ['[?e :transaction/date]
|
||||||
'(or-join [?e]
|
'(or-join [?e]
|
||||||
(not [?e :transaction/accounts])
|
(not [?e :transaction/accounts])
|
||||||
(and [?e :transaction/accounts ?tas]
|
(and [?e :transaction/accounts ?tas]
|
||||||
(not [?tas :transaction-account/account]))) ]}})
|
(not [?tas :transaction-account/account]))) ]}})
|
||||||
|
|
||||||
|
(seq (:location args))
|
||||||
|
(merge-query {:query {:in ['?location]
|
||||||
|
:where ['[?e :transaction/accounts ?tas]
|
||||||
|
'[?tas :transaction-account/location ?location]]}
|
||||||
|
:args [(:location args)]})
|
||||||
|
|
||||||
|
(= (:linked-to args) "payment")
|
||||||
|
(merge-query {:query {:where ['[?e :transaction/payment]]}})
|
||||||
|
|
||||||
|
(= (:linked-to args) "expected-deposit")
|
||||||
|
(merge-query {:query {:where ['[?e :transaction/expected-deposit]]}})
|
||||||
|
|
||||||
|
(= (:linked-to args) "invoice")
|
||||||
|
(merge-query {:query {:where ['[?e :transaction/payment ?p]
|
||||||
|
'[_ :invoice-payment/payment ?p]]}})
|
||||||
|
|
||||||
|
(= (:linked-to args) "none")
|
||||||
|
(merge-query {:query {:where ['(not [?e :transaction/payment])
|
||||||
|
'(not [?e :transaction/expected-deposit])]}})
|
||||||
|
|
||||||
|
(:potential-duplicates args)
|
||||||
|
(merge-query (let [bank-account-id (:db/id (:bank-account args))
|
||||||
|
_ (when-not bank-account-id
|
||||||
|
(throw (ex-info "In order to select potential duplicates, you must choose a bank account."
|
||||||
|
{:validation-error "In order to select potential duplicates, you must choose a bank account."})))
|
||||||
|
duplicate-ids (->> (dc/q '[:find ?tx ?amount ?date
|
||||||
|
:in $ ?ba
|
||||||
|
:where
|
||||||
|
[?tx :transaction/bank-account ?ba]
|
||||||
|
[?tx :transaction/amount ?amount]
|
||||||
|
[?tx :transaction/date ?date]
|
||||||
|
(not [?tx :transaction/approval-status :transaction-approval-status/suppressed])]
|
||||||
|
db
|
||||||
|
bank-account-id)
|
||||||
|
(group-by (fn [[_ amount date]]
|
||||||
|
[amount date]))
|
||||||
|
(filter (fn [[_ txes]]
|
||||||
|
(> (count txes) 1)))
|
||||||
|
(vals)
|
||||||
|
(mapcat identity)
|
||||||
|
(map first)
|
||||||
|
set)]
|
||||||
|
{:query {:in '[[?e ...]]
|
||||||
|
:where []}
|
||||||
|
:args [duplicate-ids]}))
|
||||||
|
|
||||||
(:status route-params)
|
(:status route-params)
|
||||||
(merge-query {:query {:in ['?status]
|
(merge-query {:query {:in ['?status]
|
||||||
:where ['[?e :transaction/approval-status ?status]]}
|
:where ['[?e :transaction/approval-status ?status]]}
|
||||||
@@ -223,6 +276,18 @@
|
|||||||
svg/x)]])]
|
svg/x)]])]
|
||||||
[:div {:id "exact-match-id-tag"}]))
|
[:div {:id "exact-match-id-tag"}]))
|
||||||
|
|
||||||
|
(defn import-batch-id* [request]
|
||||||
|
(when-let [import-batch-id (:import-batch-id (:query-params request))]
|
||||||
|
[:div {:x-data (hx/json {:import_batch_id import-batch-id}) :id "import-batch-id-tag"}
|
||||||
|
(com/hidden {:name "import-batch-id"
|
||||||
|
"x-model" "import_batch_id"})
|
||||||
|
(com/pill {:color :primary}
|
||||||
|
[:span.inline-flex.space-x-2.items-center
|
||||||
|
[:div (str "Batch " import-batch-id)]
|
||||||
|
[:div.w-3.h-3
|
||||||
|
(com/link {"@click" "import_batch_id=null; $nextTick(() => $dispatch('change'))"}
|
||||||
|
svg/x)]])]))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defn bank-account-filter* [request]
|
(defn bank-account-filter* [request]
|
||||||
@@ -275,40 +340,74 @@
|
|||||||
(bank-account-filter* request)
|
(bank-account-filter* request)
|
||||||
|
|
||||||
(date-range-field* request)
|
(date-range-field* request)
|
||||||
(com/field {:label "Description"}
|
(com/field {:label "Description"}
|
||||||
(com/text-input {:name "description"
|
(com/text-input {:name "description"
|
||||||
:id "description"
|
:id "description"
|
||||||
:class "hot-filter"
|
:class "hot-filter"
|
||||||
:value (:description (:query-params request))
|
:value (:description (:query-params request))
|
||||||
:placeholder "e.g., Groceries"
|
:placeholder "e.g., Groceries"
|
||||||
:size :small}))
|
:size :small}))
|
||||||
|
|
||||||
(com/field {:label "Amount"}
|
(com/field {:label "Location"}
|
||||||
[:div.flex.space-x-4.items-baseline
|
(com/text-input {:name "location"
|
||||||
(com/money-input {:name "amount-gte"
|
:id "location"
|
||||||
:id "amount-gte"
|
:class "hot-filter"
|
||||||
:hx-preserve "true"
|
:value (:location (:query-params request))
|
||||||
:class "hot-filter w-20"
|
:placeholder "SC"
|
||||||
:value (:amount-gte (:query-params request))
|
:size :small}))
|
||||||
:placeholder "0.01"
|
|
||||||
:size :small})
|
(com/field {:label "Amount"}
|
||||||
[:div.align-baseline
|
[:div.flex.space-x-4.items-baseline
|
||||||
"to"]
|
(com/money-input {:name "amount-gte"
|
||||||
(com/money-input {:name "amount-lte"
|
:id "amount-gte"
|
||||||
:hx-preserve "true"
|
:hx-preserve "true"
|
||||||
:id "amount-lte"
|
:class "hot-filter w-20"
|
||||||
:class "hot-filter w-20"
|
:value (:amount-gte (:query-params request))
|
||||||
:value (:amount-lte (:query-params request))
|
:placeholder "0.01"
|
||||||
:placeholder "9999.34"
|
:size :small})
|
||||||
:size :small})])
|
[:div.align-baseline
|
||||||
(when (is-admin? (:identity request))
|
"to"]
|
||||||
[:div.mt-4 {:x-data (hx/json {:unresolvedOnly (:unresolved (:query-params request))})}
|
(com/money-input {:name "amount-lte"
|
||||||
(com/hidden {:name "unresolved"
|
:hx-preserve "true"
|
||||||
":value" "unresolvedOnly ? 'on' : ''"})
|
:id "amount-lte"
|
||||||
(com/checkbox {:value (:unresolved (:query-params request))
|
:class "hot-filter w-20"
|
||||||
:x-model "unresolvedOnly"}
|
:value (:amount-lte (:query-params request))
|
||||||
"Unresolved only")])
|
:placeholder "9999.34"
|
||||||
(exact-match-id* request)]])
|
:size :small})])
|
||||||
|
|
||||||
|
(com/field {:label "Linking"}
|
||||||
|
(com/radio-card {:size :small
|
||||||
|
:name "linked-to"
|
||||||
|
:value (or (:linked-to (:query-params request)) "")
|
||||||
|
:options [{:value ""
|
||||||
|
:content "All"}
|
||||||
|
{:value "none"
|
||||||
|
:content "None"}
|
||||||
|
{:value "invoice"
|
||||||
|
:content "Invoice"}
|
||||||
|
{:value "expected-deposit"
|
||||||
|
:content "Expected Deposit"}
|
||||||
|
{:value "payment"
|
||||||
|
:content "Payment"}]}))
|
||||||
|
|
||||||
|
(when (is-admin? (:identity request))
|
||||||
|
[:div.mt-4 {:x-data (hx/json {:unresolvedOnly (:unresolved (:query-params request))})}
|
||||||
|
(com/hidden {:name "unresolved"
|
||||||
|
":value" "unresolvedOnly ? 'on' : ''"})
|
||||||
|
(com/checkbox {:value (:unresolved (:query-params request))
|
||||||
|
:x-model "unresolvedOnly"}
|
||||||
|
"Unresolved only")])
|
||||||
|
|
||||||
|
(when (is-admin? (:identity request))
|
||||||
|
[:div.mt-4 {:x-data (hx/json {:potentialDuplicates (:potential-duplicates (:query-params request))})}
|
||||||
|
(com/hidden {:name "potential-duplicates"
|
||||||
|
":value" "potentialDuplicates ? 'on' : ''"})
|
||||||
|
(com/checkbox {:value (:potential-duplicates (:query-params request))
|
||||||
|
:x-model "potentialDuplicates"}
|
||||||
|
"Same Amount + Date")])
|
||||||
|
|
||||||
|
(import-batch-id* request)
|
||||||
|
(exact-match-id* request)]])
|
||||||
|
|
||||||
|
|
||||||
(def grid-page
|
(def grid-page
|
||||||
@@ -318,10 +417,11 @@
|
|||||||
:page-specific-nav filters
|
:page-specific-nav filters
|
||||||
:fetch-page fetch-page
|
:fetch-page fetch-page
|
||||||
:query-schema query-schema
|
:query-schema query-schema
|
||||||
:oob-render
|
:oob-render
|
||||||
(fn [request]
|
(fn [request]
|
||||||
[(assoc-in (date-range-field* request) [1 :hx-swap-oob] true)
|
[(assoc-in (date-range-field* request) [1 :hx-swap-oob] true)
|
||||||
(assoc-in (exact-match-id* request) [1 :hx-swap-oob] true)])
|
(assoc-in (exact-match-id* request) [1 :hx-swap-oob] true)
|
||||||
|
(some-> (import-batch-id* request) (assoc-in [1 :hx-swap-oob] true))])
|
||||||
:action-buttons (fn [request]
|
:action-buttons (fn [request]
|
||||||
[
|
[
|
||||||
(com/button {:color :primary
|
(com/button {:color :primary
|
||||||
|
|||||||
Reference in New Issue
Block a user