added transaction for calculating the pqq final answer score
This commit is contained in:
@@ -39,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 });
|
||||
@@ -720,119 +720,132 @@ export class HostService {
|
||||
// }
|
||||
|
||||
async calculatePqqScoreForUser(activityXid: number) {
|
||||
// 1. Get all headers for this activity (user's answers)
|
||||
const answers = await this.prisma.activityPQQheader.findMany({
|
||||
where: { activityXid },
|
||||
include: {
|
||||
pqqQuestions: {
|
||||
include: {
|
||||
pqqSubCategories: {
|
||||
include: {
|
||||
category: true,
|
||||
return await this.prisma.$transaction(async (tx) => {
|
||||
// 1. Get all headers for this activity (user's answers)
|
||||
const answers = await this.prisma.activityPQQheader.findMany({
|
||||
where: { activityXid },
|
||||
include: {
|
||||
pqqQuestions: {
|
||||
include: {
|
||||
pqqSubCategories: {
|
||||
include: {
|
||||
category: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
pqqAnswers: true,
|
||||
},
|
||||
pqqAnswers: true,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
if (!answers.length) {
|
||||
return {
|
||||
overallPercentage: 0,
|
||||
categoryWise: {},
|
||||
};
|
||||
}
|
||||
|
||||
// Prepare accumulators
|
||||
let totalUserPoints = 0;
|
||||
let totalMaxPoints = 0;
|
||||
|
||||
// For category-wise scoring
|
||||
const categories: Record<
|
||||
number,
|
||||
{
|
||||
categoryId: number;
|
||||
categoryName: string;
|
||||
userPoints: number;
|
||||
maxPoints: number;
|
||||
}
|
||||
> = {};
|
||||
|
||||
for (const item of answers) {
|
||||
const question = item.pqqQuestions;
|
||||
const answer = item.pqqAnswers;
|
||||
|
||||
const maxPoints = question.maxPoints;
|
||||
const userPoints = answer.answerPoints;
|
||||
|
||||
totalUserPoints += userPoints;
|
||||
totalMaxPoints += maxPoints;
|
||||
|
||||
// Category
|
||||
const category = question.pqqSubCategories.category;
|
||||
const categoryId = category.id;
|
||||
|
||||
if (!categories[categoryId]) {
|
||||
categories[categoryId] = {
|
||||
categoryId,
|
||||
categoryName: category.categoryName,
|
||||
userPoints: 0,
|
||||
maxPoints: 0,
|
||||
if (!answers.length) {
|
||||
return {
|
||||
overallPercentage: 0,
|
||||
categoryWise: {},
|
||||
};
|
||||
}
|
||||
|
||||
categories[categoryId].userPoints += userPoints;
|
||||
categories[categoryId].maxPoints += maxPoints;
|
||||
}
|
||||
// Prepare accumulators
|
||||
let totalUserPoints = 0;
|
||||
let totalMaxPoints = 0;
|
||||
|
||||
// Overall percent
|
||||
const overallPercentage =
|
||||
totalMaxPoints > 0 ? (totalUserPoints / totalMaxPoints) * 100 : 0;
|
||||
// For category-wise scoring
|
||||
const categories: Record<
|
||||
number,
|
||||
{
|
||||
categoryId: number;
|
||||
categoryName: string;
|
||||
userPoints: number;
|
||||
maxPoints: number;
|
||||
}
|
||||
> = {};
|
||||
|
||||
for (const item of answers) {
|
||||
const question = item.pqqQuestions;
|
||||
const answer = item.pqqAnswers;
|
||||
|
||||
const maxPoints = question.maxPoints;
|
||||
const userPoints = answer.answerPoints;
|
||||
|
||||
totalUserPoints += userPoints;
|
||||
totalMaxPoints += maxPoints;
|
||||
|
||||
// Category
|
||||
const category = question.pqqSubCategories.category;
|
||||
const categoryId = category.id;
|
||||
|
||||
if (!categories[categoryId]) {
|
||||
categories[categoryId] = {
|
||||
categoryId,
|
||||
categoryName: category.categoryName,
|
||||
userPoints: 0,
|
||||
maxPoints: 0,
|
||||
};
|
||||
}
|
||||
|
||||
categories[categoryId].userPoints += userPoints;
|
||||
categories[categoryId].maxPoints += maxPoints;
|
||||
}
|
||||
|
||||
// Overall percent
|
||||
const overallPercentage =
|
||||
totalMaxPoints > 0 ? (totalUserPoints / totalMaxPoints) * 100 : 0;
|
||||
|
||||
if (overallPercentage > 50) {
|
||||
await this.prisma.activities.update({
|
||||
where: {
|
||||
id: activityXid
|
||||
},
|
||||
data: {
|
||||
activityInternalStatus: ACTIVITY_INTERNAL_STATUS.UNDER_REVIEW,
|
||||
activityDisplayStatus: ACTIVITY_DISPLAY_STATUS.UNDER_REVIEW
|
||||
}
|
||||
})
|
||||
} else {
|
||||
await this.prisma.activities.update({
|
||||
where: {
|
||||
id: activityXid
|
||||
},
|
||||
data: {
|
||||
activityInternalStatus: ACTIVITY_INTERNAL_STATUS.PQQ_FAILED,
|
||||
activityDisplayStatus: ACTIVITY_DISPLAY_STATUS.PQQ_FAILED
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// ---------- 🔥 ONLY FIRST 2 CATEGORIES ----------
|
||||
const categoryArray = Object.values(categories);
|
||||
|
||||
// Sort by categoryId (or change to displayOrder if needed)
|
||||
categoryArray.sort((a, b) => a.categoryId - b.categoryId);
|
||||
|
||||
// Take only first 2 categories
|
||||
const topTwo = categoryArray.slice(0, 2);
|
||||
|
||||
const categoryWise: Record<string, number> = {};
|
||||
|
||||
for (const c of topTwo) {
|
||||
categoryWise[c.categoryName] =
|
||||
c.maxPoints > 0 ? (c.userPoints / c.maxPoints) * 100 : 0;
|
||||
}
|
||||
|
||||
if (overallPercentage > 50) {
|
||||
await this.prisma.activities.update({
|
||||
where: {
|
||||
id: activityXid
|
||||
},
|
||||
data: {
|
||||
activityInternalStatus: ACTIVITY_INTERNAL_STATUS.UNDER_REVIEW,
|
||||
activityDisplayStatus: ACTIVITY_DISPLAY_STATUS.UNDER_REVIEW
|
||||
totalScore: overallPercentage,
|
||||
sustainabilityScore: categoryWise.Sustainability,
|
||||
safetyScore: categoryWise.Safety
|
||||
}
|
||||
})
|
||||
} else {
|
||||
await this.prisma.activities.update({
|
||||
where: {
|
||||
id: activityXid
|
||||
},
|
||||
data: {
|
||||
activityInternalStatus: ACTIVITY_INTERNAL_STATUS.PQQ_FAILED,
|
||||
activityDisplayStatus: ACTIVITY_DISPLAY_STATUS.PQQ_FAILED
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// ---------- 🔥 ONLY FIRST 2 CATEGORIES ----------
|
||||
const categoryArray = Object.values(categories);
|
||||
|
||||
// Sort by categoryId (or change to displayOrder if needed)
|
||||
categoryArray.sort((a, b) => a.categoryId - b.categoryId);
|
||||
|
||||
// Take only first 2 categories
|
||||
const topTwo = categoryArray.slice(0, 2);
|
||||
|
||||
const categoryWise: Record<string, number> = {};
|
||||
|
||||
for (const c of topTwo) {
|
||||
categoryWise[c.categoryName] =
|
||||
c.maxPoints > 0 ? (c.userPoints / c.maxPoints) * 100 : 0;
|
||||
}
|
||||
|
||||
// Return final score object
|
||||
return {
|
||||
overallPercentage,
|
||||
categoryWise,
|
||||
};
|
||||
// Return final score object
|
||||
return {
|
||||
overallPercentage,
|
||||
categoryWise,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
async createHeader(
|
||||
@@ -927,10 +940,52 @@ export class HostService {
|
||||
return await this.prisma.activityPQQheader.findMany({
|
||||
where: { isActive: true },
|
||||
include: {
|
||||
pqqQuestions: true,
|
||||
ActivityPQQSuggestions: true,
|
||||
pqqAnswers: true,
|
||||
ActivityPQQSupportings: true,
|
||||
pqqQuestions: {
|
||||
select: {
|
||||
questionName: true,
|
||||
maxPoints: true,
|
||||
displayOrder: true,
|
||||
pqqSubCategories: {
|
||||
select: {
|
||||
id: true,
|
||||
subCategoryName: true,
|
||||
displayOrder: true,
|
||||
category: {
|
||||
select: {
|
||||
id: true,
|
||||
categoryName: true,
|
||||
displayOrder: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
ActivityPQQSuggestions: {
|
||||
select: {
|
||||
id: true,
|
||||
title: true,
|
||||
comments: true,
|
||||
isReviewed: true,
|
||||
reviewedBy: true,
|
||||
reviewedOn: true,
|
||||
}
|
||||
},
|
||||
pqqAnswers: {
|
||||
select: {
|
||||
id: true,
|
||||
displayOrder: true,
|
||||
answerName: true,
|
||||
answerPoints: true
|
||||
}
|
||||
},
|
||||
ActivityPQQSupportings: {
|
||||
select: {
|
||||
id: true,
|
||||
mediaFileName: true,
|
||||
mediaType: true,
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user