Improvements for transaction page
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -25,6 +25,5 @@
|
||||
|
||||
(alog/info ::closed :count (count invoices-to-close))))
|
||||
|
||||
|
||||
(defn -main [& _]
|
||||
(execute "close-auto-invoices" close-auto-invoices))
|
||||
|
||||
@@ -135,7 +135,7 @@
|
||||
:fetch-page fetch-page
|
||||
:page-specific-nav filters
|
||||
:row-buttons (fn [_ entity]
|
||||
[(com/a-icon-button {:href (hu/url (bidi/path-for ssr-routes/only-routes ::transaction-routes/all-page)
|
||||
[(com/a-icon-button {:href (hu/url (bidi/path-for ssr-routes/only-routes ::transaction-routes/page)
|
||||
{:import-batch-id (:db/id entity)})
|
||||
:hx-boost true}
|
||||
svg/external-link)])
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
(atime/unparse-local atime/standard-time)
|
||||
(#(str "Synced " %)))]
|
||||
|
||||
(when-let [n (cond (-> b :bank-account/intuit-bank-account)
|
||||
#_(when-let [n (cond (-> b :bank-account/intuit-bank-account)
|
||||
"Intuit"
|
||||
(-> b :bank-account/yodlee-account)
|
||||
"Yodlee"
|
||||
|
||||
@@ -171,6 +171,10 @@
|
||||
(merge-query {:query {:in ['?vendor-id]
|
||||
:where ['[?e :transaction/vendor ?vendor-id]]}
|
||||
:args [(:db/id (:vendor args))]})
|
||||
(:import-batch-id args)
|
||||
(merge-query {:query {:in ['?import-batch-id]
|
||||
:where ['[?import-batch-id :import-batch/entry ?e]]}
|
||||
:args [(:import-batch-id args)]})
|
||||
|
||||
(:status route-params)
|
||||
(merge-query {:query {:in ['?status]
|
||||
@@ -251,6 +255,7 @@
|
||||
[:amount-gte {:optional true} [:maybe :double]]
|
||||
[:amount-lte {:optional true} [:maybe :double]]
|
||||
[:client-id {:optional true} [:maybe entity-id]]
|
||||
[:import-batch-id {:optional true} [:maybe entity-id]]
|
||||
[:description {:optional true} [:maybe [:string {:decode/string strip}]]]
|
||||
[: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]}]]]
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
exception->4xx]]
|
||||
[auto-ap.import.transactions :as i-transactions]
|
||||
[auto-ap.logging :as alog]
|
||||
[auto-ap.permissions :refer [wrap-must]]
|
||||
[auto-ap.routes.payments :as payment-route]
|
||||
[auto-ap.routes.transactions :as route]
|
||||
[auto-ap.routes.utils
|
||||
@@ -26,11 +27,12 @@
|
||||
[auto-ap.ssr.utils
|
||||
:refer [->db-id apply-middleware-to-all-handlers check-allowance
|
||||
check-location-belongs entity-id form-validation-error
|
||||
html-response modal-response ref->enum-schema strip wrap-entity
|
||||
wrap-schema-enforce]]
|
||||
html-response modal-response ref->enum-schema strip temp-id
|
||||
wrap-entity wrap-schema-enforce]]
|
||||
[auto-ap.time :as atime]
|
||||
[bidi.bidi :as bidi]
|
||||
[clj-time.coerce :as coerce]
|
||||
[clojure.edn :as edn]
|
||||
[datomic.api :as dc]
|
||||
[hiccup.util :as hu]
|
||||
[iol-ion.query :refer [dollars=]]
|
||||
@@ -72,7 +74,7 @@
|
||||
[:vector {:coerce? true}
|
||||
[:and
|
||||
[:map
|
||||
[:db/id {:optional true} [:maybe entity-id]]
|
||||
[:db/id {:optional true} [:maybe [:or temp-id entity-id]]]
|
||||
[:transaction-account/account [:and entity-id
|
||||
[:fn {:error/message "Not an allowed account."}
|
||||
#(check-allowance % :account/default-allowance)]]]
|
||||
@@ -90,10 +92,11 @@
|
||||
[:transaction-id entity-id]]]
|
||||
[:link-unpaid-invoices [:map
|
||||
|
||||
[:unpaid-invoice-ids [:vector {:coerce? true} entity-id]]]]
|
||||
[:unpaid-invoice-ids {:decode/string (fn [x] (edn/read-string x))}
|
||||
[:vector {:coerce? true} entity-id]]]]
|
||||
[:link-autopay-invoices [:map
|
||||
|
||||
[:autopay-invoice-ids [:vector {:coerce? true} entity-id]]]]
|
||||
[:autopay-invoice-ids {:decode/string (fn [x] (edn/read-string x))} [:vector {:coerce? true} entity-id]]]]
|
||||
[:link-payment [:map
|
||||
[:payment-id entity-id]]]
|
||||
[:manual [:map
|
||||
@@ -378,9 +381,6 @@
|
||||
|
||||
|
||||
;; Editable fields section
|
||||
[:div.mt-6
|
||||
[:h3.text-lg.font-semibold.mb-4 "Editable Fields"]]
|
||||
|
||||
;; Vendor field
|
||||
)
|
||||
:footer
|
||||
@@ -416,7 +416,6 @@
|
||||
(get-in request [:route-params :db/id]))
|
||||
tx (when tx-id (d-transactions/get-by-id tx-id))
|
||||
client-id (-> request :entity :transaction/client :db/id)
|
||||
_ (println "TRANSACTION" client-id)
|
||||
matches-set (when (and tx client-id)
|
||||
(i-transactions/match-transaction-to-unfulfilled-autopayments
|
||||
(:transaction/amount tx)
|
||||
@@ -432,28 +431,20 @@
|
||||
(if (seq invoice-matches)
|
||||
[:div
|
||||
[:h3.text-lg.font-bold.mb-4 "Available Autopay Invoices"]
|
||||
[:div {:hx-post (bidi/path-for ssr-routes/only-routes ::route/link-autopay-invoices)
|
||||
:hx-include "this"
|
||||
:hx-trigger "linkAutopayInvoices"
|
||||
:hx-target "#modal-holder"
|
||||
:hx-swap "outerHTML"}
|
||||
(com/hidden {:name "action"
|
||||
:value "link-autopay-invoices"})
|
||||
(com/hidden {:name "transaction-id"
|
||||
:value (get-in request [:multi-form-state :snapshot :db/id])
|
||||
:form ""})
|
||||
[:div.space-y-2
|
||||
[:label.block.text-sm.font-medium.mb-1 "Select an autopay invoice to apply:"]
|
||||
(doall (for [match-group invoice-matches]
|
||||
(doall (for [invoice match-group]
|
||||
[:div.flex.items-center
|
||||
[:input {:type :radio :value (:db/id invoice) :name "autopay-invoice-ids"}]
|
||||
[:div.ml-3
|
||||
[:span.block.text-sm.font-medium (:invoice/invoice-number invoice)]
|
||||
[:span.block.text-sm.text-gray-500 (-> invoice :invoice/vendor :vendor/name)]
|
||||
[:span.block.text-sm.font-medium (format "$%.2f" (:invoice/total invoice))]]]))))]
|
||||
(com/a-button {"@click" "$dispatch('linkAutopayInvoices')"} "Match")
|
||||
]]
|
||||
(com/hidden {:name "action"
|
||||
:value "link-autopay-invoices"})
|
||||
[:div.space-y-2
|
||||
[:label.block.text-sm.font-medium.mb-1 "Select an autopay invoice to apply:"]
|
||||
(com/radio-card {:options (for [match-group invoice-matches]
|
||||
{:value (pr-str (map :db/id match-group))
|
||||
:content (doall (for [invoice match-group]
|
||||
[:div.ml-3
|
||||
[:span.block.text-sm.font-medium (:invoice/invoice-number invoice)]
|
||||
[:span.block.text-sm.text-gray-500 (-> invoice :invoice/vendor :vendor/name)]
|
||||
[:span.block.text-sm.font-medium (format "$%.2f" (:invoice/outstanding-balance invoice))]]))})
|
||||
:name (fc/with-field :autopay-invoice-ids (fc/field-name ))
|
||||
:width "w-full"})]
|
||||
]
|
||||
[:div.text-center.py-4.text-gray-500 "No matching autopay invoices available for this transaction."])]))
|
||||
|
||||
(defn get-available-unpaid-invoices [request]
|
||||
@@ -477,30 +468,31 @@
|
||||
(if (seq invoice-matches)
|
||||
[:div
|
||||
[:h3.text-lg.font-bold.mb-4 "Available Unpaid Invoices"]
|
||||
[:div {:hx-post (bidi/path-for ssr-routes/only-routes ::route/link-unpaid-invoices)
|
||||
[:div #_{:hx-post (bidi/path-for ssr-routes/only-routes ::route/link-unpaid-invoices)
|
||||
:hx-include "this"
|
||||
:hx-params "transaction-id, action, unpaid-invoice-ids"
|
||||
:hx-trigger "linkUnpaidInvoices"
|
||||
:hx-target "#modal-holder"
|
||||
:hx-swap "outerHTML"}
|
||||
(com/hidden {:name "action"
|
||||
:hx-trigger "linkUnpaidInvoices"
|
||||
:hx-target "#modal-holder"
|
||||
:hx-swap "outerHTML"}
|
||||
(com/hidden {:name "action"
|
||||
:value "link-unpaid-invoices"
|
||||
:form ""})
|
||||
(com/hidden {:name "transaction-id"
|
||||
#_(com/hidden {:name "transaction-id"
|
||||
:value (get-in request [:multi-form-state :snapshot :db/id])
|
||||
:form ""})
|
||||
[:div.space-y-2
|
||||
[:label.block.text-sm.font-medium.mb-1 "Select an unpaid invoice to apply:"]
|
||||
(doall (for [match-group invoice-matches]
|
||||
(doall (for [invoice match-group]
|
||||
[:div.flex.items-center
|
||||
[:input {:type :radio :value (:db/id invoice) :name "unpaid-invoice-ids"}]
|
||||
[:div.ml-3
|
||||
[:span.block.text-sm.font-medium (:invoice/invoice-number invoice)]
|
||||
[:span.block.text-sm.text-gray-500 (-> invoice :invoice/vendor :vendor/name)]
|
||||
[:span.block.text-sm.font-medium (format "$%.2f" (:invoice/outstanding-balance invoice))]]]))))]
|
||||
(com/a-button {:color :primary "@click" "$dispatch('linkUnpaidInvoices')"} "Link")
|
||||
]]
|
||||
(com/radio-card {:options (for [match-group invoice-matches]
|
||||
{:value (pr-str (map :db/id match-group))
|
||||
:content (doall (for [invoice match-group]
|
||||
[:div.ml-3
|
||||
[:span.block.text-sm.font-medium (:invoice/invoice-number invoice)]
|
||||
[:span.block.text-sm.text-gray-500 (-> invoice :invoice/vendor :vendor/name)]
|
||||
[:span.block.text-sm.font-medium (format "$%.2f" (:invoice/outstanding-balance invoice))]]))})
|
||||
:name (fc/with-field :unpaid-invoice-ids (fc/field-name ))
|
||||
:width "w-full"})
|
||||
]
|
||||
#_(com/a-button {:color :primary "@click" "$dispatch('linkUnpaidInvoices')"} "Link")]]
|
||||
[:div.text-center.py-4.text-gray-500 "No matching unpaid invoices available for this transaction."])]))
|
||||
|
||||
(defn get-available-rules [request]
|
||||
@@ -536,24 +528,20 @@
|
||||
(if (seq matching-rules)
|
||||
[:div
|
||||
[:h3.text-lg.font-bold.mb-4 "Matching Transaction Rules"]
|
||||
[:div {:hx-post (bidi/path-for ssr-routes/only-routes ::route/apply-rule)
|
||||
:hx-trigger "applyRule"
|
||||
:hx-include "this"
|
||||
:hx-target "#modal-holder"
|
||||
:hx-swap "outerHTML"}
|
||||
(fc/with-field :action
|
||||
(com/hidden {:name (fc/field-name)
|
||||
:value "apply-rule"
|
||||
:form ""}))
|
||||
[:div.space-y-2
|
||||
[:label.block.text-sm.font-medium.mb-1 "Select a rule to apply:"]
|
||||
(doall (for [{:keys [:db/id :transaction-rule/note :transaction-rule/description]} matching-rules]
|
||||
[:div.flex.items-center
|
||||
[:input {:type :radio :value id :name (fc/with-field :rule-id (fc/field-name))}]
|
||||
[:div.ml-3
|
||||
[:span.block.text-sm.font-medium note]
|
||||
[:span.block.text-sm.text-gray-500 description]]]))]
|
||||
(com/a-button {"@click" "$dispatch('applyRule')"} "Apply")]]
|
||||
(fc/with-field :action
|
||||
(com/hidden {:name (fc/field-name)
|
||||
:value "apply-rule"
|
||||
:form ""}))
|
||||
[:div.space-y-2
|
||||
[:label.block.text-sm.font-medium.mb-1 "Select a rule to apply:"]
|
||||
(com/radio-card {:options (for [{:keys [:db/id :transaction-rule/note :transaction-rule/description]} matching-rules]
|
||||
{:value id
|
||||
:content [:div.ml-3
|
||||
[:span.block.text-sm.font-medium note]
|
||||
[:span.block.text-sm.text-gray-500 description]]})
|
||||
:name (fc/with-field :rule-id (fc/field-name ))
|
||||
:width "w-full"}) ]
|
||||
#_(com/a-button {"@click" "$dispatch('applyRule')"} "Apply")]
|
||||
[:div.text-center.py-4.text-gray-500 "No matching rules found for this transaction."])]))
|
||||
|
||||
(defn payment-matches-view [request]
|
||||
@@ -619,8 +607,7 @@
|
||||
" - 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"])]]
|
||||
:width "w-full"}))) ]]
|
||||
[:div.text-center.py-4.text-gray-500 "No matching payments available for this transaction."]))]))
|
||||
|
||||
(defn count-payment-matches [request]
|
||||
@@ -667,7 +654,8 @@
|
||||
:placeholder "Optional note"})]))
|
||||
[:div {:x-data (hx/json {:activeForm (if (:transaction/payment (:entity request))
|
||||
"link-payment"
|
||||
(fc/with-field :action (fc/field-value)))
|
||||
(or (fc/with-field :action (fc/field-value))
|
||||
"manual"))
|
||||
:canChange (boolean (not (:transaction/payment (:entity request))))})
|
||||
"@unlinked" "canChange=true"}
|
||||
[:div {:class "flex space-x-2 mb-4"}
|
||||
@@ -863,7 +851,7 @@
|
||||
:headers {"hx-trigger" "invalidated"})))
|
||||
|
||||
(defmethod save-handler :link-autopay-invoices
|
||||
[{{:keys [autopay-invoice-ids]} :form-params :as request transaction :entity}]
|
||||
[{{ {:keys [autopay-invoice-ids] :as snapshot} :snapshot} :multi-form-state :as request transaction :entity} ]
|
||||
(let [db (dc/db conn)
|
||||
invoice-clients (set (map #(pull-ref db :invoice/client %) autopay-invoice-ids))
|
||||
invoice-amount (reduce + 0.0 (map #(pull-attr db :invoice/total %) autopay-invoice-ids))]
|
||||
@@ -894,7 +882,8 @@
|
||||
autopay-invoice-ids)
|
||||
(-> transaction :transaction/bank-account :db/id)
|
||||
(-> transaction :transaction/client :db/id))]
|
||||
(audit-transact payment-tx (:identity request)))
|
||||
(audit-transact (conj payment-tx
|
||||
[:upsert-transaction (default-update-tx snapshot {:db/id (:db/id transaction)})]) (:identity request)))
|
||||
|
||||
(solr/touch-with-ledger (:db/id transaction))
|
||||
|
||||
@@ -905,7 +894,7 @@
|
||||
:headers {"hx-trigger" "invalidated"})))
|
||||
|
||||
(defmethod save-handler :link-unpaid-invoices
|
||||
[{{:keys [unpaid-invoice-ids]} :form-params :as request transaction :entity}]
|
||||
[{{ {:keys [unpaid-invoice-ids] :as snapshot} :snapshot} :multi-form-state :as request transaction :entity} ]
|
||||
(let [ db (dc/db conn)
|
||||
invoice-clients (set (map #(pull-ref db :invoice/client %) unpaid-invoice-ids))
|
||||
invoice-amount (reduce + 0.0 (map #(pull-attr db :invoice/outstanding-balance %) unpaid-invoice-ids))]
|
||||
@@ -938,7 +927,8 @@
|
||||
unpaid-invoice-ids)
|
||||
(-> transaction :transaction/bank-account :db/id)
|
||||
(-> transaction :transaction/client :db/id))]
|
||||
(audit-transact payment-tx (:identity request)))
|
||||
(audit-transact (conj payment-tx
|
||||
[:upsert-transaction (default-update-tx snapshot {:db/id (:db/id transaction)})]) (:identity request)))
|
||||
|
||||
(solr/touch-with-ledger (:db/id transaction))
|
||||
|
||||
@@ -958,7 +948,7 @@
|
||||
|
||||
(defmethod save-handler
|
||||
:apply-rule
|
||||
[{{{:keys [rule-id]} :snapshot} :multi-form-state :as request transaction :entity}]
|
||||
[{{{:keys [rule-id] :as snapshot} :snapshot} :multi-form-state :as request transaction :entity}]
|
||||
(let [transaction-rule (dc/pull (dc/db conn)
|
||||
[:transaction-rule/description
|
||||
:transaction-rule/vendor
|
||||
@@ -982,7 +972,8 @@
|
||||
updated-tx (rm/apply-rule {:db/id (:db/id transaction)
|
||||
:transaction/amount (:transaction/amount transaction)}
|
||||
transaction-rule
|
||||
locations)]
|
||||
locations)
|
||||
updated-tx (default-update-tx snapshot updated-tx)]
|
||||
(alog/info ::applying-rule-tx :tx-data updated-tx
|
||||
:transaction transaction
|
||||
:transaction-rule transaction-rule)
|
||||
@@ -996,16 +987,73 @@
|
||||
[:p.text-gray-600.mt-2 "The selected rule has been applied to this transaction."])
|
||||
:headers {"hx-trigger" "invalidated"})))
|
||||
|
||||
(defn- calculate-spread
|
||||
"Helper function to calculate the amount to be assigned to each location"
|
||||
[shared-amount total-locations]
|
||||
(let [base-amount (int (/ shared-amount total-locations))
|
||||
remainder (- shared-amount (* base-amount total-locations))]
|
||||
{:base-amount base-amount
|
||||
:remainder remainder}))
|
||||
|
||||
(defn- spread-account
|
||||
"Spreads the expense account amount across the given locations"
|
||||
[locations account]
|
||||
(if (= "Shared" (:transaction-account/location account))
|
||||
(let [{:keys [base-amount remainder]} (calculate-spread (:transaction-account/amount account) (count locations))]
|
||||
(map-indexed (fn [idx _]
|
||||
(assoc account
|
||||
:transaction-account/amount (+ base-amount (if (< idx remainder) 1 0))
|
||||
:transaction-account/location (nth locations idx)))
|
||||
locations))
|
||||
[account]))
|
||||
|
||||
(defn- apply-total-delta-to-account [invoice-total eas]
|
||||
(when (seq eas)
|
||||
(let [leftover (- invoice-total (reduce + 0 (map :transaction-account/amount eas)))
|
||||
leftover-beyond-a-single-cent? (or (< leftover -1)
|
||||
(> leftover 1))
|
||||
leftover (if leftover-beyond-a-single-cent?
|
||||
0
|
||||
leftover)
|
||||
[first-eas & rest] eas]
|
||||
(cons
|
||||
(update first-eas :transaction-account/amount #(+ % leftover))
|
||||
rest))))
|
||||
|
||||
(defn $->cents [x]
|
||||
(int
|
||||
(let [result (* 100M (bigdec x))]
|
||||
(.setScale result 0 java.math.BigDecimal/ROUND_HALF_UP))))
|
||||
|
||||
(defn cents->$ [x]
|
||||
(double
|
||||
(let [result (* 0.01M (bigdec x))]
|
||||
(.setScale result 2 java.math.BigDecimal/ROUND_HALF_UP))))
|
||||
|
||||
(defn maybe-spread-locations
|
||||
"Converts any expense account for a \"Shared\" location into a separate expense account for all valid locations for that client"
|
||||
([transaction]
|
||||
(maybe-spread-locations transaction (pull-attr (dc/db conn) :client/locations (:transaction/client transaction))))
|
||||
([transaction locations]
|
||||
(clojure.pprint/pprint transaction)
|
||||
(update-in transaction
|
||||
[:transaction/accounts]
|
||||
(fn [accounts]
|
||||
(->> accounts
|
||||
(map (fn [ea] (update ea :transaction-account/amount $->cents)))
|
||||
(mapcat (partial spread-account locations))
|
||||
(apply-total-delta-to-account ($->cents (:transaction/amount transaction)))
|
||||
(map (fn [ea] (update ea :transaction-account/amount cents->$))))))))
|
||||
|
||||
(defmethod save-handler :manual
|
||||
[{:as request
|
||||
transaction :entity
|
||||
:keys [multi-form-state]}]
|
||||
(let [tx-data (-> multi-form-state :snapshot (dissoc :action))
|
||||
_ (clojure.pprint/pprint tx-data)
|
||||
tx-id (:db/id tx-data)
|
||||
client-id (->db-id (:transaction/client tx-data))
|
||||
existing-tx (d-transactions/get-by-id tx-id)
|
||||
transaction [:upsert-transaction (assoc tx-data :db/id tx-id)]]
|
||||
transaction [:upsert-transaction (maybe-spread-locations (assoc tx-data :db/id tx-id))]]
|
||||
|
||||
(alog/info ::transaction transaction :entity transaction)
|
||||
(exception->4xx #(assert-can-see-client (:identity request) client-id))
|
||||
@@ -1102,10 +1150,6 @@
|
||||
(html-response (fc/with-field :step-params (payment-matches-view request))
|
||||
:headers {"hx-trigger" "unlinked"}))))
|
||||
|
||||
#_(def save-schema
|
||||
(mc/schema
|
||||
))
|
||||
|
||||
|
||||
(defrecord EditWizard [_ current-step]
|
||||
mm/LinearModalWizard
|
||||
@@ -1120,6 +1164,7 @@
|
||||
(mm/get-step this :basic-details)))
|
||||
(render-wizard [this {:keys [multi-form-state] :as request}]
|
||||
(println "HERE XYZ" (:form-errors request))
|
||||
(clojure.pprint/pprint (:snapshot multi-form-state) )
|
||||
(mm/default-render-wizard
|
||||
this request
|
||||
:form-params
|
||||
@@ -1168,15 +1213,18 @@
|
||||
(def key->handler
|
||||
(apply-middleware-to-all-handlers
|
||||
{::route/edit-wizard (-> mm/open-wizard-handler
|
||||
(wrap-must {:activity :edit :subject :transaction} (fn get-client [request] (-> request :entity :transaction/client)))
|
||||
(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-must {:activity :edit :subject :transaction} (fn get-client [request] (-> request :entity :transaction/client)))
|
||||
(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
|
||||
(wrap-must {:activity :edit :subject :transaction} (fn get-client [request] (-> request :entity :transaction/client)))
|
||||
(wrap-entity [:multi-form-state :snapshot :db/id] d-transactions/default-read)
|
||||
(mm/wrap-wizard edit-wizard)
|
||||
(mm/wrap-decode-multi-form-state))
|
||||
@@ -1204,13 +1252,14 @@
|
||||
(wrap-schema-enforce :query-schema [:map
|
||||
[:client-id {:optional true}
|
||||
[:maybe entity-id]]]))
|
||||
|
||||
|
||||
::route/unlink-payment (-> unlink-payment
|
||||
(wrap-must {:activity :edit :subject :transaction} (fn get-client [request] (-> request :entity :transaction/client)))
|
||||
(wrap-entity [:multi-form-state :snapshot :db/id] d-transactions/default-read)
|
||||
(mm/wrap-wizard edit-wizard)
|
||||
(mm/wrap-decode-multi-form-state)
|
||||
(mm/wrap-wizard edit-wizard)
|
||||
(mm/wrap-decode-multi-form-state)
|
||||
#_(wrap-schema-enforce :form-schema
|
||||
save-schema))}
|
||||
save-schema))}
|
||||
(fn [h]
|
||||
(-> h
|
||||
(wrap-client-redirect-unauthenticated)))))
|
||||
|
||||
@@ -142,11 +142,19 @@
|
||||
false)))
|
||||
|
||||
#? (:clj
|
||||
(defn wrap-must [handler policy]
|
||||
(fn [request]
|
||||
(if (can? (:identity request) policy)
|
||||
(handler request)
|
||||
{:status 302
|
||||
:headers {"Location" (str "/login?"
|
||||
(url/map->query {"redirect-to" (:uri request)}))}}))))
|
||||
(defn wrap-must
|
||||
( [handler policy]
|
||||
(fn [request]
|
||||
(if (can? (:identity request) policy)
|
||||
(handler request)
|
||||
{:status 302
|
||||
:headers {"Location" (str "/login?"
|
||||
(url/map->query {"redirect-to" (:uri request)}))}})))
|
||||
( [handler policy get-client]
|
||||
(fn [request]
|
||||
(if (can? (:identity request) (assoc policy :client (get-client request)))
|
||||
(handler request)
|
||||
{:status 302
|
||||
:headers {"Location" (str "/login?"
|
||||
(url/map->query {"redirect-to" (:uri request)}))}})))))
|
||||
|
||||
|
||||
8
tasks
8
tasks
@@ -1,10 +1,6 @@
|
||||
* Add tests for edit transaction.
|
||||
* Make it so you can create a new vendor again.
|
||||
* Hide unhelpful report from the dashboard
|
||||
* Check permissions on ledger, transactions, reports
|
||||
* Make sure that you can't change a transaction if its payment is set
|
||||
* also add tests
|
||||
* Make sure that "Shared" really shares locations
|
||||
* make sure transactions support import-batch-id query parameter
|
||||
* make locked transactions clearer on the transaction table
|
||||
* Make locked transactions not look butt ugly with errors
|
||||
* Make locked transactions not look butt ugly with errors
|
||||
* Implement bulk actions
|
||||
Reference in New Issue
Block a user