A bunch of bug fixes.
This commit is contained in:
@@ -11,8 +11,8 @@
|
|||||||
:yodlee-cobrand-name "restserver"
|
:yodlee-cobrand-name "restserver"
|
||||||
:yodlee-cobrand-login "sbCobda48aa19712a83c3ca4e935dd5e5d46b1a"
|
:yodlee-cobrand-login "sbCobda48aa19712a83c3ca4e935dd5e5d46b1a"
|
||||||
:yodlee-cobrand-password "0a07ea32-1b5d-461b-ad0f-2752cdd77602"
|
:yodlee-cobrand-password "0a07ea32-1b5d-461b-ad0f-2752cdd77602"
|
||||||
:yodlee-user-login "sbMemda48aa19712a83c3ca4e935dd5e5d46b1a2"
|
:yodlee-user-login "sbMemda48aa19712a83c3ca4e935dd5e5d46b1a4"
|
||||||
:yodlee-user-password "sbMemda48aa19712a83c3ca4e935dd5e5d46b1a2#123"
|
:yodlee-user-password "sbMemda48aa19712a83c3ca4e935dd5e5d46b1a4#123"
|
||||||
:yodlee-base-url "https://developer.api.yodlee.com/ysl"
|
:yodlee-base-url "https://developer.api.yodlee.com/ysl"
|
||||||
:yodlee-app "10003600"
|
:yodlee-app "10003600"
|
||||||
:yodlee-fastlink "https://node.developer.yodlee.com/authenticate/restserver/?channelAppName=restserver"
|
:yodlee-fastlink "https://node.developer.yodlee.com/authenticate/restserver/?channelAppName=restserver"
|
||||||
|
|||||||
@@ -164,3 +164,26 @@
|
|||||||
#_(process-all)
|
#_(process-all)
|
||||||
|
|
||||||
#_(reset! break true)
|
#_(reset! break true)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(defn keep-up-to-date []
|
||||||
|
(while (and (not @break)
|
||||||
|
(not (Thread/interrupted)))
|
||||||
|
(try
|
||||||
|
@(d/transact
|
||||||
|
(d/connect uri)
|
||||||
|
(mapv
|
||||||
|
#(auto-ap.ledger/entity-change->ledger (d/db (d/connect uri)) [:transaction %])
|
||||||
|
(concat
|
||||||
|
(->>
|
||||||
|
(d/query {:query {:find ['?t ]
|
||||||
|
:in ['$]
|
||||||
|
:where ['[?t :transaction/date]
|
||||||
|
'(not [?t :transaction/approval-status :transaction-approval-status/excluded])
|
||||||
|
'(not-join [?t] [?e :journal-entry/original-entity ?t])]}
|
||||||
|
:args [(d/db (d/connect uri))]})
|
||||||
|
(map first)))))
|
||||||
|
(Thread/sleep 60000)
|
||||||
|
(catch Exception e
|
||||||
|
(println (.toString e))))))
|
||||||
|
|||||||
@@ -58,6 +58,32 @@
|
|||||||
:headers {"Content-Type" "application/edn"}
|
:headers {"Content-Type" "application/edn"}
|
||||||
:body (pr-str {:message (.getMessage e)
|
:body (pr-str {:message (.getMessage e)
|
||||||
:error (.toString e)})})))
|
:error (.toString e)})})))
|
||||||
|
(POST "/provider-accounts/refresh/:id" {:keys [query-params identity] {:keys [id]} :route-params :as request}
|
||||||
|
(assert-admin identity)
|
||||||
|
(try
|
||||||
|
(let [[session token] (yodlee/get-access-token)]
|
||||||
|
(yodlee/refresh-provider-account (Long/parseLong id))
|
||||||
|
{:status 200
|
||||||
|
:headers {"Content-Type" "application/edn"}
|
||||||
|
:body (pr-str @yodlee/in-memory-cache) })
|
||||||
|
(catch Exception e
|
||||||
|
{:status 400
|
||||||
|
:headers {"Content-Type" "application/edn"}
|
||||||
|
:body (pr-str {:message (.getMessage e)
|
||||||
|
:error (.toString e)})})))
|
||||||
|
(POST "/provider-accounts/delete/:id" {:keys [query-params identity] {:keys [id]} :route-params :as request}
|
||||||
|
(assert-admin identity)
|
||||||
|
(try
|
||||||
|
(let [[session token] (yodlee/get-access-token)]
|
||||||
|
(yodlee/delete-provider-account (Long/parseLong id))
|
||||||
|
{:status 200
|
||||||
|
:headers {"Content-Type" "application/edn"}
|
||||||
|
:body (pr-str @yodlee/in-memory-cache) })
|
||||||
|
(catch Exception e
|
||||||
|
{:status 400
|
||||||
|
:headers {"Content-Type" "application/edn"}
|
||||||
|
:body (pr-str {:message (.getMessage e)
|
||||||
|
:error (.toString e)})})))
|
||||||
(POST "/provider-accounts/:id" {:keys [query-params identity] {:keys [id]} :route-params :as request}
|
(POST "/provider-accounts/:id" {:keys [query-params identity] {:keys [id]} :route-params :as request}
|
||||||
(assert-admin identity)
|
(assert-admin identity)
|
||||||
(try
|
(try
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
(ns auto-ap.server
|
(ns auto-ap.server
|
||||||
(:require #_[auto-ap.background.mail :refer [always-process-sqs]]
|
(:require #_[auto-ap.background.mail :refer [always-process-sqs]]
|
||||||
[auto-ap.handler :refer [app]]
|
[auto-ap.handler :refer [app]]
|
||||||
[auto-ap.ledger :refer [process-all]]
|
[auto-ap.ledger :refer [process-all keep-up-to-date]]
|
||||||
[auto-ap.yodlee.core :refer [load-in-memory-cache]]
|
[auto-ap.yodlee.core :refer [load-in-memory-cache]]
|
||||||
[nrepl.server :refer [start-server stop-server]]
|
[nrepl.server :refer [start-server stop-server]]
|
||||||
[config.core :refer [env]]
|
[config.core :refer [env]]
|
||||||
@@ -17,5 +17,6 @@
|
|||||||
(let [port (Integer/parseInt (or (env :port) "3000"))]
|
(let [port (Integer/parseInt (or (env :port) "3000"))]
|
||||||
(future (process-all))
|
(future (process-all))
|
||||||
(future (load-in-memory-cache))
|
(future (load-in-memory-cache))
|
||||||
|
(future (keep-up-to-date))
|
||||||
#_(future (always-process-sqs))
|
#_(future (always-process-sqs))
|
||||||
(run-jetty app {:port port :join? false})))
|
(run-jetty app {:port port :join? false})))
|
||||||
|
|||||||
@@ -52,6 +52,15 @@
|
|||||||
:body
|
:body
|
||||||
:account)))
|
:account)))
|
||||||
|
|
||||||
|
(defn get-accounts-for-provider-account [provider-account-id]
|
||||||
|
(let [cob-session (login-cobrand)
|
||||||
|
user-session (login-user cob-session)]
|
||||||
|
(-> (str (:yodlee-base-url env) "/accounts?providerAccountId=" provider-account-id)
|
||||||
|
(client/get {:headers (merge base-headers {"Authorization" (auth-header cob-session user-session)})
|
||||||
|
:as :json})
|
||||||
|
:body
|
||||||
|
:account)))
|
||||||
|
|
||||||
(defn get-account [i]
|
(defn get-account [i]
|
||||||
(let [cob-session (login-cobrand)
|
(let [cob-session (login-cobrand)
|
||||||
user-session (login-user cob-session)]
|
user-session (login-user cob-session)]
|
||||||
@@ -252,7 +261,7 @@
|
|||||||
(future
|
(future
|
||||||
(loop []
|
(loop []
|
||||||
(try
|
(try
|
||||||
(reset! in-memory-cache (get-provider-accounts-with-accounts))
|
(reset! in-memory-cache (get-provider-accounts-with-accounts))
|
||||||
(catch Exception e
|
(catch Exception e
|
||||||
(println e)))
|
(println e)))
|
||||||
(Thread/sleep (* 30 1000 5))
|
(Thread/sleep (* 30 1000 5))
|
||||||
@@ -260,10 +269,29 @@
|
|||||||
(recur)))))
|
(recur)))))
|
||||||
|
|
||||||
(defn refresh-provider-account [id]
|
(defn refresh-provider-account [id]
|
||||||
(swap! in-memory-cache
|
(swap! in-memory-cache
|
||||||
(fn [i]
|
(fn [i]
|
||||||
(-> (by :id i)
|
(-> (by :id i)
|
||||||
(update id merge (get-provider-account-detail id))
|
(assoc id (assoc (get-provider-account-detail id)
|
||||||
|
:accounts (get-accounts-for-provider-account id)))
|
||||||
|
vals))))
|
||||||
|
|
||||||
|
(defn delete-provider-account [id]
|
||||||
|
(let [cob-session (login-cobrand)
|
||||||
|
user-session (login-user cob-session)
|
||||||
|
batch-size 100]
|
||||||
|
|
||||||
|
(-> (str (:yodlee-base-url env) "/providerAccounts/" id )
|
||||||
|
|
||||||
|
(client/delete {:headers (merge base-headers {"Authorization" (auth-header cob-session user-session)})
|
||||||
|
:as :json})
|
||||||
|
:body
|
||||||
|
:providerAccount
|
||||||
|
first))
|
||||||
|
(swap! in-memory-cache
|
||||||
|
(fn [i]
|
||||||
|
(-> (by :id i)
|
||||||
|
(dissoc id)
|
||||||
vals))))
|
vals))))
|
||||||
|
|
||||||
(defn update-yodlee [id]
|
(defn update-yodlee [id]
|
||||||
|
|||||||
@@ -287,7 +287,7 @@
|
|||||||
'[?e :transaction/client ?c]
|
'[?e :transaction/client ?c]
|
||||||
'[?c :client/code ?client-code]
|
'[?c :client/code ?client-code]
|
||||||
]}
|
]}
|
||||||
:args [(d/db (d/connect uri)) client-code]})
|
:args [(d/db (d/connect uri)) client-code]})
|
||||||
(mapcat
|
(mapcat
|
||||||
(fn [[{:transaction/keys [accounts]}]]
|
(fn [[{:transaction/keys [accounts]}]]
|
||||||
(mapv
|
(mapv
|
||||||
@@ -300,3 +300,48 @@
|
|||||||
)
|
)
|
||||||
vec))
|
vec))
|
||||||
|
|
||||||
|
(defn patch-missing-ledger-entries []
|
||||||
|
@(d/transact
|
||||||
|
(d/connect uri)
|
||||||
|
(mapv
|
||||||
|
#(auto-ap.ledger/entity-change->ledger (d/db (d/connect uri)) [:transaction %])
|
||||||
|
(concat
|
||||||
|
(->>
|
||||||
|
(d/query {:query {:find ['?t ]
|
||||||
|
:in ['$]
|
||||||
|
:where ['[?t :transaction/date]
|
||||||
|
'(not [?t :transaction/approval-status :transaction-approval-status/excluded])
|
||||||
|
'(not-join [?t] [?e :journal-entry/original-entity ?t])]}
|
||||||
|
:args [(d/db (d/connect uri))]})
|
||||||
|
(map first))))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(defn check-for-out-of-date-ledger [?code]
|
||||||
|
[(d/query {:query {:find ['(count ?e)]
|
||||||
|
:in ['$ '?code]
|
||||||
|
:where ['[?e :transaction/accounts ?ta]
|
||||||
|
'[?e :transaction/matched-rule]
|
||||||
|
'[?e :transaction/approval-status :transaction-approval-status/approved]
|
||||||
|
'(not [?ta :transaction-account/location])
|
||||||
|
'[?e :transaction/client ?c]
|
||||||
|
'[?c :client/code ?code]
|
||||||
|
]}
|
||||||
|
:args [(d/db (d/connect uri)) ?code]})
|
||||||
|
|
||||||
|
(d/query {:query {:find ['?t ]
|
||||||
|
:in ['$]
|
||||||
|
:where ['[?t :transaction/date]
|
||||||
|
'(not [?t :transaction/approval-status :transaction-approval-status/excluded])
|
||||||
|
'(not-join [?t] [?e :journal-entry/original-entity ?t])]}
|
||||||
|
:args [(d/db (d/connect uri))]})
|
||||||
|
|
||||||
|
(d/query {:query {:find ['?t ]
|
||||||
|
:in ['$]
|
||||||
|
:where ['[?t :transaction/date]
|
||||||
|
'(not [?t :transaction/approval-status :transaction-approval-status/excluded])
|
||||||
|
'[?t :transaction/vendor ?v]
|
||||||
|
'[?j :journal-entry/original-entity ?t]
|
||||||
|
'(not [?j :journal-entry/vendor ?v])
|
||||||
|
#_'(not-join [?t] [?e :journal-entry/original-entity ?t])]}
|
||||||
|
:args [(d/db (d/connect uri))]})])
|
||||||
|
|||||||
@@ -54,3 +54,16 @@
|
|||||||
[:div.notification.is-info warning]]]
|
[:div.notification.is-info warning]]]
|
||||||
(into (r/children (r/current-component)))
|
(into (r/children (r/current-component)))
|
||||||
(into [(when saving? [:div.is-overlay {:style {"backgroundColor" "rgba(150,150,150, 0.5)"}}])]))])))
|
(into [(when saving? [:div.is-overlay {:style {"backgroundColor" "rgba(150,150,150, 0.5)"}}])]))])))
|
||||||
|
|
||||||
|
|
||||||
|
(defn simple-modal [{:keys [title foot class warning action-text id save-event can-submit? status-from] :or {can-submit? true}} & rest]
|
||||||
|
(let [{:keys [visible? saving? error-message]} @(re-frame/subscribe [::subs/modal-state id status-from])]
|
||||||
|
(when visible?
|
||||||
|
(-> [modal {:title [:span title]
|
||||||
|
:class class
|
||||||
|
:foot foot
|
||||||
|
:id id
|
||||||
|
:hide-event [::events/modal-status id {:visible? false :error-message nil}]}]
|
||||||
|
(into (r/children (r/current-component)))
|
||||||
|
(into [(when saving? [:div.is-overlay {:style {"backgroundColor" "rgba(150,150,150, 0.5)"}}])])))))
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
(ns auto-ap.views.pages.admin.yodlee
|
(ns auto-ap.views.pages.admin.yodlee
|
||||||
(:require-macros [cljs.core.async.macros :refer [go]])
|
(:require-macros [cljs.core.async.macros :refer [go]]
|
||||||
|
)
|
||||||
(:require [re-frame.core :as re-frame]
|
(:require [re-frame.core :as re-frame]
|
||||||
[auto-ap.forms :as forms]
|
[auto-ap.forms :as forms]
|
||||||
[reagent.core :as reagent]
|
[reagent.core :as reagent]
|
||||||
@@ -7,13 +8,13 @@
|
|||||||
[cljs-time.format :as f]
|
[cljs-time.format :as f]
|
||||||
[cljs-time.core :as time]
|
[cljs-time.core :as time]
|
||||||
[auto-ap.subs :as subs]
|
[auto-ap.subs :as subs]
|
||||||
[auto-ap.events.admin.clients :as events]
|
[auto-ap.events :as events]
|
||||||
[auto-ap.entities.clients :as entity]
|
[auto-ap.entities.clients :as entity]
|
||||||
[auto-ap.views.components.layouts :refer [side-bar-layout]]
|
[auto-ap.views.components.layouts :refer [side-bar-layout]]
|
||||||
[auto-ap.views.components.admin.side-bar :refer [admin-side-bar]]
|
[auto-ap.views.components.admin.side-bar :refer [admin-side-bar]]
|
||||||
[auto-ap.views.components.address :refer [address-field]]
|
[auto-ap.views.components.address :refer [address-field]]
|
||||||
[auto-ap.views.utils :refer [login-url dispatch-event dispatch-value-change bind-field horizontal-field str->date date->str with-user]]
|
[auto-ap.views.utils :refer [login-url dispatch-event dispatch-value-change bind-field horizontal-field str->date date->str with-user]]
|
||||||
[auto-ap.views.components.modal :refer [action-modal]]
|
[auto-ap.views.components.modal :refer [simple-modal modal]]
|
||||||
[cljs.reader :as edn]
|
[cljs.reader :as edn]
|
||||||
[auto-ap.routes :as routes]
|
[auto-ap.routes :as routes]
|
||||||
[bidi.bidi :as bidi]))
|
[bidi.bidi :as bidi]))
|
||||||
@@ -224,20 +225,91 @@
|
|||||||
:on-success [::authenticated]
|
:on-success [::authenticated]
|
||||||
:on-error [::forms/save-error [::mfa-form provider-account-id] ]}}))
|
:on-error [::forms/save-error [::mfa-form provider-account-id] ]}}))
|
||||||
|
|
||||||
|
(re-frame/reg-event-fx
|
||||||
|
::provider-account-refreshed
|
||||||
|
(fn [{:keys [db]} [_ i result]]
|
||||||
|
|
||||||
|
{:db (assoc-in db [::provider-accounts] result)
|
||||||
|
:dispatch [::forms/form-closing [::refresh-provider-account i]]}))
|
||||||
|
|
||||||
|
(re-frame/reg-event-fx
|
||||||
|
::refresh-provider-account
|
||||||
|
[with-user ]
|
||||||
|
(fn [{:keys [user db]} [_ provider-account-id ]]
|
||||||
|
{:db (forms/loading db [::refresh-provider-account provider-account-id])
|
||||||
|
:http {:token user
|
||||||
|
:method :post
|
||||||
|
:headers {"Content-Type" "application/edn"}
|
||||||
|
:uri (str "/api/yodlee/provider-accounts/refresh/" provider-account-id )
|
||||||
|
:body {}
|
||||||
|
:on-success [::provider-account-refreshed provider-account-id]
|
||||||
|
:on-error [::forms/save-error [::refresh-provider-account provider-account-id] ]}}))
|
||||||
|
|
||||||
|
(re-frame/reg-event-fx
|
||||||
|
::provider-account-deleted
|
||||||
|
(fn [{:keys [db]} [_ i result]]
|
||||||
|
|
||||||
|
{:db (assoc-in db [::provider-accounts] result)
|
||||||
|
:dispatch [::forms/form-closing [::refresh-provider-account i]]}))
|
||||||
|
|
||||||
|
(re-frame/reg-event-fx
|
||||||
|
::delete-provider-account
|
||||||
|
[with-user ]
|
||||||
|
(fn [{:keys [user db]} [_ provider-account-id ]]
|
||||||
|
{:db (forms/loading db [::delete-provider-account provider-account-id])
|
||||||
|
:dispatch (dispatch-event [::events/modal-status [::delete provider-account-id] {:visible? false}] )
|
||||||
|
:http {:token user
|
||||||
|
:method :post
|
||||||
|
:headers {"Content-Type" "application/edn"}
|
||||||
|
:uri (str "/api/yodlee/provider-accounts/delete/" provider-account-id )
|
||||||
|
:body {}
|
||||||
|
:on-success [::provider-account-deleted provider-account-id]
|
||||||
|
:on-error [::forms/save-error [::delete-provider-account provider-account-id] ]}}))
|
||||||
|
|
||||||
|
|
||||||
|
(defn delete-button [account-id]
|
||||||
|
(let [confirmed? (reagent/atom false)]
|
||||||
|
(fn []
|
||||||
|
(let [delete-form @(re-frame/subscribe [::forms/form [::delete-provider-account account-id]])]
|
||||||
|
[:div
|
||||||
|
(cond
|
||||||
|
(= :loading (:status delete-form)) [:button.button.is-disabled.is-loading [:i.fa.fa-times]]
|
||||||
|
(:error delete-form) [:button.button.is-disabled [:span.icon [:i.fa.fa-exclamation-triangle]]]
|
||||||
|
:else
|
||||||
|
[:button.button
|
||||||
|
{:on-click (dispatch-event [::events/modal-status [::delete account-id] {:visible? true}])}
|
||||||
|
[:span.icon [:i.fa.fa-times]]])
|
||||||
|
[simple-modal {:id [::delete account-id]
|
||||||
|
:title "Confirmation"
|
||||||
|
:foot [:div
|
||||||
|
[:button.button.is-danger {:on-click (dispatch-event [::delete-provider-account account-id] )} "Delete provider account"]
|
||||||
|
[:button.button {:on-click (dispatch-event [::events/modal-status [::delete account-id] {:visible? false}] )}"Cancel"]]}
|
||||||
|
"Are you sure you want to delete provider account " account-id "?"]]))))
|
||||||
|
|
||||||
(defn yodlee-provider-accounts-table []
|
(defn yodlee-provider-accounts-table []
|
||||||
|
|
||||||
(if @(re-frame/subscribe [::provider-accounts-loading?])
|
(if @(re-frame/subscribe [::provider-accounts-loading?])
|
||||||
[:div "Loading..."]
|
[:div "Loading..."]
|
||||||
[:div.columns
|
[:div.columns
|
||||||
[:div.column.is-three-quarters
|
[:div.column.is-half
|
||||||
(doall
|
(doall
|
||||||
(for [account @(re-frame/subscribe [::provider-accounts])]
|
(for [account @(re-frame/subscribe [::provider-accounts])
|
||||||
|
:let [{:keys [error status] :as g} @(re-frame/subscribe [::forms/form [::refresh-provider-account (:id account)]])]]
|
||||||
|
|
||||||
^{:key (:id account)}
|
^{:key (:id account)}
|
||||||
[:div.card {:style {:margin-bottom "1em"}}
|
[:div.card {:style {:margin-bottom "1em"}}
|
||||||
[:div.card-header
|
[:div.card-header
|
||||||
[:div.card-header-title "Provider account " (:id account)
|
[:div.card-header-title "Provider account " (:id account)]
|
||||||
]]
|
[:div.card-header-icon
|
||||||
|
[delete-button (:id account)]]
|
||||||
|
[:div.card-header-icon
|
||||||
|
(cond
|
||||||
|
(= :loading status) [:button.button.is-disabled.is-loading [:i.fa.fa-refresh]]
|
||||||
|
error [:button.button.is-disabled [:span.icon [:i.fa.fa-exclamation-triangle]]]
|
||||||
|
:else
|
||||||
|
[:button.button
|
||||||
|
{:on-click (dispatch-event [::refresh-provider-account (:id account)])}
|
||||||
|
[:span.icon [:i.fa.fa-refresh]]])]]
|
||||||
[:div.card-content
|
[:div.card-content
|
||||||
|
|
||||||
(if (> (some-> (-> account :dataset first :lastUpdated)
|
(if (> (some-> (-> account :dataset first :lastUpdated)
|
||||||
@@ -255,7 +327,7 @@
|
|||||||
", and last attempted "
|
", and last attempted "
|
||||||
(yodlee-date->str (-> account :dataset first :lastUpdateAttempt))
|
(yodlee-date->str (-> account :dataset first :lastUpdateAttempt))
|
||||||
"."]]]
|
"."]]]
|
||||||
[:div.level-right [:button.button.is-success {:on-click (dispatch-event [::kick (:id account)] )} "Force refresh" ]]]
|
[:div.level-right [:button.button.is-success {:on-click (dispatch-event [::kick (:id account)] )} "Sync yodlee with bank" ]]]
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -275,7 +347,7 @@
|
|||||||
change-event [::forms/change [::mfa-form (:id account)]]
|
change-event [::forms/change [::mfa-form (:id account)]]
|
||||||
{:keys [form-inline field field-holder raw-field error-notification submit-button]} (forms/vertical-form {:can-submit [::can-submit]
|
{:keys [form-inline field field-holder raw-field error-notification submit-button]} (forms/vertical-form {:can-submit [::can-submit]
|
||||||
:change-event change-event
|
:change-event change-event
|
||||||
:submit-event [::reauthenticate-mfa (:id account)]
|
:submit-event [::reauthenticate-mfa (:id account)]
|
||||||
:id [::mfa-form (:id account)]} )]
|
:id [::mfa-form (:id account)]} )]
|
||||||
(form-inline {:title "Reauthenticate"}
|
(form-inline {:title "Reauthenticate"}
|
||||||
[:<>
|
[:<>
|
||||||
|
|||||||
Reference in New Issue
Block a user