# Return Visit to Host Endpoint Guide

## Overview

The **Return Visit to Host** endpoint allows security personnel to return a visit request back to the host for corrections or additional information. This is different from rejecting a visit - it gives the host a chance to fix issues and resubmit.

## Endpoint Details

**URL**: `POST /api/visits/{id}/return`

**Authentication**: Required (Bearer token)

**Authorization**: `security_member`, `security_admin`, or `admin` roles only

## Request

### URL Parameters
- `id` (integer, required) - The visit ID

### Request Body
```json
{
  "reason": "Please provide additional documentation: company registration certificate and recent tax clearance"
}
```

### Validation Rules
- `reason` (string, required)
  - Minimum: 10 characters
  - Maximum: 500 characters

## Response

### Success Response (200 OK)
```json
{
  "message": "Visit returned to host for corrections",
  "status": "Pending Host",
  "data": {
    "id": 1,
    "status": "Pending Host",
    "rejection_reason": "Please provide additional documentation: company registration certificate and recent tax clearance"
  }
}
```

### Error Responses

#### 403 Forbidden
```json
{
  "message": "Forbidden"
}
```
User doesn't have required role (security_member, security_admin, or admin).

#### 404 Not Found
```json
{
  "message": "Visit not found"
}
```
Visit with the specified ID doesn't exist.

#### 422 Validation Error
```json
{
  "message": "The reason field is required.",
  "errors": {
    "reason": [
      "The reason field is required."
    ]
  }
}
```

## Status Flow

```
Pending Approve → [Return] → Pending Host
```

When a visit is returned:
1. Status changes from **"Pending Approve"** to **"Pending Host"**
2. The reason is stored in the `rejection_reason` field
3. Status history is updated with the transition
4. An email notification is sent to the host with the requested changes

## Use Cases

### 1. Missing Documentation
```json
{
  "reason": "Please provide the following documents: 1) Company registration certificate, 2) Tax clearance certificate from 2025"
}
```

### 2. Unclear Visit Purpose
```json
{
  "reason": "Visit purpose is too vague. Please provide specific meeting agenda and list of topics to be discussed"
}
```

### 3. Incomplete Visitor Information
```json
{
  "reason": "Additional visitor information required: Full names, ID numbers, and company affiliations for all attendees"
}
```

### 4. Compliance Issues
```json
{
  "reason": "Visit request does not meet security protocol requirements. Please review and update the visitor background check documentation"
}
```

### 5. Date/Time Conflicts
```json
{
  "reason": "Requested meeting time conflicts with facility maintenance schedule. Please propose alternative dates between Jan 10-15, 2026"
}
```

## Comparison: Return vs Reject

| Feature | Return to Host | Reject |
|---------|---------------|--------|
| **Final Decision** | No - allows resubmission | Yes - visit denied |
| **Status** | Pending Host | Rejected |
| **Host Action** | Can fix and resubmit | Cannot resubmit (must create new) |
| **Use When** | Fixable issues | Security concerns, policy violations |
| **Email Type** | "Please correct..." | "Visit rejected..." |
| **Tone** | Collaborative | Final |

## Implementation Details

### Controller Method
Location: `app/Http/Controllers/Api/VisitController.php:334`

```php
public function return(Request $request, int $id)
{
    $request->validate([
        'reason' => 'required|string|min:10|max:500',
    ]);

    $visit = Visit::findOrFail($id);

    $userEmail = $request->user();
    $userRole = UserRole::where('email', $userEmail)->first();

    // Check authorization
    if (!$userRole->hasRole(['security_member', 'security_admin', 'admin'])) {
        return response()->json(['message' => 'Forbidden'], 403);
    }

    // Transition to Pending Host
    $this->statusService->transition(
        $visit,
        'Pending Host',
        $request->reason,
        $userEmail,
        $userRole->name ?? null
    );

    // Send return email
    $this->emailService->sendSecurityReturnEmail($visit);

    return response()->json([
        'message' => 'Visit returned to host for corrections',
        'status' => 'Pending Host',
        'data' => [
            'id' => $visit->id,
            'status' => $visit->status,
            'rejection_reason' => $visit->rejection_reason,
        ],
    ]);
}
```

### Route
Location: `routes/api.php:84`

```php
Route::post('/{id}/return', [VisitController::class, 'return'])
    ->middleware('role:security_member,security_admin,admin');
```

## Testing with Postman

1. **Import Collection**: Use the updated `Beyti-API.postman_collection.json`

2. **Generate Token**:
   - Go to "Test Authentication" folder
   - Run "Generate Test Token" with security user:
     ```json
     {
       "email": "security@beyti.test"
     }
     ```

3. **Test Return Endpoint**:
   - Navigate to: **Visits → Return Visit to Host**
   - Update visit ID in URL (e.g., `:id` = `8`)
   - Modify reason in request body if needed
   - Click "Send"

4. **Verify Result**:
   - Check response status is "Pending Host"
   - Verify reason is stored
   - Check visit status in database or via GET endpoint

## Testing with cURL

```bash
curl -X POST "http://localhost:8080/beyti-api/public/api/visits/8/return" \
  -H "Authorization: Bearer YOUR_TOKEN_HERE" \
  -H "Content-Type: application/json" \
  -d '{
    "reason": "Please provide company registration certificate and visitor ID copies"
  }'
```

## Database Changes

When a visit is returned, the following database updates occur:

1. **visits table**:
   - `status` → "Pending Host"
   - `rejection_reason` → Provided reason
   - `reviewed_by_email` → Security user email
   - `reviewed_at` → Current timestamp
   - `updated_at` → Current timestamp

2. **visit_status_history table** (new record):
   - `visit_id` → Visit ID
   - `from_status` → "Pending Approve"
   - `to_status` → "Pending Host"
   - `changed_by_email` → Security user email
   - `changed_by_name` → Security user name
   - `reason` → Provided reason
   - `created_at` → Current timestamp

## Email Notification

An automated email is sent to the host via `EmailService::sendSecurityReturnEmail()` containing:

- Visit request ID
- Return reason
- Instructions for making corrections
- Link to update the visit (if applicable)
- Deadline for resubmission (if set)

## Best Practices

### Writing Good Return Reasons

✅ **Good Examples**:
- Be specific about what's missing
- Provide clear action items
- Reference specific documents or information needed
- Include deadlines if applicable

❌ **Bad Examples**:
- "Not enough info" (too vague)
- "Fix this" (not helpful)
- "Bad request" (doesn't explain what to fix)

### When to Use Return vs Reject

**Use Return when:**
- Information is incomplete but fixable
- Documentation is missing
- Visit purpose needs clarification
- Date/time adjustments needed
- Minor compliance issues that can be corrected

**Use Reject when:**
- Security policy violations
- Background check failures
- Visit purpose violates company policy
- Visitor on restricted list
- Fraudulent information detected

## Troubleshooting

### Issue: "Forbidden" Error
**Cause**: User doesn't have security role
**Solution**: Generate token with security user (security@beyti.test, security.admin@beyti.test, or admin@beyti.test)

### Issue: "Reason field is required"
**Cause**: Missing or empty reason in request body
**Solution**: Ensure reason is provided and is at least 10 characters

### Issue: "Visit not found"
**Cause**: Invalid visit ID
**Solution**: Verify visit ID exists using GET /api/visits endpoint

## Related Endpoints

- **Approve Visit**: `POST /api/visits/{id}/approve`
- **Reject Visit**: `POST /api/visits/{id}/reject`
- **Get Visit Details**: `GET /api/visits/{id}`
- **Update Visit**: `PUT /api/visits/{id}` (for host to fix issues)

## Status Workflow Reference

```
[Host creates visit]
        ↓
  Pending Visitor
        ↓
 [Visitor registers]
        ↓
  Pending Approve
        ↓
   ┌────┴────┐
   ↓         ↓
Approved  Return → Pending Host
   ↓                    ↓
Completed        [Host fixes] → Pending Approve (cycle repeats)

Alternative path:
Pending Approve → Reject → Rejected (final)
```
