refactor(all): rewrite all behavior docs in table format with checkboxes
Rewrite all 11 remaining behavior documents to match the streamlined invoice.md format: - dashboard.md: 250 lines, 62 behaviors - payment.md: 260 lines, behaviors for list, void, check printing, ACH - transaction.md: 310 lines, list, import, admin insights - ledger.md: 519 lines, entries, P&L, balance sheet, cash flows - company.md: 320 lines, profile, 1099s, Plaid/Yodlee, reports - admin.md: 494 lines, clients, accounts, vendors, rules, jobs, history - pos.md: 405 lines, sales, deposits, tenders, refunds, shifts - search-indicators.md: 167 lines, search modal, indicators - auth.md: 184 lines, login, logout, impersonation, sessions - outgoing-invoice.md: 192 lines, create, line items, PDF - legacy-spa.md: 340 lines, all legacy pages (docs only) All documents now use: - Testing Patterns section with reusable abstractions - Numbered tables: # | Behavior | Test Strategy | Status - It should... behavior descriptions - Checkboxes [ ]/[x] for tracking implementation - Cross-Cutting Behaviors for permissions, lock dates, etc. - Test Data Requirements tables - Existing Tests to Preserve sections Total: 3,844 lines of behavior documentation across 12 subsystem docs.
This commit is contained in:
@@ -4,364 +4,516 @@
|
||||
|
||||
The Ledger module is the core accounting interface of Integreat. It provides server-side rendered (HTMX) pages for viewing journal entries, creating manual journal entries, and generating financial reports (Profit & Loss, Balance Sheet, Cash Flows). All ledger pages are permission-gated and client-scoped.
|
||||
|
||||
## Routes & Pages
|
||||
**Testing Philosophy**
|
||||
- Prefer unit tests for pure business logic (calculations, validations, transformations)
|
||||
- Use integration tests for database interactions and cross-system flows
|
||||
- Use UI tests only for end-to-end happy paths that touch multiple pages
|
||||
- Every behavior must be user-visible; no tests for implementation details
|
||||
|
||||
| Route | Method | Handler | Description |
|
||||
|-------|--------|---------|-------------|
|
||||
| `/ledger` | GET | `::all-page` | Main ledger entries list (internal) |
|
||||
| `/ledger/external-new` | GET | `::external-page` | External ledger entries list |
|
||||
| `/ledger/new` | GET | `::new` | Modal form for new journal entry |
|
||||
| `/ledger/new` | POST | `::new-submit` | Submit new journal entry |
|
||||
| `/ledger/new/location-select` | GET | `::location-select` | Location dropdown for line item |
|
||||
| `/ledger/new/account-typeahead` | GET | `::account-typeahead` | Account search for line item |
|
||||
| `/ledger/new/line-item` | GET | `::new-line-item` | Add new line item row |
|
||||
| `/ledger/external-import-new` | GET | `::external-import-page` | External TSV import page |
|
||||
| `/ledger/external-import-new/parse` | POST | `::external-import-parse` | Parse clipboard TSV data |
|
||||
| `/ledger/external-import-new/import` | POST | `::external-import-import` | Import validated entries |
|
||||
| `/ledger/investigate` | GET | `::investigate` | Investigation modal for report drill-down |
|
||||
| `/ledger/investigate/results` | GET | `::investigate-results` | Investigation results table |
|
||||
| `/ledger/table` | GET | `::table` | HTMX table fragment for ledger entries |
|
||||
| `/ledger/csv` | GET | `::csv` | CSV export of ledger entries |
|
||||
| `/ledger/bank-account-filter` | GET | `::bank-account-filter` | Bank account filter widget |
|
||||
| `/ledger/reports/profit-and-loss` | GET | `::profit-and-loss` | P&L report page |
|
||||
| `/ledger/reports/profit-and-loss/run` | PUT | `::run-profit-and-loss` | Run P&L report |
|
||||
| `/ledger/reports/profit-and-loss/export` | POST | `::export-profit-and-loss` | Export P&L to PDF |
|
||||
| `/ledger/reports/balance-sheet` | GET | `::balance-sheet` | Balance sheet page |
|
||||
| `/ledger/reports/balance-sheet/run` | GET | `::run-balance-sheet` | Run balance sheet |
|
||||
| `/ledger/reports/balance-sheet/export` | POST | `::export-balance-sheet` | Export balance sheet to PDF |
|
||||
| `/ledger/reports/cash-flows` | GET | `::cash-flows` | Cash flows page |
|
||||
| `/ledger/reports/cash-flows/run` | PUT | `::run-cash-flows` | Run cash flows report |
|
||||
| `/ledger/reports/cash-flows/export` | POST | `::export-cash-flows` | Export cash flows to PDF |
|
||||
---
|
||||
|
||||
## Behaviors by Page
|
||||
## Testing Patterns
|
||||
|
||||
### Ledger Entries List
|
||||
### Pattern: Grid Page Behaviors
|
||||
Most list pages in Integreat follow the same pattern:
|
||||
1. Fetch IDs via Datomic query with filters
|
||||
2. Hydrate results via `pull-many`
|
||||
3. Render table with sortable columns
|
||||
4. Support selection (individual / all / all-filtered)
|
||||
5. Action buttons appear conditionally based on permissions and selection state
|
||||
|
||||
**Page load**
|
||||
- Displays a paginated, sortable data grid of journal entries
|
||||
- Shows client selection sidebar if user has access to multiple clients
|
||||
- Title reflects status filter: e.g. "Unpaid Register" or "Paid Register"
|
||||
- Includes an "Add journal entry" button (hidden on external ledger page)
|
||||
**Test implications:** Validate the query generation, not the rendering. UI tests only need to verify one filter and one sort work end-to-end.
|
||||
|
||||
**Columns displayed**
|
||||
- Client (hidden if only 1 client with 1 location)
|
||||
- Vendor (falls back to `alternate-description` if no vendor)
|
||||
- Source (hidden on internal ledger)
|
||||
- External ID (hidden on internal ledger, truncated to max-width)
|
||||
- Date
|
||||
- Amount (formatted as currency)
|
||||
- Debit lines (account + location + amount)
|
||||
- Credit lines (account + location + amount)
|
||||
- Links dropdown (links to original invoice, source file, transaction, or memo)
|
||||
### Pattern: Modal Form Behaviors
|
||||
Modal forms are HTMX-driven dialogs:
|
||||
1. Opened via GET request that renders a form fragment
|
||||
2. Form submissions are POST/PUT with validation
|
||||
3. On success, the modal closes and the table updates in place
|
||||
4. On validation failure, the modal shows error messages
|
||||
|
||||
**Row actions**
|
||||
- Void button for unpaid invoices (requires `:delete :invoice` permission)
|
||||
- Edit button for unpaid/paid invoices (requires `:edit :invoice` permission)
|
||||
- Unvoid button for voided invoices (requires `:edit :invoice` permission)
|
||||
- Trash icon with confirmation for delete operations
|
||||
**Test implications:** Unit test validation logic. Integration test the full modal flow once. UI test only the happy path.
|
||||
|
||||
**Sorting**
|
||||
- Available sorts: Client, Vendor, Source, External ID, Date, Amount, Account
|
||||
- Default sort: Date ascending
|
||||
- Sorting by Vendor or Source groups rows with break headers
|
||||
### Pattern: Report Behaviors
|
||||
Financial reports follow a consistent pattern:
|
||||
1. Form with client multi-select, date/period selectors, and toggles
|
||||
2. Run button triggers HTMX request to generate report
|
||||
3. Report data is computed from account snapshots and running balances
|
||||
4. Export button generates PDF and returns a download modal
|
||||
|
||||
**Filtering (left sidebar)**
|
||||
- Vendor typeahead search
|
||||
- Account typeahead search
|
||||
- Bank account radio filter (refreshes on client change)
|
||||
- Date range picker
|
||||
- Invoice number text search
|
||||
- Account code range (gte/lte inputs)
|
||||
- Amount range (gte/lte inputs)
|
||||
- "Show unbalanced" checkbox (filters to entries where debits ≠ credits)
|
||||
- Exact match ID pill (clears on click)
|
||||
**Test implications:** Unit test calculation logic. Integration test report generation with various filter combinations. UI test only one report end-to-end.
|
||||
|
||||
**Pagination**
|
||||
- Default 25 entries per page
|
||||
- Configurable per-page
|
||||
- Pagination controls at bottom
|
||||
### Pattern: Permission Gates
|
||||
Every mutating operation checks:
|
||||
1. `assert-can-see-client` — user has access to the client
|
||||
2. `assert-not-locked` — entry date >= client locked-until
|
||||
3. `can?` — user has the specific permission for the activity
|
||||
|
||||
**CSV Export**
|
||||
- Exports all matching entries with line-item-level rows
|
||||
- Columns: ID, Client, Vendor, Source, External ID, Date, Amount, Account, Debit, Credit
|
||||
**Test implications:** Integration test each gate independently. UI tests only verify the happy path with a permitted user.
|
||||
|
||||
### New Journal Entry
|
||||
---
|
||||
|
||||
**Modal form**
|
||||
- Opens as modal dialog (750px wide)
|
||||
- Client typeahead (pre-filled if client already selected on parent page)
|
||||
- Date input (default today, format MM/DD/YYYY)
|
||||
- Vendor typeahead (disabled if editing existing entry)
|
||||
- Total amount input (must be ≥ $0.01)
|
||||
- Memo text input (optional)
|
||||
- Line items grid with columns: Account, Location, Debit, Credit
|
||||
## Ledger Entries List
|
||||
|
||||
**Line item behaviors**
|
||||
- Account typeahead searches accounts scoped to selected client
|
||||
- Location dropdown updates based on selected account's required location
|
||||
- If account has a fixed location, dropdown is locked to that location
|
||||
- If account has no location restriction, shows client's locations
|
||||
- New line item rows added via HTMX request
|
||||
- Line items can be removed with X button
|
||||
### Display Behaviors
|
||||
|
||||
**Validation**
|
||||
- Client is required
|
||||
- Date is required and must be valid
|
||||
- Vendor is required
|
||||
- Amount must be ≥ $0.01
|
||||
- Each line item must have an allowed account
|
||||
- Each line item must have a location belonging to the account
|
||||
- Debits must sum to total amount
|
||||
- Credits must sum to total amount
|
||||
- Debits and credits must each equal the journal entry amount
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 1.1 | It should display a paginated, sortable data grid of journal entries | UI | [ ] |
|
||||
| 1.2 | It should show the Client column only when multiple clients OR multiple locations are selected | Integration | [ ] |
|
||||
| 1.3 | It should display the Vendor column, falling back to `alternate-description` when no vendor is present | Integration | [ ] |
|
||||
| 1.4 | It should hide the Source column on the internal ledger page | UI | [ ] |
|
||||
| 1.5 | It should hide the External ID column on the internal ledger page | UI | [ ] |
|
||||
| 1.6 | It should truncate the External ID column to a max-width when displayed | UI | [ ] |
|
||||
| 1.7 | It should display the Date column with formatted dates | UI | [ ] |
|
||||
| 1.8 | It should display the Amount column formatted as currency | UI | [ ] |
|
||||
| 1.9 | It should display Debit lines with account, location, and amount per line item | UI | [ ] |
|
||||
| 1.10 | It should display Credit lines with account, location, and amount per line item | UI | [ ] |
|
||||
| 1.11 | It should display a Links dropdown with links to original invoice, source file, transaction, or memo | UI | [ ] |
|
||||
| 1.12 | It should show the page title reflecting the status filter, e.g. "Unpaid Register" or "Paid Register" | UI | [ ] |
|
||||
| 1.13 | It should show an "Add journal entry" button on the internal ledger page | UI | [ ] |
|
||||
| 1.14 | It should hide the "Add journal entry" button on the external ledger page | UI | [ ] |
|
||||
| 1.15 | It should show a client selection sidebar when the user has access to multiple clients | UI | [ ] |
|
||||
|
||||
**On save**
|
||||
- Generates external ID: `manual-<uuid>`
|
||||
- Updates client's `ledger-last-change` timestamp
|
||||
- On POST: prepends new row to table, triggers modal close
|
||||
- On PUT: replaces existing row in table, triggers modal close
|
||||
### Filtering Behaviors
|
||||
|
||||
### External Import
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 2.1 | It should filter entries by vendor typeahead selection | Integration | [ ] |
|
||||
| 2.2 | It should filter entries by account typeahead selection | Integration | [ ] |
|
||||
| 2.3 | It should filter entries by bank account via radio filter | Integration | [ ] |
|
||||
| 2.4 | It should refresh the bank account filter when the client selection changes | Integration | [ ] |
|
||||
| 2.5 | It should filter entries by date range | Integration | [ ] |
|
||||
| 2.6 | It should filter entries by invoice number text search | Integration | [ ] |
|
||||
| 2.7 | It should filter entries by account code range (gte/lte inputs) | Integration | [ ] |
|
||||
| 2.8 | It should filter entries by amount range (gte/lte inputs) | Integration | [ ] |
|
||||
| 2.9 | It should filter to unbalanced entries when "Show unbalanced" is checked | Integration | [ ] |
|
||||
| 2.10 | It should support exact-match navigation to a specific entry by ID, bypassing other filters | Integration | [ ] |
|
||||
| 2.11 | It should clear the exact match ID pill when clicked | UI | [ ] |
|
||||
| 2.12 | Given multiple filters are applied, when the user changes one filter, then the table should refresh with the combined filter set | Integration | [ ] |
|
||||
|
||||
**Clipboard paste**
|
||||
- User clicks "Load from clipboard" button
|
||||
- Reads TSV data from browser clipboard
|
||||
- Parses tab-separated values with columns: Id, Client, Source, Vendor, Date, Account Code, Location, Debit, Credit
|
||||
### Sorting Behaviors
|
||||
|
||||
**Parse validation**
|
||||
- Validates all rows have required fields
|
||||
- Dates must be parseable
|
||||
- Account codes must be numeric or bank account strings
|
||||
- Locations must be 1-2 characters
|
||||
- Debits/Credits must be valid money amounts
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 3.1 | It should sort by Client ascending/descending | Integration | [ ] |
|
||||
| 3.2 | It should sort by Vendor ascending/descending | Integration | [ ] |
|
||||
| 3.3 | It should sort by Source ascending/descending | Integration | [ ] |
|
||||
| 3.4 | It should sort by External ID ascending/descending | Integration | [ ] |
|
||||
| 3.5 | It should sort by Date ascending/descending | Integration | [ ] |
|
||||
| 3.6 | It should sort by Amount ascending/descending | Integration | [ ] |
|
||||
| 3.7 | It should sort by Account ascending/descending | Integration | [ ] |
|
||||
| 3.8 | It should default to Date ascending | Integration | [ ] |
|
||||
| 3.9 | Given sorting by Vendor, then rows should be grouped with break headers | Integration | [ ] |
|
||||
| 3.10 | Given sorting by Source, then rows should be grouped with break headers | Integration | [ ] |
|
||||
| 3.11 | Given the user clicks a column header twice, then the sort direction should toggle | Integration | [ ] |
|
||||
|
||||
**Import validation**
|
||||
- Client code must exist
|
||||
- Vendor must exist (creates hidden vendor if missing)
|
||||
- Client must not be locked for the entry date
|
||||
- Debits and credits must balance per entry
|
||||
- Entry cannot total $0.00 (warning)
|
||||
- Location must belong to client
|
||||
- Account code must exist
|
||||
- Bank account code must belong to client
|
||||
- Account location requirements must be satisfied
|
||||
### Pagination Behaviors
|
||||
|
||||
**Import results**
|
||||
- Successful entries are imported
|
||||
- Entries with warnings are ignored (removed if previously existed)
|
||||
- Entries with errors block import and show error counts
|
||||
- Retracts existing entries by external ID before importing
|
||||
- Indexes imported entries in Solr asynchronously
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 4.1 | It should display 25 entries per page by default | Integration | [ ] |
|
||||
| 4.2 | It should allow changing the per-page count | Integration | [ ] |
|
||||
| 4.3 | It should show pagination controls at the bottom of the table | UI | [ ] |
|
||||
|
||||
### P&L Report
|
||||
### Row Action Behaviors
|
||||
|
||||
**Form**
|
||||
- Customer multi-select typeahead (max 20, defaults to first 5 if "all")
|
||||
- Periods dropdown (default: year-to-date)
|
||||
- "Column per location" toggle
|
||||
- "Include deltas" toggle
|
||||
- Run button (HTMX PUT)
|
||||
- Export PDF button
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 5.1 | It should show a void button for unpaid invoices when the user has `:delete :invoice` permission | UI | [ ] |
|
||||
| 5.2 | It should show an edit button for unpaid and paid invoices when the user has `:edit :invoice` permission | UI | [ ] |
|
||||
| 5.3 | It should show an unvoid button for voided invoices when the user has `:edit :invoice` permission | UI | [ ] |
|
||||
| 5.4 | It should show a trash icon with confirmation for delete operations | UI | [ ] |
|
||||
|
||||
**Report generation**
|
||||
- Computes running balances before generating
|
||||
- Queries detailed account snapshots for each client/period end date
|
||||
- Amounts calculated as: debits - credits for assets/dividends/expenses, credits - debits for others
|
||||
- Groups data by client, location, and period
|
||||
### CSV Export Behaviors
|
||||
|
||||
**Report output**
|
||||
- Summary table: Sales, COGS, Payroll, Gross Profits, Overhead, Net Income
|
||||
- Detail table: Account-level breakdown within each category
|
||||
- Percent of sales calculated for each row
|
||||
- Deltas shown between periods if enabled
|
||||
- Column-per-location mode shows each location as separate columns
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 6.1 | It should export all matching entries with line-item-level rows | Integration | [ ] |
|
||||
| 6.2 | It should include columns: ID, Client, Vendor, Source, External ID, Date, Amount, Account, Debit, Credit | Integration | [ ] |
|
||||
|
||||
**Warnings**
|
||||
- Warns if >20 clients selected (truncates to 20)
|
||||
- Warns about unresolved ledger entries (missing numeric codes)
|
||||
- Shows sample links to admin history for invalid entries (if user has `:view :history` permission)
|
||||
---
|
||||
|
||||
**PDF Export**
|
||||
- Generates PDF with Calibri Light font, 6pt
|
||||
- Uploads to S3 at `reports/profit-and-loss/<uuid>/<name>.pdf`
|
||||
- Persists report record in Datomic
|
||||
- Returns modal with download link
|
||||
## New Journal Entry
|
||||
|
||||
### Balance Sheet
|
||||
### Modal Form Behaviors
|
||||
|
||||
**Form**
|
||||
- Customer multi-select typeahead (max 20, defaults to first 5 if "all")
|
||||
- Date dropdown (single date, default today)
|
||||
- "Include deltas" toggle
|
||||
- Run button (HTMX GET)
|
||||
- Export PDF button
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 7.1 | It should open as a modal dialog 750px wide | UI | [ ] |
|
||||
| 7.2 | It should show a client typeahead pre-filled if a client is already selected on the parent page | UI | [ ] |
|
||||
| 7.3 | It should show a date input defaulting to today in MM/DD/YYYY format | UI | [ ] |
|
||||
| 7.4 | It should show a vendor typeahead disabled when editing an existing entry | UI | [ ] |
|
||||
| 7.5 | It should show a total amount input requiring a value of at least $0.01 | Unit + Integration | [ ] |
|
||||
| 7.6 | It should show an optional memo text input | UI | [ ] |
|
||||
| 7.7 | It should display a line items grid with Account, Location, Debit, and Credit columns | UI | [ ] |
|
||||
|
||||
**Report generation**
|
||||
- Computes running balances before generating
|
||||
- Queries account snapshot as of each selected date
|
||||
- Groups by account categories: Assets, Liabilities, Owner's Equity
|
||||
- Includes Retained Earnings (net income across all P&L categories)
|
||||
### Line Item Behaviors
|
||||
|
||||
**Report output**
|
||||
- Assets section with account detail and subtotal
|
||||
- Liabilities section with account detail and subtotal
|
||||
- Owner's Equity section with account detail and subtotal
|
||||
- Retained Earnings line
|
||||
- Delta columns between periods if enabled and multiple dates selected
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 8.1 | It should allow account typeahead search scoped to the selected client | Integration | [ ] |
|
||||
| 8.2 | It should update the location dropdown based on the selected account's required location | Integration | [ ] |
|
||||
| 8.3 | It should lock the location dropdown to a fixed location when the account requires it | Integration | [ ] |
|
||||
| 8.4 | It should show all client locations when the account has no location restriction | Integration | [ ] |
|
||||
| 8.5 | It should add new line item rows via HTMX request | UI | [ ] |
|
||||
| 8.6 | It should allow removing line item rows with an X button | UI | [ ] |
|
||||
|
||||
**Warnings**
|
||||
- Warns if >20 clients selected
|
||||
- Warns about unresolved ledger entries
|
||||
### Validation Behaviors
|
||||
|
||||
**PDF Export**
|
||||
- Generates PDF, uploads to S3 at `reports/balance-sheet/<uuid>/<name>.pdf`
|
||||
- Persists report record in Datomic
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 9.1 | It should require a client | Unit + Integration | [ ] |
|
||||
| 9.2 | It should require a valid date | Unit + Integration | [ ] |
|
||||
| 9.3 | It should require a vendor | Unit + Integration | [ ] |
|
||||
| 9.4 | It should require an amount of at least $0.01 | Unit + Integration | [ ] |
|
||||
| 9.5 | It should require each line item to have an allowed account | Unit + Integration | [ ] |
|
||||
| 9.6 | It should require each line item to have a location belonging to the account | Unit + Integration | [ ] |
|
||||
| 9.7 | It should validate that debits sum to the total amount | Unit + Integration | [ ] |
|
||||
| 9.8 | It should validate that credits sum to the total amount | Unit + Integration | [ ] |
|
||||
| 9.9 | It should validate that debits and credits each equal the journal entry amount | Unit + Integration | [ ] |
|
||||
| 9.10 | It should block saving when the entry date is on or before the client's `locked-until` date | Integration | [ ] |
|
||||
|
||||
### Cash Flows
|
||||
### Save Behaviors
|
||||
|
||||
**Form**
|
||||
- Customer multi-select typeahead (max 20, defaults to first 5 if "all")
|
||||
- Periods dropdown (default: year-to-date)
|
||||
- Run button (HTMX PUT)
|
||||
- Export PDF button
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 10.1 | It should generate an external ID in the format `manual-<uuid>` | Unit | [ ] |
|
||||
| 10.2 | It should update the client's `ledger-last-change` timestamp | Integration | [ ] |
|
||||
| 10.3 | Given a new entry is saved successfully, then it should prepend the new row to the table and close the modal | UI | [ ] |
|
||||
| 10.4 | Given an existing entry is saved successfully, then it should replace the existing row in the table and close the modal | UI | [ ] |
|
||||
|
||||
**Report generation**
|
||||
- Queries account snapshot as of period end + 1 day
|
||||
- Groups accounts into: Operating Activities, Investment Activities, Financing Activities, Cash
|
||||
- Calculates cash flow effect: add or subtract based on account code ranges
|
||||
---
|
||||
|
||||
**Report output**
|
||||
- Net Income starting point
|
||||
- Operating Activities detail (increases, decreases, +/- in cash)
|
||||
- Investment Activities detail
|
||||
- Financing Activities detail
|
||||
- Change in Cash and Cash Equivalents total
|
||||
- Bank Accounts / Cash detail
|
||||
## External Import
|
||||
|
||||
**Warnings**
|
||||
- Warns if >20 clients selected
|
||||
- Warns about unresolved ledger entries
|
||||
### Clipboard Paste Behaviors
|
||||
|
||||
**PDF Export**
|
||||
- Generates PDF, uploads to S3 at `reports/cash-flows/<uuid>/<name>.pdf`
|
||||
- Persists report record in Datomic
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 11.1 | It should allow clicking a "Load from clipboard" button | UI | [ ] |
|
||||
| 11.2 | It should read TSV data from the browser clipboard | UI | [ ] |
|
||||
| 11.3 | It should parse tab-separated values with columns: Id, Client, Source, Vendor, Date, Account Code, Location, Debit, Credit | Integration | [ ] |
|
||||
|
||||
### Investigation
|
||||
### Parse Validation Behaviors
|
||||
|
||||
**Modal behavior**
|
||||
- Opens as modal dialog from report table cell clicks
|
||||
- Shows ledger entries filtered by the clicked cell's filters (account code range, client, location, date range)
|
||||
- Displays raw table without checkboxes
|
||||
- Max height 600px with scrollable content
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 12.1 | It should validate that all rows have required fields | Integration | [ ] |
|
||||
| 12.2 | It should validate that dates are parseable | Unit + Integration | [ ] |
|
||||
| 12.3 | It should validate that account codes are numeric or bank account strings | Unit + Integration | [ ] |
|
||||
| 12.4 | It should validate that locations are 1-2 characters | Unit + Integration | [ ] |
|
||||
| 12.5 | It should validate that debits and credits are valid money amounts | Unit + Integration | [ ] |
|
||||
|
||||
**Table behavior**
|
||||
- Uses same query schema as main ledger list
|
||||
- Supports sorting and pagination
|
||||
- Does not push URL state
|
||||
### Import Validation Behaviors
|
||||
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 13.1 | It should validate that the client code exists | Integration | [ ] |
|
||||
| 13.2 | It should validate that the vendor exists, creating a hidden vendor if missing | Integration | [ ] |
|
||||
| 13.3 | It should block entries for dates when the client is locked | Integration | [ ] |
|
||||
| 13.4 | It should validate that debits and credits balance per entry | Unit + Integration | [ ] |
|
||||
| 13.5 | It should warn when an entry totals $0.00 | Unit + Integration | [ ] |
|
||||
| 13.6 | It should validate that the location belongs to the client | Integration | [ ] |
|
||||
| 13.7 | It should validate that the account code exists | Integration | [ ] |
|
||||
| 13.8 | It should validate that bank account codes belong to the client | Integration | [ ] |
|
||||
| 13.9 | It should validate that account location requirements are satisfied | Integration | [ ] |
|
||||
|
||||
### Import Result Behaviors
|
||||
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 14.1 | It should import successful entries | Integration | [ ] |
|
||||
| 14.2 | It should ignore entries with warnings, removing them if they previously existed | Integration | [ ] |
|
||||
| 14.3 | It should block import and show error counts when entries have errors | Integration | [ ] |
|
||||
| 14.4 | It should retract existing entries by external ID before importing | Integration | [ ] |
|
||||
| 14.5 | It should index imported entries in Solr asynchronously | Integration | [ ] |
|
||||
|
||||
---
|
||||
|
||||
## P&L Report
|
||||
|
||||
### Form Behaviors
|
||||
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 15.1 | It should show a customer multi-select typeahead with a max of 20 selections | UI | [ ] |
|
||||
| 15.2 | It should default to the first 5 customers when "all" is selected | Integration | [ ] |
|
||||
| 15.3 | It should show a periods dropdown defaulting to year-to-date | UI | [ ] |
|
||||
| 15.4 | It should show a "Column per location" toggle | UI | [ ] |
|
||||
| 15.5 | It should show an "Include deltas" toggle | UI | [ ] |
|
||||
| 15.6 | It should trigger report generation via HTMX PUT on the Run button | UI | [ ] |
|
||||
| 15.7 | It should show an Export PDF button | UI | [ ] |
|
||||
|
||||
### Report Generation Behaviors
|
||||
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 16.1 | It should compute running balances before generating the report | Integration | [ ] |
|
||||
| 16.2 | It should query detailed account snapshots for each client and period end date | Integration | [ ] |
|
||||
| 16.3 | It should calculate amounts as debits minus credits for assets, dividends, and expenses | Unit | [ ] |
|
||||
| 16.4 | It should calculate amounts as credits minus debits for liabilities, equity, and revenue | Unit | [ ] |
|
||||
| 16.5 | It should group data by client, location, and period | Integration | [ ] |
|
||||
|
||||
### Report Output Behaviors
|
||||
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 17.1 | It should display a summary table with Sales, COGS, Payroll, Gross Profits, Overhead, and Net Income | UI | [ ] |
|
||||
| 17.2 | It should display a detail table with account-level breakdown within each category | UI | [ ] |
|
||||
| 17.3 | It should calculate percent of sales for each row | Unit | [ ] |
|
||||
| 17.4 | It should show deltas between periods when enabled | UI | [ ] |
|
||||
| 17.5 | It should show each location as separate columns when column-per-location mode is enabled | UI | [ ] |
|
||||
|
||||
### Warning Behaviors
|
||||
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 18.1 | It should warn when more than 20 clients are selected and truncate to 20 | Integration | [ ] |
|
||||
| 18.2 | It should warn about unresolved ledger entries with missing numeric codes | Integration | [ ] |
|
||||
| 18.3 | It should show sample links to admin history for invalid entries when the user has `:view :history` permission | Integration | [ ] |
|
||||
|
||||
### PDF Export Behaviors
|
||||
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 19.1 | It should generate a PDF with Calibri Light font at 6pt | Integration | [ ] |
|
||||
| 19.2 | It should upload the PDF to S3 at `reports/profit-and-loss/<uuid>/<name>.pdf` | Integration | [ ] |
|
||||
| 19.3 | It should persist a report record in Datomic | Integration | [ ] |
|
||||
| 19.4 | It should return a modal with a download link | UI | [ ] |
|
||||
|
||||
---
|
||||
|
||||
## Balance Sheet
|
||||
|
||||
### Form Behaviors
|
||||
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 20.1 | It should show a customer multi-select typeahead with a max of 20 selections | UI | [ ] |
|
||||
| 20.2 | It should default to the first 5 customers when "all" is selected | Integration | [ ] |
|
||||
| 20.3 | It should show a date dropdown defaulting to today | UI | [ ] |
|
||||
| 20.4 | It should show an "Include deltas" toggle | UI | [ ] |
|
||||
| 20.5 | It should trigger report generation via HTMX GET on the Run button | UI | [ ] |
|
||||
| 20.6 | It should show an Export PDF button | UI | [ ] |
|
||||
|
||||
### Report Generation Behaviors
|
||||
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 21.1 | It should compute running balances before generating the report | Integration | [ ] |
|
||||
| 21.2 | It should query account snapshots as of each selected date | Integration | [ ] |
|
||||
| 21.3 | It should group accounts into Assets, Liabilities, and Owner's Equity | Integration | [ ] |
|
||||
| 21.4 | It should include Retained Earnings as net income across all P&L categories | Unit | [ ] |
|
||||
|
||||
### Report Output Behaviors
|
||||
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 22.1 | It should display an Assets section with account detail and subtotal | UI | [ ] |
|
||||
| 22.2 | It should display a Liabilities section with account detail and subtotal | UI | [ ] |
|
||||
| 22.3 | It should display an Owner's Equity section with account detail and subtotal | UI | [ ] |
|
||||
| 22.4 | It should display a Retained Earnings line | UI | [ ] |
|
||||
| 22.5 | It should show delta columns between periods when enabled and multiple dates are selected | UI | [ ] |
|
||||
|
||||
### Warning Behaviors
|
||||
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 23.1 | It should warn when more than 20 clients are selected | Integration | [ ] |
|
||||
| 23.2 | It should warn about unresolved ledger entries | Integration | [ ] |
|
||||
|
||||
### PDF Export Behaviors
|
||||
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 24.1 | It should generate a PDF and upload to S3 at `reports/balance-sheet/<uuid>/<name>.pdf` | Integration | [ ] |
|
||||
| 24.2 | It should persist a report record in Datomic | Integration | [ ] |
|
||||
| 24.3 | It should return a modal with a download link | UI | [ ] |
|
||||
|
||||
---
|
||||
|
||||
## Cash Flows
|
||||
|
||||
### Form Behaviors
|
||||
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 25.1 | It should show a customer multi-select typeahead with a max of 20 selections | UI | [ ] |
|
||||
| 25.2 | It should default to the first 5 customers when "all" is selected | Integration | [ ] |
|
||||
| 25.3 | It should show a periods dropdown defaulting to year-to-date | UI | [ ] |
|
||||
| 25.4 | It should trigger report generation via HTMX PUT on the Run button | UI | [ ] |
|
||||
| 25.5 | It should show an Export PDF button | UI | [ ] |
|
||||
|
||||
### Report Generation Behaviors
|
||||
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 26.1 | It should query account snapshots as of period end plus one day | Integration | [ ] |
|
||||
| 26.2 | It should group accounts into Operating Activities, Investment Activities, Financing Activities, and Cash | Integration | [ ] |
|
||||
| 26.3 | It should calculate cash flow effect by adding or subtracting based on account code ranges | Unit | [ ] |
|
||||
|
||||
### Report Output Behaviors
|
||||
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 27.1 | It should display Net Income as the starting point | UI | [ ] |
|
||||
| 27.2 | It should display Operating Activities detail with increases, decreases, and cash impact | UI | [ ] |
|
||||
| 27.3 | It should display Investment Activities detail | UI | [ ] |
|
||||
| 27.4 | It should display Financing Activities detail | UI | [ ] |
|
||||
| 27.5 | It should display Change in Cash and Cash Equivalents total | UI | [ ] |
|
||||
| 27.6 | It should display Bank Accounts / Cash detail | UI | [ ] |
|
||||
|
||||
### Warning Behaviors
|
||||
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 28.1 | It should warn when more than 20 clients are selected | Integration | [ ] |
|
||||
| 28.2 | It should warn about unresolved ledger entries | Integration | [ ] |
|
||||
|
||||
### PDF Export Behaviors
|
||||
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 29.1 | It should generate a PDF and upload to S3 at `reports/cash-flows/<uuid>/<name>.pdf` | Integration | [ ] |
|
||||
| 29.2 | It should persist a report record in Datomic | Integration | [ ] |
|
||||
| 29.3 | It should return a modal with a download link | UI | [ ] |
|
||||
|
||||
---
|
||||
|
||||
## Investigation
|
||||
|
||||
### Modal Behaviors
|
||||
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 30.1 | It should open as a modal dialog from report table cell clicks | UI | [ ] |
|
||||
| 30.2 | It should filter ledger entries by the clicked cell's filters: account code range, client, location, and date range | Integration | [ ] |
|
||||
| 30.3 | It should display a raw table without checkboxes | UI | [ ] |
|
||||
| 30.4 | It should constrain the modal to a max height of 600px with scrollable content | UI | [ ] |
|
||||
|
||||
### Table Behaviors
|
||||
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 31.1 | It should use the same query schema as the main ledger list | Integration | [ ] |
|
||||
| 31.2 | It should support sorting and pagination | Integration | [ ] |
|
||||
| 31.3 | It should not push URL state on filter or sort changes | Integration | [ ] |
|
||||
|
||||
---
|
||||
|
||||
## Cross-Cutting Behaviors
|
||||
|
||||
### Report generation
|
||||
- All reports call `upsert-running-balance` before querying to ensure cached balances are current
|
||||
- Reports use `detailed-account-snapshot` Datomic query for raw data
|
||||
- Account lookups built per-client via `build-account-lookup`
|
||||
- Reports skip entries without numeric codes (unassigned accounts) and warn
|
||||
### Report Generation Behaviors
|
||||
|
||||
### Export
|
||||
- All three reports support PDF export via `clj-pdf`
|
||||
- PDFs use Calibri Light 6pt font on letter size
|
||||
- Uploaded to S3 data bucket with UUID-based key
|
||||
- Report metadata persisted to Datomic (`:report/name`, `:report/client`, `:report/key`, `:report/url`, `:report/creator`, `:report/created`)
|
||||
- Export returns modal with S3 download link
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 32.1 | It should call `upsert-running-balance` before querying to ensure cached balances are current | Integration | [ ] |
|
||||
| 32.2 | It should use `detailed-account-snapshot` Datomic query for raw report data | Integration | [ ] |
|
||||
| 32.3 | It should build account lookups per-client via `build-account-lookup` | Integration | [ ] |
|
||||
| 32.4 | It should skip entries without numeric codes and warn about unresolved entries | Integration | [ ] |
|
||||
|
||||
### Filtering and sorting
|
||||
- Ledger list filters applied via HTMX on change (500ms debounce) or keyup (1000ms debounce for hot filters)
|
||||
- Bank account filter refreshes when client selection changes
|
||||
- Sorting supports multiple sort keys with ascending/descending
|
||||
- Default sort is date ascending
|
||||
- Exact match ID filter bypasses all other filters
|
||||
### Export Behaviors
|
||||
|
||||
### Permissions
|
||||
- All ledger pages require authenticated user
|
||||
- Main ledger: `:read :ledger`
|
||||
- New/Edit journal entry: `:edit :ledger`
|
||||
- External import: `:import :ledger` + admin assertion
|
||||
- P&L report: `:read :profit-and-loss`
|
||||
- Balance sheet: `:read :balance-sheet`
|
||||
- Cash flows: `:read :cash-flows`
|
||||
- Users can only see clients they have permission for (`assert-can-see-client`)
|
||||
- Invoice void/edit/unvoid actions require respective invoice permissions
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 33.1 | It should support PDF export via `clj-pdf` for all three reports | Integration | [ ] |
|
||||
| 33.2 | It should use Calibri Light 6pt font on letter size for all PDF exports | Integration | [ ] |
|
||||
| 33.3 | It should upload PDFs to the S3 data bucket with a UUID-based key | Integration | [ ] |
|
||||
| 33.4 | It should persist report metadata to Datomic with name, client, key, URL, creator, and created timestamp | Integration | [ ] |
|
||||
| 33.5 | It should return a modal with an S3 download link after export | UI | [ ] |
|
||||
|
||||
## Edge Cases
|
||||
### Filtering and Sorting Behaviors
|
||||
|
||||
**Empty states**
|
||||
- No entries: empty table with pagination showing 0 results
|
||||
- No matching filters: empty table, filter pills remain
|
||||
- Report with no data: empty report form, no table rendered
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 34.1 | It should apply ledger list filters via HTMX on change with a 500ms debounce | Integration | [ ] |
|
||||
| 34.2 | It should apply hot filters via HTMX on keyup with a 1000ms debounce | Integration | [ ] |
|
||||
| 34.3 | It should refresh the bank account filter when client selection changes | Integration | [ ] |
|
||||
| 34.4 | It should support multiple sort keys with ascending and descending direction | Integration | [ ] |
|
||||
| 34.5 | It should default to date ascending sort | Integration | [ ] |
|
||||
| 34.6 | It should bypass all other filters when an exact match ID filter is active | Integration | [ ] |
|
||||
|
||||
**Data locking**
|
||||
- Journal entries cannot be created for dates on or before client's `locked-until` date
|
||||
- External import rejects entries for locked dates
|
||||
### Permission Behaviors
|
||||
|
||||
**Unbalanced entries**
|
||||
- "Show unbalanced" filter computes debit/credit sums per entry and filters to mismatches
|
||||
- Unbalanced entries are still displayed in normal view
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 35.1 | It should require an authenticated user for all ledger pages | Integration | [ ] |
|
||||
| 35.2 | It should require `:read :ledger` permission for the main ledger page | Integration | [ ] |
|
||||
| 35.3 | It should require `:edit :ledger` permission for new and edit journal entry | Integration | [ ] |
|
||||
| 35.4 | It should require `:import :ledger` permission plus admin assertion for external import | Integration | [ ] |
|
||||
| 35.5 | It should require `:read :profit-and-loss` permission for the P&L report | Integration | [ ] |
|
||||
| 35.6 | It should require `:read :balance-sheet` permission for the balance sheet | Integration | [ ] |
|
||||
| 35.7 | It should require `:read :cash-flows` permission for the cash flows report | Integration | [ ] |
|
||||
| 35.8 | It should restrict users to clients they have permission for via `assert-can-see-client` | Integration | [ ] |
|
||||
| 35.9 | It should require `:delete :invoice` permission for invoice void actions | Integration | [ ] |
|
||||
| 35.10 | It should require `:edit :invoice` permission for invoice edit and unvoid actions | Integration | [ ] |
|
||||
|
||||
**Account location mismatches**
|
||||
- Account with fixed location rejects other locations
|
||||
- Account without location restriction rejects "A" (all) location
|
||||
- Validation occurs on both frontend (location select) and backend (schema)
|
||||
### Empty State Behaviors
|
||||
|
||||
**Multi-client reports**
|
||||
- Capped at 20 clients for performance
|
||||
- "All" clients defaults to first 5 for reports
|
||||
- Report names include all selected client names
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 36.1 | It should show an empty table with pagination showing 0 results when no entries exist | UI | [ ] |
|
||||
| 36.2 | It should show an empty table with filter pills remaining when filters match nothing | UI | [ ] |
|
||||
| 36.3 | It should show an empty report form with no table rendered when report data is empty | UI | [ ] |
|
||||
|
||||
**Running balance cache**
|
||||
- `refresh-running-balance-cache` recomputes balances for dirty line items
|
||||
- Changing a ledger entry marks its line items and subsequent entries as dirty
|
||||
- Non-dirty entries are not recomputed
|
||||
### Data Locking Behaviors
|
||||
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 37.1 | It should block creating journal entries for dates on or before the client's `locked-until` date | Integration | [ ] |
|
||||
| 37.2 | It should reject external import entries for locked dates | Integration | [ ] |
|
||||
|
||||
### Unbalanced Entry Behaviors
|
||||
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 38.1 | It should compute debit and credit sums per entry for the "Show unbalanced" filter | Unit | [ ] |
|
||||
| 38.2 | It should display unbalanced entries in the normal view without filtering | UI | [ ] |
|
||||
|
||||
### Account Location Behaviors
|
||||
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 39.1 | It should reject locations other than the fixed location for accounts with fixed locations | Integration | [ ] |
|
||||
| 39.2 | It should reject "A" (all) location for accounts without location restrictions | Integration | [ ] |
|
||||
| 39.3 | It should validate account location requirements on both the frontend location select and backend schema | Integration | [ ] |
|
||||
|
||||
### Running Balance Cache Behaviors
|
||||
|
||||
| # | Behavior | Test Strategy | Status |
|
||||
|---|----------|---------------|--------|
|
||||
| 40.1 | It should recompute balances for dirty line items via `refresh-running-balance-cache` | Integration | [ ] |
|
||||
| 40.2 | It should mark a changed entry's line items and subsequent entries as dirty | Integration | [ ] |
|
||||
| 40.3 | It should skip recomputation for non-dirty entries | Integration | [ ] |
|
||||
|
||||
---
|
||||
|
||||
## Test Data Requirements
|
||||
|
||||
**Clients**
|
||||
- At least 2 clients with different locations
|
||||
- Client with `locked-until` date in the past
|
||||
| Entity | Requirements |
|
||||
|--------|-------------|
|
||||
| **Clients** | At least 2 clients with different locations; at least 1 client with a `locked-until` date in the past |
|
||||
| **Accounts** | Asset accounts (11000-11999); Liability accounts (20000-28999); Equity accounts (30000-39999); Revenue accounts (40000-49999); Expense accounts (50000-98999); accounts with fixed locations; accounts without location restrictions |
|
||||
| **Vendors** | Existing vendors; hidden vendors (auto-created on import) |
|
||||
| **Journal Entries** | Balanced entries (debits = credits); unbalanced entries (debits ≠ credits); entries with multiple line items; entries linked to invoices; entries with external IDs; entries across multiple dates and locations |
|
||||
| **Bank Accounts** | Bank accounts linked to clients |
|
||||
|
||||
**Accounts**
|
||||
- Asset accounts (11000-11999)
|
||||
- Liability accounts (20000-28999)
|
||||
- Equity accounts (30000-39999)
|
||||
- Revenue accounts (40000-49999)
|
||||
- Expense accounts (50000-98999)
|
||||
- Accounts with fixed locations
|
||||
- Accounts without location restrictions
|
||||
## Existing Tests to Preserve
|
||||
|
||||
**Vendors**
|
||||
- Existing vendors
|
||||
- Hidden vendors (auto-created on import)
|
||||
|
||||
**Journal entries**
|
||||
- Entries with debits = credits (balanced)
|
||||
- Entries with debits ≠ credits (unbalanced)
|
||||
- Entries with multiple line items
|
||||
- Entries linked to invoices
|
||||
- Entries with external IDs
|
||||
- Entries across multiple dates and locations
|
||||
|
||||
**Bank accounts**
|
||||
- Bank accounts linked to clients
|
||||
- `test/clj/auto_ap/ssr/ledger/ledger_test.clj` — Ledger page rendering and grid behaviors
|
||||
- `test/clj/auto_ap/integration/routes/ledger_test.clj` — Ledger routes and mutations
|
||||
- `test/clj/auto_ap/ledger/reports_test.clj` — Report generation and calculation logic
|
||||
|
||||
## Dependencies
|
||||
|
||||
- `auto-ap.ssr.ledger.common` - Shared grid page config, query schema, filtering
|
||||
- `auto-ap.ledger.reports` - Report aggregation and formatting logic
|
||||
- `auto-ap.ledger` - Running balance cache, account lookups
|
||||
- `auto-ap.datomic.accounts` - Account querying and clientization
|
||||
- `auto-ap.permissions` - Permission checks and middleware
|
||||
- `auto-ap.ssr.grid-page-helper` - Generic data grid behaviors
|
||||
- `auto-ap.ssr.components` - UI components (typeahead, date inputs, buttons)
|
||||
- `auto-ap.ssr.form-cursor` - Form state management
|
||||
- `clj-pdf` - PDF generation
|
||||
- `amazonica.aws.s3` - S3 upload for exports
|
||||
- `datomic.api` - Database queries and transactions
|
||||
- `auto-ap.ssr.ledger.common` — Shared grid page config, query schema, filtering
|
||||
- `auto-ap.ledger.reports` — Report aggregation and formatting logic
|
||||
- `auto-ap.ledger` — Running balance cache, account lookups
|
||||
- `auto-ap.datomic.accounts` — Account querying and clientization
|
||||
- `auto-ap.permissions` — Permission checks and middleware
|
||||
- `auto-ap.ssr.grid-page-helper` — Generic data grid behaviors
|
||||
- `auto-ap.ssr.components` — UI components (typeahead, date inputs, buttons)
|
||||
- `auto-ap.ssr.form-cursor` — Form state management
|
||||
- `clj-pdf` — PDF generation
|
||||
- `amazonica.aws.s3` — S3 upload for exports
|
||||
- `datomic.api` — Database queries and transactions
|
||||
|
||||
Reference in New Issue
Block a user