diff --git a/resources/public/css/main.css b/resources/public/css/main.css
index 2f605a11..f3714bac 100644
--- a/resources/public/css/main.css
+++ b/resources/public/css/main.css
@@ -478,3 +478,12 @@ table.balance-sheet th.total {
}
}
+
+
+.loader.big {
+ height: 150px !important;
+ width: 150px !important;
+ border: 4px solid #00d1b2;
+ border-right-color: transparent;
+ border-top-color: transparent;
+}
diff --git a/resources/public/index.html b/resources/public/index.html
index 6a5b9f1d..e86a1157 100644
--- a/resources/public/index.html
+++ b/resources/public/index.html
@@ -17,37 +17,7 @@
-
+
diff --git a/src/clj/auto_ap/datomic/invoices.clj b/src/clj/auto_ap/datomic/invoices.clj
index 6823d955..fae52eeb 100644
--- a/src/clj/auto_ap/datomic/invoices.clj
+++ b/src/clj/auto_ap/datomic/invoices.clj
@@ -193,3 +193,16 @@
(map <-datomic)))
+(defn get-existing-set []
+ (d/query
+ (cond-> {:query {:find ['?vendor '?client '?invoice-number]
+ :in ['$]
+ :where '[[?e :invoice/invoice-number ?invoice-number]
+ [?e :invoice/vendor ?vendor]
+ [?e :invoice/client ?client]
+ (not [?e :invoice/status :invoice-status/voided])
+ ]}
+
+ :args [(d/db (d/connect uri))]})))
+
+
diff --git a/src/clj/auto_ap/ledger.clj b/src/clj/auto_ap/ledger.clj
index fa8989e0..49b4595f 100644
--- a/src/clj/auto_ap/ledger.clj
+++ b/src/clj/auto_ap/ledger.clj
@@ -174,7 +174,7 @@
@(d/transact
(d/connect uri)
(mapv
- #(auto-ap.ledger/entity-change->ledger (d/db (d/connect uri)) [:transaction %])
+ #(entity-change->ledger (d/db (d/connect uri)) [:transaction %])
(concat
(->>
(d/query {:query {:find ['?t ]
diff --git a/src/clj/auto_ap/routes/invoices.clj b/src/clj/auto_ap/routes/invoices.clj
index 2ba45682..fe544515 100644
--- a/src/clj/auto_ap/routes/invoices.clj
+++ b/src/clj/auto_ap/routes/invoices.clj
@@ -39,8 +39,6 @@
(if-let [id (:db/id (or (clients client-code)
(clients client)))]
(do
- (println "FOUND CLIENT" (or (clients client-code)
- (clients client)))
(when (not ((set (:client/locations (or (clients client-code)
(clients client))))
default-location))
@@ -78,8 +76,8 @@
(defn parse-account-numeric-code [i]
(try
(when-let [account-numeric-code (:account-numeric-code i)]
- (d-accounts/get-account-by-numeric-code-and-sets (Integer/parseInt account-numeric-code)
- ["default"]))
+ (:db/id (d-accounts/get-account-by-numeric-code-and-sets (Integer/parseInt account-numeric-code)
+ ["default"])))
(catch Exception e
(throw (Exception. (str "Could not parse expense account from value '" (:account-numeric-code i) "'") e)))))
@@ -481,12 +479,7 @@
{{:keys [excel-rows]} :edn-params user :identity}
(assert-admin user)
(let [parsed-invoice-rows (parse-invoice-rows excel-rows)
- existing-rows (->> (d-invoices/get-graphql {:count Integer/MAX_VALUE})
- first
- (filter (fn [i] (not= :invoice-status/voided (:invoice/status i))))
- (map (fn [{:keys [:invoice/vendor :invoice/client :invoice/invoice-number]}]
- [(:db/id vendor) (:db/id client) invoice-number]))
- set)
+ existing-rows (set (d-invoices/get-existing-set ))
grouped-rows (group-by
(fn [i]
(cond (seq (:errors i))
diff --git a/src/clj/user.clj b/src/clj/user.clj
index 17330052..6acd73d3 100644
--- a/src/clj/user.clj
+++ b/src/clj/user.clj
@@ -2,6 +2,7 @@
(:require [auto-ap.datomic :refer [uri]]
[auto-ap.utils :refer [by]]
+ #_[auto-ap.ledger :as l]
[datomic.api :as d]
[clojure.data.csv :as csv]
[clj-time.coerce :as c]
@@ -300,11 +301,12 @@
)
vec))
-(defn patch-missing-ledger-entries []
+;; TODO uncommenting the two below this makes lein build not work, probably related to the ledger
+#_(defn patch-missing-ledger-entries []
@(d/transact
(d/connect uri)
(mapv
- #(auto-ap.ledger/entity-change->ledger (d/db (d/connect uri)) [:transaction %])
+ #(l/entity-change->ledger (d/db (d/connect uri)) [:transaction %])
(concat
(->>
(d/query {:query {:find ['?t ]
@@ -317,7 +319,7 @@
-(defn check-for-out-of-date-ledger [?code]
+#_(defn check-for-out-of-date-ledger [code]
[(d/query {:query {:find ['(count ?e)]
:in ['$ '?code]
:where ['[?e :transaction/accounts ?ta]
@@ -327,11 +329,13 @@
'[?e :transaction/client ?c]
'[?c :client/code ?code]
]}
- :args [(d/db (d/connect uri)) ?code]})
+ :args [(d/db (d/connect uri)) code]})
(d/query {:query {:find ['?t ]
:in ['$]
:where ['[?t :transaction/date]
+ '[?t :transaction/client ?c]
+ '[?c :client/code ?code]
'(not [?t :transaction/approval-status :transaction-approval-status/excluded])
'(not-join [?t] [?e :journal-entry/original-entity ?t])]}
:args [(d/db (d/connect uri))]})
@@ -339,9 +343,20 @@
(d/query {:query {:find ['?t ]
:in ['$]
:where ['[?t :transaction/date]
+ '[?t :transaction/client ?c]
+ '[?c :client/code ?code]
'(not [?t :transaction/approval-status :transaction-approval-status/excluded])
'[?t :transaction/vendor ?v]
'[?j :journal-entry/original-entity ?t]
'(not [?j :journal-entry/vendor ?v])
#_'(not-join [?t] [?e :journal-entry/original-entity ?t])]}
+ :args [(d/db (d/connect uri))]})
+
+ (d/query {:query {:find ['(count ?i) ]
+ :in ['$]
+ :where ['[?i :invoice/client ?c]
+ '(not [?i :invoice/status :invoice-status/voided])
+ '[?c :client/code ?code]
+ '(not-join [?i] [?e :journal-entry/original-entity ?i])]}
:args [(d/db (d/connect uri))]})])
+
diff --git a/src/cljs/auto_ap/events.cljs b/src/cljs/auto_ap/events.cljs
index ac68d5d2..e9d117c0 100644
--- a/src/cljs/auto_ap/events.cljs
+++ b/src/cljs/auto_ap/events.cljs
@@ -19,7 +19,6 @@
::initialize-db
(fn [{:keys [db]} [_ token]]
(let [handler (:handler (bidi/match-route routes/routes (.. js/window -location -pathname)))]
- (prn (and token (get (jwt->data token) "user/role")))
(cond
(and (not= :login handler) (not token))
{:redirect "/login"
@@ -38,6 +37,7 @@
:else
{:db (assoc db/default-db
:active-page handler
+ :is-initial-loading? true
:last-client-id (.getItem js/localStorage "last-client-id")
:query-params (auto-ap.views.utils/query-params)
:user token)
@@ -84,7 +84,9 @@
[:accounts [:numeric-code :name :location :type :account_set :applicability :id [:client-overrides [:name [:client [:name :id]]]]]]]}
:on-success [::received-initial]}
- :db (assoc db :user (assoc user :token token))}))
+ :db (assoc db
+ :user (assoc user :token token)
+ :is-initial-loading? true)}))
(re-frame/reg-event-db
::received-initial
@@ -93,6 +95,7 @@
(-> db
(assoc :clients (by :id clients) )
(assoc :vendors (by :id vendors) )
+ (assoc :is-initial-loading? false)
(assoc :accounts accounts )
(assoc :client (or (when (= 1 (count clients)) (->> clients first :id ))
(->> clients
diff --git a/src/cljs/auto_ap/subs.cljs b/src/cljs/auto_ap/subs.cljs
index 7e8c459b..8a2da605 100644
--- a/src/cljs/auto_ap/subs.cljs
+++ b/src/cljs/auto_ap/subs.cljs
@@ -150,6 +150,11 @@
(fn [db]
(:menu db)))
+(re-frame/reg-sub
+ ::is-initial-loading?
+ (fn [db]
+ (:is-initial-loading? db)))
+
(re-frame/reg-sub
::modal-state
(fn [db [_ id status-from]]
diff --git a/src/cljs/auto_ap/views/components/invoices/side_bar.cljs b/src/cljs/auto_ap/views/components/invoices/side_bar.cljs
index eedaa5b5..88ada957 100644
--- a/src/cljs/auto_ap/views/components/invoices/side_bar.cljs
+++ b/src/cljs/auto_ap/views/components/invoices/side_bar.cljs
@@ -37,7 +37,8 @@
url-filters {:vendor (when-let [vendor-id (:vendor-id url-filters)]
{:id (str vendor-id)
:name (get-in vendors-by-id [(str vendor-id) :name] "Loading...")})
- :date-range (:date-range url-filters)
+ :date-range {:raw (:date-range url-filters)
+ :settled (:date-range url-filters)}
:due-range (:due-range url-filters)
:amount-range {:raw {:amount-gte (:amount-gte url-filters)
:amount-lte (:amount-lte url-filters)}
@@ -60,7 +61,7 @@
(fn [[filters ap ]]
{:vendor-id (:id (:vendor filters))
- :date-range (:date-range filters)
+ :date-range (:settled (:date-range filters))
:due-range (:due-range filters)
:amount-gte (:amount-gte (:settled (:amount-range filters)))
:amount-lte (:amount-lte (:settled (:amount-range filters)))
@@ -114,6 +115,25 @@
:key ::amount-range}
:db (assoc-in db [:raw which] value)}))
+(re-frame/reg-event-fx
+ ::date-range-settled
+ [(re-frame/path [::filters :date-range])]
+ (fn [{:keys [db]} [_ which value]]
+ {:db (assoc-in db [:settled which] value)
+ :dispatch [::filter-changed :date-range [:settled] (assoc (:settled db) which value)]}))
+
+;; TODO for some reason reloading is borken, and typing will unset stuff, has nothing to do with it being debounced
+(re-frame/reg-event-fx
+ ::date-range-changed
+ [(re-frame/path [::filters :date-range])]
+ (fn [{:keys [db]} [_ [which] value]]
+ (println which value)
+ {:dispatch-debounce
+ {:event [::date-range-settled which value]
+ :time 1000
+ :key ::date-range}
+ :db (assoc-in db [:raw which] value)}))
+
(defn invoice-number-filter []
[:div.field
[:div.control [:input.input {:placeholder "AP-123"
@@ -171,8 +191,8 @@
[:p.menu-label "Date Range"]
[:div
[date-range-filter
- {:on-change-event [::filter-changed :date-range]
- :value @(re-frame/subscribe [::filter :date-range])}]]
+ {:on-change-event [::date-range-changed]
+ :value (:raw @(re-frame/subscribe [::filter :date-range]))}]]
[:p.menu-label "Due Range"]
[:div
diff --git a/src/cljs/auto_ap/views/components/layouts.cljs b/src/cljs/auto_ap/views/components/layouts.cljs
index 1fb6229a..86128d69 100644
--- a/src/cljs/auto_ap/views/components/layouts.cljs
+++ b/src/cljs/auto_ap/views/components/layouts.cljs
@@ -90,71 +90,75 @@
clients (re-frame/subscribe [::subs/clients])
matching-clients @(re-frame/subscribe [::matching-clients])
menu (re-frame/subscribe [::subs/menu])
- client-search @(re-frame/subscribe [::client-search])]
+ client-search @(re-frame/subscribe [::client-search])
+ is-initial-loading @(re-frame/subscribe [::subs/is-initial-loading?])]
[:nav {:class "navbar has-shadow is-fixed-top"}
[:div {:class "container"}
[:div {:class "navbar-brand"}
[:a {:class "navbar-item", :href "../"}
[:img {:src "/img/logo.png"}]]]
[:div.navbar-menu
- [:div.navbar-start
- [:a.navbar-item {:class [(active-when ap = :index)]
- :href (bidi/path-for routes/routes :index)}
- "Home" ]
- [:a.navbar-item {:class [(active-when ap #{:unpaid-invoices :paid-invoices})]
- :href (bidi/path-for routes/routes :unpaid-invoices)}
- "Invoices" ]
- [:a.navbar-item {:class [(active-when ap = :payments)]
- :href (bidi/path-for routes/routes :payments)}
- "Payments" ]
- [:a.navbar-item {:class [(active-when ap = :transactions)]
- :href (bidi/path-for routes/routes :transactions)}
- "Transactions" ]
-
- (when (not= "manager" (:user/role @user))
- [:a.navbar-item {:class [(active-when ap = :ledger)]
- :href (bidi/path-for routes/routes :ledger)}
- "Ledger" ])]
+ (when-not is-initial-loading
+ [:div.navbar-start
+ [:a.navbar-item {:class [(active-when ap = :index)]
+ :href (bidi/path-for routes/routes :index)}
+ "Home" ]
+ [:a.navbar-item {:class [(active-when ap #{:unpaid-invoices :paid-invoices})]
+ :href (bidi/path-for routes/routes :unpaid-invoices)}
+ "Invoices" ]
+ [:a.navbar-item {:class [(active-when ap = :payments)]
+ :href (bidi/path-for routes/routes :payments)}
+ "Payments" ]
+ [:a.navbar-item {:class [(active-when ap = :transactions)]
+ :href (bidi/path-for routes/routes :transactions)}
+ "Transactions" ]
+
+ (when (not= "manager" (:user/role @user))
+ [:a.navbar-item {:class [(active-when ap = :ledger)]
+ :href (bidi/path-for routes/routes :ledger)}
+ "Ledger" ])])
[:div {:class "navbar-burger burger", :data-target "navMenu"}
[:span]
[:span]
[:span]]
- [:div.navbar-end
- [:div.navbar-item
- [:a.button.is-primary.is-outlined
- {:on-click (dispatch-event [::vendor-dialog/started {}])}
- [:span.icon [:i.fa.fa-plus] ] [:span "Vendor"]]]
-
+ (when-not is-initial-loading
+ [:div.navbar-end
+ [:div.navbar-item
+ [:a.button.is-primary.is-outlined
+ {:on-click (dispatch-event [::vendor-dialog/started {}])}
+ [:span.icon [:i.fa.fa-plus] ] [:span "Vendor"]]]
+
- (when (> (count @clients) 1)
- [navbar-drop-down {:header (str "Client: " (if @client (:name @client)
- "All"))
- :id ::select-client}
- [:div
- [:a {:class "navbar-item"
- :on-click (fn []
- (re-frame/dispatch [::events/swap-client nil]))} "All" ]
- [:hr {:class "navbar-divider"}]
- [bind-field
- [:input.input.navbar-item {:placeholder "Client name"
- :auto-focus true
- :field [:value]
- :on-key-up (fn [k]
- (when (= 13 (.-which k))
- (do
- (re-frame/dispatch [::events/swap-client (first matching-clients)])
- (re-frame/dispatch [::events/toggle-menu ::select-client])
- (re-frame/dispatch [::client-search-changed [:value] nil])))
- )
- :event [::client-search-changed]
- :subscription client-search}]]
- (for [{:keys [name id] :as client} matching-clients]
- ^{:key id }
+ (when (> (count @clients) 1)
+ [navbar-drop-down {:header (str "Client: " (if @client (:name @client)
+ "All"))
+ :id ::select-client}
+ [:div
[:a {:class "navbar-item"
:on-click (fn []
- (re-frame/dispatch [::events/swap-client client]))
- } name])]])]]
- [login-dropdown]]]))
+ (re-frame/dispatch [::events/swap-client nil]))} "All" ]
+ [:hr {:class "navbar-divider"}]
+ [bind-field
+ [:input.input.navbar-item {:placeholder "Client name"
+ :auto-focus true
+ :field [:value]
+ :on-key-up (fn [k]
+ (when (= 13 (.-which k))
+ (do
+ (re-frame/dispatch [::events/swap-client (first matching-clients)])
+ (re-frame/dispatch [::events/toggle-menu ::select-client])
+ (re-frame/dispatch [::client-search-changed [:value] nil])))
+ )
+ :event [::client-search-changed]
+ :subscription client-search}]]
+ (for [{:keys [name id] :as client} matching-clients]
+ ^{:key id }
+ [:a {:class "navbar-item"
+ :on-click (fn []
+ (re-frame/dispatch [::events/swap-client client]))
+ } name])]])])]
+ (when-not is-initial-loading
+ [login-dropdown])]]))
(defn footer []
@@ -170,7 +174,8 @@
(defn side-bar-layout [{:keys [side-bar main ap bottom right-side-bar]}]
(let [ap @(re-frame/subscribe [::subs/active-page])
- client @(re-frame/subscribe [::subs/client])]
+ client @(re-frame/subscribe [::subs/client])
+ is-initial-loading @(re-frame/subscribe [::subs/is-initial-loading?])]
[:div
[navbar ap]
[:div {:class "columns has-shadow", :style {:margin-bottom "0px" :height "calc(100vh - 46px)" } :id "mail-app" }
@@ -190,7 +195,8 @@
]
#_[footer]
[:div
- [vendor-dialog {}]
+ (when-not is-initial-loading
+ [vendor-dialog {}])
bottom]
[:div#dz-hidden]]))
@@ -198,3 +204,11 @@
(defn side-bar [{:keys [on-close]} children]
[:div [:a.delete.is-pulled-right {:on-click on-close}] [:div children]])
+(defn loading-layout []
+ [side-bar-layout
+ {:main [:div.has-text-centered.hero.is-fullheight.is-vertically-centered.is-centered
+ [:div.hero-body
+ [:div.container
+ [:div.column.is-4.is-offset-4.has-text-centered
+ [:div.loader.is-loading.is-active.big.is-centered]]]]]}])
+
diff --git a/src/cljs/auto_ap/views/main.cljs b/src/cljs/auto_ap/views/main.cljs
index de212b22..41b1c71c 100644
--- a/src/cljs/auto_ap/views/main.cljs
+++ b/src/cljs/auto_ap/views/main.cljs
@@ -6,7 +6,7 @@
[auto-ap.subs :as subs]
[auto-ap.events :as events]
[auto-ap.views.utils :refer [active-when active-when= login-url dispatch-event]]
- [auto-ap.views.components.layouts :refer [side-bar-layout]]
+ [auto-ap.views.components.layouts :refer [side-bar-layout loading-layout]]
[auto-ap.views.pages.unpaid-invoices :refer [unpaid-invoices-page]]
[auto-ap.views.pages.import-invoices :refer [import-invoices-page]]
[auto-ap.views.pages.needs-activation :refer [needs-activation-page]]
@@ -111,8 +111,44 @@
(defmethod page :admin-excel-import [_]
[admin-excel-import-page])
+;;
+;; ;;
(defn active-page []
- (let [ap (re-frame/subscribe [::subs/active-page])]
- [:div
- ^{:key @ap} [page @ap]]))
+ (let [ap (re-frame/subscribe [::subs/active-page])
+ is-loading? @(re-frame/subscribe [::subs/is-initial-loading?])]
+ (if is-loading?
+ [loading-layout]
+
+ [:div
+ ^{:key @ap} [page @ap]])))
diff --git a/src/cljs/auto_ap/views/pages/transactions/side_bar.cljs b/src/cljs/auto_ap/views/pages/transactions/side_bar.cljs
index b75f7d8d..9860c055 100644
--- a/src/cljs/auto_ap/views/pages/transactions/side_bar.cljs
+++ b/src/cljs/auto_ap/views/pages/transactions/side_bar.cljs
@@ -27,8 +27,8 @@
{:vendor-id (:id (:vendor filters))
:date-range (:date-range filters)
:bank-account-id (:id (:bank-account filters))
- :amount-gte (:amount-gte (:amount-range filters))
- :amount-lte (:amount-lte (:amount-range filters))
+ :amount-gte (:amount-gte (:settled (:amount-range filters)))
+ :amount-lte (:amount-lte (:settled (:amount-range filters)))
:description (:settled (:description filters))
:approval-status (condp = ap
:transactions nil
@@ -65,6 +65,23 @@
:key ::description}
:db (assoc db :raw description)}))
+(re-frame/reg-event-fx
+ ::amount-range-settled
+ [(re-frame/path [::filters :amount-range])]
+ (fn [{:keys [db]} [_ which value]]
+ {:db (assoc-in db [:settled which] value)
+ :dispatch [::filter-changed :amount-range [:settled] (assoc (:settled db) which value)]}))
+
+(re-frame/reg-event-fx
+ ::amount-range-changed
+ [(re-frame/path [::filters :amount-range])]
+ (fn [{:keys [db]} [_ [which] value]]
+ {:dispatch-debounce
+ {:event [::amount-range-settled which value]
+ :time 500
+ :key ::amount-range}
+ :db (assoc-in db [:raw which] value)}))
+
(defn side-bar []
(let [ap @(re-frame/subscribe [::subs/active-page])
user @(re-frame/subscribe [::subs/user])]
@@ -119,8 +136,8 @@
[:p.menu-label "Amount"]
[:div
[number-filter
- {:on-change-event [::filter-changed :amount-range]
- :value @(re-frame/subscribe [::filter :amount-range])}]]
+ {:on-change-event [::amount-range-changed]
+ :value (:raw @(re-frame/subscribe [::filter :amount-range]))}]]
[:p.menu-label "Vendor"]
[:div
diff --git a/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs b/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs
index fd392bc5..0ab55eb0 100644
--- a/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs
+++ b/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs
@@ -82,7 +82,6 @@
(seq filter-params) (merge filter-params)
(seq table-params) (merge table-params))]
(when (not= params last-params)
- (println "DISPATCHING" params last-params)
(re-frame/dispatch [::params-change]))
params)))
@@ -113,6 +112,7 @@
(re-frame/reg-event-fx
::unmounted
(fn [{:keys [db]} _]
+ (println "UNMOUNTING?")
{:db (dissoc db ::invoice-page ::table/table-params ::side-bar/filters ::last-params)}))
(re-frame/reg-event-db