From bbe725dd9e4f142714c19deb79f5a3fe457271f1 Mon Sep 17 00:00:00 2001 From: paritosh18 Date: Mon, 1 Dec 2025 13:29:10 +0530 Subject: [PATCH] Update HTTP methods to PATCH for rejectHostApplication endpoints and implement pagination in getAllInvitationDetails and getAllInvitedCoadminAndAM handlers --- serverless/functions/minglaradmin.yml | 4 +- .../getOnboardingNewApplications.ts | 67 +++++--- .../teammates/getAllInvitationDetails.ts | 79 +++++---- .../teammates/getAllInvitedCoadminAndAM.ts | 78 +++++---- .../minglaradmin/services/minglar.service.ts | 154 ++++++++++++------ 5 files changed, 250 insertions(+), 132 deletions(-) diff --git a/serverless/functions/minglaradmin.yml b/serverless/functions/minglaradmin.yml index a8c19c8..2e06928 100644 --- a/serverless/functions/minglaradmin.yml +++ b/serverless/functions/minglaradmin.yml @@ -361,7 +361,7 @@ rejectHostApplication: events: - httpApi: path: /minglaradmin/hosthub/onboarding/reject-host-application - method: post + method: patch rejectHostApplicationAM: handler: src/modules/minglaradmin/handlers/hosthub/hosts/rejectHostApplicationAM.handler @@ -377,7 +377,7 @@ rejectHostApplicationAM: events: - httpApi: path: /minglaradmin/hosthub/hosts/reject-host-application-am - method: post + method: patch addPQQSuggestion: handler: src/modules/minglaradmin/handlers/hosthub/hosts/addPQQSuggestion.handler diff --git a/src/modules/minglaradmin/handlers/hosthub/onboarding/getOnboardingNewApplications.ts b/src/modules/minglaradmin/handlers/hosthub/onboarding/getOnboardingNewApplications.ts index f0b6429..f7b6a24 100644 --- a/src/modules/minglaradmin/handlers/hosthub/onboarding/getOnboardingNewApplications.ts +++ b/src/modules/minglaradmin/handlers/hosthub/onboarding/getOnboardingNewApplications.ts @@ -1,9 +1,14 @@ import { verifyOnlyMinglarAdminToken } from '../../../../../common/middlewares/jwt/authForOnlyMinglarAdmin'; -import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda'; +import { + APIGatewayProxyEvent, + APIGatewayProxyResult, + Context, +} from 'aws-lambda'; import { PrismaService } from '../../../../../common/database/prisma.service'; import { safeHandler } from '../../../../../common/utils/handlers/safeHandler'; import ApiError from '../../../../../common/utils/helper/ApiError'; import { MinglarService } from '../../../services/minglar.service'; +import { paginationService } from '../../../../../common/utils/pagination/pagination.service'; const prismaService = new PrismaService(); const minglarService = new MinglarService(prismaService); @@ -12,14 +17,19 @@ const minglarService = new MinglarService(prismaService); * Get all host applications handler * Returns host details with status, submission date, and account manager info */ -export const handler = safeHandler(async ( +export const handler = safeHandler( + async ( event: APIGatewayProxyEvent, - context?: Context -): Promise => { + context?: Context, + ): Promise => { // Verify authentication token - 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(401, 'This is a protected route. Please provide a valid token.'); + throw new ApiError( + 401, + 'This is a protected route. Please provide a valid token.', + ); } // Verify token and get user info @@ -27,27 +37,42 @@ export const handler = safeHandler(async ( // Get user details including role const user = await prismaService.user.findUnique({ - where: { id: userInfo.id }, - select: { id: true, roleXid: true } + where: { id: userInfo.id }, + select: { id: true, roleXid: true }, }); if (!user) { - throw new ApiError(404, 'User not found'); + throw new ApiError(404, 'User not found'); } + // Pagination + const paginationParams = paginationService.getPaginationFromEvent(event); + const paginationOptions = + paginationService.parsePaginationParams(paginationParams); + // Get all host applications from service based on user role - const hostApplications = await minglarService.getAllOnboardingHostApplications_New(); + const { data, totalCount } = + await minglarService.getAllOnboardingHostApplications_New( + paginationOptions, + ); + + const paginatedResponse = paginationService.createPaginatedResponse( + data, + totalCount, + paginationOptions, + ); return { - statusCode: 200, - headers: { - 'Content-Type': 'application/json', - 'Access-Control-Allow-Origin': '*', - }, - body: JSON.stringify({ - success: true, - message: 'Host applications retrieved successfully', - data: hostApplications, - }), + statusCode: 200, + headers: { + 'Content-Type': 'application/json', + 'Access-Control-Allow-Origin': '*', + }, + body: JSON.stringify({ + success: true, + message: 'Host applications retrieved successfully', + ...paginatedResponse, + }), }; -}); + }, +); diff --git a/src/modules/minglaradmin/handlers/settings/teammates/getAllInvitationDetails.ts b/src/modules/minglaradmin/handlers/settings/teammates/getAllInvitationDetails.ts index 8d94741..f575927 100644 --- a/src/modules/minglaradmin/handlers/settings/teammates/getAllInvitationDetails.ts +++ b/src/modules/minglaradmin/handlers/settings/teammates/getAllInvitationDetails.ts @@ -1,42 +1,65 @@ import { verifyOnlyMinglarAdminToken } from '@/common/middlewares/jwt/authForOnlyMinglarAdmin'; -import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda'; +import { + APIGatewayProxyEvent, + APIGatewayProxyResult, + Context, +} from 'aws-lambda'; import { PrismaService } from '../../../../../common/database/prisma.service'; import { safeHandler } from '../../../../../common/utils/handlers/safeHandler'; import ApiError from '../../../../../common/utils/helper/ApiError'; import { MinglarService } from '../../../services/minglar.service'; +import { paginationService } from '../../../../../common/utils/pagination/pagination.service'; const prismaService = new PrismaService(); const minglarService = new MinglarService(prismaService); -export const handler = safeHandler(async ( - event: APIGatewayProxyEvent, - context?: Context -): Promise => { - // Extract token from headers - 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.'); - } +export const handler = safeHandler( + async ( + event: APIGatewayProxyEvent, + context?: Context, + ): Promise => { + // Extract token from headers + 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.', + ); + } - // Authenticate user using the shared authForHost function - await verifyOnlyMinglarAdminToken(token); + // Authenticate user using the shared authForHost function + await verifyOnlyMinglarAdminToken(token); - // Extract search parameter from query string - const search = event.queryStringParameters?.search || ''; + // Extract search parameter from query string + const search = event.queryStringParameters?.search || ''; - const result = await minglarService.getAllInvitationDetails(search); + const paginationParams = paginationService.getPaginationFromEvent(event); + const paginationOptions = + paginationService.parsePaginationParams(paginationParams); - return { - statusCode: 200, - headers: { - 'Content-Type': 'application/json', - 'Access-Control-Allow-Origin': '*', - }, - body: JSON.stringify({ - success: true, - message: 'Data retrieved successfully', - data: result, - }), - }; -}); + const { data, totalCount } = await minglarService.getAllInvitationDetails( + search, + paginationOptions, + ); + const paginatedResponse = paginationService.createPaginatedResponse( + data, + totalCount, + paginationOptions, + ); + + return { + statusCode: 200, + headers: { + 'Content-Type': 'application/json', + 'Access-Control-Allow-Origin': '*', + }, + body: JSON.stringify({ + success: true, + message: 'Data retrieved successfully', + ...paginatedResponse, + }), + }; + }, +); diff --git a/src/modules/minglaradmin/handlers/settings/teammates/getAllInvitedCoadminAndAM.ts b/src/modules/minglaradmin/handlers/settings/teammates/getAllInvitedCoadminAndAM.ts index 9e626c7..3a02f4b 100644 --- a/src/modules/minglaradmin/handlers/settings/teammates/getAllInvitedCoadminAndAM.ts +++ b/src/modules/minglaradmin/handlers/settings/teammates/getAllInvitedCoadminAndAM.ts @@ -1,42 +1,64 @@ import { verifyOnlyMinglarAdminToken } from '@/common/middlewares/jwt/authForOnlyMinglarAdmin'; -import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda'; +import { + APIGatewayProxyEvent, + APIGatewayProxyResult, + Context, +} from 'aws-lambda'; import { PrismaService } from '../../../../../common/database/prisma.service'; import { safeHandler } from '../../../../../common/utils/handlers/safeHandler'; import ApiError from '../../../../../common/utils/helper/ApiError'; import { MinglarService } from '../../../services/minglar.service'; +import { paginationService } from '../../../../../common/utils/pagination/pagination.service'; const prismaService = new PrismaService(); const minglarService = new MinglarService(prismaService); -export const handler = safeHandler(async ( - event: APIGatewayProxyEvent, - context?: Context -): Promise => { - // Extract token from headers - 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.'); - } +export const handler = safeHandler( + async ( + event: APIGatewayProxyEvent, + context?: Context, + ): Promise => { + // Extract token from headers + 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.', + ); + } - // Authenticate user using the shared authForHost function - await verifyOnlyMinglarAdminToken(token); + // Authenticate user using the shared authForHost function + await verifyOnlyMinglarAdminToken(token); - // Extract search parameter from query string - const search = event.queryStringParameters?.search || ''; + // Extract search parameter from query string + const search = event.queryStringParameters?.search || ''; - const response = await minglarService.getAllInvitedCoadminAndAM(search); + // Pagination + const paginationParams = paginationService.getPaginationFromEvent(event); + const paginationOptions = + paginationService.parsePaginationParams(paginationParams); - return { - statusCode: 200, - headers: { - 'Content-Type': 'application/json', - 'Access-Control-Allow-Origin': '*', - }, - body: JSON.stringify({ - success: true, - message: 'Data retrieved successfully', - data: response, - }), - }; -}); + const { data, totalCount } = + await minglarService.getAllInvitedCoadminAndAM(search, paginationOptions); + const paginatedResponse = paginationService.createPaginatedResponse( + data, + totalCount, + paginationOptions, + ); + + return { + statusCode: 200, + headers: { + 'Content-Type': 'application/json', + 'Access-Control-Allow-Origin': '*', + }, + body: JSON.stringify({ + success: true, + message: 'Data retrieved successfully', + ...paginatedResponse, + }), + }; + }, +); \ No newline at end of file diff --git a/src/modules/minglaradmin/services/minglar.service.ts b/src/modules/minglaradmin/services/minglar.service.ts index 6ad067a..31597a7 100644 --- a/src/modules/minglaradmin/services/minglar.service.ts +++ b/src/modules/minglaradmin/services/minglar.service.ts @@ -637,25 +637,33 @@ export class MinglarService { } } - async getAllInvitationDetails(search?: string) { - // Build search filter if search term is provided - const userSearchFilter = search - ? { - OR: [ - { emailAddress: { contains: search, mode: 'insensitive' as const } }, - { firstName: { contains: search, mode: 'insensitive' as const } }, - { lastName: { contains: search, mode: 'insensitive' as const } }, - { userRefNumber: { contains: search, mode: 'insensitive' as const } }, - ], - } - : {}; + async getAllInvitationDetails( + search?: string, + paginationOptions?: PaginationOptions, + ) { + const filters: any = { + isMinglarInvitation: true, + isActive: true, + }; - return await this.prisma.inviteDetails.findMany({ - where: { - isMinglarInvitation: true, - isActive: true, - user: search ? userSearchFilter : undefined, - }, + if (search?.trim()) { + const term = search.trim(); + filters.user = { + OR: [ + { emailAddress: { contains: term, mode: 'insensitive' as const } }, + { firstName: { contains: term, mode: 'insensitive' as const } }, + { lastName: { contains: term, mode: 'insensitive' as const } }, + { userRefNumber: { contains: term, mode: 'insensitive' as const } }, + ], + }; + } + + const totalCount = await this.prisma.inviteDetails.count({ + where: filters, + }); + + const invitations = await this.prisma.inviteDetails.findMany({ + where: filters, include: { user: { select: { @@ -675,7 +683,17 @@ export class MinglarService { }, }, }, + orderBy: { + createdAt: 'desc', + }, + skip: paginationOptions?.skip ?? 0, + take: paginationOptions?.limit ?? 10, }); + + return { + data: invitations, + totalCount, + }; } // Update your MinglarService method @@ -879,12 +897,18 @@ export class MinglarService { return onBoardingHostApp; } - async getAllOnboardingHostApplications_New() { + async getAllOnboardingHostApplications_New( + paginationOptions?: PaginationOptions, + ) { + const where = { + isActive: true, + adminStatusInternal: MINGLAR_STATUS_INTERNAL.ADMIN_TO_REVIEW, + }; + + const totalCount = await this.prisma.hostHeader.count({ where }); + const onBoardingHostApp = await this.prisma.hostHeader.findMany({ - where: { - isActive: true, - adminStatusInternal: MINGLAR_STATUS_INTERNAL.ADMIN_TO_REVIEW, - }, + where, select: { id: true, companyName: true, @@ -928,6 +952,11 @@ export class MinglarService { }, }, }, + orderBy: { + createdAt: 'desc', + }, + skip: paginationOptions?.skip ?? 0, + take: paginationOptions?.limit ?? 10, }); const bucket = config.aws.bucketName; @@ -939,15 +968,18 @@ export class MinglarService { const am = host.accountManager; if (am?.profileImage) { - const key = am.profileImage.startsWith("http") - ? am.profileImage.split(".com/")[1] + const key = am.profileImage.startsWith('http') + ? am.profileImage.split('.com/')[1] : am.profileImage; am.profileImage = await getPresignedUrl(bucket, key); } } - return onBoardingHostApp; + return { + data: onBoardingHostApp, + totalCount, + }; } async getAllCoadminAndAM(search?: string) { @@ -1017,34 +1049,40 @@ export class MinglarService { })); } - async getAllInvitedCoadminAndAM(search?: string) { - // Build search filter if search term is provided - const searchFilter = search - ? { - OR: [ - { emailAddress: { contains: search, mode: 'insensitive' as const } }, - { firstName: { contains: search, mode: 'insensitive' as const } }, - { lastName: { contains: search, mode: 'insensitive' as const } }, - { userRefNumber: { contains: search, mode: 'insensitive' as const } }, - ], - } - : {}; - - return await this.prisma.user.findMany({ - where: { - roleXid: { - in: [ - ROLE.MINGLAR_ADMIN, // Admin - ROLE.CO_ADMIN, // Co-Admin - ROLE.ACCOUNT_MANAGER, // AM - ], - }, - isActive: true, - userStatus: { - not: USER_STATUS.DE_ACTIVATED, // Exclude DE_ACTIVATED status - }, - ...searchFilter, + async getAllInvitedCoadminAndAM( + search?: string, + paginationOptions?: PaginationOptions, + ) { + const baseFilters: any = { + roleXid: { + in: [ + ROLE.MINGLAR_ADMIN, // Admin + ROLE.CO_ADMIN, // Co-Admin + ROLE.ACCOUNT_MANAGER, // AM + ], }, + isActive: true, + userStatus: { + not: USER_STATUS.DE_ACTIVATED, // Exclude DE_ACTIVATED status + }, + }; + + if (search?.trim()) { + const term = search.trim(); + baseFilters.OR = [ + { emailAddress: { contains: term, mode: 'insensitive' as const } }, + { firstName: { contains: term, mode: 'insensitive' as const } }, + { lastName: { contains: term, mode: 'insensitive' as const } }, + { userRefNumber: { contains: term, mode: 'insensitive' as const } }, + ]; + } + + const totalCount = await this.prisma.user.count({ + where: baseFilters, + }); + + const users = await this.prisma.user.findMany({ + where: baseFilters, include: { role: { select: { @@ -1053,7 +1091,17 @@ export class MinglarService { }, }, }, + orderBy: { + createdAt: 'desc', + }, + skip: paginationOptions?.skip ?? 0, + take: paginationOptions?.limit ?? 10, }); + + return { + data: users, + totalCount, + }; } async assignAMToHost(