# Validation Report: URS-043

**Title:** Link shipments to orders with LOT numbers
**Date:** 2026-04-23T03:42:21.536Z
**Duration:** 45.2s
**Overall Status:** ✅ PASS

## User Requirement

> The system shall maintain traceability of a product's LOT through orders and shipments.

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

## Environment

- **Inbox URL:** http://localhost:64529
- **Database:** localhost:64530/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: Orders list shows ZBO-2025-001 — ✅ PASS

**What this step proves:**

Logs in as alex.admin@zurimed.com and navigates to /billing with the "All Orders" filter. Confirms ZBO-2025-001 (the Bill-Only Order that carries the seeded LOT numbers) is visible in the table. This is the entry point of the traceability chain.

**Screenshots:**

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

**Video recording:**

[▶ Watch step recording](videos/step-01-orders-list.webm)

---

### 2. Step 2: BO detail shows both LOT numbers — ✅ PASS

**What this step proves:**

Opens the ZBO-2025-001 detail page and verifies a "LOT/Serial" column header is rendered. Both seeded LOT numbers (LOT-SP-2024-0891 on line 1 and LOT-FL-2024-0334 on line 2) must appear on separate rows. This proves the order-to-LOT link in the chain.

**Screenshots:**

![step 02 bo detail lots](screenshots/step-02-bo-detail-lots.png)

**Video recording:**

[▶ Watch step recording](videos/step-02-bo-detail-lots.webm)

---

### 3. Step 3: Packages list — ✅ PASS

**What this step proves:**

Navigates to /packages and confirms both seeded Shipping Packages are visible: MAN-2025-0156 (the "linked" package whose items reference ZBO-2025-001) and MAN-2025-0147 (the "tracking" package used to validate carrier/tracking evidence).

**Screenshots:**

![step 03 packages list](screenshots/step-03-packages-list.png)

**Video recording:**

[▶ Watch step recording](videos/step-03-packages-list.webm)

---

### 4. Step 4: Package items reference source BO — ✅ PASS

**What this step proves:**

Opens MAN-2025-0156 detail page and confirms the items table includes "Order Number" and "Line Number" columns. Both rows must show ZBO-2025-001 as the order number and line numbers 1 and 2 respectively. This proves the shipment-to-order linkage required by URS-043.

**Screenshots:**

![step 04 package detail order linkage](screenshots/step-04-package-detail-order-linkage.png)

**Video recording:**

[▶ Watch step recording](videos/step-04-package-linked-to-order.webm)

---

### 5. Step 5: Tracking + carrier visible on shipment — ✅ PASS

**What this step proves:**

Opens MAN-2025-0147 detail page and confirms that both the carrier (FedEx) and the tracking number (775899342290) are rendered on the shipment entity. This validates the URS requirement that shipments surface tracking metadata.

**Screenshots:**

![step 05 tracking visible](screenshots/step-05-tracking-visible.png)

**Video recording:**

[▶ Watch step recording](videos/step-05-tracking-visible.webm)

---

### 6. Step 6a: Package → Order reference — ✅ PASS

**What this step proves:**

Starting from the MAN-2025-0156 package detail page, reads the ZBO-2025-001 order number from the items table. This is Part A of the end-to-end traceability walk: confirming the text reference exists so the user can look up the originating order.

**Screenshots:**

![step 06a package shows order number](screenshots/step-06a-package-shows-order-number.png)

**Video recording:**

[▶ Watch step recording](videos/step-06-traceability-walk.webm)

---

### 7. Step 6b: BO detail LOTs re-confirmed — ✅ PASS

**What this step proves:**

Follows the order number reference from the package detail back to the ZBO-2025-001 Bill-Only Order and re-confirms both LOT numbers are still present. This closes the full chain: Package → Order Number → LOT numbers, completing the traceability walk.

**Screenshots:**

![step 06b bo detail lots reconfirmed](screenshots/step-06b-bo-detail-lots-reconfirmed.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.

### Bill-Only Order carries the expected LOT numbers — ✅ PASS

**Assertion:** ZBO-2025-001 should own 2 line items with LOTs LOT-FL-2024-0334, LOT-SP-2024-0891, owned by the ZuriMED manufacturer org.

```sql

    SELECT bo.order_number, bo.manufacturer_organization_id, boi.lot_number, op.sku AS product_sku
      FROM billing_orders bo
      JOIN billing_order_items boi ON boi.billing_order_id = bo.id
      JOIN org_products op ON op.id = boi.product_id
     WHERE bo.id = $1
     ORDER BY boi.created_at, boi.id
```

| order_number | manufacturer_organization_id | lot_number | product_sku |
| --- | --- | --- | --- |
| ZBO-2025-001 | a1b2c3d4-e5f6-7890-abcd-ef1234567890 | LOT-SP-2024-0891 | SP019N1A |
| ZBO-2025-001 | a1b2c3d4-e5f6-7890-abcd-ef1234567890 | LOT-FL-2024-0334 | FL516SNA |

### Shipping Package items reference the Bill-Only Order by text linkage — ✅ PASS

**Assertion:** MAN-2025-0156 should have 2 items with order_number=ZBO-2025-001 and order_line_number ∈ (1, 2).

```sql

    SELECT sp.manifest_id, spi.order_number, spi.order_line_number, spi.quantity
      FROM shipping_packages sp
      JOIN shipping_package_items spi ON spi.package_id = sp.id
     WHERE sp.id = $1
     ORDER BY spi.order_line_number
```

| manifest_id | order_number | order_line_number | quantity |
| --- | --- | --- | --- |
| MAN-2025-0156 | ZBO-2025-001 | 1 | 5 |
| MAN-2025-0156 | ZBO-2025-001 | 2 | 3 |

### Shipping Package surfaces carrier + tracking number — ✅ PASS

**Assertion:** MAN-2025-0147 should report tracking_number=775899342290, carrier=FedEx, status=in_transit.

```sql

    SELECT manifest_id, tracking_number, carrier, status
      FROM shipping_packages
     WHERE id = $1
```

| manifest_id | tracking_number | carrier | status |
| --- | --- | --- | --- |
| MAN-2025-0147 | 775899342290 | FedEx | in_transit |

### Traceability join: BO ↔ Shipping Package links resolve to LOT-bearing rows — ✅ PASS

**Assertion:** Joining billing_order_items ↔ shipping_package_items on order_number should yield 4 rows (2 BO lines × 2 package lines for ZBO-2025-001), every row carrying a LOT, covering LOT-SP-2024-0891, LOT-FL-2024-0334.

```sql

    SELECT bo.order_number,
           boi.lot_number,
           sp.manifest_id,
           spi.order_line_number,
           spi.quantity
      FROM billing_orders bo
      JOIN billing_order_items boi
        ON boi.billing_order_id = bo.id
      JOIN shipping_package_items spi
        ON spi.order_number = bo.order_number
      JOIN shipping_packages sp
        ON sp.id = spi.package_id
     WHERE bo.id = $1
       AND sp.id = $2
     ORDER BY spi.order_line_number, boi.created_at, boi.id
```

| order_number | lot_number | manifest_id | order_line_number | quantity |
| --- | --- | --- | --- | --- |
| ZBO-2025-001 | LOT-SP-2024-0891 | MAN-2025-0156 | 1 | 5 |
| ZBO-2025-001 | LOT-FL-2024-0334 | MAN-2025-0156 | 1 | 5 |
| ZBO-2025-001 | LOT-SP-2024-0891 | MAN-2025-0156 | 2 | 3 |
| ZBO-2025-001 | LOT-FL-2024-0334 | MAN-2025-0156 | 2 | 3 |

## 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:42:19.640Z

<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:42:23Z | user_log | user:login | alex.admin@zurimed.com | ZuriMED | — | — |  |
| 2026-04-23 03:42:30Z | user_log | user:login | alex.admin@zurimed.com | ZuriMED | — | — |  |
| 2026-04-23 03:42:39Z | user_log | user:login | alex.admin@zurimed.com | ZuriMED | — | — |  |
| 2026-04-23 03:42:45Z | user_log | user:login | alex.admin@zurimed.com | ZuriMED | — | — |  |
| 2026-04-23 03:42:52Z | user_log | user:login | alex.admin@zurimed.com | ZuriMED | — | — |  |
| 2026-04-23 03:42:59Z | user_log | user:login | alex.admin@zurimed.com | ZuriMED | — | — |  |
