diff --git a/resources/public/index.html b/resources/public/index.html index 37eb6a23..e528250a 100644 --- a/resources/public/index.html +++ b/resources/public/index.html @@ -245,8 +245,20 @@ } .card.active { background-color:#F5F5F5; +} + @media print { + footer { + page-break-after: always; + } + } +@font-face { + font-family: 'MICR'; + src: url("/micrenc.ttf") format("truetype"); + font-weight: normal; + font-style: normal; } +
@@ -279,47 +291,6 @@
- - - diff --git a/resources/public/micrenc.ttf b/resources/public/micrenc.ttf new file mode 100755 index 00000000..b5028902 Binary files /dev/null and b/resources/public/micrenc.ttf differ diff --git a/src/clj/auto_ap/db/invoices.clj b/src/clj/auto_ap/db/invoices.clj index 8557ffdd..20515223 100644 --- a/src/clj/auto_ap/db/invoices.clj +++ b/src/clj/auto_ap/db/invoices.clj @@ -51,6 +51,10 @@ (defn get-all [] (query base-query)) +(defn get-multi [ids] + (query (-> base-query + (helpers/merge-where [:in :id ids])))) + (defn approve [] (j/update! (get-conn) :invoices {:imported true} [] )) diff --git a/src/clj/auto_ap/handler.clj b/src/clj/auto_ap/handler.clj index 2654f37e..0895ce55 100644 --- a/src/clj/auto_ap/handler.clj +++ b/src/clj/auto_ap/handler.clj @@ -6,6 +6,7 @@ [auto-ap.routes.reminders :as reminders] [auto-ap.routes.graphql :as graphql] [auto-ap.routes.vendors :as vendors] + [auto-ap.routes.checks :as checks] [buddy.auth.backends.token :refer [jws-backend]] [buddy.auth.middleware :refer [wrap-authentication wrap-authorization]] @@ -31,6 +32,7 @@ companies/routes vendors/routes reminders/routes + checks/routes graphql/routes auth/routes)) diff --git a/src/clj/auto_ap/routes/checks.clj b/src/clj/auto_ap/routes/checks.clj new file mode 100644 index 00000000..6ae1be12 --- /dev/null +++ b/src/clj/auto_ap/routes/checks.clj @@ -0,0 +1,21 @@ +(ns auto-ap.routes.checks + (:require [auto-ap.db.companies :as companies] + [auto-ap.db.vendors :as vendors] + [auto-ap.db.invoices :as invoices] + [auto-ap.db.utils :refer [query]] + [auto-ap.parse :as parse] + [auto-ap.routes.utils :refer [wrap-secure]] + [compojure.core :refer [GET POST context defroutes + wrap-routes]] + [clojure.string :as str])) + +(defroutes routes + (wrap-routes + (context "/checks" [] + (POST "/" {:keys [edn-params]} + (invoices/get-multi (:invoice-ids edn-params)) + + {:status 200 + :body (pr-str (invoices/get-multi (:invoice-ids edn-params))) + :headers {"Content-Type" "application/edn"}})) + wrap-secure)) diff --git a/src/cljs/auto_ap/routes.cljs b/src/cljs/auto_ap/routes.cljs index d94c8135..7dca3a47 100644 --- a/src/cljs/auto_ap/routes.cljs +++ b/src/cljs/auto_ap/routes.cljs @@ -3,6 +3,7 @@ (def routes ["/" {"" :index "login/" :login + "check/" :check "admin/" {"" :admin "companies" :admin-companies "reminders" :admin-reminders diff --git a/src/cljs/auto_ap/views/components/invoice_table.cljs b/src/cljs/auto_ap/views/components/invoice_table.cljs index 82208b31..06eacd57 100644 --- a/src/cljs/auto_ap/views/components/invoice_table.cljs +++ b/src/cljs/auto_ap/views/components/invoice_table.cljs @@ -24,12 +24,12 @@ -(defn invoice-table [{:keys [id invoice-page status on-params-change vendors params check-boxes on-check-changed]}] +(defn invoice-table [{:keys [id invoice-page status on-params-change vendors params check-boxes checked on-check-changed]}] (let [state (reagent/atom (or @params {})) opc (fn [p] (swap! state merge p) (on-params-change p))] - (fn [{:keys [id invoice-page status on-params-change vendors]}] + (fn [{:keys [id invoice-page status on-params-change vendors checked]}] (let [{:keys [sort-by asc]} @state {:keys [invoices start end count total]} @invoice-page] [:div @@ -82,8 +82,12 @@ ^{:key id} [:tr (when check-boxes - [:td [:input.checkbox {:type "checkbox" :on-change (fn [x e] (when on-check-changed - (on-check-changed id)))} ]]) + [:td [:input.checkbox {:type "checkbox" + :checked (if (get checked id) + "checked" + "") + :on-change (fn [x e] (when on-check-changed + (on-check-changed id)))} ]]) [:td (:name vendor)] [:td (:name company)] [:td invoice-number] diff --git a/src/cljs/auto_ap/views/main.cljs b/src/cljs/auto_ap/views/main.cljs index 065ef025..ab6f4513 100644 --- a/src/cljs/auto_ap/views/main.cljs +++ b/src/cljs/auto_ap/views/main.cljs @@ -11,6 +11,7 @@ (defn page->layout [page] ({:login :blank + :check :blank :index :left-panel :invoices :left-panel :import-invoices :left-panel diff --git a/src/cljs/auto_ap/views/pages.cljs b/src/cljs/auto_ap/views/pages.cljs index 73c26761..f0ca284d 100644 --- a/src/cljs/auto_ap/views/pages.cljs +++ b/src/cljs/auto_ap/views/pages.cljs @@ -7,6 +7,7 @@ [auto-ap.views.pages.login :refer [login-page]] [auto-ap.views.pages.index :refer [index-page]] [auto-ap.views.pages.admin :refer [admin-page]] + [auto-ap.views.pages.check :refer [check-page]] [auto-ap.views.pages.admin.companies :refer [admin-companies-page]] [auto-ap.views.pages.admin.vendors :refer [admin-vendors-page]] [auto-ap.views.pages.admin.reminders :refer [admin-reminders-page]] @@ -34,6 +35,9 @@ (defmethod active-page :admin [] [admin-page]) +(defmethod active-page :check [] + [check-page]) + (defmethod active-page :admin-companies [] [admin-companies-page]) diff --git a/src/cljs/auto_ap/views/pages/check.cljs b/src/cljs/auto_ap/views/pages/check.cljs new file mode 100644 index 00000000..d3c70d09 --- /dev/null +++ b/src/cljs/auto_ap/views/pages/check.cljs @@ -0,0 +1,187 @@ +(ns auto-ap.views.pages.check + (:require-macros [cljs.core.async.macros :refer [go]]) + (:require [re-frame.core :as re-frame] + [reagent.core :as reagent] + [auto-ap.subs :as subs] + [auto-ap.events :as events] + [auto-ap.views.utils :refer [login-url]] + [cljs.reader :as edn] + [auto-ap.routes :as routes] + [bidi.bidi :as bidi] + [goog.string :as gstring])) + +(defn check-page [] + [:div + (for [{:keys [vendor-name paid-to company check date amount memo]} + [{:vendor-name "Covert Affairs, INC" + :paid-to "Covert Affairs, INC" + :amount 1234.56 + :check "1234" + :memo "Invoice #'s: 870034 ($400.34), 77335 ($732.55), 76668 ($101.67)" + :date "5/10/2018" + :company {:name "Campbell Brewing Company LLC" + :address1 "200 E Campbell Ave" + :city "Campbell" + :state "CA" + :zip "95008" + :bank {:name "Bank of America, NA" + :acct "11-35/2010" + :acct-number "123456789"}}} + + {:vendor-name "Good meat, INC" + :paid-to "Good meat, INC" + :amount 973.45 + :check "1235" + :memo "Invoice #'s: 070034 ($400.34), 77335 ($732.55), 76668 ($101.67)" + :date "5/10/2018" + :company {:name "Campbell Brewing Company LLC" + :address1 "200 E Campbell Ave" + :city "Campbell" + :state "CA" + :zip "95008" + :bank {:name "Bank of America, NA" + :acct "11-35/2010" + :acct-number "123456789"}}}] + + :let [amount (gstring/format "--%.2f--" amount)]] + [:div + [:div.columns + (let [{:keys [name address1 city state zip bank]} company] + (list + [:div.column.is-4 + [:p name] + [:p address1] + [:p city ", " state zip]] + [:div.column.is-7 + + [:p.has-text-centered (:name bank)] + [:p.has-text-centered (:acct bank)] + ])) + + [:div.column + check] + ] + [:div.columns + [:div.column.is-11] + [:div.column date] + ] + [:div.columns + [:div.column + "PAY" + ] + [:div.column + "TO THE ORDER OF"] + [:div.column.is-9 + vendor-name] + [:div.column + + amount]] + + [:div.columns + [:div.column] + [:div.column.is-8 {:style {"border-bottom" "1px solid black"}} "One thousand two hundred thirty four and fifty six cents"] + [:div.column.is-3]] + + [:div.columns + [:div.column ""]] + [:div.columns + [:div.column " "]] + + + [:div.columns + [:div.column + "MEMO"] + [:div.column.is-7 {:style {"border-bottom" "1px solid black"}} + memo] + [:div.column.is-4]] + + [:div.columns + [:div.column.is-2 ] + [:div.column.is-10 {:style {"font-family" "MICR" "font-size" "20pt"}} + (str "c" check "c a" (:acct-number (:bank company)) "a 10302c")]] + + + [:div.columns + [:div.column " "]] + + [:div.columns + [:div.column " "]] + + [:div.columns + [:div.column " "]] + + [:div.columns + [:div.column " "]] + + [:div.columns + [:div.column] + [:div.column.is-10 + (let [{:keys [name address1 city state zip bank]} company] + (list + [:p name] + [:p address1] + [:p city ", " state zip] + )) + + + + ] + [:div.column + check]] + + [:div.columns + [:div.column " "]] + [:div.columns + [:div.column " "]] + [:div.columns + [:div.column " "]] + [:div.columns + [:div.column " "]] + [:div.columns + [:div.column " "]] + + [:div.columns + [:div.column] + [:div.column.is-5 + vendor-name] + [:div.column + [:p.has-text-right "Paid to:"] + [:p.has-text-right "Amount:"] + [:p.has-text-right "Date:"]] + + [:div.column.is-5 + [:p paid-to] + [:p amount] + [:p date]]] + + [:div.columns + [:div.column "MEMO"] + [:div.column.is-11 + memo + ]] + + [:div.columns + [:div.column " "]] + + [:div.columns + [:div.column.is-6] + [:div.column + [:p.has-text-right "Check:"] + [:p.has-text-right "Vendor:"] + [:p.has-text-right "Bank Account:"] + [:p.has-text-right "Paid To:"] + [:p.has-text-right "Amount:"] + [:p.has-text-right "Date:"]] + + [:div.column.is-5 + [:p check] + [:p vendor-name] + [:p (:name (:bank company))] + [:p paid-to] + [:p amount] + [:p date]]] + [:div.columns + [:div.column "MEMO"] + [:div.column.is-11 + memo]] + [:footer]])]) diff --git a/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs b/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs index 272a6c9e..ec165ec9 100644 --- a/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs +++ b/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs @@ -3,6 +3,7 @@ [auto-ap.entities.companies :as company] [auto-ap.entities.vendors :as vendor] [auto-ap.events :as events] + [auto-ap.views.utils :refer [dispatch-event]] [auto-ap.views.components.invoice-table :refer [invoice-table] :as invoice-table] [auto-ap.subs :as subs] [auto-ap.events :as events])) @@ -44,6 +45,18 @@ (disj x data) (conj x data))))))) +(re-frame/reg-event-fx + ::print-checks + (fn [{:keys [db]} [_ data]] + {:db (assoc-in db [::invoice-page :checked] nil) + :http {:method :post + :token (:user db) + :body (pr-str {:invoice-ids (get-in db [::invoice-page :checked])}) + :headers {"Content-Type" "application/edn"} + :uri (str "/api/checks/") + :on-success [::save-complete] + :on-error [::save-error]}})) + (re-frame/reg-event-fx ::invalidated (fn [cofx [_ params]] @@ -52,18 +65,20 @@ (def unpaid-invoices-page (with-meta (fn [] - [:div - [:h1.title "Unpaid invoices"] - [:div.is-pulled-right - [:button.button.is-primary "Print check(s)"]] - - [invoice-table {:id :unpaid - :params (re-frame/subscribe [::params]) - :invoice-page (re-frame/subscribe [::invoice-page]) - :status (re-frame/subscribe [::subs/status]) - :on-params-change (fn [params] - (re-frame/dispatch [::params-change params])) - :check-boxes true - :on-check-changed (fn [which] - (re-frame/dispatch [::toggle-check which]))}]]) + (let [checked (:checked @(re-frame/subscribe [::invoice-page]))] + [:div + [:h1.title "Unpaid invoices"] + [:div.is-pulled-right + [:button.button.is-primary {:on-click (dispatch-event [::print-checks ])} "Print check(s)"]] + + [invoice-table {:id :unpaid + :params (re-frame/subscribe [::params]) + :invoice-page (re-frame/subscribe [::invoice-page]) + :status (re-frame/subscribe [::subs/status]) + :on-params-change (fn [params] + (re-frame/dispatch [::params-change params])) + :check-boxes true + :checked checked + :on-check-changed (fn [which] + (re-frame/dispatch [::toggle-check which]))}]])) {:component-will-mount #(re-frame/dispatch-sync [::params-change {}]) }))