API: Cancel All Seats from Issue

Request

Cancel all pending seat requests from a specific issue with a DELETE request:

POST /seat-requests/cancel-issue

Headers:


Content-Type: application/json
Authorization: Bearer {your_access_token}
                

Request Body:


{
  "issue_id": "ISSUE_20250828_001"
}
                

Success Response (200 OK):


{
  "status": "success",
  "code": 200,
  "message": "All seats cancelled from issue successfully",
  "data": {
    "issue_id": "ISSUE_20250828_001",
    "cancelled_seats_count": 3,
    "cancelled_seats": [
      {
        "seat_request_id": 123,
        "seat_inventory_id": 456,
        "seat_id": 101,
        "status": "cancelled"
      },
      {
        "seat_request_id": 124,
        "seat_inventory_id": 457,
        "seat_id": 102,
        "status": "cancelled"
      },
      {
        "seat_request_id": 125,
        "seat_inventory_id": 458,
        "seat_id": 103,
        "status": "cancelled"
      }
    ],
    "user_id": 25,
    "cancelled_at": "2025-08-28T10:30:15.000000Z"
  }
}
                

Request Parameters:

  • issue_id - Required, the issue ID containing all seat requests to cancel

Response Fields:

  • issue_id - The cancelled issue identifier
  • cancelled_seats_count - Number of seats successfully cancelled
  • cancelled_seats - Array of all cancelled seat requests
  • user_id - ID of the user who cancelled the issue
  • cancelled_at - Timestamp when cancellation occurred

Key Features:

  • Bulk Cancellation - Cancel all seats in an issue with one request
  • Atomic Operation - All seats are cancelled together or not at all
  • Immediate Release - All cancelled seats become available instantly
  • Complete Cleanup - Entire issue is cleared from the system

Error Responses:

404 Not Found - No Pending Requests

{
  "status": "error",
  "code": 404,
  "message": "No pending seat requests found for this issue",
  "data": null
}
                
422 Validation Error - Invalid Data

{
  "status": "error",
  "code": 422,
  "message": "The given data was invalid.",
  "data": {
    "issue_id": ["The issue id field is required."]
  }
}
                
500 Server Error - Database Error

{
  "status": "error",
  "code": 500,
  "message": "Failed to cancel seat request: Database connection error",
  "data": null
}
                

JavaScript Example:


async function cancelAllSeatsFromIssue(issueId) {
  try {
    const response = await fetch('/api/seat-requests/cancel-issue', {
      method: 'DELETE',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${localStorage.getItem('access_token')}`
      },
      body: JSON.stringify({
        issue_id: issueId
      })
    });

    if (!response.ok) {
      const errorData = await response.json();
      throw new Error(errorData.message);
    }

    const data = await response.json();

    console.log('Issue cancelled successfully:');
    console.log(`- Issue ID: ${data.data.issue_id}`);
    console.log(`- Cancelled seats: ${data.data.cancelled_seats_count}`);

    // Log each cancelled seat
    data.data.cancelled_seats.forEach(seat => {
      console.log(`  - Seat request ${seat.seat_request_id}: cancelled`);
    });

    // Clear the UI
    clearSeatSelection();
    resetIssueState();

    return data;
  } catch (error) {
    console.error('Error cancelling issue:', error);
    showErrorMessage(`Failed to cancel all seats: ${error.message}`);
    throw error;
  }
}

// Usage example with confirmation
async function cancelIssueWithConfirmation(issueId, seatCount) {
  const message = `Are you sure you want to cancel all ${seatCount} seat(s) from issue ${issueId}?`;
  const confirm = window.confirm(message);

  if (confirm) {
    try {
      const result = await cancelAllSeatsFromIssue(issueId);

      showSuccessMessage(
        `Successfully cancelled ${result.data.cancelled_seats_count} seats from issue ${issueId}`
      );

      // Redirect to seat selection or trip search
      redirectToSeatSelection();

      return result;
    } catch (error) {
      // Error handling is done in cancelAllSeatsFromIssue
    }
  } else {
    console.log('Issue cancellation aborted by user');
  }
}

// Enhanced usage with pre-flight check
async function safeCancelIssue(issueId) {
  try {
    // First check current status
    const statusResponse = await fetch(`/api/seat-requests/${issueId}`, {
      headers: {
        'Authorization': `Bearer ${localStorage.getItem('access_token')}`
      }
    });

    if (!statusResponse.ok) {
      throw new Error('Could not check issue status');
    }

    const statusData = await statusResponse.json();
    const pendingSeats = statusData.data.seats.filter(s => s.status === 'pending');

    if (pendingSeats.length === 0) {
      showInfoMessage('No pending seats to cancel in this issue');
      return null;
    }

    // Show detailed confirmation
    const seatNumbers = pendingSeats.map(s => s.seat_info.seat.seat_number).join(', ');
    const confirmMessage = `Cancel ${pendingSeats.length} pending seats (${seatNumbers}) from issue ${issueId}?`;

    if (window.confirm(confirmMessage)) {
      const result = await cancelAllSeatsFromIssue(issueId);

      showSuccessMessage(
        `Successfully cancelled seats: ${seatNumbers}`
      );

      return result;
    }

    return null;
  } catch (error) {
    showErrorMessage(`Error during cancellation: ${error.message}`);
    throw error;
  }
}

// Batch operations helper
async function cancelMultipleIssues(issueIds) {
  const results = [];
  const errors = [];

  for (const issueId of issueIds) {
    try {
      const result = await cancelAllSeatsFromIssue(issueId);
      results.push(result);
    } catch (error) {
      errors.push({ issueId, error: error.message });
    }
  }

  // Report results
  if (results.length > 0) {
    const totalCancelled = results.reduce((sum, r) => sum + r.data.cancelled_seats_count, 0);
    showSuccessMessage(`Successfully cancelled ${totalCancelled} seats from ${results.length} issues`);
  }

  if (errors.length > 0) {
    showErrorMessage(`Failed to cancel ${errors.length} issues`);
    console.error('Cancellation errors:', errors);
  }

  return { results, errors };
}

// Helper functions
function clearSeatSelection() {
  // Clear all selected seats from UI
  document.querySelectorAll('.seat.selected').forEach(seat => {
    seat.classList.remove('selected');
    seat.classList.add('available');
  });
}

function resetIssueState() {
  // Reset issue-related UI state
  const issueInfoElement = document.getElementById('issue-info');
  if (issueInfoElement) {
    issueInfoElement.innerHTML = '

No seats selected

'; } // Clear stored issue ID sessionStorage.removeItem('current_issue_id'); } function showSuccessMessage(message) { // Your success notification implementation console.log('[SUCCESS]', message); } function showErrorMessage(message) { // Your error notification implementation console.log('[ERROR]', message); } function showInfoMessage(message) { // Your info notification implementation console.log('[INFO]', message); } function redirectToSeatSelection() { // Redirect back to seat selection window.location.href = '/select-seats'; }

Use Cases:

  • Complete Cancellation - User decides not to proceed with any seat selection
  • Start Over - User wants to start fresh with seat selection
  • Timeout Prevention - Cancel all seats before they expire automatically
  • Session Cleanup - Clear all selections when user leaves booking flow
  • Group Booking Abort - Cancel entire group reservation

Best Practices:

  • Confirmation - Always confirm before cancelling multiple seats
  • Status Check - Verify issue status before attempting cancellation
  • Clear Feedback - Show exactly which seats were cancelled
  • UI Reset - Clear all seat selection UI after successful cancellation
  • Error Recovery - Handle partial failures gracefully
  • Audit Trail - Log bulk cancellations for tracking purposes

Comparison with Individual Cancellation:

Feature Individual Cancellation Issue Cancellation
Endpoint /seat-requests/cancel /seat-requests/cancel-issue
Scope Single seat request All seats in issue
Parameters seat_inventory_id + issue_id issue_id only
Use Case Selective cancellation Complete cancellation
Issue Impact Issue continues with remaining seats Entire issue is cleared

Notes:

  • Only cancels pending seat requests - already booked seats are not affected
  • Operation is atomic - all seats are cancelled together or none at all
  • All cancelled seats become immediately available for other users
  • The issue ID becomes invalid after successful cancellation
  • Cannot be undone - user must create new seat requests if needed