Revamps all of the IOL's routing, so that the new history page can share with the rest.

This commit is contained in:
2023-01-12 16:56:40 -08:00
parent ce01a63797
commit 46dd191391
29 changed files with 1294 additions and 1053 deletions

View File

@@ -1,11 +1,11 @@
(ns auto-ap.routes.auth
(:require [auto-ap.datomic.users :as users]
[buddy.sign.jwt :as jwt]
[clj-http.client :as http]
[clj-time.core :as time]
[compojure.core :refer [GET defroutes]]
[config.core :refer [env]]
[clojure.tools.logging :as log]))
(:require
[auto-ap.datomic.users :as users]
[buddy.sign.jwt :as jwt]
[clj-http.client :as http]
[clj-time.core :as time]
[clojure.tools.logging :as log]
[config.core :refer [env]]))
(def google-client-id "264081895820-0nndcfo3pbtqf30sro82vgq5r27h8736.apps.googleusercontent.com")
(def google-client-secret "OC-WemHurPXYpuIw5cT-B90g")
@@ -19,48 +19,50 @@
(:jwt-secret env)
{:alg :hs512}))
(defroutes routes
(GET "/oauth" {{:strs [code]} :query-params {:strs [host]} :headers}
(try
(let [auth (-> "https://accounts.google.com/o/oauth2/token"
(http/post
{:form-params {"client_id" google-client-id
"client_secret" google-client-secret
"code" code
"redirect_uri" (str (:scheme env) "://" host "/api/oauth")
"grant_type" "authorization_code"}
:as :json})
:body)
token (:access_token auth)
profile (-> (http/get "https://www.googleapis.com/oauth2/v1/userinfo"
{:headers {"Authorization" (str "Bearer " token)} :as :json})
:body)
user (users/find-or-insert! {:user/provider "google"
:user/provider-id (:id profile)
:user/role :user-role/none
:user/name (:name profile)})
auth {:user (:name profile)
:exp (time/plus (time/now) (time/days 30))
:user/clients (map (fn [c]
(select-keys c [:client/code :db/id :client/name :client/locations]))
(:user/clients user))
:user/role (name (:user/role user))
:user/name (:name profile)}
]
(log/info "authenticated as user" user)
;; TODO - these namespaces are not being transmitted/deserialized properly
(if (and token user)
(let [jwt (jwt/sign auth
(:jwt-secret env)
{:alg :hs512})]
{:status 301
:headers {"Location" (str "/?jwt=" jwt)}
:session {:identity (dissoc auth :exp)}})
{:status 401
:body "Couldn't authenticate"}))
(catch Exception e
(log/warn e )
{:status 401
:body (str "Couldn't authenticate " (.toString e))}))))
(defn oauth [{{:strs [code]} :query-params {:strs [host]} :headers}]
(try
(let [auth (-> "https://accounts.google.com/o/oauth2/token"
(http/post
{:form-params {"client_id" google-client-id
"client_secret" google-client-secret
"code" code
"redirect_uri" (str (:scheme env) "://" host "/api/oauth")
"grant_type" "authorization_code"}
:as :json})
:body)
token (:access_token auth)
profile (-> (http/get "https://www.googleapis.com/oauth2/v1/userinfo"
{:headers {"Authorization" (str "Bearer " token)} :as :json})
:body)
user (users/find-or-insert! {:user/provider "google"
:user/provider-id (:id profile)
:user/role :user-role/none
:user/name (:name profile)})
auth {:user (:name profile)
:exp (time/plus (time/now) (time/days 30))
:user/clients (map (fn [c]
(select-keys c [:client/code :db/id :client/name :client/locations]))
(:user/clients user))
:user/role (name (:user/role user))
:user/name (:name profile)}
]
(log/info "authenticated as user" user)
;; TODO - these namespaces are not being transmitted/deserialized properly
(if (and token user)
(let [jwt (jwt/sign auth
(:jwt-secret env)
{:alg :hs512})]
{:status 301
:headers {"Location" (str "/?jwt=" jwt)}
:session {:identity (dissoc auth :exp)}})
{:status 401
:body "Couldn't authenticate"}))
(catch Exception e
(log/warn e )
{:status 401
:body (str "Couldn't authenticate " (.toString e))})))
(def routes {"api" {"/oauth" :oauth}})
(def match->handler {:oauth oauth})

View File

@@ -11,13 +11,13 @@
[auto-ap.routes.utils :refer [wrap-secure]]
[auto-ap.time :as atime]
[buddy.sign.jwt :as jwt]
[cheshire.generate :as generate]
[clj-time.coerce :as coerce :refer [to-date]]
[clj-time.core :as time]
[clojure.data.csv :as csv]
[clojure.edn :refer [read-string]]
[clojure.tools.logging :as log]
[com.unbounce.dogstatsd.core :as statsd]
[compojure.core :refer [context defroutes GET routes wrap-routes]]
[config.core :refer [env]]
[datomic.api :as d]
[ring.middleware.json :refer [wrap-json-response]]
@@ -30,25 +30,25 @@
(csv/write-csv w %)
(.toString w))))))
(def api-key-authed-routes
(context "/" []
(GET "/sales/aggregated/export" {:keys [query-params]}
(let [client-id (Long/parseLong (get query-params "client-id"))
identity (jwt/unsign (get query-params "key") (:jwt-secret env) {:alg :hs512})]
(assert-can-see-client identity client-id)
(into (list)
(d/query {:query {:find '[?d4 (sum ?total) (sum ?tax) (sum ?tip) (sum ?service-charge)]
:in '[$ ?c]
:where '[[?s :sales-order/client ?c]
[?s :sales-order/date ?d]
[?s :sales-order/total ?total]
[?s :sales-order/tax ?tax]
[?s :sales-order/tip ?tip]
[?s :sales-order/service-charge ?service-charge]
[(clj-time.coerce/to-date-time ?d) ?d2]
[(auto-ap.time/localize ?d2) ?d3]
[(auto-ap.time/unparse ?d3 auto-ap.time/normal-date) ?d4]]}
:args [(d/db conn) client-id]}))))))
(defn aggregated-sales-export [{:keys [query-params]}]
(let [client-id (Long/parseLong (get query-params "client-id"))
identity (jwt/unsign (get query-params "key") (:jwt-secret env) {:alg :hs512})]
(assert-can-see-client identity client-id)
(into (list)
(d/query {:query {:find '[?d4 (sum ?total) (sum ?tax) (sum ?tip) (sum ?service-charge)]
:in '[$ ?c]
:where '[[?s :sales-order/client ?c]
[?s :sales-order/date ?d]
[?s :sales-order/total ?total]
[?s :sales-order/tax ?tax]
[?s :sales-order/tip ?tip]
[?s :sales-order/service-charge ?service-charge]
[(clj-time.coerce/to-date-time ?d) ?d2]
[(auto-ap.time/localize ?d2) ?d3]
[(auto-ap.time/unparse ?d3 auto-ap.time/normal-date) ?d4]]}
:args [(d/db conn) client-id]}))))
(defn client-tag [params]
(when-let [code (or (params "client-code")
@@ -82,332 +82,366 @@
]))
m))
(def admin-only-routes
(context "/" []
(GET "/invoices/export" {:keys [query-params identity]}
(assert-admin identity)
(statsd/time! [(str "export.time") {:tags #{(client-tag query-params)
"export:invoice"}}]
(list (into (list)
(map datomic-map->graphql-map)
(d/q '[:find [(pull ?i [:db/id :invoice/total :invoice/outstanding-balance :invoice/invoice-number :invoice/date :invoice/original-id
{ :invoice/status [:db/ident]
:invoice/payments
[:invoice-payment/amount
{:invoice-payment/payment [:payment/check-number
:payment/memo
{:payment/bank_account [:bank-account/id :bank-account/name :bank-account/number :bank-account/bank-name :bank-account/bank-code :bank-account/code]}]}]
:invoice/vendor [:vendor/name
:db/id
{:vendor/primary-contact [:contact/name]
:vendor/address [:address/street1 :address/city :address/state :address/zip]}]
:invoice/expense-accounts [:db/id
:invoice-expense-account/amount
:invoice-expense-account/id
:invoice-expense-account/location
{:invoice-expense-account/account
[:db/id :account/numeric-code :account/name]}]
:invoice/client [:client/name :db/id :client/code :client/locations]}]) ...]
:in $ ?c
:where [?i :invoice/client ?c]]
(d/db conn)
[:client/code (query-params "client-code")])))))
(GET "/payments/export" {:keys [query-params identity]}
(assert-admin identity)
(statsd/time! [(str "export.time") {:tags #{(client-tag query-params)
"export:payment"}}]
(let [query [[:all_payments
{:client-code (query-params "client-code")
:original-id (query-params "original")}
[:id :check-number :amount :memo :date :status :type :original-id
[:invoices [[:invoice [:id :original-id]] :amount]]
[:bank-account [:number :code :bank-name :bank-code :id]]
[:vendor [:name :id [:primary-contact [:name :email :phone]] [:default-account [:name :numeric-code :id]] [:address [:street1 :city :state :zip]]]]
[:client [:id :name :code]]
]]]
payments (graphql/query identity (venia/graphql-query {:venia/queries (->graphql query)}))]
(list (:all-payments (:data payments))))))
(defn export-invoices [{:keys [query-params identity]}]
(assert-admin identity)
(statsd/time! [(str "export.time") {:tags #{(client-tag query-params)
"export:invoice"}}]
{:body
(list (into (list)
(map datomic-map->graphql-map)
(d/q '[:find [(pull ?i [:db/id :invoice/total :invoice/outstanding-balance :invoice/invoice-number :invoice/date :invoice/original-id
{ :invoice/status [:db/ident]
:invoice/payments
[:invoice-payment/amount
{:invoice-payment/payment [:payment/check-number
:payment/memo
{:payment/bank_account [:bank-account/id :bank-account/name :bank-account/number :bank-account/bank-name :bank-account/bank-code :bank-account/code]}]}]
:invoice/vendor [:vendor/name
:db/id
{:vendor/primary-contact [:contact/name]
:vendor/address [:address/street1 :address/city :address/state :address/zip]}]
:invoice/expense-accounts [:db/id
:invoice-expense-account/amount
:invoice-expense-account/id
:invoice-expense-account/location
{:invoice-expense-account/account
[:db/id :account/numeric-code :account/name]}]
:invoice/client [:client/name :db/id :client/code :client/locations]}]) ...]
:in $ ?c
:where [?i :invoice/client ?c]]
(d/db conn)
[:client/code (query-params "client-code")])))}))
(GET "/sales/export" {:keys [query-params identity]}
(assert-admin identity)
(statsd/time! [(str "export.time") {:tags #{(client-tag query-params)
"export:sales"}}]
(let [query [[:all_sales_orders
(cond-> {:client-code (query-params "client-code")}
(query-params "after") (assoc :date-range {:start (query-params "after")
:end nil}))
[:id
:location
:external_id
:total
:tip
:tax
:discount
:returns
:service_charge
:date
[:charges [:type_name :total :tip]]
[:line_items [:item_name :total :tax :discount :category]]
[:client [:id :name :code]]]]]
payments (graphql/query identity (venia/graphql-query {:venia/queries (->graphql query)}))
parsedouble #(some-> % Double/parseDouble) ]
(seq (map
(fn [s]
(-> s
(assoc :utc_date (:date s))
(update :date (fn [d]
(coerce/to-string (coerce/to-local-date-time (time/to-time-zone (coerce/to-date-time d) (time/time-zone-for-id "America/Los_Angeles"))))))
(update :total parsedouble)
(update :tax parsedouble)
(update :discount parsedouble)
(update :tip parsedouble)
(update :line-items (fn [lis]
(map
(fn [li]
(-> li
(update :tax parsedouble)
(update :discount parsedouble)
(update :total parsedouble)))
lis)))
(update :charges (fn [charges]
(map
(fn [charge]
(-> charge
(update :tip parsedouble)
(update :total parsedouble)))
charges)))))
(:all-sales-orders (:data payments))))))
)
(GET "/expected-deposit/export" {:keys [query-params identity]}
(assert-admin identity)
(statsd/time! [(str "export.time") {:tags #{(client-tag query-params)
"export:deposit"}}]
(let [query [[:all_expected_deposits
(cond-> {:client-code (query-params "client-code")}
(query-params "after") (assoc :date-range {:start (query-params "after")
:end nil}))
[:id
[:client [:id :name :code]]
:location
:external_id
:total
:fee
:date]]]
payments (graphql/query identity (venia/graphql-query {:venia/queries (->graphql query)}))]
(seq (map
(fn [d]
(-> d
(update :fee #(some-> % Double/parseDouble))
(update :total #(some-> % Double/parseDouble))))
(:all-expected-deposits (:data payments)))))))
(GET "/clients/export" {:keys [identity]}
(assert-admin identity)
(map <-graphql (d-clients/get-all)))
(GET "/vendors/export" {:keys [identity]}
(assert-admin identity)
(statsd/time! [(str "export.time") {:tags #{"export:vendors"}}]
(map <-graphql (->> (d/q '[:find [?e ...]
:in $
:where [?e :vendor/name]]
(d/db conn))
(d/pull-many (d/db conn) vendor/default-read)))))
(GET "/vendors/company/export" {:keys [identity query-params]}
(statsd/time! [(str "export.time") {:tags #{"export:company-vendors"}}]
(let [client (:db/id (d/pull (d/db conn) [:db/id] [:client/code (get query-params "client")]))
_ (assert-can-see-client identity client)
data (->> (d/q '[:find (pull ?v [:vendor/name
:vendor/terms
{:vendor/default-account [:account/name :account/numeric-code
{:account/client-overrides
[:account-client-override/client
:account-client-override/name]}]
:vendor/terms-overrides [:vendor-terms-override/client
:vendor-terms-override/terms]
:vendor/account-overrides [:vendor-account-override/client
{:vendor-account-override/account [:account/numeric-code :account/name
{:account/client-overrides
[:account-client-override/client
:account-client-override/name]}]}]
:vendor/address [:address/street1 :address/city :address/state :address/zip]}])
:in $ ?c
:where [?vu :vendor-usage/client ?c]
[?vu :vendor-usage/count ?count]
[(>= ?vu 0)]
[?vu :vendor-usage/vendor ?v]
(not [?v :vendor/hidden true])]
(d/db conn)
client)
(map (fn [[v]]
[(-> v :vendor/name)
(-> v :vendor/address :address/street1)
(-> v :vendor/address :address/city)
(-> v :vendor/address :address/state)
(-> v :vendor/address :address/zip)
(-> v (vendor/terms-for-client-id client) )
(-> v (vendor/account-for-client-id client) (accounts/clientize client) :account/name)
(-> v (vendor/account-for-client-id client) :account/numeric-code)
]
))
(into [["Vendor Name" "Address" "City" "State" "Zip" "Terms" "Account" "Account Code"]]))]
{:body
(with-open [w (java.io.StringWriter.)]
(csv/write-csv w data
:quote? (constantly true))
(.toString w))
:headers {"Content-Type" "application/csv"}})))
(GET "/ledger/export" {:keys [identity query-params]}
(let [start-date (or (some-> (query-params "start-date")
(atime/parse atime/iso-date))
(time/plus (time/now) (time/days -120)))]
(log/info "exporting for " (query-params "client-code") "starting" start-date)
(assert-admin identity)
(statsd/time! [(str "export.time") {:tags #{(client-tag query-params)
"export:ledger2"}}]
(let [results (->> (d/q '[:find (pull ?e [:db/id
:journal-entry/external-id
:journal-entry/cleared
:journal-entry/alternate-description
:journal-entry/date
:journal-entry/note
:journal-entry/amount
:journal-entry/source
:journal-entry/cleared-against
:journal-entry/original-entity
{:journal-entry/client [:client/name :client/code :db/id]
:journal-entry/vendor [:vendor/name :db/id]
:journal-entry/line-items [:db/id
:journal-entry-line/location
:journal-entry-line/debit
:journal-entry-line/credit
{:journal-entry-line/account [:bank-account/include-in-reports
:bank-account/bank-name
:bank-account/numeric-code
:bank-account/code
:bank-account/visible
:bank-account/name
:bank-account/number
:account/code
:account/name
:account/numeric-code
:account/location
{:account/type [:db/ident :db/id]}
{:bank-account/type [:db/ident :db/id]}]}]}])
:in $ ?c ?start-date
:where [?e :journal-entry/client ?c]
[?e :journal-entry/date ?date]
[(>= ?date ?start-date)]]
(d/db conn)
[:client/code (query-params "client-code")]
(coerce/to-date start-date)))
tf-result (transduce (comp
(map first)
(filter (fn [je]
(every?
(fn [jel]
(let [include-in-reports (-> jel :journal-entry-line/account :bank-account/include-in-reports)]
(or (nil? include-in-reports)
(true? include-in-reports))))
(:journal-entry/line-items je))))
(map <-graphql))
conj
(list)
results)]
tf-result))))
(defn export-payments [{:keys [query-params identity]}]
(assert-admin identity)
(statsd/time! [(str "export.time") {:tags #{(client-tag query-params)
"export:payment"}}]
(let [query [[:all_payments
{:client-code (query-params "client-code")
:original-id (query-params "original")}
[:id :check-number :amount :memo :date :status :type :original-id
[:invoices [[:invoice [:id :original-id]] :amount]]
[:bank-account [:number :code :bank-name :bank-code :id]]
[:vendor [:name :id [:primary-contact [:name :email :phone]] [:default-account [:name :numeric-code :id]] [:address [:street1 :city :state :zip]]]]
[:client [:id :name :code]]
]]]
payments (graphql/query identity (venia/graphql-query {:venia/queries (->graphql query)}))]
{:body
(list (:all-payments (:data payments)))})))
(defn export-sales [{:keys [query-params identity]}]
(assert-admin identity)
(statsd/time! [(str "export.time") {:tags #{(client-tag query-params)
"export:sales"}}]
(let [query [[:all_sales_orders
(cond-> {:client-code (query-params "client-code")}
(query-params "after") (assoc :date-range {:start (query-params "after")
:end nil}))
[:id
:location
:external_id
:total
:tip
:tax
:discount
:returns
:service_charge
:date
[:charges [:type_name :total :tip]]
[:line_items [:item_name :total :tax :discount :category]]
[:client [:id :name :code]]]]]
payments (graphql/query identity (venia/graphql-query {:venia/queries (->graphql query)}))
parsedouble #(some-> % Double/parseDouble) ]
{:body
(seq (map
(fn [s]
(-> s
(assoc :utc_date (:date s))
(update :date (fn [d]
(coerce/to-string (coerce/to-local-date-time (time/to-time-zone (coerce/to-date-time d) (time/time-zone-for-id "America/Los_Angeles"))))))
(update :total parsedouble)
(update :tax parsedouble)
(update :discount parsedouble)
(update :tip parsedouble)
(update :line-items (fn [lis]
(map
(fn [li]
(-> li
(update :tax parsedouble)
(update :discount parsedouble)
(update :total parsedouble)))
lis)))
(update :charges (fn [charges]
(map
(fn [charge]
(-> charge
(update :tip parsedouble)
(update :total parsedouble)))
charges)))))
(:all-sales-orders (:data payments))))})))
(GET "/accounts/export" {:keys [query-params identity]}
(assert-admin identity)
(statsd/time! [(str "export.time") {:tags #{(client-tag query-params)
"export:accounts"}}]
(let [client-id (d-clients/code->id (query-params "client-code"))
query [[:all-accounts
[:id :numeric_code :type :applicability :location :name [:client_overrides [:name [:client [:id :code :name]]]]]]]
all-accounts (graphql/query identity (venia/graphql-query {:venia/queries (->graphql query)}))]
(defn export-expected-deposits [{:keys [query-params identity]}]
(assert-admin identity)
(statsd/time! [(str "export.time") {:tags #{(client-tag query-params)
"export:deposit"}}]
(let [query [[:all_expected_deposits
(cond-> {:client-code (query-params "client-code")}
(query-params "after") (assoc :date-range {:start (query-params "after")
:end nil}))
[:id
[:client [:id :name :code]]
:location
:external_id
:total
:fee
:date]]]
payments (graphql/query identity (venia/graphql-query {:venia/queries (->graphql query)}))]
{:body
(seq (map
(fn [d]
(-> d
(update :fee #(some-> % Double/parseDouble))
(update :total #(some-> % Double/parseDouble))))
(:all-expected-deposits (:data payments))))})))
(list (transduce
(comp
(filter (fn [a]
(let [overriden-clients (set (map (comp :id :client) (:client-overrides a)))]
(or (nil? (:applicability a))
(= :global (:applicability a))
(overriden-clients (str client-id))))))
(map (fn [a]
(let [client->name (reduce
(fn [override co]
(assoc override (str (:id (:client co))) (:name co)))
{}
(:client-overrides a))]
(-> a
(assoc :global-name (:name a))
(assoc :client-name (client->name (str client-id) (:name a)))
(dissoc :client-overrides))))))
conj
(list)
(:all-accounts (:data all-accounts)))))))
(GET "/transactions/export" {:keys [query-params identity]}
(assert-admin identity)
(statsd/time! [(str "export.time") {:tags #{(client-tag query-params)
"export:transactions"}}]
(let [[transactions] (d-transactions/get-graphql {:client-code (query-params "client-code")
#_#_:original-id (Integer/parseInt (query-params "original"))
:count Integer/MAX_VALUE})]
(map (comp ->graphql (fn [i]
(cond-> i
true (update :transaction/date to-date)
true (update :transaction/post-date to-date)
(:transaction/payment i) (update-in [:transaction/payment :payment/date] to-date)
(:transaction/expected-deposit i) (update-in [:transaction/expected-deposit :expected-deposit/date] to-date))))
transactions)))
)
(generate/add-encoder org.joda.time.DateTime
(fn [c jsonGenerator]
(.writeString jsonGenerator (str c))))
(GET "/transactions/export2" {:keys [query-params identity]}
(assert-admin identity)
(statsd/time! [(str "export.time") {:tags #{(client-tag query-params)
"export:transactions2"}}]
(let [db (d/db conn)]
(->>
(d/query {:query {:find ['?e]
:in ['$ '?client-code]
:where ['[?e :transaction/client ?client-code]]}
:args [db [:client/code (query-params "client-code")]]})
(map first)
(map (fn [e]
(let [e (d/entity db e)
client (:transaction/client e)
bank-account (:transaction/bank-account e)]
{:id (:db/id e)
:date (:transaction/date e)
:post_date (:transaction/post-date e)
:client { :code (:client/code client)
:id (:db/id client)
:name (:client/name client)}
:amount (:transaction/amount e)
:description_original (:transaction/description-original e)
:approval_status (:transaction/approval-status e)
:bank_account {:name (:bank-account/name bank-account)
:code (:bank-account/code bank-account)
:id (:db/id bank-account)}})))))))
(GET "/raw" {:keys [query-params identity]}
(assert-admin identity)
(log/info "Executing raw query " (get query-params "query" ))
(statsd/time! [(str "export.time") {:tags #{"export:raw"}}]
(into (list) (apply d/q (read-string (get query-params "query" )) (into [(d/db conn)] (read-string (get query-params "args" "[]")))))))))
(defn export-clients[{:keys [identity]}]
(assert-admin identity)
{:body (into []
(map <-graphql)
(d-clients/get-all))})
(defroutes export-routes
(routes
(wrap-routes api-key-authed-routes
wrap-csv-response)
(defn export-vendors [{:keys [identity]}]
(assert-admin identity)
(statsd/time! [(str "export.time") {:tags #{"export:vendors"}}]
{:body
(map <-graphql (->> (d/q '[:find [?e ...]
:in $
:where [?e :vendor/name]]
(d/db conn))
(d/pull-many (d/db conn) vendor/default-read)))}))
(wrap-routes (wrap-routes admin-only-routes wrap-secure)
wrap-json-response)))
(defn export-company-vendors [{:keys [identity query-params]}]
(statsd/time! [(str "export.time") {:tags #{"export:company-vendors"}}]
(let [client (:db/id (d/pull (d/db conn) [:db/id] [:client/code (get query-params "client")]))
_ (assert-can-see-client identity client)
data (->> (d/q '[:find (pull ?v [:vendor/name
:vendor/terms
{:vendor/default-account [:account/name :account/numeric-code
{:account/client-overrides
[:account-client-override/client
:account-client-override/name]}]
:vendor/terms-overrides [:vendor-terms-override/client
:vendor-terms-override/terms]
:vendor/account-overrides [:vendor-account-override/client
{:vendor-account-override/account [:account/numeric-code :account/name
{:account/client-overrides
[:account-client-override/client
:account-client-override/name]}]}]
:vendor/address [:address/street1 :address/city :address/state :address/zip]}])
:in $ ?c
:where [?vu :vendor-usage/client ?c]
[?vu :vendor-usage/count ?count]
[(>= ?vu 0)]
[?vu :vendor-usage/vendor ?v]
(not [?v :vendor/hidden true])]
(d/db conn)
client)
(map (fn [[v]]
[(-> v :vendor/name)
(-> v :vendor/address :address/street1)
(-> v :vendor/address :address/city)
(-> v :vendor/address :address/state)
(-> v :vendor/address :address/zip)
(-> v (vendor/terms-for-client-id client) )
(-> v (vendor/account-for-client-id client) (accounts/clientize client) :account/name)
(-> v (vendor/account-for-client-id client) :account/numeric-code)
]
))
(into [["Vendor Name" "Address" "City" "State" "Zip" "Terms" "Account" "Account Code"]]))]
{:body
(into (list)
data)})))
(defn export-ledger [{:keys [identity query-params]}]
(let [start-date (or (some-> (query-params "start-date")
(atime/parse atime/iso-date))
(time/plus (time/now) (time/days -120)))]
(log/info "exporting for " (query-params "client-code") "starting" start-date)
(assert-admin identity)
(statsd/time! [(str "export.time") {:tags #{(client-tag query-params)
"export:ledger2"}}]
(let [results (->> (d/q '[:find (pull ?e [:db/id
:journal-entry/external-id
:journal-entry/cleared
:journal-entry/alternate-description
:journal-entry/date
:journal-entry/note
:journal-entry/amount
:journal-entry/source
:journal-entry/cleared-against
:journal-entry/original-entity
{:journal-entry/client [:client/name :client/code :db/id]
:journal-entry/vendor [:vendor/name :db/id]
:journal-entry/line-items
[:db/id
:journal-entry-line/location
:journal-entry-line/debit
:journal-entry-line/credit
{:journal-entry-line/account
[:bank-account/include-in-reports
:bank-account/bank-name
:bank-account/numeric-code
:bank-account/code
:bank-account/visible
:bank-account/name
:bank-account/number
:account/code
:account/name
:account/numeric-code
:account/location
{:account/type [:db/ident :db/id]}
{:bank-account/type [:db/ident :db/id]}]}]}])
:in $ ?c ?start-date
:where [?e :journal-entry/client ?c]
[?e :journal-entry/date ?date]
[(>= ?date ?start-date)]]
(d/db conn)
[:client/code (query-params "client-code")]
(coerce/to-date start-date)))
tf-result (transduce (comp
(map first)
(filter (fn [je]
(every?
(fn [jel]
(let [include-in-reports (-> jel :journal-entry-line/account :bank-account/include-in-reports)]
(or (nil? include-in-reports)
(true? include-in-reports))))
(:journal-entry/line-items je))))
(map <-graphql))
conj
(list)
results)]
{:body
tf-result}))))
(defn export-accounts [{:keys [query-params identity]}]
(assert-admin identity)
(statsd/time! [(str "export.time") {:tags #{(client-tag query-params)
"export:accounts"}}]
(let [client-id (d-clients/code->id (query-params "client-code"))
query [[:all-accounts
[:id :numeric_code :type :applicability :location :name [:client_overrides [:name [:client [:id :code :name]]]]]]]
all-accounts (graphql/query identity (venia/graphql-query {:venia/queries (->graphql query)}))]
{:body
(list (transduce
(comp
(filter (fn [a]
(let [overriden-clients (set (map (comp :id :client) (:client-overrides a)))]
(or (nil? (:applicability a))
(= :global (:applicability a))
(overriden-clients (str client-id))))))
(map (fn [a]
(let [client->name (reduce
(fn [override co]
(assoc override (str (:id (:client co))) (:name co)))
{}
(:client-overrides a))]
(-> a
(assoc :global-name (:name a))
(assoc :client-name (client->name (str client-id) (:name a)))
(dissoc :client-overrides))))))
conj
(list)
(:all-accounts (:data all-accounts))))})))
(defn export-transactions2 [{:keys [query-params identity]}]
(assert-admin identity)
(statsd/time! [(str "export.time") {:tags #{(client-tag query-params)
"export:transactions2"}}]
{:body (let [db (d/db conn)]
(->>
(d/query {:query {:find ['?e]
:in ['$ '?client-code]
:where ['[?e :transaction/client ?client-code]]}
:args [db [:client/code (query-params "client-code")]]})
(map first)
(map (fn [e]
(let [e (d/entity db e)
client (:transaction/client e)
bank-account (:transaction/bank-account e)]
{:id (:db/id e)
:date (:transaction/date e)
:post_date (:transaction/post-date e)
:client { :code (:client/code client)
:id (:db/id client)
:name (:client/name client)}
:amount (:transaction/amount e)
:description_original (:transaction/description-original e)
:approval_status (:transaction/approval-status e)
:bank_account {:name (:bank-account/name bank-account)
:code (:bank-account/code bank-account)
:id (:db/id bank-account)}})))))}))
(defn export-transactions [{:keys [query-params identity]}]
(assert-admin identity)
(statsd/time! [(str "export.time") {:tags #{(client-tag query-params)
"export:transactions"}}]
(let [[transactions] (d-transactions/get-graphql {:client-code (query-params "client-code")
#_#_:original-id (Integer/parseInt (query-params "original"))
:count Integer/MAX_VALUE})]
{:body (map
(comp ->graphql
(fn [i]
(cond-> i
true (update :transaction/date to-date)
true (update :transaction/post-date to-date)
(:transaction/payment i) (update-in [:transaction/payment :payment/date] to-date)
(:transaction/expected-deposit i) (update-in [:transaction/expected-deposit :expected-deposit/date] to-date))))
transactions)})))
(defn export-raw [{:keys [query-params identity]}]
(assert-admin identity)
(log/info "Executing raw query " (get query-params "query" ))
(statsd/time! [(str "export.time") {:tags #{"export:raw"}}]
{:body
(into (list) (apply d/q (read-string (get query-params "query" )) (into [(d/db conn)] (read-string (get query-params "args" "[]")))))}))
(def routes2 {"api/" {"sales/" {"aggregated/" {#"export/?" {:get :aggregated-sales-export}}
#"export/?" {:get :export-sales}}
"invoices/" {#"export/?" {:get :export-invoices}}
"payments/" {#"export/?" {:get :export-payments}}
"expected-deposit/" {#"export/?" {:get :export-expected-deposits}}
"clients/" {#"export/?" {:get :export-clients}}
"vendors/" {#"export/?" {:get :export-vendors}
"/company" {#"export/?" {:get :export-company-vendors}}}
"ledger/" {#"export/?" {:get :export-ledger}}
"accounts/" {#"export/?" {:get :export-accounts}}
"transactions/" {#"export/?" {:get :export-transactions}
#"export2/?" {:get :export-transactions2}}
#"raw/?" {:get :export-raw}}})
(def match->handler {:aggregated-sales-export (wrap-csv-response aggregated-sales-export)
:export-invoices (-> export-invoices wrap-json-response wrap-secure )
:export-payments (-> export-payments wrap-json-response wrap-secure)
:export-sales (-> export-sales wrap-json-response wrap-secure)
:export-expected-deposits (-> export-expected-deposits wrap-json-response wrap-secure)
:export-clients (-> export-clients wrap-json-response wrap-secure)
:export-vendors (-> export-vendors wrap-json-response wrap-secure)
:export-company-vendors (-> export-company-vendors wrap-csv-response wrap-secure)
:export-ledger (-> export-ledger wrap-json-response wrap-secure)
:export-accounts (-> export-accounts wrap-json-response wrap-secure)
:export-transactions (-> export-transactions wrap-json-response wrap-secure)
:export-transactions2 (-> export-transactions2 wrap-json-response wrap-secure)
:export-raw (-> export-raw wrap-json-response wrap-secure)})

View File

@@ -1,23 +1,30 @@
(ns auto-ap.routes.ezcater
(:require
[clojure.tools.logging :as log]
[compojure.core :refer [context defroutes GET POST wrap-routes]]
[ring.middleware.json :refer [wrap-json-params]]
[auto-ap.ezcater.core :as e]
[ring.util.request :refer [body-string]]))
[auto-ap.logging :as alog]
[ring.middleware.json :refer [wrap-json-params]]))
(defroutes routes
(wrap-routes
(context "/ezcater" []
(GET "/event" request
(log/info (str "GET EVENT " (body-string request) request))
{:status 200
:headers {"Content-Type" "application/json"}
:body "{}"})
(POST "/event" request
(log/info (str "POST EVENT " (body-string request) request))
(e/import-order (:json-params request))
{:status 200
:headers {"Content-Type" "application/json"}
:body "{}"}))
wrap-json-params))
(defn handle-ezcater [{:keys [request-method json-params] :as r}]
(cond
(= :get request-method)
{:status 200
:headers {"Content-Type" "application/json"}
:body "{}"}
(= :post request-method)
(do
(alog/info ::ezcater-request
:json-params json-params)
(e/import-order json-params)
{:status 200
:headers {"Content-Type" "application/json"}
:body "{}"})
:else
{:status 404}))
(def routes {"api/" {"ezcater/" {#"event/?" :ezcater-event}}})
(def match->handler {:ezcater-event (-> handle-ezcater
wrap-json-params)})

View File

@@ -4,8 +4,6 @@
[auto-ap.logging :refer [warn-event]]
[buddy.auth :refer [throw-unauthorized]]
[clojure.edn :as edn]
[compojure.core :refer [GET POST context defroutes
wrap-routes]]
[clojure.tools.logging :as log]))
(defn handle-graphql [{:keys [request-method query-params] :as r}]
(when (= "none" (:user/role (:identity r)))
@@ -39,9 +37,5 @@
:headers {"Content-Type" "application/edn"}}))))))
(defroutes routes
(wrap-routes
(context "/graphql" []
(GET "/" x (handle-graphql x))
(POST "/" x (handle-graphql x)))
wrap-secure))
(def routes {"api/" {#"graphql/?" :graphql}})
(def match->handler {:graphql (wrap-secure handle-graphql)})

View File

@@ -0,0 +1,19 @@
(ns auto-ap.routes.health
(:require [mount.core :as mount]))
(def running? (atom false))
#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
(mount/defstate manage-running?
:start (reset! running? true)
:stop (reset! running? false))
(defn health-check [request]
(if @running?
{:status 200
:body "Ok"}
{:status 503
:body "Application shut down"}))
(def routes {"api/" {"health-check" :health}})
(def match->handler {:health health-check})

View File

@@ -18,7 +18,6 @@
[clojure.java.io :as io]
[clojure.string :as str]
[clojure.tools.logging :as log]
[compojure.core :refer [context defroutes POST wrap-routes]]
[config.core :refer [env]]
[datomic.api :as d]
[digest]
@@ -385,142 +384,147 @@
rows)]
(transact-with-ledger txes nil)))
(defroutes routes
(wrap-routes
(context "/" []
(context "/transactions" []
(POST "/batch-upload"
{{:keys [data]} :edn-params user :identity}
(assert-admin user)
(try
(let [stats (manual/import-batch (manual/tabulate-data data) (:user/name user))]
{:status 200
:body (pr-str stats)
:headers {"Content-Type" "application/edn"}})
(catch Exception e
(log/error e)
{:status 500
:body (pr-str {:message (.getMessage e)
:error (.toString e)
:data (ex-data e)})
:headers {"Content-Type" "application/edn"}}))))
(defn batch-upload-transactions [{{:keys [data]} :edn-params user :identity}]
(assert-admin user)
(try
(let [stats (manual/import-batch (manual/tabulate-data data) (:user/name user))]
{:status 200
:body (pr-str stats)
:headers {"Content-Type" "application/edn"}})
(catch Exception e
(log/error e)
{:status 500
:body (pr-str {:message (.getMessage e)
:error (.toString e)
:data (ex-data e)})
:headers {"Content-Type" "application/edn"}})))
(context "/invoices" []
(POST "/upload"
{{files :file
files-2 "file"
client :client
client-2 "client"
location :location
location-2 "location"
vendor :vendor
vendor-2 "vendor"} :params
user :identity}
(let [files (or files files-2)
client (or client client-2)
location (or location location-2)
vendor (some-> (or vendor vendor-2)
(Long/parseLong))
{:keys [filename tempfile]} files]
(lc/with-context {:parsing-file filename}
(log/info tempfile)
(try
(let [extension (last (str/split (.getName (io/file filename)) #"\."))
s3-location (str "invoice-files/" (str (UUID/randomUUID)) "." extension)
_ (s3/put-object (:data-bucket env)
s3-location
(io/input-stream tempfile)
{:content-type (if (= "csv" extension)
"text/csv"
"application/pdf")
:content-length (.length tempfile)})
imports (->> (parse/parse-file (.getPath tempfile) filename)
(map #(assoc %
:client-override client
:location-override location
:vendor-override vendor
:source-url (str "http://" (:data-bucket env)
".s3-website-us-east-1.amazonaws.com/"
s3-location))))]
(import-uploaded-invoice user imports))
{:status 200
:body (pr-str {})
:headers {"Content-Type" "application/edn"}}
(catch Exception e
(log/warn e)
{:status 400
:body (pr-str {:message (.getMessage e)
:error (.toString e)
:data (ex-data e)})
:headers {"Content-Type" "application/edn"}})))))
(defn upload-invoices [{{files :file
files-2 "file"
client :client
client-2 "client"
location :location
location-2 "location"
vendor :vendor
vendor-2 "vendor"} :params
user :identity}]
(let [files (or files files-2)
client (or client client-2)
location (or location location-2)
vendor (some-> (or vendor vendor-2)
(Long/parseLong))
{:keys [filename tempfile]} files]
(lc/with-context {:parsing-file filename}
(log/info tempfile)
(try
(let [extension (last (str/split (.getName (io/file filename)) #"\."))
s3-location (str "invoice-files/" (str (UUID/randomUUID)) "." extension)
_ (s3/put-object (:data-bucket env)
s3-location
(io/input-stream tempfile)
{:content-type (if (= "csv" extension)
"text/csv"
"application/pdf")
:content-length (.length tempfile)})
imports (->> (parse/parse-file (.getPath tempfile) filename)
(map #(assoc %
:client-override client
:location-override location
:vendor-override vendor
:source-url (str "http://" (:data-bucket env)
".s3-website-us-east-1.amazonaws.com/"
s3-location))))]
(import-uploaded-invoice user imports))
{:status 200
:body (pr-str {})
:headers {"Content-Type" "application/edn"}}
(catch Exception e
(log/warn e)
{:status 400
:body (pr-str {:message (.getMessage e)
:error (.toString e)
:data (ex-data e)})
:headers {"Content-Type" "application/edn"}})))))
(POST "/upload-integreat"
{{:keys [excel-rows]} :edn-params user :identity}
(assert-admin user)
(let [parsed-invoice-rows (parse-invoice-rows excel-rows)
existing-rows (set (d-invoices/get-existing-set))
grouped-rows (group-by
(fn [i]
(cond (seq (:errors i))
:error
(defn bulk-upload-invoices [{{:keys [excel-rows]} :edn-params user :identity}]
(assert-admin user)
(let [parsed-invoice-rows (parse-invoice-rows excel-rows)
existing-rows (set (d-invoices/get-existing-set))
grouped-rows (group-by
(fn [i]
(cond (seq (:errors i))
:error
(existing-rows [(:vendor-id i) (:client-id i) (:invoice-number i)])
:exists
(existing-rows [(:vendor-id i) (:client-id i) (:invoice-number i)])
:exists
:else
:new))
parsed-invoice-rows)
vendors-not-found (->> parsed-invoice-rows
(filter #(and (nil? (:vendor-id %))
(not= "Cash" (:check %))))
(map :vendor-name)
set)
_ (transact-with-ledger (invoice-rows->transaction (:new grouped-rows)
user)
user)]
{:status 200
:body (pr-str {:imported (count (:new grouped-rows))
:already-imported (count (:exists grouped-rows))
:vendors-not-found vendors-not-found
:errors (map #(dissoc % :date) (:error grouped-rows))})
:headers {"Content-Type" "application/edn"}})))
(POST "/transactions/cleared-against"
{{files :file
files-2 "file"} :params
user :identity}
(let [files (or files files-2)
{:keys [tempfile]} files]
(assert-admin user)
(try
(import-transactions-cleared-against (.getPath tempfile))
{:status 200
:body (pr-str {})
:headers {"Content-Type" "application/edn"}}
(catch Exception e
(log/error e)
{:status 500
:body (pr-str {:message (.getMessage e)
:error (.toString e)
:data (ex-data e)})
:headers {"Content-Type" "application/edn"}}))))
(wrap-json-response (POST "/account-overrides"
{{files :file
files-2 "file"
client :client
client-2 "client"} :params
user :identity}
(let [files (or files files-2)
client (or client client-2)
{:keys [tempfile]} files]
(assert-admin user)
(try
{:status 200
:body (import-account-overrides client (.getPath tempfile))
:headers {"Content-Type" "application/json"}}
(catch Exception e
(log/error e)
{:status 500
:body {:message (.getMessage e)
:data (ex-data e)}
:headers {"Content-Type" "application/json"}}))))))
wrap-secure))
:else
:new))
parsed-invoice-rows)
vendors-not-found (->> parsed-invoice-rows
(filter #(and (nil? (:vendor-id %))
(not= "Cash" (:check %))))
(map :vendor-name)
set)
_ (transact-with-ledger (invoice-rows->transaction (:new grouped-rows)
user)
user)]
{:status 200
:body (pr-str {:imported (count (:new grouped-rows))
:already-imported (count (:exists grouped-rows))
:vendors-not-found vendors-not-found
:errors (map #(dissoc % :date) (:error grouped-rows))})
:headers {"Content-Type" "application/edn"}}))
(defn cleared-against [{{files :file
files-2 "file"} :params
user :identity}]
(let [files (or files files-2)
{:keys [tempfile]} files]
(assert-admin user)
(try
(import-transactions-cleared-against (.getPath tempfile))
{:status 200
:body (pr-str {})
:headers {"Content-Type" "application/edn"}}
(catch Exception e
(log/error e)
{:status 500
:body (pr-str {:message (.getMessage e)
:error (.toString e)
:data (ex-data e)})
:headers {"Content-Type" "application/edn"}}))))
(defn bulk-account-overrides [{{files :file
files-2 "file"
client :client
client-2 "client"} :params
user :identity}]
(let [files (or files files-2)
client (or client client-2)
{:keys [tempfile]} files]
(assert-admin user)
(try
{:status 200
:body (import-account-overrides client (.getPath tempfile))
:headers {"Content-Type" "application/json"}}
(catch Exception e
(log/error e)
{:status 500
:body {:message (.getMessage e)
:data (ex-data e)}
:headers {"Content-Type" "application/json"}}))))
(def routes {"api/" {"transactions/" {:post {#"batch-upload/?" :batch-upload-transactions
#"cleared-against/?" :cleared-against}}
"invoices/" {:post {#"upload/?" :upload-invoices
#"upload-integreat/?" :bulk-upload-invoices}}
:post {#"account-overrides/?" :bulk-account-overrides}}})
(def match->handler {:batch-upload-transactions (wrap-secure batch-upload-transactions)
:upload-invoices (wrap-secure upload-invoices)
:bulk-upload-invoices (wrap-secure bulk-upload-invoices)
:cleared-against (wrap-secure cleared-against)
:bulk-account-overrides (wrap-secure (wrap-json-response bulk-account-overrides))})

View File

@@ -1,22 +1,21 @@
(ns auto-ap.routes.queries
(:require [amazonica.aws.s3 :as s3]
[auto-ap.datomic :refer [conn]]
[auto-ap.graphql.utils :refer [assert-admin]]
[clojure.data.csv :as csv]
[clojure.java.io :as io]
[clojure.string :as str]
[clojure.tools.logging :as log]
[com.unbounce.dogstatsd.core :as statsd]
[compojure.core
:refer
[context defroutes GET POST PUT routes wrap-routes]]
[config.core :refer [env]]
[clojure.edn :as edn]
[datomic.api :as d]
[ring.middleware.json :refer [wrap-json-response]]
[ring.util.request :refer [body-string]]
[unilog.context :as lc])
(:import java.util.UUID))
(:require
[amazonica.aws.s3 :as s3]
[auto-ap.datomic :refer [conn]]
[auto-ap.graphql.utils :refer [assert-admin]]
[clojure.data.csv :as csv]
[clojure.edn :as edn]
[clojure.java.io :as io]
[clojure.string :as str]
[clojure.tools.logging :as log]
[com.unbounce.dogstatsd.core :as statsd]
[config.core :refer [env]]
[datomic.api :as d]
[ring.middleware.json :refer [wrap-json-response]]
[ring.util.request :refer [body-string]]
[unilog.context :as lc])
(:import
(java.util UUID)))
(defn wrap-csv-response [handler]
(fn [request]
@@ -62,64 +61,77 @@
:csv-results-url (str "/api/queries/" guid "/results/csv")
:json-results-url (str "/api/queries/" guid "/results/json")}}))
(def json-routes
(context "/queries" []
(POST "/" {:keys [query-params identity] :as request}
(assert-admin identity)
(log/info "Note" (query-params "note"))
(put-query (str (UUID/randomUUID)) (body-string request) (query-params "note")))
(PUT "/:query-id" {:keys [query-params identity params] :as request}
(assert-admin identity)
(log/info "Note" (query-params "note"))
(put-query (:query-id params) (body-string request) (query-params "note")))
(GET "/:query-id" {:keys [identity params]}
(assert-admin identity)
(let [{:keys [query-id]} params
obj (s3/get-object :bucket-name (:data-bucket env)
:key (str "queries/" query-id))
query-string (str (slurp (:object-content obj)))]
(log/info obj)
{:body {:query query-string
:note (:note (:user-metadata (:object-metadata obj)))
:id query-id
:csv-results-url (str "/api/queries/" query-id "/results/csv")
:json-results-url (str "/api/queries/" query-id "/results/json")}}))
(GET "/" {:keys [identity]}
(assert-admin identity)
(let [obj (s3/list-objects :bucket-name (:data-bucket env)
:prefix (str "queries/"))]
(log/info obj)
{:body (->> (:object-summaries obj)
(map (fn [o]
{:last-modified (.toString (:last-modified o))
:key (str/replace (:key o) #"^queries\/" "")})))}))
(GET "/:query-id/results/json" {:keys [query-params params]}
(statsd/time! [(str "export.query.time") {:tags #{(str "query:" (:query-id params))}}]
{:body (execute-query query-params params)}))))
(def raw-routes
(context "/queries" []
(GET "/:query-id/raw" {:keys [identity params]}
(assert-admin identity)
(let [{:keys [query-id]} params
obj (s3/get-object :bucket-name (:data-bucket env)
:key (str "queries/" query-id))
query-string (str (slurp (:object-content obj)))]
(log/info obj)
{:body query-string}))))
(defn get-queries [{:keys [identity]}]
(assert-admin identity)
(let [obj (s3/list-objects :bucket-name (:data-bucket env)
:prefix (str "queries/"))]
(log/info obj)
{:body (->> (:object-summaries obj)
(map (fn [o]
{:last-modified (.toString (:last-modified o))
:key (str/replace (:key o) #"^queries\/" "")})))}))
(defn create-query [{:keys [query-params identity] :as request}]
(assert-admin identity)
(log/info "Note" (query-params "note"))
(put-query (str (UUID/randomUUID)) (body-string request) (query-params "note")))
(defn get-query [{:keys [identity params]} ]
(assert-admin identity)
(let [{:keys [query-id]} params
obj (s3/get-object :bucket-name (:data-bucket env)
:key (str "queries/" query-id))
query-string (str (slurp (:object-content obj)))]
(log/info obj)
{:body {:query query-string
:note (:note (:user-metadata (:object-metadata obj)))
:id query-id
:csv-results-url (str "/api/queries/" query-id "/results/csv")
:json-results-url (str "/api/queries/" query-id "/results/json")}}))
(defn update-query [{:keys [query-params identity params] :as request} ]
(assert-admin identity)
(log/info "Note" (query-params "note"))
(put-query (:query-id params) (body-string request) (query-params "note")))
(defn results-json-query [{:keys [query-params params]}]
(statsd/time! [(str "export.query.time") {:tags #{(str "query:" (:query-id params))}}]
{:body (execute-query query-params params)}))
(defn raw-query [{:keys [identity params]}]
(assert-admin identity)
(let [{:keys [query-id]} params
obj (s3/get-object :bucket-name (:data-bucket env)
:key (str "queries/" query-id))
query-string (str (slurp (:object-content obj)))]
(log/info obj)
{:body query-string}))
(defn results-csv-query [{:keys [query-params params]}]
(statsd/time! [(str "export.query.time") {:tags #{(str "query:" (:query-id params))}}]
{:body (execute-query query-params params)}))
(def routes2 {"api/" {#"queries/?" {[:query-id "/raw"] {:get :raw-query}
[:query-id "/results/csv"] {:get :results-csv-query}
[:query-id "/results/json"] {:get :results-json-query}
[:query-id] {:get :get-query
:put :update-query}
:get :get-queries
:post :create-query}}})
(def match->handler {:get-queries get-queries
:create-query create-query
:raw-query raw-query
:get-query (-> get-query
wrap-json-response)
:update-query (-> update-query
wrap-json-response)
:results-json-query (-> results-json-query
wrap-json-response)
:results-csv-query (-> results-csv-query
wrap-csv-response)})
(def csv-routes
(context "/queries" []
(GET "/:query-id/results/csv" {:keys [query-params params]}
(statsd/time! [(str "export.query.time") {:tags #{(str "query:" (:query-id params))}}]
{:body (execute-query query-params params)}))))
(defroutes query2-routes
(routes
raw-routes
(wrap-routes json-routes
wrap-json-response)
(wrap-routes csv-routes wrap-csv-response)))

View File

@@ -1,5 +1,8 @@
(ns auto-ap.routes.utils
(:require [buddy.auth :refer [authenticated?]]))
(:require
[auto-ap.graphql.utils :refer [is-admin?]]
[buddy.auth :refer [authenticated?]]
[auto-ap.logging :as alog]))
(defn wrap-secure [handler]
(fn [request]
@@ -7,3 +10,20 @@
(handler request)
{:status 401
:body "not authenticated"})))
(defn wrap-admin [handler]
(fn [request]
(if (is-admin? (:identity request))
(handler request)
(do
(alog/warn ::unauthenticated)
{:status 302
:headers "/login"}))))
(defn wrap-client-redirect-unauthenticated [handler]
(fn [request]
(let [response (handler request)]
(println )
(if (= 401 (get response :status))
(assoc-in response [:headers "hx-redirect"] "/login/")
response))))

View File

@@ -6,99 +6,113 @@
[auto-ap.routes.utils :refer [wrap-secure]]
[auto-ap.yodlee.core2 :as yodlee]
[clojure.tools.logging :as log]
[compojure.core :refer [context defroutes GET POST wrap-routes]]
[config.core :refer [env]]
[datomic.api :as d]))
(defroutes routes
(wrap-routes
(context "/yodlee2" []
(GET "/fastlink" {:keys [query-params identity]}
(assert-can-see-client identity (d/pull (d/db conn) [:db/id] [:client/code (get query-params "client")]))
(let [token (if-let [client-id (get query-params "client-id")]
(-> client-id
Long/parseLong
d-clients/get-by-id
:client/code
(yodlee/get-access-token))
(yodlee/get-access-token (get query-params "client")))]
{:status 200
:headers {"Content-Type" "application/edn"}
:body (pr-str {:token token
:url (:yodlee2-fastlink env)}) }))
(POST "/provider-accounts/refresh/" {:keys [identity edn-params]}
(assert-admin identity)
(log/info "refreshing " edn-params)
(try
(yodlee/refresh-provider-account (-> (:client-id edn-params)
Long/parseLong
d-clients/get-by-id
:client/code)
(:provider-account-id edn-params))
{:status 200
:headers {"Content-Type" "application/edn"}
:body "{}" }
(catch Exception e
(log/error e)
{:status 400
:headers {"Content-Type" "application/edn"}
:body (pr-str {:message (.getMessage e)
:error (.toString e)})})))
(defn fastlink [{:keys [query-params identity]}]
(assert-can-see-client identity (d/pull (d/db conn) [:db/id] [:client/code (get query-params "client")]))
(let [token (if-let [client-id (get query-params "client-id")]
(-> client-id
Long/parseLong
d-clients/get-by-id
:client/code
(yodlee/get-access-token))
(yodlee/get-access-token (get query-params "client")))]
{:status 200
:headers {"Content-Type" "application/edn"}
:body (pr-str {:token token
:url (:yodlee2-fastlink env)}) }))
(defn refresh-provider-accounts [{:keys [identity edn-params]}]
(assert-admin identity)
(log/info "refreshing " edn-params)
(try
(yodlee/refresh-provider-account (-> (:client-id edn-params)
Long/parseLong
d-clients/get-by-id
:client/code)
(:provider-account-id edn-params))
{:status 200
:headers {"Content-Type" "application/edn"}
:body "{}" }
(catch Exception e
(log/error e)
{:status 400
:headers {"Content-Type" "application/edn"}
:body (pr-str {:message (.getMessage e)
:error (.toString e)})})))
(GET "/provider-accounts/:client/:id" {:keys [identity]
{:keys [client id]} :route-params}
(assert-admin identity)
(log/info "looking-up " client id)
(try
{:status 200
:headers {"Content-Type" "application/edn"}
:body (pr-str (yodlee/get-provider-account-detail (-> client
Long/parseLong
d-clients/get-by-id
:client/code)
id))}
(catch Exception e
(log/error e)
{:status 400
:headers {"Content-Type" "application/edn"}
:body (pr-str {:message (.getMessage e)
:error (.toString e)})})))
(POST "/provider-accounts/delete/" {:keys [edn-params identity]}
(assert-admin identity)
(try
(yodlee/delete-provider-account (-> (:client-id edn-params)
Long/parseLong
d-clients/get-by-id
:client/code)
(:provider-account-id edn-params))
{:status 200
:headers {"Content-Type" "application/edn"}
:body (pr-str {}) }
(catch Exception e
(log/error e)
{:status 400
:headers {"Content-Type" "application/edn"}
:body (pr-str {:message (.getMessage e)
:error (.toString e)})})))
(POST "/reauthenticate/:id" {:keys [identity] {:keys [id]} :route-params
data :edn-params}
(assert-admin identity)
(try
{:status 200
:headers {"Content-Type" "application/edn"}
:body (pr-str (yodlee/reauthenticate-and-recache
(-> (:client-id data)
Long/parseLong
d-clients/get-by-id
:client/code)
(Long/parseLong id)
(dissoc data :client-id )))}
(catch Exception e
(log/error e)
{:status 500
:headers {"Content-Type" "application/edn"}
:body (pr-str {:message (.getMessage e)
:error (.toString e)})}))))
wrap-secure))
(defn get-provider-account-detail [{:keys [identity]
{:keys [client id]} :route-params}]
(assert-admin identity)
(log/info "looking-up " client id)
(try
{:status 200
:headers {"Content-Type" "application/edn"}
:body (pr-str (yodlee/get-provider-account-detail (-> client
Long/parseLong
d-clients/get-by-id
:client/code)
id))}
(catch Exception e
(log/error e)
{:status 400
:headers {"Content-Type" "application/edn"}
:body (pr-str {:message (.getMessage e)
:error (.toString e)})})))
(defn reauthenticate [{:keys [identity] {:keys [id]} :route-params
data :edn-params}]
(assert-admin identity)
(try
{:status 200
:headers {"Content-Type" "application/edn"}
:body (pr-str (yodlee/reauthenticate-and-recache
(-> (:client-id data)
Long/parseLong
d-clients/get-by-id
:client/code)
(Long/parseLong id)
(dissoc data :client-id )))}
(catch Exception e
(log/error e)
{:status 500
:headers {"Content-Type" "application/edn"}
:body (pr-str {:message (.getMessage e)
:error (.toString e)})})))
(defn delete-provider-account [{:keys [edn-params identity]}]
(assert-admin identity)
(try
(yodlee/delete-provider-account (-> (:client-id edn-params)
Long/parseLong
d-clients/get-by-id
:client/code)
(:provider-account-id edn-params))
{:status 200
:headers {"Content-Type" "application/edn"}
:body (pr-str {}) }
(catch Exception e
(log/error e)
{:status 400
:headers {"Content-Type" "application/edn"}
:body (pr-str {:message (.getMessage e)
:error (.toString e)})})))
(defn valid-for [handler & methods]
(let [methods (into #{} methods)]
(fn [request]
(if (methods (:request-method request))
(handler request)
{:status 404}))))
(def routes {"api" {"/yodlee2" {"/fastlink" :fastlink
"/provider-accounts/refresh/" :refresh-provider-accounts
["/provider-accounts/" :client "/" :id ] :get-provider-account-detail
["/reauthenticate/" :id ] :reauthenticate
"/provider-accounts/delete/" :delete-provider-account}}})
(def match->handler {:fastlink (-> fastlink wrap-secure (valid-for :get))
:refresh-provider-accounts (-> refresh-provider-accounts wrap-secure (valid-for :post))
:get-provider-account-detail (-> get-provider-account-detail wrap-secure (valid-for :get))
:reauthenticate (-> reauthenticate wrap-secure (valid-for :post))
:delete-provider-account (-> delete-provider-account wrap-secure (valid-for :post))} )