# Validation Report: URS-029

**Title:** Collect Return Information per Individual Item
**Date:** 2026-04-23T03:40:19.404Z
**Duration:** 65.4s
**Overall Status:** ✅ PASS

## User Requirement

> The system shall collect return information for each individual item.

*Source: `User_Requirement_Specifications_ZuriMED_DeviceFlow.xlsx` — the run below proves the system meets this requirement.*

## Environment

- **Inbox URL:** http://localhost:63900
- **Database:** localhost:63901/cc_repinbox_dev

## Setup

Status: ✅ PASS

## Run Recording

This validation was captured as a single end-to-end screencast covering every step below.

[▶ Watch full run recording](videos/step-01-full-run.webm)

## Test Steps

Each step below corresponds to one Playwright test that ran sequentially. Screenshots and video recordings provide visual evidence of the UI behaviour.

### 1. Login — ✅ PASS

**What this step proves:**

Authenticates as Bob Kauffman (StellarTech sales rep) to establish the user identity that will be associated with the return submission.

**Audit events generated by this step:**

*(Evidence matched by declared name — step timing not available or no events fell in window)*

| Time | Type | Action | User | Org | Performed |
|------|------|--------|------|-----|-----------|
| 2026-04-23 03:40:25Z | user_log | user:login | bob.kauffman@stellartech.com | StellarTech Medical Solutions | — |

**Screenshots:**

![01 logged in](screenshots/01-logged-in.png)

---

### 2. New Return opened — ✅ PASS

**What this step proves:**

Navigates to the new return form, confirming the multi-step return workflow is accessible.

**Screenshots:**

![02 new return form](screenshots/02-new-return-form.png)

---

### 3. Account selected — ✅ PASS

**What this step proves:**

Selects the sales account to associate with the return, establishing the account-level context for per-item traceability.

**Screenshots:**

![03 account selected](screenshots/03-account-selected.png)

---

### 4. Event details — ✅ PASS

**What this step proves:**

Records the reporting user, event date, and a unique run marker in the notes field so the database validation step can locate this specific return.

**Screenshots:**

![04 event details](screenshots/04-event-details.png)

---

### 5. Quantities filled — ✅ PASS

**What this step proves:**

Sets return quantities for three products (2 SpeedPatch, 3 FiberLocker, 1 Medical Gelatin = 6 total units), enabling per-unit item card generation.

**Screenshots:**

![05 product quantities set](screenshots/05-product-quantities-set.png)

---

### 6. Lots filled — ✅ PASS

**What this step proves:**

Assigns distinct lot numbers to each individual unit, demonstrating that the form supports per-unit lot tracking rather than a single shared lot.

**Screenshots:**

![06 product lots filled](screenshots/06-product-lots-filled.png)

---

### 7. All 6 item cards rendered — ✅ PASS

**What this step proves:**

Verifies that the form renders one item card per unit (6 total), each with product-specific question fields — the prerequisite for per-item data capture.

**Screenshots:**

![07 per item cards rendered](screenshots/07-per-item-cards-rendered.png)

---

### 8. All per-item questions filled — ✅ PASS

**What this step proves:**

Fills distinct answers for every unit's product-specific questions, proving that each unit's response is captured independently rather than shared across units.

**Screenshots:**

![08 per item questions filled](screenshots/08-per-item-questions-filled.png)

---

### 9. Locations selected — ✅ PASS

**What this step proves:**

Selects return and replacement shipping locations to complete the return request before the review step.

**Screenshots:**

![09 locations selected](screenshots/09-locations-selected.png)

---

### 10. Review summary — ✅ PASS

**What this step proves:**

Displays the full summary of all 6 units with their individual lot numbers and answers, confirming per-item data is preserved through to the review step.

**Screenshots:**

![10 review summary](screenshots/10-review-summary.png)

---

### 11. Submission success — ✅ PASS

**What this step proves:**

Confirms the return was submitted successfully, triggering back-end persistence of return_items and per-item question responses for each unit.

**Screenshots:**

![11 submission success](screenshots/11-submission-success.png)

---

## Database Validations

The following SQL queries ran against the application database after the Playwright scenarios completed. Each query asserts a specific condition that proves the feature under test persisted its data correctly.

### Return created for StellarTech → ZuriMED — ✅ PASS

**Assertion:** Exactly one return with status=submitted should exist, created in the last 2 hours.

```sql
SELECT id, return_number, status, date_of_event, notes, created_at
    FROM returns
    WHERE sales_organization_id = $1
      AND manufacturer_organization_id = $2
      AND notes LIKE 'URS-029%'
      AND created_at > NOW() - INTERVAL '2 hours'
    ORDER BY created_at DESC
```

| id | return_number | status | date_of_event | notes | created_at |
| --- | --- | --- | --- | --- | --- |
| 019db86d-8fcb-7980-9cb4-7a529e8a3cf5 | RET-1 | submitted | 2026-04-22T05:00:00.000Z | URS-029 validation run 2026-04-23T03:40:20.286Z | 2026-04-23T03:41:21.211Z |

### Per-item return_items rows — ✅ PASS

**Assertion:** Each individual unit should have its own return_items row. Expected 6.

```sql
SELECT ri.id, ri.product_id, op.sku, op.title, ri.lot_number,
      ri.return_item_number, ri.created_at
    FROM return_items ri
    JOIN org_products op ON op.id = ri.product_id
    WHERE ri.return_id = $1
    ORDER BY op.sku, ri.lot_number
```

| id | product_id | sku | title | lot_number | return_item_number | created_at |
| --- | --- | --- | --- | --- | --- | --- |
| 019db86d-8fcd-73fd-aaed-0e003377ff4b | 66a80423-2315-4d10-8ecf-238b3058528b | DB2025G | Medical gelatin (For demonstration purpose) | URS029-MG-001 | RET-1-DB2025G-1 | 2026-04-23T03:41:21.211Z |
| 019db86d-8fcd-73fd-aaed-0dfd765e15a7 | 01989ca1-f2f8-7ab7-8269-7179342797cc | FL516SNA | FiberLocker® Instrument SN | URS029-FL-001 | RET-1-FL516SNA-1 | 2026-04-23T03:41:21.211Z |
| 019db86d-8fcd-73fd-aaed-0dfee0130dbf | 01989ca1-f2f8-7ab7-8269-7179342797cc | FL516SNA | FiberLocker® Instrument SN | URS029-FL-002 | RET-1-FL516SNA-2 | 2026-04-23T03:41:21.211Z |
| 019db86d-8fcd-73fd-aaed-0dff222354c9 | 01989ca1-f2f8-7ab7-8269-7179342797cc | FL516SNA | FiberLocker® Instrument SN | URS029-FL-003 | RET-1-FL516SNA-3 | 2026-04-23T03:41:21.211Z |
| 019db86d-8fcd-73fd-aaed-0dfbc7ed5054 | 01989ca2-6a54-7834-8376-06a0251bacd8 | SP019N1A | SpeedPatch® PET | URS029-SP-001 | RET-1-SP019N1A-1 | 2026-04-23T03:41:21.211Z |
| 019db86d-8fcd-73fd-aaed-0dfc2eeefe06 | 01989ca2-6a54-7834-8376-06a0251bacd8 | SP019N1A | SpeedPatch® PET | URS029-SP-002 | RET-1-SP019N1A-2 | 2026-04-23T03:41:21.211Z |

### Each unit has its own distinct lot number — ✅ PASS

**Assertion:** All expected per-unit lot numbers should appear exactly once, proving per-item data was stored.

```sql
-- Expected lot numbers: URS029-SP-001, URS029-SP-002, URS029-FL-001, URS029-FL-002, URS029-FL-003, URS029-MG-001
```

| lot_number | sku |
| --- | --- |
| URS029-MG-001 | DB2025G |
| URS029-FL-001 | FL516SNA |
| URS029-FL-002 | FL516SNA |
| URS029-FL-003 | FL516SNA |
| URS029-SP-001 | SP019N1A |
| URS029-SP-002 | SP019N1A |

### Each returned unit has per-item question responses — ✅ PASS

**Assertion:** Every return_item should have at least one associated return_item_question_response row.

```sql
SELECT riqr.id, riqr.return_item_id, riqr.question_version_id,
      riqr.response_text, riqr.response_values::text AS response_values_json,
      ri.lot_number, rpqv.question_type, rpqv.is_required, rpqv.question_text
    FROM return_item_question_responses riqr
    JOIN return_items ri ON ri.id = riqr.return_item_id
    JOIN return_product_question_versions rpqv ON rpqv.id = riqr.question_version_id
    JOIN return_product_questions rpq ON rpq.id = rpqv.question_id
    WHERE ri.return_id = $1
    ORDER BY ri.lot_number, rpq.display_order NULLS LAST, rpqv.version_number
```

| id | return_item_id | question_version_id | response_text | response_values_json | lot_number | question_type | is_required | question_text |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 019db86d-8fd0-7c32-aafe-ac8e0f1e0543 | 019db86d-8fcd-73fd-aaed-0dfd765e15a7 | 0c020902-aaaa-4002-9002-000000000002 | NULL | ["opened"] | URS029-FL-001 | single_select | true | Condition at return |
| 019db86d-8fd0-7c32-aafe-ac92aebacca6 | 019db86d-8fcd-73fd-aaed-0dfd765e15a7 | 0c020902-aaaa-4002-9002-000000000004 | Customer confirmed seal integrity at receipt. | NULL | URS029-FL-001 | text | false | Additional notes (optional) |
| 019db86d-8fd0-7c32-aafe-ac8fb398632f | 019db86d-8fcd-73fd-aaed-0dfee0130dbf | 0c020902-aaaa-4002-9002-000000000002 | NULL | ["unopened"] | URS029-FL-002 | single_select | true | Condition at return |
| 019db86d-8fd0-7c32-aafe-ac90d06c62f2 | 019db86d-8fcd-73fd-aaed-0dff222354c9 | 0c020902-aaaa-4002-9002-000000000002 | NULL | ["defective"] | URS029-FL-003 | single_select | true | Condition at return |
| 019db86d-8fd0-7c32-aafe-ac9198b47347 | 019db86d-8fcd-73fd-aaed-0e003377ff4b | 0c020903-aaaa-4003-9002-000000000002 | URS029 MG unit 1: hydraulic seal failure observed. | NULL | URS029-MG-001 | text | true | Unit inspection note |
| 019db86d-8fcf-7a98-997b-49e8cd7c6118 | 019db86d-8fcd-73fd-aaed-0dfbc7ed5054 | 0c020901-aaaa-4001-9002-000000000002 | NULL | ["damaged"] | URS029-SP-001 | single_select | true | Return reason |
| 019db86d-8fd0-7c32-aafe-ac8b7a8f2c5f | 019db86d-8fcd-73fd-aaed-0dfbc7ed5054 | 0c020901-aaaa-4001-9002-000000000004 | URS029 unit 1: screen cracked during shipping, non-functional. | NULL | URS029-SP-001 | text | true | Per-unit notes |
| 019db86d-8fd0-7c32-aafe-ac8cd12b2d46 | 019db86d-8fcd-73fd-aaed-0dfc2eeefe06 | 0c020901-aaaa-4001-9002-000000000002 | NULL | ["unused"] | URS029-SP-002 | single_select | true | Return reason |
| 019db86d-8fd0-7c32-aafe-ac8d3b3064b1 | 019db86d-8fcd-73fd-aaed-0dfc2eeefe06 | 0c020901-aaaa-4001-9002-000000000004 | URS029 unit 2: never opened, preventative return. | NULL | URS029-SP-002 | text | true | Per-unit notes |

### Required per-item question responses present — ✅ PASS

**Assertion:** Expected 8 required-question responses across all items.

```sql
-- Filter to versions: 0c020901-aaaa-4001-9002-000000000002, 0c020901-aaaa-4001-9002-000000000004, 0c020902-aaaa-4002-9002-000000000002, 0c020903-aaaa-4003-9002-000000000002
```

| lot_number | question_text | response_text | response_values |
| --- | --- | --- | --- |
| URS029-FL-001 | Condition at return | NULL | ["opened"] |
| URS029-FL-002 | Condition at return | NULL | ["unopened"] |
| URS029-FL-003 | Condition at return | NULL | ["defective"] |
| URS029-MG-001 | Unit inspection note | URS029 MG unit 1: hydraulic seal failure observed. | NULL |
| URS029-SP-001 | Return reason | NULL | ["damaged"] |
| URS029-SP-001 | Per-unit notes | URS029 unit 1: screen cracked during shipping, non-functional. | NULL |
| URS029-SP-002 | Return reason | NULL | ["unused"] |
| URS029-SP-002 | Per-unit notes | URS029 unit 2: never opened, preventative return. | NULL |

### SpeedPatch per-unit free-text answers are distinct — ✅ PASS

**Assertion:** Each SpeedPatch unit should have a distinct per-unit note, proving per-item data is collected independently.

```sql
-- Filter to speedPatchNotesVersion = 0c020901-aaaa-4001-9002-000000000004
```

| lot_number | response_text |
| --- | --- |
| URS029-SP-001 | URS029 unit 1: screen cracked during shipping, non-functional. |
| URS029-SP-002 | URS029 unit 2: never opened, preventative return. |

## Audit & Email Assertion Ledger

Per-declaration outcome of every `expectedAuditActions` and `expectedEmailTemplates` entry written into the orchestrator. Missing evidence here is a real test failure, not a soft warning.

### Audit Action Assertions

Each row asserts that a declared `expectedAuditActions` entry produced a matching row in `audit_events`. A ❌ flips overall status to FAIL — the declaration is real proof, not just an annotation.

| Step | Expected Audit Action | Found |
|------|-----------------------|-------|
| Login | `user_log:user:login` | ✅ |

## Audit Log Events

Every row written to `audit_events` while this test was running (scoped to the demo organizations). Provides compliance evidence that user actions are traced end-to-end (URS-003).

**Capture window start:** 2026-04-23T03:40:17.491Z

<details><summary>Query used to capture events</summary>

```sql
SELECT
    ae.created_at,
    ae.event_type,
    ae.action,
    ae.user_id,
    u.email AS user_email,
    ae.organization_id,
    o.name AS organization_name,
    ae.object_id,
    ae.secondary_object_id,
    ae.payload,
    ae.route,
    ae.trace_id
  FROM audit_events ae
  LEFT JOIN users u ON u.id = ae.user_id
  LEFT JOIN organizations o ON o.id = ae.organization_id
  WHERE ae.created_at >= $1
    AND ae.organization_id = ANY($2::uuid[])
  ORDER BY ae.created_at ASC
```
</details>

1 event(s) captured:

| Time | Type | Action | User | Org | Object ID | Performed | Reason |
|------|------|--------|------|-----|-----------|-----------|--------|
| 2026-04-23 03:40:25Z | user_log | user:login | bob.kauffman@stellartech.com | StellarTech Medical Solutions | — | — |  |
