better health check.
This commit is contained in:
@@ -37,6 +37,12 @@
|
||||
:where ['[?e :transaction/bank-account ?bank-account-id]]}
|
||||
:args [(:bank-account-id args)]})
|
||||
|
||||
(:account-id args)
|
||||
(merge-query {:query {:in ['?account-id]
|
||||
:where ['[?e :transaction/accounts ?accounts]
|
||||
'[?accounts :transaction-account/account ?account-id]]}
|
||||
:args [(:account-id args)]})
|
||||
|
||||
(:client-id args)
|
||||
(merge-query {:query {:in ['?client-id]
|
||||
:where ['[?e :transaction/client ?client-id]]}
|
||||
|
||||
@@ -590,6 +590,7 @@
|
||||
:transaction_filters {:fields {:client_id {:type :id}
|
||||
:vendor_id {:type :id}
|
||||
:bank_account_id {:type :id}
|
||||
:account_id {:type :id}
|
||||
:date_range {:type :date_range}
|
||||
:amount_lte {:type :money}
|
||||
:amount_gte {:type :money}
|
||||
|
||||
@@ -85,8 +85,7 @@
|
||||
(when (not (get (into #{"Shared"} (:client/locations client))
|
||||
(:location a)))
|
||||
(let [err (str "Account " name " uses location " (:location a) ", but doesn't belong to the client " location)]
|
||||
(throw (ex-info err {:validation-error err}) )))
|
||||
)
|
||||
(throw (ex-info err {:validation-error err}) ))))
|
||||
rule-id (if id
|
||||
id
|
||||
"transaction-rule")
|
||||
|
||||
@@ -1,48 +1,56 @@
|
||||
(ns auto-ap.handler
|
||||
(:require [amazonica.core :refer [defcredential]]
|
||||
[auto-ap.routes.auth :as auth]
|
||||
[auto-ap.routes.clients :as clients]
|
||||
[auto-ap.routes.invoices :as invoices]
|
||||
[auto-ap.routes.reminders :as reminders]
|
||||
[auto-ap.routes.graphql :as graphql]
|
||||
[auto-ap.routes.yodlee :as yodlee]
|
||||
[auto-ap.routes.events :as events]
|
||||
[auto-ap.routes.checks :as checks]
|
||||
[auto-ap.routes.exports :as exports]
|
||||
[auto-ap.routes.graphql :as graphql]
|
||||
[auto-ap.routes.invoices :as invoices]
|
||||
[auto-ap.routes.yodlee :as yodlee]
|
||||
[buddy.auth.backends.token :refer [jws-backend]]
|
||||
[buddy.auth.middleware :refer [wrap-authentication
|
||||
wrap-authorization]]
|
||||
[clojure.java.jdbc :as jdbc]
|
||||
[buddy.auth.middleware :refer [wrap-authentication wrap-authorization]]
|
||||
[clojure.tools.logging :as log]
|
||||
[compojure.core :refer :all]
|
||||
[compojure.route :as route]
|
||||
[config.core :refer [env]]
|
||||
[clojure.tools.logging :as log]
|
||||
[unilog.context :as lc]
|
||||
[mount.core :as mount]
|
||||
[ring.middleware.edn :refer [wrap-edn-params]]
|
||||
[ring.middleware.gzip :refer [wrap-gzip]]
|
||||
[ring.middleware.multipart-params :as mp]
|
||||
[ring.middleware.params :refer [wrap-params]]
|
||||
[ring.middleware.reload :refer [wrap-reload]]
|
||||
[ring.middleware.gzip :refer [wrap-gzip]]
|
||||
[ring.util.response :as response]))
|
||||
[ring.util.response :as response]
|
||||
[unilog.context :as lc]))
|
||||
|
||||
(when (:aws-access-key-id env)
|
||||
(defcredential (:aws-access-key-id env) (:aws-secret-access-key env) (:aws-region env)))
|
||||
|
||||
(def running? (atom false))
|
||||
|
||||
(mount/defstate manage-running?
|
||||
:start (reset! running? true)
|
||||
:stop (reset! running? false))
|
||||
|
||||
(defroutes static-routes
|
||||
(GET "/" [] (response/resource-response "index.html" {:root "public"}))
|
||||
(route/resources "/")
|
||||
(routes (ANY "*" [] (response/resource-response "index.html" {:root "public"}))))
|
||||
|
||||
(defroutes health-check
|
||||
(GET "/health-check" []
|
||||
(if @running?
|
||||
{:status 200
|
||||
:body "Ok"}
|
||||
{:status 503
|
||||
:body "Application shut down"})))
|
||||
|
||||
(defroutes api-routes
|
||||
(context "/api" []
|
||||
exports/routes
|
||||
yodlee/routes
|
||||
invoices/routes
|
||||
clients/routes
|
||||
reminders/routes
|
||||
checks/routes
|
||||
graphql/routes
|
||||
auth/routes))
|
||||
auth/routes
|
||||
health-check))
|
||||
|
||||
|
||||
(def auth-backend (jws-backend {:secret (:jwt-secret env) :options {:alg :hs512}}))
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
(ns auto-ap.routes.checks
|
||||
(:require
|
||||
[hiccup.core :refer [html]]
|
||||
[auto-ap.routes.utils :refer [wrap-secure]]
|
||||
[compojure.core :refer [GET POST context defroutes wrap-routes]]))
|
||||
(defroutes routes
|
||||
(wrap-routes
|
||||
(context "/checks" [])
|
||||
wrap-secure))
|
||||
@@ -1,29 +0,0 @@
|
||||
(ns auto-ap.routes.clients
|
||||
(:require [auto-ap.datomic.clients :as clients]
|
||||
[auto-ap.graphql.utils :refer [can-see-client? assert-can-see-client]]
|
||||
[auto-ap.routes.utils :refer [wrap-secure wrap-spec]]
|
||||
[auto-ap.entities.clients :as entity]
|
||||
[compojure.core :refer [GET PUT context defroutes
|
||||
wrap-routes]]))
|
||||
|
||||
|
||||
(defroutes routes
|
||||
(wrap-routes
|
||||
(context "/clients" []
|
||||
#_(wrap-spec
|
||||
(PUT "/:id" {{:keys [address email locations new-bank-accounts]} :edn-params :keys [edn-params] {:keys [id ]} :route-params :as r}
|
||||
(assert-can-see-client (:identity r) id)
|
||||
(let [id (Integer/parseInt id)
|
||||
company (d-clients/get-by-id id)
|
||||
updated-company (merge company {:address address
|
||||
:email email
|
||||
:locations locations})]
|
||||
#_(companies/upsert id updated-company)
|
||||
#_(doseq [bank-account new-bank-accounts]
|
||||
(companies/add-bank-account id bank-account))
|
||||
|
||||
{:status 200
|
||||
:body (pr-str (clients/get-by-id id))
|
||||
:headers {"Content-Type" "application/edn"}}))
|
||||
::entity/company))
|
||||
wrap-secure))
|
||||
@@ -1,100 +0,0 @@
|
||||
(ns auto-ap.routes.reminders
|
||||
(:require
|
||||
[auto-ap.routes.utils :refer [wrap-secure]]
|
||||
[auto-ap.graphql.utils :refer [assert-admin]]
|
||||
[config.core :refer [env]]
|
||||
[clj-http.client :as http]
|
||||
[clj-time.coerce :as c]
|
||||
[clj-time.core :as time]
|
||||
[clj-time.periodic :as p]
|
||||
[clj-time.predicates :as pred]
|
||||
[clojure.data.json :as json]
|
||||
[compojure.core :refer [GET PUT POST context defroutes
|
||||
wrap-routes]])
|
||||
(:import (org.joda.time DateTime)))
|
||||
|
||||
#_(POST "/:id/remind" {:keys [edn-params] {:keys [id :<< as-int]} :route-params :as r}
|
||||
(assert-admin (:identity r))
|
||||
(let [id (if (int? id)
|
||||
id
|
||||
(Integer/parseInt id))
|
||||
vendor (vendors/get-by-id id)]
|
||||
(reminders/insert (assoc
|
||||
(reminders/template)
|
||||
:email (:primary-email vendor)
|
||||
:vendor-id id
|
||||
:scheduled (time/now)))
|
||||
(-> (reminders/get-ready)
|
||||
(reminders/send-emails))
|
||||
{:status 200
|
||||
:body "{}"
|
||||
:headers {"Content-Type" "application/edn"}}))
|
||||
#_(defn next-sunday []
|
||||
(let [sunday (->> (p/periodic-seq (time/plus (time/today) (time/days 1)) (time/days 1))
|
||||
(filter pred/sunday?)
|
||||
first)]
|
||||
(time/from-time-zone (time/date-time (time/year sunday) (time/month sunday) (time/day sunday))
|
||||
(time/time-zone-for-id "America/Los_Angeles"))))
|
||||
|
||||
#_(defn schedule-reminders []
|
||||
(let [vendors (vendors/find-with-reminders)
|
||||
future-reminders (reminders/find-future (map :id vendors))
|
||||
has-reminder-scheduled? (set (map :vendor-id future-reminders))
|
||||
vendors-without-scheduled (filter #(not (has-reminder-scheduled? (:id %))) vendors)]
|
||||
(println "Reminders already scheduled:" future-reminders)
|
||||
(println "Reminders will happen at" (next-sunday))
|
||||
(println "Reminders to schedule" vendors-without-scheduled)
|
||||
|
||||
(doseq [{:keys [id primary-email invoice-reminder-schedule]} vendors-without-scheduled]
|
||||
(reminders/insert (assoc (reminders/template)
|
||||
:vendor-id id
|
||||
:email primary-email
|
||||
:scheduled (next-sunday))))))
|
||||
|
||||
#_(defn find-ready-reminders []
|
||||
(let [vendors (vendors/get-all)
|
||||
ready-reminders (reminders/get-ready)]
|
||||
ready-reminders))
|
||||
|
||||
|
||||
|
||||
#_(defn replace-joda [x]
|
||||
(into {} (map (fn [[k v]]
|
||||
[k (if (instance? DateTime v)
|
||||
(c/to-date v)
|
||||
v)])
|
||||
x)))
|
||||
|
||||
(defroutes routes
|
||||
(context "/reminders" []
|
||||
|
||||
#_(POST "/send" {:keys [query-params headers body] :as x}
|
||||
(let [notification-type (get headers "x-amz-sns-message-type")]
|
||||
(println "Received notification " notification-type)
|
||||
(if (= "SubscriptionConfirmation" notification-type)
|
||||
(do
|
||||
(println "Responding to confirmation" )
|
||||
(let [json (json/read-str (slurp body))]
|
||||
(println json)
|
||||
(http/get (get json "SubscribeURL"))))
|
||||
(do
|
||||
(println "Scheduling")
|
||||
(schedule-reminders)
|
||||
(-> (reminders/get-ready)
|
||||
(reminders/send-emails)))))
|
||||
|
||||
{:status 200
|
||||
:body "{}"
|
||||
:headers {"Content-Type" "application/edn"}})
|
||||
#_(wrap-routes
|
||||
(PUT "/:id" {:keys [ edn-params] {:keys [id] } :route-params identity :identity}
|
||||
(assert-admin identity)
|
||||
(let [id (if (int? id)
|
||||
id
|
||||
(Integer/parseInt id))]
|
||||
(assert (not (:sent (reminders/get-by-id id))))
|
||||
(reminders/update! id edn-params)
|
||||
{:status 200
|
||||
:body "{}"
|
||||
:headers {"Content-Type" "application/edn"}}))
|
||||
wrap-secure)))
|
||||
@@ -14,14 +14,19 @@
|
||||
[mount.core :as mount])
|
||||
(:gen-class))
|
||||
|
||||
|
||||
(defn add-shutdown-hook! [^Runnable f]
|
||||
(.addShutdownHook (Runtime/getRuntime)
|
||||
(Thread. f)))
|
||||
|
||||
(mount/defstate port :start (Integer/parseInt (or (env :port) "3000")))
|
||||
(mount/defstate jetty
|
||||
:start (run-jetty app {:port port :join? false})
|
||||
:stop (.stop jetty)
|
||||
)
|
||||
:stop (.stop jetty))
|
||||
|
||||
(defn shutdown-mount []
|
||||
(mount/stop))
|
||||
|
||||
(defn -main [& args]
|
||||
(add-shutdown-hook! shutdown-mount)
|
||||
(start-server :port 9000 :bind "0.0.0.0" #_#_:handler (cider-nrepl-handler))
|
||||
(mount/start))
|
||||
|
||||
@@ -49,6 +49,17 @@
|
||||
:on-change #(re-frame/dispatch [::data-page/filter-changed data-page :bank-account %])
|
||||
:value @(re-frame/subscribe [::data-page/filter data-page :bank-account])}]]
|
||||
|
||||
|
||||
|
||||
[:p.menu-label "Financial Account"]
|
||||
[:div
|
||||
[typeahead-entity {:matches accounts
|
||||
:match->text (fn [x ] (str (:numeric-code x) " - " (:name x)))
|
||||
:include-keys [:name :id :numeric-code]
|
||||
:type "typeahead-entity"
|
||||
:on-change #(re-frame/dispatch [::data-page/filter-changed data-page :account %])
|
||||
:value @(re-frame/subscribe [::data-page/filter data-page :account])}]]
|
||||
|
||||
[:p.menu-label "Vendor"]
|
||||
[:div
|
||||
[typeahead-entity {:matches @(re-frame/subscribe [::subs/searchable-vendors])
|
||||
@@ -58,22 +69,15 @@
|
||||
:type "typeahead-entity"
|
||||
:value @(re-frame/subscribe [::data-page/filter data-page :vendor])}]]
|
||||
|
||||
[:p.menu-label "Account"]
|
||||
[:div
|
||||
[typeahead-entity {:matches accounts
|
||||
:match->text (fn [x ] (str (:numeric-code x) " - " (:name x)))
|
||||
:include-keys [:name :id :numeric-code]
|
||||
:type "typeahead-entity"
|
||||
:on-change #(re-frame/dispatch [::data-page/filter-changed data-page :account %])
|
||||
:value @(re-frame/subscribe [::data-page/filter data-page :account])}]]
|
||||
[:p.menu-label "Amount"]
|
||||
[:div
|
||||
[number-filter
|
||||
{:on-change-event [::data-page/filter-changed data-page :amount-range]
|
||||
:value @(re-frame/subscribe [::data-page/filter data-page :amount-range])}]]
|
||||
|
||||
|
||||
[:p.menu-label "Date Range"]
|
||||
[:div
|
||||
[date-range-filter
|
||||
{:on-change-event [::data-page/filter-changed data-page :date-range]
|
||||
:value @(re-frame/subscribe [::data-page/filter data-page :date-range])}]]])]]))
|
||||
:value @(re-frame/subscribe [::data-page/filter data-page :date-range])}]]
|
||||
[:p.menu-label "Amount"]
|
||||
[:div
|
||||
[number-filter
|
||||
{:on-change-event [::data-page/filter-changed data-page :amount-range]
|
||||
:value @(re-frame/subscribe [::data-page/filter data-page :amount-range])}]]])]]))
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
:client-id (:id @(re-frame/subscribe [::subs/client]))
|
||||
:vendor-id (:id (:vendor params))
|
||||
:date-range (:date-range params)
|
||||
:account-id (:id (:account params))
|
||||
:bank-account-id (:id (:bank-account params))
|
||||
:amount-gte (:amount-gte (:amount-range params))
|
||||
:amount-lte (:amount-lte (:amount-range params))
|
||||
|
||||
@@ -10,11 +10,10 @@
|
||||
[re-frame.core :as re-frame]
|
||||
[auto-ap.views.pages.data-page :as data-page]))
|
||||
|
||||
|
||||
|
||||
(defn side-bar [{:keys [data-page]}]
|
||||
(let [ap @(re-frame/subscribe [::subs/active-page])
|
||||
user @(re-frame/subscribe [::subs/user])]
|
||||
user @(re-frame/subscribe [::subs/user])
|
||||
accounts @(re-frame/subscribe [::subs/accounts])]
|
||||
[:div
|
||||
[:div [:p.menu-label "Type"]
|
||||
[:ul.menu-list
|
||||
@@ -57,11 +56,25 @@
|
||||
:value @(re-frame/subscribe [::data-page/filter data-page :bank-account])
|
||||
:bank-accounts @(re-frame/subscribe [::subs/bank-accounts])}]]
|
||||
|
||||
[:p.menu-label "Date Range"]
|
||||
[:div
|
||||
[date-range-filter
|
||||
{:on-change-event [::data-page/filter-changed data-page :date-range]
|
||||
:value @(re-frame/subscribe [::data-page/filter data-page :date-range])}]]
|
||||
[:p.menu-label "Financial Account"]
|
||||
[:div
|
||||
[typeahead-entity {:matches accounts
|
||||
:match->text (fn [x ] (str (:numeric-code x) " - " (:name x)))
|
||||
:include-keys [:name :id :numeric-code]
|
||||
:type "typeahead-entity"
|
||||
:on-change #(re-frame/dispatch [::data-page/filter-changed data-page :account %])
|
||||
:value @(re-frame/subscribe [::data-page/filter data-page :account])}]]
|
||||
|
||||
[:p.menu-label "Vendor"]
|
||||
[:div
|
||||
[typeahead-entity {:matches @(re-frame/subscribe [::subs/searchable-vendors])
|
||||
:on-change #(re-frame/dispatch [::data-page/filter-changed data-page :vendor %])
|
||||
:include-keys [:name :id]
|
||||
:match->text :name
|
||||
:type "typeahead-entity"
|
||||
:value @(re-frame/subscribe [::data-page/filter data-page :vendor])}]]
|
||||
|
||||
|
||||
|
||||
[:p.menu-label "Amount"]
|
||||
[:div
|
||||
@@ -69,14 +82,13 @@
|
||||
{:on-change-event [::data-page/filter-changed data-page :amount-range]
|
||||
:value @(re-frame/subscribe [::data-page/filter data-page :amount-range])}]]
|
||||
|
||||
[:p.menu-label "Vendor"]
|
||||
[:div
|
||||
[typeahead-entity {:matches @(re-frame/subscribe [::subs/searchable-vendors])
|
||||
:on-change #(re-frame/dispatch [::data-page/filter-changed data-page :vendor %])
|
||||
:include-keys [:name :id]
|
||||
:match->text :name
|
||||
:type "typeahead-entity"
|
||||
:value @(re-frame/subscribe [::data-page/filter data-page :vendor])}]]
|
||||
[:p.menu-label "Date Range"]
|
||||
[:div
|
||||
[date-range-filter
|
||||
{:on-change-event [::data-page/filter-changed data-page :date-range]
|
||||
:value @(re-frame/subscribe [::data-page/filter data-page :date-range])}]]
|
||||
|
||||
|
||||
|
||||
[:p.menu-label "Description"]
|
||||
[:div
|
||||
|
||||
Reference in New Issue
Block a user