Add vendor pre-population for bulk code and individual edit forms

- Add vendor-changed HTMX handlers for both bulk code and individual edit
- Pre-populate default account at 100% when vendor is selected and no accounts exist
- Fix render-accounts-section to render from step-params correctly
- Change bulk code vendor-changed from hx-get to hx-post to include form data
- Add routes for vendor-changed endpoints
- Update e2e tests to cover vendor pre-population
- Run lein cljfmt fix across codebase
This commit is contained in:
2026-05-21 14:45:19 -07:00
parent 8bd0cee1b1
commit ba87805d4c
210 changed files with 8694 additions and 9627 deletions

View File

@@ -1,7 +1,7 @@
(ns auto-ap.ssr.invoice.new-invoice-wizard
(:require
[auto-ap.datomic
:refer [audit-transact conn pull-attr]]
:refer [audit-transact conn pull-attr]]
[auto-ap.datomic.accounts :as d-accounts]
[auto-ap.datomic.invoices :as d-invoices]
[auto-ap.graphql.utils :refer [assert-can-see-client assert-not-locked
@@ -9,7 +9,7 @@
[auto-ap.logging :as alog]
[auto-ap.routes.invoice :as route]
[auto-ap.routes.utils
:refer [wrap-client-redirect-unauthenticated]]
:refer [wrap-client-redirect-unauthenticated]]
[auto-ap.solr :as solr]
[auto-ap.ssr-routes :as ssr-routes]
[auto-ap.ssr.common-handlers :refer [add-new-entity-handler]]
@@ -21,10 +21,10 @@
[auto-ap.ssr.nested-form-params :refer [wrap-nested-form-params]]
[auto-ap.ssr.svg :as svg]
[auto-ap.ssr.utils
:refer [->db-id apply-middleware-to-all-handlers check-allowance
check-location-belongs clj-date-schema entity-id
form-validation-error html-response money strip
wrap-schema-enforce]]
:refer [->db-id apply-middleware-to-all-handlers check-allowance
check-location-belongs clj-date-schema entity-id
form-validation-error html-response money strip
wrap-schema-enforce]]
[auto-ap.time :as atime]
[bidi.bidi :as bidi]
[clj-time.coerce :as coerce]
@@ -48,10 +48,6 @@
[:vendor-terms-override/client :vendor-terms-override/terms]}]
vendor-id))
(defn check-vendor-default-account [vendor-id]
(some? (:vendor/default-account (get-vendor vendor-id))))
@@ -83,7 +79,7 @@
[:invoice-expense-account/location :string]
[:invoice-expense-account/amount :double]]
[:fn {:error/fn (fn [r x] (:type r))
:error/path [:invoice-expense-account/location]}
:error/path [:invoice-expense-account/location]}
(fn [iea]
(check-location-belongs (:invoice-expense-account/location iea)
(:invoice-expense-account/account iea)))]]]]])
@@ -95,7 +91,6 @@
true
(and invoice-number vendor client)))]])
(defn clientize-vendor [{:vendor/keys [terms-overrides automatically-paid-when-due default-account account-overrides] :as vendor} client-id]
(if (nil? vendor)
nil
@@ -142,7 +137,6 @@
{:value (name :customize)
:content [:div "Customize accounts"]}])}))))
(defrecord BasicDetailsStep [linear-wizard]
mm/ModalWizardStep
(step-name [_]
@@ -181,7 +175,6 @@
(com/hidden {:name (fc/field-name)
:value (fc/field-value)})))
(fc/with-field :customize-due-and-scheduled?
(com/hidden {:name (fc/field-name)
:value (fc/field-value)
@@ -220,11 +213,10 @@
[:div.mb-4
;; TODO DO NOT MERGE UNTIL THIS IS FIXED
#_[:span.text-sm.text-gray-500 "Can't find the vendor? "
(com/link {:href ...
:target "new"}
"Add new vendor")
" in a new window, then return here."]]
(com/link {:href ...
:target "new"}
"Add new vendor")
" in a new window, then return here."]]
[:div.flex.items-center.gap-2
(fc/with-field :invoice/date
@@ -333,7 +325,6 @@
#_(mm/navigate-handler {:request request
:to-step :next-steps}))))
(defn location-select*
[{:keys [name account-location client-locations value]}]
(let [options (into (cond account-location
@@ -433,8 +424,8 @@
(filter number?)
(reduce + 0.0))
balance (-
(-> request :multi-form-state :snapshot :invoice/total)
total)]
(-> request :multi-form-state :snapshot :invoice/total)
total)]
[:span {:class (when-not (dollars= 0.0 balance)
"text-red-300")}
(format "$%,.2f" balance)]))
@@ -569,7 +560,6 @@
nil
:validation-route ::route/new-wizard-navigate)))
(defn assert-no-conflicting [{:invoice/keys [invoice-number client vendor] :db/keys [id]}]
(when (seq (d-invoices/find-conflicting {:invoice/invoice-number invoice-number
:invoice/vendor (->db-id vendor)
@@ -577,13 +567,11 @@
:db/id id}))
(form-validation-error (str "Invoice '" invoice-number "' already exists."))))
(defn assert-invoice-amounts-add-up [{:keys [:invoice/expense-accounts :invoice/total]}]
(let [expense-account-total (reduce + 0 (map (fn [x] (:invoice-expense-account/amount x)) expense-accounts))]
(when-not (dollars= total expense-account-total)
(form-validation-error (str "Expense account total (" expense-account-total ") does not equal invoice total (" total ")")))))
(defn- calculate-spread
"Helper function to calculate the amount to be assigned to each location"
[shared-amount total-locations]
@@ -592,7 +580,6 @@
{:base-amount base-amount
:remainder remainder}))
(defn- spread-expense-account
"Spreads the expense account amount across the given locations"
[locations expense-account]
@@ -628,7 +615,6 @@
(update first-eas :invoice-expense-account/amount #(+ % leftover))
rest))))
(defn maybe-spread-locations
"Converts any expense account for a \"Shared\" location into a separate expense account for all valid locations for that client"
([invoice]
@@ -643,8 +629,6 @@
(apply-total-delta-to-account ($->cents (:invoice/total invoice)))
(map (fn [ea] (update ea :invoice-expense-account/amount cents->$))))))))
(defrecord NewWizard2 [_ current-step]
mm/LinearModalWizard
(hydrate-from-request
@@ -728,13 +712,12 @@
(exception->4xx #(assert-not-locked client-id (:invoice/date invoice)))
(let [transaction-result (audit-transact [transaction] (:identity request))]
(try
(try
(solr/touch-with-ledger (get-in transaction-result [:tempids "invoice"]))
(catch Exception e
(alog/error ::cant-save-solr
:error e
))
)
(alog/error ::cant-save-solr
:error e)))
(if extant?
(html-response
@@ -750,7 +733,6 @@
(def new-wizard (->NewWizard2 nil nil))
(defn initial-new-wizard-state [request]
(mm/->MultiStepFormState {:invoice/date (time/now)
:customize-accounts :default}
@@ -758,9 +740,6 @@
{:invoice/date (time/now)
:customize-accounts :default}))
(defn initial-edit-wizard-state [request]
(let [entity (dc/pull (dc/db conn) default-read (:db/id (:route-params request)))
entity (select-keys entity (mut/keys new-form-schema))]
@@ -779,7 +758,6 @@
:client-locations (some->> client-id
(pull-attr (dc/db conn) :client/locations))})))
(defn due-date [{:keys [multi-form-state]}]
(let [vendor (clientize-vendor (get-vendor (:invoice/vendor (:step-params multi-form-state)))
(->db-id (:invoice/client (:step-params multi-form-state))))
@@ -816,7 +794,6 @@
:error? false
:placeholder "1/1/2024"}))))
(defn account-prediction [{:keys [multi-form-state form-errors] :as request}]
(html-response
(account-prediction* request)))