new /addfooditem route handler, query

*needs re-run of ddl
This commit is contained in:
Bart Akeley 2018-02-10 11:49:54 -06:00
parent dfe3309432
commit 7af08e122b
7 changed files with 84 additions and 55 deletions

View file

@ -1,30 +1,25 @@
CREATE EXTENSION IF NOT EXISTS "postgis";
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE TYPE QUANTITY_ENUM AS ENUM ('lots', 'many', 'few', 'none');
CREATE TYPE CATEGORY_ENUM AS ENUM ('beverages', 'desserts', 'entrees', 'other');
create table food_items (
CREATE TYPE QUANTITY AS ENUM ('lots', 'many', 'few', 'none');
CREATE TYPE CATEGORY AS ENUM ('beverages', 'desserts', 'entrees', 'other');
DROP TABLE IF EXISTS food_items CASCADE;
CREATE TABLE food_items (
id uuid PRIMARY KEY,
name VARCHAR(100),
place_id VARCHAR(50),
category CATEGORY_ENUM,
category CATEGORY,
images VARCHAR,
thumbImage VARCHAR,
loc geography(POINT,4326)
);
create table quantities (
DROP TABLE quantities CASCADE;
CREATE TABLE quantities (
food_item_id uuid,
date timestamp (1) with time zone,
quantity QUANTITY_ENUM,
quantity QUANTITY,
PRIMARY KEY(food_item_id, date)
);
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 (
uuid_generate_v4(),
@ -35,7 +30,6 @@ INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc)
'http://images.media-allrecipes.com/userphotos/560x315/1107530.jpg',
ST_GeogFromText('SRID=4326;POINT(-97.7532464 30.270667599999996)')
);
INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc)
VALUES (
uuid_generate_v4(),
@ -46,7 +40,6 @@ INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc)
'https://timenewsfeed.files.wordpress.com/2013/06/jellydonut.jpg',
ST_GeogFromText('SRID=4326;POINT(-97.742308 30.263963300000004)')
);
INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc)
VALUES (
uuid_generate_v4(),
@ -57,7 +50,6 @@ INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc)
'http://www.momshealthyeats.com/wp-content/uploads/2011/11/spelt-fudge-brownie.jpg',
ST_GeogFromText('SRID=4326;POINT(-97.7419085 30.265019100000004)')
);
INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc)
VALUES (
uuid_generate_v4(),
@ -68,7 +60,6 @@ INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc)
'http://cookingontheside.com/wp-content/uploads/2009/04/oatmeal_raisin_cookies_stack-400.jpg',
ST_GeogFromText('SRID=4326;POINT(-97.7532464 30.270667599999996)')
);
INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc)
VALUES (
uuid_generate_v4(),
@ -79,7 +70,6 @@ INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc)
'https://dannivee.files.wordpress.com/2013/10/img_1950.jpg',
ST_GeogFromText('SRID=4326;POINT(-97.742308 30.263963300000004)')
);
INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc)
VALUES (
uuid_generate_v4(),
@ -90,7 +80,6 @@ INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc)
'http://3.bp.blogspot.com/-NUKSXr1qLHs/UQmsaEFgbTI/AAAAAAAAA_Y/l4psfVl4a5A/s1600/white-powdered-sugar-doughnuts-tracie-kaska.jpg',
ST_GeogFromText('SRID=4326;POINT(-97.742308 30.263963300000004)')
);
INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc)
VALUES (
uuid_generate_v4(),
@ -101,7 +90,6 @@ INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc)
'http://josephcphillips.com/wp-content/uploads/2015/02/snickerdoodles2.jpg',
ST_GeogFromText('SRID=4326;POINT(-97.73798459999999 30.266898599999998)')
);
INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc)
VALUES (
uuid_generate_v4(),
@ -112,9 +100,7 @@ INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc)
'http://www.foodandhealth.co.uk/wp-content/uploads/2016/05/Hot-stone-Vegan-Pizza.jpg',
ST_GeogFromText('SRID=4326;POINT(-97.73798459999999 30.266898599999998)')
);
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
);

View file

@ -1,6 +1,6 @@
(ns aretherecookies.app
(:gen-class)
(:require [aretherecookies.handler :refer [food-items-handler quantity-handler]]
(:require [aretherecookies.handler :refer [food-items-handler quantity-handler add-food-item-handler]]
[aretherecookies.auth :refer [auth-backend]]
[environ.core :refer [env]]
[compojure.handler :refer [api]]
@ -16,7 +16,8 @@
(GET "/" [] (str {:csrf-token *anti-forgery-token*}))
(POST "/test" [] "ok")
(POST "/fooditems" [] food-items-handler)
(POST "/quantity" [] quantity-handler))
(POST "/quantity" [] quantity-handler)
(POST "/addfooditem" [] add-food-item-handler))
(def app-config (assoc-in api-defaults [:security :anti-forgery] false))

View file

@ -7,13 +7,13 @@
(defn facebook-me [token]
(client/get (str "https://graph.facebook.com/me?access_token=" token) {:accept :json}))
(defn facebook-me-ok [token]
(defn facebook-me-ok? [token]
(= 200 (:status (facebook-me token))) (swap! tokens assoc (keyword token) true))
(defn facebook-token-auth [_ token]
(cond
(get @tokens (keyword token)) token
(facebook-me-ok token) token))
(facebook-me-ok? token) token))
(def auth-backend
(backends/token {:token-name "facebook-token" :authfn facebook-token-auth}))

View file

@ -63,7 +63,10 @@
: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)}))
(insert-quantity-query @pooled-db {:food_item_id foodItemId :quantity quantity}))
(defn select-latest-quantity [{:keys [:foodItemId]}]
(select-latest-quantity-query @pooled-db {:food_item_id (wrap-in-quotes foodItemId)}))
(defn create-food-item [{:keys [:name :placeId :category :latitude :longitude]}]
(insert-food-item @pooled-db {:name name :placeId placeId :category category :longitude longitude :latitude latitude}))

View file

@ -1,24 +1,52 @@
(ns aretherecookies.handler
(:require [aretherecookies.db :refer [query-food-items insert-quantity]]
[aretherecookies.parsers :refer [food-items-to-json
parse-special-types]]
(:require [aretherecookies.db :refer [query-food-items
insert-quantity
create-food-item]]
[aretherecookies.parsers :refer [parse-special-types parse-location]]
[clojure.data.json :as json]
[clojure.string :as str]
[buddy.auth :refer [authenticated? throw-unauthorized]]))
(defn safe-json
"converts hashmaps into a JSON string suitable for a network response"
[data]
(json/write-str data :value-fn parse-special-types))
(defn bad-request
"returns a HTTP 404 error with the supplied body"
[body]
{:status 400 :body (safe-json body)})
(defn food-items-handler [req]
(println "req ---->" (:body req))
(println "/fooditems ---->" (:body req))
(let [{body :body} req]
(json/write-str
(safe-json
(hash-map
:filter (get body :filter)
:fooditems (food-items-to-json (query-food-items body)))
:value-fn parse-special-types)))
:filter (:filter body)
:fooditems (map parse-location (query-food-items body))))))
(defn quantity-handler [req]
(let [{{foodItemId :foodItemId quantity :quantity} :body} req]
(if-not (authenticated? req) (throw-unauthorized))
(println "req ---->" foodItemId quantity)
(println "/quantity ---->" foodItemId quantity)
(json/write-str
(insert-quantity {:foodItemId foodItemId :quantity quantity})
:value-fn parse-special-types)))
(def required-keys [:name :placeId :latitude :longitude :category :quantity])
(defn get-missing-keys
[foodItem]
(filter #(get foodItem %) required-keys))
(defn add-food-item-handler
"validate food item fields from request and insert into database returning newly created item"
[req]
(println "/addfooditem ---->" (:body req))
(if-not (authenticated? req) (throw-unauthorized))
(let [food-item (:body req) missing-keys (get-missing-keys food-item)]
(if (< (count missing-keys) 0)
(bad-request {"missingkeys" missing-keys})
(as->
(create-food-item food-item) %
(map parse-location %)
(safe-json %)))))

View file

@ -12,24 +12,16 @@
(defn get-coords [item]
(->
item
(:location)
json/read-str
(:coordinates)))
(defn build-lat-lng [[lng lat]]
(hash-map :longitude lng :latitude lat))
(:location item)
json/read-str
(:coordinates)))
(defn build-latlng [item]
(let [[lng lat] (get-coords item)]
(hash-map :longitude lng :latitude lat)))
(let [[longitude latitude] (get-coords item)]
(hash-map :longitude longitude :latitude latitude)))
(defn parse-location [item]
(defn parse-location [food-item]
(->
item
build-latlng
(merge item)
(dissoc :location)))
(defn food-items-to-json [query-result]
(map parse-location query-result))
(build-latlng food-item)
(merge food-item)
(dissoc :location)))

View file

@ -36,11 +36,30 @@ 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)
VALUES (:v:food_item_id::uuid, :v:quantity::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
ORDER BY date DESC LIMIT 1
-- :name insert-food-item
INSERT INTO food_items (id, name, place_id, category, loc)
VALUES (
uuid_generate_v4(),
:v:name,
:v:placeId,
:v:category::category,
ST_SetSRID(ST_Point(:longitude, :latitude), 4326)::geography
)
RETURNING
id AS id,
name AS name,
place_id AS place_id,
category AS category,
images AS images,
thumbImage AS thumbImage,
ST_AsGeoJSON(loc) AS location,
ST_Distance(loc, ST_SetSRID(ST_Point(:longitude, :latitude), 4326)::geography) / 1609 AS distance