(ns ezcater-xls (:require [auto-ap.datomic :refer [conn]] [auto-ap.time :as atime] [clj-time.coerce :as coerce] [datomic.api :as dc] [clojure.data.json :as json] [dk.ative.docjure.spreadsheet :as doc] [auto-ap.parse :as parse] [com.brunobonacci.mulog :as mu] [auto-ap.logging :as alog] [clojure.java.io :as io])) (defn fmt-amount [a] (with-precision 2 (some-> a bigdec (.setScale 2 java.math.RoundingMode/HALF_UP) (double)))) (defn extract-sheet-details [f] (into [] (for [row (->> (doc/load-workbook f) (doc/sheet-seq) first (doc/row-seq) )] (mapv doc/read-cell (doc/cell-seq row)) ))) (defn rows->maps [rows] (let [[headers & rows] rows] (for [r rows] (into {} (map vector headers r))))) (defn map->sales-order [r clients] (let [order-number (get r "Order Number") event-date (get r "Event Date") store-name (get r "Store Name") adjustments (get r "Adjustments") tax (get r "Sales Tax") food-total (get r "Food Total") commission (get r "Commission") fee (get r "Payment Transaction Fee") tip (get r "Tip") caterer-name (get r "Caterer Name") client (some->> caterer-name (parse/exact-match clients)) client-id (:db/id client) location (first (:client/locations client))] (if (and event-date client-id location) #:sales-order {:date (atime/unparse-local (atime/localize (coerce/to-date-time event-date)) atime/iso-date) :order-number order-number :external-id (str "ezcater/order/" client-id "-" location "-" order-number) :client client :location location :reference-link (str order-number) :line-items [#:order-line-item {:external-id (str "ezcater/order/" client-id "-" location "-" order-number "-" 0) :item-name "EZCater Catering" :category "EZCater Catering" :discount (fmt-amount (or adjustments 0.0)) :tax (fmt-amount tax) :total (fmt-amount (+ food-total tax tip))}] :charges [#:charge {:type-name "CARD" :date (atime/unparse-local (atime/localize (coerce/to-date-time event-date)) atime/iso-date) :client client-id :location location :external-id (str "ezcater/charge/" client-id "-" location "-" order-number "-" 0) :processor :ccp-processor/ezcater :total (fmt-amount (+ food-total tax tip )) :tip (fmt-amount tip)}] :total (fmt-amount (+ food-total tax)) :discount (fmt-amount (or adjustments 0.0)) :service-charge (fmt-amount (+ fee commission)) :tax (fmt-amount tax) :tip (fmt-amount tip) :returns 0.0 :vendor :vendor/ccp-ezcater } (alog/warn ::missing-client :order order-number :store-name store-name :caterer-name caterer-name)))) (defn stream->sales-orders [s] (let [clients (map first (dc/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]] (dc/db conn)))] (into [] (->> s extract-sheet-details rows->maps (map #(map->sales-order % clients)) (filter identity))))) (defn import-stuff [] (with-open [s (io/input-stream "/home/brycecovert/Downloads/test_2023-04-01_2023-04-30_2023-05-04.xlsx")] (stream->sales-orders s)))