several fixes for invoices.
This commit is contained in:
@@ -55,14 +55,29 @@
|
||||
:total #"Total:\s+\$ ([0-9.]+)"}
|
||||
: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
|
||||
{: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 ]+)"
|
||||
:customer-identifier #"Bill To:.*\n\s*(.*?)\s{2,}"
|
||||
:invoice-number #"Invoice\s([\w\./]+)*"
|
||||
:total #"Total Invoice\s+([0-9.]+)"}
|
||||
:parser {:date [:clj-time "MM/dd/yy"]}}
|
||||
:total #"Total Invoice\s+([\-]?[0-9.]+)"}
|
||||
:parser {:date [:clj-time "MM/dd/yy"]
|
||||
:total [:trim-commas-and-negate nil]}}
|
||||
|
||||
|
||||
|
||||
;; SOUTHBAY FRESH
|
||||
{:vendor "Southbay Fresh Produce"
|
||||
@@ -105,6 +120,16 @@
|
||||
:parser {:date [:clj-time "EEE MMM dd, yyyy HH:mm aa"]
|
||||
: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
|
||||
{:vendor "Del Monte Meat Co"
|
||||
:keywords [#"Del Monte"]
|
||||
@@ -226,11 +251,13 @@
|
||||
:keywords [#"Suncrest.*Invoice"]
|
||||
:extract {:date #"Date.*\n\s*\n(?:.*?)([0-9]+/[0-9]+/[0-9]+)"
|
||||
: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})"}
|
||||
:parser {:date [:clj-time "MM/dd/yyyy"]
|
||||
:total [:trim-commas nil]}}
|
||||
|
||||
|
||||
|
||||
;; PACIFIC SEAFOOD
|
||||
{:vendor "Pacific Seafood"
|
||||
:keywords [#"pacseafood"]
|
||||
@@ -266,12 +293,12 @@
|
||||
;; US FOODS
|
||||
{:vendor "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,}
|
||||
:invoice-number #"INVOICE NUMBER[^\n]+\n\n\d+\s+(\d+)"
|
||||
:total #"(?:DELIVERED AMOUNT|PLEASE REMIT).*(?=\$)\$([0-9.,]+)\s*\n"}
|
||||
:parser {:date [:clj-time "MM/dd/yyyy"]
|
||||
:total [:trim-commas nil]}}
|
||||
:total #"(?:DELIVERED AMOUNT|PLEASE REMIT|AMOUNT).*?\$([0-9.,]+( CR)?)\n"}
|
||||
:parser {:date [:clj-time ["MM/dd/yyyy" "yyyy/MM/dd"]]
|
||||
:total [:trim-commas-and-negate nil]}}
|
||||
|
||||
;; SYSCO
|
||||
{:vendor "Sysco"
|
||||
@@ -387,7 +414,7 @@
|
||||
:extract {:date #"([0-9]+/[0-9]+/[0-9]+)"
|
||||
:customer-identifier #"SOLD\s+([\S ]+?)(?=(\s{2,}|\n))"
|
||||
: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"]
|
||||
:total [:trim-commas-and-negate nil]}}])
|
||||
|
||||
|
||||
@@ -27,8 +27,20 @@
|
||||
|
||||
(defmethod parse-value :clj-time
|
||||
[_ format value]
|
||||
(time/from-time-zone (f/parse (f/formatter format) value)
|
||||
(time/time-zone-for-id "America/Los_Angeles")))
|
||||
(let [format (if (sequential? format)
|
||||
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
|
||||
[_ _ value]
|
||||
|
||||
@@ -207,7 +207,7 @@
|
||||
(= (:db/id c) (Long/parseLong client)))
|
||||
clients))))
|
||||
_ (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
|
||||
:customer-identifier customer-identifier
|
||||
:vendor-code vendor-code})))
|
||||
@@ -237,7 +237,9 @@
|
||||
(throw (ex-info (str "Failed to find potential matching invoice with"
|
||||
" invoice " invoice-number
|
||||
" vendor " matching-vendor
|
||||
" client " (:client/name matching-client))
|
||||
" client " (:client/name matching-client)
|
||||
". "
|
||||
(.toString e))
|
||||
{:args [ invoice-number matching-vendor (:db/id matching-client)]})))
|
||||
))]
|
||||
|
||||
@@ -270,7 +272,7 @@
|
||||
imports)]
|
||||
(when-not (seq transactions)
|
||||
(throw (ex-info "No invoices found."
|
||||
{:imports imports})))
|
||||
{:imports (str imports)})))
|
||||
@(d/transact (d/connect uri) (vec (set transactions)))))
|
||||
|
||||
|
||||
|
||||
@@ -15,50 +15,52 @@
|
||||
[cljsjs.dropzone :as dropzone]
|
||||
[cljs.reader :as edn]
|
||||
[clojure.string :as str]))
|
||||
(def dropzone
|
||||
(defn dropzone []
|
||||
(let [client (re-frame/subscribe [::subs/client])
|
||||
token (re-frame/subscribe [::subs/token])
|
||||
vendor (reagent/atom nil)]
|
||||
(with-meta
|
||||
(fn []
|
||||
[:form.dz {:action "/api/invoices/upload"}
|
||||
[:div.field.has-addons
|
||||
[: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%"}}
|
||||
[:span
|
||||
[:span {:class "icon"}
|
||||
[:i {:class "fa fa-cloud-download"}]]
|
||||
"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>"})))})))
|
||||
(reagent/create-class
|
||||
{:display-name "dropzone"
|
||||
: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>"})))
|
||||
:reagent-render (fn []
|
||||
[:form.dz {:action "/api/invoices/upload"}
|
||||
[:div.field.has-addons
|
||||
[: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%"}}
|
||||
[:span
|
||||
[:span {:class "icon"}
|
||||
[:i {:class "fa fa-cloud-download"}]]
|
||||
"Drop any invoices you want to process here"]]]])})
|
||||
))
|
||||
|
||||
|
||||
(re-frame/reg-sub
|
||||
@@ -191,12 +193,13 @@
|
||||
(fn []
|
||||
(let [invoice-page (re-frame/subscribe [::invoice-page])
|
||||
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
|
||||
[:h1.title "Upload invoices"]
|
||||
|
||||
[dropzone]
|
||||
|
||||
|
||||
[:div {:class "section"}
|
||||
(when @error
|
||||
|
||||
Reference in New Issue
Block a user