fixes
This commit is contained in:
@@ -25,8 +25,9 @@
|
||||
[auto-ap.ssr.svg :as svg]
|
||||
[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-entity wrap-schema-enforce]]
|
||||
check-location-belongs entity-id form-validation-error
|
||||
html-response modal-response ref->enum-schema strip wrap-entity
|
||||
wrap-schema-enforce]]
|
||||
[auto-ap.time :as atime]
|
||||
[bidi.bidi :as bidi]
|
||||
[clj-time.coerce :as coerce]
|
||||
@@ -34,8 +35,7 @@
|
||||
[hiccup.util :as hu]
|
||||
[iol-ion.query :refer [dollars=]]
|
||||
[iol-ion.tx :refer [random-tempid]]
|
||||
[malli.core :as mc]
|
||||
[malli.util :as mut]))
|
||||
[malli.core :as mc]))
|
||||
|
||||
(def transaction-approval-status
|
||||
{:transaction-approval-status/unapproved "Unapproved"
|
||||
@@ -627,45 +627,30 @@
|
||||
[: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, action"
|
||||
:hx-trigger "unlinkPayment"
|
||||
:hx-target "#payment-matches"
|
||||
:hx-include "this"
|
||||
: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")]]])
|
||||
(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.space-y-2
|
||||
[:label.block.text-sm.font-medium.mb-1 "Select a payment to match:"]
|
||||
(when payments
|
||||
(let [payment-id-field (fc/with-field :payment-id (fc/field-name ))]
|
||||
(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-field
|
||||
: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]
|
||||
@@ -809,8 +794,9 @@
|
||||
(-> request :multi-form-state :snapshot :action)))
|
||||
|
||||
(defmethod save-handler
|
||||
:link-payment [{{:keys [transaction-id payment-id]} :form-params :as request transaction :entity}]
|
||||
(let [payment (d-checks/get-by-id payment-id)]
|
||||
:link-payment [{{ {:keys [transaction-id payment-id]} :snapshot} :multi-form-state :as request transaction :entity}]
|
||||
(let [_ (println "PAYMENT ID IS")
|
||||
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)))
|
||||
@@ -818,7 +804,10 @@
|
||||
|
||||
(when (not= (-> transaction :transaction/client :db/id)
|
||||
(-> payment :payment/client :db/id))
|
||||
(throw (ex-info "Clients don't match" {:validation-error "Payment and client do not match."})))
|
||||
(form-validation-error "Clients don't match."
|
||||
:payment-client-id (:payment/client payment)
|
||||
:transaction-client-id (:transaction/client transaction))
|
||||
#_(throw (ex-info "Clients don't match" {:validation-error "Payment and client do not match."})))
|
||||
|
||||
(when-not (dollars= (- (:transaction/amount transaction))
|
||||
(:payment/amount payment))
|
||||
@@ -828,7 +817,7 @@
|
||||
[{:db/id (:db/id payment)
|
||||
:payment/status :payment-status/cleared
|
||||
:payment/date (coerce/to-date (first (sort [(:payment/date payment)
|
||||
(:transaction/date transaction)])))}
|
||||
(coerce/to-date-time (:transaction/date transaction))])))}
|
||||
|
||||
[:upsert-transaction
|
||||
{:db/id (:db/id transaction)
|
||||
@@ -1025,86 +1014,74 @@
|
||||
[:div]
|
||||
:headers {"hx-trigger" "modalclose"}))))
|
||||
|
||||
(defn unlink-payment [{{:keys [transaction-id] :as fp} :form-params :as request}]
|
||||
(let [transaction (dc/pull (dc/db conn)
|
||||
'[:transaction/approval-status
|
||||
(defn unlink-payment [{{{transaction-id :db/id} :snapshot} :multi-form-state :as request}]
|
||||
|
||||
(fc/start-form (:multi-form-state request) (when (:form-errors request) {:step-params (:form-errors request)})
|
||||
(let [transaction (dc/pull (dc/db conn)
|
||||
'[:transaction/approval-status
|
||||
|
||||
:transaction/date
|
||||
:transaction/location
|
||||
:transaction/vendor
|
||||
:transaction/accounts
|
||||
:transaction/status
|
||||
:transaction/client [:db/id]
|
||||
{:transaction/payment [:payment/date
|
||||
{[:payment/status :xform iol-ion.query/ident] [:db/ident]} :db/id]}]
|
||||
transaction-id)
|
||||
payment (-> transaction :transaction/payment)]
|
||||
:transaction/date
|
||||
:transaction/location
|
||||
:transaction/vendor
|
||||
:transaction/accounts
|
||||
:transaction/status
|
||||
:transaction/client [:db/id]
|
||||
{:transaction/payment [:payment/date
|
||||
{[:payment/status :xform iol-ion.query/ident] [:db/ident]} :db/id]}]
|
||||
transaction-id)
|
||||
payment (-> transaction :transaction/payment)]
|
||||
|
||||
(exception->4xx #(assert-can-see-client (:identity request) (-> transaction :transaction/client :db/id)))
|
||||
(exception->4xx #(assert-not-locked (-> transaction :transaction/client :db/id) (:transaction/date transaction)))
|
||||
(exception->4xx #(assert-can-see-client (:identity request) (-> transaction :transaction/client :db/id)))
|
||||
(exception->4xx #(assert-not-locked (-> transaction :transaction/client :db/id) (:transaction/date transaction)))
|
||||
|
||||
(when (not= :payment-status/cleared (-> payment :payment/status))
|
||||
(throw (ex-info "Payment can't be undone because it isn't cleared."
|
||||
{:validation-error "Payment can't be undone because it isn't cleared."})))
|
||||
(when (not= :payment-status/cleared (-> payment :payment/status))
|
||||
(throw (ex-info "Payment can't be undone because it isn't cleared."
|
||||
{:validation-error "Payment can't be undone because it isn't cleared."})))
|
||||
|
||||
(let [is-autopay-payment? (some->> (dc/q {:find ['?sp]
|
||||
:in ['$ '?payment]
|
||||
:where ['[?ip :invoice-payment/payment ?payment]
|
||||
'[?ip :invoice-payment/invoice ?i]
|
||||
'[(get-else $ ?i :invoice/scheduled-payment "N/A") ?sp]]}
|
||||
(dc/db conn) (:db/id payment))
|
||||
seq
|
||||
(map first)
|
||||
(every? #(instance? java.util.Date %)))]
|
||||
(if is-autopay-payment?
|
||||
(audit-transact
|
||||
(-> [{:db/id (:db/id payment)
|
||||
:payment/status :payment-status/pending}
|
||||
[:upsert-transaction
|
||||
{:db/id (:db/id transaction)
|
||||
:transaction/approval-status :transaction-approval-status/unapproved
|
||||
:transaction/payment nil
|
||||
:transaction/vendor nil
|
||||
:transaction/location nil
|
||||
:transaction/accounts nil}]
|
||||
[:db/retractEntity (:db/id payment)]]
|
||||
(into (map (fn [[invoice-payment]]
|
||||
[:db/retractEntity invoice-payment])
|
||||
(dc/q {:find ['?ip]
|
||||
:in ['$ '?p]
|
||||
:where ['[?ip :invoice-payment/payment ?p]]}
|
||||
(dc/db conn)
|
||||
(:db/id payment)))))
|
||||
(:identity request))
|
||||
(audit-transact
|
||||
[{:db/id (:db/id payment)
|
||||
:payment/status :payment-status/pending}
|
||||
[:upsert-transaction
|
||||
{:db/id (:db/id transaction)
|
||||
:transaction/approval-status :transaction-approval-status/unapproved
|
||||
:transaction/payment nil
|
||||
:transaction/vendor nil
|
||||
:transaction/location nil
|
||||
:transaction/accounts nil}]]
|
||||
(:identity request))))
|
||||
(let [is-autopay-payment? (some->> (dc/q {:find ['?sp]
|
||||
:in ['$ '?payment]
|
||||
:where ['[?ip :invoice-payment/payment ?payment]
|
||||
'[?ip :invoice-payment/invoice ?i]
|
||||
'[(get-else $ ?i :invoice/scheduled-payment "N/A") ?sp]]}
|
||||
(dc/db conn) (:db/id payment))
|
||||
seq
|
||||
(map first)
|
||||
(every? #(instance? java.util.Date %)))]
|
||||
(if is-autopay-payment?
|
||||
(audit-transact
|
||||
(-> [{:db/id (:db/id payment)
|
||||
:payment/status :payment-status/pending}
|
||||
[:upsert-transaction
|
||||
{:db/id (:db/id transaction)
|
||||
:transaction/approval-status :transaction-approval-status/unapproved
|
||||
:transaction/payment nil
|
||||
:transaction/vendor nil
|
||||
:transaction/location nil
|
||||
:transaction/accounts nil}]
|
||||
[:db/retractEntity (:db/id payment)]]
|
||||
(into (map (fn [[invoice-payment]]
|
||||
[:db/retractEntity invoice-payment])
|
||||
(dc/q {:find ['?ip]
|
||||
:in ['$ '?p]
|
||||
:where ['[?ip :invoice-payment/payment ?p]]}
|
||||
(dc/db conn)
|
||||
(:db/id payment)))))
|
||||
(:identity request))
|
||||
(audit-transact
|
||||
[{:db/id (:db/id payment)
|
||||
:payment/status :payment-status/pending}
|
||||
[:upsert-transaction
|
||||
{:db/id (:db/id transaction)
|
||||
:transaction/approval-status :transaction-approval-status/unapproved
|
||||
:transaction/payment nil
|
||||
:transaction/vendor nil
|
||||
:transaction/location nil
|
||||
:transaction/accounts nil}]]
|
||||
(:identity request))))
|
||||
|
||||
(solr/touch-with-ledger (:db/id transaction))
|
||||
(html-response (payment-matches-view request)
|
||||
:headers {"hx-trigger" "unlinked"})
|
||||
|
||||
#_(modal-response
|
||||
(com/success-modal {:title "Transaction unlinked successfully"}
|
||||
|
||||
[:p.text-gray-600.mt-2 "The transaction has been unlinked from its payment."]
|
||||
[:p "If you'd like to also void the payment, click "
|
||||
(com/link
|
||||
{:hx-boost true
|
||||
:href (hu/url (bidi/path-for ssr-routes/only-routes ::payment-route/all-page)
|
||||
{:exact-match-id (:db/id payment)})}
|
||||
"here")
|
||||
" to view the payment"])
|
||||
|
||||
:headers {"hx-trigger" "invalidated"})))
|
||||
(solr/touch-with-ledger (:db/id transaction))
|
||||
(html-response (fc/with-field :step-params (payment-matches-view request))
|
||||
:headers {"hx-trigger" "unlinked"}))))
|
||||
|
||||
#_(def save-schema
|
||||
(mc/schema
|
||||
@@ -1143,6 +1120,7 @@
|
||||
(form-schema [_]
|
||||
edit-form-schema)
|
||||
(submit [this {:keys [multi-form-state request-method identity] :as request}]
|
||||
(println "SUBMITTING")
|
||||
(save-handler request)
|
||||
))
|
||||
|
||||
@@ -1209,9 +1187,11 @@
|
||||
[:client-id {:optional true}
|
||||
[:maybe entity-id]]]))
|
||||
|
||||
#_#_::route/unlink-payment (-> unlink-payment
|
||||
(wrap-entity [:form-params :transaction-id] d-transactions/default-read)
|
||||
(wrap-schema-enforce :form-schema
|
||||
::route/unlink-payment (-> unlink-payment
|
||||
(wrap-entity [:multi-form-state :snapshot :db/id] d-transactions/default-read)
|
||||
(mm/wrap-wizard edit-wizard)
|
||||
(mm/wrap-decode-multi-form-state)
|
||||
#_(wrap-schema-enforce :form-schema
|
||||
save-schema))}
|
||||
(fn [h]
|
||||
(-> h
|
||||
|
||||
@@ -29,13 +29,10 @@
|
||||
[:link {:rel "stylesheet", :href "/output.css"}]
|
||||
[:script {:src "https://cdn.plaid.com/link/v2/stable/link-initialize.js"}]
|
||||
[:script { :src "https://cdn.jsdelivr.net/npm/@ryangjchandler/alpine-tooltip@1.x.x/dist/cdn.min.js" :defer true}]
|
||||
[:link {:rel "stylesheet" :href "https://unpkg.com/tippy.js@6/dist/tippy.css"}]
|
||||
[:link {:rel "stylesheet" :href "https://unpkg.com/tippy.js@6/themes/light.css"}]
|
||||
(if (= "dev" (:dd-env env))
|
||||
[:script {:src "https://unpkg.com/htmx.org@1.9.6/dist/htmx.js"
|
||||
:crossorigin= "anonymous"}]
|
||||
[:script {:src "https://unpkg.com/htmx.org@1.9.6/dist/htmx.min.js"
|
||||
:crossorigin= "anonymous"}])
|
||||
[:link {:rel "stylesheet" :href "/css/tippy/tippy.css"}]
|
||||
[:link {:rel "stylesheet" :href "/css/tippy/light.css"}]
|
||||
[:script {:src "/js/htmx.min.js"
|
||||
:crossorigin= "anonymous"}]
|
||||
|
||||
[:script {:src "https://cdn.jsdelivr.net/npm/sortablejs@1.15.2/Sortable.min.js"}]
|
||||
[:script {:src "/js/htmx-disable.js"}]
|
||||
|
||||
@@ -196,6 +196,7 @@
|
||||
:form-errors (assoc-in {} path [m])}))))
|
||||
|
||||
(defn form-validation-error [m & {:as data}]
|
||||
(alog/warn ::form-validaiton-error :data data)
|
||||
(throw+ (ex-info m (merge data {:type :form-validation
|
||||
:form-validation-errors [m]}))))
|
||||
|
||||
|
||||
6
tasks
6
tasks
@@ -8,4 +8,8 @@
|
||||
* also add tests
|
||||
* Make sure that "Shared" really shares locations
|
||||
* make sure transactions support import-batch-id query parameter
|
||||
* make locked transactions clearer
|
||||
* make locked transactions clearer
|
||||
* unlinking then linking requires first closing the dialog.
|
||||
* make approved/unapproved be on the actions page
|
||||
* make memo on the acations page
|
||||
|
||||
|
||||
Reference in New Issue
Block a user