Add ActivityTrack model to schema and update User and Activities models to include activityTracks relation. Modify seed data to reflect new interest names and activity types. Implement activity reference number generation in HostService for activity creation.
This commit is contained in:
@@ -66,6 +66,7 @@ model User {
|
||||
friendOf Friends[] @relation("FriendUser")
|
||||
userAddressDetails UserAddressDetails[]
|
||||
userDocuments UserDocuments[]
|
||||
activityTracks ActivityTrack[]
|
||||
|
||||
@@map("users")
|
||||
@@schema("usr")
|
||||
@@ -908,6 +909,7 @@ model Activities {
|
||||
ActivityEquipmentTaxes ActivityEquipmentTaxes[]
|
||||
ScheduleHeader ScheduleHeader[]
|
||||
ItineraryActivities ItineraryActivities[]
|
||||
activityTracks ActivityTrack[]
|
||||
|
||||
@@map("activities")
|
||||
@@schema("act")
|
||||
@@ -932,6 +934,25 @@ model ActivityOtherDetails {
|
||||
@@schema("act")
|
||||
}
|
||||
|
||||
model ActivityTrack {
|
||||
id Int @id @default(autoincrement())
|
||||
activityXid Int @map("activity_xid")
|
||||
activity Activities @relation(fields: [activityXid], references: [id], onDelete: Cascade)
|
||||
trackType String? @default("PQQ") @map("track_type")
|
||||
updatedByRole String? @map("updated_by_role")
|
||||
trackStatus String? @map("track_status")
|
||||
updatedByXid Int? @map("updated_by_xid")
|
||||
user User? @relation(fields: [updatedByXid], references: [id], onDelete: Cascade)
|
||||
updatedOn DateTime? @map("updated_on")
|
||||
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("activity_track")
|
||||
@@schema("act")
|
||||
}
|
||||
|
||||
model ActivitiesMedia {
|
||||
id Int @id @default(autoincrement())
|
||||
activityXid Int @map("activity_xid")
|
||||
|
||||
@@ -78,35 +78,51 @@ async function main() {
|
||||
create: { interestName: 'Chill and Zen', displayOrder: 1 },
|
||||
});
|
||||
const sweatmode = await prisma.interests.upsert({
|
||||
where: { interestName: 'Sweat Mode' },
|
||||
where: { interestName: 'Sweat Mode On' },
|
||||
update: {},
|
||||
create: { interestName: 'Sweat Mode', displayOrder: 2 },
|
||||
create: { interestName: 'Sweat Mode On', displayOrder: 2 },
|
||||
});
|
||||
const gameon = await prisma.interests.upsert({
|
||||
where: { interestName: 'Game On' },
|
||||
const trackracer = await prisma.interests.upsert({
|
||||
where: { interestName: 'Track Racer' },
|
||||
update: {},
|
||||
create: { interestName: 'Game On', displayOrder: 3 },
|
||||
create: { interestName: 'Track Racer', displayOrder: 3 },
|
||||
});
|
||||
const circuitracer = await prisma.interests.upsert({
|
||||
where: { interestName: 'Circuit Racer' },
|
||||
update: {},
|
||||
create: { interestName: 'Circuit Racer', displayOrder: 4 },
|
||||
});
|
||||
const thermalGliding = await prisma.interests.upsert({
|
||||
where: { interestName: 'Thermal Gliding' },
|
||||
update: {},
|
||||
create: { interestName: 'Thermal Gliding', displayOrder: 5 },
|
||||
});
|
||||
const partycentral = await prisma.interests.upsert({
|
||||
where: { interestName: 'Party Central' },
|
||||
update: {},
|
||||
create: { interestName: 'Party Central', displayOrder: 4 },
|
||||
create: { interestName: 'Party Central', displayOrder: 6 },
|
||||
});
|
||||
const artsy = await prisma.interests.upsert({
|
||||
where: { interestName: 'Artsy' },
|
||||
const aqua = await prisma.interests.upsert({
|
||||
where: { interestName: 'Aqua' },
|
||||
update: {},
|
||||
create: { interestName: 'Artsy', displayOrder: 5 },
|
||||
create: { interestName: 'Aqua', displayOrder: 7 },
|
||||
});
|
||||
const foodiediaries = await prisma.interests.upsert({
|
||||
where: { interestName: 'Foodie Diaries' },
|
||||
const foodie = await prisma.interests.upsert({
|
||||
where: { interestName: 'Foodie' },
|
||||
update: {},
|
||||
create: { interestName: 'Foodie Diaries', displayOrder: 6 },
|
||||
create: { interestName: 'Foodie', displayOrder: 8 },
|
||||
});
|
||||
|
||||
await prisma.activityTypes.createMany({
|
||||
data: [
|
||||
{ interestXid: chillandzen.id, activityTypeName: 'Cricket' },
|
||||
{ interestXid: chillandzen.id, activityTypeName: 'Football' },
|
||||
{ interestXid: aqua.id, activityTypeName: 'Scuba-Diving' },
|
||||
{ interestXid: sweatmode.id, activityTypeName: 'Cloudboarding' },
|
||||
{ interestXid: partycentral.id, activityTypeName: 'Soaring Glider' },
|
||||
{ interestXid: sweatmode.id, activityTypeName: 'Speedway Racer' },
|
||||
{ interestXid: aqua.id, activityTypeName: 'Aerial Surfing' },
|
||||
{ interestXid: foodie.id, activityTypeName: 'Wine Tasting' },
|
||||
{ interestXid: trackracer.id, activityTypeName: 'Track Racer' },
|
||||
{ interestXid: thermalGliding.id, activityTypeName: 'Thermal Gliding' },
|
||||
],
|
||||
skipDuplicates: true,
|
||||
});
|
||||
|
||||
@@ -38,6 +38,20 @@ interface HostDocumentInput {
|
||||
documentName: string;
|
||||
filePath: string; // S3 URL
|
||||
}
|
||||
export async function generateActivityRefNumber(tx: any) {
|
||||
const lastrecord = await tx.activities.findFirst({
|
||||
orderBy: {
|
||||
id: 'desc',
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
});
|
||||
|
||||
const nextId = lastrecord ? lastrecord.id + 1 : 1;
|
||||
|
||||
return `ACT-${String(nextId).padStart(6, '0')}`;;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class HostService {
|
||||
@@ -330,6 +344,7 @@ export class HostService {
|
||||
where: { id: data.hostXid },
|
||||
data: {
|
||||
stepper: STEPPER.BANK_DETAILS_UPDATED,
|
||||
currencyXid: data.currencyXid
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -1206,42 +1221,48 @@ export class HostService {
|
||||
activityTypeXid: number,
|
||||
frequenciesXid?: number,
|
||||
) {
|
||||
// Find host header for this user
|
||||
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 },
|
||||
});
|
||||
if (!activityType) {
|
||||
throw new ApiError(404, 'Activity type not found');
|
||||
}
|
||||
return await this.prisma.$transaction(async (tx) => {
|
||||
|
||||
// Optionally validate frequency
|
||||
if (frequenciesXid) {
|
||||
const freq = await this.prisma.frequencies.findUnique({
|
||||
where: { id: frequenciesXid },
|
||||
// Fetch host
|
||||
const host = await tx.hostHeader.findFirst({
|
||||
where: { userXid: userId, isActive: true },
|
||||
});
|
||||
if (!freq) throw new ApiError(404, 'Frequency not found');
|
||||
}
|
||||
if (!host) throw new ApiError(404, 'Host not found for the user');
|
||||
|
||||
const created = await this.prisma.activities.create({
|
||||
data: {
|
||||
hostXid: host.id,
|
||||
activityTypeXid: activityTypeXid,
|
||||
frequenciesXid: frequenciesXid || null,
|
||||
activityInternalStatus: ACTIVITY_INTERNAL_STATUS.DRAFT_PQ,
|
||||
activityDisplayStatus: ACTIVITY_DISPLAY_STATUS.DRAFT_PQ,
|
||||
amInternalStatus: ACTIVITY_AM_INTERNAL_STATUS.DRAFT_PQ,
|
||||
amDisplayStatus: ACTIVITY_AM_DISPLAY_STATUS.DRAFT_PQ,
|
||||
},
|
||||
// Validate activityType
|
||||
const activityType = await tx.activityTypes.findUnique({
|
||||
where: { id: activityTypeXid },
|
||||
});
|
||||
if (!activityType) throw new ApiError(404, 'Activity type not found');
|
||||
|
||||
// Validate frequency
|
||||
if (frequenciesXid) {
|
||||
const freq = await tx.frequencies.findUnique({
|
||||
where: { id: frequenciesXid },
|
||||
});
|
||||
if (!freq) throw new ApiError(404, 'Frequency not found');
|
||||
}
|
||||
|
||||
// Generate reference number
|
||||
const referenceNumber = await generateActivityRefNumber(tx);
|
||||
|
||||
// Create activity
|
||||
const created = await tx.activities.create({
|
||||
data: {
|
||||
hostXid: host.id,
|
||||
activityTypeXid,
|
||||
frequenciesXid: frequenciesXid || null,
|
||||
activityInternalStatus: ACTIVITY_INTERNAL_STATUS.DRAFT_PQ,
|
||||
activityDisplayStatus: ACTIVITY_DISPLAY_STATUS.DRAFT_PQ,
|
||||
amInternalStatus: ACTIVITY_AM_INTERNAL_STATUS.DRAFT_PQ,
|
||||
amDisplayStatus: ACTIVITY_AM_DISPLAY_STATUS.DRAFT_PQ,
|
||||
activityRefNumber: referenceNumber,
|
||||
},
|
||||
});
|
||||
|
||||
return created;
|
||||
});
|
||||
|
||||
return created;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -192,6 +192,18 @@ export class MinglarService {
|
||||
isActive: true,
|
||||
userStatus: USER_STATUS.ACTIVE,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
firstName: true,
|
||||
lastName: true,
|
||||
emailAddress: true,
|
||||
mobileNumber: true,
|
||||
roleXid: true,
|
||||
isProfileUpdated: true,
|
||||
userStatus: true,
|
||||
profileImage: true,
|
||||
userPassword: true,
|
||||
}
|
||||
});
|
||||
|
||||
if (!existingUser) {
|
||||
@@ -214,6 +226,16 @@ export class MinglarService {
|
||||
throw new ApiError(401, 'Invalid credentials');
|
||||
}
|
||||
|
||||
if (existingUser?.profileImage) {
|
||||
const key = existingUser.profileImage.startsWith("http")
|
||||
? existingUser.profileImage.split(".com/")[1]
|
||||
: existingUser.profileImage;
|
||||
|
||||
existingUser.profileImage = await getPresignedUrl(bucket, key);
|
||||
}
|
||||
|
||||
delete existingUser.userPassword;
|
||||
|
||||
return existingUser;
|
||||
}
|
||||
|
||||
@@ -742,19 +764,36 @@ export class MinglarService {
|
||||
}
|
||||
|
||||
/** APPLICATION STATUS FILTER (NEW) **/
|
||||
const APPLICATION_STATUS_MAP: Record<string, string> = {
|
||||
"New": MINGLAR_STATUS_INTERNAL.AM_TO_REVIEW && MINGLAR_STATUS_DISPLAY.NEW,
|
||||
"To_Review": MINGLAR_STATUS_INTERNAL.AM_TO_REVIEW && MINGLAR_STATUS_DISPLAY.TO_REVIEW,
|
||||
"Enchancing": MINGLAR_STATUS_INTERNAL.AM_REJECTED,
|
||||
const APPLICATION_STATUS_MAP: Record<
|
||||
string,
|
||||
{ internal: string; display: string }
|
||||
> = {
|
||||
New: {
|
||||
internal: MINGLAR_STATUS_INTERNAL.AM_TO_REVIEW,
|
||||
display: MINGLAR_STATUS_DISPLAY.NEW,
|
||||
},
|
||||
To_Review: {
|
||||
internal: MINGLAR_STATUS_INTERNAL.AM_TO_REVIEW,
|
||||
display: MINGLAR_STATUS_DISPLAY.TO_REVIEW,
|
||||
},
|
||||
Enhancing: {
|
||||
internal: MINGLAR_STATUS_INTERNAL.AM_REJECTED,
|
||||
display: MINGLAR_STATUS_DISPLAY.ENHANCING,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
if (applicationStatus?.trim()) {
|
||||
const key = applicationStatus.trim();
|
||||
if (APPLICATION_STATUS_MAP[key]) {
|
||||
filters.adminStatusInternal = APPLICATION_STATUS_MAP[key];
|
||||
const statusObj = APPLICATION_STATUS_MAP[key];
|
||||
|
||||
if (statusObj) {
|
||||
filters.adminStatusInternal = statusObj.internal;
|
||||
filters.adminStatusDisplay = statusObj.display;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** ROLE-BASED FILTER **/
|
||||
if (userRoleXid === ROLE.CO_ADMIN || userRoleXid === ROLE.ACCOUNT_MANAGER) {
|
||||
filters.accountManagerXid = userId;
|
||||
@@ -1513,7 +1552,21 @@ export class MinglarService {
|
||||
async getAMdetailById(id: number) {
|
||||
const user = await this.prisma.user.findUnique({
|
||||
where: { id: id, isActive: true, userStatus: USER_STATUS.ACTIVE },
|
||||
include: {
|
||||
select: {
|
||||
id: true,
|
||||
firstName: true,
|
||||
lastName: true,
|
||||
emailAddress: true,
|
||||
isdCode: true,
|
||||
mobileNumber: true,
|
||||
roleXid: true,
|
||||
userStatus: true,
|
||||
isProfileUpdated: true,
|
||||
dateOfBirth: true,
|
||||
profileImage: true,
|
||||
isEmailVerfied: true,
|
||||
isMobileVerfied: true,
|
||||
isBiometric: true,
|
||||
userAddressDetails: {
|
||||
select: {
|
||||
id: true,
|
||||
|
||||
@@ -11,15 +11,11 @@ export class PrePopulateService {
|
||||
isActive: true,
|
||||
deletedAt: null,
|
||||
},
|
||||
include: {
|
||||
BankBranches: {
|
||||
select: {
|
||||
id: true,
|
||||
branchAddress: true,
|
||||
ifscCode: true,
|
||||
},
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
bankName: true,
|
||||
},
|
||||
orderBy: { bankName: 'asc' }
|
||||
});
|
||||
}
|
||||
|
||||
@@ -28,7 +24,6 @@ export class PrePopulateService {
|
||||
where: {
|
||||
bankXid,
|
||||
isActive: true,
|
||||
deletedAt: null
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
@@ -60,6 +55,12 @@ export class PrePopulateService {
|
||||
isActive: true,
|
||||
deletedAt: null,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
currencyName: true,
|
||||
currencySymbol: true,
|
||||
},
|
||||
orderBy: { currencyName: 'asc' }
|
||||
});
|
||||
}
|
||||
|
||||
@@ -68,27 +69,41 @@ export class PrePopulateService {
|
||||
where: { isActive: true },
|
||||
include: {
|
||||
pqqsubCategories: {
|
||||
include: {
|
||||
where: { isActive: true },
|
||||
select: {
|
||||
id: true,
|
||||
subCategoryName: true,
|
||||
categoryXid: true,
|
||||
displayOrder: true,
|
||||
questions: {
|
||||
include: {
|
||||
where: { isActive: true },
|
||||
select: {
|
||||
id: true,
|
||||
questionName: true,
|
||||
maxPoints: true,
|
||||
displayOrder: true,
|
||||
PQQAnswers: {
|
||||
orderBy: {
|
||||
displayOrder: 'asc'
|
||||
where: { isActive: true },
|
||||
orderBy: { displayOrder: 'asc' },
|
||||
select: {
|
||||
id: true,
|
||||
answerName: true,
|
||||
answerPoints: true,
|
||||
displayOrder: true
|
||||
}
|
||||
}
|
||||
},
|
||||
orderBy: {
|
||||
displayOrder: 'asc'
|
||||
}
|
||||
}
|
||||
orderBy: { displayOrder: 'asc' }
|
||||
},
|
||||
},
|
||||
orderBy: { displayOrder: 'asc' }
|
||||
}
|
||||
orderBy: { displayOrder: 'asc' },
|
||||
},
|
||||
},
|
||||
orderBy: { displayOrder: 'asc' }
|
||||
orderBy: { displayOrder: 'asc' },
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
async getAllDocumentTypeWithCountryStateCity() {
|
||||
const [documentDetails, countryDetails, stateDetails, companyTypeDetails] =
|
||||
await this.prisma.$transaction([
|
||||
|
||||
Reference in New Issue
Block a user