(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]] [bidi.bidi :as bidi] [clojure.string :as str] [goog.crypt.base64 :as b64] [re-frame.core :as re-frame])) (defn jwt->data [token] (js->clj (.parse js/JSON (b64/decodeString (second (str/split token #"\." )))))) (defn client-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 [: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 [: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)))] (cond (= :login handler) {:db (assoc db/default-db :active-route :login :last-client-id (.getItem js/localStorage "last-client-id") :user nil)} (and (not= :login handler) (not token)) {:redirect "/login" :db (assoc db/default-db :active-route :login :last-client-id (.getItem js/localStorage "last-client-id") :user token)} (and token (= "none" (or (get (jwt->data token) "role") (get (jwt->data token) "user/role")) )) {:redirect "/needs-activation" :db (assoc db/default-db :active-route :needs-activation :last-client-id (.getItem js/localStorage "last-client-id") :user token)} :else {:db (assoc db/default-db :active-route handler :is-initial-loading? true :last-client-id (.getItem js/localStorage "last-client-id") :query-params (auto-ap.views.utils/query-params) :user token) :graphql {:token token :query-obj {:venia/queries [[:client (client-query token)]]} :on-success [::received-initial] :on-error [::failed-initial]}})))) (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}]] {:db (-> db (assoc :clients (by :id clients) ) (assoc :is-initial-loading? false) (assoc :client (or (when (= 1 (count clients)) (->> clients first :id )) (->> clients (map :id) (filter #(= % (:last-client-id db))) first)))) :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 token)]]} :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-db ::swap-client (fn [db [_ client]] (.setItem js/localStorage "last-client-id" (:id client)) (assoc db :client (:id client)))) (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 :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}}))