implemented crud
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
[clj-time.core :as time]
|
||||
[clj-time.coerce :as coerce]))
|
||||
|
||||
(def uri "datomic:sql://invoices-backup?jdbc:postgresql://database:5432/datomic?user=datomic&password=datomic")
|
||||
(def uri "datomic:sql://invoices?jdbc:postgresql://database:5432/datomic?user=datomic&password=datomic")
|
||||
|
||||
(defn create-database []
|
||||
(d/create-database uri))
|
||||
|
||||
@@ -20,12 +20,15 @@
|
||||
:args [db]}
|
||||
(:sort-by args) (add-sorter-field {"client" ['[?e :transaction-rule/client ?c]
|
||||
'[?c :client/name ?sorter]]
|
||||
|
||||
"yodlee-merchant" ['[?e :transaction-rule/yodlee-merchant ?c]
|
||||
'[?c :yodlee-merchant/name ?sorter]]
|
||||
"bank-account" ['[?e :transaction-rule/bank-account ?c]
|
||||
'[?c :bank-account/name ?sorter]]
|
||||
"amount_lte" ['[?e :transaction-rule/amount-lte ?sorter]]
|
||||
"amount_gte" ['[?e :transaction-rule/amount-gte ?sorter]]
|
||||
"description" ['[?e :transaction-rule/description ?sorter]]
|
||||
"note" ['[?e :transaction-rule/note ?sorter]]
|
||||
"amount-lte" ['[?e :transaction-rule/amount-lte ?sorter]]
|
||||
"amount-gte" ['[?e :transaction-rule/amount-gte ?sorter]]
|
||||
}
|
||||
args)
|
||||
|
||||
|
||||
@@ -39,7 +39,14 @@
|
||||
:ident {:parse (schema/as-conformer (fn [x] {:db/ident x}))
|
||||
:serialize (schema/as-conformer #(or (:ident %) (:db/ident %) %))}
|
||||
:iso_date {:parse (schema/as-conformer #(time/parse % time/iso-date))
|
||||
:serialize (schema/as-conformer #(time/unparse % time/iso-date))}}
|
||||
:serialize (schema/as-conformer #(time/unparse % time/iso-date))}
|
||||
:money {:parse (schema/as-conformer #(if (string? %)
|
||||
(Double/parseDouble %)
|
||||
%))
|
||||
:serialize (schema/as-conformer #(if (double? %)
|
||||
(str %)
|
||||
%))
|
||||
}}
|
||||
:objects
|
||||
{
|
||||
:client
|
||||
@@ -493,6 +500,15 @@
|
||||
:vendor_id {:type :id}
|
||||
:accounts {:type '(list :edit_expense_account)}}}
|
||||
|
||||
:edit_transaction_rule
|
||||
{:fields {:id {:type :id}
|
||||
:description {:type 'String}
|
||||
:note {:type 'String}
|
||||
:bank_account_id {:type :id}
|
||||
:client_id {:type :id}
|
||||
:amount_lte {:type :money}
|
||||
:amount_gte {:type :money}}}
|
||||
|
||||
:edit_account
|
||||
{:fields {:id {:type :id}
|
||||
:type {:type :account_type}
|
||||
@@ -552,6 +568,10 @@
|
||||
:upsert_vendor {:type :vendor
|
||||
:args {:vendor {:type :add_vendor}}
|
||||
:resolve :mutation/upsert-vendor}
|
||||
|
||||
:upsert_transaction_rule {:type :transaction_rule
|
||||
:args {:transaction_rule {:type :edit_transaction_rule}}
|
||||
:resolve :mutation/upsert-transaction-rule}
|
||||
:add_invoice {:type :invoice
|
||||
:args {:invoice {:type :add_invoice}}
|
||||
:resolve :mutation/add-invoice}
|
||||
@@ -739,6 +759,7 @@
|
||||
:mutation/add-and-print-invoice gq-invoices/add-and-print-invoice
|
||||
:mutation/edit-invoice gq-invoices/edit-invoice
|
||||
:mutation/edit-transaction gq-transactions/edit-transaction
|
||||
:mutation/upsert-transaction-rule gq-transaction-rules/upsert-transaction-rule
|
||||
:mutation/match-transaction gq-transactions/match-transaction
|
||||
:mutation/edit-client gq-clients/edit-client
|
||||
:mutation/upsert-vendor gq-vendors/upsert-vendor
|
||||
|
||||
@@ -1,8 +1,28 @@
|
||||
(ns auto-ap.graphql.transaction-rules
|
||||
(:require [auto-ap.datomic.transaction-rules :as tr]
|
||||
[datomic.api :as d]
|
||||
[auto-ap.datomic :refer [remove-nils uri]]
|
||||
[auto-ap.graphql.utils :refer [->graphql <-graphql limited-clients assert-admin result->page]]))
|
||||
|
||||
(defn get-transaction-rule-page [context args value]
|
||||
(let [args (assoc args :id (:id context))
|
||||
[journal-entries journal-entries-count] (tr/get-graphql (<-graphql args))]
|
||||
(result->page journal-entries journal-entries-count :transaction_rules args)))
|
||||
|
||||
(defn upsert-transaction-rule [context {{:keys [id description note client_id bank_account_id amount_lte amount_gte ]} :transaction_rule :as z} value]
|
||||
(let [transaction [(remove-nils #:transaction-rule {:db/id (if id
|
||||
id
|
||||
"transaction-rule")
|
||||
:description description
|
||||
:note note
|
||||
:client client_id
|
||||
:bank-account bank_account_id
|
||||
:amount-lte amount_lte
|
||||
:amount-gte amount_gte})]
|
||||
_ (println transaction)
|
||||
transaction-result @(d/transact (d/connect uri) transaction)]
|
||||
(println "HI" (or (-> transaction-result )
|
||||
id))
|
||||
(-> (tr/get-by-id (or (-> transaction-result :tempids (get "transaction-rule"))
|
||||
id))
|
||||
(->graphql))))
|
||||
|
||||
11
src/cljc/auto_ap/entities/transaction_rule.cljc
Normal file
11
src/cljc/auto_ap/entities/transaction_rule.cljc
Normal file
@@ -0,0 +1,11 @@
|
||||
(ns auto-ap.entities.transaction-rule
|
||||
(:require [clojure.spec.alpha :as s]))
|
||||
|
||||
(s/def ::client (s/nilable map?))
|
||||
(s/def ::description (s/nilable string?))
|
||||
(s/def ::amount-gte (s/nilable double?))
|
||||
(s/def ::amount-lte (s/nilable double?))
|
||||
(s/def ::note (s/nilable string?))
|
||||
(s/def ::bank-account (s/nilable map?))
|
||||
|
||||
(s/def ::transaction-rule (s/keys :req-un [::client ::description ::amount-gte ::amount-lte ::note ::bank-account]))
|
||||
@@ -63,6 +63,11 @@
|
||||
(fn [client]
|
||||
(->> client :bank-accounts (filter #(= (:type %) :check)) (sort-by :sort-order))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::real-bank-accounts-for-client
|
||||
(fn [db [_ {:keys [id]}]]
|
||||
(sort-by :sort-order (-> db :clients (get id) :bank-accounts ))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::locations-for-client
|
||||
|
||||
|
||||
@@ -4,9 +4,14 @@
|
||||
[auto-ap.views.components.admin.side-bar :refer [admin-side-bar]]
|
||||
[auto-ap.views.components.layouts :refer [appearing-side-bar side-bar-layout]]
|
||||
[auto-ap.views.pages.admin.rules.table :as table]
|
||||
[auto-ap.views.pages.admin.rules.form :as form]
|
||||
[auto-ap.views.pages.admin.rules.common :refer [default-read]]
|
||||
[auto-ap.views.utils :refer [dispatch-event with-user]]
|
||||
[auto-ap.utils :refer [replace-by]]
|
||||
[re-frame.core :as re-frame]))
|
||||
|
||||
;; SUBS
|
||||
|
||||
(re-frame/reg-sub
|
||||
::notification
|
||||
(fn [db]
|
||||
@@ -22,13 +27,22 @@
|
||||
(fn [db]
|
||||
(-> db (::params {}))))
|
||||
|
||||
(def rule-read [:description-matches])
|
||||
(re-frame/reg-event-db
|
||||
::edit-completed
|
||||
(fn [db [_ edit-transaction-rule]]
|
||||
(println edit-transaction-rule)
|
||||
(-> db
|
||||
(update-in [::page :transaction-rules]
|
||||
replace-by :id (assoc edit-transaction-rule :class "live-added")))))
|
||||
|
||||
;; EVENTS
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::received
|
||||
(fn [db [_ data]]
|
||||
(println data)
|
||||
(-> db
|
||||
(update ::page merge (first (:rule-page data)))
|
||||
(update ::page merge (:transaction-rule-page data))
|
||||
(assoc-in [:status :loading] false))))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
@@ -39,14 +53,22 @@
|
||||
(assoc-in [:status :loading] true)
|
||||
(assoc-in [::params] params))
|
||||
:graphql {:token user
|
||||
:query-obj {:venia/queries [[:rule_page
|
||||
:query-obj {:venia/queries [[:transaction_rule_page
|
||||
(assoc params :client-id (:id @(re-frame/subscribe [::subs/client])))
|
||||
[[:rules rule-read]
|
||||
[[:transaction-rules default-read]
|
||||
:total
|
||||
:start
|
||||
:end]]]}
|
||||
:on-success [::received]}}))
|
||||
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::new-rule-clicked
|
||||
(fn [{:keys [db]} _]
|
||||
{:dispatch [::form/adding {:client @(re-frame/subscribe [::subs/client])}]}))
|
||||
|
||||
;; VIEWS
|
||||
|
||||
(def rules-content
|
||||
(with-meta
|
||||
(fn []
|
||||
@@ -57,17 +79,19 @@
|
||||
[:h1.title "Transaction Rules"]
|
||||
(when (= "admin" (:user/role user))
|
||||
[:div.is-pulled-right
|
||||
[:button.button.is-outlined.is-primary {:on-click (dispatch-event [::create-rule-clicked])} "New Rule"]])
|
||||
[:button.button.is-outlined.is-primary {:on-click (dispatch-event [::new-rule-clicked])} "New Rule"]])
|
||||
[table/table {:id :transactions
|
||||
:params (re-frame/subscribe [::params])
|
||||
:rule-page (re-frame/subscribe [::page])
|
||||
:status (re-frame/subscribe [::subs/status])
|
||||
:on-params-change (fn [params]
|
||||
(re-frame/dispatch [::params-change params]))}]
|
||||
]))
|
||||
{:component-will-mount #(re-frame/dispatch-sync [::params-change {}]) }))
|
||||
|
||||
(defn admin-rules-page []
|
||||
(let [{:keys [active?]} @(re-frame/subscribe [::forms/form ::new-client])]
|
||||
(let [{:keys [active?]} @(re-frame/subscribe [::forms/form ::form/form])]
|
||||
[side-bar-layout {:side-bar [admin-side-bar {}]
|
||||
:main [rules-content]
|
||||
:right-side-bar [appearing-side-bar {:visible? active?} [:div]] }]))
|
||||
:right-side-bar [appearing-side-bar {:visible? active?}
|
||||
[form/form {:rule-saved [::edit-completed]}]] }]))
|
||||
|
||||
10
src/cljs/auto_ap/views/pages/admin/rules/common.cljs
Normal file
10
src/cljs/auto_ap/views/pages/admin/rules/common.cljs
Normal file
@@ -0,0 +1,10 @@
|
||||
(ns auto-ap.views.pages.admin.rules.common)
|
||||
|
||||
(def default-read [:id
|
||||
:description
|
||||
:note
|
||||
:amount-gte
|
||||
:amount-lte
|
||||
[:client [:name :id]]
|
||||
[:bank-account [:name :id]]
|
||||
])
|
||||
149
src/cljs/auto_ap/views/pages/admin/rules/form.cljs
Normal file
149
src/cljs/auto_ap/views/pages/admin/rules/form.cljs
Normal file
@@ -0,0 +1,149 @@
|
||||
(ns auto-ap.views.pages.admin.rules.form
|
||||
(:require [auto-ap.entities.transaction-rule :as entity]
|
||||
[auto-ap.events :as events]
|
||||
[auto-ap.forms :as forms]
|
||||
[auto-ap.subs :as subs]
|
||||
[auto-ap.utils :refer [dollars=]]
|
||||
[auto-ap.views.components.dropdown :refer [drop-down]]
|
||||
[auto-ap.views.components.expense-accounts-field :as expense-accounts-field :refer [expense-accounts-field recalculate-amounts]]
|
||||
[auto-ap.views.components.layouts :as layouts]
|
||||
[auto-ap.views.components.typeahead :refer [typeahead-entity]]
|
||||
[auto-ap.views.pages.admin.rules.common :refer [default-read]]
|
||||
[auto-ap.views.utils :refer [date->str date-picker dispatch-event standard with-user]]
|
||||
[cljs-time.core :as c]
|
||||
[clojure.spec.alpha :as s]
|
||||
[clojure.string :as str]
|
||||
[re-frame.core :as re-frame]))
|
||||
|
||||
;; SUBS
|
||||
|
||||
|
||||
(re-frame/reg-sub
|
||||
::can-submit
|
||||
:<- [::forms/form ::form]
|
||||
(fn [{:keys [data status]} _]
|
||||
(s/valid? ::entity/transaction-rule data)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::query
|
||||
:<- [::forms/form ::form]
|
||||
(fn [{:keys [data] }]
|
||||
{:venia/operation {:operation/type :mutation
|
||||
:operation/name "UpsertTransactionRule"}
|
||||
:venia/queries [{:query/data [:upsert-transaction-rule
|
||||
{:transaction-rule (-> data
|
||||
(select-keys [:id
|
||||
:description
|
||||
:amount-lte
|
||||
:amount-gte
|
||||
:note])
|
||||
(assoc :client-id (:id (:client data)))
|
||||
(assoc :bank-account-id (:id (:bank-account data))))}
|
||||
default-read]}]}))
|
||||
|
||||
;; EVENTS
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::adding
|
||||
(fn [db [_ new]]
|
||||
(-> db (forms/start-form ::form (assoc new
|
||||
:description nil)))))
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::editing
|
||||
(fn [db [_ which]]
|
||||
(-> db (forms/start-form ::form {}))))
|
||||
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::changed
|
||||
(forms/change-handler ::form
|
||||
(fn [data field value]
|
||||
[])))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::saving
|
||||
[with-user (forms/triggers-loading ::form) (forms/in-form ::form)]
|
||||
(fn [{:keys [user] {:keys [data]} :db} [_ params]]
|
||||
{:graphql
|
||||
{:token user
|
||||
:query-obj @(re-frame/subscribe [::query])
|
||||
:on-success [::succeeded params]
|
||||
:on-error [::forms/save-error ::form]}}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::succeeded
|
||||
[(forms/triggers-stop ::form)]
|
||||
(fn [{:keys [db]} [_ {:keys [rule-saved]} result]]
|
||||
{:db (forms/start-form db ::form {:client @(re-frame/subscribe [::subs/client])})
|
||||
:dispatch (conj rule-saved (:upsert-transaction-rule result))}))
|
||||
|
||||
|
||||
|
||||
;; VIEWS
|
||||
|
||||
(def rule-form (forms/vertical-form {:can-submit [::can-submit]
|
||||
:change-event [::changed]
|
||||
:submit-event [::saving ]
|
||||
:id ::form}))
|
||||
|
||||
(defn form [{:keys [can-change-amount?] :as params}]
|
||||
[layouts/side-bar {:on-close (dispatch-event [::forms/form-closing ::form ])}
|
||||
(let [{:keys [data active? error id]} @(re-frame/subscribe [::forms/form ::form])
|
||||
{:keys [form field raw-field error-notification submit-button ]} rule-form
|
||||
exists? (:id data)
|
||||
chooseable-expense-accounts @(re-frame/subscribe [::subs/chooseable-expense-accounts])
|
||||
accounts-by-id @(re-frame/subscribe [::subs/accounts-for-client-by-id])]
|
||||
^{:key id}
|
||||
[form (assoc params :title "New Invoice")
|
||||
(when-not @(re-frame/subscribe [::subs/client])
|
||||
[field "Client"
|
||||
[typeahead-entity {:matches @(re-frame/subscribe [::subs/clients])
|
||||
:match->text :name
|
||||
:type "typeahead-entity"
|
||||
:auto-focus (if @(re-frame/subscribe [::subs/client]) false true)
|
||||
:field [:client]
|
||||
:spec ::entity/client}]])
|
||||
|
||||
[field "Bank account"
|
||||
[typeahead-entity {:matches @(re-frame/subscribe [::subs/real-bank-accounts-for-client (:client data)])
|
||||
:match->text :name
|
||||
:auto-focus (if @(re-frame/subscribe [::subs/client]) true false)
|
||||
:type "typeahead-entity"
|
||||
:field [:bank-account]
|
||||
:spec ::entity/bank-account}]]
|
||||
|
||||
[field "Description"
|
||||
[:input.input {:type "text"
|
||||
:field [:description]
|
||||
:spec ::entity/description}]]
|
||||
|
||||
[:div.field
|
||||
[:p.help "Amount"]
|
||||
[:div.control
|
||||
[:div.columns
|
||||
[:div.column
|
||||
[raw-field
|
||||
[:input.input {:type "number"
|
||||
:placeholder ">="
|
||||
:field [:amount-gte]
|
||||
:spec ::entity/amount-gte
|
||||
:step "0.01"}]]]
|
||||
[:div.column
|
||||
[raw-field
|
||||
[:input.input {:type "number"
|
||||
:placeholder "<="
|
||||
:field [:amount-lte]
|
||||
:spec ::entity/amount-lte
|
||||
:step "0.01"}]]]]]]
|
||||
|
||||
[field "Note"
|
||||
[:input.input {:type "text"
|
||||
:field [:note]
|
||||
:spec ::entity/note}]]
|
||||
|
||||
|
||||
|
||||
[error-notification]
|
||||
|
||||
[submit-button "Save"]])])
|
||||
@@ -1,5 +1,76 @@
|
||||
(ns auto-ap.views.pages.admin.rules.table)
|
||||
(ns auto-ap.views.pages.admin.rules.table
|
||||
(:require [auto-ap.subs :as subs]
|
||||
[auto-ap.views.components.paginator :refer [paginator]]
|
||||
[auto-ap.views.components.sorter :refer [sorted-column]]
|
||||
[re-frame.core :as re-frame]))
|
||||
|
||||
(defn table [{:keys [id rule-page on-params-change params status]}]
|
||||
(let [opc (fn [p]
|
||||
(on-params-change (merge @params p )))]
|
||||
(fn [{:keys [id rule-page on-params-change params status]}]
|
||||
(let [{:keys [sort-by asc]} @params
|
||||
{:keys [transaction-rules start end count total]} @rule-page
|
||||
selected-client @(re-frame/subscribe [::subs/client])]
|
||||
[:div
|
||||
[paginator {:start start :end end :count count :total total
|
||||
:on-change (fn [p ]
|
||||
(on-params-change (merge @params p)))}]
|
||||
[:table.table.is-fullwidth.compact
|
||||
[:thead
|
||||
[:tr
|
||||
[sorted-column {:on-sort opc
|
||||
:style {:width "25%" :cursor "pointer"}
|
||||
:sort-key "client"
|
||||
:sort-by sort-by
|
||||
:asc asc}
|
||||
"Client"]
|
||||
|
||||
(defn table [x]
|
||||
[:div])
|
||||
[sorted-column {:on-sort opc
|
||||
:style {:width "25%" :cursor "pointer"}
|
||||
:sort-key "bank-account"
|
||||
:sort-by sort-by
|
||||
:asc asc}
|
||||
"Bank Account"]
|
||||
|
||||
[sorted-column {:on-sort opc
|
||||
:style {:width "25%" :cursor "pointer"}
|
||||
:sort-key "description"
|
||||
:sort-by sort-by
|
||||
:asc asc}
|
||||
"Description"]
|
||||
|
||||
[sorted-column {:on-sort opc
|
||||
:style {:width "8em" :cursor "pointer"}
|
||||
:class "has-text-right"
|
||||
:sort-key "amount-gte"
|
||||
:sort-by sort-by
|
||||
:asc asc}
|
||||
">="]
|
||||
[sorted-column {:on-sort opc
|
||||
:class "has-text-right"
|
||||
:style {:width "8em" :cursor "pointer"}
|
||||
:sort-key "amount-lte"
|
||||
:sort-by sort-by
|
||||
:asc asc}
|
||||
"<="]
|
||||
|
||||
[sorted-column {:on-sort opc
|
||||
:style {:width "25%" :cursor "pointer"}
|
||||
:sort-key "note"
|
||||
:sort-by sort-by
|
||||
:asc asc}
|
||||
"Note"]]]
|
||||
[:tbody
|
||||
(if (:loading @status)
|
||||
[:tr
|
||||
[:td {:col-span 5}
|
||||
[:i.fa.fa-spin.fa-spinner]]]
|
||||
(for [{:keys [client bank-account description amount-lte amount-gte note] :as r} transaction-rules]
|
||||
^{:key id}
|
||||
[:tr {:class (:class r)}
|
||||
[:td (:name client)]
|
||||
[:td (:name bank-account)]
|
||||
[:td description]
|
||||
[:td.has-text-right amount-gte ]
|
||||
[:td.has-text-right amount-lte]
|
||||
[:td note]]))]]]))))
|
||||
|
||||
Reference in New Issue
Block a user