diff --git a/src/clj/auto_ap/graphql/accounts.clj b/src/clj/auto_ap/graphql/accounts.clj index 0c9d4e91..e9340cec 100644 --- a/src/clj/auto_ap/graphql/accounts.clj +++ b/src/clj/auto_ap/graphql/accounts.clj @@ -8,14 +8,31 @@ (->graphql (d-accounts/get-accounts (<-graphql args)))) (defn upsert-account [context args value] - @(d/transact (d/connect uri) - [(remove-nils - {:db/id (:id (:account args)) - :account/name (:name (:account args)) - :account/type (keyword "account-type" (name (:type (:account args)))) - :account/account-set (:account_set (:account args)) - :account/numeric-code (if-not (:id (:account args)) - (:numeric_code (:account args))) - })]) - (:account args)) + (let [{{:keys [id numeric-code account-set name type]} :account} (<-graphql args)] + (when-not id + (when (seq (d/query {:query {:find ['?e] + :in '[$ ?account-set ?numeric-code] + :where ['[?e :account/account-set ?account-set] + '[?e :account/numeric-code ?numeric-code]]} + :args [(d/db (d/connect uri)) account-set numeric-code]})) + + (throw (ex-info (str "Account set " account-set " already has an account for code " numeric-code) + {} )))) + + (let [ + result @(d/transact (d/connect uri) + [(remove-nils + {:db/id (or id "new-account") + :account/name name + :account/type (keyword "account-type" (clojure.core/name type)) + :account/account-set account-set + :account/numeric-code (if-not id + numeric-code) + :account/code (if-not id + (str numeric-code))})])] + (->graphql + (if id + (:account args) + (assoc (:account args) + :id (get-in result [:tempids "new-account"]))))))) diff --git a/src/cljc/auto_ap/entities/account.cljc b/src/cljc/auto_ap/entities/account.cljc new file mode 100644 index 00000000..866ffa28 --- /dev/null +++ b/src/cljc/auto_ap/entities/account.cljc @@ -0,0 +1,16 @@ +(ns auto-ap.entities.account + (:require [clojure.spec.alpha :as s] + [clojure.string :as str] + [auto-ap.entities.shared :as shared])) + +(def numeric-regex #"^[0-9]+$") + +(s/def ::account-set string?) +(s/def ::numeric-code (s/or :numericstring? (s/and string? + #(re-matches numeric-regex %)) + :numeric? int?)) +(s/def ::name string?) +(s/def ::type #{:dividend :expense :asset :liability :equities :revenue}) + +(s/def ::account (s/keys :req-un [::account-set ::numeric-code ::name ::type])) + diff --git a/src/cljc/auto_ap/utils.cljc b/src/cljc/auto_ap/utils.cljc index 96c93a4b..a79ed434 100644 --- a/src/cljc/auto_ap/utils.cljc +++ b/src/cljc/auto_ap/utils.cljc @@ -19,12 +19,18 @@ existing)) (defn replace-by [xs f x] - (mapv - (fn [t] - (if (= (f t) (f x)) - x - t)) - xs)) + (let [found? (atom false) + replaced (mapv + (fn [t] + (if (= (f t) (f x)) + (do (reset! found? true) + (println "found" (f t) t (f x) x) + x) + t)) + xs)] + (if @found? + replaced + (conj replaced x)))) (defn dollars-0? [amt] (< -0.001 amt 0.001)) diff --git a/src/cljs/auto_ap/forms.cljs b/src/cljs/auto_ap/forms.cljs index 80fcea71..95a57d28 100644 --- a/src/cljs/auto_ap/forms.cljs +++ b/src/cljs/auto_ap/forms.cljs @@ -29,13 +29,17 @@ :id (random-uuid) :status nil :data data})) + +(defn saved-form [db form data] + (update-in db [::forms form] + assoc :error nil :status nil :data data)) + (defn stop-form [db form] (update db ::forms dissoc form)) (re-frame/reg-event-db ::form-closing (fn [db [_ f]] - (-> db (stop-form f)))) @@ -56,7 +60,6 @@ (re-frame/reg-event-db ::save-error (fn [db [_ form result]] - (-> db (assoc-in [::forms form :status] :error) (assoc-in [::forms form :error] (or (:message (first result)) diff --git a/src/cljs/auto_ap/views/pages/admin/accounts.cljs b/src/cljs/auto_ap/views/pages/admin/accounts.cljs index 152551d0..f690500c 100644 --- a/src/cljs/auto_ap/views/pages/admin/accounts.cljs +++ b/src/cljs/auto_ap/views/pages/admin/accounts.cljs @@ -16,35 +16,36 @@ (-> db (update :accounts replace-by :id edit-account)))) -(defn accounts-table [{:keys [accounts]} ] - +(defn accounts-table [{:keys [accounts]}] [:div (for [[account-set accounts] (group-by :account-set accounts)] - (do (println accounts) - ^{:key account-set} - [:div - [:h2.title.is-4 account-set] - [:table.table.compact - [:thead - [:th "Code"] - [:th "Name"] - [:th "Type"] - [:th {:style {:width "5em"}}] - ] - [:tbody - (for [{:keys [id numeric-code name type] :as account} (sort-by :numeric-code accounts)] - ^{:key id} - [:tr - [:td numeric-code] - [:td name] - [:td type] - [:td [:a.button {:on-click (dispatch-event [::account-form/editing account])} [:span [:span.icon [:i.fa.fa-pencil]]]]]])]]]))]) + ^{:key (or account-set "blank")} + [:div + [:h2.title.is-4 account-set] + [:table.table.compact.is-fullwidth + [:thead + [:tr + [:th "Code"] + [:th "Name"] + [:th "Type"] + [:th {:style {:width "5em"}}]]] + [:tbody + (for [{:keys [id numeric-code name type] :as account} (sort-by :numeric-code accounts)] + ^{:key id} + [:tr + [:td numeric-code] + [:td name] + [:td type] + [:td [:a.button {:on-click (dispatch-event [::account-form/editing account])} [:span [:span.icon [:i.fa.fa-pencil]]]]]])]]])]) (defn admin-accounts-content [] [:div (let [accounts @(re-frame/subscribe [::subs/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"}])} "New Account"]] [accounts-table {:accounts accounts}]])]) (defn admin-accounts-page [] diff --git a/src/cljs/auto_ap/views/pages/admin/accounts/form.cljs b/src/cljs/auto_ap/views/pages/admin/accounts/form.cljs index 0d1fbad2..73ebe875 100644 --- a/src/cljs/auto_ap/views/pages/admin/accounts/form.cljs +++ b/src/cljs/auto_ap/views/pages/admin/accounts/form.cljs @@ -1,6 +1,8 @@ (ns auto-ap.views.pages.admin.accounts.form (:require [auto-ap.forms :as forms] [clojure.string :as str] + [clojure.spec.alpha :as s] + [auto-ap.entities.account :as entity] [auto-ap.views.utils :refer [bind-field dispatch-event]] [re-frame.core :as re-frame])) @@ -11,6 +13,16 @@ (fn [db] true)) +(re-frame/reg-sub + ::account-request + :<- [::forms/form ::form] + (fn [{{:keys [id type numeric-code name account-set]} :data}] + {:id id + :type (keyword type) + :numeric-code numeric-code + :name name + :account-set account-set})) + (re-frame/reg-event-db ::editing (fn [db [_ which]] @@ -20,8 +32,7 @@ (re-frame/reg-event-fx ::edited (fn [{:keys [db]} [_ edit-completed {:keys [upsert-account]}]] - {:db (-> db - (forms/stop-form ::form)) + {:db (-> db (forms/saved-form ::form upsert-account)) :dispatch (conj edit-completed upsert-account)})) (re-frame/reg-event-fx @@ -35,11 +46,7 @@ :query-obj {:venia/operation {:operation/type :mutation :operation/name "UpsertAccount"} :venia/queries [{:query/data [:upsert-account - {:account {:id id - :type (keyword type) - :numeric-code numeric-code - :name name - :account-set account-set}} + {:account @(re-frame/subscribe [::account-request])} [:id :type :name :account-set :numeric-code]]}]} :on-success [::edited edit-completed] :on-error [::forms/save-error ::form]}})))) @@ -50,7 +57,23 @@ [forms/side-bar-form {:form ::form} [:form - [:h1.title.is-2 "Add/edit account"] + [:h1.title.is-2 (if (:id account) + "Edit account" + "Add account")] + + [:div.field + [:p.help "Account Set"] + [:div.control + [bind-field + [:input.input {:type "text" + :field :account-set + :disabled (if (:id account) + "disabled" + "") + :spec ::entity/account-set + :event change-event + :subscription account}]]]] + [:div.field [:p.help "Code"] [:div.control @@ -60,7 +83,7 @@ :disabled (if (:id account) "disabled" "") - #_:spec #_:entity/name + :spec ::entity/numeric-code :event change-event :subscription account}]]]] @@ -70,12 +93,14 @@ [bind-field [:input.input {:type "text" :field :name - #_:spec #_:entity/name + :spec ::entity/name :event change-event :subscription account}]]]] + + [:div.field - [:p.help "Location"] + [:p.help "Account Type"] [:div.control [:div.select [bind-field @@ -85,15 +110,13 @@ :event change-event :subscription account} (map (fn [l] - [:option {:value (name l)} (str/capitalize (name l))]) types)]]]]] (when error [:div.notification.is-warning.animated.fadeInUp error]) - - [:submit.button.is-large.is-primary {#_:disabled #_(if (s/valid? :entity/client @(re-frame/subscribe [::new-client-request])) + [:button.button.is-large.is-primary {:disabled (if (s/valid? ::entity/account @(re-frame/subscribe [::account-request])) "" "disabled") :on-click (dispatch-event [::saving edit-completed])