From 8f14eaa1bf7cce2fa1297141e012d04549e677c0 Mon Sep 17 00:00:00 2001 From: Bryce Covert Date: Thu, 4 May 2023 22:50:41 -0700 Subject: [PATCH] Cash drawer setup --- scratch-sessions/cash-shift.repl | 68 +++++++++++++++++++ src/clj/auto_ap/graphql/clients.clj | 31 ++++++++- src/clj/auto_ap/square/core3.clj | 100 ++++++++++++++++++++++++++-- 3 files changed, 191 insertions(+), 8 deletions(-) create mode 100644 scratch-sessions/cash-shift.repl diff --git a/scratch-sessions/cash-shift.repl b/scratch-sessions/cash-shift.repl new file mode 100644 index 00000000..8b7719d3 --- /dev/null +++ b/scratch-sessions/cash-shift.repl @@ -0,0 +1,68 @@ +;; This buffer is for Clojure experiments and evaluation. + +;; Press C-j to evaluate the last expression. + +;; You can also press C-u C-j to evaluate the expression and pretty-print its result. + +(def c + (first (get-square-clients "NGAK"))) + +(def l {:db/id 17592186051554, + :square-location/name "Almaden", + :square-location/square-id "68MJ8J2RX7KE1"}) + +@(cash-drawer-shifts c l ) + +@(get-cash-shift c "ac34dc1e-5d2e-4a83-929c-c33e24ba2882") + +@(cash-drawer-shifts c l) + +@(upsert-cash-shifts c) + +@(d/transact conn [{:db/ident :cash-drawer-shift/external-id + :db/doc "The client for the sale" + :db/valueType :db.type/string + :db/cardinality :db.cardinality/one + :db/unique :db.unique/identity} + + {:db/ident :cash-drawer-shift/client + :db/doc "The client for the sale" + :db/valueType :db.type/ref + :db/cardinality :db.cardinality/one} + + {:db/ident :cash-drawer-shift/vendor + :db/doc "The client for the sale" + :db/valueType :db.type/ref + :db/cardinality :db.cardinality/one} + + {:db/ident :cash-drawer-shift/location + :db/doc "The location of the sale" + :db/valueType :db.type/string + :db/cardinality :db.cardinality/one} + + {:db/ident :cash-drawer-shift/date + :db/doc "The date the order was placed" + :db/valueType :db.type/instant + :db/cardinality :db.cardinality/one} + + {:db/ident :cash-drawer-shift/paid-in + :db/doc "The amount of money added to the cash drawer for reasons other than cash payments. " + :db/valueType :db.type/double + :db/cardinality :db.cardinality/one} + + {:db/ident :cash-drawer-shift/paid-out + :db/doc "The amount of money removed from the cash drawer for reasons other than cash refunds." + :db/valueType :db.type/double + :db/cardinality :db.cardinality/one} + + {:db/ident :cash-drawer-shift/expected-cash + :db/doc "The amount of money that should be in the cash drawer at the end of the shift, based on the shift's other money amounts." + :db/valueType :db.type/double + :db/cardinality :db.cardinality/one} + + {:db/ident :cash-drawer-shift/opened-cash + :db/doc "The amount of money in the cash drawer at the start of the shift." + :db/valueType :db.type/double + :db/cardinality :db.cardinality/one} + + ]) diff --git a/src/clj/auto_ap/graphql/clients.clj b/src/clj/auto_ap/graphql/clients.clj index c9f1ec6d..258fd991 100644 --- a/src/clj/auto_ap/graphql/clients.clj +++ b/src/clj/auto_ap/graphql/clients.clj @@ -406,6 +406,25 @@ [(auto-ap.time/localize ?d2) ?d3] [(auto-ap.time/unparse-local ?d3 auto-ap.time/normal-date) ?d4]]") +(def cash-drawer-shift-query + "[:find ?d4 (sum ?paid-in) (sum ?paid-out) (sum ?expected-cash) (sum ?opened-cash) +:with ?cds +:in $ +:where +[?cds :cash-drawer-shift/date ?date] +[(ground (clj-time.coerce/to-date (clj-time.core/minus (auto-ap.time/local-now) (clj-time.core/days 90)))) ?min-d] +[(>= ?date ?min-d)] +[?cds :cash-drawer-shift/client [:client/code \"%s\"]] +[?cds :cash-drawer-shift/paid-in ?paid-in] +[?cds :cash-drawer-shift/paid-in ?paid-out] +[?cds :cash-drawer-shift/paid-in ?expected-cash] +[?cds :cash-drawer-shift/paid-in ?opened-cash] +[(clj-time.coerce/to-date-time ?date) ?d2] +[(auto-ap.time/localize ?d2) ?d3] +[(auto-ap.time/unparse-local ?d3 auto-ap.time/normal-date) ?d4]]") + + + (defn setup-sales-queries [context args _] @@ -442,12 +461,19 @@ (str "refunds query for " client-code) (str client-code "-refund") [:client/code client-code]) + + (q/put-query (str (UUID/randomUUID)) + (format cash-drawer-shift-query client-code) + (str "cash drawer shift query for " client-code) + (str client-code "-cash-drawer-shift") + [:client/code client-code]) (let [sales-summary-id (:saved-query/guid (d/pull (d/db auto-ap.datomic/conn) [:saved-query/guid] [:saved-query/lookup-key (str client-code "-sales-summary")])) sales-category-id (:saved-query/guid (d/pull (d/db auto-ap.datomic/conn) [:saved-query/guid] [:saved-query/lookup-key (str client-code "-sales-category")])) expected-deposit-id (:saved-query/guid (d/pull (d/db auto-ap.datomic/conn) [:saved-query/guid] [:saved-query/lookup-key (str client-code "-expected-deposit")])) tender-id (:saved-query/guid (d/pull (d/db auto-ap.datomic/conn) [:saved-query/guid] [:saved-query/lookup-key (str client-code "-tender")])) - refund-id (:saved-query/guid (d/pull (d/db auto-ap.datomic/conn) [:saved-query/guid] [:saved-query/lookup-key (str client-code "-refund")]))] + refund-id (:saved-query/guid (d/pull (d/db auto-ap.datomic/conn) [:saved-query/guid] [:saved-query/lookup-key (str client-code "-refund")])) + cash-drawer-shift-id (:saved-query/guid (d/pull (d/db auto-ap.datomic/conn) [:saved-query/guid] [:saved-query/lookup-key (str client-code "-cash-drawer-shift")]))] {:message (str/join "\n" [ (str "For " client-code ":") @@ -455,7 +481,8 @@ (str "Sales Category: " "https://app.integreatconsult.com/api/queries/" sales-category-id "/results/json") (str "Expected Deposits: " "https://app.integreatconsult.com/api/queries/" expected-deposit-id "/results/json") (str "Tenders: " "https://app.integreatconsult.com/api/queries/" tender-id "/results/json") - (str "Refund: " "https://app.integreatconsult.com/api/queries/" refund-id "/results/json")])}))) + (str "Refund: " "https://app.integreatconsult.com/api/queries/" refund-id "/results/json") + (str "Cash Drawer Shift: " "https://app.integreatconsult.com/api/queries/" cash-drawer-shift-id "/results/json")])}))) (def objects diff --git a/src/clj/auto_ap/square/core3.clj b/src/clj/auto_ap/square/core3.clj index ed0b9a73..ae766f3e 100644 --- a/src/clj/auto_ap/square/core3.clj +++ b/src/clj/auto_ap/square/core3.clj @@ -19,10 +19,16 @@ [manifold.stream :as s] [manifold.time :as mt])) -(defn client-base-headers [client] - {"Square-Version" "2021-08-18" - "Authorization" (str "Bearer " (:client/square-auth-token client)) - "Content-Type" "application/json"}) +(defn client-base-headers + ([client] (client-base-headers client "2021-08-18")) + ([client v] + {"Square-Version" v + "Authorization" (str "Bearer " (:client/square-auth-token client)) + "Content-Type" "application/json"})) + + +(defn ->square-date [d] + (f/unparse (f/formatter "YYYY-MM-dd'T'HH:mm:ssZZ") d)) (def manifold-api-stream @@ -182,8 +188,8 @@ {"query" {"filter" {"date_time_filter" { "created_at" { - "start_at" (f/unparse (f/formatter "YYYY-MM-dd'T'HH:mm:ssZZ") start) - "end_at" (f/unparse (f/formatter "YYYY-MM-dd'T'HH:mm:ssZZ") end) + "start_at" (->square-date start) + "end_at" (->square-date end) }}} "sort" { @@ -611,6 +617,83 @@ (log/info ::done-loading-refunds))))))) + +(defn get-cash-shift [client id] + (de/chain (manifold-api-call {:url (str (url/url "https://connect.squareup.com/v2/cash-drawers/shifts" id + + )) + :method :get + + :headers (client-base-headers client "2023-04-19") + :as :json}) + :body + :cash_drawer_shift)) + +(defn cash-drawer-shifts + ([client l] + (cash-drawer-shifts client l (time/plus (time/now) (time/days -14)) (time/now))) + ([client l start end] + (de/chain (manifold-api-call {:url (str "https://connect.squareup.com/v2/cash-drawers/shifts" + "?" + + (url/map->query + {:location_id (:square-location/square-id l) + :begin_time (->square-date start) + :end_time (->square-date end)})) + :method :get + + :headers (client-base-headers client "2023-04-19") + :as :json}) + :body + :cash_drawer_shifts + (fn [shifts] + (->> shifts + (filter (fn [r] (= "ENDED" (:state r)))) + (s/->source ) + (s/map (fn [s] + (de/chain + (get-cash-shift client (:id s)) + (fn [cash-drawer-shift] + #:cash-drawer-shift {:external-id (str "square/cash-drawer-shift/" (:id cash-drawer-shift)) + :vendor :vendor/ccp-square + :paid-in (amount->money (:cash_paid_in_money cash-drawer-shift)) + :paid-out (amount->money (:cash_paid_out_money cash-drawer-shift)) + :expected-cash (amount->money (:expected_cash_money cash-drawer-shift)) + :opened-cash (amount->money (:opened_cash_money cash-drawer-shift)) + :date (coerce/to-date (:opened_at cash-drawer-shift)) + :client (:db/id client) + :location (:square-location/client-location l) + })))) + (s/buffer 5) + (s/realize-each) + (s/reduce conj [])))))) + +(defn upsert-cash-shifts + ([client] + (apply de/zip + (for [square-location (:client/square-locations client) + :when (:square-location/client-location square-location)] + (upsert-cash-shifts client square-location)))) + ([client location] + (with-context-as {:source "Square cash shift loading" + :client (:client/code client)} lc + + (de/chain (cash-drawer-shifts client location) + (fn [cash-shifts] + (mu/with-context lc + (try + (doseq [x (partition-all 100 cash-shifts)] + (log/info ::loading-cash-shifts + :count (count x) + :sample (first x)) + @(d/transact conn x)) + + (catch Throwable e + (log/error ::upsert-cash-shifts-failed + :exception e))) + + (log/info ::done-loading-cash-shifts))))))) + (def square-read [:db/id :client/code :client/square-auth-token @@ -704,6 +787,11 @@ (mu/with-context lc (log/info ::upsert-refunds-started) (upsert-refunds client))) + + (fn [_] + (mu/with-context lc + (log/info ::upsert-cash-shifts) + (upsert-cash-shifts client))) (fn [_] (mu/with-context lc (log/info ::upsert-done))