editable recurs

This commit is contained in:
Daniel O'Connell 2022-04-20 19:00:47 +02:00
parent b4ed659718
commit f6167bf3c0
9 changed files with 283 additions and 78 deletions

View File

@ -37,11 +37,11 @@
:end_date (t/to-db-date end-date))))
(defn duplicate-order! [tx user-id order updates]
(->> updates
(merge {:user_id user-id})
(set-dates order)
(sql/insert! tx :orders)
:orders/id))
(->> updates
(merge {:user_id user-id})
(set-dates order)
(sql/insert! tx :orders)
:orders/id))
(defn update-non-recurring [tx order updates]
(let [order-id (:orders/id order)
@ -55,12 +55,29 @@
(upsert-exception! tx order-id order_date (:recurrence_exceptions/status exception)))
order-id))
(update-non-recurring db/db-uri (db/get-by-id db/db-uri 2 :orders 285) {:notes "asddqwqwd" :order_date "2020-04-19"})
(recurrence-exception? db/db-uri 285 "2022-04-20")
(defn update-single-item [tx user-id from-date {:orders/keys [id order_date] :as order} updates]
(upsert-exception! tx id (t/to-db-date (or from-date order_date)) "canceled")
(duplicate-order! tx user-id (dissoc order :orders/recurrence) (dissoc updates :recurrence)))
(defn update-from-date [tx user-id from-date {:orders/keys [id order_date recurrence] :as order} updates]
(let [[recur-part-1 recur-part-2] (t/split-rule order_date recurrence from-date)]
(cond
;; Split the order into 2, from the given date
recur-part-2
(do
(sql/update! tx :orders {:end_date (t/to-db-date from-date) :recurrence recur-part-1} {:id id})
(duplicate-order! tx user-id order (assoc updates :recurrence recur-part-2)))
;; No need to split the event, as it's the first one
recur-part-1
(sql/update! tx :orders (set-dates order updates) {:id id})
:else nil ;; FIXME: What should happen if an invalid date is provided?
)))
(defn upsert-order! [tx user-id customer-id {:keys [id day notes update-type order-date recurrence]}]
(let [updates (assoc? {:customer_id customer-id}
:recurrence recurrence
:recurrence (some-> recurrence t/make-rule)
:notes notes
:order_date (some-> day t/to-db-date))
order (db/get-by-id tx user-id :orders id)]
@ -75,20 +92,26 @@
(do (sql/update! tx :orders (set-dates order updates) {:id id}) id)
(= :from-here update-type)
(do
;; TODO: update magic recurrence rules to handle splitting stuff here
(sql/update! tx :orders {:end_date (t/to-db-date order-date)} {:id id})
(duplicate-order! tx user-id order updates))
(update-from-date tx user-id order-date order updates)
:else ; single item modified
(do
(upsert-exception! tx id order-date "canceled")
(duplicate-order! tx user-id order updates)))))
(update-single-item tx user-id order-date order updates))))
;; (db/get-by-id db/db-uri 2 :orders 267)
;; (upsert-order! db/db-uri 2 15 {:notes "no recur1" :day "2022-04-20"})
;; (upsert-order! db/db-uri 2 15 {:notes "recur2" :day "2022-04-18" :recurrence "FREQ=DAILY;COUNT=10"})
;; (upsert-order! db/db-uri 2 15 {:update-type :all :id 279 :notes "recur2" :day "2022-04-18" :recurrence "FREQ=DAILY;COUNT=10"})
;; (upsert-order! db/db-uri 2 15 {:id 267 :notes "main-default" :day "2022-04-18" :order-date "2022-04-18"})
;; (upsert-order! db/db-uri 2 15 {:id 267 :notes "main" :day "2022-04-18"})
;; (upsert-order! db/db-uri 2 15 {:id 267 :notes "main-all" :update-type :all :day "2022-04-18" :order-date "2022-04-18"})
;; (upsert-order! db/db-uri 2 15 {:id 267 :notes "main-from" :update-type :from-here :day "2022-04-18" :order-date "2022-04-22"})
;; (upsert-order! db/db-uri 2 15 {:id 267 :notes "12323" :update-type :single :day "2022-04-18" :order-date "2022-04-18"})
;; (upsert-order! db/db-uri 2 15 {:id 260 :notes "1dsf2a" :update-type :single :day "2022-04-19"})
(defn structure-order [items]
{:id (-> items first :orders/id)
:notes (-> items first :orders/notes)
:recurrence (-> items first :orders/recurrence)
:recurrence (some-> items first :orders/recurrence t/parse-rule)
:who {:id (-> items first :customers/id)
:name (-> items first :customers/name)}
:products (->> items
@ -100,7 +123,8 @@
"Get all days between `from` and `to` (inclusively) for which the order applies."
[from to items]
(let [{:orders/keys [recurrence order_date]} (first items)]
(->> (t/recurrence->dates (t/latest from order_date) (or recurrence "FREQ=MONTHLY;COUNT=1"))
(->> (t/recurrence->dates order_date (or recurrence "FREQ=MONTHLY;COUNT=1"))
(remove #(t/before % (t/to-inst from)))
(take-while #(not (t/after % (t/to-inst to))))
(map #(vector (t/format-date %) :waiting))
(into {}))))
@ -140,7 +164,8 @@
vals
(map (partial items->orders from to))
(apply concat)
(filter #(t/between from (:day %) to)))))
(filter #(t/between from (:day %) to))
(remove (comp #{:canceled} :state)))))
(defn get-order [tx user-id id & [day]]
(first
@ -197,7 +222,6 @@
(defn delete! [user-id day action-type id]
(jdbc/with-transaction [tx db/db-uri]
(prn (->> id (db/get-by-id tx user-id :orders)))
(cond
;; Delete the order along with all recurrences
(or (->> id (db/get-by-id tx user-id :orders) :orders/recurrence nil?)
@ -207,3 +231,16 @@
;; Only delete the one day
:else
(change-state! tx user-id id day "canceled"))))
;; (delete! 2 "2022-04-20" 240)
;; (delete! 2 nil 241)
;; (change-state! 2 240 "2022-04-20" "waiting")
;; (change-state! 2 250 "2022-04-23" "fulfilled")
;; (get-orders db/db-uri (t/to-inst #inst "2022-04-20T00:00:00Z") (t/to-inst #inst "2022-04-20T00:00:00Z") nil nil)
;; (get-orders db/db-uri (t/to-inst #inst "2022-04-23T00:00:00Z") (t/to-inst #inst "2022-04-24T00:00:00Z") nil nil)
;; (get-order db/db-uri 2 242 (t/to-inst #inst "2022-04-20T00:00:00Z"))
;; (orders-for-days db/db-uri 2 #inst "2022-04-23T00:00:00Z" #inst "2022-04-23T00:00:00Z")
;; (orders-for-days db/db-uri 2 #inst "2022-04-23T00:00:00Z")
;; (orders-for-days db/db-uri 2 "2022-04-19")
;; (get-all 2)

View File

@ -2,7 +2,7 @@
(:import [java.time Instant LocalDate ZoneOffset]
[java.time.format DateTimeFormatter]
[java.sql Timestamp]
[org.dmfs.rfc5545.recur RecurrenceRule]
[org.dmfs.rfc5545.recur RecurrenceRule Freq]
[org.dmfs.rfc5545 DateTime]))
(defn parse-date [date]
@ -47,21 +47,102 @@
(defn earliest [& ds] (->> ds (map to-inst) (sort before) first))
(defn latest [& ds] (->> ds (map to-inst) (sort after) first))
(defn between [d1 d2 d3] (and (not (before d2 d1)) (not (after d2 d3))))
(defn same-day [d1 d2]
(when (and d1 d2)
(= (format-date d1) (format-date d2))))
(defn now [] (Instant/now))
(def min-date (parse-date "2020-01-01"))
(def max-date (.plusSeconds (now) (* 40 356 24 60 60))) ; 40 years from now - can't be bothered to do this properly...
;; Recurrence helpers
(defn to-recur-datetime [d] (-> d to-inst (.toEpochMilli) (DateTime.)))
(defn recurrence->dates [start rule]
(let [iterator (.iterator (RecurrenceRule. rule)
(-> start (.toEpochMilli) (DateTime.)))]
(let [iterator (.iterator (RecurrenceRule. rule) (to-recur-datetime start))]
(take-while identity
(repeatedly #(when (.hasNext iterator)
(-> iterator (.nextDateTime) (.getTimestamp) (Instant/ofEpochMilli)))))))
(defn next-date
"Get the next date after `day`"
[start rule day]
(->> (recurrence->dates (to-inst start) rule)
(filter (partial before (to-inst day)))
first))
(defn last-date
"Get the end date for the given rule"
[start rule]
(->> (recurrence->dates (to-inst start) rule)
(take-while #(before % max-date))
last))
(defn recurrence-pos
"The index of the day in the sequence for `day`."
[start rule day]
(->> (recurrence->dates (to-inst start) rule)
(keep-indexed (fn [i d] (when (same-day d day) i)))
first))
(def freq-units {"day" Freq/DAILY "week" Freq/WEEKLY "month" Freq/MONTHLY "year" Freq/YEARLY})
(defn set-freq [rule freq]
(.toString
(if rule
(doto (RecurrenceRule. rule) (.setFreq (freq-units freq Freq/WEEKLY) true))
(RecurrenceRule. (freq-units freq Freq/WEEKLY)))))
(defn get-freq [rule]
(-> rule
(RecurrenceRule.)
(.getFreq)
((clojure.set/map-invert freq-units))))
(defn get-interval [rule] (.getInterval (RecurrenceRule. rule)))
(defn set-interval [rule interval]
(let [rule (RecurrenceRule. rule)]
(.setInterval rule interval)
(.toString rule)))
(defn get-count [rule] (.getCount (RecurrenceRule. rule)))
(defn set-count [rule count]
(let [rule (RecurrenceRule. rule)]
(.setCount rule count)
(.toString rule)))
(defn get-until [rule]
(some-> rule (RecurrenceRule.) (.getUntil) (.getTimestamp) (Instant/ofEpochMilli)))
(defn set-until [rule until]
(let [rule (RecurrenceRule. rule)]
(.setUntil rule (to-recur-datetime until))
(.toString rule)))
(defn split-rule [start rule day]
(let [pos (recurrence-pos start rule day)]
(cond
;; FIXME: think this through...
(nil? pos) nil
;; the first date is the one to split on - so just leave it as is
(zero? pos) [rule]
(get-count rule)
[(set-count rule pos) (set-count rule (- (get-count rule) pos))]
(get-until rule)
[(set-until rule day) rule]
:else nil)))
(defn make-rule [{:keys [times until unit every]}]
(let [rule (-> nil
(set-freq unit)
(set-interval every))]
(if times
(set-count rule times)
(set-until rule until))))
(defn parse-rule [rule]
{:times (get-count rule)
:until (get-until rule)
:unit (get-freq rule)
:every (get-interval rule)})

View File

@ -10,7 +10,7 @@
[clojure.test :refer [deftest is testing]]))
(defn raw-order-row [& {:keys [id notes status date user_id user_name products recurrence]
:or {id 1 notes "note" status "pending" date #inst "2020-01-01"
:or {id 1 notes "note" status "waiting" date #inst "2020-01-01"
user_id 2 user_name "mr blobby" recurrence nil
products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}}}]
(if products
@ -44,7 +44,7 @@
(is (= params [(t/to-db-date t/min-date) (t/to-db-date t/max-date) 123 "1"]))
(raw-order-row))]
(is (= (sut/get-order :tx "1" 123)
{:id 1, :notes "note", :recurrence nil :state :pending, :day "2020-01-01",
{:id 1, :notes "note", :recurrence nil :state :waiting, :day "2020-01-01",
:who {:id 2, :name "mr blobby"},
:products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}}))))
@ -55,7 +55,7 @@
(concat (raw-order-row)
(raw-order-row :id 21)))]
(is (= (sut/get-order :tx "1" 123)
{:id 1, :notes "note", :state :pending, :day "2020-01-01",
{:id 1, :notes "note", :state :waiting, :day "2020-01-01",
:who {:id 2, :name "mr blobby"}, :recurrence nil
:products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}})))))
@ -73,13 +73,13 @@
{"2020-01-01" [{:id 1, :notes "note", :state :waiting, :day "2020-01-01",
:who {:id 2, :name "mr blobby"}, :recurrence nil
:products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}}
{:id 3, :notes "note", :state :pending, :day "2020-01-01",
{:id 3, :notes "note", :state :waiting, :day "2020-01-01",
:who {:id 43, :name "John"}, :recurrence nil
:products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}}
{:id 4, :notes "note", :state :pending, :day "2020-01-01",
{:id 4, :notes "note", :state :waiting, :day "2020-01-01",
:who {:id 2, :name "mr blobby"}, :recurrence nil
:products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}}]
"2020-01-03" [{:id 2, :notes "note", :state :pending, :day "2020-01-03",
"2020-01-03" [{:id 2, :notes "note", :state :waiting, :day "2020-01-03",
:who {:id 2, :name "mr blobby"}, :recurrence nil
:products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}}]})))))
@ -105,7 +105,7 @@
{"2020-01-01" [{:id 1, :notes "note", :state :waiting, :day "2020-01-01",
:who {:id 2, :name "mr blobby"}, :recurrence nil
:products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}}
{:id 4, :notes "note", :state :pending, :day "2020-01-01",
{:id 4, :notes "note", :state :waiting, :day "2020-01-01",
:who {:id 2, :name "mr blobby"}, :recurrence nil
:products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}}]})))))
@ -127,10 +127,6 @@
(raw-order-row :id 1 :status "waiting" :date #inst "2020-01-02")
(raw-order-row :id 4)))]
(is (= {"2020-01-02" [{:id 1, :notes "note", :recurrence nil,
:who {:id 2, :name "mr blobby"},
:day "2020-01-02", :state :waiting
:products {:eggs {:amount 12, :price nil}, :milk {:amount 3, :price 423}},}
{:id 4, :notes "note", :recurrence nil,
:who {:id 2, :name "mr blobby"},
:day "2020-01-02", :state :waiting
:products {:eggs {:amount 12, :price nil}, :milk {:amount 3, :price 423}}}]}
@ -157,7 +153,7 @@
{"2020-01-01" [{:id 1, :notes "note", :state :waiting, :day "2020-01-01",
:who {:id 2, :name "mr blobby"}, :recurrence nil
:products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}}
{:id 4, :notes "note", :state :pending, :day "2020-01-01",
{:id 4, :notes "note", :state :waiting, :day "2020-01-01",
:who {:id 2, :name "mr blobby"}, :recurrence nil
:products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}}]}))))))
@ -170,7 +166,7 @@
(is (= by {:id 1 :user_id :user-id})))
sql/query (constantly (raw-order-row :id 4))]
(is (= (sut/delete! :user-id nil nil 1)
{"2020-01-01" [{:id 4, :notes "note", :state :pending, :day "2020-01-01",
{"2020-01-01" [{:id 4, :notes "note", :state :waiting, :day "2020-01-01",
:who {:id 2, :name "mr blobby"}, :recurrence nil
:products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}}]}))))
@ -196,7 +192,7 @@
(testing "deleting without provided a date will remove the whole order"
(reset! invocations [])
(is (= (sut/delete! :user-id nil nil 1)
{"2020-01-01" [{:id 4, :notes "note", :state :pending, :day "2020-01-01",
{"2020-01-01" [{:id 4, :notes "note", :state :waiting, :day "2020-01-01",
:who {:id 2, :name "mr blobby"}, :recurrence nil
:products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}}]}))
(is (= [["deleting" :orders {:id 1 :user_id :user-id}]]
@ -205,7 +201,7 @@
(testing "a provided date is ignored and will full delete"
(reset! invocations [])
(is (= (sut/delete! :user-id "2020-01-01" nil 1)
{"2020-01-01" [{:id 4, :notes "note", :state :pending, :day "2020-01-01",
{"2020-01-01" [{:id 4, :notes "note", :state :waiting, :day "2020-01-01",
:who {:id 2, :name "mr blobby"}, :recurrence nil
:products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}}]}))
(is (= [["deleting" :orders {:id 1 :user_id :user-id}]]
@ -218,7 +214,7 @@
(reset! invocations [])
(is (= (sut/delete! :user-id "2020-01-01" :single 1)
{"2020-01-01" [{:id 4, :notes "note", :state :pending, :day "2020-01-01",
{"2020-01-01" [{:id 4, :notes "note", :state :waiting, :day "2020-01-01",
:who {:id 2, :name "mr blobby"}, :recurrence nil
:products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}}]}))
(is (= [["deleting" :orders {:id 1 :user_id :user-id}]]
@ -237,8 +233,8 @@
(testing "deleting with :all remove the whole order"
(reset! invocations [])
(is (= (sut/delete! :user-id nil :all 1)
{"2020-01-01" [{:id 4, :notes "note", :state :pending, :day "2020-01-01",
:who {:id 2, :name "mr blobby"}, :recurrence "FREQ=DAILY;COUNT=1"
{"2020-01-01" [{:id 4, :notes "note", :state :waiting, :day "2020-01-01",
:who {:id 2, :name "mr blobby"}, :recurrence {:times 1, :until nil, :unit "day", :every 1}
:products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}}]}))
(is (= [["deleting" :orders {:id 1 :user_id :user-id}]]
@invocations)))
@ -246,8 +242,8 @@
(testing "deleting with a provided date will soft remove a single order by updating it if it exists"
(reset! invocations [])
(is (= (sut/delete! :user-id "2020-01-01" nil 1)
{"2020-01-01" [{:id 4, :notes "note", :state :pending, :day "2020-01-01",
:who {:id 2, :name "mr blobby"}, :recurrence "FREQ=DAILY;COUNT=1"
{"2020-01-01" [{:id 4, :notes "note", :state :waiting, :day "2020-01-01",
:who {:id 2, :name "mr blobby"}, :recurrence {:times 1, :until nil, :unit "day", :every 1}
:products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}}]}))
(is (= [["updating" :recurrence_exceptions {:status "canceled"}
{:order_id 1, :order_date (t/to-db-date "2020-01-01")}]]
@ -260,8 +256,8 @@
(reset! invocations [])
(is (= (sut/delete! :user-id "2020-01-01" nil 1)
{"2020-01-01" [{:id 4, :notes "note", :state :pending, :day "2020-01-01",
:who {:id 2, :name "mr blobby"}, :recurrence "FREQ=DAILY;COUNT=1"
{"2020-01-01" [{:id 4, :notes "note", :state :waiting, :day "2020-01-01",
:who {:id 2, :name "mr blobby"}, :recurrence {:times 1, :until nil, :unit "day", :every 1}
:products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}}]}))
(is (= [["inserting" :recurrence_exceptions {:order_id 1, :order_date (t/to-db-date "2020-01-01") :status "canceled"}]]
@invocations))))))))

View File

@ -75,6 +75,27 @@ html body .popup .popup-content {
width: 15%;
}
html body .popup .popup-content .recurrence {
padding: 0.5em 0em 1em 1em;
}
html body .popup .popup-content .recurrence #recurrence-times {
width: 2em;
}
html body .popup .popup-content .recurrence .recurrence-freq .input-item {
display: inline-block;
}
html body .popup .popup-content .recurrence .recurrence-freq #recurrence-every {
width: 2em;
}
html body .popup .popup-content .recurrence .recurrence-freq label[for="recurrence-every"] {
min-width: 1em;
padding: 5px;
}
html body .popup .popup-content .input-item label {
min-width: 60px;
display: inline-block;

View File

@ -9,6 +9,17 @@
[chicken-master.events :as event]
[chicken-master.time :as time]))
(defn int-or-nil [val]
(let [i (js/parseInt val)]
(when-not (js/isNaN i) i)))
(defn parse-recurrence [{:strs [recurrence-till recurrence-times recurrence-unit recurrence-every]}]
(when (or (int-or-nil recurrence-times) (seq recurrence-till))
{:times (int-or-nil recurrence-times)
:until (when (seq recurrence-till) recurrence-till)
:unit recurrence-unit
:every (or (int-or-nil recurrence-every) 1)}))
(defn format-raw-order [{:strs [day who who-id notes] :as raw-values}]
{:who {:name who
:id (if (prod/num-or-nil who-id)
@ -20,6 +31,7 @@
first :id))}
:day day
:notes notes
:recurrence (parse-recurrence raw-values)
:products (prod/collect-products (remove (comp #{"who" "notes"} first) raw-values))})
(defn get-group-products [customers who]
@ -40,7 +52,7 @@
products))
(defn order-form
([order] (order-form order #{:who :day :notes :products :group-products}))
([order] (order-form order #{:who :day :notes :products :group-products :recurrence}))
([order fields]
(let [customers @(re-frame/subscribe [::subs/available-customers])
available-prods @(re-frame/subscribe [::subs/available-products])
@ -71,6 +83,18 @@
(when (:notes fields)
(html/input :notes "notka"
{:default (:notes @state)}))
(when (:recurrence fields)
[:details {:class :recurrence-details}
[:summary "powtarzanie"]
[:div {:class :recurrence}
(html/input :recurrence-times "ile razy" {:type :number :default (-> order :recurrence :times)})
(html/input :recurrence-till "do kiedy" {:type :date :default (-> order :recurrence :until)})
[:div {:class :recurrence-freq}
(html/input :recurrence-every "co" {:type :number :default (-> order :recurrence :every)})
[:select {:name :recurrence-unit :id :recurrence-unit :defaultValue (-> order :recurrence :unit)}
[:option {:key :day :value "day"} "dni"]
[:option {:key :week :value "week"} "tygodni"]
[:option {:key :month :value "month"} "miesięcy"]]]]])
(when (:products fields)
[prod/products-edit (:products @state)
:available-prods available-prods
@ -123,7 +147,6 @@
(->> (if (settings :hide-fulfilled-orders)
(remove (comp #{:fulfilled} :state) orders)
orders)
(remove (comp #{:canceled} :state))
(map (partial format-order settings))
doall)
(when (settings :show-day-add-order)

View File

@ -49,8 +49,13 @@
:margin "15% auto"
:padding "20px"
:border "1px solid #888"
:width "15%"
}
:width "15%"}
[:.recurrence {:padding "0.5em 0em 1em 1em"}
[:#recurrence-times {:width "2em"}]
[:.recurrence-freq
[:.input-item {:display :inline-block}]
[:#recurrence-every {:width "2em"}]
["label[for=\"recurrence-every\"]" {:min-width "1em" :padding "5px"}]]]
[:.input-item
[:label {:min-width "60px"
:display :inline-block}]]

View File

@ -119,7 +119,7 @@
:http-xhrio (http-post "orders"
(merge
(select-keys order [:id :day :hour :state :order-date])
(select-keys form [:id :day :hour :state :who :notes :products])))}))
(select-keys form [:id :day :hour :state :who :notes :products :recurrence])))}))
(re-frame/reg-event-fx
::process-fetched-days
@ -128,7 +128,14 @@
(update :current-days (fn [current-days]
(for [[day orders] current-days]
[day (if (contains? days day) (days day) orders)])))
(update :orders #(reduce (fn [m order] (assoc m (:id order) order)) % (mapcat second days))))
(update :orders (fn [orders] (->> days
(mapcat second)
(group-by :id)
vals
(map (fn [items] (->> items
(reduce #(assoc %1 (:day %2) (:state %2)) {})
(assoc (first items) :days))))
(reduce #(assoc %1 (:id %2) %2) orders)))))
:dispatch [::stop-loading]}))
(re-frame/reg-event-fx
@ -146,7 +153,11 @@
(fn [{{:keys [start-date orders] :as db} :db} [_ day]]
(let [day (or day start-date)
days (into #{} (time/get-weeks day 2))
filtered-orders (->> orders vals (filter (comp days :day)) (group-by :day))]
filtered-orders (->> orders vals
(mapcat (fn [order]
(map #(assoc order :day (first %) :state (second %))
(:days order))))
(filter (comp days :day)) (group-by :day))]
{:db (assoc db
:start-date day
:current-days (map #(vector % (get filtered-orders %)) (sort days)))

View File

@ -83,11 +83,11 @@
(deftest format-raw-order-test
(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 {} :recurrence nil}))
(is (= (sut/format-raw-order {"who" "bla" "notes" "ble"})
{:who {:name "bla" :id nil} :day nil :notes "ble" :products {}}))
{:who {:name "bla" :id nil} :day nil :notes "ble" :products {} :recurrence nil}))
(is (= (sut/format-raw-order {"who" "bla" "who-id" "123" "notes" "ble" "day" "2020-10-10"})
{:who {:name "bla" :id 123} :day "2020-10-10" :notes "ble" :products {}})))
{:who {:name "bla" :id 123} :day "2020-10-10" :notes "ble" :products {} :recurrence nil})))
(testing "decent products"
(is (= (sut/format-raw-order {"who" "bla" "who-id" "123" "notes" "ble"
@ -95,7 +95,7 @@
"product-eggs" "eggs" "amount-eggs" "12"
"product-cows" "cows" "amount-cows" "22" "price-cows" "2.32"
"product-milk" "milk" "amount-milk" "3.2"})
{:who {:name "bla" :id 123} :day "2020-10-10" :notes "ble"
{:who {:name "bla" :id 123} :day "2020-10-10" :notes "ble" :recurrence nil
:products {:eggs {:amount 12} :cows {:amount 22 :price 232} :milk {:amount 3.2}}})))
(testing "duplicate products"
@ -105,7 +105,7 @@
"product-cows1" "cows" "amount-cows1" "1"
"product-cows2" "cows" "amount-cows2" "2"
"product-milk" "milk" "amount-milk" "3.2"})
{:who {:name "bla" :id 123} :day nil :notes "ble"
{:who {:name "bla" :id 123} :day nil :notes "ble" :recurrence nil
:products {:eggs {:amount 24} :cows {:amount 3} :milk {:amount 3.2}}})))
(testing "unselected are ignored"
@ -115,7 +115,7 @@
"product-bad2" "" "amount-bad2" "1"
"product-milk" "milk" "amount-milk" "3.2"
"product-bad3" "" "amount-bad3" "2"})
{:who {:name "bla" :id 123} :day "2020-10-10" :notes "ble"
{:who {:name "bla" :id 123} :day "2020-10-10" :notes "ble" :recurrence nil
:products {:eggs {:amount 12} :milk {:amount 3.2}}})))
(testing "prices are handled"
@ -124,7 +124,7 @@
"product-eggs1" "eggs" "amount-eggs1" "0" "price-eggs1" "1.0"
"product-cow" "cow" "amount-cow" "0"
"product-milk" "milk" "amount-milk" "3.2"})
{:who {:name "bla" :id 123} :day "2020-10-10" :notes "ble"
{:who {:name "bla" :id 123} :day "2020-10-10" :notes "ble" :recurrence nil
:products {:eggs {:amount 12 :price 431} :milk {:amount 3.2}}})))
(testing "items with 0 are removed"
@ -133,8 +133,30 @@
"product-eggs1" "eggs" "amount-eggs1" "0"
"product-cow" "cow" "amount-cow" "0"
"product-milk" "milk" "amount-milk" "3.2"})
{:who {:name "bla" :id 123} :day "2020-10-10" :notes "ble"
:products {:eggs {:amount 12} :milk {:amount 3.2}}}))))
{:who {:name "bla" :id 123} :day "2020-10-10" :notes "ble" :recurrence nil
:products {:eggs {:amount 12} :milk {:amount 3.2}}})))
(testing "recurrence object is not created when empty vals provided"
(is (= (sut/format-raw-order {"recurrence-till" ""
"recurrence-times" ""
"recurrence-unit" ""
"recurrence-every" ""})
{:who {:name nil :id nil} :day nil :notes nil :products {} :recurrence nil})))
(testing "recurrence object is created when times provided"
(is (= (sut/format-raw-order {"recurrence-till" ""
"recurrence-times" "6"
"recurrence-unit" "week"
"recurrence-every" "3"})
{:who {:name nil :id nil} :day nil :notes nil :products {} :recurrence {:times 6, :until nil, :unit "week", :every 3}})))
(testing "recurrence object is created when till provided"
(is (= (sut/format-raw-order {"recurrence-till" "2020-01-01"
"recurrence-times" ""
"recurrence-unit" "week"
"recurrence-every" "3"})
{:who {:name nil :id nil} :day nil :notes nil :products {}
:recurrence {:times nil, :until "2020-01-01", :unit "week", :every 3}}))))
(def customers
[{:id 1 :name "mr blobby" :product-groups {"group 1" {:products {:eggs 1 :carrots 2}}

View File

@ -20,12 +20,12 @@
(rf/reg-event-fx event (fn [_ [_ & params]] (validator params) nil)))
(def sample-orders
[{:id 1 :day "2020-01-02"} {:id 2 :day "2020-01-02"} {:id 3 :day "2020-01-02"}
{:id 4 :day "2020-01-04"}
{:id 5 :day "2020-01-06"} {:id 6 :day "2020-01-06"}])
[{:id 1 :day "2020-01-02" :state :waiting} {:id 2 :day "2020-01-02" :state :waiting} {:id 3 :day "2020-01-02" :state :waiting}
{:id 4 :day "2020-01-04" :state :waiting}
{:id 5 :day "2020-01-06" :state :waiting} {:id 6 :day "2020-01-06" :state :waiting}])
(def sample-orders-by-day (group-by :day sample-orders))
(def sample-orders-by-id (reduce #(assoc %1 (:id %2) %2) {} sample-orders))
(def sample-orders-by-id (reduce #(assoc %1 (:id %2) (assoc %2 :days {(:day %2) (:state %2)})) {} sample-orders))
(deftest hide-modal
(testing "models can be hidden"
@ -143,7 +143,7 @@
(rf/dispatch [::sut/edit-order "2020-01-01" 1])
(is (= @(rf/subscribe [::subs/editted-order])
{:show true :day "2020-01-01" :id 1}))))
{:show true :day "2020-01-01" :id 1 :order-date "2020-01-01"}))))
(testing "new orders can be edited"
(rf-test/run-test-sync
@ -152,7 +152,7 @@
(rf/dispatch [::sut/edit-order "2020-01-01" :new-order])
(is (= @(rf/subscribe [::subs/editted-order])
{:show true :day "2020-01-01" :state :waiting}))))
{:show true :day "2020-01-01" :state :waiting :order-date "2020-01-01"}))))
;; FIXME: the request handler is not being overloaded
(testing "orders are fulfilled"
@ -273,11 +273,11 @@
(is (= @(rf/subscribe [::subs/current-days])
[["2020-01-01" [{:id :left-as-is :day "2020-01-01"}]]
["2020-01-02" [{:id 1 :day "2020-01-02"} {:id 2 :day "2020-01-02"} {:id 3 :day "2020-01-02"}]]
["2020-01-02" [{:id 1 :day "2020-01-02" :state :waiting} {:id 2 :day "2020-01-02" :state :waiting} {:id 3 :day "2020-01-02" :state :waiting}]]
["2020-01-03" nil]
["2020-01-04" [{:id 4 :day "2020-01-04"}]]
["2020-01-04" [{:id 4 :day "2020-01-04" :state :waiting}]]
["2020-01-05" nil]
["2020-01-06" [{:id 5 :day "2020-01-06"} {:id 6 :day "2020-01-06"}]]
["2020-01-06" [{:id 5 :day "2020-01-06" :state :waiting} {:id 6 :day "2020-01-06" :state :waiting}]]
["2020-01-07" nil]])))))
(deftest test-show-from-date
@ -297,11 +297,14 @@
[["2019-12-30" nil]
["2019-12-31" nil]
["2020-01-01" nil]
["2020-01-02" [{:id 1, :day "2020-01-02"} {:id 2, :day "2020-01-02"} {:id 3, :day "2020-01-02"}]]
["2020-01-02" [{:id 1, :day "2020-01-02" :state :waiting, :days {"2020-01-02" :waiting}}
{:id 2, :day "2020-01-02" :state :waiting, :days {"2020-01-02" :waiting}}
{:id 3, :day "2020-01-02" :state :waiting, :days {"2020-01-02" :waiting}}]]
["2020-01-03" nil]
["2020-01-04" [{:id 4, :day "2020-01-04"}]]
["2020-01-04" [{:id 4, :day "2020-01-04" :state :waiting, :days {"2020-01-04" :waiting}}]]
["2020-01-05" nil]
["2020-01-06" [{:id 5, :day "2020-01-06"} {:id 6, :day "2020-01-06"}]]
["2020-01-06" [{:id 5, :day "2020-01-06" :state :waiting, :days {"2020-01-06" :waiting}}
{:id 6, :day "2020-01-06" :state :waiting, :days {"2020-01-06" :waiting}}]]
["2020-01-07" nil] ["2020-01-08" nil] ["2020-01-09" nil]
["2020-01-10" nil] ["2020-01-11" nil] ["2020-01-12" nil]]))))
@ -314,11 +317,14 @@
[["2019-12-30" nil]
["2019-12-31" nil]
["2020-01-01" nil]
["2020-01-02" [{:id 1, :day "2020-01-02"} {:id 2, :day "2020-01-02"} {:id 3, :day "2020-01-02"}]]
["2020-01-02" [{:id 1, :day "2020-01-02" :state :waiting, :days {"2020-01-02" :waiting}}
{:id 2, :day "2020-01-02" :state :waiting, :days {"2020-01-02" :waiting}}
{:id 3, :day "2020-01-02" :state :waiting, :days {"2020-01-02" :waiting}}]]
["2020-01-03" nil]
["2020-01-04" [{:id 4, :day "2020-01-04"}]]
["2020-01-04" [{:id 4, :day "2020-01-04" :state :waiting, :days {"2020-01-04" :waiting}}]]
["2020-01-05" nil]
["2020-01-06" [{:id 5, :day "2020-01-06"} {:id 6, :day "2020-01-06"}]]
["2020-01-06" [{:id 5, :day "2020-01-06" :state :waiting, :days {"2020-01-06" :waiting}}
{:id 6, :day "2020-01-06" :state :waiting, :days {"2020-01-06" :waiting}}]]
["2020-01-07" nil] ["2020-01-08" nil] ["2020-01-09" nil]
["2020-01-10" nil] ["2020-01-11" nil] ["2020-01-12" nil]]))))
@ -331,11 +337,14 @@
[["2019-12-30" nil]
["2019-12-31" nil]
["2020-01-01" nil]
["2020-01-02" [{:id 1, :day "2020-01-02"} {:id 2, :day "2020-01-02"} {:id 3, :day "2020-01-02"}]]
["2020-01-02" [{:id 1, :day "2020-01-02" :state :waiting, :days {"2020-01-02" :waiting}}
{:id 2, :day "2020-01-02" :state :waiting, :days {"2020-01-02" :waiting}}
{:id 3, :day "2020-01-02" :state :waiting, :days {"2020-01-02" :waiting}}]]
["2020-01-03" nil]
["2020-01-04" [{:id 4, :day "2020-01-04"}]]
["2020-01-04" [{:id 4, :day "2020-01-04" :state :waiting, :days {"2020-01-04" :waiting}}]]
["2020-01-05" nil]
["2020-01-06" [{:id 5, :day "2020-01-06"} {:id 6, :day "2020-01-06"}]]
["2020-01-06" [{:id 5, :day "2020-01-06" :state :waiting, :days {"2020-01-06" :waiting}}
{:id 6, :day "2020-01-06" :state :waiting, :days {"2020-01-06" :waiting}}]]
["2020-01-07" nil] ["2020-01-08" nil] ["2020-01-09" nil]
["2020-01-10" nil] ["2020-01-11" nil] ["2020-01-12" nil]])))))