docs: add comprehensive test behavior documentation for all pages
Add behavior documentation covering all SSR and legacy SPA pages: - Testing strategy and type definitions (unit/integration/UI) - Dashboard, Invoice, Payment, Transaction, Ledger pages - Company/Settings, POS, Admin, Search, Auth pages - Legacy SPA behavior docs (no UI tests until migrated) - Edge cases, test data requirements, and dependencies per subsystem Total: 3,600+ lines of behavior documentation to guide test authorship.
This commit is contained in:
496
docs/testing/behaviors/invoice.md
Normal file
496
docs/testing/behaviors/invoice.md
Normal file
@@ -0,0 +1,496 @@
|
||||
# Invoice Behaviors
|
||||
|
||||
## Overview
|
||||
|
||||
Invoices are the core entity of the Integreat accounts payable system. They represent bills from vendors that clients must pay. The invoice subsystem supports full lifecycle management from creation/import through payment and voiding, with comprehensive filtering, bulk operations, and OCR-based automated entry via Glimpse.
|
||||
|
||||
**User value:**
|
||||
- Track all vendor bills in one place
|
||||
- Pay invoices individually or in bulk via checks, debits, cash, or credit
|
||||
- Import invoices from CSV/PDF files with automatic data extraction
|
||||
- Spread expenses across multiple locations
|
||||
- Manage invoice status (unpaid, paid, voided, scheduled)
|
||||
|
||||
## Routes & Pages
|
||||
|
||||
| Route | Handler | Purpose |
|
||||
|-------|---------|---------|
|
||||
| `GET /invoices` | `::all-page` | List all invoices |
|
||||
| `GET /invoices/unpaid` | `::unpaid-page` | List unpaid invoices |
|
||||
| `GET /invoices/paid` | `::paid-page` | List paid invoices |
|
||||
| `GET /invoices/voided` | `::voided-page` | List voided invoices |
|
||||
| `GET /invoices/table` | `::table` | HTMX table refresh |
|
||||
| `GET /invoices/new` | `::new-wizard` | Create new invoice wizard |
|
||||
| `POST/PUT /invoices/new` | `::new-invoice-submit` | Submit new/edit invoice |
|
||||
| `PUT /invoices/new/navigate` | `::new-wizard-navigate` | Wizard step navigation |
|
||||
| `PUT /invoices/new/due-date` | `::due-date` | Calculate due date from vendor terms |
|
||||
| `PUT /invoices/new/scheduled-payment-date` | `::scheduled-payment-date` | Calculate scheduled payment from vendor autopay |
|
||||
| `PUT /invoices/new/account/prediction` | `::account-prediction` | Show vendor default account suggestion |
|
||||
| `PUT /invoices/new/total` | `::expense-account-total` | Calculate expense account total |
|
||||
| `PUT /invoices/new/balance` | `::expense-account-balance` | Calculate balance vs invoice total |
|
||||
| `GET /invoices/new/account/new` | `::new-wizard-new-account` | Add new expense account row |
|
||||
| `GET /invoices/new/account/location-select` | `::location-select` | Location dropdown for account |
|
||||
| `GET /invoices/pay-button` | `::pay-button` | Render pay button with selected invoice totals |
|
||||
| `GET /invoices/pay` | `::pay-wizard` | Pay selected invoices wizard |
|
||||
| `POST /invoices/pay` | `::pay-submit` | Submit payment |
|
||||
| `POST /invoices/pay/using-credit` | `::pay-using-credit` | Pay using vendor credit balance |
|
||||
| `PUT /invoices/pay/navigate` | `::pay-wizard-navigate` | Pay wizard step navigation |
|
||||
| `GET /invoices/bulk-delete` | `::bulk-delete` | Bulk void confirmation dialog |
|
||||
| `DELETE /invoices/bulk-delete` | `::bulk-delete-confirm` | Execute bulk void |
|
||||
| `GET /invoices/bulk-edit` | `::bulk-edit` | Bulk edit expense accounts wizard |
|
||||
| `PUT /invoices/bulk-edit` | `::bulk-edit-submit` | Submit bulk edit |
|
||||
| `GET /invoices/bulk-edit/account` | `::bulk-edit-new-account` | Add new account row in bulk edit |
|
||||
| `PUT /invoices/bulk-edit/total` | `::bulk-edit-total` | Calculate percentage total |
|
||||
| `PUT /invoices/bulk-edit/balance` | `::bulk-edit-balance` | Calculate percentage balance |
|
||||
| `DELETE /invoices/:id` | `::delete` | Void single invoice |
|
||||
| `PUT /invoices/:id/undo-autopay` | `::undo-autopay` | Undo scheduled autopay |
|
||||
| `PUT /invoices/:id/unvoid` | `::unvoid` | Restore voided invoice |
|
||||
| `PUT /invoices/:id/edit` | `::edit-wizard` | Edit existing invoice |
|
||||
| `GET /invoices/import` | `::import-page` | Import invoices page |
|
||||
| `POST /invoices/import/upload` | `::import-file` | Upload and parse invoice files |
|
||||
| `GET /invoices/import/table` | `::import-table` | Import table refresh |
|
||||
| `DELETE /invoices/import/:id/disapprove` | `::disapprove` | Remove pending imported invoice |
|
||||
| `PUT /invoices/import/:id/approve` | `::approve` | Approve pending imported invoice |
|
||||
| `DELETE /invoices/import/disapprove` | `::bulk-disapprove` | Bulk remove pending imports |
|
||||
| `PUT /invoices/import/approve` | `::bulk-approve` | Bulk approve pending imports |
|
||||
|
||||
## Behaviors by Page
|
||||
|
||||
### Invoice List Page
|
||||
|
||||
#### Unit Tests
|
||||
- `fetch-ids` generates correct Datomic queries for all filter combinations
|
||||
- `fetch-page` returns `[results count outstanding-sum total-sum]` tuple
|
||||
- `sum-outstanding` and `sum-total-amount` calculate aggregates correctly
|
||||
- `selected->ids` resolves "all selected" vs individual selection
|
||||
- `hydrate-results` groups and orders pulled entities by input IDs
|
||||
- `payable-ids` filters to only unpaid, non-scheduled invoices
|
||||
- `can-undo-autopayment` validates invoice state for undo eligibility
|
||||
|
||||
#### Integration Tests
|
||||
- **Happy path:** Load list page with invoices, verify table renders
|
||||
- **Filter by vendor:** Select vendor, table refreshes with filtered results
|
||||
- **Filter by account:** Select account, table refreshes
|
||||
- **Filter by date range:** Apply date range, results filtered
|
||||
- **Filter by amount range:** Set min/max amounts, results filtered
|
||||
- **Filter by invoice number:** Partial match on invoice number
|
||||
- **Filter by check number:** Search by check number
|
||||
- **Exact match:** Navigate from notification to specific invoice via `exact-match-id`
|
||||
- **Sort by each column:** Click column headers (client, vendor, date, due, invoice-number, total, outstanding-balance, location, description-original)
|
||||
- **Pagination:** Navigate pages, change per-page (default 25)
|
||||
- **Selection:** Check individual rows, select all, select all filtered
|
||||
- **Action buttons appear conditionally:** Based on permissions and selection state
|
||||
- **Legacy redirects:** Old routes redirect to new SSR routes
|
||||
|
||||
#### UI Tests (SSR)
|
||||
- Table renders with correct columns: Client, Vendor, Invoice #, Date, Due, Status, Account, Outstanding, Links
|
||||
- Status pills display correctly: Paid (primary), Voided (red), Scheduled (yellow), Unpaid (secondary)
|
||||
- Due date shows relative time: "today", "in X days", "X days ago" with color coding
|
||||
- Outstanding shows partial payment indicator when balance != total
|
||||
- Links dropdown shows payments, transactions, ledger entries, source files
|
||||
- Client column hidden when single client with single location
|
||||
- Row action buttons: Void (unpaid), Edit (unpaid/paid), Unvoid (voided), Undo autopay (eligible)
|
||||
- Pay button tooltip explains why disabled: no selection, multiple clients, mixed debit/credit
|
||||
- Break table grouping by vendor name when sorting by vendor
|
||||
|
||||
### New Invoice Wizard
|
||||
|
||||
#### Unit Tests
|
||||
- `new-form-schema` validates required fields, money amounts, entity IDs
|
||||
- Vendor must have default expense account (`check-vendor-default-account`)
|
||||
- `clientize-vendor` applies client-specific terms, account overrides, autopay settings
|
||||
- `assert-no-conflicting` prevents duplicate invoice numbers per vendor/client
|
||||
- `assert-invoice-amounts-add-up` validates expense accounts sum to total
|
||||
- `maybe-spread-locations` spreads "Shared" location across all client locations
|
||||
- Existing tests in `new_invoice_wizard_test.clj` cover:
|
||||
- Equal spread across 2 locations
|
||||
- Negative amount spreading
|
||||
- Remainder distribution (33.34, 33.33, 33.33)
|
||||
- Negative remainder distribution
|
||||
- Single cent leftover tolerance (`apply-total-delta-to-account`)
|
||||
- `$->cents` and `cents->$` round correctly
|
||||
- `calculate-spread` distributes base amount + remainder
|
||||
|
||||
#### Integration Tests
|
||||
- **Happy path create:**
|
||||
1. Open wizard, select client, vendor, date, invoice number, total
|
||||
2. Due date auto-calculates from vendor terms when client+date+vendor selected
|
||||
3. Scheduled payment auto-calculates from vendor autopay setting
|
||||
4. Save with default account → invoice created with vendor's default account
|
||||
5. Wizard navigates to "Next Steps" with Pay now / Add another / Close options
|
||||
- **Happy path customize accounts:**
|
||||
1. Select "Customize accounts" on basic details
|
||||
2. Add multiple expense account rows
|
||||
3. Select account, location (auto-populated from account or Shared), amount
|
||||
4. Total and balance update dynamically via HTMX
|
||||
5. Location dropdown updates when account changes
|
||||
6. Save validates totals match
|
||||
- **Edit existing invoice:**
|
||||
1. Open edit wizard for unpaid/paid invoice
|
||||
2. Vendor field disabled (cannot change)
|
||||
3. Modify amounts, add/remove accounts
|
||||
4. Save updates row in place
|
||||
|
||||
#### UI Tests (SSR)
|
||||
- Wizard renders as modal with Basic Details → Expense Accounts (optional) → Next Steps
|
||||
- Client typeahead searches companies
|
||||
- Vendor typeahead searches vendors, disabled when editing
|
||||
- Date inputs use normal date format
|
||||
- "Add due / scheduled payment date" link appears when dates not set
|
||||
- Account prediction radio shows vendor default account name
|
||||
- Expense account grid: Account, Location, Amount columns
|
||||
- New account row button adds empty row
|
||||
- Remove row button with Alpine.js transition
|
||||
- Total/Balance rows update on amount change
|
||||
- Validation errors display per field
|
||||
|
||||
### Pay Wizard
|
||||
|
||||
#### Unit Tests
|
||||
- `payment-form-schema` validates payment structure
|
||||
- `does-amount-exceed-outstanding?` catches over/under payments
|
||||
- `can-handwrite?` validates single vendor and positive balance for handwritten checks
|
||||
- `credit-only?` detects when all vendor totals are negative (credit scenario)
|
||||
- `pay-button*` calculates vendor totals and detects credit payment scenarios
|
||||
|
||||
#### Integration Tests
|
||||
- **Happy path - debit:**
|
||||
1. Select unpaid invoices from same client
|
||||
2. Click Pay → Choose Payment Method modal opens
|
||||
3. Select bank account → click Debit
|
||||
4. Confirm "Pay in full" or switch to "Customize payments"
|
||||
5. Submit → payments created, checks printed if applicable
|
||||
- **Happy path - print check:**
|
||||
1. Select check-type bank account
|
||||
2. Choose "Print check"
|
||||
3. Payment processed, PDF URL returned for printing
|
||||
- **Happy path - cash:**
|
||||
1. Select cash-type bank account
|
||||
2. Payment processed immediately
|
||||
- **Happy path - handwrite check:**
|
||||
1. Single vendor, positive balance required
|
||||
2. Enter check number and date
|
||||
3. Payment created with pending status
|
||||
- **Happy path - credit payment:**
|
||||
1. Select invoices where vendor total is 0 (credit + debit balance)
|
||||
2. Pay button shows "Pay invoices using credit"
|
||||
3. Credit invoices offset payment invoices
|
||||
4. Balance payment created
|
||||
- **Validation:**
|
||||
- Cannot pay invoices from multiple clients
|
||||
- Cannot pay with mixed vendor debit/credit totals
|
||||
- Custom payment amounts cannot exceed outstanding balance
|
||||
- Handwritten check requires check number
|
||||
- Locked client dates blocked
|
||||
|
||||
#### UI Tests (SSR)
|
||||
- Pay button shows count and total amount
|
||||
- Warning pill appears when some selected invoices are locked/scheduled
|
||||
- Bank account cards show type-appropriate icons (cash=green, check=blue, credit=purple)
|
||||
- Tooltip on Pay button explains disabled state
|
||||
- Payment method selection buttons: Print check, With cash, Debit, Handwrite check
|
||||
- Payment details step shows invoice grid with vendor, number, total, pay amount
|
||||
- Mode toggle: "Pay in full" vs "Customize payments"
|
||||
- Success modal shows thumbs up, PDF download link for checks, scaling reminder
|
||||
|
||||
### Bulk Edit
|
||||
|
||||
#### Unit Tests
|
||||
- `assert-percentages-add-up` validates percentages sum to 100%
|
||||
- `maybe-code-accounts` distributes expense accounts by percentage
|
||||
- Shared location spreads across all client locations
|
||||
- Rounds cents correctly with remainder handling
|
||||
- Validates account location matches
|
||||
|
||||
#### Integration Tests
|
||||
- **Happy path:**
|
||||
1. Select invoices via checkboxes
|
||||
2. Click "Bulk Edit" → wizard opens
|
||||
3. Add expense account rows with account, location, percentage
|
||||
4. Submit → all selected invoices coded with new expense accounts
|
||||
- **Locked invoices excluded:** Only invoices with date >= client locked-until are processed
|
||||
- **Validation:**
|
||||
- Percentages must sum to 100%
|
||||
- Account location must match account's configured location
|
||||
|
||||
#### UI Tests (SSR)
|
||||
- Wizard shows count of invoices to be edited
|
||||
- Account typeahead with location dropdown
|
||||
- Percentage input (displayed as whole number, stored as decimal)
|
||||
- Total/Balance percentage display
|
||||
- New account row button
|
||||
|
||||
### Bulk Delete/Void
|
||||
|
||||
#### Unit Tests
|
||||
- `void-invoices-internal`:
|
||||
- Voids cash payments linked to selected invoices
|
||||
- Only voids invoices without linked invoice-payments
|
||||
- Only voids invoices with date >= client locked-until
|
||||
- Sets total, outstanding-balance, and expense account amounts to 0
|
||||
|
||||
#### Integration Tests
|
||||
- **Happy path:**
|
||||
1. Select invoices
|
||||
2. Click "Void selected" → confirmation modal
|
||||
3. Confirm → invoices voided, table refreshes with notification
|
||||
- **Admin only:** Bulk delete requires admin permission
|
||||
- **Validation:**
|
||||
- Paid invoices with linked payments require voiding payments first
|
||||
- Locked dates blocked
|
||||
|
||||
#### UI Tests (SSR)
|
||||
- Red alert icon in confirmation modal
|
||||
- Shows count of invoices to void
|
||||
- Modal closes on success with notification
|
||||
|
||||
### Import Page
|
||||
|
||||
#### Unit Tests
|
||||
- `import->invoice` maps parsed data to invoice entity
|
||||
- `validate-invoice` checks required keys and client access
|
||||
- `match-vendor` finds vendor by code or throws with search hint
|
||||
- `admin-only-if-multiple-clients` flags source-url for admin-only when multiple clients
|
||||
- `upload-schema` validates force-client, force-vendor, force-location, force-chatgpt
|
||||
|
||||
#### Integration Tests
|
||||
- **Happy path CSV/PDF import:**
|
||||
1. Upload file(s) via drag-and-drop or file input
|
||||
2. File parsed (CSV direct, PDF via OCR when allowed)
|
||||
3. Invoices created with pending import status
|
||||
4. Results table shows success/failure per file
|
||||
- **Force overrides:**
|
||||
- Force client overrides parsed client
|
||||
- Force vendor overrides parsed vendor
|
||||
- Force location overrides parsed location
|
||||
- Force ChatGPT restricts to GPT-only parsing
|
||||
- **Approve/disapprove:**
|
||||
- Individual approve → status changes to imported
|
||||
- Individual disapprove → invoice deleted
|
||||
- Bulk approve/disapprove with selection
|
||||
- **Validation:**
|
||||
- Missing client, vendor, date, total → error
|
||||
- No client access → error
|
||||
- Vendor not found → error with search hint
|
||||
|
||||
#### UI Tests (SSR)
|
||||
- Upload zone with drag-and-drop styling (blue idle, green hover)
|
||||
- File list shows selected files
|
||||
- Force client/vendor/location typeaheads
|
||||
- "Only use ChatGPT" checkbox
|
||||
- Results table: File, Result, Template, Sample columns
|
||||
- Green/red styling for success/error
|
||||
- Error list shows first 5 errors
|
||||
- Import table shows pending invoices with approve/disapprove buttons
|
||||
- Filters: vendor, date range, check number, invoice number, amount range
|
||||
|
||||
### Glimpse (OCR Import)
|
||||
|
||||
#### Unit Tests
|
||||
- `textract->textract-invoice` extracts fields from AWS Textract response
|
||||
- `stack-rank` sorts field descriptors by confidence
|
||||
- `clean-customer` normalizes customer names for search
|
||||
- `deduplicate` removes duplicate parsed values
|
||||
- `textract-invoice->invoice` converts to invoice with vendor terms and autopay
|
||||
|
||||
#### Integration Tests
|
||||
- **Happy path:**
|
||||
1. Upload PDF to Glimpse page
|
||||
2. File uploaded to S3, Textract job started
|
||||
3. Poll every 5s while IN_PROGRESS
|
||||
4. On SUCCESS, display extracted fields with alternatives
|
||||
5. User selects client, vendor, date, total, invoice number from alternatives
|
||||
6. Save creates invoice and links to textract job
|
||||
- **Field extraction:**
|
||||
- Total: from AMOUNT_DUE or TOTAL fields
|
||||
- Customer: from CUSTOMER_NUMBER or RECEIVER_NAME (with Solr fallback)
|
||||
- Vendor: from VENDOR_NAME with Solr search
|
||||
- Date: from INVOICE_RECEIPT_DATE, ORDER_DATE, DELIVERY_DATE
|
||||
- Invoice number: from INVOICE_RECEIPT_ID or PO_NUMBER
|
||||
|
||||
#### UI Tests (SSR)
|
||||
- Upload form with Dropzone integration (PDF only)
|
||||
- Progress indicator while analyzing
|
||||
- Side-by-side layout: PDF preview iframe + form
|
||||
- Form fields: Client, Location, Vendor, Date, Total, Invoice Number
|
||||
- Alternatives shown as clickable pills below each field
|
||||
- Disabled fields for client and vendor (must select from alternatives)
|
||||
- Success notification with link to view new invoice
|
||||
|
||||
## Cross-Cutting Behaviors
|
||||
|
||||
### Filtering
|
||||
All list pages support these filters (applied via HTMX with debounce):
|
||||
|
||||
- **Vendor:** Typeahead search, filters to specific vendor
|
||||
- **Account:** Typeahead search, filters invoices with that expense account
|
||||
- **Date range:** Start/end date for invoice date (uses `scan-invoices` for performance)
|
||||
- **Due date range:** Start/end due date
|
||||
- **Amount range:** Min/max total amount (inclusive)
|
||||
- **Invoice number:** Partial string match via `.contains`
|
||||
- **Check number:** Text search
|
||||
- **Status:** Route-param based (all, unpaid, paid, voided) or query-param
|
||||
- **Import status:** Filter by pending/imported
|
||||
- **Exact match:** Navigate to specific invoice by ID (bypasses other filters)
|
||||
- **Scheduled payments:** Filter to invoices with scheduled payment date
|
||||
- **Unresolved:** Invoices missing expense accounts or with unassigned accounts
|
||||
- **Location:** Filter by expense account location
|
||||
|
||||
### Sorting
|
||||
Click column headers to sort. Supported sort keys:
|
||||
- client (by client name)
|
||||
- vendor (by vendor name)
|
||||
- description-original
|
||||
- location (by expense account location)
|
||||
- date
|
||||
- due (nulls last with default 2050-01-01)
|
||||
- invoice-number
|
||||
- total
|
||||
- outstanding-balance
|
||||
|
||||
Default sort: descending by scan-invoices default. Toggle asc/desc.
|
||||
|
||||
### Pagination
|
||||
- Default 25 per page
|
||||
- Configurable per-page
|
||||
- Offset-based pagination
|
||||
- Import table supports up to 250 for "all selected" operations
|
||||
|
||||
### Selection
|
||||
- Individual row checkboxes
|
||||
- "Select all" checkbox selects all visible
|
||||
- "Select all filtered" selects all matching current filters (up to 250)
|
||||
- Selection state maintained via Alpine.js
|
||||
- Pay/Void/Edit/Bulk-Edit buttons use selection
|
||||
|
||||
### Permissions
|
||||
All invoice operations check permissions via `can?`:
|
||||
|
||||
| Activity | Required Permission |
|
||||
|----------|-------------------|
|
||||
| Create invoice | `{:subject :invoice :activity :create}` |
|
||||
| Edit invoice | `{:subject :invoice :activity :edit}` |
|
||||
| Delete/Void invoice | `{:subject :invoice :activity :delete}` |
|
||||
| Pay invoice | `{:subject :invoice :activity :pay}` |
|
||||
| Bulk delete | `{:subject :invoice :activity :bulk-delete}` |
|
||||
| Bulk edit | `{:subject :invoice :activity :bulk-edit}` |
|
||||
| Import | `{:subject :invoice :activity :import}` |
|
||||
|
||||
Additional checks:
|
||||
- `assert-can-see-client` - user must have access to invoice's client
|
||||
- `assert-not-locked` - invoice date must be >= client's locked-until date
|
||||
- Admin-only for bulk delete confirmation
|
||||
|
||||
## Edge Cases
|
||||
|
||||
### Voiding Paid Invoices
|
||||
- Single void: Blocked if invoice has linked non-voided payments. User must void payments first.
|
||||
- Bulk void: Automatically voids linked cash payments before voiding invoices.
|
||||
|
||||
### Unvoiding
|
||||
- Restores invoice to original status, total, outstanding balance, and expense accounts
|
||||
- Uses Datomic history to reconstruct previous state
|
||||
- Requires edit permission and client access
|
||||
|
||||
### Undo Autopay
|
||||
- Only available for paid invoices with scheduled payment and no linked payments
|
||||
- Resets status to unpaid, outstanding to total, clears scheduled payment
|
||||
- Locked dates blocked
|
||||
|
||||
### Paying with Credit
|
||||
- Triggered when selected invoices for single vendor have net 0 balance (credit invoices + payment invoices)
|
||||
- Credit invoices (negative balance) offset payment invoices
|
||||
- Creates balance-credit payment
|
||||
|
||||
### Location Spreading
|
||||
- "Shared" location in expense accounts spreads across all client locations
|
||||
- Base amount = total / location count (integer division in cents)
|
||||
- Remainder distributed 1 cent at a time to first N locations
|
||||
- Total delta applied to first account to handle rounding
|
||||
|
||||
### Negative Amounts
|
||||
- Supported throughout (credit memos, overpayments)
|
||||
- Spread calculations handle negative totals
|
||||
- Pay button validates all-credits-or-debits (can't mix positive and negative vendor totals)
|
||||
|
||||
### Zero Balances
|
||||
- Invoices with 0 outstanding balance show as paid
|
||||
- Zero-balance selections excluded from payment
|
||||
|
||||
### Duplicate Invoice Numbers
|
||||
- `assert-no-conflicting` prevents same invoice number for same vendor/client
|
||||
- Edit wizard preserves existing invoice number unless changed
|
||||
|
||||
### Missing Vendor/Account
|
||||
- New invoice wizard requires vendor with default expense account
|
||||
- Import validation fails if vendor not found
|
||||
- Unresolved filter finds invoices missing expense accounts
|
||||
|
||||
### Locked Clients
|
||||
- Client has `locked-until` date
|
||||
- Invoices with date < locked-until cannot be: edited, paid, voided, imported, approved
|
||||
- Bulk operations filter out locked invoices
|
||||
- Pay wizard shows warning when some selections are locked
|
||||
|
||||
### Large Invoice Counts
|
||||
- `scan-invoices` Datomic query used for efficient date/client filtering
|
||||
- Pagination limits to 25 per page by default
|
||||
- "All selected" capped at 250 for bulk operations
|
||||
- Outstanding/total sums calculated from all-ids, not just page
|
||||
|
||||
## Test Data Requirements
|
||||
|
||||
### Entities Needed
|
||||
- **Clients:** Multiple clients with different locations, some with locked-until dates
|
||||
- **Vendors:** With/without default accounts, terms, autopay settings, account overrides, terms overrides
|
||||
- **Accounts:** Expense accounts with/without invoice allowance, different locations
|
||||
- **Bank Accounts:** Check, cash, credit types, visible/hidden
|
||||
- **Invoices:** Various statuses, dates, amounts, with/without payments, with/without scheduled payments
|
||||
|
||||
### Specific Test Scenarios
|
||||
- Client with multiple locations (for spreading)
|
||||
- Client with single location (client column hidden)
|
||||
- Vendor with terms (auto-due date) and autopay (auto-scheduled payment)
|
||||
- Invoice with partial payment (outstanding < total)
|
||||
- Invoice with linked payment (void blocked)
|
||||
- Voided invoice with history (unvoid test)
|
||||
- Paid invoice with scheduled payment, no linked payment (undo autopay)
|
||||
- Negative balance invoice (credit)
|
||||
- Imported pending invoice (approve/disapprove)
|
||||
- Locked client with pre/post-lock invoices
|
||||
|
||||
### File Upload Test Data
|
||||
- Valid CSV with proper headers
|
||||
- PDF with embedded text
|
||||
- PDF requiring OCR
|
||||
- File with multiple clients (admin-only source-url)
|
||||
- File with missing required fields
|
||||
- File with unmatchable vendor
|
||||
|
||||
## Dependencies
|
||||
|
||||
- **Datomic:** Primary data store, history for unvoid
|
||||
- **AWS S3:** File storage for imports and Glimpse PDFs
|
||||
- **AWS Textract:** OCR for Glimpse PDF processing
|
||||
- **Solr:** Search for vendor/client matching in Glimpse
|
||||
- **HTMX/Alpine.js:** Frontend interactivity
|
||||
- **Bidi:** Route generation
|
||||
- **Malli:** Schema validation for forms and query params
|
||||
- **clj-time:** Date parsing and manipulation
|
||||
|
||||
## Existing Tests to Preserve
|
||||
|
||||
### Unit Tests
|
||||
- `test/clj/auto_ap/ssr/invoice/new_invoice_wizard_test.clj`
|
||||
- `maybe-spread-locations-test` - 6 test cases for location spreading logic
|
||||
|
||||
### Integration Tests
|
||||
- `test/clj/auto_ap/integration/routes/invoice_test.clj`
|
||||
- `import-uploaded-invoices` - import single, duplicate prevention, location override, coded invoice
|
||||
- `test/clj/auto_ap/integration/graphql/invoices.clj`
|
||||
- `test-add-invoice` - add with valid/invalid accounts, vendor special accounts
|
||||
- `edit-invoice` - edit fields, vendor change blocked, conflicting invoice numbers
|
||||
- `edit-expense-accounts` - modify expense accounts
|
||||
- `bulk-change-invoices` - bulk coding with percentages
|
||||
- `void-invoices` - bulk void and unvoid
|
||||
- `void-invoice` - single void and unvoid
|
||||
Reference in New Issue
Block a user