292 lines
12 KiB
Clojure
292 lines
12 KiB
Clojure
(ns auto-ap.events
|
|
(:require
|
|
[auto-ap.db :as db]
|
|
[auto-ap.routes :as routes]
|
|
[auto-ap.utils :refer [by]]
|
|
[auto-ap.views.pages.data-page :as data-page]
|
|
[auto-ap.views.utils :refer [parse-jwt with-user gunzip]]
|
|
[bidi.bidi :as bidi]
|
|
[clojure.string :as str]
|
|
[clojure.edn :as edn]
|
|
[goog.crypt.base64 :as b64]
|
|
[re-frame.core :as re-frame]
|
|
[auto-ap.ssr-routes :as ssr-routes]
|
|
[cemerick.url :as url]
|
|
[auto-ap.subs :as subs]
|
|
[pako]))
|
|
|
|
|
|
|
|
(defn jwt->data [token]
|
|
(let [raw (js->clj (.parse js/JSON (b64/decodeString (second (str/split token #"\." )))))
|
|
gz-clients (or (:gz-clients raw)
|
|
(get raw "gz-clients"))]
|
|
(cond-> raw
|
|
gz-clients (assoc "user/clients" (gunzip gz-clients)))))
|
|
|
|
|
|
|
|
(defn client-query []
|
|
(cond-> [:id :name :code :email :locations :feature-flags
|
|
[:emails [:id :email :description]]
|
|
[:bank-accounts [:id :code :bank-name :name :type :visible
|
|
:locations :include-in-reports :current-balance
|
|
:sort-order]]]))
|
|
|
|
(defn client-detail-query [token]
|
|
(cond-> [:id :name :signature-file :code :email :matches :week-a-debits :week-a-credits :week-b-debits :week-b-credits :locations :locked-until :square-auth-token :feature-flags
|
|
[:square-integration-status [:last-updated :last-attempt :message :state :id]]
|
|
[:square-locations [:square-id :id :name :client-location]]
|
|
[:ezcater-locations [:id [:caterer [:name :id]] :location]]
|
|
[:emails [:id :email :description]]
|
|
[:location-matches [:id :location :match]]
|
|
[:bank-accounts [:id :start-date :numeric-code :code :number :bank-name :bank-code :check-number :name :routing :type :sort-order :visible :yodlee-account-id
|
|
[:integration-status [:last-updated :last-attempt :message :state :id]]
|
|
[:yodlee-account [:name :id :number]]
|
|
[:plaid-account [:name :id :number]]
|
|
[:intuit-bank-account [:name :id :external-id]]
|
|
:use-date-instead-of-post-date
|
|
:locations :include-in-reports :current-balance :yodlee-balance-old] ]
|
|
[:address [:id :street1 :street2 :city :state :zip]]
|
|
[:forecasted-transactions [:id :amount :identifier :day-of-month]]]
|
|
(= "admin" (or (get (jwt->data token) "role") (get (jwt->data token) "user/role")) ) (into [[:yodlee-provider-accounts [:id [:accounts [:id :name :number :available-balance]]]]
|
|
[:plaid-items [:id [:accounts [:id :name :number :balance]]]]])))
|
|
|
|
(re-frame/reg-event-fx
|
|
::initialize-db
|
|
(fn [{:keys [_]} [_ token]]
|
|
(let [handler (:handler (bidi/match-route routes/routes (.. js/window -location -pathname)))
|
|
last-client-id (.getItem js/localStorage "last-client-id")
|
|
last-selected-clients (edn/read-string (.getItem js/localStorage "last-selected-clients"))
|
|
jwt-data (some-> token jwt->data)
|
|
selected-client-assignment (cond (and token
|
|
(= "admin" (get jwt-data "user/role"))
|
|
(not last-selected-clients))
|
|
:mine
|
|
|
|
(and token
|
|
last-client-id
|
|
(not last-selected-clients))
|
|
[(js/parseInt last-client-id)]
|
|
|
|
:else
|
|
nil)]
|
|
|
|
|
|
(cond
|
|
(= :login handler)
|
|
{:db (cond-> (assoc db/default-db
|
|
:active-route :login
|
|
:last-client-id last-client-id
|
|
:selected-clients last-selected-clients
|
|
:user nil))}
|
|
|
|
(and (not= :login handler) (not token))
|
|
{:redirect "/login"
|
|
:db (assoc db/default-db
|
|
:active-route :login
|
|
:last-client-id last-client-id
|
|
:selected-clients last-selected-clients
|
|
:user token)}
|
|
|
|
(and token (= "none" (or (get jwt-data "role") (get jwt-data "user/role")) ))
|
|
{:redirect "/needs-activation"
|
|
:db (assoc db/default-db
|
|
:active-route :needs-activation
|
|
:last-client-id last-client-id
|
|
:selected-clients last-selected-clients
|
|
:user token)}
|
|
|
|
:else
|
|
(cond-> {:db (cond-> (assoc db/default-db
|
|
:active-route handler
|
|
:is-initial-loading? true
|
|
:last-client-id last-client-id
|
|
:selected-clients last-selected-clients
|
|
:query-params (auto-ap.views.utils/query-params)
|
|
:user token)
|
|
selected-client-assignment
|
|
(assoc :selected-clients selected-client-assignment))
|
|
:graphql {:token token
|
|
:query-obj {:venia/queries [[:client (client-query)]]}
|
|
:on-success [::received-initial]
|
|
:on-error [::failed-initial]}}
|
|
selected-client-assignment
|
|
(assoc :set-local-storage ["last-selected-clients" selected-client-assignment]))))))
|
|
|
|
|
|
(re-frame/reg-event-db
|
|
::toggle-menu
|
|
(fn [db [_ which]]
|
|
(update-in db [:menu which :active?] #(not %))))
|
|
|
|
|
|
(re-frame/reg-event-fx
|
|
::received-initial
|
|
(fn [{:keys [db]} [_ {clients :client}]]
|
|
(let [only-one-client (when (= 1 (count clients))
|
|
(->> clients first :id ))]
|
|
(when only-one-client
|
|
(.setItem js/localStorage "last-client-id" only-one-client)
|
|
(.setItem js/localStorage "last-selected-clients"
|
|
(pr-str [(js/parseInt only-one-client)])))
|
|
{:db (cond-> (-> db
|
|
(assoc :clients (by :id clients) )
|
|
(assoc :is-initial-loading? false)
|
|
(assoc :client (or only-one-client
|
|
(->> clients
|
|
(map :id)
|
|
(filter #(= % (:last-client-id db)))
|
|
first))))
|
|
only-one-client (assoc :last-client-id only-one-client
|
|
:selected-clients [only-one-client]))
|
|
:interval {:action :start
|
|
:id :refresh-clients
|
|
:frequency 600000
|
|
:event [::refresh-clients]}})))
|
|
|
|
(re-frame/reg-event-fx
|
|
::refresh-clients
|
|
(fn [{:keys [db]}]
|
|
(let [token (-> db :user)]
|
|
{:graphql {:token token
|
|
:query-obj {:venia/queries [[:client (client-query)]]}
|
|
:on-success [::received-refreshed-clients]}})))
|
|
|
|
(re-frame/reg-event-fx
|
|
::received-refreshed-clients
|
|
(fn [{:keys [db]} [_ {clients :client}]]
|
|
{:db (assoc db :clients (by :id clients))}))
|
|
|
|
(re-frame/reg-event-db
|
|
::failed-initial
|
|
(fn [db [_ e]]
|
|
(assoc db :initial-error e
|
|
|
|
:is-initial-loading? false
|
|
:active-route :initial-error)))
|
|
|
|
(re-frame/reg-event-fx
|
|
::swapped-client
|
|
(fn [{:keys [db]} [_ client client-identifier]]
|
|
(when (:id client)
|
|
(.setItem js/localStorage "last-client-id" (:id client)))
|
|
(.setItem js/localStorage "last-selected-clients"
|
|
(condp = client-identifier
|
|
:all
|
|
:all
|
|
|
|
:mine
|
|
:mine
|
|
|
|
(pr-str [(js/parseInt (:id client))])))
|
|
|
|
{:db (assoc db :client (:id client)
|
|
:selected-clients
|
|
(condp = client-identifier
|
|
:all
|
|
:all
|
|
|
|
:mine
|
|
:mine
|
|
|
|
[(js/parseInt (:id client))]))}))
|
|
|
|
(re-frame/reg-event-fx
|
|
::swap-client
|
|
[with-user]
|
|
(fn [{:keys [db user]} [_ client]]
|
|
(let [client-identifier (or (:id client) client)]
|
|
|
|
{:http {:token user
|
|
:method :put
|
|
:uri (str (bidi/path-for ssr-routes/only-routes
|
|
:active-client
|
|
:request-method :put)
|
|
"?"
|
|
(url/map->query {:search-client client-identifier}))
|
|
:on-success [::swapped-client client client-identifier]}})))
|
|
|
|
(re-frame/reg-event-fx
|
|
::set-active-route
|
|
(fn [{:keys [db]} [_ handler params route-params]]
|
|
(cond
|
|
(and (not= :login handler) (not (:user db)))
|
|
{:redirect (bidi/path-for routes/routes :login)
|
|
:db (assoc db :active-route :login
|
|
:active-page :login
|
|
:menu nil
|
|
:page-failure nil)}
|
|
|
|
(and (not= "admin" (:user/role (parse-jwt (:user db))))
|
|
(str/includes? (name handler) "admin"))
|
|
{:redirect (bidi/path-for routes/routes :index)
|
|
:db (assoc db :active-route :index
|
|
:active-page :index
|
|
:menu nil
|
|
:page-failure nil)}
|
|
:else
|
|
{:db (-> db
|
|
(assoc :active-route handler
|
|
:auto-ap.views.components.modal/state nil
|
|
:page-failure nil
|
|
:menu nil
|
|
:query-params params
|
|
:route-params route-params)
|
|
(data-page/dispose-all))})))
|
|
|
|
|
|
(re-frame/reg-event-fx
|
|
::logout
|
|
(fn [{:keys [db]} [_ logout-reason]]
|
|
{:db (assoc db :user nil :menu {:client {:active? false}
|
|
:account {:active? false}}
|
|
:logout-reason logout-reason)
|
|
:redirect (bidi/path-for routes/routes :login)
|
|
:set-local-storage ["jwt" nil]}))
|
|
|
|
|
|
(re-frame/reg-event-db
|
|
::yodlee-merchants-received
|
|
(fn [db [_ data]]
|
|
(assoc db :yodlee-merchants (:yodlee-merchants data))))
|
|
|
|
(re-frame/reg-event-fx
|
|
::yodlee-merchants-needed
|
|
(fn [{:keys [db]} _]
|
|
{:graphql {:token (:user db)
|
|
:query-obj {:venia/queries [[:yodlee-merchants
|
|
[:name :yodlee-id :id]]]}
|
|
:on-success [::yodlee-merchants-received]}}))
|
|
|
|
(re-frame/reg-event-fx
|
|
::vendor-preferences-requested
|
|
[with-user]
|
|
(fn [{:keys [user]} [_ {:keys [ client-id vendor-id on-success on-failure owns-state]}]]
|
|
{:graphql {:token user
|
|
:query-obj {:venia/queries [[:vendor-by-id
|
|
{:id vendor-id}
|
|
[[:automatically-paid-when-due [:id]]
|
|
[:schedule-payment-dom [[:client [:id]] :dom]]
|
|
[:default-account [:id]]]]
|
|
[:account-for-vendor
|
|
{:vendor-id vendor-id
|
|
:client-id client-id}
|
|
[:name :id :numeric-code :location]]]}
|
|
:owns-state owns-state
|
|
:on-success (fn [r]
|
|
(let [schedule-payment-dom (->> r
|
|
:vendor-by-id
|
|
:schedule-payment-dom
|
|
(filter (fn [spd]
|
|
(= (-> spd :client :id)
|
|
client-id)))
|
|
first
|
|
:dom)
|
|
automatically-paid-when-due (boolean ((->> r :vendor-by-id :automatically-paid-when-due (map :id) set) client-id))]
|
|
(conj on-success {:default-account (:account-for-vendor r)
|
|
:schedule-payment-dom schedule-payment-dom
|
|
:automatically-paid-when-due automatically-paid-when-due
|
|
:vendor-autopay? (or automatically-paid-when-due (boolean schedule-payment-dom))})))
|
|
:on-failure on-failure}}))
|