fixes bug, adds CSV template
This commit is contained in:
@@ -657,22 +657,45 @@
|
|||||||
:keywords [#"Mama Lu's Foods"]
|
:keywords [#"Mama Lu's Foods"]
|
||||||
:extract (fn [sheet vendor]
|
:extract (fn [sheet vendor]
|
||||||
(transduce (comp
|
(transduce (comp
|
||||||
(drop 5)
|
(drop 5)
|
||||||
(filter
|
(filter
|
||||||
(fn [r]
|
(fn [r]
|
||||||
(and
|
(and
|
||||||
(seq r)
|
(seq r)
|
||||||
(->> r second not-empty))))
|
(->> r second not-empty))))
|
||||||
(map
|
(map
|
||||||
(fn [r]
|
(fn [r]
|
||||||
(let [[_ customer-order-number num date name amount] r]
|
(let [[_ customer-order-number num date name amount] r]
|
||||||
{:customer-identifier (second (re-find #"([^:]*):" name))
|
{:customer-identifier (second (re-find #"([^:]*):" name))
|
||||||
:text name
|
:text name
|
||||||
:full-text name
|
:full-text name
|
||||||
:date (u/parse-value :clj-time "MM/dd/yyyy" (str/trim date))
|
:date (u/parse-value :clj-time "MM/dd/yyyy" (str/trim date))
|
||||||
:invoice-number (str customer-order-number "-" (Integer/parseInt num))
|
:invoice-number (str customer-order-number "-" (Integer/parseInt num))
|
||||||
:total (str amount)
|
:total (str amount)
|
||||||
:vendor-code vendor}))))
|
:vendor-code vendor}))))
|
||||||
|
conj
|
||||||
|
[]
|
||||||
|
sheet))}
|
||||||
|
|
||||||
|
{:vendor "Daylight Foods"
|
||||||
|
:keywords [#"CUSTNO"]
|
||||||
|
:extract (fn [sheet vendor]
|
||||||
|
(transduce (comp
|
||||||
|
(drop 1)
|
||||||
|
(filter
|
||||||
|
(fn [r]
|
||||||
|
(and
|
||||||
|
(seq r)
|
||||||
|
(->> r first not-empty))))
|
||||||
|
(map
|
||||||
|
(fn [[customer-number _ _ _ invoice-number date amount :as row]]
|
||||||
|
{:customer-identifier customer-number
|
||||||
|
:text (str/join " " row)
|
||||||
|
:full-text (str/join " " row)
|
||||||
|
:date (u/parse-value :clj-time "MM/dd/yyyy" (str/trim date))
|
||||||
|
:invoice-number invoice-number
|
||||||
|
:total (str amount)
|
||||||
|
:vendor-code vendor})))
|
||||||
conj
|
conj
|
||||||
[]
|
[]
|
||||||
sheet))}])
|
sheet))}])
|
||||||
|
|||||||
135
src/clj/auto_ap/ssr/company/reports/expense.clj
Normal file
135
src/clj/auto_ap/ssr/company/reports/expense.clj
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
(ns auto-ap.ssr.company.reports.expense
|
||||||
|
(:require [auto-ap.datomic :refer [conn merge-query]]
|
||||||
|
[auto-ap.graphql.utils :refer [extract-client-ids]]
|
||||||
|
[auto-ap.logging :as alog]
|
||||||
|
[auto-ap.ssr-routes :as ssr-routes]
|
||||||
|
[auto-ap.ssr.components :as com]
|
||||||
|
[auto-ap.ssr.form-cursor :as fc]
|
||||||
|
[auto-ap.ssr.hx :as hx]
|
||||||
|
[auto-ap.ssr.ui :refer [base-page]]
|
||||||
|
[auto-ap.ssr.utils :refer [apply-middleware-to-all-handlers
|
||||||
|
html-response wrap-schema-enforce]]
|
||||||
|
[bidi.bidi :as bidi]
|
||||||
|
[cemerick.url :as url]
|
||||||
|
[clj-time.coerce :as coerce]
|
||||||
|
[clj-time.core :as time]
|
||||||
|
[datomic.api :as dc]
|
||||||
|
[hiccup2.core :as hiccup]))
|
||||||
|
|
||||||
|
(defn lookup-data [request]
|
||||||
|
(let [query (cond-> {:query '{:find [?an ?user-date (sum ?amt)]
|
||||||
|
:in [$ [?clients ?start ?end]]
|
||||||
|
:where
|
||||||
|
[[(iol-ion.query/scan-invoices $ ?clients ?start ?end) [[?e _ ?sort-default] ...]]
|
||||||
|
[?e :invoice/date ?d]
|
||||||
|
[?e :invoice/expense-accounts ?iea]
|
||||||
|
[?iea :invoice-expense-account/amount ?amt]
|
||||||
|
[?iea :invoice-expense-account/account ?a]
|
||||||
|
[?a :account/name ?an]
|
||||||
|
[(iol-ion.query/iso-date ?d) ?user-date]]}
|
||||||
|
:args
|
||||||
|
[(dc/db conn)
|
||||||
|
[(extract-client-ids (:clients request)
|
||||||
|
(:client-id request)
|
||||||
|
(when (:client-code request)
|
||||||
|
[:client/code (:client-code request)]))
|
||||||
|
(some-> (time/plus (time/now) (time/days -14)) coerce/to-date)
|
||||||
|
(some-> (time/now) coerce/to-date)]]}
|
||||||
|
|
||||||
|
(:vendor-id (:query-params request))
|
||||||
|
(merge-query {:query '{:in [?v]
|
||||||
|
:where [ [?e :invoice/vendor ?v]]}
|
||||||
|
:args [ (:db/id (:vendor-id (:query-params request)))]}))]
|
||||||
|
|
||||||
|
(dc/query query)))
|
||||||
|
|
||||||
|
(defn card* [request]
|
||||||
|
(com/content-card {:class "w-full" :id "report"}
|
||||||
|
[:div {:class "flex flex-col px-8 py-8 space-y-3"}
|
||||||
|
[:div
|
||||||
|
[:h1.text-2xl.mb-3.font-bold "Expenses by day, 14 days"]
|
||||||
|
[:form {:hx-get (bidi.bidi/path-for ssr-routes/only-routes :company-expense-report-card )
|
||||||
|
:hx-trigger "change"
|
||||||
|
:hx-target "#report"
|
||||||
|
:hx-swap "outerHTML"}
|
||||||
|
(fc/start-form
|
||||||
|
(:query-params request)
|
||||||
|
(:form-errors request)
|
||||||
|
[:div
|
||||||
|
(fc/with-field :vendor-id
|
||||||
|
(com/validated-field {:label "Vendor"
|
||||||
|
:errors (fc/field-errors)}
|
||||||
|
(com/typeahead {:name (fc/field-name)
|
||||||
|
:class "w-64"
|
||||||
|
:url (bidi/path-for ssr-routes/only-routes :vendor-search)
|
||||||
|
:value (fc/field-value)
|
||||||
|
:value-fn :db/id
|
||||||
|
:content-fn :vendor/name})))])]
|
||||||
|
[:div
|
||||||
|
(let [data (lookup-data request)
|
||||||
|
distinct-accounts (take 5 (->> data
|
||||||
|
(reduce
|
||||||
|
(fn [acc [an _ amount]]
|
||||||
|
(update acc an (fnil + 0.0) amount))
|
||||||
|
{})
|
||||||
|
(sort-by last)
|
||||||
|
(reverse)
|
||||||
|
(map first)
|
||||||
|
(take 5)))
|
||||||
|
lookup (->>
|
||||||
|
(reduce
|
||||||
|
(fn [acc [a d v]]
|
||||||
|
(assoc-in acc [a d] v))
|
||||||
|
{}
|
||||||
|
data))
|
||||||
|
dates (for [d (range -14 0)]
|
||||||
|
(iol-ion.query/iso-date (coerce/to-date (time/plus (time/now) (time/days d)))))
|
||||||
|
series (for [ea distinct-accounts]
|
||||||
|
(for [d dates]
|
||||||
|
(get-in lookup [ea d] 0)))]
|
||||||
|
[:div {:class "w-full h-64"
|
||||||
|
:id "client-chart"
|
||||||
|
:x-data (hx/json {:chart {:labels dates
|
||||||
|
#_["2 years ago" "1 year ago" "today"],
|
||||||
|
:series (alog/peek ::test series)}})
|
||||||
|
:x-init (hiccup/raw "new Chartist.Bar($el, chart, {seriesBarDistance:10}); ")}
|
||||||
|
[:div.flex.space-x-2.my-4
|
||||||
|
(for [[d color] (map vector distinct-accounts ["bg-green-500" "bg-red-500" "bg-blue-500" "bg-yellow-500" "bg-purple-500"])]
|
||||||
|
[:span.px-2.py-1.rounded.rounded-full.text-sm.text-gray-100 {:class color} d])]])]]]))
|
||||||
|
|
||||||
|
(defn page [request]
|
||||||
|
(base-page
|
||||||
|
request
|
||||||
|
(com/page {:nav com/company-aside-nav
|
||||||
|
:client-selection (:client-selection request)
|
||||||
|
:client (:client request)
|
||||||
|
:clients (:clients request)
|
||||||
|
:identity (:identity request)
|
||||||
|
:app-params {:hx-get (bidi/path-for ssr-routes/only-routes :company-expense-report)
|
||||||
|
:hx-trigger "clientSelected from:body"
|
||||||
|
:hx-select "#app-contents"
|
||||||
|
:hx-swap "outerHTML swap:300ms"}}
|
||||||
|
(com/breadcrumbs {}
|
||||||
|
[:a {:href (bidi/path-for ssr-routes/only-routes :company)}
|
||||||
|
"My Company"]
|
||||||
|
[:a {:href (bidi/path-for ssr-routes/only-routes :company-expense-report)}
|
||||||
|
"Expense Report"])
|
||||||
|
(card* request))
|
||||||
|
"My Company"))
|
||||||
|
|
||||||
|
(defn card [request]
|
||||||
|
(html-response
|
||||||
|
(card* request)
|
||||||
|
:headers {"hx-push-url" (str "?" (url/map->query (update (:query-params request) :vendor-id :db/id))) }))
|
||||||
|
|
||||||
|
(def key->handler
|
||||||
|
(apply-middleware-to-all-handlers
|
||||||
|
{:company-expense-report page
|
||||||
|
:company-expense-report-card card}
|
||||||
|
(fn [h]
|
||||||
|
(-> h
|
||||||
|
(wrap-schema-enforce :query-schema
|
||||||
|
[:map {:default {}}
|
||||||
|
[:vendor-id {:optional true}
|
||||||
|
[:maybe
|
||||||
|
[:entity-map {:pull [:vendor/name :db/id]}]]]] )))))
|
||||||
Reference in New Issue
Block a user