From bcb7699a7e5a38fc1a1a10aaf09a6b2d1bca5027 Mon Sep 17 00:00:00 2001 From: Bart Akeley Date: Sun, 26 Nov 2017 19:46:55 -0600 Subject: [PATCH] quantity endpoint inserts a new quantity into the quantities table and returns what it created - timestamp is generated at the SQL level --- README.md | 4 +++- ...le-post.json => sample-food-item-post.json | 0 sample-quantity-post.json | 4 ++++ scripts/ddl.sql | 6 +++++- src/aretherecookies/app.clj | 7 +++---- src/aretherecookies/db.clj | 14 ++++++++++---- src/aretherecookies/handler.clj | 10 ++++++++-- src/aretherecookies/queries.sql | 19 ++++++++++++++----- 8 files changed, 47 insertions(+), 17 deletions(-) rename sample-post.json => sample-food-item-post.json (100%) create mode 100644 sample-quantity-post.json diff --git a/README.md b/README.md index 61bf0fe..ba904bf 100644 --- a/README.md +++ b/README.md @@ -16,4 +16,6 @@ To start a web server for the application, run: To test a request/response, run: - curl --data @sample-post.json --header "Content-Type: application/json" http://localhost:3000/fooditems + curl --data @sample-food-item-post.json --header "Content-Type: application/json" http://localhost:3000/fooditems + + curl --data @sample-quantity-post.json --header "Content-Type: application/json" http://localhost:3000/quantity diff --git a/sample-post.json b/sample-food-item-post.json similarity index 100% rename from sample-post.json rename to sample-food-item-post.json diff --git a/sample-quantity-post.json b/sample-quantity-post.json new file mode 100644 index 0000000..827ec0f --- /dev/null +++ b/sample-quantity-post.json @@ -0,0 +1,4 @@ +{ + "foodItemId": "9e1661c8-a453-4eb9-af07-d06cbaebd650", + "quantity": "lots" +} diff --git a/scripts/ddl.sql b/scripts/ddl.sql index 2b9bb01..1af0aa5 100644 --- a/scripts/ddl.sql +++ b/scripts/ddl.sql @@ -23,7 +23,7 @@ create table quantities ( PRIMARY KEY(food_item_id, date) ); -CREATE INDEX food_loc_index ON food_items USING GIST ( loc ); +CREATE INDEX IF NOT EXISTS food_loc_index ON food_items USING GIST ( loc ); INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc) VALUES ( @@ -114,3 +114,7 @@ INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc) ); INSERT INTO quantities SELECT id, current_timestamp, 'many' FROM food_items; + +CREATE VIEW latest_quantities AS SELECT food_item_id, quantity, date from quantities q1 where date = ( + SELECT max(date) FROM quantities q2 WHERE q1.food_item_id=q2.food_item_id +); \ No newline at end of file diff --git a/src/aretherecookies/app.clj b/src/aretherecookies/app.clj index 4da5314..cac8c6f 100644 --- a/src/aretherecookies/app.clj +++ b/src/aretherecookies/app.clj @@ -1,6 +1,6 @@ (ns aretherecookies.app (:gen-class) - (:require [aretherecookies.handler :refer [food-items-handler]] + (:require [aretherecookies.handler :refer [food-items-handler quantity-handler]] [environ.core :refer [env]] [compojure.handler :refer [site]] [compojure.core :refer :all] @@ -11,11 +11,10 @@ [ring.middleware.defaults :refer [wrap-defaults api-defaults]])) (defroutes app-routes - (GET "/" [] (str {:csrf-token - *anti-forgery-token*})) + (GET "/" [] (str {:csrf-token *anti-forgery-token*})) (POST "/test" req "ok") (POST "/fooditems" req (wrap-json-body food-items-handler)) - (GET "/echo" [location filter] (str location filter))) + (POST "/quantity" req (wrap-json-body quantity-handler))) (def app-config (assoc-in api-defaults [:security :anti-forgery] false)) diff --git a/src/aretherecookies/db.clj b/src/aretherecookies/db.clj index 49bbe13..8da46e9 100644 --- a/src/aretherecookies/db.clj +++ b/src/aretherecookies/db.clj @@ -44,14 +44,14 @@ :else by-distance) args)) -(defn wrap-single-quotes [tokenVec] - (map #(str/replace % #"(^|$)" "'") tokenVec)) +(defn wrap-in-quotes [token] + (str/replace token #"(^|$)" "'")) (defn get-where [{:keys [:lat :lng :filter]}] (let [radius (-> (filter "radius") (or 10)) categories (filter "categories")] (cond - categories (has-category {:categories (wrap-single-quotes categories) :lat lat :lng lng :dist radius}) + categories (has-category {:categories (map wrap-in-quotes categories) :lat lat :lng lng :dist radius}) :else (within-radius {:lat lat :lng lng :dist radius})))) (defn query-food-items [{lat "lat" lng "lng" filter "filter"}] @@ -60,4 +60,10 @@ {:lat lat :lng lng :where (get-where {:lat lat :lng lng :filter filter}) - :order (get-orderby filter)})) \ No newline at end of file + :order (get-orderby filter)})) + +(defn insert-quantity [{:keys [foodItemId quantity]}] + (insert-quantity-query @pooled-db {:food_item_id (wrap-in-quotes foodItemId) :quantity (wrap-in-quotes quantity)})) + +(defn select-latest-quantity [{:keys [:foodItemId]}] + (select-latest-quantity-query @pooled-db {:food_item_id (wrap-in-quotes foodItemId)})) diff --git a/src/aretherecookies/handler.clj b/src/aretherecookies/handler.clj index 473d2e4..16a3f45 100644 --- a/src/aretherecookies/handler.clj +++ b/src/aretherecookies/handler.clj @@ -1,15 +1,21 @@ (ns aretherecookies.handler - (:require [aretherecookies.db :refer [query-food-items]] + (:require [aretherecookies.db :refer [query-food-items insert-quantity]] [aretherecookies.parsers :refer [food-items-to-json parse-special-types]] [clojure.data.json :as json] [clojure.string :as str])) (defn food-items-handler [req] - (println "req---->" (:body req)) + (println "req ---->" (:body req)) (let [{body :body} req] (json/write-str (hash-map :filter (get body "filter") :fooditems (food-items-to-json (query-food-items body))) :value-fn parse-special-types))) + +(defn quantity-handler [{{foodItemId "foodItemId" quantity "quantity"} :body}] + (println "req ---->" foodItemId quantity) + (json/write-str + (insert-quantity {:foodItemId foodItemId :quantity quantity}) + :value-fn parse-special-types)) diff --git a/src/aretherecookies/queries.sql b/src/aretherecookies/queries.sql index 1584d83..83b2464 100644 --- a/src/aretherecookies/queries.sql +++ b/src/aretherecookies/queries.sql @@ -9,11 +9,9 @@ SELECT ST_AsGeoJSON(f.loc) AS location, ST_Distance(f.loc, ST_SetSRID(ST_Point(:lng, :lat), 4326)::geography) / 1609 AS distance, q.quantity AS quantity, - q.updated AS lastUpdated + q.date AS lastUpdated FROM food_items f -LEFT OUTER JOIN ( - SELECT food_item_id, quantity, MAX(date) AS updated FROM quantities GROUP BY food_item_id, quantity -) q +LEFT OUTER JOIN latest_quantities q ON f.id = q.food_item_id :snip:where :snip:order @@ -34,4 +32,15 @@ ORDER BY distance ASC ORDER BY lastUpdated DESC -- :snip by-quantity -ORDER BY quantity DESC \ No newline at end of file +ORDER BY quantity DESC + +-- :name insert-quantity-query +INSERT INTO quantities (food_item_id, quantity, date) +VALUES (:i:food_item_id, :i:quantity, current_timestamp) +RETURNING * + +-- :name select-latest-quantity-query +SELECT food_item_id, quantity, date AS updated +FROM quantities +WHERE food_item_id=:i:food_item_id +ORDER BY date DESC LIMIT 1 \ No newline at end of file