merged.
This commit is contained in:
@@ -19,7 +19,8 @@
|
|||||||
:vendor-account-override/account [:account/name :account/numeric-code :db/id]}]
|
:vendor-account-override/account [:account/name :account/numeric-code :db/id]}]
|
||||||
:vendor/terms-overrides [* {:vendor-terms-override/client [:client/name :client/code :db/id]}]
|
:vendor/terms-overrides [* {:vendor-terms-override/client [:client/name :client/code :db/id]}]
|
||||||
:vendor/schedule-payment-dom [* {:vendor-schedule-payment-dom/client [:client/name :client/code :db/id]}]
|
:vendor/schedule-payment-dom [* {:vendor-schedule-payment-dom/client [:client/name :client/code :db/id]}]
|
||||||
:vendor/automatically-paid-when-due [:db/id :client/name]}])
|
:vendor/automatically-paid-when-due [:db/id :client/name]
|
||||||
|
:vendor/default-account [:db/id :account/numeric-code :account/name]}])
|
||||||
|
|
||||||
(defn get-usages [args]
|
(defn get-usages [args]
|
||||||
(->> (cond-> {:query {:find ['?v '?c '(count ?e)]
|
(->> (cond-> {:query {:find ['?v '?c '(count ?e)]
|
||||||
|
|||||||
@@ -40,12 +40,17 @@
|
|||||||
:serialize #(or (:ident %) (:db/ident %) %)}
|
:serialize #(or (:ident %) (:db/ident %) %)}
|
||||||
: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 #(cond (and (string? %)
|
:money {:parse #(do
|
||||||
(not (str/blank? %)))
|
(cond (and (string? %)
|
||||||
(Double/parseDouble %)
|
(not (str/blank? %)))
|
||||||
|
(Double/parseDouble %)
|
||||||
|
|
||||||
(int? %)
|
(and (string? %)
|
||||||
(double %)
|
(str/blank? %))
|
||||||
|
0.0
|
||||||
|
|
||||||
|
(int? %)
|
||||||
|
(double %)
|
||||||
|
|
||||||
:else
|
:else
|
||||||
%)
|
%)
|
||||||
|
|||||||
@@ -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,99 +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 :line_items
|
(when-not (all-clients (:client_code entry))
|
||||||
(fn [lis]
|
(throw (ex-info (str "Client '" (:client_code entry )"' not found.") {:status :error}) ))
|
||||||
(mapv
|
(when-not vendor
|
||||||
(fn [li ]
|
(throw (ex-info (str "Vendor '" (:vendor_name entry) "' not found.") {:status :error})))
|
||||||
(-> li
|
(when-not (re-find #"\d{1,2}/\d{1,2}/\d{4}" (:date entry))
|
||||||
(update :debit (fnil identity 0.0))
|
(throw (ex-info (str "Date must be MM/dd/yyyy") {:status :error})))
|
||||||
(update :credit (fnil identity 0.0))))
|
(when-not (dollars= (reduce + 0.0 (map :debit (:line_items entry)))
|
||||||
lis))))]
|
(reduce + 0.0 (map :credit (:line_items entry))))
|
||||||
(let [vendor (all-vendors (:vendor_name entry))]
|
(throw (ex-info (str "Debits '"
|
||||||
(when-not (all-clients (:client_code entry))
|
(reduce + 0 (map :debit (:line_items entry)))
|
||||||
(throw (ex-info (str "Client '" (:client_code entry )"' not found.") {:status :error}) ))
|
"' and credits '"
|
||||||
(when-not vendor
|
(reduce + 0 (map :credit (:line_items entry)))
|
||||||
(throw (ex-info (str "Vendor '" (:vendor_name entry) "' not found.") {:status :error})))
|
"' do not add up.")
|
||||||
(when-not (re-find #"\d{1,2}/\d{1,2}/\d{4}" (:date entry))
|
{:status :error})))
|
||||||
(throw (ex-info (str "Date must be MM/dd/yyyy") {:status :error})))
|
(when (dollars= (reduce + 0.0 (map :debit (:line_items entry)))
|
||||||
(when-not (dollars= (reduce + 0.0 (map :debit (:line_items entry)))
|
0.0)
|
||||||
(reduce + 0.0 (map :credit (:line_items entry))))
|
(throw (ex-info (str "Cannot have ledger entries that total $0.00")
|
||||||
(throw (ex-info (str "Debits '"
|
{:status :ignored})))
|
||||||
(reduce + 0 (map :debit (:line_items entry)))
|
(assoc entry
|
||||||
"' and credits '"
|
:status :success
|
||||||
(reduce + 0 (map :credit (:line_items entry)))
|
:tx
|
||||||
"' do not add up.")
|
(remove-nils
|
||||||
{:status :error})))
|
{:journal-entry/source (:source entry)
|
||||||
(when (dollars= (reduce + 0.0 (map :debit (:line_items entry)))
|
:journal-entry/client [:client/code (:client_code entry)]
|
||||||
0.0)
|
:journal-entry/date (coerce/to-date (parse/parse-value :clj-time "MM/dd/yyyy" (:date entry)))
|
||||||
(throw (ex-info (str "Cannot have ledger entries that total $0.00")
|
:journal-entry/external-id (:external_id entry)
|
||||||
{:status :ignored})))
|
:journal-entry/vendor (:db/id (all-vendors (:vendor_name entry)))
|
||||||
(assoc entry
|
:journal-entry/amount (:amount entry)
|
||||||
:status :success
|
:journal-entry/note (:note entry)
|
||||||
:tx
|
:journal-entry/cleared-against (:cleared_against entry)
|
||||||
(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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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]
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user