From 3fd9a1c96414ed0ac20306e2cf31b7c5239ca104 Mon Sep 17 00:00:00 2001 From: Bryce Covert Date: Tue, 16 Apr 2019 11:22:19 -0700 Subject: [PATCH] splitting out form for refactoring. --- src/cljc/auto_ap/utils.cljc | 5 +- .../auto_ap/views/pages/invoices/common.cljs | 9 + .../auto_ap/views/pages/invoices/form.cljs | 364 ++++++++++++++++ .../auto_ap/views/pages/unpaid_invoices.cljs | 391 ++---------------- 4 files changed, 408 insertions(+), 361 deletions(-) create mode 100644 src/cljs/auto_ap/views/pages/invoices/common.cljs create mode 100644 src/cljs/auto_ap/views/pages/invoices/form.cljs diff --git a/src/cljc/auto_ap/utils.cljc b/src/cljc/auto_ap/utils.cljc index a79ed434..6aa6b3c7 100644 --- a/src/cljc/auto_ap/utils.cljc +++ b/src/cljc/auto_ap/utils.cljc @@ -24,13 +24,12 @@ (fn [t] (if (= (f t) (f x)) (do (reset! found? true) - (println "found" (f t) t (f x) x) - x) + x) t)) xs)] (if @found? replaced - (conj replaced x)))) + (into [x] replaced)))) (defn dollars-0? [amt] (< -0.001 amt 0.001)) diff --git a/src/cljs/auto_ap/views/pages/invoices/common.cljs b/src/cljs/auto_ap/views/pages/invoices/common.cljs new file mode 100644 index 00000000..c160cfde --- /dev/null +++ b/src/cljs/auto_ap/views/pages/invoices/common.cljs @@ -0,0 +1,9 @@ +(ns auto-ap.views.pages.invoices.common) + +(def invoice-read [:id :total :outstanding-balance :date :invoice-number :status + [:client [:id :name :locations]] + [:payments [:amount [:payment [:amount :s3_url :check_number ]]]] + [:vendor [:id :name]] + [:expense_accounts [:amount :id + :location + [:account [:id :numeric-code :name :location]]]]]) diff --git a/src/cljs/auto_ap/views/pages/invoices/form.cljs b/src/cljs/auto_ap/views/pages/invoices/form.cljs new file mode 100644 index 00000000..851f072f --- /dev/null +++ b/src/cljs/auto_ap/views/pages/invoices/form.cljs @@ -0,0 +1,364 @@ +(ns auto-ap.views.pages.invoices.form + (:require [auto-ap.entities.invoice :as invoice] + [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.pages.invoices.common :refer [invoice-read]] + [auto-ap.views.utils + :refer + [bind-field date->str date-picker dispatch-event standard]] + [cljs-time.core :as c] + [clojure.spec.alpha :as s] + [re-frame.core :as re-frame])) + +;; SUBS + +(re-frame/reg-sub + ::can-submit-edit-invoice + :<- [::forms/form ::new-invoice] + (fn [{:keys [data status]} _] + + (let [min-total (if (= (:total (:original data)) (:outstanding-balance (:original data))) + nil + (- (:total (:original data)) (:outstanding-balance (:original data))))] + (and (not= :loading status) + (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)))))) + +;; EVENTS +(re-frame/reg-event-db + ::adding + (fn [db [_ new]] + (-> db (forms/start-form ::new-invoice new)))) + +(re-frame/reg-event-db + ::editing + (fn [db [_ which]] + (let [edit-invoice (update which :date #(date->str % standard)) + edit-invoice (assoc edit-invoice :original edit-invoice)] + (-> db + (forms/start-form ::new-invoice {:id (:id edit-invoice) + :status (:status edit-invoice) + :date (:date edit-invoice) + :invoice-number (:invoice-number edit-invoice) + :total (:total edit-invoice) + :original edit-invoice + :vendor-id (:id (:vendor edit-invoice)) + :vendor-name (:name (:vendor edit-invoice)) + :client-id (:id (:client edit-invoice)) + :expense-accounts (:expense-accounts edit-invoice) + :client-name (:name (:client edit-invoice))}))))) + + +(re-frame/reg-event-fx + ::change-new-invoice-client + (fn [{:keys [db ]} [_ location field value]] + (let [first-location (-> @(re-frame/subscribe [::subs/clients-by-id]) + (get-in [value :locations]) + first)] + {:dispatch [::forms/change ::new-invoice + [:client-id] value + [:location] first-location]}))) + +(re-frame/reg-event-fx + ::create-submitted + (fn [{:keys [db]} [_ invoice-created]] + (when @(re-frame/subscribe [::can-submit-edit-invoice]) + (let [{:keys [data]} @(re-frame/subscribe [::forms/form ::new-invoice])] + {:db (forms/loading db ::new-invoice) + :graphql + {:token (-> db :user) + :query-obj {:venia/operation {:operation/type :mutation + :operation/name "AddInvoice"} + :venia/queries [{:query/data [:add-invoice + {:invoice {:date (:date data) + :vendor-id (:vendor-id data) + :client-id (:client-id data) + :invoice-number (:invoice-number data) + :location (:location data) + :total (:total data) + }} + invoice-read]}]} + :on-success [::succeeded :create invoice-created nil] + :on-error [::forms/save-error ::new-invoice]}})))) + +(re-frame/reg-event-fx + ::update-submitted + (fn [{:keys [db]} [_ invoice-created]] + (when @(re-frame/subscribe [::can-submit-edit-invoice]) + (let [{{:keys [date total invoice-number id expense-accounts]} :data} @(re-frame/subscribe [::forms/form ::new-invoice])] + {:db (-> db + (assoc-in [::forms/forms ::new-invoice :status] :loading) + (assoc-in [::forms/forms ::new-invoice :error] nil)) + :graphql + {:token (-> db :user) + :query-obj {:venia/operation {:operation/type :mutation + :operation/name "EditInvoice"} + :venia/queries [{:query/data [:edit-invoice + {:invoice {:id id :invoice-number invoice-number :date date :total total :expense-accounts (map (fn [ea] + {:id (:id ea) + :amount (:amount ea)}) + expense-accounts)}} + invoice-read]}]} + :on-success [::succeeded :edit invoice-created nil] + :on-error [::forms/save-error ::new-invoice]}})))) + +(re-frame/reg-event-fx + ::add-and-print-submitted + (fn [{:keys [db]} [_ invoice-created invoice-printed bank-account-id type ]] + (when @(re-frame/subscribe [::can-submit-edit-invoice]) + (let [{:keys [data]} @(re-frame/subscribe [::forms/form ::new-invoice])] + {:db (forms/loading db ::new-invoice) + :graphql + {:token (-> db :user) + :query-obj {:venia/operation {:operation/type :mutation + :operation/name "AddAndPrintInvoice"} + :venia/queries [{:query/data [:add-and-print-invoice + {:invoice {:date (:date data) + :vendor-id (:vendor-id data) + :client-id (:client-id data) + :invoice-number (:invoice-number data) + :location (:location data) + :total (:total data)} + :bank-account-id bank-account-id + :type type} + [:pdf-url [:invoices invoice-read]]]}]} + :on-success [::succeeded :add-and-print invoice-created invoice-printed] + :on-error [::forms/save-error ::new-invoice]}})))) + + +(re-frame/reg-event-fx + ::succeeded + (fn [{:keys [db]} [_ command invoice-created invoice-printed result]] + (let [invoice (condp = command + :edit (:edit-invoice result) + + :create (:add-invoice result) + + :add-and-print (first (:invoices (:add-and-print-invoice result)))) + db (condp = command + :edit (-> db (forms/stop-form ::new-invoice)) + :create (-> db + (forms/stop-form ::new-invoice) + (forms/start-form ::new-invoice {:client-id (:id @(re-frame/subscribe [::subs/client])) + :status :unpaid + :date (date->str (c/now) standard) + :location (first (:locations @(re-frame/subscribe [::subs/client])))})) + :add-and-print (-> db + (forms/stop-form ::new-invoice) + (forms/start-form ::new-invoice {:client-id (:id @(re-frame/subscribe [::subs/client])) + :status :unpaid + :date (date->str (c/now) standard) + :location (first (:locations @(re-frame/subscribe [::subs/client])))}))) + events (cond-> [(conj invoice-created invoice)] + (= :add-and-print command) (conj (conj invoice-printed (:pdf-url (:add-and-print-invoice result)))))] + + {:db db + :dispatch-n events}))) + +(re-frame/reg-event-fx + ::invoice-created-and-printed + (fn [{:keys [db]} [_ {:keys [add-and-print-invoice]}]] + {:db (-> db + (forms/stop-form ::new-invoice) + (forms/start-form ::new-invoice {:client-id (:id @(re-frame/subscribe [::subs/client])) + :status :unpaid + :date (date->str (c/now) standard) + :location (first (:locations @(re-frame/subscribe [::subs/client])))}) + (update-in [::invoice-page :invoices] + (fn [is] + (into (vec (map #(assoc % :class "live-added") + (:invoices add-and-print-invoice))) + is))) + (assoc-in [::check-results :shown?] true) + (assoc-in [::check-results :pdf-url] (:pdf-url add-and-print-invoice)))})) + + +;; VIEWS + +(defn form [{:keys [can-change-amount? invoice-created invoice-printed]}] + [forms/side-bar-form {:form ::new-invoice } + (let [{:keys [data active? error id]} @(re-frame/subscribe [::forms/form ::new-invoice]) + exists? (:id data) + current-client @(re-frame/subscribe [::subs/client]) + can-change-amount? (#{:unpaid ":unpaid"} (:status data)) + change-event [::forms/change ::new-invoice] + locations (get-in @(re-frame/subscribe [::subs/clients-by-id]) [(:client-id data) :locations]) + multi-location? (> (count locations) 1) + + min-total (if (= (:total (:original data)) (:outstanding-balance (:original data))) + nil + (- (:total (:original data)) (:outstanding-balance (:original data)))) + should-select-location? (and locations + (> (count locations) 1)) + chooseable-expense-accounts @(re-frame/subscribe [::subs/chooseable-expense-accounts])] + ^{:key id} + [:form { :on-submit (fn [e] + (when (.-stopPropagation e) + (.stopPropagation e) + (.preventDefault e)) + (if exists? + (re-frame/dispatch-sync [::update-submitted invoice-created]) + (re-frame/dispatch-sync [::create-submitted invoice-created])))} + [:h1.title.is-2 "New Invoice"] + (when-not @(re-frame/subscribe [::subs/client]) + [:div.field + [:p.help "Client"] + [:div.control + [bind-field + [typeahead {:matches (map (fn [x] [(:id x) (:name x)]) @(re-frame/subscribe [::subs/clients])) + :type "typeahead" + :auto-focus (if @(re-frame/subscribe [::subs/client]) false true) + :field [:client-id] + :disabled exists? + :event [::change-new-invoice-client [::new-invoice]] + :spec ::invoice/client-id + :subscription data}]]]]) + + (when (and should-select-location? (not exists?)) + [:div.field + [:p.help "Location"] + [:div.control + [:div.select + [bind-field + [:select {:type "select" + :field [:location] + :spec (set locations) + :event change-event + :subscription data} + (map (fn [l] [:option {:value l} l]) locations)]]]]]) + [:div.field + [:p.help "Vendor"] + [:div.control + [bind-field + [typeahead {:matches (map (fn [x] [(:id x) (:name x)]) @(re-frame/subscribe [::subs/vendors])) + :type "typeahead" + :disabled exists? + :auto-focus (if @(re-frame/subscribe [::subs/client]) true false) + :field [:vendor-id] + :text-field [:vendor-name] + :event change-event + :spec (s/nilable ::invoice/vendor-id) + :subscription data}]]]] + + [:div.field + [:p.help "Date"] + [:div.control + [bind-field + [date-picker {:class-name "input" + :class "input" + :format-week-number (fn [] "") + :previous-month-button-label "" + :placeholder "mm/dd/yyyy" + :next-month-button-label "" + :next-month-label "" + :type "date" + :field [:date] + :event change-event + :spec ::invoice/date + :subscription data}] + #_[:input.input {:type "date" + :field [:date] + :event change-event + :spec ::invoice/date + :subscription data}]]]] + + + #_[horizontal-field + [:label.label "Date 2 "] + + ] + + [:div.field + [:p.help "Invoice #"] + [:div.control + [bind-field + [:input.input {:type "text" + :field [:invoice-number] + :event change-event + :spec ::invoice/invoice-number + :subscription data}]]]] + + [:div.field + [:p.help "Total"] + [:div.control + [:div.field.has-addons.is-extended + [:p.control [:a.button.is-static "$"]] + [:p.control + [bind-field + [:input.input {:type "number" + :field [:total] + :disabled (if can-change-amount? "" "disabled") + :event change-event + :min min-total + :subscription data + :spec ::invoice/total + :step "0.01"}]]]]]] + + (when exists? + [:div + [:h2.subtitle "Expense Accounts"] + + (for [[index {:keys [id location] :as expense-account {account-id :id account-numeric-code :numeric-code account-name :name} :account}] (map vector (range) (:expense-accounts data))] + ^{:key id} + [:div.columns + [:div.column account-numeric-code " - " account-name] + + (when multi-location? + [:div.column location]) + + [:div.column + [: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"} + :event [::forms/change ::new-invoice] + :subscription data + :value (get-in expense-account [:amount]) + :max (:total data) + :step "0.01"}]]]]]]])]) + + (when error + ^{:key error} [:div.notification.is-warning.animated.fadeInUp + error]) + + [:div.columns + (when-not exists? + [:div.column + [drop-down {:header [:button.button.is-info.is-outlined.is-medium.is-fullwidth {:aria-haspopup true + :type "button" + :on-click (dispatch-event [::events/toggle-menu ::add-and-print-invoice ]) + :disabled (if @(re-frame/subscribe [::can-submit-edit-invoice]) + "" + "disabled") + + :class (if false + "is-loading" + "")} + "Save & Pay " + [:span " "] + [:span.icon.is-small [:i.fa.fa-angle-down {:aria-hidden "true"}]]] + :class "is-fullwidth" + :id ::add-and-print-invoice} + [:div + (list + (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 [::add-and-print-invoice invoice-created invoice-printed id :cash])} "With cash"] + (list + ^{:key (str id "-check")} [:a.dropdown-item {:on-click (dispatch-event [::add-and-print-submitted invoice-created invoice-printed id :check])} "Print checks from " name] + ^{:key (str id "-debit")} [:a.dropdown-item {:on-click (dispatch-event [::add-and-print-submitted invoice-created invoice-printed id :debit])} "Debit from " name]))))]]]) + [:div.column + [:button.button.is-medium.is-primary.is-fullwidth {:disabled (if @(re-frame/subscribe [::can-submit-edit-invoice]) + "" + "disabled") + :class (str @(re-frame/subscribe [::forms/loading-class ::new-invoice]) + (when error " animated shake"))} "Save"]] ]])]) diff --git a/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs b/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs index b37b9146..216bff55 100644 --- a/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs +++ b/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs @@ -3,7 +3,8 @@ [auto-ap.events :as events] [auto-ap.forms :as forms] [auto-ap.subs :as subs] - [auto-ap.utils :refer [by replace-if]] + [auto-ap.utils :refer [by replace-if replace-by]] + [auto-ap.views.pages.invoices.form :as form] [auto-ap.views.components.dropdown :refer [drop-down]] [auto-ap.views.components.expense-accounts-dialog :as expense-accounts-dialog :refer [change-expense-accounts-modal]] [auto-ap.views.components.invoice-table :as invoice-table :refer [invoice-table]] @@ -13,6 +14,7 @@ [auto-ap.views.components.typeahead :refer [typeahead]] [auto-ap.views.components.vendor-dialog :refer [vendor-dialog]] [auto-ap.views.components.vendor-filter :refer [vendor-filter]] + [auto-ap.views.pages.invoices.common :refer [invoice-read]] [auto-ap.views.utils :refer [bind-field @@ -28,14 +30,6 @@ [re-frame.core :as re-frame] [reagent.core :as r])) -(def invoice-read [:id :total :outstanding-balance :date :invoice-number :status - [:client [:id :name :locations]] - [:payments [:amount [:payment [:amount :s3_url :check_number ]]]] - [:vendor [:id :name]] - [:expense_accounts [:amount :id - :location - [:account [:id :numeric-code :name :location]]]]]) - (defn does-amount-exceed-outstanding? [amount outstanding-balance] (let [amount (js/parseFloat amount) outstanding-balance (js/parseFloat outstanding-balance)] @@ -83,6 +77,13 @@ (fn [db] (-> db (::params {})))) +(re-frame/reg-event-db + ::invoice-updated + (fn [db [_ invoice]] + (println "HERE") + (update-in db + [::invoice-page :invoices] + replace-by :id (assoc invoice :class "live-added")))) (re-frame/reg-event-fx ::params-change @@ -262,10 +263,15 @@ (assoc-in [::invoice-page :checked] nil) (assoc-in [::invoice-page :print-checks-loading?] false) (assoc-in [::advanced-print-checks :printing?] false) - (assoc-in [::advanced-print-checks :shown?] false) - (assoc-in [::check-results :shown?] true) - (assoc-in [::check-results :pdf-url] pdf-url) - )}))) + (assoc-in [::advanced-print-checks :shown?] false)) + :dispatch [::checks-printed pdf-url]}))) + +(re-frame/reg-event-db + ::checks-printed + (fn [db [_ pdf-url :as g]] + (-> db + (assoc-in [::check-results :shown?] true) + (assoc-in [::check-results :pdf-url] pdf-url)))) (re-frame/reg-event-fx ::invalidated @@ -275,106 +281,18 @@ (re-frame/reg-event-fx ::new-invoice-clicked (fn [{:keys [db]} _] - {:db - (-> db - (forms/start-form ::new-invoice {:client-id (:id @(re-frame/subscribe [::subs/client])) - :status :unpaid - #_#_:date (date->str (c/now) standard) - :location (first (:locations @(re-frame/subscribe [::subs/client])))}))})) - -(re-frame/reg-event-db - ::edit-invoice - (fn [db [_ which]] - (let [edit-invoice (update which :date #(date->str % standard)) - edit-invoice (assoc edit-invoice :original edit-invoice)] - - (-> db - - (forms/start-form ::new-invoice {:id (:id edit-invoice) - :status (:status edit-invoice) - :date (:date edit-invoice) #_(date->str (:date edit-invoice) standard) - :invoice-number (:invoice-number edit-invoice) - :total (:total edit-invoice) - :original edit-invoice - :vendor-id (:id (:vendor edit-invoice)) - :vendor-name (:name (:vendor edit-invoice)) - :client-id (:id (:client edit-invoice)) - :expense-accounts (:expense-accounts edit-invoice) - :client-name (:name (:client edit-invoice))}))))) + {:dispatch [::form/adding {:client-id (:id @(re-frame/subscribe [::subs/client])) + :status :unpaid + #_#_:date (date->str (c/now) standard) + :location (first (:locations @(re-frame/subscribe [::subs/client])))}]})) + + -(re-frame/reg-event-fx - ::create-invoice - (fn [{:keys [db]} _] - (when @(re-frame/subscribe [::can-submit-edit-invoice]) - (let [{:keys [data]} @(re-frame/subscribe [::forms/form ::new-invoice])] - {:db (forms/loading db ::new-invoice) - :graphql - {:token (-> db :user) - :query-obj {:venia/operation {:operation/type :mutation - :operation/name "AddInvoice"} - - :venia/queries [{:query/data [:add-invoice - {:invoice {:date (:date data) - :vendor-id (:vendor-id data) - :client-id (:client-id data) - :invoice-number (:invoice-number data) - :location (:location data) - :total (:total data) - }} - invoice-read]}]} - :on-success [::invoice-created] - :on-error [::forms/save-error ::new-invoice]}})))) - -(re-frame/reg-event-fx - ::save-and-print-invoice - (fn [{:keys [db]} [_ bank-account-id type ]] - - (when @(re-frame/subscribe [::can-submit-edit-invoice]) - (let [{:keys [data]} @(re-frame/subscribe [::forms/form ::new-invoice])] - {:db (forms/loading db ::new-invoice) - :graphql - {:token (-> db :user) - :query-obj {:venia/operation {:operation/type :mutation - :operation/name "AddAndPrintInvoice"} - - :venia/queries [{:query/data [:add-and-print-invoice - {:invoice {:date (:date data) - :vendor-id (:vendor-id data) - :client-id (:client-id data) - :invoice-number (:invoice-number data) - :location (:location data) - :total (:total data)} - :bank-account-id bank-account-id - :type type} - [:pdf-url [:invoices invoice-read]]]}]} - :on-success [::invoice-created-and-printed] - :on-error [::forms/save-error ::new-invoice]}})))) -(re-frame/reg-event-fx - ::edit-invoice-saving - (fn [{:keys [db]} _] - (when @(re-frame/subscribe [::can-submit-edit-invoice]) - (let [{{:keys [date total invoice-number id expense-accounts]} :data} @(re-frame/subscribe [::forms/form ::new-invoice])] - {:db (-> db - (assoc-in [::forms/forms ::new-invoice :status] :loading) - (assoc-in [::forms/forms ::new-invoice :error] nil)) - :graphql - {:token (-> db :user) - :query-obj {:venia/operation {:operation/type :mutation - :operation/name "EditInvoice"} - - :venia/queries [{:query/data [:edit-invoice - {:invoice {:id id :invoice-number invoice-number :date date :total total :expense-accounts (map (fn [ea] - {:id (:id ea) - :amount (:amount ea)}) - expense-accounts)}} - invoice-read]}]} - :on-success [::invoice-edited] - :on-error [::forms/save-error ::new-invoice]}})))) (re-frame/reg-event-fx ::unvoid-invoice @@ -447,48 +365,11 @@ -(re-frame/reg-event-fx - ::invoice-created - (fn [{:keys [db]} [_ {:keys [add-invoice]}]] - {:db (-> db - (forms/stop-form ::new-invoice) - (forms/start-form ::new-invoice {:client-id (:id @(re-frame/subscribe [::subs/client])) - :status :unpaid - :date (date->str (c/now) standard) - :location (first (:locations @(re-frame/subscribe [::subs/client])))}) - (update-in [::invoice-page :invoices] - (fn [is] - (into [(assoc add-invoice :class "live-added")] - is))))})) -(re-frame/reg-event-fx - ::invoice-created-and-printed - (fn [{:keys [db]} [_ {:keys [add-and-print-invoice]}]] - {:db (-> db - (forms/stop-form ::new-invoice) - (forms/start-form ::new-invoice {:client-id (:id @(re-frame/subscribe [::subs/client])) - :status :unpaid - :date (date->str (c/now) standard) - :location (first (:locations @(re-frame/subscribe [::subs/client])))}) - (update-in [::invoice-page :invoices] - (fn [is] - (into (vec (map #(assoc % :class "live-added") - (:invoices add-and-print-invoice))) - is))) - (assoc-in [::check-results :shown?] true) - (assoc-in [::check-results :pdf-url] (:pdf-url add-and-print-invoice)))})) -(re-frame/reg-event-fx - ::invoice-edited - (fn [{:keys [db]} [_ {:keys [edit-invoice]}]] - {:db (-> db - (forms/stop-form ::new-invoice) - (update-in [::invoice-page :invoices] - (fn [is] - (mapv (fn [i] - (if (= (:id i) (:id edit-invoice)) - (assoc edit-invoice :class "live-added") - i)) is))))})) + + + @@ -587,19 +468,7 @@ :max outstanding-balance :step "0.01"}]]]]]])]]]))) -(re-frame/reg-sub - ::can-submit-edit-invoice - :<- [::forms/form ::new-invoice] - (fn [{:keys [data status]} _] - - (let [min-total (if (= (:total (:original data)) (:outstanding-balance (:original data))) - nil - (- (:total (:original data)) (:outstanding-balance (:original data))))] - (and (not= :loading status) - (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)))))) + (defn handwrite-checks-modal [] (let [{:keys [checked]} @(re-frame/subscribe [::invoice-page]) @@ -685,204 +554,9 @@ #_#_:max outstanding-balance :step "0.01"}]]]]]])]]])) -(re-frame/reg-event-fx - ::change-new-invoice-client - (fn [{:keys [db ]} [_ location field value]] - (let [first-location (-> @(re-frame/subscribe [::subs/clients-by-id]) - (get-in [value :locations]) - first)] - {:dispatch [::forms/change ::new-invoice - [:client-id] value - [:location] first-location]}))) -(defn edit-invoice-form [{:keys [can-change-amount?]}] - [forms/side-bar-form {:form ::new-invoice } - (let [{:keys [data active? error id]} @(re-frame/subscribe [::forms/form ::new-invoice]) - exists? (:id data) - current-client @(re-frame/subscribe [::subs/client]) - can-change-amount? (#{:unpaid ":unpaid"} (:status data)) - change-event [::forms/change ::new-invoice] - locations (get-in @(re-frame/subscribe [::subs/clients-by-id]) [(:client-id data) :locations]) - multi-location? (> (count locations) 1) - min-total (if (= (:total (:original data)) (:outstanding-balance (:original data))) - nil - (- (:total (:original data)) (:outstanding-balance (:original data)))) - should-select-location? (and locations - (> (count locations) 1)) - chooseable-expense-accounts @(re-frame/subscribe [::subs/chooseable-expense-accounts])] - ^{:key id} - [:form { :on-submit (fn [e] - (when (.-stopPropagation e) - (.stopPropagation e) - (.preventDefault e)) - (if exists? - (re-frame/dispatch-sync [::edit-invoice-saving]) - (re-frame/dispatch-sync [::create-invoice])))} - [:h1.title.is-2 "New Invoice"] - (when-not @(re-frame/subscribe [::subs/client]) - [:div.field - [:p.help "Client"] - [:div.control - [bind-field - [typeahead {:matches (map (fn [x] [(:id x) (:name x)]) @(re-frame/subscribe [::subs/clients])) - :type "typeahead" - :auto-focus (if @(re-frame/subscribe [::subs/client]) false true) - :field [:client-id] - :disabled exists? - :event [::change-new-invoice-client [::new-invoice]] - :spec ::invoice/client-id - :subscription data}]]]]) - (when (and should-select-location? (not exists?)) - [:div.field - [:p.help "Location"] - [:div.control - [:div.select - [bind-field - [:select {:type "select" - :field [:location] - :spec (set locations) - :event change-event - :subscription data} - (map (fn [l] [:option {:value l} l]) locations)]]]]]) - [:div.field - [:p.help "Vendor"] - [:div.control - [bind-field - [typeahead {:matches (map (fn [x] [(:id x) (:name x)]) @(re-frame/subscribe [::subs/vendors])) - :type "typeahead" - :disabled exists? - :auto-focus (if @(re-frame/subscribe [::subs/client]) true false) - :field [:vendor-id] - :text-field [:vendor-name] - :event change-event - :spec (s/nilable ::invoice/vendor-id) - :subscription data}]]]] - - [:div.field - [:p.help "Date"] - [:div.control - [bind-field - [date-picker {:class-name "input" - :class "input" - :format-week-number (fn [] "") - :previous-month-button-label "" - :placeholder "mm/dd/yyyy" - :next-month-button-label "" - :next-month-label "" - :type "date" - :field [:date] - :event change-event - :spec ::invoice/date - :subscription data}] - #_[:input.input {:type "date" - :field [:date] - :event change-event - :spec ::invoice/date - :subscription data}]]]] - - - #_[horizontal-field - [:label.label "Date 2 "] - - ] - - [:div.field - [:p.help "Invoice #"] - [:div.control - [bind-field - [:input.input {:type "text" - :field [:invoice-number] - :event change-event - :spec ::invoice/invoice-number - :subscription data}]]]] - - [:div.field - [:p.help "Total"] - [:div.control - [:div.field.has-addons.is-extended - [:p.control [:a.button.is-static "$"]] - [:p.control - [bind-field - [:input.input {:type "number" - :field [:total] - :disabled (if can-change-amount? "" "disabled") - :event change-event - :min min-total - :subscription data - :spec ::invoice/total - :step "0.01"}]]]]]] - - (when exists? - [:div - [:h2.subtitle "Expense Accounts"] - - (for [[index {:keys [id location] :as expense-account {account-id :id account-numeric-code :numeric-code account-name :name} :account}] (map vector (range) (:expense-accounts data))] - ^{:key id} - [:div.columns - [:div.column account-numeric-code " - " account-name] - - (when multi-location? - [:div.column location]) - - [:div.column - [: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"} - :event [::forms/change ::new-invoice] - :subscription data - :value (get-in expense-account [:amount]) - :max (:total data) - :step "0.01"}]]]]]]])]) - - (when error - ^{:key error} [:div.notification.is-warning.animated.fadeInUp - error]) - - [:div.columns - (when-not exists? - [:div.column - [drop-down {:header [:button.button.is-info.is-outlined.is-medium.is-fullwidth {:aria-haspopup true - :type "button" - :on-click (dispatch-event [::events/toggle-menu ::save-and-print-invoice ]) - :disabled (if @(re-frame/subscribe [::can-submit-edit-invoice]) - "" - "disabled") - - :class (if false - "is-loading" - "")} - "Save & Pay " - [:span " "] - [:span.icon.is-small [:i.fa.fa-angle-down {:aria-hidden "true"}]]] - :class "is-fullwidth" - :id ::save-and-print-invoice} - [:div - (list - (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 [::save-and-print-invoice id :cash])} "With cash"] - (list - ^{:key (str id "-check")} [:a.dropdown-item {:on-click (dispatch-event [::save-and-print-invoice id :check])} "Print checks from " name] - ^{:key (str id "-debit")} [:a.dropdown-item {:on-click (dispatch-event [::save-and-print-invoice id :debit])} "Debit from " name]))))]]]) - [:div.column - [:button.button.is-medium.is-primary.is-fullwidth {:disabled (if @(re-frame/subscribe [::can-submit-edit-invoice]) - "" - "disabled") - :class (str @(re-frame/subscribe [::forms/loading-class ::new-invoice]) - (when error " animated shake"))} "Save"]] - - ] - - - ])] - ) (re-frame/reg-event-db @@ -1008,7 +682,7 @@ :invoice-page (re-frame/subscribe [::invoice-page]) :status (re-frame/subscribe [::subs/status]) :on-edit-invoice (fn [which] - (re-frame/dispatch [::edit-invoice which])) + (re-frame/dispatch [::form/editing which])) :on-unvoid-invoice (fn [which] (re-frame/dispatch [::unvoid-invoice which])) @@ -1029,7 +703,7 @@ :component-will-mount #(re-frame/dispatch-sync [::params-change {:status status}]) })) (defn unpaid-invoices-page [{:keys [status]}] - (let [{invoice-bar-active? :active?} @(re-frame/subscribe [::forms/form ::new-invoice])] + (let [{invoice-bar-active? :active?} @(re-frame/subscribe [::forms/form ::form/new-invoice])] [side-bar-layout {:side-bar [invoices-side-bar {} ^{:key "extra-filter"} [:div @@ -1048,4 +722,5 @@ [print-checks-modal] [handwrite-checks-modal] [change-expense-accounts-modal {:updated-event [::expense-accounts-updated]}]] - :right-side-bar [appearing-side-bar {:visible? invoice-bar-active?} [edit-invoice-form]]}])) + :right-side-bar [appearing-side-bar {:visible? invoice-bar-active?} [form/form {:invoice-created [::invoice-updated] + :invoice-printed [::checks-printed]}]]}]))