You can now pay invoices with credits from the same vendor.

This commit is contained in:
2022-05-31 13:21:49 -07:00
parent abd79c4b41
commit 49a0684d63
4 changed files with 131 additions and 14 deletions

View File

@@ -508,6 +508,9 @@
:db/cardinality :db.cardinality/one}]]}
:auto-ap/add-payment-type-credit {:txes [[{:db/ident :payment-type/credit
:db/doc "Credit for negative invoices"}]]}
:auto-ap/add-payment-type-balance-credit {:txes [[{:db/ident :payment-type/balance-credit
:db/doc "Used for paying invoices from statement credits."}]]}
:auto-ap/fulltext-accounts {:txes [[{:db/ident :account/search-terms
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one

View File

@@ -10,7 +10,7 @@
[auto-ap.datomic.transactions :as d-transactions]
[auto-ap.datomic.vendors :as d-vendors]
[auto-ap.graphql.utils
:refer [->graphql <-graphql assert-admin assert-can-see-client enum->keyword assert-not-locked assert-none-locked]]
:refer [->graphql <-graphql assert-admin assert-failure assert-can-see-client enum->keyword assert-not-locked assert-none-locked]]
[auto-ap.numeric :refer [num->words]]
[auto-ap.time :refer [iso-date local-now parse]]
[auto-ap.utils :refer [by dollars-0?]]
@@ -212,7 +212,8 @@
type))
(defn invoice-payments [invoices invoice-amounts]
(->> (for [invoice invoices
:let [invoice-amount (invoice-amounts (:db/id invoice))]]
:let [invoice-amount (invoice-amounts (:db/id invoice))]
:when invoice-amount]
[{:invoice-payment/payment (-> invoice :invoice/vendor :db/id str)
:invoice-payment/amount invoice-amount
:invoice-payment/invoice (:db/id invoice)}
@@ -292,6 +293,16 @@
(conj payment)
(into (invoice-payments invoices invoice-amounts)))))
(defmethod invoices->entities :payment-type/balance-credit [invoices vendor client bank-account type index invoice-amounts]
(when (<= (->> invoices
(map (comp invoice-amounts :db/id))
(reduce + 0.0))
0.001)
(throw (ex-info "The selected invoices do not have an outstanding balance."
{:validation-error "The selected invoices do not have an outstanding balance."})))
)
(defmethod invoices->entities :payment-type/credit [invoices vendor client bank-account type index invoice-amounts]
(when (>= (->> invoices
(map (comp invoice-amounts :db/id))
@@ -552,6 +563,76 @@
(:type args)
(:id context))))
(defn pay-invoices-from-balance [context {invoices :invoices
client-id :client_id} _]
(assert-can-see-client (:id context) client-id)
(let [invoices (d-invoices/get-multi invoices)
client (d-clients/get-by-id client-id)
_ (when (> (count (set (map :invoice/vendor invoices))) 1)
(assert-failure "Balance payments can only be done on one vendor at a time."))
_ (when (> (reduce + 0 (map :invoice/outstanding-balance invoices)) 0.001)
(assert-failure "There isn't a positive balance to pay from."))
invoices-to-be-paid (filter
(fn [i]
(> (:invoice/outstanding-balance i)
0.001))
invoices)
credit-invoices (filter
(fn [i]
(< (:invoice/outstanding-balance i)
0.001))
invoices)
total-to-pay (reduce + 0 (map :invoice/outstanding-balance invoices-to-be-paid))
_ (when (<= total-to-pay 0.001)
(assert-failure "You must select invoices that need to be paid."))
invoice-amounts (->> invoices-to-be-paid
(map (fn [i]
[(:db/id i)
(:invoice/outstanding-balance i)]))
(concat (->> credit-invoices
(reduce
(fn [[remaining-to-pay invoice-amounts] invoice]
(cond (dollars-0? (+ remaining-to-pay (:invoice/outstanding-balance invoice)))
(reduced (conj invoice-amounts
[(:db/id invoice)
(:invoice/outstanding-balance invoice)]))
(< (+ remaining-to-pay (:invoice/outstanding-balance invoice)) 0.0)
(reduced (conj invoice-amounts
[(:db/id invoice)
(- remaining-to-pay)]))
:else
[(+ remaining-to-pay (:invoice/outstanding-balance invoice))
(conj invoice-amounts [(:db/id invoice)
(:invoice/outstanding-balance invoice)])]))
[total-to-pay []])))
(into {}))
vendor-id (:db/id (:invoice/vendor (first invoices)))
payment {:db/id (str vendor-id)
:payment/amount total-to-pay
:payment/vendor vendor-id
:payment/client (:db/id client)
:payment/date (c/to-date (time/now))
:payment/invoices (map :db/id invoices)
:payment/type :payment-type/balance-credit
:payment/status :payment-status/cleared}]
(audit-transact (-> []
(conj payment)
(into (invoice-payments invoices invoice-amounts))) (:id context))
(->graphql {:invoices (d-invoices/get-multi (map :db/id invoices))})))
(def objects
{:payment {:fields {:id {:type :id}
:type {:type :payment_type}
@@ -601,6 +682,11 @@
:type {:type :payment_type}
:client_id {:type :id}}
:resolve :mutation/print-checks}
:pay_invoices_from_balance {:type :check_result
:args {:invoices {:type '(list :id)}
:client_id {:type :id}}
:resolve :mutation/pay-invoices-from-balance}
:add_handwritten_check {:type :check_result
:args {:invoice_payments {:type '(list :invoice_payment_amount)}
:date {:type 'String}
@@ -637,7 +723,8 @@
{:payment_type {:values [{:enum-value :check}
{:enum-value :cash}
{:enum-value :debit}
{:enum-value :credit}]}
{:enum-value :credit}
{:enum-value :balance_credit}]}
:payment_status {:values [{:enum-value :voided}
{:enum-value :pending}
{:enum-value :cleared}]}})
@@ -650,6 +737,7 @@
:mutation/void-payment void-payment
:mutation/void-payments void-payments
:mutation/print-checks print-checks
:mutation/pay-invoices-from-balance pay-invoices-from-balance
:mutation/add-handwritten-check add-handwritten-check
})

View File

@@ -689,13 +689,7 @@
})
(def enums
{:payment_type {:values [{:enum-value :check}
{:enum-value :cash}
{:enum-value :debit}
{:enum-value :credit}]}
:payment_status {:values [{:enum-value :voided}
{:enum-value :pending}
{:enum-value :cleared}]}})
{})
(def resolvers