Merge branch 'master' into side-panel
This commit is contained in:
@@ -119,6 +119,19 @@
|
||||
node))
|
||||
m))
|
||||
|
||||
(defonce timeouts
|
||||
(atom {}))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:dispatch-debounce
|
||||
(fn [{:keys [event time key]}]
|
||||
(js/clearTimeout (@timeouts key))
|
||||
(swap! timeouts assoc key
|
||||
(js/setTimeout (fn []
|
||||
(re-frame/dispatch event)
|
||||
(swap! timeouts dissoc key))
|
||||
time))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:graphql
|
||||
(fn [{:keys [query on-success on-error token variables query-obj]}]
|
||||
|
||||
@@ -133,10 +133,12 @@
|
||||
}
|
||||
""]]]
|
||||
[:tbody
|
||||
(println checked)
|
||||
(if (:loading @status)
|
||||
[:tr
|
||||
[:td {:col-span 5}
|
||||
[:i.fa.fa-spin.fa-spinner]]]
|
||||
|
||||
(for [{:keys [client payments expense-accounts invoice-number date total outstanding-balance id vendor] :as i} (:invoices @invoice-page)]
|
||||
^{:key id}
|
||||
[:tr {:class (:class i)}
|
||||
@@ -146,7 +148,8 @@
|
||||
"checked"
|
||||
"")
|
||||
:on-change (fn [x e] (when on-check-changed
|
||||
(on-check-changed id)))} ]])
|
||||
(println id i)
|
||||
(on-check-changed id i)))} ]])
|
||||
(when-not selected-client
|
||||
[:td (:name client)])
|
||||
[:td (:name vendor)]
|
||||
@@ -174,7 +177,7 @@
|
||||
[:div.dropdown-content
|
||||
(for [e expense-accounts]
|
||||
^{:key (:id e)}
|
||||
[:span.dropdown-item (:name (:expense-account e)) " "(gstring/format "$%.2f" (:amount e) ) ])
|
||||
[:span.dropdown-item (:name (:expense-account e)) " " (gstring/format "$%.2f" (:amount e) ) ])
|
||||
|
||||
[:hr.dropdown-divider]
|
||||
|
||||
|
||||
@@ -19,15 +19,22 @@
|
||||
[:li.menu-item
|
||||
[:a.item {:href (bidi/path-for routes/routes :unpaid-invoices)
|
||||
:class [(active-when ap = :unpaid-invoices)]}
|
||||
[:span {:class "icon icon-accounting-document" :style {:font-size "25px"}}]
|
||||
[:span {:class "icon icon-accounting-invoice-mail" :style {:font-size "25px"}}]
|
||||
[:span {:class "name"} "Unpaid Invoices"]]]
|
||||
[:li.menu-item
|
||||
[:a.item {:href (bidi/path-for routes/routes :paid-invoices)
|
||||
:class [(active-when ap = :paid-invoices)]}
|
||||
|
||||
[:span {:class "icon icon-accounting-invoice-mail" :style {:font-size "25px"}}]
|
||||
[:span {:class "icon icon-check-payment-give" :style {:font-size "25px"}}]
|
||||
|
||||
[:span {:class "name"} "Paid Invoices"]]]]]
|
||||
[:span {:class "name"} "Paid Invoices"]]]
|
||||
[:li.menu-item
|
||||
[:a.item {:href (bidi/path-for routes/routes :import-invoices)
|
||||
:class [(active-when ap = :import-invoices)]}
|
||||
|
||||
[:span {:class "icon icon-accounting-document" :style {:font-size "25px"}}]
|
||||
|
||||
[:span {:class "name"} "Import Invoices"]]]]]
|
||||
[:div
|
||||
rest]
|
||||
[:div {:class "compose has-text-centered"}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
[auto-ap.views.utils :refer [active-when active-when= login-url dispatch-event]]
|
||||
[auto-ap.views.components.layouts :refer [side-bar-layout]]
|
||||
[auto-ap.views.pages.unpaid-invoices :refer [unpaid-invoices-page]]
|
||||
[auto-ap.views.pages.import-invoices :refer [import-invoices-page]]
|
||||
[auto-ap.views.pages.paid-invoices :refer [paid-invoices-page]]
|
||||
[auto-ap.views.pages.transactions :refer [transactions-page]]
|
||||
[auto-ap.views.pages.login :refer [login-page]]
|
||||
@@ -25,6 +26,10 @@
|
||||
(defmethod page :unpaid-invoices [_]
|
||||
(unpaid-invoices-page {:status "unpaid"}))
|
||||
|
||||
(defmethod page :import-invoices [_]
|
||||
(import-invoices-page ))
|
||||
|
||||
|
||||
(defmethod page :paid-invoices [_]
|
||||
(unpaid-invoices-page {:status "paid"}))
|
||||
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
[auto-ap.events :as events]
|
||||
[auto-ap.subs :as subs]
|
||||
[auto-ap.entities.clients :as client]
|
||||
[auto-ap.views.components.layouts :refer [side-bar-layout]]
|
||||
[auto-ap.views.components.invoices.side-bar :refer [invoices-side-bar]]
|
||||
[auto-ap.views.utils :refer [dispatch-event]]
|
||||
[auto-ap.entities.vendors :as vendor]
|
||||
[auto-ap.views.components.invoice-table :refer [invoice-table] :as invoice-table]
|
||||
[cljsjs.dropzone :as dropzone]
|
||||
@@ -56,7 +59,7 @@
|
||||
(assoc-in [:status :loading] true)
|
||||
(assoc-in [::params] params))
|
||||
:graphql {:token (-> cofx :db :user)
|
||||
:query-obj (invoice-table/query (assoc params :imported false))
|
||||
:query-obj (invoice-table/query (assoc params :import-status "pending"))
|
||||
:on-success [::received]}}))
|
||||
|
||||
(re-frame/reg-event-db
|
||||
@@ -67,15 +70,32 @@
|
||||
(assoc-in [:status :loading] false))))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::reject-invoices
|
||||
(fn [cofx [_ on-success]]
|
||||
{:http {:method :post
|
||||
:token (-> cofx :db :user)
|
||||
:uri (str "/api/invoices/reject"
|
||||
(when-let [client-id (:id @(re-frame/subscribe [::subs/client]))]
|
||||
(str "?client=" client-id)))
|
||||
:on-success on-success
|
||||
}}))
|
||||
::reject-invoices-clicked
|
||||
(fn [{:keys [db]} [_ invoices on-success]]
|
||||
{:graphql
|
||||
{:token (-> db :user)
|
||||
:query-obj {:venia/operation {:operation/type :mutation
|
||||
:operation/name "RejectInvoices"}
|
||||
|
||||
:venia/queries [[:reject-invoices
|
||||
{:invoices (keys invoices)}
|
||||
[]]]}
|
||||
:on-success [::invalidated]}
|
||||
}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::approve-invoices-clicked
|
||||
(fn [{:keys [db]} [_ invoices on-success]]
|
||||
{:graphql
|
||||
{:token (-> db :user)
|
||||
:query-obj {:venia/operation {:operation/type :mutation
|
||||
:operation/name "ApproveInvoices"}
|
||||
|
||||
:venia/queries [[:approve-invoices
|
||||
{:invoices (keys invoices)}
|
||||
[]]]}
|
||||
:on-success [::invalidated]}
|
||||
}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::approve-invoices
|
||||
@@ -88,7 +108,46 @@
|
||||
:on-success on-success
|
||||
}}))
|
||||
|
||||
(def import-invoices-page
|
||||
(re-frame/reg-event-db
|
||||
::toggle-check
|
||||
(fn [db [_ id invoice]]
|
||||
(-> db
|
||||
(update-in [::invoice-page :checked] (fn [x]
|
||||
(let [x (or x {})]
|
||||
(if (x id)
|
||||
(dissoc x id)
|
||||
(assoc x id invoice))))))))
|
||||
|
||||
(defn approve-reject-button [checked]
|
||||
[:div.is-pulled-right
|
||||
|
||||
[:button.button.is-success {:on-click (dispatch-event [::approve-invoices-clicked checked])
|
||||
:disabled (if (seq checked)
|
||||
""
|
||||
"disabled")}
|
||||
"Approve "
|
||||
(when (> (count checked ))
|
||||
(str
|
||||
(count checked)
|
||||
" invoices"))
|
||||
|
||||
|
||||
[:span " "]]
|
||||
[:button.button.is-danger {:on-click (dispatch-event [::reject-invoices-clicked checked])
|
||||
:disabled (if (seq checked)
|
||||
""
|
||||
"disabled")}
|
||||
"Reject "
|
||||
(when (> (count checked ))
|
||||
(str
|
||||
(count checked)
|
||||
" invoices"))
|
||||
|
||||
|
||||
[:span " "]
|
||||
]])
|
||||
|
||||
(def import-invoices-content
|
||||
(with-meta
|
||||
(fn []
|
||||
(let [invoice-page (re-frame/subscribe [::invoice-page])
|
||||
@@ -102,30 +161,27 @@
|
||||
[:div {:class "card-header"}
|
||||
[:span {:class "card-header-title"} "Found Invoices"]]
|
||||
[:div {:class "card-content"}
|
||||
[approve-reject-button (:checked @invoice-page)]
|
||||
(if (:loading @status)
|
||||
[:h1.title
|
||||
[:i.fa.fa-spin.fa-spinner]]
|
||||
(if (seq (:invoices @invoice-page))
|
||||
[invoice-table {:id :approved
|
||||
:invoice-page invoice-page
|
||||
:check-boxes true
|
||||
:checked (:checked @invoice-page)
|
||||
:on-check-changed (fn [which invoice]
|
||||
(re-frame/dispatch [::toggle-check which invoice]))
|
||||
:status (re-frame/subscribe [::subs/status])
|
||||
:params (re-frame/subscribe [::params])
|
||||
:on-params-change (fn [params]
|
||||
(re-frame/dispatch [::params-change params])) }]
|
||||
[:span "No pending invoices"]))]
|
||||
(if (and (seq (:invoices @invoice-page)) (not (:loading @status)))
|
||||
[:div.card-footer
|
||||
[:a.card-footer-item
|
||||
{:on-click (fn [e]
|
||||
(.preventDefault e)
|
||||
(re-frame/dispatch [::approve-invoices
|
||||
[::invalidated]]))}
|
||||
"Accept all"]
|
||||
[:a.card-footer-item
|
||||
{:on-click (fn [e]
|
||||
(.preventDefault e)
|
||||
(re-frame/dispatch [::reject-invoices
|
||||
[::invalidated]]))}
|
||||
"Reject all"]])]]))
|
||||
[:span "No pending invoices"]))]]]))
|
||||
{:component-will-mount (fn []
|
||||
(re-frame/dispatch-sync [::invalidated]))}))
|
||||
|
||||
(defn import-invoices-page []
|
||||
[side-bar-layout {:side-bar [invoices-side-bar {}]
|
||||
:main [import-invoices-content ]}])
|
||||
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
[auto-ap.views.components.invoices.side-bar :refer [invoices-side-bar]]
|
||||
[auto-ap.expense-accounts :as expense-accounts]
|
||||
[auto-ap.entities.invoices-expense-accounts :as invoices-expense-accounts]
|
||||
[auto-ap.views.utils :refer [active-when dispatch-event bind-field horizontal-field date->str str->date pretty standard]]
|
||||
[auto-ap.views.utils :refer [active-when dispatch-event bind-field horizontal-field date->str date-time->str str->date pretty standard]]
|
||||
[auto-ap.utils :refer [by replace-if]]
|
||||
[auto-ap.views.pages.check :as check]
|
||||
[auto-ap.views.components.invoice-table :refer [invoice-table] :as invoice-table]
|
||||
@@ -72,6 +72,7 @@
|
||||
(fn [db]
|
||||
(-> db (::params {}))))
|
||||
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::params-change
|
||||
(fn [cofx [_ params]]
|
||||
@@ -79,24 +80,30 @@
|
||||
(assoc-in [:status :loading] true)
|
||||
(assoc-in [::params] params))
|
||||
:graphql {:token (-> cofx :db :user)
|
||||
:query-obj (invoice-table/query (doto (assoc params :imported true) println))
|
||||
:query-obj (invoice-table/query (-> params (assoc :import-status "imported") (dissoc :invoice-number-like-current)) )
|
||||
:on-success [::received]}}))
|
||||
(re-frame/reg-event-db
|
||||
::unmount-invoices
|
||||
(fn [db [_ data]]
|
||||
(-> db
|
||||
(dissoc ::invoice-page ))))
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::received
|
||||
(fn [db [_ data]]
|
||||
(-> db
|
||||
(assoc ::invoice-page (first (:invoice-page data)))
|
||||
(update ::invoice-page merge (first (:invoice-page data)))
|
||||
(assoc-in [:status :loading] false))))
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::toggle-check
|
||||
(fn [db [_ data]]
|
||||
(update-in db [::invoice-page :checked] (fn [x]
|
||||
(let [x (or x #{})]
|
||||
(if (x data)
|
||||
(disj x data)
|
||||
(conj x data)))))))
|
||||
(fn [db [_ id invoice]]
|
||||
(-> db
|
||||
(update-in [::invoice-page :checked] (fn [x]
|
||||
(let [x (or x {})]
|
||||
(if (x id)
|
||||
(dissoc x id)
|
||||
(assoc x id invoice))))))))
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::print-checks-clicked
|
||||
@@ -111,8 +118,8 @@
|
||||
(update-in [::invoice-page :print-checks-shown?] #(not %) )
|
||||
(assoc-in [::advanced-print-checks] {:shown? true
|
||||
:bank-account-id (:id (first (:bank-accounts @(re-frame/subscribe [::subs/clients]))))
|
||||
:invoices (->> invoices
|
||||
(filter (comp checked :id))
|
||||
:invoices (->> checked
|
||||
vals
|
||||
(map #(assoc % :amount (:outstanding-balance %))))} )))))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
@@ -171,22 +178,20 @@
|
||||
(re-frame/reg-event-fx
|
||||
::print-checks
|
||||
(fn [{:keys [db]} [_ bank-account-id type]]
|
||||
(let [invoice-amounts (by :id :outstanding-balance (get-in db [::invoice-page :invoices]))]
|
||||
|
||||
{:db (-> db
|
||||
(assoc-in [::invoice-page :print-checks-shown?] false )
|
||||
(assoc-in [::invoice-page :print-checks-loading?] true ))
|
||||
:graphql
|
||||
{:token (-> db :user)
|
||||
|
||||
:query-obj (print-checks-query (map (fn [id]
|
||||
{:invoice-id id
|
||||
:amount (invoice-amounts id)})
|
||||
(get-in db [::invoice-page :checked]))
|
||||
bank-account-id
|
||||
type
|
||||
(:client db))
|
||||
:on-success [::checks-created]}})))
|
||||
{:db (-> db
|
||||
(assoc-in [::invoice-page :print-checks-shown?] false )
|
||||
(assoc-in [::invoice-page :print-checks-loading?] true ))
|
||||
:graphql
|
||||
{:token (-> db :user)
|
||||
|
||||
:query-obj (print-checks-query (map (fn [[id invoice]]
|
||||
{:invoice-id id
|
||||
:amount (:outstanding-balance invoice)})
|
||||
(get-in db [::invoice-page :checked]))
|
||||
bank-account-id
|
||||
type
|
||||
(:client db))
|
||||
:on-success [::checks-created]}}))
|
||||
|
||||
|
||||
|
||||
@@ -675,57 +680,96 @@
|
||||
(if (and (= key :vendor-id)
|
||||
(not= value (get-in db [::params :vendor-id])))
|
||||
(do
|
||||
(re-frame/dispatch [::params-change (assoc (::params updated) :vendor-id value)])
|
||||
(re-frame/dispatch [::params-change (assoc (::params updated) :vendor-id value :start 0)])
|
||||
(assoc-in updated [::params :vendor-id] value))
|
||||
updated))))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::invoice-number-like-current-changed
|
||||
(fn [{:keys [db]} [_ params invoice-like]]
|
||||
{:db (assoc-in db [::params :invoice-number-like-current] invoice-like )
|
||||
:dispatch-debounce {:event [::invoice-number-like-settled invoice-like]
|
||||
:time 500
|
||||
:key ::invoice-nuber-like}}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::invoice-number-like-settled
|
||||
(fn [{:keys [db]} [_ invoice-like]]
|
||||
{:dispatch [::params-change (assoc (::params db) :invoice-number-like invoice-like :start 0) ]}))
|
||||
|
||||
(defn invoice-number-filter []
|
||||
(let [{:keys [invoice-number-like] :as params} @(re-frame/subscribe [::params])]
|
||||
(let [{:keys [invoice-number-like-current] :as params} @(re-frame/subscribe [::params])]
|
||||
[:div.field
|
||||
[:div.control [:input.input {:placeholder "AP-123"
|
||||
:value invoice-number-like
|
||||
:value invoice-number-like-current
|
||||
:on-change (fn [x]
|
||||
(re-frame/dispatch [::params-change (assoc params :invoice-number-like (.. x -target -value)) ])
|
||||
)} ]]]))
|
||||
(re-frame/dispatch [::invoice-number-like-current-changed params (.. x -target -value) ]))} ]]]))
|
||||
|
||||
(defn pay-button [{:keys [print-checks-shown? checked-invoices print-checks-loading?]}]
|
||||
(let [current-client @(re-frame/subscribe [::subs/client])]
|
||||
[:div.is-pulled-right
|
||||
[:button.button.is-danger {:on-click (dispatch-event [::new-invoice])} "New Invoice"]
|
||||
(when current-client
|
||||
[:div.dropdown.is-right {:class (if print-checks-shown?
|
||||
"is-active"
|
||||
"")}
|
||||
[:div.dropdown-trigger
|
||||
[:button.button.is-success {:aria-haspopup true
|
||||
:on-click (dispatch-event [::print-checks-clicked ])
|
||||
:disabled (if (seq checked-invoices)
|
||||
""
|
||||
"disabled")
|
||||
[:div
|
||||
|
||||
|
||||
|
||||
[:div.is-pulled-right
|
||||
|
||||
|
||||
[:button.button.is-danger {:on-click (dispatch-event [::new-invoice])} "New Invoice"]
|
||||
|
||||
|
||||
(when current-client
|
||||
[:div.dropdown.is-right {:class (if print-checks-shown?
|
||||
"is-active"
|
||||
"")}
|
||||
[:div.dropdown-trigger
|
||||
[:button.button.is-success {:aria-haspopup true
|
||||
:on-click (dispatch-event [::print-checks-clicked ])
|
||||
:disabled (if (seq checked-invoices)
|
||||
""
|
||||
"disabled")
|
||||
|
||||
:class (if print-checks-loading?
|
||||
"is-loading"
|
||||
"")}
|
||||
"Pay "
|
||||
[:span " "]
|
||||
[:span.icon.is-small [:i.fa.fa-angle-down {:aria-hidden "true"}]]]]
|
||||
[:div.dropdown-menu {:role "menu"}
|
||||
[:div.dropdown-content
|
||||
(list
|
||||
(for [{:keys [id number name type]} (:bank-accounts current-client)]
|
||||
(if (= :cash type)
|
||||
^{:key id} [:a.dropdown-item {:on-click (dispatch-event [::print-checks id :cash])} "With cash"]
|
||||
(list
|
||||
^{:key (str id "-check")} [:a.dropdown-item {:on-click (dispatch-event [::print-checks id :check])} "Print checks from " name]
|
||||
^{:key (str id "-debit")} [:a.dropdown-item {:on-click (dispatch-event [::print-checks id :debit])} "Debit from " name])))
|
||||
^{:key "advanced-divider"} [:hr.dropdown-divider]
|
||||
:class (if print-checks-loading?
|
||||
"is-loading"
|
||||
"")}
|
||||
"Pay "
|
||||
(when (> (count checked-invoices ))
|
||||
(str
|
||||
(count checked-invoices)
|
||||
" invoices "
|
||||
"(" (->> checked-invoices
|
||||
vals
|
||||
(map (comp js/parseFloat :outstanding-balance))
|
||||
(reduce + 0)
|
||||
(gstring/format "$%.2f" ))
|
||||
")"))
|
||||
|
||||
|
||||
[:span " "]
|
||||
[:span.icon.is-small [:i.fa.fa-angle-down {:aria-hidden "true"}]]]]
|
||||
[:div.dropdown-menu {:role "menu"}
|
||||
[:div.dropdown-content
|
||||
(list
|
||||
(for [{:keys [id number name type]} (:bank-accounts current-client)]
|
||||
(if (= :cash type)
|
||||
^{:key id} [:a.dropdown-item {:on-click (dispatch-event [::print-checks id :cash])} "With cash"]
|
||||
(list
|
||||
^{:key (str id "-check")} [:a.dropdown-item {:on-click (dispatch-event [::print-checks id :check])} "Print checks from " name]
|
||||
^{:key (str id "-debit")} [:a.dropdown-item {:on-click (dispatch-event [::print-checks id :debit])} "Debit from " name])))
|
||||
^{:key "advanced-divider"} [:hr.dropdown-divider]
|
||||
|
||||
(when (= 1 (count checked-invoices))
|
||||
^{:key "handwritten"} [:a.dropdown-item {:on-click (dispatch-event [::handwrite-checks])} "Handwritten Check..."])
|
||||
^{:key "advanced"} [:a.dropdown-item {:on-click (dispatch-event [::advanced-print-checks])} "Advanced..."])]]])]))
|
||||
(when (= 1 (count checked-invoices))
|
||||
^{:key "handwritten"} [:a.dropdown-item {:on-click (dispatch-event [::handwrite-checks])} "Handwritten Check..."])
|
||||
^{:key "advanced"} [:a.dropdown-item {:on-click (dispatch-event [::advanced-print-checks])} "Advanced..."])]]])]
|
||||
[:div.is-pulled-right
|
||||
(into [:div.tags {:style {:margin-right ".5 rem;"}}] (map (fn [[id invoice]] [:span.tag.is-medium (:invoice-number invoice) [:button.delete.is-small {:on-click (dispatch-event [::toggle-check id invoice])}]]) checked-invoices))]]
|
||||
))
|
||||
|
||||
(defn unpaid-invoices-content [{:keys [status]}]
|
||||
(r/create-class {:display-name "unpaid-invoices-content"
|
||||
:component-will-unmount (fn [this]
|
||||
(re-frame/dispatch [::unmount-invoices])
|
||||
|
||||
)
|
||||
:reagent-render (fn [{:keys [status]}]
|
||||
(let [{:keys [checked print-checks-shown? print-checks-loading? advanced-print-shown? vendor-filter]} @(re-frame/subscribe [::invoice-page])
|
||||
current-client @(re-frame/subscribe [::subs/client])
|
||||
@@ -736,6 +780,7 @@
|
||||
[pay-button {:print-checks-shown? print-checks-shown? :checked-invoices checked :print-checks-loading? print-checks-loading?}])
|
||||
|
||||
|
||||
|
||||
[invoice-table {:id :unpaid
|
||||
:params (re-frame/subscribe [::params])
|
||||
:invoice-page (re-frame/subscribe [::invoice-page])
|
||||
@@ -749,8 +794,8 @@
|
||||
(re-frame/dispatch [::params-change params]))
|
||||
:check-boxes (= status "unpaid")
|
||||
:checked checked
|
||||
:on-check-changed (fn [which]
|
||||
(re-frame/dispatch [::toggle-check which]))
|
||||
:on-check-changed (fn [which invoice]
|
||||
(re-frame/dispatch [::toggle-check which invoice]))
|
||||
:expense-event [::expense-accounts-dialog/change-expense-accounts]}]
|
||||
|
||||
[print-checks-modal]
|
||||
|
||||
Reference in New Issue
Block a user