tons of bug fixes
This commit is contained in:
@@ -44,9 +44,6 @@ proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl;
|
||||
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
|
||||
# Mitigate httpoxy attack (see README for details)
|
||||
proxy_set_header Proxy "";
|
||||
proxy_buffer_size 128k;
|
||||
proxy_buffers 4 256k;
|
||||
proxy_busy_buffers_size 256k;
|
||||
server {
|
||||
server_name _; # This is just an invalid value which will never trigger on a real hostname.
|
||||
listen 80;
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
gzip on;
|
||||
gzip_types application/edn;
|
||||
proxy_connect_timeout 300;
|
||||
proxy_send_timeout 300;
|
||||
proxy_read_timeout 300;
|
||||
send_timeout 300;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
(ns fixing-transactions-manually-imported-incorrectl)
|
||||
(ns auto-ap.yodlee.import)
|
||||
|
||||
|
||||
;; This buffer is for Clojure experiments and evaluation.
|
||||
@@ -14,15 +14,31 @@
|
||||
|
||||
(first all-ts)
|
||||
|
||||
|
||||
(def g (auto-ap.yodlee.import/get-existing))
|
||||
(map
|
||||
:transaction/yodlee-merchant
|
||||
(let [all-bank-accounts (get-all-bank-accounts)
|
||||
(first
|
||||
(let [all-bank-accounts (auto-ap.yodlee.import/get-all-bank-accounts)
|
||||
transaction->bank-account (comp (by :bank-account/yodlee-account-id all-bank-accounts) :accountId)
|
||||
all-rules (tr/get-all)]
|
||||
(transactions->txs all-ts transaction->bank-account (rm/rule-applying-fn all-rules) (get-existing))))
|
||||
|
||||
(count g)
|
||||
(with-open [writer (java.io.StringWriter.)]
|
||||
(clojure.data.csv/write-csv writer
|
||||
(->>
|
||||
(let [all-bank-accounts (auto-ap.yodlee.import/get-all-bank-accounts)
|
||||
all-clients (by :db/id (d-clients/get-all))
|
||||
transaction->bank-account (comp (by :bank-account/yodlee-account-id all-bank-accounts) :accountId)
|
||||
all-bank-accounts (by :db/id all-bank-accounts)
|
||||
all-rules (tr/get-all)]
|
||||
(->> (transactions->txs all-ts transaction->bank-account (rm/rule-applying-fn all-rules) (get-existing))
|
||||
(map (fn [r]
|
||||
[(:transaction/id r) (:transaction/amount r)
|
||||
(coerce/to-date-time (:transaction/date r))
|
||||
(:transaction/description-original r)
|
||||
(:bank-account/code (all-bank-accounts (:transaction/bank-account r)))
|
||||
(:client/code (all-clients (:transaction/client r)))]))))))
|
||||
(println (.toString writer)))
|
||||
|
||||
(g (digest/sha-256 (str 2553824503)))
|
||||
|
||||
@@ -32,20 +48,117 @@
|
||||
(with-open [writer (java.io.StringWriter.)]
|
||||
(clojure.data.csv/write-csv writer
|
||||
(->>
|
||||
(d/query {:query {:find ['?e]
|
||||
(d/query {:query {:find ['?e '?e2]
|
||||
:in ['$]
|
||||
:where ['[?e :transaction/id ?tid]
|
||||
'[?e :transaction/date ?d]
|
||||
'(not [?e :transaction/type])]}
|
||||
:args [(d/since (d/db (d/connect uri)) #inst "2020-06-01")]})
|
||||
(map first)
|
||||
'[?e :transaction/type]
|
||||
'[?e :transaction/bank-account ?ba]
|
||||
'[?e2 :transaction/date ?d]
|
||||
'[(not= ?e2 ?e)]
|
||||
'[?e :transaction/amount ?a1]
|
||||
'[?e2 :transaction/amount ?a2]
|
||||
'[?e2 :transaction/bank-account ?ba]
|
||||
'[(auto-ap.utils/dollars= ?a1 ?a2)]
|
||||
'(not [?e2 :transaction/type])]}
|
||||
:args [(d/since (d/db (d/connect uri)) #inst "2020-04-01")]})
|
||||
vec
|
||||
(d/pull-many (d/db (d/connect uri))
|
||||
[:db/id
|
||||
:transaction/date :transaction/id :transaction/amount
|
||||
:transaction/description-original
|
||||
{:transaction/client [:client/code]}
|
||||
{:transaction/bank-account [:bank-account/code]}])
|
||||
(map (fn [r]
|
||||
[(:transaction/id r) (:db/id r) (:transaction/amount r) (coerce/to-date-time (:transaction/date r)) (:transaction/description-original r) (:bank-account/code (:transaction/bank-account r)) (:client/code (:transaction/client r))]))))
|
||||
(map (fn [[e1 e2]]
|
||||
[
|
||||
(d/pull (d/db (d/connect uri))
|
||||
[:db/id
|
||||
:transaction/date :transaction/id :transaction/amount
|
||||
:transaction/description-original
|
||||
{:transaction/client [:client/code]}
|
||||
{:transaction/bank-account [:bank-account/code]}]
|
||||
e1)
|
||||
(d/pull (d/db (d/connect uri))
|
||||
[:db/id
|
||||
:transaction/date :transaction/id :transaction/amount
|
||||
:transaction/description-original
|
||||
{:transaction/client [:client/code]}
|
||||
{:transaction/bank-account [:bank-account/code]}]
|
||||
e2)
|
||||
]))
|
||||
|
||||
(map (fn [[r1 r2]]
|
||||
[(:transaction/id r1)
|
||||
(:db/id r1 )
|
||||
(:transaction/amount r1)
|
||||
(coerce/to-date-time (:transaction/date r1))
|
||||
(:transaction/description-original r1)
|
||||
(:bank-account/code (:transaction/bank-account r1))
|
||||
(:client/code (:transaction/client r1))
|
||||
|
||||
(:transaction/id r2)
|
||||
(:db/id r2)
|
||||
(:transaction/amount r2)
|
||||
(coerce/to-date-time (:transaction/date r2))
|
||||
(:transaction/description-original r2)
|
||||
(:bank-account/code (:transaction/bank-account r2))
|
||||
(:client/code (:transaction/client r2))])))
|
||||
|
||||
)
|
||||
(println (.toString writer)))
|
||||
|
||||
|
||||
|
||||
(def matches-to-repair2
|
||||
(->>
|
||||
(d/query {:query {:find ['?e '?e2]
|
||||
:in ['$]
|
||||
:where ['[?e :transaction/id ?tid]
|
||||
'[?e :transaction/date ?d]
|
||||
'[?e :transaction/type]
|
||||
'[?e :transaction/bank-account ?ba]
|
||||
'[?e2 :transaction/date ?d]
|
||||
'[(not= ?e2 ?e)]
|
||||
'[?e :transaction/amount ?a1]
|
||||
'[?e2 :transaction/amount ?a2]
|
||||
'[?e2 :transaction/bank-account ?ba]
|
||||
'[(auto-ap.utils/dollars= ?a1 ?a2)]
|
||||
'(not [?e2 :transaction/type])]}
|
||||
:args [(d/since (d/db (d/connect uri)) #inst "2020-04-01")]})
|
||||
vec
|
||||
(map (fn [[e1 e2]]
|
||||
[
|
||||
(d/pull (d/db (d/connect uri))
|
||||
[:db/id
|
||||
:transaction/date :transaction/id :transaction/amount
|
||||
:transaction/description-original
|
||||
:transaction/approval-status
|
||||
{:transaction/client [:client/code]}
|
||||
{:transaction/bank-account [:bank-account/code]}
|
||||
{:journal-entry/_original-entity ['*]}]
|
||||
e1)
|
||||
(d/pull (d/db (d/connect uri))
|
||||
[:db/id
|
||||
:transaction/date :transaction/id :transaction/amount
|
||||
:transaction/description-original
|
||||
:transaction/approval-status
|
||||
{:transaction/client [:client/code]}
|
||||
{:transaction/bank-account [:bank-account/code]}
|
||||
{:journal-entry/_original-entity ['*]}]
|
||||
e2)
|
||||
]))
|
||||
))
|
||||
|
||||
(count matches-to-repair2)
|
||||
|
||||
(defn repair-transaction [[t-auto t-manual]]
|
||||
(into
|
||||
[{:db/id "datomic.tx"
|
||||
:db/doc "Deletes a transaction that was added manually and automatically"}
|
||||
[:db/retractEntity (:db/id t-auto)]]
|
||||
(mapv
|
||||
(fn [j]
|
||||
[:db/retractEntity (:db/id j)])
|
||||
(:journal-entry/_original-entity t-auto))))
|
||||
|
||||
(defn map-new-transaction-id [[t-auto t-manual]]
|
||||
[[:db/add (:db/id t-manual) :transaction/id (:transaction/id t-auto)]])
|
||||
|
||||
(map-new-transaction-id (first matches-to-repair))
|
||||
|
||||
(doseq [t matches-to-repair]
|
||||
@(d/transact (d/connect uri) (map-new-transaction-id t)))
|
||||
|
||||
@@ -33,8 +33,13 @@
|
||||
|
||||
(defmethod entity-change->ledger :invoice
|
||||
[db [type id]]
|
||||
(let [entity (d/pull db ['* {:invoice/vendor '[*] :invoice/payment '[*]}] id)]
|
||||
(when-not (= true (:invoice/exclude-from-ledger entity))
|
||||
(let [entity (d/pull db ['* {:invoice/vendor '[*]
|
||||
:invoice/payment '[*]
|
||||
:invoice/status '[:db/ident]
|
||||
:invoice/import-status '[:db/ident]}] id)]
|
||||
(when-not (or (= true (:invoice/exclude-from-ledger entity))
|
||||
(= :import-status/pending (:db/ident (:invoice/import-status entity)))
|
||||
(= :invoice-status/voided (:db/ident (:invoice/status entity))))
|
||||
(remove-nils
|
||||
{:journal-entry/source "invoice"
|
||||
:journal-entry/client (:db/id (:invoice/client entity))
|
||||
@@ -157,3 +162,5 @@
|
||||
#_(process-one (d/tx-report-queue (d/connect uri) ))
|
||||
|
||||
#_(process-all)
|
||||
|
||||
#_(reset! break true)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
(ns auto-ap.parse.excel
|
||||
(:require [auto-ap.parse.templates :as t]
|
||||
[auto-ap.parse.util :as u]
|
||||
[clojure.string :as str]
|
||||
[dk.ative.docjure.spreadsheet :as d])
|
||||
(:import (org.apache.poi.ss.util CellAddress)))
|
||||
@@ -9,7 +10,7 @@
|
||||
(defn template-applies? [text {:keys [keywords]}]
|
||||
(every? #(re-find % text) keywords))
|
||||
|
||||
(defn extract [wb {:keys [extract vendor]}]
|
||||
(defn extract [wb {:keys [extract vendor parser]}]
|
||||
(if (fn? extract)
|
||||
(extract wb vendor)
|
||||
[(reduce-kv
|
||||
@@ -24,11 +25,15 @@
|
||||
(map (fn [cell]
|
||||
(let [address (.getAddress cell)
|
||||
cell-value (str (d/read-cell (d/select-cell (.toString (CellAddress. (+ offset-row (.getRow address)) (+ offset-column (.getColumn address)) ))
|
||||
(first (d/sheet-seq wb)))))]
|
||||
(if extract-regex
|
||||
(second (re-find extract-regex cell-value))
|
||||
|
||||
cell-value))))
|
||||
(first (d/sheet-seq wb)))))
|
||||
raw-result (if extract-regex
|
||||
(second (re-find extract-regex cell-value))
|
||||
|
||||
cell-value)]
|
||||
(if (get parser k)
|
||||
(u/parse-value (first (get parser k) ) (second (get parser k) ) raw-result)
|
||||
raw-result
|
||||
))))
|
||||
first)))
|
||||
{:vendor-code vendor}
|
||||
extract)]))
|
||||
|
||||
@@ -271,7 +271,7 @@
|
||||
|
||||
;; PACIFIC SEAFOOD
|
||||
{:vendor "Pacific Seafood"
|
||||
:keywords [#"pacseafood"]
|
||||
:keywords [#"(pacseafood|PACIFIC FRESH)"]
|
||||
:extract {:date #"DATE(?:.*\n.*(?=([0-9]+/[0-9]+/[0-9]+)))([0-9]+/[0-9]+/[0-9]+)"
|
||||
:customer-identifier #"DELIVER TO:(?:.*\n)(.*?)(?=\s{2})"
|
||||
:invoice-number #"INVOICE NO\.\n(?:.*?(?= [0-9]+\n)) ([0-9]+)"
|
||||
@@ -439,12 +439,15 @@
|
||||
:total [#"PAY THIS" -1 0]
|
||||
:date [#"INVOICE DATE" 0 1]
|
||||
:invoice-number [#"INVOICE NUMBER" 0 1]}}
|
||||
{:vendor "SWO"
|
||||
{:vendor "Southern Glazers"
|
||||
:keywords [#"Please note that the total invoice amount may"]
|
||||
:extract {:customer-identifier [#"Customer #" 1 0]
|
||||
:total [#"Total Invoice" 0 5]
|
||||
:total [#"Subtotal" 0 16 ]
|
||||
:date [#"Date" 0 0 #"Date: (.*)"]
|
||||
:invoice-number [#"Invoice #" 0 0 #"Invoice #: (.*)"]}}
|
||||
:invoice-number [#"Invoice #" 0 0 #"Invoice #: (.*)"]
|
||||
:account-number [#"Customer #" 0 0 #"Customer #: (.*)"]}
|
||||
:parser { :total [:trim-commas-and-remove-dollars nil]
|
||||
:date [:clj-time "MM/dd/yyyy"]}}
|
||||
{:vendor "Mama Lu's Foods"
|
||||
:keywords [#"Mama Lu's Foods"]
|
||||
:extract (fn [wb vendor]
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
[_ _ value]
|
||||
(str/replace value #"," "")
|
||||
)
|
||||
(defmethod parse-value :trim-commas-and-remove-dollars
|
||||
[_ _ value]
|
||||
(str/replace (str/replace value #"," "") #"\$" ""))
|
||||
|
||||
(defmethod parse-value :trim-commas-and-negate
|
||||
[_ _ value]
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
(let [[session token] (yodlee/get-access-token)]
|
||||
{:status 200
|
||||
:headers {"Content-Type" "application/edn"}
|
||||
:body (pr-str (yodlee/get-provider-accounts-with-accounts)) }))
|
||||
:body (pr-str @yodlee/in-memory-cache) }))
|
||||
(POST "/reauthenticate/:id" {:keys [query-params identity] {:keys [id]} :route-params
|
||||
data :edn-params
|
||||
:as request}
|
||||
@@ -53,6 +53,7 @@
|
||||
:headers {"Content-Type" "application/edn"}
|
||||
:body (pr-str (yodlee/reauthenticate (Long/parseLong id) data)) })
|
||||
(catch Exception e
|
||||
(println e)
|
||||
{:status 500
|
||||
:headers {"Content-Type" "application/edn"}
|
||||
:body (pr-str {:message (.getMessage e)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
(:require #_[auto-ap.background.mail :refer [always-process-sqs]]
|
||||
[auto-ap.handler :refer [app]]
|
||||
[auto-ap.ledger :refer [process-all]]
|
||||
[auto-ap.yodlee.core :refer [load-in-memory-cache]]
|
||||
[nrepl.server :refer [start-server stop-server]]
|
||||
[config.core :refer [env]]
|
||||
[ring.adapter.jetty :refer [run-jetty]])
|
||||
@@ -15,5 +16,6 @@
|
||||
(start-server :port 9000 :bind "0.0.0.0" #_#_:handler (cider-nrepl-handler))
|
||||
(let [port (Integer/parseInt (or (env :port) "3000"))]
|
||||
(future (process-all))
|
||||
(future (load-in-memory-cache))
|
||||
#_(future (always-process-sqs))
|
||||
(run-jetty app {:port port :join? false})))
|
||||
|
||||
@@ -157,20 +157,9 @@
|
||||
:as :json}))))
|
||||
|
||||
|
||||
(defn reauthenticate [pa data]
|
||||
(let [cob-session (login-cobrand)
|
||||
user-session (login-user cob-session)
|
||||
batch-size 100]
|
||||
|
||||
(-> (str (:yodlee-base-url env) "/providerAccounts?providerAccountIds=" pa)
|
||||
|
||||
(client/put {:headers (merge base-headers {"Authorization" (auth-header cob-session user-session)})
|
||||
:body (json/write-str data)
|
||||
:as :json}))))
|
||||
|
||||
(defn update-yodlee [id]
|
||||
(update-provider-account id)
|
||||
(get-provider-account id))
|
||||
|
||||
(defn get-specific-transactions [account]
|
||||
(let [cob-session (login-cobrand)
|
||||
@@ -255,6 +244,41 @@
|
||||
(update-in provider-accounts [(:providerAccountId a) :accounts] conj a)) provider-accounts)
|
||||
vals)))
|
||||
|
||||
(defonce in-memory-cache (atom []))
|
||||
|
||||
(defn load-in-memory-cache []
|
||||
(future
|
||||
(loop []
|
||||
(try
|
||||
(reset! in-memory-cache (get-provider-accounts-with-accounts))
|
||||
(catch Exception e
|
||||
(println e)))
|
||||
(Thread/sleep (* 60 * 1000 * 5))
|
||||
(recur))))
|
||||
|
||||
(defn refresh-provider-account [id]
|
||||
(swap! in-memory-cache
|
||||
(fn [i]
|
||||
(-> (by :id i)
|
||||
(update id merge (get-provider-account-detail id))
|
||||
vals))))
|
||||
|
||||
(defn update-yodlee [id]
|
||||
(update-provider-account id)
|
||||
(refresh-provider-account id)
|
||||
)
|
||||
|
||||
(defn reauthenticate [pa data]
|
||||
(let [cob-session (login-cobrand)
|
||||
user-session (login-user cob-session)
|
||||
batch-size 100]
|
||||
|
||||
(-> (str (:yodlee-base-url env) "/providerAccounts?providerAccountIds=" pa)
|
||||
|
||||
(client/put {:headers (merge base-headers {"Authorization" (auth-header cob-session user-session)})
|
||||
:body (json/write-str data)
|
||||
:as :json}))
|
||||
(refresh-provider-account pa)))
|
||||
#_(defn get-users []
|
||||
(let [cob-session (login-cobrand)]
|
||||
(-> "https://developer.api.yodlee.com/ysl/user"
|
||||
|
||||
@@ -224,8 +224,6 @@
|
||||
|
||||
txes (transduce
|
||||
(comp
|
||||
|
||||
|
||||
(mapcat (fn parse-map [[account account-name override-name _ type]]
|
||||
(let [code (some-> account
|
||||
not-empty
|
||||
@@ -277,3 +275,28 @@
|
||||
[{:db/id [:client/code client-code]
|
||||
:client/signature-file (str "https://s3.amazonaws.com/integreat-signature-images/" filename)}]))
|
||||
|
||||
|
||||
(defn fix-transactions-without-locations [client-code location]
|
||||
(->>
|
||||
(d/query {:query {:find ['(pull ?e [*])]
|
||||
:in ['$ '?client-code]
|
||||
:where ['[?e :transaction/accounts ?ta]
|
||||
'[?e :transaction/matched-rule]
|
||||
'[?e :transaction/approval-status :transaction-approval-status/approved]
|
||||
'(not [?ta :transaction-account/location])
|
||||
'[?e :transaction/client ?c]
|
||||
'[?c :client/code ?client-code]
|
||||
]}
|
||||
:args [(d/db (d/connect uri)) client-code]})
|
||||
(mapcat
|
||||
(fn [[{:transaction/keys [accounts]}]]
|
||||
(mapv
|
||||
(fn [a]
|
||||
{:db/id (:db/id a)
|
||||
:transaction-account/location location}
|
||||
)
|
||||
accounts)
|
||||
)
|
||||
)
|
||||
vec))
|
||||
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
|
||||
|
||||
(s/def ::account map?)
|
||||
(s/def ::location (s/and string?
|
||||
not-empty))
|
||||
|
||||
(s/def ::transaction-rule-account (s/keys :req-un [::account]
|
||||
(s/def ::transaction-rule-account (s/keys :req-un [::account
|
||||
::location]
|
||||
:opt-un []))
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
|
||||
|
||||
(defn vertical-form [{:keys [can-submit id change-event submit-event ]}]
|
||||
{:form ^{:key "form"}
|
||||
{:form
|
||||
(fn [{:keys [title] :as params} & children]
|
||||
(let [{:keys [data active? error]} @(re-frame/subscribe [::form id])
|
||||
can-submit @(re-frame/subscribe can-submit)]
|
||||
@@ -157,6 +157,20 @@
|
||||
[:h1.title.is-2 title]
|
||||
[:<>
|
||||
children]]))
|
||||
|
||||
:form-inline
|
||||
(fn [{:keys [title] :as params} children]
|
||||
(let [{:keys [data active? error]} @(re-frame/subscribe [::form id])
|
||||
can-submit @(re-frame/subscribe can-submit)]
|
||||
|
||||
[:form { :on-submit (fn [e]
|
||||
(when (.-stopPropagation e)
|
||||
(.stopPropagation e)
|
||||
(.preventDefault e))
|
||||
(when can-submit
|
||||
(re-frame/dispatch-sync (vec (conj submit-event params)))))}
|
||||
[:h1.title.is-2 title]
|
||||
children]))
|
||||
:raw-field (fn [control]
|
||||
(let [{:keys [data]} @(re-frame/subscribe [::form id])]
|
||||
[bind-field (-> control
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
[clojure.string :as str]))
|
||||
|
||||
(defn get-valid-matches [matches not-found-description not-found-value text]
|
||||
(let [valid-matches (take 5 (for [[[id t :as match] i] (map vector matches (range))
|
||||
(let [valid-matches (take 15 (for [[[id t :as match] i] (map vector matches (range))
|
||||
:when (str/includes? (or (some-> t .toLowerCase) "") (or (some-> text .toLowerCase) ""))]
|
||||
match))
|
||||
valid-matches (if (and not-found-description text)
|
||||
@@ -111,10 +111,14 @@
|
||||
nil)]))})))
|
||||
|
||||
(defn get-valid-entity-matches [matches not-found-description not-found-value text match->text]
|
||||
(let [valid-matches (take 5 (for [[match i] (map vector matches (range))
|
||||
:let [t (match->text match)]
|
||||
:when (str/includes? (or (some-> t .toLowerCase) "") (or (some-> text .toLowerCase) ""))]
|
||||
match))
|
||||
(let [valid-matches (->> (for [[match i] (map vector matches (range))
|
||||
:let [t (match->text match)
|
||||
match-index (str/index-of (or (some-> t .toLowerCase) "") (or (some-> text .toLowerCase) ""))]
|
||||
:when match-index]
|
||||
[match match-index ])
|
||||
(sort-by second)
|
||||
(map first)
|
||||
(take 10))
|
||||
valid-matches (if (and not-found-description text)
|
||||
(concat valid-matches [[:not-found (not-found-description text) (not-found-value text)]])
|
||||
valid-matches)]
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
[reagent.core :as reagent]
|
||||
[clojure.string :as str]
|
||||
[cljs-time.format :as f]
|
||||
[cljs-time.core :as time]
|
||||
[auto-ap.subs :as subs]
|
||||
[auto-ap.events.admin.clients :as events]
|
||||
[auto-ap.entities.clients :as entity]
|
||||
@@ -70,8 +71,9 @@
|
||||
(fn [{:keys [db]} _]
|
||||
{:db (-> db
|
||||
(assoc ::yodlee {:provider-accounts-loading? true})
|
||||
#_(assoc ::provider-accounts [])
|
||||
#_(assoc ::provider-accounts-loading? true))
|
||||
(assoc ::save-error nil)
|
||||
(assoc ::provider-accounts [])
|
||||
(assoc ::provider-accounts-loading? true))
|
||||
:http {:token (:user db)
|
||||
:method :get
|
||||
:headers {"Content-Type" "application/edn"}
|
||||
@@ -121,7 +123,7 @@
|
||||
(re-frame/reg-event-fx
|
||||
::save-error
|
||||
(fn [{:keys [db]} [_ authentication]]
|
||||
{:dispatch [::mounted]}))
|
||||
{:db (assoc :db ::load-error "error")}))
|
||||
|
||||
(defn yodlee-link-button []
|
||||
[:div
|
||||
@@ -149,6 +151,14 @@
|
||||
|
||||
[:button.button.is-primary {:class (if loading? "is-loading" "") :on-click (dispatch-event [::authenticate-with-yodlee])} "Authenticate with Yodlee"]))])
|
||||
|
||||
(defn yodlee-date->date [d]
|
||||
(try
|
||||
(some-> d
|
||||
(str->date (:date-time-no-ms f/formatters))
|
||||
)
|
||||
(catch js/Error e
|
||||
nil)))
|
||||
|
||||
(defn yodlee-date->str [d]
|
||||
(try
|
||||
(or (some-> d
|
||||
@@ -209,11 +219,16 @@
|
||||
:uri (str "/api/yodlee/reauthenticate/" provider-account-id )
|
||||
:body {"loginForm"
|
||||
{"row"
|
||||
[{"field"
|
||||
(mapv (fn [[k v]]
|
||||
{"id" k
|
||||
"value" v})
|
||||
(:data (get-in db [::forms/forms [::login-form provider-account-id]])))}]}}
|
||||
(->> (get-in db [::forms/forms [::login-form provider-account-id]])
|
||||
:data
|
||||
(sort-by (fn [[k v]] k))
|
||||
(map second)
|
||||
(map (fn [row]
|
||||
{"field"
|
||||
(mapv (fn [[k v]]
|
||||
{"id" k
|
||||
"value" v})
|
||||
row)})))}}
|
||||
|
||||
:on-success [::authenticated]
|
||||
:on-error [::forms/save-error [::login-form provider-account-id]]}}))
|
||||
@@ -233,57 +248,73 @@
|
||||
[:div.card-header-title "Provider account " (:id account)
|
||||
]]
|
||||
[:div.card-content
|
||||
[:div.notification.is-info.is-light
|
||||
[:div.level
|
||||
[:div.level-left
|
||||
[:div.level-item
|
||||
[:p
|
||||
"This account was last updated on "
|
||||
(yodlee-date->str (-> account :dataset first :lastUpdated))
|
||||
", and last attempted "
|
||||
(yodlee-date->str (-> account :dataset first :lastUpdateAttempt))
|
||||
"."]]]
|
||||
[:div.level-right [:button.button.is-success {:on-click (dispatch-event [::kick (:id account)] )} "Force refresh" ]]]
|
||||
|
||||
]
|
||||
[:div.notification.is-info.is-warning
|
||||
[:div.level
|
||||
[:div.level-left
|
||||
[:div.level-item
|
||||
"This provider account's status is '"
|
||||
(-> account :dataset first :additionalStatus)
|
||||
"'. If this is in error, it might help to try reauthenticating by filling out the form below."]]]]
|
||||
(if (> (some-> (-> account :dataset first :lastUpdated)
|
||||
(yodlee-date->date )
|
||||
(time/interval (time/now))
|
||||
(time/in-days ))
|
||||
1)
|
||||
[:div.notification.is-info.is-light
|
||||
[:div.level
|
||||
[:div.level-left
|
||||
[:div.level-item
|
||||
[:p
|
||||
"This account was last updated on "
|
||||
(yodlee-date->str (-> account :dataset first :lastUpdated))
|
||||
", and last attempted "
|
||||
(yodlee-date->str (-> account :dataset first :lastUpdateAttempt))
|
||||
"."]]]
|
||||
[:div.level-right [:button.button.is-success {:on-click (dispatch-event [::kick (:id account)] )} "Force refresh" ]]]
|
||||
|
||||
])
|
||||
|
||||
|
||||
[yodlee-accounts-table (:accounts account)]
|
||||
[:div
|
||||
(if (:field account)
|
||||
(for [f (:field account)]
|
||||
(let [{error :error account-data :data } @(re-frame/subscribe [::forms/form [::mfa-form (:id account)]])
|
||||
change-event [::forms/change [::mfa-form (:id account)]]
|
||||
{:keys [form field field-holder raw-field error-notification submit-button]} (forms/vertical-form {:can-submit [::can-submit]
|
||||
:change-event change-event
|
||||
:submit-event [::reauthenticate-mfa (:id account)]
|
||||
:id [::mfa-form (:id account)]} )]
|
||||
(form {:title "Reauthenticate (login)"}
|
||||
(if (not= (-> account :dataset first :additionalStatus)
|
||||
"AVAILABLE_DATA_RETRIEVED")
|
||||
[:div
|
||||
[:div.notification.is-info.is-warning
|
||||
[:div.level
|
||||
[:div.level-left
|
||||
[:div.level-item
|
||||
"This provider account's status is '"
|
||||
(-> account :dataset first :additionalStatus)
|
||||
"'. If this is in error, it might help to try reauthenticating by filling out the form below."]]]]
|
||||
(if (:field account)
|
||||
(for [f (:field account)]
|
||||
(let [{error :error account-data :data } @(re-frame/subscribe [::forms/form [::mfa-form (:id account)]])
|
||||
change-event [::forms/change [::mfa-form (:id account)]]
|
||||
{:keys [form-inline field field-holder raw-field error-notification submit-button]} (forms/vertical-form {:can-submit [::can-submit]
|
||||
:change-event change-event
|
||||
:submit-event [::reauthenticate-mfa (:id account)]
|
||||
:id [::mfa-form (:id account)]} )]
|
||||
(form-inline {:title "Reauthenticate (mfa)"}
|
||||
[:<>
|
||||
(error-notification)
|
||||
(doall
|
||||
(for [f (-> account :field)]
|
||||
^{:key (:id f)}
|
||||
(field (:label f)
|
||||
[:input.input {:type "text" :field [(:id f)] :value (-> f :field first :value)}])))
|
||||
(submit-button "Reauthenticate")])))
|
||||
(let [{error :error account-data :data } @(re-frame/subscribe [::forms/form [::login-form (:id account)]])
|
||||
change-event [::forms/change [::login-form (:id account)]]
|
||||
{:keys [form-inline field field-holder raw-field error-notification submit-button]} (forms/vertical-form {:can-submit [::can-submit]
|
||||
:change-event change-event
|
||||
:submit-event [::reauthenticate (:id account)]
|
||||
:id [::login-form (:id account)]} )]
|
||||
(form-inline {:title "Reauthenticate (login)"}
|
||||
[:<>
|
||||
|
||||
(error-notification)
|
||||
(for [f (-> account :field)]
|
||||
^{:key (:id f)}
|
||||
(field (:label f)
|
||||
[:input.input {:type "text" :field [(:id f)] :value (-> f :field first :value)}]))
|
||||
(submit-button "Reauthenticate"))))
|
||||
(let [{error :error account-data :data } @(re-frame/subscribe [::forms/form [::login-form (:id account)]])
|
||||
change-event [::forms/change [::login-form (:id account)]]
|
||||
{:keys [form field field-holder raw-field error-notification submit-button]} (forms/vertical-form {:can-submit [::can-submit]
|
||||
:change-event change-event
|
||||
:submit-event [::reauthenticate (:id account)]
|
||||
:id [::login-form (:id account)]} )]
|
||||
(form {:title "Reauthenticate (MFA)"}
|
||||
(error-notification)
|
||||
(for [f (-> account :loginForm first :row)]
|
||||
^{:key (:id f)}
|
||||
(field (:label f)
|
||||
[:input.input {:type "text" :field [(:id f)] :value (-> f :field first :value)}]))
|
||||
(submit-button "Reauthenticate"))))]]]))]]))
|
||||
(doall
|
||||
(for [[row i] (map vector (-> account :loginForm last :row) (range))
|
||||
f (:field row)]
|
||||
^{:key (:id f)}
|
||||
[:div
|
||||
(field (:label row)
|
||||
[:input.input {:type "text" :field [i (:id f)]}])]))
|
||||
(submit-button "Reauthenticate")])))])]]))]]))
|
||||
|
||||
|
||||
(defn admin-yodlee-content []
|
||||
|
||||
@@ -184,7 +184,6 @@
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::succeeded
|
||||
[(forms/triggers-stop ::form)]
|
||||
(fn [{:keys [db]} [_ {:keys [invoice-created invoice-printed]} command result]]
|
||||
(let [invoice (condp = command
|
||||
:edit (:edit-invoice result)
|
||||
@@ -192,11 +191,13 @@
|
||||
:create (:add-invoice result)
|
||||
|
||||
:add-and-print (first (:invoices (:add-and-print-invoice result))))]
|
||||
|
||||
|
||||
{:db (cond-> db
|
||||
(#{:create :add-and-print} command) (forms/start-form ::form {:client @(re-frame/subscribe [::subs/client])
|
||||
:status :unpaid
|
||||
:date (date->str (c/now) standard)}))
|
||||
:date (date->str (c/now) standard)})
|
||||
(= :edit command) (forms/stop-form ::form))
|
||||
:dispatch-n (cond-> [(conj invoice-created invoice)]
|
||||
(= :add-and-print command) (conj (conj invoice-printed (:pdf-url (:add-and-print-invoice result)))))})))
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
(ns auto-ap.views.pages.ledger.profit-and-loss
|
||||
(:require [auto-ap.subs :as subs]
|
||||
[auto-ap.views.components.layouts :refer [side-bar-layout appearing-side-bar]]
|
||||
[auto-ap.views.pages.ledger.table :refer [table]]
|
||||
[auto-ap.views.pages.ledger.table :as ledger-table ]
|
||||
[vimsical.re-frame.cofx.inject :as inject]
|
||||
[goog.string :as gstring]
|
||||
[auto-ap.utils :refer [dollars-0? by ]]
|
||||
[auto-ap.views.pages.ledger.side-bar :refer [ledger-side-bar]]
|
||||
[auto-ap.views.utils :refer [date->str date-picker bind-field standard dispatch-event local-now ->% ->$ str->date]]
|
||||
[auto-ap.views.utils :refer [date->str date-picker bind-field standard dispatch-event local-now ->% ->$ str->date with-user]]
|
||||
[cljs-time.core :as t]
|
||||
[re-frame.core :as re-frame]))
|
||||
(def ranges
|
||||
@@ -67,9 +68,29 @@
|
||||
(-> db ::ledger-list :ledger-page)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::ledger-params
|
||||
::last-ledger-params
|
||||
(fn [db]
|
||||
(-> db (::ledger-params {}) )))
|
||||
(-> db ::last-ledger-params )))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::investigate-ledger-params
|
||||
(fn [db]
|
||||
(-> db ::investigate-ledger-params )))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::ledger-params
|
||||
:<- [::last-ledger-params]
|
||||
:<- [::subs/client]
|
||||
:<- [::ledger-table/table-params]
|
||||
:<- [::investigate-ledger-params]
|
||||
(fn [[last-params client table-params investigate-ledger-params]]
|
||||
(let [params (cond-> {}
|
||||
client (assoc :client-id (:id client))
|
||||
(seq table-params) (merge table-params)
|
||||
(seq investigate-ledger-params) (merge investigate-ledger-params))]
|
||||
(when (not= params last-params)
|
||||
(re-frame/dispatch [::ledger-params-changed]))
|
||||
params)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::accounts
|
||||
@@ -200,6 +221,8 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::date-picked
|
||||
(fn [cofx [_ f date]]
|
||||
@@ -218,14 +241,15 @@
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::ledger-params-changed
|
||||
(fn [{:keys [db]} [_ params]]
|
||||
[with-user (re-frame/inject-cofx ::inject/sub [::ledger-params])]
|
||||
(fn [{:keys [user ::ledger-params db]} [_ ]]
|
||||
|
||||
{:db (assoc db
|
||||
::ledger-list-loading true
|
||||
::ledger-params params)
|
||||
:graphql {:token (-> db :user)
|
||||
::last-ledger-params ledger-params)
|
||||
:graphql {:token user
|
||||
:query-obj {:venia/queries [[:ledger-page
|
||||
params
|
||||
ledger-params
|
||||
[[:journal-entries [:id
|
||||
:source
|
||||
:amount
|
||||
@@ -242,26 +266,25 @@
|
||||
:end]]]}
|
||||
:on-success [::ledger-list-received]}}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
(re-frame/reg-event-db
|
||||
::investigate-clicked
|
||||
(fn [{:keys [db] } [_ location from-numeric-code to-numeric-code which]]
|
||||
{:db (assoc db
|
||||
::ledger-list-active? true
|
||||
::ledger-list-loading true)
|
||||
|
||||
:dispatch [::ledger-params-changed (assoc (::ledger-params db)
|
||||
:client-id (:id @(re-frame/subscribe [::subs/client]))
|
||||
:from-numeric-code from-numeric-code
|
||||
:to-numeric-code to-numeric-code
|
||||
:location location
|
||||
:date-range {:start (if (= :current which)
|
||||
(:from-date (::params db))
|
||||
(date->str (t/minus (str->date (:from-date (::params db)) standard) (t/years 1))
|
||||
standard))
|
||||
:end (if (= :current which)
|
||||
(:to-date (::params db))
|
||||
(date->str (t/minus (str->date (:to-date (::params db)) standard) (t/years 1))
|
||||
standard))})]}))
|
||||
(fn [db [_ location from-numeric-code to-numeric-code which]]
|
||||
(-> db
|
||||
(assoc
|
||||
::ledger-list-active? true
|
||||
::ledger-list-loading true
|
||||
::investigate-ledger-params {:client-id (:id @(re-frame/subscribe [::subs/client]))
|
||||
:from-numeric-code from-numeric-code
|
||||
:to-numeric-code to-numeric-code
|
||||
:location location
|
||||
:date-range {:start (if (= :current which)
|
||||
(:from-date (::params db))
|
||||
(date->str (t/minus (str->date (:from-date (::params db)) standard) (t/years 1))
|
||||
standard))
|
||||
:end (if (= :current which)
|
||||
(:to-date (::params db))
|
||||
(date->str (t/minus (str->date (:to-date (::params db)) standard) (t/years 1))
|
||||
standard))}}))))
|
||||
|
||||
(def groupings
|
||||
{:sales [["40000-43999 Food Sales " 40000 43999]
|
||||
@@ -625,17 +648,18 @@
|
||||
[:div [:a.delete.is-pulled-right {:on-click (dispatch-event [::ledger-list-closing])}]
|
||||
[:div
|
||||
[:h1.title "Ledger entries"]
|
||||
[table {:id :ledger
|
||||
:ledger-page ledger-page
|
||||
:status? false
|
||||
:status (re-frame/subscribe [::ledger-list-loading])
|
||||
:params (re-frame/subscribe [::ledger-params])
|
||||
:on-params-change (fn [params]
|
||||
(re-frame/dispatch [::ledger-params-changed params]))}]]]))
|
||||
[ledger-table/table {:id :ledger
|
||||
:ledger-page ledger-page
|
||||
:status? false
|
||||
:status (re-frame/subscribe [::ledger-list-loading])
|
||||
:params (re-frame/subscribe [::ledger-params])
|
||||
:on-params-change (fn [params]
|
||||
(re-frame/dispatch [::ledger-params-changed params]))}]]]))
|
||||
|
||||
(defn profit-and-loss-page []
|
||||
(let [ledger-list-active? @(re-frame/subscribe [::ledger-list-active?])
|
||||
user (re-frame/subscribe [::subs/user])]
|
||||
user (re-frame/subscribe [::subs/user])
|
||||
ledger-params @(re-frame/subscribe [::ledger-params])]
|
||||
(if (not= "manager" (:user/role @user))
|
||||
[side-bar-layout
|
||||
{:side-bar [ledger-side-bar]
|
||||
|
||||
@@ -216,22 +216,23 @@
|
||||
:field [:description-original]
|
||||
:disabled "disabled"}]]
|
||||
|
||||
(when (and (seq (:potential-transaction-rule-matches data))
|
||||
(not (:matched-rule data))
|
||||
(not (:payment data))
|
||||
is-admin?)
|
||||
(cond
|
||||
(and (seq (:potential-transaction-rule-matches data))
|
||||
(not (:matched-rule data))
|
||||
(not (:payment data))
|
||||
is-admin?)
|
||||
[potential-transaction-rule-matches-box {:potential-transaction-rule-matches (:potential-transaction-rule-matches data)
|
||||
:edit-completed edit-completed}])
|
||||
:edit-completed edit-completed}]
|
||||
|
||||
|
||||
(when (and (seq (:potential-payment-matches data))
|
||||
(not (:payment data))
|
||||
is-admin?)
|
||||
(and (seq (:potential-payment-matches data))
|
||||
(not (:payment data))
|
||||
is-admin?)
|
||||
[potential-payment-matches-box {:potential-payment-matches (:potential-payment-matches data)
|
||||
:edit-completed edit-completed}])
|
||||
:edit-completed edit-completed}]
|
||||
|
||||
(when (and (not (seq (:potential-payment-matches data)))
|
||||
(not (seq (:potential-transaction-rule-matches data))))
|
||||
(and (not (seq (:potential-payment-matches data)))
|
||||
(not (seq (:potential-transaction-rule-matches data))))
|
||||
[:div
|
||||
[field "Vendor"
|
||||
[typeahead-entity {:matches @(re-frame/subscribe [::subs/vendors])
|
||||
@@ -274,4 +275,30 @@
|
||||
|
||||
[error-notification]
|
||||
(when-not should-disable-for-client?
|
||||
[submit-button "Save"])])])])
|
||||
[submit-button "Save"])]
|
||||
|
||||
:else
|
||||
|
||||
[:div
|
||||
[field "Approval Status"
|
||||
[button-radio
|
||||
{:type "button-radio"
|
||||
:field [:approval-status]
|
||||
:options [[:unapproved "Unapproved"]
|
||||
[:requires-feedback "Client Review"]
|
||||
[:approved "Approved"]
|
||||
[:excluded "Excluded from Ledger"]]
|
||||
:disabled should-disable-for-client?}]]
|
||||
|
||||
[field "Forecasted-transaction"
|
||||
[typeahead-entity {:matches (doto @(re-frame/subscribe [::subs/forecasted-transactions-for-client (:id (:client data))]) println)
|
||||
:match->text :identifier
|
||||
:type "typeahead-entity"
|
||||
:field [:forecast-match]}]]
|
||||
|
||||
[:hr]
|
||||
|
||||
[error-notification]
|
||||
(when-not should-disable-for-client?
|
||||
[submit-button "Save"])]
|
||||
)])])
|
||||
|
||||
Reference in New Issue
Block a user