diff --git a/src/clj/auto_ap/ssr/pos/sales_summaries.clj b/src/clj/auto_ap/ssr/pos/sales_summaries.clj index 5582d532..a0bcb687 100644 --- a/src/clj/auto_ap/ssr/pos/sales_summaries.clj +++ b/src/clj/auto_ap/ssr/pos/sales_summaries.clj @@ -173,69 +173,59 @@ {:key "debits" :name "Debits" :sort-key "debits" - :class "w-64 align-top" + :class "w-72 align-top" :render (fn [ss] (let [items (:sales-summary/items ss) debit-items (filter #(= :ledger-side/debit (:ledger-mapped/ledger-side %)) (sort-items items)) credit-count (count (filter #(= :ledger-side/credit (:ledger-mapped/ledger-side %)) items)) - total-debits (total-debits items) - total-credits (total-credits items) - delta (- total-debits total-credits)] + total-debits (total-debits items)] [:div.flex.flex-col.h-full - [:div.font-semibold.text-sm "Debits"] - [:ul.space-y-0.5.flex-grow + [:ul.flex-grow (for [si debit-items] - [:li.text-sm.text-gray-700 - [:span.text-gray-500 (truncate (:sales-summary-item/category si) 30)] - [:span.ml-2 "→"] - [:span.ml-2.font-mono (format "$%,.2f" (:ledger-mapped/amount si))] + [:li.flex.items-baseline.gap-2.py-0.5.text-sm.text-gray-700 + [:span.flex-1.min-w-0.truncate.text-gray-600 + (:sales-summary-item/category si)] (when-not (:ledger-mapped/account si) - [:span.ml-2 (com/pill {:color :red} "?")])]) + [:span.shrink-0 (com/pill {:color :red} "?")]) + [:span.shrink-0.font-mono.tabular-nums.text-right.text-gray-900.whitespace-nowrap + (format "$%,.2f" (:ledger-mapped/amount si))]]) (for [_ (range (max 0 (- credit-count (count debit-items))))] - [:li "\u00a0"])] - [:div.border-t.mt-1.pt-1.flex.justify-between.items-center.w-full - [:span.font-semibold "Total"] - [:span.font-mono.font-semibold (format "$%,.2f" total-debits)]] - (when-not (dollars-0? delta) - [:div.text-xs.text-red-600.flex.justify-between.w-full.mt-1 - [:span "Delta:"] - [:span.font-mono (format "$%,.2f" delta)]])]))} + [:li.py-0.5.text-sm " "])] + [:div.border-t-2.border-gray-300.mt-1.pt-1.flex.justify-between.items-baseline + [:span.text-xs.uppercase.tracking-wider.font-semibold.text-gray-500 "Total"] + [:span.font-mono.tabular-nums.font-bold.text-gray-900 + (format "$%,.2f" total-debits)]]]))} {:key "credits" :name "Credits" :sort-key "credits" - :class "w-64 align-top" + :class "w-72 align-top" :render (fn [ss] (let [items (:sales-summary/items ss) credit-items (filter #(= :ledger-side/credit (:ledger-mapped/ledger-side %)) (sort-items items)) debit-count (count (filter #(= :ledger-side/debit (:ledger-mapped/ledger-side %)) items)) - total-debits (total-debits items) - total-credits (total-credits items) - delta (- total-credits total-debits)] + total-credits (total-credits items)] [:div.flex.flex-col.h-full - [:div.font-semibold.text-sm "Credits"] - [:ul.space-y-0.5.flex-grow + [:ul.flex-grow (for [si credit-items] - [:li.text-sm.text-gray-700 - [:span.text-gray-500 (truncate (:sales-summary-item/category si) 30)] - [:span.ml-2 "→"] - [:span.ml-2.font-mono (format "$%,.2f" (:ledger-mapped/amount si))] + [:li.flex.items-baseline.gap-2.py-0.5.text-sm.text-gray-700 + [:span.flex-1.min-w-0.truncate.text-gray-600 + (:sales-summary-item/category si)] (when-not (:ledger-mapped/account si) - [:span.ml-2 (com/pill {:color :red} "?")])]) + [:span.shrink-0 (com/pill {:color :red} "?")]) + [:span.shrink-0.font-mono.tabular-nums.text-right.text-gray-900.whitespace-nowrap + (format "$%,.2f" (:ledger-mapped/amount si))]]) (for [_ (range (max 0 (- debit-count (count credit-items))))] - [:li "\u00a0"])] - [:div.border-t.mt-1.pt-1.flex.justify-between.items-center.w-full - [:span.font-semibold "Total"] - [:span.font-mono.font-semibold (format "$%,.2f" total-credits)]] - (when-not (dollars-0? delta) - [:div.text-xs.text-green-600.flex.justify-between.w-full.mt-1 - [:span "Delta:"] - [:span.font-mono (format "$%,.2f" delta)]])]))} + [:li.py-0.5.text-sm " "])] + [:div.border-t-2.border-gray-300.mt-1.pt-1.flex.justify-between.items-baseline + [:span.text-xs.uppercase.tracking-wider.font-semibold.text-gray-500 "Total"] + [:span.font-mono.tabular-nums.font-bold.text-gray-900 + (format "$%,.2f" total-credits)]]]))} {:key "balance" - :name "Balance" + :name "Status" :sort-key "balance" - :class "w-24" + :class "w-28 align-top" :render (fn [ss] (let [items (:sales-summary/items ss) total-debits (total-debits items) @@ -243,16 +233,19 @@ delta (- total-debits total-credits) balanced? (dollars= total-debits total-credits) missing-account? (some #(not (:ledger-mapped/account %)) items)] - [:div.flex.flex-col.items-center.pt-2 + [:div.flex.flex-col.items-center.gap-1.pt-2 (when missing-account? - [:span.text-red-600.font-bold.text-xs "Missing acct"]) + [:span.inline-block.text-xs.font-semibold.uppercase.tracking-wider.text-amber-800.bg-amber-100.border.border-amber-300.rounded-sm.px-1.5.py-0.5 + "Missing acct"]) (if balanced? (when-not missing-account? - [:span.text-green-600.font-bold "✓ Balanced"]) - (list - [:span.text-red-600.font-mono (format "$%,.2f" (Math/abs delta))] - [:span.text-xs.text-gray-500.mt-1 - (if (> total-debits total-credits) "Debit over" "Credit over")]))]))} + [:span.inline-block.text-xs.font-semibold.uppercase.tracking-wider.text-emerald-800.bg-emerald-100.border.border-emerald-300.rounded-sm.px-1.5.py-0.5 + "Balanced"]) + [:div.flex.flex-col.items-center + [:span.font-mono.tabular-nums.text-red-700.font-bold.text-sm + (format "$%,.2f" (Math/abs delta))] + [:span.text-xs.uppercase.tracking-wider.text-red-600.font-medium.mt-0.5 + (if (> total-debits total-credits) "Debit over" "Credit over")]])]))} {:key "links" :name "Links" @@ -311,16 +304,22 @@ (total-debits))] (com/data-grid-row {:id "total-row" + :class "bg-slate-50 border-t-2 border-slate-300" :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)) + [:span.text-xs.uppercase.tracking-wider.font-semibold.text-slate-600 + "Total"]) (com/data-grid-cell {:class "text-right"} - (format "$%,.2f" total-credits))))) + [:span.font-mono.tabular-nums.font-bold.text-slate-900 + (format "$%,.2f" total-debits)]) + (com/data-grid-cell {:class "text-right"} + [:span.font-mono.tabular-nums.font-bold.text-slate-900 + (format "$%,.2f" total-credits)]) + (com/data-grid-cell {})))) (defn unbalanced-row* [request] (let [total-credits (-> request @@ -332,25 +331,31 @@ :multi-form-state :step-params :sales-summary/items - (total-debits))] + (total-debits)) + unbalanced? (not (dollars= total-credits total-debits)) + debit-over? (and unbalanced? (> total-debits total-credits)) + credit-over? (and unbalanced? (> total-credits total-debits))] - (com/data-grid-row {:id "total-row" + (com/data-grid-row {:id "unbalanced-row" + :class (when unbalanced? "bg-red-50 border-t border-red-200") :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)))) + (when unbalanced? + [:span.text-xs.uppercase.tracking-wider.font-semibold.text-red-700 + "Out of balance"])) (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))))))) + (when debit-over? + [:span.font-mono.tabular-nums.font-bold.text-red-700 + (format "$%,.2f" (- total-debits total-credits))])) + (com/data-grid-cell {:class "text-right"} + (when credit-over? + [:span.font-mono.tabular-nums.font-bold.text-red-700 + (format "$%,.2f" (- total-credits total-debits))])) + (com/data-grid-cell {})))) (defn- account-typeahead* [{:keys [name value client-id]}] @@ -368,7 +373,9 @@ (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 {})} + :x-data (hx/json {}) + :class (when manual? + "bg-indigo-50/40 border-l-2 border-indigo-300")} (fc/field-value (:new? value)) (hx/htmx-transition-appear)) (fc/with-field :db/id (com/hidden {:name (fc/field-name) @@ -377,7 +384,7 @@ (fc/with-field :sales-summary-item/manual? (com/hidden {:name (fc/field-name) :value true}))) - (com/data-grid-cell {} + (com/data-grid-cell {:class "align-top"} (fc/with-field :sales-summary-item/category (if manual? (com/validated-field {:errors (fc/field-errors)} @@ -388,35 +395,38 @@ (list (com/hidden {:name (fc/field-name) :value (fc/field-value)}) - (fc/field-value (:sales-summary-item/category value)))))) - (com/data-grid-cell {} + [:span.text-sm.text-gray-700 + (fc/field-value (:sales-summary-item/category value))])))) + (com/data-grid-cell {:class "align-top"} (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"} + (com/data-grid-cell {:class "text-right align-top"} (if manual? (fc/with-field :debit (com/validated-field {:errors (fc/field-errors)} - (com/money-input {:class "w-24" + (com/money-input {:class "w-24 text-right font-mono tabular-nums" :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"} + [:span.font-mono.tabular-nums.text-gray-900.text-sm.whitespace-nowrap + (format "$%,.2f" (fc/field-value (:ledger-mapped/amount value)))]))) + (com/data-grid-cell {:class "text-right align-top"} (if manual? (fc/with-field :credit (com/validated-field {:errors (fc/field-errors)} - (com/money-input {:class "w-24" + (com/money-input {:class "w-24 text-right font-mono tabular-nums" :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)))))) + [:span.font-mono.tabular-nums.text-gray-900.text-sm.whitespace-nowrap + (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)))))) @@ -467,7 +477,7 @@ :footer (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]"))) + :width-height-class "lg:w-[920px] lg:h-[640px]"))) (defn attach-ledger [i] (cond-> i