fixes for some issues found

This commit is contained in:
Bryce Covert
2021-01-04 18:57:52 -08:00
parent 65db253593
commit 0f7a5c1f00
5 changed files with 115 additions and 113 deletions

View File

@@ -41,11 +41,14 @@
:iso_date {:parse #(time/parse % time/iso-date) :iso_date {:parse #(time/parse % time/iso-date)
:serialize #(time/unparse % time/iso-date)} :serialize #(time/unparse % time/iso-date)}
:money {:parse #(do :money {:parse #(do
(log/info "parsing money...")
(cond (and (string? %) (cond (and (string? %)
(not (str/blank? %))) (not (str/blank? %)))
(Double/parseDouble %) (Double/parseDouble %)
(and (string? %)
(str/blank? %))
0.0
(int? %) (int? %)
(double %) (double %)
@@ -681,14 +684,14 @@
:import_ledger_line_item {:fields {:account_identifier {:type 'String} :import_ledger_line_item {:fields {:account_identifier {:type 'String}
:location {:type 'String} :location {:type 'String}
:debit {:type 'String} :debit {:type :money}
:credit {:type 'String}}} :credit {:type :money}}}
:import_ledger_entry {:fields {:source {:type 'String} :import_ledger_entry {:fields {:source {:type 'String}
:external_id {:type 'String} :external_id {:type 'String}
:client_code {:type 'String} :client_code {:type 'String}
:date {:type 'String} :date {:type 'String}
:vendor_name {:type 'String} :vendor_name {:type 'String}
:amount {:type 'String} :amount {:type :money}
:note {:type 'String} :note {:type 'String}
:cleared_against {:type 'String} :cleared_against {:type 'String}
:line_items {:type '(list :import_ledger_line_item)}}} :line_items {:type '(list :import_ledger_line_item)}}}

View File

@@ -204,6 +204,7 @@
(try (try
(f entry) (f entry)
(catch Exception e (catch Exception e
(log/warn e)
(assoc entry :error (.getMessage e) (assoc entry :error (.getMessage e)
:status (or (:status (ex-data e)) :status (or (:status (ex-data e))
:error)))))) :error))))))
@@ -267,100 +268,90 @@
all-accounts (transduce (map (comp str :account/numeric-code)) conj #{} (a/get-accounts)) all-accounts (transduce (map (comp str :account/numeric-code)) conj #{} (a/get-accounts))
transaction (doall (map transaction (doall (map
(assoc-error (fn [entry] (assoc-error (fn [entry]
(let [entry (-> entry (let [vendor (all-vendors (:vendor_name entry))]
(update :amount #(Double/parseDouble %)) (when-not (all-clients (:client_code entry))
(update :line_items (throw (ex-info (str "Client '" (:client_code entry )"' not found.") {:status :error}) ))
(fn [lis] (when-not vendor
(mapv (throw (ex-info (str "Vendor '" (:vendor_name entry) "' not found.") {:status :error})))
(fn [li ] (when-not (re-find #"\d{1,2}/\d{1,2}/\d{4}" (:date entry))
(-> li (throw (ex-info (str "Date must be MM/dd/yyyy") {:status :error})))
(update :debit #(Double/parseDouble (if (str/blank? %) "0" %))) (when-not (dollars= (reduce + 0.0 (map :debit (:line_items entry)))
(update :credit #(Double/parseDouble (if (str/blank? %) "0" %))))) (reduce + 0.0 (map :credit (:line_items entry))))
lis))))] (throw (ex-info (str "Debits '"
(let [vendor (all-vendors (:vendor_name entry))] (reduce + 0 (map :debit (:line_items entry)))
(when-not (all-clients (:client_code entry)) "' and credits '"
(throw (ex-info (str "Client '" (:client_code entry )"' not found.") {:status :error}) )) (reduce + 0 (map :credit (:line_items entry)))
(when-not vendor "' do not add up.")
(throw (ex-info (str "Vendor '" (:vendor_name entry) "' not found.") {:status :error}))) {:status :error})))
(when-not (re-find #"\d{1,2}/\d{1,2}/\d{4}" (:date entry)) (when (dollars= (reduce + 0.0 (map :debit (:line_items entry)))
(throw (ex-info (str "Date must be MM/dd/yyyy") {:status :error}))) 0.0)
(when-not (dollars= (reduce + 0.0 (map :debit (:line_items entry))) (throw (ex-info (str "Cannot have ledger entries that total $0.00")
(reduce + 0.0 (map :credit (:line_items entry)))) {:status :ignored})))
(throw (ex-info (str "Debits '" (assoc entry
(reduce + 0 (map :debit (:line_items entry))) :status :success
"' and credits '" :tx
(reduce + 0 (map :credit (:line_items entry))) (remove-nils
"' do not add up.") {:journal-entry/source (:source entry)
{:status :error}))) :journal-entry/client [:client/code (:client_code entry)]
(when (dollars= (reduce + 0.0 (map :debit (:line_items entry))) :journal-entry/date (coerce/to-date (parse/parse-value :clj-time "MM/dd/yyyy" (:date entry)))
0.0) :journal-entry/external-id (:external_id entry)
(throw (ex-info (str "Cannot have ledger entries that total $0.00") :journal-entry/vendor (:db/id (all-vendors (:vendor_name entry)))
{:status :ignored}))) :journal-entry/amount (:amount entry)
(assoc entry :journal-entry/note (:note entry)
:status :success :journal-entry/cleared-against (:cleared_against entry)
:tx
(remove-nils
{:journal-entry/source (:source entry)
:journal-entry/client [:client/code (:client_code entry)]
:journal-entry/date (coerce/to-date (parse/parse-value :clj-time "MM/dd/yyyy" (:date entry)))
:journal-entry/external-id (:external_id entry)
:journal-entry/vendor (:db/id (all-vendors (:vendor_name entry)))
:journal-entry/amount (:amount entry)
:journal-entry/note (:note entry)
:journal-entry/cleared-against (:cleared_against entry)
:journal-entry/line-items :journal-entry/line-items
(mapv (fn [ea] (mapv (fn [ea]
(when (and (not (get (when (and (not (get
(get all-client-locations (:client_code entry)) (get all-client-locations (:client_code entry))
(:location ea)))
(not= "A" (:location ea)))
(throw (ex-info (str "Location '" (:location ea) "' not found.")
{:status :error})))
(when (and (<= (:debit ea 0.0) 0.0)
(<= (:credit ea 0.0) 0.0))
(throw (ex-info (str "Line item amount " (or (:debit ea) (:credit ea)) " must be greater than 0.")
{:status :error})))
(when (and (not (all-accounts (:account_identifier ea)))
(not (get
(get all-client-bank-accounts (:client_code entry))
(:account_identifier ea))))
(throw (ex-info (str "Account '" (:account_identifier ea) "' not found.")
{:status :error})))
(let [matching-account (when (re-matches #"^[0-9]+$" (:account_identifier ea))
(a/get-account-by-numeric-code-and-sets (Integer/parseInt (:account_identifier ea)) ["default"]))]
(when (and matching-account
(:account/location matching-account)
(not= (:account/location matching-account)
(:location ea))) (:location ea)))
(not= "A" (:location ea))) (throw (ex-info (str "Account '"
(throw (ex-info (str "Location '" (:location ea) "' not found.") (:account/numeric-code matching-account)
"' requires location '"
(:account/location matching-account)
"' but got '"
(:location ea)
"'")
{:status :error}))) {:status :error})))
(when (and (<= (:debit ea 0.0) 0.0)
(<= (:credit ea 0.0) 0.0))
(throw (ex-info (str "Line item amount " (or (:debit ea) (:credit ea)) " must be greater than 0.")
{:status :error})))
(when (and (not (all-accounts (:account_identifier ea)))
(not (get
(get all-client-bank-accounts (:client_code entry))
(:account_identifier ea))))
(throw (ex-info (str "Account '" (:account_identifier ea) "' not found.")
{:status :error})))
(let [matching-account (when (re-matches #"^[0-9]+$" (:account_identifier ea))
(a/get-account-by-numeric-code-and-sets (Integer/parseInt (:account_identifier ea)) ["default"]))]
(when (and matching-account
(:account/location matching-account)
(not= (:account/location matching-account)
(:location ea)))
(throw (ex-info (str "Account '"
(:account/numeric-code matching-account)
"' requires location '"
(:account/location matching-account)
"' but got '"
(:location ea)
"'")
{:status :error})))
(when (and matching-account (when (and matching-account
(not (:account/location matching-account)) (not (:account/location matching-account))
(= "A" (:location ea))) (= "A" (:location ea)))
(throw (ex-info (str "Account '" (throw (ex-info (str "Account '"
(:account/numeric-code matching-account) (:account/numeric-code matching-account)
"' cannot use location '" "' cannot use location '"
(:location ea) (:location ea)
"'") "'")
{:status :error}))) {:status :error})))
(remove-nils (cond-> {:journal-entry-line/location (:location ea) (remove-nils (cond-> {:journal-entry-line/location (:location ea)
:journal-entry-line/debit (when (> (:debit ea) 0) :journal-entry-line/debit (when (> (:debit ea) 0)
(:debit ea)) (:debit ea))
:journal-entry-line/credit (when (> (:credit ea) 0) :journal-entry-line/credit (when (> (:credit ea) 0)
(:credit ea))} (:credit ea))}
matching-account (assoc :journal-entry-line/account (:db/id matching-account)) matching-account (assoc :journal-entry-line/account (:db/id matching-account))
(not matching-account) (assoc :journal-entry-line/account [:bank-account/code (:account_identifier ea)]))))) (not matching-account) (assoc :journal-entry-line/account [:bank-account/code (:account_identifier ea)])))))
(:line_items entry)) (:line_items entry))
:journal-entry/cleared true})))))) :journal-entry/cleared true})))))
(:entries args))) (:entries args)))
errors (filter #(= (:status %) :error) transaction) errors (filter #(= (:status %) :error) transaction)
ignored (filter #(= (:status %) :ignored) transaction) ignored (filter #(= (:status %) :ignored) transaction)

View File

@@ -12,7 +12,7 @@
(defn make-api-token [] (defn make-api-token []
(jwt/sign {:user "API" (jwt/sign {:user "API"
:exp (time/plus (time/now) (time/days 700)) :exp (time/plus (time/now) (time/days 1000))
:user/role "admin" :user/role "admin"
:user/name "API"} :user/name "API"}
(:jwt-secret env) (:jwt-secret env)

View File

@@ -24,7 +24,7 @@
:location (if (clojure.string/blank? location) :location (if (clojure.string/blank? location)
nil nil
location) location)
:numeric-code numeric-code :numeric-code (js/parseInt numeric-code)
:name name :name name
:account-set account-set :account-set account-set
:client-overrides (map (fn [client-override] :client-overrides (map (fn [client-override]

View File

@@ -11,7 +11,8 @@
[cljs-time.core :as t] [cljs-time.core :as t]
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[reagent.core :as r] [reagent.core :as r]
[clojure.string :as str])) [clojure.string :as str]
[auto-ap.status :as status]))
@@ -63,7 +64,8 @@
(let [successful-set (set (map :external-id (:successful (:import-ledger result)))) (let [successful-set (set (map :external-id (:successful (:import-ledger result))))
error-set (into {} (map (juxt :external-id :error) (:errors (:import-ledger result)))) error-set (into {} (map (juxt :external-id :error) (:errors (:import-ledger result))))
existing-set (set (map :external-id (:existing (:import-ledger result)))) existing-set (set (map :external-id (:existing (:import-ledger result))))
ignored-set (set (map :external-id (:ignored (:import-ledger result))))] ignored-set (set (map :external-id (:ignored (:import-ledger result))))
seen-set (atom #{})]
{:db (-> (forms/save-succeeded db ::form ) {:db (-> (forms/save-succeeded db ::form )
(assoc-in [::forms/forms ::form :result] {:errors error-set :success successful-set :existing existing-set :ignored ignored-set}) (assoc-in [::forms/forms ::form :result] {:errors error-set :success successful-set :existing existing-set :ignored ignored-set})
@@ -80,16 +82,19 @@
(existing-set (line->id %)) (existing-set (line->id %))
"" ""
(error-set (line->id %)) (and (error-set (line->id %))
[drop-down {:id [::ledger-import-line (line->id %) ] (not (@seen-set (line->id %))))
:is-right? true (do
:header [:a.button {:aria-haspopup true (swap! seen-set conj (line->id %))
:on-click (dispatch-event [::events/toggle-menu [::ledger-import-line (line->id %)]]) [drop-down {:id [::ledger-import-line (line->id %) ]
:tab-index "0"} :is-right? true
[:span.is-warning.icon {:title (error-set (line->id %))} [:i.fa.fa-exclamation-triangle]]]} :header [:a.button {:aria-haspopup true
[drop-down-contents :on-click (dispatch-event [::events/toggle-menu [::ledger-import-line (line->id %)]])
[:div :tab-index "0"}
[:span.dropdown-item (error-set (line->id %)) ]]]] [:span.is-warning.icon {:title (error-set (line->id %))} [:i.fa.fa-exclamation-triangle]]]}
[drop-down-contents
[:div
[:span.dropdown-item (error-set (line->id %)) ]]]])
) )
:status-category :status-category
(cond (successful-set (line->id %)) (cond (successful-set (line->id %))
@@ -110,9 +115,9 @@
::importing ::importing
(fn [{:keys [db]} _] (fn [{:keys [db]} _]
(when @(re-frame/subscribe [::can-submit]) (when @(re-frame/subscribe [::can-submit])
{:db (forms/loading db ::form ) {:graphql
:graphql
{:token (-> db :user) {:token (-> db :user)
:owns-state {:single ::import}
:query-obj {:venia/operation {:operation/type :mutation :query-obj {:venia/operation {:operation/type :mutation
:operation/name "ImportLedger"} :operation/name "ImportLedger"}
:venia/queries [{:query/data [:import-ledger :venia/queries [{:query/data [:import-ledger
@@ -137,7 +142,7 @@
[:form.form [:form.form
(if value (if value
[:div [:div
[:table.table [:table.table {:style {:width "100%"}}
[:thead [:thead
[:tr [:tr
(list (list
@@ -190,22 +195,25 @@
(fn [] (fn []
(let [current-client @(re-frame/subscribe [::subs/client]) (let [current-client @(re-frame/subscribe [::subs/client])
user @(re-frame/subscribe [::subs/user]) user @(re-frame/subscribe [::subs/user])
status @(re-frame/subscribe [::status/single ::import])
{:keys [data result active? error id]} @(re-frame/subscribe [::forms/form ::form]) ] {:keys [data result active? error id]} @(re-frame/subscribe [::forms/form ::form]) ]
[:div [:div
[:div.level [:div.level
[:div.level-left [:div.level-left
[:h1.title "Eternal Import"]] [:h1.title "Eternal Import"]]
[:div.level-right [:div.level-right
[:button.button.is-primary.is-pulled-right.is-large {:disabled (not data) [:button.button.is-primary.is-pulled-right.is-large {:disabled (not data)
:on-click (dispatch-event [::importing])} "Import"]]] :on-click (dispatch-event [::importing])} "Import"]]]
[status/status-notification {:statuses [[::status/single ::import]]} ]
(when result (when result
[:div.notification [:div.notification
"Imported with " "Imported with "
(count (:errors result)) " errors, " (count (:errors result)) " errors, "
(count (:ignored result)) " ignored, " (count (:ignored result)) " ignored, "
(count (:success result)) " successful."]) (count (:success result)) " successful."])
(if @(re-frame/subscribe [::forms/is-loading? ::form]) (if (= :loading (:state status ))
[:div [:i.icon.fa.fa-spin.fa-spinner]] [status/big-loader status]
[:div [:div
[:div.is-clearfix [:div.is-clearfix
[:div.is-pulled-right [:div.is-pulled-right