Ledger Behaviors
Overview
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.
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
Testing Patterns
Pattern: Grid Page Behaviors
Most list pages in Integreat follow the same pattern:
- Fetch IDs via Datomic query with filters
- Hydrate results via
pull-many
- Render table with sortable columns
- Support selection (individual / all / all-filtered)
- Action buttons appear conditionally based on permissions and selection state
Test implications: Validate the query generation, not the rendering. UI tests only need to verify one filter and one sort work end-to-end.
Pattern: Modal Form Behaviors
Modal forms are HTMX-driven dialogs:
- Opened via GET request that renders a form fragment
- Form submissions are POST/PUT with validation
- On success, the modal closes and the table updates in place
- On validation failure, the modal shows error messages
Test implications: Unit test validation logic. Integration test the full modal flow once. UI test only the happy path.
Pattern: Report Behaviors
Financial reports follow a consistent pattern:
- Form with client multi-select, date/period selectors, and toggles
- Run button triggers HTMX request to generate report
- Report data is computed from account snapshots and running balances
- Export button generates PDF and returns a download modal
Test implications: Unit test calculation logic. Integration test report generation with various filter combinations. UI test only one report end-to-end.
Pattern: Permission Gates
Every mutating operation checks:
assert-can-see-client — user has access to the client
assert-not-locked — entry date >= client locked-until
can? — user has the specific permission for the activity
Test implications: Integration test each gate independently. UI tests only verify the happy path with a permitted user.
Ledger Entries List
Display Behaviors
| # |
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 |
[ ] |
Filtering Behaviors
| # |
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 |
[ ] |
Sorting Behaviors
| # |
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 |
[ ] |
| # |
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 |
[ ] |
Row Action Behaviors
| # |
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 |
[ ] |
CSV Export Behaviors
| # |
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 |
[ ] |
New Journal Entry
Modal Form Behaviors
| # |
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 |
[ ] |
Line Item Behaviors
| # |
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 |
[ ] |
Validation Behaviors
| # |
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 |
[ ] |
Save Behaviors
| # |
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 |
[ ] |
External Import
Clipboard Paste Behaviors
| # |
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 |
[ ] |
Parse Validation Behaviors
| # |
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 |
[ ] |
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 Behaviors
| # |
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 |
[ ] |
Export Behaviors
| # |
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 |
[ ] |
Filtering and Sorting Behaviors
| # |
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 |
[ ] |
Permission Behaviors
| # |
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 |
[ ] |
Empty State Behaviors
| # |
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 |
[ ] |
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
| 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 |
Existing Tests to Preserve
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