(ns auto-ap.ezcater-test (:require [auto-ap.ezcater.core :as sut] [clojure.test :as t] [datomic.api :as d ] [auto-ap.utils :refer [dollars=]] [auto-ap.datomic :refer [uri]] [auto-ap.datomic.migrate :as m] [auto-ap.time-reader])) (defn wrap-setup [f] (with-redefs [auto-ap.datomic/uri "datomic:mem://datomic-transactor:4334/invoice"] (d/create-database uri) (with-redefs [auto-ap.datomic/conn (d/connect uri)] (m/migrate auto-ap.datomic/conn) (f) (d/release auto-ap.datomic/conn) (d/delete-database uri)))) (t/use-fixtures :each wrap-setup) (def sample-event {"id" "bf3dcf5c-a68f-42d9-9084-049133e03d3d", "parent_type" "Caterer", "parent_id" "91541331-d7ae-4634-9e8b-ccbbcfb2ce70", "entity_type" "Order", "entity_id" "9ab05fee-a9c5-483b-a7f2-14debde4b7a8", "key" "accepted", "occurred_at" "2022-07-21T19:21:07.549Z"}) (def known-order {:uuid "9ab05fee-a9c5-483b-a7f2-14debde4b7a8", :client-code "ABC", :client-location "DT" :orderSourceType "MARKETPLACE", :caterer {:name "Nick The Greek", :uuid "91541331-d7ae-4634-9e8b-ccbbcfb2ce70", :address {:street "165 Plaza Dr"}}, :event {:timestamp "2022-07-21T19:15:00Z", :catererHandoffFoodTime "2022-07-21T19:15:00Z", :orderType "TAKEOUT"}, :catererCart {:orderItems [{:name "Spartan Package", :quantity 10, :posItemId nil, :totalInSubunits {:currency "USD", :subunits 20950}} {:name "Spartan Package", :quantity 10, :posItemId nil, :totalInSubunits {:currency "USD", :subunits 20950}}], :totals {:catererTotalDue 420.65}, :feesAndDiscounts []}, :totals {:customerTotalDue {:currency "USD", :subunits 45409}, :pointOfSaleIntegrationFee {:currency "USD", :subunits 0}, :tip {:currency "USD", :subunits 0}, :salesTax {:currency "USD", :subunits 3509}, :salesTaxRemittance {:currency "USD", :subunits 0}, :subTotal {:currency "USD", :subunits 41900}}}) (t/deftest lookup-order (t/testing "It should find the order from ezcater" (with-redefs [sut/get-caterer (fn [k] (t/is (= k "91541331-d7ae-4634-9e8b-ccbbcfb2ce70")) { :ezcater-integration/_caterers {:ezcater-integration/api-key "bmlrdHNpZ2FyaXNAZ21haWwuY29tOmQwMzQwMjYzOWI2ODQxNmVkMjdmZWYxMWFhZTk3YzU1MDlmNTcyNjYwMDAzOTA5MDE2OGMzODllNDBjNTVkZGE"} :ezcater-location/_caterer [{:ezcater-location/location "DT" :client/_ezcater-locations {:client/code "ABC"}}] })] (t/is (= known-order (sut/lookup-order sample-event)))))) (t/deftest order->sales-order (t/testing "It should use the date" (t/is (= #clj-time/date-time "2022-01-01T00:00:00-08:00" (-> known-order (assoc-in [:event :timestamp] "2022-01-01T08:00:00Z") (sut/order->sales-order) (:sales-order/date )))) (t/is (= #clj-time/date-time "2022-06-01T00:00:00-07:00" (-> known-order (assoc-in [:event :timestamp] "2022-06-01T07:00:00Z") (sut/order->sales-order) (:sales-order/date ))))) (t/testing "It should categorize every item as 'External Catering'" (t/is (= 2 (-> known-order sut/order->sales-order :sales-order/line-items count))) (t/is (= #{"External Catering"} (->> known-order sut/order->sales-order :sales-order/line-items (map :order-line-item/category) set)))) (t/testing "It should generate an id for every line item" (t/is (= ["ezcater/order/ABC-DT-9ab05fee-a9c5-483b-a7f2-14debde4b7a8-0" "ezcater/order/ABC-DT-9ab05fee-a9c5-483b-a7f2-14debde4b7a8-1"] (->> known-order sut/order->sales-order :sales-order/line-items (map :order-line-item/external-id))))) (t/testing "It should generate an external-id" (t/is (= "ezcater/order/ABC-DT-9ab05fee-a9c5-483b-a7f2-14debde4b7a8" (:sales-order/external-id (sut/order->sales-order known-order))))) (t/testing "Should include package name" (t/is (= #{"Spartan Package"} (->> known-order sut/order->sales-order :sales-order/line-items (map :order-line-item/item-name) set)))) (t/testing "Should use the total amount" (t/is (= [34.29 206.75] (->> (-> known-order (assoc-in [:catererCart :orderItems 0 :totalInSubunits :subunits] 3429) (assoc-in [:catererCart :orderItems 1 :totalInSubunits :subunits] 20675)) sut/order->sales-order :sales-order/line-items (map :order-line-item/total))))) (t/testing "Should capture amounts" (t/is (= 35.09 (-> known-order sut/order->sales-order :sales-order/tax))) (t/is (= 0.0 (-> known-order sut/order->sales-order :sales-order/tip)))) (t/testing "Should calculate 7% commision on ezcater orders" (t/is (dollars= 7.0 (-> known-order (assoc :orderSourceType "EZCATER") (assoc-in [:totals :subTotal :subunits] 10000) sut/commision))) (t/testing "Should inlclude delivery fee in commision" (t/is (dollars= 14.0 (-> known-order (assoc :orderSourceType "EZCATER") (assoc-in [:totals :subTotal :subunits] 10000) (assoc-in [:catererCart :feesAndDiscounts 0 :subunits] 10000) sut/commision))))) (t/testing "Should calculate 15% commision on marketplace orders" (t/is (dollars= 15.0 (-> known-order (assoc :orderSourceType "MARKETPLACE") (assoc-in [:totals :subTotal :subunits] 10000) sut/commision))) (t/testing "Should inlclude delivery fee in commision" (t/is (dollars= 30.0 (-> known-order (assoc :orderSourceType "MARKETPLACE") (assoc-in [:totals :subTotal :subunits] 10000) (assoc-in [:catererCart :feesAndDiscounts 0 :subunits] 10000) sut/commision))))) (t/testing "Should calculate 2.75% ccp fee" (t/is (dollars= 8.25 (-> known-order (assoc :orderSourceType "MARKETPLACE") (assoc-in [:totals :subTotal :subunits] 10000) (assoc-in [:totals :salesTax :subunits] 10000) (assoc-in [:catererCart :feesAndDiscounts 0 :subunits] 10000) sut/ccp-fee)))) (t/testing "Should use ezcater total paid to the customer" (t/is (dollars= 420.65 (-> known-order sut/order->sales-order :sales-order/total)))) (t/testing "Should derive adjustments food-total + sales-tax - caterer-total - service fee - ccp fee" (t/is (dollars= -41.8975 (-> known-order sut/order->sales-order :sales-order/discount)))))