(ns auto-ap.ssr.pos.tenders (:require [auto-ap.datomic :refer [add-sorter-fields apply-pagination apply-sort-3 conn merge-query pull-many query2]] [auto-ap.query-params :as query-params :refer [wrap-copy-qp-pqp]] [auto-ap.ssr-routes :as ssr-routes] [auto-ap.ssr.components :as com] [auto-ap.ssr.grid-page-helper :as helper :refer [wrap-apply-sort]] [auto-ap.ssr.pos.common :refer [date-range-field* processor-field* total-field*]] [auto-ap.ssr.svg :as svg] [auto-ap.ssr.utils :refer [apply-middleware-to-all-handlers clj-date-schema default-grid-fields-schema ref->enum-schema wrap-merge-prior-hx wrap-schema-enforce]] [auto-ap.time :as atime] [bidi.bidi :as bidi] [clj-time.coerce :as c] [datomic.api :as dc] [malli.core :as mc])) ;; always should be fast (defn filters [request] [:form {"hx-trigger" "datesApplied, change delay:500ms, keyup changed from:.hot-filter delay:1000ms" "hx-get" (bidi/path-for ssr-routes/only-routes :pos-tender-table) "hx-target" "#tender-table" "hx-indicator" "#tender-table" #_#_:hx-disabled-elt "find fieldset"} [:fieldset.space-y-6 (date-range-field* request) (processor-field* request) (total-field* request)]]) (def query-schema (mc/schema [:maybe (into [:map {:date-range [:date-range :start-date :end-date]} [:total-gte {:optional true} [:maybe :double]] [:total-lte {:optional true} [:maybe :double]] [:start-date {:optional true} [:maybe clj-date-schema]] [:end-date {:optional true} [:maybe clj-date-schema]] [:client {:optional true :default nil} [:maybe [:entity-map {:pull [:db/id :client/name]}]]] [:processor {:optional true} [:maybe (ref->enum-schema "ccp-processor")]]] default-grid-fields-schema)])) (def default-read '[:db/id :charge/reference-link :charge/total :charge/tip [:charge/date :xform clj-time.coerce/from-date] {:charge/client [:client/name :db/id :client/code] [:charge/processor :xform iol-ion.query/ident] [:db/ident] :expected-deposit/_charges [:expected-deposit/date :db/id]}]) (defn fetch-ids [db request] (let [query-params (:query-params request) query (cond-> {:query {:find [] :in ['$ '[?clients ?start-date ?end-date]] :where '[[(iol-ion.query/scan-charges $ ?clients ?start-date ?end-date) [[?e _ ?sort-default] ...]]]} :args [db [(:trimmed-clients request) (some-> (:start-date query-params) c/to-date) (some-> (:end-date query-params) c/to-date)]]} (:sort query-params) (add-sorter-fields {"client" ['[?e :charge/client ?c] '[?c :client/name ?sort-client]] "date" ['[?e :charge/date ?sort-date]] "total" ['[?e :charge/total ?sort-total]] "tip" ['[?e :charge/tip ?sort-tip]] "processor" ['[?e :charge/processor ?p] '[?p :db/ident ?p2] '[(name ?p2) ?sort-processor]]} query-params) (:exact-match-id query-params) (merge-query {:query {:in ['?e] :where []} :args [(:exact-match-id query-params)]}) (:total-gte query-params) (merge-query {:query {:in ['?total-gte] :where ['[?e :charge/total ?a] '[(>= ?a ?total-gte)]]} :args [(:total-gte query-params)]}) (:total-lte query-params) (merge-query {:query {:in ['?total-lte] :where ['[?e :charge/total ?a] '[(<= ?a ?total-lte)]]} :args [(:total-lte query-params)]}) (:processor query-params) (merge-query {:query {:in '[?processor] :where ['[?e :charge/processor ?processor]]} :args [(:processor query-params)]}) true (merge-query {:query {:find ['?sort-default '?e]}}))] (cond->> (query2 query) true (apply-sort-3 query-params) true (apply-pagination query-params)))) (defn hydrate-results [ids db _] (let [results (->> (pull-many db default-read ids) (group-by :db/id)) charges (->> ids (map results) (map first))] charges)) (defn fetch-page [request] (let [db (dc/db conn) {ids-to-retrieve :ids matching-count :count} (fetch-ids db request)] [(->> (hydrate-results ids-to-retrieve db request)) matching-count])) (def grid-page (helper/build {:id "tender-table" :nav com/main-aside-nav :page-specific-nav filters :fetch-page fetch-page :oob-render (fn [request] [(assoc-in (date-range-field* request) [1 :hx-swap-oob] true)]) :breadcrumbs [[:a {:href (bidi/path-for ssr-routes/only-routes :company)} "POS"] [:a {:href (bidi/path-for ssr-routes/only-routes :pos-tenders)} "Tenders"]] :title "Tenders" :entity-name "Tender" :query-schema query-schema :route :pos-tender-table :row-buttons (fn [request e] (when (:charge/reference-link e) [(com/a-icon-button {:href (:charge/reference-link e)} svg/external-link)])) :headers [{:key "client" :name "Client" :sort-key "client" :hide? (fn [request] (= (count (:clients request)) 1)) :render #(-> % :charge/client :client/code)} {:key "date" :name "Date" :sort-key "date" :render #(atime/unparse-local (:charge/date %) atime/standard-time)} {:key "total" :name "Total" :sort-key "total" :render #(some->> % :charge/total (format "$%.2f"))} {:key "processor" :name "Processor" :sort-key "processor" :render (fn [sales-order] (when (:charge/processor sales-order) (com/pill {:color :primary} (name (:charge/processor sales-order)))))} {:key "tip" :name "Tip" :sort-key "tip" :render #(some->> % :charge/tip (format "$%.2f"))} {:key "links" :name "Links" :render (fn [entity] (when-let [expected-deposit-id (some->> entity :expected-deposit/_charges first :db/id)] [:a {:href (str (bidi/path-for ssr-routes/only-routes :pos-expected-deposits) "?exact-match-id=" expected-deposit-id) :hx-boost "true"} (com/pill {:color :secondary} "expected deposit")]))}]})) (def row* (partial helper/row* grid-page)) (def table* (partial helper/table* grid-page)) (def key->handler (apply-middleware-to-all-handlers {:pos-tenders (helper/page-route grid-page) :pos-tender-table (helper/table-route grid-page)} (fn [h] (-> h (wrap-copy-qp-pqp) (wrap-apply-sort grid-page) (wrap-merge-prior-hx) (wrap-schema-enforce :query-schema query-schema) (wrap-schema-enforce :hx-schema query-schema)))))