Better experience for adding new journal entry

This commit is contained in:
2024-11-04 13:23:37 -08:00
parent 48d575fe70
commit 71d7461eb9
4 changed files with 73 additions and 48 deletions

View File

@@ -135,20 +135,21 @@
(defn new-row- [{:keys [index colspan tr-params row-offset] :as params} & content] (defn new-row- [{:keys [index colspan tr-params row-offset] :as params} & content]
(row- (row-
(merge {:class "new-row" (merge {:class "new-row"
"x-on:htmx:after-settle.camel" "let options=$el.parentNode.querySelectorAll('tr'); let target=options[options.length-2]; $nextTick(() => $focus.within(target).first())"
:x-data (hx/json {:newRowIndex index :x-data (hx/json {:newRowIndex index
:offset (or row-offset 0)}) :offset (or row-offset 0)}) }
}
tr-params) tr-params)
(cell- {:colspan colspan (cell- {:colspan colspan
:class "bg-gray-100"} :class "bg-gray-100"}
[:div.flex.justify-center [:div.flex.justify-center
(a-button- (merge (a-button- (merge
(dissoc params :index :colspan) (dissoc params :index :colspan)
{ {"@click.prevent" "$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 }")
:hx-target "closest .new-row" :hx-target "closest .new-row"
:hx-swap "beforebegin"}) :hx-swap "beforebegin"
})
content)]))) content)])))

View File

@@ -22,6 +22,7 @@
[auto-ap.ssr.ledger.cash-flows :as cash-flows] [auto-ap.ssr.ledger.cash-flows :as cash-flows]
[auto-ap.ssr.ledger.common :refer [bank-account-filter default-read [auto-ap.ssr.ledger.common :refer [bank-account-filter default-read
fetch-ids grid-page query-schema]] fetch-ids grid-page query-schema]]
[auto-ap.ssr.ledger.common :as ledger.common]
[auto-ap.ssr.ledger.investigate :as investigate] [auto-ap.ssr.ledger.investigate :as investigate]
[auto-ap.ssr.ledger.new :as new] [auto-ap.ssr.ledger.new :as new]
[auto-ap.ssr.ledger.profit-and-loss :as profit-and-loss] [auto-ap.ssr.ledger.profit-and-loss :as profit-and-loss]
@@ -76,7 +77,7 @@
;; TODO test as a real user ;; TODO test as a real user
(def row* (partial helper/row* grid-page))
(defn delete [{invoice :entity :as request identity :identity}] (defn delete [{invoice :entity :as request identity :identity}]
(exception->notification (exception->notification
@@ -103,7 +104,7 @@
(:invoice/expense-accounts invoice))}]] (:invoice/expense-accounts invoice))}]]
identity) identity)
(html-response (row* (:identity request) (dc/pull (dc/db conn) default-read (:db/id invoice)) (html-response (ledger.common/row* (:identity request) (dc/pull (dc/db conn) default-read (:db/id invoice))
{:class "live-removed"}) {:class "live-removed"})
:headers {"hx-retarget" (format "#entity-table tr[data-id=\"%d\"]" (:db/id invoice))})) :headers {"hx-retarget" (format "#entity-table tr[data-id=\"%d\"]" (:db/id invoice))}))

View File

@@ -528,3 +528,5 @@
{:exact-match-id (:db/id (:journal-entry/original-entity i))}) {:exact-match-id (:db/id (:journal-entry/original-entity i))})
:color :primary :color :primary
:content (format "Transaction '%s'" (-> i :journal-entry/original-entity :transaction/description-original))}))))}]})) :content (format "Transaction '%s'" (-> i :journal-entry/original-entity :transaction/description-original))}))))}]}))
(def row* (partial helper/row* grid-page))

View File

@@ -1,6 +1,6 @@
(ns auto-ap.ssr.ledger.new (ns auto-ap.ssr.ledger.new
(:require (:require
[auto-ap.datomic :refer [conn pull-attr]] [auto-ap.datomic :refer [audit-transact conn pull-attr]]
[auto-ap.datomic.accounts :as d-accounts] [auto-ap.datomic.accounts :as d-accounts]
[auto-ap.datomic.accounts :as a] [auto-ap.datomic.accounts :as a]
[auto-ap.logging :as alog] [auto-ap.logging :as alog]
@@ -12,6 +12,7 @@
[auto-ap.ssr.components :as com] [auto-ap.ssr.components :as com]
[auto-ap.ssr.form-cursor :as fc] [auto-ap.ssr.form-cursor :as fc]
[auto-ap.ssr.hx :as hx] [auto-ap.ssr.hx :as hx]
[auto-ap.ssr.ledger.common :as ledger.common]
[auto-ap.ssr.nested-form-params :refer [wrap-nested-form-params]] [auto-ap.ssr.nested-form-params :refer [wrap-nested-form-params]]
[auto-ap.ssr.svg :as svg] [auto-ap.ssr.svg :as svg]
[auto-ap.ssr.utils :refer [apply-middleware-to-all-handlers check-allowance [auto-ap.ssr.utils :refer [apply-middleware-to-all-handlers check-allowance
@@ -20,10 +21,13 @@
wrap-form-4xx-2 wrap-schema-enforce]] wrap-form-4xx-2 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 coerce]
[clojure.string :as str] [clojure.string :as str]
[datomic.api :as dc] [datomic.api :as dc]
[iol-ion.query :refer [dollars=]]) [iol-ion.query :refer [dollars=]]
(:import [java.util UUID])) [iol-ion.utils :refer [remove-nils]])
(:import
[java.util UUID]))
(def new-ledger-schema (def new-ledger-schema
[:and [:and
@@ -179,13 +183,18 @@
(defn form* [request] (defn form* [request]
(alog/peek :FP (:form-errors request)) (alog/peek :FP (:form-errors request))
(let [client (some-> request :form-params :journal-entry/client) (let [client (some-> request :form-params :journal-entry/client)
client-locations (some-> client :client/locations)] client-locations (some-> client :client/locations)
extant? false] ;;TODO
(fc/start-form (:form-params request) (fc/start-form (:form-params request)
(:form-errors request) (:form-errors request)
[:div.flex.gap-4.flex-col {:x-data (hx/json {:clientId (or (:db/id (fc/field-value (:journal-entry/client fc/*current*))) [:div.flex.gap-4.flex-col {:x-data (hx/json {:clientId (or (:db/id (fc/field-value (:journal-entry/client fc/*current*)))
(:db/id (:client request))) (:db/id (:client request)))
:vendorId (:db/id (fc/field-value (:journal-entry/vendor fc/*current*))) })} :vendorId (:db/id (fc/field-value (:journal-entry/vendor fc/*current*)))})}
(fc/with-field :journal-entry/client (fc/with-field :journal-entry/client
(if (or (:client request) extant?)
(com/hidden {:name (fc/field-name)
:value (:db/id (:client request))})
[:div.w-96
(com/validated-field (com/validated-field
{:label "Client" {:label "Client"
:errors (fc/field-errors)} :errors (fc/field-errors)}
@@ -198,7 +207,7 @@
:value (fc/field-value) :value (fc/field-value)
:value-fn :db/id :value-fn :db/id
:content-fn :client/name :content-fn :client/name
:x-model "clientId"})])) :x-model "clientId"})])]))
(fc/with-field :journal-entry/date (fc/with-field :journal-entry/date
(com/validated-field (com/validated-field
{:label "Date" {:label "Date"
@@ -265,23 +274,35 @@
[:div (com/button {:color :primary} "Save")])]))) [:div (com/button {:color :primary} "Save")])])))
(defn new-submit [request] (defn new-submit [request]
@(dc/transact conn (let [id (:db/id (:form-params request))
[(-> (:form-params request) entity (cond-> (-> (:form-params request)
(update :journal-entry/date coerce/to-date)
(update :journal-entry/client :db/id) (update :journal-entry/client :db/id)
(update :journal-entry/vendor :db/id) (update :journal-entry/vendor :db/id)
(update :journal-entry/line-items (update :journal-entry/line-items
(fn [li] (fn [li]
(mapv (mapv
#(update % :journal-entry-line/account :db/id) #(remove-nils (update % :journal-entry-line/account :db/id))
li))) li)))
(assoc :journal-entry/external-id (str "manual-" (UUID/randomUUID))))]) (assoc :journal-entry/external-id (str "manual-" (UUID/randomUUID))))
(= :post (:request-method request)) (assoc :db/id "new"))
{:keys [tempids]} (audit-transact [[:upsert-entity entity]]
(:identity request))
updated-entity (dc/pull (dc/db conn)
ledger.common/default-read
(or (get tempids (:db/id entity)) (:db/id entity)))]
(html-response (html-response
[:div "GOOD"] (ledger.common/row* identity updated-entity
:headers (cond-> {"hx-trigger" "modalclose" {:flash? true
#_#_"hx-retarget" (format "#entity-table tr[data-id=\"%d\"]" (:db/id invoice)) :request request})
#_#_"hx-reswap" "outerHTML"}))) :headers (cond-> {"hx-trigger" "modalclose"}
(= :put (:request-method request))
(assoc "hx-retarget" (format "#entity-table tr[data-id=\"%d\"]" id)
"hx-reswap" "outerHTML")
(= :post (:request-method request))
(assoc "hx-retarget" "#entity-table tbody"
"hx-reswap" "afterbegin")))))
(def key->handler (def key->handler