# Validation Report: URS-030

**Title:** Attach/Generate Required Documents for Returns
**Date:** 2026-08-03T23:03:18.187Z
**Duration:** 106.2s
**Overall Status:** ✅ PASS

## User Requirement

> The system shall attach or generate required documents for returns and replacements.

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

## Environment

- **Inbox URL:** http://localhost:38443
- **Database:** localhost:44149/cc_repinbox_dev

## Setup

Status: ✅ PASS

## 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. Step 1: Navigate to returns — ✅ PASS

**What this step proves:**

A sales rep logs in and navigates to the returns section of the application. This verifies the returns feature is accessible before the document-generation flow begins.

**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-08-03 23:03:22Z | user_log | user:login | blair.bennett@corvetasurgical.com | Corveta Surgical Group | — |
| 2026-08-03 23:03:27Z | user_log | user:login | blair.bennett@corvetasurgical.com | Corveta Surgical Group | — |
| 2026-08-03 23:04:13Z | user_log | user:login | blair.bennett@corvetasurgical.com | Corveta Surgical Group | — |
| 2026-08-03 23:04:50Z | user_log | user:login | blair.bennett@corvetasurgical.com | Corveta Surgical Group | — |
| 2026-08-03 23:04:56Z | user_log | user:login | blair.bennett@corvetasurgical.com | Corveta Surgical Group | — |

**Screenshots:**

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

![step 01 returns list](screenshots/step-01-returns-list.png)

**Video recording:**

[▶ Watch step recording](videos/step-01-navigate-returns.webm)

---

### 2. Step 2: Submit return — ✅ PASS

**What this step proves:**

The sales rep completes the multi-step return form (account, event details with notes, product with lot number, required product question, locations) and submits it. The confirmation page must state that a return form document is being generated, showing the system attaches required documents to returns automatically.

**Audit events generated by this step:**

*(Evidence scoped to step execution window: 2026-08-03T23:04:07.795Z → 2026-08-03T23:04:10.312Z)*

| Time | Type | Action | User | Org | Performed |
|------|------|--------|------|-----|-----------|
| 2026-08-03 23:04:09Z | decision | create_replacement_order_on_return | blair.bennett@corvetasurgical.com | Vantis | no |
| 2026-08-03 23:04:09Z | return_request | created | blair.bennett@corvetasurgical.com | Vantis | — |

**Screenshots:**

![step 02 review before submit](screenshots/step-02-review-before-submit.png)

![step 02 submitted with document notice](screenshots/step-02-submitted-with-document-notice.png)

**Video recording:**

[▶ Watch step recording](videos/step-02-submit-return.webm)

---

### 3. Step 3: Document linked to return — ✅ PASS

**What this step proves:**

The asynchronous document pipeline (Restate workflow → document generator → S3) is given time to complete, then the return details page is opened. The Documents card must list the generated return form with a "System generated" badge and a generation timestamp, proving the document is linked to the return.

**Screenshots:**

![step 03 documents card](screenshots/step-03-documents-card.png)

**Video recording:**

[▶ Watch step recording](videos/step-03-document-linked.webm)

---

### 4. Step 4: Download and verify PDF — ✅ PASS

**What this step proves:**

The generated PDF is downloaded through the application (authenticated, org-scoped endpoint) and its text is extracted. The document must contain the return number, product name and SKU, lot number, facility, rep details, the notes entered on the form, and the product question answer — the required content for a return document. The rendered first page is captured as visual evidence.

**Screenshots:**

![step 04 generated pdf content](screenshots/step-04-generated-pdf-content.png)

**Video recording:**

[▶ Watch step recording](videos/step-04-download-verify-pdf.webm)

---

### 5. Step 5: Document persists after reload — ✅ PASS

**What this step proves:**

After navigating away, returning, and fully reloading the page, the generated document must still be listed on the return. This proves the document is durably attached to the return record rather than session state.

**Screenshots:**

![step 05 document persists after reload](screenshots/step-05-document-persists-after-reload.png)

**Video recording:**

[▶ Watch step recording](videos/step-05-document-persists.webm)

---

## 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 record created with test item — ✅ PASS

**Assertion:** A return created by Blair Bennett in the last 30 minutes should contain an item with lot "URS030-RETURN-001"

```sql
SELECT r.id, r.return_number, r.status, r.created_at, ri.lot_number
      FROM returns r
      JOIN return_items ri ON ri.return_id = r.id
      WHERE r.created_by_user_id = $1
        AND r.created_at > NOW() - INTERVAL '30 minutes'
        AND ri.lot_number = $2
      ORDER BY r.created_at DESC
      LIMIT 1
```

| id | return_number | status | created_at | lot_number |
| --- | --- | --- | --- | --- |
| 019fc9de-cdc8-75e4-af68-fba296a40a87 | RET-1 | submitted | 2026-08-03T23:04:09.785Z | URS030-RETURN-001 |

### Generated document linked to return with S3 storage — ✅ PASS

**Assertion:** A return_form_documents row for the return should have status 'created' with s3_bucket and s3_key set

```sql
SELECT d.id, d.return_id, r.return_number, d.status,
        d.s3_bucket, d.s3_key, d.generated_by_user_id, d.organization_id,
        d.created_at, d.updated_at
      FROM return_form_documents d
      JOIN returns r ON r.id = d.return_id
      JOIN return_items ri ON ri.return_id = r.id
      WHERE r.created_by_user_id = $1
        AND r.created_at > NOW() - INTERVAL '30 minutes'
        AND ri.lot_number = $2
      ORDER BY d.created_at DESC
```

| id | return_id | return_number | status | s3_bucket | s3_key | generated_by_user_id | organization_id | created_at | updated_at |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 019fc9de-cf70-73f8-9837-c5532a75a431 | 019fc9de-cdc8-75e4-af68-fba296a40a87 | RET-1 | created | df-inbox-documents-private-dev | returns/a1b2c3d4-e5f6-7890-abcd-ef1234567890/019fc9de-cdc8-75e4-af68-fba296a40a87/2026-08-03T23-04-10-921Z-019fc9de.pdf | 17b8c9d0-e1f2-3456-1234-567890123456 | a1b2c3d4-e5f6-7890-abcd-ef1234567890 | 2026-08-03T23:04:10.353Z | 2026-08-03T23:04:10.942Z |

### Document records the generating user and manufacturer org — ✅ PASS

**Assertion:** The generated document should record generated_by_user_id = Blair Bennett (submitter) and organization_id = Vantis (manufacturer)

```sql
SELECT d.id, d.return_id, r.return_number, d.status,
        d.s3_bucket, d.s3_key, d.generated_by_user_id, d.organization_id,
        d.created_at, d.updated_at
      FROM return_form_documents d
      JOIN returns r ON r.id = d.return_id
      JOIN return_items ri ON ri.return_id = r.id
      WHERE r.created_by_user_id = $1
        AND r.created_at > NOW() - INTERVAL '30 minutes'
        AND ri.lot_number = $2
      ORDER BY d.created_at DESC
```

| id | return_id | return_number | status | s3_bucket | s3_key | generated_by_user_id | organization_id | created_at | updated_at |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 019fc9de-cf70-73f8-9837-c5532a75a431 | 019fc9de-cdc8-75e4-af68-fba296a40a87 | RET-1 | created | df-inbox-documents-private-dev | returns/a1b2c3d4-e5f6-7890-abcd-ef1234567890/019fc9de-cdc8-75e4-af68-fba296a40a87/2026-08-03T23-04-10-921Z-019fc9de.pdf | 17b8c9d0-e1f2-3456-1234-567890123456 | a1b2c3d4-e5f6-7890-abcd-ef1234567890 | 2026-08-03T23:04:10.353Z | 2026-08-03T23:04:10.942Z |

### No failed or stuck document generation attempts — ✅ PASS

**Assertion:** Every return_form_documents row for the return should have status 'created' (no 'error' or lingering 'pending' rows)

```sql
SELECT d.id, d.status, d.created_at
      FROM return_form_documents d
      JOIN returns r ON r.id = d.return_id
      JOIN return_items ri ON ri.return_id = r.id
      WHERE r.created_by_user_id = $1
        AND r.created_at > NOW() - INTERVAL '30 minutes'
        AND ri.lot_number = $2
        AND d.status != 'created'
```

*No rows returned*

### Document generated promptly after submission — ✅ PASS

**Assertion:** The document should be generated within 5 minutes of return submission (async pipeline)

```sql
SELECT d.id, r.return_number,
        r.created_at AS return_created_at,
        d.updated_at AS document_completed_at,
        EXTRACT(EPOCH FROM (d.updated_at - r.created_at)) AS seconds_after_submission
      FROM return_form_documents d
      JOIN returns r ON r.id = d.return_id
      JOIN return_items ri ON ri.return_id = r.id
      WHERE r.created_by_user_id = $1
        AND r.created_at > NOW() - INTERVAL '30 minutes'
        AND ri.lot_number = $2
        AND d.status = 'created'
      ORDER BY d.created_at DESC
      LIMIT 1
```

| id | return_number | return_created_at | document_completed_at | seconds_after_submission |
| --- | --- | --- | --- | --- |
| 019fc9de-cf70-73f8-9837-c5532a75a431 | RET-1 | 2026-08-03T23:04:09.785Z | 2026-08-03T23:04:10.942Z | 1.156673 |

### No orphaned or cross-org documents — ✅ PASS

**Assertion:** Every recent return_form_documents row must reference an existing return and carry that return's manufacturer organization id

```sql
SELECT d.id, d.return_id, d.organization_id, r.manufacturer_organization_id
      FROM return_form_documents d
      LEFT JOIN returns r ON r.id = d.return_id
      WHERE d.created_at > NOW() - INTERVAL '30 minutes'
        AND (r.id IS NULL OR r.manufacturer_organization_id != d.organization_id)
```

*No rows returned*

## 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 |
|------|-----------------------|-------|
| Step 1: Navigate to returns | `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-08-03T23:03:16.280Z

<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>

9 event(s) captured:

| Time | Type | Action | User | Org | Object ID | Performed | Reason |
|------|------|--------|------|-----|-----------|-----------|--------|
| 2026-08-03 23:03:16Z | decision | ensure_lot_expiration_checklist | — | Corveta Surgical Group | b2c3d4e5-f6a7-8901-bcde-f12345678901 | yes | created_1_reopened_0_already_open_1 |
| 2026-08-03 23:03:22Z | user_log | user:login | blair.bennett@corvetasurgical.com | Corveta Surgical Group | — | — |  |
| 2026-08-03 23:03:27Z | user_log | user:login | blair.bennett@corvetasurgical.com | Corveta Surgical Group | — | — |  |
| 2026-08-03 23:04:09Z | decision | create_replacement_order_on_return | blair.bennett@corvetasurgical.com | Vantis | 019fc9de-cdc8-75e4-af68-fba296a40a87 | no | manufacturer_setting_disabled |
| 2026-08-03 23:04:09Z | return_request | created | blair.bennett@corvetasurgical.com | Vantis | 019fc9de-cdc8-75e4-af68-fba296a40a87 | — |  |
| 2026-08-03 23:04:12Z | transactional_email | return_submitted | — | Corveta Surgical Group | 019fc9de-cdc8-75e4-af68-fba296a40a87 | — |  |
| 2026-08-03 23:04:13Z | user_log | user:login | blair.bennett@corvetasurgical.com | Corveta Surgical Group | — | — |  |
| 2026-08-03 23:04:50Z | user_log | user:login | blair.bennett@corvetasurgical.com | Corveta Surgical Group | — | — |  |
| 2026-08-03 23:04:56Z | user_log | user:login | blair.bennett@corvetasurgical.com | Corveta Surgical Group | — | — |  |

## Email Evidence

1 notification email(s) were captured during this test run. Each email is rendered as a screenshot for compliance review.

### 1. Return Submitted - RET-1

**Template:** `Return_Submitted_-_RET-1`

![Return Submitted - RET-1](screenshots/emails/2026-08-03T23-04-12-949Z-Return_Submitted_-_RET-1.png)
