(ns iol-ion.tx.upsert-ledger (:import [java.util UUID Date]) (:require [datomic.api :as dc])) (defn -random-tempid [] (dc/tempid :db.part/user)) (defn get-line-items-after [db journal-entry] (for [jel (:journal-entry/line-items journal-entry) next-jel (->> (dc/index-pull db {:index :avet :selector [:db/id :journal-entry-line/client+account+location+date] :start [:journal-entry-line/client+account+location+date (:journal-entry-line/client+account+location+date jel) (:db/id jel)]}) (take-while (fn line-must-match-client-account-location [result] (and (= (take 3 (:journal-entry-line/client+account+location+date result)) (take 3 (:journal-entry-line/client+account+location+date jel))) (not= (:db/id jel) (:db/id result))))) (take 2)) :when next-jel] (:db/id next-jel))) (def extant-read '[:db/id :journal-entry/date :journal-entry/client {:journal-entry/line-items [:journal-entry-line/account :journal-entry-line/location :db/id :journal-entry-line/client+account+location+date]}]) (defn current-date [db] (let [last-tx (dc/t->tx (dc/basis-t db)) [[date]] (seq (dc/q '[:find ?ti :in $ ?tx :where [?tx :db/txInstant ?ti]] db last-tx))] date)) (defn calc-client+account+location+date [je jel] [(or (:db/id (:journal-entry/client je)) (:journal-entry/client je)) (or (:db/id (:journal-entry-line/account jel)) (:journal-entry-line/account jel)) (-> jel :journal-entry-line/location) (-> je :journal-entry/date)]) (defn upsert-ledger [db ledger-entry] (assert (:journal-entry/date ledger-entry) (format "Must at least provide date when updating ledger: %s" (pr-str ledger-entry))) (assert (:journal-entry/client ledger-entry) "Must at least provide client when updating ledger") ;; TODO these are not always true ;; (assert (every? :journal-entry-line/account (:journal-entry/line-items ledger-entry)) "must at least provide account when updating ledger") ;; (assert (every? :journal-entry-line/location (:journal-entry/line-items ledger-entry)) "Must at least provide location when updating ledger") (let [extant-entry (or (when-let [original-entity (:journal-entry/original-entity ledger-entry)] (dc/pull db extant-read [:journal-entry/original-entity original-entity])) (when-let [external-id (:journal-entry/external-id ledger-entry)] (dc/pull db extant-read [:journal-entry/external-id external-id])))] (cond-> [[:upsert-entity (into (-> ledger-entry (assoc :db/id (or (:db/id ledger-entry) (:db/id extant-entry) (-random-tempid))) (update :journal-entry/line-items (fn [lis] (mapv #(-> % (assoc :journal-entry-line/date (:journal-entry/date ledger-entry)) (assoc :journal-entry-line/client (:journal-entry/client ledger-entry))) lis)))))] {:db/id (:journal-entry/client ledger-entry) :client/ledger-last-change (current-date db)}])))