mirror of
https://github.com/mruwnik/chicken-master.git
synced 2025-06-28 15:14:49 +02:00
editable recurs
This commit is contained in:
parent
b4ed659718
commit
f6167bf3c0
@ -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)
|
||||
|
@ -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)})
|
||||
|
@ -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))))))))
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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}]]
|
||||
|
@ -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)))
|
||||
|
@ -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}}
|
||||
|
@ -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]])))))
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user