From 0c87309c34607aba80a059e7a054527ee4528b6c Mon Sep 17 00:00:00 2001 From: Bryce Covert Date: Thu, 13 Aug 2020 18:09:13 -0700 Subject: [PATCH] Fixing minor bugs. --- src/clj/auto_ap/graphql/transaction_rules.clj | 6 +- src/clj/auto_ap/rule_matching.clj | 10 +- .../views/components/vendor_dialog.cljs | 10 +- .../auto_ap/views/pages/admin/accounts.cljs | 131 +++++++++++------- .../auto_ap/views/pages/invoices/form.cljs | 15 +- .../views/pages/ledger/profit_and_loss.cljs | 37 ++--- src/cljs/auto_ap/views/utils.cljs | 5 + 7 files changed, 134 insertions(+), 80 deletions(-) diff --git a/src/clj/auto_ap/graphql/transaction_rules.clj b/src/clj/auto_ap/graphql/transaction_rules.clj index d057f2c4..7f7cbac2 100644 --- a/src/clj/auto_ap/graphql/transaction_rules.clj +++ b/src/clj/auto_ap/graphql/transaction_rules.clj @@ -10,7 +10,8 @@ [clojure.string :as str] [auto-ap.datomic.transactions :as d-transactions] [auto-ap.rule-matching :as rm] - [clj-time.coerce :as coerce]) + [clj-time.coerce :as coerce] + [clojure.tools.logging :as log]) (:import [java.time.temporal ChronoField])) @@ -126,7 +127,7 @@ (merge-query {:query {:in ['?description-regex] :where ['[?e :transaction/description-original ?do] '[(re-find ?description-regex ?do)]]} - :args [(re-pattern description)]}) + :args [(rm/->pattern description)]}) yodlee-merchant (merge-query {:query {:in ['?yodlee-merchant-id] @@ -187,6 +188,7 @@ (defn test-transaction-rule [{:keys [id]} {{:keys [description note client_id bank_account_id amount_lte amount_gte dom_lte dom_gte yodlee_merchant_id]} :transaction_rule :as z} value] (assert-admin id) + (log/info "HI") (-test-transaction-rule id #:transaction-rule {:description description :client (when client_id {:db/id client_id}) :bank-account (when bank_account_id {:db/id bank_account_id}) diff --git a/src/clj/auto_ap/rule_matching.clj b/src/clj/auto_ap/rule_matching.clj index 4dea14dc..f25e4c0e 100644 --- a/src/clj/auto_ap/rule_matching.clj +++ b/src/clj/auto_ap/rule_matching.clj @@ -10,7 +10,8 @@ [auto-ap.datomic.transactions :as d-transactions] [auto-ap.datomic.clients :as d-clients] [auto-ap.time :as time] - [auto-ap.datomic.transaction-rules :as tr])) + [auto-ap.datomic.transaction-rules :as tr] + [clojure.tools.logging :as log])) (defn rule-applies? [transaction {:keys [:transaction-rule/description :transaction-rule/dom-gte :transaction-rule/dom-lte @@ -82,16 +83,19 @@ (recur rules))) []))) +(defn ->pattern [x] + (. java.util.regex.Pattern (compile x java.util.regex.Pattern/CASE_INSENSITIVE))) + (defn group-rules-by-priority [rules] (->> rules - (map (fn [r] (update r :transaction-rule/description #(some-> % re-pattern)))) + (map (fn [r] (update r :transaction-rule/description #(some-> % ->pattern)))) (group-by rule-priority) (sort-by first) (map second))) (defn get-matching-rules [transaction all-rules] (->> all-rules - (map (fn [r] (update r :transaction-rule/description #(some-> % re-pattern)))) + (map (fn [r] (update r :transaction-rule/description #(some-> % ->pattern)))) (filter #(rule-applies? transaction %)))) (defn apply-rule [transaction rule valid-locations] diff --git a/src/cljs/auto_ap/views/components/vendor_dialog.cljs b/src/cljs/auto_ap/views/components/vendor_dialog.cljs index 70182371..a427b8d0 100644 --- a/src/cljs/auto_ap/views/components/vendor_dialog.cljs +++ b/src/cljs/auto_ap/views/components/vendor_dialog.cljs @@ -166,12 +166,14 @@ [:div.column.is-1 [:a.button {:on-click (dispatch-event [::removed-override override-key i])} [:span.icon [:span.icon-remove]]]]]))]))) -(defn default-with-overrides [{:keys [override-key override-value-key change-event default-key data]} template] +(defn default-with-overrides [{:keys [override-key override-value-key change-event default-key data mandatory?]} template] (let [clients @(re-frame/subscribe [::subs/clients]) is-admin? @(re-frame/subscribe [::subs/is-admin?])] [:div [horizontal-field - [:label.label "Default"] + [:label.label [:span "Default" + (when mandatory? + [:span.has-text-danger " *"])]] [bind-field (template default-key nil) #_(assoc-in template [1 :field ] default-key)]] @@ -207,7 +209,8 @@ is-admin? @(re-frame/subscribe [::subs/is-admin?])] [:div [horizontal-field - [:label.label "Name"] + [:label.label [:span "Name " + [:span.has-text-danger "*"]]] [:div.control [bind-field [:input.input {:type "text" @@ -258,6 +261,7 @@ [:h2.subtitle "Expense Accounts"] [default-with-overrides {:data data :change-event change-event + :mandatory? true :default-key :default-account :override-key :account-overrides} (fn [field client] diff --git a/src/cljs/auto_ap/views/pages/admin/accounts.cljs b/src/cljs/auto_ap/views/pages/admin/accounts.cljs index c3b6e1ca..ef642857 100644 --- a/src/cljs/auto_ap/views/pages/admin/accounts.cljs +++ b/src/cljs/auto_ap/views/pages/admin/accounts.cljs @@ -3,6 +3,7 @@ [auto-ap.subs :as subs] [auto-ap.utils :refer [replace-by]] [auto-ap.views.components.admin.side-bar :refer [admin-side-bar]] + [auto-ap.views.pages.admin.accounts.side-bar :as side-bar] [auto-ap.views.utils :refer [dispatch-event action-cell-width]] [auto-ap.views.components.layouts :refer @@ -12,86 +13,118 @@ [auto-ap.views.components.grid :as grid] [auto-ap.status :as status] [auto-ap.views.components.buttons :as buttons] - [reagent.core :as reagent])) + [reagent.core :as reagent] + [clojure.string :as str] + [vimsical.re-frame.fx.track :as track])) (re-frame/reg-event-db ::edit-completed (fn [db [_ edit-account]] (-> db (update :accounts replace-by :id (assoc edit-account :class "live-added"))))) - (re-frame/reg-event-db - ::params-changed + ::table-params-changed (fn [db [_ p]] - (assoc db ::params p))) + (assoc db ::table-params p))) + +(re-frame/reg-event-fx + ::params-change + (fn [db [_ p]] + {:set-uri-params p})) + +(re-frame/reg-sub + ::table-params + (fn [db] + (-> db ::table-params))) (re-frame/reg-sub ::params - (fn [db] - (-> db ::params))) + :<- [::table-params] + :<- [::side-bar/filter-params] + (fn [[table-params filter-params]] + (cond-> {} + (seq filter-params) (merge filter-params) + (seq table-params) (merge table-params)))) + (re-frame/reg-event-fx ::unmounted (fn [{:keys [db]} _] - {:db (dissoc db ::params)})) + {:db (dissoc db ::table-params ::side-bar/filter-params) + ::track/dispose {:id ::params}})) + +(re-frame/reg-event-fx + ::mounted + (fn [{:keys [db]} _] + {::track/register {:id ::params + :subscription [::params] + :event-fn (fn [params] [::params-change params])}})) +(re-frame/reg-sub + ::account-page + :<- [::params] + :<- [::subs/all-accounts] + (fn [[params all-accounts]] + (let [matching-accounts (cond->> all-accounts + (:name-like params) (filter #(str/includes? (str/lower-case (or (:name %) "")) + (str/lower-case (:name-like params)))) + (not-empty (:code-like params)) (filter #(str/starts-with? (str (or (:numeric-code %) "")) + (str/lower-case (:code-like params)))))] + (assoc (grid/virtual-paginate-controls (:start params ) matching-accounts) + :data (grid/virtual-paginate (:start params) + + (sort-by :numeric-code matching-accounts)))))) (defn accounts-table [{:keys [accounts]}] (let [status @(re-frame/subscribe [::status/single ::page]) opc (fn [p] - (re-frame/dispatch [::params-changed p])) + (re-frame/dispatch [::table-params-changed p])) params @(re-frame/subscribe [::params])] - [:div - (for [[account-set full-accounts] (group-by :account-set accounts) - :let [full-accounts (sort-by :numeric-code full-accounts) - accounts (grid/virtual-paginate (:start params 0) full-accounts )]] - ^{:key (or account-set "blank")} - [:div - [:h2.title.is-4 account-set] - [grid/grid {:status status - :on-params-change opc - :params params - :column-count 5} - [grid/controls (grid/virtual-paginate-controls (:start params) full-accounts)] - [grid/table {:fullwidth true} - [grid/header - [grid/row {} - [grid/header-cell {} "Code"] - [grid/header-cell {} "Name"] - [grid/header-cell {} "Type"] - [grid/header-cell {} "Location"] - [grid/header-cell {:style {:width (action-cell-width 1)}} ]]] - [grid/body - (for [{:keys [id numeric-code name type location class] :as account} accounts] - ^{:key id} - [grid/row {:class (:class account)} - [grid/cell {} numeric-code] - [grid/cell {} name] - [grid/cell {} type] - [grid/cell {} location] - [grid/cell {} - [buttons/fa-icon {:event [::account-form/editing account [::edit-completed]] - :icon "fa-pencil"}]]])]]]])])) + [:div + [grid/grid {:status status + :on-params-change opc + :params params + :column-count 5} + [grid/controls accounts] + [grid/table {:fullwidth true} + [grid/header + [grid/row {} + [grid/header-cell {} "Code"] + [grid/header-cell {} "Name"] + [grid/header-cell {} "Type"] + [grid/header-cell {} "Location"] + [grid/header-cell {:style {:width (action-cell-width 1)}} ]]] + [grid/body + (for [{:keys [id numeric-code name type location class] :as account} (:data accounts)] + ^{:key id} + [grid/row {:class (:class account)} + [grid/cell {} numeric-code] + [grid/cell {} name] + [grid/cell {} type] + [grid/cell {} location] + [grid/cell {} + [buttons/fa-icon {:event [::account-form/editing account [::edit-completed]] + :icon "fa-pencil"}]]])]]]])) (defn admin-accounts-content [] [:div - (let [accounts @(re-frame/subscribe [::subs/all-accounts])] - [:div - [:h1.title "Accounts"] - [:div.is-pulled-right - [:a.button.is-success {:on-click (dispatch-event [::account-form/editing - {:type :asset - :account-set "default"} - [::edit-completed]])} "New Account"]] - [accounts-table {:accounts accounts}]])]) + [:h1.title "Accounts"] + [:div.is-pulled-right + [:a.button.is-success {:on-click (dispatch-event [::account-form/editing + {:type :asset + :account-set "default"} + [::edit-completed]])} "New Account"]] + [accounts-table {:accounts @(re-frame/subscribe [::account-page])}]]) (defn admin-accounts-page [] (reagent/create-class {:display-name "accounts-page" :component-will-unmount #(re-frame/dispatch [::unmounted]) + :component-did-mount #(re-frame/dispatch [::mounted]) :reagent-render (fn [] (let [{:keys [active?]} @(re-frame/subscribe [::forms/form ::account-form/form])] - [side-bar-layout {:side-bar [admin-side-bar {}] + [side-bar-layout {:side-bar [admin-side-bar {} + [side-bar/accounts-side-bar]] :main [admin-accounts-content] :right-side-bar [appearing-side-bar {:visible? active?} [account-form/form ]]}]))})) diff --git a/src/cljs/auto_ap/views/pages/invoices/form.cljs b/src/cljs/auto_ap/views/pages/invoices/form.cljs index a21dc36e..0f148317 100644 --- a/src/cljs/auto_ap/views/pages/invoices/form.cljs +++ b/src/cljs/auto_ap/views/pages/invoices/form.cljs @@ -233,7 +233,8 @@ (form-inline (assoc params :title "New Invoice") [:<> (when-not @(re-frame/subscribe [::subs/client]) - (field "Client" + (field [:span "Client" + [:span.has-text-danger " *"]] [typeahead-entity {:matches @(re-frame/subscribe [::subs/clients]) :match->text :name :type "typeahead" @@ -242,7 +243,8 @@ :disabled exists? :spec ::invoice/client}])) - (field "Vendor" + (field [:span "Vendor" + [:span.has-text-danger " *"]] [typeahead-entity {:matches @(re-frame/subscribe [::subs/vendors]) :match->text :name :type "typeahead" @@ -250,7 +252,8 @@ :auto-focus (if @(re-frame/subscribe [::subs/client]) true false) :field [:vendor]}]) - (field "Date" + (field [:span "Date" + [:span.has-text-danger " *"]] [date-picker {:class-name "input" :class "input" :format-week-number (fn [] "") @@ -282,13 +285,15 @@ :spec ::invoice/automatically-paid-when-due}]) " Mark as paid on due date"]] - (field "Invoice #" + (field [:span "Invoice #" + [:span.has-text-danger " *"]] [:input.input {:type "text" :field [:invoice-number] :spec ::invoice/invoice-number}]) - (field "Total" + (field [:span "Total" + [:span.has-text-danger " *"]] [money-field {:type "money" :field [:total] :disabled (if can-change-amount? "" "disabled") diff --git a/src/cljs/auto_ap/views/pages/ledger/profit_and_loss.cljs b/src/cljs/auto_ap/views/pages/ledger/profit_and_loss.cljs index 24259e10..1ba5b205 100644 --- a/src/cljs/auto_ap/views/pages/ledger/profit_and_loss.cljs +++ b/src/cljs/auto_ap/views/pages/ledger/profit_and_loss.cljs @@ -6,7 +6,7 @@ [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 pretty dispatch-event local-now ->% ->$ str->date with-user]] + [auto-ap.views.utils :refer [date->str date-picker bind-field standard pretty dispatch-event local-today ->% ->$ str->date with-user]] [cljs-time.core :as t] [re-frame.core :as re-frame] [auto-ap.status :as status])) @@ -199,6 +199,7 @@ (re-frame/reg-event-fx ::date-picked (fn [cofx [_ [_ period which] date]] + (println date (str->date date standard)) {:dispatch [::range-selected (assoc-in @(re-frame/subscribe [::periods]) [period which] (str->date date standard)) nil]})) (re-frame/reg-event-fx @@ -493,8 +494,8 @@ {:class (when (= (:selected params) "13 periods") "is-active") :on-click (dispatch-event [::range-selected - (let [this-month (t/local-date (t/year (local-now)) - (t/month (local-now)) + (let [this-month (t/local-date (t/year (local-today)) + (t/month (local-today)) 1)] (into [[this-month (t/minus (t/plus this-month (t/months 1)) (t/days 1))]] @@ -509,7 +510,7 @@ [:a.button {:class (when (= (:selected params) "Last week") "is-active") :on-click (dispatch-event - (let [last-sunday (loop [current (local-now)] + (let [last-sunday (loop [current (local-today)] (if (= 7 (t/day-of-week current)) current (recur (t/minus current (t/period :days 1)))))] @@ -521,23 +522,23 @@ [:a.button {:class (when (= (:selected params) "Week to date") "is-active") :on-click (dispatch-event [::range-selected - (and-last-year [(loop [current (local-now)] + (and-last-year [(loop [current (local-today)] (if (= 1 (t/day-of-week current)) current (recur (t/minus current (t/period :days 1))))) - (local-now)]) + (local-today)]) "Week to date"])} "Week to date"]] [:div.control [:a.button {:class (when (= (:selected params) "Last Month") "is-active") :on-click (dispatch-event [::range-selected - (and-last-year [(t/minus (t/local-date (t/year (local-now)) - (t/month (local-now)) + (and-last-year [(t/minus (t/local-date (t/year (local-today)) + (t/month (local-today)) 1) (t/period :months 1)) - (t/minus (t/local-date (t/year (local-now)) - (t/month (local-now)) + (t/minus (t/local-date (t/year (local-today)) + (t/month (local-today)) 1) (t/period :days 1))]) "Last Month"])} @@ -546,27 +547,27 @@ [:a.button {:class (when (= (:selected params) "Month to date") "is-active") :on-click (dispatch-event [::range-selected - (and-last-year [(t/local-date (t/year (local-now)) - (t/month (local-now)) + (and-last-year [(t/local-date (t/year (local-today)) + (t/month (local-today)) 1) - (local-now)]) + (local-today)]) "Month to date"])} "Month to date"]] [:div.control [:a.button {:class (when (= (:selected params) "Year to date") "is-active") :on-click (dispatch-event [::range-selected - (and-last-year [(t/local-date (t/year (local-now)) 1 1) - (local-now)]) + (and-last-year [(t/local-date (t/year (local-today)) 1 1) + (local-today)]) "Year to date"])} "Year to date"]] [:div.control [:a.button {:class (when (= (:selected params) "Full year") "is-active") :on-click (dispatch-event [::range-selected - (and-last-year [(t/plus (t/minus (local-now) (t/period :years 1)) + (and-last-year [(t/plus (t/minus (local-today) (t/period :years 1)) (t/period :days 1)) - (local-now)]) + (local-today)]) "Full year"])} "Full year"]]]] (for [[_ i] (map vector periods (range))] @@ -635,7 +636,7 @@ ^{:key location} [location-rows location] )]]]])]))) - {:component-will-mount #(do (re-frame/dispatch-sync [::range-selected (and-last-year [(t/minus (local-now) (t/period :years 1)) (local-now)]) nil])) })) + {:component-will-mount #(do (re-frame/dispatch-sync [::range-selected (and-last-year [(t/minus (local-today) (t/period :years 1)) (local-today)]) nil])) })) diff --git a/src/cljs/auto_ap/views/utils.cljs b/src/cljs/auto_ap/views/utils.cljs index 2112eff3..e6182761 100644 --- a/src/cljs/auto_ap/views/utils.cljs +++ b/src/cljs/auto_ap/views/utils.cljs @@ -90,6 +90,7 @@ (defn dispatch-date-change [event] (fn [e g] + (println e (c/from-date e) (time/from-default-time-zone (c/from-date e)) (date->str (time/from-default-time-zone (c/from-date e)) standard)) (re-frame/dispatch (conj event (if (str/blank? e) e @@ -283,6 +284,7 @@ :else selected ) + keys (assoc keys :on-change (dispatch-date-change (conj event field)) :selected selected @@ -411,6 +413,9 @@ (defn local-now [] (t/to-default-time-zone (t/now))) +(defn local-today [] + (t/at-midnight (t/to-default-time-zone (t/now)))) + (def with-user (re-frame/->interceptor :id :with-user