merged.
This commit is contained in:
@@ -47,6 +47,12 @@
|
||||
:invoice-status/paid
|
||||
:invoice-status/unpaid)]])})}]] )
|
||||
|
||||
(def add-client-identifier
|
||||
[[{:db/ident :invoice/client-identifier
|
||||
:db/doc "An identifier found in an uploaded invoice"
|
||||
:db/valueType :db.type/string
|
||||
:db/cardinality :db.cardinality/one}]])
|
||||
|
||||
(defn -main [& args]
|
||||
(println "Creating database ..." uri)
|
||||
(doto (d/create-database uri) println)
|
||||
@@ -125,18 +131,13 @@
|
||||
:requires [:auto-ap/add-hidden-to-vendor]}
|
||||
:auto-ap/convert-invoices {:txes-fn `add-general-ledger/convert-invoices
|
||||
:requires [:auto-ap/convert-vendors]}
|
||||
|
||||
:auto-ap/add-yodlee-merchant2 {:txes add-general-ledger/add-yodlee-merchant :requires [:auto-ap/convert-vendors]}
|
||||
:auto-ap/add-external-id-to-ledger {:txes add-general-ledger/add-external-id-to-ledger :requires [:auto-ap/add-yodlee-merchant2]}
|
||||
:auto-ap/add-exclude-to-transaction {:txes add-general-ledger/add-exclude-to-transaction :requires [:auto-ap/add-external-id-to-ledger]}
|
||||
|
||||
|
||||
:auto-ap/add-client-identifier2 {:txes add-client-identifier :requires [:auto-ap/make-every-account-visible]}
|
||||
:auto-ap/add-transaction-rules {:txes add-general-ledger/add-transaction-rules :requires [:auto-ap/add-exclude-to-transaction]}
|
||||
:auto-ap/add-bank-account-locations {:txes add-general-ledger/add-bank-account-locations :requires [:auto-ap/add-transaction-rules]}
|
||||
:auto-ap/convert-transactions {:txes-fn `add-general-ledger/convert-transactions :requires [:auto-ap/add-bank-account-locations]}
|
||||
|
||||
|
||||
}]
|
||||
:auto-ap/convert-transactions {:txes-fn `add-general-ledger/convert-transactions :requires [:auto-ap/add-bank-account-locations]}}]
|
||||
(println "Conforming database...")
|
||||
(c/ensure-conforms conn norms-map)
|
||||
(when (not (seq args))
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
:address {:type :address}
|
||||
:location_matches {:type '(list :location_match)}
|
||||
:locations {:type '(list String)}
|
||||
:matches {:type '(list String)}
|
||||
:bank_accounts {:type '(list :bank_account)}}}
|
||||
:contact
|
||||
{:fields {:id {:type :id}
|
||||
@@ -253,6 +254,7 @@
|
||||
:invoice
|
||||
{:fields {:id {:type :id}
|
||||
:original_id {:type 'Int}
|
||||
:client_identifier {:type 'String}
|
||||
:total {:type 'String}
|
||||
:outstanding_balance {:type 'String}
|
||||
:invoice_number {:type 'String}
|
||||
@@ -473,6 +475,7 @@
|
||||
:email {:type 'String}
|
||||
:address {:type :add_address}
|
||||
:locations {:type '(list String)}
|
||||
:matches {:type '(list String)}
|
||||
:location_matches {:type '(list :edit_location_match)}
|
||||
:bank_accounts {:type '(list :edit_bank_account)}}}
|
||||
:edit_bank_account
|
||||
|
||||
@@ -25,11 +25,17 @@
|
||||
id (or (:db/id client) "new-client")
|
||||
_ (println id)
|
||||
_ (println edit_client)
|
||||
_ (when client
|
||||
@(d/transact (d/connect uri)
|
||||
(into
|
||||
(mapv (fn [lm] [:db/retractEntity (:db/id lm)]) (:client/location-matches client))
|
||||
(mapv (fn [m] [:db/retract (:db/id client) :client/matches m]) (:client/matches client)))))
|
||||
transactions [(remove-nils {:db/id id
|
||||
:client/code (if (str/blank? (:client/code client))
|
||||
(:code edit_client)
|
||||
(:client/code client))
|
||||
:client/name (:name edit_client)
|
||||
:client/matches (:matches edit_client)
|
||||
:client/email (:email edit_client)
|
||||
:client/locations (filter identity (:locations edit_client))
|
||||
:client/location-matches (->> (:location_matches edit_client)
|
||||
@@ -65,7 +71,16 @@
|
||||
})]
|
||||
result @(d/transact (d/connect uri) transactions)]
|
||||
(println result "ID" id)
|
||||
(-> result :tempids (get id) (or id) d-clients/get-by-id ->graphql)))
|
||||
(-> result :tempids (get id) (or id) d-clients/get-by-id
|
||||
(update :client/location-matches
|
||||
(fn [lms]
|
||||
(mapcat (fn [lm]
|
||||
(map (fn [m]
|
||||
{:location-match/match m
|
||||
:location-match/location (:location-match/location lm)})
|
||||
(:location-match/matches lm)))
|
||||
lms)))
|
||||
->graphql)))
|
||||
|
||||
|
||||
(defn get-client [context args value]
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
(defn extract-template
|
||||
([text template]
|
||||
(println "template" template)
|
||||
(if (:multi template)
|
||||
(mapcat
|
||||
#(extract-template % text (dissoc template :multi))
|
||||
@@ -37,12 +38,15 @@
|
||||
(first (map second (re-seq v full-text))))
|
||||
str/trim )
|
||||
[value-parser parser-params] (-> template :parser k)]
|
||||
(assoc result k (u/parse-value value-parser parser-params value))))
|
||||
(assoc result k (try (u/parse-value value-parser parser-params value)
|
||||
(catch Exception e
|
||||
(println e))))))
|
||||
{:vendor-code (:vendor template)
|
||||
:text text
|
||||
:full-text full-text}))])))
|
||||
|
||||
(defn parse [text]
|
||||
(println "Parsing PDF " text)
|
||||
(reset! last-text text)
|
||||
(->> t/pdf-templates
|
||||
(filter (partial template-applies? text))
|
||||
@@ -79,7 +83,6 @@
|
||||
(let [fuzzy-match (->> clients
|
||||
(mapcat (fn [{:keys [:db/id :client/matches :client/name] :as client :or {matches []}}]
|
||||
(map (fn [m]
|
||||
(println m invoice-client-name)
|
||||
[client (m/jaccard (.toLowerCase invoice-client-name) (.toLowerCase m))])
|
||||
(conj matches name))))
|
||||
(filter #(< (second %) 0.25))
|
||||
@@ -111,7 +114,6 @@
|
||||
|
||||
(map (fn [match] [location match]) matches)))
|
||||
(filter (fn [[location match]]
|
||||
(println "loc " location match text)
|
||||
(re-find (re-pattern (str "(?i)" match)) text)) )
|
||||
first
|
||||
first)
|
||||
@@ -124,3 +126,10 @@
|
||||
first)
|
||||
(:client/default-location client)
|
||||
(first (:client/locations client))))
|
||||
|
||||
(defn dbg-parse [v]
|
||||
(doto
|
||||
(map
|
||||
(fn [x] (dissoc x :full-text :text))
|
||||
(parse v))
|
||||
clojure.pprint/pprint ))
|
||||
|
||||
@@ -20,16 +20,19 @@
|
||||
|
||||
(defmethod parse-csv :mama-lus
|
||||
[rows]
|
||||
(println "MAMA LU")
|
||||
(println "MAMA LU4")
|
||||
(transduce
|
||||
(comp (drop 1)
|
||||
(map (fn [[_ po-number despatch-number invoice-number invoice-date customer value :as row]]
|
||||
{:vendor-code "Mama Lu's Foods"
|
||||
:customer-identifier customer
|
||||
:invoice-number (str po-number "-" invoice-number )
|
||||
:date (u/parse-value :clj-time "MM/dd/yy HH:ss" invoice-date)
|
||||
:total value
|
||||
:text (str/join " " row)})))
|
||||
:date (try (u/parse-value :clj-time "M/d/yyyy HH:ss" invoice-date)
|
||||
(catch Exception _
|
||||
(u/parse-value :clj-time "M/d/yyyy" invoice-date)))
|
||||
:total (str/replace value #"," "")
|
||||
:text (str/join " " row)
|
||||
:full-text (str/join " " row)})))
|
||||
conj
|
||||
[]
|
||||
rows))
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
|
||||
|
||||
(def pdf-templates
|
||||
[{:vendor "CHFW"
|
||||
[
|
||||
;; CHEF's WAREHOUSE
|
||||
{:vendor "CHFW"
|
||||
:keywords [#"CHEF'S WAREHOUSE"]
|
||||
:extract {:total #"2 WKS C\.C\.\s+([\d.,]+)"
|
||||
:customer-identifier #"\n([A-Z][A-Z ]+)\s{2,}"
|
||||
@@ -13,6 +15,7 @@
|
||||
:invoice-number #"\s+[0-9]+/[0-9]+/[0-9]+\s+([0-9]+)"}
|
||||
:parser {:date [:clj-time "MM/dd/yyyy"]}}
|
||||
|
||||
;; GGM
|
||||
{:vendor "Golden Gate Meat Company, Inc"
|
||||
:keywords [#"Golden Gate Meat"]
|
||||
:extract {:total #"Invoice Total\:\s+\$([\d.,]+)"
|
||||
@@ -22,6 +25,7 @@
|
||||
:parser {:date [:clj-time "MM/dd/yyyy"]
|
||||
:total [:trim-commas nil]}}
|
||||
|
||||
;; CINTAS
|
||||
{:vendor "CINTAS"
|
||||
:keywords [#"CINTAS CORPORATION"]
|
||||
:extract {:invoice-number #"INVOICE\s#\s+([\d.,]+)"
|
||||
@@ -31,13 +35,17 @@
|
||||
:parser {:date [:clj-time "MM/dd/yy"]}
|
||||
:multi #"\f\f"}
|
||||
|
||||
;; CARBONIC
|
||||
{:vendor "Carbonic Service Inc"
|
||||
:keywords [#"CARBONIC SERVICE INC"]
|
||||
:extract {:invoice-number #"Invoice #\s*\n\s*[\w\.]+\s+[\w\./]+(.*)\s*\n"
|
||||
: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"]}}
|
||||
:total #"Total\s+\$([0-9.,]+)"}
|
||||
:parser {:date [:clj-time "MM/dd/yy"]
|
||||
:total [:trim-commas nil]}}
|
||||
|
||||
;; DVW
|
||||
{:vendor "DVW Commercial"
|
||||
:keywords [#"DVW Commercial"]
|
||||
:extract {:date #"\s*([0-9]+/[0-9]+/[0-9]+)"
|
||||
@@ -45,6 +53,8 @@
|
||||
:invoice-number #"Invoice\s*\n\s*([\w\./]+)*"
|
||||
:total #"Total:\s+\$ ([0-9.]+)"}
|
||||
:parser {:date [:clj-time "MM/dd/yy"]}}
|
||||
|
||||
;; DAYLIGHT FOOD
|
||||
{:vendor "Daylight Foods"
|
||||
:keywords [#"DAYLIGHT FOODS"]
|
||||
:extract {:date #"\n\s*Date[^\n]+\n\s*([0-9]+/[0-9]+/[0-9]+)"
|
||||
@@ -52,36 +62,193 @@
|
||||
:invoice-number #"Invoice\s([\w\./]+)*"
|
||||
:total #"Total Invoice\s+([0-9.]+)"}
|
||||
:parser {:date [:clj-time "MM/dd/yy"]}}
|
||||
|
||||
;; SOUTHBAY FRESH
|
||||
{:vendor "Southbay Fresh Produce"
|
||||
:keywords [#"SOUTH BAY FRESH PRODUCE"]
|
||||
:extract {:date #"^([0-9]+/[0-9]+/[0-9]+)"
|
||||
:customer-identifier #"FAX:[^\n]+\n\s+([A-Za-z ]+)\s{2}"
|
||||
:invoice-number #"^[0-9]+/[0-9]+/[0-9]+\s+(\d+)"
|
||||
:total #"\$([0-9.]+)"}
|
||||
:customer-identifier #"To:[^\n]*\n\s+([A-Za-z' ]+)\s{2}"
|
||||
:invoice-number #"INV #\/(\d+)"
|
||||
:total #"\$([0-9.]+)\."}
|
||||
:parser {:date [:clj-time "MM/dd/yyyy"]}
|
||||
:multi #"\n"
|
||||
:multi-match? #"^[0-9]+/[0-9]+/[0-9]+\s+(\d+)"}
|
||||
{:vendor "Performance Food Group"
|
||||
:multi-match? #"^[0-9]+/[0-9]+/[0-9]+\s+INV "}
|
||||
|
||||
;; PFG - LEDYARD
|
||||
{:vendor "Performance Food Group - LEDYARD"
|
||||
:keywords [#"performancefoodservice"]
|
||||
:extract {:date #"DELIVER TO[^\n]+\n.+?(?=[0-9]+/[0-9]+/[0-9]+)([0-9]+/[0-9]+/[0-9]+)"
|
||||
:customer-identifier #"DELIVER TO[^\n]+\n\s*[\S ]+?(?=\s{2,}([\S ]+?)\s{2,})" ;; ([\S ]+)\s{2,}
|
||||
:invoice-number #"DELIVER TO[^\n]+\n.+?(?=\d+)(\d+)\s*\n"
|
||||
:total #"([0-9.]+)\s+Status Code"}
|
||||
:parser {:date [:clj-time "MM/dd/yy"]}}
|
||||
:total #"([0-9.\-]+)\s+Status Code"}
|
||||
:parser {:date [:clj-time "MM/dd/yy"]
|
||||
:total [:trim-commas-and-negate nil]}}
|
||||
|
||||
;; SOUTHERN GLAZER'S
|
||||
{:vendor "Southern Glazers"
|
||||
:keywords [#"Southern Glazer's"]
|
||||
:extract {:date #"INVOICE DATE(?s:.*)(?= (?:[0-9]+/[0-9]+/[0-9]+)\s+([0-9]+/[0-9]+/[0-9]+)) "
|
||||
:customer-identifier #"SOLD TO:(?:.*)(?=\n)\n(.*)(?=\s{2,})" ;; ([\S ]+)\s{2,}
|
||||
:invoice-number #"INVOICE\n(?:.*?)(?=\d{4,})(\d+)"
|
||||
:total #"PAY THIS AMOUNT(?s:.*)(?= ([0-9,]+\.[0-9]{2}))"}
|
||||
:parser {:date [:clj-time "MM/dd/yy"]
|
||||
:total [:trim-commas nil]}}
|
||||
|
||||
;; GOLDEN BRANDS
|
||||
{:vendor "Golden Brands San Jose"
|
||||
:keywords [#"GOLDEN BRANDS"]
|
||||
:extract {:date #"0430\n(.*)"
|
||||
:customer-identifier #"Account:(?:.*\n)(.*(?=\s{2,}))"
|
||||
:invoice-number #"Invoice#: (\d+)"
|
||||
:total #"Invoice Total\s+([0-9]+\.[0-9]{2})"}
|
||||
:parser {:date [:clj-time "EEE MMM dd, yyyy HH:mm aa"]
|
||||
:total [:trim-commas nil]}}
|
||||
|
||||
;; WINE WAREHOUSE
|
||||
{:vendor "Wine Warehouse"
|
||||
:keywords [#"WINE WAREHOUSE"]
|
||||
:extract {:date #"INVOICE DATE\s+([0-9]+/[0-9]+/[0-9]+)"
|
||||
:customer-identifier #"SHIP-TO-PARTY.*\n(.*?)(?=\s{2,})"
|
||||
:invoice-number #"INV #\s+(\d+)"
|
||||
:total #"PLEASE PAY THIS AMOUNT\s+([0-9]+\.[0-9]{2})"}
|
||||
:parser {:date [:clj-time "MM/dd/yyyy"]
|
||||
:total [:trim-commas nil]}}
|
||||
|
||||
;; REGAL
|
||||
{:vendor "Regal Wine Co"
|
||||
:keywords [#"REGAL WINE"]
|
||||
:extract {:date #"INVOICE DATE.*\n\n(?:.*?)([0-9]+/[0-9]+/[0-9]+)"
|
||||
:customer-identifier #"INVOICE\n(.*?)\s{2,}"
|
||||
:invoice-number #"INVOICE NUMBER.*\n\n(?:.*?)(\d+)"
|
||||
:total #"Total Amount Due(?:.*?)([0-9,]+\.[0-9]{2})"}
|
||||
:parser {:date [:clj-time "MM/dd/yy"]
|
||||
:total [:trim-commas nil]}}
|
||||
|
||||
;; ALSCO
|
||||
{:vendor "Alsco"
|
||||
:keywords [#"Alsco"]
|
||||
:extract {:date #"Invoice Date:\s+(.*)"
|
||||
:customer-identifier #"Invoice F o r(?:.*?)\n\s+(.*?)\s{2,}"
|
||||
:invoice-number #" (\S+)\n\s+Invoice Date"
|
||||
:total #"Invoice Total\s+\$([0-9,]+\.[0-9]{2})"}
|
||||
:parser {:date [:clj-time "MMM dd yyyy"]
|
||||
:total [:trim-commas nil]}}
|
||||
|
||||
;; SUNCREST
|
||||
{:vendor "Suncrest USA Inc"
|
||||
: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,})"
|
||||
:total #"Balance Due\s+\$([0-9,]+\.[0-9]{2})"}
|
||||
:parser {:date [:clj-time "MM/dd/yyyy"]
|
||||
:total [:trim-commas nil]}}
|
||||
|
||||
;; SUNCREST STATEMENT
|
||||
{:vendor "Suncrest USA Inc"
|
||||
:keywords [#"Suncrest.*\n.*Statement"]
|
||||
:extract {:date #"^([0-9]+/[0-9]+/[0-9]+)"
|
||||
:customer-identifier #"To:(?:.*?)\n\s*(.*?)\s{2,}"
|
||||
:invoice-number #"INV #(\d+)"
|
||||
:total #"Orig\. Amount \$([0-9,]+\.[0-9]{2})"}
|
||||
:parser {:date [:clj-time "MM/dd/yyyy"]
|
||||
:total [:trim-commas nil]}
|
||||
:multi #"\n"
|
||||
:multi-match? #"^[0-9]+/[0-9]+/[0-9]+\s+INV "}
|
||||
|
||||
;; 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]+)"
|
||||
: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\s+\$([0-9.]+)"}
|
||||
:parser {:date [:clj-time "MM/dd/yyyy"]}}
|
||||
:total #"(?:DELIVERED AMOUNT|PLEASE REMIT).*(?=\$)\$([0-9.,]+)\s*\n"}
|
||||
:parser {:date [:clj-time "MM/dd/yyyy"]
|
||||
:total [:trim-commas nil]}}
|
||||
|
||||
;; SYSCO
|
||||
{:vendor "Sysco"
|
||||
:keywords [#"SYSCO"]
|
||||
:extract {:date #"INVOICE NUMBER[^\n]+\n([^\n]+)\n"
|
||||
:customer-identifier #"INVOICE NUMBER[^\n]+\n[^\n]+\n([\S ]+?)(?=\s{2,})" ;; ([\S ]+)\s{2,}
|
||||
:invoice-number #"INVOICE NUMBER[^\n]+\n[^\n]+\n.*?(?=[\d]{9})(\d{9})"
|
||||
:total #"\s{2,}INVOICE\s{2,}.*?(?=TOTAL)TOTAL\s+([0-9.]+)"}
|
||||
:parser {:date [:clj-time "MM/dd/yyyy"]}}])
|
||||
:parser {:date [:clj-time "MM/dd/yyyy"]}}
|
||||
|
||||
;; LE BOULANGER
|
||||
{:vendor "Le Boulanger"
|
||||
:keywords [#"Le Boulanger"]
|
||||
:extract {:date #"Invoice Date: ([^\n]+)\n"
|
||||
:customer-identifier #"Ship to\n+\s+([\S ]+?)(?=\s{2,})"
|
||||
:invoice-number #"Invoice No: ([^\n]+)\n"
|
||||
:total #" Total:\s+([\d\.]+)"}
|
||||
:parser {:date [:clj-time "MMM dd, yyyy"]}}
|
||||
|
||||
|
||||
;; A&B
|
||||
{:vendor "A&B Produce"
|
||||
:keywords [#"ABProduce"]
|
||||
:extract {:date #"^\s+([0-9]+/[0-9]+/[0-9]+)"
|
||||
:customer-identifier #"BILL TO:[^\n]+\n[^\n]+\n[^\n]+\n(.*)\s{2,}"
|
||||
:invoice-number #"(\d+)\s+(?:INV|C/M)"
|
||||
:total #" (?:INV|C/M)\s+([\d\.\-]+)"}
|
||||
:parser {:date [:clj-time "MM/dd/yyyy"]
|
||||
:total [:trim-commas-and-negate nil]}
|
||||
:multi #"\n"
|
||||
:multi-match? #"^\s+[0-9]+/[0-9]+/[0-9]+\s+\d+\s+(INV|C/M)\s+"}
|
||||
|
||||
;; CHEF's CHOICE
|
||||
{:vendor "Chef's Choice Produce Co"
|
||||
:keywords [#"(2170 MARTIN AVENUE|213-3886)"]
|
||||
:extract {:date #"([0-9/]{10,10})"
|
||||
:customer-identifier #"\n B\s+([\S ]+?)(?=\s{2,}I) "
|
||||
:invoice-number #"^0*([0-9]+)"
|
||||
:total #"INVOICE\s+([\d\.]+)"}
|
||||
:parser {:date [:clj-time "MM/dd/yyyy"]} ;; may want to try two approaches [:clj-time ["MM/dd/yyyy" "MM1dd1yyyy"]]
|
||||
:multi #"\n"
|
||||
:multi-match? #"\s+INVOICE\s+"}
|
||||
|
||||
;; FRESH AND BELT
|
||||
{:vendor "Fresh and Best Produce"
|
||||
:keywords [#"freshbestproduce"]
|
||||
:extract {:date #"\n\s+([0-9]+/[0-9]+/[0-9]+)"
|
||||
:customer-identifier #"Bill To[^\n]+\n([A-Za-z ']+)"
|
||||
:invoice-number #"\n\s+[0-9/]+\s+(\d+)"
|
||||
:total #"Balance Due\s+\$([0-9\.]+)"}
|
||||
:parser {:date [:clj-time "MM/dd/yyyy"]}}
|
||||
|
||||
|
||||
;; PFG - ROMA
|
||||
{:vendor "Performance Food Group - ROMA"
|
||||
:keywords [#"Performance Food Group, Inc\n\f"]
|
||||
:extract {:date #"Date: ([0-9]+/[0-9]+/[0-9]+)"
|
||||
:customer-identifier #"BILL TO:\s+([\S ]+?)(?=\s{2,})"
|
||||
:invoice-number #"INVOICE NO.\s+ ([\d]+)"
|
||||
:total #"([\d\.,]+)\s+INVOICE TOTAL"}
|
||||
:parser {:date [:clj-time "MM/dd/yy"]
|
||||
:total [:trim-commas nil]}}
|
||||
|
||||
;; PFG - ROMA LOOK 1
|
||||
{:vendor "Performance Food Group - ROMA"
|
||||
:keywords [#"inquiries call 1-800-233-6211"]
|
||||
:extract {:date #"([0-9]+/[0-9]+/[0-9]+)"
|
||||
:customer-identifier #"BILL TO:\s+([\S ]+?)(?=\s{2,})"
|
||||
:invoice-number #"^\s+([\dA-Z]+)"
|
||||
:total #"([\d\.,\-]+\.[\d\-]+)"}
|
||||
:parser {:date [:clj-time "MM/dd/yyyy"]
|
||||
:total [:trim-commas-and-negate nil]}
|
||||
:multi #"\n"
|
||||
:multi-match? #"^\s+[\d]{6,8}\s+\d+"}
|
||||
|
||||
;; JFC
|
||||
{:vendor "JFC International"
|
||||
:keywords [#"48490 MILMONT DRIVE"]
|
||||
: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)?)"}
|
||||
:parser {:date [:clj-time "MM/dd/yyyy"]
|
||||
:total [:trim-commas-and-negate nil]}}])
|
||||
|
||||
(defn offset [c x y]
|
||||
(.toString (CellAddress. (+ y (.getRow (.getAddress c))) (+ x (.getColumn (.getAddress c))) )))
|
||||
|
||||
@@ -14,6 +14,17 @@
|
||||
(str/replace value #"," "")
|
||||
)
|
||||
|
||||
(defmethod parse-value :trim-commas-and-negate
|
||||
[_ _ value]
|
||||
(let [[_ raw-value] (re-find #"([\d\.]+)"
|
||||
(-> value
|
||||
(str/replace #"," "")
|
||||
(str/replace #"-" "")))]
|
||||
(if (or (str/includes? value "-")
|
||||
(str/includes? value "CR"))
|
||||
(str (- (Double/parseDouble raw-value)))
|
||||
(str raw-value))))
|
||||
|
||||
(defmethod parse-value :clj-time
|
||||
[_ format value]
|
||||
(time/from-time-zone (f/parse (f/formatter format) value)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
(defroutes routes
|
||||
(GET "/oauth" {{:strs [code]} :query-params :keys [scheme] :as r {:strs [host]} :headers}
|
||||
(println "Authenticating with" r "..." code)
|
||||
(try
|
||||
(let [auth (-> "https://accounts.google.com/o/oauth2/token"
|
||||
(http/post
|
||||
@@ -44,17 +45,19 @@
|
||||
|
||||
;; TODO - these namespaces are not being transmitted/deserialized properly
|
||||
(if (and token user)
|
||||
{:status 301
|
||||
:headers {"Location" (str "/?jwt=" (jwt/sign (doto {:user (:name profile)
|
||||
:exp (time/plus (time/now) (time/days 30))
|
||||
:user/clients (map (fn [c]
|
||||
(dissoc c :client/bank-accounts ))
|
||||
(:user/clients user))
|
||||
:user/role (name (:user/role user))
|
||||
:user/name (:name profile)}
|
||||
println)
|
||||
(:jwt-secret env)
|
||||
{:alg :hs512}))}}
|
||||
(let [jwt (jwt/sign (doto {:user (:name profile)
|
||||
:exp (time/plus (time/now) (time/days 30))
|
||||
:user/clients (map (fn [c]
|
||||
(dissoc c :client/bank-accounts :client/location-matches))
|
||||
(:user/clients user))
|
||||
:user/role (name (:user/role user))
|
||||
:user/name (:name profile)}
|
||||
println)
|
||||
(:jwt-secret env)
|
||||
{:alg :hs512})]
|
||||
(println "authenticated. using jwt" jwt)
|
||||
{:status 301
|
||||
:headers {"Location" (str "/?jwt=" jwt)}})
|
||||
{:status 401
|
||||
:body "Couldn't authenticate"}))
|
||||
(catch Exception e
|
||||
|
||||
@@ -166,7 +166,6 @@
|
||||
|
||||
(defn import-uploaded-invoice [imports]
|
||||
(let [clients (d-clients/get-all)
|
||||
_ (clojure.pprint/pprint imports)
|
||||
|
||||
transactions (reduce (fn [result {:keys [invoice-number customer-identifier total date vendor-code text full-text] :as info}]
|
||||
(println "searching for" vendor-code)
|
||||
@@ -204,6 +203,7 @@
|
||||
|
||||
:else
|
||||
(conj result (remove-nils #:invoice {:invoice/client (:db/id matching-client)
|
||||
:invoice/client-identifier customer-identifier
|
||||
:invoice/vendor matching-vendor
|
||||
:invoice/invoice-number invoice-number
|
||||
:invoice/total (Double/parseDouble total)
|
||||
@@ -219,8 +219,7 @@
|
||||
))
|
||||
[]
|
||||
imports)]
|
||||
|
||||
@(d/transact (d/connect uri) transactions)))
|
||||
@(d/transact (d/connect uri) (vec (set transactions)))))
|
||||
|
||||
(defroutes routes
|
||||
(wrap-routes
|
||||
|
||||
@@ -163,6 +163,21 @@
|
||||
(recur (concat transactions transaction-batch) (+ batch-size skip))
|
||||
transactions)))))
|
||||
|
||||
(defn count-specific-transactions [account]
|
||||
(let [cob-session (login-cobrand)
|
||||
user-session (login-user cob-session)]
|
||||
|
||||
(-> (str (:yodlee-base-url env) "/transactions/count?accountId=" account)
|
||||
(doto println)
|
||||
|
||||
(client/get {:headers (doto
|
||||
(merge base-headers {"Authorization" (auth-header cob-session user-session)})
|
||||
println)
|
||||
:as :json})
|
||||
:body
|
||||
:transaction
|
||||
)))
|
||||
|
||||
(defn get-access-token []
|
||||
(let [cob-session (login-cobrand)
|
||||
user-session (login-user cob-session)
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
:graphql {:token token
|
||||
:query-obj {:venia/queries [[:client
|
||||
|
||||
[: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 :locations] ]
|
||||
[:id :name :code :email :matches :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 :locations] ]
|
||||
[:address [:street1 :street2 :city :state :zip]]]]
|
||||
[:vendor
|
||||
[:id :name :hidden [:default-account [:name :id :location]] [:primary-contact [:name :phone :email :id]] [:secondary-contact [:id :name :phone :email]] :print-as :invoice-reminder-schedule :code]]
|
||||
@@ -68,7 +68,7 @@
|
||||
(fn [{:keys [db]} [_ token user]]
|
||||
{:graphql {:token token
|
||||
:query-obj {:venia/queries [[:client
|
||||
[: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 :locations] ]]]
|
||||
[:id :name :code :matches :locations [: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 :locations] ]]]
|
||||
[:vendor
|
||||
[:id :name :hidden [:default-account [:name :id :location]] [:primary-contact [:name :phone :email :id]] [:secondary-contact [:id :name :phone :email]] :print-as :invoice-reminder-schedule :code]]
|
||||
[:accounts [:numeric-code :name :location :type :account_set :id]]]}
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
{:venia/queries [[:invoice_page
|
||||
(assoc params
|
||||
:client-id (:id @(re-frame/subscribe [::subs/client])))
|
||||
[[:invoices [:id :total :outstanding-balance :invoice-number :date :status
|
||||
[[:invoices [:id :total :outstanding-balance :invoice-number :date :status :client-identifier
|
||||
[:vendor [:name :id]]
|
||||
[:expense_accounts [:amount :id :location
|
||||
[:account [:id :name :numeric-code :location ]]]]
|
||||
@@ -58,7 +58,7 @@
|
||||
:start
|
||||
:end]]]})
|
||||
|
||||
(defn invoice-table [{:keys [id invoice-page status on-params-change vendors params check-boxes checked on-check-changed on-edit-invoice on-void-invoice on-unvoid-invoice expense-event]}]
|
||||
(defn invoice-table [{:keys [id invoice-page status on-params-change vendors params check-boxes checked on-check-changed on-edit-invoice on-void-invoice on-unvoid-invoice expense-event overrides]}]
|
||||
(let [visible-checks @(re-frame/subscribe [::visible-checks])
|
||||
visible-expense-accounts @(re-frame/subscribe [::visible-expense-accounts])
|
||||
selected-client @(re-frame/subscribe [::subs/client])
|
||||
@@ -156,7 +156,9 @@
|
||||
|
||||
(on-check-changed id i)))} ]])
|
||||
(when-not selected-client
|
||||
[:td (:name client)])
|
||||
[:td (if-let [client-override (:client overrides)]
|
||||
(client-override i)
|
||||
(:name client))])
|
||||
[:td (:name vendor)]
|
||||
[:td invoice-number]
|
||||
[:td (date->str date) ]
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
::edit-client-clicked
|
||||
(fn [{:keys [db]} [_ client-id]]
|
||||
{:db (-> db
|
||||
(forms/stop-form ::new-client)
|
||||
(forms/start-form ::new-client (get (:clients db) client-id)))}))
|
||||
|
||||
(re-frame/reg-sub
|
||||
@@ -42,6 +43,7 @@
|
||||
:code (:code new-client-data) ;; TODO add validation can't change
|
||||
:email (:email new-client-data)
|
||||
:locations (:locations new-client-data)
|
||||
:matches (vec (:matches new-client-data))
|
||||
:location-matches (:location-matches new-client-data)
|
||||
:address {:street1 (:street1 (:address new-client-data))
|
||||
:street2 (:street2 (:address new-client-data)),
|
||||
@@ -87,7 +89,7 @@
|
||||
:operation/name "EditClient"}
|
||||
:venia/queries [{:query/data [:edit-client
|
||||
{:edit-client new-client-req}
|
||||
[: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 :locations]]]]}]}
|
||||
[:id :name :code :email :locations :matches [: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 :locations]]]]}]}
|
||||
:on-success [::save-complete]
|
||||
:on-error [::forms/save-error ::new-client]}}
|
||||
{:db new-client-form}))))
|
||||
@@ -118,6 +120,23 @@
|
||||
(update-in [:bank-accounts which-account :locations] #(conj (or % #{}) (get-in client [:bank-accounts which-account :location-select])))
|
||||
(update-in [:bank-accounts which-account] dissoc :location-select))))
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::add-new-match
|
||||
[(forms/in-form ::new-client) (re-frame/path [:data])]
|
||||
(fn [client _]
|
||||
(-> client
|
||||
(update :matches conj (:match client))
|
||||
(update :matches set)
|
||||
(dissoc :match))))
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::remove-match
|
||||
[(forms/in-form ::new-client) (re-frame/path [:data])]
|
||||
(fn [client [_ which]]
|
||||
(-> client
|
||||
(update :matches set)
|
||||
(update :matches disj which))))
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::add-new-location-match
|
||||
[(forms/in-form ::new-client) (re-frame/path [:data])]
|
||||
@@ -126,6 +145,18 @@
|
||||
(update :location-matches conj (:location-match client))
|
||||
(dissoc :location-match))))
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::remove-location-match
|
||||
[(forms/in-form ::new-client) (re-frame/path [:data])]
|
||||
(fn [client [_ i]]
|
||||
(-> client
|
||||
(update :location-matches (fn [lm]
|
||||
(->> lm
|
||||
(map vector (range))
|
||||
(filter (fn [[index item]]
|
||||
(not= index i)))
|
||||
(map second)))))))
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::add-new-bank-account
|
||||
[(forms/in-form ::new-client) (re-frame/path [:data])]
|
||||
@@ -433,6 +464,22 @@
|
||||
:spec ::entity/email
|
||||
:event change-event
|
||||
:subscription new-client}]]]]
|
||||
[:div.field
|
||||
[:p.help "Matches"]
|
||||
[:div.control
|
||||
[:div.field.has-addons
|
||||
[:p.control
|
||||
[bind-field
|
||||
[:input.input {:type "text"
|
||||
:field :match
|
||||
:event change-event
|
||||
:subscription new-client}]]]
|
||||
[:p.control [:button.button.is-primary {:on-click (dispatch-event [::add-new-match])} "Add"]]]]
|
||||
[:ul
|
||||
(for [match (:matches new-client)]
|
||||
^{:key match} [:li match [:a {:on-click (dispatch-event [::remove-match match])} [:span.icon [:span.fa.fa-times]]]])]]
|
||||
|
||||
|
||||
|
||||
[:div.field
|
||||
[:p.help "Locations"]
|
||||
@@ -470,9 +517,11 @@
|
||||
: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 ])]]]
|
||||
(for [[index {:keys [location match]}] (map vector (range) (:location-matches new-client))]
|
||||
^{:key index} [:li match "->" location [:a {:on-click (dispatch-event [::remove-location-match index])} [:span.icon
|
||||
[:span.fa.fa-times]]]])]]]
|
||||
|
||||
[:div {:style {:padding-bottom "0.75em" :padding-top "0.75em"}}
|
||||
[:h2.subtitle "Address"]
|
||||
|
||||
@@ -171,6 +171,11 @@
|
||||
(if (seq (:invoices @invoice-page))
|
||||
[invoice-table {:id :approved
|
||||
:invoice-page invoice-page
|
||||
:overrides {:client (fn [row]
|
||||
[:p (:name (:client row))
|
||||
[:p [:i.is-size-7 (:client-identifier row)]]]
|
||||
|
||||
)}
|
||||
:check-boxes true
|
||||
:checked (:checked @invoice-page)
|
||||
:on-check-changed (fn [which invoice]
|
||||
|
||||
Reference in New Issue
Block a user