transaction links is visible.

This commit is contained in:
2025-03-02 20:44:08 -08:00
parent 7c7fc10a8d
commit bd501b512a
2 changed files with 117 additions and 69 deletions

File diff suppressed because one or more lines are too long

View File

@@ -251,41 +251,76 @@
(render-step (render-step
[this {:keys [multi-form-state] :as request}] [this {:keys [multi-form-state] :as request}]
(let [extant? (mm/get-mfs-field multi-form-state :db/id) (let [tx-id (mm/get-mfs-field multi-form-state :db/id)
tx (d-transactions/get-by-id extant?)] tx (d-transactions/get-by-id tx-id)]
(alog/info ::TRANSACTION :i multi-form-state) (alog/info ::TRANSACTION :i multi-form-state)
(mm/default-render-step (mm/default-render-step
linear-wizard this linear-wizard this
:head [:div.p-2 (if extant? :head [:div.p-2 "Edit transaction"]
"Edit transaction"
"New transaction")]
:body (mm/default-step-body :body (mm/default-step-body
{} {}
[:div {:x-data (hx/json {:clientId (or (fc/field-value (:transaction/client fc/*current*)) [:div {:x-data (hx/json {:clientId (or (fc/field-value (:transaction/client fc/*current*))
(:db/id (:client request))) (:db/id (:client request)))
:vendorId (fc/field-value (:transaction/vendor fc/*current*))})} :vendorId (fc/field-value (:transaction/vendor fc/*current*))})}
;; Read-only transaction details
[:div.mb-6.border.rounded-lg.p-4.bg-gray-50
[:h3.text-lg.font-semibold.mb-2 "Transaction Details"]
[:div.grid.grid-cols-2.gap-4
[:div
[:div.text-sm.font-medium.text-gray-500 "Amount"]
[:div.text-base (format "$%,.2f" (Math/abs (:transaction/amount tx)))]
]
[:div
[:div.text-sm.font-medium.text-gray-500 "Date"]
[:div.text-base (some-> tx :transaction/date coerce/to-date-time (atime/unparse-local atime/normal-date))]
]
[:div
[:div.text-sm.font-medium.text-gray-500 "Bank Account"]
[:div.text-base (or (-> tx :transaction/bank-account :bank-account/name) "-")]
]
[:div
[:div.text-sm.font-medium.text-gray-500 "Post Date"]
[:div.text-base (some-> tx :transaction/post-date coerce/to-date-time (atime/unparse-local atime/normal-date))]
]
[:div
[:div.text-sm.font-medium.text-gray-500 "Original Description"]
[:div.text-base (or (:transaction/description-original tx) "-")]
]
[:div
[:div.text-sm.font-medium.text-gray-500 "Simplified Description"]
[:div.text-base (or (:transaction/description-simple tx) "-")]
]
[:div
[:div.text-sm.font-medium.text-gray-500 "Check Number"]
[:div.text-base (or (:transaction/check-number tx) "-")]
]
[:div
[:div.text-sm.font-medium.text-gray-500 "Status"]
[:div.text-base (or (some-> tx :transaction/status) "-")]
]
[:div
[:div.text-sm.font-medium.text-gray-500 "Transaction Type"]
[:div.text-base (or (some-> tx :transaction/type) "-")]
]
]]
;; Hidden ID field
(fc/with-field :db/id (fc/with-field :db/id
(when extant? (com/hidden {:name (fc/field-name)
(com/hidden {:name (fc/field-name) :value (fc/field-value)}))
:value (fc/field-value)})))
;; Hidden client field
(fc/with-field :transaction/client (fc/with-field :transaction/client
(if (or (:client request) extant?) (com/hidden {:name (fc/field-name)
(com/hidden {:name (fc/field-name) :value (or (mm/get-mfs-field multi-form-state :transaction/client)
:value (or (mm/get-mfs-field multi-form-state :transaction/client) (:db/id (:client request)))}))
(:db/id (:client request)))})
(com/validated-field ;; Editable fields section
{:label "Client" [:div.mt-6
:errors (fc/field-errors)} [:h3.text-lg.font-semibold.mb-4 "Editable Fields"]]
[:div.w-96
(com/typeahead {:name (fc/field-name) ;; Vendor field
:error? (fc/error?)
:class "w-96"
:placeholder "Search..."
:url (bidi/path-for ssr-routes/only-routes :company-search)
:value (fc/field-value)
:content-fn (fn [c] (pull-attr (dc/db conn) :client/name c))
:x-model "clientId"})])))
(fc/with-field :transaction/vendor (fc/with-field :transaction/vendor
(com/validated-field (com/validated-field
{:label "Vendor" {:label "Vendor"
@@ -308,6 +343,7 @@
"Add new vendor") "Add new vendor")
" in a new window, then return here."]] " in a new window, then return here."]]
;; Memo field
(fc/with-field :transaction/memo (fc/with-field :transaction/memo
(com/validated-field (com/validated-field
{:label "Memo" {:label "Memo"
@@ -318,6 +354,7 @@
:error? (fc/field-errors) :error? (fc/field-errors)
:placeholder "Optional note"})])) :placeholder "Optional note"})]))
;; Approval status field
(fc/with-field :transaction/approval-status (fc/with-field :transaction/approval-status
(com/validated-field (com/validated-field
{:label "Status" {:label "Status"
@@ -327,10 +364,7 @@
:value (name (or (fc/field-value) :transaction-approval-status/unapproved)) :value (name (or (fc/field-value) :transaction-approval-status/unapproved))
:name (fc/field-name)})))]) :name (fc/field-name)})))])
:footer :footer
(mm/default-step-footer linear-wizard this :validation-route ::route/edit-wizard-navigate (mm/default-step-footer linear-wizard this :validation-route ::route/edit-wizard-navigate)
#_#_:next-button (com/button {:color :primary :x-ref "next" :class "w-32"
:hx-put (bidi.bidi/path-for ssr-routes/only-routes
::route/edit-wizard-navigate)} "Next"))
:validation-route ::route/edit-wizard-navigate))) :validation-route ::route/edit-wizard-navigate)))
mm/Initializable mm/Initializable
@@ -576,39 +610,53 @@
(let [tx-id (or (-> request :multi-form-state :snapshot :db/id) (let [tx-id (or (-> request :multi-form-state :snapshot :db/id)
(get-in request [:route-params :db/id])) (get-in request [:route-params :db/id]))
tx (when tx-id (d-transactions/get-by-id tx-id)) tx (when tx-id (d-transactions/get-by-id tx-id))
patterns (dc/q '[:find ?r ?name ?pattern patterns (dc/q '[:find (pull ?r
[:db/id
:transaction-rule/description
:transaction-rule/note
:transaction-rule/client-group
:transaction-rule/dom-gte :transaction-rule/dom-lte
:transaction-rule/amount-gte :transaction-rule/amount-lte
:transaction-rule/client :transaction-rule/bank-account
:transaction-rule/yodlee-merchant])
:where :where
[?r :transaction-rule/description ?pattern] [?r :transaction-rule/description]
[?r :transaction-rule/name ?name]] ]
(dc/db conn))] (dc/db conn))]
(when tx (when tx
patterns (->> patterns
#_(filter (fn [[rule-id rule-name pattern]] (map first)
(rm/pattern-matches? pattern (:transaction/description-original tx))) (filter (fn [rule]
patterns)))) (rm/rule-applies? (-> tx
(update :transaction/date coerce/to-date)
) (-> rule
(update :transaction-rule/description #(some-> % iol-ion.query/->pattern))))))
))))
(defn transaction-rules-view [request] (defn transaction-rules-view [request]
(let [matching-rules (get-available-rules request)] (let [matching-rules (get-available-rules request)]
(alog/peek ::MATCHING matching-rules)
[:div [:div
(if (seq matching-rules) (if (seq matching-rules)
[:div [:div
[:h3.text-lg.font-bold.mb-4 "Matching Transaction Rules"] [:h3.text-lg.font-bold.mb-4 "Matching Transaction Rules"]
[:div.space-y-2 [:div.space-y-2
(for [[rule-id rule-name pattern] matching-rules] (for [{:keys [:db/id :transaction-rule/note :transaction-rule/description]} matching-rules]
[:form.py-2.border-b.border-gray-200 {:hx-post (bidi/path-for ssr-routes/only-routes [:div.py-2.border-b.border-gray-200 {:hx-post (bidi/path-for ssr-routes/only-routes
::route/apply-rule) ::route/apply-rule)
:hx-target "#modal-holder" :hx-trigger "applyRule"
:hx-swap "outerHTML"} :hx-target "#modal-holder"
:hx-swap "outerHTML"}
(com/hidden {:name "transaction-id" (com/hidden {:name "transaction-id"
:value (get-in request [:multi-form-state :snapshot :db/id])}) :value (get-in request [:multi-form-state :snapshot :db/id])})
(com/hidden {:name "rule-id" (com/hidden {:name "rule-id"
:value rule-id}) :value id})
[:div.flex.justify-between.items-center [:div.flex.justify-between.items-center
[:div.space-y-1 [:div.space-y-1
[:div.font-medium rule-name] [:div.font-medium note]
[:div.text-sm.text-gray-600 [:div.text-sm.text-gray-600
(str "Pattern: " pattern)]] (str "Pattern: " description)]]
(com/button {:color :primary :size :small} "Apply")]])]] (com/a-button {:color :primary :size :small "@click" "$dispatch('applyRule')"} "Apply")]])]]
[:div.text-center.py-4.text-gray-500 "No matching rules found for this transaction."])])) [:div.text-center.py-4.text-gray-500 "No matching rules found for this transaction."])]))
(defn payment-info-view [request] (defn payment-info-view [request]
@@ -704,7 +752,7 @@
:accounts :accounts
:links]) :links])
(get-step [this step-key] (get-step [this step-key]
(let [step-key-result (mc/parse mm/step-key-schema step-key) (let [step-key-result (mc/parse mm/step-key-schema step-key)
[step-key-type step-key] step-key-result] [step-key-type step-key] step-key-result]
(get {:basic-details (->BasicDetailsStep this) (get {:basic-details (->BasicDetailsStep this)
:accounts (->AccountsStep this) :accounts (->AccountsStep this)
@@ -716,10 +764,8 @@
(let [tx-data (-> multi-form-state :snapshot) (let [tx-data (-> multi-form-state :snapshot)
tx-id (:db/id tx-data) tx-id (:db/id tx-data)
client-id (->db-id (:transaction/client tx-data)) client-id (->db-id (:transaction/client tx-data))
existing-tx (when tx-id (d-transactions/get-by-id tx-id)) existing-tx (d-transactions/get-by-id tx-id)
transaction [:upsert-transaction (cond-> tx-data transaction [:upsert-transaction (assoc tx-data :db/id tx-id)]]
true (dissoc :db/id)
tx-id (assoc :db/id tx-id))]]
(alog/info ::transaction transaction :entity transaction) (alog/info ::transaction transaction :entity transaction)
(exception->4xx #(assert-can-see-client (:identity request) client-id)) (exception->4xx #(assert-can-see-client (:identity request) client-id))
@@ -739,7 +785,7 @@
(let [transaction-result (audit-transact [transaction] (:identity request))] (let [transaction-result (audit-transact [transaction] (:identity request))]
(try (try
(solr/touch-with-ledger (or tx-id (get-in transaction-result [:tempids "invoice"]))) (solr/touch-with-ledger tx-id)
(catch Exception e (catch Exception e
(alog/error ::cant-save-solr :error e))) (alog/error ::cant-save-solr :error e)))
@@ -751,24 +797,24 @@
(defn initial-edit-wizard-state [request] (defn initial-edit-wizard-state [request]
(let [tx-id (-> request :route-params :db/id) (let [tx-id (-> request :route-params :db/id)
entity (when tx-id entity (dc/pull (dc/db conn)
(dc/pull (dc/db conn) '[:db/id
'[:db/id :transaction/vendor
:transaction/vendor :transaction/client
:transaction/client :transaction/description-original
:transaction/memo :transaction/status
{ [ :transaction/approval-status :xform iol-ion.query/ident] [:db/ident]} :transaction/type
:transaction/amount :transaction/memo
:transaction/accounts] { [ :transaction/approval-status :xform iol-ion.query/ident] [:db/ident]}
tx-id)) :transaction/amount
entity (if entity :transaction/accounts]
(-> entity tx-id)
(update :transaction/vendor :db/id) entity (-> entity
(update :transaction/client :db/id)) (update :transaction/vendor :db/id)
{})] (update :transaction/client :db/id))]
(mm/->MultiStepFormState entity (mm/->MultiStepFormState entity
[] []
entity))) entity)))
(defn match-payment [{{:strs [transaction-id payment-id]} :form-params :as request}] (defn match-payment [{{:strs [transaction-id payment-id]} :form-params :as request}]
(let [transaction-id (Long/parseLong transaction-id) (let [transaction-id (Long/parseLong transaction-id)
@@ -916,7 +962,8 @@
(defn apply-rule [{{:strs [transaction-id rule-id]} :form-params :as request}] (defn apply-rule [{{:strs [transaction-id rule-id]} :form-params :as request}]
(let [transaction-id (Long/parseLong transaction-id) (let [transaction-id (Long/parseLong transaction-id)
rule-id (Long/parseLong rule-id) rule-id (Long/parseLong rule-id)
transaction (d-transactions/get-by-id transaction-id) transaction (-> (d-transactions/get-by-id transaction-id)
(update :transaction/date coerce/to-date)) ;; TODO make rule application flexible for date-time and dates
transaction-rule (dc/pull (dc/db conn) transaction-rule (dc/pull (dc/db conn)
[:transaction-rule/description [:transaction-rule/description
:transaction-rule/vendor :transaction-rule/vendor
@@ -941,6 +988,7 @@
:transaction/amount (:transaction/amount transaction)} :transaction/amount (:transaction/amount transaction)}
transaction-rule transaction-rule
locations)] locations)]
(alog/peek ::APPLY-RULE updated-tx)
(audit-transact [[:upsert-transaction updated-tx]] (:identity request))) (audit-transact [[:upsert-transaction updated-tx]] (:identity request)))
(solr/touch-with-ledger transaction-id) (solr/touch-with-ledger transaction-id)