# Validation Report: URS-072

**Title:** User transfers inventory to another user through the field-transfer lifecycle
**Date:** 2026-08-03T23:05:21.655Z
**Duration:** 73.8s
**Overall Status:** ✅ PASS

## User Requirement

> The system shall let a user transfer inventory to another user through a controlled field-transfer lifecycle — recipient approval, manual shipment with carrier and tracking, and receipt confirmation — recording each status transition, relocating the inventory to the destination and flipping it to available only upon receipt, and recording an audit decision at each lifecycle step.

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

## Environment

- **Inbox URL:** http://localhost:37247
- **Database:** localhost:34769/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: Initiate the field transfer — ✅ PASS

**What this step proves:**

A Corveta sales rep (Blair Bennett) opens /transfers and initiates a new field transfer to a second rep (Rana Reyes). The wizard collects the destination, the item to move from the seeded source trunk lot, and the shipping mode ("Ship to recipient"). Submitting creates the transfer at status pending_receiver_approval, allocates an FT-{n} number, immediately reserves the inventory in transit at the target, and records the opening status change. The initiate path logs a field_transfer.initiate decision. This verifies a rep can start a controlled transfer to another user.

**Audit events generated by this step:**

*(Evidence scoped to step execution window: 2026-08-03T23:05:59.639Z → 2026-08-03T23:06:13.877Z)*

| Time | Type | Action | User | Org | Performed |
|------|------|--------|------|-----|-----------|
| 2026-08-03 23:06:13Z | checklist | checklists.create | blair.bennett@corvetasurgical.com | Corveta Surgical Group | — |
| 2026-08-03 23:06:13Z | decision | field_transfer.initiate | blair.bennett@corvetasurgical.com | Corveta Surgical Group | yes |
| 2026-08-03 23:06:13Z | decision | send_field_transfer_initiated_notification | — | Vantis | yes |

**Screenshots:**

![step 01 wizard start](screenshots/step-01-wizard-start.png)

![step 01 products selected](screenshots/step-01-products-selected.png)

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

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

**Video recording:**

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

---

### 2. Step 2: Recipient approves the transfer for shipment — ✅ PASS

**What this step proves:**

The recipient (Rana Reyes) logs in, opens the transfer, and approves it. Because the transfer ships with an external label, approval confirms the ship-to address and advances the transfer from pending_receiver_approval to pending_shipment (the inventory stays reserved in transit). The approval logs a transfer.approve_receiver decision and a transfer_approve_receiver audit event. This verifies the recipient controls whether the transfer proceeds.

**Audit events generated by this step:**

*(Evidence scoped to step execution window: 2026-08-03T23:06:18.401Z → 2026-08-03T23:06:20.030Z)*

| Time | Type | Action | User | Org | Performed |
|------|------|--------|------|-----|-----------|
| 2026-08-03 23:06:19Z | decision | transfer.approve_receiver | rana.reyes@corvetasurgical.com | Corveta Surgical Group | yes |
| 2026-08-03 23:06:19Z | decision | tickets.checklist_item_resolve.auto_resolve_ticket | — | Corveta Surgical Group | no |
| 2026-08-03 23:06:19Z | decision | field_transfer.approve_for_shipment | rana.reyes@corvetasurgical.com | Corveta Surgical Group | yes |
| 2026-08-03 23:06:19Z | transfer | transfer_approve_receiver | rana.reyes@corvetasurgical.com | Corveta Surgical Group | — |

**Screenshots:**

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

![step 02 approved](screenshots/step-02-approved.png)

**Video recording:**

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

---

### 3. Step 3: Sender records the manual shipment — ✅ PASS

**What this step proves:**

The sender (Blair Bennett) records the manual carrier shipment — carrier and tracking number — which advances the transfer from pending_shipment to in_transit and stamps shipped_at / shipped_by. No inventory moves here (it is already reserved at the target). The shipment logs a transfer.mark_shipped decision and a transfer_mark_shipped audit event. This verifies shipment details are captured against the transfer.

**Audit events generated by this step:**

*(Evidence scoped to step execution window: 2026-08-03T23:06:25.985Z → 2026-08-03T23:06:26.789Z)*

| Time | Type | Action | User | Org | Performed |
|------|------|--------|------|-----|-----------|
| 2026-08-03 23:06:26Z | transfer | transfer_mark_shipped | blair.bennett@corvetasurgical.com | Corveta Surgical Group | — |
| 2026-08-03 23:06:26Z | decision | transfer.mark_shipped | blair.bennett@corvetasurgical.com | Corveta Surgical Group | yes |

**Screenshots:**

![step 03 shipment form](screenshots/step-03-shipment-form.png)

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

**Video recording:**

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

---

### 4. Step 4: Recipient records receipt and completes the transfer — ✅ PASS

**What this step proves:**

The recipient (Rana Reyes) records receipt, which writes the inbound-verification checkpoint and then completes the transfer: status becomes completed, received_at / received_by are stamped, and the moved inventory flips from in_transit to ready at the recipient's trunk. Receipt logs a transfer.record_receipt decision and a transfer_record_receipt audit event. This is the primary URS-072 evidence that the transfer completes and the inventory lands at the destination.

**Audit events generated by this step:**

*(Evidence scoped to step execution window: 2026-08-03T23:06:31.856Z → 2026-08-03T23:06:32.664Z)*

| Time | Type | Action | User | Org | Performed |
|------|------|--------|------|-----|-----------|
| 2026-08-03 23:06:32Z | decision | field_transfer.receive_tote | rana.reyes@corvetasurgical.com | Corveta Surgical Group | no |
| 2026-08-03 23:06:32Z | decision | field_transfer.receive | rana.reyes@corvetasurgical.com | Corveta Surgical Group | yes |
| 2026-08-03 23:06:32Z | decision | loan.advanceOnFieldTransferReceipt | rana.reyes@corvetasurgical.com | Corveta Surgical Group | no |
| 2026-08-03 23:06:32Z | decision | transfer.record_receipt | rana.reyes@corvetasurgical.com | Corveta Surgical Group | yes |
| 2026-08-03 23:06:32Z | transfer | transfer_record_receipt | rana.reyes@corvetasurgical.com | Corveta Surgical Group | — |
| 2026-08-03 23:06:32Z | decision | send_field_transfer_received_notification | — | Vantis | yes |

**Screenshots:**

![step 04 receipt form](screenshots/step-04-receipt-form.png)

![step 04 completed](screenshots/step-04-completed.png)

**Video recording:**

[▶ Watch step recording](videos/step-04-receive.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.

### Completed field transfer created for Blair → Rana with shipment details — ✅ PASS

**Assertion:** A URS-072 field transfer should exist with status=completed, owning org=Vantis, recipient=Rana, shipping_mode=external_label, carrier=FedEx, tracking=URS072-TRACK-001, and shipped_at/received_at stamped (marker: "URS-072 validation run").

```sql
SELECT id, transfer_number, status, owning_organization_id,
      requesting_organization_id, initiated_by_user_id, sender_user_id, recipient_user_id,
      shipping_mode, carrier, tracking_number, shipped_at, shipped_by_user_id,
      received_at, received_by_user_id, notes, created_at
    FROM field_transfers
    WHERE initiated_by_user_id = $1
      AND requesting_organization_id = $2
      AND notes LIKE '%URS-072%'
      AND created_at > NOW() - INTERVAL '2 hours'
    ORDER BY created_at DESC
```

| id | transfer_number | status | owning_organization_id | requesting_organization_id | initiated_by_user_id | sender_user_id | recipient_user_id | shipping_mode | carrier | tracking_number | shipped_at | shipped_by_user_id | received_at | received_by_user_id | notes | created_at |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 019fc9e0-b151-720d-bfa3-2d2cdb06a86c | FT-1 | completed | a1b2c3d4-e5f6-7890-abcd-ef1234567890 | b2c3d4e5-f6a7-8901-bcde-f12345678901 | 17b8c9d0-e1f2-3456-1234-567890123456 | 17b8c9d0-e1f2-3456-1234-567890123456 | 28c9d0e1-f2a3-4567-2345-678901234567 | external_label | FedEx | URS072-TRACK-001 | 2026-08-03T23:06:26.557Z | 17b8c9d0-e1f2-3456-1234-567890123456 | 2026-08-03T23:06:32.427Z | 28c9d0e1-f2a3-4567-2345-678901234567 | URS-072 validation run — submitted at 2026-08-03T23:06:09.297Z | 2026-08-03T23:06:13.697Z |

### Status-change chain records the full shipped lifecycle — ✅ PASS

**Assertion:** The field_transfer_status_changes log should record the transitions to pending_receiver_approval, pending_shipment, in_transit, and completed.

```sql
SELECT from_status, to_status, created_at
    FROM field_transfer_status_changes
    WHERE field_transfer_id = $1
    ORDER BY created_at ASC
```

| from_status | to_status | created_at |
| --- | --- | --- |
| NULL | pending_receiver_approval | 2026-08-03T23:06:13.697Z |
| pending_receiver_approval | pending_shipment | 2026-08-03T23:06:19.803Z |
| pending_shipment | in_transit | 2026-08-03T23:06:26.555Z |
| in_transit | pending_inbound_verification | 2026-08-03T23:06:32.423Z |
| pending_inbound_verification | completed | 2026-08-03T23:06:32.423Z |

### Item movement fully received — ✅ PASS

**Assertion:** The transfer's item_movement_items should show quantity_received = quantity_expected (> 0), proving the moved units were received.

```sql
SELECT mi.quantity_expected, mi.quantity_received
    FROM item_movement_items mi
    JOIN item_movements m ON m.id = mi.movement_id
    WHERE m.field_transfer_id = $1
```

| quantity_expected | quantity_received |
| --- | --- |
| 1 | 1 |

### Moved inventory is available at the recipient's trunk — ✅ PASS

**Assertion:** After receipt, an inventory_items row for lot URS072-SHV-001 should exist at Rana's trunk with quantity_ready > 0 and quantity_in_transit = 0 (the moved units landed and are ready).

```sql
SELECT id, real_world_location_id, lot, quantity_ready, quantity_in_transit
    FROM inventory_items
    WHERE real_world_location_id = $1
      AND lot = $2
      AND manufacturer_organization_id = $3
      AND quantity_ready > 0
      AND quantity_in_transit = 0
```

| id | real_world_location_id | lot | quantity_ready | quantity_in_transit |
| --- | --- | --- | --- | --- |
| 019fc9e0-b15c-731a-92b7-19302e7a0f46 | b7f8a9b0-c1d2-3456-1234-567890123456 | URS072-SHV-001 | 1 | 0 |

### Source lot depleted at the sender's trunk — ✅ PASS

**Assertion:** After the transfer, the source lot URS072-SHV-001 at Blair's trunk should have quantity_ready = 0 (all transferred units left the source).

```sql
SELECT COALESCE(SUM(quantity_ready), 0)::int AS remaining_ready
    FROM inventory_items
    WHERE real_world_location_id = $1
      AND lot = $2
      AND manufacturer_organization_id = $3
```

| remaining_ready |
| --- |
| 0 |

### Each lifecycle step recorded a decision audit event — ✅ PASS

**Assertion:** The shipped lifecycle should log decision audit events for field_transfer.initiate, transfer.approve_receiver, transfer.mark_shipped, and transfer.record_receipt within the run window.

```sql
SELECT action, object_id, payload, created_at
    FROM audit_events
    WHERE created_at >= $1
      AND event_type = 'decision'
      AND action = ANY($2)
      AND object_id = $3
    ORDER BY created_at ASC
```

| action | object_id | payload | created_at |
| --- | --- | --- | --- |
| field_transfer.initiate | 019fc9e0-b151-720d-bfa3-2d2cdb06a86c | `{"reason":"Field transfer initiated","itemCount":1,"performed":true,"toteCount":0,"entityType":"field_transfer","recipientOrganizationId":"b2c3d4e5-f6a7-8901-bcde-f12345678901","crossOrgAuthorizationReason":null}` | 2026-08-03T23:06:13.697Z |
| transfer.approve_receiver | 019fc9e0-b151-720d-bfa3-2d2cdb06a86c | `{"reason":"Shipped trunk transfer approved for shipment","performed":true,"entityType":"field_transfer","shippingMode":"external_label"}` | 2026-08-03T23:06:19.803Z |
| transfer.mark_shipped | 019fc9e0-b151-720d-bfa3-2d2cdb06a86c | `{"reason":"Manual shipment label recorded","performed":true,"entityType":"field_transfer","shippingMode":"external_label","hasLabelEvidence":false}` | 2026-08-03T23:06:26.555Z |
| transfer.record_receipt | 019fc9e0-b151-720d-bfa3-2d2cdb06a86c | `{"reason":"Field transfer receipt recorded and completed","performed":true,"entityType":"field_transfer","shippingMode":"external_label","hasReceiptNotes":false,"receiptEvidenceCount":0}` | 2026-08-03T23:06:32.423Z |

## 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: Initiate the field transfer | `decision:field_transfer.initiate` | ✅ |
| Step 2: Recipient approves the transfer for shipment | `decision:transfer.approve_receiver` | ✅ |
| Step 3: Sender records the manual shipment | `decision:transfer.mark_shipped` | ✅ |
| Step 4: Recipient records receipt and completes the transfer | `decision:transfer.record_receipt` | ✅ |

## 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:05:19.795Z

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

23 event(s) captured:

| Time | Type | Action | User | Org | Object ID | Performed | Reason |
|------|------|--------|------|-----|-----------|-----------|--------|
| 2026-08-03 23:05:20Z | checklist | checklists.create | — | Corveta Surgical Group | 019fc9df-e295-7e5f-9b20-44ed50d0ce8e | — |  |
| 2026-08-03 23:05:21Z | 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:05:56Z | user_log | user:login | blair.bennett@corvetasurgical.com | Corveta Surgical Group | — | — |  |
| 2026-08-03 23:06:13Z | checklist | checklists.create | blair.bennett@corvetasurgical.com | Corveta Surgical Group | 019fc9e0-b167-704e-9675-c8186ca712dd | — |  |
| 2026-08-03 23:06:13Z | decision | field_transfer.initiate | blair.bennett@corvetasurgical.com | Corveta Surgical Group | 019fc9e0-b151-720d-bfa3-2d2cdb06a86c | yes | Field transfer initiated |
| 2026-08-03 23:06:13Z | decision | send_field_transfer_initiated_notification | — | Vantis | 019fc9e0-b151-720d-bfa3-2d2cdb06a86c | yes | Notifying sender (17b8c9d0-e1f2-3456-1234-567890123456) and recipient (28c9d0e1-f2a3-4567-2345-678901234567) |
| 2026-08-03 23:06:14Z | transactional_email | field_transfer_initiated | — | Vantis | 019fc9e0-b151-720d-bfa3-2d2cdb06a86c | — |  |
| 2026-08-03 23:06:15Z | user_log | user:login | rana.reyes@corvetasurgical.com | Corveta Surgical Group | — | — |  |
| 2026-08-03 23:06:19Z | decision | transfer.approve_receiver | rana.reyes@corvetasurgical.com | Corveta Surgical Group | 019fc9e0-b151-720d-bfa3-2d2cdb06a86c | yes | Shipped trunk transfer approved for shipment |
| 2026-08-03 23:06:19Z | decision | tickets.checklist_item_resolve.auto_resolve_ticket | — | Corveta Surgical Group | 019fc9e0-b16d-7fee-9ad0-f9d5b2eed21f | no | Checklist item is not linked to any ticket. |
| 2026-08-03 23:06:19Z | decision | field_transfer.approve_for_shipment | rana.reyes@corvetasurgical.com | Corveta Surgical Group | 019fc9e0-b151-720d-bfa3-2d2cdb06a86c | yes | Field transfer approved for shipment |
| 2026-08-03 23:06:19Z | transfer | transfer_approve_receiver | rana.reyes@corvetasurgical.com | Corveta Surgical Group | 019fc9e0-b151-720d-bfa3-2d2cdb06a86c | — |  |
| 2026-08-03 23:06:21Z | user_log | user:login | blair.bennett@corvetasurgical.com | Corveta Surgical Group | — | — |  |
| 2026-08-03 23:06:26Z | transfer | transfer_mark_shipped | blair.bennett@corvetasurgical.com | Corveta Surgical Group | 019fc9e0-b151-720d-bfa3-2d2cdb06a86c | — |  |
| 2026-08-03 23:06:26Z | decision | transfer.mark_shipped | blair.bennett@corvetasurgical.com | Corveta Surgical Group | 019fc9e0-b151-720d-bfa3-2d2cdb06a86c | yes | Manual shipment label recorded |
| 2026-08-03 23:06:28Z | user_log | user:login | rana.reyes@corvetasurgical.com | Corveta Surgical Group | — | — |  |
| 2026-08-03 23:06:32Z | decision | field_transfer.receive_tote | rana.reyes@corvetasurgical.com | Corveta Surgical Group | 019fc9e0-b151-720d-bfa3-2d2cdb06a86c | no | No linked totes to transition |
| 2026-08-03 23:06:32Z | decision | field_transfer.receive | rana.reyes@corvetasurgical.com | Corveta Surgical Group | 019fc9e0-b151-720d-bfa3-2d2cdb06a86c | yes | Field transfer receipt completed |
| 2026-08-03 23:06:32Z | decision | loan.advanceOnFieldTransferReceipt | rana.reyes@corvetasurgical.com | Corveta Surgical Group | 019fc9e0-b151-720d-bfa3-2d2cdb06a86c | no | no linked loan |
| 2026-08-03 23:06:32Z | decision | transfer.record_receipt | rana.reyes@corvetasurgical.com | Corveta Surgical Group | 019fc9e0-b151-720d-bfa3-2d2cdb06a86c | yes | Field transfer receipt recorded and completed |
| 2026-08-03 23:06:32Z | transfer | transfer_record_receipt | rana.reyes@corvetasurgical.com | Corveta Surgical Group | 019fc9e0-b151-720d-bfa3-2d2cdb06a86c | — |  |
| 2026-08-03 23:06:32Z | decision | send_field_transfer_received_notification | — | Vantis | 019fc9e0-b151-720d-bfa3-2d2cdb06a86c | yes | Notifying sender (17b8c9d0-e1f2-3456-1234-567890123456) and recipient (28c9d0e1-f2a3-4567-2345-678901234567) |
| 2026-08-03 23:06:33Z | transactional_email | field_transfer_received | — | Vantis | 019fc9e0-b151-720d-bfa3-2d2cdb06a86c | — |  |

## Email Evidence

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

### 1. Field Transfer Initiated — FT-1

**Template:** `Field_Transfer_Initiated_—_FT-1`

![Field Transfer Initiated — FT-1](screenshots/emails/2026-08-03T23-06-14-904Z-Field_Transfer_Initiated_—_FT-1.png)

### 2. Field Transfer Received — FT-1

**Template:** `Field_Transfer_Received_—_FT-1`

![Field Transfer Received — FT-1](screenshots/emails/2026-08-03T23-06-33-454Z-Field_Transfer_Received_—_FT-1.png)
