(ns auto-ap.views.pages.transactions (:require [auto-ap.effects.forward :as forward] [auto-ap.forms :as forms] [auto-ap.subs :as subs] [auto-ap.utils :refer [replace-by]] [auto-ap.views.components.layouts :refer [appearing-side-bar side-bar-layout]] [auto-ap.views.pages.data-page :as data-page] [auto-ap.views.pages.transactions.common :refer [transaction-read]] [auto-ap.views.pages.transactions.form :as edit] [auto-ap.views.pages.transactions.manual :as manual] [auto-ap.views.pages.transactions.side-bar :as side-bar] [auto-ap.views.pages.transactions.table :as table] [auto-ap.views.utils :refer [dispatch-event with-user]] [clojure.set :as set] [re-frame.core :as re-frame] [reagent.core :as reagent] [vimsical.re-frame.fx.track :as track] [auto-ap.status :as status])) (defn data-params->query-params [params] {:start (:start params 0) :per-page (:per-page params) :sort (:sort params) :client-id (:id @(re-frame/subscribe [::subs/client])) :vendor-id (:id (:vendor params)) :date-range (:date-range params) :account-id (:id (:account params)) :bank-account-id (:id (:bank-account params)) :amount-gte (:amount-gte (:amount-range params)) :exact-match-id (some-> (:exact-match-id params) str) :unresolved (:unresolved params) :location (:location params) :import-batch-id (some-> (:import-batch-id params) str) :amount-lte (:amount-lte (:amount-range params)) :description (:description params) :approval-status (condp = @(re-frame/subscribe [::subs/active-page]) :transactions nil :unapproved-transactions :unapproved :requires-feedback-transactions :requires-feedback :excluded-transactions :excluded :approved-transactions :approved)}) (re-frame/reg-event-fx ::params-change [with-user] (fn [{:keys [user db ]} [_ params]] (try {:graphql {:token user :owns-state {:single [::data-page/page ::page]} :query-obj {:venia/queries [{:query/data [:transaction_page {:filters (data-params->query-params params)} [[:data transaction-read] :total :start :end]] :query/alias :result}]} :on-success (fn [result] [::data-page/received ::page (:result result)])}} (catch js/Error e ;; this catches an error where you choose a parameter, change to invoices page, then change to voided invoices (println "Error!" e))))) (re-frame/reg-event-fx ::bulk-change-transaction-status (fn [cofx [_ status params]] (let [checked @(re-frame/subscribe [::data-page/checked ::page]) checked-params (get checked "header") specific-transactions (map :id (vals (dissoc checked "header")))] (println checked-params) {:db (-> (:db cofx) (assoc-in [:status :loading] true)) :graphql {:token (-> cofx :db :user) :owns-state {:single ::bulk-change-transaction-status} :query-obj {:venia/operation {:operation/type :mutation :operation/name "BulkChangeTransactionStatus"} :venia/queries [{:query/data [:bulk-change-transaction-status {:filters (some-> checked-params data-params->query-params) :status status :ids specific-transactions} [:message]]}]} :on-success (fn [result] [::params-change params])}}))) (re-frame/reg-event-fx ::delete-selected (fn [cofx [_ params]] (let [checked @(re-frame/subscribe [::data-page/checked ::page]) checked-params (get checked "header") specific-transactions (map :id (vals (dissoc checked "header")))] {:db (-> (:db cofx) (assoc-in [:status :loading] true)) :graphql {:token (-> cofx :db :user) :owns-state {:single ::delete-selected} :query-obj {:venia/operation {:operation/type :mutation :operation/name "DeleteTransactions"} :venia/queries [{:query/data [:delete-transactions {:filters (some-> checked-params data-params->query-params) :ids specific-transactions} [:message]]}]} :on-success (fn [result] [::params-change params])} :dispatch [::data-page/reset-checked ::page]}))) (re-frame/reg-event-fx ::unmounted (fn [{:keys [db]} _] {:dispatch-n [[::data-page/dispose ::page] [::status/dispose-single ::manual-import]] ::track/dispose {:id ::params} ::forward/dispose [{:id ::updated} {:id ::manual-import}]})) (re-frame/reg-event-fx ::mounted (fn [{:keys [db]} _] {::track/register {:id ::params :subscription [::data-page/params ::page] :event-fn (fn [params] [::params-change params])} ::forward/register [{:id ::updated :events #{::edit/edited} :event-fn (fn [[_ edited-transaction]] [::data-page/updated-entity ::page edited-transaction])} {:id ::manual-import :events #{::manual/import-completed} :event-fn (fn [[_ {:keys [imported errors] :as result}]] [::status/info ::manual-import (str "Successfully imported " imported " transactions" (when (seq errors) (str ", " (count errors) " errors. " "Example: '" (str (:info (first (:errors (first errors))))) "'")))])}]})) (defn content [] (let [is-admin? @(re-frame/subscribe [::subs/is-admin?]) params @(re-frame/subscribe [::data-page/params ::page]) checked @(re-frame/subscribe [::data-page/checked ::page])] [:div [:h1.title "Transactions"] [status/status-notification {:statuses [[::status/single ::bulk-change-transaction-status] [::status/single ::delete-selected] [::status/single ::manual-import]]}] (when is-admin? [:div.is-pulled-right [:div.buttons (into [:div.tags ] (map (fn [[z {:keys [id]}]] (if (= "header" z) [:span.tag.is-medium {:on-click (dispatch-event [::data-page/remove-check ::page "header"])} "All visible transactions"] [:span.tag.is-medium id [:button.delete.is-small {:on-click (dispatch-event [::data-page/remove-check ::page id])}]])) checked)) [:button.button.is-outlined.is-primary {:on-click (dispatch-event [::manual/opening])} "Manual Yodlee Import"] [:button.button.is-warning {:on-click (dispatch-event [::bulk-change-transaction-status :unapproved params]) :class (status/class-for @(re-frame/subscribe [::status/single ::bulk-change-transaction-status])) :disabled (or (status/disabled-for @(re-frame/subscribe [::status/single ::bulk-change-transaction-status])) (not (seq checked)))} "Unapprove selected"] [:button.button.is-warning {:on-click (dispatch-event [::bulk-change-transaction-status :excluded params]) :class (status/class-for @(re-frame/subscribe [::status/single ::bulk-change-transaction-status])) :disabled (or (status/disabled-for @(re-frame/subscribe [::status/single ::bulk-change-transaction-status])) (not (seq checked)))} "Exclude selected"] [:button.button.is-warning {:on-click (dispatch-event [::bulk-change-transaction-status :requires-feedback params]) :class (status/class-for @(re-frame/subscribe [::status/single ::bulk-change-transaction-status])) :disabled (or (status/disabled-for @(re-frame/subscribe [::status/single ::bulk-change-transaction-status])) (not (seq checked)))} "Client Review"] [:button.button.is-danger {:on-click (dispatch-event [::delete-selected params]) :class (status/class-for @(re-frame/subscribe [::status/single ::delete-selected])) :disabled (or (status/disabled-for @(re-frame/subscribe [::status/single ::delete-selected])) (not (seq checked)))} "Suppress selected"]]]) [table/table {:id :transactions :check-boxes? is-admin? :data-page ::page}]])) (defn transactions-page [{:keys [approval-status]}] (reagent/create-class {:display-name "transaction-page" :component-will-unmount #(re-frame/dispatch [::unmounted]) :component-did-mount #(re-frame/dispatch [::mounted]) :reagent-render (fn [] (let [{transaction-bar-active? :active?} @(re-frame/subscribe [::forms/form ::edit/form])] [side-bar-layout {:side-bar [side-bar/side-bar {:data-page ::page}] :main [:div ^{:key approval-status} [content]] :right-side-bar [appearing-side-bar {:visible? transaction-bar-active?} [edit/form]]}]))}))