mirror of
https://github.com/mruwnik/chicken-master.git
synced 2025-06-08 21:34:43 +02:00
calculate prices
This commit is contained in:
parent
9bee3a66f9
commit
06059b830d
@ -24,6 +24,9 @@
|
|||||||
(defn save-product-group [user-id customer-id body]
|
(defn save-product-group [user-id customer-id body]
|
||||||
(customers/save-product-group user-id (Integer/parseInt customer-id) body)
|
(customers/save-product-group user-id (Integer/parseInt customer-id) body)
|
||||||
(get-customers user-id))
|
(get-customers user-id))
|
||||||
|
(defn save-customer-prices [user-id customer-id body]
|
||||||
|
(customers/save-prices user-id (Integer/parseInt customer-id) body)
|
||||||
|
(get-customers user-id))
|
||||||
|
|
||||||
(defn delete-customer [user-id id]
|
(defn delete-customer [user-id id]
|
||||||
(->> id edn/read-string (customers/delete! user-id))
|
(->> id edn/read-string (customers/delete! user-id))
|
||||||
@ -52,6 +55,8 @@
|
|||||||
(DELETE "/customers/:id" [id :as {user-id :basic-authentication}] (delete-customer user-id id))
|
(DELETE "/customers/:id" [id :as {user-id :basic-authentication}] (delete-customer user-id id))
|
||||||
(POST "/customers/:id/product-group" [id :as {user-id :basic-authentication body :body}]
|
(POST "/customers/:id/product-group" [id :as {user-id :basic-authentication body :body}]
|
||||||
(save-product-group user-id id body))
|
(save-product-group user-id id body))
|
||||||
|
(POST "/customers/:id/prices" [id :as {user-id :basic-authentication body :body}]
|
||||||
|
(save-customer-prices user-id id body))
|
||||||
|
|
||||||
(GET "/products" request (get-products request))
|
(GET "/products" request (get-products request))
|
||||||
(POST "/products" request (save-products request))
|
(POST "/products" request (save-products request))
|
||||||
|
@ -23,18 +23,40 @@
|
|||||||
(reduce-kv insert-products {})
|
(reduce-kv insert-products {})
|
||||||
(assoc client :product-groups))))
|
(assoc client :product-groups))))
|
||||||
|
|
||||||
(def users-select-query
|
|
||||||
"SELECT * FROM customers c
|
(def user-product-groups-query
|
||||||
|
"SELECT c.id, c.name, cg.name, cg.id, cgp.amount, cgp.price, p.name FROM customers c
|
||||||
LEFT OUTER JOIN customer_groups cg on c.id = cg.customer_id
|
LEFT OUTER JOIN customer_groups cg on c.id = cg.customer_id
|
||||||
LEFT OUTER JOIN customer_group_products cgp on cg.id = cgp.customer_group_id
|
LEFT OUTER JOIN customer_group_products cgp on cg.id = cgp.customer_group_id
|
||||||
LEFT OUTER JOIN products p ON p.id = cgp.product_id
|
LEFT OUTER JOIN products p ON p.id = cgp.product_id
|
||||||
WHERE c.deleted IS NULL aND c.user_id = ?")
|
WHERE c.deleted IS NULL AND c.user_id = ?")
|
||||||
|
|
||||||
(defn get-all [user-id]
|
(def user-prices-query
|
||||||
(->> (sql/query db/db-uri [users-select-query user-id])
|
"SELECT c.id, c.name, cp.price, p.name FROM customers c
|
||||||
|
LEFT OUTER JOIN customer_products cp on c.id = cp.customer_id
|
||||||
|
LEFT OUTER JOIN products p ON p.id = cp.product_id
|
||||||
|
WHERE c.deleted IS NULL AND c.user_id = ?")
|
||||||
|
|
||||||
|
|
||||||
|
(defn get-product-groups [user-id]
|
||||||
|
(->> (sql/query db/db-uri [user-product-groups-query user-id])
|
||||||
(group-by (fn [{:customers/keys [id name]}] {:id id :name name}))
|
(group-by (fn [{:customers/keys [id name]}] {:id id :name name}))
|
||||||
(map (partial apply extract-product-groups))))
|
(map (partial apply extract-product-groups))))
|
||||||
|
|
||||||
|
(defn get-prices [user-id]
|
||||||
|
(->> (sql/query db/db-uri [user-prices-query user-id])
|
||||||
|
(filter :customer_products/price)
|
||||||
|
(group-by :customers/id)
|
||||||
|
(reduce-kv (fn [coll user vals]
|
||||||
|
(->> vals
|
||||||
|
(reduce #(assoc-in %1 [(-> %2 :products/name keyword) :price] (:customer_products/price %2)) {})
|
||||||
|
(assoc coll user))) {})))
|
||||||
|
|
||||||
|
(defn get-all [user-id]
|
||||||
|
(let [prices (get-prices user-id)]
|
||||||
|
(map #(assoc % :prices (-> % :id prices))
|
||||||
|
(get-product-groups user-id))))
|
||||||
|
|
||||||
(defn create! [user-id name]
|
(defn create! [user-id name]
|
||||||
(jdbc/execute! db/db-uri
|
(jdbc/execute! db/db-uri
|
||||||
["INSERT INTO customers (name, user_id) VALUES(?, ?) ON CONFLICT (name, user_id) DO UPDATE SET deleted = NULL"
|
["INSERT INTO customers (name, user_id) VALUES(?, ?) ON CONFLICT (name, user_id) DO UPDATE SET deleted = NULL"
|
||||||
@ -54,7 +76,6 @@
|
|||||||
(do (create! user-id name)
|
(do (create! user-id name)
|
||||||
(get-by-name tx user-id name))))
|
(get-by-name tx user-id name))))
|
||||||
|
|
||||||
|
|
||||||
(defn upsert-customer-group! [tx user-id customer-id {:keys [id name]}]
|
(defn upsert-customer-group! [tx user-id customer-id {:keys [id name]}]
|
||||||
(if (jdbc/execute-one! tx ["SELECT * FROM customer_groups WHERE user_id = ? AND customer_id = ? AND id =?"
|
(if (jdbc/execute-one! tx ["SELECT * FROM customer_groups WHERE user_id = ? AND customer_id = ? AND id =?"
|
||||||
user-id customer-id id])
|
user-id customer-id id])
|
||||||
@ -69,3 +90,8 @@
|
|||||||
tx user-id :customer_group
|
tx user-id :customer_group
|
||||||
(upsert-customer-group! tx user-id customer-id group)
|
(upsert-customer-group! tx user-id customer-id group)
|
||||||
(:products group))))
|
(:products group))))
|
||||||
|
|
||||||
|
(defn save-prices [user-id customer-id group]
|
||||||
|
(jdbc/with-transaction [tx db/db-uri]
|
||||||
|
(when (db/get-by-id tx user-id :customers customer-id)
|
||||||
|
(products/update-products-mapping! tx user-id :customer customer-id group))))
|
||||||
|
@ -71,35 +71,37 @@
|
|||||||
|
|
||||||
(deftest test-get-all
|
(deftest test-get-all
|
||||||
(testing "query is correct"
|
(testing "query is correct"
|
||||||
(with-redefs [sql/query (fn [_ query]
|
(with-redefs [sql/query (fn [_ [query id]]
|
||||||
(is (= query [sut/users-select-query "1"]))
|
(is (#{sut/user-product-groups-query
|
||||||
[])]
|
sut/user-prices-query} query))
|
||||||
(sut/get-all "1")))
|
(is (= id 1))
|
||||||
|
{})]
|
||||||
|
(sut/get-all 1)))
|
||||||
|
|
||||||
(testing "results are mapped correctly"
|
(testing "product results are mapped correctly"
|
||||||
(with-redefs [sql/query (constantly [{:customers/id 1 :customers/name "mr blobby" :bla 123}])]
|
(with-redefs [sql/query (constantly [{:customers/id 1 :customers/name "mr blobby" :bla 123}])]
|
||||||
(is (= (sut/get-all 2)
|
(is (= (sut/get-all 2)
|
||||||
[{:id 1 :name "mr blobby" :product-groups {}}]))))
|
[{:id 1 :name "mr blobby" :product-groups {} :prices nil}]))))
|
||||||
|
|
||||||
(testing "customer groups are mapped correctly"
|
(testing "customer groups are mapped correctly"
|
||||||
(with-redefs [sql/query (constantly sample-customers)]
|
(with-redefs [sql/query (constantly sample-customers)]
|
||||||
(is (= (sut/get-all "1")
|
(is (= (sut/get-all "1")
|
||||||
[{:id 1, :name "klient 1",
|
[{:id 1, :name "klient 1" :prices nil
|
||||||
:product-groups {"group1" {:id 1, :products {:eggs {:amount 2, :price 43},
|
:product-groups {"group1" {:id 1 :products {:eggs {:amount 2, :price 43},
|
||||||
:milk {:amount 32, :price nil}}},
|
:milk {:amount 32, :price nil}}},
|
||||||
"group 2" {:id 2, :products {:milk {:amount 1, :price 91},
|
"group 2" {:id 2 :products {:milk {:amount 1, :price 91},
|
||||||
:eggs {:amount 6, :price 23},
|
:eggs {:amount 6, :price 23},
|
||||||
:carrots {:amount 89, :price nil}}}}}
|
:carrots {:amount 89, :price nil}}}}}
|
||||||
{:id 2, :name "klient 2",
|
{:id 2, :name "klient 2" :prices nil
|
||||||
:product-groups {"group 3" {:id 3, :products {:milk {:amount 41, :price 12},
|
:product-groups {"group 3" {:id 3 :products {:milk {:amount 41, :price 12},
|
||||||
:eggs {:amount 6, :price nil}}}}}])))))
|
:eggs {:amount 6, :price nil}}}}}])))))
|
||||||
|
|
||||||
(deftest test-create!
|
(deftest test-create!
|
||||||
(testing "correct format is returned"
|
(testing "correct format is returned"
|
||||||
(with-redefs [jdbc/execute! (constantly [])
|
(with-redefs [jdbc/execute! (constantly [])
|
||||||
sql/query (constantly [{:customers/id 1 :customers/name "mr blobby" :bla 123}])]
|
sql/query (constantly [{:customers/id 1 :customers/name "mr blobby" :bla 123}])]
|
||||||
(is (= (sut/create! "1" "mr blobby")
|
(is (= (sut/create! "1" "mr blobby")
|
||||||
{:customers [{:id 1 :name "mr blobby" :product-groups {}}]})))))
|
{:customers [{:id 1 :name "mr blobby" :prices nil :product-groups {}}]})))))
|
||||||
|
|
||||||
|
|
||||||
(deftest save-product-group-test
|
(deftest save-product-group-test
|
||||||
|
@ -247,6 +247,12 @@ html body .calendar .day .product .product-name {
|
|||||||
html body .calendar .day .product .product-amount {
|
html body .calendar .day .product .product-amount {
|
||||||
width: 40px;
|
width: 40px;
|
||||||
max-height: 5px;
|
max-height: 5px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
html body .calendar .day .product .product-price {
|
||||||
|
width: 40px;
|
||||||
|
max-height: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
html body .calendar .day .summary {
|
html body .calendar .day .summary {
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
[reagent.core :as reagent]
|
[reagent.core :as reagent]
|
||||||
[chicken-master.subs :as subs]
|
[chicken-master.subs :as subs]
|
||||||
[chicken-master.html :as html]
|
[chicken-master.html :as html]
|
||||||
|
[chicken-master.config :as config]
|
||||||
[chicken-master.products :as prod]
|
[chicken-master.products :as prod]
|
||||||
[chicken-master.events :as event]
|
[chicken-master.events :as event]
|
||||||
[chicken-master.time :as time]))
|
[chicken-master.time :as time]))
|
||||||
@ -26,6 +27,13 @@
|
|||||||
first :product-groups
|
first :product-groups
|
||||||
(reduce-kv #(assoc %1 %2 (:products %3)) {})))
|
(reduce-kv #(assoc %1 %2 (:products %3)) {})))
|
||||||
|
|
||||||
|
(defn calc-order-prices [{:keys [who products] :as order}]
|
||||||
|
(->> products
|
||||||
|
(reduce-kv (fn [coll prod {:keys [amount price]}]
|
||||||
|
(assoc-in coll [prod :final-price]
|
||||||
|
(prod/calc-price (:id who) prod price amount))) products)
|
||||||
|
(assoc order :products)))
|
||||||
|
|
||||||
(defn order-form
|
(defn order-form
|
||||||
([order] (order-form order #{:who :day :notes :products :group-products}))
|
([order] (order-form order #{:who :day :notes :products :group-products}))
|
||||||
([order fields]
|
([order fields]
|
||||||
@ -59,7 +67,9 @@
|
|||||||
(html/input :notes "notka"
|
(html/input :notes "notka"
|
||||||
{:default (:notes @state)}))
|
{:default (:notes @state)}))
|
||||||
(when (:products fields)
|
(when (:products fields)
|
||||||
[prod/products-edit (:products @state) :available-prods available-prods])]))))
|
[prod/products-edit (:products @state)
|
||||||
|
:available-prods available-prods
|
||||||
|
:fields (if (config/settings :prices) #{:amount :price} #{:amount})])]))))
|
||||||
|
|
||||||
(defn edit-order []
|
(defn edit-order []
|
||||||
(html/modal
|
(html/modal
|
||||||
@ -68,7 +78,7 @@
|
|||||||
;; On success
|
;; On success
|
||||||
:on-submit (fn [form] (re-frame/dispatch [::event/save-order (format-raw-order form)]))))
|
:on-submit (fn [form] (re-frame/dispatch [::event/save-order (format-raw-order form)]))))
|
||||||
|
|
||||||
(defn format-order [settings {:keys [id who day hour notes products state]}]
|
(defn format-order [settings {:keys [id who day hour notes state products]}]
|
||||||
[:div {:class [:order state] :key (gensym)
|
[:div {:class [:order state] :key (gensym)
|
||||||
:draggable true
|
:draggable true
|
||||||
:on-drag-start #(-> % .-dataTransfer (.setData "text" id))}
|
:on-drag-start #(-> % .-dataTransfer (.setData "text" id))}
|
||||||
@ -93,30 +103,33 @@
|
|||||||
(into [:div {:class :products}]))])
|
(into [:div {:class :products}]))])
|
||||||
|
|
||||||
(defn day [settings [date orders]]
|
(defn day [settings [date orders]]
|
||||||
[:div {:class [:day (when (-> date time/parse-date time/today?) :today)]
|
(let [orders (map calc-order-prices orders)]
|
||||||
:on-drag-over #(.preventDefault %)
|
[:div {:class [:day (when (-> date time/parse-date time/today?) :today)]
|
||||||
:on-drop #(let [id (-> % .-dataTransfer (.getData "text") prod/num-or-nil)]
|
:on-drag-over #(.preventDefault %)
|
||||||
(.preventDefault %)
|
:on-drop #(let [id (-> % .-dataTransfer (.getData "text") prod/num-or-nil)]
|
||||||
(re-frame/dispatch [::event/move-order id date]))}
|
(.preventDefault %)
|
||||||
[:div {:class :day-header} (-> date time/parse-date time/format-date)]
|
(re-frame/dispatch [::event/move-order id date]))}
|
||||||
[:div
|
[:div {:class :day-header} (-> date time/parse-date time/format-date)]
|
||||||
[:div {:class :orders}
|
[:div
|
||||||
(if (settings :hide-fulfilled-orders)
|
[:div {:class :orders}
|
||||||
(->> orders (remove (comp #{:fulfilled} :state)) (map (partial format-order settings)))
|
(->> (if (settings :hide-fulfilled-orders)
|
||||||
(map (partial format-order settings) orders))
|
(remove (comp #{:fulfilled} :state) orders)
|
||||||
(when (settings :show-day-add-order)
|
orders)
|
||||||
[:button {:type :button
|
(map (partial format-order settings))
|
||||||
:on-click #(re-frame/dispatch [::event/edit-order date])} "+"])
|
doall)
|
||||||
(when (seq (map :products orders))
|
(when (settings :show-day-add-order)
|
||||||
[:div {:class :summary}
|
[:button {:type :button
|
||||||
[:hr {:class :day-seperator}]
|
:on-click #(re-frame/dispatch [::event/edit-order date])} "+"])
|
||||||
[:div {:class :header} "w sumie:"]
|
(when (seq (map :products orders))
|
||||||
(->> orders
|
[:div {:class :summary}
|
||||||
(map :products)
|
[:hr {:class :day-seperator}]
|
||||||
(apply merge-with +)
|
[:div {:class :header} "w sumie:"]
|
||||||
(sort-by first)
|
(->> orders
|
||||||
(map (partial prod/format-product settings))
|
(map :products)
|
||||||
(into [:div {:class :products-sum}]))])]]])
|
(apply merge-with (partial merge-with +))
|
||||||
|
(sort-by first)
|
||||||
|
(map (partial prod/format-product settings))
|
||||||
|
(into [:div {:class :products-sum}]))])]]]))
|
||||||
|
|
||||||
(defn calendar [days settings]
|
(defn calendar [days settings]
|
||||||
(->> days
|
(->> days
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
:editable-number-inputs (get-setting :editable-number-inputs false) ; only allow number modifications in the edit modal
|
:editable-number-inputs (get-setting :editable-number-inputs false) ; only allow number modifications in the edit modal
|
||||||
:hide-fulfilled-orders (get-setting :hide-fulfilled-orders false)
|
:hide-fulfilled-orders (get-setting :hide-fulfilled-orders false)
|
||||||
|
|
||||||
:prices (get-setting :prices false)
|
:prices (get-setting :prices true)
|
||||||
|
|
||||||
:backend-url (get-setting :backend-url
|
:backend-url (get-setting :backend-url
|
||||||
(if (= (.. js/window -location -href) "http://localhost:8280/")
|
(if (= (.. js/window -location -href) "http://localhost:8280/")
|
||||||
|
@ -135,7 +135,10 @@
|
|||||||
:overflow :hidden
|
:overflow :hidden
|
||||||
:margin-right "10px"}]
|
:margin-right "10px"}]
|
||||||
[:.product-amount {:width "40px"
|
[:.product-amount {:width "40px"
|
||||||
:max-height "5px"}]
|
:max-height "5px"
|
||||||
|
:display :inline-block}]
|
||||||
|
[:.product-price {:width "40px"
|
||||||
|
:max-height "5px"}]
|
||||||
|
|
||||||
]]
|
]]
|
||||||
[:.summary {:margin-top "10px"}]]]
|
[:.summary {:margin-top "10px"}]]]
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
[chicken-master.products :as prod]
|
[chicken-master.products :as prod]
|
||||||
[chicken-master.subs :as subs]
|
[chicken-master.subs :as subs]
|
||||||
[chicken-master.html :as html]
|
[chicken-master.html :as html]
|
||||||
|
[chicken-master.config :as config]
|
||||||
[chicken-master.events :as event]))
|
[chicken-master.events :as event]))
|
||||||
|
|
||||||
(defn order-adder [order who]
|
(defn order-adder [order who]
|
||||||
@ -47,6 +48,16 @@
|
|||||||
(when (and (:name @state) (:products @state))
|
(when (and (:name @state) (:products @state))
|
||||||
(re-frame/dispatch [::event/save-product-group (:id who) (assoc @state :products %)])))]])])))
|
(re-frame/dispatch [::event/save-product-group (:id who) (assoc @state :products %)])))]])])))
|
||||||
|
|
||||||
|
(defn price-adder [who]
|
||||||
|
(let [state (reagent/atom (:prices who))]
|
||||||
|
(fn []
|
||||||
|
[:details {:class :customer-prices}
|
||||||
|
[:summary "Ceny"]
|
||||||
|
[prod/products-edit state
|
||||||
|
:fields #{:price}
|
||||||
|
:getter-fn #(when (seq @state)
|
||||||
|
(re-frame/dispatch [::event/save-customer-prices (:id who) @state]))]])))
|
||||||
|
|
||||||
|
|
||||||
(defn show-customers []
|
(defn show-customers []
|
||||||
(html/modal
|
(html/modal
|
||||||
@ -57,12 +68,16 @@
|
|||||||
(let [client-orders (->> @(re-frame/subscribe [::subs/orders])
|
(let [client-orders (->> @(re-frame/subscribe [::subs/orders])
|
||||||
vals
|
vals
|
||||||
(group-by #(get-in % [:who :id])))]
|
(group-by #(get-in % [:who :id])))]
|
||||||
(for [{:keys [name id] :as who} @(re-frame/subscribe [::subs/available-customers])]
|
(doall
|
||||||
[:details {:class "client" :key (gensym)}
|
(for [{:keys [name id] :as who} @(re-frame/subscribe [::subs/available-customers])]
|
||||||
[:summary [:span name [:button {:on-click #(re-frame/dispatch
|
[:details {:class :client :key (gensym)}
|
||||||
[::event/confirm-action
|
[:summary [:span name [:button {:on-click #(re-frame/dispatch
|
||||||
"na pewno usunąć?"
|
[::event/confirm-action
|
||||||
::event/remove-customer id])} "-"]]]
|
"na pewno usunąć?"
|
||||||
|
::event/remove-customer id])} "-"]]]
|
||||||
|
(when (config/settings :prices)
|
||||||
|
[price-adder who])
|
||||||
|
|
||||||
[:details {:class :customer}
|
[:details {:class :customer}
|
||||||
[:summary "Stałe zamówienia"]
|
[:summary "Stałe zamówienia"]
|
||||||
(for [group (:product-groups who)]
|
(for [group (:product-groups who)]
|
||||||
@ -70,9 +85,9 @@
|
|||||||
[product-group-adder who group]])
|
[product-group-adder who group]])
|
||||||
[product-group-adder who []]]
|
[product-group-adder who []]]
|
||||||
|
|
||||||
[:details {:class :client-orders}
|
[:details {:class :client-orders}
|
||||||
[:summary "Zamówienia"]
|
[:summary "Zamówienia"]
|
||||||
[order-adder who]
|
[order-adder who]
|
||||||
(for [order (reverse (sort-by :day (client-orders id)))]
|
(for [order (reverse (sort-by :day (client-orders id)))]
|
||||||
[order-adder (assoc order :key (gensym)) who])]]))]
|
[order-adder (assoc order :key (gensym)) who])]])))]
|
||||||
:class :wide-popup))
|
:class :wide-popup))
|
||||||
|
@ -178,6 +178,13 @@
|
|||||||
:body group
|
:body group
|
||||||
:on-success ::process-stock)}))
|
:on-success ::process-stock)}))
|
||||||
|
|
||||||
|
(re-frame/reg-event-fx
|
||||||
|
::save-customer-prices
|
||||||
|
(fn [_ [_ id products]]
|
||||||
|
{:dispatch [::start-loading]
|
||||||
|
:http-xhrio (http-request :post (str "customers/" id "/prices")
|
||||||
|
:body products
|
||||||
|
:on-success ::process-stock)}))
|
||||||
|
|
||||||
;;; Storage events
|
;;; Storage events
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[reagent.core :as reagent]
|
[reagent.core :as reagent]
|
||||||
[chicken-master.html :as html]
|
[chicken-master.html :as html]
|
||||||
[chicken-master.config :as config]
|
|
||||||
[chicken-master.subs :as subs]))
|
[chicken-master.subs :as subs]))
|
||||||
|
|
||||||
(defn num-or-nil [val]
|
(defn num-or-nil [val]
|
||||||
@ -46,30 +45,31 @@
|
|||||||
(apply merge-with +))]))
|
(apply merge-with +))]))
|
||||||
(into {})))
|
(into {})))
|
||||||
|
|
||||||
(defn product-item [available state what]
|
(defn product-item [available state fields what]
|
||||||
(let [id (gensym)]
|
(let [id (gensym)]
|
||||||
[:div {:class :product-item-edit :key (gensym)}
|
[:div {:class :product-item-edit :key (gensym)}
|
||||||
[:div {:class :input-item}
|
[:div {:class :input-item}
|
||||||
;; [:label {:for :product} "co"]
|
;; [:label {:for :product} "co"]
|
||||||
[:select {:name (str "product-" id) :id :product :defaultValue (or (some-> what name) "-")
|
[:select {:name (str "product-" id) :id :product :defaultValue (or (some-> what name) "-")
|
||||||
:on-change #(let [prod (-> % .-target .-value keyword)]
|
:on-change #(let [prod (-> % .-target .-value keyword)]
|
||||||
(if-not (= prod :-)
|
(if-not (= prod :-) (swap! state assoc prod {}))
|
||||||
(swap! state assoc prod (+ (@state prod) (@state what))))
|
|
||||||
(swap! state dissoc what))}
|
(swap! state dissoc what))}
|
||||||
(for [product (->> available (concat [what]) (remove nil?) sort vec)]
|
(for [product (->> available (concat [what]) (remove nil?) sort vec)]
|
||||||
[:option {:key (gensym) :value product} (name product)])
|
[:option {:key (gensym) :value product} (name product)])
|
||||||
[:option {:key (gensym) :value nil} "-"]]]
|
[:option {:key (gensym) :value nil} "-"]]]
|
||||||
(number-input (str "amount-" id) nil (get-in @state [what :amount])
|
(when (:amount fields)
|
||||||
#(swap! state assoc-in [what :amount] (-> % .-target .-value num-or-nil)))
|
(number-input (str "amount-" id) nil (get-in @state [what :amount])
|
||||||
(when (config/settings :prices)
|
#(swap! state assoc-in [what :amount] (-> % .-target .-value num-or-nil))))
|
||||||
|
(when (:price fields)
|
||||||
[:div {:class :stock-product-price}
|
[:div {:class :stock-product-price}
|
||||||
(number-input (str "price-" id) "cena" (format-price (get-in @state [what :price]))
|
(number-input (str "price-" id) "cena" (format-price (get-in @state [what :price]))
|
||||||
#(swap! state assoc-in
|
#(swap! state assoc-in
|
||||||
[what :price]
|
[what :price]
|
||||||
(some-> % .-target .-value num-or-nil normalise-price)))])]))
|
(some-> % .-target .-value num-or-nil normalise-price)))])]))
|
||||||
|
|
||||||
(defn products-edit [state & {:keys [available-prods getter-fn]
|
(defn products-edit [state & {:keys [available-prods getter-fn fields]
|
||||||
:or {available-prods @(re-frame/subscribe [::subs/available-products])}}]
|
:or {available-prods @(re-frame/subscribe [::subs/available-products])
|
||||||
|
fields #{:amount :price}}}]
|
||||||
(let [all-product-names (-> available-prods keys set)]
|
(let [all-product-names (-> available-prods keys set)]
|
||||||
(swap! state #(or % {}))
|
(swap! state #(or % {}))
|
||||||
(fn []
|
(fn []
|
||||||
@ -78,7 +78,7 @@
|
|||||||
(conj (->> @state (map first) vec) nil)
|
(conj (->> @state (map first) vec) nil)
|
||||||
(map first @state))
|
(map first @state))
|
||||||
products (->> product-names
|
products (->> product-names
|
||||||
(map (partial product-item available state))
|
(map (partial product-item available state fields))
|
||||||
(into [:div {:class :product-items-edit}]))]
|
(into [:div {:class :product-items-edit}]))]
|
||||||
(if getter-fn
|
(if getter-fn
|
||||||
(conj products
|
(conj products
|
||||||
@ -86,12 +86,21 @@
|
|||||||
:on-click #(getter-fn (dissoc @state nil))} "ok"])
|
:on-click #(getter-fn (dissoc @state nil))} "ok"])
|
||||||
products)))))
|
products)))))
|
||||||
|
|
||||||
(defn format-product [settings [product {:keys [amount price]}]]
|
(defn calc-price [who what price amount]
|
||||||
|
(when-let [price (or price
|
||||||
|
(get-in @(re-frame/subscribe [::subs/customer-prices]) [who what])
|
||||||
|
(get-in @(re-frame/subscribe [::subs/available-products]) [what :price]))]
|
||||||
|
(* amount price)))
|
||||||
|
|
||||||
|
(defn format-product [settings [product {:keys [amount final-price]}]]
|
||||||
[:div {:key (gensym) :class :product}
|
[:div {:key (gensym) :class :product}
|
||||||
[:span {:class :product-name} product]
|
[:span {:class :product-name} product]
|
||||||
(if (settings :editable-number-inputs)
|
(if (settings :editable-number-inputs)
|
||||||
(number-input (str "amount-" product) "" amount nil)
|
(number-input (str "amount-" product) "" amount nil)
|
||||||
[:span {:class :product-amount} amount])])
|
[:span {:class :product-amount} amount])
|
||||||
|
(when (settings :prices)
|
||||||
|
[:span {:class :product-price}
|
||||||
|
(format-price final-price)])])
|
||||||
|
|
||||||
(defn item-adder [& {:keys [type value callback button class]
|
(defn item-adder [& {:keys [type value callback button class]
|
||||||
:or {type :text value "" button nil}}]
|
:or {type :text value "" button nil}}]
|
||||||
|
@ -8,6 +8,12 @@
|
|||||||
|
|
||||||
(re-frame/reg-sub ::available-products (fn [db] (:products db)))
|
(re-frame/reg-sub ::available-products (fn [db] (:products db)))
|
||||||
(re-frame/reg-sub ::available-customers (fn [db] (:customers db)))
|
(re-frame/reg-sub ::available-customers (fn [db] (:customers db)))
|
||||||
|
(re-frame/reg-sub
|
||||||
|
::customer-prices
|
||||||
|
(fn [db]
|
||||||
|
(->> db :customers
|
||||||
|
(reduce (fn [col {:keys [id prices]}]
|
||||||
|
(assoc col id (reduce-kv #(assoc %1 %2 (:price %3)) {} prices))) {}))))
|
||||||
(re-frame/reg-sub ::orders (fn [db] (:orders db)))
|
(re-frame/reg-sub ::orders (fn [db] (:orders db)))
|
||||||
|
|
||||||
(defn- show-modal? [modal db] (and (-> modal db :show) (-> db :loading? zero?)))
|
(defn- show-modal? [modal db] (and (-> modal db :show) (-> db :loading? zero?)))
|
||||||
|
@ -1,8 +1,57 @@
|
|||||||
(ns chicken-master.calendar-test
|
(ns chicken-master.calendar-test
|
||||||
(:require
|
(:require
|
||||||
[chicken-master.calendar :as sut]
|
[chicken-master.calendar :as sut]
|
||||||
|
[day8.re-frame.test :as rf-test]
|
||||||
|
[re-frame.core :as rf]
|
||||||
[cljs.test :refer-macros [deftest is testing]]))
|
[cljs.test :refer-macros [deftest is testing]]))
|
||||||
|
|
||||||
|
(defn set-db [updates]
|
||||||
|
(rf/reg-event-db
|
||||||
|
::merge-db
|
||||||
|
(fn [db [_ incoming]] (merge db incoming)))
|
||||||
|
(rf/dispatch [::merge-db updates]))
|
||||||
|
|
||||||
|
(deftest calc-order-prices-test
|
||||||
|
(let [order {:who {:name "bla" :id 123} :day "2020-10-10" :notes "ble"}]
|
||||||
|
(testing "no products"
|
||||||
|
(is (= (sut/calc-order-prices order) (assoc order :products nil))))
|
||||||
|
|
||||||
|
(testing "prices set in order"
|
||||||
|
(is (= (sut/calc-order-prices (assoc order :products {:eggs {:amount 12 :price 2}}))
|
||||||
|
(assoc order :products {:eggs {:amount 12 :price 2 :final-price 24}}))))
|
||||||
|
|
||||||
|
(testing "prices set per customer"
|
||||||
|
(rf-test/run-test-sync
|
||||||
|
(set-db {:customers [{:id 123 :prices {:eggs {:price 3}}}]})
|
||||||
|
(is (= (sut/calc-order-prices (assoc order :products {:eggs {:amount 12}}))
|
||||||
|
(assoc order :products {:eggs {:amount 12 :final-price 36}})))))
|
||||||
|
|
||||||
|
(testing "prices set globally"
|
||||||
|
(rf-test/run-test-sync
|
||||||
|
(set-db {:products {:eggs {:price 4}}})
|
||||||
|
(is (= (sut/calc-order-prices (assoc order :products {:eggs {:amount 12}}))
|
||||||
|
(assoc order :products {:eggs {:amount 12 :final-price 48}})))))
|
||||||
|
|
||||||
|
(testing "no price set"
|
||||||
|
(rf-test/run-test-sync
|
||||||
|
(set-db {:products {}})
|
||||||
|
(is (= (sut/calc-order-prices (assoc order :products {:eggs {:amount 12}}))
|
||||||
|
(assoc order :products {:eggs {:amount 12 :final-price nil}})))))
|
||||||
|
|
||||||
|
(testing "all together"
|
||||||
|
(rf-test/run-test-sync
|
||||||
|
(set-db {:products {:eggs {:price 4}}
|
||||||
|
:customers [{:id 123 :prices {:cows {:price 3}}}]})
|
||||||
|
(is (= (sut/calc-order-prices
|
||||||
|
(assoc order :products {:eggs {:amount 12}
|
||||||
|
:cows {:amount 2}
|
||||||
|
:milk {:amount 3 :price 5}
|
||||||
|
:carrots {:amount 6}}))
|
||||||
|
(assoc order :products {:eggs {:amount 12 :final-price 48}
|
||||||
|
:cows {:amount 2 :final-price 6}
|
||||||
|
:milk {:amount 3 :price 5 :final-price 15}
|
||||||
|
:carrots {:amount 6 :final-price nil}})))))))
|
||||||
|
|
||||||
(deftest format-raw-order-test
|
(deftest format-raw-order-test
|
||||||
(testing "no products"
|
(testing "no products"
|
||||||
(is (= (sut/format-raw-order {}) {:who {:name nil :id nil} :day nil :notes nil :products {}}))
|
(is (= (sut/format-raw-order {}) {:who {:name nil :id nil} :day nil :notes nil :products {}}))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user