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:
@@ -28,19 +28,17 @@
|
||||
(defn read-xml [stream]
|
||||
(-> (slurp stream)
|
||||
(.getBytes)
|
||||
(java.io.ByteArrayInputStream. )
|
||||
(java.io.ByteArrayInputStream.)
|
||||
xml/parse
|
||||
zip/xml-zip))
|
||||
|
||||
|
||||
|
||||
(defn mark-key [k]
|
||||
(s3/copy-object {:source-bucket-name bucket-name
|
||||
:destination-bucket-name bucket-name
|
||||
:destination-key (str/replace-first k "pending" "imported")
|
||||
:source-key k})
|
||||
#_(s3/delete-object {:bucket-name bucket-name
|
||||
:key k}))
|
||||
:key k}))
|
||||
|
||||
(defn is-csv-file? [x]
|
||||
(= "dat" (last (str/split x #"[\\.]"))))
|
||||
@@ -54,7 +52,7 @@
|
||||
(and (str/includes? k "GeneralProduce")
|
||||
(str/includes? k "FRANCHISEE")
|
||||
(is-csv-file? k))
|
||||
:general-produce
|
||||
:general-produce
|
||||
|
||||
:else
|
||||
:unknown))
|
||||
@@ -66,15 +64,15 @@
|
||||
[k input-stream clients]
|
||||
(log/info ::parsing-general-produce :key k)
|
||||
(let [missing-client-hints (atom #{})]
|
||||
(try
|
||||
(try
|
||||
(->> (read-csv input-stream)
|
||||
(drop 1)
|
||||
#_(filter (fn [[_ _ _ _ _ _ _ _ _ _ _ break-flag]]
|
||||
(= "Y" break-flag)))
|
||||
(map (fn [[_ location-hint invoice-number ship-date invoice-total ]]
|
||||
(map (fn [[_ location-hint invoice-number ship-date invoice-total]]
|
||||
(let [matching-client (and location-hint
|
||||
(parse/exact-match clients location-hint))
|
||||
location (parse/best-location-match matching-client location-hint location-hint )
|
||||
location (parse/best-location-match matching-client location-hint location-hint)
|
||||
vendor (d/pull (d/db conn) '[:vendor/default-account] :vendor/general-produce)]
|
||||
(when-not (and matching-client
|
||||
(not (@missing-client-hints location-hint))
|
||||
@@ -99,8 +97,7 @@
|
||||
(-> vendor :vendor/default-account :db/id)
|
||||
:invoice-expense-account/location location
|
||||
:invoice-expense-account/amount (Math/abs (Double/parseDouble invoice-total))
|
||||
:db/id (random-tempid)
|
||||
}]})))
|
||||
:db/id (random-tempid)}]})))
|
||||
(filter :invoice/client)
|
||||
(reduce (fn [[seen-so-far list] i]
|
||||
(let [k [(:invoice/invoice-number i) (:invoice/client i)]]
|
||||
@@ -108,8 +105,7 @@
|
||||
[seen-so-far list]
|
||||
[(conj seen-so-far k) (conj list i)])))
|
||||
[#{} []])
|
||||
(second)
|
||||
)
|
||||
(second))
|
||||
(catch Exception e
|
||||
(log/error ::cant-import-general-produce
|
||||
:error e)
|
||||
@@ -123,8 +119,8 @@
|
||||
|
||||
(defn zip-seq [zipper]
|
||||
(->> (zip/xml-zip (zip/node zipper))
|
||||
(iterate zip/next )
|
||||
(take-while (complement zip/end?))))
|
||||
(iterate zip/next)
|
||||
(take-while (complement zip/end?))))
|
||||
|
||||
(defmethod extract-invoice-details :cintas
|
||||
[k input-stream clients]
|
||||
@@ -160,10 +156,10 @@
|
||||
atime/localize
|
||||
(atime/unparse atime/iso-date)
|
||||
(atime/parse atime/iso-date))))
|
||||
location (parse/best-location-match matching-client location-hint location-hint )
|
||||
location (parse/best-location-match matching-client location-hint location-hint)
|
||||
due (-> invoice-date
|
||||
(time/plus (time/days 30))
|
||||
(coerce/to-date))
|
||||
(time/plus (time/days 30))
|
||||
(coerce/to-date))
|
||||
total (->> node-seq
|
||||
(filter (fn [zipper]
|
||||
(= (:tag (zip/node zipper))
|
||||
@@ -178,7 +174,7 @@
|
||||
:content
|
||||
first
|
||||
Double/parseDouble)
|
||||
invoice {:db/id (random-tempid )
|
||||
invoice {:db/id (random-tempid)
|
||||
:invoice/vendor :vendor/cintas
|
||||
:invoice/import-status :import-status/imported
|
||||
:invoice/status :invoice-status/unpaid
|
||||
@@ -188,37 +184,36 @@
|
||||
:invoice/total total
|
||||
:invoice/outstanding-balance total
|
||||
:invoice/invoice-number (->> node-seq
|
||||
(map zip/node)
|
||||
(filter (fn [node]
|
||||
(= (:tag node)
|
||||
:InvoiceDetailRequestHeader)))
|
||||
first
|
||||
(#(-> % :attrs :invoiceID)))
|
||||
(map zip/node)
|
||||
(filter (fn [node]
|
||||
(= (:tag node)
|
||||
:InvoiceDetailRequestHeader)))
|
||||
first
|
||||
(#(-> % :attrs :invoiceID)))
|
||||
:invoice/due due
|
||||
|
||||
:invoice/scheduled-payment (when-not ((into #{} (->> matching-client
|
||||
:client/feature-flags))
|
||||
"manually-pay-cintas")
|
||||
due)
|
||||
due)
|
||||
|
||||
:invoice/date (coerce/to-date invoice-date)
|
||||
:invoice/expense-accounts [{:invoice-expense-account/account
|
||||
(-> vendor :vendor/default-account :db/id)
|
||||
:invoice-expense-account/location location
|
||||
:invoice-expense-account/amount (Math/abs total)
|
||||
:db/id (random-tempid)
|
||||
}]}]
|
||||
:db/id (random-tempid)}]}]
|
||||
(log/info ::cintas-invoice-importing
|
||||
:invoice invoice)
|
||||
[invoice])
|
||||
(do
|
||||
(do
|
||||
;; disabling logging for cintas
|
||||
#_(log/warn ::missing-client
|
||||
:client-hint location-hint)
|
||||
:client-hint location-hint)
|
||||
[]))))
|
||||
|
||||
(defn mark-error [k]
|
||||
(s3/copy-object {:source-bucket-name bucket-name
|
||||
(s3/copy-object {:source-bucket-name bucket-name
|
||||
:destination-bucket-name bucket-name
|
||||
:source-key k
|
||||
:destination-key (str "ntg-invoices/error/"
|
||||
@@ -232,17 +227,17 @@
|
||||
(s3/copy-object {:source-bucket-name bucket-name
|
||||
:destination-bucket-name bucket-name
|
||||
:source-key k
|
||||
:destination-key invoice-key })
|
||||
:destination-key invoice-key})
|
||||
invoice-key))
|
||||
|
||||
(defn get-all-keys
|
||||
([]
|
||||
(let [first-page-result (s3/list-objects-v2 {:bucket-name bucket-name
|
||||
(let [first-page-result (s3/list-objects-v2 {:bucket-name bucket-name
|
||||
:prefix "ntg-invoices/pending"})]
|
||||
(lazy-seq (concat (:object-summaries first-page-result) (get-all-keys (:next-continuation-token first-page-result))))))
|
||||
([next-token ]
|
||||
(when next-token
|
||||
(let [page-result (s3/list-objects-v2 {:bucket-name bucket-name
|
||||
([next-token]
|
||||
(when next-token
|
||||
(let [page-result (s3/list-objects-v2 {:bucket-name bucket-name
|
||||
:prefix "ntg-invoices/pending"
|
||||
:continuation-token next-token})]
|
||||
(println "getting next page " next-token)
|
||||
@@ -250,60 +245,58 @@
|
||||
(lazy-seq (concat (:object-summaries page-result) (get-all-keys (:next-continuation-token page-result)))))))))
|
||||
|
||||
(defn recent? [k]
|
||||
(time/after? (:last-modified k) (time/plus (time/now) (time/days -15)))
|
||||
)
|
||||
(time/after? (:last-modified k) (time/plus (time/now) (time/days -15))))
|
||||
|
||||
(defn import-ntg-invoices
|
||||
([] (import-ntg-invoices (->> (get-all-keys)
|
||||
(filter recent?)
|
||||
(map :key))))
|
||||
([keys]
|
||||
(let [clients (map first (d/q '[:find (pull ?c [:client/code
|
||||
:db/id
|
||||
:client/feature-flags
|
||||
{:client/location-matches [:location-match/matches :location-match/location]}
|
||||
:client/name
|
||||
:client/matches
|
||||
:client/locations])
|
||||
:where [?c :client/code]]
|
||||
(d/db conn)))]
|
||||
(log/info ::found-invoice-keys
|
||||
:keys keys )
|
||||
(let [transaction (->> keys
|
||||
(mapcat (fn [k]
|
||||
(try
|
||||
(let [invoice-key (copy-readable-version k)
|
||||
invoice-url (str "https://" bucket-name "/" invoice-key)]
|
||||
(with-open [is (-> (s3/get-object {:bucket-name bucket-name
|
||||
:key k})
|
||||
:input-stream)]
|
||||
(->> (extract-invoice-details k
|
||||
is
|
||||
clients)
|
||||
(set)
|
||||
(map (fn [i]
|
||||
(log/info ::importing-invoice
|
||||
:invoice i)
|
||||
i))
|
||||
(mapv (fn [i]
|
||||
(if (= :vendor/cintas (:invoice/vendor i))
|
||||
[:propose-invoice (assoc i :invoice/source-url invoice-url)]
|
||||
[:propose-invoice i]))))))
|
||||
(catch Exception e
|
||||
(log/error ::cant-load-file
|
||||
:key k
|
||||
:exception e)
|
||||
(mark-error k)
|
||||
[]))))
|
||||
(into []))]
|
||||
(doseq [t transaction]
|
||||
(audit-transact [t] {:user/name "sysco importer" :user/role "admin"}))
|
||||
(log/info ::success
|
||||
:count (count transaction)
|
||||
:sample (take 3 transaction)))
|
||||
(doseq [k keys]
|
||||
(mark-key k)))))
|
||||
|
||||
(let [clients (map first (d/q '[:find (pull ?c [:client/code
|
||||
:db/id
|
||||
:client/feature-flags
|
||||
{:client/location-matches [:location-match/matches :location-match/location]}
|
||||
:client/name
|
||||
:client/matches
|
||||
:client/locations])
|
||||
:where [?c :client/code]]
|
||||
(d/db conn)))]
|
||||
(log/info ::found-invoice-keys
|
||||
:keys keys)
|
||||
(let [transaction (->> keys
|
||||
(mapcat (fn [k]
|
||||
(try
|
||||
(let [invoice-key (copy-readable-version k)
|
||||
invoice-url (str "https://" bucket-name "/" invoice-key)]
|
||||
(with-open [is (-> (s3/get-object {:bucket-name bucket-name
|
||||
:key k})
|
||||
:input-stream)]
|
||||
(->> (extract-invoice-details k
|
||||
is
|
||||
clients)
|
||||
(set)
|
||||
(map (fn [i]
|
||||
(log/info ::importing-invoice
|
||||
:invoice i)
|
||||
i))
|
||||
(mapv (fn [i]
|
||||
(if (= :vendor/cintas (:invoice/vendor i))
|
||||
[:propose-invoice (assoc i :invoice/source-url invoice-url)]
|
||||
[:propose-invoice i]))))))
|
||||
(catch Exception e
|
||||
(log/error ::cant-load-file
|
||||
:key k
|
||||
:exception e)
|
||||
(mark-error k)
|
||||
[]))))
|
||||
(into []))]
|
||||
(doseq [t transaction]
|
||||
(audit-transact [t] {:user/name "sysco importer" :user/role "admin"}))
|
||||
(log/info ::success
|
||||
:count (count transaction)
|
||||
:sample (take 3 transaction)))
|
||||
(doseq [k keys]
|
||||
(mark-key k)))))
|
||||
|
||||
(defn -main [& _]
|
||||
(execute "ntg" import-ntg-invoices))
|
||||
|
||||
Reference in New Issue
Block a user