Files
integreat/src/cljs/auto_ap/events.cljs

277 lines
10 KiB
Clojure

(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 :locked-until
[: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
[:yodlee-account [:name :id :number]]
[:plaid-account [:name :id :number]]
[:intuit-bank-account [:name :id :external-id]]
: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 [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]}}))