Seperate users

This commit is contained in:
Daniel O'Connell 2021-02-23 23:26:32 +01:00
parent d0a14bd1ab
commit 182e613deb
6 changed files with 81 additions and 66 deletions

View File

@ -9,22 +9,24 @@ CREATE TABLE users (
CREATE TABLE customers (
id SERIAL,
name VARCHAR(512) UNIQUE,
name VARCHAR(512),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
deleted BOOLEAN,
user_id INT,
PRIMARY KEY(id),
UNIQUE(name, user_id),
CONSTRAINT fk_users FOREIGN KEY(user_id) REFERENCES users(id)
);
CREATE TABLE products (
id SERIAL,
name VARCHAR(512) UNIQUE,
name VARCHAR(512),
amount NUMERIC,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
deleted BOOLEAN,
user_id INT,
PRIMARY KEY(id),
UNIQUE(name, user_id),
CONSTRAINT fk_users FOREIGN KEY(user_id) REFERENCES users(id)
);

View File

@ -4,17 +4,17 @@
[chicken-master.db :as db]
[chicken-master.orders :as orders]))
(defn get-all []
(->> (sql/query db/db-uri ["select * from customers where deleted is null"])
(defn get-all [user-id]
(->> (sql/query db/db-uri ["select * from customers where deleted is null AND user_id = ?" user-id])
(map (fn [{:customers/keys [id name]}] {:id id :name name}))))
(defn create! [name]
(defn create! [user-id name]
(jdbc/execute! db/db-uri
["INSERT INTO customers (name) VALUES(?) ON CONFLICT (name) DO UPDATE SET deleted = NULL"
name])
{:customers (get-all)})
["INSERT INTO customers (name, user_id) VALUES(?, ?) ON CONFLICT (name, user_id) DO UPDATE SET deleted = NULL"
name user-id])
{:customers (get-all user-id)})
(defn delete! [id]
(sql/update! db/db-uri :customers {:deleted true} {:id id})
{:orders (orders/get-all)
:customers (get-all)})
(defn delete! [user-id id]
(sql/update! db/db-uri :customers {:deleted true} {:id id :user_id user-id})
{:orders (orders/get-all user-id)
:customers (get-all user-id)})

View File

@ -15,9 +15,15 @@
["INSERT INTO users (name, password) VALUES (?, crypt(?, gen_salt('bf')))" name passwd]))
(defn valid-user? [name passwd]
(jdbc/execute-one!
db-uri
[" SELECT * FROM users WHERE name = ? AND password = crypt(?, password)" name passwd]))
(:users/id (jdbc/execute-one!
db-uri
["SELECT * FROM users WHERE name = ? AND password = crypt(?, password)" name passwd])))
(defn get-by-id
([tx user-id table id] (get-by-id tx user-id table id :id))
([tx user-id table id id-column]
(jdbc/execute-one! tx [(str "SELECT * from " (name table) " WHERE " (name id-column) " = ? AND user_id = ?")
id user-id])))
(comment
(create-user "siloa" "krach")

View File

@ -16,41 +16,44 @@
{:headers {"Content-Type" "application/edn"}
:body resp})
(defn get-customers [] (as-edn (customers/get-all)))
(defn add-customer [request] (as-edn (some-> request :body :name customers/create!)))
(defn delete-customer [id] (as-edn (customers/delete! (edn/read-string id))))
(defn get-customers [user-id] (as-edn (customers/get-all user-id)))
(defn add-customer [{:keys [body basic-authentication]}]
(as-edn (some->> body :name (customers/create! basic-authentication))))
(defn delete-customer [user-id id] (->> id edn/read-string (customers/delete! user-id) as-edn))
(defn get-products [_] (as-edn (products/get-all)))
(defn save-products [request] (as-edn (some-> request :body products/update!)))
(defn get-products [user-id] (as-edn (products/get-all user-id)))
(defn save-products [{:keys [body basic-authentication]}]
(some->> body (products/update! basic-authentication) as-edn))
(defn get-orders [params] (as-edn {:orders (orders/get-all)}))
(defn get-orders [user-id] (as-edn {:orders (orders/get-all user-id)}))
(defn update-order [request]
(let [id (some-> request :route-params :id (Integer/parseInt))
(let [user-id (:basic-authentication request)
id (some-> request :route-params :id (Integer/parseInt))
order (-> request :body (update :id #(or % id)))]
(as-edn (orders/replace! order))))
(as-edn (orders/replace! user-id order))))
(defn delete-order [id] (as-edn (orders/delete! (edn/read-string id))))
(defn set-order-state [id status] (as-edn (orders/change-state! (edn/read-string id) status)))
(defn delete-order [user-id id] (->> id edn/read-string (orders/delete! user-id) as-edn))
(defn set-order-state [user-id id status] (as-edn (orders/change-state! user-id (edn/read-string id) status)))
(defn get-stock [params]
(defn get-stock [user-id]
(as-edn
{:customers (:body (get-customers))
:products (:body (get-products params))}))
{:customers (:body (get-customers user-id))
:products (:body (get-products user-id))}))
(defroutes routes
(GET "/stock" {params :query-params} (get-stock params))
(GET "/customers" [] (get-customers))
(GET "/stock" [:as {user-id :basic-authentication}] (get-stock user-id))
(GET "/customers" [:as {user-id :basic-authentication}] (get-customers user-id))
(POST "/customers" request (add-customer request))
(DELETE "/customers/:id" [id] (delete-customer id))
(DELETE "/customers/:id" [id :as {user-id :basic-authentication}] (delete-customer user-id id))
(GET "/products" request (get-products request))
(POST "/products" request (save-products request))
(GET "/orders" {params :query-params} (get-orders params))
(GET "/orders" [:as {user-id :basic-authentication}] (get-orders user-id))
(POST "/orders" request (update-order request))
(PUT "/orders/:id" request (update-order request))
(DELETE "/orders/:id" [id] (delete-order id))
(POST "/orders/:id/:status" [id status] (set-order-state id status))
(DELETE "/orders/:id" [id :as {user-id :basic-authentication}] (delete-order user-id id))
(POST "/orders/:id/:status" [id status :as {user-id :basic-authentication}] (set-order-state user-id id status))
(GET "/" [] (resource-response "index.html" {:root "public"}))
(resources "/")

View File

@ -6,14 +6,15 @@
[chicken-master.products :as products]
[chicken-master.time :as t]))
(defn- upsert-order! [tx user-id {:keys [id day state notes]}]
(let [order {:customer_id user-id
(defn- upsert-order! [tx user-id customer-id {:keys [id day state notes]}]
(let [order {:customer_id customer-id
:notes notes
:status (some-> state name jdbc.types/as-other)
:order_date (some-> day t/parse-date t/inst->timestamp)}]
(if id
(if (db/get-by-id tx user-id :orders id)
(do (sql/update! tx :orders order {:id id}) id)
(:orders/id (sql/insert! tx :orders order)))))
(:orders/id (sql/insert! tx :orders (assoc order :user_id user-id))))))
(defn- structure-order [items]
{:id (-> items first :orders/id)
@ -39,32 +40,35 @@
vals
(map structure-order)))
(defn get-order [tx id]
(first (get-orders tx "WHERE o.id = ?" [id])))
(defn get-order [tx user-id id]
(first (get-orders tx "WHERE o.id = ? AND o.user_id = ?" [id user-id])))
(defn get-all [] (get-orders db/db-uri nil []))
(defn get-all [user-id] (get-orders db/db-uri "WHERE o.user_id = ?" [user-id]))
(defn- orders-for-days [tx & days]
(defn- orders-for-days [tx user-id & days]
(let [days (remove nil? days)]
(->> days
(map t/inst->timestamp)
(map jdbc.types/as-date)
(get-orders tx (str "WHERE o.order_date::date IN " (db/psql-list days))))))
(into [user-id])
(get-orders tx (str "WHERE o.user_id = ? AND o.order_date::date IN " (db/psql-list days))))))
(defn- orders-between [tx from to]
(defn- orders-between [tx user-id from to]
(get-orders
tx
"WHERE o.order_date::date >= ? AND o.order_date::date <= ?"
"WHERE o.order_date::date >= ? AND o.order_date::date <= ? AND o.user_id = ?"
[(some-> from t/inst->timestamp jdbc.types/as-date)
(some-> to t/inst->timestamp jdbc.types/as-date)]))
(some-> to t/inst->timestamp jdbc.types/as-date)
user-id]))
(defn replace! [{:keys [who products] :as order}]
(defn replace! [user-id {:keys [who products] :as order}]
(prn order)
(jdbc/with-transaction [tx db/db-uri]
(let [user-id (or (:id who)
(:customers/id (sql/get-by-id tx :customers (:name who) :name {})))
(let [customer-id (or (:id who)
(:customers/id (db/get-by-id tx user-id :customers (:name who) :name)))
products-map (products/products-map tx products)
previous-day (some->> order :id (sql/get-by-id tx :orders) :orders/order_date (.toInstant))
order-id (upsert-order! tx user-id order)]
previous-day (some->> order :id (db/get-by-id tx user-id :orders) :orders/order_date (.toInstant))
order-id (upsert-order! tx user-id customer-id order)]
(sql/delete! tx :order_products {:order_id order-id})
(sql/insert-multi! tx :order_products
[:order_id :product_id :amount]
@ -72,21 +76,21 @@
:let [product-id (-> n name products-map)]
:when product-id]
[order-id product-id amount]))
(orders-for-days tx previous-day (some-> order :day t/parse-date)))))
(orders-for-days tx user-id previous-day (some-> order :day t/parse-date)))))
(defn delete! [id]
(defn delete! [user-id id]
(jdbc/with-transaction [tx db/db-uri]
(let [day (some->> id (sql/get-by-id tx :orders) :orders/order_date (.toInstant))]
(sql/delete! tx :orders {:id id})
(when day (orders-for-days tx day)))))
(let [day (some->> id (db/get-by-id tx user-id :orders) :orders/order_date (.toInstant))]
(sql/delete! tx :orders {:id id :user_id user-id})
(when day (orders-for-days tx user-id day)))))
(defn change-state!
"Update the state of the given order and also modify the number of products available:
* when `fulfilled` decrement the number of products
* when `waiting` increment the number (as this means a previously fulfilled order has been returned)"
[id state]
[user-id id state]
(jdbc/with-transaction [tx db/db-uri]
(let [order (get-order tx id)
(let [order (get-order tx user-id id)
operator (condp = state
"fulfilled" "-"
"waiting" "+")]
@ -96,4 +100,4 @@
[(str "UPDATE products SET amount = amount " operator " ? WHERE name = ?")
amount (name prod)]))
(sql/update! tx :orders {:status (jdbc.types/as-other state)} {:id id}))
(orders-for-days tx (-> order :day t/parse-date)))))
(orders-for-days tx user-id (-> order :day t/parse-date)))))

View File

@ -3,8 +3,8 @@
[next.jdbc.sql :as sql]
[chicken-master.db :as db]))
(defn get-all []
(->> (sql/query db/db-uri ["select * from products where deleted is null"])
(defn get-all [user-id]
(->> (sql/query db/db-uri ["select * from products where deleted is null and user_id = ?" user-id])
(map (fn [{:products/keys [name amount]}] [(keyword name) amount]))
(into {})))
@ -15,15 +15,15 @@
(map #(vector (:products/name %) (:products/id %)))
(into {})))
(defn update! [new-products]
(defn update! [user-id new-products]
(jdbc/with-transaction [tx db/db-uri]
(doseq [[prod amount] new-products]
(jdbc/execute! tx
["INSERT INTO products (name, amount) VALUES(?, ?)
ON CONFLICT (name) DO UPDATE SET amount = EXCLUDED.amount, deleted = NULL"
(name prod) amount]))
["INSERT INTO products (name, amount, user_id) VALUES(?, ?, ?)
ON CONFLICT (name, user_id) DO UPDATE SET amount = EXCLUDED.amount, deleted = NULL"
(name prod) amount user-id]))
(sql/update! tx :products
{:deleted true}
(into [(str "name NOT IN " (db/psql-list (keys new-products)))]
(->> new-products keys (map name)))))
(get-all))
(get-all user-id))