From 7ac17c9cbc3edfbdf1fbe4993c0aa87212f4b5df Mon Sep 17 00:00:00 2001 From: Bryce Covert Date: Tue, 4 Jun 2019 07:08:10 -0700 Subject: [PATCH] bank accounts can now have locations. --- data/etc/nginx/conf.d/default.conf | 15 +++++++ src/clj/auto_ap/datomic/migrate.clj | 1 + .../datomic/migrate/add_general_ledger.clj | 6 +++ src/clj/auto_ap/datomic/transactions.clj | 4 +- src/clj/auto_ap/graphql.clj | 4 +- src/clj/auto_ap/graphql/clients.clj | 1 + src/clj/auto_ap/graphql/transactions.clj | 4 +- src/clj/auto_ap/yodlee/import.clj | 8 ++-- src/cljs/auto_ap/events.cljs | 4 +- src/cljs/auto_ap/subs.cljs | 10 +++++ .../auto_ap/views/pages/admin/clients.cljs | 43 +++++++++++++++++-- .../auto_ap/views/pages/admin/rules/form.cljs | 2 +- test/clj/auto_ap/graphql.clj | 6 +-- 13 files changed, 90 insertions(+), 18 deletions(-) diff --git a/data/etc/nginx/conf.d/default.conf b/data/etc/nginx/conf.d/default.conf index 88bba364..11119d0b 100644 --- a/data/etc/nginx/conf.d/default.conf +++ b/data/etc/nginx/conf.d/default.conf @@ -50,3 +50,18 @@ server { access_log /var/log/nginx/access.log vhost; return 503; } +# local.app.integreatconsult.com +upstream local.app.integreatconsult.com { + ## Can be connected with "integreat_default" network + # integreat_app_1 + server 172.30.0.3:3000; +} +server { + server_name local.app.integreatconsult.com; + listen 80 ; + access_log /var/log/nginx/access.log vhost; + location / { + proxy_pass http://local.app.integreatconsult.com; + include /etc/nginx/vhost.d/default_location; + } +} diff --git a/src/clj/auto_ap/datomic/migrate.clj b/src/clj/auto_ap/datomic/migrate.clj index 200279fb..800ba9d0 100644 --- a/src/clj/auto_ap/datomic/migrate.clj +++ b/src/clj/auto_ap/datomic/migrate.clj @@ -132,6 +132,7 @@ :auto-ap/convert-transactions {:txes-fn `add-general-ledger/convert-transactions :requires [:auto-ap/add-external-id-to-ledger]} :auto-ap/add-transaction-rules {:txes add-general-ledger/add-transaction-rules :requires [:auto-ap/convert-transactions]} + :auto-ap/add-bank-account-locations {:txes add-general-ledger/add-bank-account-locations :requires [:auto-ap/add-transaction-rules]} diff --git a/src/clj/auto_ap/datomic/migrate/add_general_ledger.clj b/src/clj/auto_ap/datomic/migrate/add_general_ledger.clj index 5b860593..979c3255 100644 --- a/src/clj/auto_ap/datomic/migrate/add_general_ledger.clj +++ b/src/clj/auto_ap/datomic/migrate/add_general_ledger.clj @@ -400,6 +400,12 @@ {:db/ident :transaction-approval-status/excluded} ]]) +(def add-bank-account-locations + [[{:db/ident :bank-account/locations + :db/valueType :db.type/string + :db/cardinality :db.cardinality/many + :db/doc "Which bank accounts this bank account is valid for"}]]) + (def add-credit-bank-account [[{:db/ident :bank-account-type/credit}]]) diff --git a/src/clj/auto_ap/datomic/transactions.clj b/src/clj/auto_ap/datomic/transactions.clj index 20c57d2f..a6ef7b84 100644 --- a/src/clj/auto_ap/datomic/transactions.clj +++ b/src/clj/auto_ap/datomic/transactions.clj @@ -94,7 +94,7 @@ (defn graphql-results [ids db args] (let [results (->> (d/pull-many db '[* {:transaction/client [:client/name :db/id :client/code] :transaction/approval-status [:db/ident :db/id] - :transaction/bank-account [:bank-account/name :bank-account/code :bank-account/yodlee-account-id :db/id] + :transaction/bank-account [:bank-account/name :bank-account/code :bank-account/yodlee-account-id :db/id :bank-account/locations] :transaction/vendor [:db/id :vendor/name] :transaction/matched-rule [:db/id :transaction-rule/note] :transaction/accounts [:transaction-account/amount @@ -123,7 +123,7 @@ (d/pull (d/db (d/connect uri)) '[* {:transaction/client [:client/name :db/id :client/code :client/locations] :transaction/approval-status [:db/ident :db/id] - :transaction/bank-account [:bank-account/name :bank-account/code :bank-account/yodlee-account-id :db/id] + :transaction/bank-account [:bank-account/name :bank-account/code :bank-account/yodlee-account-id :db/id :bank-account/locations] :transaction/vendor [:db/id :vendor/name] :transaction/matched-rule [:db/id :transaction-rule/note] :transaction/accounts [:transaction-account/amount diff --git a/src/clj/auto_ap/graphql.clj b/src/clj/auto_ap/graphql.clj index 3514e1a0..669f229c 100644 --- a/src/clj/auto_ap/graphql.clj +++ b/src/clj/auto_ap/graphql.clj @@ -84,7 +84,8 @@ :name {:type 'String} :bank_code {:type 'String} :bank_name {:type 'String} - :yodlee_account_id {:type 'Int}}} + :yodlee_account_id {:type 'Int} + :locations {:type '(list String)}}} :balance_sheet_account {:fields {:id {:type 'String} :amount {:type 'String} @@ -470,6 +471,7 @@ :bank_code {:type 'String} :routing {:type 'String} :bank_name {:type 'String} + :locations {:type '(list String)} :yodlee_account_id {:type 'Int}}} :edit_user {:fields {:id {:type :id} diff --git a/src/clj/auto_ap/graphql/clients.clj b/src/clj/auto_ap/graphql/clients.clj index dffdda2b..a6893c09 100644 --- a/src/clj/auto_ap/graphql/clients.clj +++ b/src/clj/auto_ap/graphql/clients.clj @@ -51,6 +51,7 @@ :bank-account/number (:number %) :bank-account/check-number (:check_number %) :bank-account/sort-order (:sort_order %) + :bank-account/locations (:locations %) :bank-account/yodlee-account-id (:yodlee_account_id %) :bank-account/type (keyword "bank-account-type" (name (:type %))) diff --git a/src/clj/auto_ap/graphql/transactions.clj b/src/clj/auto_ap/graphql/transactions.clj index 6c9a9162..aa8d5160 100644 --- a/src/clj/auto_ap/graphql/transactions.clj +++ b/src/clj/auto_ap/graphql/transactions.clj @@ -138,8 +138,8 @@ :transaction/amount (:transaction/amount transaction)} transaction-rule - ;; TODO use bank account locations as well - (-> transaction :transaction/client :client/locations)))] + (or (-> transaction :transaction/bank-account :bank-account/locations) + (-> transaction :transaction/client :client/locations))))] (map (fn [x] [:db/retractEntity (:db/id x)] ) (:transaction/accounts transaction))))) (-> (d-transactions/get-by-id transaction_id) diff --git a/src/clj/auto_ap/yodlee/import.clj b/src/clj/auto_ap/yodlee/import.clj index 0e1e0d59..b24701fc 100644 --- a/src/clj/auto_ap/yodlee/import.clj +++ b/src/clj/auto_ap/yodlee/import.clj @@ -11,7 +11,8 @@ [auto-ap.datomic.clients :as d-clients] [auto-ap.time :as time] [auto-ap.datomic.transaction-rules :as tr] - [auto-ap.rule-matching :as rm])) + [auto-ap.rule-matching :as rm] + [clojure.string :as str])) @@ -77,7 +78,7 @@ bank-account-id (:db/id bank-account) client (:client/_bank-accounts bank-account) client-id (:db/id client) - valid-locations (:client/locations client) + valid-locations (or (:bank-account/locations bank-account) (:client/locations client)) check (transaction->payment transaction check-number client-id bank-account-id amount id)] :when (and client-id (not (existing (sha-256 (str id)))))] @@ -87,7 +88,8 @@ :id (sha-256 (str id)) :account-id account-id :date (coerce/to-date (time/parse date "YYYY-MM-dd")) - :yodlee-merchant (when (and merchant-id merchant-name) + :yodlee-merchant (when (and merchant-id merchant-name (not (str/blank? merchant-id))) + {:yodlee-merchant/yodlee-id merchant-id :yodlee-merchant/name merchant-name}) :amount (double amount) diff --git a/src/cljs/auto_ap/events.cljs b/src/cljs/auto_ap/events.cljs index e107bc15..58e2ce82 100644 --- a/src/cljs/auto_ap/events.cljs +++ b/src/cljs/auto_ap/events.cljs @@ -42,7 +42,7 @@ :graphql {:token token :query-obj {:venia/queries [[:client - [:id :name :code :email :locations [:bank-accounts [:id :code :number :bank-name :bank-code :check-number :name :routing :type :sort-order :visible :yodlee-account-id] ] + [:id :name :code :email :locations [:bank-accounts [:id :code :number :bank-name :bank-code :check-number :name :routing :type :sort-order :visible :yodlee-account-id :locations] ] [:address [:street1 :street2 :city :state :zip]]]] [:vendor [:id :name :hidden [:default-account [:name :id :location]] [:primary-contact [:name :phone :email :id]] [:secondary-contact [:id :name :phone :email]] :print-as :invoice-reminder-schedule :code]] @@ -65,7 +65,7 @@ (fn [{:keys [db]} [_ token user]] {:graphql {:token token :query-obj {:venia/queries [[:client - [:id :name :code [:address [:street1 :street2 :city :state :zip]] [:bank-accounts [:id :code :number :bank-name :bank-code :check-number :name :routing :type :sort-order :visible :yodlee-account-id] ]]] + [:id :name :code [:address [:street1 :street2 :city :state :zip]] [:bank-accounts [:id :code :number :bank-name :bank-code :check-number :name :routing :type :sort-order :visible :yodlee-account-id :locations] ]]] [:vendor [:id :name :hidden [:default-account [:name :id :location]] [:primary-contact [:name :phone :email :id]] [:secondary-contact [:id :name :phone :email]] :print-as :invoice-reminder-schedule :code]] [:accounts [:numeric-code :name :location :type :account_set :id]]]} diff --git a/src/cljs/auto_ap/subs.cljs b/src/cljs/auto_ap/subs.cljs index 8f513384..742e31e8 100644 --- a/src/cljs/auto_ap/subs.cljs +++ b/src/cljs/auto_ap/subs.cljs @@ -74,6 +74,16 @@ (fn [db [_ client]] (:locations (get (:clients db) (or client (:client db)))))) +(re-frame/reg-sub + ::locations-for-client-or-bank-account + (fn [db [_ client-id bank-account-id]] + (let [client (get (:clients db) (or client (:client db))) + client-locations (:locations client) + bank-account-locations (-> (by :id (:bank-accounts client)) + (get bank-account-id) + :locations)] + (or bank-account-locations client-locations)))) + (re-frame/reg-sub ::clients-by-id (fn [db] diff --git a/src/cljs/auto_ap/views/pages/admin/clients.cljs b/src/cljs/auto_ap/views/pages/admin/clients.cljs index 1911a79b..afe6c802 100644 --- a/src/cljs/auto_ap/views/pages/admin/clients.cljs +++ b/src/cljs/auto_ap/views/pages/admin/clients.cljs @@ -47,7 +47,7 @@ :city (:city (:address new-client-data)) :state (:state (:address new-client-data)) :zip (:zip (:address new-client-data))} - :bank-accounts (map (fn [{:keys [number name check-number type id code bank-name routing bank-code new? sort-order visible yodlee-account-id]}] + :bank-accounts (map (fn [{:keys [number name check-number type id code bank-name routing bank-code new? sort-order visible yodlee-account-id locations]}] {:number number :name name :check-number check-number @@ -55,6 +55,7 @@ :id id :sort-order sort-order :visible visible + :locations (vec locations) :yodlee-account-id (when yodlee-account-id (js/parseInt yodlee-account-id)) :code (if new? @@ -85,7 +86,7 @@ :operation/name "EditClient"} :venia/queries [{:query/data [:edit-client {:edit-client new-client-req} - [:id :name :code :email :locations [:address [:street1 :street2 :city :state :zip]] [:bank-accounts [:id :number :check-number :name :code :bank-code :bank-name :routing :type :visible :yodlee-account-id :sort-order]]]]}]} + [:id :name :code :email :locations [:address [:street1 :street2 :city :state :zip]] [:bank-accounts [:id :number :check-number :name :code :bank-code :bank-name :routing :type :visible :yodlee-account-id :sort-order :locations]]]]}]} :on-success [::save-complete] :on-error [::forms/save-error ::new-client]}} {:db new-client-form})))) @@ -107,6 +108,15 @@ (update :locations conj (:location client)) (dissoc :location)))) +(re-frame/reg-event-db + ::add-location-to-bank-account + [(forms/in-form ::new-client) (re-frame/path [:data])] + (fn [client [_ which-account]] + (println client which-account) + (-> client + (update-in [:bank-accounts which-account :locations] #(conj (or % #{}) (get-in client [:bank-accounts which-account :location-select]))) + (update-in [:bank-accounts which-account] dissoc :location-select)))) + (re-frame/reg-event-db ::add-new-bank-account [(forms/in-form ::new-client) (re-frame/path [:data])] @@ -306,7 +316,9 @@ :type "text" :field [:bank-accounts sort-order :yodlee-account-id] :event change-event - :subscription new-client}]]]]]) + :subscription new-client}]]]] + + ]) (when (#{:credit ":credit"} type ) [:div @@ -340,7 +352,30 @@ :type "text" :field [:bank-accounts sort-order :yodlee-account-id] :event change-event - :subscription new-client}]]]]])]) + :subscription new-client}]]]]]) + [:div.field + [:label.label "Locations"] + [:div.control + [:p.help "If this account is location-specific, add the valid locations"] + [:div.field.has-addons + [:p.control + [:div.select + [bind-field + [:select {:type "select" + :style {:width "7em"} + :field [:bank-accounts sort-order :location-select] + :allow-nil? true + :spec (set (get-in new-client [:locations])) + :event change-event + :subscription new-client} + (map (fn [l] ^{:key l} [:option {:value l} l]) (get-in new-client [:locations]))]]]] + [:p.control {:on-click (dispatch-event [::add-location-to-bank-account sort-order]) } [:a.button "Add"]]]] + + (if-let [locations (seq (get-in new-client [:bank-accounts sort-order :locations]))] + [:ul + (for [location locations] + ^{:key location} [:li location ])] + [:i "This account applies to all locations"])]]) (when active? [:footer.card-footer diff --git a/src/cljs/auto_ap/views/pages/admin/rules/form.cljs b/src/cljs/auto_ap/views/pages/admin/rules/form.cljs index 1315d1f2..f7769914 100644 --- a/src/cljs/auto_ap/views/pages/admin/rules/form.cljs +++ b/src/cljs/auto_ap/views/pages/admin/rules/form.cljs @@ -289,7 +289,7 @@ [expense-accounts-field {:type "expense-accounts" :descriptor "account asssignment" :percentage-only? true - :locations (into ["Shared"] @(re-frame/subscribe [::subs/locations-for-client (:id (:client data))])) + :locations (into ["Shared"] @(re-frame/subscribe [::subs/locations-for-client-or-bank-account (:id (:client data)) (:id (:bank-account data))])) :max 100 :field [:accounts]}]] diff --git a/test/clj/auto_ap/graphql.clj b/test/clj/auto_ap/graphql.clj index f93d2407..68a3622a 100644 --- a/test/clj/auto_ap/graphql.clj +++ b/test/clj/auto_ap/graphql.clj @@ -189,7 +189,7 @@ (testing "based on date " (is (= [{:id "2019-01-15 nonmatching-desc 2"}] (rule-test {:dom-gte 14 :dom-lte 16}))) (is (= [{:id "2019-01-15 nonmatching-desc 2"}] (rule-test {:dom-gte 14}))) - (is (= [{:id "2019-01-05 matching-desc 1"} {:id "2019-01-15 nonmatching-desc 2"}] (rule-test {:dom-lte 15}))) + (is (= (set [{:id "2019-01-05 matching-desc 1"} {:id "2019-01-15 nonmatching-desc 2"}]) (set (rule-test {:dom-lte 15})))) (is (= [{:id "2019-01-15 nonmatching-desc 2"}] (rule-test {:dom-gte 15}))) (is (= [{:id "2019-01-15 nonmatching-desc 2"}] (rule-test {:dom-gte 15 :dom-lte 15})))) @@ -198,8 +198,8 @@ (testing "based on amount" (is (= [{:id "2019-01-05 matching-desc 1"}] (rule-test {:amount-gte 1.0 :amount-lte 1.0}))) - (is (= [{:id "2019-01-05 matching-desc 1"} {:id "2019-01-15 nonmatching-desc 2"}] (rule-test {:amount-gte 1.0 })) ) - (is (= [{:id "2019-01-05 matching-desc 1"} {:id "2019-01-15 nonmatching-desc 2"}] (rule-test {:amount-lte 2.0 })) )) + (is (= (set [{:id "2019-01-05 matching-desc 1"} {:id "2019-01-15 nonmatching-desc 2"}]) (set (rule-test {:amount-gte 1.0 }))) ) + (is (= (set [{:id "2019-01-05 matching-desc 1"} {:id "2019-01-15 nonmatching-desc 2"}]) (set (rule-test {:amount-lte 2.0 }))) )) (testing "based on client" (is (= [{:id "2019-01-05 matching-desc 1"}] (rule-test {:client-id client-1})))