Cancel all pending seat requests from a specific issue with a DELETE request:
POST /seat-requests/cancel-issue
Content-Type: application/json
Authorization: Bearer {your_access_token}
{
"issue_id": "ISSUE_20250828_001"
}
{
"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"
}
}
{
"status": "error",
"code": 404,
"message": "No pending seat requests found for this issue",
"data": null
}
{
"status": "error",
"code": 422,
"message": "The given data was invalid.",
"data": {
"issue_id": ["The issue id field is required."]
}
}
{
"status": "error",
"code": 500,
"message": "Failed to cancel seat request: Database connection error",
"data": null
}
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';
}
| 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 |