# Company Behaviors ## Overview The Company section provides company-level settings and reporting for Integreat users. It is implemented as SSR pages using HTMX and is accessed via the left navigation sidebar under "My Company". All pages require authentication and enforce client-level access controls. Most pages react to client selection changes by refreshing their content via HTMX. **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: Permission Gates Every mutating operation checks: 1. `assert-can-see-client` — user has access to the client 2. `can?` — user has the specific permission for the activity 3. Admin role checks for destructive operations **Test implications:** Integration test each gate independently. UI tests only verify the happy path with a permitted user. ### Pattern: HTMX Refresh on Client Switch All company pages listen for `clientSelected from:body` event and refresh `#app-contents` with a 300ms swap animation. **Test implications:** Integration test the event handling and route params. UI test only one page to verify the swap animation. --- ## Company Profile ### Display Behaviors | # | Behavior | Test Strategy | Status | |---|----------|---------------|--------| | 1.1 | It should display a "Please select a company" placeholder card when no client is selected | UI | [ ] | | 1.2 | It should display the company name as a heading when a client is selected | UI | [ ] | | 1.3 | It should display the company address (street, city, state, zip) when address data exists | UI | [ ] | | 1.4 | It should omit missing address fields without showing error placeholders | UI | [ ] | | 1.5 | It should show a "Download vendor list" button | UI | [ ] | | 1.6 | It should download a CSV/Excel export when the download button is clicked | Integration | [ ] | ### Signature Behaviors | # | Behavior | Test Strategy | Status | |---|----------|---------------|--------| | 2.1 | It should show the signature section only when the user has signature edit permission | Integration | [ ] | | 2.2 | It should display the saved signature image when one exists | UI | [ ] | | 2.3 | It should show a "New signature" button that enables drawing mode on a canvas | UI | [ ] | | 2.4 | It should show a "Clear" button that clears the canvas while in drawing mode | UI | [ ] | | 2.5 | It should show an "Accept" button that submits the drawn signature | UI | [ ] | | 2.6 | It should reject invalid signature image data with a validation error | Unit + Integration | [ ] | | 2.7 | It should provide a drag-and-drop zone for uploading JPEG signature files | UI | [ ] | | 2.8 | It should change the drop zone background color on hover | UI | [ ] | | 2.9 | It should refresh the signature section with the uploaded image on successful upload | Integration | [ ] | --- ## 1099 Reports ### Display Behaviors | # | Behavior | Test Strategy | Status | |---|----------|---------------|--------| | 3.1 | It should display vendors who received $600 or more in check payments during the current tax year | Integration | [ ] | | 3.2 | It should show grid columns: Client, Vendor Name, TIN, Expense Account, Address, Paid | UI | [ ] | | 3.3 | It should display the vendor's legal entity name as a subtitle under the vendor name | UI | [ ] | | 3.4 | It should show a 1099 type pill badge when a 1099 type is set | UI | [ ] | | 3.5 | It should display the TIN with a TIN type pill (EIN or SSN) | UI | [ ] | | 3.6 | It should show "No address" placeholder when the vendor has no address | UI | [ ] | | 3.7 | It should display the total paid amount as a pill badge rounded to the nearest dollar | UI | [ ] | | 3.8 | It should show an edit icon button on each row | UI | [ ] | | 3.9 | It should show vendors shared across multiple clients in each client's context | Integration | [ ] | | 3.10 | It should show an empty grid when no vendors received $600+ in checks during the tax year | UI | [ ] | ### Filtering & Sorting Behaviors | # | Behavior | Test Strategy | Status | |---|----------|---------------|--------| | 4.1 | It should support standard grid query params (sort, pagination, search) | Integration | [ ] | | 4.2 | It should default sort by client code then amount | Integration | [ ] | ### Edit Behaviors | # | Behavior | Test Strategy | Status | |---|----------|---------------|--------| | 5.1 | It should open a vendor edit dialog in a modal when the edit icon is clicked | UI | [ ] | | 5.2 | It should display address fields (Street 1, Street 2, City, State, ZIP) in the dialog | UI | [ ] | | 5.3 | It should validate the ZIP code as 5 digits or empty | Unit + Integration | [ ] | | 5.4 | It should allow entering either a legal entity name or first/middle/last name | UI | [ ] | | 5.5 | It should allow entering a TIN and selecting TIN type (EIN or SSN) | UI | [ ] | | 5.6 | It should allow selecting a 1099 type from a dropdown | UI | [ ] | | 5.7 | It should close the modal and refresh the row with a flash highlight on successful save | Integration | [ ] | | 5.8 | It should null the address if all address fields are empty and no existing address | Integration | [ ] | --- ## Expense Reports ### Chart Behaviors | # | Behavior | Test Strategy | Status | |---|----------|---------------|--------| | 6.1 | It should display a bar chart of expenses grouped by top 20 expense accounts over the last 8 weeks | UI | [ ] | | 6.2 | It should show week ranges (Monday-Sunday) formatted as dates on the X-axis | UI | [ ] | | 6.3 | It should provide a vendor typeahead to filter expenses to a specific vendor | Integration | [ ] | | 6.4 | It should provide an expense account typeahead to filter to a specific account | Integration | [ ] | | 6.5 | It should refresh the chart when filters change | Integration | [ ] | | 6.6 | It should default to last 65 days of data but display last 8 weeks | Integration | [ ] | ### Invoice Totals Behaviors | # | Behavior | Test Strategy | Status | |---|----------|---------------|--------| | 7.1 | It should display a grid of total invoice amounts per vendor per company | UI | [ ] | | 7.2 | It should provide start and end date range filters | UI | [ ] | | 7.3 | It should default the date range to the last 30 days | Integration | [ ] | | 7.4 | It should show the vendor name in a sticky left column | UI | [ ] | | 7.5 | It should show "-" for zero amounts | UI | [ ] | | 7.6 | It should push filter changes to browser history | Integration | [ ] | --- ## Reconciliation Reports ### Access Behaviors | # | Behavior | Test Strategy | Status | |---|----------|---------------|--------| | 8.1 | It should show the reconciliation navigation link only when the user has reconciliation report permission | Integration | [ ] | | 8.2 | It should require start and end dates to be submitted via a "Run" button | UI | [ ] | | 8.3 | It should show a "Please choose a time range to run the report" message when no dates are selected | UI | [ ] | ### Display Behaviors | # | Behavior | Test Strategy | Status | |---|----------|---------------|--------| | 8.4 | It should display a grid with columns: Bank Account, Source Count, Synced Count, Approved, Unapproved, Requires Feedback, Missing | UI | [ ] | | 8.5 | It should highlight rows with green background when external count equals synced count | UI | [ ] | | 8.6 | It should highlight rows with red background when counts mismatch | UI | [ ] | | 8.7 | It should display a missing transactions count with a tooltip button | UI | [ ] | | 8.8 | It should show a popup table of missing transaction dates and amounts when the tooltip is clicked | UI | [ ] | | 8.9 | It should hide the missing transactions tooltip when the count is zero | UI | [ ] | --- ## Plaid Bank Linking ### Account Grid Behaviors | # | Behavior | Test Strategy | Status | |---|----------|---------------|--------| | 9.1 | It should display a grid of Plaid-linked accounts with columns: Plaid Item, Integreat Status, Plaid Bank Status, Accounts | UI | [ ] | | 9.2 | It should show a red pill with error message tooltip when any linked bank account has failed or unauthorized status | UI | [ ] | | 9.3 | It should show a green "Success" pill when all accounts are healthy | UI | [ ] | | 9.4 | It should display linked accounts with name, masked number, last synced date, and identicon | UI | [ ] | | 9.5 | It should support sorting by external ID and Plaid bank status | Integration | [ ] | | 9.6 | It should show an empty grid when no bank accounts are linked | UI | [ ] | ### Link Behaviors | # | Behavior | Test Strategy | Status | |---|----------|---------------|--------| | 10.1 | It should show a "Link account" button when a client is selected | UI | [ ] | | 10.2 | It should hide the link button when no client is selected | UI | [ ] | | 10.3 | It should open a Plaid Link modal when the link button is clicked | UI | [ ] | | 10.4 | It should create the Plaid item and accounts in the system after successful linking | Integration | [ ] | | 10.5 | It should redirect back to the Plaid page after successful account linking | Integration | [ ] | ### Re-authenticate Behaviors | # | Behavior | Test Strategy | Status | |---|----------|---------------|--------| | 11.1 | It should show a "Reauthenticate" button on each row | UI | [ ] | | 11.2 | It should open Plaid Link in update mode when reauthenticate is clicked | UI | [ ] | | 11.3 | It should refresh the row after successful reauthentication | Integration | [ ] | --- ## Yodlee Bank Linking ### Account Grid Behaviors | # | Behavior | Test Strategy | Status | |---|----------|---------------|--------| | 12.1 | It should display a grid of Yodlee provider accounts with columns: Client, Provider Account, Status, Detailed Status, Last Updated, Accounts | UI | [ ] | | 12.2 | It should hide the Client column when the user has only one client | UI | [ ] | | 12.3 | It should show a green pill for success status and a yellow pill for other statuses | UI | [ ] | | 12.4 | It should display linked accounts with name and number | UI | [ ] | | 12.5 | It should support sorting by status, client, provider account, and last updated | Integration | [ ] | | 12.6 | It should show an empty grid when no bank accounts are linked | UI | [ ] | ### Link Behaviors | # | Behavior | Test Strategy | Status | |---|----------|---------------|--------| | 13.1 | It should show a "Link new account" button | UI | [ ] | | 13.2 | It should disable the link button and show helper text when no client is selected | UI | [ ] | | 13.3 | It should open a Yodlee Fastlink modal when the link button is clicked | UI | [ ] | | 13.4 | It should display an error notification and close the modal after 3 seconds when Yodlee returns an error | Integration | [ ] | ### Re-authenticate Behaviors | # | Behavior | Test Strategy | Status | |---|----------|---------------|--------| | 14.1 | It should show a "Reauthenticate" button per row | UI | [ ] | | 14.2 | It should open Fastlink in edit mode when reauthenticate is clicked | UI | [ ] | | 14.3 | It should refresh the row after successful reauthentication | Integration | [ ] | ### Admin Behaviors | # | Behavior | Test Strategy | Status | |---|----------|---------------|--------| | 15.1 | It should show a refresh button on each row for admin users | Integration | [ ] | | 15.2 | It should trigger a Yodlee account refresh when the refresh button is clicked | Integration | [ ] | | 15.3 | It should refresh the row after successful Yodlee refresh | Integration | [ ] | --- ## Generated Reports List ### Display Behaviors | # | Behavior | Test Strategy | Status | |---|----------|---------------|--------| | 16.1 | It should display a grid of previously generated reports with columns: Name, Created by, Created | UI | [ ] | | 16.2 | It should show the creator name as a pill badge | UI | [ ] | | 16.3 | It should show an empty grid when no reports have been generated | UI | [ ] | ### Row Action Behaviors | # | Behavior | Test Strategy | Status | |---|----------|---------------|--------| | 17.1 | It should provide a download link to the report file on each row | UI | [ ] | | 17.2 | It should show a delete button on each row for admin users | Integration | [ ] | | 17.3 | It should delete the report and its file when the delete button is clicked | Integration | [ ] | ### Filtering & Sorting Behaviors | # | Behavior | Test Strategy | Status | |---|----------|---------------|--------| | 18.1 | It should support filtering by date range and client | Integration | [ ] | | 18.2 | It should support sorting by client, created date, creator, and name | Integration | [ ] | --- ## Cross-Cutting Behaviors ### Client Switching Behaviors | # | Behavior | Test Strategy | Status | |---|----------|---------------|--------| | 19.1 | It should refresh page content with a 300ms swap animation when the user switches clients | Integration | [ ] | | 19.2 | It should show appropriate placeholder states when no client is selected on pages that require one | UI | [ ] | | 19.3 | It should operate 1099 and reports grids across all visible clients when no single client is selected | Integration | [ ] | ### Permission Behaviors | # | Behavior | Test Strategy | Status | |---|----------|---------------|--------| | 20.1 | It should block access to company pages for unauthenticated users | Integration | [ ] | | 20.2 | It should block access to company pages for users without client access | Integration | [ ] | | 20.3 | It should hide the signature section from users without signature edit permission | Integration | [ ] | | 20.4 | It should hide the reconciliation report navigation link from users without reconciliation report permission | Integration | [ ] | | 20.5 | It should hide the delete report button from non-admin users | Integration | [ ] | | 20.6 | It should hide the Yodlee refresh button from non-admin users | Integration | [ ] | ### Bank Account Search Behaviors | # | Behavior | Test Strategy | Status | |---|----------|---------------|--------| | 21.1 | It should provide a bank account typeahead for searching accounts belonging to a specific client | Integration | [ ] | | 21.2 | It should show "Please select a client" message when no client is selected in the bank account typeahead | UI | [ ] | --- ## Test Data Requirements | Entity | Requirements | |--------|-------------| | **Clients** | Multiple clients with different codes, names, and addresses; one with complete address, one with no address; one with existing signature file, one without | | **Vendors** | With 1099 data (legal entity name, TIN, TIN type, 1099 type, address); with and without addresses; who received $600+ in check payments in 2025; who received less than $600; shared across multiple clients | | **Payments** | Check payments dated within 2025 for 1099 testing; payments of different types (check, ACH) — only checks count toward 1099; payments to vendors across multiple clients | | **Invoices** | Non-voided invoices with expense account allocations for expense report testing; with different vendors and expense accounts; dated across multiple weeks for 8-week breakdown | | **Bank Accounts** | Plaid-linked accounts with various statuses (success, error, unauthorized); Yodlee-linked accounts with various statuses | | **Reports** | At least one generated report with name, creator, created date, and file URL; reports belonging to different clients | | **Users** | Admin user (full access); user with signature edit permission; user with reconciliation report permission; user with single client access; user with multiple client access; read-only user (should not see company nav) | ## Existing Tests to Preserve - No existing company-specific behavior tests were identified at the time of writing. - Any future company behavior tests should be added under `test/clj/auto_ap/company/` or similar. ## Dependencies - Datomic (primary store for all entities and queries) - Amazonica S3 (signature image storage and report file storage) - Plaid API (bank account linking) - Yodlee API (bank account linking) - Intuit/QuickBooks API (reconciliation report data) - Solr (client name search) - HTMX (server-rendered interactions) - Alpine.js (signature canvas state, drag-and-drop, modal state, chart initialization) - Chart.js (expense breakdown bar chart) - SignaturePad library (canvas signature drawing) - Plaid Link SDK (Plaid account linking) - Yodlee Fastlink SDK (Yodlee account linking) - Jdenticon (account identicons in Plaid grid)