Refactor openCanceledSlot handler to improve readability and error handling. Updated body structure to support multiple cancellations and enhanced token validation. Adjusted imports for better organization.

This commit is contained in:
paritosh18
2026-02-26 11:05:56 +05:30
parent e736cdaa7b
commit e49d08fb14
3 changed files with 728 additions and 692 deletions

View File

@@ -1,24 +1,31 @@
import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda';
import { safeHandler } from '../../../../../common/utils/handlers/safeHandler';
import {
APIGatewayProxyEvent,
APIGatewayProxyResult,
Context,
} from 'aws-lambda';
import { prismaClient } from '../../../../../common/database/prisma.lambda.service';
import { verifyHostToken } from '../../../../../common/middlewares/jwt/authForHost';
import { safeHandler } from '../../../../../common/utils/handlers/safeHandler';
import ApiError from '../../../../../common/utils/helper/ApiError';
import { SchedulingService } from '../../../services/activityScheduling.service';
import { HostService } from '../../../services/host.service';
import ApiError from '../../../../../common/utils/helper/ApiError';
import { verifyHostToken } from '../../../../../common/middlewares/jwt/authForHost';
import { scheduleActivity } from '../../../../../common/utils/validation/host/createSchedulingOfAct.validation';
import { z } from 'zod';
const schedulingService = new SchedulingService(prismaClient);
const hostService = new HostService(prismaClient);
export const handler = safeHandler(async (
export const handler = safeHandler(
async (
event: APIGatewayProxyEvent,
context?: Context
): Promise<APIGatewayProxyResult> => {
context?: Context,
): Promise<APIGatewayProxyResult> => {
// Extract token from headers
const token = event.headers['x-auth-token'] || event.headers['X-Auth-Token']
const token =
event.headers['x-auth-token'] || event.headers['X-Auth-Token'];
if (!token) {
throw new ApiError(400, 'This is a protected route. Please provide a valid token.');
throw new ApiError(
400,
'This is a protected route. Please provide a valid token.',
);
}
// Authenticate user using the shared authForHost function
@@ -26,60 +33,72 @@ export const handler = safeHandler(async (
const hostId = userInfo.id;
if (Number.isNaN(hostId)) {
throw new ApiError(400, 'Host id must be a number');
throw new ApiError(400, 'Host id must be a number');
}
const host = await hostService.getHostIdByUserXid(hostId);
if (!host) {
throw new ApiError(404, 'Host not found');
throw new ApiError(404, 'Host not found');
}
let body: { activityXid: number; venueXid: number; cancellationXid: number; slotXid: number; };
let body: {
activityXid: number;
venueXid: number;
cancellations: { cancellationXid: number; slotXid: number }[];
};
try {
body = event.body ? JSON.parse(event.body) : {};
body = event.body ? JSON.parse(event.body) : {};
} catch {
throw new ApiError(400, 'Invalid JSON payload');
throw new ApiError(400, 'Invalid JSON payload');
}
if (!body.activityXid || !body.venueXid || !body.cancellationXid || !body.slotXid) {
throw new ApiError(400, 'Missing required fields');
if (
!body.activityXid ||
!body.venueXid ||
!Array.isArray(body.cancellations) ||
body.cancellations.length === 0
) {
throw new ApiError(400, 'Missing required fields');
}
const activity = await schedulingService.getActivityByXid(body.activityXid);
if (!activity) {
throw new ApiError(404, "Activity not found");
throw new ApiError(404, 'Activity not found');
}
const venueExists = await schedulingService.getVenueFromVenueXid(
body.venueXid,
body.activityXid
body.venueXid,
body.activityXid,
);
if (!venueExists) {
throw new ApiError(
404,
`Venue not found for this activity`
)
throw new ApiError(404, `Venue not found for this activity`);
}
await schedulingService.openCanceledSlot(
Number(body.cancellationXid),
Number(body.slotXid),
body.cancellations.map((item: any) => ({
cancellationXid: Number(item.cancellationXid),
slotXid: Number(item.slotXid),
})),
);
const result = await schedulingService.getVenueDurationByAct(Number(body.activityXid), Number(hostId));
const result = await schedulingService.getVenueDurationByAct(
Number(body.activityXid),
Number(hostId),
);
return {
statusCode: 200,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
},
body: JSON.stringify({
success: true,
message: 'Slot opened successfully',
data: result
}),
statusCode: 200,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
},
body: JSON.stringify({
success: true,
message: 'Slot opened successfully',
data: result,
}),
};
});
},
);

File diff suppressed because it is too large Load Diff

View File

@@ -1546,16 +1546,21 @@ export class HostService {
for (const item of answers) {
const question = item.pqqQuestions;
const answer = item.pqqAnswers;
const answer = item.pqqAnswers; // may be null if no answer selected
const maxPoints = question.maxPoints;
const userPoints = answer.answerPoints;
// skip if question missing
if (!question) continue;
const maxPoints = Number(question.maxPoints || 0);
const userPoints = Number(answer?.answerPoints || 0);
totalUserPoints += userPoints;
totalMaxPoints += maxPoints;
// Category
const category = question.pqqSubCategories.category;
// Category (guard nested relations)
const category = question.pqqSubCategories?.category;
if (!category) continue;
const categoryId = category.id;
if (!categories[categoryId]) {