better health check.
This commit is contained in:
@@ -37,6 +37,12 @@
|
|||||||
:where ['[?e :transaction/bank-account ?bank-account-id]]}
|
:where ['[?e :transaction/bank-account ?bank-account-id]]}
|
||||||
:args [(:bank-account-id args)]})
|
: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)
|
(:client-id args)
|
||||||
(merge-query {:query {:in ['?client-id]
|
(merge-query {:query {:in ['?client-id]
|
||||||
:where ['[?e :transaction/client ?client-id]]}
|
:where ['[?e :transaction/client ?client-id]]}
|
||||||
|
|||||||
@@ -590,6 +590,7 @@
|
|||||||
:transaction_filters {:fields {:client_id {:type :id}
|
:transaction_filters {:fields {:client_id {:type :id}
|
||||||
:vendor_id {:type :id}
|
:vendor_id {:type :id}
|
||||||
:bank_account_id {:type :id}
|
:bank_account_id {:type :id}
|
||||||
|
:account_id {:type :id}
|
||||||
:date_range {:type :date_range}
|
:date_range {:type :date_range}
|
||||||
:amount_lte {:type :money}
|
:amount_lte {:type :money}
|
||||||
:amount_gte {:type :money}
|
:amount_gte {:type :money}
|
||||||
|
|||||||
@@ -85,8 +85,7 @@
|
|||||||
(when (not (get (into #{"Shared"} (:client/locations client))
|
(when (not (get (into #{"Shared"} (:client/locations client))
|
||||||
(:location a)))
|
(:location a)))
|
||||||
(let [err (str "Account " name " uses location " (:location a) ", but doesn't belong to the client " location)]
|
(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
|
rule-id (if id
|
||||||
id
|
id
|
||||||
"transaction-rule")
|
"transaction-rule")
|
||||||
|
|||||||
@@ -1,48 +1,56 @@
|
|||||||
(ns auto-ap.handler
|
(ns auto-ap.handler
|
||||||
(:require [amazonica.core :refer [defcredential]]
|
(:require [amazonica.core :refer [defcredential]]
|
||||||
[auto-ap.routes.auth :as auth]
|
[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.events :as events]
|
||||||
[auto-ap.routes.checks :as checks]
|
|
||||||
[auto-ap.routes.exports :as exports]
|
[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.backends.token :refer [jws-backend]]
|
||||||
[buddy.auth.middleware :refer [wrap-authentication
|
[buddy.auth.middleware :refer [wrap-authentication wrap-authorization]]
|
||||||
wrap-authorization]]
|
[clojure.tools.logging :as log]
|
||||||
[clojure.java.jdbc :as jdbc]
|
|
||||||
[compojure.core :refer :all]
|
[compojure.core :refer :all]
|
||||||
[compojure.route :as route]
|
[compojure.route :as route]
|
||||||
[config.core :refer [env]]
|
[config.core :refer [env]]
|
||||||
[clojure.tools.logging :as log]
|
[mount.core :as mount]
|
||||||
[unilog.context :as lc]
|
|
||||||
[ring.middleware.edn :refer [wrap-edn-params]]
|
[ring.middleware.edn :refer [wrap-edn-params]]
|
||||||
|
[ring.middleware.gzip :refer [wrap-gzip]]
|
||||||
[ring.middleware.multipart-params :as mp]
|
[ring.middleware.multipart-params :as mp]
|
||||||
[ring.middleware.params :refer [wrap-params]]
|
[ring.middleware.params :refer [wrap-params]]
|
||||||
[ring.middleware.reload :refer [wrap-reload]]
|
[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)
|
(when (:aws-access-key-id env)
|
||||||
(defcredential (:aws-access-key-id env) (:aws-secret-access-key env) (:aws-region 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
|
(defroutes static-routes
|
||||||
(GET "/" [] (response/resource-response "index.html" {:root "public"}))
|
(GET "/" [] (response/resource-response "index.html" {:root "public"}))
|
||||||
(route/resources "/")
|
(route/resources "/")
|
||||||
(routes (ANY "*" [] (response/resource-response "index.html" {:root "public"}))))
|
(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
|
(defroutes api-routes
|
||||||
(context "/api" []
|
(context "/api" []
|
||||||
exports/routes
|
exports/routes
|
||||||
yodlee/routes
|
yodlee/routes
|
||||||
invoices/routes
|
invoices/routes
|
||||||
clients/routes
|
|
||||||
reminders/routes
|
|
||||||
checks/routes
|
|
||||||
graphql/routes
|
graphql/routes
|
||||||
auth/routes))
|
auth/routes
|
||||||
|
health-check))
|
||||||
|
|
||||||
|
|
||||||
(def auth-backend (jws-backend {:secret (:jwt-secret env) :options {:alg :hs512}}))
|
(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])
|
[mount.core :as mount])
|
||||||
(:gen-class))
|
(: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 port :start (Integer/parseInt (or (env :port) "3000")))
|
||||||
(mount/defstate jetty
|
(mount/defstate jetty
|
||||||
:start (run-jetty app {:port port :join? false})
|
:start (run-jetty app {:port port :join? false})
|
||||||
:stop (.stop jetty)
|
:stop (.stop jetty))
|
||||||
)
|
|
||||||
|
(defn shutdown-mount []
|
||||||
|
(mount/stop))
|
||||||
|
|
||||||
(defn -main [& args]
|
(defn -main [& args]
|
||||||
|
(add-shutdown-hook! shutdown-mount)
|
||||||
(start-server :port 9000 :bind "0.0.0.0" #_#_:handler (cider-nrepl-handler))
|
(start-server :port 9000 :bind "0.0.0.0" #_#_:handler (cider-nrepl-handler))
|
||||||
(mount/start))
|
(mount/start))
|
||||||
|
|||||||
@@ -49,6 +49,17 @@
|
|||||||
:on-change #(re-frame/dispatch [::data-page/filter-changed data-page :bank-account %])
|
:on-change #(re-frame/dispatch [::data-page/filter-changed data-page :bank-account %])
|
||||||
:value @(re-frame/subscribe [::data-page/filter 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"]
|
[:p.menu-label "Vendor"]
|
||||||
[:div
|
[:div
|
||||||
[typeahead-entity {:matches @(re-frame/subscribe [::subs/searchable-vendors])
|
[typeahead-entity {:matches @(re-frame/subscribe [::subs/searchable-vendors])
|
||||||
@@ -58,22 +69,15 @@
|
|||||||
:type "typeahead-entity"
|
:type "typeahead-entity"
|
||||||
:value @(re-frame/subscribe [::data-page/filter data-page :vendor])}]]
|
: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"]
|
[:p.menu-label "Date Range"]
|
||||||
[:div
|
[:div
|
||||||
[date-range-filter
|
[date-range-filter
|
||||||
{:on-change-event [::data-page/filter-changed data-page :date-range]
|
{: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]))
|
:client-id (:id @(re-frame/subscribe [::subs/client]))
|
||||||
:vendor-id (:id (:vendor params))
|
:vendor-id (:id (:vendor params))
|
||||||
:date-range (:date-range params)
|
:date-range (:date-range params)
|
||||||
|
:account-id (:id (:account params))
|
||||||
:bank-account-id (:id (:bank-account params))
|
:bank-account-id (:id (:bank-account params))
|
||||||
:amount-gte (:amount-gte (:amount-range params))
|
:amount-gte (:amount-gte (:amount-range params))
|
||||||
:amount-lte (:amount-lte (:amount-range params))
|
:amount-lte (:amount-lte (:amount-range params))
|
||||||
|
|||||||
@@ -10,11 +10,10 @@
|
|||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[auto-ap.views.pages.data-page :as data-page]))
|
[auto-ap.views.pages.data-page :as data-page]))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defn side-bar [{:keys [data-page]}]
|
(defn side-bar [{:keys [data-page]}]
|
||||||
(let [ap @(re-frame/subscribe [::subs/active-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
|
||||||
[:div [:p.menu-label "Type"]
|
[:div [:p.menu-label "Type"]
|
||||||
[:ul.menu-list
|
[:ul.menu-list
|
||||||
@@ -57,17 +56,14 @@
|
|||||||
:value @(re-frame/subscribe [::data-page/filter data-page :bank-account])
|
:value @(re-frame/subscribe [::data-page/filter data-page :bank-account])
|
||||||
:bank-accounts @(re-frame/subscribe [::subs/bank-accounts])}]]
|
:bank-accounts @(re-frame/subscribe [::subs/bank-accounts])}]]
|
||||||
|
|
||||||
[:p.menu-label "Date Range"]
|
[:p.menu-label "Financial Account"]
|
||||||
[:div
|
[:div
|
||||||
[date-range-filter
|
[typeahead-entity {:matches accounts
|
||||||
{:on-change-event [::data-page/filter-changed data-page :date-range]
|
:match->text (fn [x ] (str (:numeric-code x) " - " (:name x)))
|
||||||
:value @(re-frame/subscribe [::data-page/filter data-page :date-range])}]]
|
:include-keys [:name :id :numeric-code]
|
||||||
|
:type "typeahead-entity"
|
||||||
[:p.menu-label "Amount"]
|
:on-change #(re-frame/dispatch [::data-page/filter-changed data-page :account %])
|
||||||
[:div
|
:value @(re-frame/subscribe [::data-page/filter data-page :account])}]]
|
||||||
[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 "Vendor"]
|
[:p.menu-label "Vendor"]
|
||||||
[:div
|
[:div
|
||||||
@@ -78,6 +74,22 @@
|
|||||||
:type "typeahead-entity"
|
:type "typeahead-entity"
|
||||||
:value @(re-frame/subscribe [::data-page/filter data-page :vendor])}]]
|
:value @(re-frame/subscribe [::data-page/filter data-page :vendor])}]]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[: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])}]]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[:p.menu-label "Description"]
|
[:p.menu-label "Description"]
|
||||||
[:div
|
[:div
|
||||||
[:div.field
|
[:div.field
|
||||||
|
|||||||
Reference in New Issue
Block a user