starting work on cash flow.

This commit is contained in:
Bryce Covert
2020-06-15 08:19:43 -07:00
parent bd17cd3caa
commit ef843ac9a2
11 changed files with 136 additions and 20 deletions

View File

@@ -111,7 +111,7 @@
"location" ['[?e :invoice/expense-accounts ?iea]
'[?iea :invoice-expense-account/location ?sort-location]]
"date" ['[?e :invoice/date ?sort-date]]
"due" ['[?e :invoice/due ?sort-due]]
"due" ['[(get-else $ ?e :invoice/due #inst "2050-01-01") ?sort-due]]
"invoice-number" ['[?e :invoice/invoice-number ?sort-invoice-number]]
"total" ['[?e :invoice/total ?sort-total]]
"outstanding-balance" ['[?e :invoice/outstanding-balance ?sort-outstanding-balance]]}
@@ -134,13 +134,30 @@
(mapv <-datomic))]
invoices))
(defn sum-outstanding [ids]
(->>
(d/query {:query {:find ['?o]
:in ['$ '[?id ...]]
:where ['[?id :invoice/outstanding-balance ?o]]
}
:args [(d/db (d/connect uri))
ids]})
(map first)
(reduce
+
0.0)))
(defn get-graphql [args]
(let [db (d/db (d/connect uri))
{ids-to-retrieve :ids matching-count :count} (raw-graphql-ids db args)]
{ids-to-retrieve :ids matching-count :count} (raw-graphql-ids db args)
outstanding (sum-outstanding ids-to-retrieve)]
[(->> (graphql-results ids-to-retrieve db args))
matching-count]))
matching-count
(doto
outstanding println)]))
(defn get-by-id [id]
(-> (d/db (d/connect uri))

View File

@@ -74,7 +74,8 @@
:location_matches {:type '(list :location_match)}
:locations {:type '(list String)}
:matches {:type '(list String)}
:bank_accounts {:type '(list :bank_account)}}}
:bank_accounts {:type '(list :bank_account)}
:forecasted_transactions {:type '(list :forecasted_transaction)}}}
:contact
{:fields {:id {:type :id}
:name {:type 'String}
@@ -96,6 +97,10 @@
:bank_name {:type 'String}
:yodlee_account_id {:type 'Int}
:locations {:type '(list String)}}}
:forecasted_transaction {:fields {:identifier {:type 'String}
:id {:type :id}
:day_of_month {:type 'Int}
:amount {:type :money}}}
:balance_sheet_account
{:fields {:id {:type 'String}
:amount {:type 'String}
@@ -295,6 +300,7 @@
:invoice_page {:fields {:invoices {:type '(list :invoice)}
:outstanding {:type :money}
:count {:type 'Int}
:total {:type 'Int}
:start {:type 'Int}
@@ -500,7 +506,13 @@
:invoice_payment_amount {:fields {:invoice_id {:type :id}
:amount {:type 'Float}}}
:edit_location_match {:fields {:location {:type 'String}
:match {:type 'String}}}
:match {:type 'String}}}
:edit_forecasted_transaction {:fields {:identifier {:type 'String}
:id {:type :id}
:day_of_month {:type 'Int}
:amount {:type :money}}}
:date_range {:fields {:start {:type :iso_date}
:end {:type :iso_date}}}
@@ -529,7 +541,9 @@
:locations {:type '(list String)}
:matches {:type '(list String)}
:location_matches {:type '(list :edit_location_match)}
:bank_accounts {:type '(list :edit_bank_account)}}}
:bank_accounts {:type '(list :edit_bank_account)}
:forecasted_transactions {:type '(list :edit_forecasted_transaction)}
}}
:edit_bank_account
{:fields {:id {:type :id }
:code {:type 'String}

View File

@@ -47,6 +47,7 @@
:address/state (:state (:address edit_client))
:address/zip (:zip (:address edit_client))})
:client/bank-accounts (map #(remove-nils
{:db/id (:id %)
:bank-account/code (:code %)
@@ -67,7 +68,14 @@
}
) (:bank_accounts edit_client))
})]
})
[:reset id :client/forecasted-transactions (map #(remove-nils
{:db/id (:id %)
:forecasted-transaction/day-of-month (:day_of_month %)
:forecasted-transaction/identifier (:identifier %)
:forecasted-transaction/amount (:amount %)}
)
(:forecasted_transactions edit_client))]]
result @(d/transact (d/connect uri) transactions)]
(println result "ID" id)
(-> result :tempids (get id) (or id) d-clients/get-by-id

View File

@@ -17,8 +17,9 @@
(defn get-invoice-page [context args value]
(let [args (assoc args :id (:id context))
[invoices invoice-count] (d-invoices/get-graphql (update (<-graphql (assoc args :id (:id context))) :status enum->keyword "invoice-status"))]
[invoices invoice-count outstanding] (d-invoices/get-graphql (update (<-graphql (assoc args :id (:id context))) :status enum->keyword "invoice-status"))]
[{:invoices (map ->graphql invoices)
:outstanding outstanding
:total invoice-count
:count (count invoices)
:start (:start args 0)

View File

@@ -159,7 +159,6 @@
:graphql
(fn [{:keys [query on-success on-error token variables query-obj]}]
(go
(println on-error)
(let [headers (if token
{"Authorization" (str "Token " token)}
{})

View File

@@ -45,7 +45,8 @@
:query-obj {:venia/queries [[:client
[:id :name :code :email :matches :weekly-debits :weekly-credits :locations [:location-matches [:location :match]] [:bank-accounts [:id :code :number :bank-name :bank-code :check-number :name :routing :type :sort-order :visible :yodlee-account-id :locations :include-in-reports] ]
[:address [:street1 :street2 :city :state :zip]]]]
[:address [:street1 :street2 :city :state :zip]]
[:forecasted-transactions [:id :amount :identifier :day-of-month]]]]
[:vendor
[:id :name :hidden [:default-account [:name :id :location]] [:primary-contact [:name :phone :email :id]] [:secondary-contact [:id :name :phone :email]] :print-as :invoice-reminder-schedule :code
[:account-overrides [[:client [:id :name]] :id [:account [:id :numeric-code :name]]]]
@@ -71,7 +72,10 @@
(fn [{:keys [db]} [_ token user]]
{:graphql {:token token
:query-obj {:venia/queries [[:client
[:id :name :code :matches :locations :weekly-debits :weekly-credits [:location-matches [:location :match]] [:address [:street1 :street2 :city :state :zip]] [:bank-accounts [:id :code :number :bank-name :bank-code :check-number :name :routing :type :sort-order :visible :yodlee-account-id :locations :include-in-reports] ]]]
[:id :name :code :matches :locations :weekly-debits :weekly-credits [:location-matches [:location :match]]
[:address [:street1 :street2 :city :state :zip]]
[:bank-accounts [:id :code :number :bank-name :bank-code :check-number :name :routing :type :sort-order :visible :yodlee-account-id :locations :include-in-reports] ]
[:forecasted-transactions [:id :amount :identifier :day-of-month]]]]
[:vendor
[:id :name :hidden [:default-account [:name :id :location]] [:primary-contact [:name :phone :email :id]] [:secondary-contact [:id :name :phone :email]] :print-as :invoice-reminder-schedule :code]]
[:accounts [:numeric-code :name :location :type :account_set :applicability :id [:client-overrides [:name [:client [:name :id]]]]]]]}

View File

@@ -57,6 +57,7 @@
[:client [:name :id :locations]]
[:payments [:amount :id [:payment [:id :status :amount :s3_url :check_number
[:transaction [:post_date]]]]]]]]
:outstanding
:total
:start
:end]]]})
@@ -172,7 +173,7 @@
visible-expense-accounts @(re-frame/subscribe [::visible-expense-accounts])
selected-client @(re-frame/subscribe [::subs/client])
{:keys [sort]} @(re-frame/subscribe [::table-params])
{:keys [invoices start end count total]} @invoice-page
{:keys [invoices outstanding start end count total]} @invoice-page
visible-checks @(re-frame/subscribe [::visible-checks])
visible-expense-accounts @(re-frame/subscribe [::visible-expense-accounts])
selected-client @(re-frame/subscribe [::subs/client])
@@ -200,7 +201,9 @@
:on-change opc}]]
[:div.level-item
[sort-by-list {:sort sort
:on-change opc}]]]]
:on-change opc}]]
[:div.level-item
"Outstanding" (nf outstanding)]]]
(doall
(for [invoices invoice-groups]
^{:key (:id (first invoices))}

View File

@@ -14,7 +14,7 @@
[:header.modal-card-head
[:p.modal-card-title
title]
[:button.delete {:on-click (fn [] (re-frame/dispatch hide-event))}]]
[:button.delete {:on-click (fn [e] (.preventDefault e) (re-frame/dispatch hide-event))}]]
(into [:section.modal-card-body]
(r/children (r/current-component)))

View File

@@ -107,7 +107,7 @@
::save
[with-user with-is-admin? (forms/triggers-loading ::vendor-form) (forms/in-form ::vendor-form)]
(fn [{:keys [user is-admin?] {{:keys [name hidden print-as terms invoice-reminder-schedule primary-contact secondary-contact address default-account terms-overrides account-overrides id] :as data} :data} :db} _]
(println user)
(println user is-admin?)
(when (s/valid? ::entity/vendor data)
{ :graphql
{:token user

View File

@@ -13,7 +13,7 @@
[auto-ap.views.components.address :refer [address-field]]
[auto-ap.views.components.layouts :refer [side-bar-layout appearing-side-bar side-bar] ]
[auto-ap.views.components.admin.side-bar :refer [admin-side-bar]]
[auto-ap.views.utils :refer [login-url dispatch-event dispatch-value-change bind-field horizontal-field]]
[auto-ap.views.utils :refer [login-url dispatch-event dispatch-value-change bind-field horizontal-field nf]]
[auto-ap.views.components.modal :refer [action-modal]]
[cljs.reader :as edn]
[auto-ap.routes :as routes]
@@ -58,6 +58,12 @@
:city (:city (:address new-client-data))
:state (:state (:address new-client-data))
:zip (:zip (:address new-client-data))}
:forecasted-transactions (map (fn [{:keys [id day-of-month identifier amount]}]
{:id id
:day-of-month day-of-month
:identifier identifier
:amount amount})
(:forecasted-transactions new-client-data))
:bank-accounts (map (fn [{:keys [number name check-number include-in-reports type id code bank-name routing bank-code new? sort-order visible yodlee-account-id locations]}]
{:number number
:name name
@@ -101,6 +107,7 @@
[:id :name :code :email :locations :matches :weekly-debits :weekly-credits
[:location-matches [:location :match]]
[:address [:street1 :street2 :city :state :zip]]
[:forecasted-transactions [:id :amount :identifier :day-of-month]]
[:bank-accounts [:id :number :check-number :name :code :bank-code :bank-name :routing :type :visible :yodlee-account-id :sort-order :locations]]]]}]}
:on-success [::save-complete]
:on-error [::forms/save-error ::new-client]}}
@@ -157,6 +164,28 @@
(update :location-matches conj (:location-match client))
(dissoc :location-match))))
(re-frame/reg-event-db
::add-forecasted-transaction
[(forms/in-form ::form) (re-frame/path [:data])]
(fn [client _]
(-> client
(update :forecasted-transactions conj (assoc (:new-forecasted-transaction client) :temp-id (random-uuid)))
(dissoc :new-forecasted-transaction))))
(re-frame/reg-event-db
::remove-forecasted-transaction
[(forms/in-form ::form) (re-frame/path [:data])]
(fn [client [_ which]]
(-> client
(update :forecasted-transactions #(transduce
(filter (fn [x] (and (not= (:temp-id x) which)
(not= (:id x) which))))
conj
[]
%)))))
(re-frame/reg-event-db
::remove-location-match
[(forms/in-form ::form) (re-frame/path [:data])]
@@ -506,6 +535,7 @@
[:div.column.is-third
[:a.button.is-primary.is-outlined.is-fullwidth {:on-click (dispatch-event [::add-new-bank-account :cash])} "Add Cash Account"]]]
[:h2.subtitle "Cash flow"]
[field "Weekly credits"
[:input.input {:type "number"
:placeholder "250.00"
@@ -516,8 +546,42 @@
:placeholder "250.00"
:field [:weekly-debits]
:step "0.01"}]]
[:div.field
[:label.label "Forecasted transactions"]
[:div.control
[horizontal-field
nil
[:p.control
[:p.help "Identifier"]
[raw-field
[:input.input {:type "text"
:placeholder "Identifier"
:field [:new-forecasted-transaction :identifier]}]]]
[:p.control
[:p.help "Day of month"]
[raw-field
[:input.input {:type "number"
:placeholder "Day of month"
:step "1"
:field [:new-forecasted-transaction :day-of-month]}]]]
[:p.control
[:p.help "Amount"]
[raw-field
[:input.input {:type "number"
:placeholder "250.00"
:field [:new-forecasted-transaction :amount]
:step "0.01"}]]]
[:a.button {:on-click (dispatch-event [::add-forecasted-transaction])} "Add"]]]
[:ul
(for [forecasted-transaction (:forecasted-transactions new-client)]
^{:key (or (:id forecasted-transaction)
(:temp-id forecasted-transaction))}
[:li (:identifier forecasted-transaction) ": " (nf (:amount forecasted-transaction)) " on day " (:day-of-month forecasted-transaction) " of the month"
[:a {:on-click (dispatch-event [::remove-forecasted-transaction (or (:id forecasted-transaction)
(:temp-id forecasted-transaction))])} [:span.icon [:span.fa.fa-times]]]])]]
[error-notification]
[submit-button "Save"]]]))

View File

@@ -11,7 +11,8 @@
[cljs-time.format :as format]
[goog.i18n.NumberFormat.Format]
[cljs-time.core :as t]
[clojure.string :as str])
[clojure.string :as str]
[goog.crypt.base64 :as base64])
(:import
(goog.i18n NumberFormat)
(goog.i18n.NumberFormat Format)))
@@ -327,8 +328,13 @@
:before (fn [context]
(-> context
(assoc-in [:coeffects :is-admin?] (= "admin"
(:user/role
(get-in context [:coeffects :db :user]))))))))
(-> (get-in context [:coeffects :db :user])
(str/split #"\.")
second
(base64/decodeString )
(#(.parse js/JSON % ))
(js->clj :keywordize-keys true)
:user/role)))))))
(defn query-params []
(reduce-kv