consolidate sales summary ledger entry creation into upsert-sales-summary tx
Move journal entry calculation and creation from the reconcile-ledger background job into the upsert-sales-summary tx function. Now any save of a sales summary (job recalculation, admin edit wizard, or manual touch) automatically creates the journal entry if balanced with all accounts mapped, or retracts it if conditions no longer hold. Eliminates the need for a separate upsert-sales-summary-ledger call and the reconcile ledger pass for sales summaries.
This commit is contained in:
@@ -50,7 +50,7 @@
|
||||
(datomic-fn :upsert-invoice #'iol-ion.tx.upsert-invoice/upsert-invoice)
|
||||
(datomic-fn :upsert-ledger #'iol-ion.tx.upsert-ledger/upsert-ledger)
|
||||
(datomic-fn :upsert-transaction #'iol-ion.tx.upsert-transaction/upsert-transaction)
|
||||
(datomic-fn :upsert-sales-summary-ledger #'iol-ion.tx.upsert-sales-summary-ledger/upsert-sales-summary-ledger)])))
|
||||
(datomic-fn :upsert-sales-summary #'iol-ion.tx.upsert-sales-summary-ledger/upsert-sales-summary)])))
|
||||
|
||||
(comment
|
||||
(regenerate-literals)
|
||||
|
||||
@@ -1,28 +1,7 @@
|
||||
(ns iol-ion.tx.upsert-sales-summary-ledger
|
||||
(:import [java.util UUID Date])
|
||||
(:require [datomic.api :as dc]))
|
||||
|
||||
(defn -random-tempid []
|
||||
(dc/tempid :db.part/user))
|
||||
|
||||
(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)])
|
||||
(:require [datomic.api :as dc]
|
||||
[iol-ion.tx.upsert-entity :as upsert-entity]
|
||||
[iol-ion.tx.upsert-ledger :as upsert-ledger]))
|
||||
|
||||
(defn summary->journal-entry [db summary-id]
|
||||
(let [summary (dc/pull db '[:sales-summary/client
|
||||
@@ -44,35 +23,38 @@
|
||||
acc-items))))
|
||||
line-items (mapv (fn [{:keys [account] :as m}]
|
||||
(cond-> {:db/id (str (java.util.UUID/randomUUID))
|
||||
:journal-entry-line/account account}
|
||||
:journal-entry-line/account account
|
||||
:journal-entry-line/location "A"}
|
||||
(get m :ledger-side/debit) (assoc :journal-entry-line/debit (get m :ledger-side/debit))
|
||||
(get m :ledger-side/credit) (assoc :journal-entry-line/credit (get m :ledger-side/credit))))
|
||||
aggregated)
|
||||
total-amount (reduce + 0.0 (map #(get % :ledger-side/debit 0.0) aggregated))]
|
||||
(when (seq line-items)
|
||||
total-debits (reduce + 0.0 (map #(get % :ledger-side/debit 0.0) aggregated))
|
||||
total-credits (reduce + 0.0 (map #(get % :ledger-side/credit 0.0) aggregated))]
|
||||
(when (and (seq line-items)
|
||||
(= (Math/round (* 1000 total-debits))
|
||||
(Math/round (* 1000 total-credits))))
|
||||
{:journal-entry/source "sales-summary"
|
||||
:journal-entry/client (:db/id (:sales-summary/client summary))
|
||||
:journal-entry/date (:sales-summary/date summary)
|
||||
:journal-entry/original-entity summary-id
|
||||
:journal-entry/amount total-amount
|
||||
:journal-entry/amount total-debits
|
||||
:journal-entry/line-items line-items})))
|
||||
|
||||
(defn upsert-sales-summary-ledger [db summary]
|
||||
(assert (:db/id summary) "Must provide summary id")
|
||||
(let [upserted-entity [[:upsert-entity {:db/id (:db/id summary)}]]
|
||||
with-summary (dc/with db upserted-entity)
|
||||
(defn upsert-sales-summary [db summary]
|
||||
(let [upserted-summary [[:upsert-entity summary]]
|
||||
db-after (-> (dc/with db upserted-summary) :db-after)
|
||||
summary-id (:db/id summary)
|
||||
journal-entry (summary->journal-entry (:db-after with-summary) summary-id)
|
||||
client-id (-> (dc/pull (:db-after with-summary)
|
||||
[{:sales-summary/client [:db/id]}]
|
||||
summary-id)
|
||||
client-id (-> (dc/pull db-after [{:sales-summary/client [:db/id]}] summary-id)
|
||||
:sales-summary/client
|
||||
:db/id)]
|
||||
(into upserted-entity
|
||||
:db/id)
|
||||
journal-entry (summary->journal-entry db-after summary-id)]
|
||||
(into upserted-summary
|
||||
(if journal-entry
|
||||
[[:upsert-ledger journal-entry]
|
||||
{:db/id client-id
|
||||
:client/ledger-last-change (current-date db)}]
|
||||
[[:db/retractEntity [:journal-entry/original-entity summary-id]]
|
||||
{:db/id client-id
|
||||
:client/ledger-last-change (current-date db)}]))))
|
||||
[[:upsert-ledger journal-entry]]
|
||||
(let [existing-je-id (ffirst (dc/q '[:find ?je . :in $ ?ss
|
||||
:where [?je :journal-entry/original-entity ?ss]]
|
||||
db-after summary-id))]
|
||||
(concat
|
||||
(when existing-je-id [[:db/retractEntity existing-je-id]])
|
||||
(when client-id [{:db/id client-id
|
||||
:client/ledger-last-change (upsert-ledger/current-date db)}])))))))
|
||||
|
||||
@@ -276,40 +276,6 @@
|
||||
:ledger-mapped/amount amount
|
||||
:ledger-mapped/ledger-side :ledger-side/debit}))
|
||||
|
||||
(defn- summary->journal-entry [db summary-id]
|
||||
(let [summary (dc/pull db '[:sales-summary/client
|
||||
:sales-summary/date
|
||||
{:sales-summary/items [:sales-summary-item/category
|
||||
:ledger-mapped/account
|
||||
:ledger-mapped/amount
|
||||
:ledger-mapped/ledger-side]}]
|
||||
summary-id)
|
||||
items (:sales-summary/items summary)
|
||||
;; Aggregate items by account and ledger side
|
||||
aggregated (->> items
|
||||
(filter :ledger-mapped/account)
|
||||
(group-by :ledger-mapped/account)
|
||||
(map (fn [[account acc-items]]
|
||||
(reduce
|
||||
(fn [m item]
|
||||
(update m (:ledger-mapped/ledger-side item) (fnil + 0.0) (:ledger-mapped/amount item 0.0)))
|
||||
{:account account}
|
||||
acc-items))))
|
||||
line-items (mapv (fn [{:keys [account] :as m}]
|
||||
(cond-> {:db/id (str (java.util.UUID/randomUUID))
|
||||
:journal-entry-line/account account}
|
||||
(get m :ledger-side/debit) (assoc :journal-entry-line/debit (get m :ledger-side/debit))
|
||||
(get m :ledger-side/credit) (assoc :journal-entry-line/credit (get m :ledger-side/credit))))
|
||||
aggregated)
|
||||
total-amount (reduce + 0.0 (map #(get % :ledger-side/debit 0.0) aggregated))]
|
||||
(when (seq line-items)
|
||||
{:journal-entry/source "sales-summary"
|
||||
:journal-entry/client (:db/id (:sales-summary/client summary))
|
||||
:journal-entry/date (:sales-summary/date summary)
|
||||
:journal-entry/original-entity summary-id
|
||||
:journal-entry/amount total-amount
|
||||
:journal-entry/line-items line-items})))
|
||||
|
||||
(defn- calc-aggregate-totals [items]
|
||||
(reduce
|
||||
(fn [acc item]
|
||||
@@ -376,7 +342,7 @@
|
||||
(do
|
||||
(alog/info ::upserting-summaries
|
||||
:category-count (count (:sales-summary/items result)))
|
||||
@(dc/transact conn [[:upsert-entity result]]))
|
||||
@(dc/transact conn [[:upsert-sales-summary result]]))
|
||||
@(dc/transact conn [{:db/id id :sales-summary/dirty false}]))))))
|
||||
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
(dc/db conn) start-date)
|
||||
(map first)
|
||||
(mapv (fn [ss]
|
||||
[:upsert-sales-summary-ledger {:db/id ss}])))
|
||||
[:upsert-sales-summary {:db/id ss}])))
|
||||
|
||||
repairs (vec (concat txes-missing-ledger-entries invoices-missing-ledger-entries sales-summaries-missing-ledger-entries))]
|
||||
(when (seq repairs)
|
||||
|
||||
@@ -483,7 +483,7 @@
|
||||
edit-schema)
|
||||
(submit [this {:keys [multi-form-state request-method identity] :as request}]
|
||||
(let [result (:snapshot multi-form-state )
|
||||
transaction [:upsert-entity {:db/id (:db/id result)
|
||||
transaction [:upsert-sales-summary {:db/id (:db/id result)
|
||||
:sales-summary/items (map
|
||||
(fn [i]
|
||||
(if (:sales-summary-item/manual? i)
|
||||
|
||||
Reference in New Issue
Block a user