diff --git a/src/clj/auto_ap/datomic.clj b/src/clj/auto_ap/datomic.clj index 21e9c5c2..e7d83f66 100644 --- a/src/clj/auto_ap/datomic.clj +++ b/src/clj/auto_ap/datomic.clj @@ -24,7 +24,7 @@ (let [result (reduce-kv (fn [m k v] - (if v + (if (not (nil? v)) (assoc m k v) m )) diff --git a/src/clj/auto_ap/datomic/clients.clj b/src/clj/auto_ap/datomic/clients.clj index e25fa9d9..d82d8cb0 100644 --- a/src/clj/auto_ap/datomic/clients.clj +++ b/src/clj/auto_ap/datomic/clients.clj @@ -11,9 +11,12 @@ (map (fn [c] (update c :client/bank-accounts (fn [bas] - (map (fn [ba] - (update ba :bank-account/type :db/ident )) - bas))))))) + (map (fn [i ba] + (-> ba + (update :bank-account/type :db/ident ) + (update :bank-account/sort-order (fn [so] (or so i))))) + (range) bas))))) + )) (defn get-by-id [id] (->> (d/query (-> {:query {:find ['(pull ?e [*])] diff --git a/src/clj/auto_ap/datomic/migrate.clj b/src/clj/auto_ap/datomic/migrate.clj index 62f946d1..fb0cfe97 100644 --- a/src/clj/auto_ap/datomic/migrate.clj +++ b/src/clj/auto_ap/datomic/migrate.clj @@ -63,6 +63,9 @@ :auto-ap/add-import-status-existing-invoices {:txes-fn 'auto-ap.datomic.migrate.invoice-converter/add-import-status-existing-invoices :requires [:auto-ap/add-import-status]} :auto-ap/fix-check-numbers {:txes-fn 'auto-ap.datomic.migrate.check-numbers/fix-check-numbers :requires [:auto-ap/add-import-status-existing-invoices]} :auto-ap/add-new-vendors {:txes-fn 'auto-ap.datomic.migrate.add-new-vendors/add-new-vendors :requires [:auto-ap/fix-check-numbers]} + :auto-ap/add-account-visibility-fields {:txes-fn 'auto-ap.datomic.migrate.account-sorting/add-account-visibility-fields :requires [:auto-ap/add-new-vendors]} + :auto-ap/make-every-account-visible {:txes-fn 'auto-ap.datomic.migrate.account-sorting/make-every-account-visible :requires [:auto-ap/add-account-visibility-fields]} + }] (println "Conforming database...") (println (c/ensure-conforms conn norms-map)) diff --git a/src/clj/auto_ap/datomic/migrate/account_sorting.clj b/src/clj/auto_ap/datomic/migrate/account_sorting.clj new file mode 100644 index 00000000..3a184146 --- /dev/null +++ b/src/clj/auto_ap/datomic/migrate/account_sorting.clj @@ -0,0 +1,27 @@ +(ns auto-ap.datomic.migrate.account-sorting + (:require [datomic.api :as d])) + + +(defn add-account-visibility-fields [conn] + [[ + {:db/ident :bank-account/visible + :db/valueType :db.type/boolean + :db/cardinality :db.cardinality/one + :db/doc "Whether this bank account is visible"} + {:db/ident :bank-account/sort-order + :db/valueType :db.type/long + :db/cardinality :db.cardinality/one + :db/doc "The sort order of the bank account"}]]) + +(defn make-every-account-visible [conn] + (let [all-account-ids (d/query + {:query {:find ['?e] + :in ['$] + :where ['[?e :bank-account/code]]} + :args [(d/db conn)]} + )] + [(map + (fn [[account-id]] + {:db/id account-id :bank-account/visible true} + ) + all-account-ids)])) diff --git a/src/clj/auto_ap/graphql.clj b/src/clj/auto_ap/graphql.clj index c8e05c92..73e555b0 100644 --- a/src/clj/auto_ap/graphql.clj +++ b/src/clj/auto_ap/graphql.clj @@ -56,6 +56,8 @@ {:fields {:id {:type :id } :type {:type :ident} :number {:type 'String} + :sort_order {:type 'Int} + :visible {:type 'Boolean} :routing {:type 'String} :code {:type 'String} :check_number {:type 'Int} @@ -295,6 +297,8 @@ :type {:type :bank_account_type} :number {:type 'String} :check_number {:type 'Int} + :visible {:type 'Boolean} + :sort_order {:type 'Int} :name {:type 'String} :bank_code {:type 'String} :routing {:type 'String} diff --git a/src/clj/auto_ap/graphql/clients.clj b/src/clj/auto_ap/graphql/clients.clj index b10cc038..dffdda2b 100644 --- a/src/clj/auto_ap/graphql/clients.clj +++ b/src/clj/auto_ap/graphql/clients.clj @@ -24,6 +24,7 @@ (let [client (when (:id edit_client) (d-clients/get-by-id (:id edit_client))) id (or (:db/id client) "new-client") _ (println id) + _ (println edit_client) transactions [(remove-nils {:db/id id :client/code (if (str/blank? (:client/code client)) (:code edit_client) @@ -46,8 +47,10 @@ :bank-account/routing (:routing %) :bank-account/name (:name %) + :bank-account/visible (:visible %) :bank-account/number (:number %) :bank-account/check-number (:check_number %) + :bank-account/sort-order (:sort_order %) :bank-account/yodlee-account-id (:yodlee_account_id %) :bank-account/type (keyword "bank-account-type" (name (:type %))) diff --git a/src/cljs/auto_ap/events.cljs b/src/cljs/auto_ap/events.cljs index 467d33cf..94623deb 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] ] + [:id :name :code :email :locations [:bank-accounts [:id :code :number :bank-name :bank-code :check-number :name :routing :type :sort-order :visible] ] [:address [:street1 :street2 :city :state :zip]]]] [:vendor [:id :name :default-expense-account [: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] ]]] + [: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] ]]] [:vendor [:id :name :default-expense-account [:primary-contact [:name :phone :email :id]] [:secondary-contact [:id :name :phone :email]] :print-as :invoice-reminder-schedule :code]]]} diff --git a/src/cljs/auto_ap/views/pages/admin/clients.cljs b/src/cljs/auto_ap/views/pages/admin/clients.cljs index 60f6fd6f..86c9e351 100644 --- a/src/cljs/auto_ap/views/pages/admin/clients.cljs +++ b/src/cljs/auto_ap/views/pages/admin/clients.cljs @@ -75,12 +75,14 @@ :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?]}] + :bank-accounts (map (fn [{:keys [number name check-number type id code bank-name routing bank-code new? sort-order visible]}] {:number number :name name :check-number check-number :type type :id id + :sort-order sort-order + :visible visible :code (if new? (str (:code new-client-data) "-" code) code) @@ -109,7 +111,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]]]]}]} + [: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 :sort-order]]]]}]} :on-success [::save-complete] :on-error [::save-error]}} {:db new-client-form})))) @@ -149,7 +151,7 @@ ::add-new-bank-account [(re-frame/path [::forms ::new-client :data])] (fn [client [_ type]] - (update client :bank-accounts conj {:type type :active? true :new? true}))) + (update client :bank-accounts conj {:type type :active? true :new? true :visible true :sort-order (count (:bank-accounts client))}))) (re-frame/reg-event-db ::bank-account-activated @@ -189,6 +191,27 @@ (fn [bas] (filter #(not= (:code %) code) bas))))) +(re-frame/reg-event-db + ::sort-swapped + [(re-frame/path [::forms ::new-client :data :bank-accounts ])] + (fn [bank-accounts [_ source dest]] + (->> (-> bank-accounts + (assoc-in [source :sort-order] (get-in bank-accounts [dest :sort-order])) + (assoc-in [dest :sort-order] (get-in bank-accounts [source :sort-order])) + + ) + (sort-by :sort-order) + vec))) + +(re-frame/reg-event-db + ::toggle-visible + [(re-frame/path [::forms ::new-client :data :bank-accounts ])] + (fn [bank-accounts [_ account]] + (-> (->> bank-accounts + (sort-by :sort-order) + vec) + (update-in [account :visible] #(not %))))) + (defn clients-table [] (let [clients (re-frame/subscribe [::subs/clients]) editing-client (:client @(re-frame/subscribe [::subs/admin]))] @@ -224,8 +247,9 @@ (defn side-bar-form [_ children] [:div [:a.delete.is-pulled-right {:on-click (dispatch-event [::form-closing ::new-client])}] [:div children]]) -(defn bank-account-card [new-client {:keys [active? new? type code name number check-number id] :as bank-account} index] - (println new-client) +(defn bank-account-card [new-client {:keys [active? new? type visible code name number check-number id sort-order] :as bank-account} first? last?] + + [:div.card {:style {:margin-bottom "1em"}} [:header.card-header [:p.card-header-title {:style {:text-overflow "ellipsis"}} @@ -234,13 +258,24 @@ [:span.icon-check-payment-sign] [:span.icon-accounting-bill])] code ": " name] + [:p {:style {:padding "0.75em 0.25em"}} + [:a.button.is-outlined {:on-click (dispatch-event [::toggle-visible sort-order])} [:span.icon (if visible + [:span.fa.fa-eye] + [:span.fa.fa-eye-slash] + )]]] + (when-not last? + [:p {:style {:padding "0.75em 0.25em"}} + [:a.button.is-primary.is-outlined {:on-click (dispatch-event [::sort-swapped sort-order (inc sort-order)])} [:span.icon [:span.fa.fa-sort-down]]]]) + (when-not first? + [:p {:style {:padding "0.75em 0.25em"}} + [:a.button.is-primary.is-outlined {:on-click (dispatch-event [::sort-swapped sort-order (dec sort-order)])} [:span.icon [:span.fa.fa-sort-up]]]]) (if active? [:a.card-header-icon - {:on-click (dispatch-event [::bank-account-deactivated index])} + {:on-click (dispatch-event [::bank-account-deactivated sort-order])} [:span.icon [:span.fa.fa-angle-up]]] [:a.card-header-icon - {:on-click (dispatch-event [::bank-account-activated index])} + {:on-click (dispatch-event [::bank-account-activated sort-order])} [:span.icon [:span.fa.fa-angle-down]]])] (when active? @@ -256,7 +291,7 @@ [:p.control [bind-field [:input.input {:type "code" - :field [:bank-accounts index :code] + :field [:bank-accounts sort-order :code] :spec ::entity/code :event ::change-new :subscription new-client}]]]] @@ -267,10 +302,10 @@ [bind-field [:input.input {:placeholder "BOA Checking #1" :type "text" - :field [:bank-accounts index :name] + :field [:bank-accounts sort-order :name] :event ::change-new :subscription new-client}]]]] - (when (#{:check ":check"} (doto type println) ) + (when (#{:check ":check"} type ) [:div [:label.label "Bank"] @@ -281,7 +316,7 @@ [bind-field [:input.input {:placeholder "Bank of America" :type "text" - :field [:bank-accounts index :bank-name] + :field [:bank-accounts sort-order :bank-name] :event ::change-new :subscription new-client}]]] [:div.control @@ -289,7 +324,7 @@ [bind-field [:input.input {:placeholder "104819123" :type "text" - :field [:bank-accounts index :routing] + :field [:bank-accounts sort-order :routing] :event ::change-new :subscription new-client}]]] [:div.control @@ -297,7 +332,7 @@ [bind-field [:input.input {:placeholder "12/10123" :type "text" - :field [:bank-accounts index :bank-code] + :field [:bank-accounts sort-order :bank-code] :event ::change-new :subscription new-client}]]]] @@ -309,7 +344,7 @@ [bind-field [:input.input {:placeholder "123456789" :type "text" - :field [:bank-accounts index :number] + :field [:bank-accounts sort-order :number] :event ::change-new :subscription new-client}]]] [:div.control @@ -317,7 +352,7 @@ [bind-field [:input.input {:placeholder "10000" :type "text" - :field [:bank-accounts index :check-number] + :field [:bank-accounts sort-order :check-number] :event ::change-new :subscription new-client}]]]] [:div.field @@ -328,17 +363,13 @@ :type "text" :field [:bank-accounts :yodlee-account-id] :event ::change-new - :subscription new-client}]]] - ]] + :subscription new-client}]]]]])]) - )] - - ) (when active? [:footer.card-footer - [:a.card-footer-item {:href "#" :on-click (dispatch-event [::bank-account-deactivated index])} "Done"] + [:a.card-footer-item {:href "#" :on-click (dispatch-event [::bank-account-deactivated sort-order])} "Done"] (when new? - [:a.card-footer-item.is-warning {:href "#" :on-click (dispatch-event [::bank-account-removed index])} "Remove"])])] + [:a.card-footer-item.is-warning {:href "#" :on-click (dispatch-event [::bank-account-removed sort-order])} "Remove"])])] ) (defn new-client-form [] @@ -399,9 +430,9 @@ :subscription new-client}]] [:h2.subtitle "Bank accounts"] - (for [[bank-account index] (map vector (:bank-accounts new-client) (range))] - ^{:key index} - [bank-account-card new-client bank-account index]) + (for [bank-account (sort-by :sort-order (:bank-accounts new-client))] + ^{:key (:sort-order bank-account)} + [bank-account-card new-client bank-account (= 0 (:sort-order bank-account)) (= (:sort-order bank-account) (dec (count (:bank-accounts new-client))))]) [:div.columns [:div.column.is-half diff --git a/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs b/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs index 1287384d..40fa2f63 100644 --- a/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs +++ b/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs @@ -465,7 +465,7 @@ :field :bank-account-id :event ::edit-payment-bank-account :subscription advanced-print-checks} - (for [{:keys [id number name]} (:bank-accounts current-client)] + (for [{:keys [id number name]} (sort-by :sort-order (:bank-accounts current-client))] ^{:key id} [:option {:value id} name])]]]] [:table.table.is-fullwidth @@ -512,7 +512,7 @@ :field :bank-account-id :event change-event :subscription handwrite-checks} - (for [{:keys [id number name]} (:bank-accounts current-client)] + (for [{:keys [id number name]} (->> current-client :bank-accounts (filter #(= (:type %) :check)) (sort-by :sort-order))] ^{:key id} [:option {:value id} name])]]]] [horizontal-field @@ -776,7 +776,7 @@ [:div.dropdown-menu {:role "menu"} [:div.dropdown-content (list - (for [{:keys [id number name type]} (:bank-accounts current-client)] + (for [{:keys [id number name type]} (->> (:bank-accounts current-client) (filter :visible) (sort-by :sort-order))] (if (= :cash type) ^{:key id} [:a.dropdown-item {:on-click (dispatch-event [::print-checks id :cash])} "With cash"] (list