makes all sales orders use new grid helper

This commit is contained in:
2023-09-27 23:52:57 -07:00
parent da6e492b4d
commit fddd3d9007
14 changed files with 926 additions and 122 deletions

View File

@@ -83,6 +83,33 @@
[c (or (next-day end) #inst "2030-03-05T08:00:00.000-00:00") ]))]
[(:e r) (first (:v r)) (second (:v r))]))
(defn scan-charges [db clients start end]
(for [c clients
:let [c (entid db c)]
r (seq (dc/index-range db
:charge/client+date
[c (or start #inst "2001-01-01T08:00:00.000-00:00") ]
[c (or (next-day end) #inst "2030-03-05T08:00:00.000-00:00") ]))]
[(:e r) (first (:v r)) (second (:v r))]))
(defn scan-sales-refunds [db clients start end]
(for [c clients
:let [c (entid db c)]
r (seq (dc/index-range db
:sales-refund/client+date
[c (or start #inst "2001-01-01T08:00:00.000-00:00") ]
[c (or (next-day end) #inst "2030-03-05T08:00:00.000-00:00") ]))]
[(:e r) (first (:v r)) (second (:v r))]))
(defn scan-cash-drawer-shifts [db clients start end]
(for [c clients
:let [c (entid db c)]
r (seq (dc/index-range db
:cash-drawer-shift/client+date
[c (or start #inst "2001-01-01T08:00:00.000-00:00") ]
[c (or (next-day end) #inst "2030-03-05T08:00:00.000-00:00") ]))]
[(:e r) (first (:v r)) (second (:v r))]))
(defn scan-invoices [db clients start end]
(for [c clients
:let [c (entid db c)]

View File

@@ -1651,6 +1651,18 @@ input:checked + .toggle-bg {
margin-bottom: calc(1.5rem * var(--tw-space-y-reverse));
}
.space-y-1 > :not([hidden]) ~ :not([hidden]) {
--tw-space-y-reverse: 0;
margin-top: calc(0.25rem * calc(1 - var(--tw-space-y-reverse)));
margin-bottom: calc(0.25rem * var(--tw-space-y-reverse));
}
.space-y-1\.5 > :not([hidden]) ~ :not([hidden]) {
--tw-space-y-reverse: 0;
margin-top: calc(0.375rem * calc(1 - var(--tw-space-y-reverse)));
margin-bottom: calc(0.375rem * var(--tw-space-y-reverse));
}
.divide-y > :not([hidden]) ~ :not([hidden]) {
--tw-divide-y-reverse: 0;
border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));

View File

@@ -1806,6 +1806,23 @@
:db/valueType :db.type/tuple
:db/tupleAttrs [ :payment/client :payment/date]
:db/cardinality :db.cardinality/one
:db/index true}
{:db/ident :charge/client+date
:db/valueType :db.type/tuple
:db/tupleAttrs [ :charge/client :charge/date]
:db/cardinality :db.cardinality/one
:db/index true}
{:db/ident :sales-refund/client+date
:db/valueType :db.type/tuple
:db/tupleAttrs [ :sales-refund/client :sales-refund/date]
:db/cardinality :db.cardinality/one
:db/index true}
{:db/ident :cash-drawer-shift/client+date
:db/valueType :db.type/tuple
:db/tupleAttrs [ :cash-drawer-shift/client :cash-drawer-shift/date]
:db/cardinality :db.cardinality/one
:db/index true}]

View File

@@ -180,4 +180,37 @@
{:user/name "hydrate-tuples"})
(auto-ap.datomic/audit-transact-batch (->> (dc/q '[:find ?e ?c
:in $
:where [?e :charge/client ?c]]
(dc/db conn)
)
(map (fn [[i c]]
{:db/id i
:charge/client c})))
{:user/name "hydrate-tuples"})
(auto-ap.datomic/audit-transact-batch (->> (dc/q '[:find ?e ?c
:in $
:where [?e :cash-drawer-shift/client ?c]]
(dc/db conn)
)
(map (fn [[i c]]
{:db/id i
:cash-drawer-shift/client c})))
{:user/name "hydrate-tuples"})
(auto-ap.datomic/audit-transact-batch (->> (dc/q '[:find ?e ?c
:in $
:where [?e :sales-refund/client ?c]]
(dc/db conn)
)
(map (fn [[i c]]
{:db/id i
:sales-refund/client c})))
{:user/name "hydrate-tuples"})
)

View File

@@ -10,7 +10,7 @@
[:a (-> params
(dissoc :icon)
(assoc :type "button")
(update :class str " cursor-pointer flex items-center p-2 w-full text-sm text-gray-600 rounded-lg transition duration-75 group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700")
(update :class str " cursor-pointer flex items-center p-2 w-full text-xs text-gray-600 rounded-lg transition duration-75 group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700")
(assoc :hx-indicator "find .htmx-indicator")
(assoc :hx-select "#app-contents")
(assoc :hx-target "#app-contents")
@@ -28,7 +28,7 @@
(svg/spinner-primary {:class "inline w-4 h-4 text-white"})]]])
(defn sub-menu- [params & children]
[:ul {:id (:id params) :class "hidden py-2 space-y-2"}
[:ul {:id (:id params) :class "hidden py-2 space-y-1.5"}
(for [c children]
[:li
(update-in c [1 1 :class ] str " flex items-center p-2 pl-11 w-full text-base font-normal text-gray-900 rounded-lg transition duration-75 group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700")])])
@@ -148,7 +148,7 @@
")]])
(defn main-aside-nav- []
[:ul {:class "space-y-2"}
[:ul {:class "space-y-1"}
[:li
(menu-button- {:icon svg/pie
@@ -178,11 +178,22 @@
:icon svg/receipt-register-1}
"Sales")
(sub-menu- {:id "dropdown-sales"}
(menu-button- {:href (str (bidi/path-for client-routes/routes
(menu-button- {:href (str (bidi/path-for ssr-routes/only-routes
:pos-sales)
"?date-range=week")} "Sales")
(menu-button- {:href (bidi/path-for client-routes/routes
:expected-deposits)} "Expected Deposits")
(menu-button- {:href (str (bidi/path-for ssr-routes/only-routes
:pos-expected-deposits)
"?date-range=week")} "Expected Deposits")
(menu-button- {:href (str (bidi/path-for ssr-routes/only-routes
:pos-tenders)
"?date-range=week")} "Tenders")
(menu-button- {:href (str (bidi/path-for ssr-routes/only-routes
:pos-refunds)
"?date-range=week")} "Refunds")
(menu-button- {:href (str (bidi/path-for ssr-routes/only-routes
:pos-cash-drawer-shifts)
"?date-range=week")} "Cash drawer shifts")
#_(menu-button- {:href "Sales"} "Cash Shifts")
#_(menu-button- {:href "Sales"} "Tenders"))]
[:li

View File

@@ -13,49 +13,57 @@
[auto-ap.ssr.company.reports :as company-reports]
[auto-ap.ssr.invoice.glimpse :as invoice-glimpse]
[auto-ap.ssr.pos.sales-orders :as pos-sales]
[auto-ap.ssr.pos.refunds :as pos-refunds]
[auto-ap.ssr.pos.expected-deposits :as pos-expected-deposits]
[auto-ap.ssr.pos.cash-drawer-shifts :as pos-cash-drawer-shifts]
[auto-ap.ssr.pos.tenders :as pos-tenders]
[auto-ap.routes.ezcater-xls :as ezcater-xls]
[auto-ap.ssr.company :as company]))
;; from auto-ap.ssr-routes, because they're shared
(def key->handler (into {:logout auth/logout
:admin-history (wrap-client-redirect-unauthenticated (wrap-secure (wrap-admin history/page)))
:admin-history-search (wrap-client-redirect-unauthenticated (wrap-secure (wrap-admin history/page)))
:admin-history-inspect (wrap-client-redirect-unauthenticated (wrap-secure (wrap-admin history/inspect)))
:active-client (wrap-client-redirect-unauthenticated (wrap-secure (wrap-secure company-dropdown/active-client)))
:company-dropdown-search-results
(wrap-client-redirect-unauthenticated (wrap-secure company-dropdown/dropdown-search-results))
:company (wrap-client-redirect-unauthenticated (wrap-secure company/page))
:company-1099 (wrap-client-redirect-unauthenticated (wrap-secure company-1099/page))
:company-1099-vendor-table (wrap-client-redirect-unauthenticated (wrap-secure company-1099/vendor-table))
:company-1099-vendor-dialog (wrap-client-redirect-unauthenticated (wrap-secure company-1099/vendor-dialog))
:company-1099-vendor-save (wrap-client-redirect-unauthenticated (wrap-secure company-1099/vendor-save))
:company-plaid (wrap-client-redirect-unauthenticated (wrap-secure company-plaid/page))
:company-plaid-table (wrap-client-redirect-unauthenticated (wrap-secure company-plaid/table))
:company-plaid-link (wrap-client-redirect-unauthenticated (wrap-secure company-plaid/link))
:company-plaid-relink (wrap-client-redirect-unauthenticated (wrap-secure company-plaid/relink))
:company-yodlee (wrap-client-redirect-unauthenticated (wrap-secure company-yodlee/page))
:company-yodlee-table (wrap-client-redirect-unauthenticated (wrap-secure company-yodlee/table))
:company-yodlee-fastlink-dialog (wrap-client-redirect-unauthenticated (wrap-secure company-yodlee/fastlink-dialog))
:company-yodlee-provider-account-refresh (wrap-client-redirect-unauthenticated (wrap-admin company-yodlee/refresh-provider-account))
:company-yodlee-provider-account-reauthenticate (wrap-client-redirect-unauthenticated (wrap-admin company-yodlee/reauthenticate))
:company-reports (wrap-client-redirect-unauthenticated (wrap-secure company-reports/page))
:company-reports-table (wrap-client-redirect-unauthenticated (wrap-secure company-reports/table))
:company-reports-delete (wrap-client-redirect-unauthenticated (wrap-admin company-reports/delete-report))
:invoice-glimpse (wrap-client-redirect-unauthenticated (wrap-admin invoice-glimpse/page))
:invoice-glimpse-upload (wrap-client-redirect-unauthenticated (wrap-admin invoice-glimpse/upload))
:invoice-glimpse-textract-invoice (wrap-client-redirect-unauthenticated (wrap-admin invoice-glimpse/textract-invoice))
:invoice-glimpse-create-invoice (wrap-client-redirect-unauthenticated (wrap-admin invoice-glimpse/create-invoice))
:invoice-glimpse-update-textract-invoice (wrap-client-redirect-unauthenticated (wrap-admin invoice-glimpse/update-textract-invoice))
:transaction-insights (wrap-client-redirect-unauthenticated (wrap-admin insights/page))
:transaction-insight-table (wrap-client-redirect-unauthenticated (wrap-admin insights/insight-table))
:transaction-insight-rows (wrap-client-redirect-unauthenticated (wrap-admin insights/transaction-rows))
:transaction-insight-code (wrap-client-redirect-unauthenticated (wrap-admin insights/code))
:transaction-insight-disapprove (wrap-client-redirect-unauthenticated (wrap-admin insights/disapprove))
:transaction-insight-explain (wrap-client-redirect-unauthenticated (wrap-admin insights/explain))
:admin-ezcater-xls (wrap-client-redirect-unauthenticated (wrap-admin ezcater-xls/page))
:search (wrap-client-redirect-unauthenticated (wrap-secure search/dialog-contents))}
pos-sales/key->handler))
(def key->handler
(-> {:logout auth/logout
:admin-history (wrap-client-redirect-unauthenticated (wrap-secure (wrap-admin history/page)))
:admin-history-search (wrap-client-redirect-unauthenticated (wrap-secure (wrap-admin history/page)))
:admin-history-inspect (wrap-client-redirect-unauthenticated (wrap-secure (wrap-admin history/inspect)))
:active-client (wrap-client-redirect-unauthenticated (wrap-secure (wrap-secure company-dropdown/active-client)))
:company-dropdown-search-results
(wrap-client-redirect-unauthenticated (wrap-secure company-dropdown/dropdown-search-results))
:company (wrap-client-redirect-unauthenticated (wrap-secure company/page))
:company-1099 (wrap-client-redirect-unauthenticated (wrap-secure company-1099/page))
:company-1099-vendor-table (wrap-client-redirect-unauthenticated (wrap-secure company-1099/vendor-table))
:company-1099-vendor-dialog (wrap-client-redirect-unauthenticated (wrap-secure company-1099/vendor-dialog))
:company-1099-vendor-save (wrap-client-redirect-unauthenticated (wrap-secure company-1099/vendor-save))
:company-plaid (wrap-client-redirect-unauthenticated (wrap-secure company-plaid/page))
:company-plaid-table (wrap-client-redirect-unauthenticated (wrap-secure company-plaid/table))
:company-plaid-link (wrap-client-redirect-unauthenticated (wrap-secure company-plaid/link))
:company-plaid-relink (wrap-client-redirect-unauthenticated (wrap-secure company-plaid/relink))
:company-yodlee (wrap-client-redirect-unauthenticated (wrap-secure company-yodlee/page))
:company-yodlee-table (wrap-client-redirect-unauthenticated (wrap-secure company-yodlee/table))
:company-yodlee-fastlink-dialog (wrap-client-redirect-unauthenticated (wrap-secure company-yodlee/fastlink-dialog))
:company-yodlee-provider-account-refresh (wrap-client-redirect-unauthenticated (wrap-admin company-yodlee/refresh-provider-account))
:company-yodlee-provider-account-reauthenticate (wrap-client-redirect-unauthenticated (wrap-admin company-yodlee/reauthenticate))
:company-reports (wrap-client-redirect-unauthenticated (wrap-secure company-reports/page))
:company-reports-table (wrap-client-redirect-unauthenticated (wrap-secure company-reports/table))
:company-reports-delete (wrap-client-redirect-unauthenticated (wrap-admin company-reports/delete-report))
:invoice-glimpse (wrap-client-redirect-unauthenticated (wrap-admin invoice-glimpse/page))
:invoice-glimpse-upload (wrap-client-redirect-unauthenticated (wrap-admin invoice-glimpse/upload))
:invoice-glimpse-textract-invoice (wrap-client-redirect-unauthenticated (wrap-admin invoice-glimpse/textract-invoice))
:invoice-glimpse-create-invoice (wrap-client-redirect-unauthenticated (wrap-admin invoice-glimpse/create-invoice))
:invoice-glimpse-update-textract-invoice (wrap-client-redirect-unauthenticated (wrap-admin invoice-glimpse/update-textract-invoice))
:transaction-insights (wrap-client-redirect-unauthenticated (wrap-admin insights/page))
:transaction-insight-table (wrap-client-redirect-unauthenticated (wrap-admin insights/insight-table))
:transaction-insight-rows (wrap-client-redirect-unauthenticated (wrap-admin insights/transaction-rows))
:transaction-insight-code (wrap-client-redirect-unauthenticated (wrap-admin insights/code))
:transaction-insight-disapprove (wrap-client-redirect-unauthenticated (wrap-admin insights/disapprove))
:transaction-insight-explain (wrap-client-redirect-unauthenticated (wrap-admin insights/explain))
:admin-ezcater-xls (wrap-client-redirect-unauthenticated (wrap-admin ezcater-xls/page))
:search (wrap-client-redirect-unauthenticated (wrap-secure search/dialog-contents))}
(into pos-sales/key->handler)
(into pos-expected-deposits/key->handler)
(into pos-tenders/key->handler)
(into pos-cash-drawer-shifts/key->handler)
(into pos-refunds/key->handler)))

View File

@@ -88,6 +88,7 @@
:thead-params {:hx-get (bidi/path-for ssr-routes/only-routes
(:route grid-spec))
:hx-target (str "#" (:id grid-spec))
:hx-indicator (str "#" (:id grid-spec))
:hx-trigger "sorted once"
:hx-vals "js:{\"toggle-sort\": event.detail.key || \"\"}"}
:headers

View File

@@ -0,0 +1,177 @@
(ns auto-ap.ssr.pos.cash-drawer-shifts
(:require
[auto-ap.datomic
:refer [add-sorter-fields
apply-pagination
apply-sort-3
conn
merge-query
pull-many
query2]]
[auto-ap.graphql.utils :refer [extract-client-ids]]
[auto-ap.routes.utils
:refer [wrap-client-redirect-unauthenticated wrap-secure]]
[auto-ap.ssr.pos.common :refer [date-range-field* processor-field* total-field*]]
[auto-ap.ssr-routes :as ssr-routes]
[auto-ap.ssr.components :as com]
[auto-ap.ssr.grid-page-helper :as helper]
[auto-ap.ssr.svg :as svg]
[auto-ap.time :as atime]
[bidi.bidi :as bidi]
[clj-time.coerce :as c]
[datomic.api :as dc]
[clojure.set :as set]))
;; always should be fast
;; make params parsing composable
(defn filters [params]
[:form {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
"hx-get" (bidi/path-for ssr-routes/only-routes
:pos-cash-drawer-shift-table)
"hx-target" "#cash-drawer-shift-table"
"hx-indicator" "#cash-drawer-shift-table"
#_#_:hx-disabled-elt "find fieldset"}
[:fieldset.space-y-6
(date-range-field* params)
(total-field* params)]])
(defn <-datomic [result]
(cond-> result
true (update :cash-drawer-shift/date c/from-date)))
(def default-read '[*
{:cash-drawer-shift/client [:client/name :db/id :client/code]}])
(defn fetch-ids [db args]
(let [query-params (:parsed-query-params args)
valid-clients (extract-client-ids (:clients args)
(:client-id query-params)
(when (:client-code query-params)
[:client/code (:client-code query-params)]))
valid-clients (->> valid-clients
(take 10)
set)
start-date (some-> args
:parsed-query-params
:start-date
(atime/parse atime/normal-date))
end-date (some-> args
:parsed-query-params
:end-date
(atime/parse atime/normal-date))
query (cond-> {:query {:find []
:in ['$ '[?clients ?start-date ?end-date]]
:where '[[(iol-ion.query/scan-cash-drawer-shifts $ ?clients ?start-date ?end-date) [[?e _ ?sort-default] ...]]]}
:args [db [valid-clients
(some-> start-date c/to-date)
(some-> end-date c/to-date )]]}
(:sort query-params) (add-sorter-fields {"client" ['[?e :cash-drawer-shift/client ?c]
'[?c :client/name ?sort-client]]
"date" ['[?e :cash-drawer-shift/date ?sort-date]]
"paid-in" ['[?e :cash-drawer-shift/paid-in ?sort-paid-in]]
"paid-out" ['[?e :cash-drawer-shift/paid-out ?sort-paid-out]]
"expected-cash" ['[?e :cash-drawer-shift/expected-cash ?sort-expected-cash]]
"opened-cash" ['[?e :cash-drawer-shift/opened-cash ?sort-opened-cash]]
}
query-params)
(:exact-match-id query-params)
(merge-query {:query {:in ['?e]
:where []}
:args [(:exact-match-id query-params)]})
start-date
(merge-query {:query {:in '[?start-date]
:where ['[?e :cash-drawer-shift/date ?date]
'[(>= ?date ?start-date)]]}
:args [(c/to-date start-date)]})
end-date
(merge-query {:query {:in '[?end-date]
:where ['[?e :cash-drawer-shift/date ?date]
'[(<= ?date ?end-date)]]}
:args [(c/to-date end-date)]})
true
(merge-query {:query {:find ['?sort-default '?e]
:where ['[?e :cash-drawer-shift/date ?sort-default]]}}))]
(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))
cash-drawer-shifts (->> ids
(map results)
(map first)
(mapv <-datomic)
)]
cash-drawer-shifts))
(defn fetch-page [_ args]
(let [db (dc/db conn)
{ids-to-retrieve :ids matching-count :count} (fetch-ids db args)]
[(->> (hydrate-results ids-to-retrieve db args))
matching-count]))
(def grid-page {:id "cash-drawer-shift-table"
:nav (com/main-aside-nav)
:page-specific-nav filters
:id-fn :db/id
:fetch-page fetch-page
:oob-render
(fn [_ params]
[(assoc-in (date-range-field* params) [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-cash-drawer-shifts)}
"Cash Drawer Shifts"]]
:title "Cash drawer shifts"
:entity-name "Cash drawer shift"
:route :pos-cash-drawer-shift-table
:action-buttons (fn [_ args])
:row-buttons (fn [_ e])
:headers [{:key "client"
:name "Client"
:sort-key "client"
:hide? (fn [args]
(= (count (:clients args)) 1))
:render #(-> % :cash-drawer-shift/client :client/code)}
{:key "date"
:name "Date"
:sort-key "date"
:render #(atime/unparse-local (:cash-drawer-shift/date %) atime/standard-time)}
{:key "paid-in"
:name "Paid in"
:sort-key "paid-in"
:render #(some->> % :cash-drawer-shift/paid-in (format "$%.2f"))}
{:key "paid-out"
:name "Paid out"
:sort-key "paid-out"
:render #(some->> % :cash-drawer-shift/paid-out (format "$%.2f"))}
{:key "expected-cash"
:name "Expected cash"
:sort-key "expected-cash"
:render #(some->> % :cash-drawer-shift/expected-cash (format "$%.2f"))}
{:key "opened-cash"
:name "Opened cash"
:sort-key "opened-cash"
:render #(some->> % :cash-drawer-shift/opened-cash (format "$%.2f"))}
]})
(def row* (partial helper/row* grid-page))
(def table* (partial helper/table* grid-page))
(def table (partial helper/table grid-page))
(def page (partial helper/page grid-page))
(def key->handler
{:pos-cash-drawer-shifts (wrap-client-redirect-unauthenticated (wrap-secure page))
:pos-cash-drawer-shift-table (wrap-client-redirect-unauthenticated (wrap-secure table))})

View File

@@ -0,0 +1,77 @@
(ns auto-ap.ssr.pos.common
(:require [auto-ap.ssr.components :as com]
[auto-ap.time :as atime]))
(defn date-range-field* [params]
[:div#date-range {}
(com/field {:label "Date Range"}
[:div.space-y-4
[:div
(com/button-group {:name "date-range"}
(com/button-group-button {:size :small :value "all" :hx-trigger "click"} "All")
(com/button-group-button {:size :small :value "week" :hx-trigger "click"} "Week")
(com/button-group-button {:size :small :value "month" :hx-trigger "click"} "Month")
(com/button-group-button {:size :small :value "year" :hx-trigger "click"} "Year"))
]
[:div.flex.space-x-1.items-baseline
(com/date-input {:name "start-date"
:value (some-> params
:parsed-query-params
:start-date
(atime/parse atime/normal-date)
(atime/unparse-local
atime/normal-date))
:placeholder "Date"
:size :small})
(com/date-input {:name "end-date"
:value (some-> params
:parsed-query-params
:end-date
(atime/parse atime/normal-date)
(atime/unparse-local
atime/normal-date))
:placeholder "Date"
:size :small})]]
)])
(defn processor-field* [params]
(com/field {:label "Processor"}
(com/radio {:size :small
:name "processor"
:options [{:value ""
:content "All"}
{:value "square"
:content [:div.flex.space-x-2 [:img.align-center {:src "/img/square.png" :style {:width "16px" :height "16px"}}] [:div "Square"]]}
{:value "doordash"
:content [:div.flex.space-x-2 [:img.align-center {:src "/img/doordash.png" :style {:width "16px" :height "16px"}}] [:div "Doordash"]]}
{:value "uber-eats"
:content [:div.flex.space-x-2 [:img.align-center {:src "/img/ubereats.png" :style {:width "16px" :height "16px"}}] [:div "Uber eats"]]}
{:value "grubhub"
:content [:div.flex.space-x-2 [:img.align-center {:src "/img/grubhub.png" :style {:width "16px" :height "16px"}}] [:div "Grubhub"]]}
{:value "koala"
:content [:div.flex.space-x-2 [:img.align-center {:src "/img/koala.png" :style {:width "16px" :height "16px"}}] [:div "Koala"]]}
{:value "ezcater"
:content [:div.flex.space-x-2 [:img.align-center {:src "/img/ezcater.png" :style {:width "16px" :height "16px"}}] [:div "EZCater"]]}
{:value "na"
:content "No Processor"}]})))
(defn total-field* [params]
(com/field {:label "Total"}
[:div.flex.space-x-4.items-baseline
(com/money-input {:name "total-gte"
:id "total-gte"
:hx-preserve "true"
:class "hot-filter"
:value (:total-gte (:parsed-query-params params))
:placeholder "0.01"
:size :small})
[:div.align-baseline
"to"]
(com/money-input {:name "total-lte"
:hx-preserve "true"
:id "total-lte"
:class "hot-filter"
:value (:total-lte (:parsed-query-params params))
:placeholder "9999.34"
:size :small})]))

View File

@@ -0,0 +1,110 @@
(ns auto-ap.ssr.pos.expected-deposits
(:require
[auto-ap.datomic.expected-deposit :as d-expected-deposit]
[auto-ap.routes.utils
:refer [wrap-client-redirect-unauthenticated wrap-secure]]
[auto-ap.ssr-routes :as ssr-routes]
[auto-ap.ssr.components :as com]
[auto-ap.ssr.grid-page-helper :as helper]
[auto-ap.ssr.pos.common :refer [date-range-field* total-field*]]
[auto-ap.ssr.svg :as svg]
[auto-ap.time :as atime]
[bidi.bidi :as bidi]))
;; TODO refunds
;; always should be fast
;; make params parsing composable
(defn filters [params]
[:form {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
"hx-get" (bidi/path-for ssr-routes/only-routes
:pos-expected-deposit-table)
"hx-target" "#expected-deposit-table"
"hx-indicator" "#expected-deposit-table"
#_#_:hx-disabled-elt "find fieldset"}
[:fieldset.space-y-6
(date-range-field* params)
(total-field* params)]])
(defn args->graphql-params [args]
{:clients (:clients args)
:start (:start (:parsed-query-params args))
:sort (:sort (:parsed-query-params args))
:per-page (:per-page (:parsed-query-params args))
:exact-match-id (some-> (:parsed-query-params args) :exact-match-id Long/parseLong)
:date-range {:start (some-> args
:parsed-query-params
:start-date
(atime/parse atime/normal-date))
:end (some-> args
:parsed-query-params
:end-date
(atime/parse atime/normal-date))}
:total-gte (some-> args :raw-query-params (get "total-gte") not-empty (#(if (string? %) (Double/parseDouble %) (double %))))
:total-lte (some-> args :raw-query-params (get "total-lte") not-empty (#(if (string? %) (Double/parseDouble %) (double %))))})
(def grid-page {:id "expected-deposit-table"
:nav (com/main-aside-nav)
:page-specific-nav filters
:id-fn :db/id
:fetch-page (fn [_ args]
(d-expected-deposit/get-graphql
(args->graphql-params args)))
:oob-render
(fn [_ params]
[(assoc-in (date-range-field* params) [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-expected-deposits)}
"Expected deposits"]]
:title "Expected deposits"
:entity-name "Expected deposit"
:route :pos-expected-deposit-table
:action-buttons (fn [_ args]
#_(let [{:keys [total tax]} (d-sales/summarize-graphql (args->graphql-params args))]
[
(com/pill {:color :primary}
(format "Total $%.2f" total)
)
(com/pill {:color :secondary}
(format "Tax $%.2f" tax )
)]))
:row-buttons (fn [_ e]
(when (:expected-deposit/reference-link e)
[(com/a-icon-button {:href (:expected-deposit/reference-link e)}
svg/external-link)]))
:headers [{:key "client"
:name "Client"
:sort-key "client"
:hide? (fn [args]
(= (count (:clients args)) 1))
:render #(-> % :expected-deposit/client :client/code)}
{:key "date"
:name "Date"
:sort-key "date"
:render #(atime/unparse-local (:expected-deposit/date %) atime/standard-time)}
{:key "sales-date"
:name "Sales Date"
:sort-key "sales-date"
:render #(atime/unparse-local (:expected-deposit/sales-date %) atime/standard-time)}
{:key "total"
:name "Total"
:sort-key "total"
:render #(some->> % :expected-deposit/total (format "$%.2f"))}
{:key "fee"
:name "Fee"
:sort-key "fee"
:render #(some->> % :expected-deposit/fee (format "$%.2f"))}]})
(def row* (partial helper/row* grid-page))
(def table* (partial helper/table* grid-page))
(def table (partial helper/table grid-page))
(def page (partial helper/page grid-page))
(def key->handler
{:pos-expected-deposits (wrap-client-redirect-unauthenticated (wrap-secure page))
:pos-expected-deposit-table (wrap-client-redirect-unauthenticated (wrap-secure table))})

View File

@@ -0,0 +1,185 @@
(ns auto-ap.ssr.pos.refunds
(:require
[auto-ap.datomic
:refer [add-sorter-fields
apply-pagination
apply-sort-3
conn
merge-query
pull-many
query2]]
[auto-ap.graphql.utils :refer [extract-client-ids]]
[auto-ap.routes.utils
:refer [wrap-client-redirect-unauthenticated wrap-secure]]
[auto-ap.ssr.pos.common :refer [date-range-field* processor-field* total-field*]]
[auto-ap.ssr-routes :as ssr-routes]
[auto-ap.ssr.components :as com]
[auto-ap.ssr.grid-page-helper :as helper]
[auto-ap.ssr.svg :as svg]
[auto-ap.time :as atime]
[bidi.bidi :as bidi]
[clj-time.coerce :as c]
[datomic.api :as dc]
[clojure.set :as set]))
;; TODO refunds
;; always should be fast
;; make params parsing composable
(defn filters [params]
[:form {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
"hx-get" (bidi/path-for ssr-routes/only-routes
:pos-refund-table)
"hx-target" "#refund-table"
"hx-indicator" "#refund-table"
#_#_:hx-disabled-elt "find fieldset"}
[:fieldset.space-y-6
(date-range-field* params)
(total-field* params)]])
(defn <-datomic [result]
(cond-> result
true (update :sales-refund/date c/from-date)))
(def default-read '[*
{:sales-refund/client [:client/name :db/id :client/code]}])
(defn fetch-ids [db args]
(let [query-params (:parsed-query-params args)
valid-clients (extract-client-ids (:clients args)
(:client-id query-params)
(when (:client-code query-params)
[:client/code (:client-code query-params)]))
valid-clients (->> valid-clients
(take 10)
set)
start-date (some-> args
:parsed-query-params
:start-date
(atime/parse atime/normal-date))
end-date (some-> args
:parsed-query-params
:end-date
(atime/parse atime/normal-date))
total-gte (some-> args :parsed-query-params :total-gte not-empty (#(if (string? %) (Double/parseDouble %) (double %))))
total-lte (some-> args :parsed-query-params :total-lte not-empty (#(if (string? %) (Double/parseDouble %) (double %))))
query (cond-> {:query {:find []
:in ['$ '[?clients ?start-date ?end-date]]
:where '[[(iol-ion.query/scan-sales-refunds $ ?clients ?start-date ?end-date) [[?e _ ?sort-default] ...]]]}
:args [db [valid-clients
(some-> start-date c/to-date)
(some-> end-date c/to-date )]]}
(:sort query-params) (add-sorter-fields {"client" ['[?e :sales-refund/client ?c]
'[?c :client/name ?sort-client]]
"date" ['[?e :sales-refund/date ?sort-date]]
"total" ['[?e :sales-refund/total ?sort-total]]
"fee" ['[?e :sales-refund/fee ?sort-tip]]
"type" ['[?e :sales-refund/type ?type]]}
query-params)
(:exact-match-id query-params)
(merge-query {:query {:in ['?e]
:where []}
:args [(:exact-match-id query-params)]})
total-gte
(merge-query {:query {:in ['?total-gte]
:where ['[?e :sales-refund/total ?a]
'[(>= ?a ?total-gte)]]}
:args [total-gte]})
total-lte
(merge-query {:query {:in ['?total-lte]
:where ['[?e :sales-refund/total ?a]
'[(<= ?a ?total-lte)]]}
:args [total-lte]})
start-date
(merge-query {:query {:in '[?start-date]
:where ['[?e :sales-refund/date ?date]
'[(>= ?date ?start-date)]]}
:args [(c/to-date start-date)]})
end-date
(merge-query {:query {:in '[?end-date]
:where ['[?e :sales-refund/date ?date]
'[(<= ?date ?end-date)]]}
:args [(c/to-date end-date)]})
true
(merge-query {:query {:find ['?sort-default '?e]
:where ['[?e :sales-refund/date ?sort-default]]}}))]
(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))
refunds (->> ids
(map results)
(map first)
(mapv <-datomic)
)]
refunds))
(defn fetch-page [_ args]
(let [db (dc/db conn)
{ids-to-retrieve :ids matching-count :count} (fetch-ids db args)]
[(->> (hydrate-results ids-to-retrieve db args))
matching-count]))
(def grid-page {:id "refund-table"
:nav (com/main-aside-nav)
:page-specific-nav filters
:id-fn :db/id
:fetch-page fetch-page
:oob-render
(fn [_ params]
[(assoc-in (date-range-field* params) [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-refunds)}
"Refunds"]]
:title "Refunds"
:entity-name "Refund"
:route :pos-refund-table
:action-buttons (fn [_ args])
:row-buttons (fn [_ e])
:headers [{:key "client"
:name "Client"
:sort-key "client"
:hide? (fn [args]
(= (count (:clients args)) 1))
:render #(-> % :sales-refund/client :client/code)}
{:key "date"
:name "Date"
:sort-key "date"
:render #(atime/unparse-local (:sales-refund/date %) atime/standard-time)}
{:key "total"
:name "Total"
:sort-key "total"
:render #(some->> % :sales-refund/total (format "$%.2f"))}
{:key "type"
:name "Type"
:sort-key "type"
:render :sales-refund/type}
{:key "fee"
:name "Fee"
:sort-key "fee"
:render #(some->> % :sales-refund/fee (format "$%.2f"))}]})
(def row* (partial helper/row* grid-page))
(def table* (partial helper/table* grid-page))
(def table (partial helper/table grid-page))
(def page (partial helper/page grid-page))
(def key->handler
{:pos-refunds (wrap-client-redirect-unauthenticated (wrap-secure page))
:pos-refund-table (wrap-client-redirect-unauthenticated (wrap-secure table))})

View File

@@ -6,6 +6,8 @@
[auto-ap.ssr-routes :as ssr-routes]
[auto-ap.ssr.components :as com]
[auto-ap.ssr.grid-page-helper :as helper]
[auto-ap.ssr.pos.common
:refer [date-range-field* processor-field* total-field*]]
[auto-ap.ssr.svg :as svg]
[auto-ap.time :as atime]
[bidi.bidi :as bidi]))
@@ -15,67 +17,18 @@
;; always should be fast
;; make params parsing composable
(defn date-range-field* [params]
[:div#date-range {}
(com/field {:label "Date Range"}
[:div.space-y-4
[:div
(com/button-group {:name "date-range"}
(com/button-group-button {:size :small :value "all" :hx-trigger "click"} "All")
(com/button-group-button {:size :small :value "week" :hx-trigger "click"} "Week")
(com/button-group-button {:size :small :value "month" :hx-trigger "click"} "Month")
(com/button-group-button {:size :small :value "year" :hx-trigger "click"} "Year"))
]
[:div.flex.space-x-1.items-baseline
(com/date-input {:name "start-date"
:value (some-> params
:parsed-query-params
:start-date
(atime/parse atime/normal-date)
(atime/unparse-local
atime/normal-date))
:placeholder "Date"
:size :small})
(com/date-input {:name "end-date"
:value (some-> params
:parsed-query-params
:end-date
(atime/parse atime/normal-date)
(atime/unparse-local
atime/normal-date))
:placeholder "Date"
:size :small})]]
)])
(defn filters [params]
[:form {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
"hx-get" (bidi/path-for ssr-routes/only-routes
[:form {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
"hx-get" (bidi/path-for ssr-routes/only-routes
:pos-sales-table)
"hx-target" "#sales-table"
"hx-indicator" "#sales-table"
"hx-target" "#sales-table"
"hx-indicator" "#sales-table"
#_#_:hx-disabled-elt "find fieldset"}
[:fieldset.space-y-6
(date-range-field* params)
[:div
(com/field {:label "Total"}
[:div.flex.space-x-4.items-baseline
(com/money-input {:name "total-gte"
:id "total-gte"
:hx-preserve "true"
:class "hot-filter"
:value (:total-gte (:parsed-query-params params))
:placeholder "0.01"
:size :small})
[:div.align-baseline
"to"]
(com/money-input {:name "total-lte"
:hx-preserve "true"
:id "total-lte"
:class "hot-filter"
:value (:total-lte (:parsed-query-params params))
:placeholder "9999.34"
:size :small})])]
[:div (total-field* params)]
[:div
(com/field {:label "Payment Method"}
(com/radio {:size :small
@@ -92,27 +45,7 @@
:content "Other"}
]}))]
[:div
(com/field {:label "Processor"}
(com/radio {:size :small
:name "processor"
:options [{:value ""
:content "All"}
{:value "square"
:content [:div.flex.space-x-2 [:img.align-center {:src "/img/square.png" :style {:width "16px" :height "16px"}}] [:div "Square"]]}
{:value "doordash"
:content [:div.flex.space-x-2 [:img.align-center {:src "/img/doordash.png" :style {:width "16px" :height "16px"}}] [:div "Doordash"]]}
{:value "uber-eats"
:content [:div.flex.space-x-2 [:img.align-center {:src "/img/ubereats.png" :style {:width "16px" :height "16px"}}] [:div "Uber eats"]]}
{:value "grubhub"
:content [:div.flex.space-x-2 [:img.align-center {:src "/img/grubhub.png" :style {:width "16px" :height "16px"}}] [:div "Grubhub"]]}
{:value "koala"
:content [:div.flex.space-x-2 [:img.align-center {:src "/img/koala.png" :style {:width "16px" :height "16px"}}] [:div "Koala"]]}
{:value "ezcater"
:content [:div.flex.space-x-2 [:img.align-center {:src "/img/ezcater.png" :style {:width "16px" :height "16px"}}] [:div "EZCater"]]}
{:value "na"
:content "No Processor"}
]}))]
(processor-field* params)]
[:div
(com/field {:label "Category"}

View File

@@ -0,0 +1,204 @@
(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.graphql.utils :refer [extract-client-ids]]
[auto-ap.routes.utils
:refer [wrap-client-redirect-unauthenticated wrap-secure]]
[auto-ap.ssr.pos.common :refer [date-range-field* processor-field* total-field*]]
[auto-ap.ssr-routes :as ssr-routes]
[auto-ap.ssr.components :as com]
[auto-ap.ssr.grid-page-helper :as helper]
[auto-ap.ssr.svg :as svg]
[auto-ap.time :as atime]
[bidi.bidi :as bidi]
[clj-time.coerce :as c]
[datomic.api :as dc]
[clojure.set :as set]))
;; TODO refunds
;; always should be fast
;; make params parsing composable
(defn filters [params]
[:form {"hx-trigger" "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* params)
(processor-field* params)
(total-field* params)]])
(defn <-datomic [result]
(let [expected-deposit (some-> (:expected-deposit/_charges result)
first
(update :expected-deposit/date c/from-date))]
(cond-> result
true (update :charge/date c/from-date)
true (update :charge/processor :db/ident)
expected-deposit (assoc :expected-deposit expected-deposit))))
(def default-read '[*
{:charge/client [:client/name :db/id :client/code]
:charge/processor [:db/ident]
:expected-deposit/_charges [:expected-deposit/date :db/id]}])
(defn fetch-ids [db args]
(let [query-params (:parsed-query-params args)
valid-clients (extract-client-ids (:clients args)
(:client args)
(:client-id query-params)
(when (:client-code query-params)
[:client/code (:client-code query-params)]))
valid-clients (->> valid-clients
(take 10)
set)
_ (println "valid clients" valid-clients)
start-date (some-> args
:parsed-query-params
:start-date
(atime/parse atime/normal-date))
end-date (some-> args
:parsed-query-params
:end-date
(atime/parse atime/normal-date))
total-gte (some-> args :parsed-query-params :total-gte not-empty (#(if (string? %) (Double/parseDouble %) (double %))))
total-lte (some-> args :parsed-query-params :total-lte not-empty (#(if (string? %) (Double/parseDouble %) (double %))))
processor (some-> query-params :processor (#(keyword "ccp-processor" (name %))))
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 [valid-clients
(some-> start-date c/to-date)
(some-> end-date 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
(merge-query {:query {:in ['?total-gte]
:where ['[?e :charge/total ?a]
'[(>= ?a ?total-gte)]]}
:args [total-gte]})
total-lte
(merge-query {:query {:in ['?total-lte]
:where ['[?e :charge/total ?a]
'[(<= ?a ?total-lte)]]}
:args [total-lte]})
processor
(merge-query {:query {:in '[?processor]
:where ['[?e :charge/processor ?processor]]}
:args [processor]})
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)
(mapv <-datomic)
)]
charges))
(defn fetch-page [_ args]
(let [db (dc/db conn)
{ids-to-retrieve :ids matching-count :count} (fetch-ids db args)]
[(->> (hydrate-results ids-to-retrieve db args))
matching-count]))
(def grid-page {:id "tender-table"
:nav (com/main-aside-nav)
:page-specific-nav filters
:id-fn :db/id
:fetch-page fetch-page
:oob-render
(fn [_ params]
[(assoc-in (date-range-field* params) [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"
:route :pos-tender-table
:action-buttons (fn [_ args])
:row-buttons (fn [_ 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 [args]
(= (count (:clients args)) 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 :db/id)]
[:a {:href (str (bidi/path-for ssr-routes/only-routes
:pos-expected-deposits)
"?exact-match-id=" expected-deposit-id)}
(com/pill {:color :secondary} "expected deposit")]))}]})
(def row* (partial helper/row* grid-page))
(def table* (partial helper/table* grid-page))
(def table (partial helper/table grid-page))
(def page (partial helper/page grid-page))
(def key->handler
{:pos-tenders (wrap-client-redirect-unauthenticated (wrap-secure page))
:pos-tender-table (wrap-client-redirect-unauthenticated (wrap-secure table))})

View File

@@ -20,7 +20,16 @@
["/rows/" [#"\d+" :after]] {:get :transaction-insight-rows}
["/explain/" [#"\d+" :transaction-id]] {:get :transaction-insight-explain}}}
"pos" {"/sales" {"" {:get :pos-sales}
"/table" {:get :pos-sales-table}}}
"/table" {:get :pos-sales-table}}
"/expected-deposit" {"" {:get :pos-expected-deposits}
"/table" {:get :pos-expected-deposit-table}}
"/tenders" {"" {:get :pos-tenders}
"/table" {:get :pos-tender-table}}
"/refunds" {"" {:get :pos-refunds}
"/table" {:get :pos-refund-table}}
"/cash-drawer-shifts" {"" {:get :pos-cash-drawer-shifts}
"/table" {:get :pos-cash-drawer-shift-table}}}
"company" {"" :company
"/dropdown" :company-dropdown-search-results
"/active" {:put :active-client}