diff --git a/serverless/functions/host.yml b/serverless/functions/host.yml index 2b1d8f9..4b27789 100644 --- a/serverless/functions/host.yml +++ b/serverless/functions/host.yml @@ -307,7 +307,6 @@ updatePQQ_LastAnswer: path: /host/Activity_Hub/OnBoarding/submit-final-pqq-answer method: post - submitPQQForReview: handler: src/modules/host/handlers/Activity_Hub/OnBoarding/submitPQQForReview.handler memorySize: 384 @@ -339,6 +338,21 @@ getAllPQQwithSubmittedAns: path: /host/Activity_Hub/OnBoarding/get-all-pqq-ques-submited-ans method: get +getAllDetailsOfActivityAndVenue: + handler: src/modules/host/handlers/Activity_Hub/OnBoarding/getAllDetailsOfActivityAndVenue.handler + memorySize: 512 + package: + patterns: + - 'src/modules/host/handlers/Activity_Hub/OnBoarding/**' + - ${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-details-activity-venue/{activityXid} + method: get + updateSuggestionAsReviewed: handler: src/modules/host/handlers/Activity_Hub/OnBoarding/updateSuggestionAsReviewed.handler memorySize: 512 diff --git a/src/modules/host/handlers/Activity_Hub/OnBoarding/getAllActivityType.ts b/src/modules/host/handlers/Activity_Hub/OnBoarding/getAllActivityType.ts index e6839d0..ffab71c 100644 --- a/src/modules/host/handlers/Activity_Hub/OnBoarding/getAllActivityType.ts +++ b/src/modules/host/handlers/Activity_Hub/OnBoarding/getAllActivityType.ts @@ -25,7 +25,7 @@ export const handler = safeHandler(async ( } // Verify token and get user info - const userInfo = await verifyHostToken(token); + await verifyHostToken(token); // Read optional search query (supports ?search= or ?q=) diff --git a/src/modules/host/handlers/Activity_Hub/OnBoarding/getAllDetailsOfActivityAndVenue.ts b/src/modules/host/handlers/Activity_Hub/OnBoarding/getAllDetailsOfActivityAndVenue.ts new file mode 100644 index 0000000..a8e72ae --- /dev/null +++ b/src/modules/host/handlers/Activity_Hub/OnBoarding/getAllDetailsOfActivityAndVenue.ts @@ -0,0 +1,47 @@ +import { verifyMinglarAdminHostToken } from '../../../../../common/middlewares/jwt/authForMinglarAdminHost'; +import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda'; +import { prismaClient } from '../../../../../common/database/prisma.lambda.service'; +import { safeHandler } from '../../../../../common/utils/handlers/safeHandler'; +import ApiError from '../../../../../common/utils/helper/ApiError'; +import { HostService } from '../../../services/host.service'; + +const hostService = new HostService(prismaClient); + +/** + * 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 + await verifyMinglarAdminHostToken(token); + + const activityXid = event.pathParameters?.activityXid + if (!activityXid) { + throw new ApiError(400, 'activityXid is required in path parameters'); + } + + const data = await hostService.getAllDetailsOfActivityAndVenue(Number(activityXid)); + + 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/host/services/host.service.ts b/src/modules/host/services/host.service.ts index 9a68f9a..622bd41 100644 --- a/src/modules/host/services/host.service.ts +++ b/src/modules/host/services/host.service.ts @@ -106,7 +106,7 @@ const bucket = config.aws.bucketName; @Injectable() export class HostService { - constructor(private prisma: PrismaClient) {} + constructor(private prisma: PrismaClient) { } async createHost(data: CreateHostDto) { return this.prisma.user.create({ data }); @@ -761,7 +761,7 @@ export class HostService { if ( existingHostCompany && existingHostCompany.hostStatusInternal === - HOST_STATUS_INTERNAL.HOST_TO_UPDATE && + HOST_STATUS_INTERNAL.HOST_TO_UPDATE && !isDraft ) { hostStatusInternal = HOST_STATUS_INTERNAL.HOST_SUBMITTED; @@ -774,7 +774,7 @@ export class HostService { else if ( existingHostCompany && existingHostCompany.hostStatusInternal === - HOST_STATUS_INTERNAL.HOST_TO_UPDATE && + HOST_STATUS_INTERNAL.HOST_TO_UPDATE && isDraft ) { // keep original @@ -885,19 +885,19 @@ export class HostService { // Safely handle city connection - only connect if valid ID exists cities: parentCompanyData?.cityXid && - !isNaN(Number(parentCompanyData.cityXid)) + !isNaN(Number(parentCompanyData.cityXid)) ? { connect: { id: Number(parentCompanyData.cityXid) } } : undefined, states: parentCompanyData?.stateXid && - !isNaN(Number(parentCompanyData.stateXid)) + !isNaN(Number(parentCompanyData.stateXid)) ? { connect: { id: Number(parentCompanyData.stateXid) } } : undefined, countries: parentCompanyData?.countryXid && - !isNaN(Number(parentCompanyData.countryXid)) + !isNaN(Number(parentCompanyData.countryXid)) ? { connect: { id: Number(parentCompanyData.countryXid) } } : undefined, pinCode: parentCompanyData.pinCode || null, @@ -1047,19 +1047,19 @@ export class HostService { address2: parentCompanyData.address2 || null, cities: parentCompanyData?.cityXid && - !isNaN(Number(parentCompanyData.cityXid)) + !isNaN(Number(parentCompanyData.cityXid)) ? { connect: { id: Number(parentCompanyData.cityXid) } } : undefined, states: parentCompanyData?.stateXid && - !isNaN(Number(parentCompanyData.stateXid)) + !isNaN(Number(parentCompanyData.stateXid)) ? { connect: { id: Number(parentCompanyData.stateXid) } } : undefined, countries: parentCompanyData?.countryXid && - !isNaN(Number(parentCompanyData.countryXid)) + !isNaN(Number(parentCompanyData.countryXid)) ? { connect: { id: Number(parentCompanyData.countryXid) } } : undefined, pinCode: parentCompanyData.pinCode || null, @@ -1105,19 +1105,19 @@ export class HostService { address2: parentCompanyData.address2 || null, cities: parentCompanyData?.cityXid && - !isNaN(Number(parentCompanyData.cityXid)) + !isNaN(Number(parentCompanyData.cityXid)) ? { connect: { id: Number(parentCompanyData.cityXid) } } : undefined, states: parentCompanyData?.stateXid && - !isNaN(Number(parentCompanyData.stateXid)) + !isNaN(Number(parentCompanyData.stateXid)) ? { connect: { id: Number(parentCompanyData.stateXid) } } : undefined, countries: parentCompanyData?.countryXid && - !isNaN(Number(parentCompanyData.countryXid)) + !isNaN(Number(parentCompanyData.countryXid)) ? { connect: { id: Number(parentCompanyData.countryXid) } } : undefined, pinCode: parentCompanyData.pinCode || null, @@ -1703,6 +1703,241 @@ export class HostService { }); } + async getAllDetailsOfActivityAndVenue(activityXid: number) { + return await this.prisma.activities.findMany({ + where: { id: activityXid, isActive: true }, + select: { + id: true, + activityTitle: true, + activityDescription: true, + activityDisplayStatus: true, + activityInternalStatus: true, + activityRefNumber: true, + checkInAddress: true, + checkInLat: true, + checkInLong: true, + checkOutAddress: true, + checkOutLat: true, + checkOutLong: true, + pickUpDropAvailable: true, + pickUpDropIsChargeable: true, + activityDurationMins: true, + activityType: { + select: { + id: true, + activityTypeName: true, + } + }, + ActivityPickUpDetails: { + where: { + isActive: true, + activityPickUpTransport: { + isActive: true, + transportMode: { + isActive: true + } + } + }, + select: { + id: true, + isPickUp: true, + locationAddress: true, + locationLat: true, + locationLong: true, + transportTotalPrice: true, + transportBasePrice: true, + + activityPickUpTransport: { + select: { + id: true, + isTransportModeChargeable: true, + + transportMode: { + select: { + transportModeName: true, + transportModeIcon: true + } + } + } + } + } + }, + foodAvailable: true, + foodIsChargeable: true, + activityFoodTypes: { + where: { isActive: true }, + select: { + id: true, + foodType: { + select: { + id: true, + foodTypeName: true + } + }, + } + }, + activityCuisines: { + where: { + isActive: true + }, + select: { + id: true, + foodCuisine: { + select: { + id: true, + cuisineName: true + } + } + } + }, + alcoholAvailable: true, + trainerAvailable: true, + trainerIsChargeable: true, + ActivityTrainers: { + where: { + isActive: true + }, + select: { + id: true, + totalAmount: true + } + }, + ActivityNavigationModes: { + where: { + isActive: true + }, + select: { + id: true, + isInActivityChargeable: true, + navigationModesTotalPrice: true, + navigationMode: { + select: { + id: true, + navigationModeName: true, + navigationModeIcon: true + } + } + } + }, + equipmentAvailable: true, + equipmentIsChargeable: true, + ActivityEquipments: { + where: { + isActive: true + }, + select: { + id: true, + equipmentName: true, + isEquipmentChargeable: true, + equipmentTotalPrice: true, + } + }, + ActivityOtherDetails: { + where: { + isActive: true + }, + select: { + id: true, + exclusiveNotes: true, + dosNotes: true, + dontsNotes: true, + tipsNotes: true, + termsAndCondition: true, + } + }, + energyLevel: { + where: { + isActive: true + }, + select: { + id: true, + energyLevelName: true, + energyIcon: true, + energyColor: true + } + }, + ActivityEligibility: { + where: { + isActive: true + }, + select: { + id: true, + isAgeRestriction: true, + ageRestriction: { + select: { + id: true, + ageRestrictionName: true, + minAge: true, + maxAge: true, + } + }, + isWeightRestriction: true, + weightRestrictionName: true, + weightEntered: true, + weightIn: true, + minWeight: true, + maxWeight: true, + isHeightRestriction: true, + heightRestrictionName: true, + heightEntered: true, + heightIn: true, + minHeight: true, + maxHeight: true + } + }, + ActivityAllowedEntry: { + where: { + isActive: true + }, + select: { + id: true, + allowedEntryType: { + select: { + id: true, + allowedEntryTypeName: true + } + } + } + }, + ActivityAmenities: { + where: { + isActive: true + }, + select: { + id: true, + amenities: { + select: { + id: true, + amenitiesName: true + } + } + } + }, + cancellationAvailable: true, + cancellationAllowedBeforeMins: true + // accountManager: { + // select: { + // id: true, + // firstName: true, + // lastName: true, + // emailAddress: true, + // mobileNumber: true, + // } + // }, + // host: { + // select: { + // id: true, + // companyName: true, + // stepper: true, + // adminStatusDisplay: true, + // adminStatusInternal: true, + // } + // } + + } + }) + } + async createActivity( userId: number, activityTypeXid: number, @@ -1973,340 +2208,436 @@ export class HostService { * ActivityPickUpTransport/Details + ActivityNavigationModes + ActivityEquipments + * ActivityAmenities + ActivityEligibility */ -async createOrUpdateActivity( - userId: number, - payload: any, - isDraft: boolean, -) { - /* ===================================================== - * HELPERS - * ===================================================== */ - const toBool = (v: any) => - v === true || v === 'true' || v === 1 || v === '1'; + async createOrUpdateActivity( + userId: number, + payload: any, + isDraft: boolean, + ) { + /* ===================================================== + * HELPERS + * ===================================================== */ + const toBool = (v: any) => + v === true || v === 'true' || v === 1 || v === '1'; - const toNumber = (v: any) => - v === undefined || v === null || v === '' ? undefined : Number(v); + const toNumber = (v: any) => + v === undefined || v === null || v === '' ? undefined : Number(v); - const round2 = (v: number) => Math.round(v); + const round2 = (v: number) => Math.round(v); - const computeBasePriceAndTaxes = ( - sellPrice: number, - taxes: Array<{ id: number; taxPer: number }>, - ) => { - if (!taxes.length) { - return { basePrice: round2(sellPrice), taxDetails: [] }; - } + const computeBasePriceAndTaxes = ( + sellPrice: number, + taxes: Array<{ id: number; taxPer: number }>, + ) => { + if (!taxes.length) { + return { basePrice: round2(sellPrice), taxDetails: [] }; + } - const totalTaxPer = taxes.reduce((s, t) => s + Number(t.taxPer || 0), 0); - const basePrice = round2(sellPrice / (1 + totalTaxPer / 100)); + const totalTaxPer = taxes.reduce((s, t) => s + Number(t.taxPer || 0), 0); + const basePrice = round2(sellPrice / (1 + totalTaxPer / 100)); - return { - basePrice, - taxDetails: taxes.map((t) => ({ - taxXid: t.id, - taxPer: t.taxPer, - taxAmount: round2(basePrice * (t.taxPer / 100)), - })), + return { + basePrice, + taxDetails: taxes.map((t) => ({ + taxXid: t.id, + taxPer: t.taxPer, + taxAmount: round2(basePrice * (t.taxPer / 100)), + })), + }; }; - }; - /* ===================================================== - * BASIC GUARDS - * ===================================================== */ - if (!payload.activityXid) { - throw new ApiError(400, 'activityXid is required'); - } - - /* ===================================================== - * HARD NORMALIZATION (SERVICE-LEVEL) - * ===================================================== */ - payload.foodAvailable = toBool(payload.foodAvailable); - payload.alcoholAvailable = toBool(payload.alcoholAvailable); - payload.trainerAvailable = toBool(payload.trainerAvailable); - payload.pickUpDropAvailable = toBool(payload.pickUpDropAvailable); - payload.inActivityAvailable = toBool(payload.inActivityAvailable); - payload.equipmentAvailable = toBool(payload.equipmentAvailable); - payload.cancellationAvailable = toBool(payload.cancellationAvailable); - payload.isInstantBooking = toBool(payload.isInstantBooking); - payload.isCheckOutSame = toBool(payload.isCheckOutSame); - - payload.trainerTotalAmount = toNumber(payload.trainerTotalAmount); - - if (payload.trainerAvailable) { - if ( - typeof payload.trainerTotalAmount !== 'number' || - Number.isNaN(payload.trainerTotalAmount) || - payload.trainerTotalAmount <= 0 - ) { - throw new ApiError(400, 'trainerTotalAmount must be > 0'); - } - } else { - delete payload.trainerTotalAmount; - } - - if (payload.venues && !Array.isArray(payload.venues)) { - throw new ApiError(400, 'venues must be an array'); - } - - payload.venues?.forEach((v, idx) => { - v.isMinPeopleReqMandatory = toBool(v.isMinPeopleReqMandatory); - - if (!v.venueName) { - throw new ApiError(400, `venues[${idx}] venueName required`); + /* ===================================================== + * BASIC GUARDS + * ===================================================== */ + if (!payload.activityXid) { + throw new ApiError(400, 'activityXid is required'); } - if (v.isMinPeopleReqMandatory && !v.minPeopleRequired) { - throw new ApiError(400, `venues[${idx}] min people requirement missing`); + /* ===================================================== + * HARD NORMALIZATION (SERVICE-LEVEL) + * ===================================================== */ + payload.foodAvailable = toBool(payload.foodAvailable); + payload.alcoholAvailable = toBool(payload.alcoholAvailable); + payload.trainerAvailable = toBool(payload.trainerAvailable); + payload.pickUpDropAvailable = toBool(payload.pickUpDropAvailable); + payload.inActivityAvailable = toBool(payload.inActivityAvailable); + payload.equipmentAvailable = toBool(payload.equipmentAvailable); + payload.cancellationAvailable = toBool(payload.cancellationAvailable); + payload.isInstantBooking = toBool(payload.isInstantBooking); + payload.isCheckOutSame = toBool(payload.isCheckOutSame); + + payload.trainerTotalAmount = toNumber(payload.trainerTotalAmount); + + if (payload.trainerAvailable) { + if ( + typeof payload.trainerTotalAmount !== 'number' || + Number.isNaN(payload.trainerTotalAmount) || + payload.trainerTotalAmount <= 0 + ) { + throw new ApiError(400, 'trainerTotalAmount must be > 0'); + } + } else { + delete payload.trainerTotalAmount; } - if (!Array.isArray(v.prices) || !v.prices.length) { - throw new ApiError(400, `venues[${idx}] must have at least one price`); + if (payload.venues && !Array.isArray(payload.venues)) { + throw new ApiError(400, 'venues must be an array'); } - }); - /* ===================================================== - * ROOT TAX - * ===================================================== */ - const taxIds = Array.isArray(payload.taxXids) - ? payload.taxXids.map(Number) - : []; + payload.venues?.forEach((v, idx) => { + v.isMinPeopleReqMandatory = toBool(v.isMinPeopleReqMandatory); - const rootTaxes = - taxIds.length > 0 - ? await this.prisma.taxes.findMany({ + if (!v.venueName) { + throw new ApiError(400, `venues[${idx}] venueName required`); + } + + if (v.isMinPeopleReqMandatory && !v.minPeopleRequired) { + throw new ApiError(400, `venues[${idx}] min people requirement missing`); + } + + if (!Array.isArray(v.prices) || !v.prices.length) { + throw new ApiError(400, `venues[${idx}] must have at least one price`); + } + }); + + /* ===================================================== + * ROOT TAX + * ===================================================== */ + const taxIds = Array.isArray(payload.taxXids) + ? payload.taxXids.map(Number) + : []; + + const rootTaxes = + taxIds.length > 0 + ? await this.prisma.taxes.findMany({ where: { id: { in: taxIds }, isActive: true }, select: { id: true, taxPer: true }, }) - : []; + : []; - if (taxIds.length !== rootTaxes.length) { - throw new ApiError(400, 'Invalid or inactive tax provided'); - } - - /* ===================================================== - * TRANSACTION - * ===================================================== */ - return await this.prisma.$transaction(async (tx) => { - /* -------------------------------- - * 1️⃣ HOST - * -------------------------------- */ - const host = await tx.hostHeader.findFirst({ - where: { userXid: userId, isActive: true }, - }); - if (!host) throw new ApiError(404, 'Host not found'); - - /* -------------------------------- - * 2️⃣ ACTIVITY - * -------------------------------- */ - const existingActivity = await tx.activities.findFirst({ - where: { - id: Number(payload.activityXid), - hostXid: host.id, - isActive: true, - }, - }); - if (!existingActivity) { - throw new ApiError(404, 'Activity not found'); + if (taxIds.length !== rootTaxes.length) { + throw new ApiError(400, 'Invalid or inactive tax provided'); } - /* -------------------------------- - * 3️⃣ STATUS DECISION - * -------------------------------- */ - let activityInternalStatus; - let activityDisplayStatus; - let amInternalStatus; - let amDisplayStatus; + /* ===================================================== + * TRANSACTION + * ===================================================== */ + return await this.prisma.$transaction(async (tx) => { + /* -------------------------------- + * 1️⃣ HOST + * -------------------------------- */ + const host = await tx.hostHeader.findFirst({ + where: { userXid: userId, isActive: true }, + }); + if (!host) throw new ApiError(404, 'Host not found'); - const wasRejected = - existingActivity.activityInternalStatus === - ACTIVITY_INTERNAL_STATUS.ACTIVITY_REJECTED; + /* -------------------------------- + * 2️⃣ ACTIVITY + * -------------------------------- */ + const existingActivity = await tx.activities.findFirst({ + where: { + id: Number(payload.activityXid), + hostXid: host.id, + isActive: true, + }, + }); + if (!existingActivity) { + throw new ApiError(404, 'Activity not found'); + } - if (wasRejected) { - if (isDraft) { - activityInternalStatus = existingActivity.activityInternalStatus; - activityDisplayStatus = existingActivity.activityDisplayStatus; - amInternalStatus = existingActivity.amInternalStatus; - amDisplayStatus = existingActivity.amDisplayStatus; + /* -------------------------------- + * 3️⃣ STATUS DECISION + * -------------------------------- */ + let activityInternalStatus; + let activityDisplayStatus; + let amInternalStatus; + let amDisplayStatus; + + const wasRejected = + existingActivity.activityInternalStatus === + ACTIVITY_INTERNAL_STATUS.ACTIVITY_REJECTED; + + if (wasRejected) { + if (isDraft) { + activityInternalStatus = existingActivity.activityInternalStatus; + activityDisplayStatus = existingActivity.activityDisplayStatus; + amInternalStatus = existingActivity.amInternalStatus; + amDisplayStatus = existingActivity.amDisplayStatus; + } else { + activityInternalStatus = ACTIVITY_INTERNAL_STATUS.ACTIVITY_SUBMITTED; + activityDisplayStatus = ACTIVITY_DISPLAY_STATUS.ACTIVITY_IN_REVIEW; + amInternalStatus = ACTIVITY_AM_INTERNAL_STATUS.ACTIVITY_TO_REVIEW; + amDisplayStatus = ACTIVITY_AM_DISPLAY_STATUS.ACTIVITY_NEW; + } } else { - activityInternalStatus = ACTIVITY_INTERNAL_STATUS.ACTIVITY_SUBMITTED; - activityDisplayStatus = ACTIVITY_DISPLAY_STATUS.ACTIVITY_IN_REVIEW; - amInternalStatus = ACTIVITY_AM_INTERNAL_STATUS.ACTIVITY_TO_REVIEW; - amDisplayStatus = ACTIVITY_AM_DISPLAY_STATUS.ACTIVITY_NEW; - } - } else { - if (isDraft) { - activityInternalStatus = ACTIVITY_INTERNAL_STATUS.ACTIVITY_DRAFT; - activityDisplayStatus = ACTIVITY_DISPLAY_STATUS.ACTIVITY_DRAFT; - amInternalStatus = ACTIVITY_AM_INTERNAL_STATUS.ACTIVITY_DRAFT; - amDisplayStatus = ACTIVITY_AM_DISPLAY_STATUS.ACTIVITY_DRAFT; - } else { - activityInternalStatus = ACTIVITY_INTERNAL_STATUS.ACTIVITY_SUBMITTED; - activityDisplayStatus = ACTIVITY_DISPLAY_STATUS.ACTIVITY_IN_REVIEW; - amInternalStatus = ACTIVITY_AM_INTERNAL_STATUS.ACTIVITY_TO_REVIEW; - amDisplayStatus = ACTIVITY_AM_DISPLAY_STATUS.ACTIVITY_NEW; - } - } - - /* -------------------------------- - * 4️⃣ UPDATE ACTIVITY CORE + FLAGS - * -------------------------------- */ - const activity = await tx.activities.update({ - where: { id: existingActivity.id }, - data: { - activityTypeXid: payload.activityTypeXid ?? undefined, - frequenciesXid: payload.frequenciesXid ?? undefined, - activityTitle: payload.activityTitle ?? undefined, - activityDescription: payload.activityDescription ?? undefined, - - checkInLat: payload.checkInLat ?? undefined, - checkInLong: payload.checkInLong ?? undefined, - checkInAddress: payload.checkInAddress ?? undefined, - isCheckOutSame: toBool(payload.isCheckOutSame), - checkOutLat: payload.checkOutLat ?? undefined, - checkOutLong: payload.checkOutLong ?? undefined, - checkOutAddress: payload.checkOutAddress ?? undefined, - - energyLevelXid: payload.energyLevelXid ?? undefined, - activityDurationMins: payload.activityDurationMins ?? undefined, - - currencyXid: payload.currencyXid ?? undefined, - sustainabilityScore: payload.sustainabilityScore ?? undefined, - safetyScore: payload.safetyScore ?? undefined, - isInstantBooking: payload.isInstantBooking ?? undefined, - - foodAvailable: payload.foodAvailable, - foodIsChargeable: toBool(payload.foodIsChargeable), - alcoholAvailable: payload.alcoholAvailable, - trainerAvailable: payload.trainerAvailable, - trainerIsChargeable: toBool(payload.trainerIsChargeable), - pickUpDropAvailable: payload.pickUpDropAvailable, - pickUpDropIsChargeable: toBool(payload.pickUpDropIsChargeable), - inActivityAvailable: payload.inActivityAvailable, - inActivityIsChargeable: toBool(payload.inActivityIsChargeable), - equipmentAvailable: payload.equipmentAvailable, - equipmentIsChargeable: toBool(payload.equipmentIsChargeable), - cancellationAvailable: payload.cancellationAvailable, - - activityInternalStatus, - activityDisplayStatus, - amInternalStatus, - amDisplayStatus, - }, - }); - - const activityXid = activity.id; - - /* -------------------------------- - * 5️⃣ CLEAN OLD ACTIVITY MEDIA - * -------------------------------- */ - await tx.activitiesMedia.deleteMany({ where: { activityXid } }); - - /* -------------------------------- - * 6️⃣ SAVE NEW ACTIVITY MEDIA - * -------------------------------- */ - if (Array.isArray(payload.media) && payload.media.length) { - await tx.activitiesMedia.createMany({ - data: payload.media.map((m, index) => ({ - activityXid, - mediaType: m.mediaType ?? 'unknown', - mediaFileName: m.mediaFileName, - displayOrder: index + 1, - })), - }); - } - - /* -------------------------------- - * 7️⃣ CLEAN OLD VENUES & RELATED DATA - * -------------------------------- */ - const oldVenueIds = ( - await tx.activityVenues.findMany({ - where: { activityXid }, - select: { id: true }, - }) - ).map((v) => v.id); - - if (oldVenueIds.length) { - // Clean venue artifacts (media) - await tx.activityVenueArtifacts.deleteMany({ - where: { activityVenueXid: { in: oldVenueIds } }, - }); - - // Clean price taxes and prices - const priceIds = ( - await tx.activityPrices.findMany({ - where: { activityVenueXid: { in: oldVenueIds } }, - select: { id: true }, - }) - ).map((p) => p.id); - - if (priceIds.length) { - await tx.activityPriceTaxes.deleteMany({ - where: { activityPriceXid: { in: priceIds } }, - }); - await tx.activityPrices.deleteMany({ - where: { id: { in: priceIds } }, - }); + if (isDraft) { + activityInternalStatus = ACTIVITY_INTERNAL_STATUS.ACTIVITY_DRAFT; + activityDisplayStatus = ACTIVITY_DISPLAY_STATUS.ACTIVITY_DRAFT; + amInternalStatus = ACTIVITY_AM_INTERNAL_STATUS.ACTIVITY_DRAFT; + amDisplayStatus = ACTIVITY_AM_DISPLAY_STATUS.ACTIVITY_DRAFT; + } else { + activityInternalStatus = ACTIVITY_INTERNAL_STATUS.ACTIVITY_SUBMITTED; + activityDisplayStatus = ACTIVITY_DISPLAY_STATUS.ACTIVITY_IN_REVIEW; + amInternalStatus = ACTIVITY_AM_INTERNAL_STATUS.ACTIVITY_TO_REVIEW; + amDisplayStatus = ACTIVITY_AM_DISPLAY_STATUS.ACTIVITY_NEW; + } } - // Clean venues - await tx.activityVenues.deleteMany({ - where: { id: { in: oldVenueIds } }, - }); - } - - /* -------------------------------- - * 8️⃣ CREATE VENUES WITH MEDIA & PRICES - * -------------------------------- */ - for (const venue of payload.venues ?? []) { - const venueRow = await tx.activityVenues.create({ + /* -------------------------------- + * 4️⃣ UPDATE ACTIVITY CORE + FLAGS + * -------------------------------- */ + const activity = await tx.activities.update({ + where: { id: existingActivity.id }, data: { - activityXid, - venueName: venue.venueName, - venueCapacity: toNumber(venue.venueCapacity) ?? 0, - availableSeats: toNumber(venue.availableSeats) ?? 0, - isMinPeopleReqMandatory: venue.isMinPeopleReqMandatory, - minPeopleRequired: toNumber(venue.minPeopleRequired) ?? null, - minReqfullfilledBeforeMins: - toNumber(venue.minReqfullfilledBeforeMins) ?? null, - venueDescription: venue.venueDescription ?? null, + activityTypeXid: payload.activityTypeXid ?? undefined, + frequenciesXid: payload.frequenciesXid ?? undefined, + activityTitle: payload.activityTitle ?? undefined, + activityDescription: payload.activityDescription ?? undefined, + + checkInLat: payload.checkInLat ?? undefined, + checkInLong: payload.checkInLong ?? undefined, + checkInAddress: payload.checkInAddress ?? undefined, + isCheckOutSame: toBool(payload.isCheckOutSame), + checkOutLat: payload.checkOutLat ?? undefined, + checkOutLong: payload.checkOutLong ?? undefined, + checkOutAddress: payload.checkOutAddress ?? undefined, + + energyLevelXid: payload.energyLevelXid ?? undefined, + activityDurationMins: payload.activityDurationMins ?? undefined, + + currencyXid: payload.currencyXid ?? undefined, + sustainabilityScore: payload.sustainabilityScore ?? undefined, + safetyScore: payload.safetyScore ?? undefined, + isInstantBooking: payload.isInstantBooking ?? undefined, + + foodAvailable: payload.foodAvailable, + foodIsChargeable: toBool(payload.foodIsChargeable), + alcoholAvailable: payload.alcoholAvailable, + trainerAvailable: payload.trainerAvailable, + trainerIsChargeable: toBool(payload.trainerIsChargeable), + pickUpDropAvailable: payload.pickUpDropAvailable, + pickUpDropIsChargeable: toBool(payload.pickUpDropIsChargeable), + inActivityAvailable: payload.inActivityAvailable, + inActivityIsChargeable: toBool(payload.inActivityIsChargeable), + equipmentAvailable: payload.equipmentAvailable, + equipmentIsChargeable: toBool(payload.equipmentIsChargeable), + cancellationAvailable: payload.cancellationAvailable, + + activityInternalStatus, + activityDisplayStatus, + amInternalStatus, + amDisplayStatus, }, }); - // Create venue media/artifacts - if (Array.isArray(venue.media) && venue.media.length) { - await tx.activityVenueArtifacts.createMany({ - data: venue.media.map((m) => ({ - activityVenueXid: venueRow.id, - mediaType: m.mediaType ?? 'image', + const activityXid = activity.id; + + /* -------------------------------- + * 5️⃣ CLEAN OLD ACTIVITY MEDIA + * -------------------------------- */ + await tx.activitiesMedia.deleteMany({ where: { activityXid } }); + + /* -------------------------------- + * 6️⃣ SAVE NEW ACTIVITY MEDIA + * -------------------------------- */ + if (Array.isArray(payload.media) && payload.media.length) { + await tx.activitiesMedia.createMany({ + data: payload.media.map((m, index) => ({ + activityXid, + mediaType: m.mediaType ?? 'unknown', mediaFileName: m.mediaFileName, + displayOrder: index + 1, })), }); } - // Create venue prices with taxes - for (const price of venue.prices ?? []) { - const sellPrice = Number(price.sellPrice); + /* -------------------------------- + * 7️⃣ CLEAN OLD VENUES & RELATED DATA + * -------------------------------- */ + const oldVenueIds = ( + await tx.activityVenues.findMany({ + where: { activityXid }, + select: { id: true }, + }) + ).map((v) => v.id); + + if (oldVenueIds.length) { + // Clean venue artifacts (media) + await tx.activityVenueArtifacts.deleteMany({ + where: { activityVenueXid: { in: oldVenueIds } }, + }); + + // Clean price taxes and prices + const priceIds = ( + await tx.activityPrices.findMany({ + where: { activityVenueXid: { in: oldVenueIds } }, + select: { id: true }, + }) + ).map((p) => p.id); + + if (priceIds.length) { + await tx.activityPriceTaxes.deleteMany({ + where: { activityPriceXid: { in: priceIds } }, + }); + await tx.activityPrices.deleteMany({ + where: { id: { in: priceIds } }, + }); + } + + // Clean venues + await tx.activityVenues.deleteMany({ + where: { id: { in: oldVenueIds } }, + }); + } + + /* -------------------------------- + * 8️⃣ CREATE VENUES WITH MEDIA & PRICES + * -------------------------------- */ + for (const venue of payload.venues ?? []) { + const venueRow = await tx.activityVenues.create({ + data: { + activityXid, + venueName: venue.venueName, + venueCapacity: toNumber(venue.venueCapacity) ?? 0, + availableSeats: toNumber(venue.availableSeats) ?? 0, + isMinPeopleReqMandatory: venue.isMinPeopleReqMandatory, + minPeopleRequired: toNumber(venue.minPeopleRequired) ?? null, + minReqfullfilledBeforeMins: + toNumber(venue.minReqfullfilledBeforeMins) ?? null, + venueDescription: venue.venueDescription ?? null, + }, + }); + + // Create venue media/artifacts + if (Array.isArray(venue.media) && venue.media.length) { + await tx.activityVenueArtifacts.createMany({ + data: venue.media.map((m) => ({ + activityVenueXid: venueRow.id, + mediaType: m.mediaType ?? 'image', + mediaFileName: m.mediaFileName, + })), + }); + } + + // Create venue prices with taxes + for (const price of venue.prices ?? []) { + const sellPrice = Number(price.sellPrice); + const { basePrice, taxDetails } = computeBasePriceAndTaxes( + sellPrice, + rootTaxes, + ); + + const priceRow = await tx.activityPrices.create({ + data: { + activityVenueXid: venueRow.id, + noOfSession: price.noOfSession ?? 1, + isPackage: price.isPackage ?? false, + sessionValidity: price.sessionValidity ?? 0, + sessionValidityFrequency: price.sessionValidityFrequency ?? 'Days', + basePrice, + sellPrice, + }, + }); + + if (taxDetails.length) { + await tx.activityPriceTaxes.createMany({ + data: taxDetails.map((t) => ({ + activityPriceXid: priceRow.id, + taxXid: t.taxXid, + taxPer: t.taxPer, + taxAmount: t.taxAmount, + })), + }); + } + } + } + + /* -------------------------------- + * 9️⃣ CLEAN & CREATE EQUIPMENT WITH TAXES + * -------------------------------- */ + const oldEquipmentIds = ( + await tx.activityEquipments.findMany({ + where: { activityXid }, + select: { id: true }, + }) + ).map((e) => e.id); + + if (oldEquipmentIds.length) { + await tx.activityEquipmentTaxes.deleteMany({ + where: { activityEquipmentXid: { in: oldEquipmentIds } }, + }); + await tx.activityEquipments.deleteMany({ + where: { id: { in: oldEquipmentIds } }, + }); + } + + if (Array.isArray(payload.equipments) && payload.equipments.length) { + for (const eq of payload.equipments) { + const totalPrice = toNumber(eq.equipmentTotalPrice) ?? 0; + const { basePrice, taxDetails } = computeBasePriceAndTaxes( + totalPrice, + rootTaxes, + ); + + const equipment = await tx.activityEquipments.create({ + data: { + activityXid, + equipmentName: eq.equipmentName, + isEquipmentChargeable: toBool(eq.isEquipmentChargeable), + equipmentBasePrice: basePrice, + equipmentTotalPrice: totalPrice, + }, + }); + + if (taxDetails.length) { + await tx.activityEquipmentTaxes.createMany({ + data: taxDetails.map((t) => ({ + activityEquipmentXid: equipment.id, + taxXid: t.taxXid, + taxPer: t.taxPer, + taxAmount: t.taxAmount, + })), + }); + } + } + } + + /* -------------------------------- + * 🔟 CLEAN & CREATE TRAINER WITH TAXES + * -------------------------------- */ + const oldTrainerIds = ( + await tx.activityTrainers.findMany({ + where: { activityXid }, + select: { id: true }, + }) + ).map((t) => t.id); + + if (oldTrainerIds.length) { + await tx.activityTrainerTaxes.deleteMany({ + where: { activityTrainerXid: { in: oldTrainerIds } }, + }); + await tx.activityTrainers.deleteMany({ + where: { id: { in: oldTrainerIds } }, + }); + } + + if (payload.trainerAvailable) { const { basePrice, taxDetails } = computeBasePriceAndTaxes( - sellPrice, + payload.trainerTotalAmount, rootTaxes, ); - const priceRow = await tx.activityPrices.create({ + const trainer = await tx.activityTrainers.create({ data: { - activityVenueXid: venueRow.id, - noOfSession: price.noOfSession ?? 1, - isPackage: price.isPackage ?? false, - sessionValidity: price.sessionValidity ?? 0, - sessionValidityFrequency: price.sessionValidityFrequency ?? 'Days', - basePrice, - sellPrice, + activityXid, + baseAmount: basePrice, + totalAmount: payload.trainerTotalAmount, }, }); if (taxDetails.length) { - await tx.activityPriceTaxes.createMany({ + await tx.activityTrainerTaxes.createMany({ data: taxDetails.map((t) => ({ - activityPriceXid: priceRow.id, + activityTrainerXid: trainer.id, taxXid: t.taxXid, taxPer: t.taxPer, taxAmount: t.taxAmount, @@ -2314,358 +2645,262 @@ async createOrUpdateActivity( }); } } - } - /* -------------------------------- - * 9️⃣ CLEAN & CREATE EQUIPMENT WITH TAXES - * -------------------------------- */ - const oldEquipmentIds = ( - await tx.activityEquipments.findMany({ - where: { activityXid }, - select: { id: true }, - }) - ).map((e) => e.id); + /* -------------------------------- + * 1️⃣1️⃣ CLEAN & CREATE PICKUP/DROP TRANSPORTS WITH DETAILS & TAXES + * -------------------------------- */ + const oldTransportIds = ( + await tx.activityPickUpTransport.findMany({ + where: { activityXid }, + select: { id: true }, + }) + ).map((t) => t.id); - if (oldEquipmentIds.length) { - await tx.activityEquipmentTaxes.deleteMany({ - where: { activityEquipmentXid: { in: oldEquipmentIds } }, - }); - await tx.activityEquipments.deleteMany({ - where: { id: { in: oldEquipmentIds } }, - }); - } + if (oldTransportIds.length) { + // Get all pickup details for these transports + const oldPickupDetailIds = ( + await tx.activityPickUpDetails.findMany({ + where: { activityPickUpTransportXid: { in: oldTransportIds } }, + select: { id: true }, + }) + ).map((p) => p.id); - if (Array.isArray(payload.equipments) && payload.equipments.length) { - for (const eq of payload.equipments) { - const totalPrice = toNumber(eq.equipmentTotalPrice) ?? 0; + if (oldPickupDetailIds.length) { + // Delete taxes first + await tx.activityPickUpTransportTaxes.deleteMany({ + where: { activityPickUpDetailsXid: { in: oldPickupDetailIds } }, + }); + // Delete pickup details + await tx.activityPickUpDetails.deleteMany({ + where: { id: { in: oldPickupDetailIds } }, + }); + } + + // Delete transports + await tx.activityPickUpTransport.deleteMany({ + where: { id: { in: oldTransportIds } }, + }); + } + + if ( + Array.isArray(payload.pickupTransports) && + payload.pickupTransports.length + ) { + for (const transport of payload.pickupTransports) { + // Create transport mode + const transportRow = await tx.activityPickUpTransport.create({ + data: { + activityXid, + transportModeXid: transport.transportModeXid, + isTransportModeChargeable: toBool( + transport.isTransportModeChargeable, + ), + }, + }); + + // Create pickup details for this transport + if ( + Array.isArray(transport.pickupDetails) && + transport.pickupDetails.length + ) { + for (const detail of transport.pickupDetails) { + const totalPrice = toNumber(detail.transportTotalPrice) ?? 0; + const { basePrice, taxDetails } = computeBasePriceAndTaxes( + totalPrice, + rootTaxes, + ); + + const pickupDetail = await tx.activityPickUpDetails.create({ + data: { + activityPickUpTransportXid: transportRow.id, + isPickUp: toBool(detail.isPickUp), + locationLat: toNumber(detail.locationLat), + locationLong: toNumber(detail.locationLong), + locationAddress: detail.locationAddress ?? null, + transportBasePrice: basePrice, + transportTotalPrice: totalPrice, + }, + }); + + if (taxDetails.length) { + await tx.activityPickUpTransportTaxes.createMany({ + data: taxDetails.map((t) => ({ + activityPickUpDetailsXid: pickupDetail.id, + taxXid: t.taxXid, + taxPer: t.taxPer, + taxAmount: t.taxAmount, + })), + }); + } + } + } + } + } + + /* -------------------------------- + * 1️⃣2️⃣ CLEAN & CREATE NAVIGATION MODES WITH TAXES + * -------------------------------- */ + const oldNavIds = ( + await tx.activityNavigationModes.findMany({ + where: { activityXid }, + select: { id: true }, + }) + ).map((n) => n.id); + + if (oldNavIds.length) { + await tx.activityNavigationModesTaxes.deleteMany({ + where: { activityNavigationModeXid: { in: oldNavIds } }, + }); + await tx.activityNavigationModes.deleteMany({ + where: { id: { in: oldNavIds } }, + }); + } + + if ( + Array.isArray(payload.navigationModes) && + payload.navigationModes.length + ) { + const totalPrice = toNumber(payload.navigationModeTotalPrice) ?? 0; const { basePrice, taxDetails } = computeBasePriceAndTaxes( totalPrice, rootTaxes, ); - const equipment = await tx.activityEquipments.create({ - data: { - activityXid, - equipmentName: eq.equipmentName, - isEquipmentChargeable: toBool(eq.isEquipmentChargeable), - equipmentBasePrice: basePrice, - equipmentTotalPrice: totalPrice, - }, - }); - - if (taxDetails.length) { - await tx.activityEquipmentTaxes.createMany({ - data: taxDetails.map((t) => ({ - activityEquipmentXid: equipment.id, - taxXid: t.taxXid, - taxPer: t.taxPer, - taxAmount: t.taxAmount, - })), + for (const modeId of payload.navigationModes) { + const navMode = await tx.activityNavigationModes.create({ + data: { + activityXid, + navigationModeXid: modeId, + isInActivityChargeable: toBool(payload.navigationModeIsChargeable), + navigationModesBasePrice: basePrice, + navigationModesTotalPrice: totalPrice, + }, }); - } - } - } - /* -------------------------------- - * 🔟 CLEAN & CREATE TRAINER WITH TAXES - * -------------------------------- */ - const oldTrainerIds = ( - await tx.activityTrainers.findMany({ - where: { activityXid }, - select: { id: true }, - }) - ).map((t) => t.id); - - if (oldTrainerIds.length) { - await tx.activityTrainerTaxes.deleteMany({ - where: { activityTrainerXid: { in: oldTrainerIds } }, - }); - await tx.activityTrainers.deleteMany({ - where: { id: { in: oldTrainerIds } }, - }); - } - - if (payload.trainerAvailable) { - const { basePrice, taxDetails } = computeBasePriceAndTaxes( - payload.trainerTotalAmount, - rootTaxes, - ); - - const trainer = await tx.activityTrainers.create({ - data: { - activityXid, - baseAmount: basePrice, - totalAmount: payload.trainerTotalAmount, - }, - }); - - if (taxDetails.length) { - await tx.activityTrainerTaxes.createMany({ - data: taxDetails.map((t) => ({ - activityTrainerXid: trainer.id, - taxXid: t.taxXid, - taxPer: t.taxPer, - taxAmount: t.taxAmount, - })), - }); - } - } - - /* -------------------------------- - * 1️⃣1️⃣ CLEAN & CREATE PICKUP/DROP TRANSPORTS WITH DETAILS & TAXES - * -------------------------------- */ - const oldTransportIds = ( - await tx.activityPickUpTransport.findMany({ - where: { activityXid }, - select: { id: true }, - }) - ).map((t) => t.id); - - if (oldTransportIds.length) { - // Get all pickup details for these transports - const oldPickupDetailIds = ( - await tx.activityPickUpDetails.findMany({ - where: { activityPickUpTransportXid: { in: oldTransportIds } }, - select: { id: true }, - }) - ).map((p) => p.id); - - if (oldPickupDetailIds.length) { - // Delete taxes first - await tx.activityPickUpTransportTaxes.deleteMany({ - where: { activityPickUpDetailsXid: { in: oldPickupDetailIds } }, - }); - // Delete pickup details - await tx.activityPickUpDetails.deleteMany({ - where: { id: { in: oldPickupDetailIds } }, - }); - } - - // Delete transports - await tx.activityPickUpTransport.deleteMany({ - where: { id: { in: oldTransportIds } }, - }); - } - - if ( - Array.isArray(payload.pickupTransports) && - payload.pickupTransports.length - ) { - for (const transport of payload.pickupTransports) { - // Create transport mode - const transportRow = await tx.activityPickUpTransport.create({ - data: { - activityXid, - transportModeXid: transport.transportModeXid, - isTransportModeChargeable: toBool( - transport.isTransportModeChargeable, - ), - }, - }); - - // Create pickup details for this transport - if ( - Array.isArray(transport.pickupDetails) && - transport.pickupDetails.length - ) { - for (const detail of transport.pickupDetails) { - const totalPrice = toNumber(detail.transportTotalPrice) ?? 0; - const { basePrice, taxDetails } = computeBasePriceAndTaxes( - totalPrice, - rootTaxes, - ); - - const pickupDetail = await tx.activityPickUpDetails.create({ - data: { - activityPickUpTransportXid: transportRow.id, - isPickUp: toBool(detail.isPickUp), - locationLat: toNumber(detail.locationLat), - locationLong: toNumber(detail.locationLong), - locationAddress: detail.locationAddress ?? null, - transportBasePrice: basePrice, - transportTotalPrice: totalPrice, - }, + if (taxDetails.length) { + await tx.activityNavigationModesTaxes.createMany({ + data: taxDetails.map((t) => ({ + activityNavigationModeXid: navMode.id, + taxXid: t.taxXid, + taxPer: t.taxPer, + taxAmount: t.taxAmount, + })), }); - - if (taxDetails.length) { - await tx.activityPickUpTransportTaxes.createMany({ - data: taxDetails.map((t) => ({ - activityPickUpDetailsXid: pickupDetail.id, - taxXid: t.taxXid, - taxPer: t.taxPer, - taxAmount: t.taxAmount, - })), - }); - } } } } - } - /* -------------------------------- - * 1️⃣2️⃣ CLEAN & CREATE NAVIGATION MODES WITH TAXES - * -------------------------------- */ - const oldNavIds = ( - await tx.activityNavigationModes.findMany({ - where: { activityXid }, - select: { id: true }, - }) - ).map((n) => n.id); + /* -------------------------------- + * 1️⃣3️⃣ CLEAN & CREATE AMENITIES + * -------------------------------- */ + await tx.activityAmenities.deleteMany({ where: { activityXid } }); - if (oldNavIds.length) { - await tx.activityNavigationModesTaxes.deleteMany({ - where: { activityNavigationModeXid: { in: oldNavIds } }, - }); - await tx.activityNavigationModes.deleteMany({ - where: { id: { in: oldNavIds } }, - }); - } + if (Array.isArray(payload.amenitiesIds) && payload.amenitiesIds.length) { + await tx.activityAmenities.createMany({ + data: payload.amenitiesIds.map((amenityId) => ({ + activityXid, + amenitiesXid: amenityId, + })), + }); + } - if ( - Array.isArray(payload.navigationModes) && - payload.navigationModes.length - ) { - const totalPrice = toNumber(payload.navigationModeTotalPrice) ?? 0; - const { basePrice, taxDetails } = computeBasePriceAndTaxes( - totalPrice, - rootTaxes, - ); + /* -------------------------------- + * 1️⃣4️⃣ CLEAN & CREATE ELIGIBILITY + * -------------------------------- */ + await tx.activityEligibility.deleteMany({ where: { activityXid } }); - for (const modeId of payload.navigationModes) { - const navMode = await tx.activityNavigationModes.create({ + if (payload.eligibility) { + await tx.activityEligibility.create({ data: { activityXid, - navigationModeXid: modeId, - isInActivityChargeable: toBool(payload.navigationModeIsChargeable), - navigationModesBasePrice: basePrice, - navigationModesTotalPrice: totalPrice, + isAgeRestriction: toBool(payload.eligibility.isAgeRestriction), + ageRestrictionXid: toNumber(payload.eligibility.ageRestrictionXid), + isWeightRestriction: toBool(payload.eligibility.isWeightRestriction), + weightRestrictionName: payload.eligibility.weightRestrictionName ?? null, + weightEntered: toNumber(payload.eligibility.weightEntered), + weightIn: payload.eligibility.weightIn ?? null, + minWeight: toNumber(payload.eligibility.minWeight), + maxWeight: toNumber(payload.eligibility.maxWeight), + isHeightRestriction: toBool(payload.eligibility.isHeightRestriction), + heightRestrictionName: payload.eligibility.heightRestrictionName ?? null, + heightEntered: toNumber(payload.eligibility.heightEntered), + heightIn: payload.eligibility.heightIn ?? null, + minHeight: toNumber(payload.eligibility.minHeight), + maxHeight: toNumber(payload.eligibility.maxHeight), }, }); - - if (taxDetails.length) { - await tx.activityNavigationModesTaxes.createMany({ - data: taxDetails.map((t) => ({ - activityNavigationModeXid: navMode.id, - taxXid: t.taxXid, - taxPer: t.taxPer, - taxAmount: t.taxAmount, - })), - }); - } } - } - /* -------------------------------- - * 1️⃣3️⃣ CLEAN & CREATE AMENITIES - * -------------------------------- */ - await tx.activityAmenities.deleteMany({ where: { activityXid } }); + /* -------------------------------- + * 1️⃣5️⃣ CLEAN & CREATE OTHER DETAILS + * -------------------------------- */ + await tx.activityOtherDetails.deleteMany({ where: { activityXid } }); - if (Array.isArray(payload.amenitiesIds) && payload.amenitiesIds.length) { - await tx.activityAmenities.createMany({ - data: payload.amenitiesIds.map((amenityId) => ({ - activityXid, - amenitiesXid: amenityId, - })), - }); - } + if (payload.otherDetails) { + await tx.activityOtherDetails.create({ + data: { + activityXid, + exclusiveNotes: payload.otherDetails.exclusiveNotes ?? null, + dosNotes: payload.otherDetails.dosNotes ?? null, + dontsNotes: payload.otherDetails.dontsNotes ?? null, + tipsNotes: payload.otherDetails.tipsNotes ?? null, + termsAndCondition: payload.otherDetails.termsAndCondition ?? null, + }, + }); + } - /* -------------------------------- - * 1️⃣4️⃣ CLEAN & CREATE ELIGIBILITY - * -------------------------------- */ - await tx.activityEligibility.deleteMany({ where: { activityXid } }); + /* -------------------------------- + * 1️⃣6️⃣ CLEAN & CREATE FOOD TYPES + * -------------------------------- */ + await tx.activityFoodTypes.deleteMany({ where: { activityXid } }); - if (payload.eligibility) { - await tx.activityEligibility.create({ + if (Array.isArray(payload.foodTypeIds) && payload.foodTypeIds.length) { + await tx.activityFoodTypes.createMany({ + data: payload.foodTypeIds.map((foodTypeId) => ({ + activityXid, + foodTypeXid: foodTypeId, + })), + }); + } + + /* -------------------------------- + * 1️⃣7️⃣ CLEAN & CREATE CUISINES + * -------------------------------- */ + await tx.activityCuisine.deleteMany({ where: { activityXid } }); + + if (Array.isArray(payload.cuisineIds) && payload.cuisineIds.length) { + await tx.activityCuisine.createMany({ + data: payload.cuisineIds.map((cuisineId) => ({ + activityXid, + foodCuisineXid: cuisineId, + })), + }); + } + + /* -------------------------------- + * 1️⃣8️⃣ ACTIVITY TRACK + * -------------------------------- */ + await tx.activityTrack.create({ data: { activityXid, - isAgeRestriction: toBool(payload.eligibility.isAgeRestriction), - ageRestrictionXid: toNumber(payload.eligibility.ageRestrictionXid), - isWeightRestriction: toBool(payload.eligibility.isWeightRestriction), - weightRestrictionName: payload.eligibility.weightRestrictionName ?? null, - weightEntered: toNumber(payload.eligibility.weightEntered), - weightIn: payload.eligibility.weightIn ?? null, - minWeight: toNumber(payload.eligibility.minWeight), - maxWeight: toNumber(payload.eligibility.maxWeight), - isHeightRestriction: toBool(payload.eligibility.isHeightRestriction), - heightRestrictionName: payload.eligibility.heightRestrictionName ?? null, - heightEntered: toNumber(payload.eligibility.heightEntered), - heightIn: payload.eligibility.heightIn ?? null, - minHeight: toNumber(payload.eligibility.minHeight), - maxHeight: toNumber(payload.eligibility.maxHeight), + trackType: 'ACTIVITY', + trackStatus: activityInternalStatus, + updatedByXid: userId, + updatedByRole: ROLE_NAME.HOST, + updatedOn: new Date(), }, }); - } - /* -------------------------------- - * 1️⃣5️⃣ CLEAN & CREATE OTHER DETAILS - * -------------------------------- */ - await tx.activityOtherDetails.deleteMany({ where: { activityXid } }); - - if (payload.otherDetails) { - await tx.activityOtherDetails.create({ - data: { - activityXid, - exclusiveNotes: payload.otherDetails.exclusiveNotes ?? null, - dosNotes: payload.otherDetails.dosNotes ?? null, - dontsNotes: payload.otherDetails.dontsNotes ?? null, - tipsNotes: payload.otherDetails.tipsNotes ?? null, - termsAndCondition: payload.otherDetails.termsAndCondition ?? null, - }, - }); - } - - /* -------------------------------- - * 1️⃣6️⃣ CLEAN & CREATE FOOD TYPES - * -------------------------------- */ - await tx.activityFoodTypes.deleteMany({ where: { activityXid } }); - - if (Array.isArray(payload.foodTypeIds) && payload.foodTypeIds.length) { - await tx.activityFoodTypes.createMany({ - data: payload.foodTypeIds.map((foodTypeId) => ({ - activityXid, - foodTypeXid: foodTypeId, - })), - }); - } - - /* -------------------------------- - * 1️⃣7️⃣ CLEAN & CREATE CUISINES - * -------------------------------- */ - await tx.activityCuisine.deleteMany({ where: { activityXid } }); - - if (Array.isArray(payload.cuisineIds) && payload.cuisineIds.length) { - await tx.activityCuisine.createMany({ - data: payload.cuisineIds.map((cuisineId) => ({ - activityXid, - foodCuisineXid: cuisineId, - })), - }); - } - - /* -------------------------------- - * 1️⃣8️⃣ ACTIVITY TRACK - * -------------------------------- */ - await tx.activityTrack.create({ - data: { + /* -------------------------------- + * 1️⃣9️⃣ RESPONSE + * -------------------------------- */ + return { activityXid, - trackType: 'ACTIVITY', - trackStatus: activityInternalStatus, - updatedByXid: userId, - updatedByRole: ROLE_NAME.HOST, - updatedOn: new Date(), - }, + activityRefNumber: activity.activityRefNumber, + status: isDraft ? ACTIVITY_INTERNAL_STATUS.ACTIVITY_DRAFT : ACTIVITY_INTERNAL_STATUS.ACTIVITY_SUBMITTED, + }; }); - - /* -------------------------------- - * 1️⃣9️⃣ RESPONSE - * -------------------------------- */ - return { - activityXid, - activityRefNumber: activity.activityRefNumber, - status: isDraft ? ACTIVITY_INTERNAL_STATUS.ACTIVITY_DRAFT : ACTIVITY_INTERNAL_STATUS.ACTIVITY_SUBMITTED, - }; - }); -} + } async getAllPQUpdatedResponse(activityXid: number) { const pqqHeaderData = await this.prisma.activityPQQheader.findMany({ where: { diff --git a/src/modules/minglaradmin/handlers/hosthub/hosts/rejectHostApplicationAM.ts b/src/modules/minglaradmin/handlers/hosthub/hosts/rejectHostApplicationAM.ts index 4e47a59..35ad79d 100644 --- a/src/modules/minglaradmin/handlers/hosthub/hosts/rejectHostApplicationAM.ts +++ b/src/modules/minglaradmin/handlers/hosthub/hosts/rejectHostApplicationAM.ts @@ -5,6 +5,7 @@ import { safeHandler } from '../../../../../common/utils/handlers/safeHandler'; import ApiError from '../../../../../common/utils/helper/ApiError'; import { MinglarService } from '../../../services/minglar.service'; import { sendAMRejectionMailtoHost } from '../../../services/rejectionMailtoHost.service'; +import config from '../../../../../config/config'; const minglarService = new MinglarService(prismaClient); @@ -47,7 +48,7 @@ export const handler = safeHandler(async ( // Add suggestion using service await minglarService.rejectHostApplicationAM(hostXid, userInfo.id); const hostDetails = await minglarService.getUserDetails(hostXid) - await sendAMRejectionMailtoHost(hostDetails.emailAddress, hostDetails.firstName) + await sendAMRejectionMailtoHost(hostDetails.emailAddress, hostDetails.firstName, config.HOST_LINK) return { statusCode: 200, diff --git a/src/modules/minglaradmin/services/rejectionMailtoHost.service.ts b/src/modules/minglaradmin/services/rejectionMailtoHost.service.ts index 8f50509..0d2f8f8 100644 --- a/src/modules/minglaradmin/services/rejectionMailtoHost.service.ts +++ b/src/modules/minglaradmin/services/rejectionMailtoHost.service.ts @@ -39,7 +39,8 @@ export async function sendEmailToHostForRejectedApplication( export async function sendAMRejectionMailtoHost( emailAddress: string, - name: string + name: string, + link: string ): Promise<{ sent: boolean; // messageId: string @@ -53,8 +54,8 @@ export async function sendAMRejectionMailtoHost( Please make the necessary improvements and re-submit your application to proceed with the onboarding process on Minglar.

You may access your application using the link below:
Link: - - ${config.HOST_LINK} + + ${link}

If you have any questions, please feel free to contact the Minglar Support Team.