Tweaks for editing invoices

This commit is contained in:
2024-04-02 20:52:40 -07:00
parent b7c6493bd6
commit 179e3b219b
4 changed files with 115 additions and 72 deletions

View File

@@ -53,8 +53,9 @@
:x-modelable "value.value" :x-modelable "value.value"
:x-model (:x-model params) :x-model (:x-model params)
:x-init "popper = Popper.createPopper($refs.input, $refs.dropdown, {placement: 'bottom-start', strategy: 'fixed', modifiers: {name: 'offset', options: {offset: [0, 10]}}}) :x-init "popper = Popper.createPopper($refs.input, $refs.dropdown, {placement: 'bottom-start', strategy: 'fixed', modifiers: {name: 'offset', options: {offset: [0, 10]}}})
warning_badge = Popper.createPopper($refs.warning_badge, $refs.warning_pop, {placement: 'top', strategy: 'fixed', modifiers: {name: 'offset', options: {offset: [10,0 ]}}})" warning_badge = Popper.createPopper($refs.warning_badge, $refs.warning_pop, {placement: 'top', strategy: 'fixed', modifiers: {name: 'offset', options: {offset: [10,0 ]}}})"}
} (if (:disabled params)
[:span {:x-text "value.label"}]
[:a {:class (-> (hh/add-class (or (:class params) "") default-input-classes) [:a {:class (-> (hh/add-class (or (:class params) "") default-input-classes)
(hh/add-class "cursor-pointer")) (hh/add-class "cursor-pointer"))
"@click.prevent" "open = !open; popper.update()" "@click.prevent" "open = !open; popper.update()"
@@ -62,8 +63,7 @@
"@keydown.backspace" "value = {value: '', label: '' }" "@keydown.backspace" "value = {value: '', label: '' }"
:tabindex 0 :tabindex 0
:x-init (:x-init params) :x-init (:x-init params)
:x-ref "input" :x-ref "input"}
}
[:input (-> params [:input (-> params
(dissoc :class) (dissoc :class)
(dissoc :value-fn) (dissoc :value-fn)
@@ -71,6 +71,7 @@
(dissoc :placeholder) (dissoc :placeholder)
(dissoc :x-model) (dissoc :x-model)
(assoc (assoc
"x-ref" "hidden" "x-ref" "hidden"
:type "hidden" :type "hidden"
@@ -89,8 +90,7 @@
[:div {:x-show "value.warning" [:div {:x-show "value.warning"
:x-ref "warning_pop" :x-ref "warning_pop"
:class "hidden peer-hover:block bg-red-50 dark:bg-gray-600 rounded-lg shadow-2xl w-max z-50 p-4" :class "hidden peer-hover:block bg-red-50 dark:bg-gray-600 rounded-lg shadow-2xl w-max z-50 p-4"
:x-text "value.warning"} :x-text "value.warning"}]]]])
]]]]
[:ul.dropdown-contents {:class "bg-gray-100 dark:bg-gray-600 rounded-lg shadow-2xl w-max z-50 ring-1" [:ul.dropdown-contents {:class "bg-gray-100 dark:bg-gray-600 rounded-lg shadow-2xl w-max z-50 ring-1"
"x-ref" "dropdown" "x-ref" "dropdown"
@@ -127,8 +127,7 @@
"x-html" "element.label"}]]] "x-html" "element.label"}]]]
[:template {:x-if "elements.length == 0"} [:template {:x-if "elements.length == 0"}
[:li {:class "px-4 py-2 flex gap-2 items-center outline-0 focus:bg-neutral-100 hover:bg-neutral-100 whitespace-nowrap [&.active]:bg-primary-500 text-gray-800 dark:text-gray-100 text-xs "} [:li {:class "px-4 py-2 flex gap-2 items-center outline-0 focus:bg-neutral-100 hover:bg-neutral-100 whitespace-nowrap [&.active]:bg-primary-500 text-gray-800 dark:text-gray-100 text-xs "}
"No results found"]]] "No results found"]]]]])
]])
(defn use-size [size] (defn use-size [size]

View File

@@ -2,10 +2,10 @@
(:require [auto-ap.datomic (:require [auto-ap.datomic
:refer [audit-transact conn pull-attr]] :refer [audit-transact conn pull-attr]]
[auto-ap.datomic.accounts :as d-accounts] [auto-ap.datomic.accounts :as d-accounts]
[auto-ap.ssr.invoice.common :refer [default-read]]
[auto-ap.datomic.invoices :as d-invoices] [auto-ap.datomic.invoices :as d-invoices]
[auto-ap.graphql.utils :refer [assert-can-see-client [auto-ap.graphql.utils :refer [assert-can-see-client
assert-not-locked exception->4xx]] assert-not-locked exception->4xx]]
[auto-ap.logging :as alog]
[auto-ap.routes.invoice :as route] [auto-ap.routes.invoice :as route]
[auto-ap.routes.utils [auto-ap.routes.utils
:refer [wrap-client-redirect-unauthenticated]] :refer [wrap-client-redirect-unauthenticated]]
@@ -22,7 +22,6 @@
[auto-ap.ssr.utils [auto-ap.ssr.utils
:refer [->db-id apply-middleware-to-all-handlers clj-date-schema :refer [->db-id apply-middleware-to-all-handlers clj-date-schema
entity-id form-validation-error html-response money strip entity-id form-validation-error html-response money strip
->OOBElements
wrap-schema-enforce]] wrap-schema-enforce]]
[auto-ap.time :as atime] [auto-ap.time :as atime]
[bidi.bidi :as bidi] [bidi.bidi :as bidi]
@@ -70,10 +69,15 @@
(defn check-vendor-default-account [vendor-id] (defn check-vendor-default-account [vendor-id]
(some? (:vendor/default-account (get-vendor vendor-id)))) (some? (:vendor/default-account (get-vendor vendor-id))))
;; TODO negative expense accounts for negative invoices?
;; TODO make changing expense accounts work for editing invoices
;; TODO make a change of total automatically change the expense accounts when editing
;; TODO just close when editing, don't go to print screen
(def new-form-schema (def new-form-schema
[:map [:map
[:db/id {:optional true} [:maybe entity-id]]
[:customize-due-and-scheduled? {:optional true :default false :decode/arbitrary (fn [x] (if (= "" x) [:customize-due-and-scheduled? {:optional true :default false :decode/arbitrary (fn [x] (if (= "" x)
false false
x))} [:maybe :boolean]] x))} [:maybe :boolean]]
@@ -81,10 +85,11 @@
[:invoice/date clj-date-schema] [:invoice/date clj-date-schema]
[:invoice/due {:optional true} [:maybe clj-date-schema]] [:invoice/due {:optional true} [:maybe clj-date-schema]]
[:invoice/scheduled-payment {:optional true} [:maybe clj-date-schema]] [:invoice/scheduled-payment {:optional true} [:maybe clj-date-schema]]
[:invoice/vendor [:and entity-id [:invoice/vendor {:optional true}
[:and entity-id
[:fn {:error/message "Vendor is missing default expense account"} [:fn {:error/message "Vendor is missing default expense account"}
check-vendor-default-account]]] check-vendor-default-account]]]
[:invoice/invoice-number [:string {:min 1 :decode/string strip}]] [:invoice/invoice-number {:optional true} [:string {:min 1 :decode/string strip}]]
[:invoice/total money] [:invoice/total money]
[:invoice/expense-accounts [:invoice/expense-accounts
[:vector {:coerce? true} [:vector {:coerce? true}
@@ -98,6 +103,15 @@
[:fn {:error/fn (fn [r x] (:type r)) [:fn {:error/fn (fn [r x] (:type r))
:error/path [:invoice-expense-account/location]} check-invoice-expense-account-location]]]]]) :error/path [:invoice-expense-account/location]} check-invoice-expense-account-location]]]]])
(defn wrap-schema [s]
[:and s
[:fn (fn [{:keys [:db/id :invoice/invoice-number :invoice/vendor] :as z}]
(println "HERE" id invoice-number vendor z)
(if id
true
(and invoice-number vendor)))]])
(defn clientize-vendor [{:vendor/keys [terms-overrides automatically-paid-when-due default-account account-overrides] :as vendor} client-id] (defn clientize-vendor [{:vendor/keys [terms-overrides automatically-paid-when-due default-account account-overrides] :as vendor} client-id]
(let [terms-override (->> terms-overrides (let [terms-override (->> terms-overrides
(filter (fn [to] (filter (fn [to]
@@ -139,7 +153,7 @@
[]) [])
(step-schema [_] (step-schema [_]
(mut/select-keys (mm/form-schema linear-wizard) #{:invoice/client :invoice/vendor :invoice/date :invoice/due :invoice/scheduled-payment :invoice/total :invoice/invoice-number :customize-due-and-scheduled?})) (wrap-schema (mut/select-keys (mm/form-schema linear-wizard) #{:invoice/client :invoice/vendor :invoice/date :invoice/due :invoice/scheduled-payment :invoice/total :invoice/invoice-number :db/id :customize-due-and-scheduled?})))
(render-step [this request] (render-step [this request]
(mm/default-render-step (mm/default-render-step
@@ -157,6 +171,12 @@
:scheduledPayment (some-> (fc/field-value (:invoice/scheduled-payment fc/*current*)) :scheduledPayment (some-> (fc/field-value (:invoice/scheduled-payment fc/*current*))
(atime/unparse-local atime/normal-date)) (atime/unparse-local atime/normal-date))
:customizeDueAndScheduled (fc/field-value (:customize-due-and-scheduled? fc/*current*))})} :customizeDueAndScheduled (fc/field-value (:customize-due-and-scheduled? fc/*current*))})}
(fc/with-field :db/id
(when (fc/field-value)
(com/hidden {:name (fc/field-name)
:value (fc/field-value)})))
(fc/with-field :customize-due-and-scheduled? (fc/with-field :customize-due-and-scheduled?
(com/hidden {:name (fc/field-name) (com/hidden {:name (fc/field-name)
:value (fc/field-value) :value (fc/field-value)
@@ -184,6 +204,7 @@
[:div.w-96 [:div.w-96
(com/typeahead {:name (fc/field-name) (com/typeahead {:name (fc/field-name)
:error? (fc/error?) :error? (fc/error?)
:disabled (boolean (-> request :multi-form-state :snapshot :db/id))
:class "w-96" :class "w-96"
:placeholder "Search..." :placeholder "Search..."
:url (bidi/path-for ssr-routes/only-routes :vendor-search) :url (bidi/path-for ssr-routes/only-routes :vendor-search)
@@ -254,6 +275,7 @@
:errors (fc/field-errors)} :errors (fc/field-errors)}
[:div {:class "w-24"} [:div {:class "w-24"}
(com/text-input {:value (-> (fc/field-value)) (com/text-input {:value (-> (fc/field-value))
:disabled (boolean (-> request :multi-form-state :snapshot :db/id))
:name (fc/field-name) :name (fc/field-name)
:error? (fc/field-errors) :error? (fc/field-errors)
:placeholder "HA-123"})])) :placeholder "HA-123"})]))
@@ -561,15 +583,16 @@
:accounts (->AccountsStep this) :accounts (->AccountsStep this)
:next-steps (->NextSteps this)} :next-steps (->NextSteps this)}
step-key))) step-key)))
(form-schema [_] new-form-schema) (form-schema [_]
new-form-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 [invoice (:snapshot multi-form-state)
client-id (->db-id (:invoice/client invoice)) client-id (->db-id (:invoice/client invoice))
vendor-id (->db-id (:invoice/vendor invoice)) vendor-id (->db-id (:invoice/vendor invoice))
transaction [:upsert-invoice (-> multi-form-state transaction [:upsert-invoice (-> multi-form-state
:snapshot :snapshot
(assoc :db/id "invoice") (assoc :db/id (or (:db/id invoice) "invoice"))
(dissoc :customize-due-and-scheduled?) (dissoc :customize-due-and-scheduled? :invoice/journal-entry :invoice/payments)
(assoc :invoice/expense-accounts (if-let [ieas (seq (-> multi-form-state :snapshot :invoice/expense-accounts))] (assoc :invoice/expense-accounts (if-let [ieas (seq (-> multi-form-state :snapshot :invoice/expense-accounts))]
ieas ieas
[{:db/id "123" [{:db/id "123"
@@ -585,15 +608,15 @@
(update :invoice/date coerce/to-date) (update :invoice/date coerce/to-date)
(update :invoice/due coerce/to-date))]] (update :invoice/due coerce/to-date))]]
(assert-invoice-amounts-add-up (second transaction)) (assert-invoice-amounts-add-up (second transaction))
(assert-no-conflicting invoice) (when-not (:db/id invoice)
(assert-no-conflicting invoice))
(exception->4xx #(assert-can-see-client (:identity request) client-id)) (exception->4xx #(assert-can-see-client (:identity request) client-id))
(exception->4xx #(assert-not-locked client-id (:invoice/date invoice))) (exception->4xx #(assert-not-locked client-id (:invoice/date invoice)))
(let [transaction-result (audit-transact [transaction] (:identity request))] (let [transaction-result (audit-transact [transaction] (:identity request))]
(solr/touch-with-ledger (get-in transaction-result [:tempids "invoice"])) (solr/touch-with-ledger (get-in transaction-result [:tempids "invoice"]))
(assoc-in (mm/render-navigate {:request (assoc-in request [:multi-form-state :snapshot :db/id] (get-in transaction-result [:tempids "invoice"])) (assoc-in (mm/render-navigate {:request (assoc-in request [:multi-form-state :snapshot :db/id] (get-in transaction-result [:tempids "invoice"]))
:to-step :next-steps :to-step :next-steps})
})
[:headers "hx-trigger"] "invalidated"))))) [:headers "hx-trigger"] "invalidated")))))
(def new-wizard (->NewWizard2 nil nil)) (def new-wizard (->NewWizard2 nil nil))
@@ -604,6 +627,17 @@
[] []
{:invoice/date (time/now)})) {:invoice/date (time/now)}))
(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 new-form-schema))]
(mm/->MultiStepFormState entity
[]
entity)))
(defn location-select [{{:keys [name account-id client-id value] :as qp} :query-params}] (defn location-select [{{:keys [name account-id client-id value] :as qp} :query-params}]
(html-response (location-select* {:name name (html-response (location-select* {:name name
:value value :value value
@@ -676,6 +710,10 @@
{::route/new-wizard (-> mm/open-wizard-handler {::route/new-wizard (-> mm/open-wizard-handler
(mm/wrap-wizard new-wizard) (mm/wrap-wizard new-wizard)
(mm/wrap-init-multi-form-state initial-new-wizard-state)) (mm/wrap-init-multi-form-state initial-new-wizard-state))
::route/edit-wizard (-> mm/open-wizard-handler
(mm/wrap-wizard new-wizard)
(mm/wrap-init-multi-form-state initial-edit-wizard-state)
(wrap-schema-enforce :route-schema [:map [:db/id entity-id]]))
::route/due-date (-> due-date ::route/due-date (-> due-date
(mm/wrap-wizard new-wizard) (mm/wrap-wizard new-wizard)
(mm/wrap-decode-multi-form-state) (mm/wrap-decode-multi-form-state)

View File

@@ -407,7 +407,11 @@
::route/delete ::route/delete
:db/id (:db/id entity)) :db/id (:db/id entity))
:hx-confirm "Are you sure you want to void this invoice?"} :hx-confirm "Are you sure you want to void this invoice?"}
svg/trash))]) svg/trash))
(com/icon-button {:hx-put (bidi/path-for ssr-routes/only-routes
::route/edit-wizard
:db/id (:db/id entity)) }
svg/pencil)])
:breadcrumbs [[:a {:href (bidi/path-for ssr-routes/only-routes ::route/page)} :breadcrumbs [[:a {:href (bidi/path-for ssr-routes/only-routes ::route/page)}
"Invoices"]] "Invoices"]]
:title (fn [r] :title (fn [r]

View File

@@ -12,13 +12,15 @@
"/account/location-select" ::location-select "/account/location-select" ::location-select
"/account/prediction" ::account-prediction "/account/prediction" ::account-prediction
"/total" ::expense-account-total} "/total" ::expense-account-total}
"/pay-button" ::pay-button "/pay-button" ::pay-button
"/pay" {:get ::pay-wizard "/pay" {:get ::pay-wizard
"/navigate" ::pay-wizard-navigate "/navigate" ::pay-wizard-navigate
:post ::pay-submit} :post ::pay-submit}
"/bulk-delete" {:get ::bulk-delete "/bulk-delete" {:get ::bulk-delete
:delete ::bulk-delete-confirm} :delete ::bulk-delete-confirm}
["/" [#"\d+" :db/id]] {:delete ::delete} ["/" [#"\d+" :db/id]] {:delete ::delete
"/edit" ::edit-wizard}
"/table" ::table "/table" ::table
"/glimpse" {"" {:get :invoice-glimpse "/glimpse" {"" {:get :invoice-glimpse