tons of bug fixes

This commit is contained in:
Bryce Covert
2020-07-08 21:44:11 -07:00
parent 86f51f93e4
commit d120b7e810
18 changed files with 442 additions and 156 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -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)))

View File

@@ -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)

View File

@@ -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)]))

View File

@@ -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]

View File

@@ -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]

View File

@@ -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)

View File

@@ -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})))

View File

@@ -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"

View File

@@ -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))

View File

@@ -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 []))

View File

@@ -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

View File

@@ -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)]

View File

@@ -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 []

View File

@@ -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)))))})))

View File

@@ -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]

View File

@@ -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"])]
)])])