          pets
          groceries] (find-accounts context "Checking" "Pets" "Groceries")
         result (-> (find-transaction context (t/local-date 2016 3 16) "Kroger")
-                   (assoc-in [:items 0 :quantity] 102M)
-                   (assoc-in [:items 0 :value] 102M)
+                   (update-items {(:id groceries) {:quantity 102M
+                                                   :value 102M}})
                    (update-in [:items] #(remove (fn [item]
                                                   (= (:account-id item)
                                                      (:id pets)))

                         :balance 103M}]
        actual-items (map #(select-keys % [:index :quantity :balance])
                          (items-by-account (:id groceries)))]
    (is (valid? result) (str "Expected the transaction to be valid: " (prn-str result)))
    (assert-account-quantities pets 0M groceries 306M checking 694M)
    (is (= expected-items actual-items)
        "The account for the changed item should have the correct items")))

           (map :transaction-date actual))
        "The transactions from the specified day are returned")))

(defn- update-items
  [{:keys [items] :as transaction} change-map]
  (let [indexed-items (index-by :account-id items)
        updated-items (reduce (fn [items [account-id item]]
                                (update-in items [account-id] merge item))
                              indexed-items
                              change-map)]
    (assoc transaction :items (vals updated-items))))

(deftest update-a-transaction-change-quantity
  (let [ctx (realize update-context)
        checking (find-account ctx "Checking")
        groceries (find-account ctx "Groceries")
        result (-> (find-transaction ctx (t/local-date 2016 3 12) "Kroger")
                   (update-items {(:id groceries) {:quantity 99.99M}
                                  (:id checking) {:quantity 99.99M}})
                   transactions/update)]
    (is (valid? result))
    (is (seq-of-maps-like? [{:index 2 :quantity  102.00M :balance   798.01M}
                            {:index 1 :quantity   99.99M :balance   900.01M}
                            {:index 0 :quantity 1000.00M :balance 1000.00M}]
                           (items-by-account (:id checking)))
        "Expected the checking account items to be updated.")
    (is (seq-of-maps-like? [{:index 1 :quantity 102.00M :balance 201.99M}
                            {:index 0 :quantity  99.99M :balance  99.99M}]
                           (items-by-account (:id groceries)))
        "Expected the groceries account items to be updated.")
    (assert-account-quantities checking 798.01M groceries 201.99M)))

(deftest rollback-a-failed-update
  (let [real-reload transactions/reload
        ctx (realize update-context)
        checking (find-account ctx "Checking")
        groceries (find-account ctx "Groceries")
        trx (find-transaction ctx (t/local-date 2016 3 12) "Kroger")
        call-count (atom 0)]
    (with-redefs [transactions/reload (fn [transaction]
                                        (swap! call-count inc)
                                        (if (= 2 @call-count)
                                          (throw (RuntimeException. "Induced exception"))
                                          (real-reload transaction)))]
      (try
        (-> trx
            (update-items {(:id groceries) {:quantity 99.99M}
                           (:id checking) {:quantity 99.99M}})
            transactions/update)
        (catch RuntimeException _ nil)))
    (testing "transaction items are not updated"
      (is (= #{101M} (->> (:items (transactions/reload trx))
                          (map :quantity)
                          (into #{})))))
    (assert-account-quantities checking 797M groceries 203M)))

(deftest update-a-transaction-change-date
  (let [ctx (realize update-context)
        checking (find-account ctx "Checking")
        groceries (find-account ctx "Groceries")
        trx (find-transaction ctx (t/local-date 2016 3 22) "Kroger")
        result (-> trx
                   (change-date (t/local-date 2016 3 10))
                   transactions/update)]
    (is (valid? result))
    (is (seq-of-maps-like? [{:index 2 :transaction-date (t/local-date 2016 3 12) :quantity 101M  :balance 797M}
                            {:index 1 :transaction-date (t/local-date 2016 3 10) :quantity 102M  :balance 898M}
                            {:index 0 :transaction-date (t/local-date 2016 3 2)  :quantity 1000M :balance 1000M}]
                           (items-by-account (:id checking)))
        "Expected the checking items to be updated")
    (is (seq-of-maps-like? [{:index 1 :transaction-date (t/local-date 2016 3 12) :quantity 101M :balance 203M}
                            {:index 0 :transaction-date (t/local-date 2016 3 10) :quantity 102M :balance 102M}]
                           (items-by-account (:id groceries)))
        "Expected the groceries items to be updated")
    (assert-account-quantities checking 797M groceries 203M)
    (testing "transaction is updated"
      (is (= (t/local-date 2016 3 10)
             (:transaction-date (transactions/reload result)))
          "The transaction should be updated"))))

(deftest update-a-transaction-cross-partition-boundary
  (let [ctx (realize update-context)
        checking (find-account ctx "Checking")
        groceries (find-account ctx "Groceries")
        trx (find-transaction ctx (t/local-date 2016 3 12) "Kroger")
        result (-> trx (assoc :transaction-date (t/local-date 2016 4 12)
                              :original-transaction-date (:transaction-date trx))
                   transactions/update)]
    (is (valid? result))
    (is (seq-of-maps-like? [{:index 2 :quantity  101M :balance  797M}
                            {:index 1 :quantity  102M :balance  898M}
                            {:index 0 :quantity 1000M :balance 1000M}]
                           (items-by-account (:id checking)))
        "Expected the checking items to be updated")
    (is (seq-of-maps-like? [{:index 1 :quantity 101M :balance 203M}
                            {:index 0 :quantity 102M :balance 102M}]
                           (items-by-account (:id groceries)))
        "Expected the groceries items to be updated")
    (assert-account-quantities checking 797M groceries 203M)
    (testing "transaction is updated"
      (is (= (t/local-date 2016 4 12)
             (:transaction-date (transactions/reload result)))
          "The transaction should be updated"))))

(def short-circuit-context
  (merge
