From a23975f9cf24c44ecdc447e22f434070df7550a0 Mon Sep 17 00:00:00 2001 From: BC Date: Thu, 28 Jun 2018 23:24:01 -0700 Subject: [PATCH] Now you can add manual checks. --- .../1530242355-DOWN-add-check-number.sql | 3 + .../1530242355-UP-add-check-number.sql | 2 + src/clj/auto_ap/db/checks.clj | 3 +- src/clj/auto_ap/graphql.clj | 9 ++ src/clj/auto_ap/graphql/checks.clj | 22 ++++ src/clj/auto_ap/routes/checks.clj | 1 + src/clj/auto_ap/yodlee/import.clj | 12 +- .../views/components/invoice_table.cljs | 8 +- src/cljs/auto_ap/views/pages/checks.cljs | 6 +- .../auto_ap/views/pages/unpaid_invoices.cljs | 116 +++++++++++++++++- 10 files changed, 171 insertions(+), 11 deletions(-) diff --git a/migrator/migrations/1530242355-DOWN-add-check-number.sql b/migrator/migrations/1530242355-DOWN-add-check-number.sql index 65d571f8..250cd905 100644 --- a/migrator/migrations/1530242355-DOWN-add-check-number.sql +++ b/migrator/migrations/1530242355-DOWN-add-check-number.sql @@ -1,3 +1,6 @@ -- 1530242355 DOWN add-check-number alter table transactions drop column check_number; alter table transactions drop column bank_account_id; + + +alter table checks drop column bank_account_id; diff --git a/migrator/migrations/1530242355-UP-add-check-number.sql b/migrator/migrations/1530242355-UP-add-check-number.sql index 8fc0912e..ae2443d3 100644 --- a/migrator/migrations/1530242355-UP-add-check-number.sql +++ b/migrator/migrations/1530242355-UP-add-check-number.sql @@ -1,3 +1,5 @@ -- 1530242355 UP add-check-number alter table transactions add column check_number INT; alter table transactions add column bank_account_id int; + +alter table checks add column bank_account_id int; diff --git a/src/clj/auto_ap/db/checks.clj b/src/clj/auto_ap/db/checks.clj index 16335823..e9e4e6de 100644 --- a/src/clj/auto_ap/db/checks.clj +++ b/src/clj/auto_ap/db/checks.clj @@ -68,9 +68,10 @@ :else q))) -(defn base-graphql [{:keys [company-id vendor-id check-number]}] +(defn base-graphql [{:keys [company-id vendor-id check-number bank-account-id]}] (cond-> base-query (not (nil? company-id)) (helpers/merge-where [:= :company-id company-id]) + (not (nil? bank-account-id)) (helpers/merge-where [:= :bank-account-id bank-account-id]) (not (nil? vendor-id)) (helpers/merge-where [:= :vendor-id vendor-id]) (not (nil? check-number)) (helpers/merge-where [:= :check-number check-number]))) diff --git a/src/clj/auto_ap/graphql.clj b/src/clj/auto_ap/graphql.clj index 6a8574eb..9115a525 100644 --- a/src/clj/auto_ap/graphql.clj +++ b/src/clj/auto_ap/graphql.clj @@ -232,6 +232,14 @@ :bank_account_id {:type 'Int} :company_id {:type 'Int}} :resolve :mutation/print-checks} + + :add_handwritten_check {:type :check_result + :args {:invoice_id {:type 'Int} + :amount {:type 'Float} + :date {:type 'String} + :check_number {:type 'Int} + :bank_account_id {:type 'Int}} + :resolve :mutation/add-handwritten-check} :edit_user {:type :user :args {:edit_user {:type :edit_user}} :resolve :mutation/edit-user} @@ -398,6 +406,7 @@ :get-company get-company :get-user get-user :get-user-companies get-user-companies + :mutation/add-handwritten-check gq-checks/add-handwritten-check :mutation/print-checks print-checks :mutation/edit-user gq-users/edit-user :mutation/add-invoice gq-invoices/add-invoice diff --git a/src/clj/auto_ap/graphql/checks.clj b/src/clj/auto_ap/graphql/checks.clj index 77278caa..0c909c5f 100644 --- a/src/clj/auto_ap/graphql/checks.clj +++ b/src/clj/auto_ap/graphql/checks.clj @@ -4,8 +4,10 @@ [com.walmartlabs.lacinia :refer [execute]] [com.walmartlabs.lacinia.executor :as executor] [com.walmartlabs.lacinia.resolve :as resolve] + [auto-ap.db.invoices-checks :as invoices-checks] [auto-ap.db.checks :as checks] [auto-ap.db.vendors :as vendors] + [auto-ap.db.invoices :as invoices] [auto-ap.utils :refer [by]] [auto-ap.db.companies :as companies] [auto-ap.time :refer [parse normal-date]])) @@ -39,6 +41,26 @@ :start (:start args 0) :end (+ (:start args 0) (count checks))}] extra-context))) +(defn add-handwritten-check [context args value] + (let [invoice (invoices/get-by-id (:invoice_id args)) + check (checks/insert! {:s3-uuid nil + :s3-key nil + :s3-url nil + :check-number (:check_number args) + :amount (:amount args) + :bank-account-id (:bank_account_id args) + :vendor-id (:vendor-id invoice) + :company-id (:company-id invoice) + :invoices [(:invoice_id args)]})] + + (invoices-checks/insert-multi! [{:invoice-id (:invoice_id args) + :check-id (:id check) + :amount (:amount args)}]) + (invoices/apply-payment (:invoice_id args) (:amount args)) + (->graphql + {:s3-url nil + :invoices [(invoices/get-by-id (:invoice_id args))]}))) + diff --git a/src/clj/auto_ap/routes/checks.clj b/src/clj/auto_ap/routes/checks.clj index f82ae5ab..8e61ee95 100644 --- a/src/clj/auto_ap/routes/checks.clj +++ b/src/clj/auto_ap/routes/checks.clj @@ -176,6 +176,7 @@ :s3-key (str "checks/" uuid ".pdf") :s3-url (str "http://" (:data-bucket env) ".s3-website-us-east-1.amazonaws.com/checks/" uuid ".pdf") :check-number (+ index (:check-number bank-account)) + :bank-account-id bank-account-id :amount (reduce + 0 (map (comp invoice-amounts :id) invoices)) :memo memo :vendor-id (:id vendor) diff --git a/src/clj/auto_ap/yodlee/import.clj b/src/clj/auto_ap/yodlee/import.clj index 9d16e941..c04b200d 100644 --- a/src/clj/auto_ap/yodlee/import.clj +++ b/src/clj/auto_ap/yodlee/import.clj @@ -13,9 +13,10 @@ first :id)) -(defn transaction->check-id [_ check-number company-id vendor-id] +(defn transaction->check-id [_ check-number company-id bank-account-id vendor-id] (when check-number (-> (checks/get-graphql {:company-id company-id + :bank-account-id bank-account-id :check-number check-number}) first :id))) @@ -54,11 +55,12 @@ status :status} transaction transaction (if (= 0 (rand-int 3)) - (assoc-in transaction [:description :original] (str "check xxx" (rand-nth ["6789" "1234" "6790"]))) + (assoc-in transaction [:description :original] (str "check xxx1236")) transaction) check-number (extract-check-number transaction) company-id (account->company account-id) - vendor-id (transaction->vendor-id transaction)]] + vendor-id (transaction->vendor-id transaction) + bank-account-id (yodlee-account-id->bank-account-id account-id)]] (try (transactions/upsert! @@ -74,8 +76,8 @@ :company-id company-id :vendor-id vendor-id :check-number check-number - :bank-account-id (yodlee-account-id->bank-account-id account-id) - :check-id (transaction->check-id transaction check-number company-id vendor-id) + :bank-account-id bank-account-id + :check-id (transaction->check-id transaction check-number company-id bank-account-id vendor-id) }) (catch Exception e (println e)))))) diff --git a/src/cljs/auto_ap/views/components/invoice_table.cljs b/src/cljs/auto_ap/views/components/invoice_table.cljs index 6ec12934..41c12893 100644 --- a/src/cljs/auto_ap/views/components/invoice_table.cljs +++ b/src/cljs/auto_ap/views/components/invoice_table.cljs @@ -130,5 +130,9 @@ ^{:key (:id e)} [:a.tag {:on-click (dispatch-event (conj expense-event id))} (:name (:expense-account e)) " "(gstring/format "$%.2f" (:amount e) ) ])] [:td (for [check checks] - ^{:key (:id check)} - [:a.tag {:href (:s3-url (:check check)) :target "_new"} [:i.fa.fa-money-check] [:span.icon [:i.fa.fa-money]] (str " " (:check-number (:check check)) " (" (gstring/format "$%.2f" (:amount check) ) ")")])]]))]]])))) + (if (:s3-url (:check check)) + ^{:key (:id check)} + [:a.tag {:href (:s3-url (:check check)) :target "_new"} [:i.fa.fa-money-check] [:span.icon [:i.fa.fa-money]] (str " " (:check-number (:check check)) " (" (gstring/format "$%.2f" (:amount check) ) ")")] + + ^{:key (:id check)} + [:span.tag [:i.fa.fa-money-check] [:span.icon [:i.fa.fa-money]] (str " " (:check-number (:check check)) " (" (gstring/format "$%.2f" (:amount check) ) ")")]))]]))]]])))) diff --git a/src/cljs/auto_ap/views/pages/checks.cljs b/src/cljs/auto_ap/views/pages/checks.cljs index 8f47f025..7da4d4b7 100644 --- a/src/cljs/auto_ap/views/pages/checks.cljs +++ b/src/cljs/auto_ap/views/pages/checks.cljs @@ -121,7 +121,11 @@ [:td check-number] [:td (date->str date) ] [:td (gstring/format "$%.2f" amount )] - [:td [:a.tag {:href s3-url :target "_new"} [:i.fa.fa-money-check] [:span.icon [:i.fa.fa-money]] (str " " check-number " (" (gstring/format "$%.2f" amount ) ")")]] + [:td + (if s3-url + [:a.tag {:href s3-url :target "_new"} [:i.fa.fa-money-check] [:span.icon [:i.fa.fa-money]] (str " " check-number " (" (gstring/format "$%.2f" amount ) ")")] + [:span.tag [:i.fa.fa-money-check] [:span.icon [:i.fa.fa-money]] (str " " check-number " (" (gstring/format "$%.2f" amount ) ")")]) + ] ]))]]])))) diff --git a/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs b/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs index fe04eaef..8d6e52d5 100644 --- a/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs +++ b/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs @@ -32,6 +32,11 @@ (fn [db] (-> db ::advanced-print-checks))) +(re-frame/reg-sub + ::handwrite-checks + (fn [db] + (-> db ::handwrite-checks))) + (re-frame/reg-sub ::change-expense-accounts (fn [db] @@ -96,6 +101,22 @@ (filter (comp checked :id)) (map #(assoc % :amount (:outstanding-balance %))))} ))))) +(re-frame/reg-event-fx + ::handwrite-checks + (fn [{:keys [db]} _] + (let [{:keys [checked invoices]} (get-in db [::invoice-page]) + invoice (->> invoices + (filter (comp checked :id)) + first) + ] + + {:dispatch [::events/modal-status ::handwrite-checks {:visible? true}] + :db (-> db + (update-in [::invoice-page :print-checks-shown?] #(not %) ) + (assoc-in [::handwrite-checks] {:bank-account-id (:id (first (:bank-accounts @(re-frame/subscribe [::subs/company])))) + :amount (:outstanding-balance invoice) + :invoice invoice } ))}))) + (re-frame/reg-event-db ::cancel-advanced-print (fn [db _] @@ -221,6 +242,39 @@ ]]}]} :on-success [::invoice-created]}}))) +(re-frame/reg-event-fx + ::handwrite-checks-save + (fn [{:keys [db]} _] + (let [{:keys [date invoice amount check-number bank-account-id]} @(re-frame/subscribe [::handwrite-checks])] + {:graphql + {:token (-> db :user) + :query-obj {:venia/operation {:operation/type :mutation + :operation/name "AddHandwrittenCheck"} + + :venia/queries [{:query/data [:add-handwritten-check + {:date date + :amount amount + :check-number check-number + :bank-account-id bank-account-id + :invoice_id (:id invoice) + } + [[:invoices [:id :outstanding-balance [:checks [:amount [:check [:amount :s3_url :check_number ]]]]]]]]}]} + :on-success [::handwrite-checks-succeeded]}}))) + +(re-frame/reg-event-fx + ::handwrite-checks-succeeded + (fn [{:keys [db]} [_ {:keys [add-handwritten-check] :as result}]] + (let [invoices-by-id (by :id (:invoices add-handwritten-check))] + {:dispatch [::events/modal-completed ::handwrite-checks] + :db (-> db + (update-in [::invoice-page :invoices] + (fn [invoices] + (println invoices-by-id) + (map (fn [i] + (merge i (invoices-by-id (:id i)))) + invoices))) + (dissoc ::handwrite-checks))}))) + (re-frame/reg-event-fx ::invoice-created (fn [{:keys [db]} [_ {:keys [add-invoice]}]] @@ -411,6 +465,59 @@ :max outstanding-balance :step "0.01"}]]]]]])]]]))) +(defn handwrite-checks-modal [] + (let [{:keys [checked]} @(re-frame/subscribe [::invoice-page]) + {:keys [invoice] :as handwrite-checks} @(re-frame/subscribe [::handwrite-checks]) + change-event [::events/change-form [::handwrite-checks]] + current-company @(re-frame/subscribe [::subs/company])] + + [action-modal {:id ::handwrite-checks + :title "Handwrite Check" + :action-text "Save" + :save-event [::handwrite-checks-save] + #_#_:can-submit? (s/valid? ::invoice/invoice data)} + [horizontal-field + [:label.label "Pay using"] + [:span.select + [bind-field + [:select {:type "select" + :field :bank-account-id + :event change-event + :subscription handwrite-checks} + (for [{:keys [id number name]} (:bank-accounts current-company)] + ^{:key id} [:option {:value id} name])]]]] + + [horizontal-field + [:label.label "Paid amount"] + [:div.field.has-addons.is-extended + [:p.control [:a.button.is-static "$"]] + [:p.control + [bind-field + [:input.input {:type "number" + :field [:amount] + :event change-event + :subscription handwrite-checks + :spec ::invoice/total + :step "0.01"}]]]]] + + [horizontal-field + [:label.label "Date"] + [bind-field + [:input.input {:type "date" + :field [:date] + :event change-event + :spec ::invoice/date + :subscription handwrite-checks}]]] + + [horizontal-field + [:label.label "Check number"] + [bind-field + [:input.input {:type "number" + :field [:check-number] + :event change-event + #_#_:spec ::check/date + :subscription handwrite-checks}]]]])) + (defn new-invoice-modal [] (let [data @(re-frame/subscribe [::new-invoice]) @@ -502,14 +609,18 @@ :class (if print-checks-loading? "is-loading" "")} - "Print checks " + "Pay " + [:span " "] [:span.icon.is-small [:i.fa.fa-angle-down {:aria-hidden "true"}]]]] [:div.dropdown-menu {:role "menu"} [:div.dropdown-content (list (for [{:keys [id number name]} (:bank-accounts current-company)] - ^{:key id} [:a.dropdown-item {:on-click (dispatch-event [::print-checks id])} name]) + ^{:key id} [:a.dropdown-item {:on-click (dispatch-event [::print-checks id])} "Print checks from " name]) ^{:key "advanced-divider"} [:hr.dropdown-divider] + + (when (= 1 (count checked)) + ^{: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..."])]]])] [invoice-table {:id :unpaid :params (re-frame/subscribe [::params]) @@ -525,6 +636,7 @@ [print-checks-modal] [new-invoice-modal] + [handwrite-checks-modal] [change-expense-accounts-modal] (when check-results-shown? [modal