Files
integreat/src/clj/auto_ap/ssr/account.clj
Bryce ba87805d4c 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
2026-05-21 14:45:19 -07:00

112 lines
6.1 KiB
Clojure

(ns auto-ap.ssr.account
(:require
[auto-ap.datomic :refer [conn]]
[auto-ap.graphql.utils
:refer [assert-can-see-client can-see-client? cleanse-query is-admin?]]
[auto-ap.solr :as solr]
[auto-ap.logging :as alog]
[auto-ap.ssr.utils
:refer [entity-id ref->enum-schema wrap-schema-enforce]]
[com.brunobonacci.mulog :as mu]
[datomic.api :as dc]
[ring.middleware.json :refer [wrap-json-response]]
[auto-ap.datomic.accounts :as d-accounts]))
;; TODO this is basically duplicative of graphql version, make sure to keep in sync
;; TODO use valid clients from request rather than stuff like assert-can-see-client
(def search-pattern [:db/id
:account/numeric-code
:account/location
:account/name
{:account/vendor-allowance [:db/ident]
:account/default-allowance [:db/ident]
:account/invoice-allowance [:db/ident]
:account/client-overrides [:db/id
:account-client-override/name
{:account-client-override/client [:db/id :client/name]}]}])
(defn search- [id query client]
(let [client-part (if (some->> client (can-see-client? id))
(format "((applicability:(global OR optional) AND -client_id:*) OR (account_client_override_id:* AND client_id:%s))" client)
"(applicability:(global OR optional) AND -client_id:*)")
query (format "_text_:(%s) AND %s" (cleanse-query query) client-part)]
(mu/log ::searching :search-query query)
(for [{:keys [account_id name] :as g} (solr/query solr/impl "accounts"
{"query" query
"fields" "id, name, client_id, numeric_code, applicability, account_id"})]
{:account_id (first account_id)
:name (first name)})))
(defn account-search [{{:keys [q client-id purpose vendor-id] :as qp} :query-params id :identity :as request}]
(let [client-id (or client-id (:db/id (:client request)))]
(when client-id
(assert-can-see-client id client-id))
(let [num (some-> (re-find #"([0-9]+)" q)
second
(not-empty)
Integer/parseInt)
valid-allowances (cond-> #{:allowance/allowed
:allowance/warn}
(is-admin? id) (conj :allowance/admin-only))
allowance (cond (= purpose "vendor")
:account/vendor-allowance
(= purpose "invoice")
:account/invoice-allowance
:else
:account/default-allowance)
vendor-account (when vendor-id
(-> (dc/q '[:find ?da
:in $ ?v
:where [?v :vendor/default-account ?da]]
(dc/db conn)
vendor-id)
ffirst))
xform (comp
(filter (fn [[_ a]]
(or
(valid-allowances (-> a allowance :db/ident))
(= (:db/id a) vendor-account))))
(map (fn [[n a]]
{:label (str (:account/numeric-code a) " - " (if client-id
(:account/name (d-accounts/clientize a client-id))
n))
:value (:db/id a)
:location (:account/location a)
:warning (when (= :allowance/warn (-> a allowance :db/ident))
"This account is not typically used for this purpose.")})))]
{:body (take 10 (if q
(if num
(->> (dc/q '[:find ?n (pull ?i pattern)
:in $ ?numeric-code ?allowance pattern
:where [?i :account/numeric-code ?numeric-code]
[?i :account/name ?n]
(or [?i :account/applicability :account-applicability/global]
[?i :account/applicability :account-applicability/optional]
[?i :account/applicability :account-applicability/customized])]
(dc/db conn)
num
allowance
search-pattern)
(sequence xform))
(->> (search- id q client-id)
(sequence
(comp (map (fn [i] [(:name i) (dc/pull (dc/db conn) search-pattern (:account_id i))]))
xform))))
[]))})))
(def account-search (wrap-json-response (wrap-schema-enforce account-search
:query-schema [:map
[:q :string]
[:client-id {:optional true
:default nil}
[:maybe entity-id]]
[:vendor-id {:optional true}
[:maybe entity-id]]
[:purpose {:optional true}
[:maybe :string]]])))