Migrates back to datomic on-prem

This commit is contained in:
2023-04-29 07:12:51 -07:00
parent aca8f7c92c
commit b2ad7790cf
88 changed files with 2289 additions and 2286 deletions

View File

@@ -0,0 +1,5 @@
{:lint-as
{rewrite-clj.zip/subedit-> clojure.core/->
rewrite-clj.zip/subedit->> clojure.core/->>
rewrite-clj.zip/edit-> clojure.core/->
rewrite-clj.zip/edit->> clojure.core/->>}}

View File

@@ -2,7 +2,7 @@
(:require [clj-time.core :as time]
[clj-time.coerce :as coerce]
[clj-time.format :as f]
[datomic.client.api :as dc]))
[datomic.api :as dc]))
#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
(defn dollars-0? [amt]

View File

@@ -1,406 +1,12 @@
(ns iol-ion.tx
(:require [datomic.client.api :as dc])
(:require [datomic.api :as dc]
[iol-ion.utils])
(:import [java.util UUID]))
(defn random-tempid []
(str (UUID/randomUUID)))
(defn by
([f xs]
(by f identity xs))
([f fv xs]
(reduce
#(assoc %1 (f %2) (fv %2))
{}
xs)))
(defn pull-many [db read ids ]
(->> (dc/q '[:find (pull ?e r)
:in $ [?e ...] r]
db
ids
read)
(map first)))
(declare upsert-entity)
(defn reset-rels [db e a vs]
(assert (every? :db/id vs) (format "In order to reset attribute %s, every value must have :db/id" a))
(let [ids (when-not (string? e)
(->> (dc/q '[:find ?z
:in $ ?e ?a
:where [?e ?a ?z]]
db e a)
(map first)))
new-id-set (set (map :db/id vs))
retract-ids (filter (complement new-id-set) ids)
{is-component? :db/isComponent} (dc/pull db [:db/isComponent] a)
new-rels (filter (complement (set ids)) (map :db/id vs))]
(-> []
(into (map (fn [i] (if is-component?
[:db/retractEntity i]
[:db/retract e a i ])) retract-ids))
(into (map (fn [i] [:db/add e a i]) new-rels))
(into (mapcat (fn [i] (upsert-entity db i)) vs)))))
(defn reset-scalars [db e a vs]
(let [extant (when-not (string? e)
(->> (dc/q '[:find ?z
:in $ ?e ?a
:where [?e ?a ?z]]
db e a)
(map first)))
retracts (filter (complement (set vs)) extant)
new (filter (complement (set extant)) vs)]
(-> []
(into (map (fn [i] [:db/retract e a i ]) retracts))
(into (map (fn [i] [:db/add e a i]) new)))))
;; TODO unit test this
(defn upsert-entity [db entity]
(assert (or (:db/id entity)
(:db/ident entity))
(str "Cannot upsert without :db/id or :db/ident, " entity))
(let [e (or (:db/id entity) (:db/ident entity))
is-new? (string? e)
extant-entity (when-not is-new?
(dc/pull db (keys entity) (or (:db/id entity) (:db/ident entity))))
ident->value-type (by :db/ident (comp :db/ident
:db/valueType)
(pull-many
db
[:db/valueType :db/ident]
(keys entity)))
ident->cardinality (by :db/ident (comp :db/ident
:db/cardinality)
(pull-many
db
[:db/cardinality :db/ident]
(keys entity)))
ops (->> entity
(reduce
(fn [ops [a v]]
(cond
(= :db/id a)
ops
(= :db/ident a)
ops
(or (= v (a extant-entity))
(= v (:db/ident (a extant-entity) :nope))
(= v (:db/id (a extant-entity)) :nope))
ops
(and (nil? v)
(not (nil? (a extant-entity))))
(if (= :db.cardinality/many (ident->cardinality a))
(into ops (map (fn [v]
[:db/retract e a (cond-> v
(:db/id v) :db/id)])
(a extant-entity)))
(conj ops [:db/retract e a (cond-> (a extant-entity)
(:db/id (a extant-entity)) :db/id)]))
(nil? v)
ops
;; reset relationships if it's refs, and not a lookup (i.e., seq of maps, or empty seq)
(and (sequential? v) (= :db.type/tuple (ident->value-type a)))
(conj ops [:db/add e a v])
(and (sequential? v) (= :db.type/ref (ident->value-type a)) (every? map? v))
(into ops (reset-rels db e a v))
(= :db.cardinality/many (ident->cardinality a))
(into ops (reset-scalars db e a v))
(and (sequential? v) (not= :db.type/ref (ident->value-type a)))
(into ops (reset-scalars db e a v))
(and (map? v)
(= :db.type/ref (ident->value-type a)))
(let [id (or (:db/id v) (random-tempid))]
(-> ops
(conj [:db/add e a id])
(into (upsert-entity db (assoc v :db/id id)))))
:else
(conj ops [:db/add e a v])
))
[]))]
ops))
(defn min-by [sorter]
(->> sorter
sort
last
last))
(defn get-line-items-after [db journal-entry]
(for [jel (:journal-entry/line-items journal-entry)
:let [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)]
:limit 3
})
(filter (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)))
))
first
:db/id)]
:when next-jel]
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 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) "Must at least provide date when updating ledger")
(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])))
extant-entry-exists? (:db/id extant-entry)]
(cond->
(upsert-entity db (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/dirty true)
(assoc :journal-entry-line/client+account+location+date
(calc-client+account+location+date ledger-entry %)))
lis))))
))
extant-entry-exists? (into (map (fn [li]
{:journal-entry-line/dirty true
:db/id li})
(get-line-items-after db extant-entry))))))
(defn remove-nils [m]
(let [result (reduce-kv
(fn [m k v]
(if (not (nil? v))
(assoc m k v)
m
))
{}
m)]
(if (seq result)
result
nil)))
(defn invoice->journal-entry
([db invoice-id]
(invoice->journal-entry db invoice-id invoice-id))
;; the 3-arity version allows you to pass a potential tempid in instead of the invoice-id,
;; which would be a temporary value after the transaction
([db invoice-id raw-invoice-id]
(let [entity (dc/pull db
'[:invoice/total
:invoice/exclude-from-ledger
:invoice/outstanding-balance
:invoice/date
{:invoice/vendor [:db/id :vendor/name]
:invoice/client [:db/id :client/code]
:invoice/payment [:db/id {:payment/status [:db/ident]}]
:invoice/status [:db/ident]
:invoice/import-status [:db/ident]
:invoice/expense-accounts [:invoice-expense-account/account
:invoice-expense-account/amount
:invoice-expense-account/location]}]
invoice-id)
credit-invoice? (< (:invoice/total entity 0.0) 0.0)]
(when-not (or
(not (:invoice/total entity))
(= true (:invoice/exclude-from-ledger entity))
(= :import-status/pending (:db/ident (:invoice/import-status entity)))
(= :invoice-status/voided (:db/ident (:invoice/status entity)))
(< -0.001 (:invoice/total entity) 0.001))
(remove-nils
{:journal-entry/source "invoice"
:journal-entry/client (:db/id (:invoice/client entity))
:journal-entry/date (:invoice/date entity)
:journal-entry/original-entity raw-invoice-id
:journal-entry/vendor (:db/id (:invoice/vendor entity))
:journal-entry/amount (Math/abs (:invoice/total entity))
:journal-entry/line-items (into [(cond-> {:db/id (str raw-invoice-id "-" 0)
:journal-entry-line/account :account/accounts-payable
:journal-entry-line/location "A"
}
credit-invoice? (assoc :journal-entry-line/debit (Math/abs (:invoice/total entity)))
(not credit-invoice?) (assoc :journal-entry-line/credit (Math/abs (:invoice/total entity))))]
(map-indexed (fn [i ea]
(cond->
{:db/id (str raw-invoice-id "-" (inc i))
:journal-entry-line/account (:db/id (:invoice-expense-account/account ea))
:journal-entry-line/location (or (:invoice-expense-account/location ea) "HQ")
}
credit-invoice? (assoc :journal-entry-line/credit (Math/abs (:invoice-expense-account/amount ea)))
(not credit-invoice?) (assoc :journal-entry-line/debit (Math/abs (:invoice-expense-account/amount ea)))))
(:invoice/expense-accounts entity)))
:journal-entry/cleared (and (< (:invoice/outstanding-balance entity) 0.01)
(every? #(= :payment-status/cleared (:payment/status %)) (:invoice/payments entity))
)})))))
(defn upsert-invoice [db invoice]
(let [
upserted-entity (upsert-entity db invoice)
with-invoice (try (dc/with db {:tx-data upserted-entity})
(catch ClassCastException e
(println "Dev local does not support with in tx functions. :(")
(dc/with (dc/with-db @(resolve 'auto-ap.datomic/conn)) {:tx-data upserted-entity})
))
invoice-id (or (-> with-invoice :tempids (get (:db/id invoice)))
(:db/id invoice))
journal-entry (invoice->journal-entry (:db-after with-invoice)
invoice-id
(:db/id invoice))]
(into upserted-entity
(if journal-entry
(upsert-ledger db journal-entry)
[[:db/retractEntity [:journal-entry/original-entity (:db/id invoice)]]]))))
(defn propose-invoice [db invoice]
(let [existing? (boolean (seq (dc/q '[:find ?i
:in $ ?invoice-number ?client ?vendor
:where
[?i :invoice/invoice-number ?invoice-number]
[?i :invoice/client ?client]
[?i :invoice/vendor ?vendor]
(not [?i :invoice/status :invoice-status/voided])]
db
(:invoice/invoice-number invoice)
(:invoice/client invoice)
(:invoice/vendor invoice))))]
(if existing?
[]
(upsert-invoice db invoice))))
(defn transaction->journal-entry
([db transaction-id]
(transaction->journal-entry db transaction-id transaction-id))
;; the 3-arity version allows you to pass a potential tempid in instead of the invoice-id,
;; which would be a temporary value after the transaction
([db transaction-id raw-transaction-id]
(let [entity (dc/pull db [:transaction/client
:transaction/date
:transaction/description-original
:db/id
:transaction/vendor
:transaction/amount
:transaction/cleared-against
{:transaction/accounts [:transaction-account/account
:transaction-account/location
:transaction-account/amount]
:transaction/approval-status [:db/ident]
:transaction/bank-account [:db/id {:bank-account/type [:db/ident]}]}]
transaction-id)
decreasing? (< (or (:transaction/amount entity) 0.0) 0.0)
credit-from-bank? decreasing?
debit-from-bank? (not decreasing?)]
(when (and (not (= :transaction-approval-status/excluded (:db/ident (:transaction/approval-status entity))))
(not (= :transaction-approval-status/suppressed (:db/ident (:transaction/approval-status entity))))
(:transaction/amount entity)
(not (< -0.001 (:transaction/amount entity) 0.001)))
(remove-nils
{:journal-entry/source "transaction"
:journal-entry/client (:db/id (:transaction/client entity))
:journal-entry/date (:transaction/date entity)
:journal-entry/original-entity raw-transaction-id
:journal-entry/alternate-description (:transaction/description-original entity)
:journal-entry/vendor (:db/id (:transaction/vendor entity))
:journal-entry/amount (Math/abs (:transaction/amount entity))
:journal-entry/cleared-against (:transaction/cleared-against entity)
:journal-entry/line-items (into [(remove-nils {:journal-entry-line/account (:db/id (:transaction/bank-account entity))
:db/id (str raw-transaction-id "-" 0)
:journal-entry-line/location "A"
:journal-entry-line/credit (when credit-from-bank?
(Math/abs (:transaction/amount entity)))
:journal-entry-line/debit (when debit-from-bank?
(Math/abs (:transaction/amount entity)))})
]
(map-indexed
(fn [i a]
(remove-nils{
:db/id (str raw-transaction-id "-" (inc i))
:journal-entry-line/account (:db/id (:transaction-account/account a))
:journal-entry-line/location (:transaction-account/location a)
:journal-entry-line/debit (when credit-from-bank?
(Math/abs (:transaction-account/amount a)))
:journal-entry-line/credit (when debit-from-bank?
(Math/abs (:transaction-account/amount a)))}))
(if (seq (:transaction/accounts entity))
(:transaction/accounts entity)
[{:transaction-account/amount (:transaction/amount entity)}])))
:journal-entry/cleared true})))))
(defn upsert-transaction [db transaction]
;; because some transactions will reference temp ids, you have to dissoc them, like :transaction/payment
(let [upserted-entity (upsert-entity db (dissoc transaction :transaction/payment :import-batch/_entry))
with-transaction (try (dc/with db {:tx-data upserted-entity})
(catch ClassCastException e
(println "Dev local does not support with in tx functions. :(")
(dc/with (dc/with-db @(resolve 'auto-ap.datomic/conn)) {:tx-data upserted-entity})
))
transaction-id (or (-> with-transaction :tempids (get (:db/id transaction)))
(:db/id transaction))
journal-entry (transaction->journal-entry (:db-after with-transaction)
transaction-id
(:db/id transaction))]
(into (upsert-entity db transaction)
(if journal-entry
(upsert-ledger db journal-entry)
[[:db/retractEntity [:journal-entry/original-entity (:db/id transaction)]]]))))
(defn pay [db e amount]
(let [current-outstanding-balance (-> (dc/pull db [:invoice/outstanding-balance] e) :invoice/outstanding-balance)
new-outstanding-balance (- current-outstanding-balance amount)]
(upsert-invoice db {:db/id e
:invoice/outstanding-balance new-outstanding-balance
:invoice/status (if (> new-outstanding-balance 0)
:invoice-status/unpaid
:invoice-status/paid)})))
(def random-tempid iol-ion.utils/random-tempid)
(def by iol-ion.utils/by)
(def pull-many iol-ion.utils/pull-many)
(def remove-nils iol-ion.utils/remove-nils)
;; TODO expected-deposit ledger entry
@@ -424,5 +30,7 @@
:location "A"
:account :account/ccp}]}))
(defn plus [db e a amount]
[[:db/add e a (-> (dc/pull db [a] e) a (+ amount))]])

View File

@@ -0,0 +1,11 @@
(ns iol-ion.tx.pay
(:require [datomic.api :as dc]))
(defn pay [db e amount]
(let [current-outstanding-balance (-> (dc/pull db [:invoice/outstanding-balance] e) :invoice/outstanding-balance)
new-outstanding-balance (- current-outstanding-balance amount)]
[[:upsert-invoice {:db/id e
:invoice/outstanding-balance new-outstanding-balance
:invoice/status (if (> new-outstanding-balance 0)
:invoice-status/unpaid
:invoice-status/paid)}]]))

View File

@@ -0,0 +1,5 @@
(ns iol-ion.tx.plus
(:require [datomic.api :as dc]))
(defn plus [db e a amount]
[[:db/add e a (-> (dc/pull db [a] e) a (+ amount))]])

View File

@@ -0,0 +1,18 @@
(ns iol-ion.tx.propose-invoice
(:require [datomic.api :as dc]))
(defn propose-invoice [db invoice]
(let [existing? (boolean (seq (dc/q '[:find ?i
:in $ ?invoice-number ?client ?vendor
:where
[?i :invoice/invoice-number ?invoice-number]
[?i :invoice/client ?client]
[?i :invoice/vendor ?vendor]
(not [?i :invoice/status :invoice-status/voided])]
db
(:invoice/invoice-number invoice)
(:invoice/client invoice)
(:invoice/vendor invoice))))]
(if existing?
[]
[[:upsert-invoice invoice]])))

View File

@@ -0,0 +1,21 @@
(ns iol-ion.tx.reset-rels
(:require [datomic.api :as dc]))
(defn reset-rels [db e a vs]
(assert (every? :db/id vs) (format "In order to reset attribute %s, every value must have :db/id" a))
(let [ids (when-not (string? e)
(->> (dc/q '[:find ?z
:in $ ?e ?a
:where [?e ?a ?z]]
db e a)
(map first)))
new-id-set (set (map :db/id vs))
retract-ids (filter (complement new-id-set) ids)
{is-component? :db/isComponent} (dc/pull db [:db/isComponent] a)
new-rels (filter (complement (set ids)) (map :db/id vs))]
(-> []
(into (map (fn [i] (if is-component?
[:db/retractEntity i]
[:db/retract e a i ])) retract-ids))
(into (map (fn [i] [:db/add e a i]) new-rels))
(into (map (fn [i] [:upsert-entity i]) vs)))))

View File

@@ -0,0 +1,16 @@
(ns iol-ion.tx.reset-scalars
(:require [datomic.api :as dc]))
(defn reset-scalars [db e a vs]
(let [extant (when-not (string? e)
(->> (dc/q '[:find ?z
:in $ ?e ?a
:where [?e ?a ?z]]
db e a)
(map first)))
retracts (filter (complement (set vs)) extant)
new (filter (complement (set extant)) vs)]
(-> []
(into (map (fn [i] [:db/retract e a i ]) retracts))
(into (map (fn [i] [:db/add e a i]) new)))))

View File

@@ -0,0 +1,103 @@
(ns iol-ion.tx.upsert-entity
(:require [datomic.api :as dc])
(:import [java.util UUID]))
(defn -random-tempid []
(str (UUID/randomUUID)))
(defn -by
[f fv xs]
(reduce
#(assoc %1 (f %2) (fv %2))
{}
xs))
(defn -pull-many [db read ids ]
(->> (dc/q '[:find (pull ?e r)
:in $ [?e ...] r]
db
ids
read)
(map first)))
(defn upsert-entity [db entity]
(when-not (or (:db/id entity)
(:db/ident entity))
(datomic.api/cancel {:cognitect.anomalies/category :cognitect.anomalies/incorrect
:cognitect.anomalies/message
(str "Cannot upsert without :db/id or :db/ident, " entity)}))
[]
(let [e (or (:db/id entity) (:db/ident entity))
is-new? (string? e)
extant-entity (when-not is-new?
(dc/pull db (keys entity) (or (:db/id entity) (:db/ident entity))))
ident->value-type (-by :db/ident (comp :db/ident
:db/valueType)
(-pull-many
db
[{:db/valueType [:db/ident]} :db/ident]
(keys entity)))
ident->cardinality (-by :db/ident (comp :db/ident
:db/cardinality)
(-pull-many
db
[{:db/cardinality [:db/ident]} :db/ident]
(keys entity)))
ops (->> entity
(reduce
(fn [ops [a v]]
(cond
(= :db/id a)
ops
(= :db/ident a)
ops
(or (= v (a extant-entity))
(= v (:db/ident (a extant-entity) :nope))
(= v (:db/id (a extant-entity)) :nope))
ops
(and (nil? v)
(not (nil? (a extant-entity))))
(if (= :db.cardinality/many (ident->cardinality a))
(into ops (map (fn [v]
[:db/retract e a (cond-> v
(:db/id v) :db/id)])
(a extant-entity)))
(conj ops [:db/retract e a (cond-> (a extant-entity)
(:db/id (a extant-entity)) :db/id)]))
(nil? v)
ops
;; reset relationships if it's refs, and not a lookup (i.e., seq of maps, or empty seq)
(and (sequential? v) (= :db.type/tuple (ident->value-type a)))
(conj ops [:db/add e a v])
(and (sequential? v) (= :db.type/ref (ident->value-type a)) (every? map? v))
(into ops [[:reset-rels e a v]])
(= :db.cardinality/many (ident->cardinality a))
(into ops [[:reset-scalars e a v]])
(and (sequential? v) (not= :db.type/ref (ident->value-type a)))
(into ops [[:reset-scalars e a v]])
(and (map? v)
(= :db.type/ref (ident->value-type a)))
(let [id (or (:db/id v) (-random-tempid))]
(-> ops
(conj [:db/add e a id])
(into [[:upsert-entity (assoc v :db/id id)]])))
:else
(conj ops [:db/add e a v])
))
[]))]
ops))

View File

@@ -0,0 +1,81 @@
(ns iol-ion.tx.upsert-invoice
(:require [datomic.api :as dc]))
(defn -remove-nils [m]
(let [result (reduce-kv
(fn [m k v]
(if (not (nil? v))
(assoc m k v)
m
))
{}
m)]
(if (seq result)
result
nil)))
(defn invoice->journal-entry
[db invoice-id raw-invoice-id]
(let [entity (dc/pull db
'[:invoice/total
:invoice/exclude-from-ledger
:invoice/outstanding-balance
:invoice/date
{:invoice/vendor [:db/id :vendor/name]
:invoice/client [:db/id :client/code]
:invoice/payment [:db/id {:payment/status [:db/ident]}]
:invoice/status [:db/ident]
:invoice/import-status [:db/ident]
:invoice/expense-accounts [:invoice-expense-account/account
:invoice-expense-account/amount
:invoice-expense-account/location]}]
invoice-id)
credit-invoice? (< (:invoice/total entity 0.0) 0.0)]
(when-not (or
(not (:invoice/total entity))
(= true (:invoice/exclude-from-ledger entity))
(= :import-status/pending (:db/ident (:invoice/import-status entity)))
(= :invoice-status/voided (:db/ident (:invoice/status entity)))
(< -0.001 (:invoice/total entity) 0.001))
(-remove-nils
{:journal-entry/source "invoice"
:journal-entry/client (:db/id (:invoice/client entity))
:journal-entry/date (:invoice/date entity)
:journal-entry/original-entity raw-invoice-id
:journal-entry/vendor (:db/id (:invoice/vendor entity))
:journal-entry/amount (Math/abs (:invoice/total entity))
:journal-entry/line-items (into [(cond-> {:db/id (str raw-invoice-id "-" 0)
:journal-entry-line/account :account/accounts-payable
:journal-entry-line/location "A"
}
credit-invoice? (assoc :journal-entry-line/debit (Math/abs (:invoice/total entity)))
(not credit-invoice?) (assoc :journal-entry-line/credit (Math/abs (:invoice/total entity))))]
(map-indexed (fn [i ea]
(cond->
{:db/id (str raw-invoice-id "-" (inc i))
:journal-entry-line/account (:db/id (:invoice-expense-account/account ea))
:journal-entry-line/location (or (:invoice-expense-account/location ea) "HQ")
}
credit-invoice? (assoc :journal-entry-line/credit (Math/abs (:invoice-expense-account/amount ea)))
(not credit-invoice?) (assoc :journal-entry-line/debit (Math/abs (:invoice-expense-account/amount ea)))))
(:invoice/expense-accounts entity)))
:journal-entry/cleared (and (< (:invoice/outstanding-balance entity) 0.01)
(every? #(= :payment-status/cleared (:payment/status %)) (:invoice/payments entity))
)})))
)
(defn upsert-invoice [db invoice]
(let [upserted-entity [[:upsert-entity invoice]]
with-invoice (dc/with db upserted-entity)
invoice-id (or (-> with-invoice :tempids (get (:db/id invoice)))
(:db/id invoice))
journal-entry (invoice->journal-entry (:db-after with-invoice)
invoice-id
(:db/id invoice))]
(into upserted-entity
(if journal-entry
[[:upsert-ledger journal-entry]]
[[:db/retractEntity [:journal-entry/original-entity (:db/id invoice)]]]))))

View File

@@ -0,0 +1,71 @@
(ns iol-ion.tx.upsert-ledger
(:import [java.util UUID])
(:require [datomic.api :as dc]))
(defn -random-tempid []
(str (UUID/randomUUID)))
(defn get-line-items-after [db journal-entry]
(for [jel (:journal-entry/line-items journal-entry)
:let [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)]
:limit 3
})
(filter (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)))
))
first
:db/id)]
:when next-jel]
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 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) "Must at least provide date when updating ledger")
(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])))
extant-entry-exists? (:db/id extant-entry)]
(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/dirty true)
(assoc :journal-entry-line/client+account+location+date
(calc-client+account+location+date ledger-entry %)))
lis))))
)]]
extant-entry-exists? (into (map (fn [li]
{:journal-entry-line/dirty true
:db/id li})
(get-line-items-after db extant-entry))))))

View File

@@ -0,0 +1,86 @@
(ns iol-ion.tx.upsert-transaction
(:require [datomic.api :as dc]))
(defn -remove-nils [m]
(let [result (reduce-kv
(fn [m k v]
(if (not (nil? v))
(assoc m k v)
m
))
{}
m)]
(if (seq result)
result
nil)))
(defn transaction->journal-entry
[db transaction-id raw-transaction-id]
(let [entity (dc/pull db [:transaction/client
:transaction/date
:transaction/description-original
:db/id
:transaction/vendor
:transaction/amount
:transaction/cleared-against
{:transaction/accounts [:transaction-account/account
:transaction-account/location
:transaction-account/amount]
:transaction/approval-status [:db/ident]
:transaction/bank-account [:db/id {:bank-account/type [:db/ident]}]}]
transaction-id)
decreasing? (< (or (:transaction/amount entity) 0.0) 0.0)
credit-from-bank? decreasing?
debit-from-bank? (not decreasing?)]
(when (and (not (= :transaction-approval-status/excluded (:db/ident (:transaction/approval-status entity))))
(not (= :transaction-approval-status/suppressed (:db/ident (:transaction/approval-status entity))))
(:transaction/amount entity)
(not (< -0.001 (:transaction/amount entity) 0.001)))
(-remove-nils
{:journal-entry/source "transaction"
:journal-entry/client (:db/id (:transaction/client entity))
:journal-entry/date (:transaction/date entity)
:journal-entry/original-entity raw-transaction-id
:journal-entry/alternate-description (:transaction/description-original entity)
:journal-entry/vendor (:db/id (:transaction/vendor entity))
:journal-entry/amount (Math/abs (:transaction/amount entity))
:journal-entry/cleared-against (:transaction/cleared-against entity)
:journal-entry/line-items (into [(-remove-nils {:journal-entry-line/account (:db/id (:transaction/bank-account entity))
:db/id (str raw-transaction-id "-" 0)
:journal-entry-line/location "A"
:journal-entry-line/credit (when credit-from-bank?
(Math/abs (:transaction/amount entity)))
:journal-entry-line/debit (when debit-from-bank?
(Math/abs (:transaction/amount entity)))})
]
(map-indexed
(fn [i a]
(-remove-nils{
:db/id (str raw-transaction-id "-" (inc i))
:journal-entry-line/account (:db/id (:transaction-account/account a))
:journal-entry-line/location (:transaction-account/location a)
:journal-entry-line/debit (when credit-from-bank?
(Math/abs (:transaction-account/amount a)))
:journal-entry-line/credit (when debit-from-bank?
(Math/abs (:transaction-account/amount a)))}))
(if (seq (:transaction/accounts entity))
(:transaction/accounts entity)
[{:transaction-account/amount (:transaction/amount entity)}])))
:journal-entry/cleared true}))))
(defn upsert-transaction [db transaction]
;; because some transactions will reference temp ids, you have to dissoc them, like :transaction/payment
(let [upserted-entity [[:upsert-entity (dissoc transaction :transaction/payment :import-batch/_entry)]]
with-transaction (dc/with db upserted-entity)
transaction-id (or (-> with-transaction :tempids (get (:db/id transaction)))
(:db/id transaction))
journal-entry (transaction->journal-entry (:db-after with-transaction)
transaction-id
(:db/id transaction))]
(into [[:upsert-entity transaction]]
(if journal-entry
[[:upsert-ledger journal-entry]]
[[:db/retractEntity [:journal-entry/original-entity (:db/id transaction)]]]))))

View File

@@ -0,0 +1,36 @@
(ns iol-ion.utils
(:require [datomic.api :as dc])
(:import [java.util UUID]))
(defn random-tempid []
(str (UUID/randomUUID)))
(defn by
([f xs]
(by f identity xs))
([f fv xs]
(reduce
#(assoc %1 (f %2) (fv %2))
{}
xs)))
(defn pull-many [db read ids ]
(->> (dc/q '[:find (pull ?e r)
:in $ [?e ...] r]
db
ids
read)
(map first)))
(defn remove-nils [m]
(let [result (reduce-kv
(fn [m k v]
(if (not (nil? v))
(assoc m k v)
m
))
{}
m)]
(if (seq result)
result
nil)))

View File

@@ -2,17 +2,13 @@
:description "FIXME: write description"
:url "http://example.com/FIXME"
:min-lein-version "2.0.0"
:repositories {"my.datomic.com" {:url "https://my.datomic.com/repo"
:username "datomic@brycecovertoperations.com"
:password "9a382afc-d119-44db-83c2-98d8057d7666"}}
:dependencies [[com.google.guava/guava "31.1-jre"]
[org.clojure/clojure "1.10.1"]
[com.unbounce/clojure-dogstatsd-client "0.7.0"]
[org.clojure/tools.reader "1.3.6"]
[com.cognitect/hmac-authn "0.1.210"]
[com.datomic/client-cloud "1.0.123"]
[com.cognitect/http-client "1.0.115"]
[com.github.ivarref/gen-fn "0.2.46"]
[com.datomic/peer "1.0.6726"]
[lambdaisland/edn-lines "1.0.10"]
[bidi "2.1.6"]
[ring/ring-defaults "0.3.2" :exclusions [ring ring/ring-core]]
@@ -131,7 +127,7 @@
:dependencies [#_[binaryage/devteols "1.0.2"]
[postgresql/postgresql "9.3-1102.jdbc41"]
[org.clojure/java.jdbc "0.7.11"]
[com.datomic/dev-local "1.0.243"]
#_[com.datomic/dev-local "1.0.243"]
[etaoin "0.4.1"]
[com.bhauman/figwheel-main "0.2.18" :exclusions [org.clojure/clojurescript
ring

View File

@@ -12,6 +12,7 @@
}
{:db/valueType :db.type/tuple
:db/tupleTypes [:db.type/ref :db.type/ref :db.type/string :db.type/instant]
:db/index true
:db/cardinality :db.cardinality/one,
:db/ident :journal-entry-line/client+account+location+date
:db/doc "Used to find accounts and locations quickly",
@@ -20,6 +21,7 @@
{:db/valueType :db.type/tuple
:db/tupleAttrs [:sales-order/client :sales-order/date]
:db/index true
:db/cardinality :db.cardinality/one,
:db/ident :sales-order/client+date
:db/doc "Used to find sales orders quickly",

View File

@@ -1,10 +1,20 @@
(ns auto-ap.datomic
(:require
[iol-ion.tx.pay]
[iol-ion.tx.plus]
[iol-ion.tx.propose-invoice]
[iol-ion.tx.reset-rels]
[iol-ion.tx.reset-scalars]
[iol-ion.tx.upsert-entity]
[iol-ion.tx.upsert-invoice]
[iol-ion.tx.upsert-ledger]
[iol-ion.tx.upsert-transaction]
[com.github.ivarref.gen-fn :refer [gen-fn! datomic-fn]]
[auto-ap.utils :refer [default-pagination-size by]]
[clojure.tools.logging :as log]
[clojure.edn :as edn]
[config.core :refer [env]]
[datomic.client.api :as dc]
[datomic.api :as dc]
[com.brunobonacci.mulog :as mu]
[mount.core :as mount]
[clojure.java.io :as io])
@@ -13,12 +23,12 @@
(def uri (:datomic-url env))
(mount/defstate client
#_(mount/defstate client
:start (dc/client (:client-config env))
:stop nil)
(mount/defstate conn
:start (dc/connect client {:db-name (:db-name env)})
:start (dc/connect "datomic:ddb://us-east-1/iol-dev/dev")
:stop nil)
#_(def uri "datomic:mem://datomic-transactor:4334/invoice")
@@ -627,7 +637,7 @@
_ (mu/log ::transacting-batch
:batch batch-id
:count (count batch))
tx-result (dc/transact conn {:tx-data batch})]
tx-result @(dc/transact conn batch)]
(cond-> full-tx
(:tx-data full-tx) (update :tx-data #(into % (:tx-data tx-result)))
@@ -641,8 +651,8 @@
(defn audit-transact [txes id]
(try
(dc/transact conn {:tx-data (conj txes {:db/id "datomic.tx"
:audit/user (str (:user/role id) "-" (:user/name id))})})
@(dc/transact conn (conj txes {:db/id "datomic.tx"
:audit/user (str (:user/role id) "-" (:user/name id))}))
(catch Exception e
(mu/log ::transaction-error
:exception e
@@ -821,15 +831,24 @@
)
(defn install-functions []
@(datomic.api/transact auto-ap.datomic/conn [(datomic-fn :pay #'iol-ion.tx.pay/pay)
(datomic-fn :plus #'iol-ion.tx.plus/plus)
(datomic-fn :propose-invoice #'iol-ion.tx.propose-invoice/propose-invoice)
(datomic-fn :reset-rels #'iol-ion.tx.reset-rels/reset-rels)
(datomic-fn :reset-scalars #'iol-ion.tx.reset-scalars/reset-scalars)
(datomic-fn :upsert-entity #'iol-ion.tx.upsert-entity/upsert-entity)
(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)]))
(defn transact-schema [conn]
(dc/transact conn
{:tx-data (edn/read-string (slurp (io/resource "schema.edn")))})
@(dc/transact conn
(edn/read-string (slurp (io/resource "schema.edn"))))
;; this is temporary for any new stuff that needs to be asserted for cloud migration.
(dc/transact conn
{:tx-data (edn/read-string (slurp (io/resource "cloud-migration-schema.edn")))}))
@(dc/transact conn
(edn/read-string (slurp (io/resource "cloud-migration-schema.edn")))))
(defn backoff [n]
(let [base-timeout 500
@@ -842,7 +861,7 @@
([tx ] (transact-with-backoff tx 0))
([tx attempt]
(try
(dc/transact conn {:tx-data tx})
@(dc/transact conn tx)
(catch Exception e
(if (< attempt 10)
(do
@@ -870,3 +889,8 @@
(#{"manager" "user" "power-user"} (:user/role id))
(into #{}
(map :db/id (:user/clients id [])))))
(defn query2 [query]
(apply dc/q (:query query) (:args query)))

View File

@@ -1,10 +1,16 @@
(ns auto-ap.datomic.accounts
(:require
[auto-ap.datomic
:refer [add-sorter-fields apply-pagination apply-sort-3 conn merge-query conn pull-many]]
:refer [add-sorter-fields
apply-pagination
apply-sort-3
conn
merge-query
pull-many
query2]]
[clojure.string :as str]
[datomic.client.api :as dc]
[clojure.tools.logging :as log]))
[clojure.tools.logging :as log]
[datomic.api :as dc]))
(defn <-datomic [a]
(-> a
@@ -42,19 +48,19 @@
:where [['?e :account/account-set '?account-set]]}
:args [(:account-set args)]}))]
(->>
(dc/q query)
(query2 query)
(map first)
(map <-datomic)))))
(defn get-by-id [id]
(let [query {:query {:find [(list 'pull '?e default-read)]
:in ['$ '?e]}
:args [(dc/db conn ) id]}]
(->>
(dc/q query)
(map first)
(map <-datomic)
first)))
(->>
(dc/q {:find [(list 'pull '?e default-read)]
:in ['$ '?e]}
(dc/db conn )
id)
(map first)
(map <-datomic)
first))
(defn get-for-vendor [vendor-id client-id]
(if client-id
@@ -87,15 +93,14 @@
default-read))))
(defn get-account-by-numeric-code-and-sets [numeric-code _]
(let [query (cond-> {:query {:find ['(pull ?e [* {:account/type [:db/ident :db/id]}])]
:in ['$ '?numeric-code]
:where ['[?e :account/numeric-code ?numeric-code]]}
:args [(dc/db conn) numeric-code]})]
(->>
(dc/q query)
(map first)
(map <-datomic)
(first))))
(->>
(dc/q {:find ['(pull ?e [* {:account/type [:db/ident :db/id]}])]
:in ['$ '?numeric-code]
:where ['[?e :account/numeric-code ?numeric-code]]}
(dc/db conn) numeric-code)
(map first)
(map <-datomic)
(first)))
(defn raw-graphql-ids [db args]
(let [query (cond-> {:query {:find []
@@ -122,8 +127,7 @@
'[?e :account/numeric-code ?sort-default]]}}))]
(cond->> query
true (dc/q)
(cond->> (query2 query)
true (apply-sort-3 args)
true (apply-pagination args))))

View File

@@ -1,7 +1,7 @@
(ns auto-ap.datomic.bank-accounts
(:require
[auto-ap.datomic :refer [conn]]
[datomic.client.api :as dc]))
[datomic.api :as dc]))
(defn add-arg [query name value where & rest]
(let [query (-> query
@@ -20,15 +20,9 @@
(defn get-by-id [id]
(->>
(dc/q (-> {:query {:find [default-read]
:in ['$]
:where []}
:args [(dc/db conn)]}
(add-arg '?e id ['?e])))
(map first)
(<-datomic)
(first)))
(->> [(dc/pull (dc/db conn default-read id))]
(<-datomic)
(first)))

View File

@@ -6,12 +6,13 @@
apply-sort-3
conn
merge-query
pull-many]]
pull-many
query2]]
[auto-ap.graphql.utils :refer [limited-clients]]
[clj-time.coerce :as c]
[datomic.client.api :as dc]
[clojure.set :refer [rename-keys]]
[clojure.tools.logging :as log]))
[clojure.tools.logging :as log]
[datomic.api :as dc]))
(defn <-datomic [result]
(-> result
@@ -154,8 +155,7 @@
(log/info query)
(cond->> query
true (dc/q)
(cond->> (query2 query)
true (apply-sort-3 (assoc args :default-asc? false))
true (apply-pagination args)))))
@@ -178,11 +178,10 @@
(defn filter-ids [ids]
(if ids
(->> {:query {:find ['?e]
:in ['$ '[?e ...]]
:where ['[?e :payment/date]]}
:args [(dc/db conn) ids]}
(dc/q)
(->> (dc/q {:find ['?e]
:in ['$ '[?e ...]]
:where ['[?e :payment/date]]}
(dc/db conn) ids)
(map first)
vec)
[]))

View File

@@ -1,17 +1,19 @@
(ns auto-ap.datomic.clients
(:require
[auto-ap.datomic :refer [add-sorter-fields
apply-pagination
apply-sort-3
conn
merge-query
pull-many]]
[auto-ap.graphql.utils :refer [can-see-client? limited-clients]]
[auto-ap.datomic
:refer [add-sorter-fields
apply-pagination
apply-sort-3
conn
merge-query
pull-many
query2]]
[auto-ap.graphql.utils :refer [limited-clients]]
[auto-ap.search :as search]
[clj-time.coerce :as coerce]
[clojure.string :as str]
[datomic.client.api :as dc]
[com.brunobonacci.mulog :as mu]))
[com.brunobonacci.mulog :as mu]
[datomic.api :as dc]))
(def full-read '[*
{:client/square-integration-status [:integration-status/message
@@ -97,10 +99,10 @@
(defn code->id [code]
(->>
(dc/q (-> {:query {:find ['?e]
:in ['$ '?code]
:where [['?e :client/code '?code ]]}
:args [(dc/db conn) code]}))
(dc/q (-> {:find ['?e]
:in ['$ '?code]
:where [['?e :client/code '?code ]]}
(dc/db conn) code))
(first)
(first)))
@@ -155,8 +157,7 @@
(merge-query {:query {:find ['?sort-default '?e] :where ['[?e :client/name ?sort-default]]}}))]
(mu/log ::q
:query query)
(->> query
(dc/q)
(->> (query2 query)
(apply-sort-3 (update args :sort conj {:sort-key "default-2" :asc true}))
(apply-pagination args))))

View File

@@ -1,10 +1,16 @@
(ns auto-ap.datomic.expected-deposit
(:require
[auto-ap.datomic
:refer [add-sorter-fields apply-pagination apply-sort-3 conn merge-query pull-many]]
:refer [add-sorter-fields
apply-pagination
apply-sort-3
conn
merge-query
pull-many
query2]]
[auto-ap.graphql.utils :refer [limited-clients]]
[clj-time.coerce :as c]
[datomic.client.api :as dc]))
[datomic.api :as dc]))
(defn <-datomic [result]
(let [transaction (first (:transaction/_expected-deposit result))
@@ -87,8 +93,7 @@
(merge-query {:query {:find ['?sort-default '?e]
:where ['[?e :expected-deposit/date ?sort-default]]}}))]
(cond->> query
true (dc/q)
(cond->> (query2 query)
true (apply-sort-3 args)
true (apply-pagination args))))

View File

@@ -3,6 +3,7 @@
[auto-ap.datomic
:refer [add-sorter-fields
apply-pagination
query2
apply-sort-3
conn
merge-query
@@ -14,7 +15,7 @@
[clj-time.coerce :as coerce]
[clj-time.core :as time]
[clojure.set :refer [rename-keys]]
[datomic.client.api :as dc]
[datomic.api :as dc]
[iol-ion.tx :refer [random-tempid]]))
(def default-read '[*
@@ -45,134 +46,134 @@
([args]
(raw-graphql-ids (dc/db conn) args))
([db args]
(->> (cond-> {:query {:find []
:in ['$]
:where ['[?e :invoice/client]]}
:args [db]}
(let [query (cond-> {:query {:find []
:in ['$]
:where ['[?e :invoice/client]]}
:args [db]}
(:exact-match-id args)
(merge-query {:query {:in ['?e]
:where []}
:args [(:exact-match-id args)]})
(limited-clients (:id args))
(merge-query {:query {:in ['[?xx ...]]
:where ['[?e :invoice/client ?xx]]}
:args [ (set (map :db/id (limited-clients (:id args))))]})
(:client-id args)
(merge-query {:query {:in ['?client-id]
:where ['[?e :invoice/client ?client-id]]}
:args [ (:client-id args)]})
(:exact-match-id args)
(merge-query {:query {:in ['?e]
:where []}
:args [(:exact-match-id args)]})
(limited-clients (:id args))
(merge-query {:query {:in ['[?xx ...]]
:where ['[?e :invoice/client ?xx]]}
:args [ (set (map :db/id (limited-clients (:id args))))]})
(:client-id args)
(merge-query {:query {:in ['?client-id]
:where ['[?e :invoice/client ?client-id]]}
:args [ (:client-id args)]})
(:client-code args)
(merge-query {:query {:in ['?client-code]
:where ['[?e :invoice/client ?client-id]
'[?client-id :client/code ?client-code]]}
:args [ (:client-code args)]})
(:client-code args)
(merge-query {:query {:in ['?client-code]
:where ['[?e :invoice/client ?client-id]
'[?client-id :client/code ?client-code]]}
:args [ (:client-code args)]})
(:original-id args)
(merge-query {:query {:in ['?original-id]
:where [
'[?e :invoice/client ?c]
'[?c :client/original-id ?original-id]]}
:args [ (cond-> (:original-id args)
(string? (:original-id args)) Long/parseLong )]})
(:original-id args)
(merge-query {:query {:in ['?original-id]
:where [
'[?e :invoice/client ?c]
'[?c :client/original-id ?original-id]]}
:args [ (cond-> (:original-id args)
(string? (:original-id args)) Long/parseLong )]})
(:start (:date-range args)) (merge-query {:query {:in '[?start-date]
:where ['[?e :invoice/date ?date]
'[(>= ?date ?start-date)]]}
:args [(coerce/to-date (:start (:date-range args)))]})
(:start (:date-range args)) (merge-query {:query {:in '[?start-date]
:where ['[?e :invoice/date ?date]
'[(>= ?date ?start-date)]]}
:args [(coerce/to-date (:start (:date-range args)))]})
(:end (:date-range args)) (merge-query {:query {:in '[?end-date]
:where ['[?e :invoice/date ?date]
'[(<= ?date ?end-date)]]}
:args [(coerce/to-date (:end (:date-range args)))]})
(:end (:date-range args)) (merge-query {:query {:in '[?end-date]
:where ['[?e :invoice/date ?date]
'[(<= ?date ?end-date)]]}
:args [(coerce/to-date (:end (:date-range args)))]})
(:start (:due-range args)) (merge-query {:query {:in '[?start-due]
:where ['[?e :invoice/due ?due]
'[(>= ?due ?start-due)]]}
:args [(coerce/to-date (:start (:due-range args)))]})
(:start (:due-range args)) (merge-query {:query {:in '[?start-due]
:where ['[?e :invoice/due ?due]
'[(>= ?due ?start-due)]]}
:args [(coerce/to-date (:start (:due-range args)))]})
(:end (:due-range args)) (merge-query {:query {:in '[?end-due]
:where ['[?e :invoice/due ?due]
'[(<= ?due ?end-due)]]}
:args [(coerce/to-date (:end (:due-range args)))]})
(:end (:due-range args)) (merge-query {:query {:in '[?end-due]
:where ['[?e :invoice/due ?due]
'[(<= ?due ?end-due)]]}
:args [(coerce/to-date (:end (:due-range args)))]})
(:import-status args)
(merge-query {:query {:in ['?import-status]
:where ['[?e :invoice/import-status ?import-status]]}
:args [ (keyword "import-status" (:import-status args))]})
(:status args)
(merge-query {:query {:in ['?status]
:where ['[?e :invoice/status ?status]]}
:args [ (:status args)]})
(:vendor-id args)
(merge-query {:query {:in ['?vendor-id]
:where ['[?e :invoice/vendor ?vendor-id]]}
:args [ (:vendor-id args)]})
(:import-status args)
(merge-query {:query {:in ['?import-status]
:where ['[?e :invoice/import-status ?import-status]]}
:args [ (keyword "import-status" (:import-status args))]})
(:status args)
(merge-query {:query {:in ['?status]
:where ['[?e :invoice/status ?status]]}
:args [ (:status args)]})
(:vendor-id args)
(merge-query {:query {:in ['?vendor-id]
:where ['[?e :invoice/vendor ?vendor-id]]}
:args [ (:vendor-id args)]})
(:account-id args)
(merge-query {:query {:in ['?account-id]
:where ['[?e :invoice/expense-accounts ?iea ?]
'[?iea :invoice-expense-account/account ?account-id]]}
:args [ (:account-id args)]})
(:account-id args)
(merge-query {:query {:in ['?account-id]
:where ['[?e :invoice/expense-accounts ?iea ?]
'[?iea :invoice-expense-account/account ?account-id]]}
:args [ (:account-id args)]})
(:amount-gte args)
(merge-query {:query {:in ['?amount-gte]
:where ['[?e :invoice/total ?total-filter]
'[(>= ?total-filter ?amount-gte)]]}
:args [(:amount-gte args)]})
(:amount-gte args)
(merge-query {:query {:in ['?amount-gte]
:where ['[?e :invoice/total ?total-filter]
'[(>= ?total-filter ?amount-gte)]]}
:args [(:amount-gte args)]})
(:amount-lte args)
(merge-query {:query {:in ['?amount-lte]
:where ['[?e :invoice/total ?total-filter]
'[(<= ?total-filter ?amount-lte)]]}
:args [(:amount-lte args)]})
(:amount-lte args)
(merge-query {:query {:in ['?amount-lte]
:where ['[?e :invoice/total ?total-filter]
'[(<= ?total-filter ?amount-lte)]]}
:args [(:amount-lte args)]})
(seq (:invoice-number-like args))
(merge-query {:query {:in ['?invoice-number-like]
:where ['[?e :invoice/invoice-number ?invoice-number]
'[(.contains ^String ?invoice-number ?invoice-number-like)]]}
:args [(:invoice-number-like args)]})
(seq (:invoice-number-like args))
(merge-query {:query {:in ['?invoice-number-like]
:where ['[?e :invoice/invoice-number ?invoice-number]
'[(.contains ^String ?invoice-number ?invoice-number-like)]]}
:args [(:invoice-number-like args)]})
(:scheduled-payments args)
(merge-query {:query {:in []
:where ['[?e :invoice/scheduled-payment]]}
:args []})
(:scheduled-payments args)
(merge-query {:query {:in []
:where ['[?e :invoice/scheduled-payment]]}
:args []})
(:unresolved args)
(merge-query {:query {:in []
:where ['(or-join [?e]
(not [?e :invoice/expense-accounts ])
(and [?e :invoice/expense-accounts ?ea]
(not [?ea :invoice-expense-account/account])))]}
:args []})
(:unresolved args)
(merge-query {:query {:in []
:where ['(or-join [?e]
(not [?e :invoice/expense-accounts ])
(and [?e :invoice/expense-accounts ?ea]
(not [?ea :invoice-expense-account/account])))]}
:args []})
(seq (:location args))
(merge-query {:query {:in ['?location]
:where ['[?e :invoice/expense-accounts ?eas]
'[?eas :invoice-expense-account/location ?location]]}
:args [(:location args)]})
(seq (:location args))
(merge-query {:query {:in ['?location]
:where ['[?e :invoice/expense-accounts ?eas]
'[?eas :invoice-expense-account/location ?location]]}
:args [(:location args)]})
(:sort args) (add-sorter-fields {"client" ['[?e :invoice/client ?c]
'[?c :client/name ?sort-client]]
"vendor" ['[?e :invoice/vendor ?v]
'[?v :vendor/name ?sort-vendor]]
"description-original" ['[?e :transaction/description-original ?sort-description-original]]
"location" ['[?e :invoice/expense-accounts ?iea]
'[?iea :invoice-expense-account/location ?sort-location]]
"date" ['[?e :invoice/date ?sort-date]]
"due" ['[(get-else $ ?e :invoice/due #inst "2050-01-01") ?sort-due]]
"invoice-number" ['[?e :invoice/invoice-number ?sort-invoice-number]]
"total" ['[?e :invoice/total ?sort-total]]
"outstanding-balance" ['[?e :invoice/outstanding-balance ?sort-outstanding-balance]]}
args)
true
(merge-query {:query {:find ['?sort-default '?e ]
:where ['[?e :invoice/client]
'[?e :invoice/date ?sort-default]]}}) )
(dc/q)
(apply-sort-3 args)
(apply-pagination args))))
(:sort args) (add-sorter-fields {"client" ['[?e :invoice/client ?c]
'[?c :client/name ?sort-client]]
"vendor" ['[?e :invoice/vendor ?v]
'[?v :vendor/name ?sort-vendor]]
"description-original" ['[?e :transaction/description-original ?sort-description-original]]
"location" ['[?e :invoice/expense-accounts ?iea]
'[?iea :invoice-expense-account/location ?sort-location]]
"date" ['[?e :invoice/date ?sort-date]]
"due" ['[(get-else $ ?e :invoice/due #inst "2050-01-01") ?sort-due]]
"invoice-number" ['[?e :invoice/invoice-number ?sort-invoice-number]]
"total" ['[?e :invoice/total ?sort-total]]
"outstanding-balance" ['[?e :invoice/outstanding-balance ?sort-outstanding-balance]]}
args)
true
(merge-query {:query {:find ['?sort-default '?e ]
:where ['[?e :invoice/client]
'[?e :invoice/date ?sort-default]]}}) )]
(->> (query2 query)
(apply-sort-3 args)
(apply-pagination args)))))
(defn graphql-results [ids db _]
@@ -188,12 +189,11 @@
(defn sum-outstanding [ids]
(->>
(dc/q {:query {:find ['?id '?o]
:in ['$ '[?id ...]]
:where ['[?id :invoice/outstanding-balance ?o]]
}
:args [(dc/db conn)
ids]})
(dc/q {:find ['?id '?o]
:in ['$ '[?id ...]]
:where ['[?id :invoice/outstanding-balance ?o]]}
(dc/db conn)
ids)
(map last)
(reduce
+
@@ -202,12 +202,12 @@
(defn sum-total-amount [ids]
(->>
(dc/q {:query {:find ['?id '?o]
:in ['$ '[?id ...]]
:where ['[?id :invoice/total ?o]]
}
:args [(dc/db conn)
ids]})
(dc/q {:find ['?id '?o]
:in ['$ '[?id ...]]
:where ['[?id :invoice/total ?o]]
}
(dc/db conn)
ids)
(map last)
(reduce
+
@@ -240,38 +240,35 @@
(defn find-conflicting [{:keys [:invoice/invoice-number :invoice/vendor :invoice/client :db/id]}]
(->> (dc/q
(cond-> {:query {:find [(list 'pull '?e default-read)]
:in ['$ '?invoice-number '?vendor '?client '?invoice-id]
:where '[[?e :invoice/invoice-number ?invoice-number]
[?e :invoice/vendor ?vendor]
[?e :invoice/client ?client]
(not [?e :invoice/status :invoice-status/voided])
[(not= ?e ?invoice-id)]]}
:args [(dc/db conn) invoice-number vendor client (or id 0)]}))
{:find [(list 'pull '?e default-read)]
:in ['$ '?invoice-number '?vendor '?client '?invoice-id]
:where '[[?e :invoice/invoice-number ?invoice-number]
[?e :invoice/vendor ?vendor]
[?e :invoice/client ?client]
(not [?e :invoice/status :invoice-status/voided])
[(not= ?e ?invoice-id)]]}
(dc/db conn) invoice-number vendor client (or id 0))
(map first)
(map <-datomic)))
(defn get-existing-set []
(let [vendored-results (set (dc/q {:query {:find ['?vendor '?client '?invoice-number]
:in ['$]
:where '[[?e :invoice/invoice-number ?invoice-number]
[?e :invoice/vendor ?vendor]
[?e :invoice/client ?client]
(not [?e :invoice/status :invoice-status/voided])
]}
:args [(dc/db conn)]}))
vendorless-results (->> (dc/q {:query {:find ['?client '?invoice-number]
:in ['$]
:where '[[?e :invoice/invoice-number ?invoice-number]
(not [?e :invoice/vendor])
[?e :invoice/client ?client]
(not [?e :invoice/status :invoice-status/voided])
]}
:args [(dc/db conn)]})
(let [vendored-results (set (dc/q {:find ['?vendor '?client '?invoice-number]
:in ['$]
:where '[[?e :invoice/invoice-number ?invoice-number]
[?e :invoice/vendor ?vendor]
[?e :invoice/client ?client]
(not [?e :invoice/status :invoice-status/voided])
]}
(dc/db conn)))
vendorless-results (->> (dc/q {:find ['?client '?invoice-number]
:in ['$]
:where '[[?e :invoice/invoice-number ?invoice-number]
(not [?e :invoice/vendor])
[?e :invoice/client ?client]
(not [?e :invoice/status :invoice-status/voided])
]}
(dc/db conn))
(mapv (fn [[client invoice-number]]
[nil client invoice-number]) )
set)]
@@ -279,13 +276,13 @@
(defn filter-ids [ids]
(if ids
(->> {:query {:find ['?e]
:in ['$ '[?e ...]]
:where ['[?e :invoice/date]]}
:args [(dc/db conn) ids]}
(dc/q)
(map first)
vec)
(->>
(dc/q {:find ['?e]
:in ['$ '[?e ...]]
:where ['[?e :invoice/date]]}
(dc/db conn) ids)
(map first)
vec)
[]))
(defn code-invoice [invoice]

View File

@@ -6,11 +6,12 @@
apply-sort-3
conn
merge-query
pull-many]]
pull-many
query2]]
[auto-ap.datomic.accounts :as d-accounts]
[auto-ap.graphql.utils :refer [limited-clients]]
[clj-time.coerce :as c]
[datomic.client.api :as dc]))
[datomic.api :as dc]))
(defn raw-graphql-ids [db args]
(let [query (cond-> {:query {:find []
@@ -126,8 +127,7 @@
true
(merge-query {:query {:find ['?sort-default '?e] :where ['[?e :journal-entry/date ?sort-default]]}}))]
(->> query
(dc/q)
(->> (query2 query)
(apply-sort-3 (update args :sort conj {:sort-key "default-2" :asc true}))
(apply-pagination args))))
@@ -168,11 +168,10 @@
(defn filter-ids [ids]
(if ids
(->> {:query {:find ['?e]
:in ['$ '[?e ...]]
:where ['[?e :journal-entry/date]]}
:args [(dc/db conn) ids]}
(dc/q)
(->> (dc/q {:find ['?e]
:in ['$ '[?e ...]]
:where ['[?e :journal-entry/date]]}
(dc/db conn) ids)
(map first)
vec)
[]))

View File

@@ -6,10 +6,11 @@
apply-sort-3
conn
merge-query
pull-many]]
pull-many
query2]]
[auto-ap.graphql.utils :refer [can-see-client? limited-clients]]
[clj-time.coerce :as c]
[datomic.client.api :as dc]))
[datomic.api :as dc]))
(defn raw-graphql-ids [db args]
(let [query (cond-> {:query {:find []
@@ -37,8 +38,7 @@
true
(merge-query {:query {:find ['?sort-default '?e] :where ['[?e :report/created ?sort-default]]}}))]
(->> query
(dc/q)
(->> (query2 query)
(apply-sort-3 (update args :sort conj {:sort-key "default-2" :asc true}))
(apply-pagination args))))

View File

@@ -4,18 +4,18 @@
:refer [add-sorter-fields-2
apply-pagination
apply-sort-3
pull-id
conn
merge-query
pull-id
pull-many
visible-clients
conn]]
[iol-ion.query]
query2
visible-clients]]
[clj-time.coerce :as c]
[clj-time.core :as time]
[clojure.set :as set]
[datomic.client.api :as dc]
[com.brunobonacci.mulog :as mu]
))
[datomic.api :as dc]
[iol-ion.query]))
(defn <-datomic [result]
(-> result
@@ -115,8 +115,7 @@
:stats (:query-stats (dc/q (assoc query :query-stats true)))
:q (str query))
(cond->> query
true (dc/q)
(cond->> (query2 query)
true (apply-sort-3 (assoc args :default-asc? false))
true (apply-pagination args))))
@@ -132,14 +131,14 @@
(defn summarize-orders [ids]
(let [[total tax] (->>
(dc/q {:query {:find ['(sum ?t) '(sum ?tax)]
:with ['?id]
:in ['$ '[?id ...]]
:where ['[?id :sales-order/total ?t]
'[?id :sales-order/tax ?tax]]}
:args [(dc/db conn)
ids]})
first)]
(dc/q {:find ['(sum ?t) '(sum ?tax)]
:with ['?id]
:in ['$ '[?id ...]]
:where ['[?id :sales-order/total ?t]
'[?id :sales-order/tax ?tax]]}
(dc/db conn)
ids)
first)]
{:total total
:tax tax}))

View File

@@ -6,10 +6,11 @@
apply-sort-3
conn
merge-query
pull-many]]
pull-many
query2]]
[auto-ap.graphql.utils :refer [limited-clients]]
[clojure.string :as str]
[datomic.client.api :as dc]))
[datomic.api :as dc]))
(defn <-datomic [result]
result)
@@ -82,8 +83,7 @@
:where ['[?e :transaction-rule/transaction-approval-status]]}}))]
(cond->> query
true (dc/q)
(cond->> (query2 query)
true (apply-sort-3 args)
true (apply-pagination args))))
@@ -109,10 +109,10 @@
(defn get-all []
(mapv first
(dc/q {:query {:find [(list 'pull '?e default-read )]
:in ['$]
:where ['[?e :transaction-rule/transaction-approval-status]]}
:args [(dc/db conn)]})))
(dc/q {:find [(list 'pull '?e default-read )]
:in ['$]
:where ['[?e :transaction-rule/transaction-approval-status]]}
(dc/db conn))))
(defn get-all-for-client [client-id]
(mapv first

View File

@@ -1,13 +1,19 @@
(ns auto-ap.datomic.transactions
(:require
[auto-ap.datomic
:refer [add-sorter-fields apply-pagination apply-sort-3 conn merge-query conn pull-many]]
:refer [add-sorter-fields
apply-pagination
apply-sort-3
conn
merge-query
pull-many
query2]]
[auto-ap.datomic.accounts :as d-accounts]
[auto-ap.graphql.utils :refer [limited-clients]]
[clj-time.coerce :as coerce]
[clojure.string :as str]
[clojure.tools.logging :as log]
[datomic.client.api :as dc]))
[datomic.api :as dc]))
(defn potential-duplicate-ids [db args]
(when (and (:potential-duplicates args)
@@ -168,8 +174,7 @@
'[?e :transaction/date ?sort-default]
'(not [?e :transaction/approval-status :transaction-approval-status/suppressed])]}}))]
(log/info "query is" query)
(cond->> query
true (dc/q)
(cond->> (query2 query)
true (apply-sort-3 (assoc args :default-asc? false))
true (apply-pagination args)))))
@@ -220,11 +225,10 @@
(defn filter-ids [ids]
(if ids
(->> {:query {:find ['?e]
:in ['$ '[?e ...]]
:where ['[?e :transaction/date]]}
:args [(dc/db conn) ids]}
(dc/q)
(->> (dc/q {:find ['?e]
:in ['$ '[?e ...]]
:where ['[?e :transaction/date]]}
(dc/db conn) ids)
(map first)
vec)
[]))

View File

@@ -1,7 +1,7 @@
(ns auto-ap.datomic.users
(:require
[auto-ap.datomic :refer [conn]]
[datomic.client.api :as dc]))
[datomic.api :as dc]))
(defn add-arg [query name value where & rest]
(let [query (-> query
@@ -11,53 +11,46 @@
(reduce #(update-in %1 [:query :where] conj %2) query rest)))
(defn get-by-id [id]
(let [query (-> {:query {:find ['(pull ?e [*
{:user/clients [*]}
{:user/role [:db/ident]}])]
:in ['$]
:where []}
:args [(dc/db conn)]}
(add-arg '?e id ['?e]))]
(->> (dc/q query)
(map first)
(map #(update % :user/role :db/ident))
first)))
(->> [(dc/pull (dc/db conn)
'[*
{:user/clients [*]}
{:user/role [:db/ident]}]
id)]
(map #(update % :user/role :db/ident))
first))
(defn find-or-insert! [{:keys [:user/provider :user/provider-id] :as new-user}]
(let [is-first-user? (not (seq (dc/q {:query [:find '?e
:in '$
:where '[?e :user/provider]]
:args [(dc/db conn)]})))
user (some-> {:query [:find '(pull ?e [*
{:user/clients [*]}
{:user/role [:db/ident]}])
:in '$ '?provider '?provider-id
:where '[?e :user/provider ?provider]
'[?e :user/provider-id ?provider-id]]
:args [(dc/db conn) provider provider-id]}
(dc/q)
(let [is-first-user? (not (seq (dc/q [:find '?e
:in '$
:where '[?e :user/provider]]
(dc/db conn))))
user (some-> (dc/q [:find '(pull ?e [*
{:user/clients [*]}
{:user/role [:db/ident]}])
:in '$ '?provider '?provider-id
:where '[?e :user/provider ?provider]
'[?e :user/provider-id ?provider-id]]
(dc/db conn) provider provider-id)
first
first
(update :user/role :db/ident))]
(if user
user
(let [new-user-trans (dc/transact conn {:tx-data [(cond-> new-user
true (assoc :db/id "user")
is-first-user? (assoc :user/role :user-role/admin))]})]
(let [new-user-trans @(dc/transact conn [(cond-> new-user
true (assoc :db/id "user")
is-first-user? (assoc :user/role :user-role/admin))])]
(get-by-id (-> new-user-trans :tempids (get "user")))))))
(defn raw-graphql [_]
(let [query (cond-> {:query {:find ['(pull ?e [*
{:user/clients [*]}
{:user/role [:db/ident]}])]
:in ['$]
:where ['[?e :user/role]]}
:args [(dc/db conn)]})]
(->> (dc/q query)
(map first)
(map #(update % :user/role :db/ident))
)))
(->> (dc/q {:find ['(pull ?e [*
{:user/clients [*]}
{:user/role [:db/ident]}])]
:in ['$]
:where ['[?e :user/role]]}
(dc/db conn))
(map first)
(map #(update % :user/role :db/ident))
))
(defn sort-fn [args]
(cond

View File

@@ -1,10 +1,17 @@
(ns auto-ap.datomic.vendors
(:require
[auto-ap.datomic :refer [conn merge-query add-sorter-fields apply-pagination merge-query apply-sort-3 pull-many]]
[auto-ap.datomic
:refer [add-sorter-fields
apply-pagination
apply-sort-3
conn
merge-query
pull-many
query2]]
[auto-ap.datomic.accounts :as d-accounts]
[auto-ap.graphql.utils :refer [limited-clients]]
[clojure.string :as str]
[datomic.client.api :as dc]
[auto-ap.datomic.accounts :as d-accounts]))
[datomic.api :as dc]))
(defn <-datomic [a]
(cond-> a
@@ -63,8 +70,7 @@
:where ['[?e :vendor/name]]}}))]
(cond->> query
true (dc/q)
(cond->> (query2 query)
true (apply-sort-3 args)
true (apply-pagination args))))
@@ -102,11 +108,10 @@
)
(defn get-graphql-by-id [args id]
(->> (cond-> {:query {:find [(list 'pull '?e default-read)]
:in ['$ '?e]
:where ['[?e :vendor/name]]}
:args [(dc/db conn) id]})
(dc/q)
(->> (dc/q {:find [(list 'pull '?e default-read)]
:in ['$ '?e]
:where ['[?e :vendor/name]]}
(dc/db conn) id)
(map first)
(map #(cleanse (:id args) %))
(map <-datomic)

View File

@@ -1,10 +1,16 @@
(ns auto-ap.datomic.yodlee2
(:require
[auto-ap.datomic
:refer [add-sorter-fields apply-pagination apply-sort-3 merge-query conn pull-many]]
:refer [add-sorter-fields
apply-pagination
apply-sort-3
conn
merge-query
pull-many
query2]]
[auto-ap.graphql.utils :refer [limited-clients]]
[clj-time.coerce :as c]
[datomic.client.api :as dc]))
[datomic.api :as dc]))
(def default-read '[*])
@@ -39,7 +45,7 @@
(merge-query {:query {:find ['?e ]
:where ['[?e :yodlee-provider-account/id]]}}) )
(dc/q)
(query2)
(apply-sort-3 args)
(apply-pagination args)))

View File

@@ -1,14 +1,13 @@
(ns auto-ap.datomic.yodlee-merchants
(:require
[auto-ap.datomic :refer [conn]]
[datomic.client.api :as dc]))
[datomic.api :as dc]))
(defn get-merchants [_]
;; TODO admin?
(let [query {:query {:find ['(pull ?e [:yodlee-merchant/name :yodlee-merchant/yodlee-id :db/id])]
:in ['$]
:where [['?e :yodlee-merchant/name]]}
:args [(dc/db conn)]}]
(->>
(dc/q query)
(mapv first))))
(->>
(dc/q {:find ['(pull ?e [:yodlee-merchant/name :yodlee-merchant/yodlee-id :db/id])]
:in ['$]
:where [['?e :yodlee-merchant/name]]}
(dc/db conn))
(mapv first)))

View File

@@ -1,7 +1,7 @@
(ns auto-ap.ezcater.core
(:require
[auto-ap.datomic :refer [conn random-tempid]]
[datomic.client.api :as dc]
[datomic.api :as dc]
[clj-http.client :as client]
[venia.core :as v]
[clojure.string :as str]
@@ -44,21 +44,21 @@
(dc/db conn))))
(defn mark-integration-status [integration integration-status]
(dc/transact conn
{:tx-data [{:db/id (:db/id integration)
:ezcater-integration/integration-status (assoc integration-status
:db/id (or (-> integration :ezcater-integration/integration-status :db/id)
(random-tempid)))}]}))
@(dc/transact conn
[{:db/id (:db/id integration)
:ezcater-integration/integration-status (assoc integration-status
:db/id (or (-> integration :ezcater-integration/integration-status :db/id)
(random-tempid)))}]))
(defn upsert-caterers
([integration]
(dc/transact
@(dc/transact
conn
{:tx-data (for [caterer (get-caterers integration)]
{:db/id (:db/id integration)
:ezcater-integration/caterers [{:ezcater-caterer/name (str (:name caterer) " (" (:street (:address caterer)) ")")
:ezcater-caterer/search-terms (str (:name caterer) " " (:street (:address caterer)))
:ezcater-caterer/uuid (:uuid caterer)}]})})))
(for [caterer (get-caterers integration)]
{:db/id (:db/id integration)
:ezcater-integration/caterers [{:ezcater-caterer/name (str (:name caterer) " (" (:street (:address caterer)) ")")
:ezcater-caterer/search-terms (str (:name caterer) " " (:street (:address caterer)))
:ezcater-caterer/uuid (:uuid caterer)}]}))))
(defn upsert-used-subscriptions
([integration]
@@ -270,12 +270,12 @@
(alog/info
::try-import-order
:json json)
(dc/transact conn {:tx-data (filter identity
[(some-> json
(lookup-order)
(order->sales-order)
(update :sales-order/date coerce/to-date)
(update-in [:sales-order/charges 0 :charge/date] coerce/to-date))])}))
@(dc/transact conn (filter identity
[(some-> json
(lookup-order)
(order->sales-order)
(update :sales-order/date coerce/to-date)
(update-in [:sales-order/charges 0 :charge/date] coerce/to-date))])))
(defn upsert-recent []
(upsert-ezcater)
@@ -346,6 +346,6 @@
updated-order))]
(alog/info :found-orders-to-update
:orders orders-to-update)
(dc/transact conn {:tx-data orders-to-update})))
@(dc/transact conn orders-to-update)))

View File

@@ -1,6 +1,6 @@
(ns auto-ap.graphql
(:require
[auto-ap.datomic :refer [merge-query conn]]
[auto-ap.datomic :refer [conn merge-query query2]]
[auto-ap.datomic.users :as d-users]
[auto-ap.graphql.accounts :as gq-accounts]
[auto-ap.graphql.checks :as gq-checks]
@@ -34,8 +34,7 @@
[com.walmartlabs.lacinia :refer [execute]]
[com.walmartlabs.lacinia.parser :as p]
[com.walmartlabs.lacinia.schema :as schema]
[com.walmartlabs.lacinia.util :refer [attach-resolvers]]
[datomic.client.api :as dc]
[datomic.api :as dc]
[unilog.context :as lc]
[yang.time :refer [time-it]])
(:import
@@ -622,7 +621,7 @@
(defn get-expense-account-stats [_ {:keys [client_id] } _]
(let [result (cond-> {:query {:find ['?account '?account-name '(sum ?amount)]
(let [query (cond-> {:query {:find ['?account '?account-name '(sum ?amount)]
:in ['$]
:where []}
:args [(dc/db conn) client_id]}
@@ -635,14 +634,13 @@
'[?i :invoice/expense-accounts ?expense-account]
'[?expense-account :invoice-expense-account/account ?account]
'[?account :account/name ?account-name]
'[?expense-account :invoice-expense-account/amount ?amount]]}})
true (dc/q))]
'[?expense-account :invoice-expense-account/amount ?amount]]}}))
result (query2 query)]
(for [[account-id account-name total] result]
{:account {:id account-id :name account-name} :total total})))
(defn get-invoice-stats [_ {:keys [client_id] } _]
(let [result (cond-> {:query {:find ['?name '(sum ?outstanding-balance) '(sum ?total)]
(let [query (cond-> {:query {:find ['?name '(sum ?outstanding-balance) '(sum ?total)]
:in ['$]
:where []}
:args [(dc/db conn) client_id]}
@@ -664,10 +662,9 @@
(and [(<= ?d3 60)]
[(ground :due-30) ?name])
(and [(> ?d3 60)]
[(ground :due-later) ?name]))]}})
true (dc/q))
result (group-by first result)]
[(ground :due-later) ?name]))]}}))
result (->> (query2 query)
(group-by first))]
(for [[id name] [[:due "Due"] [:due-30 "0-30 days"] [:due-60 "31-60 days"] [:due-later ">60 days"]]
:let [[[_ outstanding-balance total] ] (id result nil)
@@ -699,44 +696,44 @@
(- (+ total credit)
debit))
0.0
(dc/q {:query {:find '[?debit ?credit]
:in '[$ ?client]
:where ['[?client :client/bank-accounts ?ba]
'[?ba :bank-account/type :bank-account-type/check]
'[?je :journal-entry-line/account ?ba]
'[(get-else $ ?je :journal-entry-line/debit 0.0) ?debit]
'[(get-else $ ?je :journal-entry-line/credit 0.0) ?credit]]}
:args [(dc/db conn) client_id]}))
bills-due-soon (dc/q {:query {:find '[?due ?outstanding ?invoice-number ?vendor-id ?vendor-name]
:in '[$ ?client ?due-before]
:where ['[?i :invoice/client ?client]
'[?i :invoice/status :invoice-status/unpaid]
'[?i :invoice/due ?due]
'[(<= ?due ?due-before)]
'[?i :invoice/outstanding-balance ?outstanding]
'[?i :invoice/invoice-number ?invoice-number]
'[?i :invoice/vendor ?vendor-id]
'[?vendor-id :vendor/name ?vendor-name]]}
:args [(dc/db conn) client_id (coerce/to-date (t/plus (time/local-now) (t/days 180)))]})
(dc/q {:find '[?debit ?credit]
:in '[$ ?client]
:where ['[?client :client/bank-accounts ?ba]
'[?ba :bank-account/type :bank-account-type/check]
'[?je :journal-entry-line/account ?ba]
'[(get-else $ ?je :journal-entry-line/debit 0.0) ?debit]
'[(get-else $ ?je :journal-entry-line/credit 0.0) ?credit]]}
(dc/db conn) client_id))
bills-due-soon (dc/q {:find '[?due ?outstanding ?invoice-number ?vendor-id ?vendor-name]
:in '[$ ?client ?due-before]
:where ['[?i :invoice/client ?client]
'[?i :invoice/status :invoice-status/unpaid]
'[?i :invoice/due ?due]
'[(<= ?due ?due-before)]
'[?i :invoice/outstanding-balance ?outstanding]
'[?i :invoice/invoice-number ?invoice-number]
'[?i :invoice/vendor ?vendor-id]
'[?vendor-id :vendor/name ?vendor-name]]}
(dc/db conn) client_id (coerce/to-date (t/plus (time/local-now) (t/days 180))))
outstanding-checks (reduce
+
0.0
(map first (dc/q {:query {:find '[?amount]
:in '[$ ?client ?due-before]
:where ['[?p :payment/client ?client]
'[?p :payment/status :payment-status/pending]
'[?p :payment/amount ?amount]
'(or
[?p :payment/type :payment-type/debit]
[?p :payment/type :payment-type/check])]}
:args [(dc/db conn) client_id (coerce/to-date (t/plus (time/local-now) (t/days 180)))]})))
recent-fulfillments (dc/q {:query {:find '[?f ?d]
:in '[$ ?client ?min-date]
:where ['[?t :transaction/forecast-match ?f]
'[?t :transaction/client ?client]
'[?t :transaction/date ?d]
'[(>= ?d ?min-date)]]}
:args [(dc/db conn) client_id (coerce/to-date (t/plus (time/local-now) (t/months -2)))]})
(map first (dc/q {:find '[?amount]
:in '[$ ?client ?due-before]
:where ['[?p :payment/client ?client]
'[?p :payment/status :payment-status/pending]
'[?p :payment/amount ?amount]
'(or
[?p :payment/type :payment-type/debit]
[?p :payment/type :payment-type/check])]}
(dc/db conn) client_id (coerce/to-date (t/plus (time/local-now) (t/days 180))))))
recent-fulfillments (dc/q {:find '[?f ?d]
:in '[$ ?client ?min-date]
:where ['[?t :transaction/forecast-match ?f]
'[?t :transaction/client ?client]
'[?t :transaction/date ?d]
'[(>= ?d ?min-date)]]}
(dc/db conn) client_id (coerce/to-date (t/plus (time/local-now) (t/months -2))))
forecasted-transactions (for [{:forecasted-transaction/keys [amount identifier day-of-month]
:db/keys [id]} forecasted-transactions
month (range -1 7)

View File

@@ -13,8 +13,8 @@
result->page]]
[auto-ap.search :as search]
[auto-ap.utils :refer [heartbeat]]
[datomic.client.api :as dc]
[iol-ion.tx :refer [random-tempid upsert-entity]]
[datomic.api :as dc]
[iol-ion.tx :refer [random-tempid]]
[mount.core :as mount]
[yang.scheduler :as scheduler]))
@@ -38,36 +38,36 @@
(defn upsert-account [context args _]
(let [{{:keys [id client-overrides numeric-code location applicability account-set name invoice-allowance vendor-allowance type]} :account} (<-graphql args)]
(when-not id
(when (seq (dc/q {:query {:find ['?e]
:in '[$ ?account-set ?numeric-code]
:where ['[?e :account/account-set ?account-set]
'[?e :account/numeric-code ?numeric-code]]}
:args [(dc/db conn) account-set numeric-code]}))
(when (seq (dc/q {:find ['?e]
:in '[$ ?account-set ?numeric-code]
:where ['[?e :account/account-set ?account-set]
'[?e :account/numeric-code ?numeric-code]]}
(dc/db conn) account-set numeric-code))
(throw (ex-info (str "Account set " account-set " already has an account for code " numeric-code)
{} ))))
(let [result (audit-transact [`(upsert-entity
~(cond-> {:db/id (or id "new-account")
:account/name name
:account/search-terms name
:account/type (keyword "account-type" (clojure.core/name type))
:account/applicability (or (enum->keyword applicability "account-applicability")
:account-applicability/global)
:account/invoice-allowance (some-> invoice-allowance (enum->keyword "allowance"))
:account/vendor-allowance (some-> vendor-allowance (enum->keyword "allowance"))
:account/default-allowance :allowance/allowed
:account/account-set account-set
:account/location location
:account/numeric-code numeric-code
:account/code (str numeric-code)
:account/client-overrides (mapv
(fn [client-override]
{:db/id (or (:id client-override) (random-tempid))
:account-client-override/client (:client-id client-override)
:account-client-override/name (:name client-override)
:account-client-override/search-terms (:name client-override)})
client-overrides)}
id (dissoc :account/numeric-code :account/code)))]
(let [result (audit-transact [[:upsert-entity
(cond-> {:db/id (or id "new-account")
:account/name name
:account/search-terms name
:account/type (keyword "account-type" (clojure.core/name type))
:account/applicability (or (enum->keyword applicability "account-applicability")
:account-applicability/global)
:account/invoice-allowance (some-> invoice-allowance (enum->keyword "allowance"))
:account/vendor-allowance (some-> vendor-allowance (enum->keyword "allowance"))
:account/default-allowance :allowance/allowed
:account/account-set account-set
:account/location location
:account/numeric-code numeric-code
:account/code (str numeric-code)
:account/client-overrides (mapv
(fn [client-override]
{:db/id (or (:id client-override) (random-tempid))
:account-client-override/client (:client-id client-override)
:account-client-override/name (:name client-override)
:account-client-override/search-terms (:name client-override)})
client-overrides)}
id (dissoc :account/numeric-code :account/code))]]
(:id context))]
(->graphql
(d-accounts/get-by-id (or id (get-in result [:tempids "new-account"])))))))
@@ -149,12 +149,12 @@
(defn rebuild-search-index []
(search/full-index-query
(for [result (map first (dc/qseq '[:find (pull ?aco [:account-client-override/search-terms :account-client-override/client :db/id {:account/_client-overrides [:account/numeric-code :account/location :db/id]}])
:in $
:where [?aco :account-client-override/client ]
[?aco :account-client-override/search-terms ]
[_ :account/client-overrides ?aco]]
(dc/db conn)))
(for [result (map first (dc/qseq {:query '[:find (pull ?aco [:account-client-override/search-terms :account-client-override/client :db/id {:account/_client-overrides [:account/numeric-code :account/location :db/id]}])
:in $
:where [?aco :account-client-override/client ]
[?aco :account-client-override/search-terms ]
[_ :account/client-overrides ?aco]]
:args [(dc/db conn)]}))
:when (:account/numeric-code (:account/_client-overrides result))]
{:id (:db/id (:account/_client-overrides result))
:account-client-override-id (:db/id result)
@@ -165,14 +165,14 @@
"account-client-override")
(search/full-index-query
(for [result (map first (dc/qseq '[:find (pull ?a [:account/numeric-code
:account/search-terms
{:account/applicability [:db/ident]}
:db/id
:account/location])
:in $
:where [?a :account/search-terms ]]
(dc/db conn)))
(for [result (map first (dc/qseq {:query '[:find (pull ?a [:account/numeric-code
:account/search-terms
{:account/applicability [:db/ident]}
:db/id
:account/location])
:in $
:where [?a :account/search-terms ]]
:args [(dc/db conn)]}))
:when (:account/search-terms result)
]
{:id (:db/id result)
@@ -183,11 +183,11 @@
"account"))
#_(dc/transact conn
{:tx-data [{:db/ident :account-client-override/k2
:db/valueType :db.type/tuple
:db/tupleAttrs [:account/_client-overrides :account-client-override/client ]
:db/cardinality :db.cardinality/one
:db/unique :db.unique/identity}]})
[{:db/ident :account-client-override/k2
:db/valueType :db.type/tuple
:db/tupleAttrs [:account/_client-overrides :account-client-override/client ]
:db/cardinality :db.cardinality/one
:db/unique :db.unique/identity}])
#_(dc/q '[:find ?o
:where [_ :account-client-override/k ?o]]

View File

@@ -3,7 +3,6 @@
[amazonica.aws.s3 :as s3]
[auto-ap.datomic :refer [conn remove-nils pull-many audit-transact]]
[auto-ap.datomic.accounts :as a]
[iol-ion.tx :refer [upsert-invoice pay plus]]
[auto-ap.datomic.bank-accounts :as d-bank-accounts]
[auto-ap.datomic.checks :as d-checks]
[auto-ap.datomic.clients :as d-clients]
@@ -35,7 +34,7 @@
[com.walmartlabs.lacinia.util :refer [attach-resolvers]]
[config.core :refer [env]]
[clj-time.coerce :as coerce]
[datomic.client.api :as dc]
[datomic.api :as dc]
[digest])
(:import
(java.io ByteArrayOutputStream)
@@ -230,7 +229,7 @@
[{:invoice-payment/payment (-> invoice :invoice/vendor :db/id str)
:invoice-payment/amount invoice-amount
:invoice-payment/invoice (:db/id invoice)}
`(pay ~(:db/id invoice) ~invoice-amount)])
[:pay (:db/id invoice) invoice-amount]])
(reduce into [])))
(defn base-payment [invoices vendor client bank-account _ _ invoice-amounts]
@@ -408,7 +407,7 @@
(reduce into [])
doall))
checks (if (= type :payment-type/check)
(conj checks `(plus ~(:db/id bank-account) ~:bank-account/check-number ~(count invoices-grouped-by-vendor)))
(conj checks [:plus (:db/id bank-account) :bank-account/check-number (count invoices-grouped-by-vendor)])
checks)]
(when (= type :payment-type/check)
(mu/trace ::making-pdfs [:checks checks]
@@ -501,11 +500,11 @@
new-balance (+ (:invoice/outstanding-balance invoice)
(:invoice-payment/amount x))]
[[:db/retractEntity (:db/id x)]
`(upsert-invoice ~{:db/id (:db/id invoice)
:invoice/outstanding-balance new-balance
:invoice/status (if (dollars-0? new-balance)
(:invoice/status invoice)
:invoice-status/unpaid)})]))
[:upsert-invoice {:db/id (:db/id invoice)
:invoice/outstanding-balance new-balance
:invoice/status (if (dollars-0? new-balance)
(:invoice/status invoice)
:invoice-status/unpaid)}]]))
(:payment/invoices check))
updated-payment {:db/id id
:payment/amount 0.0
@@ -543,11 +542,11 @@
(let [new-balance (+ (:invoice/outstanding-balance invoice)
amount)]
[[:db.fn/retractEntity id]
`(upsert-invoice ~{:db/id (:db/id invoice)
:invoice/outstanding-balance new-balance
:invoice/status (if (dollars-0? new-balance)
(:invoice/status invoice)
:invoice-status/unpaid)})]))))))))
[:upsert-invoice {:db/id (:db/id invoice)
:invoice/outstanding-balance new-balance
:invoice/status (if (dollars-0? new-balance)
(:invoice/status invoice)
:invoice-status/unpaid)}]]))))))))
id))

View File

@@ -20,8 +20,8 @@
[clojure.string :as str]
[clojure.tools.logging :as log]
[com.brunobonacci.mulog :as mu]
[datomic.client.api :as dc]
[iol-ion.tx :refer [random-tempid upsert-entity]]
[datomic.api :as dc]
[iol-ion.tx :refer [random-tempid]]
[mount.core :as mount]
[unilog.context :as lc]
[yang.scheduler :as scheduler])
@@ -30,10 +30,10 @@
(org.apache.commons.codec.binary Base64)))
(defn assert-client-code-is-unique [code]
(when (seq (dc/q {:query {:find '[?id]
:in ['$ '?code]
:where ['[?id :client/code ?code]]}
:args [(dc/db conn) code]}))
(when (seq (dc/q {:find '[?id]
:in ['$ '?code]
:where ['[?id :client/code ?code]]}
(dc/db conn) code))
(throw (ex-info "Client is not unique" {:validation-error (str "Client code '" code "' is not unique.")}))))
(defn upload-signature-data [signature-data]
@@ -52,8 +52,8 @@
(str "https://integreat-signature-images.s3.amazonaws.com/" signature-id ".jpg")))))
(defn assert-no-shared-transaction-sources [client-code txes]
(let [new-db (:db-after (dc/with (dc/with-db conn)
{:tx-data txes}))]
(let [new-db (:db-after (dc/with (dc/db conn)
txes))]
(when (seq (->> (dc/q '[:find ?src (count ?ba)
:in $ ?c
:where [?c :client/bank-accounts ?ba]
@@ -150,10 +150,10 @@
}
_ (mu/log ::upserting :up updated-entity)
_ (assert-no-shared-transaction-sources client-code [`(upsert-entity ~updated-entity)])
_ (assert-no-shared-transaction-sources client-code [[:upsert-entity updated-entity]])
_ (log/info "upserting client" updated-entity)
result (audit-transact [`(upsert-entity ~updated-entity)] (:id context))]
result (audit-transact [[:upsert-entity updated-entity]] (:id context))]
(when (:square_auth_token edit_client)
(square/upsert-locations (-> result :tempids (get id) (or id) d-clients/get-by-id)))
(-> (-> result :tempids (get id) (or id) d-clients/get-by-id)
@@ -178,26 +178,25 @@
clients (dc/q '[:find (pull ?c [:db/id :client/code {:client/bank-accounts [:db/id :bank-account/code]}])
:where [?c :client/code]]
db )]
(dc/transact conn
{:tx-data
(for [[{client :db/id code :client/code bank-accounts :client/bank-accounts}] clients
{bank-account :db/id bac :bank-account/code} bank-accounts]
{:db/id bank-account
:bank-account/current-balance
(or
(->> (dc/index-pull db
{:index :avet
:selector [:db/id :journal-entry-line/location :journal-entry-line/account :journal-entry-line/running-balance :journal-entry-line/client+account+location+date {:journal-entry/_line-items [:journal-entry/date :journal-entry/client]}]
:start [:journal-entry-line/client+account+location+date [client bank-account "A" #inst "2030-01-01"]]
:limit 1
:reverse true
})
(filter (fn [{[c b] :journal-entry-line/client+account+location+date}]
(and (= c client)
(= b bank-account))))
(map :journal-entry-line/running-balance)
(first))
0.0)})}))))
@(dc/transact conn
(for [[{client :db/id code :client/code bank-accounts :client/bank-accounts}] clients
{bank-account :db/id bac :bank-account/code} bank-accounts]
{:db/id bank-account
:bank-account/current-balance
(or
(->> (dc/index-pull db
{:index :avet
:selector [:db/id :journal-entry-line/location :journal-entry-line/account :journal-entry-line/running-balance :journal-entry-line/client+account+location+date {:journal-entry/_line-items [:journal-entry/date :journal-entry/client]}]
:start [:journal-entry-line/client+account+location+date [client bank-account "A" #inst "2030-01-01"]]
:limit 1
:reverse true
})
(filter (fn [{[c b] :journal-entry-line/client+account+location+date}]
(and (= c client)
(= b bank-account))))
(map :journal-entry-line/running-balance)
(first))
0.0)})))))
(defn get-client [context _ _]
(->graphql

View File

@@ -5,7 +5,7 @@
:refer [assert-admin attach-tracing-resolvers cleanse-query]]
[auto-ap.search :as search]
[auto-ap.utils :refer [heartbeat]]
[datomic.client.api :as dc]
[datomic.api :as dc]
[mount.core :as mount]
[yang.scheduler :as scheduler]))
@@ -19,10 +19,10 @@
(defn rebuild-search-index []
(search/full-index-query
(for [result (map first (dc/qseq '[:find (pull ?a [:ezcater-caterer/search-terms :db/id :ezcater-caterer/name])
:in $
:where [?a :ezcater-caterer/search-terms ]]
(dc/db conn)))]
(for [result (map first (dc/qseq {:query '[:find (pull ?a [:ezcater-caterer/search-terms :db/id :ezcater-caterer/name])
:in $
:where [?a :ezcater-caterer/search-terms ]]
:args [(dc/db conn)]}))]
{:id (:db/id result)
:text (:ezcater-caterer/search-terms result)})
"ezcater-caterer"))

View File

@@ -1,12 +1,21 @@
(ns auto-ap.graphql.import-batch
(:require
[auto-ap.datomic :refer [add-sorter-fields apply-pagination apply-sort-3 conn merge-query pull-many-by-id]]
[auto-ap.datomic
:refer [add-sorter-fields
apply-pagination
apply-sort-3
conn
merge-query
pull-many-by-id
query2]]
[auto-ap.graphql.utils
:refer
[<-graphql assert-admin ident->enum-f result->page attach-tracing-resolvers]]
:refer [<-graphql
assert-admin
attach-tracing-resolvers
ident->enum-f
result->page]]
[clj-time.coerce :as coerce]
[com.walmartlabs.lacinia.util :refer [attach-resolvers]]
[datomic.client.api :as dc]))
[datomic.api :as dc]))
(def default-read '[:db/id
:import-batch/external-id
@@ -32,8 +41,7 @@
:where ['[?e :import-batch/date]]}}))]
(cond->> query
true (dc/q)
(cond->> (query2 query)
true (apply-sort-3 args)
true (apply-pagination args))))

View File

@@ -2,7 +2,7 @@
(:require
[auto-ap.datomic :refer [conn]]
[auto-ap.graphql.utils :refer [->graphql assert-admin]]
[datomic.client.api :as dc]))
[datomic.api :as dc]))
(defn get-intuit-bank-accounts [context _ _]
(assert-admin (:id context))

View File

@@ -2,7 +2,6 @@
(:require
[auto-ap.datomic
:refer [conn pull-attr pull-many pull-ref random-tempid audit-transact audit-transact-batch]]
[iol-ion.tx :refer [upsert-entity upsert-invoice]]
[auto-ap.datomic.clients :as d-clients]
[auto-ap.datomic.invoices :as d-invoices]
[auto-ap.datomic.vendors :as d-vendors]
@@ -23,7 +22,7 @@
[clj-time.core :as time]
[clojure.tools.logging :as log]
[com.brunobonacci.mulog :as mu]
[datomic.client.api :as dc]))
[datomic.api :as dc]))
(defn ->graphql [invoice user ]
(if (= "admin" (:user/role user))
@@ -74,7 +73,7 @@
i)]]
(assert-can-see-client (:id context) (-> invoice :invoice/client :db/id))
(assert-not-locked (-> invoice :invoice/client :db/id) (-> invoice :invoice/date)))
(let [transactions (map (fn [i] `(upsert-invoice ~{:db/id i :invoice/import-status :import-status/imported})) invoices)]
(let [transactions (map (fn [i] [:upsert-invoice {:db/id i :invoice/import-status :import-status/imported}]) invoices)]
(audit-transact transactions (:id context))
invoices))
@@ -109,19 +108,19 @@
_ (when-not (:db/id account)
(throw (ex-info (str "Vendor '" (:vendor/name vendor) "' does not have a default expense acount.") {:vendor-id vendor_id})))]
`(upsert-invoice ~{:db/id "invoice"
:invoice/invoice-number invoice_number
:invoice/client client_id
:invoice/vendor vendor_id
:invoice/import-status :import-status/imported
:invoice/total total
:invoice/outstanding-balance total
:invoice/status :invoice-status/unpaid
:invoice/date (coerce/to-date date)
:invoice/expense-accounts (map expense-account->entity
expense_accounts)
:invoice/due (coerce/to-date due)
:invoice/scheduled-payment (coerce/to-date scheduled_payment)})))
[:upsert-invoice {:db/id "invoice"
:invoice/invoice-number invoice_number
:invoice/client client_id
:invoice/vendor vendor_id
:invoice/import-status :import-status/imported
:invoice/total total
:invoice/outstanding-balance total
:invoice/status :invoice-status/unpaid
:invoice/date (coerce/to-date date)
:invoice/expense-accounts (map expense-account->entity
expense_accounts)
:invoice/due (coerce/to-date due)
:invoice/scheduled-payment (coerce/to-date scheduled_payment)}]))
(defn assert-valid-expense-accounts [expense_accounts vendor_id]
(doseq [expense-account expense_accounts
@@ -230,7 +229,7 @@
expense_accounts)
:invoice/due (coerce/to-date due)
:invoice/scheduled-payment (coerce/to-date scheduled_payment)}]
(audit-transact [`(upsert-invoice ~updated-invoice)]
(audit-transact [[:upsert-invoice updated-invoice]]
(:id context))
(-> (d-invoices/get-by-id id)
(->graphql (:id context)))))
@@ -239,13 +238,13 @@
(let [invoice (d-invoices/get-by-id id)]
(assert-can-see-client (:id context) (:db/id (:invoice/client invoice)))
(assert-not-locked (:db/id (:invoice/client invoice)) (:invoice/date invoice))
(audit-transact [`(upsert-invoice ~{:db/id id
(audit-transact [[:upsert-invoice {:db/id id
:invoice/total 0.0
:invoice/outstanding-balance 0.0
:invoice/status :invoice-status/voided
:invoice/expense-accounts (map (fn [ea] {:db/id (:db/id ea)
:invoice-expense-account/amount 0.0})
(:invoice/expense-accounts invoice))})]
(:invoice/expense-accounts invoice))}]]
(:id context))
(-> (d-invoices/get-by-id id) (->graphql (:id context)))))
@@ -308,15 +307,15 @@
(dc/db conn))
(map
(fn [[i]]
`(upsert-invoice ~{:db/id (:db/id i)
:invoice/total 0.0
:invoice/outstanding-balance 0.0
:invoice/status :invoice-status/voided
:invoice/expense-accounts (map
(fn [iea]
{:db/id (:db/id iea)
:invoice-expense-account/amount 0.0})
(:invoice/expense-accounts i))}))))
[:upsert-invoice {:db/id (:db/id i)
:invoice/total 0.0
:invoice/outstanding-balance 0.0
:invoice/status :invoice-status/voided
:invoice/expense-accounts (map
(fn [iea]
{:db/id (:db/id iea)
:invoice-expense-account/amount 0.0})
(:invoice/expense-accounts i))}])))
(:id context))
{:message (str "Succesfully voided " (count all-ids))}))
@@ -325,26 +324,26 @@
_ (assert-can-see-client (:id context) (:db/id (:invoice/client invoice)))
_ (assert-not-locked (:db/id (:invoice/client invoice)) (:invoice/date invoice))
history (dc/history (dc/db conn))
txs (dc/q {:query {:find ['?tx '?e '?original-status '?original-outstanding '?total '?ea '?ea-amount]
:where ['[?e :invoice/status :invoice-status/voided ?tx true]
'[?e :invoice/status ?original-status ?tx false]
'[?e :invoice/outstanding-balance ?original-outstanding ?tx false]
'[?e :invoice/total ?total ?tx false]
'[?ea :invoice-expense-account/amount ?ea-amount ?tx false]]
:in ['$ '?e]}
:args [history id]})
txs (dc/q {:find ['?tx '?e '?original-status '?original-outstanding '?total '?ea '?ea-amount]
:where ['[?e :invoice/status :invoice-status/voided ?tx true]
'[?e :invoice/status ?original-status ?tx false]
'[?e :invoice/outstanding-balance ?original-outstanding ?tx false]
'[?e :invoice/total ?total ?tx false]
'[?ea :invoice-expense-account/amount ?ea-amount ?tx false]]
:in ['$ '?e]}
history id)
[last-transaction] (->> txs (sort-by first) (last))]
(audit-transact [`(upsert-invoice
~(->> txs
(filter (fn [[tx]] (= tx last-transaction)))
(reduce (fn [new-transaction [_ entity original-status original-outstanding total expense-account expense-account-amount]]
(-> new-transaction
(assoc :db/id entity
:invoice/total total
:invoice/status original-status
:invoice/outstanding-balance original-outstanding)
(update :invoice/expense-accounts conj {:db/id expense-account :invoice-expense-account/amount expense-account-amount})))
{})))]
(audit-transact [[:upsert-invoice
(->> txs
(filter (fn [[tx]] (= tx last-transaction)))
(reduce (fn [new-transaction [_ entity original-status original-outstanding total expense-account expense-account-amount]]
(-> new-transaction
(assoc :db/id entity
:invoice/total total
:invoice/status original-status
:invoice/outstanding-balance original-outstanding)
(update :invoice/expense-accounts conj {:db/id expense-account :invoice-expense-account/amount expense-account-amount})))
{}))]]
(:id context))
(-> (d-invoices/get-by-id id)
@@ -360,11 +359,11 @@
(assert-can-see-client (:id context) (:db/id (:invoice/client invoice)))
(assert-not-locked (:db/id (:invoice/client invoice)) (:invoice/date invoice))
(assert (not (seq (:invoice-payment/_invoice invoice))))
(audit-transact [`(upsert-invoice
~{:db/id id
:invoice/status :invoice-status/unpaid
:invoice/outstanding-balance (:invoice/total invoice)
:invoice/scheduled-payment nil})]
(audit-transact [[:upsert-invoice
{:db/id id
:invoice/status :invoice-status/unpaid
:invoice/outstanding-balance (:invoice/total invoice)
:invoice/scheduled-payment nil}]]
(:id context))
(-> (d-invoices/get-by-id id)
@@ -377,10 +376,10 @@
_ (assert-not-locked (:db/id (:invoice/client invoice)) (:invoice/date invoice))
_ (assert-valid-expense-accounts (:expense_accounts args) (:db/id (:invoice/vendor invoice )))]
(audit-transact [`(upsert-invoice ~{:db/id invoice-id
:invoice/expense-accounts (map
expense-account->entity
(:expense_accounts args))})]
(audit-transact [[:upsert-invoice {:db/id invoice-id
:invoice/expense-accounts (map
expense-account->entity
(:expense_accounts args))}]]
(:id context))
(->graphql
(d-invoices/get-by-id (:invoice_id args))
@@ -469,8 +468,8 @@
(log/info "Bulk coding " (count all-ids) args)
(audit-transact-batch
(map (fn [i]
`(upsert-invoice ~{:db/id (:db/id i)
:invoice/expense-accounts (maybe-code-accounts i (:accounts args) locations)}))
[:upsert-invoice {:db/id (:db/id i)
:invoice/expense-accounts (maybe-code-accounts i (:accounts args) locations)}])
invoices)
(:id context))
{:message (str "Successfully coded " (count all-ids) " invoices.")}))

View File

@@ -27,8 +27,8 @@
[clojure.data.csv :as csv]
[clojure.tools.logging :as log]
[com.brunobonacci.mulog :as mu]
[datomic.client.api :as dc]
[iol-ion.tx :refer [random-tempid upsert-ledger]])
[datomic.api :as dc]
[iol-ion.tx :refer [random-tempid]])
(:import
(org.apache.commons.codec.binary Base64)))
@@ -132,26 +132,25 @@
(defn full-ledger-for-client [client-id]
(->> (dc/q
{:query {:find ['?d '?jel '?account '?location '?debit '?credit]
:in ['$ '?client-id]
:where '[[?e :journal-entry/client ?client-id]
[?e :journal-entry/date ?d]
[?e :journal-entry/line-items ?jel]
(or-join [?e]
(and [?e :journal-entry/original-entity ?i]
(or-join [?e ?i]
(and
[?i :transaction/bank-account ?b]
(or [?b :bank-account/include-in-reports true]
(not [?b :bank-account/include-in-reports])))
(not [?i :transaction/bank-account])))
(not [?e :journal-entry/original-entity ]))
[(get-else $ ?jel :journal-entry-line/account :account/unknown) ?account]
[(get-else $ ?jel :journal-entry-line/debit 0.0) ?debit ]
[(get-else $ ?jel :journal-entry-line/credit 0.0) ?credit]
[(get-else $ ?jel :journal-entry-line/location "") ?location]]
}
:args [(dc/db conn) client-id]})
{:find ['?d '?jel '?account '?location '?debit '?credit]
:in ['$ '?client-id]
:where '[[?e :journal-entry/client ?client-id]
[?e :journal-entry/date ?d]
[?e :journal-entry/line-items ?jel]
(or-join [?e]
(and [?e :journal-entry/original-entity ?i]
(or-join [?e ?i]
(and
[?i :transaction/bank-account ?b]
(or [?b :bank-account/include-in-reports true]
(not [?b :bank-account/include-in-reports])))
(not [?i :transaction/bank-account])))
(not [?e :journal-entry/original-entity ]))
[(get-else $ ?jel :journal-entry-line/account :account/unknown) ?account]
[(get-else $ ?jel :journal-entry-line/debit 0.0) ?debit ]
[(get-else $ ?jel :journal-entry-line/credit 0.0) ?credit]
[(get-else $ ?jel :journal-entry-line/location "") ?location]]}
(dc/db conn) client-id)
(sort-by first)))
(defn get-balance-sheet [context args _]
@@ -438,71 +437,71 @@
(assoc entry
:status :success
:tx
`(upsert-ledger
~(remove-nils
{:journal-entry/source (:source entry)
:journal-entry/client [:client/code (:client_code entry)]
:journal-entry/date (coerce/to-date (parse/parse-value :clj-time "MM/dd/yyyy" (:date entry)))
:journal-entry/external-id (:external_id entry)
:journal-entry/vendor (:db/id (all-vendors (:vendor_name entry)))
:journal-entry/amount (:amount entry)
:journal-entry/note (:note entry)
:journal-entry/cleared-against (:cleared_against entry)
[:upsert-ledger
(remove-nils
{:journal-entry/source (:source entry)
:journal-entry/client [:client/code (:client_code entry)]
:journal-entry/date (coerce/to-date (parse/parse-value :clj-time "MM/dd/yyyy" (:date entry)))
:journal-entry/external-id (:external_id entry)
:journal-entry/vendor (:db/id (all-vendors (:vendor_name entry)))
:journal-entry/amount (:amount entry)
:journal-entry/note (:note entry)
:journal-entry/cleared-against (:cleared_against entry)
:journal-entry/line-items
(mapv (fn [ea]
(let [debit (or (:debit ea) 0.0)
credit (or (:credit ea) 0.0)]
(when (and (not (get
(get all-client-locations (:client_code entry))
(:location ea)))
(not= "A" (:location ea)))
(throw (ex-info (str "Location '" (:location ea) "' not found.")
:journal-entry/line-items
(mapv (fn [ea]
(let [debit (or (:debit ea) 0.0)
credit (or (:credit ea) 0.0)]
(when (and (not (get
(get all-client-locations (:client_code entry))
(:location ea)))
(not= "A" (:location ea)))
(throw (ex-info (str "Location '" (:location ea) "' not found.")
{:status :error})))
(when (and (<= debit 0.0)
(<= credit 0.0))
(throw (ex-info (str "Line item amount " (or debit credit) " must be greater than 0.")
{:status :error})))
(when (and (not (all-accounts (:account_identifier ea)))
(not (get
(get all-client-bank-accounts (:client_code entry))
(:account_identifier ea))))
(throw (ex-info (str "Account '" (:account_identifier ea) "' not found.")
{:status :error})))
(let [matching-account (when (re-matches #"^[0-9]+$" (:account_identifier ea))
(a/get-account-by-numeric-code-and-sets (Integer/parseInt (:account_identifier ea)) ["default"]))]
(when (and matching-account
(:account/location matching-account)
(not= (:account/location matching-account)
(:location ea)))
(throw (ex-info (str "Account '"
(:account/numeric-code matching-account)
"' requires location '"
(:account/location matching-account)
"' but got '"
(:location ea)
"'")
{:status :error})))
(when (and (<= debit 0.0)
(<= credit 0.0))
(throw (ex-info (str "Line item amount " (or debit credit) " must be greater than 0.")
(when (and matching-account
(not (:account/location matching-account))
(= "A" (:location ea)))
(throw (ex-info (str "Account '"
(:account/numeric-code matching-account)
"' cannot use location '"
(:location ea)
"'")
{:status :error})))
(when (and (not (all-accounts (:account_identifier ea)))
(not (get
(get all-client-bank-accounts (:client_code entry))
(:account_identifier ea))))
(throw (ex-info (str "Account '" (:account_identifier ea) "' not found.")
{:status :error})))
(let [matching-account (when (re-matches #"^[0-9]+$" (:account_identifier ea))
(a/get-account-by-numeric-code-and-sets (Integer/parseInt (:account_identifier ea)) ["default"]))]
(when (and matching-account
(:account/location matching-account)
(not= (:account/location matching-account)
(:location ea)))
(throw (ex-info (str "Account '"
(:account/numeric-code matching-account)
"' requires location '"
(:account/location matching-account)
"' but got '"
(:location ea)
"'")
{:status :error})))
(when (and matching-account
(not (:account/location matching-account))
(= "A" (:location ea)))
(throw (ex-info (str "Account '"
(:account/numeric-code matching-account)
"' cannot use location '"
(:location ea)
"'")
{:status :error})))
(remove-nils (cond-> {:db/id (random-tempid)
:journal-entry-line/location (:location ea)
:journal-entry-line/debit (when (> debit 0)
debit)
:journal-entry-line/credit (when (> credit 0)
credit)}
matching-account (assoc :journal-entry-line/account (:db/id matching-account))
(not matching-account) (assoc :journal-entry-line/account [:bank-account/code (:account_identifier ea)]))))))
(:line_items entry))
:journal-entry/cleared true}))))))
(remove-nils (cond-> {:db/id (random-tempid)
:journal-entry-line/location (:location ea)
:journal-entry-line/debit (when (> debit 0)
debit)
:journal-entry-line/credit (when (> credit 0)
credit)}
matching-account (assoc :journal-entry-line/account (:db/id matching-account))
(not matching-account) (assoc :journal-entry-line/account [:bank-account/code (:account_identifier ea)]))))))
(:line_items entry))
:journal-entry/cleared true})]))))
(:entries args))))
errors (filter #(= (:status %) :error) transaction)
ignored (filter #(= (:status %) :ignored) transaction)

View File

@@ -7,7 +7,8 @@
conn
merge-query
pull-attr
pull-many-by-id]]
pull-many-by-id
query2]]
[auto-ap.graphql.utils
:refer [->graphql
<-graphql
@@ -20,7 +21,7 @@
[clj-time.coerce :as coerce]
[clj-time.core :as time]
[clojure.tools.logging :as log]
[datomic.client.api :as dc]))
[datomic.api :as dc]))
(defn plaid-link-token [context value _]
(when-not (:client_id value)
@@ -46,16 +47,15 @@
:plaid-item/last-updated (coerce/to-date (time/now))
:db/id "plaid-item"}]
(dc/transact conn {:tx-data
(->> (:accounts account-result)
(map (fn [a]
(let [balance (some-> a :balances :current (* 0.01))]
(cond-> {:plaid-account/external-id (:account_id a)
:plaid-account/number (:mask a)
:plaid-account/name (str (:name a) " " (:mask a))
:plaid-item/_accounts "plaid-item"}
balance (assoc :plaid-account/balance balance)))))
(into [item]))})
@(dc/transact conn (->> (:accounts account-result)
(map (fn [a]
(let [balance (some-> a :balances :current (* 0.01))]
(cond-> {:plaid-account/external-id (:account_id a)
:plaid-account/number (:mask a)
:plaid-account/name (str (:name a) " " (:mask a))
:plaid-item/_accounts "plaid-item"}
balance (assoc :plaid-account/balance balance)))))
(into [item])))
(log/info "Access token was " access-token)
{:message (str "Plaid linked successfully.")}))
@@ -93,8 +93,7 @@
(merge-query {:query {:find ['?e]
:where ['[?e :plaid-item/external-id]]}}))]
(cond->> query
true (dc/q)
(cond->> (query2 query)
true (apply-sort-3 args)
true (apply-pagination args))))
@@ -126,7 +125,7 @@
(defn delete-plaid-item [context args _]
(assert-admin (:id context))
(assert-present args :id)
(dc/transact conn {:tx-data [[:db/retractEntity (:id args)]]})
@(dc/transact conn [[:db/retractEntity (:id args)]])
{:message "Item deleted."})
(defn attach [schema]

View File

@@ -6,7 +6,7 @@
[auto-ap.graphql.utils
:refer [<-graphql assert-admin attach-tracing-resolvers result->page]]
[config.core :refer [env]]
[datomic.client.api :as dc]))
[datomic.api :as dc]))
(defn get-report-page [context args _]
(let [args (assoc args :id (:id context))
@@ -25,7 +25,7 @@
(when id-to-delete
(s3/delete-object :bucket-name (:data-bucket env)
:key key)
(dc/transact conn {:tx-data [[:db/retractEntity id-to-delete]]}))
@(dc/transact conn [[:db/retractEntity id-to-delete]]))
{:message (format "deleted %s successfully" key)}))

View File

@@ -1,7 +1,6 @@
(ns auto-ap.graphql.transaction-rules
(:require
[auto-ap.datomic :refer [audit-transact conn merge-query]]
[iol-ion.tx :refer [upsert-entity random-tempid]]
[auto-ap.datomic :refer [audit-transact conn merge-query query2]]
[auto-ap.datomic.transaction-rules :as tr]
[auto-ap.datomic.transactions :as d-transactions]
[auto-ap.graphql.utils
@@ -16,8 +15,9 @@
[auto-ap.utils :refer [dollars=]]
[clj-time.coerce :as c]
[clojure.string :as str]
[datomic.client.api :as dc]
[com.brunobonacci.mulog :as mu]))
[com.brunobonacci.mulog :as mu]
[datomic.api :as dc]
[iol-ion.tx :refer [random-tempid]]))
(defn get-transaction-rule-page [context args _]
(let [args (assoc args :id (:id context))
@@ -82,7 +82,7 @@
rule-id (if id
id
"transaction-rule")
transaction [`(upsert-entity ~#:transaction-rule {:db/id (or rule-id (random-tempid))
transaction [[:upsert-entity #:transaction-rule {:db/id (or rule-id (random-tempid))
:description description
:note note
:client client_id
@@ -98,7 +98,7 @@
name
snake->kebab
(keyword "transaction-approval-status"))
:transaction-rule/accounts (map transaction-rule-account->entity accounts)})]
:transaction-rule/accounts (map transaction-rule-account->entity accounts)}]]
transaction-result (audit-transact transaction (:id context))]
@@ -108,87 +108,85 @@
(->graphql))))
(defn -test-transaction-rule [id {:keys [:transaction-rule/description :transaction-rule/client :transaction-rule/bank-account :transaction-rule/amount-lte :transaction-rule/amount-gte :transaction-rule/dom-lte :transaction-rule/dom-gte :transaction-rule/yodlee-merchant]} include-coded? count]
(->>
(dc/q
(cond-> {:query {:find ['(pull ?e [* {:transaction/client [:client/name]
:transaction/bank-account [:bank-account/name]
:transaction/payment [:db/id]}
])]
:in ['$ ]
:where []}
:args [(dc/db conn)]
:timeout 55000}
description
(merge-query {:query {:in ['?descr]
:where ['[(iol-ion.query/->pattern ?descr) ?description-regex]]}
:args [description]})
(let [query (cond-> {:query {:find ['(pull ?e [* {:transaction/client [:client/name]
:transaction/bank-account [:bank-account/name]
:transaction/payment [:db/id]}
])]
:in ['$ ]
:where []}
:args [(dc/db conn)]}
description
(merge-query {:query {:in ['?descr]
:where ['[(iol-ion.query/->pattern ?descr) ?description-regex]]}
:args [description]})
(limited-clients id)
(merge-query {:query {:in ['[?xx ...]]
:where ['[?e :transaction/client ?xx]]}
:args [(set (map :db/id (limited-clients id)))]})
(limited-clients id)
(merge-query {:query {:in ['[?xx ...]]
:where ['[?e :transaction/client ?xx]]}
:args [(set (map :db/id (limited-clients id)))]})
bank-account
(merge-query {:query {:in ['?bank-account-id]
:where ['[?e :transaction/bank-account ?bank-account-id]]}
:args [(:db/id bank-account)]})
bank-account
(merge-query {:query {:in ['?bank-account-id]
:where ['[?e :transaction/bank-account ?bank-account-id]]}
:args [(:db/id bank-account)]})
description
(merge-query {:query {:where ['[?e :transaction/description-original ?do]
'[(re-find ?description-regex ?do)]]}})
description
(merge-query {:query {:where ['[?e :transaction/description-original ?do]
'[(re-find ?description-regex ?do)]]}})
yodlee-merchant
(merge-query {:query {:in ['?yodlee-merchant-id]
:where ['[?e :transaction/yodlee-merchant ?yodlee-merchant-id]]}
:args [(:db/id yodlee-merchant)]})
yodlee-merchant
(merge-query {:query {:in ['?yodlee-merchant-id]
:where ['[?e :transaction/yodlee-merchant ?yodlee-merchant-id]]}
:args [(:db/id yodlee-merchant)]})
amount-gte
(merge-query {:query {:in ['?amount-gte]
:where ['[?e :transaction/amount ?ta]
'[(>= ?ta ?amount-gte)]]}
:args [amount-gte]})
amount-gte
(merge-query {:query {:in ['?amount-gte]
:where ['[?e :transaction/amount ?ta]
'[(>= ?ta ?amount-gte)]]}
:args [amount-gte]})
amount-lte
(merge-query {:query {:in ['?amount-lte]
:where ['[?e :transaction/amount ?ta]
'[(<= ?ta ?amount-lte)]]}
:args [amount-lte]})
amount-lte
(merge-query {:query {:in ['?amount-lte]
:where ['[?e :transaction/amount ?ta]
'[(<= ?ta ?amount-lte)]]}
:args [amount-lte]})
dom-lte
(merge-query {:query {:in ['?dom-lte]
:where ['[?e :transaction/date ?transaction-date]
'[(iol-ion.query/dom ?transaction-date) ?dom]
'[(<= ?dom ?dom-lte)]]}
:args [dom-lte]})
dom-lte
(merge-query {:query {:in ['?dom-lte]
:where ['[?e :transaction/date ?transaction-date]
'[(iol-ion.query/dom ?transaction-date) ?dom]
'[(<= ?dom ?dom-lte)]]}
:args [dom-lte]})
dom-gte
(merge-query {:query {:in ['?dom-gte]
:where ['[?e :transaction/date ?transaction-date]
'[(iol-ion.query/dom ?transaction-date) ?dom]
'[(>= ?dom ?dom-gte)]]}
:args [dom-gte]})
dom-gte
(merge-query {:query {:in ['?dom-gte]
:where ['[?e :transaction/date ?transaction-date]
'[(iol-ion.query/dom ?transaction-date) ?dom]
'[(>= ?dom ?dom-gte)]]}
:args [dom-gte]})
client
(merge-query {:query {:in ['?client-id]
:where ['[?e :transaction/client ?client-id]]}
:args [(:db/id client)]})
client
(merge-query {:query {:in ['?client-id]
:where ['[?e :transaction/client ?client-id]]}
:args [(:db/id client)]})
(not include-coded?)
(merge-query {:query {:where ['[or [?e :transaction/approval-status :transaction-approval-status/unapproved]
[(missing? $ ?e :transaction/approval-status)]]]}})
(not include-coded?)
(merge-query {:query {:where ['[or [?e :transaction/approval-status :transaction-approval-status/unapproved]
[(missing? $ ?e :transaction/approval-status)]]]}})
true
(merge-query {:query {:where ['[?e :transaction/id]]}})))
(transduce (comp
(take (or count 15))
(map first)
(map #(dissoc % :transaction/id))
(map (fn [x]
(update x :transaction/date c/from-date)))
(map ->graphql))
conj [])))
true
(merge-query {:query {:where ['[?e :transaction/id]]}}))]
(->>
(query2 query)
(transduce (comp
(take (or count 15))
(map first)
(map #(dissoc % :transaction/id))
(map (fn [x]
(update x :transaction/date c/from-date)))
(map ->graphql))
conj []))))
(defn test-transaction-rule [{:keys [id]} {{:keys [description client_id bank_account_id amount_lte amount_gte dom_lte dom_gte yodlee_merchant_id]} :transaction_rule} _]
(assert-admin id)

View File

@@ -25,8 +25,8 @@
[clojure.set :as set]
[clojure.string :as str]
[clojure.tools.logging :as log]
[datomic.client.api :as dc]
[iol-ion.tx :refer [random-tempid upsert-transaction]]
[datomic.api :as dc]
[iol-ion.tx :refer [random-tempid]]
[com.brunobonacci.mulog :as mu]))
(def approval-status->graphql (ident->enum-f :transaction/approval-status))
@@ -92,8 +92,8 @@
(audit-transact-batch
(->> all-ids
(mapv (fn [t]
`(upsert-transaction ~{:db/id t
:transaction/approval-status (enum->keyword (:status args) "transaction-approval-status")}))))
[:upsert-transaction {:db/id t
:transaction/approval-status (enum->keyword (:status args) "transaction-approval-status")}])))
(:id context))
{:message (str "Succesfully changed " (count all-ids) " transactions to be " (name (:status args) ) ".")}))
@@ -172,10 +172,10 @@
(log/info "Bulk coding " (count all-ids) args)
(audit-transact-batch
(map (fn [i]
`(upsert-transaction ~(cond-> i
(:approval_status args) (assoc :transaction/approval-status (enum->keyword (:approval_status args) "transaction-approval-status"))
(:vendor args) (assoc :transaction/vendor (:vendor args))
(seq (:accounts args)) (assoc :transaction/accounts (maybe-code-accounts i (:accounts args) locations)))))
[:upsert-transaction (cond-> i
(:approval_status args) (assoc :transaction/approval-status (enum->keyword (:approval_status args) "transaction-approval-status"))
(:vendor args) (assoc :transaction/vendor (:vendor args))
(seq (:accounts args)) (assoc :transaction/accounts (maybe-code-accounts i (:accounts args) locations)))])
transactions)
(:id context))
{:message (str "Successfully coded " (count all-ids) " transactions.")}))
@@ -252,13 +252,12 @@
(assert-not-locked (:db/id (:transaction/client transaction)) (-> transaction :transaction/payment :payment/date)))
_ (log/info "Unlinking" transaction)
payment (-> transaction :transaction/payment )
is-autopay-payment? (some->> (doto (dc/q {:query {:find ['?sp]
:in ['$ '?payment]
:where ['[?ip :invoice-payment/payment ?payment]
'[?ip :invoice-payment/invoice ?i]
'[(get-else $ ?i :invoice/scheduled-payment "N/A") ?sp]]}
:args [(dc/db conn) (:db/id payment)]})
log/info)
is-autopay-payment? (some->> (dc/q {:find ['?sp]
:in ['$ '?payment]
:where ['[?ip :invoice-payment/payment ?payment]
'[?ip :invoice-payment/invoice ?i]
'[(get-else $ ?i :invoice/scheduled-payment "N/A") ?sp]]}
(dc/db conn) (:db/id payment))
seq
(map first)
(every? #(instance? java.util.Date %)))
@@ -273,33 +272,34 @@
(audit-transact
(-> [{:db/id (:db/id payment)
:payment/status :payment-status/pending}
`(upsert-transaction
~{:db/id transaction-id
:transaction/approval-status :transaction-approval-status/unapproved
:transaction/payment nil
:transaction/vendor nil
:transaction/location nil
:transaction/accounts nil})
[:upsert-transaction
{:db/id transaction-id
:transaction/approval-status :transaction-approval-status/unapproved
:transaction/payment nil
:transaction/vendor nil
:transaction/location nil
:transaction/accounts nil}]
[:db/retractEntity (:db/id payment) ]]
(into (map (fn [[invoice-payment]]
[:db/retractEntity invoice-payment])
(dc/q {:query {:find ['?ip]
:in ['$ '?p]
:where ['[?ip :invoice-payment/payment ?p]]}
:args [(dc/db conn) (:db/id payment)]} ))))
(dc/q {:find ['?ip]
:in ['$ '?p]
:where ['[?ip :invoice-payment/payment ?p]]}
(dc/db conn)
(:db/id payment) ))))
(:id context))
(audit-transact
[{:db/id (:db/id payment)
:payment/status :payment-status/pending}
`(upsert-transaction
~{:db/id transaction-id
:transaction/approval-status :transaction-approval-status/unapproved
:transaction/payment nil
:transaction/vendor nil
:transaction/location nil
:transaction/accounts nil})]
[:upsert-transaction
{:db/id transaction-id
:transaction/approval-status :transaction-approval-status/unapproved
:transaction/payment nil
:transaction/vendor nil
:transaction/location nil
:transaction/accounts nil}]]
(:id context)))
(-> (d-transactions/get-by-id transaction-id)
approval-status->graphql
@@ -360,14 +360,14 @@
(when missing-locations
(throw (ex-info (str "Location '" (str/join ", " missing-locations) "' not found on client.") {})) )
(audit-transact [`(upsert-transaction ~{:db/id id
:transaction/vendor vendor_id
:transaction/approval-status (some->> approval_status
name
snake->kebab
(keyword "transaction-approval-status"))
:transaction/accounts (map transaction-account->entity accounts)
:transaction/forecast-match forecast_match})]
(audit-transact [[:upsert-transaction {:db/id id
:transaction/vendor vendor_id
:transaction/approval-status (some->> approval_status
name
snake->kebab
(keyword "transaction-approval-status"))
:transaction/accounts (map transaction-account->entity accounts)
:transaction/forecast-match forecast_match}]]
(:id context))
(-> (d-transactions/get-by-id id)
approval-status->graphql
@@ -392,16 +392,16 @@
:payment/date (coerce/to-date (first (sort [(:payment/date payment)
(:transaction/date transaction)])))}
`(upsert-transaction
~{:db/id (:db/id transaction)
:transaction/payment (:db/id payment)
:transaction/vendor (:db/id (:payment/vendor payment))
:transaction/location "A"
:transaction/approval-status :transaction-approval-status/approved
:transaction/accounts [{:db/id (random-tempid)
:transaction-account/account (:db/id (a/get-account-by-numeric-code-and-sets 21000 ["default"]))
:transaction-account/location "A"
:transaction-account/amount (Math/abs (:transaction/amount transaction))}]})])
[:upsert-transaction
{:db/id (:db/id transaction)
:transaction/payment (:db/id payment)
:transaction/vendor (:db/id (:payment/vendor payment))
:transaction/location "A"
:transaction/approval-status :transaction-approval-status/approved
:transaction/accounts [{:db/id (random-tempid)
:transaction-account/account (:db/id (a/get-account-by-numeric-code-and-sets 21000 ["default"]))
:transaction-account/location "A"
:transaction-account/amount (Math/abs (:transaction/amount transaction))}]}]])
(:id context)))
(-> (d-transactions/get-by-id transaction_id)
approval-status->graphql
@@ -509,13 +509,13 @@
(throw (ex-info "Transaction already associated with a payment" {:validation-error "Transaction already associated with a payment"}))))
(audit-transact (mapv (fn [t]
`(upsert-transaction
~(remove-nils (rm/apply-rule {:db/id (:db/id t)
:transaction/amount (:transaction/amount t)}
transaction-rule
[:upsert-transaction
(remove-nils (rm/apply-rule {:db/id (:db/id t)
:transaction/amount (:transaction/amount t)}
transaction-rule
(or (-> t :transaction/bank-account :bank-account/locations)
(-> t :transaction/client :client/locations))))))
(or (-> t :transaction/bank-account :bank-account/locations)
(-> t :transaction/client :client/locations))))])
transactions)
(:id context))
)

View File

@@ -4,7 +4,7 @@
[clj-time.coerce :as coerce]
[auto-ap.time :as atime]
[buddy.auth :refer [throw-unauthorized]]
[datomic.client.api :as dc]
[datomic.api :as dc]
[clojure.walk :as walk]
[com.walmartlabs.lacinia.util :refer [attach-resolvers]]
[clojure.tools.logging :as log]

View File

@@ -1,7 +1,7 @@
(ns auto-ap.graphql.vendors
(:require
[auto-ap.datomic :refer [audit-transact conn pull-attr remove-nils]]
[iol-ion.tx :refer [upsert-entity random-tempid]]
[iol-ion.tx :refer [random-tempid]]
[auto-ap.datomic.vendors :as d-vendors]
[auto-ap.graphql.utils
:refer [->graphql
@@ -19,7 +19,7 @@
[manifold.executor :as ex]
[manifold.deferred :as de]
[clojure.tools.logging :as log]
[datomic.client.api :as dc]
[datomic.api :as dc]
[yang.scheduler :as scheduler]
[mount.core :as mount]
[clj-time.core :as time]
@@ -87,55 +87,55 @@
:dom (:dom ao)
:db/id (or (:id ao) (random-tempid))})
schedule_payment_dom)
transaction `(upsert-entity ~(cond-> #:vendor {:db/id (if id
id
"vendor")
:name name
:code code
:hidden hidden
:terms terms
:print-as print_as
:default-account default_account_id
:invoice-reminder-schedule (keyword invoice_reminder_schedule)
:address (when address
(remove-nils #:address {:db/id (if (:id address)
(:id address)
"address")
:street1 (:street1 address)
:street2 (:street2 address)
:city (:city address)
:state (:state address)
:zip (:zip address)}))
:primary-contact (when primary_contact
transaction [:upsert-entity (cond-> #:vendor {:db/id (if id
id
"vendor")
:name name
:code code
:hidden hidden
:terms terms
:print-as print_as
:default-account default_account_id
:invoice-reminder-schedule (keyword invoice_reminder_schedule)
:address (when address
(remove-nils #:address {:db/id (if (:id address)
(:id address)
"address")
:street1 (:street1 address)
:street2 (:street2 address)
:city (:city address)
:state (:state address)
:zip (:zip address)}))
:primary-contact (when primary_contact
(remove-nils #:contact {:db/id (if (:id primary_contact)
(:id primary_contact)
"primary")
:name (:name primary_contact)
:phone (:phone primary_contact)
:email (:email primary_contact)}))
:secondary-contact (when secondary_contact
(remove-nils #:contact {:db/id (if (:id primary_contact)
(:id primary_contact)
"primary")
:name (:name primary_contact)
:phone (:phone primary_contact)
:email (:email primary_contact)}))
:secondary-contact (when secondary_contact
(remove-nils #:contact {:db/id (if (:id secondary_contact)
(:id secondary_contact)
"secondary")
:name (:name secondary_contact)
:phone (:phone secondary_contact)
:email (:email secondary_contact)})
)
:search-terms [name]}
(is-admin? (:id context)) (assoc
:vendor/legal-entity-name (:legal_entity_name in)
:vendor/legal-entity-first-name (:legal_entity_first_name in)
:vendor/legal-entity-middle-name (:legal_entity_middle_name in)
:vendor/legal-entity-last-name (:legal_entity_last_name in)
:vendor/legal-entity-tin (:legal_entity_tin in)
:vendor/legal-entity-tin-type (enum->keyword (:legal_entity_tin_type in) "legal-entity-tin-type")
:vendor/legal-entity-1099-type (enum->keyword (:legal_entity_1099_type in) "legal-entity-1099-type")
:vendor/account-overrides account-overrides
:vendor/terms-overrides terms-overrides
:vendor/schedule-payment-dom schedule-payment-dom
:vendor/automatically-paid-when-due (:automatically_paid_when_due in))))
(remove-nils #:contact {:db/id (if (:id secondary_contact)
(:id secondary_contact)
"secondary")
:name (:name secondary_contact)
:phone (:phone secondary_contact)
:email (:email secondary_contact)})
)
:search-terms [name]}
(is-admin? (:id context)) (assoc
:vendor/legal-entity-name (:legal_entity_name in)
:vendor/legal-entity-first-name (:legal_entity_first_name in)
:vendor/legal-entity-middle-name (:legal_entity_middle_name in)
:vendor/legal-entity-last-name (:legal_entity_last_name in)
:vendor/legal-entity-tin (:legal_entity_tin in)
:vendor/legal-entity-tin-type (enum->keyword (:legal_entity_tin_type in) "legal-entity-tin-type")
:vendor/legal-entity-1099-type (enum->keyword (:legal_entity_1099_type in) "legal-entity-1099-type")
:vendor/account-overrides account-overrides
:vendor/terms-overrides terms-overrides
:vendor/schedule-payment-dom schedule-payment-dom
:vendor/automatically-paid-when-due (:automatically_paid_when_due in)))]
transaction-result (audit-transact [transaction] (:id context))]
@@ -145,11 +145,12 @@
(->graphql))))
(defn merge-vendors [context {:keys [from to]} _]
(let [transaction (->> (dc/q {:query {:find '[?x ?a2]
:in '[$ ?vendor-from ]
:where ['[?x ?a ?vendor-from]
'[?a :db/ident ?a2]]}
:args [(dc/db conn) from]})
(let [transaction (->> (dc/q {:find '[?x ?a2]
:in '[$ ?vendor-from ]
:where ['[?x ?a ?vendor-from]
'[?a :db/ident ?a2]]}
(dc/db conn)
from)
(mapcat (fn [[src attr]]
[[:db/retract src attr from]
@@ -195,10 +196,10 @@
(de/future-with
single-thread
(search/full-index-query
(for [[result] (dc/qseq '[:find (pull ?v [:vendor/search-terms :db/id :vendor/name :vendor/hidden])
:in $
:where [?v :vendor/search-terms ]]
(dc/db conn))]
(for [[result] (dc/qseq {:query '[:find (pull ?v [:vendor/search-terms :db/id :vendor/name :vendor/hidden])
:in $
:where [?v :vendor/search-terms ]]
:args [(dc/db conn)]})]
{:id (:db/id result)
:text (or (first (:vendor/search-terms result))
(:vendor/name result))
@@ -216,12 +217,11 @@
_ (mu/log ::indexing
:last-run last-run-basis-value
:starting-from (:basisT db))
results (for [[result] (dc/qseq '[:find (pull ?v [:vendor/search-terms :db/id :vendor/name :vendor/hidden])
:in $ $$
:where [$ ?v :vendor/name ]
[$$ ?v]]
db
recent)]
results (for [[result] (dc/qseq {:query '[:find (pull ?v [:vendor/search-terms :db/id :vendor/name :vendor/hidden])
:in $ $$
:where [$ ?v :vendor/name ]
[$$ ?v]]
:args [db recent]})]
{:id (:db/id result)
:text (or (first (:vendor/search-terms result))
(:vendor/name result))

View File

@@ -2,7 +2,7 @@
(:require
[auto-ap.datomic :refer [conn pull-ref random-tempid]]
[clojure.tools.logging :as log]
[datomic.client.api :as dc]))
[datomic.api :as dc]))
(defn bank-account->integration-id [bank-account]
(or (pull-ref (dc/db conn) :bank-account/integration-status bank-account)
@@ -11,19 +11,19 @@
(defn wrap-integration [f bank-account]
(try
(let [result (f)]
(dc/transact conn {:tx-data [{:db/id bank-account
:bank-account/integration-status
{:db/id (bank-account->integration-id bank-account)
:integration-status/state :integration-state/success
:integration-status/last-attempt (java.util.Date.)
:integration-status/last-updated (java.util.Date.)}}]})
@(dc/transact conn [{:db/id bank-account
:bank-account/integration-status
{:db/id (bank-account->integration-id bank-account)
:integration-status/state :integration-state/success
:integration-status/last-attempt (java.util.Date.)
:integration-status/last-updated (java.util.Date.)}}])
result)
(catch Exception e
(dc/transact conn {:tx-data [{:db/id bank-account
:bank-account/integration-status
{:db/id (bank-account->integration-id bank-account)
:integration-status/state :integration-state/failed
:integration-status/last-attempt (java.util.Date.)
:integration-status/message (.getMessage e)}}]})
@(dc/transact conn [{:db/id bank-account
:bank-account/integration-status
{:db/id (bank-account->integration-id bank-account)
:integration-status/state :integration-state/failed
:integration-status/last-attempt (java.util.Date.)
:integration-status/message (.getMessage e)}}])
(log/warn e)
nil)))

View File

@@ -10,7 +10,7 @@
[clojure.string :as str]
[clojure.tools.logging :as log]
[com.unbounce.dogstatsd.core :as statsd]
[datomic.client.api :as dc]
[datomic.api :as dc]
[mount.core :as mount]
[yang.scheduler :as scheduler]))
@@ -78,8 +78,8 @@
(defn upsert-accounts []
(let [token (i/get-fresh-access-token)
bank-accounts (i/get-bank-accounts token)]
(dc/transact conn {:tx-data (mapv
(fn [ba]
{:intuit-bank-account/external-id (:name ba)
:intuit-bank-account/name (:name ba)})
bank-accounts)})))
@(dc/transact conn (mapv
(fn [ba]
{:intuit-bank-account/external-id (:name ba)
:intuit-bank-account/name (:name ba)})
bank-accounts))))

View File

@@ -5,7 +5,7 @@
[auto-ap.import.transactions :as t]
[clj-time.coerce :as coerce]
[clojure.data.csv :as csv]
[datomic.client.api :as dc]
[datomic.api :as dc]
[unilog.context :as lc]))

View File

@@ -8,7 +8,7 @@
[auto-ap.utils :refer [allow-once by]]
[clj-time.coerce :as coerce]
[clj-time.core :as time]
[datomic.client.api :as dc]
[datomic.api :as dc]
[digest :as di]
[unilog.context :as lc]))

View File

@@ -12,9 +12,8 @@
[clj-time.core :as t]
[clojure.core.cache :as cache]
[clojure.tools.logging :as log]
[datomic.client.api :as dc]
[digest :as di]
[iol-ion.tx :refer [upsert-invoice upsert-transaction]]))
[datomic.api :as dc]
[digest :as di]))
(defn rough-match [client-id bank-account-id amount]
(if (and client-id bank-account-id amount)
@@ -56,15 +55,15 @@
(defn match-transaction-to-unfulfilled-autopayments [amount client-id]
(log/info "trying to find uncleared autopay invoices")
(let [candidate-invoices-vendor-groups (->> (dc/q {:query {:find ['?vendor-id '?e '?total '?sd]
:in ['$ '?client-id]
:where ['[?e :invoice/client ?client-id]
'[?e :invoice/scheduled-payment ?sd]
'[?e :invoice/status :invoice-status/paid]
'(not [_ :invoice-payment/invoice ?e])
'[?e :invoice/vendor ?vendor-id]
'[?e :invoice/total ?total]]}
:args [(dc/db conn) client-id]})
(let [candidate-invoices-vendor-groups (->> (dc/q {:find ['?vendor-id '?e '?total '?sd]
:in ['$ '?client-id]
:where ['[?e :invoice/client ?client-id]
'[?e :invoice/scheduled-payment ?sd]
'[?e :invoice/status :invoice-status/paid]
'(not [_ :invoice-payment/invoice ?e])
'[?e :invoice/vendor ?vendor-id]
'[?e :invoice/total ?total]]}
(dc/db conn) client-id)
(sort-by last) ;; sort by scheduled payment date
(group-by first) ;; group by vendors
vals)
@@ -81,15 +80,15 @@
(defn match-transaction-to-unpaid-invoices [amount client-id]
(log/info "trying to find unpaid invoices for " client-id amount)
(let [candidate-invoices-vendor-groups (->> (dc/q {:query {:find ['?vendor-id '?e '?outstanding-balance '?d]
:in ['$ '?client-id]
:where ['[?e :invoice/client ?client-id]
'[?e :invoice/status :invoice-status/unpaid]
'(not [_ :invoice-payment/invoice ?e])
'[?e :invoice/vendor ?vendor-id]
'[?e :invoice/outstanding-balance ?outstanding-balance]
'[?e :invoice/date ?d]]}
:args [(dc/db conn) client-id]})
(let [candidate-invoices-vendor-groups (->> (dc/q {:find ['?vendor-id '?e '?outstanding-balance '?d]
:in ['$ '?client-id]
:where ['[?e :invoice/client ?client-id]
'[?e :invoice/status :invoice-status/unpaid]
'(not [_ :invoice-payment/invoice ?e])
'[?e :invoice/vendor ?vendor-id]
'[?e :invoice/outstanding-balance ?outstanding-balance]
'[?e :invoice/date ?d]]}
(dc/db conn) client-id)
(sort-by last) ;; sort by scheduled payment date
(group-by first) ;; group by vendors
vals)
@@ -112,33 +111,34 @@
(defn add-new-payment [transaction [[vendor] :as invoice-payments] bank-account-id client-id]
(log/info "Adding a new payment for transaction " (:transaction/id transaction) " and invoices " invoice-payments)
(let [payment-id (random-tempid)]
(-> [`(upsert-transaction ~(assoc transaction
:transaction/payment payment-id
:transaction/approval-status :transaction-approval-status/approved
:transaction/vendor vendor
:transaction/location "A"
:transaction/accounts
[#:transaction-account
{:db/id (random-tempid)
:account (:db/id (a/get-account-by-numeric-code-and-sets 21000 ["default"]))
:location "A"
:amount (Math/abs (:transaction/amount transaction))}]))]
(-> [[:upsert-transaction
(assoc transaction
:transaction/payment payment-id
:transaction/approval-status :transaction-approval-status/approved
:transaction/vendor vendor
:transaction/location "A"
:transaction/accounts
[#:transaction-account
{:db/id (random-tempid)
:account (:db/id (a/get-account-by-numeric-code-and-sets 21000 ["default"]))
:location "A"
:amount (Math/abs (:transaction/amount transaction))}])]]
(conj {:payment/bank-account bank-account-id
:payment/client client-id
:payment/amount (- (:transaction/amount transaction))
:payment/vendor vendor
:payment/date (:transaction/date transaction)
:payment/type :payment-type/debit
:payment/status :payment-status/cleared
:db/id payment-id})
:payment/client client-id
:payment/amount (- (:transaction/amount transaction))
:payment/vendor vendor
:payment/date (:transaction/date transaction)
:payment/type :payment-type/debit
:payment/status :payment-status/cleared
:db/id payment-id})
(into (mapcat (fn [[_ invoice-id invoice-amount]]
[{:invoice-payment/invoice invoice-id
:invoice-payment/payment payment-id
:invoice-payment/amount invoice-amount}
`(upsert-invoice ~{:db/id invoice-id
:invoice/outstanding-balance 0.0
:invoice/status :invoice-status/paid})])
[:upsert-invoice {:db/id invoice-id
:invoice/outstanding-balance 0.0
:invoice/status :invoice-status/paid}]])
invoice-payments)))))
(defn extract-check-number [{:transaction/keys [description-original]}]
@@ -293,11 +293,11 @@
:import-batch/not-ready 0
:import-batch/extant 0})
extant-cache (atom (cache/ttl-cache-factory {} :ttl 60000 ))
import-id (get (:tempids (dc/transact conn {:tx-data [{:db/id "import-batch"
:import-batch/date (coerce/to-date (t/now))
:import-batch/source source
:import-batch/status :import-status/started
:import-batch/user-name user}]})) "import-batch")
import-id (get (:tempids @(dc/transact conn [{:db/id "import-batch"
:import-batch/date (coerce/to-date (t/now))
:import-batch/source source
:import-batch/status :import-status/started
:import-batch/user-name user}])) "import-batch")
rule-applying-function (rm/rule-applying-fn (tr/get-all))]
(log/info "Importing transactions from " source)
@@ -317,7 +317,7 @@
:error :import-batch/error
:not-ready :import-batch/not-ready) inc))
(when (= :import action)
(audit-transact [`(upsert-transaction ~(transaction->txs transaction bank-account rule-applying-function))
(audit-transact [[:upsert-transaction (transaction->txs transaction bank-account rule-applying-function)]
{:db/id import-id
:import-batch/entry (:db/id transaction)}]
{:user/name user
@@ -329,14 +329,14 @@
(fail! [_ error]
(log/errorf "Couldn't complete import %d with error." import-id)
(log/error error)
(dc/transact conn {:tx-data [(merge {:db/id import-id
:import-batch/status :import-status/completed
:import-batch/error-message (str error)}
@stats)]}))
@(dc/transact conn [(merge {:db/id import-id
:import-batch/status :import-status/completed
:import-batch/error-message (str error)}
@stats)]))
(finish! [_]
(log/infof "Finishing import batch %d for %s with stats %s " import-id (name source) (pr-str @stats))
(dc/transact conn [(merge {:db/id import-id
@(dc/transact conn [(merge {:db/id import-id
:import-batch/status :import-status/completed}
@stats)])))))

View File

@@ -9,7 +9,7 @@
[clj-time.coerce :as coerce]
[clojure.string :as str]
[com.unbounce.dogstatsd.core :as statsd]
[datomic.client.api :as dc]
[datomic.api :as dc]
[digest :as di]
[unilog.context :as lc]))

View File

@@ -6,23 +6,23 @@
[auto-ap.time :as time]
[clj-time.coerce :as coerce]
[clojure.tools.logging :as log]
[datomic.client.api :as dc]))
[datomic.api :as dc]))
(defn close-auto-invoices []
(let [invoices-to-close (dc/q {:query {:find ['?e]
:in ['$ '?today]
:where ['[?e :invoice/scheduled-payment ?d]
'[?e :invoice/status :invoice-status/unpaid]
'[(<= ?d ?today)]]}
:args [(dc/db conn) (coerce/to-date (time/local-now))]})]
(let [invoices-to-close (dc/q {:find ['?e]
:in ['$ '?today]
:where ['[?e :invoice/scheduled-payment ?d]
'[?e :invoice/status :invoice-status/unpaid]
'[(<= ?d ?today)]]}
(dc/db conn) (coerce/to-date (time/local-now)))]
(log/info "Closing " (count invoices-to-close) "scheduled invoices")
(dc/transact conn {:tx-data (some->> invoices-to-close
seq
@(dc/transact conn (some->> invoices-to-close
seq
(mapv (fn [[i]] {:db/id i
:invoice/outstanding-balance 0.0
:invoice/status :invoice-status/paid}))
)})
(mapv (fn [[i]] {:db/id i
:invoice/outstanding-balance 0.0
:invoice/status :invoice-status/paid}))
))
(log/info "Closed " (count invoices-to-close) "scheduled invoices")))

View File

@@ -1,7 +1,7 @@
(ns auto-ap.jobs.core
(:require [auto-ap.utils :refer [heartbeat]]
[mount.core :as mount]
[auto-ap.datomic :refer [conn client]]
[auto-ap.datomic :refer [conn ]]
[clojure.tools.logging :as log]
[nrepl.server :refer [start-server]]
[auto-ap.background.metrics :refer [metrics-setup container-tags container-data logging-context]]
@@ -13,7 +13,7 @@
(lc/with-context {:background-job name}
(mu/with-context {:background-job name
:service name}
(mount/start (mount/only #{#'conn #'client #'metrics-setup #'container-tags #'logging-context #'container-data }))
(mount/start (mount/only #{#'conn #'metrics-setup #'container-tags #'logging-context #'container-data }))
(start-server :port 9000 :bind "0.0.0.0" #_#_:handler (cider-nrepl-handler))
((heartbeat f name))
(log/info "Stopping " name)

View File

@@ -11,7 +11,7 @@
[clj-time.periodic :as per]
[clojure.tools.logging :as log]
[config.core :refer [env]]
[datomic.client.api :as dc]
[datomic.api :as dc]
[unilog.context :as lc]))
#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}

View File

@@ -13,8 +13,8 @@
[clojure.string :as str]
[clojure.xml :as xml]
[clojure.zip :as zip]
[datomic.client.api :as d]
[iol-ion.tx :refer [propose-invoice random-tempid]])
[datomic.api :as d]
[iol-ion.tx :refer [random-tempid]])
(:import
(java.util UUID)))
@@ -249,7 +249,7 @@
:invoice i)
i))
(mapv (fn [i]
`(propose-invoice ~(assoc i :invoice/source-url invoice-url))))))) (catch Exception e
[:propose-invoice (assoc i :invoice/source-url invoice-url)]))))) (catch Exception e
(log/error ::cant-load-file
:key k
:exception e)

View File

@@ -12,7 +12,7 @@
[clojure.string :as str]
[clojure.tools.logging :as log]
[config.core :refer [env]]
[datomic.client.api :as dc])
[datomic.api :as dc])
(:import
(java.util UUID)))

View File

@@ -9,7 +9,7 @@
[clojure.set :as set]
[com.brunobonacci.mulog :as mu]
[config.core :refer [env]]
[datomic.client.api :as dc]
[datomic.api :as dc]
[lambdaisland.edn-lines :as ednl]
[manifold.deferred :as de]
[manifold.executor :as ex]
@@ -97,20 +97,20 @@
(let [schema (edn/read-string (slurp (pull-file backup-id "schema.edn")))
full-dependencies (edn/read-string (slurp (pull-file backup-id "full-dependencies.edn")))
entity-dependencies (edn/read-string (slurp (pull-file backup-id "entity-dependencies.edn")))]
(dc/transact connection {:tx-data [{:db/ident :entity/migration-key
:db/unique :db.unique/identity
:db/cardinality :db.cardinality/one
:db/valueType :db.type/long}]})
(dc/transact connection {:tx-data (map
(fn [s]
(set/rename-keys s {:db/id :entity/migration-key}))
schema)})
@(dc/transact connection [{:db/ident :entity/migration-key
:db/unique :db.unique/identity
:db/cardinality :db.cardinality/one
:db/valueType :db.type/long}])
@(dc/transact connection (map
(fn [s]
(set/rename-keys s {:db/id :entity/migration-key}))
schema))
;; TEMP - this has been fixed in current export (ezcater-olaciotn)
(dc/transact connection {:tx-data [{:entity/migration-key 17592257603901 :vendor/name "unknown"}
{:entity/migration-key 17592232621701}
{:entity/migration-key 17592263907739}
{:entity/migration-key 17592271516922}]})
@(dc/transact connection [{:entity/migration-key 17592257603901 :vendor/name "unknown"}
{:entity/migration-key 17592232621701}
{:entity/migration-key 17592263907739}
{:entity/migration-key 17592271516922}])
(doseq [entity (cond->> (order-of-insert entity-dependencies)

View File

@@ -6,7 +6,6 @@
[auto-ap.datomic :refer [audit-transact]]
[auto-ap.datomic.clients :as d-clients]
[auto-ap.datomic.invoices :refer [code-invoice]]
[iol-ion.tx :refer [propose-invoice]]
[auto-ap.parse :as parse]
[auto-ap.time :as t]
[clj-time.coerce :as coerce]
@@ -16,7 +15,7 @@
[clojure.tools.logging :as log]
[com.unbounce.dogstatsd.core :as statsd]
[config.core :refer [env]]
[datomic.client.api :as dc]
[datomic.api :as dc]
[auto-ap.datomic.vendors :as d-vendors])
(:import
(java.util UUID)))
@@ -134,11 +133,11 @@
:destination-bucket-name (:data-bucket env)
:source-key k
:destination-key invoice-key})
[`(propose-invoice
~(-> k
[[:propose-invoice
(-> k
read-sysco-csv
(extract-invoice-details sysco-vendor)
(assoc :invoice/source-url invoice-url)))])
(assoc :invoice/source-url invoice-url))]])
(catch Exception e
(log/error (str "Cannot load file " k) e)
(log/info

View File

@@ -3,29 +3,29 @@
(:require
[auto-ap.datomic :refer [conn]]
[auto-ap.jobs.core :refer [execute]]
[datomic.client.api :as dc]))
[datomic.api :as dc]))
(defn refresh-vendor-usages []
(dc/transact conn {:tx-data (->> (dc/q '[:find ?v ?c (count ?e)
:in $
:where
[?v :vendor/name]
(or-join [?v ?c ?e]
(and
[?e :invoice/vendor ?v]
[?e :invoice/client ?c])
(and
[?e :transaction/vendor ?v]
[?e :transaction/client ?c])
(and
[?e :journal-entry/vendor ?v]
[?e :journal-entry/client ?c]))]
(dc/db conn))
(map (fn [[v c cnt]]
#:vendor-usage {:vendor v
:client c
:key (str v "-" c)
:count cnt})))}))
@(dc/transact conn (->> (dc/q '[:find ?v ?c (count ?e)
:in $
:where
[?v :vendor/name]
(or-join [?v ?c ?e]
(and
[?e :invoice/vendor ?v]
[?e :invoice/client ?c])
(and
[?e :transaction/vendor ?v]
[?e :transaction/client ?c])
(and
[?e :journal-entry/vendor ?v]
[?e :journal-entry/client ?c]))]
(dc/db conn))
(map (fn [[v c cnt]]
#:vendor-usage {:vendor v
:client c
:key (str v "-" c)
:count cnt})))))
(defn -main [& _]
(execute "vendor-usages" refresh-vendor-usages))

View File

@@ -6,8 +6,7 @@
[clj-time.core :as t]
[com.brunobonacci.mulog :as mu]
[com.unbounce.dogstatsd.core :as statsd]
[datomic.client.api :as dc]
[iol-ion.tx :refer [upsert-invoice upsert-ledger upsert-transaction]]
[datomic.api :as dc]
[manifold.deferred :as de]
[manifold.stream :as s]
[mount.core :as mount]
@@ -18,57 +17,57 @@
(t/plus (t/months -6))
(c/to-date))))
([start-date]
(let [txes-missing-ledger-entries (->> (dc/q {:query {:find ['?t ]
:in ['$ '?sd]
:where [
'[?t :transaction/date ?d]
'[(>= ?d ?sd)]
'(not [_ :journal-entry/original-entity ?t])
'(not [?t :transaction/amount 0.0])
'(not [?t :transaction/approval-status :transaction-approval-status/excluded])
'(not [?t :transaction/approval-status :transaction-approval-status/suppressed])
]}
:args [(dc/db conn) start-date]})
(let [txes-missing-ledger-entries (->> (dc/q {:find ['?t ]
:in ['$ '?sd]
:where [
'[?t :transaction/date ?d]
'[(>= ?d ?sd)]
'(not [_ :journal-entry/original-entity ?t])
'(not [?t :transaction/amount 0.0])
'(not [?t :transaction/approval-status :transaction-approval-status/excluded])
'(not [?t :transaction/approval-status :transaction-approval-status/suppressed])
]}
(dc/db conn) start-date)
(map first)
(mapv (fn [t]
`(upsert-transaction ~{:db/id t}))))
[:upsert-transaction {:db/id t}])))
invoices-missing-ledger-entries (->> (dc/q {:query {:find ['?t ]
:in ['$ '?sd]
:where ['[?t :invoice/date ?d]
'[(>= ?d ?sd)]
'(not [_ :journal-entry/original-entity ?t])
'[?t :invoice/total ?amt]
'[(not= 0.0 ?amt)]
'(not [?t :invoice/status :invoice-status/voided])
'(not [?t :invoice/import-status :import-status/pending])
'(not [?t :invoice/exclude-from-ledger true])
]}
:args [(dc/db conn) start-date]})
invoices-missing-ledger-entries (->> (dc/q {:find ['?t ]
:in ['$ '?sd]
:where ['[?t :invoice/date ?d]
'[(>= ?d ?sd)]
'(not [_ :journal-entry/original-entity ?t])
'[?t :invoice/total ?amt]
'[(not= 0.0 ?amt)]
'(not [?t :invoice/status :invoice-status/voided])
'(not [?t :invoice/import-status :import-status/pending])
'(not [?t :invoice/exclude-from-ledger true])
]}
(dc/db conn) start-date)
(map first)
(mapv (fn [i]
`(upsert-invoice ~{:db/id i}))))
[:upsert-invoice {:db/id i}])))
repairs (vec (concat txes-missing-ledger-entries invoices-missing-ledger-entries))]
(when (seq repairs)
(mu/log ::ledger-repairs-needed
:sample (take 3 repairs)
:transaction-count (count txes-missing-ledger-entries)
:invoice-count (count invoices-missing-ledger-entries))
(dc/transact conn {:tx-data (map (fn [repair]
`(upsert-ledger ~repair))
repairs) })))))
@(dc/transact conn (map (fn [repair]
[:upsert-ledger repair])
repairs))))))
(defn touch-transaction [e]
(dc/transact conn {:tx-data [{:db/id "datomic.tx"
:db/doc "touching transaction to update ledger"}
`(upsert-transaction ~{:db/id e})]}))
@(dc/transact conn [{:db/id "datomic.tx"
:db/doc "touching transaction to update ledger"}
[:upsert-transaction {:db/id e}]]))
(defn touch-invoice [e]
(dc/transact conn {:tx-data [{:db/id "datomic.tx"
:db/doc "touching invoice to update ledger"}
`(upsert-invoice ~{:db/id e})]}))
@(dc/transact conn [{:db/id "datomic.tx"
:db/doc "touching invoice to update ledger"}
[:upsert-invoice {:db/id e}]]))
@@ -297,19 +296,19 @@
(defn build-account-lookup [client-id]
(let [accounts (by :db/id (map first (dc/q {:query {:find ['(pull ?e [:db/id :account/name
:account/numeric-code
{:account/type [:db/ident]
:account/client-overrides [:account-client-override/client :account-client-override/name]}
])]
:in ['$]
:where ['[?e :account/name]]}
:args [(dc/db conn )]})))
(let [accounts (by :db/id (map first (dc/q {:find ['(pull ?e [:db/id :account/name
:account/numeric-code
{:account/type [:db/ident]
:account/client-overrides [:account-client-override/client :account-client-override/name]}
])]
:in ['$]
:where ['[?e :account/name]]}
(dc/db conn ))))
bank-accounts (by :db/id (map first (dc/q {:query {:find ['(pull ?e [:db/id :bank-account/name :bank-account/numeric-code {:bank-account/type [:db/ident]}])]
:in ['$]
:where ['[?e :bank-account/name]]}
:args [(dc/db conn)]})))
bank-accounts (by :db/id (map first (dc/q {:find ['(pull ?e [:db/id :bank-account/name :bank-account/numeric-code {:bank-account/type [:db/ident]}])]
:in ['$]
:where ['[?e :bank-account/name]]}
(dc/db conn))))
overrides-by-client (->> accounts
vals
(mapcat (fn [a]
@@ -344,10 +343,10 @@
:client-count (count clients)}
(mu/log ::reseting-index)
(let [so-far (atom 0)]
@(->> (dc/qseq '[:find (pull ?je [:journal-entry/date :journal-entry/client {:journal-entry/line-items [:journal-entry-line/account :journal-entry-line/location :db/id]}])
:in $ ?c
:where [?je :journal-entry/client ?c]]
(dc/db conn)
@(->> (dc/qseq {:query '[:find (pull ?je [:journal-entry/date :journal-entry/client {:journal-entry/line-items [:journal-entry-line/account :journal-entry-line/location :db/id]}])
:in $ ?c
:where [?je :journal-entry/client ?c]]
:args [(dc/db conn)]}
client)
(map first)
(mapcat (fn [je]
@@ -402,17 +401,16 @@
(defn accounts-needing-rebuild [ db client]
(let [client (pull-id db client)]
(->> (dc/qseq '[:find ?c ?a ?l (min ?d)
:in $ ?c
:where
[?jel :journal-entry-line/dirty true]
[?jel :journal-entry-line/account ?a]
[?jel :journal-entry-line/location ?l]
[?je :journal-entry/line-items ?jel]
[?je :journal-entry/client ?c]
[?je :journal-entry/date ?d]]
db
client)
(->> (dc/qseq {:query '[:find ?c ?a ?l (min ?d)
:in $ ?c
:where
[?jel :journal-entry-line/dirty true]
[?jel :journal-entry-line/account ?a]
[?jel :journal-entry-line/location ?l]
[?je :journal-entry/line-items ?jel]
[?je :journal-entry/client ?c]
[?je :journal-entry/date ?d]]
:args [db client]})
(map (fn [[client account location starting-at ]]
{:client client
:account account
@@ -421,16 +419,15 @@
(defn all-accounts-needing-rebuild [ db client]
(let [client (pull-id db client)]
(->> (dc/qseq '[:find ?c ?a ?l (min ?d)
:in $ ?c
:where
[?je :journal-entry/client ?c]
[?je :journal-entry/line-items ?jel]
[?jel :journal-entry-line/account ?a]
[?jel :journal-entry-line/location ?l]
[?je :journal-entry/date ?d]]
db
client)
(->> (dc/qseq {:query '[:find ?c ?a ?l (min ?d)
:in $ ?c
:where
[?je :journal-entry/client ?c]
[?je :journal-entry/line-items ?jel]
[?jel :journal-entry-line/account ?a]
[?jel :journal-entry-line/location ?l]
[?je :journal-entry/date ?d]]
:args [db client]})
(map (fn [[client account location starting-at ]]
{:client client
:account account

View File

@@ -11,7 +11,7 @@
[clojure.string :as str]
[clojure.tools.logging :as log]
[config.core :refer [env]]
[datomic.client.api :as dc])
[datomic.api :as dc])
(:import
(java.io ByteArrayOutputStream)
(java.text DecimalFormat)
@@ -342,15 +342,15 @@
:input-stream (io/make-input-stream pdf-data {})
:metadata {:content-length (count pdf-data)
:content-type "application/pdf"})
(dc/transact conn
{:tx-data [{:report/name name
:report/client (:client_ids args)
:report/key key
:report/url url
:report/creator (:user user)
:report/created (java.util.Date.)}]})
@(dc/transact conn
[{:report/name name
:report/client (:client_ids args)
:report/key key
:report/url url
:report/creator (:user user)
:report/created (java.util.Date.)}])
{:report/name name
:report/url url }))
:report/url url }))
(defn print-cash-flows [user args data]
(let [uuid (str (UUID/randomUUID))
@@ -363,13 +363,13 @@
:input-stream (io/make-input-stream pdf-data {})
:metadata {:content-length (count pdf-data)
:content-type "application/pdf"})
(dc/transact conn
{:tx-data [{:report/name name
:report/client (:client_ids args)
:report/key key
:report/url url
:report/creator (:user user)
:report/created (java.util.Date.)}]})
@(dc/transact conn
[{:report/name name
:report/client (:client_ids args)
:report/key key
:report/url url
:report/creator (:user user)
:report/created (java.util.Date.)}])
{:report/name name
:report/url url }))
@@ -384,14 +384,13 @@
:input-stream (io/make-input-stream pdf-data {})
:metadata {:content-length (count pdf-data)
:content-type "application/pdf"})
(dc/transact conn
{:tx-data
[{:report/name name
:report/client [(:client_id args)]
:report/key key
:report/url url
:report/creator (:user user)
:report/created (java.util.Date.)}]})
@(dc/transact conn
[{:report/name name
:report/client [(:client_id args)]
:report/key key
:report/url url
:report/creator (:user user)
:report/created (java.util.Date.)}])
{:report/name name
:report/url url }))
@@ -406,13 +405,12 @@
:input-stream (io/make-input-stream pdf-data {})
:metadata {:content-length (count pdf-data)
:content-type "application/pdf"})
(dc/transact conn
{:tx-data
[{:report/name name
:report/client (:client_ids args)
:report/key key
:report/url url
:report/creator (:user user)
:report/created (java.util.Date.)}]})
@(dc/transact conn
[{:report/name name
:report/client (:client_ids args)
:report/key key
:report/url url
:report/creator (:user user)
:report/created (java.util.Date.)}])
{:report/name name
:report/url url }))

View File

@@ -19,7 +19,7 @@
[clojure.tools.logging :as log]
[com.unbounce.dogstatsd.core :as statsd]
[config.core :refer [env]]
[datomic.client.api :as dc]
[datomic.api :as dc]
[ring.middleware.json :refer [wrap-json-response]]
[venia.core :as venia]))
@@ -35,18 +35,18 @@
identity (jwt/unsign (get query-params "key") (:jwt-secret env) {:alg :hs512})]
(assert-can-see-client identity client-id)
(into (list)
(dc/q {:query {:find '[?d4 (sum ?total) (sum ?tax) (sum ?tip) (sum ?service-charge)]
:in '[$ ?c]
:where '[[?s :sales-order/client ?c]
[?s :sales-order/date ?d]
[?s :sales-order/total ?total]
[?s :sales-order/tax ?tax]
[?s :sales-order/tip ?tip]
[?s :sales-order/service-charge ?service-charge]
[(clj-time.coerce/to-date-time ?d) ?d2]
[(auto-ap.time/localize ?d2) ?d3]
[(auto-ap.time/unparse ?d3 auto-ap.time/normal-date) ?d4]]}
:args [(dc/db conn) client-id]}))))
(dc/q {:find '[?d4 (sum ?total) (sum ?tax) (sum ?tip) (sum ?service-charge)]
:in '[$ ?c]
:where '[[?s :sales-order/client ?c]
[?s :sales-order/date ?d]
[?s :sales-order/total ?total]
[?s :sales-order/tax ?tax]
[?s :sales-order/tip ?tip]
[?s :sales-order/service-charge ?service-charge]
[(clj-time.coerce/to-date-time ?d) ?d2]
[(auto-ap.time/localize ?d2) ?d3]
[(auto-ap.time/unparse ?d3 auto-ap.time/normal-date) ?d4]]}
(dc/db conn) client-id))))
(defn client-tag [params]
(when-let [code (or (params "client-code")
@@ -369,10 +369,10 @@
"export:transactions2"}}]
{:body (let [db (dc/db conn)]
(->>
(dc/q {:query {:find ['?e]
:in ['$ '?client-code]
:where ['[?e :transaction/client ?client-code]]}
:args [db [:client/code (query-params "client-code")]]})
(dc/q {:find ['?e]
:in ['$ '?client-code]
:where ['[?e :transaction/client ?client-code]]}
db [:client/code (query-params "client-code")])
(map first)
;; TODO
#_(map (fn [e]

View File

@@ -18,9 +18,9 @@
[clojure.string :as str]
[clojure.tools.logging :as log]
[config.core :refer [env]]
[datomic.client.api :as dc]
[datomic.api :as dc]
[digest]
[iol-ion.tx :refer [propose-invoice random-tempid]]
[iol-ion.tx :refer [random-tempid]]
[ring.middleware.json :refer [wrap-json-response]]
[unilog.context :as lc])
(:import
@@ -114,10 +114,10 @@
{:vendor-code vendor-code})))
(let [vendor-id (or forced-vendor
(->> (dc/q
{:query {:find ['?vendor]
:in ['$ '?vendor-name]
:where ['[?vendor :vendor/name ?vendor-name]]}
:args [(dc/db conn) vendor-code]})
{:find ['?vendor]
:in ['$ '?vendor-name]
:where ['[?vendor :vendor/name ?vendor-name]]}
(dc/db conn) vendor-code)
first
first))]
(when-not vendor-id
@@ -125,9 +125,9 @@
{:vendor-code vendor-code})))
(if-let [matching-vendor (->> (dc/q
{:query {:find [(list 'pull '?vendor-id d-vendors/default-read)]
:in ['$ '?vendor-id]}
:args [(dc/db conn) vendor-id]})
{:find [(list 'pull '?vendor-id d-vendors/default-read)]
:in ['$ '?vendor-id]}
(dc/db conn) vendor-id)
first
first)]
matching-vendor
@@ -231,8 +231,8 @@
:transaction-account/location "A"
:transaction-account/amount (Math/abs (:invoice/total invoice))}]}))
]
[`(propose-invoice ~(d-invoices/code-invoice (validate-invoice (remove-nils invoice)
user)))
[[:propose-invoice (d-invoices/code-invoice (validate-invoice (remove-nils invoice)
user))]
(some-> payment remove-nils)
transaction])))
(filter identity)))
@@ -252,7 +252,7 @@
(map #(validate-invoice % user))
admin-only-if-multiple-clients
(mapv d-invoices/code-invoice)
(mapv (fn [i] `(propose-invoice ~i))))]
(mapv (fn [i] [:propose-invoice i])))]
(log/info "creating invoice" potential-invoices)
(let [tx (audit-transact potential-invoices user)]
@@ -288,21 +288,23 @@
(defn import-account-overrides [customer filename]
(let [[_ & rows] (-> filename (io/reader) csv/read-csv)
[client-id] (first (dc/q (-> {:query {:find ['?e]
:in ['$ '?z]
:where [['?e :client/code '?z]]}
:args [(dc/db conn) customer]})))
code->existing-account (by :account/numeric-code (map first (dc/q {:query {:find ['(pull ?e [:account/numeric-code
{:account/applicability [:db/ident]}
:db/id])]
:in ['$]
:where ['[?e :account/name]]}
:args [(dc/db conn)]})))
[client-id] (first (dc/q (-> {:find ['?e]
:in ['$ '?z]
:where [['?e :client/code '?z]]}
(dc/db conn)
customer)))
code->existing-account (by :account/numeric-code (map first (dc/q {:find ['(pull ?e [:account/numeric-code
{:account/applicability [:db/ident]}
:db/id])]
:in ['$]
:where ['[?e :account/name]]}
(dc/db conn))))
existing-account-overrides (dc/q (-> {:query {:find ['?e]
:in ['$ '?client-id]
:where [['?e :account-client-override/client '?client-id]]}
:args [(dc/db conn) client-id]}))
existing-account-overrides (dc/q (-> {:find ['?e]
:in ['$ '?client-id]
:where [['?e :account-client-override/client '?client-id]]}
(dc/db conn)
client-id))
rows (transduce (comp
(map (fn [[_ account account-name override-name _ type]]
[account account-name override-name type]))
@@ -357,7 +359,7 @@
existing-account-overrides)
rows)]
(dc/transact conn {:tx-data txes})
@(dc/transact conn txes)
txes))
(defn import-transactions-cleared-against [file]

View File

@@ -10,8 +10,8 @@
[clojure.tools.logging :as log]
[com.unbounce.dogstatsd.core :as statsd]
[config.core :refer [env]]
[datomic.client.api :as dc]
[iol-ion.tx :refer [random-tempid upsert-entity]]
[datomic.api :as dc]
[iol-ion.tx :refer [random-tempid]]
[ring.middleware.json :refer [wrap-json-response]]
[ring.util.request :refer [body-string]]
[unilog.context :as lc])
@@ -45,12 +45,12 @@
(or (pull-attr (dc/db conn) :saved-query/guid [:saved-query/lookup-key lookup-key])
guid)
guid)]
(dc/transact conn {:tx-data [`(upsert-entity ~{:db/id (or id (random-tempid))
:saved-query/guid guid
:saved-query/description note
:saved-query/key (str "queries/" guid)
:saved-query/client client
:saved-query/lookup-key lookup-key})]})
@(dc/transact conn [[:upsert-entity {:db/id (or id (random-tempid))
:saved-query/guid guid
:saved-query/description note
:saved-query/key (str "queries/" guid)
:saved-query/client client
:saved-query/lookup-key lookup-key}]])
(s3/put-object :bucket-name (:data-bucket env)
:key (str "queries/" guid)
:input-stream (io/make-input-stream (.getBytes body) {})

View File

@@ -7,7 +7,7 @@
[auto-ap.yodlee.core2 :as yodlee]
[clojure.tools.logging :as log]
[config.core :refer [env]]
[datomic.client.api :as dc]))
[datomic.api :as dc]))
(defn fastlink [{:keys [query-params identity]}]
(assert-can-see-client identity (pull-attr (dc/db conn) :db/id [:client/code (get query-params "client")]))

View File

@@ -12,7 +12,7 @@
[clojure.set :as set]
[clojure.string :as str]
[clojure.tools.logging :as log]
[datomic.client.api :as dc]
[datomic.api :as dc]
[slingshot.slingshot :refer [try+]]
[unilog.context :as lc]))
@@ -395,11 +395,11 @@
(upsert client square-location (time/plus (time/now) (time/days -3)) (time/now))))
([client location start end]
(lc/with-context {:source "Square loading"}
(let [existing (->> (dc/q {:query {:find ['?external-id]
:in ['$ '?client]
:where ['[?o :sales-order/client ?client]
'[?o :sales-order/external-id ?external-id]]}
:args [(dc/db conn) (:db/id client)]})
(let [existing (->> (dc/q {:find ['?external-id]
:in ['$ '?client]
:where ['[?o :sales-order/client ?client]
'[?o :sales-order/external-id ?external-id]]}
(dc/db conn) (:db/id client))
(map first)
set)
_ (log/info (count existing) "Sales orders already exist")
@@ -407,7 +407,7 @@
(daily-results client location start end))]
(doseq [x (partition-all 20 to-create)]
(log/info "Loading " (count x))
(dc/transact conn {:tx-data x}))))))
@(dc/transact conn x))))))
(defn upsert-settlements
([client]
@@ -419,7 +419,7 @@
:client (:client/code client)}
(doseq [x (partition-all 20 (daily-settlements client location))]
(log/info "Loading expected deposit" (count x))
(dc/transact conn {:tx-data x}))
@(dc/transact conn x))
(log/info "Done loading settlements"))))
(defn upsert-refunds
@@ -433,7 +433,7 @@
:location (:square-location/client-location client)}
(doseq [x (partition-all 20 (refunds client location))]
(log/info "Loading refund" (count x))
(dc/transact conn {:tx-data x}))
@(dc/transact conn x))
(log/info "Done loading refunds"))))
(def square-read [:db/id
@@ -474,29 +474,29 @@
[(:square-location/square-id sl)
(:db/id sl)])
(:client/square-locations client)))]
(dc/transact conn {:tx-data (for [square-location (client-locations client)]
{:db/id (or (square-id->id (:id square-location)) (random-tempid))
:client/_square-locations (:db/id client)
:square-location/name (:name square-location)
:square-location/square-id (:id square-location)})}))))
@(dc/transact conn (for [square-location (client-locations client)]
{:db/id (or (square-id->id (:id square-location)) (random-tempid))
:client/_square-locations (:db/id client)
:square-location/name (:name square-location)
:square-location/square-id (:id square-location)})))))
#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
(defn reset []
(->>
(dc/q {:query {:find ['?e]
:in ['$]
:where ['(or [?e :sales-order/date]
[?e :expected-deposit/date])]}
:args [(dc/db conn)]})
(dc/q {:find ['?e]
:in ['$]
:where ['(or [?e :sales-order/date]
[?e :expected-deposit/date])]}
(dc/db conn))
(map first)
(map (fn [x] [:db/retractEntity x]))))
(defn mark-integration-status [client integration-status]
(dc/transact conn
{:tx-data [{:db/id (:db/id client)
:client/square-integration-status (assoc integration-status
:db/id (or (-> client :client/square-integration-status :db/id)
(random-tempid)))}]}))
@(dc/transact conn
[{:db/id (:db/id client)
:client/square-integration-status (assoc integration-status
:db/id (or (-> client :client/square-integration-status :db/id)
(random-tempid)))}]))
(defn upsert-all [ & clients]
(doseq [client (apply get-square-clients clients)

View File

@@ -13,7 +13,7 @@
[clojure.string :as str]
[clojure.tools.logging :as log]
[cemerick.url :as url]
[datomic.client.api :as dc]
[datomic.api :as dc]
[slingshot.slingshot :refer [try+]]
[unilog.context :as lc]))
@@ -399,7 +399,7 @@
(lc/with-context {:source "Square loading"}
(doseq [x (partition-all 20 (daily-results client location start end))]
(log/info "Loading " (count x))
(dc/transact conn {:tx-data x})))))
@(dc/transact conn x)))))
(defn upsert-settlements
([client]
@@ -411,7 +411,7 @@
:client (:client/code client)}
(doseq [x (partition-all 20 (daily-settlements client location))]
(log/info "Loading expected deposit" (count x))
(dc/transact conn {:tx-data x}))
@(dc/transact conn x))
(log/info "Done loading settlements"))))
(defn upsert-refunds
@@ -425,7 +425,7 @@
:location (:square-location/client-location client)}
(doseq [x (partition-all 20 (refunds client location))]
(log/info "Loading refund" (count x))
(dc/transact conn {:tx-data x}))
@(dc/transact conn x))
(log/info "Done loading refunds"))))
(def square-read [:db/id
@@ -466,29 +466,29 @@
[(:square-location/square-id sl)
(:db/id sl)])
(:client/square-locations client)))]
(dc/transact conn {:tx-data (for [square-location (client-locations client)]
{:db/id (or (square-id->id (:id square-location)) (random-tempid))
:client/_square-locations (:db/id client)
:square-location/name (:name square-location)
:square-location/square-id (:id square-location)})}))))
@(dc/transact conn (for [square-location (client-locations client)]
{:db/id (or (square-id->id (:id square-location)) (random-tempid))
:client/_square-locations (:db/id client)
:square-location/name (:name square-location)
:square-location/square-id (:id square-location)})))))
#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
(defn reset []
(->>
(dc/q {:query {:find ['?e]
:in ['$]
:where ['(or [?e :sales-order/date]
[?e :expected-deposit/date])]}
:args [(dc/db conn)]})
(dc/q {:find ['?e]
:in ['$]
:where ['(or [?e :sales-order/date]
[?e :expected-deposit/date])]}
(dc/db conn))
(map first)
(map (fn [x] [:db/retractEntity x]))))
(defn mark-integration-status [client integration-status]
(dc/transact conn
{:tx-data [{:db/id (:db/id client)
:client/square-integration-status (assoc integration-status
:db/id (or (-> client :client/square-integration-status :db/id)
(random-tempid)))}]}))
@(dc/transact conn
[{:db/id (:db/id client)
:client/square-integration-status (assoc integration-status
:db/id (or (-> client :client/square-integration-status :db/id)
(random-tempid)))}]))
(defn upsert-all [ & clients]
(doseq [client (apply get-square-clients clients)

View File

@@ -13,7 +13,7 @@
[clojure.set :as set]
[clojure.string :as str]
[com.brunobonacci.mulog :as mu]
[datomic.client.api :as dc]
[datomic.api :as dc]
[manifold.deferred :as de]
[manifold.executor :as ex]
[manifold.stream :as s]
@@ -562,7 +562,7 @@
(doseq [x (partition-all 100 results)]
(log/info ::loading-orders
:count (count x))
(dc/transact conn {:tx-data x}))))))))
@(dc/transact conn x))))))))
(defn upsert-settlements
@@ -582,7 +582,7 @@
(doseq [x (partition-all 20 settlements)]
(log/info ::loading-deposits
:count (count x))
(dc/transact conn {:tx-data x}))
@(dc/transact conn x))
(log/info ::done-loading-deposits)))))))
(defn upsert-refunds
@@ -603,7 +603,7 @@
(log/info ::loading-refunds
:count (count x)
:sample (first x))
(dc/transact conn {:tx-data x}))
@(dc/transact conn x))
(catch Throwable e
(log/error ::upsert-refunds-failed
@@ -653,30 +653,30 @@
(:client/square-locations client)))]
(de/chain (client-locations client)
(fn [client-locations]
(dc/transact conn
{:tx-data (for [square-location client-locations]
{:db/id (or (square-id->id (:id square-location)) (str (java.util.UUID/randomUUID)))
:client/_square-locations (:db/id client)
:square-location/name (:name square-location)
:square-location/square-id (:id square-location)})}))))))
@(dc/transact conn
(for [square-location client-locations]
{:db/id (or (square-id->id (:id square-location)) (str (java.util.UUID/randomUUID)))
:client/_square-locations (:db/id client)
:square-location/name (:name square-location)
:square-location/square-id (:id square-location)})))))))
#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
(defn reset []
(->>
(dc/q {:query {:find ['?e]
:in ['$]
:where ['(or [?e :sales-order/date]
[?e :expected-deposit/date])]}
:args [(dc/db conn)]})
(dc/q {:find ['?e]
:in ['$]
:where ['(or [?e :sales-order/date]
[?e :expected-deposit/date])]}
(dc/db conn))
(map first)
(map (fn [x] [:db/retractEntity x]))))
(defn mark-integration-status [client integration-status]
(dc/transact conn
{:tx-data [{:db/id (:db/id client)
:client/square-integration-status (assoc integration-status
:db/id (or (-> client :client/square-integration-status :db/id)
(str (java.util.UUID/randomUUID))))}]}))
@(dc/transact conn
[{:db/id (:db/id client)
:client/square-integration-status (assoc integration-status
:db/id (or (-> client :client/square-integration-status :db/id)
(str (java.util.UUID/randomUUID))))}]))
(defn upsert-all [ & clients]
(capture-context->lc

View File

@@ -8,7 +8,7 @@
[auto-ap.time :as atime]
[clj-time.coerce :as coerce]
[clojure.string :as str]
[datomic.client.api :as dc]
[datomic.api :as dc]
[hiccup2.core :as hiccup]))
(defn tx-rows->changes [history]

View File

@@ -9,7 +9,7 @@
[auto-ap.ssr.utils :refer [html-response]]
[bidi.bidi :as bidi]
[clojure.string :as str]
[datomic.client.api :as dc]
[datomic.api :as dc]
[hiccup2.core :as hiccup]))
(defn cannot-overwrite? [vendor]
@@ -210,11 +210,11 @@
(defn vendor-save [{:keys [form-params identity route-params] :as request}]
(when-not (cannot-overwrite? (dc/pull (dc/db conn) '[*] (Long/parseLong (:vendor-id route-params))))
@(dc/transact conn {:tx-data [(remove-nils
(-> (form-data->map form-params)
(assoc :db/id (Long/parseLong (:vendor-id route-params)))
(update :vendor/legal-entity-1099-type #(some->> % (keyword "legal-entity-1099-type")))
(update :vendor/legal-entity-tin-type #(some->> % (keyword "legal-entity-tin-type")))))]}))
@(dc/transact conn [(remove-nils
(-> (form-data->map form-params)
(assoc :db/id (Long/parseLong (:vendor-id route-params)))
(update :vendor/legal-entity-1099-type #(some->> % (keyword "legal-entity-1099-type")))
(update :vendor/legal-entity-tin-type #(some->> % (keyword "legal-entity-tin-type")))))]))
(html-response
(table request :flash-id (Long/parseLong (:vendor-id route-params)))))

View File

@@ -7,7 +7,7 @@
[auto-ap.ssr.components.navbar-dropdown :refer [navbar-dropdown]]
[auto-ap.ssr.utils :refer [html-response]]
[bidi.bidi :as bidi]
[datomic.client.api :as dc]
[datomic.api :as dc]
[hiccup2.core :as hiccup]))
(defn dropdown-contents [{:keys [identity]}]

View File

@@ -8,7 +8,7 @@
[auto-ap.time :as atime]
[bidi.bidi :as bidi]
[clj-time.coerce :as coerce]
[datomic.client.api :as dc]
[datomic.api :as dc]
[hiccup2.core :as hiccup]
[clj-time.core :as time]))
@@ -110,25 +110,24 @@
(let [r (dc/pull (dc/db conn)
pull-expr
(Long/parseLong transaction-id))
similar (->> {:query '[:find ?date ?do ?amt
:in $ ?tr
:where
[(iol-ion.query/recent-date 180) ?start-date]
[?tr :transaction/client ?c]
[?tr :transaction/recommended-account ?a ]
[?tr :transaction/recommended-vendor ?v ]
[?t2 :transaction/client ?c]
[?t2 :transaction/date ?date]
[(>= ?date ?start-date)]
[?t2 :transaction/vendor ?v]
[?t2 :transaction/accounts ?a2]
[?a2 :transaction-account/account ?a]
[?t2 :transaction/description-original ?do]
[?t2 :transaction/amount ?amt]]
:args [(dc/db conn)
(Long/parseLong transaction-id)]
:limit 5}
dc/q
similar (->> (dc/q '[:find ?date ?do ?amt
:in $ ?tr
:where
[(iol-ion.query/recent-date 180) ?start-date]
[?tr :transaction/client ?c]
[?tr :transaction/recommended-account ?a ]
[?tr :transaction/recommended-vendor ?v ]
[?t2 :transaction/client ?c]
[?t2 :transaction/date ?date]
[(>= ?date ?start-date)]
[?t2 :transaction/vendor ?v]
[?t2 :transaction/accounts ?a2]
[?a2 :transaction-account/account ?a]
[?t2 :transaction/description-original ?do]
[?t2 :transaction/amount ?amt]]
(dc/db conn)
(Long/parseLong transaction-id))
(take 5)
sort
reverse)]
(html-response [:div.modal.is-active.wide

View File

@@ -11,7 +11,7 @@
#_{:clj-kondo/ignore [:unused-namespace]}
[yang.scheduler :as scheduler]
[clj-time.coerce :as coerce]
[datomic.client.api :as dc]
[datomic.api :as dc]
[auto-ap.datomic :refer [conn]]
[auto-ap.datomic.clients :as d-clients]))
;; switch all of this to use tokens instead of passing around client codes, particularly because the codes
@@ -293,7 +293,7 @@
:body
:providerAccount
first))
(dc/transact conn {:tx-data [[:db/retractEntity [:yodlee-provider-account/id id]]]}))
@(dc/transact conn [[:db/retractEntity [:yodlee-provider-account/id id]]]))
(defn upsert-accounts-tx
([client-code]
@@ -322,8 +322,8 @@
(defn refresh-provider-account [client-code id]
(log/info "refreshing yodlee provider account id" id)
(dc/transact conn {:tx-data (upsert-accounts-tx client-code
[(get-provider-account client-code id)])}))
@(dc/transact conn (upsert-accounts-tx client-code
[(get-provider-account client-code id)])))
(defn upsert-accounts []
(let [concurrent 20
@@ -341,7 +341,7 @@
(async/to-chan! (d-clients/get-all)))
(let [result (async/<!! (async/into [] output-chan))]
(log/info "Current yodlee state is " result)
(dc/transact conn {:tx-data result}))))
@(dc/transact conn result))))

View File

@@ -17,7 +17,7 @@
[clojure.pprint]
[clojure.string :as str]
[config.core :refer [env]]
[datomic.client.api :as dc]
[datomic.api :as dc]
[mount.core :as mount]
[nrepl.middleware.print]
[unilog.context :as lc]
@@ -69,28 +69,29 @@
#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
(defn load-accounts [conn]
(let [[header & rows] (-> "master-account-list.csv" (io/resource) io/input-stream (BOMInputStream.) (io/reader) csv/read-csv)
code->existing-account (by :account/numeric-code (map first (dc/q {:query {:find ['(pull ?e [:account/numeric-code
:db/id])]
:in ['$]
:where ['[?e :account/name]]}
:args [(dc/db conn)]})))
code->existing-account (by :account/numeric-code (map first (dc/q {:find ['(pull ?e [:account/numeric-code
:db/id])]
:in ['$]
:where ['[?e :account/name]]}
(dc/db conn))))
also-merge-txes (fn [also-merge old-account-id]
(if old-account-id
(let [[sunset-account]
(first (dc/q {:query {:find ['?a ]
:in ['$ '?ac ]
:where ['[?a :account/numeric-code ?ac]]}
:args [(dc/db conn) also-merge ]}))]
(first (dc/q {:find ['?a ]
:in ['$ '?ac ]
:where ['[?a :account/numeric-code ?ac]]}
(dc/db conn) also-merge))]
(into (mapv
(fn [[entity id _]]
[:db/add entity id old-account-id])
(dc/q {:query {:find ['?e '?id '?a ]
:in ['$ '?ac ]
:where ['[?a :account/numeric-code ?ac]
'[?e ?at ?a]
'[?at :db/ident ?id]]}
:args [(dc/db conn) also-merge ]}))
(dc/q {:find ['?e '?id '?a ]
:in ['$ '?ac ]
:where ['[?a :account/numeric-code ?ac]
'[?e ?at ?a]
'[?at :db/ident ?id]]}
(dc/db conn)
also-merge))
[[:db/retractEntity sunset-account]]))
[]))
@@ -142,33 +143,32 @@
conj
[]
rows)]
(dc/transact conn {:tx-data txes})))
@(dc/transact conn txes)))
#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
(defn find-bad-accounts []
(set (map second (dc/q {:query {:find ['(pull ?x [*]) '?z]
:in ['$]
:where ['[?e :account/numeric-code ?z]
'[(<= ?z 9999)]
'[?x ?a ?e]]}
:args [(dc/db conn)]}))))
(set (map second (dc/q {:find ['(pull ?x [*]) '?z]
:in ['$]
:where ['[?e :account/numeric-code ?z]
'[(<= ?z 9999)]
'[?x ?a ?e]]}
(dc/db conn)))))
#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
(defn delete-4-digit-accounts []
(dc/transact conn
{:tx-data
(transduce
(comp
(map first)
(map (fn [old-account-id]
[:db/retractEntity old-account-id])))
conj
[]
(dc/q {:query {:find ['?e]
:in ['$]
:where ['[?e :account/numeric-code ?z]
'[(<= ?z 9999)]]}
:args [(dc/db conn)]}))})
@(dc/transact conn
(transduce
(comp
(map first)
(map (fn [old-account-id]
[:db/retractEntity old-account-id])))
conj
[]
(dc/q {:find ['?e]
:in ['$]
:where ['[?e :account/numeric-code ?z]
'[(<= ?z 9999)]]}
(dc/db conn))))
)
@@ -181,30 +181,30 @@
(fn [acc [e z]]
(update acc z conj e))
{}
(dc/q {:query {:find ['?e '?z]
:in ['$]
:where ['[?e :account/numeric-code ?z]]}
:args [(dc/db conn)]}))))
(dc/q {:find ['?e '?z]
:in ['$]
:where ['[?e :account/numeric-code ?z]]}
(dc/db conn)))))
#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
(defn customize-accounts [customer filename]
(let [[_ & rows] (-> filename (io/resource) io/input-stream (BOMInputStream.) (io/reader) csv/read-csv)
[client-id] (first (dc/q (-> {:query {:find ['?e]
:in ['$ '?z]
:where [['?e :client/code '?z]]}
:args [(dc/db conn) customer]})))
[client-id] (first (dc/q (-> {:find ['?e]
:in ['$ '?z]
:where [['?e :client/code '?z]]}
(dc/db conn) customer)))
_ (println client-id)
code->existing-account (by :account/numeric-code (map first (dc/q {:query {:find ['(pull ?e [:account/numeric-code
{:account/applicability [:db/ident]}
:db/id])]
:in ['$]
:where ['[?e :account/name]]}
:args [(dc/db conn)]})))
code->existing-account (by :account/numeric-code (map first (dc/q {:find ['(pull ?e [:account/numeric-code
{:account/applicability [:db/ident]}
:db/id])]
:in ['$]
:where ['[?e :account/name]]}
(dc/db conn))))
existing-account-overrides (dc/q (-> {:query {:find ['?e]
:in ['$ '?client-id]
:where [['?e :account-client-override/client '?client-id]]}
:args [(dc/db conn) client-id]}))
existing-account-overrides (dc/q {:find ['?e]
:in ['$ '?client-id]
:where [['?e :account-client-override/client '?client-id]]}
(dc/db conn) client-id)
@@ -271,16 +271,16 @@
#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
(defn fix-transactions-without-locations [client-code location]
(->>
(dc/q {:query {:find ['(pull ?e [*])]
:in ['$ '?client-code]
:where ['[?e :transaction/accounts ?ta]
'[?e :transaction/matched-rule]
'[?e :transaction/approval-status :transaction-approval-status/approved]
'(not [?ta :transaction-account/location])
'[?e :transaction/client ?c]
'[?c :client/code ?client-code]
]}
:args [(dc/db conn) client-code]})
(dc/q {:find ['(pull ?e [*])]
:in ['$ '?client-code]
:where ['[?e :transaction/accounts ?ta]
'[?e :transaction/matched-rule]
'[?e :transaction/approval-status :transaction-approval-status/approved]
'(not [?ta :transaction-account/location])
'[?e :transaction/client ?c]
'[?c :client/code ?client-code]
]}
(dc/db conn) client-code)
(mapcat
(fn [[{:transaction/keys [accounts]}]]
(mapv
@@ -293,66 +293,6 @@
)
vec))
;; TODO uncommenting the two below this makes lein build not work, probably related to the ledger
#_(defn patch-missing-ledger-entries []
@(d/transact
(d/connect uri)
(mapv
#(l/entity-change->ledger (d/db (d/connect uri)) [:transaction %])
(concat
(->>
(d/query {:query {:find ['?t ]
:in ['$]
:where ['[?t :transaction/date]
'(not [?t :transaction/approval-status :transaction-approval-status/excluded])
'(not-join [?t] [?e :journal-entry/original-entity ?t])]}
:args [(d/db (d/connect uri))]})
(map first))))))
#_(defn check-for-out-of-date-ledger [code]
[(d/query {:query {:find ['(count ?e)]
:in ['$ '?code]
:where ['[?e :transaction/accounts ?ta]
'[?e :transaction/matched-rule]
'[?e :transaction/approval-status :transaction-approval-status/approved]
'(not [?ta :transaction-account/location])
'[?e :transaction/client ?c]
'[?c :client/code ?code]
]}
:args [(d/db (d/connect uri)) code]})
(d/query {:query {:find ['?t ]
:in ['$]
:where ['[?t :transaction/date]
'[?t :transaction/client ?c]
'[?c :client/code ?code]
'(not [?t :transaction/approval-status :transaction-approval-status/excluded])
'(not-join [?t] [?e :journal-entry/original-entity ?t])]}
:args [(d/db (d/connect uri))]})
(d/query {:query {:find ['?t ]
:in ['$]
:where ['[?t :transaction/date]
'[?t :transaction/client ?c]
'[?c :client/code ?code]
'(not [?t :transaction/approval-status :transaction-approval-status/excluded])
'[?t :transaction/vendor ?v]
'[?j :journal-entry/original-entity ?t]
'(not [?j :journal-entry/vendor ?v])
#_'(not-join [?t] [?e :journal-entry/original-entity ?t])]}
:args [(d/db (d/connect uri))]})
(d/query {:query {:find ['(count ?i) ]
:in ['$]
:where ['[?i :invoice/client ?c]
'(not [?i :invoice/status :invoice-status/voided])
'[?c :client/code ?code]
'(not-join [?i] [?e :journal-entry/original-entity ?i])]}
:args [(d/db (d/connect uri))]})])
#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
(defn go []
(require '[mount.core :as mount])
@@ -362,21 +302,21 @@
#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
(defn entity-history [i]
(vec (sort-by first (dc/q
{:query {:find ['?tx '?z '?v ]
:in ['?i '$]
:where ['[?i ?a ?v ?tx ?ad]
'[?a :db/ident ?z]
'[(= ?ad true)]]}
:args [i (dc/history (dc/db conn))]}))))
{:find ['?tx '?z '?v ]
:in ['?i '$]
:where ['[?i ?a ?v ?tx ?ad]
'[?a :db/ident ?z]
'[(= ?ad true)]]}
i (dc/history (dc/db conn))))))
#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
(defn entity-history-with-revert [i]
(vec (sort-by first (dc/q
{:query {:find ['?tx '?z '?v '?ad ]
:in ['?i '$]
:where ['[?i ?a ?v ?tx ?ad]
'[?a :db/ident ?z]]}
:args [i (dc/history (dc/db conn))]}))))
{:find ['?tx '?z '?v '?ad ]
:in ['?i '$]
:where ['[?i ?a ?v ?tx ?ad]
'[?a :db/ident ?z]]}
i (dc/history (dc/db conn))))))
#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
(defn tx-detail [i]
@@ -397,7 +337,7 @@
#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
(defn start-db []
(mu/start-publisher! {:type :dev})
(mount.core/start (mount.core/only #{#'auto-ap.datomic/conn #'auto-ap.datomic/client})))
(mount.core/start (mount.core/only #{#'auto-ap.datomic/conn })))
(defn start-search []
(mount.core/start (mount.core/only #{#'auto-ap.graphql.vendors/indexer #'auto-ap.graphql.accounts/indexer})))
@@ -405,7 +345,7 @@
(defn restart-db []
#_(require 'datomic.dev-local)
#_(datomic.dev-local/release-db {:system "dev" :db-name "prod-migration"})
(mount.core/stop (mount.core/only #{#'auto-ap.datomic/conn #'auto-ap.datomic/client}))
(mount.core/stop (mount.core/only #{#'auto-ap.datomic/conn }))
(start-db))

View File

@@ -4,7 +4,7 @@
[auto-ap.import.transactions :as sut]
[auto-ap.integration.util :refer [wrap-setup]]
[iol-ion.tx :refer [upsert-transaction]]
[datomic.client.api :as dc]
[datomic.api :as dc]
[clj-time.coerce :as coerce]
[clojure.test :as t]
[digest :as di]))
@@ -78,12 +78,12 @@
(t/testing "Should import and code transactions"
(t/testing "Should import one transaction"
(let [{:strs [bank-account-id client-id]} (:tempids (dc/transact conn
{:tx-data [{:db/id "bank-account-id"
:bank-account/code "TEST-1"}
{:db/id "client-id"
:client/code "TEST"
:client/locations ["Z" "E"]
:client/bank-accounts ["bank-account-id"]}]}))
[{:db/id "bank-account-id"
:bank-account/code "TEST-1"}
{:db/id "client-id"
:client/code "TEST"
:client/locations ["Z" "E"]
:client/bank-accounts ["bank-account-id"]}]))
result (sut/transaction->txs base-transaction
(dc/pull (dc/db conn) sut/bank-account-pull bank-account-id)
noop-rule)]
@@ -94,18 +94,18 @@
result))))
(t/testing "Should match an uncleared check"
(let [{:strs [bank-account-id payment-id]} (->> {:tx-data [#:payment {:status :payment-status/pending
:date #inst "2019-01-01"
:bank-account "bank-account-id"
:client "client-id"
:check-number 10001
:amount 30.0
:db/id "payment-id"}
#:bank-account {:name "Bank account"
:db/id "bank-account-id"}
#:client {:name "Client"
:db/id "client-id"
:bank-accounts ["bank-account-id"]}]}
(let [{:strs [bank-account-id payment-id]} (->> [#:payment {:status :payment-status/pending
:date #inst "2019-01-01"
:bank-account "bank-account-id"
:client "client-id"
:check-number 10001
:amount 30.0
:db/id "payment-id"}
#:bank-account {:name "Bank account"
:db/id "bank-account-id"}
#:client {:name "Client"
:db/id "client-id"
:bank-accounts ["bank-account-id"]}]
(dc/transact conn)
:tempids)]
@@ -132,7 +132,7 @@
(:transaction/payment transaction-result)))))
(t/testing "Should not match an already matched check"
(dc/transact conn {:tx-data [{:db/id payment-id :payment/status :payment-status/cleared}]})
(dc/transact conn [{:db/id payment-id :payment/status :payment-status/cleared}])
(let [result (sut/transaction->txs (assoc base-transaction
:transaction/description-original "CHECK 10001"
:transaction/amount -30.0)
@@ -144,19 +144,19 @@
(t/testing "Should match expected-deposits"
(let [{:strs [bank-account-id client-id expected-deposit-id]} (->> {:tx-data [#:expected-deposit {:client "client-id"
:date #inst "2021-07-01T00:00:00-08:00"
:vendor :vendor/ccp-square
:total 100.0
:location "MF"
:status :expected-deposit-status/pending
:db/id "expected-deposit-id"}
#:bank-account {:name "Bank account"
:db/id "bank-account-id"}
#:client {:name "Client"
:db/id "client-id"
:locations ["MF"]
:bank-accounts ["bank-account-id"]}]}
(let [{:strs [bank-account-id client-id expected-deposit-id]} (->> [#:expected-deposit {:client "client-id"
:date #inst "2021-07-01T00:00:00-08:00"
:vendor :vendor/ccp-square
:total 100.0
:location "MF"
:status :expected-deposit-status/pending
:db/id "expected-deposit-id"}
#:bank-account {:name "Bank account"
:db/id "bank-account-id"}
#:client {:name "Client"
:db/id "client-id"
:locations ["MF"]
:bank-accounts ["bank-account-id"]}]
(dc/transact conn)
:tempids)]
@@ -250,21 +250,21 @@
(t/deftest match-transaction-to-single-unfulfilled-payments
(t/testing "Auto-pay Invoices"
(let [{:strs [vendor1-id vendor2-id]} (->> {:tx-data [#:vendor {:name "Autopay vendor 1"
:db/id "vendor1-id"}
#:vendor {:name "Autopay vendor 2"
:db/id "vendor2-id"}]}
(let [{:strs [vendor1-id vendor2-id]} (->> [#:vendor {:name "Autopay vendor 1"
:db/id "vendor1-id"}
#:vendor {:name "Autopay vendor 2"
:db/id "vendor2-id"}]
(dc/transact conn)
:tempids)]
(t/testing "Should find a single invoice that matches exactly"
(let [{:strs [client-id]} (->> {:tx-data [#:invoice {:status :invoice-status/paid
:vendor vendor1-id
:scheduled-payment #inst "2019-01-04"
:date #inst "2019-01-01"
:client "client-id"
:total 30.0
:db/id "invoice-id"}
#:client {:name "Client" :db/id "client-id"}]}
(let [{:strs [client-id]} (->> [#:invoice {:status :invoice-status/paid
:vendor vendor1-id
:scheduled-payment #inst "2019-01-04"
:date #inst "2019-01-01"
:client "client-id"
:total 30.0
:db/id "invoice-id"}
#:client {:name "Client" :db/id "client-id"}]
(dc/transact conn)
:tempids)
invoices-matches (sut/match-transaction-to-single-unfulfilled-autopayments -30.0 client-id)]
@@ -272,14 +272,13 @@
))
(t/testing "Should not match paid invoice that isn't a scheduled payment"
(let [{:strs [client-id]} (->> {:tx-data
[#:invoice{:status :invoice-status/paid
:vendor vendor1-id
:date #inst "2019-01-01"
:client "client-id"
:total 30.0
:db/id "invoice-id"}
#:client {:name "Client" :db/id "client-id"}]}
(let [{:strs [client-id]} (->> [#:invoice{:status :invoice-status/paid
:vendor vendor1-id
:date #inst "2019-01-01"
:client "client-id"
:total 30.0
:db/id "invoice-id"}
#:client {:name "Client" :db/id "client-id"}]
(dc/transact conn)
:tempids)
invoices-matches (sut/match-transaction-to-single-unfulfilled-autopayments -30.0 client-id)]
@@ -287,15 +286,14 @@
(t/is (= [] invoices-matches))))
(t/testing "Should not match unpaid invoice"
(let [{:strs [client-id]} (->> {:tx-data
[#:invoice {:status :invoice-status/unpaid
:scheduled-payment #inst "2019-01-04"
:vendor vendor1-id
:date #inst "2019-01-01"
:client "client-id"
:total 30.0
:db/id "invoice-id"}
#:client {:name "Client" :db/id "client-id"}]}
(let [{:strs [client-id]} (->> [#:invoice {:status :invoice-status/unpaid
:scheduled-payment #inst "2019-01-04"
:vendor vendor1-id
:date #inst "2019-01-01"
:client "client-id"
:total 30.0
:db/id "invoice-id"}
#:client {:name "Client" :db/id "client-id"}]
(dc/transact conn)
:tempids)
invoices-matches (sut/match-transaction-to-single-unfulfilled-autopayments -30.0 client-id)]
@@ -303,62 +301,59 @@
(t/is (= [] invoices-matches))))
(t/testing "Should not match invoice that already has a payment"
(let [{:strs [client-id]} (->> {:tx-data
[#:invoice {:status :invoice-status/paid
:scheduled-payment #inst "2019-01-04"
:vendor vendor1-id
:date #inst "2019-01-01"
:client "client-id"
:total 30.0
:db/id "invoice-id"}
{:invoice-payment/amount 30.0
:invoice-payment/invoice "invoice-id"}
#:client {:name "Client"
:db/id "client-id"}]}
(let [{:strs [client-id]} (->> [#:invoice {:status :invoice-status/paid
:scheduled-payment #inst "2019-01-04"
:vendor vendor1-id
:date #inst "2019-01-01"
:client "client-id"
:total 30.0
:db/id "invoice-id"}
{:invoice-payment/amount 30.0
:invoice-payment/invoice "invoice-id"}
#:client {:name "Client"
:db/id "client-id"}]
(dc/transact conn)
:tempids)
invoices-matches (sut/match-transaction-to-single-unfulfilled-autopayments -30.0
client-id)]
(t/is (= [] invoices-matches))))
(t/testing "Should match multiple invoices for same vendor that total to transaction amount"
(let [{:strs [client-id]} (->> {:tx-data
[#:invoice {:status :invoice-status/paid
:vendor vendor1-id
:scheduled-payment #inst "2019-01-04"
:date #inst "2019-01-01"
:client "client-id"
:total 15.0
:db/id "invoice1-id"}
#:invoice {:status :invoice-status/paid
:vendor vendor1-id
:scheduled-payment #inst "2019-01-04"
:date #inst "2019-01-01"
:client "client-id"
:total 15.0
:db/id "invoice2-id"}
#:client {:name "Client" :db/id "client-id"}]}
(let [{:strs [client-id]} (->> [#:invoice {:status :invoice-status/paid
:vendor vendor1-id
:scheduled-payment #inst "2019-01-04"
:date #inst "2019-01-01"
:client "client-id"
:total 15.0
:db/id "invoice1-id"}
#:invoice {:status :invoice-status/paid
:vendor vendor1-id
:scheduled-payment #inst "2019-01-04"
:date #inst "2019-01-01"
:client "client-id"
:total 15.0
:db/id "invoice2-id"}
#:client {:name "Client" :db/id "client-id"}]
(dc/transact conn)
:tempids)
invoices-matches (sut/match-transaction-to-single-unfulfilled-autopayments -30.0 client-id)]
(t/is (= 2 (count invoices-matches))
(str "Expected " (vec invoices-matches) " to have a singular match of two invoices."))))
(t/testing "Should not match if there are multiple candidate matches"
(let [{:strs [client-id]} (->> {:tx-data
[#:invoice {:status :invoice-status/paid
:vendor vendor1-id
:scheduled-payment #inst "2019-01-04"
:date #inst "2019-01-01"
:client "client-id"
:total 30.0
:db/id "invoice1-id"}
#:invoice {:status :invoice-status/paid
:vendor vendor1-id
:scheduled-payment #inst "2019-01-04"
:date #inst "2019-01-01"
:client "client-id"
:total 30.0
:db/id "invoice2-id"}
#:client {:name "Client" :db/id "client-id"}]}
(let [{:strs [client-id]} (->> [#:invoice {:status :invoice-status/paid
:vendor vendor1-id
:scheduled-payment #inst "2019-01-04"
:date #inst "2019-01-01"
:client "client-id"
:total 30.0
:db/id "invoice1-id"}
#:invoice {:status :invoice-status/paid
:vendor vendor1-id
:scheduled-payment #inst "2019-01-04"
:date #inst "2019-01-01"
:client "client-id"
:total 30.0
:db/id "invoice2-id"}
#:client {:name "Client" :db/id "client-id"}]
(dc/transact conn)
:tempids)
invoices-matches (sut/match-transaction-to-single-unfulfilled-autopayments -30.0 client-id)]
@@ -366,22 +361,21 @@
(str "Expected " (vec invoices-matches) " to not match due to multiple possibilities."))))
(t/testing "Should not match if invoices are for different vendors"
(let [{:strs [client-id]} (->> {:tx-data
[#:invoice {:status :invoice-status/paid
:vendor vendor1-id
:scheduled-payment #inst "2019-01-04"
:date #inst "2019-01-01"
:client "client-id"
:total 10.0
:db/id "invoice1-id"}
#:invoice {:status :invoice-status/paid
:vendor vendor2-id
:scheduled-payment #inst "2019-01-04"
:date #inst "2019-01-01"
:client "client-id"
:total 20.0
:db/id "invoice2-id"}
#:client {:name "Client" :db/id "client-id"}]}
(let [{:strs [client-id]} (->> [#:invoice {:status :invoice-status/paid
:vendor vendor1-id
:scheduled-payment #inst "2019-01-04"
:date #inst "2019-01-01"
:client "client-id"
:total 10.0
:db/id "invoice1-id"}
#:invoice {:status :invoice-status/paid
:vendor vendor2-id
:scheduled-payment #inst "2019-01-04"
:date #inst "2019-01-01"
:client "client-id"
:total 20.0
:db/id "invoice2-id"}
#:client {:name "Client" :db/id "client-id"}]
(dc/transact conn)
:tempids)
invoices-matches (sut/match-transaction-to-single-unfulfilled-autopayments -30.0 client-id)]
@@ -389,29 +383,28 @@
(str "Expected " (vec invoices-matches) " to only consider invoices for the same vendor."))))
(t/testing "Should only consider invoices chronologically"
(let [{:strs [client-id]} (->> {:tx-data
[#:invoice {:status :invoice-status/paid
:vendor vendor1-id
:scheduled-payment #inst "2019-01-04"
:date #inst "2019-01-01"
:client "client-id"
:total 10.0
:db/id "invoice1-id"}
#:invoice {:status :invoice-status/paid
:vendor vendor1-id
:scheduled-payment #inst "2019-01-06"
:date #inst "2019-01-01"
:client "client-id"
:total 21.0
:db/id "invoice2-id"}
#:invoice {:status :invoice-status/paid
:vendor vendor1-id
:scheduled-payment #inst "2019-01-05"
:date #inst "2019-01-01"
:client "client-id"
:total 30.0
:db/id "invoice3-id"}
#:client {:name "Client" :db/id "client-id"}]}
(let [{:strs [client-id]} (->> [#:invoice {:status :invoice-status/paid
:vendor vendor1-id
:scheduled-payment #inst "2019-01-04"
:date #inst "2019-01-01"
:client "client-id"
:total 10.0
:db/id "invoice1-id"}
#:invoice {:status :invoice-status/paid
:vendor vendor1-id
:scheduled-payment #inst "2019-01-06"
:date #inst "2019-01-01"
:client "client-id"
:total 21.0
:db/id "invoice2-id"}
#:invoice {:status :invoice-status/paid
:vendor vendor1-id
:scheduled-payment #inst "2019-01-05"
:date #inst "2019-01-01"
:client "client-id"
:total 30.0
:db/id "invoice3-id"}
#:client {:name "Client" :db/id "client-id"}]
(dc/transact conn)
:tempids)]
(t/is (= 2 (count (sut/match-transaction-to-single-unfulfilled-autopayments -40.0 client-id)))

View File

@@ -2,7 +2,7 @@
(:require [auto-ap.graphql :as sut]
[venia.core :as v]
[clojure.test :as t :refer [deftest is testing use-fixtures]]
[datomic.client.api :as dc]
[datomic.api :as dc]
[auto-ap.integration.util :refer [wrap-setup admin-token user-token]]
[auto-ap.datomic :refer [conn]]))
@@ -29,9 +29,8 @@
(deftest transaction-page
(testing "transaction page"
(dc/transact conn
{:tx-data
[(new-client {:db/id "client"})
(new-transaction {:transaction/client "client"})]})
[(new-client {:db/id "client"})
(new-transaction {:transaction/client "client"})])
(testing "It should find all transactions"
(let [result (:transaction-page (:data (sut/query (admin-token) "{ transaction_page(filters: {client_id: null}) { count, start, data { id } }}")))]
@@ -49,10 +48,9 @@
(deftest invoice-page
(testing "invoice page"
(dc/transact conn
{:tx-data
[(new-client {:db/id "client"})
(new-invoice {:invoice/client "client"
:invoice/status :invoice-status/paid})]})
[(new-client {:db/id "client"})
(new-invoice {:invoice/client "client"
:invoice/status :invoice-status/paid})])
(testing "It should find all invoices"
(let [result (first (:invoice-page (:data (sut/query (admin-token) "{ invoice_page(filters: {client_id: null, status:paid}) { count, start, invoices { id } }}"))))]
(is (= 1 (:count result)))
@@ -95,13 +93,12 @@
(let [{:strs [vendor-id account-id yodlee-merchant-id]} (->
(dc/transact
conn
{:tx-data
[{:vendor/name "Bryce's Meat Co"
:db/id "vendor-id"}
{:account/name "hello"
:db/id "account-id"}
{:yodlee-merchant/name "yodlee"
:db/id "yodlee-merchant-id"}]})
[{:vendor/name "Bryce's Meat Co"
:db/id "vendor-id"}
{:account/name "hello"
:db/id "account-id"}
{:yodlee-merchant/name "yodlee"
:db/id "yodlee-merchant-id"}])
:tempids)]
(testing "it should reject rules that don't add up to 100%"
@@ -194,27 +191,26 @@
(deftest test-transaction-rule
(testing "it should match rules"
(let [matching-transaction (dc/transact conn
{:tx-data
[{:transaction/description-original "matching-desc"
:transaction/date #inst "2019-01-05T00:00:00.000-08:00"
:transaction/client {:client/name "1"
:db/id "client-1"}
:transaction/bank-account {:db/id "bank-account-1"
:bank-account/name "1"}
[{:transaction/description-original "matching-desc"
:transaction/date #inst "2019-01-05T00:00:00.000-08:00"
:transaction/client {:client/name "1"
:db/id "client-1"}
:transaction/bank-account {:db/id "bank-account-1"
:bank-account/name "1"}
:transaction/amount 1.00
:transaction/id "2019-01-05 matching-desc 1"
:db/id "a"}
:transaction/amount 1.00
:transaction/id "2019-01-05 matching-desc 1"
:db/id "a"}
{:transaction/description-original "nonmatching-desc"
:transaction/client {:client/name "2"
:db/id "client-2"}
:transaction/bank-account {:db/id "bank-account-2"
:bank-account/name "2"}
:transaction/date #inst "2019-01-15T23:23:00.000-08:00"
:transaction/amount 2.00
:transaction/id "2019-01-15 nonmatching-desc 2"
:db/id "b"}]})
{:transaction/description-original "nonmatching-desc"
:transaction/client {:client/name "2"
:db/id "client-2"}
:transaction/bank-account {:db/id "bank-account-2"
:bank-account/name "2"}
:transaction/date #inst "2019-01-15T23:23:00.000-08:00"
:transaction/amount 2.00
:transaction/id "2019-01-15 nonmatching-desc 2"
:db/id "b"}])
{:strs [a b client-1 client-2 bank-account-1 bank-account-2]} (get-in matching-transaction [:tempids])
a (str a)
b (str b)
@@ -253,34 +249,33 @@
(deftest test-match-transaction-rule
(testing "it should apply a rules"
(let [{:strs [transaction-id transaction-rule-id uneven-transaction-rule-id]} (-> (dc/transact conn
{:tx-data
[{:transaction/description-original "matching-desc"
:transaction/date #inst "2019-01-05T00:00:00.000-08:00"
:transaction/client {:client/name "1"
:db/id "client-1"}
:transaction/bank-account {:db/id "bank-account-1"
:bank-account/name "1"}
:transaction/amount 1.00
:db/id "transaction-id"}
[{:transaction/description-original "matching-desc"
:transaction/date #inst "2019-01-05T00:00:00.000-08:00"
:transaction/client {:client/name "1"
:db/id "client-1"}
:transaction/bank-account {:db/id "bank-account-1"
:bank-account/name "1"}
:transaction/amount 1.00
:db/id "transaction-id"}
{:db/id "transaction-rule-id"
:transaction-rule/note "transaction rule note"
:transaction-rule/description "matching-desc"
:transaction-rule/accounts [{:transaction-rule-account/location "A"
:transaction-rule-account/account {:account/numeric-code 123 :db/id "123"}
:transaction-rule-account/percentage 1.0}]}
{:db/id "uneven-transaction-rule-id"
:transaction-rule/note "transaction rule note"
:transaction-rule/description "matching-desc"
:transaction-rule/accounts [{:transaction-rule-account/location "A"
:transaction-rule-account/account {:account/numeric-code 123 :db/id "123"}
:transaction-rule-account/percentage 0.3333333}
{:transaction-rule-account/location "B"
:transaction-rule-account/account {:account/numeric-code 123 :db/id "123"}
:transaction-rule-account/percentage 0.33333333}
{:transaction-rule-account/location "c"
:transaction-rule-account/account {:account/numeric-code 123 :db/id "123"}
:transaction-rule-account/percentage 0.333333}]}]})
{:db/id "transaction-rule-id"
:transaction-rule/note "transaction rule note"
:transaction-rule/description "matching-desc"
:transaction-rule/accounts [{:transaction-rule-account/location "A"
:transaction-rule-account/account {:account/numeric-code 123 :db/id "123"}
:transaction-rule-account/percentage 1.0}]}
{:db/id "uneven-transaction-rule-id"
:transaction-rule/note "transaction rule note"
:transaction-rule/description "matching-desc"
:transaction-rule/accounts [{:transaction-rule-account/location "A"
:transaction-rule-account/account {:account/numeric-code 123 :db/id "123"}
:transaction-rule-account/percentage 0.3333333}
{:transaction-rule-account/location "B"
:transaction-rule-account/account {:account/numeric-code 123 :db/id "123"}
:transaction-rule-account/percentage 0.33333333}
{:transaction-rule-account/location "c"
:transaction-rule-account/account {:account/numeric-code 123 :db/id "123"}
:transaction-rule-account/percentage 0.333333}]}])
:tempids)
rule-test (-> (sut/query (admin-token) (v/graphql-query {:venia/operation {:operation/type :mutation
:operation/name "MatchTransactionRules"}

View File

@@ -3,19 +3,19 @@
[auto-ap.datomic :refer [conn]]
[auto-ap.graphql.accounts :as sut]
[auto-ap.integration.util :refer [admin-token user-token wrap-setup]]
[datomic.client.api :as dc]
[datomic.api :as dc]
[clojure.test :as t :refer [deftest is testing use-fixtures]]))
(use-fixtures :each wrap-setup)
(deftest test-account-search
(testing "It should find matching account names"
(dc/transact conn {:tx-data [{:account/name "Food Research"
:db/ident :client-specific-account
:account/numeric-code 51100
:account/search-terms "Food Research"
:account/applicability :account-applicability/global
:account/default-allowance :allowance/allowed}]})
(dc/transact conn [{:account/name "Food Research"
:db/ident :client-specific-account
:account/numeric-code 51100
:account/search-terms "Food Research"
:account/applicability :account-applicability/global
:account/default-allowance :allowance/allowed}])
(sut/rebuild-search-index)
(is (> (count (sut/search {:id (admin-token)}
{:query "Food Research"}
@@ -29,12 +29,12 @@
))
1)))
(testing "It should filter out accounts that are not allowed for clients"
(dc/transact conn {:tx-data [{:account/name "CLIENT SPECIFIC"
:db/ident :client-specific-account
:account/numeric-code 99999
:account/search-terms "CLIENTSPECIFIC"
:account/applicability :account-applicability/customized
:account/default-allowance :allowance/allowed}]})
(dc/transact conn [{:account/name "CLIENT SPECIFIC"
:db/ident :client-specific-account
:account/numeric-code 99999
:account/search-terms "CLIENTSPECIFIC"
:account/applicability :account-applicability/customized
:account/default-allowance :allowance/allowed}])
(sut/rebuild-search-index)
(is (= [] (sut/search {:id (admin-token)}
{:query "CLIENTSPECIFIC"}
@@ -42,12 +42,12 @@
)))
(testing "It should show up for the client specific version"
(let [client-id (-> (dc/transact conn {:tx-data [{:client/name "CLIENT"
:db/id "client"}
{:db/ident :client-specific-account
:account/client-overrides [{:account-client-override/client "client"
:account-client-override/name "HI"
:account-client-override/search-terms "HELLOWORLD"}]}]})
(let [client-id (-> (dc/transact conn [{:client/name "CLIENT"
:db/id "client"}
{:db/ident :client-specific-account
:account/client-overrides [{:account-client-override/client "client"
:account-client-override/name "HI"
:account-client-override/search-terms "HELLOWORLD"}]}])
:tempids
(get "client"))]
(sut/rebuild-search-index)
@@ -57,14 +57,14 @@
nil))))))
(testing "It should hide accounts that arent applicable"
(dc/transact conn {:tx-data [{:account/name "DENIED"
:db/ident :denied-account
:account/numeric-code 99998
:account/search-terms "DENIED"
:account/applicability :account-applicability/global
:account/default-allowance :allowance/denied
:account/vendor-allowance :allowance/denied
:account/invoice-allowance :allowance/denied}]})
(dc/transact conn [{:account/name "DENIED"
:db/ident :denied-account
:account/numeric-code 99998
:account/search-terms "DENIED"
:account/applicability :account-applicability/global
:account/default-allowance :allowance/denied
:account/vendor-allowance :allowance/denied
:account/invoice-allowance :allowance/denied}])
(is (= 0 (count (sut/search {:id (admin-token)}
{:query "DENIED"}
nil))))
@@ -78,14 +78,14 @@
nil)))))
(testing "It should warn when using a warn account"
(dc/transact conn {:tx-data [{:account/name "WARNING"
:db/ident :warn-account
:account/numeric-code 99997
:account/search-terms "WARNING"
:account/applicability :account-applicability/global
:account/default-allowance :allowance/warn
:account/vendor-allowance :allowance/warn
:account/invoice-allowance :allowance/warn}]})
(dc/transact conn [{:account/name "WARNING"
:db/ident :warn-account
:account/numeric-code 99997
:account/search-terms "WARNING"
:account/applicability :account-applicability/global
:account/default-allowance :allowance/warn
:account/vendor-allowance :allowance/warn
:account/invoice-allowance :allowance/warn}])
(sut/rebuild-search-index)
(is (some? (:warning (first (sut/search {:id (admin-token)}
{:query "WARNING"
@@ -100,14 +100,14 @@
:allowance :vendor}
nil))))))
(testing "It should only include admin accounts for admins"
(dc/transact conn {:tx-data [{:account/name "ADMINONLY"
:db/ident :warn-account
:account/numeric-code 99997
:account/search-terms "ADMINONLY"
:account/applicability :account-applicability/global
:account/default-allowance :allowance/admin-only
:account/vendor-allowance :allowance/admin-only
:account/invoice-allowance :allowance/admin-only}]})
(dc/transact conn [{:account/name "ADMINONLY"
:db/ident :warn-account
:account/numeric-code 99997
:account/search-terms "ADMINONLY"
:account/applicability :account-applicability/global
:account/default-allowance :allowance/admin-only
:account/vendor-allowance :allowance/admin-only
:account/invoice-allowance :allowance/admin-only}])
(sut/rebuild-search-index)
(is (= 1 (count (sut/search {:id (admin-token)}
{:query "ADMINONLY"}
@@ -117,19 +117,18 @@
nil)))))
(testing "It should allow searching for vendor accounts for invoices"
(let [vendor-id (-> (dc/transact conn {:tx-data
[{:account/name "VENDORONLY"
:db/id "vendor-only"
:db/ident :vendor-only
:account/numeric-code 99996
:account/search-terms "VENDORONLY"
:account/applicability :account-applicability/global
:account/default-allowance :allowance/allowed
:account/vendor-allowance :allowance/allowed
:account/invoice-allowance :allowance/denied}
{:vendor/name "Allowed"
:vendor/default-account "vendor-only"
:db/id "vendor"}]})
(let [vendor-id (-> (dc/transact conn [{:account/name "VENDORONLY"
:db/id "vendor-only"
:db/ident :vendor-only
:account/numeric-code 99996
:account/search-terms "VENDORONLY"
:account/applicability :account-applicability/global
:account/default-allowance :allowance/allowed
:account/vendor-allowance :allowance/allowed
:account/invoice-allowance :allowance/denied}
{:vendor/name "Allowed"
:vendor/default-account "vendor-only"
:db/id "vendor"}])
:tempids
(get "vendor"))]
(sut/rebuild-search-index)
@@ -146,11 +145,11 @@
(deftest get-graphql
(testing "should retrieve a single account"
(dc/transact conn {:tx-data [{:account/numeric-code 1
:account/default-allowance :allowance/allowed
:account/type :account-type/asset
:account/location "A"
:account/name "Test"}]})
(dc/transact conn [{:account/numeric-code 1
:account/default-allowance :allowance/allowed
:account/type :account-type/asset
:account/location "A"
:account/name "Test"}])
(is (= {:name "Test",
:invoice_allowance nil,

View File

@@ -11,7 +11,7 @@
wrap-setup]]
[clojure.test :as t :refer [deftest is testing use-fixtures]]
[com.brunobonacci.mulog :as mu]
[datomic.client.api :as d]))
[datomic.api :as d]))
(use-fixtures :each wrap-setup)
@@ -31,19 +31,19 @@
(deftest get-payment-page
(testing "Should list payments"
(let [{{:strs [bank-id check-id client-id]} :tempids} (d/transact conn {:tx-data [{:bank-account/code "bank"
:db/id "bank-id"}
{:client/code "client"
:db/id "client-id"}
{:db/id "check-id"
:payment/check-number 1000
:payment/bank-account "bank-id"
:payment/client "client-id"
:payment/type :payment-type/check
:payment/amount 123.50
:payment/paid-to "Someone"
:payment/status :payment-status/pending
:payment/date #inst "2022-01-01"}]})]
(let [{{:strs [bank-id check-id client-id]} :tempids} (d/transact conn [{:bank-account/code "bank"
:db/id "bank-id"}
{:client/code "client"
:db/id "client-id"}
{:db/id "check-id"
:payment/check-number 1000
:payment/bank-account "bank-id"
:payment/client "client-id"
:payment/type :payment-type/check
:payment/amount 123.50
:payment/paid-to "Someone"
:payment/status :payment-status/pending
:payment/date #inst "2022-01-01"}])]
(is (= [ {:amount 123.5,
:type :check,
:bank_account {:id bank-id, :code "bank"},
@@ -86,103 +86,103 @@
(deftest void-payment
(testing "Should void payments"
(let [{{:strs [bank-id check-id client-id]} :tempids} (d/transact conn {:tx-data [{:bank-account/code "bank"
:db/id "bank-id"}
{:client/code "client"
:db/id "client-id"}
(sample-payment :db/id "check-id")]})]
(let [{{:strs [bank-id check-id client-id]} :tempids} (d/transact conn [{:bank-account/code "bank"
:db/id "bank-id"}
{:client/code "client"
:db/id "client-id"}
(sample-payment :db/id "check-id")])]
(sut/void-payment {:id (admin-token)} {:payment_id check-id} nil)
(is (= :payment-status/voided (-> (d/pull (d/db conn) [{:payment/status [:db/ident ]}] check-id)
:payment/status
:db/ident)))))
(testing "Should not void payments if account is locked"
(let [{{:strs [check-id]} :tempids} (d/transact conn {:tx-data [{:bank-account/code "bank"
:db/id "bank-id"}
{:client/code "client"
:db/id "client-id"
:client/locked-until #inst "2030-01-01"}
(sample-payment :payment/client "client-id"
:db/id "check-id"
:payment/date #inst "2020-01-01")]})]
(let [{{:strs [check-id]} :tempids} (d/transact conn [{:bank-account/code "bank"
:db/id "bank-id"}
{:client/code "client"
:db/id "client-id"
:client/locked-until #inst "2030-01-01"}
(sample-payment :payment/client "client-id"
:db/id "check-id"
:payment/date #inst "2020-01-01")])]
(is (thrown? Exception (sut/void-payment {:id (admin-token)} {:payment_id check-id} nil))))))
(deftest void-payments
(testing "bulk void"
(testing "Should bulk void payments if account is not locked"
(let [{{:strs [check-id]} :tempids} (d/transact conn {:tx-data [{:bank-account/code "bank"
:db/id "bank-id"}
{:client/code "client-new"
:db/id "client-id"}
(sample-payment :payment/client "client-id"
:db/id "check-id"
:payment/date #inst "2020-01-01")]})]
(let [{{:strs [check-id]} :tempids} (d/transact conn [{:bank-account/code "bank"
:db/id "bank-id"}
{:client/code "client-new"
:db/id "client-id"}
(sample-payment :payment/client "client-id"
:db/id "check-id"
:payment/date #inst "2020-01-01")])]
(sut/void-payments {:id (admin-token)} {:filters {:date_range {:start #inst "2000-01-01"}}} nil)
(is (= :payment-status/voided (-> (d/pull (d/db conn) '[{:payment/status [:db/ident]}] check-id)
:payment/status
:db/ident)))))
(testing "Should only void a payment if it matches filter criteria"
(let [{{:strs [check-id]} :tempids} (d/transact conn {:tx-data [{:bank-account/code "bank"
:db/id "bank-id"}
{:client/code "client-new"
:db/id "client-id"}
(sample-payment :payment/client "client-id"
:db/id "check-id"
:payment/date #inst "2020-01-01")]})]
(let [{{:strs [check-id]} :tempids} (d/transact conn [{:bank-account/code "bank"
:db/id "bank-id"}
{:client/code "client-new"
:db/id "client-id"}
(sample-payment :payment/client "client-id"
:db/id "check-id"
:payment/date #inst "2020-01-01")])]
(sut/void-payments {:id (admin-token)} {:filters {:date_range {:start #inst "2022-01-01"}}} nil)
(is (= :payment-status/pending (-> (d/pull (d/db conn) '[{:payment/status [:db/ident]}] check-id)
:payment/status
:db/ident)))))
(testing "Should not bulk void payments if account is locked"
(let [{{:strs [check-id]} :tempids} (d/transact conn {:tx-data [{:bank-account/code "bank"
:db/id "bank-id"}
{:client/code "client"
:db/id "client-id"
:client/locked-until #inst "2030-01-01"}
(sample-payment :payment/client "client-id"
:db/id "check-id"
:payment/date #inst "2020-01-01")]})]
(let [{{:strs [check-id]} :tempids} (d/transact conn [{:bank-account/code "bank"
:db/id "bank-id"}
{:client/code "client"
:db/id "client-id"
:client/locked-until #inst "2030-01-01"}
(sample-payment :payment/client "client-id"
:db/id "check-id"
:payment/date #inst "2020-01-01")])]
(sut/void-payments {:id (admin-token)} {:filters {:date_range {:start #inst "2000-01-01"}}} nil)
(is (= :payment-status/pending (-> (d/pull (d/db conn) '[{:payment/status [:db/ident]}] check-id)
:payment/status
:db/ident)))))
(testing "Only admins should be able to bulk void"
(let [{{:strs [check-id]} :tempids} (d/transact conn {:tx-data [{:bank-account/code "bank"
:db/id "bank-id"}
{:client/code "client"
:db/id "client-id"}
(sample-payment :payment/client "client-id"
:db/id "check-id"
:payment/date #inst "2020-01-01")]})]
(let [{{:strs [check-id]} :tempids} (d/transact conn [{:bank-account/code "bank"
:db/id "bank-id"}
{:client/code "client"
:db/id "client-id"}
(sample-payment :payment/client "client-id"
:db/id "check-id"
:payment/date #inst "2020-01-01")])]
(is (thrown? Exception (sut/void-payments {:id (user-token)} {:filters {:date_range {:start #inst "2000-01-01"}}} nil)))))))
(deftest print-checks
(testing "Print checks"
(testing "Should allow 'printing' cash checks"
(let [{{:strs [invoice-id client-id bank-id]} :tempids} (d/transact conn {:tx-data [{:client/code "client"
:db/id "client-id"
:client/locked-until #inst "2030-01-01"
:client/bank-accounts [{:bank-account/code "bank"
:db/id "bank-id"}]}
{:db/id "vendor-id"
:vendor/name "V"
:vendor/default-account "account-id"}
{:db/id "account-id"
:account/name "My account"
:account/numeric-code 21000}
{:db/id "invoice-id"
:invoice/client "client-id"
:invoice/date #inst "2022-01-01"
:invoice/vendor "vendor-id"
:invoice/total 30.0
:invoice/outstanding-balance 30.0
:invoice/expense-accounts [{:db/id "invoice-expense-account"
:invoice-expense-account/account "account-id"
:invoice-expense-account/amount 30.0}]}]})]
(let [{{:strs [invoice-id client-id bank-id]} :tempids} (d/transact conn [{:client/code "client"
:db/id "client-id"
:client/locked-until #inst "2030-01-01"
:client/bank-accounts [{:bank-account/code "bank"
:db/id "bank-id"}]}
{:db/id "vendor-id"
:vendor/name "V"
:vendor/default-account "account-id"}
{:db/id "account-id"
:account/name "My account"
:account/numeric-code 21000}
{:db/id "invoice-id"
:invoice/client "client-id"
:invoice/date #inst "2022-01-01"
:invoice/vendor "vendor-id"
:invoice/total 30.0
:invoice/outstanding-balance 30.0
:invoice/expense-accounts [{:db/id "invoice-expense-account"
:invoice-expense-account/account "account-id"
:invoice-expense-account/amount 30.0}]}])]
(let [paid-invoice (-> (sut/print-checks {:id (admin-token)} {:invoice_payments [{:invoice_id invoice-id
:amount 30.0}]
:client_id client-id
@@ -211,25 +211,25 @@
:id))))))))
(testing "Should allow 'printing' debit checks"
(let [{{:strs [invoice-id client-id bank-id]} :tempids} (d/transact conn {:tx-data [{:client/code "client"
:db/id "client-id"
:client/bank-accounts [{:bank-account/code "bank"
:db/id "bank-id"}]}
{:db/id "vendor-id"
:vendor/name "V"
:vendor/default-account "account-id"}
{:db/id "account-id"
:account/name "My account"
:account/numeric-code 21000}
{:db/id "invoice-id"
:invoice/client "client-id"
:invoice/date #inst "2022-01-01"
:invoice/vendor "vendor-id"
:invoice/total 50.0
:invoice/outstanding-balance 50.0
:invoice/expense-accounts [{:db/id "invoice-expense-account"
:invoice-expense-account/account "account-id"
:invoice-expense-account/amount 50.0}]}]})]
(let [{{:strs [invoice-id client-id bank-id]} :tempids} (d/transact conn [{:client/code "client"
:db/id "client-id"
:client/bank-accounts [{:bank-account/code "bank"
:db/id "bank-id"}]}
{:db/id "vendor-id"
:vendor/name "V"
:vendor/default-account "account-id"}
{:db/id "account-id"
:account/name "My account"
:account/numeric-code 21000}
{:db/id "invoice-id"
:invoice/client "client-id"
:invoice/date #inst "2022-01-01"
:invoice/vendor "vendor-id"
:invoice/total 50.0
:invoice/outstanding-balance 50.0
:invoice/expense-accounts [{:db/id "invoice-expense-account"
:invoice-expense-account/account "account-id"
:invoice-expense-account/amount 50.0}]}])]
(let [paid-invoice (-> (sut/print-checks {:id (admin-token)} {:invoice_payments [{:invoice_id invoice-id
:amount 50.0}]
:client_id client-id
@@ -258,33 +258,33 @@
:id)))))))))
(testing "Should allow printing checks"
(let [{{:strs [invoice-id client-id bank-id]} :tempids} (d/transact conn {:tx-data [{:client/code "client"
:db/id "client-id"
:client/bank-accounts [{:bank-account/code "bank"
:bank-account/type :bank-account-type/check
(let [{{:strs [invoice-id client-id bank-id]} :tempids} (d/transact conn [{:client/code "client"
:db/id "client-id"
:client/bank-accounts [{:bank-account/code "bank"
:bank-account/type :bank-account-type/check
:bank-account/check-number 10000
:db/id "bank-id"}]}
{:db/id "vendor-id"
:vendor/name "V"
:vendor/default-account "account-id"}
{:db/id "account-id"
:account/name "My account"
:account/numeric-code 21000}
{:db/id "invoice-id"
:invoice/client "client-id"
:invoice/date #inst "2022-01-01"
:invoice/vendor "vendor-id"
:invoice/total 150.0
:invoice/outstanding-balance 150.0
:invoice/expense-accounts [{:db/id "invoice-expense-account"
:invoice-expense-account/account "account-id"
:invoice-expense-account/amount 150.0}]}]})]
(let [result (-> (sut/print-checks {:id (admin-token)} {:invoice_payments [{:invoice_id invoice-id
:amount 150.0}]
:client_id client-id
:bank_account_id bank-id
:type :check} nil)
:bank-account/check-number 10000
:db/id "bank-id"}]}
{:db/id "vendor-id"
:vendor/name "V"
:vendor/default-account "account-id"}
{:db/id "account-id"
:account/name "My account"
:account/numeric-code 21000}
{:db/id "invoice-id"
:invoice/client "client-id"
:invoice/date #inst "2022-01-01"
:invoice/vendor "vendor-id"
:invoice/total 150.0
:invoice/outstanding-balance 150.0
:invoice/expense-accounts [{:db/id "invoice-expense-account"
:invoice-expense-account/account "account-id"
:invoice-expense-account/amount 150.0}]}])]
(let [result (-> (sut/print-checks {:id (admin-token)} {:invoice_payments [{:invoice_id invoice-id
:amount 150.0}]
:client_id client-id
:bank_account_id bank-id
:type :check} nil)
:invoices
first)
paid-invoice result]

View File

@@ -4,7 +4,7 @@
[auto-ap.datomic :refer [conn pull-attr]]
[auto-ap.graphql.clients :as sut]
[auto-ap.integration.util :refer [wrap-setup user-token admin-token]]
[datomic.client.api :as dc]
[datomic.api :as dc]
[clojure.test :as t :refer [deftest is testing use-fixtures]]))
(use-fixtures :each wrap-setup)

View File

@@ -11,7 +11,7 @@
test-invoice
test-vendor
wrap-setup]]
[datomic.client.api :as d]))
[datomic.api :as d]))
(use-fixtures :each wrap-setup)
(deftest test-add-invoice

View File

@@ -5,7 +5,7 @@
[iol-ion.tx :refer [upsert-ledger]]
[auto-ap.integration.util :refer [wrap-setup]]
[clojure.test :as t :refer [deftest is testing use-fixtures]]
[datomic.client.api :as d]))
[datomic.api :as d]))
(use-fixtures :each wrap-setup)
@@ -22,48 +22,48 @@
line-2-1
line-2-2
line-3-1
line-3-2]} (:tempids (d/transact conn {:tx-data [{:db/id "test-account-1"
:account/type :account-type/asset}
{:db/id "test-account-2"
:account/type :account-type/equity}
{:db/id "test-client"
:client/code "TEST"}
`(upsert-ledger {:db/id "journal-entry-1"
:journal-entry/external-id "1"
:journal-entry/date #inst "2022-01-01"
:journal-entry/client "test-client"
:journal-entry/line-items [{:db/id "line-1-1"
:journal-entry-line/account "test-account-1"
:journal-entry-line/location "A"
:journal-entry-line/debit 10.0}
{:db/id "line-1-2"
:journal-entry-line/account "test-account-2"
:journal-entry-line/location "A"
:journal-entry-line/credit 10.0}]})
`(upsert-ledger {:db/id "journal-entry-2"
:journal-entry/date #inst "2022-01-02"
:journal-entry/external-id "2"
:journal-entry/client "test-client"
:journal-entry/line-items [{:db/id "line-2-1"
:journal-entry-line/account "test-account-1"
:journal-entry-line/location "A"
:journal-entry-line/debit 50.0}
{:db/id "line-2-2"
:journal-entry-line/account "test-account-2"
:journal-entry-line/location "A"
:journal-entry-line/credit 50.0}]})
`(upsert-ledger {:db/id "journal-entry-3"
:journal-entry/date #inst "2022-01-03"
:journal-entry/external-id "3"
:journal-entry/client "test-client"
:journal-entry/line-items [{:db/id "line-3-1"
:journal-entry-line/account "test-account-1"
:journal-entry-line/location "A"
:journal-entry-line/debit 150.0}
{:db/id "line-3-2"
:journal-entry-line/account "test-account-2"
:journal-entry-line/location "A"
:journal-entry-line/credit 150.0}]})]}))]
line-3-2]} (:tempids (d/transact conn [{:db/id "test-account-1"
:account/type :account-type/asset}
{:db/id "test-account-2"
:account/type :account-type/equity}
{:db/id "test-client"
:client/code "TEST"}
`(upsert-ledger {:db/id "journal-entry-1"
:journal-entry/external-id "1"
:journal-entry/date #inst "2022-01-01"
:journal-entry/client "test-client"
:journal-entry/line-items [{:db/id "line-1-1"
:journal-entry-line/account "test-account-1"
:journal-entry-line/location "A"
:journal-entry-line/debit 10.0}
{:db/id "line-1-2"
:journal-entry-line/account "test-account-2"
:journal-entry-line/location "A"
:journal-entry-line/credit 10.0}]})
`(upsert-ledger {:db/id "journal-entry-2"
:journal-entry/date #inst "2022-01-02"
:journal-entry/external-id "2"
:journal-entry/client "test-client"
:journal-entry/line-items [{:db/id "line-2-1"
:journal-entry-line/account "test-account-1"
:journal-entry-line/location "A"
:journal-entry-line/debit 50.0}
{:db/id "line-2-2"
:journal-entry-line/account "test-account-2"
:journal-entry-line/location "A"
:journal-entry-line/credit 50.0}]})
`(upsert-ledger {:db/id "journal-entry-3"
:journal-entry/date #inst "2022-01-03"
:journal-entry/external-id "3"
:journal-entry/client "test-client"
:journal-entry/line-items [{:db/id "line-3-1"
:journal-entry-line/account "test-account-1"
:journal-entry-line/location "A"
:journal-entry-line/debit 150.0}
{:db/id "line-3-2"
:journal-entry-line/account "test-account-2"
:journal-entry-line/location "A"
:journal-entry-line/credit 150.0}]})]))]
(testing "should set running-balance on ledger entries missing them"
@@ -79,10 +79,9 @@
(testing "should recompute if the data is out of date"
(d/transact conn
{:tx-data
[{:db/id line-1-1
:journal-entry-line/dirty true
:journal-entry-line/running-balance 123810.23}]})
[{:db/id line-1-1
:journal-entry-line/dirty true
:journal-entry-line/running-balance 123810.23}])
(sut/refresh-running-balance-cache)
(is (= [-10.0 -60.0 -210.0]
@@ -91,20 +90,18 @@
(testing "should recompute every entry after the out of date one"
(d/transact conn
{:tx-data
[{:db/id line-1-1
:journal-entry-line/dirty true
:journal-entry-line/debit 70.0}]})
[{:db/id line-1-1
:journal-entry-line/dirty true
:journal-entry-line/debit 70.0}])
(sut/refresh-running-balance-cache)
(is (= [-70.0 -120.0 -270.0]
(map #(pull-attr (d/db conn) :journal-entry-line/running-balance %) [line-1-1 line-2-1 line-3-1]))))
(testing "should not recompute entries that aren't dirty"
(d/transact conn
{:tx-data
[{:db/id line-1-1
:journal-entry-line/dirty false
:journal-entry-line/debit 90.0}]})
[{:db/id line-1-1
:journal-entry-line/dirty false
:journal-entry-line/debit 90.0}])
(sut/refresh-running-balance-cache)
(is (= [-70.0 -120.0 -270.0]
(map #(pull-attr (d/db conn) :journal-entry-line/running-balance %) [line-1-1 line-2-1 line-3-1])))
@@ -112,19 +109,18 @@
)
(testing "changing a ledger entry should mark the line items as dirty"
(d/transact conn
{:tx-data
[`(upsert-ledger ~{:db/id journal-entry-2
:journal-entry/date #inst "2022-01-02"
:journal-entry/client test-client
:journal-entry/external-id "2"
:journal-entry/line-items [{:db/id "line-2-1"
:journal-entry-line/account test-account-1
:journal-entry-line/location "A"
:journal-entry-line/debit 50.0}
{:db/id "line-2-2"
:journal-entry-line/account test-account-2
:journal-entry-line/location "A"
:journal-entry-line/credit 50.0}]})]})
[`(upsert-ledger ~{:db/id journal-entry-2
:journal-entry/date #inst "2022-01-02"
:journal-entry/client test-client
:journal-entry/external-id "2"
:journal-entry/line-items [{:db/id "line-2-1"
:journal-entry-line/account test-account-1
:journal-entry-line/location "A"
:journal-entry-line/debit 50.0}
{:db/id "line-2-2"
:journal-entry-line/account test-account-2
:journal-entry-line/location "A"
:journal-entry-line/credit 50.0}]})])
(is (= [true true]
(->> (d/pull (d/db conn) '[{:journal-entry/line-items [:journal-entry-line/dirty]}] journal-entry-2)
(:journal-entry/line-items)

View File

@@ -14,7 +14,7 @@
user-token
wrap-setup]]
[clojure.test :as t :refer [deftest is testing use-fixtures]]
[datomic.client.api :as dc]))
[datomic.api :as dc]))
(use-fixtures :each wrap-setup)

View File

@@ -6,7 +6,7 @@
[auto-ap.integration.util :refer [admin-token user-token wrap-setup]]
[clojure.test :as t :refer [deftest is testing use-fixtures]]
[com.brunobonacci.mulog :as mu]
[datomic.client.api :as d]))
[datomic.api :as d]))
(use-fixtures :each wrap-setup)
@@ -15,12 +15,12 @@
(testing "should allow editing a user"
(let [{{:strs [user-id] } :tempids} (d/transact conn {:tx-data [{:db/id "user-id" :user/name "Bryce"}]})
(let [{{:strs [user-id] } :tempids} (d/transact conn [{:db/id "user-id" :user/name "Bryce"}])
result (sut/edit-user {:id (admin-token)} {:edit_user {:role :power_user :id user-id}} nil)]
(is (some? (:id result))
(= :power_user (:role result)))
(testing "Should allow adding clients"
(let [{{:strs [client-id] } :tempids} (d/transact conn {:tx-data [{:db/id "client-id" :client/name "Bryce"}]})
(let [{{:strs [client-id] } :tempids} (d/transact conn [{:db/id "client-id" :client/name "Bryce"}])
result (sut/edit-user {:id (admin-token)} {:edit_user {:role :power_user
:id user-id
:clients [(str client-id)]}} nil)]

View File

@@ -1,5 +1,5 @@
(ns auto-ap.integration.util
(:require [datomic.client.api :as dc]
(:require [datomic.api :as dc]
[auto-ap.datomic :refer [client conn transact-schema]]
[clj-time.core :as time]))
@@ -102,16 +102,16 @@
(dissoc x :id))
(defn setup-test-data [data]
(:tempids (dc/transact conn {:tx-data (into data
[(test-account :db/id "test-account-id")
(test-client :db/id "test-client-id"
:client/bank-accounts [(test-bank-account :db/id "test-bank-account-id")])
(test-vendor :db/id "test-vendor-id")
{:db/id "accounts-payable-id"
:account/name "Accounts Payable"
:db/ident :account/accounts-payable
:account/numeric-code 21000
:account/account-set "default"}])})))
(:tempids (dc/transact conn (into data
[(test-account :db/id "test-account-id")
(test-client :db/id "test-client-id"
:client/bank-accounts [(test-bank-account :db/id "test-bank-account-id")])
(test-vendor :db/id "test-vendor-id")
{:db/id "accounts-payable-id"
:account/name "Accounts Payable"
:db/ident :account/accounts-payable
:account/numeric-code 21000
:account/account-set "default"}]))))
(defn apply-tx [data]
(:db-after (dc/transact conn {:tx-data data})))
(:db-after (dc/transact conn data)))

View File

@@ -6,7 +6,7 @@
[auto-ap.routes.invoices :as sut]
[clj-time.coerce :as coerce]
[clojure.test :as t]
[datomic.client.api :as dc]))
[datomic.api :as dc]))
(t/use-fixtures :each wrap-setup)
@@ -39,7 +39,7 @@
(t/deftest import-uploaded-invoices
(t/testing "It should import one"
(dc/transact conn {:tx-data [client expense-account vendor]})
(dc/transact conn [client expense-account vendor])
(rebuild-search-index)
(t/is (= 0 (invoice-count-for-client [:client/code "ABC"])))
@@ -63,18 +63,17 @@
(t/is (= [["DE"]] (dc/q '[:find ?l
:where [?i :invoice/invoice-number "789"]
[?i :invoice/expense-accounts ?ea]
[?ea :invoice-expense-account/location ?l]]
[?ea :invoice-expense-account/location ?l]
(dc/db conn)))))
(t/testing "Should code invoice"
(let [{{:strs [my-default-account coded-vendor]} :tempids} (dc/transact conn
{:tx-data
[{:vendor/name "Coded"
:db/id "coded-vendor"
:vendor/terms 12
:vendor/default-account "my-default-account"}
{:db/id "my-default-account"
:account/name "My default-account"}]})]
[{:vendor/name "Coded"
:db/id "coded-vendor"
:vendor/terms 12
:vendor/default-account "my-default-account"}
{:db/id "my-default-account"
:account/name "My default-account"}])]
(sut/import-uploaded-invoice user [(assoc invoice
:invoice-number "456"
:customer-identifier "ABC"

View File

@@ -4,7 +4,7 @@
[auto-ap.integration.util
:refer [apply-tx setup-test-data test-invoice test-transaction wrap-setup]]
[clojure.test :as t :refer [deftest is testing use-fixtures]]
[datomic.client.api :as dc]
[datomic.api :as dc]
[iol-ion.tx :as sut]))
(use-fixtures :each wrap-setup)