(ns auto-ap.square.core (:require [auto-ap.datomic :refer [conn remove-nils]] [clj-http.client :as client] [clj-time.coerce :as coerce] [clj-time.core :as time] [clojure.data.json :as json] [datomic.api :as d] [unilog.context :as lc] [clojure.tools.logging :as log] [mount.core :as mount] [yang.scheduler :as scheduler])) (defn locations [] (->> (client/get "https://connect.squareup.com/v2/locations" {:headers {"Square-Version" "2020-08-12" "Authorization" "Bearer EAAAEO2xSqesDutZz71hz3eulKmrlKTiEqG3uZ4j25x5GYlOluQ2cj2JxNUXqXD7" "Content-Type" "application/json"} :as :json}) :body :locations)) (defn search [l] (log/info "Searching for" l) (->> (client/post "https://connect.squareup.com/v2/orders/search" {:headers {"Square-Version" "2020-08-12" "Authorization" "Bearer EAAAEO2xSqesDutZz71hz3eulKmrlKTiEqG3uZ4j25x5GYlOluQ2cj2JxNUXqXD7" "Content-Type" "application/json"} :body (json/write-str {"location_ids" [l] "limit" 4000}) :as :json}) :body :orders)) (defn amount->money [amt] (* 0.01 (or (:amount amt) 0.0))) (defn location_id->client-location [location] ({"2RVBYER6QSV7W" ["NGAK" "MH"] "8JT71V8XGYAT3" ["NGKG" "NB"] "SCX0Y8CTGM1S0" ["NGE1" "UC"] "FNH5VRT890WK8" ["NGMJ" "SC"] "AMQ0NPA8FGDEF" ["NGPG" "SZ"] "4X8T65741AEPS" ["NGVZ" "NP"] "KMVFQ9CRCXJ10" ["NGZO" "VT"]} location)) (defn daily-results [] (->> (locations) (map :id) (filter location_id->client-location) (mapcat search) (map (fn [order] (let [[client loc] (location_id->client-location (:location_id order))] (remove-nils #:sales-order {:date (coerce/to-date (time/to-time-zone (coerce/to-date-time (:created_at order)) (time/time-zone-for-id "America/Los_Angeles"))) :client [:client/code client] :location loc :external-id (str "square-" client "-" loc "-" (:id order)) :total (-> order :net_amounts :total_money amount->money) :tax (-> order :net_amounts :tax_money amount->money) :tip (-> order :net_amounts :tip_money amount->money) :charges (->> (:tenders order) (map (fn [t] (remove-nils #:charge {:type-name (:type t) :total (amount->money (:amount_money t)) :tip (amount->money (:tip_money t))})))) :line-items (->> (:line_items order) (map (fn [li] (remove-nils #:order-line-item {:item-name (:name li) :total (amount->money (:total_money li)) :tax (amount->money (:total_tax_money li))}))))})))))) #_(daily-results) (defn upsert [] (lc/with-context {:source "Square loading"} (try (let [existing (->> (d/query {:query {:find ['?external-id] :in ['$] :where ['[_ :sales-order/external-id ?external-id]]} :args [(d/db conn)]}) (map first) set) _ (log/info (count existing) "Sales orders already exist") to-create (filter #(not (existing (:sales-order/external-id %))) (daily-results))] (doseq [x (partition-all 20 to-create)] (log/info "Loading " (count x)) @(d/transact conn x))) (catch Exception e (log/error e))))) (defn reset [] (->> (d/query {:query {:find ['?e] :in ['$] :where ['[?e :sales-order/date]]} :args [(d/db conn)]}) (map first) (map (fn [x] [:db/retractEntity x])))) (mount/defstate square-loader :start (scheduler/every (* 15 60 1000) upsert) :stop (scheduler/stop square-loader)) (comment (daily-results) (do (upsert) nil) (do @(d/transact conn (reset)) nil))