(ns auto-ap.ssr.company.yodlee (:require [auto-ap.datomic :refer [add-sorter-fields apply-pagination apply-sort-3 conn merge-query pull-attr pull-many query2]] [auto-ap.graphql.utils :refer [assert-can-see-client is-admin?]] [auto-ap.ssr-routes :as ssr-routes] [auto-ap.ssr.components :as com] [auto-ap.ssr.grid-page-helper :as helper] [auto-ap.ssr.svg :as svg] [auto-ap.ssr.utils :refer [html-response modal-response]] [auto-ap.time :as atime] [auto-ap.yodlee.core2 :as yodlee] [bidi.bidi :as bidi] [config.core :refer [env]] [datomic.api :as dc] [hiccup2.core :as hiccup])) (def default-read '[:db/id [:yodlee-provider-account/last-updated :xform clj-time.coerce/from-date] :yodlee-provider-account/status :yodlee-provider-account/id :yodlee-provider-account/detailed-status {:yodlee-provider-account/accounts [:yodlee-account/name :yodlee-account/number] :yodlee-provider-account/client [:client/code]}]) (defn fetch-ids [db request] (let [query-params (:parsed-query-params request)] (->> (cond-> {:query {:find [] :in ['$ '[?xx ...]] :where ['[?e :yodlee-provider-account/id] '[?e :yodlee-provider-account/client ?xx]]} :args [db (:trimmed-clients request)]} (:sort query-params) (add-sorter-fields {"status" ['[?e :yodlee-provider-account/status ?sort-status]] "last-updated" ['[?e :yodlee-provider-account/last-updated ?sort-last-updated]]} query-params) true (merge-query {:query {:find ['?e ] :where ['[?e :yodlee-provider-account/id]]}})) (query2) (apply-sort-3 query-params) (apply-pagination query-params)))) (defn hydrate-results [ids db _] (let [results (->> (pull-many db default-read ids) (group-by :db/id))] (->> ids (map results) (map first)))) (defn fetch-page [request] (let [db (dc/db conn) {ids-to-retrieve :ids matching-count :count} (fetch-ids db request)] [(->> (hydrate-results ids-to-retrieve db request)) matching-count])) (defn fastlink-dialog [{:keys [client]}] (modal-response (com/modal {} (com/modal-card {} [:div.flex [:div.p-2 "Yodlee Fastlink"] ] [:div [:div#fa-spot] [:script {:lang "text/javascript"} (hiccup/raw (format " fastlink.open({fastLinkURL: '%s', accessToken: '%s', params: {'configName': 'Aggregation'}, onError: function(e) { console.log(e); htmx.trigger(\"#yodlee-table\", \"notification\", {value: \"Yodlee returned the following error: '\" + e.message + \"'.\\n\\nYou may want to refresh your browser and try again.\"}); setTimeout(hideModal, 300); }}, 'fa-spot'); " (:yodlee2-fastlink env) (yodlee/get-access-token (:client/code client))))] ] [:div])))) (defn reauthenticate [{:keys [form-params identity]}] (assert-can-see-client identity (-> (dc/pull (dc/db conn) '[{:yodlee-provider-account/client [:db/id]}] (Long/parseLong (get form-params "id"))) :yodlee-provider-account/client :db/id)) (html-response (com/modal {} (com/modal-card {} [:div.flex [:div.p-2 "Yodlee Fastlink"] ] [:div [:div#fa-spot] [:script {:lang "text/javascript"} (hiccup/raw (format " fastlink.open({fastLinkURL: '%s', accessToken: '%s', params: {'configName': 'Aggregation', 'providerAccountId': %d, 'flow': 'edit'}}, 'fa-spot'); " (:yodlee2-fastlink env) (yodlee/get-access-token (-> (dc/pull (dc/db conn) [{:yodlee-provider-account/client [:client/code]}] (Long/parseLong (get form-params "id"))) :yodlee-provider-account/client :client/code)) (pull-attr (dc/db conn) :yodlee-provider-account/id (Long/parseLong (get form-params "id")))))]] [:div])))) (def grid-page (helper/build {:id "yodlee-table" :nav com/company-aside-nav :id-fn :db/id :fetch-page fetch-page :breadcrumbs [[:a {:href (bidi/path-for ssr-routes/only-routes :company)} "My Company"] [:a {:href (bidi/path-for ssr-routes/only-routes :company-yodlee)} "Yodlee"]] :title "Yodlee Accounts" :entity-name "Yodlee accounts" :route :company-yodlee-table :action-buttons (fn [request] [[:div.flex.flex-col.flex-shrink [:div.flex-shrink (com/button {:color :primary :on-click "openFastlink()" :disabled (if (:client request) false true) :hx-get (bidi/path-for ssr-routes/only-routes :company-yodlee-fastlink-dialog) :hx-target "#modal-holder"} (com/button-icon {} svg/refresh) "Link new account")] (when-not (:client request) [:div.text-xs "Note: please select a specific customer to link a new account."])]]) :row-buttons (fn [request _] [ (com/button {:hx-put (bidi/path-for ssr-routes/only-routes :company-yodlee-provider-account-reauthenticate) :color :primary :hx-target "#modal-holder"} "Reauthenticate") (when (is-admin? (:identity request)) (com/icon-button {:hx-put (bidi/path-for ssr-routes/only-routes :company-yodlee-provider-account-refresh) :hx-target "closest tr"} svg/refresh))]) :headers [{:key "client" :name "Client" :sort-key "client" :hide? (fn [args] (= (count (:clients args)) 1)) :render #(-> % :yodlee-provider-account/client :client/code)} {:key "provider-account" :name "Provider Account" :sort-key "provider-account" :render :yodlee-provider-account/id} {:key "status" :name "Status" :sort-key "status" :render #(when-let [status (:yodlee-provider-account/status %)] (com/pill {:color (if (not= status "SUCCESS") :yellow :primary) } status))} {:key "detailed-status" :name "Detailed Status" :sort-key "detailed-status" :render #(when-let [status (:yodlee-provider-account/detailed-status %)] status)} {:key "last-updated" :name "Last Updated" :sort-key "last-updated" :render #(atime/unparse-local (:yodlee-provider-account/last-updated %) atime/normal-date)} {:key "accounts" :name "Accounts" :show-starting "md" :render (fn [e] [:ul (for [a (:yodlee-provider-account/accounts e)] [:li (:yodlee-account/name a) " - " (:yodlee-account/number a)])])}]})) (def page (helper/page-route grid-page)) (def table (helper/table-route grid-page)) (defn refresh-provider-account [{:keys [form-params identity]}] (let [provider-account (dc/pull (dc/db conn) default-read (some-> (get form-params "id") not-empty Long/parseLong))] (yodlee/refresh-provider-account (:client/code (:yodlee-provider-account/client provider-account)) (:yodlee-provider-account/id provider-account)) (html-response (helper/row* grid-page identity provider-account {:flash? true}))))