From 4dc66f3d86418bdadd3cc2e27d99c1c207d4bab2 Mon Sep 17 00:00:00 2001 From: Bryce Covert Date: Fri, 21 May 2021 16:55:04 -0700 Subject: [PATCH] allow custom sales export. --- src/clj/auto_ap/handler.clj | 2 +- src/clj/auto_ap/routes/exports.clj | 413 +++++++++++++++-------------- 2 files changed, 221 insertions(+), 194 deletions(-) diff --git a/src/clj/auto_ap/handler.clj b/src/clj/auto_ap/handler.clj index 28c71535..23986f79 100644 --- a/src/clj/auto_ap/handler.clj +++ b/src/clj/auto_ap/handler.clj @@ -53,7 +53,7 @@ (defroutes api-routes (context "/api" [] - exports/routes + exports/export-routes yodlee/routes yodlee2/routes invoices/routes diff --git a/src/clj/auto_ap/routes/exports.clj b/src/clj/auto_ap/routes/exports.clj index 6e599a96..4854a5d9 100644 --- a/src/clj/auto_ap/routes/exports.clj +++ b/src/clj/auto_ap/routes/exports.clj @@ -4,217 +4,244 @@ [auto-ap.datomic.ledger :as d-ledger] [auto-ap.datomic.transactions :as d-transactions] [auto-ap.datomic.vendors :as d-vendors] + [buddy.sign.jwt :as jwt] [auto-ap.graphql :as graphql] - [auto-ap.graphql.utils :refer [->graphql <-graphql assert-admin]] + [auto-ap.graphql.utils :refer [->graphql <-graphql assert-admin assert-can-see-client]] [auto-ap.routes.utils :refer [wrap-secure]] [clojure.tools.logging :as log] [auto-ap.logging :refer [error-event info-event warn-event]] [clj-time.coerce :as coerce :refer [to-date]] [clj-time.core :as time] - [compojure.core :refer [context defroutes GET wrap-routes]] + [config.core :refer [env]] + [compojure.core :refer [context defroutes GET wrap-routes routes]] [datomic.api :as d] [ring.middleware.json :refer [wrap-json-response]] [venia.core :as venia] [yang.time :refer [time-it]])) -(defroutes routes - (wrap-routes - (wrap-routes - (context "/" [] - (GET "/invoices/export" {:keys [query-params identity] :as request} - (assert-admin identity) - (let [query [[:all_invoices - {:client-code (query-params "client-code") - :original-id (query-params "original")} - - [:id :total :outstanding-balance :invoice-number :date :status :original-id - [:payments [:amount [:payment [:check-number :memo [:bank_account [:id :name :number :bank-name :bank-code :code]]]]]] - [:vendor [:name :id [:primary_contact [:name]] [:address [:street1 :city :state :zip]]]] - [:expense_accounts [:amount :id :location - [:account [:id :numeric-code :name]]]] - [:client [:name :id :code :locations]]]]] - invoices (graphql/query identity (venia/graphql-query {:venia/queries (->graphql query)}))] - - (list (:all-invoices (:data invoices))))) - (GET "/payments/export" {:keys [query-params identity]} - (assert-admin identity) - (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))))) +(def api-key-authed-routes + (context "/" [] + (GET "/sales/aggregated/export" {:keys [query-params identity :as 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]})))))) - (GET "/sales/export" {:keys [query-params identity]} - (assert-admin identity) - (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) - (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 [query-params identity]} - (assert-admin identity) - (map <-graphql (d-clients/get-all))) - - (GET "/vendors/export" {:keys [query-params identity]} - (assert-admin identity) - (map <-graphql (d-vendors/get-graphql {}))) - (GET "/ledger/export" {:keys [query-params identity]} - (log/info "exporting for " (query-params "client-code")) - (assert-admin identity) - (let [[result time] (time-it (transduce (comp - (map #(update % :journal-entry/date to-date)) - (map <-graphql)) - conj - (list) - (first (d-ledger/get-graphql {:count Integer/MAX_VALUE - :client-code (query-params "client-code")}))))] - (info-event "Export completed" - {:time (:time time) - :errors (seq (:errors result))}) - result)) - - (GET "/accounts/export" {:keys [query-params identity]} - (assert-admin identity) +(def admin-only-routes + (context "/" [] + (GET "/invoices/export" {:keys [query-params identity] :as request} + (assert-admin identity) + (let [query [[:all_invoices + {:client-code (query-params "client-code") + :original-id (query-params "original")} + + [:id :total :outstanding-balance :invoice-number :date :status :original-id + [:payments [:amount [:payment [:check-number :memo [:bank_account [:id :name :number :bank-name :bank-code :code]]]]]] + [:vendor [:name :id [:primary_contact [:name]] [:address [:street1 :city :state :zip]]]] + [:expense_accounts [:amount :id :location + [:account [:id :numeric-code :name]]]] + [:client [:name :id :code :locations]]]]] + invoices (graphql/query identity (venia/graphql-query {:venia/queries (->graphql query)}))] - (let [client-id (d-clients/code->id (query-params "client-code")) - query [[: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)}))] + (list (:all-invoices (:data invoices))))) + (GET "/payments/export" {:keys [query-params identity]} + (assert-admin identity) + (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))))) - (list (transduce - (comp - (filter (fn [a] - (let [overriden-clients (set (map (comp :id :client) (:client-overrides a)))] - (or (= :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 - [] - (:accounts (:data all-accounts)))))) + (GET "/sales/export" {:keys [query-params identity :as params]} + (assert-admin identity) + (println params) + (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 "/transactions/export" {:keys [query-params identity]} - (assert-admin identity) - (let [[transactions] (d-transactions/get-graphql {:client-code (query-params "client-code") + + + (GET "/expected-deposit/export" {:keys [query-params identity]} + (assert-admin identity) + (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 [query-params identity]} + (assert-admin identity) + (map <-graphql (d-clients/get-all))) + + (GET "/vendors/export" {:keys [query-params identity]} + (assert-admin identity) + (map <-graphql (d-vendors/get-graphql {}))) + (GET "/ledger/export" {:keys [query-params identity]} + (log/info "exporting for " (query-params "client-code")) + (assert-admin identity) + (let [[result time] (time-it (transduce (comp + (map #(update % :journal-entry/date to-date)) + (map <-graphql)) + conj + (list) + (first (d-ledger/get-graphql {:count Integer/MAX_VALUE + :client-code (query-params "client-code")}))))] + (info-event "Export completed" + {:time (:time time) + :errors (seq (:errors result))}) + result)) + + (GET "/accounts/export" {:keys [query-params identity]} + (assert-admin identity) + + (let [client-id (d-clients/code->id (query-params "client-code")) + query [[: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)}))] + + (list (transduce + (comp + (filter (fn [a] + (let [overriden-clients (set (map (comp :id :client) (:client-overrides a)))] + (or (= :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 + [] + (:accounts (:data all-accounts)))))) + + (GET "/transactions/export" {:keys [query-params identity]} + (assert-admin identity) + (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) - ))) - transactions))) + + + (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) + ))) + transactions))) - (GET "/transactions/export2" {:keys [query-params identity]} - (assert-admin identity) - (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 "/transactions/export2" {:keys [query-params identity]} + (assert-admin identity) + (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" )) - (into (list) (apply d/q (clojure.edn/read-string (get query-params "query" )) (into [(d/db conn)] (clojure.edn/read-string (get query-params "args" "[]"))))))) + (GET "/raw" {:keys [query-params identity]} + (assert-admin identity) + (log/info "Executing raw query " (get query-params "query" )) + (into (list) (apply d/q (clojure.edn/read-string (get query-params "query" )) (into [(d/db conn)] (clojure.edn/read-string (get query-params "args" "[]")))))))) +(defroutes export-routes + (wrap-routes + (routes + api-key-authed-routes - - wrap-secure) + (wrap-routes admin-only-routes wrap-secure)) + wrap-json-response))