Accounts don't need to be loaded

This commit is contained in:
2022-04-19 13:27:47 -07:00
parent f73b406abd
commit f51f3450d6
22 changed files with 398 additions and 420 deletions

View File

@@ -11,6 +11,16 @@
:account-client-override/name :account-client-override/name
{:account-client-override/client [:db/id :client/name]}]}]) {:account-client-override/client [:db/id :client/name]}]}])
(defn clientize [a client]
(if-let [override-name (->> a
:account/client-overrides
(filter #(= client
(:db/id (:account-client-override/client %))))
first
:account-client-override/name)]
(assoc a :account/name override-name)
a))
(defn get-accounts (defn get-accounts
([] ([]
(get-accounts {})) (get-accounts {}))

View File

@@ -6,13 +6,18 @@
[clj-time.coerce :as coerce] [clj-time.coerce :as coerce]
[auto-ap.time-utils :refer [next-dom]] [auto-ap.time-utils :refer [next-dom]]
[clj-time.core :as time] [clj-time.core :as time]
[auto-ap.datomic.vendors :as d-vendors])) [auto-ap.datomic.vendors :as d-vendors]
[clojure.tools.logging :as log]
[auto-ap.datomic.accounts :as d-accounts]))
(def default-read '[* (def default-read '[*
{:invoice/client [:client/name :db/id :client/locations :client/code]} {:invoice/client [:client/name :db/id :client/locations :client/code]}
{:invoice/vendor [* {:vendor/address [*]}]} {:invoice/vendor [* {:vendor/address [*]}]}
{:invoice/status [:db/ident]} {:invoice/status [:db/ident]}
{:invoice/expense-accounts [* {:invoice-expense-account/account [*]}]} {:invoice/expense-accounts [* {:invoice-expense-account/account [:account/name :db/id
:account/location
{:account/client-overrides [:account-client-override/name
{:account-client-override/client [:db/id]}]}]}]}
{:invoice-payment/_invoice [* {:invoice-payment/payment [* {:payment/status [*]} {:invoice-payment/_invoice [* {:invoice-payment/payment [* {:payment/status [*]}
{:payment/bank-account [*]} {:payment/bank-account [*]}
{:transaction/_payment [*]}]}]}]) {:transaction/_payment [*]}]}]}])
@@ -23,6 +28,10 @@
(update :invoice/due coerce/from-date) (update :invoice/due coerce/from-date)
(update :invoice/scheduled-payment coerce/from-date) (update :invoice/scheduled-payment coerce/from-date)
(update :invoice/status :db/ident) (update :invoice/status :db/ident)
(update :invoice/expense-accounts (fn [eas]
(map
#(update % :invoice-expense-account/account d-accounts/clientize (:db/id (:invoice/client x)))
eas)))
(rename-keys {:invoice-payment/_invoice :invoice/payments}))) (rename-keys {:invoice-payment/_invoice :invoice/payments})))
(defn raw-graphql-ids (defn raw-graphql-ids

View File

@@ -1,13 +1,9 @@
(ns auto-ap.datomic.ledger (ns auto-ap.datomic.ledger
(:require [datomic.api :as d] (:require [datomic.api :as d]
[auto-ap.graphql.utils :refer [->graphql limited-clients]] [auto-ap.graphql.utils :refer [limited-clients]]
[auto-ap.utils :refer [dollars-0?]]
[auto-ap.datomic :refer [merge-query apply-sort-3 apply-pagination add-sorter-fields conn]] [auto-ap.datomic :refer [merge-query apply-sort-3 apply-pagination add-sorter-fields conn]]
[auto-ap.datomic :refer [uri]]
[clojure.tools.logging :as log]
[clj-time.coerce :as c] [clj-time.coerce :as c]
[clj-time.core :as time])) [auto-ap.datomic.accounts :as d-accounts]))
(def export-read (def export-read
[:journal-entry/external-id [:journal-entry/external-id
@@ -34,12 +30,12 @@
:account/name :account/name
:account/numeric-code :account/numeric-code
:account/location :account/location
{:account/client-overrides [:account-client-override/name
{:account-client-override/client [:db/id]}]}
{:account/type [:db/ident :db/id]} {:account/type [:db/ident :db/id]}
{:bank-account/type [:db/ident :db/id]}]}]}]) {:bank-account/type [:db/ident :db/id]}]}]}])
(defn raw-graphql-ids [db args] (defn raw-graphql-ids [db args]
(log/info "ARGS" args)
(let [query (cond-> {:query {:find [] (let [query (cond-> {:query {:find []
:in ['$ ] :in ['$ ]
:where []} :where []}
@@ -161,20 +157,27 @@
true true
(merge-query {:query {:find ['?sort-default '?e] :where ['[?e :journal-entry/date ?sort-default]]}}))] (merge-query {:query {:find ['?sort-default '?e] :where ['[?e :journal-entry/date ?sort-default]]}}))]
(->> (doto query log/info) (->> query
(d/query) (d/query)
(apply-sort-3 (update args :sort conj {:sort-key "default-2" :asc true})) (apply-sort-3 (update args :sort conj {:sort-key "default-2" :asc true}))
(apply-pagination args)))) (apply-pagination args))))
(defn graphql-results [ids db args] (defn graphql-results [ids db _]
(let [results (->> (d/pull-many db '[* {:journal-entry/client [:client/name :client/code :db/id] (let [results (->> (d/pull-many db '[* {:journal-entry/client [:client/name :client/code :db/id]
:journal-entry/vendor [:vendor/name :db/id] :journal-entry/vendor [:vendor/name :db/id]
:journal-entry/line-items [* {:journal-entry-line/account [* :journal-entry/line-items [* {:journal-entry-line/account [*
{:account/type [*]} {:account/type [*]}
{:account/client-overrides [:account-client-override/name
{:account-client-override/client [:db/id]}]}
{:bank-account/type [*]}]}]}] {:bank-account/type [*]}]}]}]
ids) ids)
(map #(update % :journal-entry/date c/from-date)) (map #(update % :journal-entry/date c/from-date))
(map (fn [je]
(update je :journal-entry/line-items
(fn [jels]
(map
#(update % :journal-entry-line/account d-accounts/clientize (:db/id (:journal-entry/client je)))
jels)))))
(filter (fn [je] (filter (fn [je]
(every? (every?
(fn [jel] (fn [jel]
@@ -191,12 +194,9 @@
(defn get-graphql [args] (defn get-graphql [args]
(let [db (d/db conn) (let [db (d/db conn)
{ids-to-retrieve :ids matching-count :count} (raw-graphql-ids db args)] {ids-to-retrieve :ids matching-count :count} (raw-graphql-ids db args)]
[(->> (graphql-results ids-to-retrieve db args)) [(->> (graphql-results ids-to-retrieve db args))
matching-count])) matching-count]))
(defn filter-ids [ids] (defn filter-ids [ids]
(if ids (if ids
(->> {:query {:find ['?e] (->> {:query {:find ['?e]
@@ -207,8 +207,3 @@
(map first) (map first)
vec) vec)
[])) []))

View File

@@ -142,6 +142,22 @@
{:db/id accounts-payable {:db/id accounts-payable
:db/ident :account/accounts-payable}]])) :db/ident :account/accounts-payable}]]))
(defn add-account-search-terms [conn]
[(->> (d/q '[:find ?i ?n
:in $
:where [?i :account/name ?n]]
(d/db conn))
(map (fn [[i n]]
{:db/id i
:account/search-terms n})))
(->> (d/q '[:find ?i ?n
:in $
:where [?i :account-client-override/name ?n]]
(d/db conn))
(map (fn [[i n]]
{:db/id i
:account-client-override/search-terms n})))])
(defn migrate [conn] (defn migrate [conn]
(let [ (let [
norms-map (merge {:auto-ap/base-schema {:txes auto-ap.datomic/base-schema} norms-map (merge {:auto-ap/base-schema {:txes auto-ap.datomic/base-schema}
@@ -491,7 +507,20 @@
:db/valueType :db.type/boolean :db/valueType :db.type/boolean
:db/cardinality :db.cardinality/one}]]} :db/cardinality :db.cardinality/one}]]}
:auto-ap/add-payment-type-credit {:txes [[{:db/ident :payment-type/credit :auto-ap/add-payment-type-credit {:txes [[{:db/ident :payment-type/credit
:db/doc "Credit for negative invoices"}]]}} :db/doc "Credit for negative invoices"}]]}
:auto-ap/fulltext-accounts {:txes [[{:db/ident :account/search-terms
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db/doc "a name search for accounts"
:db/fulltext true}
{:db/ident :account-client-override/search-terms
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db/doc "a name search for accounts"
:db/fulltext true}]]
:requires [:auto-ap/add-account-overrides]}
:auto-ap/add-search-terms-accounts {:txes-fn `add-account-search-terms
:requires [:auto-ap/fulltext-accounts]}}

View File

@@ -5,7 +5,8 @@
[clj-time.coerce :as c] [clj-time.coerce :as c]
[clj-time.coerce :as coerce] [clj-time.coerce :as coerce]
[clojure.tools.logging :as log] [clojure.tools.logging :as log]
[clojure.string :as str])) [clojure.string :as str]
[auto-ap.datomic.accounts :as d-accounts]))
(defn sort-fn [sort-by] (defn sort-fn [sort-by]
(cond (cond
@@ -194,11 +195,20 @@
:transaction/accounts [:transaction-account/amount :transaction/accounts [:transaction-account/amount
:db/id :db/id
:transaction-account/location :transaction-account/location
{:transaction-account/account [:db/id :account/name :account/numeric-code]}] {:transaction-account/account [:account/name :db/id
:account/location
{:account/client-overrides [:account-client-override/name
{:account-client-override/client [:db/id]}]}]}]
:transaction/yodlee-merchant [:db/id :yodlee-merchant/yodlee-id :yodlee-merchant/name]}] :transaction/yodlee-merchant [:db/id :yodlee-merchant/yodlee-id :yodlee-merchant/name]}]
ids) ids)
(map #(update % :transaction/date c/from-date)) (map #(update % :transaction/date c/from-date))
(map #(update % :transaction/post-date c/from-date)) (map #(update % :transaction/post-date c/from-date))
(map #(update % :transaction/accounts
(fn [tas]
(map
(fn [ta]
(update ta :transaction-account/account d-accounts/clientize (:db/id (:transaction/client %))))
tas))))
(map (fn [transaction] (map (fn [transaction]
(cond-> transaction (cond-> transaction
(:transaction/payment transaction) (update-in [:transaction/payment :payment/date] c/from-date) (:transaction/payment transaction) (update-in [:transaction/payment :payment/date] c/from-date)
@@ -240,7 +250,10 @@
:transaction/accounts [:transaction-account/amount :transaction/accounts [:transaction-account/amount
:db/id :db/id
:transaction-account/location :transaction-account/location
{ :transaction-account/account [:db/id :account/name :account/numeric-code]}] { :transaction-account/account [:account/name :db/id
:account/location
{:account/client-overrides [:account-client-override/name
{:account-client-override/client [:db/id]}]}]}]
:transaction/yodlee-merchant [:db/id :yodlee-merchant/yodlee-id :yodlee-merchant/name]}] :transaction/yodlee-merchant [:db/id :yodlee-merchant/yodlee-id :yodlee-merchant/name]}]
id) id)
(update :transaction/date c/from-date) (update :transaction/date c/from-date)

View File

@@ -3,7 +3,8 @@
[auto-ap.datomic :refer [conn merge-query uri add-sorter-fields apply-pagination merge-query apply-sort-3]] [auto-ap.datomic :refer [conn merge-query uri add-sorter-fields apply-pagination merge-query apply-sort-3]]
[auto-ap.graphql.utils :refer [limited-clients]] [auto-ap.graphql.utils :refer [limited-clients]]
[clojure.string :as str] [clojure.string :as str]
[datomic.api :as d])) [datomic.api :as d]
[auto-ap.datomic.accounts :as d-accounts]))
(defn <-datomic [a] (defn <-datomic [a]
(cond-> a (cond-> a
@@ -18,21 +19,28 @@
nil)] nil)]
(if clients (if clients
(-> vendor (-> vendor
(update :vendor/account-overrides (fn [ao] (filter #(clients (:db/id (:vendor-account-override/client %))) ao))) (update :vendor/account-overrides (fn [aos]
(->> aos
(filter #(clients (:db/id (:vendor-account-override/client %))))
(map #(update % :vendor-account-override/account d-accounts/clientize (:db/id (:vendor-account-override/client %)))))))
(update :vendor/terms-overrides (fn [to] (filter #(clients (:db/id (:vendor-terms-override/client %))) to))) (update :vendor/terms-overrides (fn [to] (filter #(clients (:db/id (:vendor-terms-override/client %))) to)))
(update :vendor/schedule-payment-dom (fn [to] (filter #(clients (:db/id (:vendor-schedule-payment-dom/client %))) to)))) (update :vendor/schedule-payment-dom (fn [to] (filter #(clients (:db/id (:vendor-schedule-payment-dom/client %))) to))))
vendor))) (-> vendor
(update :vendor/account-overrides (fn [aos]
(->> aos
(map #(update % :vendor-account-override/account d-accounts/clientize (:db/id (:vendor-account-override/client %)))))))))))
(def default-read (def default-read
'[* {:vendor/account-overrides [* {:vendor-account-override/client [:client/name :db/id] '[* {:vendor/account-overrides [* {:vendor-account-override/client [:client/name :db/id]
: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]}] {:account/client-overrides [:account-client-override/client :account-client-override/name]}]}]
:vendor/schedule-payment-dom [* {:vendor-schedule-payment-dom/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/automatically-paid-when-due [:db/id :client/name] :vendor/automatically-paid-when-due [:db/id :client/name]
:vendor/legal-entity-tin-type [:db/ident :db/id] :vendor/legal-entity-tin-type [:db/ident :db/id]
:vendor/legal-entity-1099-type [:db/ident :db/id] :vendor/legal-entity-1099-type [:db/ident :db/id]
:vendor/default-account [:db/id :account/numeric-code :account/name] :vendor/default-account [:db/id :account/numeric-code :account/name]
:vendor-usage/_vendor [:vendor-usage/client :vendor-usage/count]}]) :vendor-usage/_vendor [:vendor-usage/client :vendor-usage/count]}])
(defn get-usages [args] (defn get-usages [args]
(->> (cond-> {:query {:find ['?v '?c '(count ?e)] (->> (cond-> {:query {:find ['?v '?c '(count ?e)]

View File

@@ -102,6 +102,11 @@
{:fields {:name {:type 'String} {:fields {:name {:type 'String}
:id {:type :id}}} :id {:type :id}}}
:account_search_result
{:fields {:name {:type 'String}
:id {:type :id}
:location {:type 'String}}}
:yodlee_provider_account :yodlee_provider_account
{:fields {:id {:type 'Int} {:fields {:id {:type 'Int}
:client {:type :client} :client {:type :client}
@@ -360,6 +365,10 @@
:search_vendor {:type '(list :search_result) :search_vendor {:type '(list :search_result)
:args {:query {:type 'String}} :args {:query {:type 'String}}
:resolve :search-vendor} :resolve :search-vendor}
:search_account {:type '(list :account_search_result)
:args {:query {:type 'String}
:client_id {:type :id}}
:resolve :search-account}
@@ -816,7 +825,8 @@
:mutation/merge-vendors gq-vendors/merge-vendors :mutation/merge-vendors gq-vendors/merge-vendors
:mutation/request-import gq-requests/request-import :mutation/request-import gq-requests/request-import
:get-vendor gq-vendors/get-graphql :get-vendor gq-vendors/get-graphql
:search-vendor gq-vendors/search}) :search-vendor gq-vendors/search
:search-account gq-accounts/search})
gq-checks/attach gq-checks/attach
gq-ledger/attach gq-ledger/attach
gq-reports/attach gq-reports/attach

View File

@@ -1,51 +1,48 @@
(ns auto-ap.graphql.accounts (ns auto-ap.graphql.accounts
(:require (:require
[auto-ap.datomic :refer [audit-transact remove-nils uri]] [auto-ap.datomic :refer [audit-transact remove-nils conn]]
[auto-ap.datomic.accounts :as d-accounts] [auto-ap.datomic.accounts :as d-accounts]
[auto-ap.graphql.utils [auto-ap.graphql.utils
:refer [->graphql <-graphql assert-can-see-client enum->keyword]] :refer [->graphql <-graphql assert-can-see-client enum->keyword]]
[datomic.api :as d])) [datomic.api :as d]
[clojure.tools.logging :as log]))
(defn get-accounts [context args value] (defn get-accounts [_ args _]
(->graphql (d-accounts/get-accounts (<-graphql args)))) (->graphql (d-accounts/get-accounts (<-graphql args))))
(defn default-for-vendor [context args value]
(defn default-for-vendor [context args _]
(assert-can-see-client (:id context) (:client_id args)) (assert-can-see-client (:id context) (:client_id args))
(let [result (d-accounts/get-for-vendor (:vendor_id args) (:client_id args))] (let [result (d-accounts/get-for-vendor (:vendor_id args) (:client_id args))]
(->graphql (->graphql (d-accounts/clientize result (:client_id args)))))
(if-let [override-name (->> result
:account/client-overrides
(filter #(= (:client_id args)
(:db/id (:account-client-override/client %))))
first
:account-client-override/name)]
(assoc result :account/name override-name)
result))))
(defn upsert-account [context args value] (defn upsert-account [context args _]
(let [{{:keys [id client-overrides numeric-code location applicability account-set name type]} :account} (<-graphql args)] (let [{{:keys [id client-overrides numeric-code location applicability account-set name type]} :account} (<-graphql args)]
(when-not id (when-not id
(when (seq (d/query {:query {:find ['?e] (when (seq (d/query {:query {:find ['?e]
:in '[$ ?account-set ?numeric-code] :in '[$ ?account-set ?numeric-code]
:where ['[?e :account/account-set ?account-set] :where ['[?e :account/account-set ?account-set]
'[?e :account/numeric-code ?numeric-code]]} '[?e :account/numeric-code ?numeric-code]]}
:args [(d/db (d/connect uri)) account-set numeric-code]})) :args [(d/db conn) account-set numeric-code]}))
(throw (ex-info (str "Account set " account-set " already has an account for code " numeric-code) (throw (ex-info (str "Account set " account-set " already has an account for code " numeric-code)
{} )))) {} ))))
(let [original (if id (d/entity (d/db (d/connect uri)) id)) (let [original (when id
(d/entity (d/db conn) id))
result (audit-transact (cond-> result (audit-transact (cond->
[(remove-nils [(remove-nils
{:db/id (or id "new-account") {:db/id (or id "new-account")
:account/name name :account/name name
:account/search-terms name
:account/type (keyword "account-type" (clojure.core/name type)) :account/type (keyword "account-type" (clojure.core/name type))
:account/applicability (enum->keyword applicability "account-applicability") :account/applicability (enum->keyword applicability "account-applicability")
:account/account-set account-set :account/account-set account-set
:account/location location :account/location location
:account/numeric-code (if-not id :account/numeric-code (when-not id
numeric-code) numeric-code)
:account/code (if-not id :account/code (when-not id
(str numeric-code))}) (str numeric-code))})
[:reset (or id "new-account") :account/client-overrides [:reset (or id "new-account") :account/client-overrides
(mapv (mapv
@@ -53,10 +50,55 @@
(remove-nils (remove-nils
{:db/id (:id client-override) {:db/id (:id client-override)
:account-client-override/client (:client-id client-override) :account-client-override/client (:client-id client-override)
:account-client-override/name (:name client-override)})) :account-client-override/name (:name client-override)
:account-client-override/search-terms (:name client-override)}))
client-overrides)]] client-overrides)]]
(and (not location) (:account/location original)) (conj [:db/retract (or id "new-account") :account/location (:account/location original)])) (and (not location) (:account/location original)) (conj [:db/retract (or id "new-account") :account/location (:account/location original)]))
(:id context))] (:id context))]
(->graphql (->graphql
(d-accounts/get-by-id (or id (get-in result [:tempids "new-account"]))))))) (d-accounts/get-by-id (or id (get-in result [:tempids "new-account"])))))))
(defn search [context {query :query client :client_id} _]
(when client
(assert-can-see-client (:id context) client))
(let [num (some-> (re-find #"([0-9]+)" query)
second
(not-empty )
Integer/parseInt)]
(if num
(->> (d/q '[:find ?n (pull ?i [:db/id :account/numeric-code :account/location])
:in $ ?numeric-code
:where [?i :account/numeric-code ?numeric-code]
[?i :account/name ?n]]
(d/db conn)
num)
(map (fn [[n a]]
{:name (str (:account/numeric-code a) " - " n)
:id (:db/id a)
:location (:account/location a)})))
(->> (d/q '[:find ?n (pull ?i [:db/id :account/numeric-code :account/location]) ?s
:in $ ?q
:where [(fulltext $ :account/search-terms ?q) [[?i ?n _ ?s]]]
[?i :account/numeric-code ?numeric-code]
(or [?i :account/applicability :account-applicability/global]
[?i :account/applicability :account-applicability/optional])]
(d/db conn)
query)
(concat (when client
(d/q '[:find ?n (pull ?a [:db/id :account/numeric-code :account/location]) ?s
:in $ ?c ?q
:where
[?i :account-client-override/client ?c]
[(fulltext $ :account-client-override/search-terms ?q) [[?i ?n _ ?s]]]
[?a :account/client-overrides ?i]
[?a :account/numeric-code ?numeric-code]]
(d/db conn)
client
query)))
(sort-by (comp - last))
(map (fn [[n a]]
{:name (str (:account/numeric-code a) " - " n)
:id (:db/id a)
:location (:account/location a)}))))))

View File

@@ -32,78 +32,6 @@
(fn [db] (fn [db]
(by :id (:accounts db)))) (by :id (:accounts db))))
(defn clientize-account [account client]
(let [override (->>
(:client-overrides account)
(filter (fn [co]
(= (:id (:client co)) (:id client))))
first)]
(condp = (:applicability account)
nil
(assoc account :name (or (:name override) (:name account)))
:global
(assoc account :name (or (:name override) (:name account)))
:optional
(when override
(assoc account :name (or (:name override) (:name account))))
:customized
(when override
(assoc account :name (or (:name override) (:name account)))))))
(re-frame/reg-sub
::accounts
:<- [::all-accounts]
:<- [::client]
(fn [[accounts client] [_ client-override]]
(transduce
(comp
(map
#(clientize-account % (or client-override client)))
(filter identity))
conj
[]
accounts)))
(re-frame/reg-sub
::accounts-index
:<- [::accounts]
(fn [accounts]
(doto (MiniSearch. #js {:fields #js ["numeric-code" "name" "content"]
:storeFields #js ["id" "numeric-code" "name" "content"]})
(.addAll (clj->js (map (fn [v] {:id (:id v)
:name (:name v)
:numeric-code (:numeric-code v)
:content (str (:numeric-code v) " " (:name v))})
accounts))))))
(re-frame/reg-sub
::account
(fn [[_ client]]
[(re-frame/subscribe [::accounts-by-id client])])
(fn [[as] [_ _ i]]
(as i)))
(defn accounts-by-id [accounts client]
(by :id
(map
#(clientize-account % client)
accounts)))
(re-frame/reg-sub
::accounts-by-id
(fn [[_ client-override]]
[(re-frame/subscribe [::accounts client-override])
(re-frame/subscribe [::client])])
(fn [[accounts client] ]
(accounts-by-id accounts client)))
(re-frame/reg-sub (re-frame/reg-sub
::bank-accounts ::bank-accounts
:<- [::clients] :<- [::clients]
@@ -181,15 +109,6 @@
(fn [db] (fn [db]
(::intuit-bank-accounts db))) (::intuit-bank-accounts db)))
(re-frame/reg-sub
::modal-state
(fn [db [_ id status-from]]
(if status-from
(assoc (get (:modal-state db) id)
:error-message (get-in db [:auto-ap.forms/forms status-from :error])
:saving? (= (get-in db [:auto-ap.forms/forms status-from :status]) :loading))
(get (:modal-state db) id))))
(re-frame/reg-sub (re-frame/reg-sub
::token ::token
(fn [db] (fn [db]
@@ -224,22 +143,6 @@
(fn [db] (fn [db]
(:active-page db))) (:active-page db)))
(re-frame/reg-sub
::pending-invoices
(fn [db]
(:pending (:invoices db))))
(re-frame/reg-sub
::status
(fn [db]
(:status db)))
(re-frame/reg-sub
::new-invoice-form
(fn [db]
(:new-invoice db)))
(re-frame/reg-sub (re-frame/reg-sub
::query-params ::query-params
(fn [db] (fn [db]

View File

@@ -1,15 +1,16 @@
(ns auto-ap.views.components.expense-accounts-dialog (ns auto-ap.views.components.expense-accounts-dialog
(:require [auto-ap.forms :as forms] (:require
[auto-ap.status :as status] [auto-ap.forms :as forms]
[auto-ap.subs :as subs] [auto-ap.status :as status]
[auto-ap.utils :refer [by]] [auto-ap.subs :as subs]
[auto-ap.views.components.modal :as modal] [auto-ap.utils :refer [by]]
[auto-ap.views.components.typeahead :refer [typeahead-v3]] [auto-ap.views.components.modal :as modal]
[auto-ap.views.pages.invoices.common :refer [invoice-read]] [auto-ap.views.components.typeahead.vendor :refer [search-backed-typeahead]]
[auto-ap.views.utils :refer [dispatch-event with-user]] [auto-ap.views.pages.invoices.common :refer [invoice-read]]
[clojure.string :as str] [auto-ap.views.utils :refer [dispatch-event with-user]]
[goog.string :as gstring] [clojure.string :as str]
[re-frame.core :as re-frame])) [goog.string :as gstring]
[re-frame.core :as re-frame]))
(re-frame/reg-sub (re-frame/reg-sub
::can-submit ::can-submit
@@ -95,7 +96,6 @@
{:keys [total] :or {total 0} {:keys [locations] :as client} :client} (:invoice data) {:keys [total] :or {total 0} {:keys [locations] :as client} :client} (:invoice data)
{:keys [form-inline horizontal-field field raw-field error-notification submit-button]} change-expense-accounts-form {:keys [form-inline horizontal-field field raw-field error-notification submit-button]} change-expense-accounts-form
multi-location? (> (count locations) 1) multi-location? (> (count locations) 1)
chooseable-expense-accounts @(re-frame/subscribe [::subs/accounts client])
expense-accounts-total (->> expense-accounts expense-accounts-total (->> expense-accounts
vals vals
(map :new-amount) (map :new-amount)
@@ -124,14 +124,17 @@
[:tr [:tr
[:td.expandable [:div.control [:td.expandable [:div.control
(raw-field (raw-field
[typeahead-v3 {:entities chooseable-expense-accounts [search-backed-typeahead {:search-query (fn [i]
:type "typeahead-v3" [:search_account
:entity->text (fn [x] (str (:numeric-code x) " - " (:name x))) {:query i
:field [:expense-accounts id :account]}])]] :client-id (:id client)}
[:name :id :location]])
:type "typeahead-v3"
:field [:expense-accounts id :account]}])]]
(when multi-location? (when multi-location?
[:td [:td
(if-let [forced-location (:location @(re-frame/subscribe [::subs/account client (get-in expense-accounts [id :account :id])]))] (if-let [forced-location (get-in expense-accounts [id :account :location])]
[:div.select [:div.select
[:select {:disabled "disabled" :value forced-location} [:option {:value forced-location} forced-location]]] [:select {:disabled "disabled" :value forced-location} [:option {:value forced-location} forced-location]]]
[:div.select [:div.select
@@ -175,21 +178,17 @@
(re-frame/reg-event-fx (re-frame/reg-event-fx
::show ::show
(fn [{:keys [db]} [_ i]] (fn [{:keys [db]} [_ i]]
(let [accounts-by-id @(re-frame/subscribe [::subs/accounts-by-id])] {:dispatch [::modal/modal-requested {:title "Change expense accounts"
{:dispatch [::modal/modal-requested {:title "Change expense accounts" :body [form]
:body [form] :confirm {:value "Save"
:confirm {:value "Save" :status-from [::status/single ::form]
:status-from [::status/single ::form] :class "is-primary"
:class "is-primary" :on-click (dispatch-event [::try-save])
:on-click (dispatch-event [::try-save]) :can-submit [::can-submit]
:can-submit [::can-submit] :close-event [::status/completed ::form]}}]
:close-event [::status/completed ::form]}}] :db (-> db
:db (-> db (forms/start-form ::form
(forms/start-form ::form
{:expense-accounts (by :id {:expense-accounts (by :id
(mapv (:expense-accounts i))
(fn [ea] :invoice i}))}))
(assoc ea :account (accounts-by-id (:id (:account ea)))))
(:expense-accounts i)))
:invoice i}))})))

View File

@@ -1,10 +1,10 @@
(ns auto-ap.views.components.expense-accounts-field (ns auto-ap.views.components.expense-accounts-field
(:require [auto-ap.subs :as subs] (:require
[auto-ap.views.components.typeahead :refer [typeahead-v3]] [auto-ap.views.utils :refer [->$ bind-field dispatch-event]]
[auto-ap.views.utils :refer [bind-field dispatch-event ->$]] [auto-ap.views.components.typeahead.vendor :refer [search-backed-typeahead]]
[goog.string :as gstring] [clojure.string :as str]
[re-frame.core :as re-frame] [goog.string :as gstring]
[clojure.string :as str])) [re-frame.core :as re-frame]))
(defn can-replace-with-default? [accounts] (defn can-replace-with-default? [accounts]
(and (or (not (seq accounts)) (and (or (not (seq accounts))
@@ -25,14 +25,11 @@
:account default-account}]) :account default-account}])
(defn from-graphql [accounts accounts-by-id total locations] (defn from-graphql [accounts total locations]
(if (seq accounts) (if (seq accounts)
(vec (map (vec (map
(fn [a] (fn [a]
(-> a (-> a
(update :account (fn [a]
(accounts-by-id (:id a))))
(update :amount js/parseFloat) (update :amount js/parseFloat)
(assoc :amount-percentage (* 100 (/ (js/parseFloat (:amount a)) (assoc :amount-percentage (* 100 (/ (js/parseFloat (:amount a))
(Math/abs total)))) (Math/abs total))))
@@ -92,14 +89,10 @@
(re-frame/reg-event-fx (re-frame/reg-event-fx
::expense-account-changed ::expense-account-changed
(fn [_ [_ event expense-accounts max-value field value]] (fn [_ [_ event expense-accounts max-value field value]]
(println field value)
(let [updated-accounts (cond-> expense-accounts (let [updated-accounts (cond-> expense-accounts
true (assoc-in field value) true (assoc-in field value)
(= (list :account) (drop 1 field)) (assoc-in [(first field) :location] nil) (= (list :account) (drop 1 field)) (assoc-in [(first field) :location] nil)
(= (list :account :id) (drop 1 field)) (-> (assoc-in [(first field) :account] @(re-frame/subscribe [::subs/account nil value]))
(assoc-in [(first field) :location] nil))
(= (list :amount-percentage) (drop 1 field)) (assoc-in [(first field) :amount] (= (list :amount-percentage) (drop 1 field)) (assoc-in [(first field) :amount]
(js/parseFloat (js/parseFloat
(goog.string/format "%.2f" (goog.string/format "%.2f"
@@ -116,111 +109,111 @@
;; VIEWS ;; VIEWS
(defn expense-accounts-field [{expense-accounts :value client :client max-value :max locations :locations event :event descriptor :descriptor disabled :disabled percentage-only? :percentage-only? :or {percentage-only? false}}] (defn expense-accounts-field [{expense-accounts :value client :client max-value :max locations :locations event :event descriptor :descriptor disabled :disabled percentage-only? :percentage-only? :or {percentage-only? false}}]
(let [chooseable-expense-accounts @(re-frame/subscribe [::subs/accounts client]) [:div
accounts-by-id @(re-frame/subscribe [::subs/accounts-by-id client])] [:div.columns
[:div [:div.column
[:div.columns [:h1.subtitle.is-4.is-inline (str/capitalize descriptor) "s"]
[:div.column (when-not percentage-only?
[:h1.subtitle.is-4.is-inline (str/capitalize descriptor) "s"] [:p.help "Remaining " (->$ (- max-value (reduce + 0 (map (comp js/parseFloat :amount) expense-accounts))))])]
(when-not percentage-only? [:div.column.is-narrow
[:p.help "Remaining " (->$ (- max-value (reduce + 0 (map (comp js/parseFloat :amount) expense-accounts))))])] (when-not disabled
[:div.column.is-narrow [:p.buttons
(when-not disabled [:a.button {:on-click (dispatch-event [::spread-evenly event expense-accounts max-value])} "Spread evenly"]
[:p.buttons [:a.button {:on-click (dispatch-event [::add-expense-account event expense-accounts locations])} "Add"]])]]
[:a.button {:on-click (dispatch-event [::spread-evenly event expense-accounts max-value])} "Spread evenly"]
[:a.button {:on-click (dispatch-event [::add-expense-account event expense-accounts locations])} "Add"]])]]
(for [[index {:keys [account id location amount amount-percentage amount-mode] :as expense-account}] (map vector (range) expense-accounts) (for [[index {:keys [account id location amount amount-percentage amount-mode] :as expense-account}] (map vector (range) expense-accounts)]
:let [account (accounts-by-id (:id account))]] ^{:key id}
^{:key id} [:div.box
[:div.box [:div.columns
[:div.columns [:div.column
[:div.column [:h1.subtitle.is-6 (cond (and account (not percentage-only?))
[:h1.subtitle.is-6 (cond (and account (not percentage-only?)) (str (:name account) " - "
(str (:name account) " - " location ": "
location ": " (gstring/format "$%.2f" (or amount 0) ))
(gstring/format "$%.2f" (or amount 0) ))
account account
(str (:name account) " - " (str (:name account) " - "
location ": %" location ": %"
amount-percentage) amount-percentage)
:else :else
[:i "New " descriptor])]] [:i "New " descriptor])]]
[:div.column.is-narrow [:div.column.is-narrow
(when-not disabled (when-not disabled
[:a.delete {:on-click (dispatch-event [::remove-expense-account event expense-accounts id])}])]] [:a.delete {:on-click (dispatch-event [::remove-expense-account event expense-accounts id])}])]]
[:div.field [:div.field
[:div.columns [:div.columns
[:div.column [:div.column
[:p.help "Account"] [:p.help "Account"]
[:div.control.is-fullwidth [:div.control.is-fullwidth
[bind-field [bind-field
^{:key (:id client)} ^{:key (:id client)}
[typeahead-v3 {:entities chooseable-expense-accounts [search-backed-typeahead {:search-query (fn [i]
:entity->text (fn [x ] [:search_account
(str (:numeric-code x) " - " (:name x))) {:query i
:disabled disabled :client-id (:id client)}
:type "typeahead-v3" [:name :id :location]])
:field [index :account] :type "typeahead-v3"
:event [::expense-account-changed event expense-accounts max-value] :field [index :account]
:subscription expense-accounts}]]]]
[:div.column.is-narrow
[:p.help "Location"]
[:div.control
(if-let [forced-location (:location account)]
[:div.select
[:select {:disabled "disabled" :style {:width "5em"} :value forced-location} [:option {:value forced-location} forced-location]]]
[:div.select
[bind-field
[:select {:type "select"
:disabled (boolean (or (:location account)
disabled))
:style {:width "5em"}
:field [index :location]
:allow-nil? true
:spec (set locations)
:event [::expense-account-changed event expense-accounts max-value]
:subscription expense-accounts}
(map (fn [l] ^{:key l} [:option {:value l} l]) locations)]]])]]]]
[:div.field :disabled disabled
[:p.help "Amount"] :event [::expense-account-changed event expense-accounts max-value]
:subscription expense-accounts}]]]]
[:div.column.is-narrow
[:p.help "Location"]
[:div.control [:div.control
[:div.field.has-addons.is-extended (if-let [forced-location (:location account)]
[:p.control [:span.select [:div.select
[bind-field [:select {:disabled "disabled" :style {:width "5em"} :value forced-location} [:option {:value forced-location} forced-location]]]
[:select {:type "select" [:div.select
:disabled (or disabled percentage-only?) [bind-field
:field [index :amount-mode] [:select {:type "select"
:allow-nil? false :disabled (boolean (or (:location account)
:event [::expense-account-changed event expense-accounts max-value] disabled))
:subscription expense-accounts} :style {:width "5em"}
[:option "$"] :field [index :location]
[:option "%"]]]]] :allow-nil? true
[:p.control :spec (set locations)
(if (= "$" amount-mode) :event [::expense-account-changed event expense-accounts max-value]
[bind-field :subscription expense-accounts}
[:input.input {:type "number" (map (fn [l] ^{:key l} [:option {:value l} l]) locations)]]])]]]]
:field [index :amount]
:style {:text-align "right" :width "7em"} [:div.field
:event [::expense-account-changed event expense-accounts max-value] [:p.help "Amount"]
:disabled disabled [:div.control
:subscription expense-accounts [:div.field.has-addons.is-extended
:precision 2 [:p.control [:span.select
:value (get-in expense-account [:amount]) [bind-field
:max max-value [:select {:type "select"
:step "0.01"}]] :disabled (or disabled percentage-only?)
[bind-field :field [index :amount-mode]
[:input.input {:type "number" :allow-nil? false
:field [index :amount-percentage] :event [::expense-account-changed event expense-accounts max-value]
:style {:text-align "right" :width "7em"} :subscription expense-accounts}
:disabled disabled [:option "$"]
:event [::expense-account-changed event expense-accounts max-value] [:option "%"]]]]]
:precision 2 [:p.control
:subscription expense-accounts (if (= "$" amount-mode)
:value (get-in expense-account [:amount-percentage]) [bind-field
:max "100" [:input.input {:type "number"
:step "0.01"}]])]]]]])])) :field [index :amount]
:style {:text-align "right" :width "7em"}
:event [::expense-account-changed event expense-accounts max-value]
:disabled disabled
:subscription expense-accounts
:precision 2
:value (get-in expense-account [:amount])
:max max-value
:step "0.01"}]]
[bind-field
[:input.input {:type "number"
:field [index :amount-percentage]
:style {:text-align "right" :width "7em"}
:disabled disabled
:event [::expense-account-changed event expense-accounts max-value]
:precision 2
:subscription expense-accounts
:value (get-in expense-account [:amount-percentage])
:max "100"
:step "0.01"}]])]]]]])])

View File

@@ -13,7 +13,6 @@
[auto-ap.views.utils :refer [date->str dispatch-event dispatch-event-with-propagation nf days-until]] [auto-ap.views.utils :refer [date->str dispatch-event dispatch-event-with-propagation nf days-until]]
[bidi.bidi :as bidi] [bidi.bidi :as bidi]
[cemerick.url :as url] [cemerick.url :as url]
[cljs-time.core :as t]
[clojure.string :as str] [clojure.string :as str]
[goog.string :as gstring] [goog.string :as gstring]
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
@@ -51,7 +50,7 @@
[[:invoices [:id :total :outstanding-balance :invoice-number :date :due :status :client-identifier :scheduled-payment :source-url :similarity [[:invoices [:id :total :outstanding-balance :invoice-number :date :due :status :client-identifier :scheduled-payment :source-url :similarity
[:vendor [:name :id]] [:vendor [:name :id]]
[:expense_accounts [:amount :id :location [:expense_accounts [:amount :id :location
[:account [:id ]]]] [:account [:id :name :location]]]]
[:client [:name :id :locations]] [:client [:name :id :locations]]
[:payments [:amount :id [:payment [:id :status :amount :s3_url :check_number [:payments [:amount :id [:payment [:id :status :amount :s3_url :check_number
[:transaction [:post_date]]]]]]]] [:transaction [:post_date]]]]]]]]
@@ -112,15 +111,13 @@
(re-frame/reg-event-fx (re-frame/reg-event-fx
::invoice-updated ::invoice-updated
(fn [{:keys [db]} [_ invoice]] (fn [{:keys [db]} [_ _]]
{:db db})) {:db db}))
(defn row [{:keys [invoice check-boxes selected-client overrides checkable? expense-event actions]}] (defn row [{:keys [invoice selected-client overrides checkable? actions]}]
(let [{:keys [client status payments expense-accounts invoice-number date due total outstanding-balance id vendor source-url] :as i} invoice (let [{:keys [client status payments expense-accounts invoice-number date due total outstanding-balance id vendor source-url] :as i} invoice
accounts-by-id @(re-frame/subscribe [::subs/accounts-by-id client])
unautopay-states @(re-frame/subscribe [::status/multi ::unautopay]) unautopay-states @(re-frame/subscribe [::status/multi ::unautopay])
editing-states @(re-frame/subscribe [::status/multi ::edits]) editing-states @(re-frame/subscribe [::status/multi ::edits])]
account->name #(:name (accounts-by-id (:id %)))]
[grid/row {:class (:class i) :id id :checkable? checkable? :entity invoice} [grid/row {:class (:class i) :id id :checkable? checkable? :entity invoice}
(when-not selected-client (when-not selected-client
[grid/cell {} [grid/cell {}
@@ -143,9 +140,8 @@
[grid/cell {:class "has-text-right"} (nf total )] [grid/cell {:class "has-text-right"} (nf total )]
[grid/cell {:class "has-text-right"} [grid/cell {:class "has-text-right"}
(if (:scheduled-payment i) (when (:scheduled-payment i)
[:<> [:div.tag.is-info.is-light "Autopay"] " "] [:<> [:div.tag.is-info.is-light "Autopay"] " "])
)
(nf outstanding-balance )] (nf outstanding-balance )]
[grid/button-cell {} [grid/button-cell {}
[:div.buttons [:div.buttons
@@ -160,7 +156,7 @@
[:div [:div
(for [e expense-accounts] (for [e expense-accounts]
^{:key (:id e)} ^{:key (:id e)}
[:span.dropdown-item (account->name (:account e)) " " (gstring/format "$%.2f" (:amount e) ) ]) [:span.dropdown-item (:name (:account e)) " " (gstring/format "$%.2f" (:amount e) ) ])
(when (get actions :expense-accounts) (when (get actions :expense-accounts)
[:<> [:<>
@@ -237,17 +233,14 @@
:class (status/class-for (get unautopay-states (:id i))) :class (status/class-for (get unautopay-states (:id i)))
:event [::unautopay i]}])]]])) :event [::unautopay i]}])]]]))
(defn invoice-table [{:keys [id check-boxes overrides actions data-page checkable-fn]}] (defn invoice-table [{:keys [check-boxes overrides actions data-page checkable-fn]}]
(let [selected-client @(re-frame/subscribe [::subs/client]) (let [{:keys [data status params table-params]} @(re-frame/subscribe [::data-page/page data-page])
{:keys [data status params table-params]} @(re-frame/subscribe [::data-page/page data-page])
selected-client @(re-frame/subscribe [::subs/client]) selected-client @(re-frame/subscribe [::subs/client])
is-loading? (= :loading (:state status)) is-loading? (= :loading (:state status))
is-sorted-by-vendor? (and (= "vendor" (:sort-key (first (:sort table-params)))) is-sorted-by-vendor? (and (= "vendor" (:sort-key (first (:sort table-params))))
(not is-loading?) (not is-loading?)
(or (apply <= (map (comp :name :vendor) (:data data))) (or (apply <= (map (comp :name :vendor) (:data data)))
(apply >= (map (comp :name :vendor) (:data data))))) (apply >= (map (comp :name :vendor) (:data data)))))
[invoice-groups] (if is-sorted-by-vendor? [invoice-groups] (if is-sorted-by-vendor?
(reduce (reduce
(fn [[acc last-vendor] invoice] (fn [[acc last-vendor] invoice]

View File

@@ -58,7 +58,7 @@
:time 250 :time 250
:key ::input-value-settled}}))) :key ::input-value-settled}})))
(defn typeahead-v3-internal [{:keys [class style ^js entity->text on-change disabled value name search-query auto-focus] :or {disabled false} :as i}] (defn typeahead-v3-internal [{:keys [class style ^js on-change disabled value name search-query auto-focus] :or {disabled false} :as i}]
(let [[items set-items] (react/useState []) (let [[items set-items] (react/useState [])
[loading-status set-loading-status] (react/useState false) [loading-status set-loading-status] (react/useState false)
[getLabelProps getMenuProps getComboboxProps getToggleButtonProps getInputProps getItemProps isOpen highlightedIndex selectItem selectedItem setInputValue] [getLabelProps getMenuProps getComboboxProps getToggleButtonProps getInputProps getItemProps isOpen highlightedIndex selectItem selectedItem setInputValue]
@@ -73,8 +73,6 @@
(when on-change (when on-change
(on-change (js->clj (aget z "selectedItem") :keywordize-keys true))))})) $ (on-change (js->clj (aget z "selectedItem") :keywordize-keys true))))})) $
(map #(aget $ %) ["getLabelProps" "getMenuProps" "getComboboxProps" "getToggleButtonProps" "getInputProps" "getItemProps" "isOpen" "highlightedIndex" "selectItem" "selectedItem" "setInputValue"]))] (map #(aget $ %) ["getLabelProps" "getMenuProps" "getComboboxProps" "getToggleButtonProps" "getInputProps" "getItemProps" "isOpen" "highlightedIndex" "selectItem" "selectedItem" "setInputValue"]))]
#_(println (getInputProps))
[:<> [:<>
[:div.typeahead (assoc (js->clj (getComboboxProps)) [:div.typeahead (assoc (js->clj (getComboboxProps))
:style style) :style style)
@@ -96,7 +94,7 @@
:tab-index "0") :tab-index "0")
[:div.control [:div.control
[:div.tags.has-addons [:div.tags.has-addons
[:span.tag (entity->text (js->clj selectedItem :keywordize-keys true))] [:span.tag (:name (js->clj selectedItem :keywordize-keys true))]
(when name (when name
[:input {:type "hidden" :name name :value (:id (js->clj selectedItem :keywordize-keys true))}]) [:input {:type "hidden" :name name :value (:id (js->clj selectedItem :keywordize-keys true))}])
(when-not disabled (when-not disabled
@@ -125,10 +123,8 @@
[:li.typeahead-suggestion (assoc (js->clj (getItemProps #js {:item item :index index})) [:li.typeahead-suggestion (assoc (js->clj (getItemProps #js {:item item :index index}))
:class (if (= index highlightedIndex) :class (if (= index highlightedIndex)
"typeahead-highlighted")) "typeahead-highlighted"))
(entity->text item)]))]]]])) (:name item)]))]]]]))
(defn search-backed-typeahead [props] (defn search-backed-typeahead [props]
[:div [:div
[:f> typeahead-v3-internal (assoc props [:f> typeahead-v3-internal props]])
:entity->text :name
)]])

View File

@@ -12,8 +12,7 @@
[auto-ap.views.components.typeahead :refer [typeahead-v3]] [auto-ap.views.components.typeahead :refer [typeahead-v3]]
[auto-ap.views.pages.admin.vendors.common :as common] [auto-ap.views.pages.admin.vendors.common :as common]
[auto-ap.views.utils [auto-ap.views.utils
:refer [account->match-text :refer [bind-field
bind-field
dispatch-event dispatch-event
horizontal-field horizontal-field
with-is-admin? with-is-admin?
@@ -87,8 +86,7 @@
:print-as print-as :print-as print-as
:terms terms :terms terms
:default-account-id (:id default-account) :default-account-id (:id default-account)
:address address :address address :primary-contact primary-contact
:primary-contact primary-contact
:secondary-contact secondary-contact :secondary-contact secondary-contact
:invoice-reminder-schedule invoice-reminder-schedule} :invoice-reminder-schedule invoice-reminder-schedule}
is-admin? (assoc :hidden hidden is-admin? (assoc :hidden hidden
@@ -288,12 +286,15 @@
:default-key :default-account :default-key :default-account
:override-key :account-overrides} :override-key :account-overrides}
(fn [field client] (fn [field client]
[typeahead-v3 {:entities @(re-frame/subscribe [::subs/accounts client]) [search-backed-typeahead {:search-query (fn [i]
:entity->text account->match-text [:search_account
:field field {:query i
:type "typeahead-v3" :client-id (:id client)}
:event change-event [:name :id]])
:subscription data}])] :type "typeahead-v3"
:field field
:event change-event
:subscription data}])]
[:h2.subtitle "Address"] [:h2.subtitle "Address"]
[address-field {:field [:address] [address-field {:field [:address]
@@ -525,10 +526,7 @@
(update :automatically-paid-when-due #(mapv identity %)) (update :automatically-paid-when-due #(mapv identity %))
(update :hidden #(if (nil? %) (update :hidden #(if (nil? %)
false false
%)) %)))))
(update :default-account
(fn [da]
@(re-frame/subscribe [::subs/account nil (:id da)]))))))
:dispatch [::modal/modal-requested :dispatch [::modal/modal-requested
{:title "Vendor" {:title "Vendor"
:class "is-wide" :class "is-wide"

View File

@@ -108,23 +108,18 @@
(re-frame/reg-event-fx (re-frame/reg-event-fx
::adding ::adding
[(re-frame/inject-cofx ::inject/sub (fn [[_ which _]] [(re-frame/inject-cofx ::inject/sub (fn [[_ which _]]
[::subs/accounts-by-id (:id (:client which))]))
(re-frame/inject-cofx ::inject/sub (fn [[_ which _]]
[::subs/locations-for-client (:id (:client which))]))] [::subs/locations-for-client (:id (:client which))]))]
(fn [{:keys [db] ::subs/keys [locations-for-client accounts-by-id]} [_ new]] (fn [{:keys [db] ::subs/keys [locations-for-client]} [_ new]]
{:db {:db
(-> db (forms/start-form ::form (assoc new :expense-accounts (-> db (forms/start-form ::form (assoc new :expense-accounts
(expense-accounts-field/from-graphql (:expense-accounts new) (expense-accounts-field/from-graphql (:expense-accounts new)
accounts-by-id
0.0 0.0
locations-for-client))))})) locations-for-client))))}))
(re-frame/reg-event-fx (re-frame/reg-event-fx
::editing ::editing
[(re-frame/inject-cofx ::inject/sub (fn [[_ which _]] [(re-frame/inject-cofx ::inject/sub (fn [[_ which _]]
[::subs/accounts-by-id (:id (:client which))]))
(re-frame/inject-cofx ::inject/sub (fn [[_ which _]]
[::subs/locations-for-client (:id (:client which))]))] [::subs/locations-for-client (:id (:client which))]))]
(fn [{:keys [db] ::subs/keys [locations-for-client accounts-by-id]} [_ which vendor-preferences]] (fn [{:keys [db] ::subs/keys [locations-for-client]} [_ which vendor-preferences]]
(let [edit-invoice (update which :date #(date->str % standard)) (let [edit-invoice (update which :date #(date->str % standard))
edit-invoice (update edit-invoice :due #(date->str % standard)) edit-invoice (update edit-invoice :due #(date->str % standard))
edit-invoice (update edit-invoice :scheduled-payment #(date->str % standard)) edit-invoice (update edit-invoice :scheduled-payment #(date->str % standard))
@@ -144,7 +139,6 @@
:vendor (:vendor edit-invoice) :vendor (:vendor edit-invoice)
:client (:client edit-invoice) :client (:client edit-invoice)
:expense-accounts (expense-accounts-field/from-graphql (:expense-accounts which) :expense-accounts (expense-accounts-field/from-graphql (:expense-accounts which)
accounts-by-id
(:total which) (:total which)
locations-for-client)}))}))) locations-for-client)}))})))

View File

@@ -1,27 +1,18 @@
(ns auto-ap.views.pages.ledger (ns auto-ap.views.pages.ledger
(:require [auto-ap.events :as events] (:require
[auto-ap.forms :as forms] [auto-ap.subs :as subs]
[auto-ap.subs :as subs] [auto-ap.views.components.layouts :refer [side-bar-layout]]
[auto-ap.views.components.bank-account-filter :refer [bank-account-filter]] [auto-ap.views.pages.data-page :as data-page]
[auto-ap.views.components.layouts :refer [appearing-side-bar side-bar-layout]] [auto-ap.views.pages.ledger.side-bar
[auto-ap.routes :as routes] :as side-bar
[bidi.bidi :as bidi] :refer [ledger-side-bar]]
[auto-ap.views.components.paginator :refer [paginator]] [auto-ap.views.pages.ledger.table :as table]
[auto-ap.views.components.sorter :refer [sorted-column]] [auto-ap.views.utils :refer [with-user]]
[auto-ap.views.pages.ledger.table :as table] [clojure.set :as set]
[auto-ap.views.pages.ledger.side-bar :refer [ledger-side-bar] :as side-bar] [re-frame.core :as re-frame]
[auto-ap.views.pages.transactions.common :refer [transaction-read]] [reagent.core :as reagent]
[vimsical.re-frame.fx.track :as track]))
[auto-ap.utils :refer [replace-by]]
[auto-ap.views.pages.transactions.manual :as manual]
[auto-ap.views.utils :refer [bind-field date->str dispatch-event nf active-when with-user]]
[goog.string :as gstring]
[re-frame.core :as re-frame]
[reagent.core :as reagent]
[auto-ap.status :as status]
[vimsical.re-frame.fx.track :as track]
[auto-ap.views.pages.data-page :as data-page]
[clojure.set :as set]))
(defn data-params->query-params [params] (defn data-params->query-params [params]
{:start (:start params 0) {:start (:start params 0)
:sort (:sort params) :sort (:sort params)
@@ -39,7 +30,7 @@
(re-frame/reg-event-fx (re-frame/reg-event-fx
::params-change ::params-change
[with-user] [with-user]
(fn [{:keys [user db]} [_ params]] (fn [{:keys [user]} [_ params]]
{:graphql {:token user {:graphql {:token user
:owns-state {:single [::data-page/page ::page]} :owns-state {:single [::data-page/page ::page]}
:query-obj {:venia/queries [[:ledger-page :query-obj {:venia/queries [[:ledger-page
@@ -57,7 +48,7 @@
[:name :id]] [:name :id]]
[:line-items [:line-items
[:id :debit :credit :location :running-balance [:id :debit :credit :location :running-balance
[:account [:id]]]] [:account [:id :name]]]]
:date]] :date]]
:total :total
:start :start
@@ -68,13 +59,13 @@
(re-frame/reg-event-fx (re-frame/reg-event-fx
::unmounted ::unmounted
(fn [{:keys [db]} _] (fn [_ _]
{:dispatch [::data-page/dispose ::page] {:dispatch [::data-page/dispose ::page]
::track/dispose {:id ::params}})) ::track/dispose {:id ::params}}))
(re-frame/reg-event-fx (re-frame/reg-event-fx
::mounted ::mounted
(fn [{:keys [db]} _] (fn [_ _]
{::track/register {:id ::params {::track/register {:id ::params
:subscription [::data-page/params ::page] :subscription [::data-page/params ::page]
:event-fn (fn [params] [::params-change params])}})) :event-fn (fn [params] [::params-change params])}}))
@@ -82,11 +73,10 @@
(defn ledger-content [] (defn ledger-content []
(let [current-client @(re-frame/subscribe [::subs/client])] [:div
[:div [:h1.title "Ledger"]
[:h1.title "Ledger"] [table/table {:id :ledger
[table/table {:id :ledger :data-page ::page}]])
:data-page ::page}]]))
(defn ledger-page [] (defn ledger-page []

View File

@@ -52,7 +52,7 @@
[:name :id]] [:name :id]]
[:line-items [:line-items
[:id :debit :credit :location :running-balance [:id :debit :credit :location :running-balance
[:account [:id]]]] [:account [:id :name]]]]
:date]] :date]]
:total :total
:start :start

View File

@@ -11,7 +11,7 @@
(defn external-ledger-row [{{:keys [client vendor alternate-description status date amount id source external-id line-items] :as i} :row (defn external-ledger-row [{{:keys [client vendor alternate-description status date amount id source external-id line-items] :as i} :row
:keys [selected-client accounts-by-id bank-accounts-by-id]}] :keys [selected-client bank-accounts-by-id]}]
[:<> [:<>
[grid/row {:class (:class i) :id id :checkable? true :entity i} [grid/row {:class (:class i) :id id :checkable? true :entity i}
(when-not selected-client (when-not selected-client
@@ -28,8 +28,8 @@
[grid/cell {:class "has-text-right"} (nf amount )]] [grid/cell {:class "has-text-right"} (nf amount )]]
[:<> [:<>
(for [{:keys [debit credit location account id running-balance]} line-items (for [{:keys [debit credit location account id running-balance]} line-items
:let [account (or (accounts-by-id (:id account)) :let [account (or (bank-accounts-by-id (:id account))
(bank-accounts-by-id (:id account)))]] account)]]
^{:key id} ^{:key id}
[grid/row {:checkable? false} [grid/row {:checkable? false}
(when-not selected-client (when-not selected-client
@@ -49,7 +49,6 @@
(defn table [{:keys [id data-page status vendors on-check-changed expense-event]}] (defn table [{:keys [id data-page status vendors on-check-changed expense-event]}]
(let [{:keys [data status params]} @(re-frame/subscribe [::data-page/page data-page]) (let [{:keys [data status params]} @(re-frame/subscribe [::data-page/page data-page])
selected-client @(re-frame/subscribe [::subs/client]) selected-client @(re-frame/subscribe [::subs/client])
accounts-by-id @(re-frame/subscribe [::subs/accounts-by-id selected-client])
bank-accounts-by-id @(re-frame/subscribe [::subs/bank-accounts-by-id])] bank-accounts-by-id @(re-frame/subscribe [::subs/bank-accounts-by-id])]
[grid/grid {:data-page data-page [grid/grid {:data-page data-page
:check-boxes? true :check-boxes? true
@@ -73,6 +72,5 @@
^{:key id} ^{:key id}
[external-ledger-row {:row i [external-ledger-row {:row i
:selected-client selected-client :selected-client selected-client
:accounts-by-id accounts-by-id
:bank-accounts-by-id bank-accounts-by-id}])]]])) :bank-accounts-by-id bank-accounts-by-id}])]]]))

View File

@@ -17,8 +17,7 @@
(defn ledger-side-bar [{:keys [data-page]}] (defn ledger-side-bar [{:keys [data-page]}]
(let [ap @(re-frame/subscribe [::subs/active-page]) (let [ap @(re-frame/subscribe [::subs/active-page])
user @(re-frame/subscribe [::subs/user]) user @(re-frame/subscribe [::subs/user])
accounts-by-id @(re-frame/subscribe [::subs/accounts-by-id]) client @(re-frame/subscribe [::subs/client])]
accounts-index @(re-frame/subscribe [::subs/accounts-index])]
[:div [:div
[:ul.menu-list [:ul.menu-list
[:li.menu-item [:li.menu-item
@@ -61,12 +60,15 @@
[:p.menu-label "Financial Account"] [:p.menu-label "Financial Account"]
[:div [:div
[typeahead-v3 {:entities-by-id accounts-by-id [search-backed-typeahead {:search-query (fn [i]
:entity-index accounts-index [:search_account
:entity->text (fn [x ] (str (:numeric-code x) " - " (:name x))) {:query i
:type "typeahead-v3" :client-id (:id client)}
:on-change #(re-frame/dispatch [::data-page/filter-changed data-page :account (some-> % (select-keys [:name :id :numeric-code]))]) [:name :id]])
:value @(re-frame/subscribe [::data-page/filter data-page :account])}]] :entity->text (fn [x ] (str (:numeric-code x) " - " (:name x)))
:type "typeahead-v3"
:on-change #(re-frame/dispatch [::data-page/filter-changed data-page :account (some-> % (select-keys [:name :id :numeric-code]))])
:value @(re-frame/subscribe [::data-page/filter data-page :account])}]]
[:p.menu-label "Vendor"] [:p.menu-label "Vendor"]
[:div [:div

View File

@@ -16,8 +16,8 @@
[cemerick.url :as url] [cemerick.url :as url]
[re-frame.core :as re-frame])) [re-frame.core :as re-frame]))
(defn ledger-row [{{:keys [client vendor alternate-description note status date amount id line-items source original-entity] :as i} :row (defn ledger-row [{{:keys [client vendor alternate-description note date amount id line-items source original-entity] :as i} :row
:keys [selected-client accounts-by-id bank-accounts-by-id]}] :keys [selected-client bank-accounts-by-id]}]
[:<> [:<>
[grid/row {:class (:class i) :id id} [grid/row {:class (:class i) :id id}
(when-not selected-client (when-not selected-client
@@ -73,8 +73,8 @@
)]]]]])]] )]]]]])]]
[:<> [:<>
(for [{:keys [debit credit location account id running-balance]} line-items (for [{:keys [debit credit location account id running-balance]} line-items
:let [account (or (accounts-by-id (:id account)) :let [account (or (bank-accounts-by-id (:id account))
(bank-accounts-by-id (:id account)))]] account)]]
^{:key id} ^{:key id}
[grid/row {} [grid/row {}
(when-not selected-client (when-not selected-client
@@ -92,10 +92,9 @@
#_[grid/cell {:class "has-text-right"} (when running-balance (nf running-balance ))]])]]) #_[grid/cell {:class "has-text-right"} (when running-balance (nf running-balance ))]])]])
(defn table [{:keys [id data-page status vendors on-check-changed expense-event]}] (defn table [{:keys [data-page]}]
(let [{:keys [data status]} @(re-frame/subscribe [::data-page/page data-page]) (let [{:keys [data]} @(re-frame/subscribe [::data-page/page data-page])
selected-client @(re-frame/subscribe [::subs/client]) selected-client @(re-frame/subscribe [::subs/client])
accounts-by-id @(re-frame/subscribe [::subs/accounts-by-id selected-client])
bank-accounts-by-id @(re-frame/subscribe [::subs/bank-accounts-by-id])] bank-accounts-by-id @(re-frame/subscribe [::subs/bank-accounts-by-id])]
[grid/grid {:data-page data-page [grid/grid {:data-page data-page
:column-count (if selected-client 5 6)} :column-count (if selected-client 5 6)}
@@ -113,10 +112,9 @@
[grid/header-cell {:style {:width (action-cell-width 1)}}] [grid/header-cell {:style {:width (action-cell-width 1)}}]
#_[grid/header-cell {:class "has-text-right" :style {:width "10em"}} "Running Balance"]]] #_[grid/header-cell {:class "has-text-right" :style {:width "10em"}} "Running Balance"]]]
[grid/body [grid/body
(for [{:keys [client vendor status date amount id line-items] :as i} (:data data)] (for [{:keys [id] :as i} (:data data)]
^{:key id} ^{:key id}
[ledger-row {:row i [ledger-row {:row i
:selected-client selected-client :selected-client selected-client
:accounts-by-id accounts-by-id
:bank-accounts-by-id bank-accounts-by-id}])]]])) :bank-accounts-by-id bank-accounts-by-id}])]]]))

View File

@@ -56,8 +56,7 @@
(re-frame/reg-event-db (re-frame/reg-event-db
::editing ::editing
(fn [db [_ which potential-payment-matches potential-autopay-invoices-matches potential-unpaid-invoices-matches potential-transaction-rule-matches]] (fn [db [_ which potential-payment-matches potential-autopay-invoices-matches potential-unpaid-invoices-matches potential-transaction-rule-matches]]
(let [locations @(re-frame/subscribe [::subs/locations-for-client (:id (:client which))]) (let [locations @(re-frame/subscribe [::subs/locations-for-client (:id (:client which))])]
accounts-by-id @(re-frame/subscribe [::subs/accounts-by-id (:client which)])]
(forms/start-form db ::form (forms/start-form db ::form
(-> which (-> which
(select-keys [:vendor :amount :payment :client :description-original (select-keys [:vendor :amount :payment :client :description-original
@@ -71,7 +70,7 @@
(assoc :potential-transaction-rule-matches potential-transaction-rule-matches) (assoc :potential-transaction-rule-matches potential-transaction-rule-matches)
(assoc :potential-autopay-invoices-matches potential-autopay-invoices-matches) (assoc :potential-autopay-invoices-matches potential-autopay-invoices-matches)
(assoc :potential-unpaid-invoices-matches potential-unpaid-invoices-matches) (assoc :potential-unpaid-invoices-matches potential-unpaid-invoices-matches)
(update :accounts expense-accounts-field/from-graphql accounts-by-id (:amount which) locations)))))) (update :accounts expense-accounts-field/from-graphql (:amount which) locations))))))
(re-frame/reg-event-db (re-frame/reg-event-db
::changed ::changed

View File

@@ -7,22 +7,18 @@
[auto-ap.views.components.date-range-filter :refer [date-range-filter]] [auto-ap.views.components.date-range-filter :refer [date-range-filter]]
[auto-ap.views.components.number-filter :refer [number-filter]] [auto-ap.views.components.number-filter :refer [number-filter]]
[auto-ap.views.components.switch-field :refer [switch-field]] [auto-ap.views.components.switch-field :refer [switch-field]]
[auto-ap.views.components.typeahead :refer [typeahead-v3]]
[auto-ap.views.components.typeahead.vendor [auto-ap.views.components.typeahead.vendor
:refer [search-backed-typeahead]] :refer [search-backed-typeahead]]
[auto-ap.views.pages.data-page :as data-page] [auto-ap.views.pages.data-page :as data-page]
[auto-ap.views.utils [auto-ap.views.utils
:refer [account->match-text active-when dispatch-event dispatch-value-change]] :refer [active-when dispatch-event dispatch-value-change]]
[bidi.bidi :as bidi] [bidi.bidi :as bidi]
[re-frame.core :as re-frame])) [re-frame.core :as re-frame]))
(defn side-bar [{:keys [data-page]}] (defn side-bar [{:keys [data-page]}]
(let [ap @(re-frame/subscribe [::subs/active-page]) (let [ap @(re-frame/subscribe [::subs/active-page])
user @(re-frame/subscribe [::subs/user]) user @(re-frame/subscribe [::subs/user])
client @(re-frame/subscribe [::subs/client])]
accounts @(re-frame/subscribe [::subs/accounts-by-id])
account-index @(re-frame/subscribe [::subs/accounts-index])
]
[:div [:div
[:div [:p.menu-label "Type"] [:div [:p.menu-label "Type"]
[:ul.menu-list [:ul.menu-list
@@ -68,12 +64,15 @@
[:p.menu-label "Financial Account"] [:p.menu-label "Financial Account"]
[:div [:div
[typeahead-v3 {:entities-by-id accounts [search-backed-typeahead {:search-query (fn [i]
:entity-index account-index [:search_account
:entity->text account->match-text {:query i
:type "typeahead-v3" :client-id (:id client)}
:on-change #(re-frame/dispatch [::data-page/filter-changed data-page :account (some-> % (select-keys [:name :id :numeric-code]))]) [:name :id]])
:value @(re-frame/subscribe [::data-page/filter data-page :account])}]] :entity->text (fn [x ] (str (:numeric-code x) " - " (:name x)))
:type "typeahead-v3"
:on-change #(re-frame/dispatch [::data-page/filter-changed data-page :account (some-> % (select-keys [:name :id :numeric-code]))])
:value @(re-frame/subscribe [::data-page/filter data-page :account])}]]
[:p.menu-label "Vendor"] [:p.menu-label "Vendor"]
[:div [:div