                                 :amount share})
                              shared-with)]
          (insert! db-trans :expense-share share-rows)
-         ; Maybe use async channel to oupdate dept?
          (clear-dept db-trans group-id)
          (save-dept db-trans group-id (calculate-group-dept db-trans group-id))
          expense-id)))))

       :name (:name group)
       :members members})))

;DeptStorage
(declare dist-dept)

(defn get-user-totals [db group-id]
  (->> (q/get-total-amount-per-user group-id)
       (run-query db)
       (reduce #(assoc %1 (:user-id %2) (:amount %2)) {})))

(defn calculate-group-dept [db group-id]
  (let [user-total (get-user-totals db group-id)
        in-dept (->> user-total

                     (sort-by second >))
        filter-loaners (comp (filter #(> 0 (second %)))
                             (map #(vector (first %) (* -1 (second %)))))
        lenders (->> user-total
                     (into [] filter-loaners)
                     (sort-by second >))]
    (dist-dept lenders in-dept)))

(defn- dist-dept [lenders in-dept]
  (loop [[l & ls] lenders
         [i & is] in-dept
         total []]
    (if (some nil? [l i])
      total
      (let [id first
            amount second]
        (case (compare (amount l) (amount i))
          -1 (let [dept (- (amount i) (amount l))
                   remainder [(id i) (- (amount i) dept)]]
               (recur ls (cons remainder is) (cons [(id i) (id l) dept] total)))

          0 (recur ls is (cons [(id i) (id l) (amount l)] total))

          1 (let [dept (- (amount l) (amount i))
                  remainder [(id l) (- (amount l) dept)]]
              (recur (cons remainder ls) is
                     (cons [(id i) (id l) (amount i)] total))))))))

(defn clear-dept [db group-id]
  (delete! db :dept ["group_id = ?" group-id]))
