Fixes two types of bugs.
This commit is contained in:
@@ -265,6 +265,7 @@
|
||||
(assert-can-see-client (:id context) (:db/id (:invoice/client (d-invoices/get-by-id (:invoice_id args)))))
|
||||
(let [invoice-id (:invoice_id args)
|
||||
invoice (d-invoices/get-by-id invoice-id)
|
||||
_ (assert-valid-expense-accounts (:expense_accounts args))
|
||||
deleted (deleted-expense-accounts invoice (:expense_accounts args))
|
||||
updated {:db/id invoice-id
|
||||
:invoice/expense-accounts (map
|
||||
|
||||
@@ -338,7 +338,8 @@
|
||||
:args [(d/db auto-ap.datomic/conn)]}))
|
||||
]
|
||||
(filter
|
||||
(fn [[e accounts]] (not= accounts (get jel-accounts e)))
|
||||
(fn [[e accounts]]
|
||||
(not= accounts (get jel-accounts e)))
|
||||
invoice-accounts)))
|
||||
|
||||
(defn touch-broken-ledger []
|
||||
|
||||
@@ -100,25 +100,36 @@
|
||||
(map (fn [r] (update r :transaction-rule/description #(some-> % ->pattern))))
|
||||
(filter #(rule-applies? transaction %))))
|
||||
|
||||
(defn spread-cents [cents n]
|
||||
(let [default-spread (for [x (range n)]
|
||||
(int (* cents (/ 1.0 n))))
|
||||
short-by (- cents (reduce + 0 default-spread)) ;; amount that was lost in the differenc
|
||||
adjusted-spread (map
|
||||
(fn [cents increments]
|
||||
(+ cents increments))
|
||||
|
||||
default-spread
|
||||
(concat (take short-by (repeat 1)) (repeat 0)))]
|
||||
(filter #(> % 0) adjusted-spread)))
|
||||
|
||||
(defn apply-rule [transaction rule valid-locations]
|
||||
(with-precision 2
|
||||
(let [accounts (vec (mapcat
|
||||
(fn [tra]
|
||||
(if (= "Shared" (:transaction-rule-account/location tra))
|
||||
(map
|
||||
(fn [location]
|
||||
{:transaction-account/account (:db/id (:transaction-rule-account/account tra))
|
||||
:transaction-account/amount (Math/abs (* (/ 1.0 (count valid-locations))
|
||||
(:transaction-rule-account/percentage tra)
|
||||
(:transaction/amount transaction)))
|
||||
:transaction-account/location location})
|
||||
|
||||
|
||||
valid-locations)
|
||||
[(cond-> {:transaction-account/account (:db/id (:transaction-rule-account/account tra))
|
||||
:transaction-account/amount (Math/abs (* (:transaction-rule-account/percentage tra)
|
||||
(:transaction/amount transaction)))}
|
||||
(:transaction-rule-account/location tra) (assoc :transaction-account/location (:transaction-rule-account/location tra)))]))
|
||||
(let [cents-to-distribute (int (Math/round (Math/abs (* (:transaction-rule-account/percentage tra)
|
||||
(:transaction/amount transaction)
|
||||
100))))]
|
||||
(if (= "Shared" (:transaction-rule-account/location tra))
|
||||
(->> valid-locations
|
||||
(map
|
||||
(fn [cents location]
|
||||
{:transaction-account/account (:db/id (:transaction-rule-account/account tra))
|
||||
:transaction-account/amount (* 0.01 cents)
|
||||
:transaction-account/location location})
|
||||
(spread-cents cents-to-distribute (count valid-locations))))
|
||||
[(cond-> {:transaction-account/account (:db/id (:transaction-rule-account/account tra))
|
||||
:transaction-account/amount (* 0.01 cents-to-distribute)}
|
||||
(:transaction-rule-account/location tra) (assoc :transaction-account/location (:transaction-rule-account/location tra)))])))
|
||||
(filter (comp seq :transaction-rule-account/account) (:transaction-rule/accounts rule))))
|
||||
accounts (mapv
|
||||
(fn [a]
|
||||
|
||||
@@ -173,86 +173,84 @@
|
||||
first)))
|
||||
|
||||
(defn transactions->txs [transactions transaction->bank-account apply-rules existing]
|
||||
(doto
|
||||
(into []
|
||||
(into []
|
||||
|
||||
(for [transaction transactions
|
||||
:let [{post-date :postDate
|
||||
account-id :accountId
|
||||
date :date
|
||||
id :id
|
||||
{amount :amount} :amount
|
||||
{description-original :original
|
||||
description-simple :simple} :description
|
||||
{merchant-id :id
|
||||
merchant-name :name} :merchant
|
||||
base-type :baseType
|
||||
type :type
|
||||
status :status}
|
||||
transaction
|
||||
amount (if (= "DEBIT" base-type)
|
||||
(- amount)
|
||||
amount)
|
||||
check-number (extract-check-number transaction)
|
||||
bank-account (transaction->bank-account transaction)
|
||||
bank-account-id (:db/id bank-account)
|
||||
client (:client/_bank-accounts bank-account)
|
||||
client-id (:db/id client)
|
||||
valid-locations (or (:bank-account/locations bank-account) (:client/locations client))
|
||||
|
||||
date (time/parse date "YYYY-MM-dd")]
|
||||
:when (and client-id
|
||||
(not (existing (sha-256 (str id))))
|
||||
(= "POSTED" status)
|
||||
(for [transaction transactions
|
||||
:let [{post-date :postDate
|
||||
account-id :accountId
|
||||
date :date
|
||||
id :id
|
||||
{amount :amount} :amount
|
||||
{description-original :original
|
||||
description-simple :simple} :description
|
||||
{merchant-id :id
|
||||
merchant-name :name} :merchant
|
||||
base-type :baseType
|
||||
type :type
|
||||
status :status}
|
||||
transaction
|
||||
amount (if (= "DEBIT" base-type)
|
||||
(- amount)
|
||||
amount)
|
||||
check-number (extract-check-number transaction)
|
||||
bank-account (transaction->bank-account transaction)
|
||||
bank-account-id (:db/id bank-account)
|
||||
client (:client/_bank-accounts bank-account)
|
||||
client-id (:db/id client)
|
||||
valid-locations (or (:bank-account/locations bank-account) (:client/locations client))
|
||||
|
||||
date (time/parse date "YYYY-MM-dd")]
|
||||
:when (and client-id
|
||||
(not (existing (sha-256 (str id))))
|
||||
(= "POSTED" status)
|
||||
|
||||
(or (not (:start-date bank-account))
|
||||
(t/after? date (:start-date bank-account))))]
|
||||
(let [existing-check (transaction->existing-payment transaction check-number client-id bank-account-id amount id)
|
||||
autopay-invoices-matches (when-not existing-check
|
||||
(match-transaction-to-unfulfilled-autopayments amount client-id ))
|
||||
unpaid-invoices-matches (when-not existing-check
|
||||
(match-transaction-to-unpaid-invoices amount client-id ))
|
||||
expected-deposit (when (and (> amount 0.0)
|
||||
(not existing-check))
|
||||
(find-expected-deposit client-id amount date))]
|
||||
(cond->
|
||||
[#:transaction
|
||||
{:post-date (coerce/to-date (time/parse post-date "YYYY-MM-dd"))
|
||||
:id (sha-256 (str id))
|
||||
:raw-id (str id)
|
||||
:account-id account-id
|
||||
:date (coerce/to-date date)
|
||||
:amount (double amount)
|
||||
:description-original (some-> description-original (str/replace #"\s+" " "))
|
||||
:description-simple (some-> description-simple (str/replace #"\s+" " "))
|
||||
:approval-status :transaction-approval-status/unapproved
|
||||
:type type
|
||||
:status status
|
||||
:client client-id
|
||||
:check-number check-number
|
||||
:bank-account bank-account-id}]
|
||||
existing-check (update 0 #(assoc % :transaction/approval-status :transaction-approval-status/approved
|
||||
:transaction/payment {:db/id (:db/id existing-check)
|
||||
:payment/status :payment-status/cleared}
|
||||
:transaction/vendor (:db/id (:payment/vendor existing-check))
|
||||
:transaction/location "A"
|
||||
:transaction/accounts [#:transaction-account
|
||||
{:account (:db/id (a/get-account-by-numeric-code-and-sets 21000 ["default"]))
|
||||
:location "A"
|
||||
:amount (Math/abs (double amount))}]))
|
||||
(or (not (:start-date bank-account))
|
||||
(t/after? date (:start-date bank-account))))]
|
||||
(let [existing-check (transaction->existing-payment transaction check-number client-id bank-account-id amount id)
|
||||
autopay-invoices-matches (when-not existing-check
|
||||
(match-transaction-to-unfulfilled-autopayments amount client-id ))
|
||||
unpaid-invoices-matches (when-not existing-check
|
||||
(match-transaction-to-unpaid-invoices amount client-id ))
|
||||
expected-deposit (when (and (> amount 0.0)
|
||||
(not existing-check))
|
||||
(find-expected-deposit client-id amount date))]
|
||||
(cond->
|
||||
[#:transaction
|
||||
{:post-date (coerce/to-date (time/parse post-date "YYYY-MM-dd"))
|
||||
:id (sha-256 (str id))
|
||||
:raw-id (str id)
|
||||
:account-id account-id
|
||||
:date (coerce/to-date date)
|
||||
:amount (double amount)
|
||||
:description-original (some-> description-original (str/replace #"\s+" " "))
|
||||
:description-simple (some-> description-simple (str/replace #"\s+" " "))
|
||||
:approval-status :transaction-approval-status/unapproved
|
||||
:type type
|
||||
:status status
|
||||
:client client-id
|
||||
:check-number check-number
|
||||
:bank-account bank-account-id}]
|
||||
existing-check (update 0 #(assoc % :transaction/approval-status :transaction-approval-status/approved
|
||||
:transaction/payment {:db/id (:db/id existing-check)
|
||||
:payment/status :payment-status/cleared}
|
||||
:transaction/vendor (:db/id (:payment/vendor existing-check))
|
||||
:transaction/location "A"
|
||||
:transaction/accounts [#:transaction-account
|
||||
{:account (:db/id (a/get-account-by-numeric-code-and-sets 21000 ["default"]))
|
||||
:location "A"
|
||||
:amount (Math/abs (double amount))}]))
|
||||
|
||||
;; temporarily removed to automatically match autopaid invoices
|
||||
#_(and (not existing-check)
|
||||
(seq autopay-invoices-matches)) #_(add-new-payment autopay-invoices-matches bank-account-id client-id)
|
||||
expected-deposit (update 0 #(assoc % :transaction/expected-deposit {:db/id expected-deposit
|
||||
:expected-deposit/status :expected-deposit-status/cleared}))
|
||||
|
||||
;; temporarily removed to automatically match autopaid invoices
|
||||
#_(and (not existing-check)
|
||||
(seq autopay-invoices-matches)) #_(add-new-payment autopay-invoices-matches bank-account-id client-id)
|
||||
expected-deposit (update 0 #(assoc % :transaction/expected-deposit {:db/id expected-deposit
|
||||
:expected-deposit/status :expected-deposit-status/cleared}))
|
||||
|
||||
|
||||
(and (not (seq autopay-invoices-matches))
|
||||
(not (seq unpaid-invoices-matches))
|
||||
(not expected-deposit)) (update 0 #(apply-rules % valid-locations))
|
||||
true (update 0 remove-nils)))))
|
||||
println))
|
||||
(and (not (seq autopay-invoices-matches))
|
||||
(not (seq unpaid-invoices-matches))
|
||||
(not expected-deposit)) (update 0 #(apply-rules % valid-locations))
|
||||
true (update 0 remove-nils))))))
|
||||
|
||||
|
||||
(defn batch-transact [transactions]
|
||||
|
||||
Reference in New Issue
Block a user