Removes old login page, more progress on transactions

This commit is contained in:
2025-03-10 14:09:45 -07:00
parent 8429d8516c
commit 7373ef41d1
16 changed files with 270 additions and 137 deletions

View File

@@ -27,7 +27,7 @@
[auto-ap.ssr.utils
:refer [->db-id apply-middleware-to-all-handlers check-allowance
check-location-belongs entity-id html-response modal-response
ref->enum-schema strip wrap-schema-enforce]]
ref->enum-schema strip wrap-entity wrap-schema-enforce]]
[auto-ap.time :as atime]
[bidi.bidi :as bidi]
[clj-time.coerce :as coerce]
@@ -261,8 +261,7 @@
:body (mm/default-step-body
{}
[:div {:x-data (hx/json {:clientId (or (fc/field-value (:transaction/client fc/*current*))
(:db/id (:client request)))
:vendorId (fc/field-value (:transaction/vendor fc/*current*))})}
(:db/id (:client request))) })}
;; Read-only transaction details
[:div.mb-6.border.rounded-lg.p-4.bg-gray-50
@@ -380,8 +379,7 @@
:placeholder "Search..."
:url (bidi/path-for ssr-routes/only-routes :vendor-search)
:value (fc/field-value)
:content-fn (fn [c] (pull-attr (dc/db conn) :vendor/name c))
:x-model "vendorId"})]))
:content-fn (fn [c] (pull-attr (dc/db conn) :vendor/name c)) })]))
[:div.mb-4
[:span.text-sm.text-gray-500 "Can't find the vendor? "
(com/link {:href (bidi.bidi/path-for
@@ -525,11 +523,11 @@
(defn get-available-payments [request]
(let [tx-id (or (-> request :multi-form-state :snapshot :db/id)
(let [tx-id (or (get-in request [:form-params :transaction-id])
(-> request :multi-form-state :snapshot :db/id)
(get-in request [:route-params :db/id]))
tx (when tx-id (d-transactions/get-by-id tx-id))
client-id (or (get-in request [:multi-form-state :snapshot :transaction/client])
(get-in request [:client :db/id]))
client-id (-> tx :transaction/client :db/id)
payments (when client-id
(dc/q '[:find [(pull ?p [:db/id :payment/invoice-number :payment/amount :payment/date
{:payment/vendor [:db/id :vendor/name]}]) ...]
@@ -541,36 +539,7 @@
client-id))]
(filter #(dollars= (Math/abs (:transaction/amount tx)) (:payment/amount %)) payments)))
(defn payment-matches-view [request]
(let [payments (get-available-payments request)]
[:div
(if (seq payments)
[:div
[:h3.text-lg.font-bold.mb-4 "Available Payments"]
[:div {:hx-post (bidi/path-for ssr-routes/only-routes ::route/match-payment)
:hx-trigger "matchPayment"
:hx-target "#modal-holder"
:hx-include "this"
:hx-swap "outerHTML"}
(com/hidden {:name "action"
:value "link-payment"
:form ""})
(com/hidden {:name "transaction-id"
:value (-> request :multi-form-state :snapshot :db/id)
:form ""})
[:div.space-y-2
[:label.block.text-sm.font-medium.mb-1 "Select a payment to match:"]
(when payments
(com/radio-card {:options (for [payment payments]
{:value (:db/id payment)
:content (str (:payment/invoice-number payment) " - "
(-> payment :payment/vendor :vendor/name)
" - Amount: $" (format "%.2f" (:payment/amount payment))
" • Date: " (some-> payment :payment/date coerce/to-date-time (atime/unparse-local atime/normal-date)))})
:name "payment-id"
:width "w-full"}))
(com/a-button {"@click" "$dispatch('matchPayment')"} "Match" #_[:button.mt-4.w-full.py-2.bg-blue-500.text-white.rounded.hover:bg-blue-600 "Match"])]] ]
[:div.text-center.py-4.text-gray-500 "No matching payments available for this transaction."]) ]))
(defn get-available-autopay-invoices [request]
(let [tx-id (or (-> request :multi-form-state :snapshot :db/id)
@@ -705,7 +674,7 @@
[:button.mt-4.w-full.py-2.bg-blue-500.text-white.rounded.hover:bg-blue-600 "Apply"]]]
[:div.text-center.py-4.text-gray-500 "No matching rules found for this transaction."])]))
(defn payment-info-view [request]
(defn linked-payment-view [request]
(let [tx-id (or (-> request :multi-form-state :snapshot :db/id)
(get-in request [:route-params :db/id]))
tx (when tx-id (d-transactions/get-by-id tx-id))
@@ -738,17 +707,52 @@
[:div.font-medium "Date"]
[:div (some-> payment :payment/date (atime/unparse-local atime/normal-date))]]
[:div.mt-4 {:hx-post (bidi/path-for ssr-routes/only-routes ::route/unlink-payment)
:hx-params "transaction-id"
:hx-params "transaction-id, action"
:hx-trigger "unlinkPayment"
:hx-target "#payment-matches"
:hx-include "this"
:hx-target "#modal-holder"
:hx-swap "outerHTML"
:hx-confirm "Are you sure you want to unlink this payment?"}
(com/hidden {:name "action"
:value "unlink-payment"
:form ""})
(com/hidden {:name "transaction-id" :value tx-id :form ""})
(com/a-button {:color :red :size :small
"@click" "$dispatch('unlinkPayment')"} "Unlink Payment")]]])))
(defn payment-matches-view [request]
(let [payments (get-available-payments request)]
[:div#payment-matches
(linked-payment-view request)
(if (seq payments)
[:div
[:h3.text-lg.font-bold.mb-4 "Available Payments"]
[:div {:hx-post (bidi/path-for ssr-routes/only-routes ::route/link-payment)
:hx-trigger "matchPayment"
:hx-target "#modal-holder"
:hx-include "this"
:hx-swap "outerHTML"}
(com/hidden {:name "action"
:value "link-payment"
:form ""})
(com/hidden {:name "transaction-id"
:value (-> request :entity :db/id)
:form ""})
[:div.space-y-2
[:label.block.text-sm.font-medium.mb-1 "Select a payment to match:"]
(when payments
(com/radio-card {:options (for [payment payments]
{:value (:db/id payment)
:content (str (:payment/invoice-number payment) " - "
(-> payment :payment/vendor :vendor/name)
" - Amount: $" (format "%.2f" (:payment/amount payment))
" • Date: " (some-> payment :payment/date coerce/to-date-time (atime/unparse-local atime/normal-date)))})
:name "payment-id"
:width "w-full"}))
(com/a-button {"@click" "$dispatch('matchPayment')"} "Match" #_[:button.mt-4.w-full.py-2.bg-blue-500.text-white.rounded.hover:bg-blue-600 "Match"])]]]
[:div.text-center.py-4.text-gray-500 "No matching payments available for this transaction."])]))
(defn count-payment-matches [request]
(count (get-available-payments request)))
@@ -781,8 +785,12 @@
:body (mm/default-step-body
{}
[:div
(payment-info-view request)
[:div {:x-data "{ activeForm: null }"}
[:div {:x-data (hx/json {:activeForm (if (:transaction/payment (:entity request))
"payment"
nil)
:canChange (boolean (not (:transaction/payment (:entity request))))})
"@unlinked" "canChange=true"}
[:div {:class "flex space-x-2 mb-4"}
(com/button-group {:name "method"}
(com/button-group-button {"@click" "activeForm = 'payment'" :value "payment" ":class" "{ '!bg-primary-200 text-primary-800': activeForm === 'payment'}" :class "relative"}
@@ -790,24 +798,29 @@
(when (> count 0)
(com/badge {:color "green"} (str count))))
"Link to payment")
(com/button-group-button {"@click" "activeForm = 'unpaid'" :value "unpaid" ":class" "{ '!bg-primary-200 text-primary-800': activeForm === 'unpaid'}" :class "relative"}
(com/button-group-button {"@click" "activeForm = 'unpaid'" :value "unpaid" ":class" "{ '!bg-primary-200 text-primary-800': activeForm === 'unpaid'}" :class "relative"
":disabled" "!canChange"}
(let [count (count-unpaid-invoice-matches request)]
(when (> count 0)
(com/badge {:color "green"} (str count))))
"Link to unpaid invoices")
(com/button-group-button {"@click" "activeForm = 'autopay'" :value "autopay" ":class" "{ '!bg-primary-200 text-primary-800': activeForm === 'autopay'}" :class "relative"}
(com/button-group-button {"@click" "activeForm = 'autopay'" :value "autopay" ":class" "{ '!bg-primary-200 text-primary-800': activeForm === 'autopay'}" :class "relative"
":disabled" "!canChange"}
(let [count (count-autopay-invoice-matches request)]
(when (> count 0)
(com/badge {:color "green"} (str count))))
"Link to autopay invoices")
(com/button-group-button {"@click" "activeForm = 'rule'" :value "rule" ":class" "{ '!bg-primary-200 text-primary-800': activeForm === 'rule'}" :class "relative"}
(com/button-group-button {"@click" "activeForm = 'rule'" :value "rule" ":class" "{ '!bg-primary-200 text-primary-800': activeForm === 'rule'}" :class "relative"
":disabled" "!canChange"}
(let [count (count-rule-matches request)]
(when (> count 0)
(com/badge {:color "green"} (str count))))
"Apply rule")
(com/button-group-button {"@click" "activeForm = 'manual'" :value "manual" ":class" "{ '!bg-primary-200 text-primary-800': activeForm === 'manual'}"}
(com/button-group-button {"@click" "activeForm = 'manual'" :value "manual" ":class" "{ '!bg-primary-200 text-primary-800': activeForm === 'manual'}"
":disabled" "!canChange"}
"Manual"))]
[:div {:x-show "activeForm === 'payment'", :x-transition:enter "transition ease-out duration-500", :x-transition:enter-start "opacity-0 transform scale-95", :x-transition:enter-end "opacity-100 transform scale-100"}
(payment-matches-view request)]
[:div {:x-show "activeForm === 'unpaid'", :x-transition:enter "transition ease-out duration-500", :x-transition:enter-start "opacity-0 transform scale-95", :x-transition:enter-end "opacity-100 transform scale-100"}
(unpaid-invoices-view request)]
@@ -960,9 +973,9 @@
[]
entity)))
(defn match-payment [{{:keys [transaction-id match-payment-id]} :form-params :as request}]
(defn link-payment [{{:keys [transaction-id payment-id]} :form-params :as request}]
(let [transaction (d-transactions/get-by-id transaction-id)
payment (d-checks/get-by-id match-payment-id)]
payment (d-checks/get-by-id payment-id)]
(exception->4xx #(assert-can-see-client (:identity request) (-> transaction :transaction/client :db/id)))
(exception->4xx #(assert-can-see-client (:identity request) (-> payment :payment/client :db/id)))
@@ -1000,7 +1013,7 @@
[:p.text-gray-600.mt-2 "The transaction has been linked to the autopay invoices."]
[:p.text-gray-600.mt-2 "To view the new payment, click "
(com/link {:href (hu/url (bidi/path-for ssr-routes/only-routes ::payment-route/all-page)
{:exact-match-id match-payment-id})
{:exact-match-id payment-id})
:hx-boost true}
"here")
" to view it."])
@@ -1201,8 +1214,10 @@
(:identity request))))
(solr/touch-with-ledger transaction-id)
(html-response (payment-matches-view request)
:headers {"hx-trigger" "unlinked"})
(modal-response
#_(modal-response
(com/success-modal {:title "Transaction unlinked successfully"}
[:p.text-gray-600.mt-2 "The transaction has been unlinked from its payment."]
@@ -1245,40 +1260,42 @@
{::route/edit-wizard (-> mm/open-wizard-handler
(mm/wrap-wizard edit-wizard)
(mm/wrap-init-multi-form-state initial-edit-wizard-state)
(wrap-entity [:route-params :db/id] d-transactions/default-read)
(wrap-schema-enforce :route-schema [:map [:db/id entity-id]]))
::route/edit-wizard-navigate (-> mm/next-handler
(wrap-entity [:multi-form-state :snapshot :db/id] d-transactions/default-read)
(mm/wrap-wizard edit-wizard)
(mm/wrap-decode-multi-form-state))
::route/edit-submit (-> mm/submit-handler
(mm/wrap-wizard edit-wizard)
(mm/wrap-decode-multi-form-state))
::route/location-select (-> location-select
(wrap-schema-enforce :query-schema [:map
[:name :string]
[:client-id {:optional true}
[:maybe entity-id]]
[:account-id {:optional true}
[:maybe entity-id]]]))
(wrap-schema-enforce :query-schema [:map
[:name :string]
[:client-id {:optional true}
[:maybe entity-id]]
[:account-id {:optional true}
[:maybe entity-id]]]))
::route/account-total (-> account-total
(mm/wrap-wizard edit-wizard)
(mm/wrap-decode-multi-form-state))
::route/account-balance (-> account-balance
(mm/wrap-wizard edit-wizard)
(mm/wrap-decode-multi-form-state))
::route/account-balance (-> account-balance
(mm/wrap-wizard edit-wizard)
(mm/wrap-decode-multi-form-state))
::route/edit-wizard-new-account (->
(add-new-entity-handler [:step-params :transaction/accounts]
(fn render [cursor request]
(transaction-account-row*
{:value cursor
:client-id (:client-id (:query-params request))}))
(fn build-new-row [base _]
(assoc base :transaction-account/location "Shared")))
(fn render [cursor request]
(transaction-account-row*
{:value cursor
:client-id (:client-id (:query-params request))}))
(fn build-new-row [base _]
(assoc base :transaction-account/location "Shared")))
(wrap-schema-enforce :query-schema [:map
[:client-id {:optional true}
[:maybe entity-id]]]))
::route/match-payment (-> match-payment
(wrap-schema-enforce :form-schema
save-schema))
::route/link-payment (-> link-payment
(wrap-schema-enforce :form-schema
save-schema))
::route/match-autopay-invoices (-> match-autopay-invoices
(wrap-schema-enforce :form-schema
[:map [:transaction-id entity-id]
@@ -1288,11 +1305,12 @@
[:map [:transaction-id entity-id]
[:unpaid-invoice-ids [:vector {:coerce? true} entity-id]]]))
::route/apply-rule (-> apply-rule
(wrap-schema-enforce :form-schema
[:map [:transaction-id entity-id]
[:rule-id entity-id]]))
(wrap-schema-enforce :form-schema
[:map [:transaction-id entity-id]
[:rule-id entity-id]]))
::route/unlink-payment (-> unlink-payment
(wrap-schema-enforce :form-schema
(wrap-entity [:form-params :transaction-id] d-transactions/default-read)
(wrap-schema-enforce :form-schema
save-schema))}
(fn [h]
(-> h