allow deleting from date

This commit is contained in:
Daniel O'Connell 2022-05-12 21:45:28 +02:00
parent c03d2831b9
commit 4aa84bb465
3 changed files with 58 additions and 21 deletions

View File

@ -173,9 +173,9 @@
(group-by :day) (group-by :day)
(merge (reduce #(assoc %1 (t/format-date %2) {}) {} days))))) (merge (reduce #(assoc %1 (t/format-date %2) {}) {} days)))))
(defn get-fortnight [tx user-id from] (defn get-fortnight [tx user-id & days]
(->> (get-orders tx from (t/plus from 14 :days) "o.user_id = ?" [user-id]) (let [fortnight-after-earliest (t/plus (apply t/earliest days) 14 :days)]
(group-by :day))) (apply orders-for-days tx user-id fortnight-after-earliest days)))
(defn replace! (defn replace!
([user-id order] (jdbc/with-transaction [tx db/db-uri] (replace! tx user-id order))) ([user-id order] (jdbc/with-transaction [tx db/db-uri] (replace! tx user-id order)))
@ -185,7 +185,7 @@
(products/update-products-mapping! tx user-id :order (products/update-products-mapping! tx user-id :order
(upsert-order! tx user-id customer-id order) (upsert-order! tx user-id customer-id order)
products) products)
(get-fortnight tx user-id (t/earliest day order-date))))) (get-fortnight tx user-id day order-date))))
(defn change-state! (defn change-state!
"Update the state of the given order and also modify the number of products available: "Update the state of the given order and also modify the number of products available:
@ -214,6 +214,21 @@
(sql/delete! tx :orders {:id id :user_id user-id}) (sql/delete! tx :orders {:id id :user_id user-id})
(get-fortnight tx user-id (t/earliest order_date end_date)))) (get-fortnight tx user-id (t/earliest order_date end_date))))
(defn- delete-from-date [tx user-id id from-date]
(when-let [{:orders/keys [order_date recurrence] :as order} (some->> id (db/get-by-id tx user-id :orders))]
(if (t/same-day order_date from-date)
;; deleting from the first date just means removing them all
(full-delete tx user-id id)
;; deleting from a given date should update the recurrence rule to end with the given date and
;; update the `end_date` field
(do
(sql/update! tx :orders
(set-dates order {:recurrence (t/recur-until order_date recurrence from-date)})
{:id id})
(->> (t/plus from-date 14 :days)
(t/dates-between order_date recurrence from-date)
(apply orders-for-days tx user-id))))))
(defn delete! [user-id day action-type id] (defn delete! [user-id day action-type id]
(jdbc/with-transaction [tx db/db-uri] (jdbc/with-transaction [tx db/db-uri]
(cond (cond
@ -222,8 +237,8 @@
(= "all" action-type)) (= "all" action-type))
(full-delete tx user-id id) (full-delete tx user-id id)
(= "from-here" action-type) nil (= "from-here" action-type)
;; TODO: handle partial deletions (delete-from-date tx user-id id day)
;; Only delete the one day ;; Only delete the one day
:else :else

View File

@ -91,6 +91,13 @@
(repeatedly #(when (.hasNext iterator) (repeatedly #(when (.hasNext iterator)
(-> iterator (.nextDateTime) (.getTimestamp) (Instant/ofEpochMilli))))))) (-> iterator (.nextDateTime) (.getTimestamp) (Instant/ofEpochMilli)))))))
(defn dates-between
"Get all dates between `from` and `to` (inclusive)"
[start rule from to]
(->> (recurrence->dates (to-inst start) rule)
(drop-while (partial after (to-inst from)))
(take-while #(not (after % (to-inst to))))))
(defn next-date (defn next-date
"Get the next date after `day`" "Get the next date after `day`"
[start rule day] [start rule day]
@ -161,10 +168,17 @@
:else nil))) :else nil)))
(defn recur-until
"Update the rule to ensure it ends before `date`"
[start rule date]
(if (get-until rule)
(set-until rule date)
(set-count rule (recurrence-pos start rule date))))
(defn make-rule [{:keys [times until unit every]}] (defn make-rule [{:keys [times until unit every]}]
(let [rule (-> nil (let [rule (-> nil
(set-freq unit) (set-freq (or unit "day"))
(set-interval every))] (set-interval (or every 1)))]
(if times (if times
(set-count rule times) (set-count rule times)
(set-until rule until)))) (set-until rule until))))

View File

@ -102,7 +102,8 @@
(raw-order-row :id 1 :status "waiting") (raw-order-row :id 1 :status "waiting")
(raw-order-row :id 4)))] (raw-order-row :id 4)))]
(is (= (sut/replace! :user-id order) (is (= (sut/replace! :user-id order)
{"2020-01-01" [{:id 1, :notes "note", :state :waiting, :day "2020-01-01", {"2020-01-15" {}
"2020-01-01" [{:id 1, :notes "note", :state :waiting, :day "2020-01-01",
:who {:id 2, :name "mr blobby"}, :recurrence nil :who {:id 2, :name "mr blobby"}, :recurrence nil
:products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}} :products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}}
{:id 4, :notes "note", :state :waiting, :day "2020-01-01", {:id 4, :notes "note", :state :waiting, :day "2020-01-01",
@ -126,7 +127,8 @@
sql/query (constantly (concat sql/query (constantly (concat
(raw-order-row :id 1 :status "waiting" :date #inst "2020-01-02") (raw-order-row :id 1 :status "waiting" :date #inst "2020-01-02")
(raw-order-row :id 4)))] (raw-order-row :id 4)))]
(is (= {"2020-01-02" [{:id 1, :notes "note", :recurrence nil, (is (= {"2020-01-16" {}
"2020-01-02" [{:id 1, :notes "note", :recurrence nil,
:who {:id 2, :name "mr blobby"}, :who {:id 2, :name "mr blobby"},
:day "2020-01-02", :state :waiting :day "2020-01-02", :state :waiting
:products {:eggs {:amount 12, :price nil}, :milk {:amount 3, :price 423}}}]} :products {:eggs {:amount 12, :price nil}, :milk {:amount 3, :price 423}}}]}
@ -150,7 +152,8 @@
(raw-order-row :id 1 :status "waiting") (raw-order-row :id 1 :status "waiting")
(raw-order-row :id 4)))] (raw-order-row :id 4)))]
(is (= (sut/replace! :user-id order) (is (= (sut/replace! :user-id order)
{"2020-01-01" [{:id 1, :notes "note", :state :waiting, :day "2020-01-01", {"2020-01-15" {}
"2020-01-01" [{:id 1, :notes "note", :state :waiting, :day "2020-01-01",
:who {:id 2, :name "mr blobby"}, :recurrence nil :who {:id 2, :name "mr blobby"}, :recurrence nil
:products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}} :products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}}
{:id 4, :notes "note", :state :waiting, :day "2020-01-01", {:id 4, :notes "note", :state :waiting, :day "2020-01-01",
@ -165,7 +168,8 @@
(is (= table :orders)) (is (= table :orders))
(is (= by {:id 1 :user_id :user-id}))) (is (= by {:id 1 :user_id :user-id})))
sql/query (constantly (raw-order-row :id 4))] sql/query (constantly (raw-order-row :id 4))]
(is (= {"2020-01-01" [{:id 4, :notes "note", :state :waiting, :day "2020-01-01", (is (= {"2020-01-15" {}
"2020-01-01" [{:id 4, :notes "note", :state :waiting, :day "2020-01-01",
:who {:id 2, :name "mr blobby"}, :recurrence nil :who {:id 2, :name "mr blobby"}, :recurrence nil
:products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}}]} :products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}}]}
(sut/delete! :user-id nil nil 1))))) (sut/delete! :user-id nil nil 1)))))
@ -191,7 +195,8 @@
sql/insert! (fn [_ table values] (swap! invocations conj ["inserting" table values]))] sql/insert! (fn [_ table values] (swap! invocations conj ["inserting" table values]))]
(testing "deleting without provided a date will remove the whole order" (testing "deleting without provided a date will remove the whole order"
(reset! invocations []) (reset! invocations [])
(is (= {"2020-01-01" [{:id 4, :notes "note", :state :waiting, :day "2020-01-01", (is (= {"2020-01-15" {}
"2020-01-01" [{:id 4, :notes "note", :state :waiting, :day "2020-01-01",
:who {:id 2, :name "mr blobby"}, :recurrence nil :who {:id 2, :name "mr blobby"}, :recurrence nil
:products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}}]} :products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}}]}
(sut/delete! :user-id nil nil 1))) (sut/delete! :user-id nil nil 1)))
@ -200,7 +205,8 @@
(testing "a provided date is ignored and will full delete" (testing "a provided date is ignored and will full delete"
(reset! invocations []) (reset! invocations [])
(is (= {"2020-01-01" [{:id 4, :notes "note", :state :waiting, :day "2020-01-01", (is (= {"2020-01-15" {}
"2020-01-01" [{:id 4, :notes "note", :state :waiting, :day "2020-01-01",
:who {:id 2, :name "mr blobby"}, :recurrence nil :who {:id 2, :name "mr blobby"}, :recurrence nil
:products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}}]} :products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}}]}
(sut/delete! :user-id "2020-01-01" nil 1))) (sut/delete! :user-id "2020-01-01" nil 1)))
@ -213,7 +219,8 @@
{:orders/order_date #inst "2020-01-01"}))] {:orders/order_date #inst "2020-01-01"}))]
(reset! invocations []) (reset! invocations [])
(is (= {"2020-01-01" [{:id 4, :notes "note", :state :waiting, :day "2020-01-01", (is (= {"2020-01-15" {}
"2020-01-01" [{:id 4, :notes "note", :state :waiting, :day "2020-01-01",
:who {:id 2, :name "mr blobby"}, :recurrence nil :who {:id 2, :name "mr blobby"}, :recurrence nil
:products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}}]} :products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}}]}
(sut/delete! :user-id "2020-01-01" :single 1))) (sut/delete! :user-id "2020-01-01" :single 1)))
@ -232,19 +239,20 @@
sql/insert! (fn [_ table values] (swap! invocations conj ["inserting" table values]))] sql/insert! (fn [_ table values] (swap! invocations conj ["inserting" table values]))]
(testing "deleting with \"all\" removes the whole order" (testing "deleting with \"all\" removes the whole order"
(reset! invocations []) (reset! invocations [])
(is (= (sut/delete! :user-id nil "all" 1) (is (= {"2020-01-15" {}
{"2020-01-01" [{:id 4, :notes "note", :state :waiting, :day "2020-01-01", "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} :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}}}]})) :products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}}]}
(sut/delete! :user-id nil "all" 1)))
(is (= [["deleting" :orders {:id 1 :user_id :user-id}]] (is (= [["deleting" :orders {:id 1 :user_id :user-id}]]
@invocations))) @invocations)))
(testing "deleting with a provided date will soft remove a single order by updating it if it exists" (testing "deleting with a provided date will soft remove a single order by updating it if it exists"
(reset! invocations []) (reset! invocations [])
(is (= (sut/delete! :user-id "2020-01-01" nil 1) (is (= {"2020-01-01" [{:id 4, :notes "note", :state :waiting, :day "2020-01-01",
{"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} :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}}}]})) :products {:eggs {:amount 12 :price nil} :milk {:amount 3 :price 423}}}]}
(sut/delete! :user-id "2020-01-01" nil 1)))
(is (= [["updating" :recurrence_exceptions {:status "canceled"} (is (= [["updating" :recurrence_exceptions {:status "canceled"}
{:order_id 1, :order_date (t/to-db-date "2020-01-01")}]] {:order_id 1, :order_date (t/to-db-date "2020-01-01")}]]
@invocations))) @invocations)))