Accounts don't need to be loaded

This commit is contained in:
2022-04-19 13:27:47 -07:00
parent f73b406abd
commit f51f3450d6
22 changed files with 398 additions and 420 deletions

View File

@@ -1,15 +1,16 @@
(ns auto-ap.views.components.expense-accounts-dialog
(:require [auto-ap.forms :as forms]
[auto-ap.status :as status]
[auto-ap.subs :as subs]
[auto-ap.utils :refer [by]]
[auto-ap.views.components.modal :as modal]
[auto-ap.views.components.typeahead :refer [typeahead-v3]]
[auto-ap.views.pages.invoices.common :refer [invoice-read]]
[auto-ap.views.utils :refer [dispatch-event with-user]]
[clojure.string :as str]
[goog.string :as gstring]
[re-frame.core :as re-frame]))
(:require
[auto-ap.forms :as forms]
[auto-ap.status :as status]
[auto-ap.subs :as subs]
[auto-ap.utils :refer [by]]
[auto-ap.views.components.modal :as modal]
[auto-ap.views.components.typeahead.vendor :refer [search-backed-typeahead]]
[auto-ap.views.pages.invoices.common :refer [invoice-read]]
[auto-ap.views.utils :refer [dispatch-event with-user]]
[clojure.string :as str]
[goog.string :as gstring]
[re-frame.core :as re-frame]))
(re-frame/reg-sub
::can-submit
@@ -95,7 +96,6 @@
{:keys [total] :or {total 0} {:keys [locations] :as client} :client} (:invoice data)
{:keys [form-inline horizontal-field field raw-field error-notification submit-button]} change-expense-accounts-form
multi-location? (> (count locations) 1)
chooseable-expense-accounts @(re-frame/subscribe [::subs/accounts client])
expense-accounts-total (->> expense-accounts
vals
(map :new-amount)
@@ -124,14 +124,17 @@
[:tr
[:td.expandable [:div.control
(raw-field
[typeahead-v3 {:entities chooseable-expense-accounts
:type "typeahead-v3"
:entity->text (fn [x] (str (:numeric-code x) " - " (:name x)))
:field [:expense-accounts id :account]}])]]
[search-backed-typeahead {:search-query (fn [i]
[:search_account
{:query i
:client-id (:id client)}
[:name :id :location]])
:type "typeahead-v3"
:field [:expense-accounts id :account]}])]]
(when multi-location?
[:td
(if-let [forced-location (:location @(re-frame/subscribe [::subs/account client (get-in expense-accounts [id :account :id])]))]
(if-let [forced-location (get-in expense-accounts [id :account :location])]
[:div.select
[:select {:disabled "disabled" :value forced-location} [:option {:value forced-location} forced-location]]]
[:div.select
@@ -175,21 +178,17 @@
(re-frame/reg-event-fx
::show
(fn [{:keys [db]} [_ i]]
(let [accounts-by-id @(re-frame/subscribe [::subs/accounts-by-id])]
{:dispatch [::modal/modal-requested {:title "Change expense accounts"
:body [form]
:confirm {:value "Save"
:status-from [::status/single ::form]
:class "is-primary"
:on-click (dispatch-event [::try-save])
:can-submit [::can-submit]
:close-event [::status/completed ::form]}}]
:db (-> db
(forms/start-form ::form
{:dispatch [::modal/modal-requested {:title "Change expense accounts"
:body [form]
:confirm {:value "Save"
:status-from [::status/single ::form]
:class "is-primary"
:on-click (dispatch-event [::try-save])
:can-submit [::can-submit]
:close-event [::status/completed ::form]}}]
:db (-> db
(forms/start-form ::form
{:expense-accounts (by :id
(mapv
(fn [ea]
(assoc ea :account (accounts-by-id (:id (:account ea)))))
(:expense-accounts i)))
:invoice i}))})))
{:expense-accounts (by :id
(:expense-accounts i))
:invoice i}))}))

View File

@@ -1,10 +1,10 @@
(ns auto-ap.views.components.expense-accounts-field
(:require [auto-ap.subs :as subs]
[auto-ap.views.components.typeahead :refer [typeahead-v3]]
[auto-ap.views.utils :refer [bind-field dispatch-event ->$]]
[goog.string :as gstring]
[re-frame.core :as re-frame]
[clojure.string :as str]))
(:require
[auto-ap.views.utils :refer [->$ bind-field dispatch-event]]
[auto-ap.views.components.typeahead.vendor :refer [search-backed-typeahead]]
[clojure.string :as str]
[goog.string :as gstring]
[re-frame.core :as re-frame]))
(defn can-replace-with-default? [accounts]
(and (or (not (seq accounts))
@@ -25,14 +25,11 @@
:account default-account}])
(defn from-graphql [accounts accounts-by-id total locations]
(defn from-graphql [accounts total locations]
(if (seq accounts)
(vec (map
(fn [a]
(-> a
(update :account (fn [a]
(accounts-by-id (:id a))))
(update :amount js/parseFloat)
(assoc :amount-percentage (* 100 (/ (js/parseFloat (:amount a))
(Math/abs total))))
@@ -92,14 +89,10 @@
(re-frame/reg-event-fx
::expense-account-changed
(fn [_ [_ event expense-accounts max-value field value]]
(println field value)
(let [updated-accounts (cond-> expense-accounts
true (assoc-in field value)
(= (list :account) (drop 1 field)) (assoc-in [(first field) :location] nil)
(= (list :account :id) (drop 1 field)) (-> (assoc-in [(first field) :account] @(re-frame/subscribe [::subs/account nil value]))
(assoc-in [(first field) :location] nil))
(= (list :amount-percentage) (drop 1 field)) (assoc-in [(first field) :amount]
(js/parseFloat
(goog.string/format "%.2f"
@@ -116,111 +109,111 @@
;; VIEWS
(defn expense-accounts-field [{expense-accounts :value client :client max-value :max locations :locations event :event descriptor :descriptor disabled :disabled percentage-only? :percentage-only? :or {percentage-only? false}}]
(let [chooseable-expense-accounts @(re-frame/subscribe [::subs/accounts client])
accounts-by-id @(re-frame/subscribe [::subs/accounts-by-id client])]
[:div
[:div.columns
[:div.column
[:h1.subtitle.is-4.is-inline (str/capitalize descriptor) "s"]
(when-not percentage-only?
[:p.help "Remaining " (->$ (- max-value (reduce + 0 (map (comp js/parseFloat :amount) expense-accounts))))])]
[:div.column.is-narrow
(when-not disabled
[:p.buttons
[:a.button {:on-click (dispatch-event [::spread-evenly event expense-accounts max-value])} "Spread evenly"]
[:a.button {:on-click (dispatch-event [::add-expense-account event expense-accounts locations])} "Add"]])]]
[:div
[:div.columns
[:div.column
[:h1.subtitle.is-4.is-inline (str/capitalize descriptor) "s"]
(when-not percentage-only?
[:p.help "Remaining " (->$ (- max-value (reduce + 0 (map (comp js/parseFloat :amount) expense-accounts))))])]
[:div.column.is-narrow
(when-not disabled
[:p.buttons
[:a.button {:on-click (dispatch-event [::spread-evenly event expense-accounts max-value])} "Spread evenly"]
[:a.button {:on-click (dispatch-event [::add-expense-account event expense-accounts locations])} "Add"]])]]
(for [[index {:keys [account id location amount amount-percentage amount-mode] :as expense-account}] (map vector (range) expense-accounts)
:let [account (accounts-by-id (:id account))]]
^{:key id}
[:div.box
[:div.columns
[:div.column
[:h1.subtitle.is-6 (cond (and account (not percentage-only?))
(str (:name account) " - "
location ": "
(gstring/format "$%.2f" (or amount 0) ))
(for [[index {:keys [account id location amount amount-percentage amount-mode] :as expense-account}] (map vector (range) expense-accounts)]
^{:key id}
[:div.box
[:div.columns
[:div.column
[:h1.subtitle.is-6 (cond (and account (not percentage-only?))
(str (:name account) " - "
location ": "
(gstring/format "$%.2f" (or amount 0) ))
account
(str (:name account) " - "
location ": %"
amount-percentage)
account
(str (:name account) " - "
location ": %"
amount-percentage)
:else
[:i "New " descriptor])]]
[:div.column.is-narrow
(when-not disabled
[:a.delete {:on-click (dispatch-event [::remove-expense-account event expense-accounts id])}])]]
[:div.field
[:div.columns
[:div.column
[:p.help "Account"]
[:div.control.is-fullwidth
[bind-field
^{:key (:id client)}
[typeahead-v3 {:entities chooseable-expense-accounts
:entity->text (fn [x ]
(str (:numeric-code x) " - " (:name x)))
:disabled disabled
:type "typeahead-v3"
:field [index :account]
:event [::expense-account-changed event expense-accounts max-value]
:subscription expense-accounts}]]]]
[:div.column.is-narrow
[:p.help "Location"]
[:div.control
(if-let [forced-location (:location account)]
[:div.select
[:select {:disabled "disabled" :style {:width "5em"} :value forced-location} [:option {:value forced-location} forced-location]]]
[:div.select
[bind-field
[:select {:type "select"
:disabled (boolean (or (:location account)
disabled))
:style {:width "5em"}
:field [index :location]
:allow-nil? true
:spec (set locations)
:event [::expense-account-changed event expense-accounts max-value]
:subscription expense-accounts}
(map (fn [l] ^{:key l} [:option {:value l} l]) locations)]]])]]]]
[:div.field
[:p.help "Amount"]
:else
[:i "New " descriptor])]]
[:div.column.is-narrow
(when-not disabled
[:a.delete {:on-click (dispatch-event [::remove-expense-account event expense-accounts id])}])]]
[:div.field
[:div.columns
[:div.column
[:p.help "Account"]
[:div.control.is-fullwidth
[bind-field
^{:key (:id client)}
[search-backed-typeahead {:search-query (fn [i]
[:search_account
{:query i
:client-id (:id client)}
[:name :id :location]])
:type "typeahead-v3"
:field [index :account]
:disabled disabled
:event [::expense-account-changed event expense-accounts max-value]
:subscription expense-accounts}]]]]
[:div.column.is-narrow
[:p.help "Location"]
[:div.control
[:div.field.has-addons.is-extended
[:p.control [:span.select
[bind-field
[:select {:type "select"
:disabled (or disabled percentage-only?)
:field [index :amount-mode]
:allow-nil? false
:event [::expense-account-changed event expense-accounts max-value]
:subscription expense-accounts}
[:option "$"]
[:option "%"]]]]]
[:p.control
(if (= "$" amount-mode)
[bind-field
[:input.input {:type "number"
:field [index :amount]
:style {:text-align "right" :width "7em"}
:event [::expense-account-changed event expense-accounts max-value]
:disabled disabled
:subscription expense-accounts
:precision 2
:value (get-in expense-account [:amount])
:max max-value
:step "0.01"}]]
[bind-field
[:input.input {:type "number"
:field [index :amount-percentage]
:style {:text-align "right" :width "7em"}
:disabled disabled
:event [::expense-account-changed event expense-accounts max-value]
:precision 2
:subscription expense-accounts
:value (get-in expense-account [:amount-percentage])
:max "100"
:step "0.01"}]])]]]]])]))
(if-let [forced-location (:location account)]
[:div.select
[:select {:disabled "disabled" :style {:width "5em"} :value forced-location} [:option {:value forced-location} forced-location]]]
[:div.select
[bind-field
[:select {:type "select"
:disabled (boolean (or (:location account)
disabled))
:style {:width "5em"}
:field [index :location]
:allow-nil? true
:spec (set locations)
:event [::expense-account-changed event expense-accounts max-value]
:subscription expense-accounts}
(map (fn [l] ^{:key l} [:option {:value l} l]) locations)]]])]]]]
[:div.field
[:p.help "Amount"]
[:div.control
[:div.field.has-addons.is-extended
[:p.control [:span.select
[bind-field
[:select {:type "select"
:disabled (or disabled percentage-only?)
:field [index :amount-mode]
:allow-nil? false
:event [::expense-account-changed event expense-accounts max-value]
:subscription expense-accounts}
[:option "$"]
[:option "%"]]]]]
[:p.control
(if (= "$" amount-mode)
[bind-field
[:input.input {:type "number"
:field [index :amount]
:style {:text-align "right" :width "7em"}
:event [::expense-account-changed event expense-accounts max-value]
:disabled disabled
:subscription expense-accounts
:precision 2
:value (get-in expense-account [:amount])
:max max-value
:step "0.01"}]]
[bind-field
[:input.input {:type "number"
:field [index :amount-percentage]
:style {:text-align "right" :width "7em"}
:disabled disabled
:event [::expense-account-changed event expense-accounts max-value]
:precision 2
:subscription expense-accounts
:value (get-in expense-account [:amount-percentage])
:max "100"
:step "0.01"}]])]]]]])])

View File

@@ -13,7 +13,6 @@
[auto-ap.views.utils :refer [date->str dispatch-event dispatch-event-with-propagation nf days-until]]
[bidi.bidi :as bidi]
[cemerick.url :as url]
[cljs-time.core :as t]
[clojure.string :as str]
[goog.string :as gstring]
[re-frame.core :as re-frame]
@@ -51,7 +50,7 @@
[[:invoices [:id :total :outstanding-balance :invoice-number :date :due :status :client-identifier :scheduled-payment :source-url :similarity
[:vendor [:name :id]]
[:expense_accounts [:amount :id :location
[:account [:id ]]]]
[:account [:id :name :location]]]]
[:client [:name :id :locations]]
[:payments [:amount :id [:payment [:id :status :amount :s3_url :check_number
[:transaction [:post_date]]]]]]]]
@@ -112,15 +111,13 @@
(re-frame/reg-event-fx
::invoice-updated
(fn [{:keys [db]} [_ invoice]]
(fn [{:keys [db]} [_ _]]
{:db db}))
(defn row [{:keys [invoice check-boxes selected-client overrides checkable? expense-event actions]}]
(defn row [{:keys [invoice selected-client overrides checkable? actions]}]
(let [{:keys [client status payments expense-accounts invoice-number date due total outstanding-balance id vendor source-url] :as i} invoice
accounts-by-id @(re-frame/subscribe [::subs/accounts-by-id client])
unautopay-states @(re-frame/subscribe [::status/multi ::unautopay])
editing-states @(re-frame/subscribe [::status/multi ::edits])
account->name #(:name (accounts-by-id (:id %)))]
editing-states @(re-frame/subscribe [::status/multi ::edits])]
[grid/row {:class (:class i) :id id :checkable? checkable? :entity invoice}
(when-not selected-client
[grid/cell {}
@@ -143,9 +140,8 @@
[grid/cell {:class "has-text-right"} (nf total )]
[grid/cell {:class "has-text-right"}
(if (:scheduled-payment i)
[:<> [:div.tag.is-info.is-light "Autopay"] " "]
)
(when (:scheduled-payment i)
[:<> [:div.tag.is-info.is-light "Autopay"] " "])
(nf outstanding-balance )]
[grid/button-cell {}
[:div.buttons
@@ -160,7 +156,7 @@
[:div
(for [e expense-accounts]
^{:key (:id e)}
[:span.dropdown-item (account->name (:account e)) " " (gstring/format "$%.2f" (:amount e) ) ])
[:span.dropdown-item (:name (:account e)) " " (gstring/format "$%.2f" (:amount e) ) ])
(when (get actions :expense-accounts)
[:<>
@@ -237,17 +233,14 @@
:class (status/class-for (get unautopay-states (:id i)))
:event [::unautopay i]}])]]]))
(defn invoice-table [{:keys [id check-boxes overrides actions data-page checkable-fn]}]
(let [selected-client @(re-frame/subscribe [::subs/client])
{:keys [data status params table-params]} @(re-frame/subscribe [::data-page/page data-page])
(defn invoice-table [{:keys [check-boxes overrides actions data-page checkable-fn]}]
(let [{:keys [data status params table-params]} @(re-frame/subscribe [::data-page/page data-page])
selected-client @(re-frame/subscribe [::subs/client])
is-loading? (= :loading (:state status))
is-sorted-by-vendor? (and (= "vendor" (:sort-key (first (:sort table-params))))
(not is-loading?)
(or (apply <= (map (comp :name :vendor) (:data data)))
(apply >= (map (comp :name :vendor) (:data data)))))
[invoice-groups] (if is-sorted-by-vendor?
(reduce
(fn [[acc last-vendor] invoice]

View File

@@ -58,7 +58,7 @@
:time 250
:key ::input-value-settled}})))
(defn typeahead-v3-internal [{:keys [class style ^js entity->text on-change disabled value name search-query auto-focus] :or {disabled false} :as i}]
(defn typeahead-v3-internal [{:keys [class style ^js on-change disabled value name search-query auto-focus] :or {disabled false} :as i}]
(let [[items set-items] (react/useState [])
[loading-status set-loading-status] (react/useState false)
[getLabelProps getMenuProps getComboboxProps getToggleButtonProps getInputProps getItemProps isOpen highlightedIndex selectItem selectedItem setInputValue]
@@ -73,8 +73,6 @@
(when on-change
(on-change (js->clj (aget z "selectedItem") :keywordize-keys true))))})) $
(map #(aget $ %) ["getLabelProps" "getMenuProps" "getComboboxProps" "getToggleButtonProps" "getInputProps" "getItemProps" "isOpen" "highlightedIndex" "selectItem" "selectedItem" "setInputValue"]))]
#_(println (getInputProps))
[:<>
[:div.typeahead (assoc (js->clj (getComboboxProps))
:style style)
@@ -96,7 +94,7 @@
:tab-index "0")
[:div.control
[:div.tags.has-addons
[:span.tag (entity->text (js->clj selectedItem :keywordize-keys true))]
[:span.tag (:name (js->clj selectedItem :keywordize-keys true))]
(when name
[:input {:type "hidden" :name name :value (:id (js->clj selectedItem :keywordize-keys true))}])
(when-not disabled
@@ -125,10 +123,8 @@
[:li.typeahead-suggestion (assoc (js->clj (getItemProps #js {:item item :index index}))
:class (if (= index highlightedIndex)
"typeahead-highlighted"))
(entity->text item)]))]]]]))
(:name item)]))]]]]))
(defn search-backed-typeahead [props]
[:div
[:f> typeahead-v3-internal (assoc props
:entity->text :name
)]])
[:f> typeahead-v3-internal props]])

View File

@@ -12,8 +12,7 @@
[auto-ap.views.components.typeahead :refer [typeahead-v3]]
[auto-ap.views.pages.admin.vendors.common :as common]
[auto-ap.views.utils
:refer [account->match-text
bind-field
:refer [bind-field
dispatch-event
horizontal-field
with-is-admin?
@@ -87,8 +86,7 @@
:print-as print-as
:terms terms
:default-account-id (:id default-account)
:address address
:primary-contact primary-contact
:address address :primary-contact primary-contact
:secondary-contact secondary-contact
:invoice-reminder-schedule invoice-reminder-schedule}
is-admin? (assoc :hidden hidden
@@ -288,12 +286,15 @@
:default-key :default-account
:override-key :account-overrides}
(fn [field client]
[typeahead-v3 {:entities @(re-frame/subscribe [::subs/accounts client])
:entity->text account->match-text
:field field
:type "typeahead-v3"
:event change-event
:subscription data}])]
[search-backed-typeahead {:search-query (fn [i]
[:search_account
{:query i
:client-id (:id client)}
[:name :id]])
:type "typeahead-v3"
:field field
:event change-event
:subscription data}])]
[:h2.subtitle "Address"]
[address-field {:field [:address]
@@ -525,10 +526,7 @@
(update :automatically-paid-when-due #(mapv identity %))
(update :hidden #(if (nil? %)
false
%))
(update :default-account
(fn [da]
@(re-frame/subscribe [::subs/account nil (:id da)]))))))
%)))))
:dispatch [::modal/modal-requested
{:title "Vendor"
:class "is-wide"