diff --git a/resources/public/output.css b/resources/public/output.css index 4b5aa9b4..e1644126 100644 --- a/resources/public/output.css +++ b/resources/public/output.css @@ -1627,6 +1627,18 @@ input:checked + .toggle-bg { margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse))); } +.space-y-1 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(0.25rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(0.25rem * var(--tw-space-y-reverse)); +} + +.space-y-1\.5 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(0.375rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(0.375rem * var(--tw-space-y-reverse)); +} + .space-y-2 > :not([hidden]) ~ :not([hidden]) { --tw-space-y-reverse: 0; margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse))); @@ -1651,18 +1663,6 @@ input:checked + .toggle-bg { margin-bottom: calc(1.5rem * var(--tw-space-y-reverse)); } -.space-y-1 > :not([hidden]) ~ :not([hidden]) { - --tw-space-y-reverse: 0; - margin-top: calc(0.25rem * calc(1 - var(--tw-space-y-reverse))); - margin-bottom: calc(0.25rem * var(--tw-space-y-reverse)); -} - -.space-y-1\.5 > :not([hidden]) ~ :not([hidden]) { - --tw-space-y-reverse: 0; - margin-top: calc(0.375rem * calc(1 - var(--tw-space-y-reverse))); - margin-bottom: calc(0.375rem * var(--tw-space-y-reverse)); -} - .divide-y > :not([hidden]) ~ :not([hidden]) { --tw-divide-y-reverse: 0; border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse))); @@ -1823,6 +1823,16 @@ input:checked + .toggle-bg { background-color: rgb(153 215 247 / var(--tw-bg-opacity)); } +.bg-blue-300 { + --tw-bg-opacity: 1; + background-color: rgb(102 196 242 / var(--tw-bg-opacity)); +} + +.bg-blue-400 { + --tw-bg-opacity: 1; + background-color: rgb(51 176 238 / var(--tw-bg-opacity)); +} + .bg-blue-50 { --tw-bg-opacity: 1; background-color: rgb(230 245 253 / var(--tw-bg-opacity)); @@ -1833,11 +1843,21 @@ input:checked + .toggle-bg { background-color: rgb(0 156 234 / var(--tw-bg-opacity)); } +.bg-blue-600 { + --tw-bg-opacity: 1; + background-color: rgb(0 125 187 / var(--tw-bg-opacity)); +} + .bg-blue-700 { --tw-bg-opacity: 1; background-color: rgb(0 94 140 / var(--tw-bg-opacity)); } +.bg-blue-800 { + --tw-bg-opacity: 1; + background-color: rgb(0 62 94 / var(--tw-bg-opacity)); +} + .bg-gray-100 { --tw-bg-opacity: 1; background-color: rgb(243 244 246 / var(--tw-bg-opacity)); @@ -1878,11 +1898,36 @@ input:checked + .toggle-bg { background-color: rgb(201 225 171 / var(--tw-bg-opacity)); } +.bg-green-300 { + --tw-bg-opacity: 1; + background-color: rgb(175 211 130 / var(--tw-bg-opacity)); +} + +.bg-green-400 { + --tw-bg-opacity: 1; + background-color: rgb(148 196 88 / var(--tw-bg-opacity)); +} + .bg-green-500 { --tw-bg-opacity: 1; background-color: rgb(121 181 46 / var(--tw-bg-opacity)); } +.bg-green-600 { + --tw-bg-opacity: 1; + background-color: rgb(97 145 37 / var(--tw-bg-opacity)); +} + +.bg-green-700 { + --tw-bg-opacity: 1; + background-color: rgb(73 109 28 / var(--tw-bg-opacity)); +} + +.bg-green-800 { + --tw-bg-opacity: 1; + background-color: rgb(48 72 18 / var(--tw-bg-opacity)); +} + .bg-primary-50 { --tw-bg-opacity: 1; background-color: rgb(242 248 234 / var(--tw-bg-opacity)); diff --git a/src/clj/auto_ap/graphql/ledger.clj b/src/clj/auto_ap/graphql/ledger.clj index 63309729..1a0ba961 100644 --- a/src/clj/auto_ap/graphql/ledger.clj +++ b/src/clj/auto_ap/graphql/ledger.clj @@ -3,7 +3,6 @@ [auto-ap.datomic :refer [audit-transact-batch conn pull-many remove-nils]] [auto-ap.datomic.accounts :as a] - [auto-ap.datomic.clients :as d-clients] [auto-ap.datomic.ledger :as l] [auto-ap.graphql.utils :refer [->graphql @@ -11,15 +10,18 @@ assert-admin assert-can-see-client attach-tracing-resolvers + extract-client-ids result->page]] [auto-ap.ledger :refer [build-account-lookup]] [auto-ap.ledger.reports :as l-reports] + [auto-ap.logging :as alog] [auto-ap.parse.util :as parse] [auto-ap.pdf.ledger :refer [print-balance-sheet print-cash-flows print-journal-detail-report print-pnl]] + [auto-ap.solr :as solr] [auto-ap.time :as atime] [auto-ap.utils :refer [by dollars=]] [clj-time.coerce :as coerce] @@ -28,9 +30,7 @@ [clojure.tools.logging :as log] [com.brunobonacci.mulog :as mu] [datomic.api :as dc] - [iol-ion.tx :refer [random-tempid]] - [auto-ap.solr :as solr] - [auto-ap.logging :as alog]) + [iol-ion.tx :refer [random-tempid]]) (:import (org.apache.commons.codec.binary Base64))) @@ -310,7 +310,9 @@ (->graphql result))) (defn balance-sheet-pdf [context args value] - (let [data (get-balance-sheet context args value) + (let [valid-clients (extract-client-ids (:clients context) + (:client_ids args)) + data (get-balance-sheet context args value) result (print-balance-sheet (:id context) args data)] (->graphql result))) diff --git a/src/clj/auto_ap/graphql/utils.clj b/src/clj/auto_ap/graphql/utils.clj index 56a4497c..fec4e274 100644 --- a/src/clj/auto_ap/graphql/utils.clj +++ b/src/clj/auto_ap/graphql/utils.clj @@ -182,7 +182,7 @@ (sequential? x) - (map x coerce-client-ids) + (mapcat coerce-client-ids x) :else [])) diff --git a/src/clj/auto_ap/pdf/ledger.clj b/src/clj/auto_ap/pdf/ledger.clj index b651d75f..a4070730 100644 --- a/src/clj/auto_ap/pdf/ledger.clj +++ b/src/clj/auto_ap/pdf/ledger.clj @@ -153,7 +153,7 @@ args (assoc args :periods (filter identity (cond-> [(:date args)] (:include-comparison args) (conj (:comparison-date args))))) - clients (pull-many (dc/db conn) [:client/code :client/name :db/id] [(:client-id args)]) + clients (pull-many (dc/db conn) [:client/code :client/name :db/id] (:client-ids args)) data (concat (->> (:balance-sheet-accounts data) (map (fn [b] (assoc b @@ -167,7 +167,6 @@ report (l-reports/summarize-balance-sheet pnl-data) output-stream (ByteArrayOutputStream.)] - (log/info report) (pdf/pdf (-> [{:left-margin 10 :right-margin 10 :top-margin 15 :bottom-margin 15 :size :letter diff --git a/src/clj/auto_ap/routes/graphql.clj b/src/clj/auto_ap/routes/graphql.clj index 441fe6d7..048d36df 100644 --- a/src/clj/auto_ap/routes/graphql.clj +++ b/src/clj/auto_ap/routes/graphql.clj @@ -23,7 +23,6 @@ (let [variables (some-> (query-params "variables") edn/read-string) body (some-> r :body slurp)] - (println "CLIENTS" clients) {:status 200 :body (pr-str (ql/query (:identity r) (if (= request-method :get) (query-params "query") body) (assoc variables diff --git a/src/clj/auto_ap/ssr/company/yodlee.clj b/src/clj/auto_ap/ssr/company/yodlee.clj index fb2401e5..71d58936 100644 --- a/src/clj/auto_ap/ssr/company/yodlee.clj +++ b/src/clj/auto_ap/ssr/company/yodlee.clj @@ -25,7 +25,7 @@ -(defn fastlink-dialog [{:keys [session]}] +(defn fastlink-dialog [{:keys [client]}] (html-response (com/modal {} @@ -39,14 +39,19 @@ (format " fastlink.open({fastLinkURL: '%s', accessToken: '%s', - params: {'configName': 'Aggregation'}}, + params: {'configName': 'Aggregation'}, + onError: function(e) { + console.log(e); + htmx.trigger(\"#yodlee-table\", \"notification\", {value: \"Yodlee returned the following error: '\" + e.message + \"'.\\n\\nYou may want to refresh your browser and try again.\"}); + setTimeout(hideModal, 300); + }}, 'fa-spot'); -" (:yodlee2-fastlink env) (yodlee/get-access-token (:client/code (:client session)))))] +" (:yodlee2-fastlink env) (yodlee/get-access-token (:client/code client))))] ] [:div])))) -(defn reauthenticate [{:keys [session form-params]}] +(defn reauthenticate [{:keys [form-params]}] (html-response (com/modal {} @@ -91,7 +96,6 @@ fastlink.open({fastLinkURL: '%s', :breadcrumbs [[:a {:href (bidi/path-for ssr-routes/only-routes :company)} "My Company"] - [:a {:href (bidi/path-for ssr-routes/only-routes :company-yodlee)} "Yodlee"]] @@ -99,13 +103,20 @@ fastlink.open({fastLinkURL: '%s', :entity-name "Yodlee accounts" :route :company-yodlee-table :action-buttons (fn [request] - [(com/button {:color :primary - :on-click "openFastlink()" - :hx-get (bidi/path-for ssr-routes/only-routes - :company-yodlee-fastlink-dialog) - :hx-target "#modal-holder"} - (com/button-icon {} svg/refresh) - "Link new account")]) + [[:div.flex.flex-col.flex-shrink + [:div.flex-shrink + (com/button {:color :primary + :on-click "openFastlink()" + :disabled (if (:client request) + false + true) + :hx-get (bidi/path-for ssr-routes/only-routes + :company-yodlee-fastlink-dialog) + :hx-target "#modal-holder"} + (com/button-icon {} svg/refresh) + "Link new account")] + (when-not (:client request) + [:div.text-xs "Note: please select a specific customer to link a new account."])]]) :row-buttons (fn [request _] [ (com/button {:hx-put (bidi/path-for ssr-routes/only-routes diff --git a/src/clj/auto_ap/ssr/components/buttons.clj b/src/clj/auto_ap/ssr/components/buttons.clj index 14a7aa1e..40574e20 100644 --- a/src/clj/auto_ap/ssr/components/buttons.clj +++ b/src/clj/auto_ap/ssr/components/buttons.clj @@ -4,12 +4,92 @@ (defn button-icon- [_ i] [:div.h-4.w-4 i]) +(defn bg-colors [color disabled] + (let [base-color (cond (= :primary color) + "green" + (= :secondary color) + "blue" + + (nil? color) + "white" + + :else + color) + disabled-weight (when disabled 400)] + + (format " bg-%s-%d hover:bg-%s-%d focus:ring-%s-%d dark:bg-%s-%d dark:hover:bg-%s-%d " + base-color + (or disabled-weight 500) + + base-color + (or disabled-weight 600) + + base-color + (or disabled-weight 200) + + base-color + (or disabled-weight 600) + + base-color + (or disabled-weight 700) + + ))) + +(defn dark-color-weight [disabled] + (if disabled + 400 + 600)) + +(defn hover-color-weight [disabled] + (if disabled + 400 + 600)) + +(for [color ["green" "blue" "white"] + weight (range 100 900 100)] + (str "bg-" color "-" weight)) +;;ensuring these colors show up +;; => ("bg-green-100" +;; "bg-green-200" +;; "bg-green-300" +;; "bg-green-400" +;; "bg-green-500" +;; "bg-green-600" +;; "bg-green-700" +;; "bg-green-800" +;; "bg-blue-100" +;; "bg-blue-200" +;; "bg-blue-300" +;; "bg-blue-400" +;; "bg-blue-500" +;; "bg-blue-600" +;; "bg-blue-700" +;; "bg-blue-800" +;; "bg-white-100" +;; "bg-white-200" +;; "bg-white-300" +;; "bg-white-400" +;; "bg-white-500" +;; "bg-white-600" +;; "bg-white-700" +;; "bg-white-800") + (defn button- [params & children] + [:button (update params :class #(cond-> % - true (str " focus:ring-4 font-bold rounded-lg text-xs p-3 text-center mr-2 inline-flex items-center hover:scale-105 transition duration-100 justify-center") - (= :secondary (:color params)) (str " text-white bg-blue-500 hover:bg-blue-600 focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700") - (= :primary (:color params)) (str " text-white bg-green-500 hover:bg-green-600 focus:ring-green-300 dark:bg-green-600 dark:hover:bg-green-700 ") + true (str " focus:ring-4 font-bold rounded-lg text-xs p-3 text-center mr-2 inline-flex items-center justify-center" + (bg-colors (:color params) (:disabled params))) + + (not (:disabled params)) + (str " hover:scale-105 transition duration-100") + + (:disabled params) + (str " cursor-not-allowed") + + (not (nil? (:color params))) + (str " text-white ") + (nil? (:color params)) (str " bg-white dark:bg-gray-600 border-gray-300 dark:border-gray-700 text-gray-500 hover:text-gray-800 dark:text-gray-400 dark:hover:text-gray-100 font-medium border border-gray-300 dark:border-gray-700"))) [:div.htmx-indicator.flex.items-center diff --git a/src/clj/auto_ap/yodlee/core2.clj b/src/clj/auto_ap/yodlee/core2.clj index 072dde91..ec4bdcbd 100644 --- a/src/clj/auto_ap/yodlee/core2.clj +++ b/src/clj/auto_ap/yodlee/core2.clj @@ -14,7 +14,8 @@ [datomic.api :as dc] [auto-ap.datomic :refer [conn]] [auto-ap.datomic.clients :as d-clients] - [clojure.string :as str])) + [clojure.string :as str] + [auto-ap.logging :as alog])) ;; switch all of this to use tokens instead of passing around client codes, particularly because the codes ;; need to be tweaked for repeats (defn client-code->login [client-code] @@ -216,10 +217,12 @@ (defn get-access-token [client-code] (try + (alog/info ::getting-access-token :client client-code) (let [cob-session (login-user (client-code->login client-code))] + (alog/info ::got-cob-session :cob-ession cob-session) cob-session) (catch Exception e - (log/error e) + (alog/error ::cant-get-access-token :exception e) (throw e)))) #_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]} diff --git a/src/cljs/auto_ap/views/pages/ledger/balance_sheet.cljs b/src/cljs/auto_ap/views/pages/ledger/balance_sheet.cljs index 86fc526a..532ed631 100644 --- a/src/cljs/auto_ap/views/pages/ledger/balance_sheet.cljs +++ b/src/cljs/auto_ap/views/pages/ledger/balance_sheet.cljs @@ -97,7 +97,7 @@ NOTE: Please review the transactions we may have question for you here: https:// :body [:div [:div "Click " [:a {:href (-> result :balance-sheet-pdf :url) :target "_new"} "here"] " to view it."] - (when (seq (:emails client)) + (when (and (seq (:emails client)) @(re-frame/subscribe [::subs/is-admin?])) [:div "Once you've confirmed you're happy with it, click " [:a {:href (str "mailto:" (str/join ";" (map :email (:emails client))) "?body=" (email-body (-> result :balance-sheet-pdf :url)) "&subject=" (-> result :balance-sheet-pdf :name) " is ready")} @@ -235,9 +235,7 @@ NOTE: Please review the transactions we may have question for you here: https:// [date-picker {:output :cljs-date}]])]] [:div.level-right [:div.buttons - - (when @(re-frame/subscribe [::subs/is-admin?]) - [:button.button.is-secondary {:on-click (dispatch-event [::export-pdf])} "Export"]) + [:button.button.is-secondary {:on-click (dispatch-event [::export-pdf])} "Export"] [:button.button.is-primary "Run"]]]] [:div.report-control-detail {:ref (fn [el] (when (not= @!box el) diff --git a/src/cljs/auto_ap/views/pages/ledger/profit_and_loss.cljs b/src/cljs/auto_ap/views/pages/ledger/profit_and_loss.cljs index c4ecc351..6b584ece 100644 --- a/src/cljs/auto_ap/views/pages/ledger/profit_and_loss.cljs +++ b/src/cljs/auto_ap/views/pages/ledger/profit_and_loss.cljs @@ -112,7 +112,7 @@ NOTE: Please review the transactions we may have question for you here: https:// :body [:div [:div "Click " [:a {:href (-> result :profit-and-loss-pdf :url) :target "_new"} "here"] " to view it."] - (when (and single-client? (seq client-emails)) + (when (and single-client? (seq client-emails) @(re-frame/subscribe [::subs/is-admin?])) [:div "Once you've confirmed you're happy with it, click " [:a {:href (str "mailto:" (str/join ";" (map :email client-emails)) "?body=" (email-body (-> result :profit-and-loss-pdf :url)) "&subject=" (-> result :profit-and-loss-pdf :name) " is ready")} @@ -402,8 +402,7 @@ NOTE: Please review the transactions we may have question for you here: https:// [:div.level-right [:div.buttons - (when @(re-frame/subscribe [::subs/is-admin?]) - [:button.button.is-secondary {:on-click (dispatch-event [::export-pdf])} "Export"]) + [:button.button.is-secondary {:on-click (dispatch-event [::export-pdf])} "Export"] [:button.button.is-primary "Run"]] ]] diff --git a/src/cljs/auto_ap/views/pages/ledger/profit_and_loss_detail.cljs b/src/cljs/auto_ap/views/pages/ledger/profit_and_loss_detail.cljs index 559f2882..44bf90ad 100644 --- a/src/cljs/auto_ap/views/pages/ledger/profit_and_loss_detail.cljs +++ b/src/cljs/auto_ap/views/pages/ledger/profit_and_loss_detail.cljs @@ -94,7 +94,7 @@ NOTE: Please review the transactions we may have question for you here: https:// :body [:div [:div "Click " [:a {:href (-> result :journal-detail-report-pdf :url) :target "_new"} "here"] " to view it."] - (when (and single-client? (seq client-emails)) + (when (and single-client? (seq client-emails) @(re-frame/subscribe [::subs/is-admin?])) [:div "Once you've confirmed you're happy with it, click " [:a {:href (str "mailto:" (str/join ";" (map :email client-emails)) "?body=" (email-body (-> result :journal-detail-report-pdf :url)) "&subject=" (-> result :journal-detail-report-pdf :name) " is ready")} @@ -181,8 +181,7 @@ NOTE: Please review the transactions we may have question for you here: https:// [date-picker {:output :cljs-date}]]] [:div.level-right [:div.buttons - (when @(re-frame/subscribe [::subs/is-admin?]) - [:button.button.is-secondary {:on-click (dispatch-event [::export-pdf])} "Export"]) + [:button.button.is-secondary {:on-click (dispatch-event [::export-pdf])} "Export"] [:button.button.is-primary "Run"]]]]] [:div.report-control-detail {:ref (fn [el] (when (not= @!box el)