- 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
165 lines
8.1 KiB
Clojure
165 lines
8.1 KiB
Clojure
(ns auto-ap.datomic.ledger
|
|
(:require
|
|
[auto-ap.datomic
|
|
:refer [add-sorter-fields
|
|
apply-pagination
|
|
apply-sort-4
|
|
conn
|
|
merge-query
|
|
observable-query
|
|
pull-many]]
|
|
[auto-ap.datomic.accounts :as d-accounts]
|
|
[auto-ap.graphql.utils :refer [extract-client-ids]]
|
|
[clj-time.coerce :as coerce]
|
|
[datomic.api :as dc]))
|
|
|
|
(defn raw-graphql-ids [db args]
|
|
(let [valid-clients (extract-client-ids (:clients args)
|
|
(:client-id args)
|
|
(when (:client-code args)
|
|
[:client/code (:client-code args)]))
|
|
query
|
|
(if (:exact-match-id args)
|
|
{:query {:find '[?e]
|
|
:in '[$ ?e [?c ...]]
|
|
:where '[[?e :journal-entry/client ?c]]}
|
|
:args [db
|
|
(:exact-match-id args)
|
|
valid-clients]}
|
|
(cond-> {:query {:find []
|
|
:in ['$ '[?clients ?start ?end]]
|
|
:where '[[(iol-ion.query/scan-ledger $ ?clients ?start ?end) [[?e _ ?sort-default] ...]]]}
|
|
:args [db
|
|
[valid-clients
|
|
(some-> (:start (:date-range args)) coerce/to-date)
|
|
(some-> (:end (:date-range args)) coerce/to-date)]]}
|
|
|
|
(:only-external args)
|
|
(merge-query {:query {:where ['(not [?e :journal-entry/original-entity])]}})
|
|
|
|
(seq (:external-id-like args))
|
|
(merge-query {:query {:in ['?external-id-like]
|
|
:where ['[?e :journal-entry/external-id ?external-id]
|
|
'[(.contains ^String ?external-id ?external-id-like)]]}
|
|
:args [(:external-id-like args)]})
|
|
|
|
(seq (:source args))
|
|
(merge-query {:query {:in ['?source]
|
|
:where ['[?e :journal-entry/source ?source]]}
|
|
:args [(:source args)]})
|
|
|
|
(:vendor-id args)
|
|
(merge-query {:query {:in ['?vendor-id]
|
|
:where ['[?e :journal-entry/vendor ?vendor-id]]}
|
|
:args [(:vendor-id args)]})
|
|
|
|
(or (seq (:numeric-code args))
|
|
(:bank-account-id args)
|
|
(not-empty (:location args)))
|
|
(merge-query {:query {:where ['[?e :journal-entry/line-items ?li]]}})
|
|
|
|
(seq (:numeric-code args))
|
|
(merge-query {:query {:in ['[[?from-numeric-code ?to-numeric-code]]]
|
|
:where ['[?li :journal-entry-line/account ?a]
|
|
'(or-join [?a ?c]
|
|
[?a :account/numeric-code ?c]
|
|
[?a :bank-account/numeric-code ?c])
|
|
'[(>= ?c ?from-numeric-code)]
|
|
'[(<= ?c ?to-numeric-code)]]}
|
|
:args [(vec (for [{:keys [from to]} (:numeric-code args)]
|
|
[(or from 0) (or to 99999)]))]})
|
|
|
|
(:amount-gte args)
|
|
(merge-query {:query {:in ['?amount-gte]
|
|
:where ['[?e :journal-entry/amount ?a]
|
|
'[(>= ?a ?amount-gte)]]}
|
|
:args [(:amount-gte args)]})
|
|
|
|
(:amount-lte args)
|
|
(merge-query {:query {:in ['?amount-lte]
|
|
:where ['[?e :journal-entry/amount ?a]
|
|
'[(<= ?a ?amount-lte)]]}
|
|
:args [(:amount-lte args)]})
|
|
|
|
(:bank-account-id args)
|
|
(merge-query {:query {:in ['?a]
|
|
:where ['[?li :journal-entry-line/account ?a]]}
|
|
:args [(:bank-account-id args)]})
|
|
|
|
(:account-id args)
|
|
(merge-query {:query {:in ['?a2]
|
|
:where ['[?e :journal-entry/line-items ?li2]
|
|
'[?li2 :journal-entry-line/account ?a2]]}
|
|
:args [(:account-id args)]})
|
|
|
|
(not-empty (:location args))
|
|
(merge-query {:query {:in ['?location]
|
|
:where ['[?li :journal-entry-line/location ?location]]}
|
|
:args [(:location args)]})
|
|
|
|
(not-empty (:locations args))
|
|
(merge-query {:query {:in ['[?location ...]]
|
|
:where ['[?li :journal-entry-line/location ?location]]}
|
|
:args [(:locations args)]})
|
|
|
|
(:sort args) (add-sorter-fields {"client" ['[?e :journal-entry/client ?c]
|
|
'[?c :client/name ?sort-client]]
|
|
"date" ['[?e :journal-entry/date ?sort-date]]
|
|
"vendor" ['[?e :journal-entry/vendor ?v]
|
|
'[?v :vendor/name ?sort-vendor]]
|
|
"amount" ['[?e :journal-entry/amount ?sort-amount]]
|
|
"external-id" ['[?e :journal-entry/external-id ?sort-external-id]]
|
|
"source" ['[?e :journal-entry/source ?sort-source]]}
|
|
args)
|
|
|
|
true
|
|
(merge-query {:query {:find ['?sort-default '?e]}})))]
|
|
(->> (observable-query query)
|
|
(apply-sort-4 (assoc args :default-asc? true))
|
|
(apply-pagination args))))
|
|
|
|
(defn graphql-results [ids db _]
|
|
(let [results (->> (pull-many db '[* {:journal-entry/client [:client/name :client/code :db/id]
|
|
:journal-entry/vendor [:vendor/name :db/id]
|
|
:journal-entry/line-items [* {:journal-entry-line/account [*
|
|
{:account/type [*]}
|
|
{:account/client-overrides [:account-client-override/name
|
|
{:account-client-override/client [:db/id]}]}
|
|
{:bank-account/type [*]}]}]}]
|
|
ids)
|
|
(map #(update % :journal-entry/date coerce/from-date))
|
|
(map (fn [je]
|
|
(update je :journal-entry/line-items
|
|
(fn [jels]
|
|
(map
|
|
#(update % :journal-entry-line/account d-accounts/clientize (:db/id (:journal-entry/client je)))
|
|
jels)))))
|
|
(filter (fn [je]
|
|
(every?
|
|
(fn [jel]
|
|
(let [include-in-reports (-> jel :journal-entry-line/account :bank-account/include-in-reports)]
|
|
(or (nil? include-in-reports)
|
|
(true? include-in-reports))))
|
|
(:journal-entry/line-items je))))
|
|
(group-by :db/id))]
|
|
(->> ids
|
|
(map results)
|
|
(filter identity)
|
|
(map first))))
|
|
|
|
(defn get-graphql [args]
|
|
(let [db (dc/db conn)
|
|
{ids-to-retrieve :ids matching-count :count} (raw-graphql-ids db args)]
|
|
[(->> (graphql-results ids-to-retrieve db args))
|
|
matching-count]))
|
|
|
|
(defn filter-ids [ids]
|
|
(if ids
|
|
(->> (dc/q {:find ['?e]
|
|
:in ['$ '[?e ...]]
|
|
:where ['[?e :journal-entry/date]]}
|
|
(dc/db conn) ids)
|
|
(map first)
|
|
vec)
|
|
[]))
|