plaid
This commit is contained in:
71
src/clj/auto_ap/plaid/core.clj
Normal file
71
src/clj/auto_ap/plaid/core.clj
Normal file
@@ -0,0 +1,71 @@
|
||||
(ns auto-ap.plaid.core
|
||||
(:require [auto-ap.datomic :refer [conn remove-nils]]
|
||||
[amazonica.aws.s3 :as s3]
|
||||
[auto-ap.utils :refer [by]]
|
||||
[clj-http.client :as client]
|
||||
[clj-time.coerce :as coerce]
|
||||
[clj-time.core :as time]
|
||||
[clj-time.format :as f]
|
||||
[config.core :refer [env] :as cfg ]
|
||||
[clojure.string :as str]
|
||||
[clojure.data.json :as json]
|
||||
[clojure.java.io :as io]
|
||||
[clojure.tools.logging :as log]
|
||||
[datomic.api :as d]
|
||||
[mount.core :as mount]
|
||||
[unilog.context :as lc]
|
||||
[yang.scheduler :as scheduler]
|
||||
[clojure.core.async :as async]
|
||||
[clojure.core.memoize :as m]))
|
||||
|
||||
(def base-url (-> env :plaid :base-url))
|
||||
|
||||
(def client-id (-> env :plaid :client-id))
|
||||
(def secret-key (-> env :plaid :secret-key))
|
||||
|
||||
|
||||
(defn get-link-token [client-code]
|
||||
(-> (client/post (str base-url "/link/token/create")
|
||||
{:as :json
|
||||
:headers {"Content-Type" "application/json"}
|
||||
:body (json/write-str {"client_id" client-id
|
||||
"secret" secret-key
|
||||
"client_name" "Integreat Consulting"
|
||||
"country_codes" ["US"]
|
||||
"language" "en"
|
||||
"user" {"client_user_id" client-code}
|
||||
"products" ["auth" "transactions"]})})
|
||||
:body
|
||||
:link_token))
|
||||
|
||||
(defn exchange-public-token [public-token client-code]
|
||||
(-> (client/post (str base-url "/item/public_token/exchange")
|
||||
{:as :json
|
||||
:headers {"Content-Type" "application/json"}
|
||||
:body (json/write-str {"client_id" client-id
|
||||
"secret" secret-key
|
||||
"public_token" public-token})})
|
||||
:body
|
||||
(doto println)))
|
||||
|
||||
(defn get-accounts [access-token ]
|
||||
(-> (client/post (str base-url "/accounts/get")
|
||||
{:as :json
|
||||
:headers {"Content-Type" "application/json"}
|
||||
:body (json/write-str {"client_id" client-id
|
||||
"secret" secret-key
|
||||
"access_token" access-token})})
|
||||
:body))
|
||||
|
||||
(defn get-transactions [access-token account-id start end]
|
||||
(-> (client/post (str base-url "/transactions/get")
|
||||
{:as :json
|
||||
:headers {"Content-Type" "application/json"}
|
||||
:body (json/write-str {"client_id" client-id
|
||||
"secret" secret-key
|
||||
"access_token" access-token
|
||||
"start_date" (auto-ap.time/unparse start auto-ap.time/iso-date)
|
||||
"end_date" (auto-ap.time/unparse end auto-ap.time/iso-date)
|
||||
"options" {"account_ids" [account-id]}})})
|
||||
:body))
|
||||
|
||||
70
src/clj/auto_ap/plaid/import.clj
Normal file
70
src/clj/auto_ap/plaid/import.clj
Normal file
@@ -0,0 +1,70 @@
|
||||
(ns auto-ap.plaid.import
|
||||
(:require
|
||||
[auto-ap.datomic :refer [conn]]
|
||||
[auto-ap.plaid.core :as p]
|
||||
[auto-ap.utils :refer [allow-once]]
|
||||
[auto-ap.yodlee.import :as y]
|
||||
[clj-time.core :as time]
|
||||
[clojure.tools.logging :as log]
|
||||
[datomic.api :as d]
|
||||
[mount.core :as mount]
|
||||
[unilog.context :as lc]
|
||||
[yang.scheduler :as scheduler]))
|
||||
|
||||
(defn get-plaid-accounts [db]
|
||||
(-> (d/q '[:find ?ba ?external-id ?t
|
||||
:in $
|
||||
:where
|
||||
[?c :client/bank-accounts ?ba]
|
||||
[?ba :bank-account/plaid-account ?pa]
|
||||
[?pa :plaid-account/external-id ?external-id]
|
||||
[?pi :plaid-item/accounts ?pa]
|
||||
[?pi :plaid-item/access-token ?t]]
|
||||
db )))
|
||||
|
||||
(defn import-plaid
|
||||
[]
|
||||
(lc/with-context {:source "Importing plaid transactions"}
|
||||
(let [db (d/db conn)
|
||||
import-id (y/start-import :import-source/plaid "Automated Plaid User")]
|
||||
(try
|
||||
(let [result (->>
|
||||
(for [[bank-account external-id access-token] (get-plaid-accounts db)
|
||||
:let [end (auto-ap.time/local-now)
|
||||
start (time/plus end (time/days -30))
|
||||
_ (log/infof "importing from %s to %s for %s" start end external-id)
|
||||
transactions (p/get-transactions access-token external-id start end)
|
||||
_ (clojure.pprint/pprint transactions)
|
||||
transactions (->> transactions
|
||||
:transactions
|
||||
(filter (fn [t]
|
||||
(not (:pending t))))
|
||||
(mapv (fn [t]
|
||||
{:description {:original (:name t)
|
||||
:simple (:name t)}
|
||||
:id (:transaction_id t)
|
||||
:amount {:amount (:amount t)}
|
||||
:date (:date t)
|
||||
:status "POSTED"}))
|
||||
)]]
|
||||
|
||||
|
||||
(y/import-for-bank-account transactions bank-account import-id))
|
||||
y/aggregate-results)]
|
||||
(log/info "Plaid transactions imported" result)
|
||||
(y/finish-import (assoc result :db/id import-id)))
|
||||
(catch Exception e
|
||||
(log/error e)
|
||||
(y/finish-import {:db/id import-id}))))))
|
||||
|
||||
(defn do-import []
|
||||
(import-plaid))
|
||||
|
||||
(def do-import (allow-once do-import))
|
||||
|
||||
(mount/defstate import-worker
|
||||
:start (scheduler/every (* 1000 60 60 3) do-import)
|
||||
:stop (scheduler/stop import-worker))
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user