Files
integreat/src/cljs/auto_ap/views/components/invoice_table.cljs
2019-01-25 13:16:21 -08:00

216 lines
10 KiB
Clojure

(ns auto-ap.views.components.invoice-table
(:require [re-frame.core :as re-frame]
[auto-ap.subs :as subs]
[auto-ap.views.utils :refer [date->str dispatch-event delayed-dispatch]]
[auto-ap.views.components.paginator :refer [paginator]]
[auto-ap.views.components.sorter :refer [sorted-column]]
[reagent.core :as reagent]
[clojure.string :as str]
[cljs-time.format :as format]
[goog.string :as gstring]))
;; TODO graphql schema enforcement
;; TODO postgres constraints for data integrity
;; TODO performance
;; TODO refactor graphql
(re-frame/reg-event-fx
::toggle-checks
(fn [{:keys [db] } [_ invoice-id]]
{:db
(update-in db [::visible-checks] (fn [i] (if (= i invoice-id) nil invoice-id) ))}))
(re-frame/reg-sub
::visible-checks
(fn [db]
(::visible-checks db)))
(re-frame/reg-event-fx
::toggle-expense-accounts
(fn [{:keys [db] } [_ invoice-id]]
{:db
(update-in db [::visible-expense-accounts] (fn [i] (if (= i invoice-id) nil invoice-id) ))}))
(re-frame/reg-sub
::visible-expense-accounts
(fn [db]
(::visible-expense-accounts db)))
(defn query [params]
{:venia/queries [[:invoice_page
(assoc params
:client-id (:id @(re-frame/subscribe [::subs/client])))
[[:invoices [:id :total :outstanding-balance :invoice-number :date
[:vendor [:name :id]]
[:expense_accounts [:amount :id :expense_account_id :location
[:expense_account [:id :name :location [:parent [:id :name]]]]]]
[:client [:name :id :locations]]
[:payments [:amount :id [:payment [:id :status :amount :s3_url :check_number
[:transaction [:post_date]]]]]]]]
:total
:start
:end]]]})
(defn invoice-table [{:keys [id invoice-page status on-params-change vendors params check-boxes checked on-check-changed on-edit-invoice on-void-invoice expense-event]}]
(let [visible-checks @(re-frame/subscribe [::visible-checks])
visible-expense-accounts @(re-frame/subscribe [::visible-expense-accounts])
selected-client @(re-frame/subscribe [::subs/client])
opc (fn [p]
(on-params-change (merge @params p)))]
(fn [{:keys [id invoice-page status on-params-change vendors checked params]}]
(let [{:keys [sort-by asc]} @params
{:keys [invoices start end count total]} @invoice-page
visible-checks @(re-frame/subscribe [::visible-checks])
visible-expense-accounts @(re-frame/subscribe [::visible-expense-accounts])
selected-client @(re-frame/subscribe [::subs/client])
percentage-size (if selected-client "%50%" "33%")
]
[:div
[paginator {:start start :end end :count count :total total
:on-change (fn [p ]
(on-params-change (merge @params p) ))}]
"Showing " (inc start) "-" end "/" total
[:table.table.is-fullwidth
[:thead
[:tr
(when check-boxes
[:th {:style {"width" "20px"}}])
(when-not selected-client
[sorted-column {:on-sort opc
:style {:width percentage-size :cursor "pointer"}
:sort-key "client"
:sort-by sort-by
:asc asc}
"Client"])
[sorted-column {:on-sort opc
:style {:width percentage-size :cursor "pointer"}
:sort-key "vendor"
:sort-by sort-by
:asc asc}
"Vendor"]
[sorted-column {:on-sort opc
:style {:width percentage-size :cursor "pointer"}
:sort-key "invoice-number"
:sort-by sort-by
:asc asc}
"Invoice #"]
[sorted-column {:on-sort opc
:style {:width "8em" :cursor "pointer"}
:sort-key "date"
:sort-by sort-by
:asc asc}
"Date"]
[sorted-column {:on-sort opc
:style {:width "8em" :cursor "pointer"}
:sort-key "location"
:sort-by sort-by
:asc asc}
"Location"]
[sorted-column {:on-sort opc
:style {:width "8em" :cursor "pointer"}
:sort-key "total"
:sort-by sort-by
:asc asc}
"Amount"]
[sorted-column {:on-sort opc
:style {:width "10em" :cursor "pointer"}
:sort-key "outstanding-balance"
:sort-by sort-by
:asc asc}
"Outstanding"]
[:th {
:style {:width "15em" :cursor "pointer"}
}
""]]]
[:tbody
(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)}
(when check-boxes
[:td [:input.checkbox {:type "checkbox"
:checked (if (get checked id)
"checked"
"")
:on-change (fn [x e] (when on-check-changed
(on-check-changed id)))} ]])
(when-not selected-client
[:td (:name client)])
[:td (:name vendor)]
[:td invoice-number]
[:td (date->str date) ]
[:td (str/join ", " (set (map :location expense-accounts)))]
[:td (gstring/format "$%.2f" total )]
[:td (gstring/format "$%.2f" outstanding-balance )]
[:td.expandable
(when (seq expense-accounts)
[:div.dropdown.is-right {:class (if (= id visible-expense-accounts)
"is-active"
"")}
[:div.dropdown-trigger
[:a.button.badge {:data-badge (str (clojure.core/count expense-accounts))
:aria-haspopup true
:tab-index "0"
:on-blur (delayed-dispatch [::toggle-expense-accounts id])
:on-focus (dispatch-event [::toggle-expense-accounts id])
} "Accounts"]]
[:div.dropdown-menu {:role "menu"}
[:div.dropdown-content
(for [e expense-accounts]
^{:key (:id e)}
[:span.dropdown-item (:name (:expense-account e)) " "(gstring/format "$%.2f" (:amount e) ) ])
[:hr.dropdown-divider]
(when expense-event
[:a.dropdown-item.is-primary {:on-click (dispatch-event (conj expense-event i))} "Change"])]]])
[:span {:style {:margin-left "1em"}}]
(when on-edit-invoice
[:button.button {:on-click (fn [] (on-edit-invoice i))} [:span.icon [:i.fa.fa-pencil]]])
(when (and on-void-invoice (= (:outstanding-balance i) (:total i)))
[:button.button.is-warning.is-outlined {:on-click (fn [] (on-void-invoice i))} [:span [:span.icon [:i.fa.fa-minus-circle]]]])
(when (seq payments)
[:div.dropdown.is-right {:class (if (= id visible-checks)
"is-active"
"")}
[:div.dropdown-trigger
[:a.button.badge {:data-badge (str (clojure.core/count payments))
:aria-haspopup true
:tab-index "0"
:on-blur (delayed-dispatch [::toggle-checks id])
:on-focus (dispatch-event [::toggle-checks id])
} "Checks"]]
[:div.dropdown-menu {:role "menu"}
[:div.dropdown-content
(for [payment payments]
(if (:s3-url (:payment payment))
^{:key (:id payment)}
[:a.dropdown-item {:href (:s3-url (:payment payment)) :target "_new"} [:i.fa.fa-money-check] [:span.icon [:i.fa.fa-money]] (str " " (:check-number (:payment payment)) " (" (gstring/format "$%.2f" (:amount payment) ) ")")]
^{:key (:id payment)}
[:span.dropdown-item [:span.icon {:class [(when (= :cleared (:status (:payment payment)))
"has-text-success")]}
[:i.fa.fa-money]] (str " " (:check-number (:payment payment)) " (" (gstring/format "$%.2f" (:amount payment) ) ") "
(when (= :cleared (:status (:payment payment)))
(str " - " (:post-date (:transaction (:payment payment))))))]))]]])
]]))]]]))))