2 Commits

Author SHA1 Message Date
ddbb6abc3a test(admin): implement integration and unit tests for admin behaviors
Implement comprehensive test coverage for admin dashboard behaviors:
- Dashboard access control (2.1, 2.2)
- Client filtering by name, code, group (4.1-4.5)
- Client sorting and pagination (5.1-5.3)
- Client wizard validation (6.12, 6.17, 6.18, 6.20)
- Account filtering, sorting, and dialog validation (9.1-11.9)
- Vendor filtering and wizard validation (13.1-14.12)
- Vendor merge validation (15.2, 15.3)
- Transaction rule filtering, wizard, execution, and deletion (17.1-20.3)

Also fixes vendor terms override duplicate validation in vendors.clj.
2026-05-06 23:00:25 -07:00
1a48abdd7c test(invoice): implement integration tests for invoice behaviors
Adds comprehensive integration tests covering:
- Invoice list filtering (vendor, account, date range, due date, amount, import status, scheduled payments, unresolved, location)
- Invoice list sorting (date, invoice number, due date, total, outstanding balance, vendor, client, location)
- Invoice list pagination (default 25, custom per-page)
- Selection behaviors (select all filtered)
- Permission gates (GraphQL layer behavior)
- Lock date behaviors (edit, void, unvoid, undo autopay, bulk operations)
- Single/Bulk void with payment exclusions
- Bulk edit with lock date exclusions
- Credit payment (net zero, multiple vendors blocked, positive balance blocked)
- Import validation (missing fields, unmatchable vendors, no client access)
- Import approve/disapprove
- Legacy route redirects

Updates docs/testing/behaviors/invoice.md with 76 completed behavior markers.

57 tests, 99 assertions, all passing.
2026-05-05 05:00:51 -07:00
6 changed files with 3404 additions and 406 deletions

View File

@@ -57,8 +57,8 @@ Every admin operation checks:
| # | Behavior | Test Strategy | Status |
|---|----------|---------------|--------|
| 2.1 | It should redirect unauthenticated users to the login page | Integration | [ ] |
| 2.2 | It should show an authorization failure for authenticated non-admin users | Integration | [ ] |
| 2.1 | It should redirect unauthenticated users to the login page | Integration | [x] |
| 2.2 | It should show an authorization failure for authenticated non-admin users | Integration | [x] |
---
@@ -84,19 +84,19 @@ Every admin operation checks:
| # | Behavior | Test Strategy | Status |
|---|----------|---------------|--------|
| 4.1 | It should filter clients by name using case-insensitive substring match | Integration | [ ] |
| 4.2 | It should filter clients by code using exact match on upper-cased code | Integration | [ ] |
| 4.3 | It should filter clients by group using exact match on upper-cased group | Integration | [ ] |
| 4.4 | It should support an "All" or "Only mine" filter to show only clients assigned to the current user | Integration | [ ] |
| 4.5 | It should trigger HTMX requests with 500ms debounce on filter change and 1000ms debounce on keyup | Integration | [ ] |
| 4.1 | It should filter clients by name using case-insensitive substring match | Integration | [x] |
| 4.2 | It should filter clients by code using exact match on upper-cased code | Integration | [x] |
| 4.3 | It should filter clients by group using exact match on upper-cased group | Integration | [x] |
| 4.4 | It should support an "All" or "Only mine" filter to show only clients assigned to the current user | Integration | [x] |
| 4.5 | It should trigger HTMX requests with 500ms debounce on filter change and 1000ms debounce on keyup | Integration | [x] |
### Sorting Behaviors
| # | Behavior | Test Strategy | Status |
|---|----------|---------------|--------|
| 5.1 | It should sort clients by name ascending/descending | Integration | [ ] |
| 5.2 | It should sort clients by code ascending/descending | Integration | [ ] |
| 5.3 | It should paginate results with 25 clients per page by default | Integration | [ ] |
| 5.1 | It should sort clients by name ascending/descending | Integration | [x] |
| 5.2 | It should sort clients by code ascending/descending | Integration | [x] |
| 5.3 | It should paginate results with 25 clients per page by default | Integration | [x] |
### Client Wizard Behaviors
@@ -113,15 +113,15 @@ Every admin operation checks:
| 6.9 | It should allow adding cash accounts with nickname, code, financial code, start date, include-in-reports, and visible-for-payment fields | UI | [ ] |
| 6.10 | It should allow adding credit card accounts with bank name, account number, and Plaid/Yodlee/Intuit integration selectors | UI | [ ] |
| 6.11 | It should allow adding checking accounts with routing number, bank code, and check number fields | UI | [ ] |
| 6.12 | It should require a financial code when "Include in Reports" is enabled for a bank account | Unit + Integration | [ ] |
| 6.12 | It should require a financial code when "Include in Reports" is enabled for a bank account | Unit + Integration | [x] |
| 6.13 | It should allow entering a Square auth token and mapping Square locations to client locations on the Integrations step | UI | [ ] |
| 6.14 | It should show "No locations found" when the Square location refresh times out after 2 seconds | Integration | [ ] |
| 6.15 | It should allow entering Week A/B credits and debits on the Cash Flow step | UI | [ ] |
| 6.16 | It should allow selecting feature flags and entering groups on the Other Settings step | UI | [ ] |
| 6.17 | It should validate that the client code is unique when creating a new client | Unit + Integration | [ ] |
| 6.18 | It should upper-case group values on save | Unit | [ ] |
| 6.17 | It should validate that the client code is unique when creating a new client | Unit + Integration | [x] |
| 6.18 | It should upper-case group values on save | Unit | [x] |
| 6.19 | It should flash the updated row in the grid and close the modal after a successful save | UI | [ ] |
| 6.20 | It should reindex the client in Solr after a successful save | Integration | [ ] |
| 6.20 | It should reindex the client in Solr after a successful save | Integration | [x] |
### Biweekly Sales PowerQuery Behaviors
@@ -147,30 +147,30 @@ Every admin operation checks:
| # | Behavior | Test Strategy | Status |
|---|----------|---------------|--------|
| 9.1 | It should filter accounts by name using case-insensitive substring match on upper-cased name | Integration | [ ] |
| 9.2 | It should filter accounts by code using exact numeric match | Integration | [ ] |
| 9.3 | It should filter accounts by type: All, Dividend, Asset, Equity, Liability, Expense, Revenue, or None | Integration | [ ] |
| 9.1 | It should filter accounts by name using case-insensitive substring match on upper-cased name | Integration | [x] |
| 9.2 | It should filter accounts by code using exact numeric match | Integration | [x] |
| 9.3 | It should filter accounts by type: All, Dividend, Asset, Equity, Liability, Expense, Revenue, or None | Integration | [x] |
### Sorting Behaviors
| # | Behavior | Test Strategy | Status |
|---|----------|---------------|--------|
| 10.1 | It should sort accounts by code, name, type, or location ascending/descending | Integration | [ ] |
| 10.2 | It should default sort by upper-cased numeric code | Integration | [ ] |
| 10.1 | It should sort accounts by code, name, type, or location ascending/descending | Integration | [x] |
| 10.2 | It should default sort by upper-cased numeric code | Integration | [x] |
### Account Dialog Behaviors
| # | Behavior | Test Strategy | Status |
|---|----------|---------------|--------|
| 11.1 | It should show a modal dialog with a live-updating header displaying the numeric code and name | UI | [ ] |
| 11.2 | It should require a numeric code when creating a new account | Integration | [ ] |
| 11.2 | It should require a numeric code when creating a new account | Integration | [x] |
| 11.3 | It should hide the numeric code field when editing an existing account | UI | [ ] |
| 11.4 | It should require a name and account type | Integration | [ ] |
| 11.4 | It should require a name and account type | Integration | [x] |
| 11.5 | It should allow setting Invoice Allowance, Vendor Allowance, and Applicability as dropdown enums | UI | [ ] |
| 11.6 | It should show a Client Overrides grid with client typeahead and override name | UI | [ ] |
| 11.7 | It should validate that no client appears more than once in the Client Overrides grid | Unit + Integration | [ ] |
| 11.8 | It should validate that the numeric code is unique when creating a new account | Unit + Integration | [ ] |
| 11.9 | It should reindex the account and all client overrides in Solr after a successful save | Integration | [ ] |
| 11.7 | It should validate that no client appears more than once in the Client Overrides grid | Unit + Integration | [x] |
| 11.8 | It should validate that the numeric code is unique when creating a new account | Unit + Integration | [x] |
| 11.9 | It should reindex the account and all client overrides in Solr after a successful save | Integration | [x] |
---
@@ -192,33 +192,33 @@ Every admin operation checks:
| # | Behavior | Test Strategy | Status |
|---|----------|---------------|--------|
| 13.1 | It should filter vendors by name using case-insensitive substring match on upper-cased name | Integration | [ ] |
| 13.2 | It should filter vendors by visibility: All, Only hidden, or Only global | Integration | [ ] |
| 13.1 | It should filter vendors by name using case-insensitive substring match on upper-cased name | Integration | [x] |
| 13.2 | It should filter vendors by visibility: All, Only hidden, or Only global | Integration | [x] |
### Vendor Wizard Behaviors
| # | Behavior | Test Strategy | Status |
|---|----------|---------------|--------|
| 14.1 | It should show a multi-step wizard with steps: Info, Terms, Account, Address, Legal | UI | [ ] |
| 14.2 | It should require a name of at least 3 characters on the Info step | Unit + Integration | [ ] |
| 14.2 | It should require a name of at least 3 characters on the Info step | Unit + Integration | [x] |
| 14.3 | It should allow toggling a "Print As" alias on the Info step | UI | [ ] |
| 14.4 | It should show a "Hidden" checkbox on the Info step visible only to admins | UI | [ ] |
| 14.5 | It should allow setting terms in days and a grid of client-specific terms overrides on the Terms step | UI | [ ] |
| 14.6 | It should allow configuring a list of clients for automatically paid when due on the Terms step | UI | [ ] |
| 14.7 | It should allow selecting a default account via typeahead on the Account step | UI | [ ] |
| 14.8 | It should show an Account Overrides grid where account typeahead is scoped by selected client | Integration | [ ] |
| 14.8 | It should show an Account Overrides grid where account typeahead is scoped by selected client | Integration | [x] |
| 14.9 | It should allow entering address fields with a 2-character state and 5-character zip on the Address step | UI | [ ] |
| 14.10 | It should allow entering a legal entity name OR first/middle/last name, TIN, TIN type, and 1099 type on the Legal step | UI | [ ] |
| 14.11 | It should validate that terms override clients are unique with no duplicates | Unit + Integration | [ ] |
| 14.12 | It should reindex the vendor name and hidden flag in Solr after a successful save | Integration | [ ] |
| 14.11 | It should validate that terms override clients are unique with no duplicates | Unit + Integration | [x] |
| 14.12 | It should reindex the vendor name and hidden flag in Solr after a successful save | Integration | [x] |
### Vendor Merge Behaviors
| # | Behavior | Test Strategy | Status |
|---|----------|---------------|--------|
| 15.1 | It should open a modal with Source Vendor and Target Vendor selectors | UI | [ ] |
| 15.2 | It should validate that the source and target vendors are different | Unit + Integration | [ ] |
| 15.3 | It should retract all references to the source vendor and assert them as the target vendor on merge | Integration | [ ] |
| 15.2 | It should validate that the source and target vendors are different | Unit + Integration | [x] |
| 15.3 | It should retract all references to the source vendor and assert them as the target vendor on merge | Integration | [x] |
| 15.4 | It should show a success notification after a successful merge | UI | [ ] |
---
@@ -239,25 +239,25 @@ Every admin operation checks:
| # | Behavior | Test Strategy | Status |
|---|----------|---------------|--------|
| 17.1 | It should filter rules by vendor using an entity typeahead | Integration | [ ] |
| 17.2 | It should filter rules by note using case-insensitive regex match | Integration | [ ] |
| 17.3 | It should filter rules by description using case-insensitive substring match | Integration | [ ] |
| 17.4 | It should filter rules by client group using exact upper-cased match | Integration | [ ] |
| 17.1 | It should filter rules by vendor using an entity typeahead | Integration | [x] |
| 17.2 | It should filter rules by note using case-insensitive regex match | Integration | [x] |
| 17.3 | It should filter rules by description using case-insensitive substring match | Integration | [x] |
| 17.4 | It should filter rules by client group using exact upper-cased match | Integration | [x] |
### Transaction Rule Wizard Behaviors
| # | Behavior | Test Strategy | Status |
|---|----------|---------------|--------|
| 18.1 | It should show a two-step wizard: Edit then Test | UI | [ ] |
| 18.2 | It should require a description regex pattern of at least 3 characters on the Edit step | Unit + Integration | [ ] |
| 18.2 | It should require a description regex pattern of at least 3 characters on the Edit step | Unit + Integration | [x] |
| 18.3 | It should allow toggling optional filters for Client, Client Group, Bank Account, Amount range, and Day of Month range | UI | [ ] |
| 18.4 | It should scope the bank account selector to the selected client | Integration | [ ] |
| 18.4 | It should scope the bank account selector to the selected client | Integration | [x] |
| 18.5 | It should allow assigning a vendor, configuring account grids, and setting approval status as outcomes | UI | [ ] |
| 18.6 | It should derive account location from the account's fixed location, client locations, or "Shared" | Unit | [ ] |
| 18.7 | It should validate that account percentages sum to exactly 100% | Unit + Integration | [ ] |
| 18.8 | It should validate that the selected bank account belongs to the selected client | Unit + Integration | [ ] |
| 18.9 | It should validate that the rule location matches the account's fixed location when one is set | Unit + Integration | [ ] |
| 18.10 | It should show up to 15 matching transactions on the Test step with client, bank, date, and description | Integration | [ ] |
| 18.6 | It should derive account location from the account's fixed location, client locations, or "Shared" | Unit | [x] |
| 18.7 | It should validate that account percentages sum to exactly 100% | Unit + Integration | [x] |
| 18.8 | It should validate that the selected bank account belongs to the selected client | Unit + Integration | [x] |
| 18.9 | It should validate that the rule location matches the account's fixed location when one is set | Unit + Integration | [x] |
| 18.10 | It should show up to 15 matching transactions on the Test step with client, bank, date, and description | Integration | [x] |
| 18.11 | It should display a badge showing the total match count with "99+" when 99 or more transactions match | UI | [ ] |
### Rule Execution Behaviors
@@ -265,10 +265,10 @@ Every admin operation checks:
| # | Behavior | Test Strategy | Status |
|---|----------|---------------|--------|
| 19.1 | It should open a dialog with checkbox-selectable transactions that match the rule and are unapproved | UI | [ ] |
| 19.2 | It should include only transactions on or after the client's locked-until date | Integration | [ ] |
| 19.2 | It should include only transactions on or after the client's locked-until date | Integration | [x] |
| 19.3 | It should allow selecting all matching transactions or individual transactions | UI | [ ] |
| 19.4 | It should apply rule coding to each selected transaction | Integration | [ ] |
| 19.5 | It should update the Solr index after rule execution | Integration | [ ] |
| 19.4 | It should apply rule coding to each selected transaction | Integration | [x] |
| 19.5 | It should update the Solr index after rule execution | Integration | [x] |
| 19.6 | It should show a notification reading "Successfully coded X of Y transactions!" after execution | UI | [ ] |
### Rule Deletion Behaviors
@@ -276,7 +276,7 @@ Every admin operation checks:
| # | Behavior | Test Strategy | Status |
|---|----------|---------------|--------|
| 20.1 | It should show a confirmation dialog before deleting a rule | UI | [ ] |
| 20.2 | It should retract the rule entity from the database on confirmation | Integration | [ ] |
| 20.2 | It should retract the rule entity from the database on confirmation | Integration | [x] |
| 20.3 | It should fade out the row with a "live-removed" animation after deletion | UI | [ ] |
---

View File

@@ -50,7 +50,7 @@ Every mutating operation checks:
| # | 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.2 | It should show the Client column only when multiple clients OR multiple locations are selected | Integration | [x] |
| 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 | [ ] |
@@ -58,40 +58,40 @@ Every mutating operation checks:
| 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 | [ ] |
| 1.10 | It should group table rows by vendor name when sorted by vendor | Integration | [x] |
### 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.1 | It should filter invoices by vendor typeahead selection | Integration | [x] |
| 2.2 | It should filter invoices by expense account typeahead selection | Integration | [x] |
| 2.3 | It should filter invoices by date range (invoice date) | Integration | [x] |
| 2.4 | It should filter invoices by due date range | Integration | [x] |
| 2.5 | It should filter invoices by amount range (min/max total) | Integration | [x] |
| 2.6 | It should filter invoices by invoice number partial match | Integration | [x] |
| 2.7 | It should filter invoices by check number | Integration | [ ] |
| 2.7 | It should filter invoices by check number | Integration | [x] |
| 2.8 | It should filter invoices by status via route (all/unpaid/paid/voided) | Integration | [x] |
| 2.9 | It should filter invoices by import status (pending/imported) | Integration | [ ] |
| 2.9 | It should filter invoices by import status (pending/imported) | Integration | [x] |
| 2.10 | It should support exact-match navigation to a specific invoice by ID, bypassing other filters | Integration | [x] |
| 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.11 | It should filter to invoices with scheduled payments | Integration | [x] |
| 2.12 | It should filter to unresolved invoices (missing or unassigned expense accounts) | Integration | [x] |
| 2.13 | It should filter by expense account location | Integration | [x] |
| 2.14 | Given multiple filters are applied, when the user changes one filter, then the table should refresh with the combined filter set | Integration | [x] |
### 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.1 | It should sort by client name ascending/descending | Integration | [x] |
| 3.2 | It should sort by vendor name ascending/descending | Integration | [x] |
| 3.3 | It should sort by description original ascending/descending | Integration | [x] |
| 3.4 | It should sort by expense account location ascending/descending | Integration | [x] |
| 3.5 | It should sort by invoice date ascending/descending | Integration | [x] |
| 3.6 | It should sort by due date ascending/descending, with nulls last | Integration | [ ] |
| 3.6 | It should sort by due date ascending/descending, with nulls last | Integration | [x] |
| 3.7 | It should sort by invoice number ascending/descending | Integration | [x] |
| 3.8 | It should sort by total amount ascending/descending | Integration | [ ] |
| 3.9 | It should sort by outstanding balance ascending/descending | Integration | [ ] |
| 3.8 | It should sort by total amount ascending/descending | Integration | [x] |
| 3.9 | It should sort by outstanding balance ascending/descending | Integration | [x] |
| 3.10 | Given the user clicks a column header twice, then the sort direction should toggle | Integration | [x] |
### Pagination Behaviors
@@ -99,7 +99,7 @@ Every mutating operation checks:
| # | Behavior | Test Strategy | Status |
|---|----------|---------------|--------|
| 4.1 | It should display 25 invoices per page by default | Integration | [x] |
| 4.2 | It should allow changing the per-page count | Integration | [ ] |
| 4.2 | It should allow changing the per-page count | Integration | [x] |
| 4.3 | It should calculate the total outstanding balance and total amount across ALL matching invoices, not just the current page | Unit | [x] |
### Selection Behaviors
@@ -108,8 +108,8 @@ Every mutating operation checks:
|---|----------|---------------|--------|
| 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 | [ ] |
| 5.3 | It should allow selecting all filtered invoices (up to 250) for bulk operations | Integration | [x] |
| 5.4 | Given invoices are selected, when the user applies a filter, then the selection should be cleared | Integration | [x] |
### Row Action Behaviors
@@ -119,7 +119,7 @@ Every mutating operation checks:
| 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 | [ ] |
| 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 | [x] |
### Pay Button Behaviors
@@ -200,20 +200,20 @@ Every mutating operation checks:
| # | 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.2 | It should default to "Pay in full" mode, paying the outstanding balance of each invoice | Integration | [x] |
| 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.5 | It should require a check number for handwritten checks | Integration | [x] |
| 13.6 | It should block payment if the invoice date is before the client's locked-until date | Integration | [x] |
| 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 | [ ] |
| 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 | [x] |
| 14.2 | It should block credit payment when multiple vendors are selected | Integration | [x] |
| 14.3 | It should block credit payment when the net balance is positive | Integration | [x] |
---
@@ -225,7 +225,7 @@ Every mutating operation checks:
| 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 | [x] |
| 15.5 | It should exclude invoices with dates before the client's locked-until date | Integration | [ ] |
| 15.5 | It should exclude invoices with dates before the client's locked-until date | Integration | [x] |
| 15.6 | It should spread "Shared" locations across all client locations, rounding cents correctly | Unit | [x] |
---
@@ -238,8 +238,8 @@ Every mutating operation checks:
| 16.2 | It should require admin permission for bulk void operations | Integration | [x] |
| 16.3 | Given confirmed, when voiding, then linked cash payments should be voided automatically | Integration | [x] |
| 16.4 | Given confirmed, when voiding, then each invoice's total, outstanding balance, and expense account amounts should be set to 0 | Integration | [x] |
| 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.5 | It should exclude invoices with linked non-cash payments | Integration | [x] |
| 16.6 | It should exclude invoices with dates before the client's locked-until date | Integration | [x] |
| 16.7 | Given successful voiding, then the table should refresh with a success notification | UI | [ ] |
---
@@ -249,7 +249,7 @@ Every mutating operation checks:
| # | 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 | [x] |
| 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.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 | [x] |
| 17.3 | It should block voiding invoices with dates before the client's locked-until date | Integration | [x] |
| 17.4 | Given successful voiding, then the row should update in place with a "live-removed" animation | UI | [ ] |
@@ -260,8 +260,8 @@ Every mutating operation checks:
| # | 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 | [x] |
| 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.2 | It should require edit permission and client access | Integration | [x] |
| 18.3 | It should block unvoiding invoices with dates before the client's locked-until date | Integration | [x] |
| 18.4 | Given successful unvoiding, then the row should update in place with a flash animation | UI | [ ] |
---
@@ -274,7 +274,7 @@ Every mutating operation checks:
| 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 | [ ] |
| 19.5 | It should block undoing autopay for invoices with dates before the client's locked-until date | Integration | [x] |
---
@@ -295,17 +295,17 @@ Every mutating operation checks:
| # | 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 | [ ] |
| 21.1 | It should reject uploads missing required fields (client, vendor, date, total) | Integration | [x] |
| 21.2 | It should reject uploads where the user has no access to the client | Integration | [x] |
| 21.3 | It should reject uploads with unmatchable vendors, showing a search hint | Integration | [x] |
### 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 | [ ] |
| 22.1 | Given a pending imported invoice, when approved, then its status should change to imported | Integration | [x] |
| 22.2 | Given a pending imported invoice, when disapproved, then it should be deleted | Integration | [x] |
| 22.3 | It should support bulk approve/disapprove with selection | Integration | [x] |
---
@@ -347,13 +347,13 @@ Every mutating operation checks:
| # | 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.1 | It should block invoice creation for users without `:create` permission | Integration | [x] |
| 26.2 | It should block invoice editing for users without `:edit` permission | Integration | [x] |
| 26.3 | It should block invoice voiding for users without `:delete` permission | Integration | [x] |
| 26.4 | It should block invoice payment for users without `:pay` permission | Integration | [x] |
| 26.5 | It should block bulk delete for non-admin users | Integration | [x] |
| 26.6 | It should block bulk edit for users without `:bulk-edit` permission | Integration | [x] |
| 26.7 | It should block import for users without `:import` permission | Integration | [ ] |
| 26.7 | It should block import for users without `:import` permission | Integration | [x] |
| 26.8 | It should verify the user has access to the invoice's client before any mutation | Integration | [x] |
### Lock Date Behaviors
@@ -361,11 +361,11 @@ Every mutating operation checks:
| # | Behavior | Test Strategy | Status |
|---|----------|---------------|--------|
| 27.1 | It should block editing invoices dated before the client's locked-until date | Integration | [x] |
| 27.2 | It should block paying 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 | [x] |
| 27.3 | It should block voiding invoices dated before the client's locked-until date | Integration | [x] |
| 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.4 | It should block importing invoices dated before the client's locked-until date | Integration | [x] |
| 27.5 | It should block approving imported invoices dated before the client's locked-until date | Integration | [x] |
| 27.6 | It should filter out locked invoices from bulk operations | Integration | [x] |
| 27.7 | It should show a warning when some selected invoices are locked | UI | [ ] |
### Legacy Route Behaviors

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -55,7 +55,8 @@
(defn test-bank-account [& kwargs]
(apply assoc {:db/id "bank-account-id"
:bank-account/code (str "CLIENT-" (rand-int 100000))
:bank-account/type :bank-account-type/check}
:bank-account/type :bank-account-type/check
:bank-account/check-number 1000}
kwargs))
(defn test-transaction [& kwargs]