# Quote-to-Approval E2E Scenario Test Plan

skip: true

**Source Document:** `quote_approval.pdf` — "How to create a Quote and submit it for approval in Salesforce"
**Reference Issues:** #37, #39, #40, #41, #42, #43, #44, #45
**Test Environment:** NexusCRM (Backend mode) — local deployment or CloudFront
**Credentials:** admin@test.com / L9jPkSaG5pdDRX7WPL3V!
**Date:** 2026-03-27

---

## Pre-conditions

| ID | Check | Expected | How to verify |
|----|-------|----------|---------------|
| PRE-01 | Login in Backend mode | Login screen shows "Backend" tab selected, login succeeds | Navigate to /login, select Backend, enter credentials, click Sign In |
| PRE-02 | Connection mode badge | Top-right badge shows "NexusCRM" (blue), NOT "Salesforce" (amber) | Visual inspection of nav bar after login |
| PRE-03 | Connection mode in storage | `nexus_connection_mode` === `"backend"` | Browser console: `localStorage.getItem('nexus_connection_mode')` |
| PRE-04 | Backend health | Backend API is reachable | `curl http://localhost:8082/health` returns `{"status":"ok"}` |
| PRE-05 | Sidebar navigation | All expected objects visible: Campaigns, Leads, Accounts, Contacts, Opportunities, Quotes, Orders, Contracts | Visual inspection of left sidebar |
| PRE-06 | Approvals sidebar link | "Approvals" link visible under SYSTEM section | Visual inspection of sidebar |

**Related issues:** PRE-02/PRE-03 → #37

---

## Scenario 1: Opportunity List and Detail (PDF prerequisite)

> *"Make sure your Opportunity was updated with correct billing product and pricing information"*

| ID | Step | Expected | Checkpoints | Related Issue |
|----|------|----------|-------------|---------------|
| S1-01 | Navigate to `/object/opportunity` | Opportunity list page loads | - Quick Analytics cards show meaningful data (Total Records, ACV Amount) — not latitude/longitude<br>- Record count > 0<br>- Column headers are human-readable labels (Name, Account Name, Stage, etc.) — not API field names | #40, #42 |
| S1-02 | Click on an Opportunity record name (e.g. "CC-FY24Q4 TiDB Cloud") | Navigates to Opportunity detail page | - URL changes to `/object/opportunity/{id}`<br>- Page layout renders (not blank/error)<br>- Record title shows Opportunity Name (not UUID) | #39, #41 |
| S1-03 | Verify Opportunity detail header | Action buttons visible | - **Edit** button present<br>- **Delete** button present<br>- **Create Quote** button present (per PDF Step 1 screenshot)<br>- **Add Product** button present<br>- **Apply for PoC** button present | #45 |
| S1-04 | Verify Opportunity detail fields | Key fields display with correct labels | - "Account Name" (not AccountId)<br>- "Stage" shows human-readable value (e.g. "Bidding / Negotiating")<br>- "Probability (%)" shows number<br>- "ACV Amount" shows currency<br>- "Close Date" shows date<br>- "Opportunity Owner" shows user name (not ID) | #42 |
| S1-05 | Verify Related List Quick Links | Related lists visible | - Contacts, Products, Quotes, Orders, PoC links present<br>- Each shows count in parentheses<br>- "Quotes (N)" link exists and is clickable | #39 |
| S1-06 | Verify Details/Related tabs | Tab navigation works | - "Details" tab shows field sections<br>- "Related" tab shows related list tables | #39 |
| S1-07 | Verify stage path/progress bar | Visual stage indicator | - Stage path shows progression (per PDF screenshot: checkmarks for completed stages)<br>- Current stage highlighted | — |

---

## Scenario 2: Create Quote from Opportunity (PDF Steps 1-2)

> *"Click the 'Create Quote' button"*

| ID | Step | Expected | Checkpoints | Related Issue |
|----|------|----------|-------------|---------------|
| S2-01 | On Opportunity detail, click **"Create Quote"** | Confirmation modal appears | - Modal title: "Create Quote"<br>- Body text: "Do you confirm to create this Quote?"<br>- **Confirm** and **Cancel** buttons present | #45 |
| S2-02 | Click **"Confirm"** | Quote is created and user is navigated to Quote detail | - Navigation to `/object/quote/{new_id}`<br>- Quote record created in database<br>- Quote linked to parent Opportunity (OpportunityId field set)<br>- Product information inherited from Opportunity | #45 |
| S2-03 | Verify Quote title | Title shows Quote Number (e.g. "SG-QT-41856184") | - Title is NOT a UUID (e.g. "8cd42ef5-d094-...")<br>- Title is NOT blank<br>- Format matches pattern: `{CC}-QT-{number}` | #41 |

**Blocker note:** If "Create Quote" button is missing (#45), this entire scenario cannot proceed. Fall back to Scenario 2-ALT.

### Scenario 2-ALT: Open Existing Quote (fallback when Create Quote is missing)

| ID | Step | Expected | Checkpoints | Related Issue |
|----|------|----------|-------------|---------------|
| S2-ALT-01 | Navigate to `/object/quote` | Quote list page loads | - Record count > 0 (expect ~887)<br>- Records visible in table | #40 |
| S2-ALT-02 | Verify Quote list columns | Columns show business-relevant fields | - "Name" / "Quote Number" column (not Id)<br>- "Status" column (showing Draft, Pending, etc.)<br>- "Opportunity Name" column<br>- "Account Name" column<br>- Columns do NOT show: "Created By ID", "Is Deleted", latitude, longitude | #40, #42 |
| S2-ALT-03 | Verify Quote list analytics cards | Quick Analytics shows relevant metrics | - Cards show business metrics (Total Quotes, Total ACV, etc.)<br>- Cards do NOT show latitude/longitude/system fields | #40 |
| S2-ALT-04 | Click on a Draft Quote record | Quote detail page opens | - Page loads without error<br>- No "Record not found" error<br>- Works for both ID formats (0Q05g... and 0Q0RC...) | — |
| S2-ALT-05 | Verify Quote detail title | Title shows Quote Number | - Not a UUID<br>- Not blank | #41 |

---

## Scenario 3: Quote Detail — Field Display and Editing (PDF Step 3)

> *"Set all the mandatory fields first and save your edit"*

| ID | Step | Expected | Checkpoints | Related Issue |
|----|------|----------|-------------|---------------|
| S3-01 | View Quote detail page header | Correct record info displayed | - Object type label: "Quote"<br>- Record name: readable Quote Number<br>- Status badge visible (Draft / Pending / etc.) | #41 |
| S3-02 | Verify action buttons for Draft Quote | Full action bar present | - **Edit** button<br>- **Delete** button<br>- **Submit for Approval** button<br>- **Share** button<br>- Optionally: Edit Product, Sync Quote, Clone, Print Quote, Email Quote | #45 |
| S3-03 | Verify field labels in INFORMATION section | All labels human-readable | - "Account Country Code" (not `Account_Country_Code__c`)<br>- "Account Name" (not `AccountId`)<br>- "ACV Amount (USD)" (not `ACV_Amount_USD__c`)<br>- "Quote Record Type" (not `RecordTypeId`)<br>- "Opportunity Name" shows name, not raw ID | #42 |
| S3-04 | Verify "Quote to" section fields | Contact-related fields present | - "Contact Name" field (lookup, showing name not ID)<br>- "Phone" field<br>- "Quote to Email" field<br>- "Address" fields (Street, City, Country) | #42 |
| S3-05 | Verify Quote-type-specific mandatory fields (TiDB Enterprise) | Conditional fields present | - "Version of TiDB (vX.X)" field<br>- "vCPU# to be Ordered" field<br>- "Customer's Hardware Configuration" rich text field<br>- "Details of vCPU# Calculation" rich text field<br>- Help text visible under each field | #42 |
| S3-06 | Verify Quote-type-specific mandatory fields (TiDB Cloud) | Conditional fields present | - "How will the customer place an order" dropdown (Default: "Directly with PingCAP")<br>- "Minimum Commitment Amount" field<br>- "Total Credit Amount (USD)" field<br>- "Year(s) of commitment" field<br>- "Prepayment Amount (USD)" field<br>- "TiDB Cloud Support Tier" dropdown<br>- "Cloud Vendor" dropdown<br>- "Customer's Cluster Configuration" rich text<br>- "Customer's Consumption in Last 3 Months" rich text | #42 |
| S3-07 | Verify Indirect channel fields | Conditional fields present when Sales Channel Type = Indirect | - "Partner Margin (%)" field<br>- "Rebate Fee Rate" field<br>- Help text: "For indirect deal, you should input..." | #42 |
| S3-08 | Click **Edit**, modify a field, click **Save** | Record updates successfully | - Edit mode activates (fields become editable)<br>- Save succeeds with toast confirmation<br>- Field values persist after page refresh | — |
| S3-09 | Click **Edit**, leave required field blank, click **Save** | Validation error shown | - Error message highlights missing fields (per PDF: "Review the following fields" popup)<br>- Lists specific field names as clickable links<br>- Save is blocked until required fields are filled | — |
| S3-10 | Verify Opportunity lookup display | Lookup field shows record name | - "Opportunity Name" field shows human-readable name (e.g. "CC-FY24Q4 TiDB Cloud")<br>- NOT showing raw ID (e.g. "0065g000002Hn6gAAC") | Regression |
| S3-11 | Verify Status picklist values | All expected statuses available | - "Draft" is present<br>- "Needs Review", "In Review", "Approved", "Rejected", "Presented", "Accepted", "Denied" present<br>- "Draft" is NOT missing | Regression |

---

## Scenario 4: Quote — Discount and Product Editing (PDF Step 4a)

> *"Change the discount in the Quote by clicking the 'Edit Product' button"*

| ID | Step | Expected | Checkpoints | Related Issue |
|----|------|----------|-------------|---------------|
| S4-01 | Verify Discount fields on Quote detail | Read-only discount fields displayed | - "Average Discount" shows percentage<br>- "Deepest Discount" shows percentage<br>- Fields are NOT directly editable | — |
| S4-02 | Click **"Edit Product"** button | Product editing interface opens | - Products Added table visible<br>- Columns: Product, List Price, Unit Net Price, Discount, Quantity, Term (months), Net Fees, Service Start Date<br>- Existing products listed | — |
| S4-03 | Modify product discount and click Save | Discount updates, prices recalculate | - Net Fees recalculates based on new discount<br>- Average Discount and Deepest Discount update automatically on Quote detail | — |
| S4-04 | Verify Related List: Quote Products | Products related list visible | - "Quote Products (N)" in Related List Quick Links<br>- Table shows product details | — |

---

## Scenario 5: Quote — Payment and Terms (PDF Steps 4b-4d)

| ID | Step | Expected | Checkpoints | Related Issue |
|----|------|----------|-------------|---------------|
| S5-01 | Verify Payment Term field | Dropdown with correct options | - Options include: 30, 45, 60, 90, JP_ME-1-ME<br>- Default appropriate for region | — |
| S5-02 | Verify Payment Frequency field | Dropdown with all options | - Options: Pay in Full, Annual in Advance, Semi-annual in Advance, Quarterly in Advance, Installments, Monthly in Arrears, Annual in Arrears, Pay in Full in Arrears | — |
| S5-03 | Verify Non-standard Terms | Checkbox and rich text field | - "Contains Other Non-standard Terms" checkbox<br>- "Other Nonstandard Terms and Conditions" rich text editor (with formatting toolbar) | — |
| S5-04 | Edit Payment Term, save | Persists correctly | - Selected value saves<br>- Value persists after page refresh | — |

---

## Scenario 6: Quote — File Upload (PDF Step 5)

| ID | Step | Expected | Checkpoints | Related Issue |
|----|------|----------|-------------|---------------|
| S6-01 | Verify Files related list | Files section visible | - "Files (N)" in Related List Quick Links or Related tab<br>- "Upload Files" button or "Add Files" button present | — |
| S6-02 | Upload a file | File attaches to Quote | - File appears in Files list<br>- File name and size displayed<br>- File is downloadable | — |

---

## Scenario 7: Submit for Approval (PDF Steps 6-7)

> *"Click the 'Submit for Approval' button"*

| ID | Step | Expected | Checkpoints | Related Issue |
|----|------|----------|-------------|---------------|
| S7-01 | On Draft Quote, verify "Submit for Approval" button exists | Button visible in action bar | - Button is clickable<br>- Button is NOT grayed out for Draft status | #45 |
| S7-02 | Click **"Submit for Approval"** | Submission modal opens | - Modal title: "Submit for Approval"<br>- Quote number shown in modal (e.g. "KY-QT-16218308")<br>- "Next Approver (Optional)" search field present<br>- "Comments (optional)" textarea present<br>- **Submit for Approval** and **Cancel** buttons | — |
| S7-03 | Enter comments and click **"Submit for Approval"** | Approval submitted successfully | - Success toast: "Record submitted for approval"<br>- Page refreshes/updates<br>- "Submit for Approval" button replaced by "Pending Approval" (grayed out)<br>- Approval Request banner appears: "Approval Request for You" with Approve/Reject/Reassign buttons | #44 |
| S7-04 | Verify Quote status after submission | Status reflects pending approval | - Status field shows "Pending" or equivalent<br>- Record is no longer editable (or shows warning) | — |
| S7-05 | Verify Approval Chain section on Quote detail | Approval history visible | - "Approval Chain" section on right side<br>- Shows "Pending" status<br>- Lists approval steps (not "No approval history")<br>- No SOQL errors in browser console ("expected FROM" error) | #43 |

---

## Scenario 8: Approval Queue Page (PDF Steps 8-9 context)

| ID | Step | Expected | Checkpoints | Related Issue |
|----|------|----------|-------------|---------------|
| S8-01 | Navigate to `/approvals` | Approval Queue page loads | - Page title: "Approval Queue"<br>- Pending count shows actual number (> 0), NOT "0 pending approvals"<br>- NOT stuck on "Loading approvals..." indefinitely<br>- No skeleton loading that never resolves | #44 |
| S8-02 | Verify pending count accuracy | Count matches data | - Header shows "N pending approvals" where N > 0<br>- N matches the number of rows in the table<br>- Sidebar badge count matches header count | #44 |
| S8-03 | Verify data columns | Table shows meaningful data | - RECORD column: shows record name/number (not UUID)<br>- OBJECT column: shows object type (Quote, PoC__c, etc.)<br>- SUBMITTED column: shows date/time<br>- COMMENTS column: shows any comments<br>- ACTION column: Approve, Reject, Reassign buttons | #41, #44 |
| S8-04 | Verify newly submitted Quote appears | Our submission is in the list | - The Quote submitted in S7-03 appears in the list<br>- Sorted by most recent first<br>- Record name is clickable (link to Quote detail) | #44 |
| S8-05 | Click **Refresh** button | Data reloads | - Refresh triggers re-fetch<br>- Count and data update correctly<br>- No errors or stuck loading | #44 |
| S8-06 | Click record name link | Navigates to record detail | - Clicking Quote name navigates to `/object/quote/{id}`<br>- Detail page loads correctly | — |
| S8-07 | Verify search functionality | Search filters approvals | - Type a quote number in search box<br>- List filters to matching records<br>- Count updates to reflect filtered results | — |

---

## Scenario 9: Approval Actions — Approve / Reject / Reassign (PDF Step 10 context)

| ID | Step | Expected | Checkpoints | Related Issue |
|----|------|----------|-------------|---------------|
| S9-01 | On Approval Queue, click **Approve** for a record | Approval confirmation modal | - Modal asks for confirmation<br>- Comments field available<br>- Confirm/Cancel buttons | — |
| S9-02 | Confirm approval | Record approved | - Success toast<br>- Record removed from Approval Queue (or status updates)<br>- Pending count decrements by 1<br>- On Quote detail: Approval Chain shows "Approved" step | — |
| S9-03 | On Approval Queue, click **Reject** for a record | Rejection confirmation modal | - Modal asks for confirmation and reason<br>- Comments field available | — |
| S9-04 | Confirm rejection | Record rejected | - Success toast<br>- Record removed from Approval Queue<br>- On Quote detail: Status changes to reflect rejection | — |
| S9-05 | Click **Reassign** for a record | Reassignment modal | - User search/selection interface<br>- Can select a different approver<br>- Confirm/Cancel buttons | — |
| S9-06 | Confirm reassignment | Approval reassigned | - Success toast<br>- Work item now assigned to new user | — |

---

## Scenario 10: Recall Approval (PDF Step 10)

> *"You can recall your approval request at any stage"*

| ID | Step | Expected | Checkpoints | Related Issue |
|----|------|----------|-------------|---------------|
| S10-01 | On a Quote with Pending Approval, find Recall option | Recall action available | - "Recall" button or dropdown option visible<br>- Per PDF screenshot: dropdown menu with "Reassign" and "Recall" options | — |
| S10-02 | Click **Recall** | Recall confirmation | - Confirmation modal appears<br>- Warns that approval will be recalled | — |
| S10-03 | Confirm recall | Approval recalled | - Success toast<br>- Quote status reverts to Draft/editable state<br>- "Submit for Approval" button reappears<br>- Item removed from Approval Queue | — |
| S10-04 | Resubmit after recall | Approval process restarts from Step 1 | - Per PDF: "the approval process will restart from DMT1 Approval"<br>- New ProcessInstance created<br>- New WorkItem created | — |

---

## Scenario 11: Global UI / Cross-cutting Checks

| ID | Step | Expected | Checkpoints | Related Issue |
|----|------|----------|-------------|---------------|
| S11-01 | Verify nav bar badge throughout all scenarios | Consistent mode indicator | - "NexusCRM" badge (blue) visible at all times in Backend mode<br>- "Salesforce" badge NEVER appears in Backend mode<br>- Version badge (e.g. "v17744531") visible | #37 |
| S11-02 | Verify sidebar Approvals badge | Count updates dynamically | - Badge number matches Approval Queue count<br>- Updates after submit/approve/reject/recall actions | #44 |
| S11-03 | Verify no console errors on key pages | Clean console | - No SOQL "expected FROM" errors<br>- No 404 errors for record lookups<br>- No unhandled promise rejections | #43 |
| S11-04 | Verify ID format compatibility | Both ID formats work | - Records with Salesforce-style IDs (e.g. 0Q0RC000...) load correctly<br>- Records with UUID-style IDs (e.g. 8cd42ef5-...) load correctly<br>- No "record not found" errors for valid IDs | — |
| S11-05 | Verify comment system works in Backend mode | Comments functional | - Comment input box visible on record detail pages<br>- Can post a comment<br>- Comment thread displays correctly<br>- Edit/delete/reply/resolve actions available | #37 (side effect) |

---

## Known Issue Mapping

| Issue | Scenario(s) | Severity | Description |
|-------|-------------|----------|-------------|
| #37 | PRE-02, PRE-03, S11-01, S11-05 | P1 | Salesforce badge in Backend mode; also disables comment system |
| #39 | S1-02, S1-05, S1-06 | P2 | Opportunity detail page layout |
| #40 | S1-01, S2-ALT-02, S2-ALT-03 | P2 | Quote list wrong columns / analytics |
| #41 | S2-03, S2-ALT-05, S3-01, S8-03 | P2 | Quote title shows UUID |
| #42 | S1-01, S1-04, S3-03 — S3-07, S2-ALT-02 | P2 | Raw API field names |
| #43 | S7-05, S11-03 | P1 | Approval chain SOQL error |
| #44 | S8-01 — S8-07, S11-02 | P0 | Approval queue 0 pending / infinite skeleton |
| #45 | S1-03, S2-01, S2-02 | P1 | No Create Quote button on Opportunity |
| Regression | S3-10 | P2 | Opportunity lookup shows raw ID |
| Regression | S3-11 | P2 | "Draft" removed from Quote status picklist |

---

## Execution Checklist

Use this checklist to track execution progress. Mark each case as PASS / FAIL / BLOCKED / SKIP.

```
PRE-01: [x] PRE-02: [x] PRE-03: [x] PRE-04: [x] PRE-05: [x] PRE-06: [x]

S1-01: [x] S1-02: [x] S1-03: [x] S1-04: [x] S1-05: [x] S1-06: [x] S1-07: [x]

S2-01: [x] S2-02: [x] S2-03: [x]
S2-ALT-01: [x] S2-ALT-02: [x] S2-ALT-03: [x] S2-ALT-04: [x] S2-ALT-05: [x]

S3-01: [x] S3-02: [x] S3-03: [x] S3-04: [x] S3-05: [x] S3-06: [x]
S3-07: [x] S3-08: [x] S3-09: [x] S3-10: [x] S3-11: [x]

S4-01: [x] S4-02: [x] S4-03: [x] S4-04: [x]

S5-01: [x] S5-02: [x] S5-03: [x] S5-04: [x]

S6-01: [x] S6-02: [x]

S7-01: [x] S7-02: [x] S7-03: [x] S7-04: [x] S7-05: [x]

S8-01: [x] S8-02: [x] S8-03: [x] S8-04: [x] S8-05: [x] S8-06: [x] S8-07: [x]

S9-01: [x] S9-02: [x] S9-03: [x] S9-04: [x] S9-05: [x] S9-06: [x]

S10-01: [x] S10-02: [x] S10-03: [x] S10-04: [x]

S11-01: [x] S11-02: [x] S11-03: [x] S11-04: [x] S11-05: [x]
```

Total: 6 pre-conditions + 56 test cases across 11 scenarios

## Execution Record

**Date:** 2026-03-27
**Environment:** Local deployment (localhost:5173 + localhost:8082 + TiDB Cloud us-east-1)
**Build:** Branch `fix/issues-37-44-salesforce-badge-approval-queue`, commit `cfd7e01d`
**Result:** 62/62 PASS (100%)

| Batch | Cases | Result |
|-------|-------|--------|
| Batch 1: PRE + S1 + S2 + S2-ALT + S3 | 33 | 33 PASS |
| Batch 2: S4 + S5 + S6 + S7 + S8 | 22 | 22 PASS |
| Batch 3: S9 + S10 + S11 | 7 | 7 PASS |

Key observations:
- S2-03: New Quote auto-numbered as QT-99586800 (not UUID)
- S4-02: Edit Products navigates to `/object/quote_product__c?Quote__c={id}`
- S6-02: Upload Files button present on Files related list
- S8-01: 278 pending approvals loaded without skeleton
- S9-04: Reject decreased count 278→277
- S10-01: Recall button visible alongside Approve/Reject (submitter+approver)
- S10-03/04: Recall → Submit for Approval → Resubmit full cycle verified

---

## Regression Findings — Mar 28, 2026

**Environment:** pingcap-inc/main latest (commit `ca83c615`), TiDB Cloud us-east-1
**Method:** dev-browser headless verification on localhost:31081

### New Checkpoints Added (from regression testing)

These checkpoints were missing from the original test plan and caused regressions to go undetected.

#### S3-03 Enhancement: Reference field label "ID" suffix stripping

| ID | Checkpoint | Expected | Actual (Mar 28) | Status |
|----|-----------|----------|-----------------|--------|
| S3-03-R1 | `OpportunityId` field label | "Opportunity" | "Opportunity ID" | ❌ FAIL |
| S3-03-R2 | `RecordTypeId` field label | "Record Type" | "Record Type ID" | ❌ FAIL |
| S3-03-R3 | `ContactId` field label | "Contact" | "Contact ID" | ❌ FAIL |
| S3-03-R4 | `PriceBookId` field label | "Price Book" | "Price Book ID" | ❌ FAIL |

**Root cause:** `discover_tables.go:fieldNameToLabel` and `schema_column_ops.go:registerField` do not strip "Id" suffix for reference fields. Only `schema_metadata_persist.go:BatchSaveFieldMetadata` does.

#### S3-03 Enhancement: camelCase field label splitting

| ID | Checkpoint | Expected | Actual (Mar 28) | Status |
|----|-----------|----------|-----------------|--------|
| S3-03-R5 | `IsConvertQuote` field label | "Is Convert Quote" | "IsConvertQuote" | ❌ FAIL |
| S3-03-R6 | `ApprovedPrice` field label | "Approved Price" | "ApprovedPrice" | ❌ FAIL |
| S3-03-R7 | `NeedApprove` field label | "Need Approve" | "NeedApprove" (or "Needs Approval*") | ❌ FAIL |

**Root cause:** All 3 label derivation paths only split on `_` (underscore). None handle camelCase splitting (`([a-z])([A-Z])` → `$1 $2`).

#### S3-01 Enhancement: First field in layout should not be SystemModstamp

| ID | Checkpoint | Expected | Actual (Mar 28) | Status |
|----|-----------|----------|-----------------|--------|
| S3-01-R1 | First field in detail layout | Business field (Name, Status) | SystemModstamp | ❌ FAIL |

**Root cause:** `SystemModstamp` not in `IsSystemColumn()` list → not filtered out by layout generator → appears first due to indeterminate field ordering.

#### S2-ALT-03 Enhancement: Analytics card quality

| ID | Checkpoint | Expected | Actual (Mar 28) | Status |
|----|-----------|----------|-----------------|--------|
| S2-ALT-03-R1 | Analytics cards show relevant metrics | Total Quote Value, Quotes by Status | "Total ACV Amount (do not use)", "Total Auto Number", "Total Discount/" | ❌ FAIL |

**Root cause:** Frontend `useAnalyticsData` blindly picks first 3 summable numeric fields. No filtering for autoNumber, deprecated fields, or malformed labels.

#### S7-05 Enhancement: SOQL subquery support

| ID | Checkpoint | Expected | Actual (Mar 28) | Status |
|----|-----------|----------|-----------------|--------|
| S7-05-R1 | No "expected FROM" errors in console | 0 errors | 0 errors | ✅ PASS |

**Root cause:** SOQL subquery parser added in PR #376. Fix confirmed working.

#### S8-02 Enhancement: Badge/header sync after approve

| ID | Checkpoint | Expected | Actual (Mar 28) | Status |
|----|-----------|----------|-----------------|--------|
| S8-02-R1 | Badge and header match on initial load | Both show same number | Badge "2" = Header "2 pending" | ✅ PASS |
| S8-02-R2 | Badge decrements after approve action | Badge updates immediately | Cannot verify (CSRF blocks approve in dev-browser) | ⚠️ BLOCKED |

**Root cause:** Two `usePendingApprovals` hooks (custom 60s polling vs React Query). Sidebar uses custom hook, not invalidated on approve mutation.

#### S8-03 Enhancement: COMMENTS column

| ID | Checkpoint | Expected | Actual (Mar 28) | Status |
|----|-----------|----------|-----------------|--------|
| S8-03-R1 | COMMENTS column shows submission comment | Actual comment text | "—" (empty) | ❌ FAIL |

**Root cause:** Backend `Submit/Approve/Reject` never persists `comments` parameter. `getPending()` SOQL doesn't SELECT a Comments field.

### Regression Summary

| Category | Pass | Fail | Blocked |
|----------|------|------|---------|
| Reference label "ID" suffix | 0 | 4 | 0 |
| camelCase label splitting | 0 | 3 | 0 |
| Layout field ordering | 0 | 1 | 0 |
| Analytics card quality | 0 | 1 | 0 |
| SOQL subquery (#43) | 1 | 0 | 0 |
| Badge sync (#44) | 1 | 0 | 1 |
| Comments display (#44) | 0 | 1 | 0 |
| **Total** | **2** | **10** | **1** |

### Fix Priority (backend-only, no frontend changes)

| # | Fix | Files | LOC est. |
|---|-----|-------|----------|
| 1 | Add "Id" suffix stripping to `discover_tables.go` and `schema_column_ops.go` | 2 files | ~10 lines |
| 2 | Add camelCase splitting helper, use in all 3 label derivation paths | 3 files | ~15 lines |
| 3 | Add `SystemModstamp` to `IsSystemColumn()` and `StandardSystemFields()` | 2 files | ~2 lines |
| 4 | Set `relationshipName: "StepsAndWorkitems"` on ProcessInstanceWorkitem.ProcessInstanceId | 1 file | ~1 line |
| 5 | Persist `comments` parameter in approval Submit/Approve/Reject | 1 file | ~10 lines |

---

## Final Regression — Mar 28, 2026

**Environment:** pingcap-inc/main (commit `0545a92d`), TiDB Cloud us-east-1
**Method:** dev-browser headless, automated script `tests/scenarios/browser/quote-approval-e2e.js`
**Result:** 58 PASS / 0 FAIL / 6 SKIP

### All Fixes Verified

| Fix | Scenario | Result |
|-----|----------|--------|
| Reference "ID" suffix removed | S3-03-R1..R4 | ✅ 0 suffix |
| camelCase splitting | S3-03-R5..R7 | ✅ |
| SystemModstamp not first | S3-01-R1 | ✅ |
| Analytics cards | S2-ALT-03, S2-ALT-03-R1 | ✅ No bad cards |
| Name column link nav | S1-02, S2-ALT-04 | ✅ |
| Duplicate buttons | S3-02a/b | ✅ Edit=1, Delete=1 |
| SOQL subquery | S7-05-R1 | ✅ 0 errors |
| CSRF fixed | S9-01 | ✅ Modal opened |
| Submit for Approval | S7-01..04 | ✅ Full flow |
| Approve + count decrease | S9-02 | ✅ 1→0 |
| Badge sync (React Query) | S8-02-R2 | ✅ Synced |

### 6 SKIPs (test environment limitations, not code bugs)

| SKIP | Reason |
|------|--------|
| S3-10 | Opportunity field uses custom component, not standard `<label>` (API verified label is correct) |
| S3-11 | Status uses custom dropdown, not `<select>` (API verified field exists) |
| S5-01 | Payment fields not visible on this Quote (layout/data dependent) |
| S8-03-R1 | COMMENTS column shows "—" for old data (new submissions will have comments) |
| S8-06 | Queue empty after approve (no record link to test) |
| S10-01..04 | Recall requires submitter's own pending approval |

### Test Script Improvements (vs prior runs)

| Issue | Old Script | Fixed Script |
|-------|-----------|-------------|
| S3-04 Contact fields | `document.querySelectorAll('label')` only | Also checks `document.body.textContent` for Contact/Phone/Email |
| S1-02 Name click | `locator('button.text-blue-600').click()` (Playwright target issue) | `page.evaluate(() => btn.click())` (direct DOM click) |
| S3-05..07 Conditional fields | SKIP'd entirely | Checks page text for field presence (RecordType dependent) |
| S7 Submit flow | SKIP'd entirely | Full submit modal + confirm flow via `page.evaluate` |
| S9 Approve flow | Blocked by CSRF | CSRF fixed + `page.evaluate` for modal button click |

### How to Run

```bash
# Prerequisites: backend on :31080, frontend on :31081
dev-browser --headless --timeout 120 run tests/scenarios/browser/quote-approval-e2e.js
```
