# Validation Report: URS-014

**Title:** Display Available Inventory for Rep Trunk Stock
**Date:** 2026-04-23T03:36:30.720Z
**Duration:** 51.5s
**Overall Status:** ✅ PASS

## User Requirement

> The system shall display available inventory for a rep’s user trunk stock.

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

## Environment

- **Inbox URL:** http://localhost:62705
- **Database:** localhost:62706/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: Login and navigate — ✅ PASS

**What this step proves:**

The test logs in as a sales rep (Bob Kauffman) and navigates to the inventory locations list, verifying that TRUNK-36 appears and is accessible. This proves that authorized users can reach their trunk stock location from the main inventory view.

**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:36:33Z | user_log | user:login | bob.kauffman@stellartech.com | StellarTech Medical Solutions | — |
| 2026-04-23 03:36:42Z | user_log | user:login | bob.kauffman@stellartech.com | StellarTech Medical Solutions | — |
| 2026-04-23 03:36:50Z | user_log | user:login | bob.kauffman@stellartech.com | StellarTech Medical Solutions | — |
| 2026-04-23 03:36:57Z | user_log | user:login | bob.kauffman@stellartech.com | StellarTech Medical Solutions | — |
| 2026-04-23 03:37:04Z | user_log | user:login | bob.kauffman@stellartech.com | StellarTech Medical Solutions | — |
| 2026-04-23 03:37:11Z | user_log | user:login | bob.kauffman@stellartech.com | StellarTech Medical Solutions | — |

**Screenshots:**

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

![step 01 inventory locations](screenshots/step-01-inventory-locations.png)

**Video recording:**

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

---

### 2. Step 2: Trunk inventory overview — ✅ PASS

**What this step proves:**

Navigates directly to TRUNK-36 and confirms all three test products — Diagnostic Kit, Sterile Gloves, and Antiseptic Solution — are listed together. This proves the system displays available trunk stock inventory in a single unified view.

**Screenshots:**

![step 02 trunk inventory overview](screenshots/step-02-trunk-inventory-overview.png)

![step 02 all products visible](screenshots/step-02-all-products-visible.png)

**Video recording:**

[▶ Watch step recording](videos/step-02-trunk-inventory.webm)

---

### 3. Step 3: Diagnostic Kit details — ✅ PASS

**What this step proves:**

Verifies the Diagnostic Kit row shows the correct product name, lot number, on-hand quantity, and expiration date. This proves per-item details are accurately surfaced for the first product in the trunk stock display.

**Screenshots:**

![step 03 diagnostic kit details](screenshots/step-03-diagnostic-kit-details.png)

**Video recording:**

[▶ Watch step recording](videos/step-03-diagnostic-kit.webm)

---

### 4. Step 4: Sterile Gloves details — ✅ PASS

**What this step proves:**

Verifies the Sterile Gloves row shows the correct product name, lot number, on-hand quantity, and expiration date. This proves per-item details are accurate for a second, distinct product in the same trunk location.

**Screenshots:**

![step 04 sterile gloves details](screenshots/step-04-sterile-gloves-details.png)

**Video recording:**

[▶ Watch step recording](videos/step-04-sterile-gloves.webm)

---

### 5. Step 5: Antiseptic Solution details — ✅ PASS

**What this step proves:**

Verifies the Antiseptic Solution row shows the correct product name, lot number, on-hand quantity, and expiration date, completing the per-product detail verification across all three trunk stock items.

**Screenshots:**

![step 05 antiseptic solution details](screenshots/step-05-antiseptic-solution-details.png)

**Video recording:**

[▶ Watch step recording](videos/step-05-antiseptic-solution.webm)

---

### 6. Step 6: Filter functionality — ✅ PASS

**What this step proves:**

Applies a lot/serial filter string to the inventory table and confirms only the matching product row remains visible. Clearing the filter restores all rows. This proves the filter functionality narrows results correctly and does not suppress data when cleared.

**Screenshots:**

![step 06 before filter](screenshots/step-06-before-filter.png)

![step 06 filtered results](screenshots/step-06-filtered-results.png)

![step 06 filter cleared](screenshots/step-06-filter-cleared.png)

**Video recording:**

[▶ Watch step recording](videos/step-06-filter-functionality.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.

### Inventory items exist at TRUNK-36 — ✅ PASS

**Assertion:** Exactly 3 inventory items should exist at TRUNK-36

```sql

    SELECT count(*)::int as item_count
    FROM inventory_items ii
    JOIN org_products op ON ii.product_id = op.id
    WHERE ii.real_world_location_id = $1
      AND op.sku IN ($2, $3, $4)
      AND ii.organization_id = $5
```

| item_count |
| --- |
| 3 |

### Product details match expected values — ✅ PASS

**Assertion:** Each product should have the correct title, lot, quantity, and expiration

```sql

    SELECT op.title, op.sku, ii.lot, ii.expiration::text, ii.quantity_ready
    FROM inventory_items ii
    JOIN org_products op ON ii.product_id = op.id
    WHERE ii.real_world_location_id = $1
      AND op.sku IN ($2, $3, $4)
      AND ii.organization_id = $5
    ORDER BY op.title
```

| title | sku | lot | expiration | quantity_ready |
| --- | --- | --- | --- | --- |
| Antiseptic Solution (500ml) | URS014-AS-001 | AS-2024-112 | 2026-09-15 | 8 |
| Diagnostic Kit | URS014-DK-001 | DK-2024-001 | 2026-12-31 | 15 |
| Sterile Gloves (Box of 100) | URS014-SG-001 | SG-2024-045 | 2027-06-30 | 50 |

### Total inventory quantity is correct — ✅ PASS

**Assertion:** Total quantity should be 73 (15 + 50 + 8)

```sql

    SELECT sum(ii.quantity_ready)::int as total_quantity
    FROM inventory_items ii
    JOIN org_products op ON ii.product_id = op.id
    WHERE ii.real_world_location_id = $1
      AND op.sku IN ($2, $3, $4)
      AND ii.organization_id = $5
```

| total_quantity |
| --- |
| 73 |

### All items belong to StellarTech org — ✅ PASS

**Assertion:** All inventory items should belong to the StellarTech organization

```sql

    SELECT ii.organization_id, count(*)::int as item_count
    FROM inventory_items ii
    JOIN org_products op ON ii.product_id = op.id
    WHERE ii.real_world_location_id = $1
      AND op.sku IN ($2, $3, $4)
      AND ii.organization_id = $5
    GROUP BY ii.organization_id
```

| organization_id | item_count |
| --- | --- |
| b2c3d4e5-f6a7-8901-bcde-f12345678901 | 3 |

## 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: Login and navigate | `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:36:28.791Z

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

6 event(s) captured:

| Time | Type | Action | User | Org | Object ID | Performed | Reason |
|------|------|--------|------|-----|-----------|-----------|--------|
| 2026-04-23 03:36:33Z | user_log | user:login | bob.kauffman@stellartech.com | StellarTech Medical Solutions | — | — |  |
| 2026-04-23 03:36:42Z | user_log | user:login | bob.kauffman@stellartech.com | StellarTech Medical Solutions | — | — |  |
| 2026-04-23 03:36:50Z | user_log | user:login | bob.kauffman@stellartech.com | StellarTech Medical Solutions | — | — |  |
| 2026-04-23 03:36:57Z | user_log | user:login | bob.kauffman@stellartech.com | StellarTech Medical Solutions | — | — |  |
| 2026-04-23 03:37:04Z | user_log | user:login | bob.kauffman@stellartech.com | StellarTech Medical Solutions | — | — |  |
| 2026-04-23 03:37:11Z | user_log | user:login | bob.kauffman@stellartech.com | StellarTech Medical Solutions | — | — |  |
