diff --git a/src/cljs/auto_ap/views/components/modal.cljs b/src/cljs/auto_ap/views/components/modal.cljs index 79b047ee..1e0929aa 100644 --- a/src/cljs/auto_ap/views/components/modal.cljs +++ b/src/cljs/auto_ap/views/components/modal.cljs @@ -125,9 +125,8 @@ [:div.buttons (when confirm [:button.button {:class (conj (status/class-for status) (:class confirm) ) - :disabled (if can-submit - false - true) + :disabled (or (status/disabled-for status) + (not can-submit)) :on-click (:on-click confirm)} (:value confirm)]) (when cancel? diff --git a/src/cljs/auto_ap/views/pages/invoices/advanced_print_checks.cljs b/src/cljs/auto_ap/views/pages/invoices/advanced_print_checks.cljs new file mode 100644 index 00000000..8dad69a2 --- /dev/null +++ b/src/cljs/auto_ap/views/pages/invoices/advanced_print_checks.cljs @@ -0,0 +1,144 @@ +(ns auto-ap.views.pages.invoices.advanced-print-checks + (: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.pages.invoices.common :refer [invoice-read does-amount-exceed-outstanding?]] + [auto-ap.views.pages.invoices.form :as form] + [auto-ap.views.utils :refer [dispatch-event horizontal-field with-user]] + [re-frame.core :as re-frame])) + +(re-frame/reg-sub + ::can-submit-advanced-print-checks + :<- [::forms/form ::advanced-print-checks] + (fn [{ {:keys [invoices invoice-amounts]} :data}] + (cond (seq (filter + (fn [{:keys [id outstanding-balance]}] + (does-amount-exceed-outstanding? (get-in invoice-amounts [id :amount]) outstanding-balance )) + invoices)) + false + + :else + true))) + +(def advanced-print-checks-form (forms/vertical-form {:submit-event [::advanced-print-checks-submitted] + :change-event [::forms/change ::advanced-print-checks] + :can-submit [::can-submit-advanced-print-checks] + :id ::advanced-print-checks})) + + +(defn print-checks-modal [] + (let [real-bank-accounts @(re-frame/subscribe [::subs/real-bank-accounts]) + {:keys [data active? error id]} @(re-frame/subscribe [::forms/form ::advanced-print-checks]) + {:keys [form-inline horizontal-field field raw-field error-notification submit-button]} advanced-print-checks-form] + + (form-inline {} + [:<> + [:div.field + [:label.label "Pay using"] + [:div.control + [:span.select + [raw-field + [:select {:type "select" + :field :bank-account-id} + (for [{:keys [id number name]} real-bank-accounts] + ^{:key id} [:option {:value id} name])]]]]] + + [:table.table.is-fullwidth + [:thead + [:tr + [:th "Vendor"] + [:th "Invoice ID"] + [:th {:style {"width" "10em"}} "Payment"]]] + [:tbody + (doall + (for [{:keys [vendor payment outstanding-balance invoice-number id] :as i} (:invoices data)] + ^{:key id} + [:tr + [:td (:name vendor)] + [:td invoice-number] + + [:td [:div.field.has-addons.is-extended + [:p.control [:a.button.is-static "$"]] + [:p.control + (raw-field + [:input.input.has-text-right {:type "number" + :field [:invoice-amounts id :amount] + :step "0.01"}])]]]]))]]]))) + +(re-frame/reg-event-fx + ::show + (fn [{:keys [db]} [_ invoices]] + {:dispatch [::modal/modal-requested {:title "Print Checks" + :body [print-checks-modal] + :confirm {:value "Print checks" + :status-from [::status/single ::advanced-print-checks] + :class "is-primary" + :on-click (dispatch-event [::advanced-print-checks-submitted]) + :can-submit [::can-submit-advanced-print-checks] + :close-event [::status/completed ::advanced-print-checks]}}] + :db (-> db + (forms/stop-form ::form/form) + (forms/start-form ::advanced-print-checks + {:bank-account-id (:id (first @(re-frame/subscribe [::subs/real-bank-accounts]))) + :invoices invoices + :invoice-amounts (into {} + (map (fn [i] [(:id i) + {:amount (:outstanding-balance i)}]) + invoices))}))})) + + + + + +(defn print-checks-query [invoice-payments bank-account-id type client-id] + {:venia/operation {:operation/type :mutation + :operation/name "PrintChecks"} + + :venia/queries [[:print-checks + {:invoice_payments invoice-payments + :type type + :bank_account_id bank-account-id + :client_id client-id} + [[:invoices invoice-read] + :pdf_url]]]}) + + +(re-frame/reg-event-fx + ::advanced-print-checks-submitted + [with-user (forms/in-form ::advanced-print-checks) ] + (fn [{:keys [db user]} [_ bank-account-id]] + (let [type (->> @(re-frame/subscribe [::subs/client]) + :bank-accounts + (filter #(= bank-account-id (:id %))) + first + :type) + {:keys [date invoices invoice-amounts check-number bank-account-id client]} (:data db)] + {:graphql + {:token user + :owns-state {:single ::advanced-print-checks} + :query-obj (print-checks-query (map (fn [x] + {:invoice-id (:id x) + :amount (get-in invoice-amounts [(:id x) :amount])}) + invoices) + bank-account-id + (cond (= type :check) + :check + (= type :cash) + :cash + + :else + :check) + (->> invoices first :client :id)) + + :on-success (fn [result] + [::checks-printed + (:invoices (:print-checks result)) + (:pdf-url (:print-checks result))])}}))) + +(re-frame/reg-event-fx + ::checks-printed + (fn [{:keys [db]} [_ data]] + {:dispatch [::modal/modal-closed]})) + diff --git a/src/cljs/auto_ap/views/pages/invoices/common.cljs b/src/cljs/auto_ap/views/pages/invoices/common.cljs index d670a2c6..39f4597f 100644 --- a/src/cljs/auto_ap/views/pages/invoices/common.cljs +++ b/src/cljs/auto_ap/views/pages/invoices/common.cljs @@ -1,5 +1,17 @@ (ns auto-ap.views.pages.invoices.common) +(defn does-amount-exceed-outstanding? [amount outstanding-balance ] + (let [amount (js/parseFloat amount) + outstanding-balance (js/parseFloat outstanding-balance)] + (or (and (> outstanding-balance 0) + (> amount outstanding-balance)) + (and (> outstanding-balance 0) + (<= amount 0)) + (and (< outstanding-balance 0) + (< amount outstanding-balance)) + (and (< outstanding-balance 0) + (>= amount 0))))) + (def invoice-read [:id :total :outstanding-balance :date :due :invoice-number :status :automatically-paid-when-due [:client [:id :name :locations]] diff --git a/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs b/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs index 58113b0e..533f0b71 100644 --- a/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs +++ b/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs @@ -2,44 +2,40 @@ (:require [auto-ap.entities.invoice :as invoice] [auto-ap.events :as events] [auto-ap.forms :as forms] + [auto-ap.status :as status] [auto-ap.subs :as subs] - [auto-ap.utils :refer [by replace-if replace-by]] - [auto-ap.views.pages.invoices.form :as form] + [auto-ap.utils :refer [by merge-by replace-if]] [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 table :refer [invoice-table]] - [auto-ap.views.components.invoices.side-bar :refer [invoices-side-bar] :as side-bar] - [auto-ap.views.components.layouts :refer [appearing-side-bar side-bar-layout]] - [auto-ap.views.components.modal :refer [action-modal modal]] - [auto-ap.views.components.typeahead :refer [typeahead]] - [auto-ap.views.components.vendor-filter :refer [vendor-filter]] - [auto-ap.views.pages.invoices.common :refer [invoice-read]] + [auto-ap.views.components.expense-accounts-dialog + :as + expense-accounts-dialog + :refer + [change-expense-accounts-modal]] + [auto-ap.views.components.invoice-table :as table] + [auto-ap.views.components.invoices.side-bar + :as + side-bar + :refer + [invoices-side-bar]] + [auto-ap.views.components.layouts + :refer + [appearing-side-bar side-bar-layout]] + [auto-ap.views.components.modal :as modal :refer [modal]] [auto-ap.views.pages.data-page :as data-page] - [auto-ap.views.utils :refer [bind-field date->str date-picker dispatch-event horizontal-field standard with-user]] - [cljs-time.core :as c] - [clojure.spec.alpha :as s] - [clojure.string :as str :refer [blank?]] + [auto-ap.views.pages.invoices.advanced-print-checks + :as + advanced-print-checks] + [auto-ap.views.pages.invoices.common :refer [invoice-read does-amount-exceed-outstanding?]] + [auto-ap.views.pages.invoices.form :as form] + [auto-ap.views.utils + :refer + [date-picker dispatch-event horizontal-field with-user]] + [clojure.set :as set] + [clojure.string :as str] [goog.string :as gstring] - [vimsical.re-frame.cofx.inject :as inject] [re-frame.core :as re-frame] [reagent.core :as r] - [auto-ap.status :as status] - [vimsical.re-frame.fx.track :as track] - [auto-ap.utils :refer [merge-by]] - [clojure.set :as set] - [auto-ap.views.components.modal :as modal])) - -(defn does-amount-exceed-outstanding? [amount outstanding-balance] - (let [amount (js/parseFloat amount) - outstanding-balance (js/parseFloat outstanding-balance)] - (or (and (> outstanding-balance 0) - (> amount outstanding-balance)) - (and (> outstanding-balance 0) - (<= amount 0)) - (and (< outstanding-balance 0) - (< amount outstanding-balance)) - (and (< outstanding-balance 0) - (>= amount 0))))) + [vimsical.re-frame.fx.track :as track])) (re-frame/reg-sub ::invoice-page @@ -52,11 +48,6 @@ (assoc i :checkable? (not (:automatically-paid-when-due i)))) is)))))) -(re-frame/reg-sub - ::advanced-print-checks - (fn [db] - (-> db ::advanced-print-checks))) - (re-frame/reg-sub ::change-expense-accounts @@ -81,7 +72,6 @@ - (re-frame/reg-event-fx ::params-change [with-user] @@ -105,7 +95,8 @@ (fn [{:keys [db]} _] {:db (dissoc db ::invoice-page ::table/table-params ::side-bar/filters ::side-bar/settled-filters ::last-params) :dispatch [::data-page/dispose :invoices] - :forward-events [{:unregister ::updated}] + :forward-events [{:unregister ::updated} + {:unregister ::advanced-print-checks-printed}] ::track/dispose [{:id ::params}]})) (re-frame/reg-event-fx @@ -120,7 +111,7 @@ :dispatch-to [::data-page/entity-updated :invoices]} {:register ::checks-printed - :events #{::form/checks-printed} + :events #{::form/checks-printed ::advanced-print-checks/checks-printed} :dispatch-to [::checks-printed]}]})) @@ -133,48 +124,6 @@ -(re-frame/reg-event-db - ::advanced-print-checks - (fn [db _] - (let [invoices @(re-frame/subscribe [::checked-invoices])] - (-> db - (forms/stop-form ::form/form) - (update-in [::invoice-page :print-checks-shown?] #(not %) ) - (assoc-in [::advanced-print-checks] {:shown? true - :bank-account-id (:id (first @(re-frame/subscribe [::subs/bank-accounts]))) - :invoices (map #(assoc % :amount (:outstanding-balance %)) invoices )} ))))) - - - -(re-frame/reg-event-db - ::cancel-advanced-print - (fn [db _] - (assoc-in db [::advanced-print-checks :shown?] false ))) - -(re-frame/reg-event-db - ::close-check-results - (fn [db _] - (assoc-in db [::check-results :shown?] false ))) - -(re-frame/reg-event-db - ::edit-payment-bank-account - (fn [db [_ f v]] - (assoc-in db [::advanced-print-checks :bank-account-id] v))) - -(re-frame/reg-event-db - ::edit-payment - (fn [db [_ which f v]] - (update-in db [::advanced-print-checks :invoices] - (fn [is] - (for [i is] - (if (= which (:id i)) - (assoc-in i f v) - i)))))) - - - - - (defn print-checks-query [invoice-payments bank-account-id type client-id] {:venia/operation {:operation/type :mutation :operation/name "PrintChecks"} @@ -206,61 +155,23 @@ :on-success [::checks-created]}})) - (re-frame/reg-event-fx - ::advanced-print-checks-submitted - (fn [{:keys [db]} [_ bank-account-id]] - (let [invoice-amounts (by :id (comp js/parseFloat :amount) (get-in db [::advanced-print-checks :invoices])) - bank-account-id (get-in db [::advanced-print-checks :bank-account-id]) - type (->> @(re-frame/subscribe [::subs/client]) - :bank-accounts - (filter #(= bank-account-id (:id %))) - first - :type)] - {:db (-> db - (assoc-in [::advanced-print-checks :printing?] true )) - :graphql - {:token (-> db :user) - - :query-obj (print-checks-query (map (fn [x] - {:invoice-id (:id x) - :amount (invoice-amounts (:id x))}) - (get-in db [::advanced-print-checks :invoices])) - bank-account-id - (cond (= type :check) - :check - (= type :cash) - :cash + ::checks-printed + (fn [{:keys [db]} [_ [_ invoices pdf-url]]] + (let [invoices-by-id (by :id invoices) ] + {:db (-> db + (assoc-in [::check-results :shown?] true) + (assoc-in [::check-results :pdf-url] pdf-url)) + :dispatch-n (mapv + (fn [i] + [::data-page/entity-updated :invoices [nil (assoc i :class "live-added")]]) + invoices)}))) - :else - :check) - (:client db)) - - :on-success [::checks-created]}}))) - -(re-frame/reg-event-fx - ::checks-created - (fn [{:keys [db]} [_ data]] - (let [{{:keys [pdf-url invoices]} :print-checks} data - invoices-by-id (by :id invoices) ] - { - :db (-> db - (update-in [::invoice-page :invoices] - (fn [invoices] - (map (fn [i] - (merge i (invoices-by-id (:id i)))) - invoices))) - (assoc-in [::invoice-page :checked] nil) - (assoc-in [::advanced-print-checks :printing?] false) - (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)))) + ::close-check-results + (fn [db _] + (assoc-in db [::check-results :shown?] false ))) (re-frame/reg-event-fx ::new-invoice-clicked @@ -295,64 +206,7 @@ (replace-if #(= (:id %1) (:id %2)) updated is))) (dissoc ::change-expense-accounts))}))) -(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]) - current-client @(re-frame/subscribe [::subs/client])] - (when shown? - [modal {:title "Print Checks" - :foot [:button.button.is-primary {:on-click (dispatch-event [::advanced-print-checks-submitted]) - :disabled (cond printing? - "disabled" - - (seq (filter - (fn [{:keys [outstanding-balance amount]}] - (does-amount-exceed-outstanding? amount outstanding-balance )) - invoices)) - "disabled" - - :else - "") - :class (if printing? "is-loading" "")} - [:span "Print"]] - :hide-event [::cancel-advanced-print]} - "Print using" - [:span.field - [:span.select - [bind-field - - [:select {:type "select" - :field :bank-account-id - :event ::edit-payment-bank-account - :subscription advanced-print-checks} - (for [{:keys [id number name]} (sort-by :sort-order (:bank-accounts current-client))] - ^{:key id} [:option {:value id} name])]]]] - - [:table.table.is-fullwidth - [:thead - [:tr - [:th "Vendor"] - [:th "Invoice ID"] - [:th {:style {"width" "10em"}} "Payment"]]] - [:tbody - (for [{:keys [vendor payment outstanding-balance invoice-number id] :as i} invoices] - ^{:key id} - [:tr - [:td (:name vendor)] - [:td invoice-number] - - [:td [:div.field.has-addons.is-extended - [:p.control [:a.button.is-static "$"]] - [:p.control - [bind-field - [:input.input {:type "number" - :field :amount - :event [::edit-payment id] - :subscription i - :value payment - :max outstanding-balance - :step "0.01"}]]]]]])]]]))) ;; HANDWRITE CHECKS @@ -363,8 +217,6 @@ (defn handwrite-checks-modal [] (let [{:keys [checked]} @(re-frame/subscribe [::invoice-page]) - change-event [::events/change-form [::handwrite-checks]] - current-client @(re-frame/subscribe [::subs/client]) real-bank-accounts @(re-frame/subscribe [::subs/real-bank-accounts]) {:keys [data active? error id]} @(re-frame/subscribe [::forms/form ::handwrite-checks]) {:keys [form-inline horizontal-field field raw-field error-notification submit-button]} handwrite-checks-form] @@ -479,8 +331,7 @@ :amount (get-in invoice-amounts [(:id x) :amount])}) invoices) :check-number check-number - :bank-account-id bank-account-id - } + :bank-account-id bank-account-id} [[:invoices invoice-read]]]}]} :on-success [::handwrite-checks-succeeded]}}))) @@ -495,10 +346,6 @@ [::data-page/entity-updated :invoices [_ (assoc i :class "live-added")]]) (:invoices add-handwritten-check)))}))) - - - - (defn pay-button [] (let [current-client @(re-frame/subscribe [::subs/client]) checked-invoices @(re-frame/subscribe [::checked-invoices])] @@ -540,13 +387,12 @@ (when (= 1 (count (set (map (comp :id :vendor) checked-invoices)))) ^{:key "handwritten"} [:a.dropdown-item {:on-click (dispatch-event [::handwrite-checks])} "Handwritten Check..."]) - ^{:key "advanced"} [:a.dropdown-item {:on-click (dispatch-event [::advanced-print-checks])} "Advanced..."])]])]] + ^{:key "advanced"} [:a.dropdown-item {:on-click (dispatch-event [::advanced-print-checks/show checked-invoices])} "Advanced..."])]])]] [:div.is-pulled-right {:style {:margin-right "0.5rem"}} (into [:div.tags ] (map (fn [{:keys [id invoice-number]}] [:span.tag.is-medium invoice-number [:button.delete.is-small {:on-click - (dispatch-event [::data-page/remove-check :invoices id])}]]) checked-invoices))]] - )) + (dispatch-event [::data-page/remove-check :invoices id])}]]) checked-invoices))]])) (defn check-results-dialog [] (let [{check-results-shown? :shown? pdf-url :pdf-url} @(re-frame/subscribe [::check-results])] @@ -595,7 +441,5 @@ :main [unpaid-invoices-content params] :bottom [:div [check-results-dialog] - [print-checks-modal] [change-expense-accounts-modal {:updated-event [::expense-accounts-updated]}]] - :right-side-bar [appearing-side-bar {:visible? invoice-bar-active?} [form/form {:invoice-created [::invoice-edited] - :invoice-printed [::checks-printed]}]]}]))})) + :right-side-bar [appearing-side-bar {:visible? invoice-bar-active?} [form/form {:invoice-printed [::checks-printed]}]]}]))}))