Makes it possible to bulk change invoices
This commit is contained in:
@@ -104,6 +104,12 @@
|
|||||||
:where ['[?e :invoice/vendor ?vendor-id]]}
|
:where ['[?e :invoice/vendor ?vendor-id]]}
|
||||||
:args [ (:vendor-id args)]})
|
: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)]})
|
||||||
|
|
||||||
(:amount-gte args)
|
(:amount-gte args)
|
||||||
(merge-query {:query {:in ['?amount-gte]
|
(merge-query {:query {:in ['?amount-gte]
|
||||||
:where ['[?e :invoice/total ?total-filter]
|
:where ['[?e :invoice/total ?total-filter]
|
||||||
|
|||||||
@@ -2,10 +2,11 @@
|
|||||||
(:require
|
(:require
|
||||||
[auto-ap.datomic
|
[auto-ap.datomic
|
||||||
:refer [conn remove-nils uri]]
|
:refer [conn remove-nils uri]]
|
||||||
[auto-ap.ledger :refer [transact-with-ledger]]
|
[auto-ap.ledger :refer [transact-with-ledger transact-batch-with-ledger]]
|
||||||
[auto-ap.datomic.clients :as d-clients]
|
[auto-ap.datomic.clients :as d-clients]
|
||||||
[auto-ap.datomic.invoices :as d-invoices]
|
[auto-ap.datomic.invoices :as d-invoices]
|
||||||
[auto-ap.datomic.vendors :as d-vendors]
|
[auto-ap.datomic.vendors :as d-vendors]
|
||||||
|
[auto-ap.rule-matching :as rm]
|
||||||
[auto-ap.graphql.checks :as gq-checks]
|
[auto-ap.graphql.checks :as gq-checks]
|
||||||
[auto-ap.graphql.utils
|
[auto-ap.graphql.utils
|
||||||
:as u
|
:as u
|
||||||
@@ -239,19 +240,23 @@
|
|||||||
|
|
||||||
(-> (d-invoices/get-by-id id) (->graphql (:id context)))))
|
(-> (d-invoices/get-by-id id) (->graphql (:id context)))))
|
||||||
|
|
||||||
(defn void-invoices [context args _]
|
|
||||||
(let [_ (assert-admin (:id context))
|
(defn get-ids-matching-filters [args]
|
||||||
args (assoc args :id (:id context))
|
(let [ids (some-> args
|
||||||
ids (some-> args
|
|
||||||
:filters
|
:filters
|
||||||
(assoc :id (:id context))
|
(assoc :id (:id args))
|
||||||
(<-graphql)
|
(<-graphql)
|
||||||
(update :status enum->keyword "invoice-status")
|
(update :status enum->keyword "invoice-status")
|
||||||
(assoc :per-page Integer/MAX_VALUE)
|
(assoc :per-page Integer/MAX_VALUE)
|
||||||
d-invoices/raw-graphql-ids
|
d-invoices/raw-graphql-ids
|
||||||
:ids)
|
:ids)
|
||||||
specific-ids (d-invoices/filter-ids (:ids args))
|
specific-ids (d-invoices/filter-ids (:ids args))]
|
||||||
all-ids (into (set ids) specific-ids)]
|
(into (set ids) specific-ids)))
|
||||||
|
|
||||||
|
(defn void-invoices [context args _]
|
||||||
|
(let [_ (assert-admin (:id context))
|
||||||
|
args (assoc args :id (:id context))
|
||||||
|
all-ids (all-ids-not-locked (get-ids-matching-filters args))]
|
||||||
|
|
||||||
(log/info "Voiding " (count all-ids) args)
|
(log/info "Voiding " (count all-ids) args)
|
||||||
(transact-with-ledger
|
(transact-with-ledger
|
||||||
@@ -341,6 +346,87 @@
|
|||||||
(d-invoices/get-by-id (:invoice_id args))
|
(d-invoices/get-by-id (:invoice_id args))
|
||||||
(:id context))))
|
(:id context))))
|
||||||
|
|
||||||
|
;; TODO - multiple versions of this now exist. fix in datomic migration?
|
||||||
|
(defn maybe-code-accounts [invoice account-rules valid-locations]
|
||||||
|
(with-precision 2
|
||||||
|
(let [accounts (vec (mapcat
|
||||||
|
(fn [ar]
|
||||||
|
(let [cents-to-distribute (int (Math/round (Math/abs (* (:percentage ar)
|
||||||
|
(:invoice/total invoice)
|
||||||
|
100))))]
|
||||||
|
(if (= "Shared" (:location ar))
|
||||||
|
(do
|
||||||
|
(->> valid-locations
|
||||||
|
(map
|
||||||
|
(fn [cents location]
|
||||||
|
{:invoice-expense-account/account (:account_id ar)
|
||||||
|
:invoice-expense-account/amount (* 0.01 cents)
|
||||||
|
:invoice-expense-account/location location})
|
||||||
|
(rm/spread-cents cents-to-distribute (count valid-locations)))))
|
||||||
|
[(cond-> {:invoice-expense-account/account (:account_id ar)
|
||||||
|
:invoice-expense-account/amount (* 0.01 cents-to-distribute)}
|
||||||
|
(:location ar) (assoc :invoice-expense-account/location (:location ar)))])))
|
||||||
|
account-rules))
|
||||||
|
accounts (mapv
|
||||||
|
(fn [a]
|
||||||
|
(update a :invoice-expense-account/amount
|
||||||
|
#(with-precision 2
|
||||||
|
(double (.setScale (bigdec %) 2 java.math.RoundingMode/HALF_UP)))))
|
||||||
|
accounts)
|
||||||
|
leftover (with-precision 2 (.round (bigdec (- (Math/abs (:invoice/total invoice))
|
||||||
|
(Math/abs (reduce + 0.0 (map #(:invoice-expense-account/amount %) accounts)))))
|
||||||
|
*math-context*))
|
||||||
|
accounts (if (seq accounts)
|
||||||
|
(update-in accounts [(dec (count accounts)) :invoice-expense-account/amount] #(+ % (double leftover)))
|
||||||
|
[])]
|
||||||
|
[:reset (:db/id invoice) :invoice/expense-accounts accounts])))
|
||||||
|
|
||||||
|
(defn all-ids-not-locked [all-ids]
|
||||||
|
(->> all-ids
|
||||||
|
(d/q '[:find [?i ...]
|
||||||
|
:in $ [?i ...]
|
||||||
|
:where
|
||||||
|
[?i :invoice/client ?c]
|
||||||
|
[(get-else $ ?c :client/locked-until #inst "2000-01-01") ?lu]
|
||||||
|
[?i :invoice/date ?d]
|
||||||
|
[(>= ?d ?lu)]]
|
||||||
|
(d/db conn))))
|
||||||
|
|
||||||
|
(defn bulk-change-invoices [context args _]
|
||||||
|
(assert-admin (:id context))
|
||||||
|
(when-not (:client_id args)
|
||||||
|
(throw (ex-info "Client is required"
|
||||||
|
{:validation-error "client is required"})))
|
||||||
|
(let [args (assoc args :id (:id context))
|
||||||
|
locations (:client/locations (d/pull (d/db conn)
|
||||||
|
[:client/locations]
|
||||||
|
(:client_id args)))
|
||||||
|
all-ids (all-ids-not-locked (get-ids-matching-filters args))
|
||||||
|
invoices (d/pull-many (d/db conn) '[:db/id :invoice/total] (vec all-ids))
|
||||||
|
account-total (reduce + 0 (map (fn [x] (:percentage x)) (:accounts args)))]
|
||||||
|
(log/info "client is" locations)
|
||||||
|
(when
|
||||||
|
(not (dollars= 1.0 account-total))
|
||||||
|
(let [error (str "Account total (" account-total ") does not reach 100%")]
|
||||||
|
(throw (ex-info error {:validation-error error}))))
|
||||||
|
(doseq [a (:accounts args)
|
||||||
|
:let [{:keys [:account/location :account/name]} (d/entity (d/db conn) (:account_id a))]]
|
||||||
|
(when (and location (not= location (:location a)))
|
||||||
|
(let [err (str "Account " name " uses location " (:location a) ", but is supposed to be " location)]
|
||||||
|
(throw (ex-info err {:validation-error err}) )))
|
||||||
|
(when (and (not location)
|
||||||
|
(not (get (into #{"Shared"} locations)
|
||||||
|
(:location a))))
|
||||||
|
(let [err (str "Account " name " uses location " (:location a) ", but doesn't belong to the client.")]
|
||||||
|
(throw (ex-info err {:validation-error err}) ))))
|
||||||
|
(log/info "Bulk coding " (count all-ids) args)
|
||||||
|
(transact-batch-with-ledger
|
||||||
|
(map (fn [i]
|
||||||
|
(maybe-code-accounts i (:accounts args) locations))
|
||||||
|
invoices)
|
||||||
|
(:id context))
|
||||||
|
{:message (str "Successfully coded " (count all-ids) " invoices.")}))
|
||||||
|
|
||||||
(def objects
|
(def objects
|
||||||
{:invoice
|
{:invoice
|
||||||
{:fields {:id {:type :id}
|
{:fields {:id {:type :id}
|
||||||
@@ -423,7 +509,14 @@
|
|||||||
:edit_expense_accounts {:type :invoice
|
:edit_expense_accounts {:type :invoice
|
||||||
:args {:invoice_id {:type :id}
|
:args {:invoice_id {:type :id}
|
||||||
:expense_accounts {:type '(list :edit_expense_account)}}
|
:expense_accounts {:type '(list :edit_expense_account)}}
|
||||||
:resolve :mutation/edit-expense-accounts}})
|
:resolve :mutation/edit-expense-accounts}
|
||||||
|
|
||||||
|
:bulk_change_invoices {:type :message
|
||||||
|
:args {:filters {:type :invoice_filters}
|
||||||
|
:client_id {:type :id}
|
||||||
|
:accounts {:type '(list :edit_percentage_account)}
|
||||||
|
:ids {:type '(list :id)}}
|
||||||
|
:resolve :mutation/bulk-change-invoices}})
|
||||||
|
|
||||||
(def input-objects
|
(def input-objects
|
||||||
{:add_invoice
|
{:add_invoice
|
||||||
@@ -462,6 +555,7 @@
|
|||||||
:scheduled_payments {:type 'Boolean}
|
:scheduled_payments {:type 'Boolean}
|
||||||
:client_id {:type :id}
|
:client_id {:type :id}
|
||||||
:vendor_id {:type :id}
|
:vendor_id {:type :id}
|
||||||
|
:account_id {:type :id}
|
||||||
:amount_lte {:type :money}
|
:amount_lte {:type :money}
|
||||||
:amount_gte {:type :money}
|
:amount_gte {:type :money}
|
||||||
:invoice_number_like {:type 'String}
|
:invoice_number_like {:type 'String}
|
||||||
@@ -485,6 +579,7 @@
|
|||||||
:mutation/edit-invoice edit-invoice
|
:mutation/edit-invoice edit-invoice
|
||||||
:mutation/void-invoice void-invoice
|
:mutation/void-invoice void-invoice
|
||||||
:mutation/void-invoices void-invoices
|
:mutation/void-invoices void-invoices
|
||||||
|
:mutation/bulk-change-invoices bulk-change-invoices
|
||||||
:mutation/unvoid-invoice unvoid-invoice
|
:mutation/unvoid-invoice unvoid-invoice
|
||||||
:mutation/unautopay-invoice unautopay-invoice
|
:mutation/unautopay-invoice unautopay-invoice
|
||||||
:mutation/edit-expense-accounts edit-expense-accounts})
|
:mutation/edit-expense-accounts edit-expense-accounts})
|
||||||
|
|||||||
@@ -28,6 +28,11 @@
|
|||||||
[:span.icon [:i.fa.fa-plus]]
|
[:span.icon [:i.fa.fa-plus]]
|
||||||
[:span name]])
|
[:span name]])
|
||||||
|
|
||||||
|
(defn event-button [{:keys [event name class ]}]
|
||||||
|
[:a.button.is-outlined {:class class
|
||||||
|
:on-click (dispatch-event event)}
|
||||||
|
[:span name]])
|
||||||
|
|
||||||
(defn dropdown [{:keys [event on-click] :as params}]
|
(defn dropdown [{:keys [event on-click] :as params}]
|
||||||
[:a.button (cond-> params
|
[:a.button (cond-> params
|
||||||
true (dissoc :event :icon)
|
true (dissoc :event :icon)
|
||||||
|
|||||||
@@ -96,7 +96,7 @@
|
|||||||
(on-change (into [] updated-expense-accounts))))}
|
(on-change (into [] updated-expense-accounts))))}
|
||||||
[:div
|
[:div
|
||||||
[:div.tags
|
[:div.tags
|
||||||
(when max-value
|
(when (and max-value (not percentage-only?))
|
||||||
[:div.tag "To Allocate: " (->$ max-value)])
|
[:div.tag "To Allocate: " (->$ max-value)])
|
||||||
|
|
||||||
(when-not percentage-only?
|
(when-not percentage-only?
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
:per-page (:per-page params)
|
:per-page (:per-page params)
|
||||||
|
|
||||||
:vendor-id (:id (:vendor params))
|
:vendor-id (:id (:vendor params))
|
||||||
|
:account-id (:id (:account params))
|
||||||
:date-range (:date-range params)
|
:date-range (:date-range params)
|
||||||
:due-range (:due-range params)
|
:due-range (:due-range params)
|
||||||
:amount-gte (:amount-gte (:amount-range params))
|
:amount-gte (:amount-gte (:amount-range params))
|
||||||
|
|||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
(defn invoices-side-bar [{:keys [data-page] :as params}]
|
(defn invoices-side-bar [{:keys [data-page] :as params}]
|
||||||
(let [ap @(re-frame/subscribe [::subs/active-page])
|
(let [ap @(re-frame/subscribe [::subs/active-page])
|
||||||
user @(re-frame/subscribe [::subs/user])]
|
user @(re-frame/subscribe [::subs/user])
|
||||||
|
client @(re-frame/subscribe [::subs/client])]
|
||||||
[:div
|
[:div
|
||||||
[:div [:p.menu-label "Type"]
|
[:div [:p.menu-label "Type"]
|
||||||
[:ul.menu-list
|
[:ul.menu-list
|
||||||
@@ -111,6 +112,18 @@
|
|||||||
[:div
|
[:div
|
||||||
[invoice-number-filter params]]
|
[invoice-number-filter params]]
|
||||||
|
|
||||||
|
[:p.menu-label "Financial Account"]
|
||||||
|
[:div
|
||||||
|
[search-backed-typeahead {:search-query (fn [i]
|
||||||
|
[:search_account
|
||||||
|
{:query i
|
||||||
|
:client-id (:id client)}
|
||||||
|
[:name :id]])
|
||||||
|
:entity->text (fn [x ] (:name x))
|
||||||
|
:type "typeahead-v3"
|
||||||
|
:on-change #(re-frame/dispatch [::data-page/filter-changed data-page :account (some-> % (select-keys [:name :id :numeric-code]))])
|
||||||
|
:value @(re-frame/subscribe [::data-page/filter data-page :account])}]]
|
||||||
|
|
||||||
(when-let [exact-match-id @(re-frame/subscribe [::data-page/filter data-page :exact-match-id])]
|
(when-let [exact-match-id @(re-frame/subscribe [::data-page/filter data-page :exact-match-id])]
|
||||||
[:div
|
[:div
|
||||||
[:p.menu-label "Specific Invoice"]
|
[:p.menu-label "Specific Invoice"]
|
||||||
|
|||||||
97
src/cljs/auto_ap/views/pages/invoices/bulk_change.cljs
Normal file
97
src/cljs/auto_ap/views/pages/invoices/bulk_change.cljs
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
(ns auto-ap.views.pages.invoices.bulk-change
|
||||||
|
(:require
|
||||||
|
[auto-ap.forms :as forms]
|
||||||
|
[auto-ap.status :as status]
|
||||||
|
[auto-ap.subs :as subs]
|
||||||
|
[auto-ap.views.components.expense-accounts-field
|
||||||
|
:as expense-accounts-field
|
||||||
|
:refer [expense-accounts-field-v2]]
|
||||||
|
[auto-ap.views.components.modal :as modal]
|
||||||
|
[auto-ap.views.pages.data-page :as data-page]
|
||||||
|
[auto-ap.views.components.invoice-table
|
||||||
|
:refer [data-params->query-params]]
|
||||||
|
[auto-ap.views.utils :refer [dispatch-event with-user]]
|
||||||
|
[clojure.string :as str]
|
||||||
|
[re-frame.core :as re-frame]
|
||||||
|
[reagent.core :as r]
|
||||||
|
[vimsical.re-frame.fx.track :as track]
|
||||||
|
[auto-ap.events :as events]
|
||||||
|
[vimsical.re-frame.cofx.inject :as inject]
|
||||||
|
[auto-ap.forms.builder :as form-builder]
|
||||||
|
[auto-ap.views.components :as com]))
|
||||||
|
|
||||||
|
(re-frame/reg-event-fx
|
||||||
|
::coded
|
||||||
|
(fn [_ [_ _ _]]
|
||||||
|
{:dispatch-n [[::modal/modal-closed]
|
||||||
|
[:auto-ap.views.pages.unpaid-invoices/params-change
|
||||||
|
@(re-frame/subscribe [::data-page/params :auto-ap.views.pages.unpaid-invoices/invoices])]]}))
|
||||||
|
|
||||||
|
(re-frame/reg-event-fx
|
||||||
|
::code-selected
|
||||||
|
[with-user (forms/in-form ::form) (re-frame/inject-cofx ::inject/sub [::subs/client])]
|
||||||
|
(fn [{:keys [user db] ::subs/keys [client]} [_ checked]]
|
||||||
|
(let [checked-params (get checked "header")
|
||||||
|
specific-invoices (map :id (vals (dissoc checked "header")))
|
||||||
|
data (:data db)]
|
||||||
|
{:graphql
|
||||||
|
{:token user
|
||||||
|
:owns-state {:single ::form}
|
||||||
|
:query-obj {:venia/operation {:operation/type :mutation
|
||||||
|
:operation/name "BulkChangeInvoices"}
|
||||||
|
:venia/queries [[:bulk-change-invoices
|
||||||
|
{:filters (some-> checked-params data-params->query-params)
|
||||||
|
:client_id (:id client)
|
||||||
|
:ids specific-invoices
|
||||||
|
:accounts (map
|
||||||
|
#(-> %
|
||||||
|
(update :id (fn [i] (if (some-> i (str/starts-with? "new-"))
|
||||||
|
nil
|
||||||
|
i)))
|
||||||
|
(assoc :percentage (/ (get-in % [:amount-percentage]) 100 ))
|
||||||
|
(assoc :account-id (get-in % [:account :id]))
|
||||||
|
(select-keys [:percentage :id :location :account-id]))
|
||||||
|
(:accounts data))}
|
||||||
|
[:message]
|
||||||
|
]]}
|
||||||
|
:on-success (fn [result]
|
||||||
|
[::coded
|
||||||
|
(:message result)
|
||||||
|
checked-params
|
||||||
|
])}})))
|
||||||
|
|
||||||
|
(defn form-content [_]
|
||||||
|
(let [{:keys [data]} @(re-frame/subscribe [::forms/form ::form])]
|
||||||
|
[form-builder/builder {:submit-event [::code-selected]
|
||||||
|
:id ::form}
|
||||||
|
|
||||||
|
[form-builder/raw-field-v2 {:field :accounts}
|
||||||
|
[expense-accounts-field-v2 {:descriptor "account asssignment"
|
||||||
|
:percentage-only? true
|
||||||
|
:client (:client data)
|
||||||
|
:locations (into ["Shared"] @(re-frame/subscribe [::subs/locations-for-client (:id (:client data))]))
|
||||||
|
:max 100}]]]))
|
||||||
|
(defn form [_]
|
||||||
|
(r/create-class
|
||||||
|
{:display-name "invoice-bulk-change-form"
|
||||||
|
:reagent-render (fn [p]
|
||||||
|
[form-content p])}))
|
||||||
|
|
||||||
|
(re-frame/reg-event-fx
|
||||||
|
::bulk-change-requested
|
||||||
|
(fn [{:keys [db]} [_ checked params total-visible]]
|
||||||
|
(let [to-change (if (get checked "header")
|
||||||
|
[:b.strong.has-text-danger "all " total-visible " visible invoices"]
|
||||||
|
(str (count checked) " invoices"))]
|
||||||
|
{:dispatch [::modal/modal-requested {:title "Confirmation"
|
||||||
|
:body [:div "Please fill in the details on how to code " to-change ":"
|
||||||
|
[form ]]
|
||||||
|
:cancel? true
|
||||||
|
:confirm {:value "Code"
|
||||||
|
:class "is-danger"
|
||||||
|
:status-from [::status/single ::form]
|
||||||
|
:on-click (dispatch-event [::code-selected checked] )}
|
||||||
|
:close-event [::status/completed ::code-selected]}]
|
||||||
|
:db (-> db
|
||||||
|
(forms/start-form ::form {:accounts []
|
||||||
|
:client @(re-frame/subscribe [::subs/client (:client-id params)])}))})))
|
||||||
@@ -132,7 +132,8 @@
|
|||||||
(defn action-buttons []
|
(defn action-buttons []
|
||||||
(let [is-admin? @(re-frame/subscribe [::subs/is-admin?])
|
(let [is-admin? @(re-frame/subscribe [::subs/is-admin?])
|
||||||
params @(re-frame/subscribe [::data-page/params ::page])
|
params @(re-frame/subscribe [::data-page/params ::page])
|
||||||
checked @(re-frame/subscribe [::data-page/checked ::page])]
|
checked @(re-frame/subscribe [::data-page/checked ::page])
|
||||||
|
{:keys [total]} @(re-frame/subscribe [::data-page/data ::page])]
|
||||||
(when is-admin?
|
(when is-admin?
|
||||||
[:<>
|
[:<>
|
||||||
[:div.level-item
|
[:div.level-item
|
||||||
@@ -154,7 +155,7 @@
|
|||||||
[:button.button.is-outlined.is-primary {:on-click (dispatch-event [::manual/opening])}
|
[:button.button.is-outlined.is-primary {:on-click (dispatch-event [::manual/opening])}
|
||||||
"Manual Yodlee Import"]
|
"Manual Yodlee Import"]
|
||||||
(when (:client-id params)
|
(when (:client-id params)
|
||||||
[:button.button.is-warning {:on-click (dispatch-event [::bulk/code-requested checked params])
|
[:button.button.is-warning {:on-click (dispatch-event [::bulk/code-requested checked params total])
|
||||||
:disabled (not (seq checked))}
|
:disabled (not (seq checked))}
|
||||||
"Code"])
|
"Code"])
|
||||||
[:button.button.is-danger {:on-click (dispatch-event [::delete-selected-requested params false])
|
[:button.button.is-danger {:on-click (dispatch-event [::delete-selected-requested params false])
|
||||||
|
|||||||
@@ -138,9 +138,9 @@
|
|||||||
|
|
||||||
(re-frame/reg-event-fx
|
(re-frame/reg-event-fx
|
||||||
::code-requested
|
::code-requested
|
||||||
(fn [{:keys [db]} [_ checked params]]
|
(fn [{:keys [db]} [_ checked params total-visible]]
|
||||||
(let [to-delete (if (get checked "header")
|
(let [to-delete (if (get checked "header")
|
||||||
[:b.strong.has-text-danger "all visible transactions"]
|
[:b.strong.has-text-danger "all " total-visible " visible transactions"]
|
||||||
(str (count checked) " transactions"))]
|
(str (count checked) " transactions"))]
|
||||||
{:dispatch [::modal/modal-requested {:title "Confirmation"
|
{:dispatch [::modal/modal-requested {:title "Confirmation"
|
||||||
:body [:div "Please fill in the details on how to code " to-delete ":"
|
:body [:div "Please fill in the details on how to code " to-delete ":"
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
[auto-ap.status :as status]
|
[auto-ap.status :as status]
|
||||||
[auto-ap.subs :as subs]
|
[auto-ap.subs :as subs]
|
||||||
[auto-ap.views.components.buttons :as buttons]
|
[auto-ap.views.components.buttons :as buttons]
|
||||||
|
[auto-ap.views.pages.invoices.bulk-change :as bulk-change]
|
||||||
[auto-ap.views.components.dropdown :refer [drop-down]]
|
[auto-ap.views.components.dropdown :refer [drop-down]]
|
||||||
[auto-ap.views.components.expense-accounts-dialog
|
[auto-ap.views.components.expense-accounts-dialog
|
||||||
:as expense-accounts-dialog]
|
:as expense-accounts-dialog]
|
||||||
@@ -208,18 +209,32 @@
|
|||||||
"Void"])))
|
"Void"])))
|
||||||
|
|
||||||
|
|
||||||
(defn pay-button []
|
(defn pay-button [status]
|
||||||
(let [current-client @(re-frame/subscribe [::subs/client])
|
(let [current-client @(re-frame/subscribe [::subs/client])
|
||||||
checked-invoices @(re-frame/subscribe [::data-page/checked :invoices])
|
checked-invoices @(re-frame/subscribe [::data-page/checked :invoices])
|
||||||
print-checks-status @(re-frame/subscribe [::status/single ::print-checks])]
|
is-admin? @(re-frame/subscribe [::subs/is-admin?])
|
||||||
|
print-checks-status @(re-frame/subscribe [::status/single ::print-checks])
|
||||||
|
params @(re-frame/subscribe [::data-page/params :invoices])
|
||||||
|
{:keys [total]} @(re-frame/subscribe [::data-page/data :invoices])
|
||||||
|
]
|
||||||
[:div.buttons
|
[:div.buttons
|
||||||
[void-selected-button]
|
(when (and (= :unpaid status)
|
||||||
|
is-admin?)
|
||||||
|
[void-selected-button])
|
||||||
|
|
||||||
[buttons/new-button {:event [::new-invoice-clicked]
|
[buttons/new-button {:event [::new-invoice-clicked]
|
||||||
:name "Invoice"
|
:name "Invoice"
|
||||||
:class "is-primary"}]
|
:class "is-primary"}]
|
||||||
|
|
||||||
(when current-client
|
(when (and is-admin?
|
||||||
|
current-client)
|
||||||
|
[buttons/event-button {:event [::bulk-change/bulk-change-requested checked-invoices params total]
|
||||||
|
:name "Bulk Edit"
|
||||||
|
:class "is-secondary"
|
||||||
|
:disabled (not (seq checked-invoices))}])
|
||||||
|
|
||||||
|
(when (and current-client
|
||||||
|
(= :unpaid status))
|
||||||
(let [balance (->> checked-invoices
|
(let [balance (->> checked-invoices
|
||||||
vals
|
vals
|
||||||
(map (comp js/parseFloat :outstanding-balance))
|
(map (comp js/parseFloat :outstanding-balance))
|
||||||
@@ -284,11 +299,10 @@
|
|||||||
|
|
||||||
[table/invoice-table {:id (:id page)
|
[table/invoice-table {:id (:id page)
|
||||||
:data-page :invoices
|
:data-page :invoices
|
||||||
:check-boxes (= status :unpaid)
|
:check-boxes true
|
||||||
:checkable-fn (fn [i] (not (:scheduled-payment i)))
|
:checkable-fn (fn [i] (not (:scheduled-payment i)))
|
||||||
:actions #{:edit :void :expense-accounts}
|
:actions #{:edit :void :expense-accounts}
|
||||||
:action-buttons (when (= status :unpaid)
|
:action-buttons [pay-button status]}]]))
|
||||||
[pay-button])}]]))
|
|
||||||
|
|
||||||
(defn layout [params]
|
(defn layout [params]
|
||||||
(let [{invoice-bar-active? :active?} @(re-frame/subscribe [::forms/form ::form/form])]
|
(let [{invoice-bar-active? :active?} @(re-frame/subscribe [::forms/form ::form/form])]
|
||||||
|
|||||||
Reference in New Issue
Block a user