feat: Implement agent verification system with a new status enum, admin update functionality, and document retrieval.

This commit is contained in:
pradeepkumar
2026-01-28 13:48:14 +05:30
parent dfd8bc38a5
commit eece0f7401
5 changed files with 208 additions and 12 deletions

View File

@@ -17,8 +17,8 @@ import {
} from '@nestjs/swagger';
import { UsersService } from './users.service';
import { JwtAuthGuard, RolesGuard } from '../auth/guards';
import { Roles } from '../auth/decorators';
import { UserRole, UserStatus } from '@prisma/client';
import { Roles, CurrentUser } from '../auth/decorators';
import { UserRole, UserStatus, VerificationStatus } from '@prisma/client';
@ApiTags('Users')
@Controller('users')
@@ -82,6 +82,19 @@ export class UsersController {
return this.usersService.findAll(pageNum, limitNum, role);
}
@Get(':id/verification-documents')
@Roles(UserRole.ADMIN)
@ApiOperation({ summary: 'Get verification documents for an agent user (Admin only)' })
@ApiResponse({
status: 200,
description: 'Verification documents retrieved',
})
@ApiResponse({ status: 400, description: 'User is not an agent' })
@ApiResponse({ status: 404, description: 'User not found' })
async getVerificationDocuments(@Param('id') id: string) {
return this.usersService.getVerificationDocuments(id);
}
@Get(':id')
@Roles(UserRole.ADMIN)
@ApiOperation({ summary: 'Get user by ID (Admin only)' })
@@ -132,4 +145,21 @@ export class UsersController {
) {
return this.usersService.updateAgentType(id, agentTypeId);
}
@Patch(':id/verification')
@Roles(UserRole.ADMIN)
@ApiOperation({ summary: 'Update verification status for an agent user (Admin only)' })
@ApiResponse({
status: 200,
description: 'Verification status updated',
})
@ApiResponse({ status: 400, description: 'User is not an agent or invalid status' })
@ApiResponse({ status: 404, description: 'User not found' })
async updateVerification(
@Param('id') id: string,
@Body() data: { status: VerificationStatus; note?: string },
@CurrentUser() admin: { id: string },
) {
return this.usersService.updateVerification(id, data, admin.id);
}
}

View File

@@ -1,5 +1,5 @@
import { Injectable, BadRequestException, NotFoundException } from '@nestjs/common';
import { UserStatus, UserRole, Prisma } from '@prisma/client';
import { UserStatus, UserRole, Prisma, VerificationStatus } from '@prisma/client';
import { PrismaService } from '../prisma/prisma.service';
type UserWithProfiles = Prisma.UserGetPayload<{
@@ -123,6 +123,12 @@ export class UsersService {
profileCompleteness: user.agentProfile.profileCompleteness,
agentTypeId: user.agentProfile.agentTypeId,
agentType: user.agentProfile.agentType,
// Verification fields
isVerified: user.agentProfile.isVerified,
verificationStatus: user.agentProfile.verificationStatus,
verificationNote: user.agentProfile.verificationNote,
verifiedAt: user.agentProfile.verifiedAt,
verifiedBy: user.agentProfile.verifiedBy,
},
};
}
@@ -193,4 +199,106 @@ export class UsersService {
message: 'Agent type updated successfully',
};
}
async getVerificationDocuments(userId: string) {
// Get user to verify they are an agent
const user = await this.prisma.user.findUnique({
where: { id: userId },
include: { agentProfile: true },
});
if (!user) {
throw new NotFoundException('User not found');
}
if (user.role !== UserRole.AGENT) {
throw new BadRequestException('User is not an agent');
}
if (!user.agentProfile) {
throw new NotFoundException('Agent profile not found');
}
// Find the upload-documents section field
const field = await this.prisma.profileField.findFirst({
where: {
section: { slug: 'upload-documents' },
slug: 'documents',
},
});
if (!field) return [];
const fieldValue = await this.prisma.agentProfileFieldValue.findUnique({
where: {
agentProfileId_fieldId: {
agentProfileId: user.agentProfile.id,
fieldId: field.id,
},
},
});
return fieldValue?.jsonValue || [];
}
async updateVerification(
userId: string,
data: {
status: VerificationStatus;
note?: string;
},
adminId: string,
) {
// Get user to verify they are an agent
const user = await this.prisma.user.findUnique({
where: { id: userId },
include: { agentProfile: true },
});
if (!user) {
throw new NotFoundException('User not found');
}
if (user.role !== UserRole.AGENT) {
throw new BadRequestException('User is not an agent');
}
if (!user.agentProfile) {
throw new NotFoundException('Agent profile not found');
}
const updateData: Prisma.AgentProfileUpdateInput = {
verificationStatus: data.status,
verificationNote: data.note || null,
};
if (data.status === VerificationStatus.APPROVED) {
updateData.isVerified = true;
updateData.verifiedAt = new Date();
updateData.verifiedBy = adminId;
} else if (data.status === VerificationStatus.REJECTED) {
updateData.isVerified = false;
updateData.verifiedAt = null;
updateData.verifiedBy = null;
}
const updatedProfile = await this.prisma.agentProfile.update({
where: { id: user.agentProfile.id },
data: updateData,
include: {
agentType: true,
},
});
return {
id: user.id,
agentProfileId: updatedProfile.id,
isVerified: updatedProfile.isVerified,
verificationStatus: updatedProfile.verificationStatus,
verificationNote: updatedProfile.verificationNote,
verifiedAt: updatedProfile.verifiedAt,
verifiedBy: updatedProfile.verifiedBy,
message: `Verification ${data.status.toLowerCase()} successfully`,
};
}
}