Files
integreat/src/clj/auto_ap/datomic/migrate/add_general_ledger.clj
2019-04-17 19:30:01 -07:00

281 lines
10 KiB
Clojure

(ns auto-ap.datomic.migrate.add-general-ledger
(:require [datomic.api :as d]
[auto-ap.datomic :refer [remove-nils]]
[auto-ap.datomic.accounts :as accounts]
[auto-ap.expense-accounts :as expense-accounts]
[auto-ap.ledger :as ledger]))
(defn test-run [txs-set]
(println "processing " (count txs-set))
(doseq [[i tx] (map vector (range) txs-set)]
@(d/transact (d/connect auto-ap.datomic/uri)
tx)
(when (= 0 (mod i 1000))
(println "processed " i))))
(def add-general-ledger
[[{:db/ident :journal-entry/source
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db/doc "The type of entity that created this entry"}
{:db/ident :journal-entry/client
:db/valueType :db.type/ref
:db/cardinality :db.cardinality/one
:db/doc "The client for the ledger"}
{:db/ident :journal-entry/date
:db/valueType :db.type/instant
:db/cardinality :db.cardinality/one
:db/doc "The time for this entry"}
{:db/ident :journal-entry/original-entity
:db/valueType :db.type/ref
:db/unique :db.unique/identity
:db/cardinality :db.cardinality/one
:db/doc "The thing that created this entry"}
{:db/ident :journal-entry/vendor
:db/valueType :db.type/ref
:db/cardinality :db.cardinality/one
:db/doc "The vendor for the ledger entry"}
{:db/ident :journal-entry/amount
:db/valueType :db.type/double
:db/cardinality :db.cardinality/one
:db/doc "The amount for the entry"}
{:db/ident :journal-entry/line-items
:db/valueType :db.type/ref
:db/cardinality :db.cardinality/many
:db/isComponent true
:db/doc "Each of the line items in the general ledger"}
{:db/ident :journal-entry/cleared
:db/valueType :db.type/boolean
:db/cardinality :db.cardinality/one
:db/doc "Has this cleared?"}
{:db/ident :journal-entry-line/expense-account
:db/valueType :db.type/long
:db/cardinality :db.cardinality/one
:db/doc "The expense account being changed"}
{:db/ident :journal-entry-line/account
:db/valueType :db.type/ref
:db/cardinality :db.cardinality/one
:db/doc "The other type of account being changed"}
{:db/ident :journal-entry-line/debit
:db/valueType :db.type/double
:db/cardinality :db.cardinality/one
:db/doc "The amount to debit"}
{:db/ident :journal-entry-line/credit
:db/valueType :db.type/double
:db/cardinality :db.cardinality/one
:db/doc "The amount to credit"}
{:db/ident :journal-entry-line/location
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db/doc "Location of the entry"}]
]
)
(def add-transaction-account
[[{:db/ident :transaction/accounts
:db/valueType :db.type/ref
:db/cardinality :db.cardinality/many
:db/isComponent true
:db/doc "The debit(s)/credit(s) for this transaction"}
{:db/ident :transaction-account/account
:db/valueType :db.type/ref
:db/cardinality :db.cardinality/one
:db/doc "Which account to debit/credit for this transaction"}
{:db/ident :transaction-account/location
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db/doc "Location for this expense account"}
{:db/ident :transaction-account/amount
:db/valueType :db.type/double
:db/cardinality :db.cardinality/one
:db/doc "How much to debit/credit - must be positive"}]])
(def add-yodlee-merchant
[[{:db/ident :yodlee-merchant/name
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db/doc "The yodlee merchant name"}
{:db/ident :yodlee-merchant/yodlee-id
:db/valueType :db.type/string
:db/unique :db.unique/identity
:db/cardinality :db.cardinality/one
:db/doc "The yodlee merchant id"}
{:db/ident :transaction/yodlee-merchant
:db/valueType :db.type/ref
:db/cardinality :db.cardinality/one
:db/doc "The yodlee merchant"}]])
(def add-accounts
[[
{:db/ident :account/code
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db/doc "The code for the expense account (e.g., A1123)"}
{:db/ident :account/numeric-code
:db/valueType :db.type/long
:db/cardinality :db.cardinality/one
:db/doc "The numeric-only for the expense account (e.g., 5150)"}
{:db/ident :account/name
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db/doc "The name of the code (e.g., \"Telephone - HQ\")"}
{:db/ident :account/location
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db/doc "A forced location for this code, e.g., HQ."}
{:db/ident :account/account-set
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db/doc "The set of accounts this entry belongs to. Allows customization."}
{:db/ident :account/type
:db/valueType :db.type/ref
:db/cardinality :db.cardinality/one
:db/doc "The type of account, (e.g., :account-type/expense :account-type/liability)"}
{:db/ident :account-type/expense}
{:db/ident :account-type/liability}
{:db/ident :account-type/revenue}
{:db/ident :account-type/dividend}
{:db/ident :account-type/asset}
{:db/ident :account-type/equity}]
(mapv
(fn [[numeric {:keys [name location]}]]
(remove-nils
{:account/type :account-type/expense
:account/numeric-code numeric
:account/code (str numeric)
:account/name name
:account/location location
:account/account-set "default"}))
expense-accounts/chooseable-expense-accounts)])
(defn add-general-ledger-fns [conn]
[[{:db/ident :replace-general-ledger
:db/doc "Deletes the general ledger entries for an entity"
:db/fn (d/function '{:lang "clojure"
:params [db origin]
:code (let [ids (->> (d/query {:query {:find ['?e]
:in ['$ '?origin]
:where [['?e :journal-entry/original-entity '?origin]]}
:args [db origin]})
(map first))]
(into []
(map (fn [i] [:db/retractEntity i ]) ids)))})}]] )
(defn bulk-load-invoice-ledger [conn]
(let [invoice-ids (map first (d/query {:query {:find '[?e]
:in '[$]
:where ['[?e :invoice/total]]}
:args [(d/db conn)]}))
z (->> invoice-ids
(mapv #(vector (ledger/entity-change->ledger (d/db conn) [:invoice %]))))]
z))
(defn bulk-load-transaction-ledger [conn]
(let [transaction-ids (map first (d/query {:query {:find '[?e]
:in '[$]
:where ['[?e :transaction/id]]}
:args [(d/db conn)]}))
_ (println (count transaction-ids))
z (->> transaction-ids
(map #(ledger/entity-change->ledger (d/db conn) [:transaction %]))
(filter identity)
(mapv #(vector %)))]
z))
#_(test-run (bulk-load-transaction-ledger (d/connect auto-ap.datomic/uri)))
#_(test-run (bulk-load-invoice-ledger (d/connect auto-ap.datomic/uri)))
#_(do (doseq [tran (convert-transactions (d/connect auto-ap.datomic/uri))]
@(d/transact (d/connect auto-ap.datomic/uri) tran))
(println "done."))
#_(do @(d/transact (d/connect auto-ap.datomic/uri)
(bulk-load-transaction-ledger (d/connect auto-ap.datomic/uri)))
(println "test"))
(def change-expense-account-to-entity
[[{:db/ident :invoice-expense-account/account
:db/valueType :db.type/ref
:db/cardinality :db.cardinality/one
:db/doc "The account entity that this expense is for"}]])
(def add-account-to-vendor
[[{:db/ident :vendor/default-account
:db/valueType :db.type/ref
:db/cardinality :db.cardinality/one
:db/doc "The account will be used when a bill is created."}]])
(defn convert-vendors [conn]
(let [vendors (d/query {:query {:find '[?v ?expense-account-id]
:in '[$]
:where ['[?v :vendor/default-expense-account ?expense-account-id]]}
:args [(d/db conn)]})]
[(mapv
(fn [[v expense-account-id]]
(remove-nils {:db/id v
:vendor/default-account (accounts/get-account-by-numeric-code-and-sets expense-account-id ["default"])}))
vendors)]))
(defn convert-invoices [conn]
(let [invoice-expense-accounts (d/query {:query {:find '[?iea ?expense-account-id]
:in '[$]
:where ['[?iea :invoice-expense-account/expense-account-id ?expense-account-id]]}
:args [(d/db conn)]})]
[(mapv
(fn [[iea expense-account-id]]
(remove-nils {:db/id iea
:invoice-expense-account/account (accounts/get-account-by-numeric-code-and-sets expense-account-id ["default"])}))
invoice-expense-accounts)]))
(defn convert-transactions [conn]
(let [matched-transactions (d/query {:query {:find '[?transaction ?v]
:in '[$]
:where ['[?transaction :transaction/payment ?payment]
'[?payment :payment/invoices ?i]
'[?i :invoice/vendor ?v]]}
:args [(d/db (d/connect auto-ap.datomic/uri))]})]
[(mapv
(fn [[transaction-id vendor-id]]
(remove-nils {:db/id transaction-id
:transaction/vendor vendor-id
:transaction/location "A"
:transaction/account (:db/id (accounts/get-account-by-numeric-code-and-sets 2110 ["default"]))
}))
matched-transactions)]))
(def add-location-to-transaction
[[{:db/ident :transaction/location
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db/doc "Location of the transaction's target"}]])
(def add-credit-bank-account
[[{:db/ident :bank-account-type/credit}]])
#_(do (doseq [tran (convert-transactions (d/connect auto-ap.datomic/uri))]
@(d/transact (d/connect auto-ap.datomic/uri) tran))
(println "done."))