Supports changing from paid invoices

This commit is contained in:
Bryce Covert
2018-11-01 17:52:43 -07:00
parent efe1ae086e
commit 23ba7a79f1
5 changed files with 252 additions and 130 deletions

View File

@@ -0,0 +1,75 @@
(ns auto-ap.events.expense-accounts
(:require [re-frame.core :as re-frame]
[reagent.core :as r]
[clojure.string :as str]
[clojure.spec.alpha :as s]
[cljs-time.core :as c]
[goog.string :as gstring]
[auto-ap.entities.companies :as company]
[auto-ap.entities.invoice :as invoice]
[auto-ap.entities.vendors :as vendor]
[auto-ap.expense-accounts :as expense-accounts]
[auto-ap.entities.invoices-expense-accounts :as invoices-expense-accounts]
[auto-ap.views.utils :refer [dispatch-event bind-field horizontal-field date->str str->date pretty standard]]
[auto-ap.utils :refer [by replace-if]]
[auto-ap.events :as events]))
(re-frame/reg-event-fx
::change-expense-accounts
(fn [{:keys [db]} [_ id]]
{:dispatch [::events/modal-status ::change-expense-accounts {:visible? true}]
:db (assoc-in db [::change-expense-accounts :invoice] (get (by :id (get-in db [::invoice-page :invoices])) id))}))
(re-frame/reg-event-fx
::change-expense-accounts-saving
(fn [{:keys [db]} [_ id]]
(let [{:keys [id expense-accounts]} (get-in db [::change-expense-accounts :invoice])]
{:graphql
{:token (-> db :user)
:query-obj {:venia/operation {:operation/type :mutation
:operation/name "EditExpenseAccounts"}
:venia/queries [{:query/data [:edit-expense-accounts
{:invoice-id id
:expense-accounts (map (fn [ea] {:id (:id ea)
:amount (:amount ea)
:location (:location ea)
:expense-account-id (:expense-account-id ea)})
expense-accounts)}
[:id :total :outstanding-balance :invoice-number :date
[:vendor [:name :id]]
[:expense_accounts [:amount :id :location :expense_account_id
[:expense_account [:id :name [:parent [:id :name]]]]]]
[:company [:name :id :locations]]
[:checks [:amount [:check [:amount :s3_url :check_number ]]]]
]]}]}
:on-success [::expense-accounts-updated]}})))
(re-frame/reg-event-fx
::expense-accounts-updated
(fn [{:keys [db]} [_ data]]
(let [updated (:edit-expense-accounts data)]
{:dispatch [::events/modal-completed ::change-expense-accounts]
:db (-> db
(update-in [::invoice-page :invoices]
(fn [is]
(replace-if #(= (:id %1) (:id %2)) updated is)))
(dissoc ::change-expense-accounts))})))
(re-frame/reg-event-db
::add-expense-account-split
(fn [db _]
(let [{{{:keys [locations]} :company} :invoice} @(re-frame/subscribe [::change-expense-accounts])]
(update-in db [::change-expense-accounts :invoice :expense-accounts]
conj {:amount 0 :expense-account-id nil :location (first locations)}))))
(re-frame/reg-event-db
::remove-expense-account-split
(fn [db [_ index]]
(update-in db [::change-expense-accounts :invoice :expense-accounts]
(fn [expense-accounts]
(vec (concat (take index expense-accounts)
(drop (inc index) expense-accounts)))))))

View File

@@ -0,0 +1,148 @@
(ns auto-ap.views.components.expense-accounts-dialog
(:require [re-frame.core :as re-frame]
[reagent.core :as r]
[clojure.string :as str]
[clojure.spec.alpha :as s]
[cljs-time.core :as c]
[goog.string :as gstring]
[auto-ap.subs :as subs]
[auto-ap.entities.companies :as company]
[auto-ap.entities.invoice :as invoice]
[auto-ap.entities.vendors :as vendor]
[auto-ap.expense-accounts :as expense-accounts]
[auto-ap.entities.invoices-expense-accounts :as invoices-expense-accounts]
[auto-ap.views.components.modal :refer [modal action-modal]]
[auto-ap.views.utils :refer [dispatch-event bind-field horizontal-field date->str str->date pretty standard]]
[auto-ap.utils :refer [by replace-if]]
[auto-ap.views.components.typeahead :refer [typeahead]]
[auto-ap.events :as events]))
(re-frame/reg-sub
::change-expense-accounts
(fn [db]
(-> db ::change-expense-accounts)))
(re-frame/reg-event-fx
::change-expense-accounts
(fn [{:keys [db]} [_ i]]
{:dispatch [::events/modal-status ::change-expense-accounts {:visible? true}]
:db (assoc-in db [::change-expense-accounts :invoice] i)}))
(re-frame/reg-event-fx
::change-expense-accounts-saving
(fn [{:keys [db]} [_ on-success id ]]
(let [{:keys [id expense-accounts]} (get-in db [::change-expense-accounts :invoice])]
{:graphql
{:token (-> db :user)
:query-obj {:venia/operation {:operation/type :mutation
:operation/name "EditExpenseAccounts"}
:venia/queries [{:query/data [:edit-expense-accounts
{:invoice-id id
:expense-accounts (map (fn [ea] {:id (:id ea)
:amount (:amount ea)
:location (:location ea)
:expense-account-id (:expense-account-id ea)})
expense-accounts)}
[:id :total :outstanding-balance :invoice-number :date
[:vendor [:name :id]]
[:expense_accounts [:amount :id :location :expense_account_id
[:expense_account [:id :name [:parent [:id :name]]]]]]
[:company [:name :id :locations]]
[:checks [:amount [:check [:amount :s3_url :check_number ]]]]
]]}]}
:on-success on-success}})))
(re-frame/reg-event-db
::add-expense-account-split
(fn [db _]
(let [{{{:keys [locations]} :company} :invoice} @(re-frame/subscribe [::change-expense-accounts])]
(update-in db [::change-expense-accounts :invoice :expense-accounts]
conj {:amount 0 :expense-account-id nil :location (first locations)}))))
(re-frame/reg-event-db
::remove-expense-account-split
(fn [db [_ index]]
(update-in db [::change-expense-accounts :invoice :expense-accounts]
(fn [expense-accounts]
(vec (concat (take index expense-accounts)
(drop (inc index) expense-accounts)))))))
(defn change-expense-accounts-modal [{:keys [updated-event]}]
(let [{{:keys [expense-accounts total ] :or {expense-accounts [] total 0} {:keys [locations]} :company} :invoice :as data} @(re-frame/subscribe [::change-expense-accounts])
multi-location? (> (count locations) 1)
change-event [::events/change-form [::change-expense-accounts]]
chooseable-expense-accounts @(re-frame/subscribe [::subs/chooseable-expense-accounts])
expense-accounts-total (->> expense-accounts
(map :amount)
(map js/parseFloat)
(map #(or % 0))
(reduce + 0))
does-add-up? (= expense-accounts-total (js/parseFloat total))]
[action-modal {:id ::change-expense-accounts
:title "Change expense accounts"
:action-text "Save"
:save-event [::change-expense-accounts-saving updated-event]
:can-submit? (and does-add-up?
(s/valid? (s/* ::invoices-expense-accounts/invoices-expense-account) expense-accounts))}
[:div
[:a.button.is-primary {:on-click (dispatch-event [::add-expense-account-split])} "Add split"]]
[:table.table
[:thead
[:tr
[:th {:style {:width "500px"}} "Expense Account"]
(when multi-location?
[:th {:style {:width "200px"}} "Location"])
[:th {:style {:width "300px"}} "Amount"]
[:th {:style {:width "5em"}}]]]
[:tbody
(for [[expense-account index] (map vector expense-accounts (range))]
^{:key index}
[:tr
[:td.expandable [:div.control
[bind-field
[typeahead {:matches (map (fn [x] [(:id x) (str (:id x) " - " (:name x))]) chooseable-expense-accounts)
:type "typeahead"
:field [:invoice :expense-accounts index :expense-account-id]
:event change-event
:spec ::invoice/vendor-id
:subscription data}]]]]
(when multi-location?
[:td
(if-let [forced-location (-> expense-account :expense-account-id expense-accounts/expense-accounts :location)]
[:div.select
[:select {:disabled "disabled" :value forced-location} [:option {:value forced-location} forced-location]]]
[:div.select
[bind-field
[:select {:type "select"
:field [:invoice :expense-accounts index :location]
:spec (set locations)
:event change-event
:subscription data}
(map (fn [l] ^{:key l} [:option {:value l} l]) locations)]]])])
[:td
[:div.control
[:div.field.has-addons.is-extended
[:p.control [:a.button.is-static "$"]]
[:p.control
[bind-field
[:input.input {:type "number"
:field [:invoice :expense-accounts index :amount]
:event change-event
:subscription data
:value (get-in data [:invoice :expense-accounts index :amount])
:max (:total data)
:step "0.01"}]]]]]]
[:td [:a.button {:on-click (dispatch-event [::remove-expense-account-split index])} [:i.fa.fa-times]]]]
)
[:tr
[:th "TOTAL"]
[:th (str (gstring/format "$%.2f" expense-accounts-total ) " (" (gstring/format "$%.2f" total ) ")" )]]]]]))

View File

@@ -169,7 +169,7 @@
:aria-haspopup true
:tab-index "0"
#_#_:on-blur (delayed-dispatch [::toggle-expense-accounts id])
:on-blur (delayed-dispatch [::toggle-expense-accounts id])
:on-focus (dispatch-event [::toggle-expense-accounts id])
} "Accounts"]]
[:div.dropdown-menu {:role "menu"}
@@ -181,7 +181,7 @@
[:hr.dropdown-divider]
(when expense-event
[:a.dropdown-item.is-primary {:on-click (dispatch-event (conj expense-event id))} "Change"])]]])
[:a.dropdown-item.is-primary {:on-click (dispatch-event (conj expense-event i))} "Change"])]]])
[:span {:style {:margin-left "1em"}}]
(when on-edit-invoice
[:button.button {:on-click (fn [] (on-edit-invoice i))} [:span.icon [:i.fa.fa-pencil]]])

View File

@@ -4,14 +4,13 @@
[auto-ap.entities.vendors :as vendor]
[auto-ap.events :as events]
[auto-ap.views.utils :refer [dispatch-event]]
[auto-ap.utils :refer [by]]
[auto-ap.utils :refer [by replace-if]]
[auto-ap.views.pages.check :as check]
[auto-ap.views.components.invoice-table :refer [invoice-table] :as invoice-table]
[auto-ap.views.components.expense-accounts-dialog :as expense-accounts-dialog]
[auto-ap.subs :as subs]))
(re-frame/reg-sub
::invoice-page
(fn [db]
@@ -47,6 +46,19 @@
(fn [cofx [_ params]]
{:dispatch [::params-change @(re-frame/subscribe [::params])]}))
(re-frame/reg-event-fx
::expense-accounts-updated
(fn [{:keys [db]} [_ data]]
(let [updated (:edit-expense-accounts data)]
{:dispatch [::events/modal-completed ::expense-accounts-dialog/change-expense-accounts]
:db (-> db
(update-in [::invoice-page :invoices]
(fn [is]
(replace-if #(= (:id %1) (:id %2)) updated is)))
(dissoc ::change-expense-accounts))})))
(def paid-invoices-page
(with-meta
@@ -60,8 +72,11 @@
:params (re-frame/subscribe [::params])
:invoice-page (re-frame/subscribe [::invoice-page])
:status (re-frame/subscribe [::subs/status])
:expense-event [::expense-accounts-dialog/change-expense-accounts]
:on-params-change (fn [params]
(re-frame/dispatch [::params-change params]))
:check-boxes false}]]))
:check-boxes false}]
[expense-accounts-dialog/change-expense-accounts-modal
{:updated-event [::expense-accounts-updated]}]]))
{:component-will-mount #(do (println "HERE2") (re-frame/dispatch-sync [::params-change {}])) }))

View File

@@ -8,6 +8,7 @@
[auto-ap.entities.companies :as company]
[auto-ap.entities.invoice :as invoice]
[auto-ap.entities.vendors :as vendor]
[auto-ap.views.components.expense-accounts-dialog :as expense-accounts-dialog]
[auto-ap.expense-accounts :as expense-accounts]
[auto-ap.entities.invoices-expense-accounts :as invoices-expense-accounts]
[auto-ap.views.utils :refer [dispatch-event bind-field horizontal-field date->str str->date pretty standard]]
@@ -15,6 +16,7 @@
[auto-ap.views.pages.check :as check]
[auto-ap.views.components.invoice-table :refer [invoice-table] :as invoice-table]
[auto-ap.views.components.modal :refer [modal action-modal]]
[auto-ap.views.components.expense-accounts-dialog :refer [change-expense-accounts-modal ] :as change-expense-accounts]
[auto-ap.views.components.typeahead :refer [typeahead]]
[auto-ap.subs :as subs]
[auto-ap.events :as events]))
@@ -387,42 +389,16 @@
(assoc void-invoice :class "live-removed")
i)) is))))}))
(re-frame/reg-event-fx
::change-expense-accounts
(fn [{:keys [db]} [_ id]]
{:dispatch [::events/modal-status ::change-expense-accounts {:visible? true}]
:db (assoc-in db [::change-expense-accounts :invoice] (get (by :id (get-in db [::invoice-page :invoices])) id))}))
(re-frame/reg-event-fx
::change-expense-accounts-saving
(fn [{:keys [db]} [_ id]]
(let [{:keys [id expense-accounts]} (get-in db [::change-expense-accounts :invoice])]
{:graphql
{:token (-> db :user)
:query-obj {:venia/operation {:operation/type :mutation
:operation/name "EditExpenseAccounts"}
:venia/queries [{:query/data [:edit-expense-accounts
{:invoice-id id
:expense-accounts (map (fn [ea] {:id (:id ea)
:amount (:amount ea)
:location (:location ea)
:expense-account-id (:expense-account-id ea)})
expense-accounts)}
[:id :total :outstanding-balance :invoice-number :date
[:vendor [:name :id]]
[:expense_accounts [:amount :id :location :expense_account_id
[:expense_account [:id :name [:parent [:id :name]]]]]]
[:company [:name :id :locations]]
[:checks [:amount [:check [:amount :s3_url :check_number ]]]]
]]}]}
:on-success [::expense-accounts-updated]}})))
(re-frame/reg-event-fx
::expense-accounts-updated
(fn [{:keys [db]} [_ data]]
(let [updated (:edit-expense-accounts data)]
{:dispatch [::events/modal-completed ::change-expense-accounts]
{:dispatch [::events/modal-completed ::expense-accounts-dialog/change-expense-accounts]
:db (-> db
(update-in [::invoice-page :invoices]
@@ -431,98 +407,6 @@
(replace-if #(= (:id %1) (:id %2)) updated is)))
(dissoc ::change-expense-accounts))})))
(re-frame/reg-event-db
::add-expense-account-split
(fn [db _]
(let [{{{:keys [locations]} :company} :invoice} @(re-frame/subscribe [::change-expense-accounts])]
(update-in db [::change-expense-accounts :invoice :expense-accounts]
conj {:amount 0 :expense-account-id nil :location (first locations)}))))
(re-frame/reg-event-db
::remove-expense-account-split
(fn [db [_ index]]
(update-in db [::change-expense-accounts :invoice :expense-accounts]
(fn [expense-accounts]
(vec (concat (take index expense-accounts)
(drop (inc index) expense-accounts)))))))
(defn change-expense-accounts-modal []
(let [{{:keys [expense-accounts total ] :or {expense-accounts [] total 0} {:keys [locations]} :company} :invoice :as data} @(re-frame/subscribe [::change-expense-accounts])
multi-location? (> (count locations) 1)
change-event [::events/change-form [::change-expense-accounts]]
chooseable-expense-accounts @(re-frame/subscribe [::subs/chooseable-expense-accounts])
expense-accounts-total (->> expense-accounts
(map :amount)
(map js/parseFloat)
(map #(or % 0))
(reduce + 0))
does-add-up? (= expense-accounts-total (js/parseFloat total))]
[action-modal {:id ::change-expense-accounts
:title "Change expense accounts"
:action-text "Save"
:save-event [::change-expense-accounts-saving]
:can-submit? (and does-add-up?
(s/valid? (s/* ::invoices-expense-accounts/invoices-expense-account) expense-accounts))}
[:div
[:a.button.is-primary {:on-click (dispatch-event [::add-expense-account-split])} "Add split"]]
[:table.table
[:thead
[:tr
[:th {:style {:width "500px"}} "Expense Account"]
(when multi-location?
[:th {:style {:width "200px"}} "Location"])
[:th {:style {:width "300px"}} "Amount"]
[:th {:style {:width "5em"}}]]]
[:tbody
(for [[expense-account index] (map vector expense-accounts (range))]
^{:key index}
[:tr
[:td.expandable [:div.control
[bind-field
[typeahead {:matches (map (fn [x] [(:id x) (str (:id x) " - " (:name x))]) chooseable-expense-accounts)
:type "typeahead"
:field [:invoice :expense-accounts index :expense-account-id]
:event change-event
:spec ::invoice/vendor-id
:subscription data}]]]]
(when multi-location?
[:td
(if-let [forced-location (-> expense-account :expense-account-id expense-accounts/expense-accounts :location)]
[:div.select
[:select {:disabled "disabled" :value forced-location} [:option {:value forced-location} forced-location]]]
[:div.select
[bind-field
[:select {:type "select"
:field [:invoice :expense-accounts index :location]
:spec (set locations)
:event change-event
:subscription data}
(map (fn [l] ^{:key l} [:option {:value l} l]) locations)]]])])
[:td
[:div.control
[:div.field.has-addons.is-extended
[:p.control [:a.button.is-static "$"]]
[:p.control
[bind-field
[:input.input {:type "number"
:field [:invoice :expense-accounts index :amount]
:event change-event
:subscription data
:value (get-in data [:invoice :expense-accounts index :amount])
:max (:total data)
:step "0.01"}]]]]]]
[:td [:a.button {:on-click (dispatch-event [::remove-expense-account-split index])} [:i.fa.fa-times]]]]
)
[:tr
[:th "TOTAL"]
[:th (str (gstring/format "$%.2f" expense-accounts-total ) " (" (gstring/format "$%.2f" total ) ")" )]]]]]))
(defn print-checks-modal []
(let [{:keys [checked]} @(re-frame/subscribe [::invoice-page])
{:keys [shown? invoices printing?] :as advanced-print-checks} @(re-frame/subscribe [::advanced-print-checks])
@@ -834,13 +718,13 @@
:checked checked
:on-check-changed (fn [which]
(re-frame/dispatch [::toggle-check which]))
:expense-event [::change-expense-accounts]}]
:expense-event [::expense-accounts-dialog/change-expense-accounts]}]
[print-checks-modal]
[new-invoice-modal]
[edit-invoice-modal]
[handwrite-checks-modal]
[change-expense-accounts-modal]
[change-expense-accounts-modal {:updated-event [::expense-accounts-updated]}]
(when check-results-shown?
(if pdf-url
[modal