Makes insights actually work
This commit is contained in:
@@ -1859,6 +1859,11 @@ input:checked + .toggle-bg {
|
|||||||
background-color: rgb(253 246 178 / var(--tw-bg-opacity));
|
background-color: rgb(253 246 178 / var(--tw-bg-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bg-red-300 {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(255 104 104 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.bg-opacity-50 {
|
.bg-opacity-50 {
|
||||||
--tw-bg-opacity: 0.5;
|
--tw-bg-opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,23 +64,27 @@
|
|||||||
(assoc similar-transaction :score score)))
|
(assoc similar-transaction :score score)))
|
||||||
|
|
||||||
(defn similar->recommendation [txs client]
|
(defn similar->recommendation [txs client]
|
||||||
(->> txs
|
(try
|
||||||
(reduce (fn [acc t]
|
(->> txs
|
||||||
(-> acc
|
(reduce (fn [acc t]
|
||||||
(update-in [[(:db/id (:transaction/vendor t))
|
(-> acc
|
||||||
(:db/id (:transaction-account/account (first (:transaction/accounts t))))]
|
(update-in [[(:db/id (:transaction/vendor t))
|
||||||
:count]
|
(:db/id (:transaction-account/account (first (:transaction/accounts t))))]
|
||||||
(fnil inc 0))
|
:count]
|
||||||
(update-in [[(:db/id (:transaction/vendor t))
|
(fnil inc 0))
|
||||||
(:db/id (:transaction-account/account (first (:transaction/accounts t))))]
|
(update-in [[(:db/id (:transaction/vendor t))
|
||||||
:seen-by-client?]
|
(:db/id (:transaction-account/account (first (:transaction/accounts t))))]
|
||||||
(fn [seen-by-client?] (or seen-by-client? (= (:db/id (:transaction/client t))
|
:seen-by-client?]
|
||||||
client))))))
|
(fn [seen-by-client?] (or seen-by-client? (= (:db/id (:transaction/client t))
|
||||||
{})
|
client))))))
|
||||||
(map (fn [[k v]]
|
{})
|
||||||
(-> k
|
(map (fn [[k v]]
|
||||||
(conj (:count v))
|
(-> k
|
||||||
(conj (:seen-by-client? v)))))))
|
(conj (:count v))
|
||||||
|
(conj (:seen-by-client? v))))))
|
||||||
|
(catch Exception e
|
||||||
|
(println e)
|
||||||
|
[])))
|
||||||
|
|
||||||
(defn get-outcome-recommendations []
|
(defn get-outcome-recommendations []
|
||||||
(for [[transaction client] (get-recent-transactions)
|
(for [[transaction client] (get-recent-transactions)
|
||||||
|
|||||||
@@ -7,13 +7,15 @@
|
|||||||
(defn button- [params & children]
|
(defn button- [params & children]
|
||||||
[:button (update params
|
[:button (update params
|
||||||
:class #(cond-> %
|
:class #(cond-> %
|
||||||
true (str " text-white focus:ring-4 font-bold rounded-lg text-xs p-3 text-center mr-2 inline-flex items-center hover:scale-105 transition duration-100 justify-center")
|
true (str " focus:ring-4 font-bold rounded-lg text-xs p-3 text-center mr-2 inline-flex items-center hover:scale-105 transition duration-100 justify-center")
|
||||||
(= :secondary (:color params)) (str " bg-blue-500 hover:bg-blue-600 focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700")
|
(= :secondary (:color params)) (str " text-white bg-blue-500 hover:bg-blue-600 focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700")
|
||||||
(= :primary (:color params)) (str " bg-green-500 hover:bg-green-600 focus:ring-green-300 dark:bg-green-600 dark:hover:bg-green-700 ")))
|
(= :primary (:color params)) (str " text-white bg-green-500 hover:bg-green-600 focus:ring-green-300 dark:bg-green-600 dark:hover:bg-green-700 ")
|
||||||
|
(nil? (:color params))
|
||||||
|
(str " bg-white dark:bg-gray-600 border-gray-300 dark:border-gray-700 text-gray-500 hover:text-gray-800 dark:text-gray-400 dark:hover:text-gray-100 font-medium border border-gray-300 dark:border-gray-700")))
|
||||||
[:div.htmx-indicator.flex.items-center
|
[:div.htmx-indicator.flex.items-center
|
||||||
(svg/spinner {:class "inline w-4 h-4 text-white"})
|
(svg/spinner {:class "inline w-4 h-4 text-white"})
|
||||||
[:div.ml-3 "Loading..."]]
|
[:div.ml-3 "Loading..."]]
|
||||||
(into [:div.htmx-indicator-hidden.inline-flex.gap-2.items-center.justify-center ] children)])
|
(into [:div.htmx-indicator-hidden.inline-flex.gap-2.items-center.justify-center] children)])
|
||||||
|
|
||||||
(defn icon-button- [params & children]
|
(defn icon-button- [params & children]
|
||||||
(into
|
(into
|
||||||
|
|||||||
@@ -20,4 +20,4 @@
|
|||||||
children))
|
children))
|
||||||
|
|
||||||
(defn badge- [params & children]
|
(defn badge- [params & children]
|
||||||
[:div {:class "absolute inline-flex items-center justify-center w-6 h-6 text-xs font-bold text-white bg-red-500 border-2 border-white rounded-full -top-2 -right-2 dark:border-gray-900"} children])
|
[:div {:class "absolute inline-flex items-center justify-center w-6 h-6 text-xs font-bold text-white bg-red-300 border-3 border-white rounded-full -top-2 -right-2 dark:border-gray-900"} children])
|
||||||
|
|||||||
@@ -23,7 +23,9 @@
|
|||||||
[datomic.api :as dc]
|
[datomic.api :as dc]
|
||||||
[hiccup2.core :as hiccup]
|
[hiccup2.core :as hiccup]
|
||||||
[iol-ion.tx :refer [random-tempid]]
|
[iol-ion.tx :refer [random-tempid]]
|
||||||
[auto-ap.client-routes :as client-routes])
|
[auto-ap.client-routes :as client-routes]
|
||||||
|
[auto-ap.datomic.vendors :as d-vendors]
|
||||||
|
[clj-time.core :as time])
|
||||||
(:import
|
(:import
|
||||||
(java.util UUID)))
|
(java.util UUID)))
|
||||||
|
|
||||||
@@ -328,10 +330,16 @@ invoice_dropzone = new Dropzone(\"#invoice\", {
|
|||||||
[_ total] (:textract-invoice/total textract-invoice)
|
[_ total] (:textract-invoice/total textract-invoice)
|
||||||
[_ date] (:textract-invoice/date textract-invoice)
|
[_ date] (:textract-invoice/date textract-invoice)
|
||||||
[_ invoice-number] (:textract-invoice/invoice-number textract-invoice)
|
[_ invoice-number] (:textract-invoice/invoice-number textract-invoice)
|
||||||
|
vendor (dc/pull (dc/db conn) d-vendors/default-read vendor-id)
|
||||||
location (when client-id
|
location (when client-id
|
||||||
(->> (dc/pull (dc/db conn) '[:client/locations] client-id)
|
(->> (dc/pull (dc/db conn) '[:client/locations] client-id)
|
||||||
:client/locations
|
:client/locations
|
||||||
first))]
|
first))
|
||||||
|
due (and (:vendor/terms vendor)
|
||||||
|
(coerce/to-date
|
||||||
|
(time/plus date (time/days (d-vendors/terms-for-client-id vendor client-id)))))
|
||||||
|
scheduled-payment (and (d-vendors/automatically-paid-for-client-id? vendor client-id)
|
||||||
|
due)]
|
||||||
(when (and client-id date invoice-number vendor-id total)
|
(when (and client-id date invoice-number vendor-id total)
|
||||||
{:db/id (random-tempid)
|
{:db/id (random-tempid)
|
||||||
:invoice/client client-id
|
:invoice/client client-id
|
||||||
@@ -340,6 +348,8 @@ invoice_dropzone = new Dropzone(\"#invoice\", {
|
|||||||
:invoice/invoice-number invoice-number
|
:invoice/invoice-number invoice-number
|
||||||
:invoice/total total
|
:invoice/total total
|
||||||
:invoice/date date
|
:invoice/date date
|
||||||
|
:invoice/due (coerce/to-date due)
|
||||||
|
:invoice/scheduled-payment (coerce/to-date scheduled-payment)
|
||||||
:invoice/location location
|
:invoice/location location
|
||||||
:invoice/import-status :import-status/imported
|
:invoice/import-status :import-status/imported
|
||||||
:invoice/outstanding-balance total
|
:invoice/outstanding-balance total
|
||||||
|
|||||||
@@ -26,6 +26,20 @@
|
|||||||
:transaction/bank-account [:bank-account/code]}
|
:transaction/bank-account [:bank-account/code]}
|
||||||
:transaction/account-confidence
|
:transaction/account-confidence
|
||||||
:transaction/date])
|
:transaction/date])
|
||||||
|
(defn parse-outcome [tx]
|
||||||
|
(update tx :transaction/outcome-recommendation
|
||||||
|
(fn [ors]
|
||||||
|
(map
|
||||||
|
(fn [[v a c s]]
|
||||||
|
{:vendor (dc/pull (dc/db conn)
|
||||||
|
[:vendor/name :db/id]
|
||||||
|
v)
|
||||||
|
:account (dc/pull (dc/db conn)
|
||||||
|
[:account/name :db/id]
|
||||||
|
a)
|
||||||
|
:count c
|
||||||
|
:seen-by-client? s})
|
||||||
|
ors))))
|
||||||
|
|
||||||
(defn transaction-recommendations [identity selected-client & {:keys [after]}]
|
(defn transaction-recommendations [identity selected-client & {:keys [after]}]
|
||||||
(let [visible-clients (visible-clients identity)]
|
(let [visible-clients (visible-clients identity)]
|
||||||
@@ -54,20 +68,7 @@
|
|||||||
(#(if after
|
(#(if after
|
||||||
(drop 1 %)
|
(drop 1 %)
|
||||||
%))
|
%))
|
||||||
(map (fn [tx]
|
(map parse-outcome)
|
||||||
(update tx :transaction/outcome-recommendation
|
|
||||||
(fn [ors]
|
|
||||||
(map
|
|
||||||
(fn [[v a c s]]
|
|
||||||
{:vendor (dc/pull (dc/db conn)
|
|
||||||
[:vendor/name :db/id]
|
|
||||||
v)
|
|
||||||
:account (dc/pull (dc/db conn)
|
|
||||||
[:account/name :db/id]
|
|
||||||
a)
|
|
||||||
:count c
|
|
||||||
:seen-by-client? s})
|
|
||||||
ors)))))
|
|
||||||
(take 50)
|
(take 50)
|
||||||
(into []))))
|
(into []))))
|
||||||
|
|
||||||
@@ -144,39 +145,52 @@
|
|||||||
[:div.tag.is-danger.is-light (str "$" (Math/round (:transaction/amount r)))]))
|
[:div.tag.is-danger.is-light (str "$" (Math/round (:transaction/amount r)))]))
|
||||||
|
|
||||||
(com/data-grid-right-stack-cell {}
|
(com/data-grid-right-stack-cell {}
|
||||||
(when-not hide-actions?
|
[:div.flex.gap-2.flex-col {:style {:width "25em"}}
|
||||||
[:div.flex.gap-2.flex-col {:style {:width "25em"}}
|
(for [or (take 3 (sort-by (comp - :count)
|
||||||
(for [or (sort-by (comp - :count)
|
(:transaction/outcome-recommendation r)))]
|
||||||
(:transaction/outcome-recommendation r))]
|
[:form {:hx-post (bidi/path-for ssr-routes/only-routes
|
||||||
[:form {:hx-post (bidi/path-for ssr-routes/only-routes
|
:transaction-insight-code
|
||||||
:transaction-insight-code
|
:transaction-id (:db/id r))
|
||||||
:transaction-id (:db/id r))
|
:hx-target "closest tr"
|
||||||
:hx-target "closest tr"}
|
:hx-swap "outerHTML"
|
||||||
(when-let [vendor-id (:db/id (:vendor or))]
|
:disabled hide-actions?}
|
||||||
[:input {:type :hidden :value vendor-id :name "vendor"}])
|
(when-let [vendor-id (:db/id (:vendor or))]
|
||||||
(when-let [account-id (:db/id (:account or))]
|
[:input {:type :hidden :value vendor-id :name "vendor"}])
|
||||||
[:input {:type :hidden :value account-id :name "account"}])
|
(when-let [account-id (:db/id (:account or))]
|
||||||
|
[:input {:type :hidden :value account-id :name "account"}])
|
||||||
|
|
||||||
(com/button {:color (if (:seen-by-client? or)
|
(com/button {:color (if (:seen-by-client? or)
|
||||||
:primary
|
:primary
|
||||||
:secondary)
|
:secondary)
|
||||||
:style {:position "relative"}}
|
:style {:position "relative"
|
||||||
(:vendor/name (:vendor or))
|
:display "block"
|
||||||
(when (:vendor/name (:vendor or))
|
:width "100%"}}
|
||||||
" | ")
|
(:vendor/name (:vendor or))
|
||||||
(:account/name (:account or))
|
(when (:vendor/name (:vendor or))
|
||||||
(com/badge {:color :secondary}
|
" | ")
|
||||||
(:count or)))])
|
(:account/name (:account or))
|
||||||
(com/icon-button {:hx-get (bidi/path-for ssr-routes/only-routes
|
(com/badge {:color :secondary}
|
||||||
:transaction-insight-explain
|
(:count or)))])
|
||||||
:transaction-id (:db/id r))
|
[:div.flex.flex-row.gap-2
|
||||||
:hx-target "#modal-holder"
|
(com/button {:hx-get (bidi/path-for ssr-routes/only-routes
|
||||||
:hx-swap "outerHTML"}
|
:transaction-insight-explain
|
||||||
svg/question)]))))
|
:transaction-id (:db/id r))
|
||||||
|
:hx-target "#modal-holder"
|
||||||
|
:hx-swap "outerHTML"}
|
||||||
|
[:div.flex
|
||||||
|
svg/question
|
||||||
|
"Explain"])
|
||||||
|
(com/button {:hx-delete (bidi/path-for ssr-routes/only-routes
|
||||||
|
:transaction-insight-disapprove
|
||||||
|
:transaction-id (:db/id r))
|
||||||
|
:hx-target "closest tr"
|
||||||
|
:hx-swap "outerHTML"}
|
||||||
|
[:div.flex
|
||||||
|
svg/question
|
||||||
|
"Reject"])]])))
|
||||||
|
|
||||||
(defn code [{:keys [identity session] {:keys [transaction-id]} :route-params {:strs [vendor account]} :form-params}]
|
(defn code [{:keys [identity session] {:keys [transaction-id]} :route-params {:strs [vendor account]} :form-params}]
|
||||||
(let [approval-details (dc/pull (dc/db conn) [{:transaction/recommended-account [:account/location :db/id]}
|
(let [approval-details (dc/pull (dc/db conn) [:transaction/recommended-vendor
|
||||||
:transaction/recommended-vendor
|
|
||||||
:transaction/amount
|
:transaction/amount
|
||||||
:db/id
|
:db/id
|
||||||
{:transaction/client [:client/locations]}]
|
{:transaction/client [:client/locations]}]
|
||||||
@@ -201,25 +215,25 @@
|
|||||||
:transaction-account/account (-> account :db/id)
|
:transaction-account/account (-> account :db/id)
|
||||||
:transaction-account/amount (* 0.01 cents)
|
:transaction-account/amount (* 0.01 cents)
|
||||||
:transaction-account/location location})
|
:transaction-account/location location})
|
||||||
(spread-cents cents-to-distribute (count valid-locations))))}]]
|
(spread-cents cents-to-distribute (count valid-locations))))}]
|
||||||
|
db-before (dc/db conn)]
|
||||||
@(dc/transact conn [updated-transaction])
|
@(dc/transact conn [updated-transaction])
|
||||||
(html-response (transaction-row
|
(html-response (transaction-row
|
||||||
(dc/pull (dc/db conn)
|
(parse-outcome (dc/pull db-before
|
||||||
pull-expr
|
pull-expr
|
||||||
(Long/parseLong transaction-id))
|
(Long/parseLong transaction-id)))
|
||||||
:auto-remove? true
|
|
||||||
:hide-actions? true
|
:hide-actions? true
|
||||||
:class "live-added"))))
|
:class "live-added"
|
||||||
|
"_" (hiccup/raw "init transition opacity to 0 then remove me")))))
|
||||||
|
|
||||||
(defn disapprove [{:keys [identity session] {:keys [transaction-id]} :route-params}]
|
(defn disapprove [{:keys [identity session] {:keys [transaction-id]} :route-params}]
|
||||||
(let [transaction-id (cond-> transaction-id string? (Long/parseLong))]
|
(let [transaction-id (cond-> transaction-id string? (Long/parseLong))
|
||||||
@(dc/transact conn [[:upsert-transaction {:db/id transaction-id :transaction/recommended-account nil :transaction/recommended-vendor nil}]])
|
db-before (dc/db conn)]
|
||||||
|
@(dc/transact conn [[:upsert-transaction {:db/id transaction-id :transaction/outcome-recommendation nil}]])
|
||||||
(html-response (transaction-row
|
(html-response (transaction-row
|
||||||
(dc/pull (dc/db conn) pull-expr transaction-id)
|
(parse-outcome (dc/pull db-before pull-expr transaction-id))
|
||||||
:auto-remove? true
|
:hide-actions? true
|
||||||
:hide-actions? true
|
"_" (hiccup/raw "init transition opacity to 0 over 500ms then remove me")))))
|
||||||
:class "live-removed"
|
|
||||||
"_" (hiccup/raw "init transition opacity to 0 then remove me")))))
|
|
||||||
(defn explain [{:keys [identity session] {:keys [transaction-id]} :route-params}]
|
(defn explain [{:keys [identity session] {:keys [transaction-id]} :route-params}]
|
||||||
(let [r (dc/pull (dc/db conn)
|
(let [r (dc/pull (dc/db conn)
|
||||||
pull-expr
|
pull-expr
|
||||||
@@ -288,7 +302,8 @@
|
|||||||
(com/data-grid-header {:style {:width "15em"}} "Account")
|
(com/data-grid-header {:style {:width "15em"}} "Account")
|
||||||
(com/data-grid-header {:style {:width "8em"}} "Date")
|
(com/data-grid-header {:style {:width "8em"}} "Date")
|
||||||
(com/data-grid-header {} "Description")
|
(com/data-grid-header {} "Description")
|
||||||
(com/data-grid-header {:style {:width "8em"}} "Amount")]})))
|
(com/data-grid-header {:style {:width "8em"}} "Amount")
|
||||||
|
(com/data-grid-header {})]})))
|
||||||
|
|
||||||
(defn insight-table [{:keys [session identity]}]
|
(defn insight-table [{:keys [session identity]}]
|
||||||
(html-response (insight-table* {:selected-client
|
(html-response (insight-table* {:selected-client
|
||||||
|
|||||||
@@ -35,7 +35,6 @@
|
|||||||
:active-route active-route
|
:active-route active-route
|
||||||
:route :admin})
|
:route :admin})
|
||||||
|
|
||||||
|
|
||||||
[:p.menu-label "Setup"]
|
[:p.menu-label "Setup"]
|
||||||
(menu-item {:label "Clients"
|
(menu-item {:label "Clients"
|
||||||
:icon-class "fa fa-star-o"
|
:icon-class "fa fa-star-o"
|
||||||
@@ -96,8 +95,14 @@
|
|||||||
:active-route active-route
|
:active-route active-route
|
||||||
:route :admin-ezcater-xls
|
:route :admin-ezcater-xls
|
||||||
:icon-style {:font-size "25px"}})
|
:icon-style {:font-size "25px"}})
|
||||||
|
(menu-item {:label "Invoice glimpse"
|
||||||
|
:icon-class "icon icon-cog-play-1"
|
||||||
|
:test-route #{:invoice-glimpse}
|
||||||
|
:active-route active-route
|
||||||
|
:route :invoice-glimpse
|
||||||
|
:icon-style {:font-size "25px"}})
|
||||||
|
|
||||||
(into [:div ] children)])
|
(into [:div] children)])
|
||||||
|
|
||||||
#?(:clj
|
#?(:clj
|
||||||
(defn admin-side-bar [active-page]
|
(defn admin-side-bar [active-page]
|
||||||
|
|||||||
Reference in New Issue
Block a user