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]