good progress on making expense accounts editable.
This commit is contained in:
@@ -50,6 +50,7 @@
|
||||
(re-frame/reg-event-db
|
||||
::change
|
||||
(fn [db [_ form & path-pairs]]
|
||||
(println "CHANGING" form path-pairs)
|
||||
(reduce
|
||||
(fn [db [path value]]
|
||||
(assoc-in db (into [::forms form :data] path) value))
|
||||
|
||||
108
src/cljs/auto_ap/views/components/expense_account_field.cljs
Normal file
108
src/cljs/auto_ap/views/components/expense_account_field.cljs
Normal file
@@ -0,0 +1,108 @@
|
||||
(ns auto-ap.views.components.expense-account-field
|
||||
(:require [auto-ap.forms :as forms]
|
||||
[auto-ap.subs :as subs]
|
||||
[auto-ap.views.components.typeahead :refer [typeahead]]
|
||||
[auto-ap.views.utils :refer [bind-field dispatch-event]]
|
||||
[goog.string :as gstring]
|
||||
[re-frame.core :as re-frame]))
|
||||
|
||||
|
||||
;; EVENTS
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::add-expense-account
|
||||
(fn [_ [_ event expense-accounts]]
|
||||
{:dispatch (conj event (conj expense-accounts
|
||||
{:amount 0 :id (str "new-" (random-uuid))}))}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::remove-expense-account
|
||||
(fn [_ [_ event expense-accounts id]]
|
||||
{:dispatch (conj event (transduce (filter
|
||||
(fn [ea]
|
||||
(not= (:id ea) id)) )
|
||||
conj
|
||||
[]
|
||||
expense-accounts))}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::expense-account-changed
|
||||
(fn [_ [_ event expense-accounts field value]]
|
||||
{:dispatch (into event [(assoc-in expense-accounts field value)
|
||||
(if (= (list :account :id) (drop 1 field))
|
||||
(if-let [location (:location @(re-frame/subscribe [::subs/account value]))]
|
||||
[[(first field) :location] location]))])}))
|
||||
|
||||
|
||||
;; VIEWS
|
||||
(defn expense-accounts-field [{expense-accounts :value max-value :max locations :locations event :event}]
|
||||
(let [chooseable-expense-accounts @(re-frame/subscribe [::subs/chooseable-expense-accounts])
|
||||
accounts-by-id @(re-frame/subscribe [::subs/accounts-for-client-by-id])]
|
||||
[:div
|
||||
[:div.columns
|
||||
[:div.column
|
||||
[:h1.subtitle.is-4.is-inline "Expense Accounts"]]
|
||||
[:div.column.is-narrow
|
||||
[:p.buttons
|
||||
[:a.button {:on-click (dispatch-event [::add-expense-account event expense-accounts])} "Add"]]]]
|
||||
|
||||
(for [[index {:keys [account id location amount] :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 (if account
|
||||
(str (:name account) " - "
|
||||
location ": "
|
||||
(gstring/format "$%.2f" (or amount 0) ))
|
||||
[:i "New expense account"])]]
|
||||
[:div.column.is-narrow
|
||||
[:a.button {:on-click (dispatch-event [::remove-expense-account event expense-accounts id])} [:span.icon [:i.fa.fa-times]]]]]
|
||||
[:div.field
|
||||
[:div.columns
|
||||
[:div.column
|
||||
[:p.help "Expense Account"]
|
||||
[:div.control.is-fullwidth
|
||||
[bind-field
|
||||
[typeahead {:matches (map (fn [x] [(:id x) (str (:numeric-code x) " - " (:name x))]) chooseable-expense-accounts)
|
||||
:type "typeahead"
|
||||
:field [index :account :id]
|
||||
:event [::expense-account-changed event expense-accounts]
|
||||
: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 (if (:location account)
|
||||
"disabled"
|
||||
"")
|
||||
:style {:width "5em"}
|
||||
:field [index :location]
|
||||
:allow-nil? true
|
||||
:spec (set locations)
|
||||
:event [::expense-account-changed event expense-accounts]
|
||||
: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 [:a.button.is-static "$"]]
|
||||
[:p.control
|
||||
[bind-field
|
||||
[:input.input {:type "number"
|
||||
:field [index :amount]
|
||||
:style {:text-align "right" :width "7em"}
|
||||
:event [::expense-account-changed event expense-accounts]
|
||||
:subscription expense-accounts
|
||||
:value (get-in expense-account [:amount])
|
||||
:max max-value
|
||||
:step "0.01"}]]]]]]])]))
|
||||
@@ -1,11 +1,12 @@
|
||||
(ns auto-ap.views.pages.invoices.form
|
||||
(:require [auto-ap.entities.invoice :as invoice]
|
||||
[auto-ap.utils :refer [by]]
|
||||
[auto-ap.utils :refer [by dollars=]]
|
||||
[auto-ap.events :as events]
|
||||
[auto-ap.forms :as forms]
|
||||
[auto-ap.subs :as subs]
|
||||
[auto-ap.views.components.dropdown :refer [drop-down]]
|
||||
[auto-ap.views.components.typeahead :refer [typeahead]]
|
||||
[auto-ap.views.components.expense-account-field :refer [expense-accounts-field]]
|
||||
[auto-ap.views.pages.invoices.common :refer [invoice-read]]
|
||||
[auto-ap.views.utils
|
||||
:refer
|
||||
@@ -21,8 +22,9 @@
|
||||
|
||||
(re-frame/reg-sub
|
||||
::can-submit-edit-invoice
|
||||
:<- [::form]
|
||||
:<- [::forms/form ::form]
|
||||
(fn [{:keys [data status]} _]
|
||||
(println (s/explain-data ::invoice/invoice data))
|
||||
(let [min-total (if (= (:total (:original data)) (:outstanding-balance (:original data)))
|
||||
nil
|
||||
(- (:total (:original data)) (:outstanding-balance (:original data))))]
|
||||
@@ -30,7 +32,7 @@
|
||||
(s/valid? ::invoice/invoice data)
|
||||
(or (not min-total) (>= (:total data) min-total))
|
||||
(or (not (:id data))
|
||||
(< (.abs js/Math (- (js/parseFloat (:total data)) (reduce + 0 (map (fn [ea] (js/parseFloat (:amount ea))) (:expense-accounts data))))) 0.001))))))
|
||||
(dollars= (js/parseFloat (:total data)) (reduce + 0 (map (fn [ea] (js/parseFloat (:amount ea))) (:expense-accounts data)))))))))
|
||||
|
||||
(defmulti submit-query (fn [_ [_ command]]
|
||||
command))
|
||||
@@ -134,33 +136,7 @@
|
||||
[:client-id] value
|
||||
[:location] first-location]})))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::change-expense-account-account
|
||||
(fn [{:keys [db]} [_ [_ which _] value]]
|
||||
|
||||
(let [account @(re-frame/subscribe [::subs/account value])
|
||||
changes (cond-> [[:expense-accounts which :account :id] value]
|
||||
(:location account) (into [[:expense-accounts which :location] (:location account)]))]
|
||||
|
||||
{:dispatch (into [::forms/change ::form] changes)})))
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::add-expense-account
|
||||
[(forms/in-form ::form) (re-frame/path [:data])]
|
||||
(fn [form]
|
||||
(update form :expense-accounts conj {:amount 0 :id (str "new-" (random-uuid))})))
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::remove-expense-account
|
||||
[(forms/in-form ::form) (re-frame/path [:data])]
|
||||
(fn [form [_ x]]
|
||||
(update form :expense-accounts (fn [eas]
|
||||
(transduce (filter
|
||||
(fn [ea]
|
||||
(not= (:id ea) x)) )
|
||||
conj
|
||||
[]
|
||||
eas)))))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::submitted
|
||||
@@ -199,6 +175,7 @@
|
||||
|
||||
;; VIEWS
|
||||
|
||||
|
||||
(defn form [{:keys [can-change-amount?] :as params}]
|
||||
[forms/side-bar-form {:form ::form }
|
||||
(let [{:keys [data active? error id]} @(re-frame/subscribe [::forms/form ::form])
|
||||
@@ -308,74 +285,15 @@
|
||||
:spec ::invoice/total
|
||||
:step "0.01"}]]]]]]
|
||||
|
||||
[:div
|
||||
[:div.columns
|
||||
[:div.column
|
||||
[:h1.subtitle.is-4.is-inline "Expense Accounts"]]
|
||||
[:div.column.is-narrow
|
||||
[:p.buttons
|
||||
[:a.button {:on-click (dispatch-event [::add-expense-account])} "Add"]]]]
|
||||
[bind-field
|
||||
[expense-accounts-field {:subscription data
|
||||
:type "expense-accounts"
|
||||
:event change-event
|
||||
:locations locations
|
||||
:max-value (:total data)
|
||||
:field [:expense-accounts]}]]
|
||||
|
||||
(for [[index {:keys [account id location amount] :as expense-account}] (map vector (range) (:expense-accounts data))
|
||||
:let [account (accounts-by-id (:id account))]]
|
||||
^{:key id}
|
||||
[:div.box
|
||||
[:div.columns
|
||||
[:div.column
|
||||
[:h1.subtitle.is-6 (if account
|
||||
(str (:name account) " - "
|
||||
location ": "
|
||||
(gstring/format "$%.2f" (or amount 0) ))
|
||||
[:i "New expense account"])]]
|
||||
[:div.column.is-narrow
|
||||
[:a.button {:on-click (dispatch-event [::remove-expense-account id])} [:span.icon [:i.fa.fa-times]]]]]
|
||||
[:div.field
|
||||
[:div.columns
|
||||
[:div.column
|
||||
[:p.help "Expense Account"]
|
||||
[:div.control.is-fullwidth
|
||||
[bind-field
|
||||
[typeahead {:matches (map (fn [x] [(:id x) (str (:numeric-code x) " - " (:name x))]) chooseable-expense-accounts)
|
||||
:type "typeahead"
|
||||
:field [:expense-accounts index :account :id]
|
||||
:event [::change-expense-account-account]
|
||||
:subscription data}]]]]
|
||||
[: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 (if (:location account)
|
||||
"disabled"
|
||||
"")
|
||||
:style {:width "5em"}
|
||||
:field [:expense-accounts index :location]
|
||||
:allow-nil? true
|
||||
:spec (set locations)
|
||||
:event [::forms/change ::form]
|
||||
:subscription data}
|
||||
(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 [:a.button.is-static "$"]]
|
||||
[:p.control
|
||||
[bind-field
|
||||
[:input.input {:type "number"
|
||||
:field [:expense-accounts index :amount]
|
||||
:style {:text-align "right" :width "7em"}
|
||||
:event [::forms/change ::form]
|
||||
:subscription data
|
||||
:value (get-in expense-account [:amount])
|
||||
:max (:total data)
|
||||
:step "0.01"}]]]]]]])]
|
||||
|
||||
|
||||
(when error
|
||||
^{:key error} [:div.notification.is-warning.animated.fadeInUp
|
||||
|
||||
@@ -140,6 +140,18 @@
|
||||
keys (dissoc keys :field :subscription :event :spec)]
|
||||
(into [dom keys] (with-keys rest))))
|
||||
|
||||
(defmethod do-bind "expense-accounts" [dom {:keys [field event subscription class spec] :as keys} & rest]
|
||||
(let [field (if (keyword? field) [field] field)
|
||||
event (if (keyword? event) [event] event)
|
||||
keys (assoc keys
|
||||
:value (get-in subscription field)
|
||||
:event (conj event field)
|
||||
:class (str class
|
||||
(when (and spec (not (s/valid? spec (get-in subscription field))))
|
||||
" is-danger")))
|
||||
keys (dissoc keys :field :subscription :spec)]
|
||||
(into [dom keys] (with-keys rest))))
|
||||
|
||||
(defmethod do-bind :default [dom {:keys [field event subscription class spec] :as keys} & rest]
|
||||
(let [field (if (keyword? field) [field] field)
|
||||
event (if (keyword? event) [event] event)
|
||||
|
||||
Reference in New Issue
Block a user