From a7aa5f3452416c96155be6ceff9b2552faa2b705 Mon Sep 17 00:00:00 2001 From: Bryce Covert Date: Sat, 6 Apr 2019 14:13:33 -0700 Subject: [PATCH] protoype. --- src/clj/auto_ap/graphql.clj | 2 + src/clj/auto_ap/yodlee/core.clj | 27 ++-- src/clj/auto_ap/yodlee/import.clj | 3 +- .../auto_ap/views/pages/transactions.cljs | 138 ++++++++++++++---- 4 files changed, 131 insertions(+), 39 deletions(-) diff --git a/src/clj/auto_ap/graphql.clj b/src/clj/auto_ap/graphql.clj index 53f4b013..0fcb90f9 100644 --- a/src/clj/auto_ap/graphql.clj +++ b/src/clj/auto_ap/graphql.clj @@ -130,8 +130,10 @@ :description_original {:type 'String} :description_simple {:type 'String} :status {:type 'String} + :merchant_name {:type 'String} :client {:type :client} :payment {:type :payment} + :vendor {:type :vendor} :bank_account {:type :bank_account} :date {:type 'String} :post_date {:type 'String}}} diff --git a/src/clj/auto_ap/yodlee/core.clj b/src/clj/auto_ap/yodlee/core.clj index e7c04a43..1881833b 100644 --- a/src/clj/auto_ap/yodlee/core.clj +++ b/src/clj/auto_ap/yodlee/core.clj @@ -25,18 +25,21 @@ :cobSession)) -(defn login-user [cob-session] - (-> (str (:yodlee-base-url env) "/user/login") - (client/post {:headers (merge base-headers {"Authorization" (auth-header cob-session)}) - :body - (json/write-str {:user {:loginName (:yodlee-user-login env) - :password (:yodlee-user-password env) - :locale "en_US"}}) - :as :json}) - :body - :user - :session - :userSession)) +(defn login-user + ([cob-session] (:yodlee-user-login env) (:yodlee-user-password env)) + ([cob-session user password] + (-> (str (:yodlee-base-url env) "/user/login") + (client/post {:headers (merge base-headers {"Authorization" (auth-header cob-session)}) + :body + (json/write-str {:user {:loginName user + :password password + :locale "en_US"}}) + :as :json}) + :body + :user + :session + :userSession)) + ) (defn get-accounts [] (let [cob-session (login-cobrand) diff --git a/src/clj/auto_ap/yodlee/import.clj b/src/clj/auto_ap/yodlee/import.clj index 942e0485..368f7365 100644 --- a/src/clj/auto_ap/yodlee/import.clj +++ b/src/clj/auto_ap/yodlee/import.clj @@ -83,8 +83,7 @@ :payment (when check-id {:db/id check-id :payment/status :payment-status/cleared} - ) - })] + )})] (d/transact (d/connect uri)))) diff --git a/src/cljs/auto_ap/views/pages/transactions.cljs b/src/cljs/auto_ap/views/pages/transactions.cljs index b1173d1b..3baa67b0 100644 --- a/src/cljs/auto_ap/views/pages/transactions.cljs +++ b/src/cljs/auto_ap/views/pages/transactions.cljs @@ -4,10 +4,12 @@ [auto-ap.entities.vendors :as vendor] [reagent.core :as reagent] [goog.string :as gstring] + [auto-ap.forms :as forms] [auto-ap.views.components.sorter :refer [sorted-column]] + [auto-ap.views.components.typeahead :refer [typeahead]] [auto-ap.views.components.modal :refer [action-modal]] [auto-ap.views.components.paginator :refer [paginator]] - [auto-ap.views.components.layouts :refer [side-bar-layout]] + [auto-ap.views.components.layouts :refer [side-bar-layout appearing-side-bar]] [auto-ap.views.components.bank-account-filter :refer [bank-account-filter]] [auto-ap.events :as events] [auto-ap.views.utils :refer [dispatch-event date->str bind-field nf]] @@ -38,6 +40,7 @@ (assoc params :client-id (:id @(re-frame/subscribe [::subs/client]))) [[:transactions [:id :amount + [:vendor [:name :id]] :date :post_date :status @@ -57,6 +60,12 @@ (assoc ::transaction-page (first (:transaction-page data))) (assoc-in [:status :loading] false)))) +(re-frame/reg-event-db + ::transaction-editing + (fn [db [_ which]] + (-> db + (forms/start-form ::edit-transaction {})))) + (re-frame/reg-event-fx ::invalidated (fn [cofx [_ params]] @@ -98,13 +107,22 @@ :sort-by sort-by :asc asc} "Client"]) - + + [sorted-column {:on-sort opc + :style {:width percentage-size :cursor "pointer"} + :sort-key "description-original" + :sort-by sort-by + :asc asc} + "Vendor"] + [sorted-column {:on-sort opc :style {:width percentage-size :cursor "pointer"} :sort-key "description-original" :sort-by sort-by :asc asc} "Description"] + + [sorted-column {:on-sort opc :style {:width "8em" :cursor "pointer"} :sort-key "date" @@ -126,30 +144,27 @@ :asc asc} "Status"] [:th {:width percentage-size} "Bank account"] - [:th {:width percentage-size} "Yodlee bank account"] - - [:th {:style {:width "10em"}} "" ]]] [:tbody (if (:loading @status) [:tr [:td {:col-span 5} [:i.fa.fa-spin.fa-spinner]]] - (for [{:keys [client check status bank-account description-original date amount id ] :as i} (:transactions @transaction-page)] + (for [{:keys [client vendor check status bank-account description-original date amount id ] :as i} (:transactions @transaction-page)] ^{:key id} [:tr {:class (:class i)} - (when-not selected-client [:td (:name client)]) + [:td (if vendor + (:name vendor) + (str "Merchant '" "Hello" "'"))] [:td description-original] [:td (date->str date) ] [:td.has-text-right (nf amount )] [:td status] [:td (:name bank-account )] - [:td (:yodlee-account-id bank-account )] - [:td - + [:a.button {:on-click (dispatch-event [::transaction-editing id])} [:span [:span.icon [:i.fa.fa-pencil]]]] (when check [:a.tag {:href (:s3-url check) :target "_new"} [:i.fa.fa-money-check] [:span.icon [:i.fa.fa-money]] (str " " (:check-number check) " (" (gstring/format "$%.2f" amount ) ")")])] ]))]]])))) @@ -216,13 +231,11 @@ (let [notification (re-frame/subscribe [::notification]) current-client @(re-frame/subscribe [::subs/client]) user @(re-frame/subscribe [::subs/user])] - [:div [:h1.title "Transactions"] (when (= "admin" (:user/role user)) (list (when (:message @notification) - (list [:div.notification (:message @notification) @@ -230,16 +243,16 @@ (when (seq (:errors @notification)) [:div.notification.is-danger [:h3 (count (:errors @notification)) " errors:"] - [:ul (for [transaction (:errors @notification) error (:errors transaction)] - [:li (:description-original transaction) "-" (:details error)]) - ]]))) - + [:li (:description-original transaction) "-" (:details error)])]]))) [:div.is-pulled-right - [:button.button.is-danger {:on-click (dispatch-event [::manual-yodlee-import])} - "Manual Yodlee Import"]])) + [:div.buttons + [:button.button.is-danger {:on-click (dispatch-event [::manual-yodlee-import])} + "Manage Rules"] + [:button.button.is-danger {:on-click (dispatch-event [::manual-yodlee-import])} + "Manual Yodlee Import"]]])) [transaction-table {:id :transactions :params (re-frame/subscribe [::params]) :transaction-page (re-frame/subscribe [::transaction-page]) @@ -248,13 +261,88 @@ (re-frame/dispatch [::params-change params]))}] [manual-yodlee-import-modal]])) {:component-will-mount #(re-frame/dispatch-sync [::params-change {}]) })) + + +(defn edit-transaction-form [] + [forms/side-bar-form {:form ::edit-transaction } + (let [{:keys [data active? error id]} @(re-frame/subscribe [::forms/form ::edit-transaction]) + data (assoc data :merchant-name "Hello") ;; TODO - just until merchant is added + current-client @(re-frame/subscribe [::subs/client]) + change-event [::forms/change ::edit-transaction]] + ^{:key id} + [:form { :on-submit (fn [e] + (when (.-stopPropagation e) + (.stopPropagation e) + (.preventDefault e)) + (re-frame/dispatch-sync [::edit-transaction-saving]))} + [:h1.title.is-2 "Edit Transaction"] + + [:div.notification + [:p "This transaction matches Invoice 'ABC' for 'DBI Beverages'. " [:a "Create payment and match"] "."]] + + + [:div.field + [:p.help "Merchant"] + [:div.control + [bind-field + [:input.input {:type "text" + :field [:merchant-name] + :disabled "disabled" + :subscription data}]]]] + + + [:div.field + [:p.help "Vendor"] + [:div.control + [bind-field + [typeahead {:matches (map (fn [x] [(:id x) (:name x)]) @(re-frame/subscribe [::subs/vendors])) + :type "typeahead" + :auto-focus (if @(re-frame/subscribe [::subs/client]) true false) + :field [:vendor-id] + :text-field [:vendor-name] + :event change-event + :subscription data}]]]] + + [:div.field + + [:p.control + [:label.checkbox + [:input.checkbox {:type "checkbox" + :field [:always-map] + :subscription data}] + " Always match Merchant '" (:merchant-name data) "' to '" (:vendor-name data) "'" ]]] + + [:div.field + [:p.help "Credit Account"] + [:div.control + [bind-field + [typeahead {:matches (map (fn [x] [(:id x) (str (:id x) " - " (:name x))]) @(re-frame/subscribe [::subs/chooseable-expense-accounts])) + :type "typeahead" + :field [:expense-account-id] + :event [::change id] + :subscription data}]]]] + + (when error + ^{:key error} [:div.notification.is-warning.animated.fadeInUp + error]) + + [:button.button.is-medium.is-primary.is-fullwidth {#_#_:disabled (if @(re-frame/subscribe [::can-submit-edit-invoice]) + "" + "disabled") + :class (str @(re-frame/subscribe [::forms/loading-class ::edit-transaction]) + (when error " animated shake"))} "Save"] + ])] + ) + (defn transactions-page [] - [side-bar-layout {:side-bar [:div - [:p.menu-label "Bank Account"] + (let [{transaction-bar-active? :active?} @(re-frame/subscribe [::forms/form ::edit-transaction])] + [side-bar-layout {:side-bar [:div + [:p.menu-label "Bank Account"] - [:div - [bank-account-filter {:on-change-event [::change-selected-bank-account] - :value (:bank-acount-filter @(re-frame/subscribe [::transaction-page])) - :bank-accounts @(re-frame/subscribe [::subs/bank-accounts])}]]] - :main [transactions-content]}]) + [:div + [bank-account-filter {:on-change-event [::change-selected-bank-account] + :value (:bank-acount-filter @(re-frame/subscribe [::transaction-page])) + :bank-accounts @(re-frame/subscribe [::subs/bank-accounts])}]]] + :main [transactions-content] + :right-side-bar [appearing-side-bar {:visible? transaction-bar-active?} [edit-transaction-form]]}]))