Merge branch 'cash-flow-idea'

This commit is contained in:
Bryce Covert
2020-05-20 06:50:17 -07:00
11 changed files with 117 additions and 105 deletions

View File

@@ -62,6 +62,16 @@
'[(<= ?date ?end-date)]]}
:args [(c/to-date (:end (:date-range args)))]})
(:start (:due-range args)) (merge-query {:query {:in '[?start-due]
:where ['[?e :invoice/due ?due]
'[(>= ?due ?start-due)]]}
:args [(c/to-date (:start (:due-range args)))]})
(:end (:due-range args)) (merge-query {:query {:in '[?end-due]
:where ['[?e :invoice/due ?due]
'[(<= ?due ?end-due)]]}
:args [(c/to-date (:end (:due-range args)))]})
(:import-status args)
(merge-query {:query {:in ['?import-status]
:where ['[?e :invoice/import-status ?import-status]]}

View File

@@ -394,6 +394,7 @@
:invoice_page {:type '(list :invoice_page)
:args {:import_status {:type 'String}
:date_range {:type :date_range}
:due_range {:type :date_range}
:status {:type :invoice_status}
:client_id {:type :id}
:vendor_id {:type :id}
@@ -871,11 +872,10 @@
true (merge-query {:query {:where ['[?i :invoice/client ?c]
'[?i :invoice/outstanding-balance ?outstanding-balance]
'[?i :invoice/total ?total]
'[?i :invoice/date ?date]
'[?i :invoice/due ?date]
'[(.toInstant ^java.util.Date ?date) ?d2]
'[(.between java.time.temporal.ChronoUnit/DAYS (java.time.Instant/now) ?d2 ) ?d3]
'[(+ 30 ?d3) ?d4]
'[(auto-ap.graphql/categorize ?d4) ?name]]}})
'[(auto-ap.graphql/categorize ?d3) ?name]]}})
true (d/query ))
result (group-by first result)]

View File

@@ -226,73 +226,7 @@
rows)]
@(d/transact conn txes)))
(defn cash-flow-simple []
(let [total-cash (reduce
(fn [total [credit debit]]
(- (+ total credit)
debit))
0.0
(d/query {:query {:find '[?debit ?credit]
:in '[$ ?client]
:where ['[?j :journal-entry/client ?c]
'[?c :client/code ?client]
'[?j :journal-entry/line-items ?je]
'[?je :journal-entry-line/account ?ba]
'[?ba :bank-account/type :bank-account-type/check]
'[(get-else $ ?je :journal-entry-line/debit 0.0) ?debit]
'[(get-else $ ?je :journal-entry-line/credit 0.0) ?credit]]}
:args [(d/db (d/connect uri)) "CBC"]}))
bills-due-soon (d/query {:query {:find '[?due ?outstanding]
:in '[$ ?client ?due-before]
:where ['[?i :invoice/client ?c]
'[?c :client/code ?client]
'[?i :invoice/status :invoice-status/unpaid]
'[?i :invoice/due ?due]
'[(<= ?due ?due-before)]
'[?i :invoice/outstanding-balance ?outstanding]]}
:args [(d/db (d/connect uri)) "CBC" (c/to-date (t/plus (auto-ap.time/local-now) (t/days 7)))]})
outstanding-checks (reduce
+
0.0
(map first (d/query {:query {:find '[?amount]
:in '[$ ?client ?due-before]
:where ['[?p :payment/client ?c]
'[?c :client/code ?client]
'[?p :payment/status :payment-status/pending]
'[?p :payment/amount ?amount]
'(or
[?p :payment/type :payment-type/debit]
[?p :payment/type :payment-type/check])]}
:args [(d/db (d/connect uri)) "CBC" (c/to-date (t/plus (auto-ap.time/local-now) (t/days 7)))]})))]
[total-cash bills-due-soon outstanding-checks])
#_(->> (d/query {:query {:find '[?account-type-ident ?date ?debit ?credit]
:in '[$ ?client]
:where ['[?j :journal-entry/line-items ?je]
'[?j :journal-entry/date ?date]
'[?je :journal-entry-line/account ?a]
'[(get-else $ ?je :journal-entry-line/debit 0.0) ?debit]
'[(get-else $ ?je :journal-entry-line/credit 0.0) ?credit]
'[?a :account/type ?account-type]
'[?account-type :db/ident ?account-type-ident]]}
:args [(d/db (d/connect uri)) "CBC"]})
(reduce
(fn [result [account-type date debit credit]]
(let [date (clj-time.coerce/from-date date)]
(let [year-month (str (clj-time.core/year date) "-" (clj-time.core/month date))]
(-> result
(update-in [year-month account-type :debit]
(fn [existing-debit]
(+ (or existing-debit 0.0)
debit)))
(update-in [year-month account-type :credit]
(fn [existing-credit]
(+ (or existing-credit 0.0)
credit)))
(update-in [year-month account-type :count] #(inc (or % 0)))))))
{})))
(defn attach-signature [client-code filename]
@(d/transact (d/connect uri)

View File

@@ -17,6 +17,22 @@
(fn [uri]
(pushy/set-token! p/history uri)))
(re-frame/reg-fx
:set-uri-params
(fn [uri-params]
(pushy/set-token! p/history
(str (.-protocol (.-location js/window)) "//" (.-host (.-location js/window)) (.-pathname (.-location js/window))
"?"
(cemerick.url/map->query (into {} (filter (fn [[k v]] v) uri-params)))
#_(reduce-kv (fn [result k v]
(if v
(str (or result "?")
(when result "&")
(name k) "=" (js/encodeURI v))
result))
nil
uri-params)))))
(re-frame/reg-fx
:new-window
(fn [url]

View File

@@ -4,6 +4,7 @@
[auto-ap.subs :as subs]
[auto-ap.routes :as routes]
[auto-ap.effects :as effects]
[auto-ap.utils :refer [by]]
[venia.core :as v]
[bidi.bidi :as bidi]
@@ -38,9 +39,7 @@
{:db (assoc db/default-db
:active-page handler
:last-client-id (.getItem js/localStorage "last-client-id")
:query-params (->> (:query (url (.-location js/window)))
(map (fn [[k v]] [(keyword k) v]))
(into {}))
:query-params (auto-ap.views.utils/query-params)
:user token)
:graphql {:token token
:query-obj {:venia/queries [[:client

View File

@@ -11,9 +11,7 @@
(defn- dispatch-route [matched-route]
(println "Matched route" matched-route)
(re-frame/dispatch [:auto-ap.events/set-active-page (:handler matched-route) (->> (:query (url (.-location js/window)))
(map (fn [[k v]] [(keyword k) v]))
(into {}))]))
(re-frame/dispatch [:auto-ap.events/set-active-page (:handler matched-route) (auto-ap.views.utils/query-params)]))
(def history (pushy/pushy dispatch-route parse-url))

View File

@@ -59,10 +59,17 @@
:end]]]})
(re-frame/reg-sub
::table-params
::specific-table-params
(fn [db]
(::table-params db)))
(re-frame/reg-sub
::table-params
:<- [::specific-table-params]
:<- [::subs/query-params]
(fn [[specific-table-params query-params]]
(merge (select-keys query-params #{:start :sort}) specific-table-params )))
(re-frame/reg-event-fx
::params-changed
[(re-frame/path [::table-params])]

View File

@@ -9,21 +9,41 @@
[auto-ap.routes :as routes]
[auto-ap.views.components.date-range-filter :refer [date-range-filter]]
[auto-ap.views.components.typeahead :refer [typeahead-entity]]
[auto-ap.views.utils :refer [active-when dispatch-event bind-field horizontal-field date->str str->date pretty standard]]
[auto-ap.views.utils :refer [active-when dispatch-event bind-field horizontal-field date->str str->date pretty standard query-params]]
[auto-ap.subs :as subs]
[auto-ap.events :as events]))
(re-frame/reg-sub
::specific-filters
(fn [db ]
(::filters db nil)))
(re-frame/reg-sub
::filters
(fn [db ]
(::filters db {})))
:<- [::specific-filters]
:<- [::subs/vendors-by-id]
:<- [::subs/query-params]
(fn [[specific-filters vendors-by-id query-params] ]
(let [url-filters (-> query-params
(select-keys #{:vendor-id
:date-range
:due-range
:invoice-number-like
:status}))
url-filters {:vendor (when-let [vendor-id (:vendor-id url-filters)]
{:id (str vendor-id)
:name (get-in vendors-by-id [(str vendor-id) :name] "Loading...")})
:date-range (:date-range url-filters)
:due-range (:due-range url-filters)
:invoice-number-like {:raw (:invoice-number-like url-filters)
:settled (:invoice-number-like url-filters)}}]
(merge url-filters specific-filters ))))
(re-frame/reg-sub
::filter
:<- [::filters]
(fn [filters [_ which]]
(filters which)))
(get filters which)))
(re-frame/reg-sub
::filter-params
@@ -32,12 +52,13 @@
(fn [[filters ap]]
{:vendor-id (:id (:vendor filters))
:date-range (:date-range filters)
:due-range (:due-range filters)
:invoice-number-like (:settled (:invoice-number-like filters))
:status (condp = ap
:invoices nil
:unpaid-invoices :unpaid
:paid-invoices :paid
:voided-invoices :voided)}))
:invoices nil
:unpaid-invoices :unpaid
:paid-invoices :paid
:voided-invoices :voided)}))
(re-frame/reg-event-fx
@@ -125,6 +146,13 @@
[date-range-filter
{:on-change-event [::filter-changed :date-range]
:value @(re-frame/subscribe [::filter :date-range])}]]
[:p.menu-label "Due Range"]
[:div
[date-range-filter
{:on-change-event [::filter-changed :due-range]
:value @(re-frame/subscribe [::filter :due-range])}]]
[:p.menu-label "Invoice #"]
[:div
[invoice-number-filter]]])]))

View File

@@ -1,10 +1,13 @@
(ns auto-ap.views.pages.home
(:require [auto-ap.views.components.layouts :refer [side-bar-layout]]
[re-frame.core :as re-frame]
[bidi.bidi :as bidi]
[auto-ap.routes :as routes]
[auto-ap.subs :as subs]
[cljs-time.core :as t]
[auto-ap.views.utils :refer [local-now date->str]]
[reagent.core :as r]))
[auto-ap.views.utils :refer [local-now date->str standard]]
[reagent.core :as r]
[pushy.core :as pushy]))
(def pie-chart (r/adapt-react-class js/Recharts.PieChart))
@@ -47,16 +50,21 @@
)
(defn make-cash-flow-chart [{:keys [width height data] }]
(println data)
[bar-chart {:width width :height height :data data :fill "#FFFFFF" :stackOffset "sign"}
[tool-tip]
[bar {:dataKey "effective-balance" :fill (get colors 1) :stackId "a" :name "Effective Balance"}]
[bar {:dataKey "outstanding-payments" :fill (get colors 0) :stackId "a" :name "Outstanding Payments"}]
[bar {:dataKey "invoices" :fill (get colors 3) :stackId "a" :name "Invoices"}]
[x-axis {:dataKey "name"}]
[y-axis]
[legend]]
(let [redirect-fn (fn [x]
(pushy/set-token! auto-ap.history/history (str (bidi/path-for routes/routes :unpaid-invoices) "?" (get (js->clj x) "query-params")))
)]
[bar-chart {:width width :height height :data data :fill "#FFFFFF" :stackOffset "sign"}
[tool-tip]
[bar {:dataKey "effective-balance" :fill (get colors 1) :stackId "a" :name "Effective Balance"
:on-click redirect-fn}]
[bar {:dataKey "outstanding-payments" :fill (get colors 0) :stackId "a" :name "Outstanding Payments"
:on-click redirect-fn}]
[bar {:dataKey "invoices" :fill (get colors 3) :stackId "a" :name "Invoices"
:on-click redirect-fn}]
[x-axis {:dataKey "name"}]
[y-axis]
[legend]])
)
(re-frame/reg-event-db
@@ -99,8 +107,6 @@
(let [due (if (t/before? (:due invoice) (local-now))
(local-now)
(:due invoice))]
(println due)
(update result (date->str due)
(fn [r] (+ (or r 0.0) (:outstanding-balance invoice))))))
{}
@@ -113,14 +119,18 @@
(reduce
(fn [[{:keys [effective-balance] } :as acc] day]
(let [invoices-due-today (invoices-due-soon (date->str (t/plus start-date (t/days day))) 0.0)]
(conj acc
{:name (date->str (t/plus start-date (t/days day)))
:effective-balance (- effective-balance invoices-due-today)
:invoices (- invoices-due-today)})))
(let [today (t/plus start-date (t/days day))]
(conj acc
{:name (date->str today)
:effective-balance (- effective-balance invoices-due-today)
:invoices (- invoices-due-today)
:query-params (cemerick.url/map->query {:due-range {:start (date->str today standard)
:end (date->str today standard)}})}))))
(list {:name (date->str start-date)
:effective-balance effective-balance
:invoices (- (invoices-due-soon (date->str start-date) 0.0))
:outstanding-payments (- outstanding-payments)})
:outstanding-payments (- outstanding-payments)
:query-params (cemerick.url/map->query {:due-range {:end (date->str start-date standard)}})})
(range 1 7))))))
(re-frame/reg-event-fx

View File

@@ -98,14 +98,17 @@
::params-change
[with-user (re-frame/inject-cofx ::inject/sub [::params])]
(fn [{::keys [params] :as cofx} _]
(println "params" params)
{:db (-> (:db cofx)
(assoc-in [:status :loading] true)
(assoc-in [::last-params] params))
:graphql {:token (-> cofx :db :user)
:query-obj (table/query params )
:on-success [::received]
:on-error [::events/page-failed]}}))
:on-error [::events/page-failed]}
:set-uri-params (dissoc params
:status
:client-id
:import-status)}))
(re-frame/reg-event-fx
::unmounted

View File

@@ -320,3 +320,10 @@
:before (fn [context]
(-> context
(assoc-in [:coeffects :user] (get-in context [:coeffects :db :user]))))))
(defn query-params []
(reduce-kv
(fn [result k v]
(assoc result (keyword k) (cljs.tools.reader.edn/read-string v)))
{}
(:query (cemerick.url/url (.-location js/window)))))