You can now pay invoices with credits from the same vendor.
This commit is contained in:
@@ -508,6 +508,9 @@
|
|||||||
:db/cardinality :db.cardinality/one}]]}
|
:db/cardinality :db.cardinality/one}]]}
|
||||||
:auto-ap/add-payment-type-credit {:txes [[{:db/ident :payment-type/credit
|
:auto-ap/add-payment-type-credit {:txes [[{:db/ident :payment-type/credit
|
||||||
:db/doc "Credit for negative invoices"}]]}
|
: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
|
:auto-ap/fulltext-accounts {:txes [[{:db/ident :account/search-terms
|
||||||
:db/valueType :db.type/string
|
:db/valueType :db.type/string
|
||||||
:db/cardinality :db.cardinality/one
|
:db/cardinality :db.cardinality/one
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
[auto-ap.datomic.transactions :as d-transactions]
|
[auto-ap.datomic.transactions :as d-transactions]
|
||||||
[auto-ap.datomic.vendors :as d-vendors]
|
[auto-ap.datomic.vendors :as d-vendors]
|
||||||
[auto-ap.graphql.utils
|
[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.numeric :refer [num->words]]
|
||||||
[auto-ap.time :refer [iso-date local-now parse]]
|
[auto-ap.time :refer [iso-date local-now parse]]
|
||||||
[auto-ap.utils :refer [by dollars-0?]]
|
[auto-ap.utils :refer [by dollars-0?]]
|
||||||
@@ -212,7 +212,8 @@
|
|||||||
type))
|
type))
|
||||||
(defn invoice-payments [invoices invoice-amounts]
|
(defn invoice-payments [invoices invoice-amounts]
|
||||||
(->> (for [invoice invoices
|
(->> (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/payment (-> invoice :invoice/vendor :db/id str)
|
||||||
:invoice-payment/amount invoice-amount
|
:invoice-payment/amount invoice-amount
|
||||||
:invoice-payment/invoice (:db/id invoice)}
|
:invoice-payment/invoice (:db/id invoice)}
|
||||||
@@ -292,6 +293,16 @@
|
|||||||
(conj payment)
|
(conj payment)
|
||||||
(into (invoice-payments invoices invoice-amounts)))))
|
(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]
|
(defmethod invoices->entities :payment-type/credit [invoices vendor client bank-account type index invoice-amounts]
|
||||||
(when (>= (->> invoices
|
(when (>= (->> invoices
|
||||||
(map (comp invoice-amounts :db/id))
|
(map (comp invoice-amounts :db/id))
|
||||||
@@ -552,6 +563,76 @@
|
|||||||
(:type args)
|
(:type args)
|
||||||
(:id context))))
|
(: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
|
(def objects
|
||||||
{:payment {:fields {:id {:type :id}
|
{:payment {:fields {:id {:type :id}
|
||||||
:type {:type :payment_type}
|
:type {:type :payment_type}
|
||||||
@@ -601,6 +682,11 @@
|
|||||||
:type {:type :payment_type}
|
:type {:type :payment_type}
|
||||||
:client_id {:type :id}}
|
:client_id {:type :id}}
|
||||||
:resolve :mutation/print-checks}
|
: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
|
:add_handwritten_check {:type :check_result
|
||||||
:args {:invoice_payments {:type '(list :invoice_payment_amount)}
|
:args {:invoice_payments {:type '(list :invoice_payment_amount)}
|
||||||
:date {:type 'String}
|
:date {:type 'String}
|
||||||
@@ -637,7 +723,8 @@
|
|||||||
{:payment_type {:values [{:enum-value :check}
|
{:payment_type {:values [{:enum-value :check}
|
||||||
{:enum-value :cash}
|
{:enum-value :cash}
|
||||||
{:enum-value :debit}
|
{:enum-value :debit}
|
||||||
{:enum-value :credit}]}
|
{:enum-value :credit}
|
||||||
|
{:enum-value :balance_credit}]}
|
||||||
:payment_status {:values [{:enum-value :voided}
|
:payment_status {:values [{:enum-value :voided}
|
||||||
{:enum-value :pending}
|
{:enum-value :pending}
|
||||||
{:enum-value :cleared}]}})
|
{:enum-value :cleared}]}})
|
||||||
@@ -650,6 +737,7 @@
|
|||||||
:mutation/void-payment void-payment
|
:mutation/void-payment void-payment
|
||||||
:mutation/void-payments void-payments
|
:mutation/void-payments void-payments
|
||||||
:mutation/print-checks print-checks
|
:mutation/print-checks print-checks
|
||||||
|
:mutation/pay-invoices-from-balance pay-invoices-from-balance
|
||||||
:mutation/add-handwritten-check add-handwritten-check
|
:mutation/add-handwritten-check add-handwritten-check
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -689,13 +689,7 @@
|
|||||||
})
|
})
|
||||||
|
|
||||||
(def enums
|
(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
|
(def resolvers
|
||||||
|
|||||||
@@ -29,7 +29,8 @@
|
|||||||
[goog.string :as gstring]
|
[goog.string :as gstring]
|
||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[reagent.core :as r]
|
[reagent.core :as r]
|
||||||
[vimsical.re-frame.fx.track :as track]))
|
[vimsical.re-frame.fx.track :as track]
|
||||||
|
[vimsical.re-frame.cofx.inject :as inject]))
|
||||||
|
|
||||||
(re-frame/reg-event-fx
|
(re-frame/reg-event-fx
|
||||||
::params-change
|
::params-change
|
||||||
@@ -105,6 +106,30 @@
|
|||||||
(:invoices (:print-checks result))
|
(:invoices (:print-checks result))
|
||||||
(:pdf-url (:print-checks result))])}}))
|
(:pdf-url (:print-checks result))])}}))
|
||||||
|
|
||||||
|
(re-frame/reg-event-fx
|
||||||
|
::pay-invoices-from-balance
|
||||||
|
[with-user (re-frame/inject-cofx ::inject/sub [::data-page/checked :invoices])]
|
||||||
|
(fn [{:keys [db user] ::data-page/keys [checked] :as cofx} _]
|
||||||
|
{:graphql
|
||||||
|
{:token user
|
||||||
|
:owns-state {:single ::print-checks}
|
||||||
|
|
||||||
|
:query-obj {:venia/operation {:operation/type :mutation
|
||||||
|
:operation/name "PayInvoicesFromBalance"}
|
||||||
|
:venia/queries [[:pay-invoices-from-balance
|
||||||
|
{:invoices (->> checked
|
||||||
|
(vals )
|
||||||
|
(filter (fn [{:keys [id outstanding-balance] }]
|
||||||
|
(and id outstanding-balance)))
|
||||||
|
(map :id))
|
||||||
|
:client_id (:client db)}
|
||||||
|
[[:invoices invoice-read]
|
||||||
|
:pdf_url]]]}
|
||||||
|
:on-success (fn [result]
|
||||||
|
[::checks-printed
|
||||||
|
(:invoices (:pay-invoices-from-balance result))
|
||||||
|
nil])}}))
|
||||||
|
|
||||||
|
|
||||||
(re-frame/reg-event-fx
|
(re-frame/reg-event-fx
|
||||||
::checks-printed
|
::checks-printed
|
||||||
@@ -229,9 +254,16 @@
|
|||||||
:disabled (status/disabled-for print-checks-status)} "Debit from " name])
|
:disabled (status/disabled-for print-checks-status)} "Debit from " name])
|
||||||
(list
|
(list
|
||||||
^{:key (str id "-credit")} [:a.dropdown-item {:on-click (dispatch-event-with-propagation [::print-checks id :credit])
|
^{:key (str id "-credit")} [:a.dropdown-item {:on-click (dispatch-event-with-propagation [::print-checks id :credit])
|
||||||
:disabled (status/disabled-for print-checks-status)} "Credit from " name]))))
|
:disabled (status/disabled-for print-checks-status)} "Credit from " name]
|
||||||
(when (> balance 0.001)
|
))))
|
||||||
^{:key "advanced-divider"} [:hr.dropdown-divider])
|
|
||||||
|
^{:key "advanced-divider"} [:hr.dropdown-divider]
|
||||||
|
|
||||||
|
(when (and (> (count checked-invoices) 1)
|
||||||
|
(= 1 (count (set (map (comp :id :vendor) (vals checked-invoices)))))
|
||||||
|
(< balance 0.001))
|
||||||
|
^{:key (str "balance-credit")} [:a.dropdown-item {:on-click (dispatch-event-with-propagation [::pay-invoices-from-balance])
|
||||||
|
:disabled (status/disabled-for print-checks-status)} "Pay invoices using balance "])
|
||||||
|
|
||||||
(when (and (= 1 (count (set (map (comp :id :vendor) (vals checked-invoices)))))
|
(when (and (= 1 (count (set (map (comp :id :vendor) (vals checked-invoices)))))
|
||||||
(> balance 0.001))
|
(> balance 0.001))
|
||||||
|
|||||||
Reference in New Issue
Block a user