(ns auto-ap.events (:require [re-frame.core :as re-frame] [auto-ap.db :as db] [auto-ap.subs :as subs] [auto-ap.routes :as routes] [auto-ap.effects :as effects] [auto-ap.utils :refer [by]] [venia.core :as v] [bidi.bidi :as bidi] [cemerick.url :refer [url]] [goog.crypt.base64 :as b64] [clojure.string :as str])) (defn jwt->data [token] (js->clj (.parse js/JSON (b64/decodeString (second (str/split token #"\." )))))) (def vendor-query [:id :name :hidden :terms [:default-account [:name :id :location]] [:account-overrides [[:client [:id :name]] :id [:account [:id :numeric-code :name]]]] [:automatically-paid-when-due [:id :name]] [:terms-overrides [[:client [:id :name]] :id :terms]] [:schedule-payment-dom [[:client [:id :name]] :id :dom]] [:usage [:client-id :count]] [:primary-contact [:name :phone :email :id]] [:secondary-contact [:id :name :phone :email]] :print-as :invoice-reminder-schedule :code :legal-entity-first-name :legal-entity-middle-name :legal-entity-last-name :legal-entity-tin :legal-entity-tin-type :legal-entity-1099-type [:address [:street1 :street2 :city :state :zip]]]) (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 [: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 [:yodlee-account [:name :id :number]] :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")) ) (conj [:yodlee-provider-accounts [:id [:accounts [:id :name :number :available-balance]]]]))) (re-frame/reg-event-fx ::initialize-db (fn [{:keys [db]} [_ token]] (let [handler (:handler (bidi/match-route routes/routes (.. js/window -location -pathname)))] (cond (= :login handler) {:db (assoc db/default-db :active-page :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-page :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-page :needs-activation :last-client-id (.getItem js/localStorage "last-client-id") :user token)} :else {:db (assoc db/default-db :active-page 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)] [:vendor vendor-query] [:accounts [:numeric-code :location :name :type :account_set :applicability :id [:client-overrides [:name :id [:client [:name :id]]]]]]]} :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 ::logged-in (fn [{:keys [db]} [_ token user]] {:graphql {:token token :query-obj {:venia/queries [[:client (client-query token)] [:vendor vendor-query] [:accounts [:numeric-code :name :location :type :account_set :applicability :id [:client-overrides [:name [:client [:name :id]]]]]]]} :on-success [::received-initial] :on-error [::failed-initial]} :db (assoc db :user (assoc user :token token) :is-initial-loading? true)})) (re-frame/reg-event-fx ::received-initial (fn [{:keys [db]} [_ {accounts :accounts clients :client vendors :vendor :as x}]] {:db (-> db (assoc :clients (by :id clients) ) (assoc :vendors (by :id vendors) ) (assoc :is-initial-loading? false) (assoc :accounts accounts ) (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-page :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-db ::change-form (fn [db [_ location field value]] (if value (assoc-in db (into location field) value) (update-in db (into location (butlast field)) dissoc (last field))))) (re-frame/reg-event-fx ::set-active-page (fn [{:keys [db]} [_ handler params]] (if (and (not= :login handler) (not (:user db))) {:redirect "/login" :db (assoc db :active-page :login :page-failure nil :auto-ap.forms/forms nil)} {:db (-> db (assoc :active-page handler :page-failure nil :query-params params :auto-ap.forms/forms nil) (auto-ap.views.pages.data-page/dispose-all))}))) (re-frame/reg-event-db ::imported-invoices (fn [db [_ new-invoices]] (assoc-in db [:invoices :pending] new-invoices))) (re-frame/reg-event-fx ::view-pending-invoices (fn [cofx []] {:db (assoc-in (:db cofx) [:status :loading] true) :graphql {:token (-> cofx :db :user) :query-obj {:venia/queries [[:invoice {:imported false :client_id (:id @(re-frame/subscribe [::subs/client]))} [:id :total :invoice-number :date [:vendor [:name :id]] [:client [:name :id]]]]]} :on-success [::received-invoices :pending]}})) (re-frame/reg-event-fx ::view-unpaid-invoices (fn [cofx []] {:db (assoc-in (:db cofx) [:status :loading] true) :graphql {:token (-> cofx :db :user) :query-obj {:venia/queries [[:invoice {:imported true :client_id (:id @(re-frame/subscribe [::subs/client]))} [:id :total :invoice-number :date [:vendor [:name :id]] [:client [:name :id]]]]]} :on-success [::received-invoices :unpaid]}})) (re-frame/reg-event-db ::submitted-new-invoice (fn [db [_ invoice]] (assoc db :new-invoice {}))) (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-fx ::submit-new-invoice (fn [{:keys [db]} [_ invoice]] {:http {:method :post :token (-> db :user) :uri "/api/invoices" :body (pr-str {:rows [(assoc invoice :imported true)]}) :headers {"Content-Type" "application/edn"} :on-success [::submitted-new-invoice]} :db (assoc-in db [:new-invoice :loading?] true)})) (re-frame/reg-event-db ::received-invoices (fn [db [_ type result]] (let [new-invoices (if (:invoice result) (:invoice result) result)] (-> db (assoc-in [:invoices type] new-invoices) (assoc-in [:status :loading] false))))) (re-frame/reg-event-db ::change-form-state (fn [db [_ target value]] (assoc-in db target value))) (re-frame/reg-event-db ::change-nested-form-state (fn [db [_ form more value]] (update-in db form (fn [x] (assoc-in x more value))))) (re-frame/reg-event-db ::page-failed (fn [db [_ result]] (println "Page failure" result) (assoc db :page-failure result :status 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]}}))