switched from auto pay to scheduled payment

This commit is contained in:
Bryce Covert
2020-09-24 08:06:17 -07:00
parent 4ab492d759
commit c5ed61b2e1
16 changed files with 918 additions and 39 deletions

View File

@@ -15,12 +15,11 @@
(let [invoices-to-close (d/query {:query {:find ['?e]
:in ['$ '?today]
:where ['[?e :invoice/automatically-paid-when-due true]
:where ['[?e :invoice/scheduled-payment ?d]
'[?e :invoice/status :invoice-status/unpaid]
'[?e :invoice/due ?d]
'[(<= ?d ?today)]]}
:args [(d/db conn) (coerce/to-date (time/local-now))]})]
(log/info "Closing " (count invoices-to-close) "automatic invoices")
(log/info "Closing " (count invoices-to-close) "scheduled invoices")
(some->> invoices-to-close
seq
@@ -29,7 +28,7 @@
:invoice/status :invoice-status/paid}))
(d/transact conn)
deref)
(log/info "Closed " (count invoices-to-close) "automatic invoices"))
(log/info "Closed " (count invoices-to-close) "scheduled invoices"))
(catch Exception e
(log/error e)))))

View File

@@ -21,6 +21,7 @@
(-> x
(update :invoice/date c/from-date)
(update :invoice/due c/from-date)
(update :invoice/scheduled-payment c/from-date)
(update :invoice/status :db/ident)
(rename-keys {:invoice-payment/_invoice :invoice/payments})))

View File

@@ -311,7 +311,12 @@
:db/doc "Whether this invoice should be marked as paid when it's due"
:db/valueType :db.type/boolean
:db/cardinality :db.cardinality/one}]]}
:auto-ap/fix-reset-rels {:txes-fn `reset-function}}
:auto-ap/fix-reset-rels {:txes-fn `reset-function}
:auto-ap/add-scheduled-payment {:txes [[{:db/ident :invoice/scheduled-payment
:db/doc "When an invoice gets marked as paid"
:db/valueType :db.type/instant
:db/cardinality :db.cardinality/one}]]}}
sales/norms-map
clients/norms-map
ledger/norms-map

View File

@@ -349,7 +349,7 @@
:payments {:type '(list :invoice_payment)}
:vendor {:type :vendor}
:client {:type :client}
:automatically_paid_when_due {:type 'Boolean}}}
:scheduled_payment {:type :iso_date}}}
@@ -718,7 +718,7 @@
:invoice_number {:type 'String}
:expense_accounts {:type '(list :edit_expense_account)}
:location {:type :iso_date}
:automatically_paid_when_due {:type 'Boolean}
:scheduled_payment {:type :iso_date}
:date {:type :iso_date}
:due {:type :iso_date}
:client_id {:type :id}
@@ -731,7 +731,7 @@
:invoice_number {:type 'String}
:expense_accounts {:type '(list :edit_expense_account)}
:date {:type :iso_date}
:automatically_paid_when_due {:type 'Boolean}
:scheduled_payment {:type :iso_date}
:due {:type :iso_date}
:total {:type 'Float}}}
:edit_transaction

View File

@@ -56,7 +56,7 @@
:account account_id
:location location}))
(defn add-invoice-transaction [{:keys [total invoice_number location automatically_paid_when_due client_id vendor_id vendor_name date due expense_accounts] :as in}]
(defn add-invoice-transaction [{:keys [total invoice_number location scheduled_payment client_id vendor_id vendor_name date due expense_accounts] :as in}]
(let [vendor (d-vendors/get-by-id vendor_id)
account (:vendor/default-account vendor)
_ (when-not (:db/id account)
@@ -76,7 +76,8 @@
(:vendor/terms vendor) (assoc :invoice/due (coerce/to-date
(time/plus date (time/days (d-vendors/terms-for-client-id vendor client_id)))))
due (assoc :invoice/due (coerce/to-date due))
(boolean? automatically_paid_when_due) (assoc :invoice/automatically-paid-when-due automatically_paid_when_due))))
scheduled_payment (assoc :invoice/scheduled-payment (coerce/to-date scheduled_payment)))))
(defn deleted-expense-accounts [invoice expense-accounts]
@@ -121,7 +122,7 @@
->graphql)))
(defn edit-invoice [context {{:keys [id due invoice_number total vendor_id date client_id expense_accounts automatically_paid_when_due] :as in} :invoice} value]
(defn edit-invoice [context {{:keys [id due invoice_number total vendor_id date client_id expense_accounts scheduled_payment] :as in} :invoice} value]
(let [invoice (d-invoices/get-by-id id)
_ (when (seq (d-invoices/find-conflicting {:db/id id
:invoice/invoice-number invoice_number
@@ -146,7 +147,7 @@
:invoice/expense-accounts (map expense-account->entity
expense_accounts)}
due (assoc :invoice/due (coerce/to-date due))
(boolean? automatically_paid_when_due) (assoc :invoice/automatically-paid-when-due automatically_paid_when_due))]
scheduled_payment (assoc :invoice/scheduled-payment (coerce/to-date scheduled_payment)))]
(audit-transact (concat [updated-invoice]
(map (fn [d] [:db/retract id :invoice/expense-accounts d]) deleted))
(:id context))

View File

@@ -161,7 +161,9 @@
:location default-location
:amount total}]}
(:vendor/terms vendor) (assoc :invoice/due (coerce/to-date
(time/plus date (time/days (d-vendors/terms-for-client-id vendor client-id))))))
(time/plus date (time/days (d-vendors/terms-for-client-id vendor client-id)))))
automatically-paid-when-due (assoc :invoice/scheduled-payment (coerce/to-date
(time/plus date (time/days (d-vendors/terms-for-client-id vendor client-id))))))
payment (if (= :invoice-status/paid (:invoice/status invoice))
#:invoice-payment {:invoice (:db/id invoice)
:amount (:invoice/total invoice)
@@ -272,7 +274,6 @@
:invoice/client-identifier customer-identifier
:invoice/vendor (:db/id matching-vendor)
:invoice/invoice-number invoice-number
:invoice/automatically-paid-when-due (boolean (automatically-paid-for (:db/id matching-client)))
:invoice/total (Double/parseDouble total)
:invoice/date (to-date date)
:invoice/import-status :import-status/pending
@@ -284,7 +285,9 @@
:db/id existing-id
})
(:vendor/terms matching-vendor) (assoc :invoice/due (coerce/to-date
(time/plus date (time/days (d-vendors/terms-for-client-id matching-vendor (:db/id matching-client)))))))))
(time/plus date (time/days (d-vendors/terms-for-client-id matching-vendor (:db/id matching-client))))))
(boolean (automatically-paid-for (:db/id matching-client))) (assoc :invoice/scheduled-payment (coerce/to-date
(time/plus date (time/days (d-vendors/terms-for-client-id matching-vendor (:db/id matching-client)))))))))
))
[]
imports)]

View File

@@ -8,9 +8,9 @@
(s/def ::invoice-number ::shared/required-identifier)
(s/def ::date ::shared/date)
(s/def ::due (s/nilable ::shared/date))
(s/def ::scheduled-payment (s/nilable ::shared/date))
(s/def ::total ::shared/money)
(s/def ::vendor-id ::shared/identifier)
(s/def ::automatically-paid-when-due (s/nilable boolean?))
(s/def ::invoice (s/keys :req-un [::client
::invoice-number
@@ -19,5 +19,5 @@
::total]
:opt-un [::vendor-name
::due
::automatically-paid-when-due
::scheduled-payment
]))

View File

@@ -40,7 +40,7 @@
:unpaid-invoices :unpaid
:paid-invoices :paid
:voided-invoices :voided)}
[[:invoices [:id :total :outstanding-balance :invoice-number :date :due :status :client-identifier :automatically-paid-when-due
[[:invoices [:id :total :outstanding-balance :invoice-number :date :due :status :client-identifier :scheduled-payment
[:vendor [:name :id]]
[:expense_accounts [:amount :id :location
[:account [:id ]]]]

View File

@@ -0,0 +1,6 @@
(ns auto-ap.views.components.switch-field)
(defn switch-field [{:keys [id label on-change checked]}]
[:<>
[:input.switch {:type "checkbox" :id id :on-change on-change :checked checked}]
[:label {:for id} label]])

View File

@@ -13,7 +13,7 @@
(>= amount 0)))))
(def invoice-read [:id :total :outstanding-balance :date :due :invoice-number :status
:automatically-paid-when-due
:scheduled-payment
[:client [:id :name :locations]]
[:payments [:amount [:payment [:amount :s3_url :check_number ]]]]
[:vendor [:id :name]]

View File

@@ -8,6 +8,7 @@
[auto-ap.views.components.expense-accounts-field :as expense-accounts-field :refer [expense-accounts-field recalculate-amounts]]
[auto-ap.views.components.layouts :as layouts]
[auto-ap.views.components.money-field :refer [money-field]]
[auto-ap.views.components.switch-field :refer [switch-field]]
[auto-ap.views.components.typeahead :refer [typeahead-entity]]
[auto-ap.views.pages.invoices.common :refer [invoice-read]]
[auto-ap.status :as status]
@@ -35,7 +36,7 @@
(re-frame/reg-sub
::create-query
:<- [::forms/form ::form]
(fn [{:keys [data] {:keys [id invoice-number date due location total expense-accounts automatically-paid-when-due vendor client]} :data}]
(fn [{:keys [data] {:keys [id invoice-number date due scheduled-payment location total expense-accounts vendor client]} :data}]
{:venia/operation {:operation/type :mutation
:operation/name "AddInvoice"}
:venia/queries [{:query/data [:add-invoice
@@ -43,7 +44,7 @@
:due due
:vendor-id (:id vendor)
:client-id (:id client)
:automatically-paid-when-due automatically-paid-when-due
:scheduled-payment scheduled-payment
:invoice-number invoice-number
:location location
:total total
@@ -59,14 +60,14 @@
(re-frame/reg-sub
::edit-query
:<- [::forms/form ::form]
(fn [{:keys [data] {:keys [id invoice-number date due location total expense-accounts vendor automatically-paid-when-due client]} :data}]
(fn [{:keys [data] {:keys [id invoice-number date due scheduled-payment location total expense-accounts vendor client]} :data}]
{:venia/operation {:operation/type :mutation
:operation/name "EditInvoice"}
:venia/queries [{:query/data [:edit-invoice
{:invoice {:id id
:invoice-number invoice-number
:date date
:automatically-paid-when-due automatically-paid-when-due
:scheduled-payment scheduled-payment
:due due
:total total
:expense-accounts (map (fn [ea]
@@ -81,14 +82,14 @@
(re-frame/reg-sub
::add-and-print-query
(fn [db [_ bank-account-id type]]
(let [{:keys [data] {:keys [id invoice-number date location total expense-accounts automatically-paid-when-due vendor client]} :data} @(re-frame/subscribe [::forms/form ::form])]
(let [{:keys [data] {:keys [id invoice-number date location total expense-accounts scheduled-payment vendor client]} :data} @(re-frame/subscribe [::forms/form ::form])]
{:venia/operation {:operation/type :mutation
:operation/name "AddAndPrintInvoice"}
:venia/queries [{:query/data [:add-and-print-invoice
{:invoice {:date date
:vendor-id (:id vendor)
:client-id (:id client)
:automatically-paid-when-due automatically-paid-when-due
:scheduled-payment scheduled-payment
:invoice-number invoice-number
:location location
:total total
@@ -134,14 +135,16 @@
(let [accounts-by-id @(re-frame/subscribe [::subs/accounts-by-id (:client which)])
edit-invoice (update which :date #(date->str % standard))
edit-invoice (update edit-invoice :due #(date->str % standard))
edit-invoice (update edit-invoice :scheduled-payment #(date->str % standard))
edit-invoice (assoc edit-invoice :original edit-invoice)
locations @(re-frame/subscribe [::subs/locations-for-client (:id (:client which))])]
locations @(re-frame/subscribe [::subs/locations-for-client (:id (:client which))])
]
(-> db
(forms/start-form ::form {:id (:id edit-invoice)
:status (:status edit-invoice)
:date (:date edit-invoice)
:due (:due edit-invoice)
:automatically-paid-when-due (:automatically-paid-when-due edit-invoice)
:scheduled-payment (:scheduled-payment edit-invoice)
:invoice-number (:invoice-number edit-invoice)
:total (:total edit-invoice)
:original edit-invoice
@@ -168,14 +171,28 @@
locations)])
true
(into [[:automatically-paid-when-due] (boolean ((set (map :id (:automatically-paid-when-due value))) (:id (:client data))))]))
(boolean ((set (map :id (:automatically-paid-when-due value))) (:id (:client data))))
(into [[:scheduled-payment] (:due data)
[:schedule-when-due] true]))
(= [:total] field)
[[:expense-accounts] (recalculate-amounts (:expense-accounts data) value)]
(and (= [:schedule-when-due] field) value)
[[:scheduled-payment] (:due data)]
(and (= [:due] field) (:schedule-when-due data))
[[:scheduled-payment] value]
:else
[])))))
(re-frame/reg-event-db
::maybe-change-client
[ (forms/in-form ::form)]
(fn [{:keys [data] :as f} [_ c]]
(if (:id data)
f
(assoc-in f [:data :client] c))))
(re-frame/reg-event-fx
::add-and-print
@@ -236,7 +253,8 @@
{::track/register [{:id ::client
:subscription [::subs/client]
:event-fn (fn [c]
[::changed [:client] c])}]}))
[::maybe-change-client c])}]}))
(re-frame/reg-event-fx
::unmounted
@@ -302,13 +320,29 @@
:field [:due]
:spec ::invoice/due}])
[:div.field
[:label.checkbox
(raw-field
[:input {:type "checkbox"
:field [:automatically-paid-when-due]
:spec ::invoice/automatically-paid-when-due}])
" Mark as paid on due date"]]
[:p.help "Scheduled payment (optional)"]
[:div.level
[:div.level-left
[:div.level-item
[:div.control
(raw-field
[date-picker {:class-name "input"
:class "input"
:disabled (boolean (:schedule-when-due data))
:format-week-number (fn [] "")
:previous-month-button-label ""
:placeholder "mm/dd/yyyy"
:next-month-button-label ""
:next-month-label ""
:type "date"
:field [:scheduled-payment]
:spec ::invoice/scheduled-payment}])]]
[:div.level-item [:div.control
(raw-field
[switch-field {:id "schedule-when-due"
:field [:schedule-when-due]
:label "Same as due date"
:type "checkbox"}])]]]]
(field [:span "Invoice #"
[:span.has-text-danger " *"]]

View File

@@ -193,7 +193,7 @@
[table/invoice-table {:id (:id page)
:data-page :invoices
:check-boxes (= status :unpaid)
:checkable-fn (fn [i] (not (:automatically-paid-when-due i)))
:checkable-fn (fn [i] (not (:scheduled-payment i)))
:actions #{:edit :void :expense-accounts}}]]))
(defn unpaid-invoices-page [params]