User can set up sales queries on their own now.
This commit is contained in:
@@ -12,6 +12,7 @@
|
|||||||
[auto-ap.datomic.migrate.invoice-converter
|
[auto-ap.datomic.migrate.invoice-converter
|
||||||
:refer [add-import-status-existing-invoices]]
|
:refer [add-import-status-existing-invoices]]
|
||||||
[auto-ap.datomic.migrate.ledger :as ledger]
|
[auto-ap.datomic.migrate.ledger :as ledger]
|
||||||
|
[auto-ap.datomic.migrate.queries :as queries]
|
||||||
[auto-ap.datomic.migrate.plaid :as plaid]
|
[auto-ap.datomic.migrate.plaid :as plaid]
|
||||||
[auto-ap.datomic.migrate.sales :as sales]
|
[auto-ap.datomic.migrate.sales :as sales]
|
||||||
[auto-ap.datomic.migrate.vendors :as vendors]
|
[auto-ap.datomic.migrate.vendors :as vendors]
|
||||||
@@ -501,7 +502,8 @@
|
|||||||
reports/norms-map
|
reports/norms-map
|
||||||
plaid/norms-map
|
plaid/norms-map
|
||||||
audit/norms-map
|
audit/norms-map
|
||||||
vendors/norms-map)]
|
vendors/norms-map
|
||||||
|
queries/norms-map)]
|
||||||
(println "Conforming database...")
|
(println "Conforming database...")
|
||||||
(c/ensure-conforms conn norms-map)
|
(c/ensure-conforms conn norms-map)
|
||||||
#_(when (not (seq args))
|
#_(when (not (seq args))
|
||||||
|
|||||||
@@ -4,16 +4,17 @@
|
|||||||
[auto-ap.graphql.utils :refer [->graphql assert-admin can-see-client? is-admin?]]
|
[auto-ap.graphql.utils :refer [->graphql assert-admin can-see-client? is-admin?]]
|
||||||
[auto-ap.utils :refer [by]]
|
[auto-ap.utils :refer [by]]
|
||||||
[auto-ap.yodlee.core :refer [in-memory-cache]]
|
[auto-ap.yodlee.core :refer [in-memory-cache]]
|
||||||
|
[auto-ap.routes.queries :as q]
|
||||||
[auto-ap.square.core :as square]
|
[auto-ap.square.core :as square]
|
||||||
[com.walmartlabs.lacinia.util :refer [attach-resolvers]]
|
[com.walmartlabs.lacinia.util :refer [attach-resolvers]]
|
||||||
[clj-time.coerce :as coerce]
|
[clj-time.coerce :as coerce]
|
||||||
[config.core :refer [env]]
|
|
||||||
[clojure.string :as str]
|
[clojure.string :as str]
|
||||||
[unilog.context :as lc]
|
[unilog.context :as lc]
|
||||||
[clojure.tools.logging :as log]
|
[clojure.tools.logging :as log]
|
||||||
[datomic.api :as d]
|
[datomic.api :as d]
|
||||||
[clojure.java.io :as io]
|
[clojure.java.io :as io]
|
||||||
[amazonica.aws.s3 :as s3]
|
[amazonica.aws.s3 :as s3]
|
||||||
|
#_{:clj-kondo/ignore [:unused-namespace]}
|
||||||
[yang.scheduler :as scheduler]
|
[yang.scheduler :as scheduler]
|
||||||
[mount.core :as mount])
|
[mount.core :as mount])
|
||||||
(:import [org.apache.commons.codec.binary Base64]
|
(:import [org.apache.commons.codec.binary Base64]
|
||||||
@@ -51,7 +52,7 @@
|
|||||||
[?ba :bank-account/plaid-account ?src]
|
[?ba :bank-account/plaid-account ?src]
|
||||||
[?ba :bank-account/yodlee-account-id ?src])]
|
[?ba :bank-account/yodlee-account-id ?src])]
|
||||||
new-db [:client/code client-code])
|
new-db [:client/code client-code])
|
||||||
(filter (fn [[src cnt]]
|
(filter (fn [[_ cnt]]
|
||||||
(> cnt 1)))))
|
(> cnt 1)))))
|
||||||
(throw (ex-info "Cannot reuse yodlee/plaid/intuit account" {:validation-error (str "Cannot reuse yodlee/plaid/intuit account")})))))
|
(throw (ex-info "Cannot reuse yodlee/plaid/intuit account" {:validation-error (str "Cannot reuse yodlee/plaid/intuit account")})))))
|
||||||
|
|
||||||
@@ -183,11 +184,11 @@
|
|||||||
[(get-else $ ?e :journal-entry-line/credit 0.0) ?credit]]}
|
[(get-else $ ?e :journal-entry-line/credit 0.0) ?credit]]}
|
||||||
:args [(d/db conn) bank-account-id]})
|
:args [(d/db conn) bank-account-id]})
|
||||||
debits (->> all-transactions
|
debits (->> all-transactions
|
||||||
(map (fn [[e debit credit]]
|
(map (fn [[_ debit _]]
|
||||||
debit))
|
debit))
|
||||||
(reduce + 0.0))
|
(reduce + 0.0))
|
||||||
credits (->> all-transactions
|
credits (->> all-transactions
|
||||||
(map (fn [[e debit credit]]
|
(map (fn [[_ _ credit]]
|
||||||
credit))
|
credit))
|
||||||
(reduce + 0.0))
|
(reduce + 0.0))
|
||||||
current-balance (if (= :bank-account-type/check (:bank-account/type (d/entity (d/db conn) bank-account-id)))
|
current-balance (if (= :bank-account-type/check (:bank-account/type (d/entity (d/db conn) bank-account-id)))
|
||||||
@@ -255,7 +256,7 @@
|
|||||||
:start (scheduler/every (* 17 60 1000) refresh-current-balance)
|
:start (scheduler/every (* 17 60 1000) refresh-current-balance)
|
||||||
:stop (scheduler/stop current-balance-worker))
|
:stop (scheduler/stop current-balance-worker))
|
||||||
|
|
||||||
(defn get-client [context args value]
|
(defn get-client [context _ _]
|
||||||
(->graphql
|
(->graphql
|
||||||
(->> (d-clients/get-all)
|
(->> (d-clients/get-all)
|
||||||
(filter #(can-see-client? (:id context) %))
|
(filter #(can-see-client? (:id context) %))
|
||||||
@@ -276,6 +277,140 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(def sales-summary-query
|
||||||
|
"[:find ?d4 (sum ?total) (sum ?tax) (sum ?tip) (sum ?service-charge) (sum ?discount) (sum ?returns)
|
||||||
|
:with ?s
|
||||||
|
:in $
|
||||||
|
:where
|
||||||
|
[?s :sales-order/client [:client/code \"%s\"]]
|
||||||
|
[?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]
|
||||||
|
[?s :sales-order/returns ?returns]
|
||||||
|
[?s :sales-order/discount ?discount]
|
||||||
|
[(clj-time.coerce/to-date-time ?d) ?d2]
|
||||||
|
[(auto-ap.time/localize ?d2) ?d3]
|
||||||
|
[(auto-ap.time/unparse-local ?d3 auto-ap.time/normal-date) ?d4]
|
||||||
|
]")
|
||||||
|
|
||||||
|
(def sales-category-query
|
||||||
|
"[:find ?d4 ?n ?n2 (sum ?total) (sum ?tax) (sum ?discount)
|
||||||
|
:with ?s ?li
|
||||||
|
:in $
|
||||||
|
:where
|
||||||
|
[?s :sales-order/client [:client/code \"%s\"]]
|
||||||
|
[?s :sales-order/date ?d]
|
||||||
|
[?s :sales-order/line-items ?li]
|
||||||
|
[?li :order-line-item/category ?n]
|
||||||
|
[(get-else $ ?li :order-line-item/item-name \"\") ?n2]
|
||||||
|
[?li :order-line-item/total ?total]
|
||||||
|
[?li :order-line-item/tax ?tax]
|
||||||
|
[?li :order-line-item/discount ?discount]
|
||||||
|
[(clj-time.coerce/to-date-time ?d) ?d2]
|
||||||
|
[(auto-ap.time/localize ?d2) ?d3]
|
||||||
|
[(auto-ap.time/unparse-local ?d3 auto-ap.time/normal-date) ?d4]
|
||||||
|
]")
|
||||||
|
|
||||||
|
(def expected-deposits-query
|
||||||
|
"[:find ?d4 ?t ?f
|
||||||
|
:in $
|
||||||
|
:where
|
||||||
|
[?c :client/code \"%s\"]
|
||||||
|
[?s :expected-deposit/client ?c]
|
||||||
|
[?s :expected-deposit/total ?t]
|
||||||
|
[?s :expected-deposit/fee ?f]
|
||||||
|
[?s :expected-deposit/sales-date ?date]
|
||||||
|
[(clj-time.coerce/to-date-time ?date) ?d2]
|
||||||
|
[(auto-ap.time/localize ?d2) ?d3]
|
||||||
|
[(auto-ap.time/unparse-local ?d3 auto-ap.time/normal-date) ?d4]
|
||||||
|
]")
|
||||||
|
|
||||||
|
(def tenders-query
|
||||||
|
"[:find ?d4 ?type ?p2 (sum ?total) (sum ?tip)
|
||||||
|
:with ?charge
|
||||||
|
:in $
|
||||||
|
:where
|
||||||
|
[?c :client/code \"%s\"]
|
||||||
|
[?s :sales-order/client ?c]
|
||||||
|
[?s :sales-order/charges ?charge]
|
||||||
|
[?charge :charge/type-name ?type]
|
||||||
|
[?charge :charge/total ?total]
|
||||||
|
[?charge :charge/tip ?tip]
|
||||||
|
[(get-else $ ?charge :charge/processor :na) ?ccp]
|
||||||
|
[(get-else $ ?ccp :db/ident :na) ?p]
|
||||||
|
[(name ?p) ?p2]
|
||||||
|
[?s :sales-order/date ?date]
|
||||||
|
[(clj-time.coerce/to-date-time ?date) ?d2]
|
||||||
|
[(auto-ap.time/localize ?d2) ?d3]
|
||||||
|
[(auto-ap.time/unparse-local ?d3 auto-ap.time/normal-date) ?d4]
|
||||||
|
]")
|
||||||
|
|
||||||
|
(def refunds-query
|
||||||
|
"[:find ?d4 ?t (sum ?total) (sum ?fee)
|
||||||
|
:with ?r
|
||||||
|
:in $
|
||||||
|
:where
|
||||||
|
[?r :sales-refund/client [:client/code \"%s\"]]
|
||||||
|
[?r :sales-refund/total ?total]
|
||||||
|
[?r :sales-refund/fee ?fee]
|
||||||
|
[?r :sales-refund/date ?date]
|
||||||
|
[?r :sales-refund/type ?t]
|
||||||
|
[(clj-time.coerce/to-date-time ?date) ?d2]
|
||||||
|
[(auto-ap.time/localize ?d2) ?d3]
|
||||||
|
[(auto-ap.time/unparse-local ?d3 auto-ap.time/normal-date) ?d4]]")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(defn setup-sales-queries [context args _]
|
||||||
|
(assert-admin (:id context))
|
||||||
|
(let [{client-code :client/code} (d/pull (d/db conn) '[:client/code] (:client_id args))]
|
||||||
|
(q/put-query (str (UUID/randomUUID))
|
||||||
|
(format sales-summary-query client-code)
|
||||||
|
(str "sales query for " client-code)
|
||||||
|
(str client-code "-sales-summary")
|
||||||
|
[:client/code client-code]
|
||||||
|
)
|
||||||
|
(q/put-query (str (UUID/randomUUID))
|
||||||
|
(format sales-category-query client-code)
|
||||||
|
(str "sales category query for " client-code)
|
||||||
|
(str client-code "-sales-category")
|
||||||
|
[:client/code client-code]
|
||||||
|
)
|
||||||
|
(q/put-query (str (UUID/randomUUID))
|
||||||
|
(format expected-deposits-query client-code)
|
||||||
|
(str "expected deposit query for " client-code)
|
||||||
|
(str client-code "-expected-deposit")
|
||||||
|
[:client/code client-code]
|
||||||
|
)
|
||||||
|
(q/put-query (str (UUID/randomUUID))
|
||||||
|
(format tenders-query client-code)
|
||||||
|
(str "tender query for " client-code)
|
||||||
|
(str client-code "-tender")
|
||||||
|
[:client/code client-code]
|
||||||
|
)
|
||||||
|
|
||||||
|
(q/put-query (str (UUID/randomUUID))
|
||||||
|
(format refunds-query client-code)
|
||||||
|
(str "refunds query for " client-code)
|
||||||
|
(str client-code "-refund")
|
||||||
|
[:client/code client-code])
|
||||||
|
|
||||||
|
(let [sales-summary-id (:saved-query/guid (d/pull (d/db auto-ap.datomic/conn) [:saved-query/guid] [:saved-query/lookup-key (str client-code "-sales-summary")]))
|
||||||
|
sales-category-id (:saved-query/guid (d/pull (d/db auto-ap.datomic/conn) [:saved-query/guid] [:saved-query/lookup-key (str client-code "-sales-category")]))
|
||||||
|
expected-deposit-id (:saved-query/guid (d/pull (d/db auto-ap.datomic/conn) [:saved-query/guid] [:saved-query/lookup-key (str client-code "-expected-deposit")]))
|
||||||
|
tender-id (:saved-query/guid (d/pull (d/db auto-ap.datomic/conn) [:saved-query/guid] [:saved-query/lookup-key (str client-code "-tender")]))
|
||||||
|
refund-id (:saved-query/guid (d/pull (d/db auto-ap.datomic/conn) [:saved-query/guid] [:saved-query/lookup-key (str client-code "-refund")]))]
|
||||||
|
{:message (str/join "\n"
|
||||||
|
[
|
||||||
|
(str "For " client-code ":")
|
||||||
|
(str "Sales: " "https://app.integreatconsult.com/api/queries/" sales-summary-id "/results/json")
|
||||||
|
(str "Sales Category: " "https://app.integreatconsult.com/api/queries/" sales-category-id "/results/json")
|
||||||
|
(str "Expected Deposits: " "https://app.integreatconsult.com/api/queries/" expected-deposit-id "/results/json")
|
||||||
|
(str "Tenders: " "https://app.integreatconsult.com/api/queries/" tender-id "/results/json")
|
||||||
|
(str "Refund: " "https://app.integreatconsult.com/api/queries/" refund-id "/results/json")])})))
|
||||||
|
|
||||||
|
|
||||||
(def objects
|
(def objects
|
||||||
{:location_match
|
{:location_match
|
||||||
@@ -353,7 +488,10 @@
|
|||||||
(def mutations
|
(def mutations
|
||||||
{:edit_client {:type :client
|
{:edit_client {:type :client
|
||||||
:args {:edit_client {:type :edit_client}}
|
:args {:edit_client {:type :edit_client}}
|
||||||
:resolve :mutation/edit-client}})
|
:resolve :mutation/edit-client}
|
||||||
|
:setup_sales_queries {:type :message
|
||||||
|
:args {:client_id {:type :id}}
|
||||||
|
:resolve :mutation/setup-sales-queries}})
|
||||||
|
|
||||||
(def input-objects
|
(def input-objects
|
||||||
{:edit_location_match {:fields {:location {:type 'String}
|
{:edit_location_match {:fields {:location {:type 'String}
|
||||||
@@ -418,7 +556,8 @@
|
|||||||
|
|
||||||
(def resolvers
|
(def resolvers
|
||||||
{:get-client get-client
|
{:get-client get-client
|
||||||
:mutation/edit-client edit-client})
|
:mutation/edit-client edit-client
|
||||||
|
:mutation/setup-sales-queries setup-sales-queries})
|
||||||
|
|
||||||
|
|
||||||
(defn attach [schema]
|
(defn attach [schema]
|
||||||
|
|||||||
@@ -40,13 +40,12 @@
|
|||||||
:user/name (:name profile)})
|
:user/name (:name profile)})
|
||||||
]
|
]
|
||||||
(log/info "authenticated as user" user)
|
(log/info "authenticated as user" user)
|
||||||
|
|
||||||
;; TODO - these namespaces are not being transmitted/deserialized properly
|
;; TODO - these namespaces are not being transmitted/deserialized properly
|
||||||
(if (and token user)
|
(if (and token user)
|
||||||
(let [jwt (jwt/sign {:user (:name profile)
|
(let [jwt (jwt/sign {:user (:name profile)
|
||||||
:exp (time/plus (time/now) (time/days 30))
|
:exp (time/plus (time/now) (time/days 30))
|
||||||
:user/clients (map (fn [c]
|
:user/clients (map (fn [c]
|
||||||
(dissoc c :client/bank-accounts :client/location-matches :client/forecasted-transactions :client/matches :client/week-a-debits :client/week-a-credits :client/week-b-debits :client/week-b-credits :client/signature-file :client/address :client/emails :client/square-auth-token :client/square-locations))
|
(select-keys c [:client/code :db/id :client/name :client/locations]))
|
||||||
(:user/clients user))
|
(:user/clients user))
|
||||||
:user/role (name (:user/role user))
|
:user/role (name (:user/role user))
|
||||||
:user/name (:name profile)}
|
:user/name (:name profile)}
|
||||||
|
|||||||
@@ -41,17 +41,27 @@
|
|||||||
(into [(d/db conn)] (clojure.edn/read-string (get query-params "args" "[]")))))))))
|
(into [(d/db conn)] (clojure.edn/read-string (get query-params "args" "[]")))))))))
|
||||||
|
|
||||||
|
|
||||||
(defn put-query [id body note]
|
(defn put-query [guid body note & [lookup-key client]]
|
||||||
(s3/put-object :bucket-name (:data-bucket env)
|
(let [guid (if lookup-key
|
||||||
:key (str "queries/" id)
|
(or (:saved-query/guid (d/pull (d/db conn) [:saved-query/guid] [:saved-query/lookup-key lookup-key]))
|
||||||
:input-stream (io/make-input-stream (.getBytes body) {})
|
guid)
|
||||||
:metadata {:content-type "application/text"
|
guid)]
|
||||||
:user-metadata {:note note}})
|
@(d/transact conn [(cond->
|
||||||
{:body {:query body
|
{:saved-query/guid guid
|
||||||
:id id
|
:saved-query/description note
|
||||||
:results-url (str "/api/queries/" id "/results")
|
:saved-query/key (str "queries/" guid)}
|
||||||
:csv-results-url (str "/api/queries/" id "/results/csv")
|
client (assoc :saved-query/client client)
|
||||||
:json-results-url (str "/api/queries/" id "/results/json")}})
|
lookup-key (assoc :saved-query/lookup-key lookup-key))])
|
||||||
|
(s3/put-object :bucket-name (:data-bucket env)
|
||||||
|
:key (str "queries/" guid)
|
||||||
|
:input-stream (io/make-input-stream (.getBytes body) {})
|
||||||
|
:metadata {:content-type "application/text"
|
||||||
|
:user-metadata {:note note}})
|
||||||
|
{:body {:query body
|
||||||
|
:id guid
|
||||||
|
:results-url (str "/api/queries/" guid "/results")
|
||||||
|
:csv-results-url (str "/api/queries/" guid "/results/csv")
|
||||||
|
:json-results-url (str "/api/queries/" guid "/results/json")}}))
|
||||||
|
|
||||||
(def json-routes
|
(def json-routes
|
||||||
(context "/queries" []
|
(context "/queries" []
|
||||||
|
|||||||
@@ -24,50 +24,68 @@
|
|||||||
(defn auth-header
|
(defn auth-header
|
||||||
([cob-session] (str "Bearer " cob-session)))
|
([cob-session] (str "Bearer " cob-session)))
|
||||||
|
|
||||||
|
(defn retry-thrice
|
||||||
|
([x] (retry-thrice x 0))
|
||||||
|
([x i]
|
||||||
|
(try
|
||||||
|
(x)
|
||||||
|
(catch Exception e
|
||||||
|
(if (>= i 3)
|
||||||
|
(throw e)
|
||||||
|
(do
|
||||||
|
(Thread/sleep 5000)
|
||||||
|
(retry-thrice x (inc i))))))))
|
||||||
|
|
||||||
(def other-config
|
(def other-config
|
||||||
(if (:yodlee2-proxy-host env)
|
(if (:yodlee2-proxy-host env)
|
||||||
{:proxy-host (:yodlee2-proxy-host env)
|
{:proxy-host (:yodlee2-proxy-host env)
|
||||||
:proxy-port (:yodlee2-proxy-port env)
|
:proxy-port (:yodlee2-proxy-port env)
|
||||||
:retry-handler (fn [ex try-count http-context]
|
:socket-timeout 60000
|
||||||
|
:connection-timeout 60000
|
||||||
|
:retry-handler (fn [ex _ _]
|
||||||
(log/error "yodlee Error." ex)
|
(log/error "yodlee Error." ex)
|
||||||
false)}
|
false)}
|
||||||
{:retry-handler (fn [ex try-count http-context]
|
{:retry-handler (fn [ex _ _]
|
||||||
(log/error "yodlee Error." ex)
|
(log/error "yodlee Error." ex)
|
||||||
false)}))
|
false)
|
||||||
|
:socket-timeout 60000
|
||||||
|
:connection-timeout 60000}))
|
||||||
|
|
||||||
(def base-headers {"Api-Version" "1.1"
|
(def base-headers {"Api-Version" "1.1"
|
||||||
"Content-Type" "application/json"})
|
"Content-Type" "application/json"})
|
||||||
|
|
||||||
(defn login-cobrand []
|
(defn login-cobrand []
|
||||||
(-> (str (:yodlee2-base-url env) "/auth/token")
|
(retry-thrice
|
||||||
(client/post (merge {:headers (assoc base-headers
|
(fn []
|
||||||
"loginName" (:yodlee2-admin-user env)
|
(-> (str (:yodlee2-base-url env) "/auth/token")
|
||||||
"Content-Type" "application/x-www-form-urlencoded")
|
(client/post (merge {:headers (assoc base-headers
|
||||||
:body (str "clientId=" (:yodlee2-client-id env) " &secret=" (:yodlee2-client-secret env))
|
"loginName" (:yodlee2-admin-user env)
|
||||||
:as :json}
|
"Content-Type" "application/x-www-form-urlencoded")
|
||||||
other-config)
|
:body (str "clientId=" (:yodlee2-client-id env) " &secret=" (:yodlee2-client-secret env))
|
||||||
)
|
:as :json}
|
||||||
:body
|
other-config)
|
||||||
:token
|
)
|
||||||
:accessToken))
|
:body
|
||||||
|
:token
|
||||||
|
:accessToken))))
|
||||||
|
|
||||||
(defn login-user [client-code]
|
(defn login-user [client-code]
|
||||||
(log/info "logging in as " client-code)
|
(retry-thrice
|
||||||
(-> (str (:yodlee2-base-url env) "/auth/token")
|
(fn []
|
||||||
(client/post (merge {:headers (assoc base-headers
|
(log/info "logging in as " client-code)
|
||||||
"loginName" (if (<= (count client-code) 3)
|
(-> (str (:yodlee2-base-url env) "/auth/token")
|
||||||
(str client-code client-code)
|
(client/post (merge {:headers (assoc base-headers
|
||||||
client-code)
|
"loginName" (if (<= (count client-code) 3)
|
||||||
"Content-Type" "application/x-www-form-urlencoded")
|
(str client-code client-code)
|
||||||
:body (str "clientId=" (:yodlee2-client-id env) " &secret=" (:yodlee2-client-secret env))
|
client-code)
|
||||||
:as :json}
|
"Content-Type" "application/x-www-form-urlencoded")
|
||||||
other-config)
|
:body (str "clientId=" (:yodlee2-client-id env) " &secret=" (:yodlee2-client-secret env))
|
||||||
)
|
:as :json}
|
||||||
:body
|
other-config)
|
||||||
:token
|
)
|
||||||
:accessToken))
|
:body
|
||||||
|
:token
|
||||||
|
:accessToken))))
|
||||||
|
|
||||||
(defn get-accounts [client-code ]
|
(defn get-accounts [client-code ]
|
||||||
(let [cob-session (login-user (client-code->login client-code))]
|
(let [cob-session (login-user (client-code->login client-code))]
|
||||||
@@ -93,14 +111,16 @@
|
|||||||
[])))
|
[])))
|
||||||
|
|
||||||
(defn get-provider-accounts [client-code ]
|
(defn get-provider-accounts [client-code ]
|
||||||
(log/info "logging in user " client-code)
|
(retry-thrice
|
||||||
(let [cob-session (login-user (client-code->login client-code))]
|
(fn []
|
||||||
(-> (str (:yodlee2-base-url env) "/providerAccounts")
|
(log/info "logging in user " client-code)
|
||||||
(-> (client/get (merge {:headers (merge base-headers {"Authorization" (auth-header cob-session )})
|
(let [cob-session (login-user (client-code->login client-code))]
|
||||||
:as :json}
|
(-> (str (:yodlee2-base-url env) "/providerAccounts")
|
||||||
other-config))
|
(-> (client/get (merge {:headers (merge base-headers {"Authorization" (auth-header cob-session )})
|
||||||
:body
|
:as :json}
|
||||||
:providerAccount))))
|
other-config))
|
||||||
|
:body
|
||||||
|
:providerAccount))))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -323,7 +343,6 @@
|
|||||||
|
|
||||||
|
|
||||||
(defn reauthenticate [client-code pa data]
|
(defn reauthenticate [client-code pa data]
|
||||||
(println client-code)
|
|
||||||
(try
|
(try
|
||||||
(-> (str (:yodlee2-base-url env) "/providerAccounts?providerAccountIds=" pa)
|
(-> (str (:yodlee2-base-url env) "/providerAccounts?providerAccountIds=" pa)
|
||||||
|
|
||||||
|
|||||||
135
src/clj/user.clj
135
src/clj/user.clj
@@ -15,7 +15,7 @@
|
|||||||
[clj-time.core :as t]
|
[clj-time.core :as t]
|
||||||
[clojure.java.io :as io]
|
[clojure.java.io :as io]
|
||||||
[clojure.string :as str]
|
[clojure.string :as str]
|
||||||
[auto-ap.routes.queries :as q]
|
|
||||||
[amazonica.aws.s3 :as s3])
|
[amazonica.aws.s3 :as s3])
|
||||||
(:import [org.apache.commons.io.input BOMInputStream]
|
(:import [org.apache.commons.io.input BOMInputStream]
|
||||||
java.util.UUID))
|
java.util.UUID))
|
||||||
@@ -477,139 +477,6 @@
|
|||||||
(println "failed " e)))
|
(println "failed " e)))
|
||||||
(async/<!! (async/into [] output-chan)))))
|
(async/<!! (async/into [] output-chan)))))
|
||||||
|
|
||||||
(def sales-summary-query
|
|
||||||
"[:find ?d4 (sum ?total) (sum ?tax) (sum ?tip) (sum ?service-charge) (sum ?discount) (sum ?returns)
|
|
||||||
:with ?s
|
|
||||||
:in $
|
|
||||||
:where
|
|
||||||
[?s :sales-order/client [:client/code \"%s\"]]
|
|
||||||
[?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]
|
|
||||||
[?s :sales-order/returns ?returns]
|
|
||||||
[?s :sales-order/discount ?discount]
|
|
||||||
[(clj-time.coerce/to-date-time ?d) ?d2]
|
|
||||||
[(auto-ap.time/localize ?d2) ?d3]
|
|
||||||
[(auto-ap.time/unparse-local ?d3 auto-ap.time/normal-date) ?d4]
|
|
||||||
]")
|
|
||||||
|
|
||||||
(def sales-category-query
|
|
||||||
"[:find ?d4 ?n ?n2 (sum ?total) (sum ?tax) (sum ?discount)
|
|
||||||
:with ?s ?li
|
|
||||||
:in $
|
|
||||||
:where
|
|
||||||
[?s :sales-order/client [:client/code \"%s\"]]
|
|
||||||
[?s :sales-order/date ?d]
|
|
||||||
[?s :sales-order/line-items ?li]
|
|
||||||
[?li :order-line-item/category ?n]
|
|
||||||
[(get-else $ ?li :order-line-item/item-name \"\") ?n2]
|
|
||||||
[?li :order-line-item/total ?total]
|
|
||||||
[?li :order-line-item/tax ?tax]
|
|
||||||
[?li :order-line-item/discount ?discount]
|
|
||||||
[(clj-time.coerce/to-date-time ?d) ?d2]
|
|
||||||
[(auto-ap.time/localize ?d2) ?d3]
|
|
||||||
[(auto-ap.time/unparse-local ?d3 auto-ap.time/normal-date) ?d4]
|
|
||||||
]")
|
|
||||||
|
|
||||||
(def expected-deposits-query
|
|
||||||
"[:find ?d4 ?t ?f
|
|
||||||
:in $
|
|
||||||
:where
|
|
||||||
[?c :client/code \"%s\"]
|
|
||||||
[?s :expected-deposit/client ?c]
|
|
||||||
[?s :expected-deposit/total ?t]
|
|
||||||
[?s :expected-deposit/fee ?f]
|
|
||||||
[?s :expected-deposit/sales-date ?date]
|
|
||||||
[(clj-time.coerce/to-date-time ?date) ?d2]
|
|
||||||
[(auto-ap.time/localize ?d2) ?d3]
|
|
||||||
[(auto-ap.time/unparse-local ?d3 auto-ap.time/normal-date) ?d4]
|
|
||||||
]")
|
|
||||||
|
|
||||||
(def tenders-query
|
|
||||||
"[:find ?d4 ?type ?p2 (sum ?total) (sum ?tip)
|
|
||||||
:with ?charge
|
|
||||||
:in $
|
|
||||||
:where
|
|
||||||
[?c :client/code \"%s\"]
|
|
||||||
[?s :sales-order/client ?c]
|
|
||||||
[?s :sales-order/charges ?charge]
|
|
||||||
[?charge :charge/type-name ?type]
|
|
||||||
[?charge :charge/total ?total]
|
|
||||||
[?charge :charge/tip ?tip]
|
|
||||||
[(get-else $ ?charge :charge/processor :na) ?ccp]
|
|
||||||
[(get-else $ ?ccp :db/ident :na) ?p]
|
|
||||||
[(name ?p) ?p2]
|
|
||||||
[?s :sales-order/date ?date]
|
|
||||||
[(clj-time.coerce/to-date-time ?date) ?d2]
|
|
||||||
[(auto-ap.time/localize ?d2) ?d3]
|
|
||||||
[(auto-ap.time/unparse-local ?d3 auto-ap.time/normal-date) ?d4]
|
|
||||||
]")
|
|
||||||
|
|
||||||
(def refunds-query
|
|
||||||
"[:find ?d4 ?t (sum ?total) (sum ?fee)
|
|
||||||
:with ?r
|
|
||||||
:in $
|
|
||||||
:where
|
|
||||||
[?r :sales-refund/client [:client/code \"%s\"]]
|
|
||||||
[?r :sales-refund/total ?total]
|
|
||||||
[?r :sales-refund/fee ?fee]
|
|
||||||
[?r :sales-refund/date ?date]
|
|
||||||
[?r :sales-refund/type ?t]
|
|
||||||
[(clj-time.coerce/to-date-time ?date) ?d2]
|
|
||||||
[(auto-ap.time/localize ?d2) ?d3]
|
|
||||||
[(auto-ap.time/unparse-local ?d3 auto-ap.time/normal-date) ?d4]]")
|
|
||||||
|
|
||||||
(defn setup-sales-queries [client-code]
|
|
||||||
(let [sales-summary-id (or (first (find-queries [client-code "service-charge"]))
|
|
||||||
(str (UUID/randomUUID)))
|
|
||||||
sales-category-id (or (first (find-queries [client-code "item-name"]))
|
|
||||||
(str (UUID/randomUUID)))
|
|
||||||
expected-deposit-id (or (first (find-queries [client-code "expected-deposit"]))
|
|
||||||
(str (UUID/randomUUID)))
|
|
||||||
tender-id (or (first (find-queries [client-code ":charge"]))
|
|
||||||
(str (UUID/randomUUID)))
|
|
||||||
refund-id (or (first (find-queries [client-code "sales-refund"]))
|
|
||||||
(str (UUID/randomUUID)))]
|
|
||||||
(map (comp :json-results-url :body)
|
|
||||||
[(q/put-query sales-summary-id
|
|
||||||
(format sales-summary-query client-code)
|
|
||||||
(str "sales query for " client-code)
|
|
||||||
)
|
|
||||||
(q/put-query sales-category-id
|
|
||||||
(format sales-category-query client-code)
|
|
||||||
(str "sales category query for " client-code)
|
|
||||||
)
|
|
||||||
(q/put-query expected-deposit-id
|
|
||||||
(format expected-deposits-query client-code)
|
|
||||||
(str "expected deposit query for " client-code)
|
|
||||||
)
|
|
||||||
(q/put-query tender-id
|
|
||||||
(format tenders-query client-code)
|
|
||||||
(str "tender query for " client-code))
|
|
||||||
|
|
||||||
(q/put-query refund-id
|
|
||||||
(format refunds-query client-code)
|
|
||||||
(str "refunds query for " client-code)
|
|
||||||
)])))
|
|
||||||
|
|
||||||
|
|
||||||
(defn print-sales-queries [client-code]
|
|
||||||
(let [sales-summary-id (first (find-queries [client-code "service-charge"]))
|
|
||||||
sales-category-id (first (find-queries [client-code "item-name"]))
|
|
||||||
expected-deposit-id (first (find-queries [client-code "expected-deposit"]))
|
|
||||||
tender-id (first (find-queries [client-code ":charge"]))
|
|
||||||
refund-id (first (find-queries [client-code "sales-refund"]))]
|
|
||||||
|
|
||||||
(println "For" client-code ":")
|
|
||||||
(println "Sales: " (str "https://app.integreatconsult.com/api/queries/" sales-summary-id "/results/json"))
|
|
||||||
(println "Sales Category: " (str "https://app.integreatconsult.com/api/queries/" sales-category-id "/results/json"))
|
|
||||||
(println "Expected Deposits: " (str "https://app.integreatconsult.com/api/queries/" expected-deposit-id "/results/json"))
|
|
||||||
(println "Tenders: " (str "https://app.integreatconsult.com/api/queries/" tender-id "/results/json"))
|
|
||||||
(println "Refund: " (str "https://app.integreatconsult.com/api/queries/" refund-id "/results/json"))
|
|
||||||
(println "")))
|
|
||||||
|
|
||||||
|
|
||||||
(defn historical-load-sales [client-code days]
|
(defn historical-load-sales [client-code days]
|
||||||
(let [client (d/pull (d/db auto-ap.datomic/conn)
|
(let [client (d/pull (d/db auto-ap.datomic/conn)
|
||||||
|
|||||||
@@ -3,9 +3,11 @@
|
|||||||
[clojure.string :as str]
|
[clojure.string :as str]
|
||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[auto-ap.views.pages.admin.clients.form :as form]
|
[auto-ap.views.pages.admin.clients.form :as form]
|
||||||
[auto-ap.views.utils :refer [action-cell-width date->str]]
|
[auto-ap.views.utils :refer [action-cell-width date->str with-user]]
|
||||||
[auto-ap.views.components.grid :as grid]
|
[auto-ap.views.components.grid :as grid]
|
||||||
[auto-ap.views.components.buttons :as buttons]))
|
[auto-ap.views.components.modal :as modal]
|
||||||
|
[auto-ap.views.components.buttons :as buttons]
|
||||||
|
[auto-ap.status :as status]))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
::specific-params
|
::specific-params
|
||||||
@@ -17,6 +19,28 @@
|
|||||||
(fn [{:keys [db]} [_ p]]
|
(fn [{:keys [db]} [_ p]]
|
||||||
{:db (assoc db ::params p)}))
|
{:db (assoc db ::params p)}))
|
||||||
|
|
||||||
|
(re-frame/reg-event-fx
|
||||||
|
::sales-queries-setup
|
||||||
|
(fn [_ [_ results]]
|
||||||
|
{:dispatch [::modal/modal-requested {:title "Sales Queries"
|
||||||
|
:body [:div [:pre (:message (:setup-sales-queries results))]]}]}))
|
||||||
|
|
||||||
|
(re-frame/reg-event-fx
|
||||||
|
::setup-sales-queries
|
||||||
|
[with-user]
|
||||||
|
(fn [{:keys [user]} [_ client-id]]
|
||||||
|
{:graphql
|
||||||
|
{:token user
|
||||||
|
:owns-state {:multi ::setup-sales-queries
|
||||||
|
:which client-id}
|
||||||
|
:query-obj {:venia/operation {:operation/type :mutation
|
||||||
|
:operation/name "SetupSalesQueries"}
|
||||||
|
:venia/queries [{:query/data [:setup-sales-queries
|
||||||
|
{:client-id client-id}
|
||||||
|
[:message]]}]}
|
||||||
|
:on-success [::sales-queries-setup]}}
|
||||||
|
))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
::params
|
::params
|
||||||
:<- [::specific-params]
|
:<- [::specific-params]
|
||||||
@@ -26,33 +50,37 @@
|
|||||||
|
|
||||||
|
|
||||||
(defn clients-table [{:keys [page status]}]
|
(defn clients-table [{:keys [page status]}]
|
||||||
[grid/grid {:on-params-change (fn [p]
|
(let [states @(re-frame/subscribe [::status/multi ::setup-sales-queries])]
|
||||||
(re-frame/dispatch [::params-changed p]))
|
[grid/grid {:on-params-change (fn [p]
|
||||||
:status status
|
(re-frame/dispatch [::params-changed p]))
|
||||||
:params @(re-frame/subscribe [::params])
|
:status status
|
||||||
:column-count 5}
|
:params @(re-frame/subscribe [::params])
|
||||||
[grid/controls page]
|
:column-count 5}
|
||||||
[grid/table {:fullwidth true}
|
[grid/controls page]
|
||||||
[grid/header
|
[grid/table {:fullwidth true}
|
||||||
[grid/row {}
|
[grid/header
|
||||||
[grid/header-cell {} "Name"]
|
[grid/row {}
|
||||||
[grid/header-cell {:style {:width "20em"}} "Code"]
|
[grid/header-cell {} "Name"]
|
||||||
[grid/header-cell {} "Locations"]
|
[grid/header-cell {:style {:width "20em"}} "Code"]
|
||||||
[grid/header-cell {} "Locked Until"]
|
[grid/header-cell {} "Locations"]
|
||||||
[grid/header-cell {} "Email"]
|
[grid/header-cell {} "Locked Until"]
|
||||||
[grid/header-cell {:style {:width (action-cell-width 1)}}]]
|
[grid/header-cell {} "Email"]
|
||||||
]
|
[grid/header-cell {:style {:width (action-cell-width 2)}}]]
|
||||||
[grid/body
|
]
|
||||||
(for [{:keys [id name email locked-until code locations] :as c} (:data page)]
|
[grid/body
|
||||||
^{:key (str name "-" id )}
|
(for [{:keys [id name email locked-until code locations]} (:data page)]
|
||||||
[grid/row {:id id}
|
^{:key (str name "-" id )}
|
||||||
[grid/cell {} name]
|
[grid/row {:id id}
|
||||||
[grid/cell {} code]
|
[grid/cell {} name]
|
||||||
[grid/cell {} (str/join ", " locations)]
|
[grid/cell {} code]
|
||||||
[grid/cell {} [:div.tag (or (some-> locked-until date->str)
|
[grid/cell {} (str/join ", " locations)]
|
||||||
"Not locked"
|
[grid/cell {} [:div.tag (or (some-> locked-until date->str)
|
||||||
|
"Not locked"
|
||||||
|
|
||||||
)]]
|
)]]
|
||||||
[grid/cell {} email]
|
[grid/cell {} email]
|
||||||
[grid/cell {} [buttons/fa-icon {:event [::form/editing id]
|
[grid/cell {} [:div.buttons [buttons/fa-icon {:event [::setup-sales-queries id]
|
||||||
:icon :fa-pencil}]]])]]])
|
:class (status/class-for (get states id))
|
||||||
|
:icon :fa-dollar}]
|
||||||
|
[buttons/fa-icon {:event [::form/editing id]
|
||||||
|
:icon :fa-pencil}]]]])]]]))
|
||||||
|
|||||||
Reference in New Issue
Block a user