several fixes for invoices.
This commit is contained in:
@@ -55,14 +55,29 @@
|
|||||||
:total #"Total:\s+\$ ([0-9.]+)"}
|
:total #"Total:\s+\$ ([0-9.]+)"}
|
||||||
:parser {:date [:clj-time "MM/dd/yy"]}}
|
:parser {:date [:clj-time "MM/dd/yy"]}}
|
||||||
|
|
||||||
|
;; DAYLIGHT FOOD STATEMENT
|
||||||
|
{:vendor "Daylight Foods"
|
||||||
|
:keywords [#"DAYLIGHT FOODS" #"Customer Statement"]
|
||||||
|
:extract {:date #"^.*?([0-9]+/[0-9]+/[0-9]+)"
|
||||||
|
:customer-identifier #"Phone:.*\n+\s+(.*)"
|
||||||
|
:invoice-number #"\s+(\w+)"
|
||||||
|
:total #"([\-]?[0-9]+\.[0-9]+)"}
|
||||||
|
:parser {:date [:clj-time "MM/dd/yy"]
|
||||||
|
:total [:trim-commas-and-negate nil]}
|
||||||
|
:multi #"\n"
|
||||||
|
:multi-match? #"^\s*[A-Z]\d+\s+([0-9]+/[0-9]+/[0-9]+)"}
|
||||||
|
|
||||||
;; DAYLIGHT FOOD
|
;; DAYLIGHT FOOD
|
||||||
{:vendor "Daylight Foods"
|
{:vendor "Daylight Foods"
|
||||||
:keywords [#"DAYLIGHT FOODS"]
|
:keywords [#"DAYLIGHT FOODS"]
|
||||||
:extract {:date #"\n\s*Date[^\n]+\n\s*([0-9]+/[0-9]+/[0-9]+)"
|
:extract {:date #"\n\s*Date[^\n]+\n\s*([0-9]+/[0-9]+/[0-9]+)"
|
||||||
:customer-identifier #"Bill To:[^\n]+\n\s*([\w ]+)"
|
:customer-identifier #"Bill To:.*\n\s*(.*?)\s{2,}"
|
||||||
:invoice-number #"Invoice\s([\w\./]+)*"
|
:invoice-number #"Invoice\s([\w\./]+)*"
|
||||||
:total #"Total Invoice\s+([0-9.]+)"}
|
:total #"Total Invoice\s+([\-]?[0-9.]+)"}
|
||||||
:parser {:date [:clj-time "MM/dd/yy"]}}
|
:parser {:date [:clj-time "MM/dd/yy"]
|
||||||
|
:total [:trim-commas-and-negate nil]}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;; SOUTHBAY FRESH
|
;; SOUTHBAY FRESH
|
||||||
{:vendor "Southbay Fresh Produce"
|
{:vendor "Southbay Fresh Produce"
|
||||||
@@ -105,6 +120,16 @@
|
|||||||
:parser {:date [:clj-time "EEE MMM dd, yyyy HH:mm aa"]
|
:parser {:date [:clj-time "EEE MMM dd, yyyy HH:mm aa"]
|
||||||
:total [:trim-commas nil]}}
|
:total [:trim-commas nil]}}
|
||||||
|
|
||||||
|
;; GOLDEN BRANDS
|
||||||
|
{:vendor "Bigoli Fresh Pasta"
|
||||||
|
:keywords [#"bigolifreshpasta.com"]
|
||||||
|
:extract {:date #"INVOICE #.*?\n.*?([0-9]+/[0-9]+/[0-9]+)" ;; HOW TO GO TO SPCIFIC LINE
|
||||||
|
:customer-identifier #"BILL TO.*\n\s+(.*?)\s{2,}"
|
||||||
|
:invoice-number #"INVOICE #.*?\n(\d+)"
|
||||||
|
:total #" TOTAL\s+([0-9,]+\.[0-9]{2})"}
|
||||||
|
:parser {:date [:clj-time "MM/dd/yyyy"]
|
||||||
|
:total [:trim-commas nil]}}
|
||||||
|
|
||||||
;; Del Monte Meats
|
;; Del Monte Meats
|
||||||
{:vendor "Del Monte Meat Co"
|
{:vendor "Del Monte Meat Co"
|
||||||
:keywords [#"Del Monte"]
|
:keywords [#"Del Monte"]
|
||||||
@@ -226,11 +251,13 @@
|
|||||||
:keywords [#"Suncrest.*Invoice"]
|
:keywords [#"Suncrest.*Invoice"]
|
||||||
:extract {:date #"Date.*\n\s*\n(?:.*?)([0-9]+/[0-9]+/[0-9]+)"
|
:extract {:date #"Date.*\n\s*\n(?:.*?)([0-9]+/[0-9]+/[0-9]+)"
|
||||||
:customer-identifier #"Bill To(?:.*?)\n\n(.*?)\s{2,}"
|
:customer-identifier #"Bill To(?:.*?)\n\n(.*?)\s{2,}"
|
||||||
:invoice-number #"Invoice #.*\n\s*\n(?:.*?)\s{2,}(\d{5,})"
|
:invoice-number #"Invoice #.*\n\s*\n.*? (\d{3,})"
|
||||||
:total #"Balance Due\s+\$([0-9,]+\.[0-9]{2})"}
|
:total #"Balance Due\s+\$([0-9,]+\.[0-9]{2})"}
|
||||||
:parser {:date [:clj-time "MM/dd/yyyy"]
|
:parser {:date [:clj-time "MM/dd/yyyy"]
|
||||||
:total [:trim-commas nil]}}
|
:total [:trim-commas nil]}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;; PACIFIC SEAFOOD
|
;; PACIFIC SEAFOOD
|
||||||
{:vendor "Pacific Seafood"
|
{:vendor "Pacific Seafood"
|
||||||
:keywords [#"pacseafood"]
|
:keywords [#"pacseafood"]
|
||||||
@@ -266,12 +293,12 @@
|
|||||||
;; US FOODS
|
;; US FOODS
|
||||||
{:vendor "US Foods"
|
{:vendor "US Foods"
|
||||||
:keywords [#"US Foods"]
|
:keywords [#"US Foods"]
|
||||||
:extract {:date #"INVOICE NUMBER[^\n]+\n\n\d+\s+\d+\s+([0-9]+/[0-9]+/[0-9]+)"
|
:extract {:date #"INVOICE DATE.*\n+.*?(?=([0-9]+/[0-9]+/[0-9]+))([0-9]+/[0-9]+/[0-9]+)"
|
||||||
:customer-identifier #"BILL TO[^\n]+\n([\S ]+?)(?=\s{2,})" ;; ([\S ]+)\s{2,}
|
:customer-identifier #"BILL TO[^\n]+\n([\S ]+?)(?=\s{2,})" ;; ([\S ]+)\s{2,}
|
||||||
:invoice-number #"INVOICE NUMBER[^\n]+\n\n\d+\s+(\d+)"
|
:invoice-number #"INVOICE NUMBER[^\n]+\n\n\d+\s+(\d+)"
|
||||||
:total #"(?:DELIVERED AMOUNT|PLEASE REMIT).*(?=\$)\$([0-9.,]+)\s*\n"}
|
:total #"(?:DELIVERED AMOUNT|PLEASE REMIT|AMOUNT).*?\$([0-9.,]+( CR)?)\n"}
|
||||||
:parser {:date [:clj-time "MM/dd/yyyy"]
|
:parser {:date [:clj-time ["MM/dd/yyyy" "yyyy/MM/dd"]]
|
||||||
:total [:trim-commas nil]}}
|
:total [:trim-commas-and-negate nil]}}
|
||||||
|
|
||||||
;; SYSCO
|
;; SYSCO
|
||||||
{:vendor "Sysco"
|
{:vendor "Sysco"
|
||||||
@@ -387,7 +414,7 @@
|
|||||||
:extract {:date #"([0-9]+/[0-9]+/[0-9]+)"
|
:extract {:date #"([0-9]+/[0-9]+/[0-9]+)"
|
||||||
:customer-identifier #"SOLD\s+([\S ]+?)(?=(\s{2,}|\n))"
|
:customer-identifier #"SOLD\s+([\S ]+?)(?=(\s{2,}|\n))"
|
||||||
:invoice-number #"(\S+)\s+(?=[0-9]+/[0-9]+/[0-9]+)"
|
:invoice-number #"(\S+)\s+(?=[0-9]+/[0-9]+/[0-9]+)"
|
||||||
:total #"(?:INVOICE|TOTAL)\s+([\d\.,\-]+\.[\d\-]+( CR)?)"}
|
:total #"(?:INVOICE|TOTAL|CREDIT)\s+([\d\.,\-]+\.[\d\-]+( CR)?)"}
|
||||||
:parser {:date [:clj-time "MM/dd/yyyy"]
|
:parser {:date [:clj-time "MM/dd/yyyy"]
|
||||||
:total [:trim-commas-and-negate nil]}}])
|
:total [:trim-commas-and-negate nil]}}])
|
||||||
|
|
||||||
|
|||||||
@@ -27,8 +27,20 @@
|
|||||||
|
|
||||||
(defmethod parse-value :clj-time
|
(defmethod parse-value :clj-time
|
||||||
[_ format value]
|
[_ format value]
|
||||||
(time/from-time-zone (f/parse (f/formatter format) value)
|
(let [format (if (sequential? format)
|
||||||
(time/time-zone-for-id "America/Los_Angeles")))
|
format
|
||||||
|
[format])]
|
||||||
|
(reduce
|
||||||
|
(fn [_ format]
|
||||||
|
(try
|
||||||
|
(reduced (time/from-time-zone (f/parse (f/formatter format) value)
|
||||||
|
(time/time-zone-for-id "America/Los_Angeles")))
|
||||||
|
(catch Exception e
|
||||||
|
(println e)
|
||||||
|
nil)))
|
||||||
|
nil
|
||||||
|
format)
|
||||||
|
))
|
||||||
|
|
||||||
(defmethod parse-value nil
|
(defmethod parse-value nil
|
||||||
[_ _ value]
|
[_ _ value]
|
||||||
|
|||||||
@@ -207,7 +207,7 @@
|
|||||||
(= (:db/id c) (Long/parseLong client)))
|
(= (:db/id c) (Long/parseLong client)))
|
||||||
clients))))
|
clients))))
|
||||||
_ (when-not matching-client
|
_ (when-not matching-client
|
||||||
(throw (ex-info (str "No client found in file. Select a client first.")
|
(throw (ex-info (str "Searched clients for '" customer-identifier "'. No client found in file. Select a client first.")
|
||||||
{:invoice-number invoice-number
|
{:invoice-number invoice-number
|
||||||
:customer-identifier customer-identifier
|
:customer-identifier customer-identifier
|
||||||
:vendor-code vendor-code})))
|
:vendor-code vendor-code})))
|
||||||
@@ -237,7 +237,9 @@
|
|||||||
(throw (ex-info (str "Failed to find potential matching invoice with"
|
(throw (ex-info (str "Failed to find potential matching invoice with"
|
||||||
" invoice " invoice-number
|
" invoice " invoice-number
|
||||||
" vendor " matching-vendor
|
" vendor " matching-vendor
|
||||||
" client " (:client/name matching-client))
|
" client " (:client/name matching-client)
|
||||||
|
". "
|
||||||
|
(.toString e))
|
||||||
{:args [ invoice-number matching-vendor (:db/id matching-client)]})))
|
{:args [ invoice-number matching-vendor (:db/id matching-client)]})))
|
||||||
))]
|
))]
|
||||||
|
|
||||||
@@ -270,7 +272,7 @@
|
|||||||
imports)]
|
imports)]
|
||||||
(when-not (seq transactions)
|
(when-not (seq transactions)
|
||||||
(throw (ex-info "No invoices found."
|
(throw (ex-info "No invoices found."
|
||||||
{:imports imports})))
|
{:imports (str imports)})))
|
||||||
@(d/transact (d/connect uri) (vec (set transactions)))))
|
@(d/transact (d/connect uri) (vec (set transactions)))))
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -15,50 +15,52 @@
|
|||||||
[cljsjs.dropzone :as dropzone]
|
[cljsjs.dropzone :as dropzone]
|
||||||
[cljs.reader :as edn]
|
[cljs.reader :as edn]
|
||||||
[clojure.string :as str]))
|
[clojure.string :as str]))
|
||||||
(def dropzone
|
(defn dropzone []
|
||||||
(let [client (re-frame/subscribe [::subs/client])
|
(let [client (re-frame/subscribe [::subs/client])
|
||||||
token (re-frame/subscribe [::subs/token])
|
token (re-frame/subscribe [::subs/token])
|
||||||
vendor (reagent/atom nil)]
|
vendor (reagent/atom nil)]
|
||||||
(with-meta
|
(reagent/create-class
|
||||||
(fn []
|
{:display-name "dropzone"
|
||||||
[:form.dz {:action "/api/invoices/upload"}
|
:component-did-mount (fn [this]
|
||||||
[:div.field.has-addons
|
(js/Dropzone. (rdom/dom-node this)
|
||||||
[:p.control
|
(clj->js {:init (fn []
|
||||||
[:a.button.is-static "Force Location"]]
|
(.on (js-this) "success" (fn [_ files]
|
||||||
[:p.control
|
(re-frame/dispatch [::invalidated])))
|
||||||
[:input.input {:name "location" :placeholder "SG" :size "4" :maxlength "2" :style {:display "inline"}}]]]
|
(.on (js-this) "error" (fn [_ error]
|
||||||
[:div.field.has-addons
|
(re-frame/dispatch [::errored error]))))
|
||||||
[:p.control
|
:paramName "file"
|
||||||
[:a.button.is-static "Force vendor"]]
|
:headers {"Authorization" (str "Token " @token)}
|
||||||
[typeahead-entity {:matches @(re-frame/subscribe [::subs/vendors])
|
:url (str "/api/invoices/upload"
|
||||||
:match->text :name
|
(when-let [client-name (-> @client :id)]
|
||||||
:name "vendor"
|
(str "?client=" client-name)))
|
||||||
:type "typeahead"
|
:previewsContainer "#dz-hidden"
|
||||||
:on-change (fn [v]
|
:previewTemplate "<div class='dz-hidden-preview'></div>"})))
|
||||||
(reset! vendor v))
|
:reagent-render (fn []
|
||||||
:value @vendor}]
|
[:form.dz {:action "/api/invoices/upload"}
|
||||||
]
|
[:div.field.has-addons
|
||||||
[:div.tile.notification
|
[:p.control
|
||||||
|
[:a.button.is-static "Force Location"]]
|
||||||
|
[:p.control
|
||||||
|
[:input.input {:name "location" :placeholder "SG" :size "4" :maxlength "2" :style {:display "inline"}}]]]
|
||||||
|
[:div.field.has-addons
|
||||||
|
[:p.control
|
||||||
|
[:a.button.is-static "Force vendor"]]
|
||||||
|
[typeahead-entity {:matches @(re-frame/subscribe [::subs/vendors])
|
||||||
|
:match->text :name
|
||||||
|
:name "vendor"
|
||||||
|
:type "typeahead"
|
||||||
|
:on-change (fn [v]
|
||||||
|
(reset! vendor v))
|
||||||
|
:value @vendor}]
|
||||||
|
]
|
||||||
|
[:div.tile.notification
|
||||||
|
|
||||||
[:div.has-text-centered {:style {:padding "80px 0px" :width "100%"}}
|
[:div.has-text-centered {:style {:padding "80px 0px" :width "100%"}}
|
||||||
[:span
|
[:span
|
||||||
[:span {:class "icon"}
|
[:span {:class "icon"}
|
||||||
[:i {:class "fa fa-cloud-download"}]]
|
[:i {:class "fa fa-cloud-download"}]]
|
||||||
"Drop any invoices you want to process here"]]]])
|
"Drop any invoices you want to process here"]]]])})
|
||||||
{:component-did-mount (fn [this]
|
))
|
||||||
(js/Dropzone. (rdom/dom-node this)
|
|
||||||
(clj->js {:init (fn []
|
|
||||||
(.on (js-this) "success" (fn [_ files]
|
|
||||||
(re-frame/dispatch [::invalidated])))
|
|
||||||
(.on (js-this) "error" (fn [_ error]
|
|
||||||
(re-frame/dispatch [::errored error]))))
|
|
||||||
:paramName "file"
|
|
||||||
:headers {"Authorization" (str "Token " @token)}
|
|
||||||
:url (str "/api/invoices/upload"
|
|
||||||
(when-let [client-name (-> @client :id)]
|
|
||||||
(str "?client=" client-name)))
|
|
||||||
:previewsContainer "#dz-hidden"
|
|
||||||
:previewTemplate "<div class='dz-hidden-preview'></div>"})))})))
|
|
||||||
|
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
@@ -191,13 +193,14 @@
|
|||||||
(fn []
|
(fn []
|
||||||
(let [invoice-page (re-frame/subscribe [::invoice-page])
|
(let [invoice-page (re-frame/subscribe [::invoice-page])
|
||||||
status (re-frame/subscribe [::subs/status])
|
status (re-frame/subscribe [::subs/status])
|
||||||
error (re-frame/subscribe [::error])]
|
error (re-frame/subscribe [::error])
|
||||||
|
client (:id @(re-frame/subscribe [::subs/client]))]
|
||||||
|
^{:key client}
|
||||||
[:div
|
[:div
|
||||||
[:h1.title "Upload invoices"]
|
[:h1.title "Upload invoices"]
|
||||||
|
|
||||||
[dropzone]
|
[dropzone]
|
||||||
|
|
||||||
|
|
||||||
[:div {:class "section"}
|
[:div {:class "section"}
|
||||||
(when @error
|
(when @error
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user