Add comprehensive unit tests for pure invoice business logic: - assert-invoice-amounts-add-up (behaviors 9.4, 11.4) - does-amount-exceed-outstanding? (behavior 13.4) - assert-percentages-add-up (behavior 15.3) - stack-rank and deduplicate (behaviors 24.1, 24.4, 24.5) - clientize-vendor (behavior 8.4) - location-select* (behavior 9.3) - maybe-code-accounts with Shared location spreading (behavior 15.6) - can-undo-autopayment (behaviors 19.2-19.4) - due date / scheduled payment calculations (behaviors 8.2, 8.3) - can-handwrite? and credit-only? (pay wizard behaviors) - due date display logic (behavior 1.7) Also fixes: - user.clj: add missing datomic.api alias (d) used in sample functions - new_invoice_wizard_test.clj: fix sut8 -> sut9 typo Marks completed unit-test behaviors with [x] in invoice.md
404 lines
22 KiB
Markdown
404 lines
22 KiB
Markdown
# Invoice Behaviors
|
|
|
|
## Overview
|
|
|
|
Invoices are the core entity of Integreat. This document catalogs every observable behavior with its recommended test strategy and implementation status.
|
|
|
|
**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:
|
|
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
|
|
|
|
**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: Wizard Behaviors
|
|
Wizards are multi-step forms with HTMX-driven navigation:
|
|
1. Each step is a GET that renders a form fragment
|
|
2. Form submissions are POST/PUT with validation
|
|
3. Navigation between steps updates the wizard state
|
|
4. Final submit creates/updates the entity
|
|
|
|
**Test implications:** Unit test validation logic and state transitions. Integration test the full wizard flow once. UI test only the happy path.
|
|
|
|
### Pattern: Permission Gates
|
|
Every mutating operation checks:
|
|
1. `assert-can-see-client` — user has access to the client
|
|
2. `assert-not-locked` — invoice date >= client locked-until
|
|
3. `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.
|
|
|
|
---
|
|
|
|
## Invoice List Page
|
|
|
|
### Display Behaviors
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 1.1 | It should display a table with columns: Client, Vendor, Invoice #, Date, Due, Status, Account, Outstanding, Links | UI | [ ] |
|
|
| 1.2 | It should show the Client column only when multiple clients OR multiple locations are selected | Integration | [ ] |
|
|
| 1.3 | It should show "Paid" status as a primary-colored pill | UI | [ ] |
|
|
| 1.4 | It should show "Voided" status as a red pill | UI | [ ] |
|
|
| 1.5 | It should show "Scheduled" status as a yellow pill when a scheduled payment exists | UI | [ ] |
|
|
| 1.6 | It should show "Unpaid" status as a secondary-colored pill | UI | [ ] |
|
|
| 1.7 | It should display due dates relative to today: "today", "in X days", or "X days ago" with appropriate color coding | Unit + UI | [x] |
|
|
| 1.8 | It should show a partial payment indicator "of $X.XX" when outstanding balance differs from total | UI | [ ] |
|
|
| 1.9 | It should display a links dropdown showing payments, transactions, ledger entries, and source files for each invoice | UI | [ ] |
|
|
| 1.10 | It should group table rows by vendor name when sorted by vendor | Integration | [ ] |
|
|
|
|
### Filtering Behaviors
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 2.1 | It should filter invoices by vendor typeahead selection | Integration | [ ] |
|
|
| 2.2 | It should filter invoices by expense account typeahead selection | Integration | [ ] |
|
|
| 2.3 | It should filter invoices by date range (invoice date) | Integration | [ ] |
|
|
| 2.4 | It should filter invoices by due date range | Integration | [ ] |
|
|
| 2.5 | It should filter invoices by amount range (min/max total) | Integration | [ ] |
|
|
| 2.6 | It should filter invoices by invoice number partial match | Integration | [ ] |
|
|
| 2.7 | It should filter invoices by check number | Integration | [ ] |
|
|
| 2.8 | It should filter invoices by status via route (all/unpaid/paid/voided) | Integration | [ ] |
|
|
| 2.9 | It should filter invoices by import status (pending/imported) | Integration | [ ] |
|
|
| 2.10 | It should support exact-match navigation to a specific invoice by ID, bypassing other filters | Integration | [ ] |
|
|
| 2.11 | It should filter to invoices with scheduled payments | Integration | [ ] |
|
|
| 2.12 | It should filter to unresolved invoices (missing or unassigned expense accounts) | Integration | [ ] |
|
|
| 2.13 | It should filter by expense account location | Integration | [ ] |
|
|
| 2.14 | 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 name ascending/descending | Integration | [ ] |
|
|
| 3.2 | It should sort by vendor name ascending/descending | Integration | [ ] |
|
|
| 3.3 | It should sort by description original ascending/descending | Integration | [ ] |
|
|
| 3.4 | It should sort by expense account location ascending/descending | Integration | [ ] |
|
|
| 3.5 | It should sort by invoice date ascending/descending | Integration | [ ] |
|
|
| 3.6 | It should sort by due date ascending/descending, with nulls last | Integration | [ ] |
|
|
| 3.7 | It should sort by invoice number ascending/descending | Integration | [ ] |
|
|
| 3.8 | It should sort by total amount ascending/descending | Integration | [ ] |
|
|
| 3.9 | It should sort by outstanding balance ascending/descending | Integration | [ ] |
|
|
| 3.10 | Given the user clicks a column header twice, then the sort direction should toggle | Integration | [ ] |
|
|
|
|
### Pagination Behaviors
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 4.1 | It should display 25 invoices per page by default | Integration | [ ] |
|
|
| 4.2 | It should allow changing the per-page count | Integration | [ ] |
|
|
| 4.3 | It should calculate the total outstanding balance and total amount across ALL matching invoices, not just the current page | Unit | [ ] |
|
|
|
|
### Selection Behaviors
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 5.1 | It should allow selecting individual invoices via checkboxes | UI | [ ] |
|
|
| 5.2 | It should allow selecting all visible invoices via a header checkbox | UI | [ ] |
|
|
| 5.3 | It should allow selecting all filtered invoices (up to 250) for bulk operations | Integration | [ ] |
|
|
| 5.4 | Given invoices are selected, when the user applies a filter, then the selection should be cleared | Integration | [ ] |
|
|
|
|
### Row Action Behaviors
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 6.1 | It should show a void button for unpaid invoices when the user has delete permission | UI | [ ] |
|
|
| 6.2 | It should show an edit button for unpaid and paid invoices when the user has edit permission | UI | [ ] |
|
|
| 6.3 | It should show an unvoid button for voided invoices when the user has edit permission | UI | [ ] |
|
|
| 6.4 | It should show an undo-autopay button for paid invoices with scheduled payments and no linked payments, when the user has edit permission | UI | [ ] |
|
|
| 6.5 | Given a paid invoice with linked non-voided payments, when the user attempts to void it, then it should be blocked with a message to void payments first | Integration | [ ] |
|
|
|
|
### Pay Button Behaviors
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 7.1 | It should display the pay button disabled when no invoices are selected | UI | [ ] |
|
|
| 7.2 | It should display the pay button disabled when invoices from multiple clients are selected | UI | [ ] |
|
|
| 7.3 | It should display the pay button disabled when selected invoices have mixed positive and negative vendor totals | UI | [ ] |
|
|
| 7.4 | It should display "Pay N invoices ($X.XX)" when valid invoices are selected | UI | [ ] |
|
|
| 7.5 | It should display "Pay invoices using credit" when selected invoices for a single vendor have a net zero balance | UI | [ ] |
|
|
| 7.6 | It should show a tooltip explaining why the pay button is disabled | UI | [ ] |
|
|
|
|
---
|
|
|
|
## New Invoice Wizard
|
|
|
|
### Basic Details Step
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 8.1 | It should require client, vendor, date, invoice number, and total | Integration | [ ] |
|
|
| 8.2 | It should auto-calculate the due date from vendor terms when client, date, and vendor are selected | Unit | [x] |
|
|
| 8.3 | It should auto-calculate the scheduled payment date from vendor autopay settings | Unit | [x] |
|
|
| 8.4 | It should suggest the vendor's default expense account | Unit | [x] |
|
|
| 8.5 | It should prevent duplicate invoice numbers for the same vendor and client | Unit + Integration | [ ] |
|
|
| 8.6 | It should allow editing all fields when creating a new invoice | UI | [ ] |
|
|
|
|
### Expense Accounts Step
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 9.1 | It should allow adding multiple expense account rows | UI | [ ] |
|
|
| 9.2 | It should allow selecting an account, location, and amount per row | UI | [ ] |
|
|
| 9.3 | It should auto-populate the location from the account's configured location, or default to "Shared" | Unit | [x] |
|
|
| 9.4 | It should validate that expense account amounts sum to the invoice total | Unit + Integration | [x] |
|
|
| 9.5 | Given a "Shared" location, when the invoice is saved, then the amount should be spread equally across all client locations | Unit | [ ] |
|
|
| 9.6 | Given a "Shared" location with an odd total, when spread across N locations, then the remainder should be distributed 1 cent at a time to the first locations | Unit | [x] |
|
|
| 9.7 | Given a negative total, when spread across locations, then negative amounts should be distributed correctly | Unit | [x] |
|
|
| 9.8 | It should allow removing individual account rows | UI | [ ] |
|
|
| 9.9 | It should update the total and balance dynamically when amounts change | UI | [ ] |
|
|
|
|
### Next Steps
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 10.1 | Given a new invoice is saved successfully, then the wizard should show "Next Steps" with Pay now, Add another, and Close options | UI | [ ] |
|
|
| 10.2 | Given the user clicks "Pay now", then the pay wizard should open for the newly created invoice | UI | [ ] |
|
|
|
|
---
|
|
|
|
## Edit Invoice
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 11.1 | It should allow editing unpaid and paid invoices | Integration | [ ] |
|
|
| 11.2 | It should disable the vendor field when editing | UI | [ ] |
|
|
| 11.3 | It should allow modifying expense account amounts, adding/removing accounts | Integration | [ ] |
|
|
| 11.4 | It should validate that modified amounts still sum to the total | Unit + Integration | [x] |
|
|
| 11.5 | Given the user saves changes, then the invoice row should update in place without a full page reload | UI | [ ] |
|
|
| 11.6 | It should block editing invoices with dates before the client's locked-until date | Integration | [ ] |
|
|
|
|
---
|
|
|
|
## Pay Wizard
|
|
|
|
### Payment Method Selection
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 12.1 | It should show bank account cards with type-appropriate icons (cash=green, check=blue, credit=purple) | UI | [ ] |
|
|
| 12.2 | It should allow selecting "Print check" for check-type bank accounts | UI | [ ] |
|
|
| 12.3 | It should allow selecting "With cash" for cash-type bank accounts | UI | [ ] |
|
|
| 12.4 | It should allow selecting "Debit" for any bank account | UI | [ ] |
|
|
| 12.5 | It should allow selecting "Handwrite check" when a single vendor is selected with positive balance | UI | [ ] |
|
|
|
|
### Payment Details
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 13.1 | It should display a grid of selected invoices with vendor, number, total, and pay amount | UI | [ ] |
|
|
| 13.2 | It should default to "Pay in full" mode, paying the outstanding balance of each invoice | Integration | [ ] |
|
|
| 13.3 | It should allow switching to "Customize payments" mode to set individual pay amounts | UI | [ ] |
|
|
| 13.4 | It should validate that custom payment amounts do not exceed the outstanding balance | Unit + Integration | [x] |
|
|
| 13.5 | It should require a check number for handwritten checks | Integration | [ ] |
|
|
| 13.6 | It should block payment if the invoice date is before the client's locked-until date | Integration | [ ] |
|
|
| 13.7 | Given the user submits a check payment, when successful, then a PDF download link should be provided | Integration | [ ] |
|
|
|
|
### Credit Payment
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 14.1 | Given selected invoices for a single vendor with a net zero balance, when the user clicks pay, then a credit payment should be created offsetting credit invoices against payment invoices | Integration | [ ] |
|
|
| 14.2 | It should block credit payment when multiple vendors are selected | Integration | [ ] |
|
|
| 14.3 | It should block credit payment when the net balance is positive | Integration | [ ] |
|
|
|
|
---
|
|
|
|
## Bulk Edit
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 15.1 | It should allow selecting multiple invoices and opening the bulk edit wizard | UI | [ ] |
|
|
| 15.2 | It should allow adding expense account rows with account, location, and percentage | UI | [ ] |
|
|
| 15.3 | It should validate that percentages sum to 100% | Unit + Integration | [x] |
|
|
| 15.4 | Given valid percentages, when submitted, then all selected invoices should be coded with the new expense accounts | Integration | [ ] |
|
|
| 15.5 | It should exclude invoices with dates before the client's locked-until date | Integration | [ ] |
|
|
| 15.6 | It should spread "Shared" locations across all client locations, rounding cents correctly | Unit | [x] |
|
|
|
|
---
|
|
|
|
## Bulk Void
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 16.1 | It should show a confirmation modal with the count of invoices to void | UI | [ ] |
|
|
| 16.2 | It should require admin permission for bulk void operations | Integration | [ ] |
|
|
| 16.3 | Given confirmed, when voiding, then linked cash payments should be voided automatically | Integration | [ ] |
|
|
| 16.4 | Given confirmed, when voiding, then each invoice's total, outstanding balance, and expense account amounts should be set to 0 | Integration | [ ] |
|
|
| 16.5 | It should exclude invoices with linked non-cash payments | Integration | [ ] |
|
|
| 16.6 | It should exclude invoices with dates before the client's locked-until date | Integration | [ ] |
|
|
| 16.7 | Given successful voiding, then the table should refresh with a success notification | UI | [ ] |
|
|
|
|
---
|
|
|
|
## Single Void
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 17.1 | Given an unpaid invoice with no linked payments, when the user voids it, then the invoice status should change to voided with zero amounts | Integration | [ ] |
|
|
| 17.2 | Given a paid invoice with linked payments, when the user attempts to void it, then it should be blocked with an error message | Integration | [ ] |
|
|
| 17.3 | It should block voiding invoices with dates before the client's locked-until date | Integration | [ ] |
|
|
| 17.4 | Given successful voiding, then the row should update in place with a "live-removed" animation | UI | [ ] |
|
|
|
|
---
|
|
|
|
## Unvoid
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 18.1 | Given a voided invoice, when the user unvoids it, then it should restore the original status, total, outstanding balance, and expense accounts from Datomic history | Integration | [ ] |
|
|
| 18.2 | It should require edit permission and client access | Integration | [ ] |
|
|
| 18.3 | It should block unvoiding invoices with dates before the client's locked-until date | Integration | [ ] |
|
|
| 18.4 | Given successful unvoiding, then the row should update in place with a flash animation | UI | [ ] |
|
|
|
|
---
|
|
|
|
## Undo Autopay
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 19.1 | Given a paid invoice with a scheduled payment and no linked payments, when the user undoes autopay, then the status should reset to unpaid and outstanding should equal total | Integration | [ ] |
|
|
| 19.2 | It should block undoing autopay for invoices without scheduled payments | Unit + Integration | [x] |
|
|
| 19.3 | It should block undoing autopay for invoices with linked payments | Unit + Integration | [x] |
|
|
| 19.4 | It should block undoing autopay for invoices that are not paid | Unit + Integration | [x] |
|
|
| 19.5 | It should block undoing autopay for invoices with dates before the client's locked-until date | Integration | [ ] |
|
|
|
|
---
|
|
|
|
## Import Page
|
|
|
|
### Upload Behaviors
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 20.1 | It should allow uploading CSV and PDF files via drag-and-drop | UI | [ ] |
|
|
| 20.2 | It should parse CSV files directly | Integration | [ ] |
|
|
| 20.3 | It should send PDF files to AWS Textract for OCR parsing when enabled | Integration | [ ] |
|
|
| 20.4 | It should create invoices with pending import status | Integration | [ ] |
|
|
| 20.5 | It should display results with success/failure per file | UI | [ ] |
|
|
| 20.6 | It should allow force-overriding client, vendor, location, and ChatGPT parsing mode | UI | [ ] |
|
|
|
|
### Validation Behaviors
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 21.1 | It should reject uploads missing required fields (client, vendor, date, total) | Integration | [ ] |
|
|
| 21.2 | It should reject uploads where the user has no access to the client | Integration | [ ] |
|
|
| 21.3 | It should reject uploads with unmatchable vendors, showing a search hint | Integration | [ ] |
|
|
|
|
### Approve/Disapprove Behaviors
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 22.1 | Given a pending imported invoice, when approved, then its status should change to imported | Integration | [ ] |
|
|
| 22.2 | Given a pending imported invoice, when disapproved, then it should be deleted | Integration | [ ] |
|
|
| 22.3 | It should support bulk approve/disapprove with selection | Integration | [ ] |
|
|
|
|
---
|
|
|
|
## Glimpse (OCR Import)
|
|
|
|
### Upload Behaviors
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 23.1 | It should allow uploading PDF files | UI | [ ] |
|
|
| 23.2 | It should upload the file to S3 and start an AWS Textract job | Integration | [ ] |
|
|
| 23.3 | It should poll every 5 seconds while the Textract job is in progress | Integration | [ ] |
|
|
| 23.4 | Given a successful Textract job, then it should display extracted fields with confidence scores | UI | [ ] |
|
|
|
|
### Field Extraction Behaviors
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 24.1 | It should extract total from AMOUNT_DUE or TOTAL fields | Unit | [x] |
|
|
| 24.2 | It should extract customer from CUSTOMER_NUMBER or RECEIVER_NAME, falling back to Solr search | Unit + Integration | [ ] |
|
|
| 24.3 | It should extract vendor from VENDOR_NAME, falling back to Solr search | Unit + Integration | [ ] |
|
|
| 24.4 | It should extract date from INVOICE_RECEIPT_DATE, ORDER_DATE, or DELIVERY_DATE | Unit | [x] |
|
|
| 24.5 | It should extract invoice number from INVOICE_RECEIPT_ID or PO_NUMBER | Unit | [x] |
|
|
|
|
### Form Behaviors
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 25.1 | It should show a side-by-side layout with PDF preview and form | UI | [ ] |
|
|
| 25.2 | It should display alternative values as clickable pills for each field | UI | [ ] |
|
|
| 25.3 | It should require selecting client and vendor from alternatives (fields disabled until selected) | UI | [ ] |
|
|
| 25.4 | Given the user saves, then it should create an invoice linked to the textract job | Integration | [ ] |
|
|
|
|
---
|
|
|
|
## Cross-Cutting Behaviors
|
|
|
|
### Permission Behaviors
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 26.1 | It should block invoice creation for users without `:create` permission | Integration | [ ] |
|
|
| 26.2 | It should block invoice editing for users without `:edit` permission | Integration | [ ] |
|
|
| 26.3 | It should block invoice voiding for users without `:delete` permission | Integration | [ ] |
|
|
| 26.4 | It should block invoice payment for users without `:pay` permission | Integration | [ ] |
|
|
| 26.5 | It should block bulk delete for non-admin users | Integration | [ ] |
|
|
| 26.6 | It should block bulk edit for users without `:bulk-edit` permission | Integration | [ ] |
|
|
| 26.7 | It should block import for users without `:import` permission | Integration | [ ] |
|
|
| 26.8 | It should verify the user has access to the invoice's client before any mutation | Integration | [ ] |
|
|
|
|
### Lock Date Behaviors
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 27.1 | It should block editing invoices dated before the client's locked-until date | Integration | [ ] |
|
|
| 27.2 | It should block paying invoices dated before the client's locked-until date | Integration | [ ] |
|
|
| 27.3 | It should block voiding invoices dated before the client's locked-until date | Integration | [ ] |
|
|
| 27.4 | It should block importing invoices dated before the client's locked-until date | Integration | [ ] |
|
|
| 27.5 | It should block approving imported invoices dated before the client's locked-until date | Integration | [ ] |
|
|
| 27.6 | It should filter out locked invoices from bulk operations | Integration | [ ] |
|
|
| 27.7 | It should show a warning when some selected invoices are locked | UI | [ ] |
|
|
|
|
### Legacy Route Behaviors
|
|
|
|
| # | Behavior | Test Strategy | Status |
|
|
|---|----------|---------------|--------|
|
|
| 28.1 | It should redirect old SPA routes (`/invoices`, `/invoices/unpaid`, etc.) to the new SSR routes | Integration | [ ] |
|
|
|
|
---
|
|
|
|
## Test Data Requirements
|
|
|
|
| Entity | Requirements |
|
|
|--------|-------------|
|
|
| **Clients** | Multiple clients with different locations; some with locked-until dates |
|
|
| **Vendors** | With/without default accounts; with/without terms and autopay settings |
|
|
| **Accounts** | Expense accounts with/without invoice allowance; different locations |
|
|
| **Bank Accounts** | Check, cash, and credit types |
|
|
| **Invoices** | Various statuses (unpaid, paid, voided, scheduled), dates, amounts |
|
|
| **Payments** | Linked to invoices; cash and check types |
|
|
| **Files** | Valid CSV, PDF with text, PDF requiring OCR |
|
|
|
|
## Existing Tests to Preserve
|
|
|
|
- `test/clj/auto_ap/ssr/invoice/new_invoice_wizard_test.clj` — Location spreading logic
|
|
- `test/clj/auto_ap/integration/routes/invoice_test.clj` — Import routes
|
|
- `test/clj/auto_ap/integration/graphql/invoices.clj` — GraphQL invoice operations
|
|
|
|
## Dependencies
|
|
|
|
- Datomic (primary store, history for unvoid)
|
|
- AWS S3 (file storage)
|
|
- AWS Textract (OCR)
|
|
- Solr (search for Glimpse matching)
|
|
- HTMX/Alpine.js (frontend interactivity)
|