From fb9a92984b7b0e35a198d7ab6dbacd29b8ab7e11 Mon Sep 17 00:00:00 2001 From: Mayank Mishra Date: Fri, 14 Nov 2025 14:08:47 +0530 Subject: [PATCH 1/3] fixed the schema issues --- prisma/schema.prisma | 139 ++++++++++++++++-- .../host/addPaymentDetails.validation.ts | 5 +- src/modules/host/dto/host.dto.ts | 4 +- .../host/handlers/addCompanyDetails.ts | 2 +- .../host/handlers/addPaymentDetails.ts | 9 +- src/modules/host/services/host.service.ts | 41 +++--- 6 files changed, 161 insertions(+), 39 deletions(-) diff --git a/prisma/schema.prisma b/prisma/schema.prisma index ad58f2e..41da670 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -33,7 +33,8 @@ model User { EnergyLevels EnergyLevels? @relation(fields: [energyLevelsId], references: [id]) isBiometric Boolean? @default(false) @map("is_biometric") energyLevelsId Int? - HostHeader HostHeader[] + hostHeaders HostHeader[] @relation("HostUser") + managedHostHeaders HostHeader[] @relation("AccountManager") Token Token[] ReviewedSuggestions HostSuggestion[] @relation("UserReviewedSuggestions") hostTrack HostTrack[] @@ -47,6 +48,13 @@ model User { ActivitySOSDetails ActivitySOSDetails[] ActivityFeedbacks ActivityFeedbacks[] ItineraryDetails ItineraryDetails[] + inviteDetails InviteDetails[] @relation("InvitedUser") + invitedInviteDetails InviteDetails[] @relation("InviterUser") + userRevenues UserRevenue[] + userInterests UserInterests[] + connectDetails ConnectDetails[] + friends Friends[] + friendOf Friends[] @relation("FriendUser") @@map("users") @@schema("usr") @@ -71,6 +79,86 @@ model UserOtp { @@schema("usr") } +model InviteDetails { + id Int @id @default(autoincrement()) + userXid Int @map("user_xid") + user User @relation("InvitedUser", fields: [userXid], references: [id], onDelete: Cascade) + is_invited Boolean @default(false) @map("is_invited") + invited_by Int @map("invited_by") + invitedBy User @relation("InviterUser", fields: [invited_by], references: [id], onDelete: Restrict) + invited_on DateTime @default(now()) @map("invited_on") + is_accepted Boolean @default(false) @map("is_accepted") + accepted_on DateTime? @map("accepted_on") + invitation_status String @default("pending") @map("invitation_status") + isActive Boolean @default(true) @map("is_active") + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + deletedAt DateTime? @map("deleted_at") + + @@map("invite_details") + @@schema("usr") +} + +model UserRevenue { + id Int @id @default(autoincrement()) + userXid Int @map("user_xid") + user User @relation(fields: [userXid], references: [id], onDelete: Cascade) + is_fixed_salary Boolean @default(false) @map("is_fixed_salary") + per_value Float @map("per_value") + isActive Boolean @default(true) @map("is_active") + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + deletedAt DateTime? @map("deleted_at") + + @@map("user_revenue") + @@schema("usr") +} + +model ConnectDetails { + id Int @id @default(autoincrement()) + userXid Int @map("user_xid") + user User @relation(fields: [userXid], references: [id], onDelete: Cascade) + connectXid Int @map("connect_xid") + connect Connections @relation(fields: [connectXid], references: [id], onDelete: Cascade) + isActive Boolean @default(true) @map("is_active") + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + deletedAt DateTime? @map("deleted_at") + + @@map("connect_details") + @@schema("usr") +} + +model Friends { + id Int @id @default(autoincrement()) + userXid Int @map("user_xid") + user User @relation(fields: [userXid], references: [id], onDelete: Cascade) + friendXid Int @map("friend_xid") + friend User @relation("FriendUser", fields: [friendXid], references: [id], onDelete: Cascade) + isActive Boolean @default(true) @map("is_active") + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + deletedAt DateTime? @map("deleted_at") + + @@map("friends") + @@schema("usr") +} + +model UserInterests { + id Int @id @default(autoincrement()) + userXid Int @map("user_xid") + user User @relation(fields: [userXid], references: [id], onDelete: Cascade) + interestXid Int @map("interest_xid") + interest Interests @relation(fields: [interestXid], references: [id], onDelete: Cascade) + isActive Boolean @default(true) @map("is_active") + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + deletedAt DateTime? @map("deleted_at") + + @@map("user_interests") + @@schema("usr") +} + model Countries { id Int @id @default(autoincrement()) countryName String @unique @map("country_name") @@ -210,6 +298,7 @@ model Interests { updatedAt DateTime @updatedAt @map("updated_at") deletedAt DateTime? @map("deleted_at") ActivityTypes ActivityTypes[] + userInterests UserInterests[] @@map("interests") @@schema("mst") @@ -233,7 +322,6 @@ model ActivityTypes { model DocumentType { id Int @id @default(autoincrement()) documentTypeName String @unique @map("document_type_name") - displayOrder Int @map("display_order") isVisible Boolean @default(true) @map("is_visible") isActive Boolean @default(true) @map("is_active") createdAt DateTime @default(now()) @map("created_at") @@ -246,6 +334,30 @@ model DocumentType { @@schema("mst") } +model FoodCuisines { + id Int @id @default(autoincrement()) + cuisineName String @unique @map("cuisine_name") + isActive Boolean @default(true) @map("is_active") + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + deletedAt DateTime? @map("deleted_at") + + @@map("food_cuisines") + @@schema("mst") +} + +model CompanyTypes { + id Int @id @default(autoincrement()) + companyTypeName String @unique @map("company_type_name") + isActive Boolean @default(true) @map("is_active") + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + deletedAt DateTime? @map("deleted_at") + + @@map("company_types") + @@schema("mst") +} + model Amenities { id Int @id @default(autoincrement()) amenitiesName String @unique @map("amenities_name") @@ -405,15 +517,16 @@ model Roles { } model Connections { - id Int @id @default(autoincrement()) - connectionType String @unique @map("connection_type") - connectionName String @map("connection_name") - locationDetails String @map("location_details") - isActive Boolean @default(true) @map("is_active") - createdAt DateTime @default(now()) @map("created_at") - updatedAt DateTime @updatedAt @map("updated_at") - deletedAt DateTime? @map("deleted_at") + id Int @id @default(autoincrement()) + connectionType String @unique @map("connection_type") + connectionName String @map("connection_name") + locationDetails String @map("location_details") + isActive Boolean @default(true) @map("is_active") + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + deletedAt DateTime? @map("deleted_at") User User[] + connectDetails ConnectDetails[] @@map("connections") @@schema("mst") @@ -459,6 +572,8 @@ model Token { model HostHeader { id Int @id @default(autoincrement()) + userXid Int @map("user_xid") + user User @relation("HostUser", fields: [userXid], references: [id], onDelete: Cascade) companyName String @map("company_name") hostRefNumber String @map("host_ref_number") address1 String @map("address_1") @@ -492,7 +607,7 @@ model HostHeader { amStatus String @default("pending") @map("am_status") agreementAccepted Boolean @default(false) @map("agreement_accepted") accountManagerXid Int? @map("account_manager_xid") - accountManager User? @relation(fields: [accountManagerXid], references: [id], onDelete: Restrict) + accountManager User? @relation("AccountManager", fields: [accountManagerXid], references: [id], onDelete: Restrict) isApproved Boolean @default(false) @map("is_approved") agreementStartDate DateTime? @map("agreement_start_date") durationNumber Int? @map("duration_number") @@ -524,7 +639,7 @@ model HostBankDetails { bankBranchXid Int @map("bank_branch_xid") bankBranches BankBranches @relation(fields: [bankBranchXid], references: [id], onDelete: Restrict) accountHolderName String @map("account_holder_name") - accountNumber Int @unique @map("account_number") + accountNumber String @unique @map("account_number") ifscCode String @map("ifsc_code") isActive Boolean @default(true) @map("is_active") createdAt DateTime @default(now()) @map("created_at") diff --git a/src/common/utils/validation/host/addPaymentDetails.validation.ts b/src/common/utils/validation/host/addPaymentDetails.validation.ts index bbd30a1..846b83d 100644 --- a/src/common/utils/validation/host/addPaymentDetails.validation.ts +++ b/src/common/utils/validation/host/addPaymentDetails.validation.ts @@ -3,9 +3,8 @@ import { z } from "zod"; export const hostBankDetailsSchema = z.object({ accountNumber: z - .number() - .int({ message: "Account number must be an integer" }) - .positive({ message: "Account number must be a positive number" }), + .string() + .nonempty("Account number is required"), accountHolderName: z .string() diff --git a/src/modules/host/dto/host.dto.ts b/src/modules/host/dto/host.dto.ts index b991589..16096ca 100644 --- a/src/modules/host/dto/host.dto.ts +++ b/src/modules/host/dto/host.dto.ts @@ -77,12 +77,12 @@ export class GetHostLoginResponseDTO { export class AddPaymentDetailsDTO { bankXid: number; bankBranchXid: number; - accountNumber: number; + accountNumber: string; accountHolderName: string; ifscCode: string; hostXid: number; - constructor(bankXid: number, bankBranchXid: number, accountNumber: number, accountHolderName: string, ifscCode: string, hostXid: number) { + constructor(bankXid: number, bankBranchXid: number, accountNumber: string, accountHolderName: string, ifscCode: string, hostXid: number) { this.bankXid = bankXid; this.bankBranchXid = bankBranchXid; this.accountNumber = accountNumber; diff --git a/src/modules/host/handlers/addCompanyDetails.ts b/src/modules/host/handlers/addCompanyDetails.ts index 1b92214..026bf6d 100644 --- a/src/modules/host/handlers/addCompanyDetails.ts +++ b/src/modules/host/handlers/addCompanyDetails.ts @@ -213,7 +213,7 @@ export const handler = safeHandler(async (event: APIGatewayProxyEvent): Promise< } // 14) Persist using hostService (we updated service to accept optional parent info) - const created = await hostService.addCompanyDetails(parsedCompany, uploadedHostDocs, parsedParentCompany, uploadedParentDocs); + const created = await hostService.addCompanyDetails(userInfo.id, parsedCompany, uploadedHostDocs, parsedParentCompany, uploadedParentDocs); if (!created) throw new ApiError(400, 'Failed to add company details.'); // 15) Success diff --git a/src/modules/host/handlers/addPaymentDetails.ts b/src/modules/host/handlers/addPaymentDetails.ts index 1ca6859..24be6ab 100644 --- a/src/modules/host/handlers/addPaymentDetails.ts +++ b/src/modules/host/handlers/addPaymentDetails.ts @@ -27,6 +27,11 @@ export const handler = safeHandler(async ( throw new ApiError(400, 'Host id must be a number'); } + const host = await hostService.getHostIdByUserXid(hostId); + if (!host) { + throw new ApiError(404, 'Host not found'); + } + // Parse request body let body: { bankXid?: number; bankBranchXid?: number; accountNumber?: string; accountHolderName?: string; ifscCode?: string }; @@ -39,7 +44,7 @@ export const handler = safeHandler(async ( // ✅ Validate payload using Zod const validationResult = hostBankDetailsSchema.safeParse({ ...(body as object), - hostXid: hostId, // inject hostId from token (not from user input) + hostXid: host.id, // inject hostId from token (not from user input) }); if (!validationResult.success) { @@ -49,7 +54,7 @@ export const handler = safeHandler(async ( const validatedData = validationResult.data; - await hostService.addPaymentDetails(hostId, validatedData); + await hostService.addPaymentDetails(validatedData); return { statusCode: 200, diff --git a/src/modules/host/services/host.service.ts b/src/modules/host/services/host.service.ts index 77d5e98..9102a79 100644 --- a/src/modules/host/services/host.service.ts +++ b/src/modules/host/services/host.service.ts @@ -32,13 +32,22 @@ export class HostService { return this.prisma.user.findMany({ where: { roleXid: 3 } }); } + async getHostIdByUserXid(user_xid: number) { + const host = await this.prisma.hostHeader.findFirst({ + where: { userXid: user_xid }, + select: { id: true, companyName: true, countryXid: true }, + }); + return host; + } + async getHostById(id: number) { const host = await this.prisma.user.findUnique({ where: { id }, include: { - HostHeader: { + hostHeaders: { select: { id: true, + userXid: true, companyName: true, hostRefNumber: true, address1: true, @@ -219,27 +228,20 @@ export class HostService { return true; } - async addPaymentDetails(id: number, data: AddPaymentDetailsDTO): Promise { - const existingUser = await this.prisma.user.findUnique({ - where: { id }, - }); - - if (!existingUser) { - throw new ApiError(404, 'User not found'); - } - + async addPaymentDetails(data: AddPaymentDetailsDTO): Promise { const addedPaymentDetails = await this.prisma.hostBankDetails.create({ data, }); - + if (!addedPaymentDetails) { throw new ApiError(400, 'Failed to add payment details'); } - + return addedPaymentDetails; } async addCompanyDetails( + user_xid: number, companyData: HostCompanyDetailsInput, documents: HostDocumentInput[], // host documents with S3 URLs parentCompanyData?: any | null, // optional parent company object @@ -253,10 +255,11 @@ export class HostService { if (existingHost) { throw new ApiError(400, 'Company already exists with this registration number'); } - + // 2) Create host header record const createdHost = await tx.hostHeader.create({ data: { + userXid: user_xid, companyName: companyData.companyName, hostRefNumber: companyData.hostRefNumber, address1: companyData.address1, @@ -285,7 +288,7 @@ export class HostService { adminStatusDisplay: MINGLAR_STATUS_DISPLAY.NEW, }, }); - + // 3) Create host documents if (documents && documents.length > 0) { const docsData = documents.map((doc) => ({ @@ -296,7 +299,7 @@ export class HostService { })); await tx.hostDocuments.createMany({ data: docsData }); } - + // 4) If subsidiary and parentCompanyData present -> create parent record + parent docs if (companyData.isSubsidairy && parentCompanyData) { // create HostParent with link to createdHost.id (hostXid) @@ -324,7 +327,7 @@ export class HostService { twitterUrl: parentCompanyData.twitterUrl || null, }, }); - + // create parent documents if (parentDocuments && parentDocuments.length > 0) { const parentDocsData = parentDocuments.map((doc) => ({ @@ -333,13 +336,13 @@ export class HostService { documentName: doc.documentName, filePath: doc.filePath, })); - + await tx.hostParenetDocuments.createMany({ data: parentDocsData }); } } - + return createdHost; }); } - + } From 6b3d2ae7cff08ab4435f4387514899dfb4af1a12 Mon Sep 17 00:00:00 2001 From: Mayank Mishra Date: Fri, 14 Nov 2025 14:44:04 +0530 Subject: [PATCH 2/3] added cors --- src/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.ts b/src/main.ts index 5da83ba..7d96fdc 100644 --- a/src/main.ts +++ b/src/main.ts @@ -16,7 +16,7 @@ async function bootstrap() { app.enableCors({ origin: [ 'http://localhost:3000', // Local Swagger UI - 'http://localhost:3006', // Local Frontend + 'http://localhost:5173', // Local Frontend 'https://editor.swagger.io', // Swagger Editor 'https://klc-admin.wdiprojects.com', 'https://admin-uat.klc.betadelivery.com', From 43a2a1c2b1f86d65881f6cccde8655c11252c600 Mon Sep 17 00:00:00 2001 From: Mayank Mishra Date: Fri, 14 Nov 2025 15:04:01 +0530 Subject: [PATCH 3/3] fixed the getbyid host endpoint --- serverless.yml | 2 +- src/modules/host/services/host.service.ts | 71 ++++------------------- 2 files changed, 11 insertions(+), 62 deletions(-) diff --git a/serverless.yml b/serverless.yml index ff5a6fa..52d1fce 100644 --- a/serverless.yml +++ b/serverless.yml @@ -189,7 +189,7 @@ functions: events: - httpApi: - path: /host/{id} + path: /host/getById method: get diff --git a/src/modules/host/services/host.service.ts b/src/modules/host/services/host.service.ts index 9102a79..52c9993 100644 --- a/src/modules/host/services/host.service.ts +++ b/src/modules/host/services/host.service.ts @@ -41,70 +41,19 @@ export class HostService { } async getHostById(id: number) { - const host = await this.prisma.user.findUnique({ - where: { id }, + const host = await this.prisma.hostHeader.findFirst({ + where: { userXid: id }, include: { - hostHeaders: { - select: { - id: true, - userXid: true, - companyName: true, - hostRefNumber: true, - address1: true, - address2: true, - cityXid: true, - stateXid: true, - countryXid: true, - pinCode: true, - logoPath: true, - isSubsidairy: true, - registrationNumber: true, - panNumber: true, - gstNumber: true, - formationDate: true, - companyType: true, - websiteUrl: true, - instagramUrl: true, - facebookUrl: true, - linkedinUrl: true, - twitterUrl: true, - currencyXid: true, - stepper: true, - hostStatusInternal: true, - hostStatusDisplay: true, - adminStatusInternal: true, - adminStatusDisplay: true, - amStatus: true, - agreementAccepted: true, - accountManagerXid: true, - isApproved: true, - agreementStartDate: true, - durationNumber: true, - durationFrequency: true, - isCommisionBase: true, - commisionPer: true, - amountPerBooking: true, - isActive: true, - createdAt: true, - updatedAt: true, - deletedAt: true, - currencies: true, - cities: true, - states: true, - countries: true, - HostBankDetails: true, - HostDocuments: true, - HostSuggestion: true, - hostParent: true, - HostTrack: true, - Activities: true, - }, - }, - }, + hostParent: true, + HostBankDetails: true, + HostDocuments: true, + HostSuggestion: true, + HostTrack: true, + } }); - if (!host || host.roleXid !== 4) { - throw new ApiError(404, 'Host not found'); + if (!host) { + throw new ApiError(404, 'Host record not found.'); } return host;