Sales nearly ready
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
[clj-time.coerce :as c]
|
||||
[clj-time.core :as time]
|
||||
[clj-time.periodic :as per]
|
||||
[clojure.string :as str]
|
||||
[com.brunobonacci.mulog :as mu]
|
||||
[datomic.api :as dc]))
|
||||
|
||||
@@ -31,6 +32,13 @@
|
||||
(dc/db conn))]
|
||||
(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 []
|
||||
@(dc/transact-async conn
|
||||
@@ -63,6 +71,30 @@
|
||||
c
|
||||
date))
|
||||
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]
|
||||
(->>
|
||||
(dc/q '[:find ?processor ?type-name (sum ?total)
|
||||
@@ -104,7 +136,9 @@
|
||||
{})
|
||||
(map (fn [[k v]]
|
||||
{:db/id (str (java.util.UUID/randomUUID))
|
||||
:sales-summary-item/sort-order 0
|
||||
:sales-summary-item/category k
|
||||
|
||||
:ledger-mapped/amount (if (= "Card Payments" k)
|
||||
(- v (get-fee c date))
|
||||
v)
|
||||
@@ -119,9 +153,10 @@
|
||||
(dc/db conn)
|
||||
[[c] date date]))]
|
||||
{:db/id (str (java.util.UUID/randomUUID))
|
||||
:sales-summary-item/sort-order 1
|
||||
:sales-summary-item/category "Discounts"
|
||||
:ledger-mapped/amount discount
|
||||
:ledger-mapped/ledger-side :ledger-side/debit }))
|
||||
:ledger-mapped/ledger-side :ledger-side/debit}))
|
||||
|
||||
(defn get-refund-items [c date]
|
||||
(->>
|
||||
@@ -149,6 +184,7 @@
|
||||
{})
|
||||
(map (fn [[k v]]
|
||||
{:db/id (str (java.util.UUID/randomUUID))
|
||||
:sales-summary-item/sort-order 3
|
||||
:sales-summary-item/category k
|
||||
:ledger-mapped/amount v
|
||||
:ledger-mapped/ledger-side :ledger-side/credit}))))
|
||||
@@ -158,12 +194,15 @@
|
||||
(defn get-fees [c date]
|
||||
(when-let [fee (get-fee c date)]
|
||||
{:db/id (str (java.util.UUID/randomUUID))
|
||||
:sales-summary-item/sort-order 2
|
||||
:sales-summary-item/category "Fees"
|
||||
:ledger-mapped/amount fee
|
||||
:ledger-mapped/ledger-side :ledger-side/debit}))
|
||||
|
||||
(defn- get-tax [c date]
|
||||
{: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/amount
|
||||
(or (ffirst (dc/q '[:find (sum ?tax)
|
||||
@@ -178,16 +217,20 @@
|
||||
0.0)})
|
||||
|
||||
(defn- get-tip [c date]
|
||||
{:ledger-mapped/ledger-side :ledger-side/credit
|
||||
:ledger-mapped/amount (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)})
|
||||
{: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)
|
||||
: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)})
|
||||
|
||||
(defn- get-sales [c date]
|
||||
(let [sales (->> (dc/q '[:find ?category (sum ?total) (sum ?tax) (sum ?discount)
|
||||
@@ -204,6 +247,7 @@
|
||||
(for [[category total tax discount] sales]
|
||||
{:db/id (str (java.util.UUID/randomUUID))
|
||||
:sales-summary-item/category category
|
||||
:sales-summary-item/sort-order 0
|
||||
:sales-summary-item/total total
|
||||
:sales-summary-item/net (- (+ total discount) tax)
|
||||
:sales-summary-item/tax tax
|
||||
@@ -212,6 +256,23 @@
|
||||
:ledger-mapped/amount (- (+ total discount) tax)
|
||||
#_#_: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 []
|
||||
(doseq [[c client-code] (dc/q '[:find ?c ?client-code
|
||||
:in $
|
||||
@@ -227,51 +288,25 @@
|
||||
:sales-summary/dirty false
|
||||
:sales-summary/client+date [c date]
|
||||
|
||||
:sales-summary/sales-items
|
||||
(conj (get-sales c date)
|
||||
{:db/id (str (java.util.UUID/randomUUID))
|
||||
:sales-summary-item/category "Returns"
|
||||
|
||||
: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))
|
||||
(cons (get-discounts c date))
|
||||
(cons (get-fees c date))
|
||||
(filter identity))
|
||||
|
||||
:sales-summary/total-tax
|
||||
(get-tax c date)
|
||||
:sales-summary/total-tip
|
||||
(get-tip c date)
|
||||
|
||||
#_#_: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}]
|
||||
(if (seq (:sales-summary/sales-items result))
|
||||
:sales-summary/items
|
||||
(->>
|
||||
(get-sales c date)
|
||||
(concat (get-payment-items c date))
|
||||
(concat (get-refund-items c date))
|
||||
(cons (get-discounts c date))
|
||||
(cons (get-fees c date))
|
||||
(cons (get-tax c date))
|
||||
(cons (get-tip c date))
|
||||
(cons (get-returns c date))
|
||||
(filter identity)
|
||||
(map (fn [z]
|
||||
(assoc z :ledger-mapped/account (some-> z :sales-summary-item/category str/lower-case name->number lookup-account)
|
||||
:sales-summary-item/manual? false))
|
||||
)) }]
|
||||
(if (seq (:sales-summary/items result))
|
||||
(do
|
||||
(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 [{: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 []
|
||||
@(dc/transact conn (->> (dc/q '[:find ?sos
|
||||
|
||||
@@ -2,23 +2,28 @@
|
||||
(:require [auto-ap.datomic
|
||||
:refer [apply-pagination apply-sort-3 conn merge-query pull-many
|
||||
query2]]
|
||||
[auto-ap.datomic.accounts :as d-accounts]
|
||||
[auto-ap.graphql.utils :refer [extract-client-ids]]
|
||||
[auto-ap.routes.admin.sales-summaries :as route]
|
||||
[auto-ap.routes.utils
|
||||
:refer [wrap-admin wrap-client-redirect-unauthenticated]]
|
||||
[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.multi-modal :as mm]
|
||||
[auto-ap.ssr.form-cursor :as fc]
|
||||
[auto-ap.ssr.grid-page-helper :as helper]
|
||||
[auto-ap.ssr.hx :as hx]
|
||||
[auto-ap.ssr.svg :as svg]
|
||||
[auto-ap.ssr.utils
|
||||
:refer [apply-middleware-to-all-handlers entity-id
|
||||
wrap-schema-enforce]]
|
||||
:refer [apply-middleware-to-all-handlers entity-id html-response
|
||||
money strip temp-id wrap-schema-enforce]]
|
||||
[auto-ap.time :as atime]
|
||||
[bidi.bidi :as bidi]
|
||||
[clj-time.coerce :as c]
|
||||
[clojure.string :as str]
|
||||
[datomic.api :as dc]
|
||||
[hiccup.util :as hu]
|
||||
[iol-ion.query :refer [dollars=]]
|
||||
[malli.core :as mc]
|
||||
[malli.util :as mut]))
|
||||
@@ -50,20 +55,18 @@
|
||||
:size :small}))]])
|
||||
|
||||
(def default-read '[:db/id
|
||||
|
||||
*
|
||||
[:sales-summary/date :xform clj-time.coerce/from-date]
|
||||
{:sales-summary/client [:client/code :client/name]}
|
||||
{:sales-summary/total-tax [{[:ledger-mapped/ledger-side :xform iol-ion.query/ident] [:db/ident]}
|
||||
:ledger-mapped/amount]}
|
||||
{:sales-summary/total-tip [{[:ledger-mapped/ledger-side :xform iol-ion.query/ident] [:db/ident]}
|
||||
:ledger-mapped/amount]}
|
||||
{:sales-summary/sales-items [{[:ledger-mapped/ledger-side :xform iol-ion.query/ident] [:db/ident]}
|
||||
{:sales-summary/client [:client/code :client/name :db/id]}
|
||||
{:sales-summary/items [{[:ledger-mapped/ledger-side :xform iol-ion.query/ident] [:db/ident]
|
||||
} ;; TODO clientize
|
||||
:ledger-mapped/account
|
||||
:ledger-mapped/amount
|
||||
:sales-summary-item/category]}
|
||||
{:sales-summary/payment-items [{[:ledger-mapped/ledger-side :xform iol-ion.query/ident] [:db/ident]}
|
||||
:ledger-mapped/amount
|
||||
:sales-summary-item/category]}]) ;; TODO
|
||||
:sales-summary-item/category
|
||||
:sales-summary-item/sort-order
|
||||
:db/id
|
||||
:sales-summary-item/manual?]
|
||||
} ]) ;; TODO
|
||||
|
||||
(defn fetch-ids [db 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)
|
||||
:discounts (+ (:sales-summary/discount 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))
|
||||
(into (:sales-summary/sales-items ss))))
|
||||
|
||||
|
||||
(defn total-debits [items]
|
||||
(->> 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
|
||||
(helper/build {:id "entity-table"
|
||||
@@ -146,7 +160,7 @@
|
||||
:fetch-page fetch-page
|
||||
:page-specific-nav filters
|
||||
: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
|
||||
:db/id (:db/id entity))}
|
||||
svg/pencil)])
|
||||
@@ -180,56 +194,40 @@
|
||||
:sort-key "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"
|
||||
:name "debits"
|
||||
:sort-key "debits"
|
||||
: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))]
|
||||
(let [total-debits (total-debits (:sales-summary/items ss))
|
||||
total-credits (total-credits (:sales-summary/items ss))]
|
||||
[: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))]
|
||||
[: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)
|
||||
:primary
|
||||
:red)} "Total: " (format "$%,.2f" total-debits))]])
|
||||
|
||||
#_(count))}]}))
|
||||
:red)} "Total: " (format "$%,.2f" total-debits))]]))}
|
||||
{:key "credits"
|
||||
: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
|
||||
;; Decide on what should be calculated as generating ledger entries, and what should be calculated
|
||||
@@ -245,9 +243,154 @@
|
||||
(def edit-schema
|
||||
[:map
|
||||
[:db/id entity-id]
|
||||
[:sales-summary/sales-items
|
||||
[:sales-summary/client [:map [:db/id entity-id]]]
|
||||
[:sales-summary/items
|
||||
[: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]
|
||||
mm/ModalWizardStep
|
||||
@@ -260,7 +403,7 @@
|
||||
[])
|
||||
|
||||
(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
|
||||
[this {:keys [multi-form-state] :as request}]
|
||||
@@ -273,16 +416,39 @@
|
||||
(fc/with-field :db/id
|
||||
(com/hidden {:name (fc/field-name)
|
||||
:value (fc/field-value)}))
|
||||
|
||||
|
||||
(pr-str multi-form-state) ])
|
||||
(com/data-grid {:headers
|
||||
[(com/data-grid-header {} "Category")
|
||||
(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
|
||||
(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"
|
||||
:hx-put (bidi.bidi/path-for ssr-routes/only-routes
|
||||
::route/edit-wizard-navigate)} "Save"))
|
||||
:validation-route ::route/edit-wizard-navigate)))
|
||||
(mm/default-step-footer linear-wizard this :validation-route ::route/edit-wizard-navigate)
|
||||
:validation-route ::route/edit-wizard-navigate
|
||||
:width-height-class "lg:w-[850px] lg:h-[900px]")))
|
||||
|
||||
(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]
|
||||
mm/LinearModalWizard
|
||||
@@ -299,8 +465,8 @@
|
||||
this request
|
||||
:form-params
|
||||
(-> mm/default-form-props
|
||||
(assoc :hx-post
|
||||
(str (bidi/path-for ssr-routes/only-routes ::route/edit-submit))))
|
||||
(assoc :hx-put
|
||||
(str (bidi/path-for ssr-routes/only-routes ::route/edit-wizard-submit))))
|
||||
:render-timeline? false))
|
||||
(steps [_]
|
||||
[:main])
|
||||
@@ -311,76 +477,36 @@
|
||||
(form-schema [_]
|
||||
edit-schema)
|
||||
(submit [this {:keys [multi-form-state request-method identity] :as request}]
|
||||
#_(let [invoice (:snapshot multi-form-state)
|
||||
|
||||
_ (alog/peek invoice)
|
||||
extant? (:db/id invoice)
|
||||
client-id (->db-id (:invoice/client invoice))
|
||||
vendor-id (->db-id (:invoice/vendor invoice))
|
||||
paid-amount (if-let [outstanding-balance
|
||||
(and extant?
|
||||
(-
|
||||
(pull-attr (dc/db conn)
|
||||
:invoice/total
|
||||
(:db/id invoice))
|
||||
(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
|
||||
(@(resolve 'auto-ap.ssr.invoices/row*) identity (dc/pull (dc/db conn) default-read (:db/id invoice)) {:flash? true
|
||||
:request request})
|
||||
:headers (cond-> {"hx-trigger" "modalclose"
|
||||
"hx-retarget" (format "#entity-table tr[data-id=\"%d\"]" (:db/id invoice))
|
||||
"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"))))))
|
||||
(let [result (:snapshot multi-form-state )
|
||||
transaction [:upsert-entity {:db/id (:db/id result)
|
||||
:sales-summary/items (map
|
||||
(fn [i]
|
||||
(if (:sales-summary-item/manual? i)
|
||||
(attach-ledger i)
|
||||
{:db/id (:db/id i)
|
||||
:ledger-mapped/account (:ledger-mapped/account i)
|
||||
}))
|
||||
(:sales-summary/items result))}]]
|
||||
(clojure.pprint/pprint (:sales-summary/items result))
|
||||
@(dc/transact conn [ transaction])
|
||||
(html-response
|
||||
(row* identity (dc/pull (dc/db conn) default-read (:db/id result))
|
||||
{:flash? true
|
||||
:request request})
|
||||
:headers (cond-> {"hx-trigger" "modalclose"
|
||||
"hx-retarget" (format "#entity-table tr[data-id=\"%d\"]" (:db/id result))
|
||||
"hx-reswap" "outerHTML"})))))
|
||||
|
||||
(def edit-wizard (->EditWizard nil nil))
|
||||
|
||||
(defn initial-edit-wizard-state [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)))
|
||||
|
||||
@@ -395,7 +521,20 @@
|
||||
(wrap-schema-enforce :route-schema [:map [:db/id entity-id]]))
|
||||
::route/edit-wizard-navigate (-> mm/next-handler
|
||||
(mm/wrap-wizard edit-wizard)
|
||||
(mm/wrap-decode-multi-form-state))})
|
||||
(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-decode-multi-form-state))})
|
||||
(fn [h]
|
||||
(-> h
|
||||
(wrap-admin)
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
(a-button- (merge
|
||||
(dissoc params :index :colspan)
|
||||
{
|
||||
"@click" "$dispatch('newRow', {index: (newRowIndex++)})"
|
||||
"@click.prevent" "$dispatch('newRow', {index: (newRowIndex++)})"
|
||||
:color :secondary
|
||||
:hx-trigger "newRow"
|
||||
:hx-vals (hiccup/raw "js:{index: event.detail.index }")
|
||||
|
||||
@@ -165,12 +165,13 @@
|
||||
:else
|
||||
[: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)))]
|
||||
(com/modal-card-advanced
|
||||
{"@keydown.enter.prevent.stop" "if ($refs.next ) {$refs.next.click()}"
|
||||
: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:-translate-x-1/4
|
||||
group-[.forward]/transition:htmx-swapping:scale-75
|
||||
|
||||
@@ -379,8 +379,7 @@
|
||||
(:account/name (d-accounts/clientize (dc/pull (dc/db conn) d-accounts/default-read value)
|
||||
client-id)))})])
|
||||
|
||||
(defn- invoice-expense-account-row*
|
||||
[{:keys [value client-id]}]
|
||||
(defn- invoice-expense-account-row* [{:keys [value client-id]}]
|
||||
(com/data-grid-row
|
||||
(-> {:x-data (hx/json {:show (boolean (not (fc/field-value (:new? value))))
|
||||
:accountId (fc/field-value (:invoice-expense-account/account value))})
|
||||
|
||||
@@ -439,10 +439,14 @@
|
||||
:explain
|
||||
(me/humanize {:errors (assoc me/default-errors
|
||||
::mc/missing-key {:error/message {:en "required"}})}))
|
||||
(map (fn [[k v]]
|
||||
(str (if (keyword? k)
|
||||
(name k)
|
||||
k) ": " (str/join ", " v))))
|
||||
(map (fn [x]
|
||||
(if (and (sequential? x)
|
||||
(= (count x) 2))
|
||||
(let [[k v] x]
|
||||
(str (if (keyword? k)
|
||||
(name k)
|
||||
k) ": " (str/join ", " v))
|
||||
(str x)))))
|
||||
(str/join ", "))
|
||||
{:type :schema-validation
|
||||
:decoded (:value (:data (ex-data e)))
|
||||
@@ -539,7 +543,8 @@
|
||||
{:path (:in e)
|
||||
:message (get-in humanized (:in e))})
|
||||
(:errors (:explain (:error e))))]
|
||||
(alog/warn ::form-4xx :errors errors)
|
||||
(alog/warn ::form-4xx :errors errors
|
||||
:data e)
|
||||
(form-handler (assoc request
|
||||
:form-params (:decoded e)
|
||||
:field-validation-errors errors
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
(ns auto-ap.routes.admin.sales-summaries)
|
||||
(def routes {"" {:get ::page}
|
||||
(def routes {"" {:get ::page
|
||||
:put ::edit-wizard-submit}
|
||||
"/table" ::table
|
||||
|
||||
["/" [#"\d+" :db/id]] {:put ::edit-wizard}
|
||||
"/edit/navigate" ::edit-wizard-navigate })
|
||||
["/" [#"\d+" :db/id]] {:get ::edit-wizard }
|
||||
|
||||
"/edit/navigate" ::edit-wizard-navigate
|
||||
"/edit/sales-summary-item" ::new-summary-item})
|
||||
Reference in New Issue
Block a user