supports yodlee manual import.
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
[auto-ap.db.vendors :as vendors]
|
||||
[auto-ap.db.invoices :as invoices]
|
||||
[auto-ap.db.utils :refer [query]]
|
||||
[auto-ap.yodlee.import :refer [manual-import]]
|
||||
[auto-ap.utils :refer [by]]
|
||||
[auto-ap.parse :as parse]
|
||||
[auto-ap.graphql.utils :refer [assert-admin]]
|
||||
@@ -48,12 +49,19 @@
|
||||
(defn parse-amount [i]
|
||||
(try
|
||||
(Double/parseDouble (str/replace (or (second
|
||||
(re-matches #"[^0-9\.,]*([0-9\.,]+)[^0-9\.,]*" (:amount i)))
|
||||
(re-matches #"[^0-9\.,\\-]*([0-9\.,\\-]+)[^0-9\.,]*" (:amount i)))
|
||||
"0")
|
||||
#"," ""))
|
||||
(catch Exception e
|
||||
(throw (Exception. (str "Could not parse total from value '" (:amount i) "'") e)))))
|
||||
|
||||
(defn parse-account-id [i]
|
||||
(try
|
||||
(Integer/parseInt (second
|
||||
(re-matches #"[^0-9,\\-]*([0-9,\\-]+)[^0-9,]*" (:account-id i))))
|
||||
(catch Exception e
|
||||
(throw (Exception. (str "Could not parse account from value '" (:account-id i) "'") e)))))
|
||||
|
||||
(defn parse-date [{:keys [raw-date]}]
|
||||
(try
|
||||
(parse/parse-value :clj-time "MM/dd/yyyy" raw-date)
|
||||
@@ -70,67 +78,102 @@
|
||||
|
||||
(defroutes routes
|
||||
(wrap-routes
|
||||
(context "/invoices" []
|
||||
#_(POST "/upload"
|
||||
{{ files "file"} :params :as params}
|
||||
(let [{:keys [filename tempfile]} files
|
||||
companies (companies/get-all)
|
||||
vendors (vendors/get-all)]
|
||||
(invoices/import (parse/parse-file (.getPath tempfile) filename) companies vendors)
|
||||
{:status 200
|
||||
:body (pr-str (invoices/get-pending ((:query-params params ) "company")))
|
||||
:headers {"Content-Type" "application/edn"}}))
|
||||
(context "/" []
|
||||
(context "/transactions" []
|
||||
(POST "/batch-upload"
|
||||
{{:keys [data company-id]} :edn-params user :identity}
|
||||
(assert-admin user)
|
||||
(let [columns [:status :raw-date :description-original :high-level-category nil nil :amount nil nil nil nil nil :account-id]
|
||||
rows (->> (str/split data #"\n" )
|
||||
(drop 1)
|
||||
(map #(str/split % #"\t"))
|
||||
(map #(into {} (filter identity (map (fn [c k] [k c] ) % columns))))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(map (parse-or-error :amount parse-amount))
|
||||
(map (parse-or-error :account-id parse-account-id))
|
||||
(map (parse-or-error :date parse-date)))
|
||||
|
||||
raw-transactions (vec (->> rows
|
||||
(filter #(not (seq (:errors %))) )
|
||||
(map (fn [{:keys [description-original status high-level-category amount account-id]}]
|
||||
{:description-original description-original
|
||||
:status status
|
||||
:high-level-category high-level-category
|
||||
:amount amount
|
||||
:account-id account-id}))))]
|
||||
|
||||
(POST "/upload-integreat"
|
||||
{{:keys [excel-rows]} :edn-params identity :identity}
|
||||
(assert-admin identity)
|
||||
(let [columns [:raw-date :vendor-name :check :location :invoice-number :amount :company :bill-entered :bill-rejected :added-on :exported-on]
|
||||
|
||||
all-vendors (by :name (vendors/get-all))
|
||||
(manual-import raw-transactions company-id 1)
|
||||
|
||||
all-companies (companies/get-all)
|
||||
all-companies (merge (by :code all-companies) (by :name all-companies))
|
||||
{:status 200
|
||||
:body (pr-str {:status "success"})
|
||||
:headers {"Content-Type" "application/edn"}}))
|
||||
)
|
||||
(context "/invoices" []
|
||||
#_(POST "/upload"
|
||||
{{ files "file"} :params :as params}
|
||||
(let [{:keys [filename tempfile]} files
|
||||
companies (companies/get-all)
|
||||
vendors (vendors/get-all)]
|
||||
(invoices/import (parse/parse-file (.getPath tempfile) filename) companies vendors)
|
||||
{:status 200
|
||||
:body (pr-str (invoices/get-pending ((:query-params params ) "company")))
|
||||
:headers {"Content-Type" "application/edn"}}))
|
||||
|
||||
|
||||
rows (->> (str/split excel-rows #"\n" )
|
||||
(map #(str/split % #"\t"))
|
||||
(map #(into {} (map (fn [c k] [k c] ) % columns)))
|
||||
(map reset-id)
|
||||
(map assoc-company-code)
|
||||
|
||||
(map (parse-or-error :company-id #(parse-company % all-companies)))
|
||||
(map (parse-or-error :vendor-id #(parse-vendor % all-vendors)))
|
||||
(map (parse-or-error :invoice-number parse-invoice-number))
|
||||
(map (parse-or-error :total parse-amount))
|
||||
(map (parse-or-error :date parse-date)))
|
||||
error-rows (filter :errors rows)
|
||||
vendors-not-found (->> rows
|
||||
(filter #(and (nil? (:vendor-id %))
|
||||
(not= "Cash" (:check %))))
|
||||
(map :vendor-name)
|
||||
set)
|
||||
insert-rows (vec (->> (filter #(not (seq (:errors %))) rows)
|
||||
(map (fn [{:keys [vendor-id total company-id amount date invoice-number default-location]}]
|
||||
{:vendor-id vendor-id
|
||||
:company-id company-id
|
||||
:default-location default-location
|
||||
:total total
|
||||
:outstanding-balance total
|
||||
:imported true
|
||||
:status "unpaid"
|
||||
:invoice-number invoice-number
|
||||
:date date}))))
|
||||
(POST "/upload-integreat"
|
||||
{{:keys [excel-rows]} :edn-params user :identity}
|
||||
(assert-admin user)
|
||||
(let [columns [:raw-date :vendor-name :check :location :invoice-number :amount :company :bill-entered :bill-rejected :added-on :exported-on]
|
||||
|
||||
all-vendors (by :name (vendors/get-all))
|
||||
|
||||
inserted-row-count (invoices/upsert-multi! insert-rows)
|
||||
already-imported-count (- (count insert-rows) inserted-row-count)]
|
||||
(expense-accounts/assign-defaults!)
|
||||
all-companies (companies/get-all)
|
||||
all-companies (merge (by :code all-companies) (by :name all-companies))
|
||||
|
||||
|
||||
|
||||
rows (->> (str/split excel-rows #"\n" )
|
||||
(map #(str/split % #"\t"))
|
||||
(map #(into {} (map (fn [c k] [k c] ) % columns)))
|
||||
(map reset-id)
|
||||
(map assoc-company-code)
|
||||
|
||||
(map (parse-or-error :company-id #(parse-company % all-companies)))
|
||||
(map (parse-or-error :vendor-id #(parse-vendor % all-vendors)))
|
||||
(map (parse-or-error :invoice-number parse-invoice-number))
|
||||
(map (parse-or-error :total parse-amount))
|
||||
(map (parse-or-error :date parse-date)))
|
||||
error-rows (filter :errors rows)
|
||||
vendors-not-found (->> rows
|
||||
(filter #(and (nil? (:vendor-id %))
|
||||
(not= "Cash" (:check %))))
|
||||
(map :vendor-name)
|
||||
set)
|
||||
insert-rows (vec (->> (filter #(not (seq (:errors %))) rows)
|
||||
(map (fn [{:keys [vendor-id total company-id amount date invoice-number default-location]}]
|
||||
{:vendor-id vendor-id
|
||||
:company-id company-id
|
||||
:default-location default-location
|
||||
:total total
|
||||
:outstanding-balance total
|
||||
:imported true
|
||||
:status "unpaid"
|
||||
:invoice-number invoice-number
|
||||
:date date}))))
|
||||
|
||||
{:status 200
|
||||
:body (pr-str {:imported inserted-row-count
|
||||
:already-imported already-imported-count
|
||||
:vendors-not-found vendors-not-found
|
||||
:errors (map #(dissoc % :date) error-rows)})
|
||||
:headers {"Content-Type" "application/edn"}})))
|
||||
inserted-row-count (invoices/upsert-multi! insert-rows)
|
||||
already-imported-count (- (count insert-rows) inserted-row-count)]
|
||||
(expense-accounts/assign-defaults!)
|
||||
|
||||
|
||||
|
||||
{:status 200
|
||||
:body (pr-str {:imported inserted-row-count
|
||||
:already-imported already-imported-count
|
||||
:vendors-not-found vendors-not-found
|
||||
:errors (map #(dissoc % :date) error-rows)})
|
||||
:headers {"Content-Type" "application/edn"}}))))
|
||||
wrap-secure))
|
||||
|
||||
@@ -22,9 +22,9 @@
|
||||
(and company-id bank-account-id amount)
|
||||
|
||||
(let [matching-checks (checks/get-graphql {:company-id company-id
|
||||
:bank-account-id bank-account-id
|
||||
:amount amount
|
||||
:status "pending"})]
|
||||
:bank-account-id bank-account-id
|
||||
:amount (- amount)
|
||||
:status "pending"})]
|
||||
(if (= 1 (count matching-checks))
|
||||
(:id (first matching-checks))
|
||||
nil))
|
||||
@@ -48,14 +48,19 @@
|
||||
description-simple :simple} :description
|
||||
{merchant-id :i
|
||||
merchant-name :name} :merchant
|
||||
base-type :baseType
|
||||
type :type
|
||||
status :status}
|
||||
transaction
|
||||
amount (if (= "DEBIT" base-type)
|
||||
(- amount)
|
||||
amount)
|
||||
check-number (extract-check-number transaction)
|
||||
company-id (yodlee-account-id->company account-id)
|
||||
bank-account-id (yodlee-account-id->bank-account-id account-id)
|
||||
check-id (transaction->check-id transaction check-number company-id bank-account-id amount)
|
||||
]]
|
||||
(println transaction)
|
||||
|
||||
(try
|
||||
(transactions/upsert!
|
||||
@@ -88,8 +93,9 @@
|
||||
|
||||
(mapcat (fn [transaction-group]
|
||||
(map
|
||||
(fn [index {:keys [date description-original high-level-category amount] :as transaction}]
|
||||
(fn [index {:keys [date description-original high-level-category amount account-id] :as transaction}]
|
||||
{:id (str date "-" description-original "-" amount "-" index)
|
||||
|
||||
:date (time/unparse date "YYYY-MM-dd")
|
||||
:amount {:amount amount}
|
||||
:description {:original description-original
|
||||
|
||||
Reference in New Issue
Block a user