Files
integreat/src/cljc/auto_ap/ssr_routes.cljc
Bryce cc31d8849b Feat/Complete Sales Summaries (#5)
## Summary

Completes the automatic sales summary pipeline end-to-end: the `sales-summaries-v2` job now calculates aggregate totals, preserves manual adjustments, and automatically posts balanced journal entries to the ledger.

## What Changed

**New Datomic transaction function** (`upsert-sales-summary-ledger`)
- Transforms detailed `sales-summary-item`s into aggregated `journal-entry` lines grouped by account and ledger side
- Handles the full upsert: posts a new journal entry for summaries with mapped accounts, or retracts the orphaned entry if items no longer qualify

**Enhanced `sales-summaries-v2` job**
- Calculates and stores 13 aggregate total attributes (card/cash/food-app/gift-card payments, refunds, fees, discounts, tax, tip, returns, unknown, net)
- Preserves manual items (`manual? true`) during recalculation — only auto-calculated items are replaced

**Ledger reconciliation**
- `reconcile-ledger` now queries for sales summaries missing journal entries and repairs them via `:upsert-sales-summary-ledger`, alongside existing invoice and transaction repairs

**Schema**
- Added 13 `total-*` attributes on `sales-summary` (all `db.type/double`, no history)
- Registered the new transaction function in `tx.clj` and `datomic.clj`

**Admin UI cleanup**
- Resolved "clientize" and HTMX `client-id` TODOs in the sales summaries admin page
- `new-summary-item` now correctly passes `client-id` via `hx-vals`
- Removed stale TODO comments and placeholder code

## Files Changed (8)

| File | Purpose |
|------|---------|
| `iol_ion/.../upsert_sales_summary_ledger.clj` | New Datomic tx function |
| `iol_ion/.../tx.clj` | Register new tx function |
| `resources/schema.edn` | 13 new `total-*` attributes |
| `src/.../datomic.clj` | Load new tx namespace |
| `src/.../jobs/sales_summaries.clj` | Aggregate totals + manual item preservation |
| `src/.../ledger.clj` | Sales summary repair in `reconcile-ledger` |
| `src/.../ssr/admin/sales_summaries.clj` | UI TODO cleanup |
| `docs/plans/...plan.md` | Implementation plan document |

Co-authored-by: Bryce <bryce@integreatconsult.com>
Reviewed-on: #5
Co-authored-by: Bryce <bryce@brycecovertoperations.com>
Co-committed-by: Bryce <bryce@brycecovertoperations.com>
2026-05-16 00:16:44 -07:00

121 lines
7.5 KiB
Clojure

(ns auto-ap.ssr-routes
(:require
[auto-ap.routes.admin.excel-invoices :as ei-routes]
[auto-ap.routes.admin.import-batch :as ib-routes]
[auto-ap.routes.indicators :as indicator-routes]
[auto-ap.routes.admin.vendors :as v-routes]
[auto-ap.routes.outgoing-invoice :as oi-routes]
[auto-ap.routes.payments :as p-routes]
[auto-ap.routes.dashboard :as d-routes]
[auto-ap.routes.invoice :as i-routes]
[auto-ap.routes.ledger :as l-routes]
[auto-ap.routes.transactions :as t-routes]
[auto-ap.routes.admin.clients :as ac-routes]
[auto-ap.routes.pos.sales-summaries :as ss-routes]
[auto-ap.routes.admin.transaction-rules :as tr-routes]))
(def routes {"impersonate" :impersonate
"logout" :logout
"search" :search
"indicators" indicator-routes/routes
"dashboard" d-routes/routes
"account" {"/search" {:get :account-search}}
"admin" {"" :auto-ap.routes.admin/page
"/client" ac-routes/routes
"/history" {"" :admin-history
"/" :admin-history
#"/search/?" :admin-history-search
["/" [#"\d+" :entity-id] #"/?"] :admin-history
["/inspect/" [#"\d+" :entity-id] #"/?"] :admin-history-inspect}
"/user" {"" {:get :users
:put :user-edit-save}
"/client/new" :user-client-new
"/table" :user-table
"/impersonate" :user-impersonate
["/" [#"\d+" :db/id] "/edit"] {:get :user-edit-dialog}}
"/account" {"" {:get :admin-accounts
:put :admin-account-save
:post :admin-account-save}
"/table" :admin-account-table
"/new" {:get :admin-account-new-dialog}
["/" [#"\d+" :db/id] "/edit"] :admin-account-edit-dialog
"/override/new" :admin-account-client-override-new}
"/background-job" {"" {:get :admin-jobs
:post :admin-job-start}
"/table" :admin-job-table
"/new" {:get :admin-job-start-dialog}
"/subform" :admin-job-subform}
"/vendor" v-routes/routes
"/ezcater-xls" :admin-ezcater-xls
"/import-batch" ib-routes/routes
"/transaction-rule" tr-routes/routes
"/excel-invoice" ei-routes/routes}
"ledger" l-routes/routes
"transaction2" t-routes/routes
"transaction" {"/insights" {"" :transaction-insights
"/table" :transaction-insight-table
["/code/" [#"\d+" :transaction-id]] {:post :transaction-insight-code}
["/disapprove/" [#"\d+" :transaction-id]] {:delete :transaction-insight-disapprove}
["/rows/" [#"\d+" :after]] {:get :transaction-insight-rows}
["/explain/" [#"\d+" :transaction-id]] {:get :transaction-insight-explain}}}
"pos" {"/summaries" ss-routes/routes
"/sales" {"" {:get :pos-sales}
"/table" {:get :pos-sales-table}}
"/expected-deposit" {"" {:get :pos-expected-deposits}
"/table" {:get :pos-expected-deposit-table}}
"/tenders" {"" {:get :pos-tenders}
"/table" {:get :pos-tender-table}}
"/refunds" {"" {:get :pos-refunds}
"/table" {:get :pos-refund-table}}
"/cash-drawer-shifts" {"" {:get :pos-cash-drawer-shifts}
"/table" {:get :pos-cash-drawer-shift-table}}}
"outgoing-invoice" oi-routes/routes
"payment" p-routes/routes
"invoice" i-routes/routes
"invoices/" i-routes/legacy-routes
"invoices" i-routes/legacy-routes
"vendor" {"/search" :vendor-search}
;; TODO Include IDS in routes for company-specific things, as opposed to headers
"company" {"" :company
"/dropdown" :company-dropdown-search-results
"/signature" {"/put" :company-update-signature
"/post" :company-upload-signature}
"/search" :company-search
"/bank-account/typeahead" :bank-account-typeahead
["/" [#"\d+" :db/id] "/bank-account"] {"/search" :bank-account-search}
"/active" {:put :active-client}
"/active-group" {:put :active-client-group}
"/1099" :company-1099
"/1099/table" {:get :company-1099-vendor-table}
"/1099/vendor-dialog" {["/" [#"\d+" :vendor-id]] {:get :company-1099-vendor-dialog
:post :company-1099-vendor-save}}
"/reports" {"" {:get :company-reports
:delete :company-reports-delete}
"/table" :company-reports-table
"/expense" {:get :company-expense-report
"/card" :company-expense-report-breakdown-card
"/invoice-total-card" :company-expense-report-invoice-total-card}
"/reconciliation"
{:get :company-reconciliation-report
"/card" :company-reconciliation-report-card}}
"/yodlee" {"" {:get :company-yodlee}
"/table" {:get :company-yodlee-table}
"/fastlink" {:get :company-yodlee-fastlink-dialog}
"/refresh" {:put :company-yodlee-provider-account-refresh}
"/reauthenticate" {:put :company-yodlee-provider-account-reauthenticate}}
"/plaid" {"" {:get :company-plaid}
"/table" {:get :company-plaid-table}
"/link" {:post :company-plaid-link}
"/relink" {:put :company-plaid-relink}
#_#_"/fastlink" {:get :company-yodlee-fastlink-dialog}
#_#_"/refresh" {:put :company-yodlee-provider-account-refresh}}}})
(def only-routes ["/" routes])