Sales nearly ready

This commit is contained in:
2024-04-30 22:38:21 -07:00
parent f6dba46835
commit e3b17e50e2
9 changed files with 421 additions and 483 deletions

File diff suppressed because one or more lines are too long

View File

@@ -1879,32 +1879,37 @@
:db/valueType :db.type/instant :db/valueType :db.type/instant
:db/cardinality :db.cardinality/one :db/cardinality :db.cardinality/one
:db/index true} :db/index true}
{:db/ident :sales-summary/sales-items {:db/ident :sales-summary/items
:db/valueType :db.type/ref
:db/isComponent true,
:db/cardinality :db.cardinality/many}
{:db/ident :sales-summary/payment-items
:db/valueType :db.type/ref :db/valueType :db.type/ref
:db/isComponent true, :db/isComponent true,
:db/cardinality :db.cardinality/many} :db/cardinality :db.cardinality/many}
{:db/ident :sales-summary/dirty
:db/noHistory true,
:db/valueType :db.type/boolean
:db/cardinality :db.cardinality/one}
{:db/ident :sales-summary/client+date
:db/valueType :db.type/tuple
:db/tupleAttrs [:sales-summary/client :sales-summary/date]
:db/cardinality :db.cardinality/one
:db/unique :db.unique/identity
:db/index true}
{:db/ident :sales-summary/client+dirty
:db/valueType :db.type/tuple
:db/tupleAttrs [:sales-summary/client :sales-summary/dirty]
:db/cardinality :db.cardinality/one
:db/index true}
{:db/ident :sales-summary-item/category {:db/ident :sales-summary-item/category
:db/valueType :db.type/string :db/valueType :db.type/string
:db/cardinality :db.cardinality/one} :db/cardinality :db.cardinality/one}
{:db/ident :ledger-mapped/ledger-side {:db/ident :sales-summary-item/sort-order
:db/valueType :db.type/ref :db/valueType :db.type/long
:db/cardinality :db.cardinality/one :db/cardinality :db.cardinality/one
:db/noHistory true} :db/noHistory true}
{:db/ident :ledger-mapped/account {:db/ident :sales-summary-item/manual?
:db/valueType :db.type/ref :db/valueType :db.type/boolean
:db/cardinality :db.cardinality/one :db/cardinality :db.cardinality/one
:db/noHistory true} :db/noHistory true}
{:db/ident :ledger-mapped/amount
:db/valueType :db.type/double
:db/cardinality :db.cardinality/one
:db/noHistory true}
{:db/ident :ledger-side/credit}
{:db/ident :ledger-side/debit}
{:db/ident :sales-summary-item/total {:db/ident :sales-summary-item/total
:db/noHistory true, :db/noHistory true,
:db/valueType :db.type/double :db/valueType :db.type/double
@@ -1921,79 +1926,23 @@
:db/noHistory true, :db/noHistory true,
:db/valueType :db.type/double :db/valueType :db.type/double
:db/cardinality :db.cardinality/one} :db/cardinality :db.cardinality/one}
{:db/ident :sales-summary/dirty
:db/noHistory true,
:db/valueType :db.type/boolean
:db/cardinality :db.cardinality/one}
{:db/ident :sales-summary/client+date
:db/valueType :db.type/tuple
:db/tupleAttrs [:sales-summary/client :sales-summary/date]
:db/cardinality :db.cardinality/one
:db/unique :db.unique/identity
:db/index true}
{:db/ident :sales-summary/client+dirty
:db/valueType :db.type/tuple
:db/tupleAttrs [:sales-summary/client :sales-summary/dirty]
:db/cardinality :db.cardinality/one
:db/index true}
{:db/ident :sales-summary/discount {:db/ident :ledger-mapped/ledger-side
:db/noHistory true,
:db/valueType :db.type/double
:db/cardinality :db.cardinality/one}
{:db/ident :sales-summary/total-card-payments
:db/noHistory true,
:db/valueType :db.type/double
:db/cardinality :db.cardinality/one}
{:db/ident :sales-summary/total-tax
:db/noHistory true,
:db/isComponent true
:db/valueType :db.type/ref :db/valueType :db.type/ref
:db/cardinality :db.cardinality/one :db/cardinality :db.cardinality/one
} :db/noHistory true}
{:db/ident :sales-summary/total-tip {:db/ident :ledger-mapped/account
:db/noHistory true,
:db/isComponent true
:db/valueType :db.type/ref :db/valueType :db.type/ref
:db/cardinality :db.cardinality/one } :db/cardinality :db.cardinality/one
{:db/ident :sales-summary/total-returns :db/noHistory true}
:db/noHistory true, {:db/ident :ledger-mapped/amount
:db/valueType :db.type/double :db/valueType :db.type/double
:db/cardinality :db.cardinality/one} :db/cardinality :db.cardinality/one
:db/noHistory true}
{:db/ident :sales-summary/total-card-fees {:db/ident :ledger-side/credit}
:db/noHistory true, {:db/ident :ledger-side/debit}
:db/valueType :db.type/double
:db/cardinality :db.cardinality/one}
{:db/ident :sales-summary/total-gift-card-payments ]
:db/noHistory true,
:db/valueType :db.type/double
:db/cardinality :db.cardinality/one}
{:db/ident :sales-summary/total-card-refunds
:db/noHistory true,
:db/valueType :db.type/double
:db/cardinality :db.cardinality/one}
{:db/ident :sales-summary/total-cash-payments
:db/noHistory true,
:db/valueType :db.type/double
:db/cardinality :db.cardinality/one}
{:db/ident :sales-summary/total-unknown-processor-payments
:db/noHistory true,
:db/valueType :db.type/double
:db/cardinality :db.cardinality/one}
{:db/ident :sales-summary/total-cash-refunds
:db/noHistory true,
:db/valueType :db.type/double
:db/cardinality :db.cardinality/one}
{:db/ident :sales-summary/total-food-app-payments
:db/noHistory true,
:db/valueType :db.type/double
:db/cardinality :db.cardinality/one}
{:db/ident :sales-summary/total-food-app-refunds
:db/noHistory true,
:db/valueType :db.type/double
:db/cardinality :db.cardinality/one}]

View File

@@ -6,6 +6,7 @@
[clj-time.coerce :as c] [clj-time.coerce :as c]
[clj-time.core :as time] [clj-time.core :as time]
[clj-time.periodic :as per] [clj-time.periodic :as per]
[clojure.string :as str]
[com.brunobonacci.mulog :as mu] [com.brunobonacci.mulog :as mu]
[datomic.api :as dc])) [datomic.api :as dc]))
@@ -31,6 +32,13 @@
(dc/db conn))] (dc/db conn))]
(apply mark-dirty c (last-n-days days)))) (apply mark-dirty c (last-n-days days))))
(defn lookup-account [number]
(ffirst (dc/q '[:find ?a
:in $ ?number
:where [?a :account/numeric-code ?number]]
(dc/db conn)
number)))
(defn delete-all [] (defn delete-all []
@(dc/transact-async conn @(dc/transact-async conn
@@ -63,6 +71,30 @@
c c
date)) date))
0.0))) 0.0)))
(def name->number
{"gyros and pitas" 40111
"returns" 41000
"card payments" 75460
"cash payments" 75452
"food app payments" 72350
"unknown" 40000
"discounts" 41000
"fees" 75400
"alcohol" 46900
"beverages" 42000
"bowls" 40118
"catering" 43010
"desserts" 40116
"fries" 40117
"plates" 40113
"sides" 40115
"soup & salads" 40114
"uncategorized" 40000
"tax" 25700
"tip" 25500
"card refunds" 41000})
(defn get-payment-items [c date] (defn get-payment-items [c date]
(->> (->>
(dc/q '[:find ?processor ?type-name (sum ?total) (dc/q '[:find ?processor ?type-name (sum ?total)
@@ -104,7 +136,9 @@
{}) {})
(map (fn [[k v]] (map (fn [[k v]]
{:db/id (str (java.util.UUID/randomUUID)) {:db/id (str (java.util.UUID/randomUUID))
:sales-summary-item/sort-order 0
:sales-summary-item/category k :sales-summary-item/category k
:ledger-mapped/amount (if (= "Card Payments" k) :ledger-mapped/amount (if (= "Card Payments" k)
(- v (get-fee c date)) (- v (get-fee c date))
v) v)
@@ -119,9 +153,10 @@
(dc/db conn) (dc/db conn)
[[c] date date]))] [[c] date date]))]
{:db/id (str (java.util.UUID/randomUUID)) {:db/id (str (java.util.UUID/randomUUID))
:sales-summary-item/sort-order 1
:sales-summary-item/category "Discounts" :sales-summary-item/category "Discounts"
:ledger-mapped/amount discount :ledger-mapped/amount discount
:ledger-mapped/ledger-side :ledger-side/debit })) :ledger-mapped/ledger-side :ledger-side/debit}))
(defn get-refund-items [c date] (defn get-refund-items [c date]
(->> (->>
@@ -149,6 +184,7 @@
{}) {})
(map (fn [[k v]] (map (fn [[k v]]
{:db/id (str (java.util.UUID/randomUUID)) {:db/id (str (java.util.UUID/randomUUID))
:sales-summary-item/sort-order 3
:sales-summary-item/category k :sales-summary-item/category k
:ledger-mapped/amount v :ledger-mapped/amount v
:ledger-mapped/ledger-side :ledger-side/credit})))) :ledger-mapped/ledger-side :ledger-side/credit}))))
@@ -158,12 +194,15 @@
(defn get-fees [c date] (defn get-fees [c date]
(when-let [fee (get-fee c date)] (when-let [fee (get-fee c date)]
{:db/id (str (java.util.UUID/randomUUID)) {:db/id (str (java.util.UUID/randomUUID))
:sales-summary-item/sort-order 2
:sales-summary-item/category "Fees" :sales-summary-item/category "Fees"
:ledger-mapped/amount fee :ledger-mapped/amount fee
:ledger-mapped/ledger-side :ledger-side/debit})) :ledger-mapped/ledger-side :ledger-side/debit}))
(defn- get-tax [c date] (defn- get-tax [c date]
{:db/id (str (java.util.UUID/randomUUID)) {:db/id (str (java.util.UUID/randomUUID))
:sales-summary-item/category "Tax"
:sales-summary-item/sort-order 1
:ledger-mapped/ledger-side :ledger-side/credit :ledger-mapped/ledger-side :ledger-side/credit
:ledger-mapped/amount :ledger-mapped/amount
(or (ffirst (dc/q '[:find (sum ?tax) (or (ffirst (dc/q '[:find (sum ?tax)
@@ -179,6 +218,10 @@
(defn- get-tip [c date] (defn- get-tip [c date]
{:ledger-mapped/ledger-side :ledger-side/credit {:ledger-mapped/ledger-side :ledger-side/credit
:sales-summary-item/sort-order 2
:db/id (str (java.util.UUID/randomUUID))
:sales-summary-item/category "Tip"
:ledger-mapped/amount (or (ffirst (dc/q '[:find (sum ?tip) :ledger-mapped/amount (or (ffirst (dc/q '[:find (sum ?tip)
:with ?c :with ?c
:in $ [?clients ?start-date ?end-date] :in $ [?clients ?start-date ?end-date]
@@ -204,6 +247,7 @@
(for [[category total tax discount] sales] (for [[category total tax discount] sales]
{:db/id (str (java.util.UUID/randomUUID)) {:db/id (str (java.util.UUID/randomUUID))
:sales-summary-item/category category :sales-summary-item/category category
:sales-summary-item/sort-order 0
:sales-summary-item/total total :sales-summary-item/total total
:sales-summary-item/net (- (+ total discount) tax) :sales-summary-item/net (- (+ total discount) tax)
:sales-summary-item/tax tax :sales-summary-item/tax tax
@@ -212,6 +256,23 @@
:ledger-mapped/amount (- (+ total discount) tax) :ledger-mapped/amount (- (+ total discount) tax)
#_#_:ledger-mapped/account nil}))) #_#_:ledger-mapped/account nil})))
(defn- get-returns [c date]
(when-let [amount (ffirst (dc/q '[:find (sum ?r)
:with ?e
:in $ [?clients ?start-date ?end-date]
:where [(iol-ion.query/scan-sales-orders $ ?clients ?start-date ?end-date) [[?e _ ?sort-default] ...]]
[?e :sales-order/returns ?r]
#_[?e :sales-order/charges ?c]
#_[?c :charge/tax ?tax]]
(dc/db conn)
[[c] date date]))]
{:db/id (str (java.util.UUID/randomUUID))
:sales-summary-item/category "Returns"
:ledger-mapped/amount amount
:ledger-mapped/ledger-side :ledger-side/debit}))
(defn sales-summaries-v2 [] (defn sales-summaries-v2 []
(doseq [[c client-code] (dc/q '[:find ?c ?client-code (doseq [[c client-code] (dc/q '[:find ?c ?client-code
:in $ :in $
@@ -227,51 +288,25 @@
:sales-summary/dirty false :sales-summary/dirty false
:sales-summary/client+date [c date] :sales-summary/client+date [c date]
:sales-summary/sales-items :sales-summary/items
(conj (get-sales c date) (->>
{:db/id (str (java.util.UUID/randomUUID)) (get-sales c date)
:sales-summary-item/category "Returns" (concat (get-payment-items c date))
:ledger-mapped/amount (or (ffirst (dc/q '[:find (sum ?r)
:with ?e
:in $ [?clients ?start-date ?end-date]
:where [(iol-ion.query/scan-sales-orders $ ?clients ?start-date ?end-date) [[?e _ ?sort-default] ...]]
[?e :sales-order/returns ?r]
#_[?e :sales-order/charges ?c]
#_[?c :charge/tax ?tax]]
(dc/db conn)
[[c] date date]))
0.0)
:ledger-mapped/ledger-side :ledger-side/debit})
:sales-summary/payment-items
(->> (get-payment-items c date)
(concat (get-refund-items c date)) (concat (get-refund-items c date))
(cons (get-discounts c date)) (cons (get-discounts c date))
(cons (get-fees c date)) (cons (get-fees c date))
(filter identity)) (cons (get-tax c date))
(cons (get-tip c date))
:sales-summary/total-tax (cons (get-returns c date))
(get-tax c date) (filter identity)
:sales-summary/total-tip (map (fn [z]
(get-tip c date) (assoc z :ledger-mapped/account (some-> z :sales-summary-item/category str/lower-case name->number lookup-account)
:sales-summary-item/manual? false))
#_#_:sales-summary/total-card-payments )) }]
(or (ffirst (dc/q '[:find (sum ?total) (if (seq (:sales-summary/items result))
:with ?c
:in $ [?clients ?start-date ?end-date]
:where [(iol-ion.query/scan-sales-orders $ ?clients ?start-date ?end-date) [[?e _ ?sort-default] ...]]
[?e :sales-order/charges ?c]
[?c :charge/type-name "CARD"]
[?c :charge/total ?total]]
(dc/db conn)
[[c] date date]))
0.0)
#_:sales-summary/total-unknown-processor-payments}]
(if (seq (:sales-summary/sales-items result))
(do (do
(alog/info ::upserting-summaries (alog/info ::upserting-summaries
:category-count (count (:sales-summary/sales-items result))) :category-count (count (:sales-summary/items result)))
@(dc/transact conn [[:upsert-entity result]])) @(dc/transact conn [[:upsert-entity result]]))
@(dc/transact conn [{:db/id id :sales-summary/dirty false}])))))) @(dc/transact conn [{:db/id id :sales-summary/dirty false}]))))))
@@ -281,199 +316,6 @@
) )
#_(defn sales-summaries-v1 []
(doseq [[c client-code] (dc/q '[:find ?c ?client-code
:in $
:where [?c :client/code ?client-code]]
(dc/db conn))
{:sales-summary/keys [date] :db/keys [id]} (dirty-sales-summaries c)]
(mu/with-context {:client-code client-code
:date date}
(alog/info ::updating)
(let [sales (->> (dc/q '[:find ?item-name ?category (sum ?total) (sum ?tax) (sum ?discount)
:with ?e ?li
:in $ [?clients ?start-date ?end-date]
:where [(iol-ion.query/scan-sales-orders $ ?clients ?start-date ?end-date) [[?e _ ?sort-default] ...]]
[?e :sales-order/line-items ?li]
[(get-else $ ?li :order-line-item/item-name "Unknown") ?item-name]
[?li :order-line-item/category ?category]
[?li :order-line-item/total ?total]
[?li :order-line-item/tax ?tax]
[?li :order-line-item/discount ?discount]]
(dc/db conn)
[[c] date date]))
result {:db/id id
:sales-summary/client c
:sales-summary/date date
:sales-summary/dirty false
:sales-summary/client+date [c date]
:sales-summary/discount (or (ffirst (dc/q '[:find (sum ?discount)
:with ?e
:in $ [?clients ?start-date ?end-date]
:where [(iol-ion.query/scan-sales-orders $ ?clients ?start-date ?end-date) [[?e _ ?sort-default] ...]]
[?e :sales-order/discount ?discount]]
(dc/db conn)
[[c] date date]))
0.0)
:sales-summary/total-returns (or (ffirst (dc/q '[:find (sum ?r)
:with ?e
:in $ [?clients ?start-date ?end-date]
:where [(iol-ion.query/scan-sales-orders $ ?clients ?start-date ?end-date) [[?e _ ?sort-default] ...]]
[?e :sales-order/returns ?r]
#_[?e :sales-order/charges ?c]
#_[?c :charge/tax ?tax]]
(dc/db conn)
[[c] date date]))
0.0)
:sales-summary/sales-items
(for [[item-name category total tax discount] sales]
{:db/id (str (java.util.UUID/randomUUID))
:sales-summary-item/item-name item-name
:sales-summary-item/category category
:sales-summary-item/total total
:sales-summary-item/tax tax
:sales-summary-item/discount discount})
:sales-summary/total-tax
(or (ffirst (dc/q '[:find (sum ?tax)
:with ?e
:in $ [?clients ?start-date ?end-date]
:where [(iol-ion.query/scan-sales-orders $ ?clients ?start-date ?end-date) [[?e _ ?sort-default] ...]]
[?e :sales-order/tax ?tax]
#_[?e :sales-order/charges ?c]
#_[?c :charge/tax ?tax]]
(dc/db conn)
[[c] date date]))
0.0)
:sales-summary/total-tip
(or (ffirst (dc/q '[:find (sum ?tip)
:with ?c
:in $ [?clients ?start-date ?end-date]
:where [(iol-ion.query/scan-sales-orders $ ?clients ?start-date ?end-date) [[?e _ ?sort-default] ...]]
[?e :sales-order/charges ?c]
[?c :charge/tip ?tip]]
(dc/db conn)
[[c] date date]))
0.0)
:sales-summary/total-card-payments
(or (ffirst (dc/q '[:find (sum ?total)
:with ?c
:in $ [?clients ?start-date ?end-date]
:where [(iol-ion.query/scan-sales-orders $ ?clients ?start-date ?end-date) [[?e _ ?sort-default] ...]]
[?e :sales-order/charges ?c]
[?c :charge/type-name "CARD"]
[?c :charge/total ?total]]
(dc/db conn)
[[c] date date]))
0.0)
:sales-summary/total-unknown-processor-payments
(or (ffirst (dc/q '[:find (sum ?total)
:with ?c
:in $ [?clients ?start-date ?end-date]
:where [(iol-ion.query/scan-sales-orders $ ?clients ?start-date ?end-date) [[?e _ ?sort-default] ...]]
[?e :sales-order/charges ?c]
[?c :charge/type-name "OTHER"]
[?c :charge/processor :ccp-processor/na]
[?c :charge/total ?total]]
(dc/db conn)
[[c] date date]))
0.0)
:sales-summary/total-card-fees
(or (ffirst (dc/q '[:find ?f
:in $ ?client ?d
:where
[?e :expected-deposit/client ?client]
[?e :expected-deposit/sales-date ?d]
[?e :expected-deposit/fee ?f]]
(dc/db conn)
c
date))
0.0)
:sales-summary/total-card-refunds
(or (ffirst (dc/q '[:find (sum ?t)
:in $ [?clients ?start-date ?end-date]
:where
:where [(iol-ion.query/scan-sales-refunds $ ?clients ?start-date ?end-date) [[?e _ ?sort-default] ...]]
[?e :sales-refund/type "CARD"]
[?e :sales-refund/total ?t]]
(dc/db conn)
[[c] date date]))
0.0)
:sales-summary/total-cash-payments
(or (ffirst (dc/q '[:find (sum ?total)
:with ?c
:in $ [?clients ?start-date ?end-date]
:where [(iol-ion.query/scan-sales-orders $ ?clients ?start-date ?end-date) [[?e _ ?sort-default] ...]]
[?e :sales-order/charges ?c]
[?c :charge/total ?total]
[?c :charge/type-name "CASH"]]
(dc/db conn)
[[c] date date]))
0.0)
:sales-summary/total-gift-card-payments
(or (ffirst (dc/q '[:find (sum ?total)
:with ?c
:in $ [?clients ?start-date ?end-date]
:where [(iol-ion.query/scan-sales-orders $ ?clients ?start-date ?end-date) [[?e _ ?sort-default] ...]]
[?e :sales-order/charges ?c]
[?c :charge/total ?total]
(or [?c :charge/type-name "SQUARE_GIFT_CARD"]
[?c :charge/type-name "WALLET"]
[?c :charge/type-name "GIFT_CARD"])]
(dc/db conn)
[[c] date date]))
0.0)
:sales-summary/total-cash-refunds
(or (ffirst (dc/q '[:find (sum ?t)
:in $ [?clients ?start-date ?end-date]
:where
:where [(iol-ion.query/scan-sales-refunds $ ?clients ?start-date ?end-date) [[?e _ ?sort-default] ...]]
[?e :sales-refund/type "CASH"]
[?e :sales-refund/total ?t]]
(dc/db conn)
[[c] date date]))
0.0)
:sales-summary/total-food-app-payments
(or (ffirst (dc/q '[:find (sum ?total)
:with ?c
:in $ [?clients ?start-date ?end-date] [?processor ...]
:where [(iol-ion.query/scan-sales-orders $ ?clients ?start-date ?end-date) [[?e _ ?sort-default] ...]]
[?e :sales-order/charges ?c]
[?c :charge/processor ?processor]
[?c :charge/total ?total]]
(dc/db conn)
[[c] date date]
#{:ccp-processor/toast
#_:ccp-processor/ezcater
#_:ccp-processor/koala
:ccp-processor/doordash
:ccp-processor/grubhub
:ccp-processor/uber-eats}))
0.0)
:sales-summary/total-food-app-refunds
(or (ffirst (dc/q '[:find (sum ?t)
:in $ [?clients ?start-date ?end-date]
:where [(iol-ion.query/scan-sales-refunds $ ?clients ?start-date ?end-date) [[?e _ ?sort-default] ...]]
[?e :sales-refund/type "EXTERNAL"]
[?e :sales-refund/total ?t]]
(dc/db conn)
[[c] date date]))
0.0)}]
(if (seq (:sales-summary/sales-items result))
(do
(alog/info ::upserting-summaries
:category-count (count (:sales-summary/sales-items result)))
@(dc/transact conn [[:upsert-entity result]]))
@(dc/transact conn [{:db/id id :sales-summary/dirty false}]))))))
(defn reset-summaries [] (defn reset-summaries []
@(dc/transact conn (->> (dc/q '[:find ?sos @(dc/transact conn (->> (dc/q '[:find ?sos

View File

@@ -2,23 +2,28 @@
(:require [auto-ap.datomic (:require [auto-ap.datomic
:refer [apply-pagination apply-sort-3 conn merge-query pull-many :refer [apply-pagination apply-sort-3 conn merge-query pull-many
query2]] query2]]
[auto-ap.datomic.accounts :as d-accounts]
[auto-ap.graphql.utils :refer [extract-client-ids]] [auto-ap.graphql.utils :refer [extract-client-ids]]
[auto-ap.routes.admin.sales-summaries :as route] [auto-ap.routes.admin.sales-summaries :as route]
[auto-ap.routes.utils [auto-ap.routes.utils
:refer [wrap-admin wrap-client-redirect-unauthenticated]] :refer [wrap-admin wrap-client-redirect-unauthenticated]]
[auto-ap.ssr-routes :as ssr-routes] [auto-ap.ssr-routes :as ssr-routes]
[auto-ap.ssr.common-handlers :refer [add-new-entity-handler]]
[auto-ap.ssr.components :as com] [auto-ap.ssr.components :as com]
[auto-ap.ssr.components.multi-modal :as mm] [auto-ap.ssr.components.multi-modal :as mm]
[auto-ap.ssr.form-cursor :as fc] [auto-ap.ssr.form-cursor :as fc]
[auto-ap.ssr.grid-page-helper :as helper] [auto-ap.ssr.grid-page-helper :as helper]
[auto-ap.ssr.hx :as hx]
[auto-ap.ssr.svg :as svg] [auto-ap.ssr.svg :as svg]
[auto-ap.ssr.utils [auto-ap.ssr.utils
:refer [apply-middleware-to-all-handlers entity-id :refer [apply-middleware-to-all-handlers entity-id html-response
wrap-schema-enforce]] money strip temp-id wrap-schema-enforce]]
[auto-ap.time :as atime] [auto-ap.time :as atime]
[bidi.bidi :as bidi] [bidi.bidi :as bidi]
[clj-time.coerce :as c] [clj-time.coerce :as c]
[clojure.string :as str]
[datomic.api :as dc] [datomic.api :as dc]
[hiccup.util :as hu]
[iol-ion.query :refer [dollars=]] [iol-ion.query :refer [dollars=]]
[malli.core :as mc] [malli.core :as mc]
[malli.util :as mut])) [malli.util :as mut]))
@@ -50,20 +55,18 @@
:size :small}))]]) :size :small}))]])
(def default-read '[:db/id (def default-read '[:db/id
* *
[:sales-summary/date :xform clj-time.coerce/from-date] [:sales-summary/date :xform clj-time.coerce/from-date]
{:sales-summary/client [:client/code :client/name]} {:sales-summary/client [:client/code :client/name :db/id]}
{:sales-summary/total-tax [{[:ledger-mapped/ledger-side :xform iol-ion.query/ident] [:db/ident]} {:sales-summary/items [{[:ledger-mapped/ledger-side :xform iol-ion.query/ident] [:db/ident]
:ledger-mapped/amount]} } ;; TODO clientize
{:sales-summary/total-tip [{[:ledger-mapped/ledger-side :xform iol-ion.query/ident] [:db/ident]} :ledger-mapped/account
:ledger-mapped/amount]}
{:sales-summary/sales-items [{[:ledger-mapped/ledger-side :xform iol-ion.query/ident] [:db/ident]}
:ledger-mapped/amount :ledger-mapped/amount
:sales-summary-item/category]} :sales-summary-item/category
{:sales-summary/payment-items [{[:ledger-mapped/ledger-side :xform iol-ion.query/ident] [:db/ident]} :sales-summary-item/sort-order
:ledger-mapped/amount :db/id
:sales-summary-item/category]}]) ;; TODO :sales-summary-item/manual?]
} ]) ;; TODO
(defn fetch-ids [db request] (defn fetch-ids [db request]
(let [query-params (:parsed-query-params request) (let [query-params (:parsed-query-params request)
@@ -133,11 +136,22 @@
:total-unknown-processor-payments (:sales-summary/total-unknown-processor-payments ss 0.0) :total-unknown-processor-payments (:sales-summary/total-unknown-processor-payments ss 0.0)
:discounts (+ (:sales-summary/discount ss 0.0)) :discounts (+ (:sales-summary/discount ss 0.0))
:returns (+ (:sales-summary/total-returns ss 0.0))}) :returns (+ (:sales-summary/total-returns ss 0.0))})
(defn sort-items [ss]
(sort-by (juxt :ledger-mapped/ledger-side :sales-summary-item/sort-order :sales-summary-item/category) ss))
(defn all-items [ss]
(->> [(:sales-summary/total-tax ss) (:sales-summary/total-tip ss)]
(into (:sales-summary/payment-items ss)) (defn total-debits [items]
(into (:sales-summary/sales-items ss)))) (->> items
(filter #(= :ledger-side/debit (:ledger-mapped/ledger-side %)))
(map #(:ledger-mapped/amount % 0.0))
(reduce + 0.0)))
(defn total-credits [items]
(->> items
(filter #(= :ledger-side/credit (:ledger-mapped/ledger-side %)))
(map #(:ledger-mapped/amount % 0.0))
(reduce + 0.0)))
(def grid-page (def grid-page
(helper/build {:id "entity-table" (helper/build {:id "entity-table"
@@ -146,7 +160,7 @@
:fetch-page fetch-page :fetch-page fetch-page
:page-specific-nav filters :page-specific-nav filters
:row-buttons (fn [_ entity] :row-buttons (fn [_ entity]
[(com/icon-button {:hx-put (bidi/path-for ssr-routes/only-routes [(com/icon-button {:hx-get (bidi/path-for ssr-routes/only-routes
::route/edit-wizard ::route/edit-wizard
:db/id (:db/id entity))} :db/id (:db/id entity))}
svg/pencil)]) svg/pencil)])
@@ -180,56 +194,40 @@
:sort-key "date" :sort-key "date"
:render #(some-> % :sales-summary/date (atime/unparse-local atime/normal-date))} :render #(some-> % :sales-summary/date (atime/unparse-local atime/normal-date))}
{:key "credits"
:name "credits"
:sort-key "credits"
:render (fn [ss]
(let [total-debits (->> (all-items ss)
(filter #(= :ledger-side/debit (:ledger-mapped/ledger-side %)))
(map #(:ledger-mapped/amount % 0.0))
(reduce + 0.0))
total-credits (->> (all-items ss)
(filter #(= :ledger-side/credit (:ledger-mapped/ledger-side %)))
(map #(:ledger-mapped/amount % 0.0))
(reduce + 0.0))]
[:ul
(for [si (:sales-summary/sales-items ss)
:when (= :ledger-side/credit (:ledger-mapped/ledger-side si))]
[:li (:sales-summary-item/category si) ": " (format "$%,.2f" (:ledger-mapped/amount si))])
[:li "Sales subtotal: " (format "$%,.2f" (reduce + 0.0 (map :ledger-mapped/amount (:sales-summary/sales-items ss))))]
(for [si (:sales-summary/payment-items ss)
:when (= :ledger-side/credit (:ledger-mapped/ledger-side si))]
[:li (:sales-summary-item/category si) ": " (format "$%,.2f" (:ledger-mapped/amount si))])
[:li "Tax: " (format "$%,.2f" (:ledger-mapped/amount (:sales-summary/total-tax ss)))]
[:li "Tips: " (format "$%,.2f" (:ledger-mapped/amount (:sales-summary/total-tip ss)))]
[:li (com/pill {:color (if (dollars= total-debits total-credits)
:primary
:red)} "Total: " (format "$%,.2f" total-credits))]])
#_(count))}
{:key "debits" {:key "debits"
:name "debits" :name "debits"
:sort-key "debits" :sort-key "debits"
:render (fn [ss] :render (fn [ss]
(let [ total-debits (->> (all-items ss) (let [total-debits (total-debits (:sales-summary/items ss))
(filter #(= :ledger-side/debit (:ledger-mapped/ledger-side %))) total-credits (total-credits (:sales-summary/items ss))]
(map #(:ledger-mapped/amount % 0.0))
(reduce + 0.0))
total-credits (->> (all-items ss)
(filter #(= :ledger-side/credit (:ledger-mapped/ledger-side %)))
(map #(:ledger-mapped/amount % 0.0))
(reduce + 0.0))]
[:ul [:ul
(for [si (:sales-summary/payment-items ss) (for [si (sort-items (:sales-summary/items ss))
:when (= :ledger-side/debit (:ledger-mapped/ledger-side si))] :when (= :ledger-side/debit (:ledger-mapped/ledger-side si))]
[:li (:sales-summary-item/category si) ": " (format "$%,.2f" (:ledger-mapped/amount si))]) [:li (:sales-summary-item/category si) ": " (format "$%,.2f" (:ledger-mapped/amount si))
(when-not (:ledger-mapped/account si)
[:span.pl-4 (com/pill {:color :red}
"missing account")])]
)
[:li (com/pill {:color (if (dollars= total-debits total-credits) [:li (com/pill {:color (if (dollars= total-debits total-credits)
:primary :primary
:red)} "Total: " (format "$%,.2f" total-debits))]]) :red)} "Total: " (format "$%,.2f" total-debits))]]))}
{:key "credits"
#_(count))}]})) :name "credits"
:sort-key "credits"
:render (fn [ss]
(let [total-debits (total-debits (:sales-summary/items ss))
total-credits (total-credits (:sales-summary/items ss))]
[:ul
(for [si (sort-items (:sales-summary/items ss))
:when (= :ledger-side/credit (:ledger-mapped/ledger-side si))]
[:li (:sales-summary-item/category si) ": " (format "$%,.2f" (:ledger-mapped/amount si))
(when-not (:ledger-mapped/account si)
[:span.pl-4 (com/pill {:color :red}
"missing account")])])
[:li (com/pill {:color (if (dollars= total-debits total-credits)
:primary
:red)} "Total: " (format "$%,.2f" total-credits))]]))}]}))
;; TODO schema cleanup ;; TODO schema cleanup
;; Decide on what should be calculated as generating ledger entries, and what should be calculated ;; Decide on what should be calculated as generating ledger entries, and what should be calculated
@@ -245,9 +243,154 @@
(def edit-schema (def edit-schema
[:map [:map
[:db/id entity-id] [:db/id entity-id]
[:sales-summary/sales-items [:sales-summary/client [:map [:db/id entity-id]]]
[:sales-summary/items
[:vector {:coerce? true} [:vector {:coerce? true}
[:map [:db/id entity-id]]]] ]) [:and
[:map
[:db/id [:or entity-id temp-id]]
[:sales-summary-item/category [:string {:decode/string strip}]]
[:sales-summary-item/manual? {:default false :decode/arbitrary (fn [x] (cond
(boolean? x)
x
(nil? x)
false
(str/blank? x)
false
:else
true))} :boolean]
[:ledger-mapped/account entity-id]
[:credit {:optional true} [:maybe money]]
[:debit {:optional true} [:maybe money]]]
[:fn {:error/message "Must choose one of credit/debit"
:error/path [:credit]}
(fn [x]
(not (and (:credit x)
(:debit x))))]]]] ])
(defn summary-total-row* [request]
(let [total-credits (-> request
:multi-form-state
:step-params
:sales-summary/items
(total-credits))
total-debits (-> request
:multi-form-state
:step-params
:sales-summary/items
(total-debits))]
(com/data-grid-row {:id "total-row"
:hx-trigger "change from:closest form target:.amount-field"
:hx-put (bidi.bidi/path-for ssr-routes/only-routes ::route/expense-account-total)
:hx-target "this"
:hx-swap "innerHTML"}
(com/data-grid-cell {})
(com/data-grid-cell {:class "text-right"} [:span.font-bold.text-right "TOTAL"])
(com/data-grid-cell {:class "text-right"}
(format "$%,.2f" total-debits))
(com/data-grid-cell {:class "text-right"}
(format "$%,.2f" total-credits)))))
(defn unbalanced-row* [request]
(let [total-credits (-> request
:multi-form-state
:step-params
:sales-summary/items
(total-credits))
total-debits (-> request
:multi-form-state
:step-params
:sales-summary/items
(total-debits))]
(com/data-grid-row {:id "total-row"
:hx-trigger "change from:closest form target:.amount-field"
:hx-put (bidi.bidi/path-for ssr-routes/only-routes ::route/expense-account-total)
:hx-target "this"
:hx-swap "innerHTML"}
(com/data-grid-cell {})
(com/data-grid-cell {:class "text-right"} [:span.font-bold.text-right "UNBALANCED"])
(com/data-grid-cell {:class "text-right"}
(when (and
(not (dollars= total-credits total-debits))
(> total-debits total-credits))
(format "$%,.2f" (- total-debits total-credits))))
(com/data-grid-cell {:class "text-right"}
(when
(and (not (dollars= total-credits total-debits))
(> total-credits total-debits))
(format "$%,.2f" (- total-credits total-debits)))))))
(defn- account-typeahead*
[{:keys [name value client-id]}]
[:div.flex.flex-col
(com/typeahead {:name name
:placeholder "Search..."
:url (hu/url (bidi/path-for ssr-routes/only-routes :account-search)
{:client-id client-id
:purpose "invoice"})
:value value
:content-fn (fn [value]
(:account/name (d-accounts/clientize (dc/pull (dc/db conn) d-accounts/default-read value)
client-id)))})])
(defn sales-summary-item-row* [{:keys [value client-id]}]
(let [manual? (fc/field-value (:sales-summary-item/manual? value))]
(com/data-grid-row (cond-> {:x-ref "p"
:x-data (hx/json {})}
(fc/field-value (:new? value)) (hx/htmx-transition-appear ))
(fc/with-field :db/id
(com/hidden {:name (fc/field-name)
:value (fc/field-value)}))
(when manual?
(fc/with-field :sales-summary-item/manual?
(com/hidden {:name (fc/field-name)
:value true})))
(com/data-grid-cell {}
(fc/with-field :sales-summary-item/category
(if manual?
(com/validated-field {:errors (fc/field-errors)}
(com/text-input {:placeholder "Category/Explanation"
:name (fc/field-name)
:value (fc/field-value)}))
(list
(com/hidden {:name (fc/field-name)
:value (fc/field-value)})
(fc/field-value (:sales-summary-item/category value))))))
(com/data-grid-cell {}
(fc/with-field :ledger-mapped/account
(com/validated-field {:errors (fc/field-errors)}
(account-typeahead* {:value (fc/field-value)
:client-id client-id
:name (fc/field-name)}))))
(com/data-grid-cell {:class "text-right"}
(if manual?
(fc/with-field :debit
(com/validated-field {:errors (fc/field-errors)}
(com/money-input {:class "w-24"
:name (fc/field-name)
:value (fc/field-value)})))
(when (= (fc/field-value (:ledger-mapped/ledger-side value))
:ledger-side/debit)
(format "$%,.2f" (fc/field-value (:ledger-mapped/amount value))))))
(com/data-grid-cell {:class "text-right"}
(if manual?
(fc/with-field :credit
(com/validated-field {:errors (fc/field-errors)}
(com/money-input {:class "w-24"
:name (fc/field-name)
:value (fc/field-value)})))
(when (= (fc/field-value (:ledger-mapped/ledger-side value))
:ledger-side/credit)
(format "$%,.2f" (fc/field-value (:ledger-mapped/amount value))))))
(com/data-grid-cell {:class "align-top"}
(when manual?
(com/a-icon-button {"@click.prevent.stop" "$refs.p.remove()"} svg/x))))))
(defrecord MainStep [linear-wizard] (defrecord MainStep [linear-wizard]
mm/ModalWizardStep mm/ModalWizardStep
@@ -260,7 +403,7 @@
[]) [])
(step-schema [_] (step-schema [_]
(mut/select-keys (mm/form-schema linear-wizard) #{:db/id})) (mut/select-keys (mm/form-schema linear-wizard) #{:db/id :sales-summary/items}))
(render-step (render-step
[this {:keys [multi-form-state] :as request}] [this {:keys [multi-form-state] :as request}]
@@ -273,16 +416,39 @@
(fc/with-field :db/id (fc/with-field :db/id
(com/hidden {:name (fc/field-name) (com/hidden {:name (fc/field-name)
:value (fc/field-value)})) :value (fc/field-value)}))
(com/data-grid {:headers
[(com/data-grid-header {} "Category")
(pr-str multi-form-state) ]) (com/data-grid-header {} "Account")
(com/data-grid-header {} "Debits")
(com/data-grid-header {} "Credits")
(com/data-grid-header {} "")]}
(fc/with-field :sales-summary/items
(list
(fc/cursor-map #(sales-summary-item-row* {:value %
:client-id (:db/id (:sales-summary/client (:snapshot multi-form-state))) }))
;; TODO
(com/data-grid-new-row {:colspan 5
:hx-get (bidi/path-for ssr-routes/only-routes ::route/new-summary-item)
:row-offset 0
:index (count (fc/field-value))
:tr-params {:hx-vals (hx/json {:client-id (:db/id (:sales-summary/client (:snapshot multi-form-state)))})}} ;; TODO
"New Summary Item")))
(summary-total-row* request)
(unbalanced-row* request)) ])
:footer :footer
(mm/default-step-footer linear-wizard this :validation-route ::route/edit-wizard-navigate (mm/default-step-footer linear-wizard this :validation-route ::route/edit-wizard-navigate)
:next-button (com/button {:color :primary :x-ref "next" :class "w-32" :validation-route ::route/edit-wizard-navigate
:hx-put (bidi.bidi/path-for ssr-routes/only-routes :width-height-class "lg:w-[850px] lg:h-[900px]")))
::route/edit-wizard-navigate)} "Save"))
:validation-route ::route/edit-wizard-navigate))) (defn attach-ledger [i]
(cond-> i
(:credit i) (assoc :ledger-mapped/ledger-side :ledger-side/credit
:ledger-mapped/amount (:credit i))
(:debit i) (assoc :ledger-mapped/ledger-side :ledger-side/debit
:ledger-mapped/amount (:debit i))
true (dissoc :credit :debit)
true (assoc :sales-summary-item/manual? true)))
(defrecord EditWizard [_ current-step] (defrecord EditWizard [_ current-step]
mm/LinearModalWizard mm/LinearModalWizard
@@ -299,8 +465,8 @@
this request this request
:form-params :form-params
(-> mm/default-form-props (-> mm/default-form-props
(assoc :hx-post (assoc :hx-put
(str (bidi/path-for ssr-routes/only-routes ::route/edit-submit)))) (str (bidi/path-for ssr-routes/only-routes ::route/edit-wizard-submit))))
:render-timeline? false)) :render-timeline? false))
(steps [_] (steps [_]
[:main]) [:main])
@@ -311,76 +477,36 @@
(form-schema [_] (form-schema [_]
edit-schema) edit-schema)
(submit [this {:keys [multi-form-state request-method identity] :as request}] (submit [this {:keys [multi-form-state request-method identity] :as request}]
#_(let [invoice (:snapshot multi-form-state) (let [result (:snapshot multi-form-state )
transaction [:upsert-entity {:db/id (:db/id result)
_ (alog/peek invoice) :sales-summary/items (map
extant? (:db/id invoice) (fn [i]
client-id (->db-id (:invoice/client invoice)) (if (:sales-summary-item/manual? i)
vendor-id (->db-id (:invoice/vendor invoice)) (attach-ledger i)
paid-amount (if-let [outstanding-balance {:db/id (:db/id i)
(and extant? :ledger-mapped/account (:ledger-mapped/account i)
(- }))
(pull-attr (dc/db conn) (:sales-summary/items result))}]]
:invoice/total (clojure.pprint/pprint (:sales-summary/items result))
(:db/id invoice)) @(dc/transact conn [ transaction])
(pull-attr (dc/db conn)
:invoice/outstanding-balance
(:db/id invoice))))]
outstanding-balance
0.0)
outstanding-balance (- (or
(:invoice/total (:step-params multi-form-state))
(:invoice/total (:snapshot multi-form-state)))
paid-amount)
transaction [:upsert-invoice (-> multi-form-state
:snapshot
(assoc :db/id (or (:db/id invoice) "invoice"))
(dissoc :customize-due-and-scheduled? :invoice/journal-entry :invoice/payments :customize-accounts)
(assoc :invoice/expense-accounts (if (= :customize (:customize-accounts invoice))
(-> multi-form-state :step-params :invoice/expense-accounts)
[{:db/id "123"
:invoice-expense-account/location "Shared"
:invoice-expense-account/account (:db/id (:vendor/default-account (clientize-vendor (get-vendor vendor-id)
client-id)))
:invoice-expense-account/amount (or (:invoice/total (:step-params multi-form-state))
(:invoice/total (:snapshot multi-form-state)))}]))
(assoc
:invoice/outstanding-balance outstanding-balance
:invoice/import-status :import-status/imported
:invoice/status (if (dollars= 0.0 outstanding-balance)
:invoice-status/paid
:invoice-status/unpaid))
(maybe-spread-locations)
(update :invoice/date coerce/to-date)
(update :invoice/due coerce/to-date)
(update :invoice/scheduled-payment coerce/to-date))]]
(assert-invoice-amounts-add-up (second transaction))
(when-not extant?
(assert-no-conflicting invoice))
(exception->4xx #(assert-can-see-client (:identity request) client-id))
(exception->4xx #(assert-not-locked client-id (:invoice/date invoice)))
(let [transaction-result (audit-transact [transaction] (:identity request))]
(solr/touch-with-ledger (get-in transaction-result [:tempids "invoice"]))
(if extant?
(html-response (html-response
(@(resolve 'auto-ap.ssr.invoices/row*) identity (dc/pull (dc/db conn) default-read (:db/id invoice)) {:flash? true (row* identity (dc/pull (dc/db conn) default-read (:db/id result))
{:flash? true
:request request}) :request request})
:headers (cond-> {"hx-trigger" "modalclose" :headers (cond-> {"hx-trigger" "modalclose"
"hx-retarget" (format "#entity-table tr[data-id=\"%d\"]" (:db/id invoice)) "hx-retarget" (format "#entity-table tr[data-id=\"%d\"]" (:db/id result))
"hx-reswap" "outerHTML"})) "hx-reswap" "outerHTML"})))))
(assoc-in (mm/navigate-handler {:request (assoc-in request [:multi-form-state :snapshot :db/id] (get-in transaction-result [:tempids "invoice"]))
:to-step :next-steps})
[:headers "hx-trigger"] "invalidated"))))))
(def edit-wizard (->EditWizard nil nil)) (def edit-wizard (->EditWizard nil nil))
(defn initial-edit-wizard-state [request] (defn initial-edit-wizard-state [request]
(let [entity (dc/pull (dc/db conn) default-read (:db/id (:route-params request))) (let [entity (dc/pull (dc/db conn) default-read (:db/id (:route-params request)))
entity (select-keys entity (mut/keys edit-schema))] entity (select-keys entity (mut/keys edit-schema))
entity (update entity :sales-summary/items (comp #(map (fn [x]
(if (= :ledger-side/debit (:ledger-mapped/ledger-side x))
(assoc x :debit (:ledger-mapped/amount x))
(assoc x :credit (:ledger-mapped/amount x))))
%) sort-items))]
(mm/->MultiStepFormState entity [] entity))) (mm/->MultiStepFormState entity [] entity)))
@@ -394,6 +520,19 @@
(mm/wrap-init-multi-form-state initial-edit-wizard-state) (mm/wrap-init-multi-form-state initial-edit-wizard-state)
(wrap-schema-enforce :route-schema [:map [:db/id entity-id]])) (wrap-schema-enforce :route-schema [:map [:db/id entity-id]]))
::route/edit-wizard-navigate (-> mm/next-handler ::route/edit-wizard-navigate (-> mm/next-handler
(mm/wrap-wizard edit-wizard)
(mm/wrap-decode-multi-form-state))
::route/new-summary-item (-> (add-new-entity-handler [:step-params :sales-summary/items]
(fn render [cursor request]
(sales-summary-item-row*
{:value cursor
:client-id (:client-id (:query-params request)) }))
(fn build-new-row [base _]
(assoc base :sales-summary-item/manual? true)))
(wrap-schema-enforce :query-schema [:map
[:client-id {:optional true}
[:maybe entity-id]]]))
::route/edit-wizard-submit (-> mm/submit-handler
(mm/wrap-wizard edit-wizard) (mm/wrap-wizard edit-wizard)
(mm/wrap-decode-multi-form-state))}) (mm/wrap-decode-multi-form-state))})
(fn [h] (fn [h]

View File

@@ -138,7 +138,7 @@
(a-button- (merge (a-button- (merge
(dissoc params :index :colspan) (dissoc params :index :colspan)
{ {
"@click" "$dispatch('newRow', {index: (newRowIndex++)})" "@click.prevent" "$dispatch('newRow', {index: (newRowIndex++)})"
:color :secondary :color :secondary
:hx-trigger "newRow" :hx-trigger "newRow"
:hx-vals (hiccup/raw "js:{index: event.detail.index }") :hx-vals (hiccup/raw "js:{index: event.detail.index }")

View File

@@ -165,12 +165,13 @@
:else :else
[:div "No action possible."])]]) [:div "No action possible."])]])
(defn default-render-step [linear-wizard step & {:keys [head body footer validation-route discard-route]}] (defn default-render-step [linear-wizard step & {:keys [head body footer validation-route discard-route width-height-class]}]
(let [is-last? (= (step-key step) (last (steps linear-wizard)))] (let [is-last? (= (step-key step) (last (steps linear-wizard)))]
(com/modal-card-advanced (com/modal-card-advanced
{"@keydown.enter.prevent.stop" "if ($refs.next ) {$refs.next.click()}" {"@keydown.enter.prevent.stop" "if ($refs.next ) {$refs.next.click()}"
:class (str :class (str
"w-full h-full md:w-[750px] md:h-[600px] (or width-height-class " md:w-[750px] md:h-[600px] ")
" w-full h-full
group-[.forward]/transition:htmx-swapping:opacity-0 group-[.forward]/transition:htmx-swapping:opacity-0
group-[.forward]/transition:htmx-swapping:-translate-x-1/4 group-[.forward]/transition:htmx-swapping:-translate-x-1/4
group-[.forward]/transition:htmx-swapping:scale-75 group-[.forward]/transition:htmx-swapping:scale-75

View File

@@ -379,8 +379,7 @@
(:account/name (d-accounts/clientize (dc/pull (dc/db conn) d-accounts/default-read value) (:account/name (d-accounts/clientize (dc/pull (dc/db conn) d-accounts/default-read value)
client-id)))})]) client-id)))})])
(defn- invoice-expense-account-row* (defn- invoice-expense-account-row* [{:keys [value client-id]}]
[{:keys [value client-id]}]
(com/data-grid-row (com/data-grid-row
(-> {:x-data (hx/json {:show (boolean (not (fc/field-value (:new? value)))) (-> {:x-data (hx/json {:show (boolean (not (fc/field-value (:new? value))))
:accountId (fc/field-value (:invoice-expense-account/account value))}) :accountId (fc/field-value (:invoice-expense-account/account value))})

View File

@@ -439,10 +439,14 @@
:explain :explain
(me/humanize {:errors (assoc me/default-errors (me/humanize {:errors (assoc me/default-errors
::mc/missing-key {:error/message {:en "required"}})})) ::mc/missing-key {:error/message {:en "required"}})}))
(map (fn [[k v]] (map (fn [x]
(if (and (sequential? x)
(= (count x) 2))
(let [[k v] x]
(str (if (keyword? k) (str (if (keyword? k)
(name k) (name k)
k) ": " (str/join ", " v)))) k) ": " (str/join ", " v))
(str x)))))
(str/join ", ")) (str/join ", "))
{:type :schema-validation {:type :schema-validation
:decoded (:value (:data (ex-data e))) :decoded (:value (:data (ex-data e)))
@@ -539,7 +543,8 @@
{:path (:in e) {:path (:in e)
:message (get-in humanized (:in e))}) :message (get-in humanized (:in e))})
(:errors (:explain (:error e))))] (:errors (:explain (:error e))))]
(alog/warn ::form-4xx :errors errors) (alog/warn ::form-4xx :errors errors
:data e)
(form-handler (assoc request (form-handler (assoc request
:form-params (:decoded e) :form-params (:decoded e)
:field-validation-errors errors :field-validation-errors errors

View File

@@ -1,6 +1,9 @@
(ns auto-ap.routes.admin.sales-summaries) (ns auto-ap.routes.admin.sales-summaries)
(def routes {"" {:get ::page} (def routes {"" {:get ::page
:put ::edit-wizard-submit}
"/table" ::table "/table" ::table
["/" [#"\d+" :db/id]] {:put ::edit-wizard} ["/" [#"\d+" :db/id]] {:get ::edit-wizard }
"/edit/navigate" ::edit-wizard-navigate })
"/edit/navigate" ::edit-wizard-navigate
"/edit/sales-summary-item" ::new-summary-item})