diff --git a/serverless/functions/host.yml b/serverless/functions/host.yml index d5b76b4..acc9c61 100644 --- a/serverless/functions/host.yml +++ b/serverless/functions/host.yml @@ -161,12 +161,12 @@ getPQQ_LastUpdatedQuestion: path: /host/Activity_Hub/OnBoarding/get-latest-pqq-question-details method: get -getAllActivity: - handler: src/modules/host/handlers/Activity_Hub/OnBoarding/getAllActivity.handler +getAllActivityType: + handler: src/modules/host/handlers/Activity_Hub/OnBoarding/getAllActivityType.handler memorySize: 384 package: patterns: - - 'src/modules/host/handlers/getActivity.*' + - 'src/modules/host/handlers/getActivityType.*' - 'src/modules/host/services/**' - ${file(./serverless/patterns/base.yml):pattern1} - ${file(./serverless/patterns/base.yml):pattern2} @@ -174,7 +174,23 @@ getAllActivity: - ${file(./serverless/patterns/base.yml):pattern4} events: - httpApi: - path: /host/Activity_Hub/OnBoarding/get-activity + path: /host/Activity_Hub/OnBoarding/get-activity-type + method: get + +getAllHostActivity: + handler: src/modules/host/handlers/Activity_Hub/OnBoarding/getAllHostActivity.handler + memorySize: 384 + package: + patterns: + - 'src/modules/host/handlers/Activity_Hub/OnBoarding/getAllHostActivity.*' + - 'src/modules/host/services/**' + - ${file(./serverless/patterns/base.yml):pattern1} + - ${file(./serverless/patterns/base.yml):pattern2} + - ${file(./serverless/patterns/base.yml):pattern3} + - ${file(./serverless/patterns/base.yml):pattern4} + events: + - httpApi: + path: /host/Activity_Hub/OnBoarding/get-all-host-activity method: get acceptAggrement: @@ -278,4 +294,19 @@ updatePQQ_LastAnswer: events: - httpApi: path: /host/Activity_Hub/OnBoarding/submit-final-pqq-answer - method: post \ No newline at end of file + method: post + +getAllPQQwithSubmittedAns: + handler: src/modules/host/handlers/Activity_Hub/OnBoarding/getAllPQQwithSubmittedAns.handler + memorySize: 512 + package: + patterns: + - 'src/modules/prepopulate/**' + - ${file(./serverless/patterns/base.yml):pattern1} + - ${file(./serverless/patterns/base.yml):pattern2} + - ${file(./serverless/patterns/base.yml):pattern3} + - ${file(./serverless/patterns/base.yml):pattern4} + events: + - httpApi: + path: /host/Activity_Hub/OnBoarding/get-all-pqq-ques-submited-ans + method: get \ No newline at end of file diff --git a/serverless/functions/minglaradmin.yml b/serverless/functions/minglaradmin.yml index 38c5897..031979e 100644 --- a/serverless/functions/minglaradmin.yml +++ b/serverless/functions/minglaradmin.yml @@ -94,8 +94,9 @@ updateMinglarProfile: path: /minglaradmin/update-profile method: patch -prepopulateTeammate: - handler: src/modules/minglaradmin/handlers/prepopulateTeammate.handler + +prepopulateRole: + handler: src/modules/minglaradmin/handlers/prepopulateRole.handler memorySize: 384 package: patterns: @@ -140,6 +141,22 @@ getAllHostApplication: path: /minglaradmin/hosthub/hosts/get-all-host-applications-am method: get +getAllHostActivityForAdmin: + handler: src/modules/minglaradmin/handlers/hosthub/onboarding/getAllActivityOfHost.handler + memorySize: 384 + package: + patterns: + - 'src/modules/minglaradmin/handlers/hosthub/onboarding/getAllActivityOfHost.handler.*' + - 'src/modules/minglaradmin/services/**' + - ${file(./serverless/patterns/base.yml):pattern1} + - ${file(./serverless/patterns/base.yml):pattern2} + - ${file(./serverless/patterns/base.yml):pattern3} + - ${file(./serverless/patterns/base.yml):pattern4} + events: + - httpApi: + path: /minglaradmin/get-all-activity-of-host/{id} + method: get + getAllOnboardingHostApplications: handler: src/modules/minglaradmin/handlers/hosthub/onboarding/getAllOnboardingHosts.handler memorySize: 512 @@ -233,6 +250,21 @@ getAllInvitedCoadminAndAMDetails: path: /minglaradmin/settings/teammates/get-all-invited-coadmin-am method: get +getAmDetailsbyId: + handler: src/modules/minglaradmin/handlers/getAmDetail_ById.handler + memorySize: 384 + package: + patterns: + - 'src/modules/minglaradmin/handlers/settings/**' + - ${file(./serverless/patterns/base.yml):pattern1} + - ${file(./serverless/patterns/base.yml):pattern2} + - ${file(./serverless/patterns/base.yml):pattern3} + - ${file(./serverless/patterns/base.yml):pattern4} + events: + - httpApi: + path: /minglaradmin/settings/teammates/get-am-details-by-id/{amXid} + method: get + assignAMToHost: handler: src/modules/minglaradmin/handlers/hosthub/onboarding/assignAM.handler memorySize: 384 diff --git a/src/modules/host/handlers/Activity_Hub/OnBoarding/getAllActivityType.ts b/src/modules/host/handlers/Activity_Hub/OnBoarding/getAllActivityType.ts new file mode 100644 index 0000000..632116e --- /dev/null +++ b/src/modules/host/handlers/Activity_Hub/OnBoarding/getAllActivityType.ts @@ -0,0 +1,51 @@ +import { verifyHostToken } from '@/common/middlewares/jwt/authForHost'; +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 { HostService } from '../../../services/host.service'; +import { PrePopulateService } from '../../../../prepopulate/services/prepopulate.service'; + +const prismaService = new PrismaService(); +const hostService = new HostService(prismaService); +const prePopulateService = new PrePopulateService(prismaService); + +/** + * Add suggestion handler for host applications + * Allows Minglar Admin, Co_Admin, and Account Manager to add suggestions + * Types: Setup Profile, Review Account, Add Payment Details, Agreement + */ +export const handler = safeHandler(async ( + event: APIGatewayProxyEvent, + context?: Context +): Promise => { + // Verify authentication 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.'); + } + + // Verify token and get user info + const userInfo = await verifyHostToken(token); + + + // Read optional search query (supports ?search= or ?q=) + const search = event.queryStringParameters?.search || event.queryStringParameters?.q || undefined; + + const data = await hostService.getAllActivityTypesWithInterest(search); + const frequencies = await prePopulateService.getAllFrequencies(); + + return { + statusCode: 200, + headers: { + 'Content-Type': 'application/json', + 'Access-Control-Allow-Origin': '*', + }, + body: JSON.stringify({ + success: true, + message: 'Data retrieved successfully', + data, + frequencies + }), + }; +}); diff --git a/src/modules/host/handlers/Activity_Hub/OnBoarding/getAllActivity.ts b/src/modules/host/handlers/Activity_Hub/OnBoarding/getAllHostActivity.ts similarity index 91% rename from src/modules/host/handlers/Activity_Hub/OnBoarding/getAllActivity.ts rename to src/modules/host/handlers/Activity_Hub/OnBoarding/getAllHostActivity.ts index 3e8d0ad..0b3e71b 100644 --- a/src/modules/host/handlers/Activity_Hub/OnBoarding/getAllActivity.ts +++ b/src/modules/host/handlers/Activity_Hub/OnBoarding/getAllHostActivity.ts @@ -4,10 +4,13 @@ import { PrismaService } from '../../../../../common/database/prisma.service'; import { safeHandler } from '../../../../../common/utils/handlers/safeHandler'; import ApiError from '../../../../../common/utils/helper/ApiError'; import { HostService } from '../../../services/host.service'; +import { string } from 'zod'; + const prismaService = new PrismaService(); const hostService = new HostService(prismaService); + /** * Add suggestion handler for host applications * Allows Minglar Admin, Co_Admin, and Account Manager to add suggestions @@ -30,7 +33,8 @@ export const handler = safeHandler(async ( // Read optional search query (supports ?search= or ?q=) const search = event.queryStringParameters?.search || event.queryStringParameters?.q || undefined; - const data = await hostService.getAllActivityTypesWithInterest(search); + const data = await hostService.getAllHostActivity(search ? String(search) : undefined, Number(userInfo.id)); + return { statusCode: 200, @@ -42,6 +46,7 @@ export const handler = safeHandler(async ( success: true, message: 'Data retrieved successfully', data, + }), }; }); diff --git a/src/modules/host/handlers/Activity_Hub/OnBoarding/getAllPQQwithSubmittedAns.ts b/src/modules/host/handlers/Activity_Hub/OnBoarding/getAllPQQwithSubmittedAns.ts new file mode 100644 index 0000000..e7f6bb8 --- /dev/null +++ b/src/modules/host/handlers/Activity_Hub/OnBoarding/getAllPQQwithSubmittedAns.ts @@ -0,0 +1,41 @@ +import { verifyOnlyMinglarAdminToken } from '@/common/middlewares/jwt/authForOnlyMinglarAdmin'; +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 { PrePopulateService } from '../../../../prepopulate/services/prepopulate.service'; +import { HostService } from '../../../services/host.service'; +import { verifyMinglarAdminHostToken } from '@/common/middlewares/jwt/authForMinglarAdmin&Host'; + +const prismaService = new PrismaService(); +const hostService = new HostService(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.'); + } + + // Authenticate user using the shared authForHost function + await verifyMinglarAdminHostToken(token); + + const result = await hostService.getAllPQQQuesAndSubmittedAns(); + + return { + statusCode: 200, + headers: { + 'Content-Type': 'application/json', + 'Access-Control-Allow-Origin': '*', + }, + body: JSON.stringify({ + success: true, + message: 'Data retrieved successfully', + data: result, + }), + }; +}); + diff --git a/src/modules/host/services/host.service.ts b/src/modules/host/services/host.service.ts index 576a336..8f85180 100644 --- a/src/modules/host/services/host.service.ts +++ b/src/modules/host/services/host.service.ts @@ -1,15 +1,30 @@ // src/modules/host/services/host.service.ts import { Injectable } from '@nestjs/common'; import { PrismaService } from '../../../common/database/prisma.service'; -import { AddPaymentDetailsDTO, CreateHostDto, UpdateHostDto } from '../dto/host.dto'; +import { + AddPaymentDetailsDTO, + CreateHostDto, + UpdateHostDto, +} from '../dto/host.dto'; import * as bcrypt from 'bcryptjs'; import ApiError from '../../../common/utils/helper/ApiError'; import { User } from '@prisma/client'; import { z } from 'zod'; import { hostCompanyDetailsSchema } from '@/common/utils/validation/host/hostCompanyDetails.validation'; -import { ACTIVITY_DISPLAY_STATUS, ACTIVITY_INTERNAL_STATUS, HOST_STATUS_DISPLAY, HOST_STATUS_INTERNAL, STEPPER } from '@/common/utils/constants/host.constant'; -import { MINGLAR_STATUS_DISPLAY, MINGLAR_STATUS_INTERNAL } from '@/common/utils/constants/minglar.constant'; -import { ROLE, ROLE_NAME, USER_STATUS } from '@/common/utils/constants/common.constant'; +import { + ACTIVITY_DISPLAY_STATUS, ACTIVITY_INTERNAL_STATUS, HOST_STATUS_DISPLAY, + HOST_STATUS_INTERNAL, + STEPPER, +} from '@/common/utils/constants/host.constant'; +import { + MINGLAR_STATUS_DISPLAY, + MINGLAR_STATUS_INTERNAL, +} from '@/common/utils/constants/minglar.constant'; +import { + ROLE, + ROLE_NAME, + USER_STATUS, +} from '@/common/utils/constants/common.constant'; import { getPresignedUrl } from '@/common/middlewares/aws/getPreSignedUrl'; import config from '@/config/config'; @@ -24,7 +39,7 @@ interface HostDocumentInput { @Injectable() export class HostService { - constructor(private prisma: PrismaService) { } + constructor(private prisma: PrismaService) {} async createHost(data: CreateHostDto) { return this.prisma.user.create({ data }); @@ -59,7 +74,7 @@ export class HostService { currencies: true, states: true, cities: true, - } + }, }); if (!host) { @@ -76,8 +91,8 @@ export class HostService { const filePath = doc.filePath; // If full URL is saved, extract only key - const key = filePath.startsWith("http") - ? filePath.split(".com/")[1] + const key = filePath.startsWith('http') + ? filePath.split('.com/')[1] : filePath; (doc as any).presignedUrl = await getPresignedUrl(bucket, key); @@ -162,7 +177,10 @@ export class HostService { throw new ApiError(403, 'Access denied. Not a host user.'); } - const matchPassword = await bcrypt.compare(userPassword, existingUser.userPassword); + const matchPassword = await bcrypt.compare( + userPassword, + existingUser.userPassword, + ); if (!matchPassword) { throw new ApiError(401, 'Invalid credentials'); } @@ -190,7 +208,10 @@ export class HostService { // Check if password already exists if (user.userPassword) { - throw new ApiError(400, 'Password already exists. Use update password instead.'); + throw new ApiError( + 400, + 'Password already exists. Use update password instead.', + ); } // Hash the password @@ -200,7 +221,11 @@ export class HostService { // Update user with hashed password await this.prisma.user.update({ where: { id: user.id }, - data: { userPassword: hashedPassword, isEmailVerfied: true, userStatus: USER_STATUS.ACTIVE }, + data: { + userPassword: hashedPassword, + isEmailVerfied: true, + userStatus: USER_STATUS.ACTIVE, + }, }); return true; @@ -219,10 +244,24 @@ export class HostService { await tx.hostHeader.update({ where: { id: data.hostXid }, data: { - stepper: STEPPER.BANK_DETAILS_UPDATED - } - }) - }) + stepper: STEPPER.BANK_DETAILS_UPDATED, + }, + }); + }); + } + + async getAllHostActivity(search?: string, hostXid?: number) { + return await this.prisma.activities.findMany({ + where: { + isActive: true, + hostXid: hostXid, + }, + include: { + ActivitiesMedia: true, + ActivityAmDetails: true, + activityType: true, + }, + }); } async acceptMinglarAgreement(user_xid: number) { @@ -231,27 +270,31 @@ export class HostService { select: { id: true, userXid: true, - } - }) + }, + }); await this.prisma.hostHeader.update({ where: { id: hostDetails.id }, data: { stepper: STEPPER.AGREEMENT_ACCEPTED, agreementAccepted: true, - } - }) + }, + }); } async getPQQQuestionDetail(question_xid: number, activity_xid: number) { return await this.prisma.activityPQQheader.findFirst({ - where: { activityXid: activity_xid, pqqQuestionXid: question_xid, isActive: true }, + where: { + activityXid: activity_xid, + pqqQuestionXid: question_xid, + isActive: true, + }, select: { pqqQuestionXid: true, pqqAnswerXid: true, ActivityPQQSupportings: true, - ActivityPQQSuggestions: true - } - }) + ActivityPQQSuggestions: true, + }, + }); } async getLatestQuestionDetailsPQQ(activity_xid: number) { @@ -265,14 +308,14 @@ export class HostService { pqqSubCategoryXid: true, pqqSubCategories: { select: { - categoryXid: true - } - } - } - } + categoryXid: true, + }, + }, + }, + }, }, - orderBy: { id: 'desc' } - }) + orderBy: { id: 'desc' }, + }); } async addOrUpdateCompanyDetails( @@ -281,7 +324,7 @@ export class HostService { documents: HostDocumentInput[], parentCompanyData?: any | null, parentDocuments?: HostDocumentInput[], - isDraft: boolean = false // Add isDraft parameter with default false + isDraft: boolean = false, // Add isDraft parameter with default false ) { return await this.prisma.$transaction(async (tx) => { // Check if host already has a company @@ -314,7 +357,11 @@ export class HostService { const existingByPan = await tx.hostHeader.findFirst({ where: { panNumber: companyData.panNumber }, }); - if (existingByPan) throw new ApiError(400, 'Company already exists with this pan/bin number'); + if (existingByPan) + throw new ApiError( + 400, + 'Company already exists with this pan/bin number', + ); } const refNumber = await this.generateHostRefNumber(tx); @@ -429,7 +476,7 @@ export class HostService { hostStatusInternal: hostStatusInternal, hostStatusDisplay: hostStatusDisplay, adminStatusInternal: minglarStatusInternal, - adminStatusDisplay: minglarStatusDisplay + adminStatusDisplay: minglarStatusDisplay, }, }); @@ -513,7 +560,9 @@ export class HostService { }); // replace parent docs - await tx.hostParenetDocuments.deleteMany({ where: { hostParentXid: parentRecord.id } }); + await tx.hostParenetDocuments.deleteMany({ + where: { hostParentXid: parentRecord.id }, + }); if (parentDocuments?.length) { const parentDocsData = parentDocuments.map((doc) => ({ hostParentXid: parentRecord.id, @@ -528,18 +577,22 @@ export class HostService { // If previously had a parent and now isSubsidairy=false -> optionally delete parent and its docs const previousParent = (existingHostCompany as any).hostParent; let prevParentId = null; - if (Array.isArray(previousParent) && previousParent.length) prevParentId = previousParent[0].id; - else if (previousParent && previousParent.id) prevParentId = previousParent.id; + if (Array.isArray(previousParent) && previousParent.length) + prevParentId = previousParent[0].id; + else if (previousParent && previousParent.id) + prevParentId = previousParent.id; if (prevParentId) { - await tx.hostParenetDocuments.deleteMany({ where: { hostParentXid: prevParentId } }); + await tx.hostParenetDocuments.deleteMany({ + where: { hostParentXid: prevParentId }, + }); await tx.hostParent.delete({ where: { id: prevParentId } }); } } const hostDetails = await this.prisma.hostHeader.findFirst({ where: { userXid: user_xid }, - }) + }); await this.prisma.hostTrack.create({ data: { @@ -547,8 +600,8 @@ export class HostService { updatedByRole: ROLE_NAME.HOST, updatedByXid: user_xid, trackStatus: hostDetails.hostStatusInternal, - } - }) + }, + }); return updatedHost; }); @@ -563,16 +616,16 @@ export class HostService { id: true, emailAddress: true, firstName: true, - } + }, }, accountManager: { select: { id: true, emailAddress: true, firstName: true, - } - } - } + }, + }, + }, }); if (!hostDetails) { @@ -580,7 +633,7 @@ export class HostService { } const hostSuggestionDetails = await this.prisma.hostSuggestion.findMany({ - where: { hostXid: hostDetails.id, isActive: true, isreviewed: false } + where: { hostXid: hostDetails.id, isActive: true, isreviewed: false }, }); if (hostSuggestionDetails) { @@ -590,15 +643,13 @@ export class HostService { isreviewed: true, reviewedByXid: hostDetails.id, reviewOn: new Date(), - } - }) + }, + }); } return { hostSuggestionDetails, hostDetails }; } - - async generateHostRefNumber(tx: any) { const lastHost = await tx.hostHeader.findFirst({ orderBy: { @@ -606,7 +657,7 @@ export class HostService { }, select: { id: true, - } + }, }); const nextId = lastHost ? lastHost.id + 1 : 1; @@ -668,7 +719,6 @@ export class HostService { // }); // } - async calculatePqqScoreForUser(activityXid: number) { // 1. Get all headers for this activity (user's answers) const answers = await this.prisma.activityPQQheader.findMany({ @@ -678,19 +728,19 @@ export class HostService { include: { pqqSubCategories: { include: { - category: true - } - } - } + category: true, + }, + }, + }, }, - pqqAnswers: true - } + pqqAnswers: true, + }, }); if (!answers.length) { return { overallPercentage: 0, - categoryWise: {} + categoryWise: {}, }; } @@ -699,12 +749,15 @@ export class HostService { let totalMaxPoints = 0; // For category-wise scoring - const categories: Record = {}; + const categories: Record< + number, + { + categoryId: number; + categoryName: string; + userPoints: number; + maxPoints: number; + } + > = {}; for (const item of answers) { const question = item.pqqQuestions; @@ -778,104 +831,107 @@ export class HostService { // Return final score object return { overallPercentage, - categoryWise + categoryWise, }; } - - async createHeader( activityXid: number, pqqQuestionXid: number, pqqAnswerXid: number, - comments?: string | null + comments?: string | null, ) { return await this.prisma.activityPQQheader.create({ data: { activityXid, pqqQuestionXid, pqqAnswerXid, - comments: comments || null // Handle null comments - } + comments: comments || null, // Handle null comments + }, }); } async findHeaderByCompositeKey( activityXid: number, pqqQuestionXid: number, - pqqAnswerXid: number + pqqAnswerXid: number, ) { return await this.prisma.activityPQQheader.findFirst({ where: { activityXid, pqqQuestionXid, - pqqAnswerXid - } + pqqAnswerXid, + }, }); } - async updateHeader( - headerId: number, - comments?: string | null - ) { + async updateHeader(headerId: number, comments?: string | null) { return await this.prisma.activityPQQheader.update({ where: { - id: headerId + id: headerId, }, data: { comments: comments || null, // Handle null comments - updatedAt: new Date() - } + updatedAt: new Date(), + }, }); } - async addSupportingFile( - headerId: number, - mimeType: string, - fileUrl: string - ) { + async addSupportingFile(headerId: number, mimeType: string, fileUrl: string) { return await this.prisma.activityPQQSupportings.create({ data: { activityPqqHeaderXid: headerId, mediaType: mimeType, - mediaFileName: fileUrl - } + mediaFileName: fileUrl, + }, }); } async getSupportingFilesByHeaderId(headerId: number) { return await this.prisma.activityPQQSupportings.findMany({ where: { - activityPqqHeaderXid: headerId + activityPqqHeaderXid: headerId, }, orderBy: { - id: 'asc' // Maintain consistent order - } + id: 'asc', // Maintain consistent order + }, }); } async updateSupportingFile( supportingFileId: number, mimeType: string, - fileUrl: string + fileUrl: string, ) { return await this.prisma.activityPQQSupportings.update({ where: { - id: supportingFileId + id: supportingFileId, }, data: { mediaType: mimeType, mediaFileName: fileUrl, - updatedAt: new Date() - } + updatedAt: new Date(), + }, }); } async deleteSupportingFile(supportingFileId: number) { return await this.prisma.activityPQQSupportings.delete({ where: { - id: supportingFileId - } + id: supportingFileId, + }, + }); + } + + async getAllPQQQuesAndSubmittedAns() { + return await this.prisma.activityPQQheader.findMany({ + where: { isActive: true }, + include: { + pqqQuestions: true, + ActivityPQQSuggestions: true, + pqqAnswers: true, + ActivityPQQSupportings: true, + }, }); } @@ -917,20 +973,26 @@ export class HostService { frequenciesXid?: number, ) { // Find host header for this user - const host = await this.prisma.hostHeader.findFirst({ where: { userXid: userId, isActive: true } }); + const host = await this.prisma.hostHeader.findFirst({ + where: { userXid: userId, isActive: true }, + }); if (!host) { throw new ApiError(404, 'Host not found for the user'); } // Validate activityType exists - const activityType = await this.prisma.activityTypes.findUnique({ where: { id: activityTypeXid } }); + const activityType = await this.prisma.activityTypes.findUnique({ + where: { id: activityTypeXid }, + }); if (!activityType) { throw new ApiError(404, 'Activity type not found'); } // Optionally validate frequency if (frequenciesXid) { - const freq = await this.prisma.frequencies.findUnique({ where: { id: frequenciesXid } }); + const freq = await this.prisma.frequencies.findUnique({ + where: { id: frequenciesXid }, + }); if (!freq) throw new ApiError(404, 'Frequency not found'); } @@ -945,5 +1007,4 @@ export class HostService { return created; } - } diff --git a/src/modules/minglaradmin/handlers/getAMDetail_ById.ts b/src/modules/minglaradmin/handlers/getAMDetail_ById.ts new file mode 100644 index 0000000..50cf6a5 --- /dev/null +++ b/src/modules/minglaradmin/handlers/getAMDetail_ById.ts @@ -0,0 +1,66 @@ +import { + APIGatewayProxyEvent, + APIGatewayProxyResult, + Context, +} from 'aws-lambda'; +import { safeHandler } from '../../../common/utils/handlers/safeHandler'; +import { PrismaService } from '../../../common/database/prisma.service'; +import { MinglarService } from '../services/minglar.service'; +import ApiError from '../../../common/utils/helper/ApiError'; +import { verifyMinglarAdminToken } from '../../../common/middlewares/jwt/authForMinglarAdmin'; + +const prismaService = new PrismaService(); +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 ( + event: APIGatewayProxyEvent, + context?: Context, + ): Promise => { + // Verify authentication 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.', + ); + } + + await verifyMinglarAdminToken(token); + + const amXid = event.pathParameters?.amXid; + if (!amXid) { + throw new ApiError( + 400, + 'Account Manager XID is required in path parameters.', + ); + } + + const amId = Number(amXid); + if (Number.isNaN(amId)) { + throw new ApiError(400, 'Account Manager XID must be a valid number.'); + } + + + // Get all host applications from service based on user role + const getAmDetailsByid = await minglarService.getAMdetailById( amId ); + + return { + statusCode: 200, + headers: { + 'Content-Type': 'application/json', + 'Access-Control-Allow-Origin': '*', + }, + body: JSON.stringify({ + success: true, + message: 'Host applications retrieved successfully', + data: getAmDetailsByid, + }), + }; + }, +); diff --git a/src/modules/minglaradmin/handlers/hosthub/onboarding/getAllActivityOfHost.ts b/src/modules/minglaradmin/handlers/hosthub/onboarding/getAllActivityOfHost.ts new file mode 100644 index 0000000..0c1a991 --- /dev/null +++ b/src/modules/minglaradmin/handlers/hosthub/onboarding/getAllActivityOfHost.ts @@ -0,0 +1,53 @@ +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 { string } from 'zod'; +import { PrePopulateService } from '../../../../prepopulate/services/prepopulate.service'; +import { MinglarService } from '../../../services/minglar.service'; +import { verifyMinglarAdminHostToken } from '@/common/middlewares/jwt/authForMinglarAdmin&Host'; + +const prismaService = new PrismaService(); +const minglarService = new MinglarService(prismaService); +const prePopulateService = new PrePopulateService(prismaService); + +/** + * Add suggestion handler for host applications + * Allows Minglar Admin, Co_Admin, and Account Manager to add suggestions + * Types: Setup Profile, Review Account, Add Payment Details, Agreement + */ +export const handler = safeHandler(async ( + event: APIGatewayProxyEvent, + context?: Context +): Promise => { + // Verify authentication 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.'); + } + + // Verify token and get user info + const userInfo = await verifyMinglarAdminHostToken(token); + + const hostXid = Number(event.pathParameters?.id) + + + // Read optional search query (supports ?search= or ?q=) + const search = event.queryStringParameters?.search || event.queryStringParameters?.q || undefined; + + const data = await minglarService.getAllHostActivityForMinglar(search ? String(search) : undefined, hostXid); + + + return { + statusCode: 200, + headers: { + 'Content-Type': 'application/json', + 'Access-Control-Allow-Origin': '*', + }, + body: JSON.stringify({ + success: true, + message: 'Data retrieved successfully', + data, + }), + }; +}); diff --git a/src/modules/minglaradmin/handlers/prepopulateRole.ts b/src/modules/minglaradmin/handlers/prepopulateRole.ts new file mode 100644 index 0000000..c762761 --- /dev/null +++ b/src/modules/minglaradmin/handlers/prepopulateRole.ts @@ -0,0 +1,56 @@ +import { + APIGatewayProxyEvent, + APIGatewayProxyResult, + Context, +} from 'aws-lambda'; +import { safeHandler } from '../../../common/utils/handlers/safeHandler'; +import { PrismaService } from '../../../common/database/prisma.service'; +import ApiError from '../../../common/utils/helper/ApiError'; +import { ROLE } from '../../../common/utils/constants/common.constant'; +import { verifyMinglarAdminToken } from '../../../common/middlewares/jwt/authForMinglarAdmin'; + +const prismaService = new 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.', + ); + } + + // Verify token and get user info + await verifyMinglarAdminToken(token); + + const roles = await prismaService.roles.findMany({ + where: { + id: { + in: [ROLE.CO_ADMIN, ROLE.ACCOUNT_MANAGER], + }, + }, + select: { + id: true, + roleName: true, + }, + }); + + return { + statusCode: 200, + headers: { + 'Content-Type': 'application/json', + 'Access-Control-Allow-Origin': '*', + }, + body: JSON.stringify({ + success: true, + message: 'Roles retrieved successfully', + data: roles, + }), + }; + }, +); diff --git a/src/modules/minglaradmin/services/minglar.service.ts b/src/modules/minglaradmin/services/minglar.service.ts index 5c6fee7..5b07545 100644 --- a/src/modules/minglaradmin/services/minglar.service.ts +++ b/src/modules/minglaradmin/services/minglar.service.ts @@ -1,4 +1,8 @@ -import { ROLE, ROLE_NAME, USER_STATUS } from '@/common/utils/constants/common.constant'; +import { + ROLE, + ROLE_NAME, + USER_STATUS, +} from '@/common/utils/constants/common.constant'; import { HOST_STATUS_DISPLAY, HOST_STATUS_INTERNAL, @@ -19,7 +23,7 @@ import { sendAMEmailForHostAssign } from './AMEmail.service'; @Injectable() export class MinglarService { - constructor(private prisma: PrismaService) { } + constructor(private prisma: PrismaService) {} async createPassword(user_xid: number, password: string): Promise { // Find user by id @@ -198,6 +202,20 @@ export class MinglarService { }); } + async getAllHostActivityForMinglar(search?: string, hostXid?: number) { + return await this.prisma.activities.findMany({ + where: { + isActive: true, + hostXid: hostXid, + }, + include: { + ActivitiesMedia: true, + ActivityAmDetails: true, + activityType: true, + }, + }); + } + async createUserRevenue( userXid: number, isFixedSalary: boolean, @@ -557,15 +575,15 @@ export class MinglarService { userId: number, userRoleXid: number, search?: string, - userStatus?: string + userStatus?: string, ) { const filters: any = { isActive: true, user: { roleXid: { - notIn: [ROLE.CO_ADMIN, ROLE.ACCOUNT_MANAGER] - } - } + notIn: [ROLE.CO_ADMIN, ROLE.ACCOUNT_MANAGER], + }, + }, }; /** ----------------------------------- @@ -582,10 +600,10 @@ export class MinglarService { filters.user = { ...filters.user, OR: [ - { emailAddress: { contains: term, mode: "insensitive" } }, - { firstName: { contains: term, mode: "insensitive" } }, - { lastName: { contains: term, mode: "insensitive" } } - ] + { emailAddress: { contains: term, mode: 'insensitive' } }, + { firstName: { contains: term, mode: 'insensitive' } }, + { lastName: { contains: term, mode: 'insensitive' } }, + ], }; } } @@ -595,7 +613,8 @@ export class MinglarService { * ----------------------------------- */ if ( userStatus && - userStatus.trim().toLowerCase() === MINGLAR_STATUS_DISPLAY.NEW.toLowerCase() + userStatus.trim().toLowerCase() === + MINGLAR_STATUS_DISPLAY.NEW.toLowerCase() ) { filters.adminStatusInternal = MINGLAR_STATUS_INTERNAL.ADMIN_TO_REVIEW; } @@ -633,8 +652,8 @@ export class MinglarService { firstName: true, lastName: true, emailAddress: true, - mobileNumber: true - } + mobileNumber: true, + }, }, accountManager: { select: { @@ -643,17 +662,17 @@ export class MinglarService { lastName: true, emailAddress: true, mobileNumber: true, - roleXid: true - } - } + roleXid: true, + }, + }, }, - orderBy: { createdAt: "desc" } + orderBy: { createdAt: 'desc' }, }); /** ----------------------------------- * TRANSFORM RESPONSE * ----------------------------------- */ - return results.map(h => ({ + return results.map((h) => ({ hostId: h.id, host: h.user, hostStatusDisplay: h.hostStatusDisplay, @@ -666,7 +685,7 @@ export class MinglarService { city: h.cities || null, state: h.states || null, country: h.countries || null, - assignedOn: h.assignedOn || null + assignedOn: h.assignedOn || null, })); } @@ -674,7 +693,7 @@ export class MinglarService { return await this.prisma.hostHeader.findMany({ where: { isActive: true, - hostStatusInternal: { notIn: [HOST_STATUS_INTERNAL.DRAFT] } + hostStatusInternal: { notIn: [HOST_STATUS_INTERNAL.DRAFT] }, }, select: { id: true, @@ -689,24 +708,26 @@ export class MinglarService { id: true, firstName: true, lastName: true, - } + }, }, accountManager: { select: { id: true, firstName: true, lastName: true, - profileImage: true - } - } - } - }) + profileImage: true, + }, + }, + }, + }); } - async getAllOnboardingHostApplications_New() { return await this.prisma.hostHeader.findMany({ - where: { isActive: true, adminStatusInternal: MINGLAR_STATUS_INTERNAL.ADMIN_TO_REVIEW }, + where: { + isActive: true, + adminStatusInternal: MINGLAR_STATUS_INTERNAL.ADMIN_TO_REVIEW, + }, select: { id: true, hostRefNumber: true, @@ -718,41 +739,40 @@ export class MinglarService { cities: { select: { id: true, - cityName: true - } + cityName: true, + }, }, countries: { select: { id: true, countryName: true, - } + }, }, states: { select: { id: true, - stateName: true - } + stateName: true, + }, }, user: { select: { id: true, firstName: true, lastName: true, - } + }, }, accountManager: { select: { id: true, firstName: true, lastName: true, - profileImage: true - } - } - } - }) + profileImage: true, + }, + }, + }, + }); } - async getAllCoadminAndAM() { // 1. Fetch all required users (Admin, Co-Admin, AM) const users = await this.prisma.user.findMany({ @@ -852,7 +872,7 @@ export class MinglarService { if ( hostDetails.adminStatusInternal !== - MINGLAR_STATUS_INTERNAL.AM_NOT_ASSIGNED && + MINGLAR_STATUS_INTERNAL.AM_NOT_ASSIGNED && hostDetails.adminStatusDisplay !== MINGLAR_STATUS_DISPLAY.AM_NOT_ASSIGNED ) { throw new ApiError(400, 'Invalid host status'); @@ -933,13 +953,12 @@ export class MinglarService { return true; } - + async addPqqSuggestion( title: string, comments: string, activity_pqq_header_xid: number, - reviewedByXid:number - + reviewedByXid: number, ) { // Check if host exists const ActivityHeader = await this.prisma.activityPQQheader.findUnique({ @@ -959,7 +978,7 @@ export class MinglarService { reviewedOn: new Date(), isActive: true, activityPqqHeaderXid: activity_pqq_header_xid, - reviewedByXid:reviewedByXid , + reviewedByXid: reviewedByXid, }, }); @@ -1040,11 +1059,9 @@ export class MinglarService { updatedByRole: ROLE_NAME.ACCOUNT_MANAGER, updatedByXid: user_xid, trackStatus: MINGLAR_STATUS_INTERNAL.AM_APPROVED, - } - }) - }) - - + }, + }); + }); } async acceptHostApplicationMinglarAdmin(host_xid: number, user_xid: number) { @@ -1072,9 +1089,9 @@ export class MinglarService { updatedByRole: ROLE_NAME.MINGLAR_ADMIN, updatedByXid: user_xid, trackStatus: MINGLAR_STATUS_INTERNAL.AM_NOT_ASSIGNED, - } - }) - }) + }, + }); + }); } async rejectHostApplication(host_xid: number, user_xid: number) { @@ -1106,8 +1123,8 @@ export class MinglarService { updatedByRole: ROLE_NAME.MINGLAR_ADMIN, updatedByXid: user_xid, trackStatus: MINGLAR_STATUS_INTERNAL.ADMIN_REJECTED, - } - }) + }, + }); await tx.user.update({ where: { id: hostDetails.userXid }, @@ -1147,8 +1164,19 @@ export class MinglarService { updatedByRole: ROLE_NAME.ACCOUNT_MANAGER, updatedByXid: user_xid, trackStatus: MINGLAR_STATUS_INTERNAL.AM_REJECTED, - } - }) - }) + }, + }); + }); + } + + async getAMdetailById(id: number) { + return this.prisma.user.findUnique({ + where: { id: id, isActive: true, userStatus: USER_STATUS.ACTIVE }, + include: { + userAddressDetails: true, + userDocuments: true, + userRevenues: true, + }, + }); } }