From 4dba769f9bd58c58d3c200d9609a183c25862574 Mon Sep 17 00:00:00 2001 From: Bryce Covert Date: Sat, 13 Jul 2019 09:37:48 -0700 Subject: [PATCH 1/3] fixidng checks. --- src/clj/auto_ap/graphql/checks.clj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/clj/auto_ap/graphql/checks.clj b/src/clj/auto_ap/graphql/checks.clj index 9c9ace0f..7d850848 100644 --- a/src/clj/auto_ap/graphql/checks.clj +++ b/src/clj/auto_ap/graphql/checks.clj @@ -64,9 +64,9 @@ [:table {:num-cols 12 :border false :leading 11 :widths (distribute [2 3 3 3 3 3 3 3 3 2 2 2])} [(let [{:keys [:client/name] {:keys [:address/street1 :address/street2 :address/city :address/state :address/zip]} :client/address} client] - [:cell {:colspan 3 } [:paragraph {:leading 14} name "\n" street1 "\n" (str city ", " state " " zip)] ]) + [:cell {:colspan 4 } [:paragraph {:leading 14} name "\n" street1 "\n" (str city ", " state " " zip)] ]) (let [{:keys [:bank-account/bank-name :bank-account/bank-code] } bank-account] - [:cell {:colspan 7 :align :center} [:paragraph {:style :bold} bank-name] [:paragraph {:size 8 :leading 8} bank-code]]) + [:cell {:colspan 6 :align :center} [:paragraph {:style :bold} bank-name] [:paragraph {:size 8 :leading 8} bank-code]]) [:cell {:colspan 2 :size 13} check]] From 1dedacd11648852845a89c18337f6d2be6fcc980 Mon Sep 17 00:00:00 2001 From: Bryce Covert Date: Wed, 9 Oct 2019 06:58:50 -0700 Subject: [PATCH 2/3] adding new expense accounts. --- src/cljc/auto_ap/expense_accounts.cljc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cljc/auto_ap/expense_accounts.cljc b/src/cljc/auto_ap/expense_accounts.cljc index 3ba40463..418a32cb 100644 --- a/src/cljc/auto_ap/expense_accounts.cljc +++ b/src/cljc/auto_ap/expense_accounts.cljc @@ -271,6 +271,7 @@ 7450 {:name "Building Cleaning & Maintenance" :parent 7400} 7455 {:name "Pest Control" :parent 7400} 7460 {:name "Repairs to Equipment" :parent 7400} + 7461 {:name "Contract Labor" :parent 7400} 7500 {:name "Office / Management Related" :parent nil} 7510 {:name "Office Supplies" :parent 7500} 7520 {:name "Printing - Internal" :parent 7500} @@ -298,6 +299,7 @@ 8430 {:name "Other Rental" :parent 8400 } 8500 {:name "Taxes and Insurance" :parent nil } 8510 {:name "Liability Insurance" :parent 8500 } + 8511 {:name "Workers Comp Insurance" :parent 8500 } 8610 {:name "Business License" :parent 8500 } 8620 {:name "Health Permit" :parent 8500 } 8710 {:name "Personal Property Taxes" :parent nil } From 8df6fb027930c1697dbe9be8237cab7f072aa8ad Mon Sep 17 00:00:00 2001 From: Bryce Covert Date: Thu, 10 Oct 2019 20:09:47 -0700 Subject: [PATCH 3/3] supports location matches, adds invoice types --- src/clj/auto_ap/datomic/clients.clj | 5 +++ src/clj/auto_ap/graphql.clj | 8 +++++ src/clj/auto_ap/graphql/clients.clj | 4 +++ src/clj/auto_ap/parse.clj | 4 ++- src/clj/auto_ap/parse/templates.clj | 14 ++++++++ src/clj/auto_ap/routes/invoices.clj | 12 ++++--- src/cljs/auto_ap/events.cljs | 4 +-- .../auto_ap/views/pages/admin/clients.cljs | 36 ++++++++++++++++++- 8 files changed, 78 insertions(+), 9 deletions(-) diff --git a/src/clj/auto_ap/datomic/clients.clj b/src/clj/auto_ap/datomic/clients.clj index 0eb7aecb..d42a8f9a 100644 --- a/src/clj/auto_ap/datomic/clients.clj +++ b/src/clj/auto_ap/datomic/clients.clj @@ -8,6 +8,11 @@ :where [?e :client/name]] (d/db (d/connect uri))) (map first) + (map (fn [c] + (update c :client/location-matches + (fn [lms] + + (map #(assoc % :location-match/match (first (:location-match/matches %))) lms))))) (map (fn [c] (update c :client/bank-accounts (fn [bas] diff --git a/src/clj/auto_ap/graphql.clj b/src/clj/auto_ap/graphql.clj index f56463c5..4abfe4a0 100644 --- a/src/clj/auto_ap/graphql.clj +++ b/src/clj/auto_ap/graphql.clj @@ -38,12 +38,17 @@ :serialize (schema/as-conformer #(or (:ident %) (:db/ident %) %))}} :objects { + :location_match + {:fields {:location {:type 'String} + :match {:type 'String}}} + :client {:fields {:id {:type :id} :name {:type 'String} :code {:type 'String} :email {:type 'String} :address {:type :address} + :location_matches {:type '(list :location_match)} :locations {:type '(list String)} :bank_accounts {:type '(list :bank_account)}}} :contact @@ -284,6 +289,8 @@ { :invoice_payment_amount {:fields {:invoice_id {:type :id} :amount {:type 'Float}}} + :edit_location_match {:fields {:location {:type 'String} + :match {:type 'String}}} :edit_client {:fields {:id {:type :id} :name {:type 'String} @@ -291,6 +298,7 @@ :email {:type 'String} :address {:type :add_address} :locations {:type '(list String)} + :location_matches {:type '(list :edit_location_match)} :bank_accounts {:type '(list :edit_bank_account)}}} :edit_bank_account {:fields {:id {:type :id } diff --git a/src/clj/auto_ap/graphql/clients.clj b/src/clj/auto_ap/graphql/clients.clj index dffdda2b..fd4a3fe2 100644 --- a/src/clj/auto_ap/graphql/clients.clj +++ b/src/clj/auto_ap/graphql/clients.clj @@ -32,6 +32,10 @@ :client/name (:name edit_client) :client/email (:email edit_client) :client/locations (filter identity (:locations edit_client)) + :client/location-matches (->> (:location_matches edit_client) + (filter (fn [lm] (and (:location lm) (:match lm)))) + (map (fn [lm] {:location-match/location (:location lm) + :location-match/matches [(:match lm)]}))) :client/address (remove-nils { :address/street1 (:street1 (:address edit_client)) :address/street2 (:street2 (:address edit_client)) diff --git a/src/clj/auto_ap/parse.clj b/src/clj/auto_ap/parse.clj index 92278a6a..30cf3cf6 100644 --- a/src/clj/auto_ap/parse.clj +++ b/src/clj/auto_ap/parse.clj @@ -26,6 +26,8 @@ [_ _ value] value) +(def last-text (atom nil)) + (defn template-applies? [text {:keys [keywords]}] (every? #(re-find % text) keywords)) @@ -49,7 +51,7 @@ :text text}))]))) (defn parse [text] - (println text) + (reset! last-text text) (->> t/pdf-templates (filter (partial template-applies? text)) first diff --git a/src/clj/auto_ap/parse/templates.clj b/src/clj/auto_ap/parse/templates.clj index b2607b64..1350a0fa 100644 --- a/src/clj/auto_ap/parse/templates.clj +++ b/src/clj/auto_ap/parse/templates.clj @@ -34,6 +34,20 @@ :customer-identifier #"Bill To[^\n]+\n[^\n]*\n([\w ]+)\s{2,}" :date #"Invoice #\s*\n\s*[\w\.]+\s+([\w\./]+)" :total #"Total\s+\$([0-9.]+)"} + :parser {:date [:clj-time "MM/dd/yy"]}} + {:vendor "DVW Commercial" + :keywords [#"DVW Commercial"] + :extract {:date #"\s*([0-9]+/[0-9]+/[0-9]+)" + :customer-identifier #"Bill To:[^\n]+\n[^\n]*\n\s*([\w ]+) \(" + :invoice-number #"Invoice\s*\n\s*([\w\./]+)*" + :total #"Total:\s+\$ ([0-9.]+)"} + :parser {:date [:clj-time "MM/dd/yy"]}} + {:vendor "Daylight Foods" + :keywords [#"DAYLIGHT FOODS"] + :extract {:date #"\n\s*Date[^\n]+\n\s*([0-9]+/[0-9]+/[0-9]+)" + :customer-identifier #"Bill To:[^\n]+\n\s*([\w ]+)" + :invoice-number #"Invoice\s([\w\./]+)*" + :total #"Total Invoice\s+([0-9.]+)"} :parser {:date [:clj-time "MM/dd/yy"]}}]) (def excel-templates diff --git a/src/clj/auto_ap/routes/invoices.clj b/src/clj/auto_ap/routes/invoices.clj index ac54ac60..d02e929c 100644 --- a/src/clj/auto_ap/routes/invoices.clj +++ b/src/clj/auto_ap/routes/invoices.clj @@ -163,13 +163,15 @@ _ (println imports) transactions (reduce (fn [result {:keys [invoice-number customer-identifier total date vendor-code text] :as info}] + (println "searching for" vendor-code) (let [[matching-vendor default-expense-account] (->> (d/query - (cond-> {:query {:find ['?vendor '?default-expense-account] - :in ['$ '?vendor-name] - :where ['[?vendor :vendor/name ?vendor-name] - '[?vendor :vendor/default-expense-account ?default-expense-account]]} - :args [(d/db (d/connect uri)) vendor-code]})) + {:query {:find ['?vendor '?default-expense-account] + :in ['$ '?vendor-name] + :where ['[?vendor :vendor/name ?vendor-name] + '[?vendor :vendor/default-expense-account ?default-expense-account]]} + :args [(d/db (d/connect uri)) vendor-code]}) first) + _ (println matching-vendor) matching-client (parse/best-match clients customer-identifier) _ (println "New invoice matches client" matching-client) matching-location (parse/best-location-match matching-client text ) diff --git a/src/cljs/auto_ap/events.cljs b/src/cljs/auto_ap/events.cljs index df1b7fbc..7ec41a5a 100644 --- a/src/cljs/auto_ap/events.cljs +++ b/src/cljs/auto_ap/events.cljs @@ -42,7 +42,7 @@ :graphql {:token token :query-obj {:venia/queries [[:client - [:id :name :code :email :locations [:bank-accounts [:id :code :number :bank-name :bank-code :check-number :name :routing :type :sort-order :visible :yodlee-account-id] ] + [:id :name :code :email :locations [:location-matches [:location :match]] [:bank-accounts [:id :code :number :bank-name :bank-code :check-number :name :routing :type :sort-order :visible :yodlee-account-id] ] [:address [:street1 :street2 :city :state :zip]]]] [:vendor [:id :name :default-expense-account [:primary-contact [:name :phone :email :id]] [:secondary-contact [:id :name :phone :email]] :print-as :invoice-reminder-schedule :code]]]} @@ -65,7 +65,7 @@ (fn [{:keys [db]} [_ token user]] {:graphql {:token token :query-obj {:venia/queries [[:client - [:id :name :code [:address [:street1 :street2 :city :state :zip]] [:bank-accounts [:id :code :number :bank-name :bank-code :check-number :name :routing :type :sort-order :visible :yodlee-account-id] ]]] + [:id :name :code [:location-matches [:location :match]] [:address [:street1 :street2 :city :state :zip]] [:bank-accounts [:id :code :number :bank-name :bank-code :check-number :name :routing :type :sort-order :visible :yodlee-account-id] ]]] [:vendor [:id :name :default-expense-account [:primary-contact [:name :phone :email :id]] [:secondary-contact [:id :name :phone :email]] :print-as :invoice-reminder-schedule :code]]]} diff --git a/src/cljs/auto_ap/views/pages/admin/clients.cljs b/src/cljs/auto_ap/views/pages/admin/clients.cljs index cb09f756..cc2b0ee9 100644 --- a/src/cljs/auto_ap/views/pages/admin/clients.cljs +++ b/src/cljs/auto_ap/views/pages/admin/clients.cljs @@ -42,6 +42,7 @@ :code (:code new-client-data) ;; TODO add validation can't change :email (:email new-client-data) :locations (:locations new-client-data) + :location-matches (:location-matches new-client-data) :address {:street1 (:street1 (:address new-client-data)) :street2 (:street2 (:address new-client-data)), :city (:city (:address new-client-data)) @@ -85,7 +86,7 @@ :operation/name "EditClient"} :venia/queries [{:query/data [:edit-client {:edit-client new-client-req} - [:id :name :code :email :locations [:address [:street1 :street2 :city :state :zip]] [:bank-accounts [:id :number :check-number :name :code :bank-code :bank-name :routing :type :visible :yodlee-account-id :sort-order]]]]}]} + [:id :name :code :email :locations [:location-matches [:location :match]] [:address [:street1 :street2 :city :state :zip]] [:bank-accounts [:id :number :check-number :name :code :bank-code :bank-name :routing :type :visible :yodlee-account-id :sort-order]]]]}]} :on-success [::save-complete] :on-error [::forms/save-error ::new-client]}} {:db new-client-form})))) @@ -111,6 +112,14 @@ (update :locations conj (:location client)) (dissoc :location)))) +(re-frame/reg-event-db + ::add-new-location-match + [(forms/in-form ::new-client) (re-frame/path [:data])] + (fn [client _] + (-> client + (update :location-matches conj (:location-match client)) + (dissoc :location-match)))) + (re-frame/reg-event-db ::add-new-bank-account [(forms/in-form ::new-client) (re-frame/path [:data])] @@ -372,6 +381,31 @@ (for [location (:locations new-client)] ^{:key location} [:li location ])]]] + [:div.field + [:p.help "Location matches"] + [:div.control + [:div.field.has-addons + + [:p.control + + [bind-field + [:input.input {:type "text" + :placeholder "San Jose" + :field [:location-match :match] + :event change-event + :subscription new-client}]]] + [:p.control + [bind-field + [:input.input {:type "text" + :placeholder "DT" + :field [:location-match :location] + :event change-event + :subscription new-client}]]] + [:p.control [:button.button.is-primary {:on-click (dispatch-event [::add-new-location-match])} "Add"]]] + [:ul + (for [{:keys [location match]} (:location-matches new-client)] + ^{:key location} [:li match "->" location ])]]] + [:div {:style {:padding-bottom "0.75em" :padding-top "0.75em"}} [:h2.subtitle "Address"] [address-field {:field [:address]