Compare commits
3 Commits
ec4f88b7fc
...
f9438ba983
| Author | SHA1 | Date | |
|---|---|---|---|
| f9438ba983 | |||
| 7d34b8a5f6 | |||
| c09d85ede6 |
@@ -28,7 +28,7 @@
|
||||
(com/data-grid-header {} "Synced count")
|
||||
(com/data-grid-header {} "Approved transactions")
|
||||
(com/data-grid-header {} "Unapproved transactions")
|
||||
(com/data-grid-header {} "Requires feedback transactions")
|
||||
(com/data-grid-header {} "Client Review transactions")
|
||||
(com/data-grid-header {} "Missing transactions")])
|
||||
#_#_:thead-params {:class "sticky top-0 z-50"}}
|
||||
(for [row report]
|
||||
@@ -84,18 +84,18 @@
|
||||
(com/validated-field {:label "Start"
|
||||
:errors (fc/field-errors)}
|
||||
[:div {:class "w-64"}
|
||||
(com/date-input {:name (fc/field-name)
|
||||
(com/date-input {:name (fc/field-name)
|
||||
:class "w-64"
|
||||
:value (some-> (fc/field-value)
|
||||
(atime/unparse-local atime/normal-date))})]))
|
||||
:value (some-> (fc/field-value)
|
||||
(atime/unparse-local atime/normal-date))})]))
|
||||
(fc/with-field :end-date
|
||||
(com/validated-field {:label "End"
|
||||
:errors (fc/field-errors)}
|
||||
[:div {:class "w-64"}
|
||||
(com/date-input {:name (fc/field-name)
|
||||
(com/date-input {:name (fc/field-name)
|
||||
:class "w-64"
|
||||
:value (some-> (fc/field-value)
|
||||
(atime/unparse-local atime/normal-date))})]))
|
||||
:value (some-> (fc/field-value)
|
||||
(atime/unparse-local atime/normal-date))})]))
|
||||
(com/button {:color :primary :class "self-center w-24"} "Run")])]
|
||||
(if report
|
||||
(report* {:request request :report report})
|
||||
@@ -104,15 +104,15 @@
|
||||
(defn page [request]
|
||||
(base-page
|
||||
request
|
||||
(com/page {:nav com/company-aside-nav
|
||||
(com/page {:nav com/company-aside-nav
|
||||
:client-selection (:client-selection request)
|
||||
:client (:client request)
|
||||
:clients (:clients request)
|
||||
:identity (:identity request)
|
||||
:app-params {:hx-get (bidi/path-for ssr-routes/only-routes :company-reconciliation-report)
|
||||
:identity (:identity request)
|
||||
:app-params {:hx-get (bidi/path-for ssr-routes/only-routes :company-reconciliation-report)
|
||||
:hx-trigger "clientSelected from:body"
|
||||
:hx-select "#app-contents"
|
||||
:hx-swap "outerHTML swap:300ms"}}
|
||||
:hx-swap "outerHTML swap:300ms"}}
|
||||
(com/breadcrumbs {}
|
||||
[:a {:href (bidi/path-for ssr-routes/only-routes :company)}
|
||||
"My Company"]
|
||||
@@ -133,7 +133,7 @@
|
||||
|
||||
(defn get-report-data [start-date end-date client-ids]
|
||||
(let [client-codes (map first (dc/q '[:find ?cc :in $ [?c ...] :where [?c :client/code ?cc]] (dc/db conn) client-ids))]
|
||||
(for [[ib ba c] (seq (apply get-intuit-bank-accounts (dc/db conn) client-codes))
|
||||
(for [[ib ba c] (seq (apply get-intuit-bank-accounts (dc/db conn) client-codes))
|
||||
:let [raw-transactions (get-transactions (atime/unparse-local start-date atime/iso-date)
|
||||
(atime/unparse-local end-date atime/iso-date)
|
||||
ib)
|
||||
|
||||
@@ -138,6 +138,33 @@
|
||||
[:div.space-y-1 {}
|
||||
children])
|
||||
|
||||
(defn flatten-form-errors
|
||||
"Walks a malli-humanized error structure and returns a flat sequence of
|
||||
human-readable strings, prefixing each leaf message with the nearest
|
||||
field name for context. Lets the footer's error bar surface every
|
||||
validation error for the whole form, even ones whose field lives on a
|
||||
hidden step/tab and so would otherwise be invisible."
|
||||
([errors] (flatten-form-errors nil errors))
|
||||
([field errors]
|
||||
(let [label (cond (keyword? field) (name field)
|
||||
(string? field) field
|
||||
:else nil)
|
||||
decorate (fn [msg] (if label (str label ": " msg) msg))]
|
||||
(cond
|
||||
(map? errors)
|
||||
(mapcat (fn [[k v]] (flatten-form-errors k v)) errors)
|
||||
|
||||
(and (sequential? errors) (every? string? errors))
|
||||
(map decorate errors)
|
||||
|
||||
(sequential? errors)
|
||||
(mapcat #(flatten-form-errors field %) errors)
|
||||
|
||||
(string? errors)
|
||||
[(decorate errors)]
|
||||
|
||||
:else nil))))
|
||||
|
||||
(defn default-step-footer [linear-wizard step & {:keys [validation-route
|
||||
discard-button
|
||||
next-button
|
||||
@@ -146,7 +173,8 @@
|
||||
[:div.flex.items-baseline.gap-x-4
|
||||
(let [step-errors (:step-params fc/*form-errors*)]
|
||||
(com/form-errors {:errors (or (:errors step-errors)
|
||||
(when (sequential? step-errors) step-errors))}))
|
||||
(when (sequential? step-errors) step-errors)
|
||||
(seq (distinct (flatten-form-errors step-errors))))}))
|
||||
(when (not= (first (steps linear-wizard))
|
||||
(step-key step))
|
||||
(when validation-route
|
||||
|
||||
@@ -185,28 +185,28 @@
|
||||
:hx-target "#account-entries"
|
||||
:hx-swap "innerHTML"
|
||||
:hx-include "closest form"}
|
||||
(fc/with-field :vendor
|
||||
(com/validated-field {:label "Vendor"
|
||||
:errors (fc/field-errors)}
|
||||
(com/typeahead {:name (fc/field-name)
|
||||
:placeholder "Search for vendor..."
|
||||
:url (bidi/path-for ssr-routes/only-routes :vendor-search)
|
||||
:value (fc/field-value)
|
||||
:content-fn (fn [c] (pull-attr (dc/db conn) :vendor/name c))})))]
|
||||
(fc/with-field :vendor
|
||||
(com/validated-field {:label "Vendor"
|
||||
:errors (fc/field-errors)}
|
||||
(com/typeahead {:name (fc/field-name)
|
||||
:placeholder "Search for vendor..."
|
||||
:url (bidi/path-for ssr-routes/only-routes :vendor-search)
|
||||
:value (fc/field-value)
|
||||
:content-fn (fn [c] (pull-attr (dc/db conn) :vendor/name c))})))]
|
||||
|
||||
;; Status field
|
||||
[:div
|
||||
(fc/with-field :approval-status
|
||||
(com/validated-field {:label "Status"
|
||||
:errors (fc/field-errors)}
|
||||
(com/select {:name (fc/field-name)
|
||||
:value (some-> (fc/field-value)
|
||||
name)
|
||||
:options [["" "No Change"]
|
||||
["approved" "Approved"]
|
||||
["unapproved" "Unapproved"]
|
||||
["suppressed" "Suppressed"]
|
||||
["requires_feedback" "Requires Feedback"]]})))]
|
||||
[:div
|
||||
(fc/with-field :approval-status
|
||||
(com/validated-field {:label "Status"
|
||||
:errors (fc/field-errors)}
|
||||
(com/select {:name (fc/field-name)
|
||||
:value (some-> (fc/field-value)
|
||||
name)
|
||||
:options [["" "No Change"]
|
||||
["approved" "Approved"]
|
||||
["unapproved" "Unapproved"]
|
||||
["suppressed" "Suppressed"]
|
||||
["requires-feedback" "Client Review"]]})))]
|
||||
|
||||
;; Accounts section
|
||||
[:div.col-span-2.pt-4
|
||||
@@ -219,10 +219,10 @@
|
||||
(com/data-grid {:headers [(com/data-grid-header {} "Account")
|
||||
(com/data-grid-header {:class "w-32"} "Location")
|
||||
(com/data-grid-header {:class "w-16"} "%")
|
||||
(com/data-grid-header {:class "w-16"})]}
|
||||
(fc/cursor-map #(transaction-account-row* {:value %}))
|
||||
(com/data-grid-header {:class "w-16"})]}
|
||||
(fc/cursor-map #(transaction-account-row* {:value %}))
|
||||
|
||||
(com/data-grid-new-row {:colspan 4
|
||||
(com/data-grid-new-row {:colspan 4
|
||||
:hx-get (bidi/path-for ssr-routes/only-routes
|
||||
::route/bulk-code-new-account)
|
||||
:row-offset 0
|
||||
@@ -357,10 +357,10 @@
|
||||
{:errors (fc/field-errors)}
|
||||
(com/data-grid {:headers [(com/data-grid-header {} "Account")
|
||||
(com/data-grid-header {:class "w-32"} "Location")
|
||||
(com/data-grid-header {:class "w-16"} "%")
|
||||
(com/data-grid-header {:class "w-16"})]}
|
||||
(fc/cursor-map #(transaction-account-row* {:value %}))
|
||||
(com/data-grid-new-row {:colspan 4
|
||||
(com/data-grid-header {:class "w-16"} "%")
|
||||
(com/data-grid-header {:class "w-16"})]}
|
||||
(fc/cursor-map #(transaction-account-row* {:value %}))
|
||||
(com/data-grid-new-row {:colspan 4
|
||||
:hx-get (bidi/path-for ssr-routes/only-routes
|
||||
::route/bulk-code-new-account)
|
||||
:row-offset 0
|
||||
|
||||
@@ -72,6 +72,27 @@
|
||||
(or (not= approval-status :transaction-approval-status/approved)
|
||||
(seq accounts)))]])
|
||||
|
||||
(def account-coding-schema
|
||||
"Validation for manually-coded transaction account rows. Applied only for
|
||||
the :manual action: link / apply-rule actions build their own accounts
|
||||
server-side, so the (often blank) account row carried along by the manual
|
||||
tab must not be required when one of those actions is submitted."
|
||||
[:maybe
|
||||
[:vector {:coerce? true}
|
||||
[:and
|
||||
[:map
|
||||
[:db/id {:optional true} [:maybe [:or temp-id entity-id]]]
|
||||
[:transaction-account/account [:and entity-id
|
||||
[:fn {:error/message "Not an allowed account."}
|
||||
#(check-allowance % :account/default-allowance)]]]
|
||||
[:transaction-account/location :string]
|
||||
[:transaction-account/amount :double]]
|
||||
[:fn {:error/fn (fn [r x] (:type r))
|
||||
:error/path [:transaction-account/location]}
|
||||
(fn [iea]
|
||||
(check-location-belongs (:transaction-account/location iea)
|
||||
(:transaction-account/account iea)))]]]])
|
||||
|
||||
(def edit-form-schema
|
||||
(mc/schema
|
||||
[:and
|
||||
@@ -81,23 +102,7 @@
|
||||
[:transaction/memo {:optional true} [:maybe [:string {:decode/string strip}]]]
|
||||
[:transaction/vendor {:optional true} [:maybe entity-id]]
|
||||
[:transaction/approval-status {:optional true} [:maybe (ref->enum-schema "transaction-approval-status")]]
|
||||
[:amount-mode {:optional true} [:maybe [:enum "$" "%"]]]
|
||||
[:transaction/accounts {:optional true}
|
||||
[:maybe
|
||||
[:vector {:coerce? true}
|
||||
[:and
|
||||
[:map
|
||||
[:db/id {:optional true} [:maybe [:or temp-id entity-id]]]
|
||||
[:transaction-account/account [:and entity-id
|
||||
[:fn {:error/message "Not an allowed account."}
|
||||
#(check-allowance % :account/default-allowance)]]]
|
||||
[:transaction-account/location :string]
|
||||
[:transaction-account/amount :double]]
|
||||
[:fn {:error/fn (fn [r x] (:type r))
|
||||
:error/path [:transaction-account/location]}
|
||||
(fn [iea]
|
||||
(check-location-belongs (:transaction-account/location iea)
|
||||
(:transaction-account/account iea)))]]]]]]
|
||||
[:amount-mode {:optional true} [:maybe [:enum "$" "%"]]]]
|
||||
[:multi {:dispatch :action}
|
||||
[:apply-rule [:map
|
||||
[:rule-id {:optional true} [:maybe entity-id]]]]
|
||||
@@ -110,7 +115,8 @@
|
||||
[:autopay-invoice-ids {:decode/string (fn [x] (edn/read-string x))} [:vector {:coerce? true} entity-id]]]]
|
||||
[:link-payment [:map
|
||||
[:payment-id entity-id]]]
|
||||
[:manual (require-approval [:map])]]]))
|
||||
[:manual (require-approval [:map
|
||||
[:transaction/accounts {:optional true} account-coding-schema]])]]]))
|
||||
|
||||
(defn clientize-vendor [{:vendor/keys [terms-overrides automatically-paid-when-due default-account account-overrides] :as vendor} client-id]
|
||||
(if (nil? vendor)
|
||||
|
||||
@@ -211,7 +211,7 @@
|
||||
(com/data-grid-cell {} (fc/with-field :description-original
|
||||
(com/text-input {:value (fc/field-value) :name (fc/field-name)})))
|
||||
(com/data-grid-cell {} (fc/with-field :amount
|
||||
(com/money-input {:value (fc/field-value) :name (fc/field-name) :class "w-28"})))
|
||||
(com/text-input {:value (fc/field-value) :name (fc/field-name) :class "w-28 text-right" :inputmode "decimal"})))
|
||||
(com/data-grid-cell {} (fc/with-field :bank-account-code
|
||||
(com/text-input {:value (fc/field-value) :name (fc/field-name) :class "w-28"})))
|
||||
(com/data-grid-cell {} (fc/with-field :client-code
|
||||
|
||||
Reference in New Issue
Block a user