diff --git a/serverless/functions/host.yml b/serverless/functions/host.yml index c8d7345..acc9c61 100644 --- a/serverless/functions/host.yml +++ b/serverless/functions/host.yml @@ -182,7 +182,7 @@ getAllHostActivity: memorySize: 384 package: patterns: - - 'src/modules/host/handlers/getActivityType.*' + - 'src/modules/host/handlers/Activity_Hub/OnBoarding/getAllHostActivity.*' - 'src/modules/host/services/**' - ${file(./serverless/patterns/base.yml):pattern1} - ${file(./serverless/patterns/base.yml):pattern2} diff --git a/serverless/functions/minglaradmin.yml b/serverless/functions/minglaradmin.yml index 23bf5a4..6aa4940 100644 --- a/serverless/functions/minglaradmin.yml +++ b/serverless/functions/minglaradmin.yml @@ -141,7 +141,7 @@ getAllHostApplication: path: /minglaradmin/hosthub/hosts/get-all-host-applications-am method: get -getAllHostActivity: +getAllHostActivityForAdmin: handler: src/modules/host/handlers/hosthub/onboarding/getAllActivityOfHost.handler memorySize: 384 package: @@ -251,7 +251,7 @@ getAllInvitedCoadminAndAMDetails: method: get getAmDetailsbyId: - handler: src/modules/minglaradmin/handlers/getAmDetailsById.handler + handler: src/modules/minglaradmin/handlers/getAmDetail_ById.handler memorySize: 384 package: patterns: diff --git a/src/modules/host/services/host.service.ts b/src/modules/host/services/host.service.ts index 1fba951..b451f51 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 { 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 { + 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,26 +244,25 @@ 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) { - - await this.prisma.activities.findMany({ + async getAllHostActivity(search?: string, hostXid?: number) { + return await this.prisma.activities.findMany({ where: { isActive: true, hostXid: hostXid, }, - include: { + include: { ActivitiesMedia: true, - ActivityAmDetails: true, + ActivityAmDetails: true, activityType: true, - }, - }) - } + }, + }); + } async acceptMinglarAgreement(user_xid: number) { const hostDetails = await this.prisma.hostHeader.findFirst({ @@ -246,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) { @@ -280,14 +308,14 @@ export class HostService { pqqSubCategoryXid: true, pqqSubCategories: { select: { - categoryXid: true - } - } - } - } + categoryXid: true, + }, + }, + }, + }, }, - orderBy: { id: 'desc' } - }) + orderBy: { id: 'desc' }, + }); } async addOrUpdateCompanyDetails( @@ -296,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 @@ -329,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); @@ -444,7 +476,7 @@ export class HostService { hostStatusInternal: hostStatusInternal, hostStatusDisplay: hostStatusDisplay, adminStatusInternal: minglarStatusInternal, - adminStatusDisplay: minglarStatusDisplay + adminStatusDisplay: minglarStatusDisplay, }, }); @@ -528,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, @@ -543,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: { @@ -562,8 +600,8 @@ export class HostService { updatedByRole: ROLE_NAME.HOST, updatedByXid: user_xid, trackStatus: hostDetails.hostStatusInternal, - } - }) + }, + }); return updatedHost; }); @@ -578,16 +616,16 @@ export class HostService { id: true, emailAddress: true, firstName: true, - } + }, }, accountManager: { select: { id: true, emailAddress: true, firstName: true, - } - } - } + }, + }, + }, }); if (!hostDetails) { @@ -595,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) { @@ -605,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: { @@ -621,7 +657,7 @@ export class HostService { }, select: { id: true, - } + }, }); const nextId = lastHost ? lastHost.id + 1 : 1; @@ -683,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({ @@ -693,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: {}, }; } @@ -714,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; @@ -771,117 +809,108 @@ 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({ + async getAllPQQQuesAndSubmittedAns() { + return await this.prisma.activityPQQheader.findMany({ where: { isActive: true }, include: { pqqQuestions: true, ActivityPQQSuggestions: true, pqqAnswers: true, - ActivityPQQSupportings: true - } - }) + ActivityPQQSupportings: true, + }, + }); } async getAllActivityTypesWithInterest(search?: string) { @@ -922,20 +951,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'); } @@ -950,5 +985,4 @@ export class HostService { return created; } - } diff --git a/src/modules/minglaradmin/handlers/getAMDetail_ById.ts b/src/modules/minglaradmin/handlers/getAMDetail_ById.ts index 2fe7334..50cf6a5 100644 --- a/src/modules/minglaradmin/handlers/getAMDetail_ById.ts +++ b/src/modules/minglaradmin/handlers/getAMDetail_ById.ts @@ -1,4 +1,8 @@ -import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda'; +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'; @@ -12,38 +16,51 @@ 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.'); - } +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); + await verifyMinglarAdminToken(token); + const amXid = event.pathParameters?.amXid; + if (!amXid) { + throw new ApiError( + 400, + 'Account Manager XID is required in path parameters.', + ); + } - 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(amXid); + + // 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, - }), - }; -}); + 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/host/handlers/prepopulateRole.ts b/src/modules/minglaradmin/handlers/prepopulateRole.ts similarity index 100% rename from src/modules/host/handlers/prepopulateRole.ts rename to src/modules/minglaradmin/handlers/prepopulateRole.ts