feat: Introduce new profile sections and fields with detailed configurations and validation rules.
This commit is contained in:
@@ -108,4 +108,29 @@ export class ProfileSectionsController {
|
||||
) {
|
||||
return this.sectionsService.removeFromAgentType(id, agentTypeId);
|
||||
}
|
||||
|
||||
@Get('agent-type/:agentTypeId')
|
||||
@UseGuards(JwtAuthGuard, RolesGuard)
|
||||
@Roles(UserRole.ADMIN)
|
||||
@ApiBearerAuth()
|
||||
@ApiOperation({ summary: 'Get all sections for an agent type with ordering (Admin only)' })
|
||||
@ApiQuery({ name: 'includeFields', required: false, type: Boolean })
|
||||
getSectionsForAgentType(
|
||||
@Param('agentTypeId', ParseUUIDPipe) agentTypeId: string,
|
||||
@Query('includeFields') includeFields?: string,
|
||||
) {
|
||||
return this.sectionsService.getSectionsForAgentType(agentTypeId, includeFields !== 'false');
|
||||
}
|
||||
|
||||
@Patch('agent-type/:agentTypeId/order')
|
||||
@UseGuards(JwtAuthGuard, RolesGuard)
|
||||
@Roles(UserRole.ADMIN)
|
||||
@ApiBearerAuth()
|
||||
@ApiOperation({ summary: 'Update section ordering for an agent type (Admin only)' })
|
||||
updateSectionOrderForAgentType(
|
||||
@Param('agentTypeId', ParseUUIDPipe) agentTypeId: string,
|
||||
@Body() body: { sectionOrders: { sectionId: string; sortOrder: number; isRequired?: boolean }[] },
|
||||
) {
|
||||
return this.sectionsService.updateSectionOrderForAgentType(agentTypeId, body.sectionOrders);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@ export class ProfileSectionsService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all sections for a specific agent type
|
||||
* Get all sections for a specific agent type with custom ordering support
|
||||
*/
|
||||
async getSectionsForAgentType(agentTypeId: string, includeFields = true) {
|
||||
const agentType = await this.prisma.agentType.findUnique({
|
||||
@@ -267,10 +267,9 @@ export class ProfileSectionsService {
|
||||
throw new NotFoundException(`Agent type with ID ${agentTypeId} not found`);
|
||||
}
|
||||
|
||||
// Get assigned sections
|
||||
// Get ALL AgentTypeSection entries for this agent type (including global sections)
|
||||
const assignments = await this.prisma.agentTypeSection.findMany({
|
||||
where: { agentTypeId },
|
||||
orderBy: { sortOrder: 'asc' },
|
||||
include: {
|
||||
section: {
|
||||
include: includeFields
|
||||
@@ -285,7 +284,10 @@ export class ProfileSectionsService {
|
||||
},
|
||||
});
|
||||
|
||||
// Also get global sections
|
||||
// Create a map of section IDs that have custom assignments
|
||||
const assignmentMap = new Map(assignments.map((a) => [a.sectionId, a]));
|
||||
|
||||
// Get all global sections
|
||||
const globalSections = await this.prisma.profileSection.findMany({
|
||||
where: {
|
||||
isGlobal: true,
|
||||
@@ -299,19 +301,104 @@ export class ProfileSectionsService {
|
||||
},
|
||||
}
|
||||
: undefined,
|
||||
orderBy: { sortOrder: 'asc' },
|
||||
});
|
||||
|
||||
// Combine all sections with their effective sort order
|
||||
const allSections: any[] = [];
|
||||
|
||||
// Add global sections (with custom order if assigned, otherwise use default)
|
||||
for (const section of globalSections) {
|
||||
const assignment = assignmentMap.get(section.id);
|
||||
allSections.push({
|
||||
...section,
|
||||
isRequired: assignment?.isRequired ?? false,
|
||||
isGlobal: true,
|
||||
effectiveSortOrder: assignment?.sortOrder ?? section.sortOrder,
|
||||
hasCustomOrder: !!assignment,
|
||||
});
|
||||
}
|
||||
|
||||
// Add non-global assigned sections
|
||||
for (const assignment of assignments) {
|
||||
if (!assignment.section.isGlobal) {
|
||||
allSections.push({
|
||||
...assignment.section,
|
||||
isRequired: assignment.isRequired,
|
||||
isGlobal: false,
|
||||
effectiveSortOrder: assignment.sortOrder,
|
||||
hasCustomOrder: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Sort by effective sort order
|
||||
allSections.sort((a, b) => a.effectiveSortOrder - b.effectiveSortOrder);
|
||||
|
||||
return {
|
||||
agentType,
|
||||
sections: [
|
||||
...globalSections.map((s) => ({ ...s, isRequired: false, isGlobal: true })),
|
||||
...assignments.map((a) => ({
|
||||
...a.section,
|
||||
isRequired: a.isRequired,
|
||||
isGlobal: false,
|
||||
})),
|
||||
],
|
||||
sections: allSections,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Update section ordering for a specific agent type
|
||||
* Creates or updates AgentTypeSection entries with custom sortOrder
|
||||
*/
|
||||
async updateSectionOrderForAgentType(
|
||||
agentTypeId: string,
|
||||
sectionOrders: { sectionId: string; sortOrder: number; isRequired?: boolean }[],
|
||||
) {
|
||||
// Verify agent type exists
|
||||
const agentType = await this.prisma.agentType.findUnique({
|
||||
where: { id: agentTypeId },
|
||||
});
|
||||
|
||||
if (!agentType) {
|
||||
throw new NotFoundException(`Agent type with ID ${agentTypeId} not found`);
|
||||
}
|
||||
|
||||
// Process each section order update
|
||||
const results = await Promise.all(
|
||||
sectionOrders.map(async ({ sectionId, sortOrder, isRequired }) => {
|
||||
// Check if assignment exists
|
||||
const existing = await this.prisma.agentTypeSection.findUnique({
|
||||
where: {
|
||||
agentTypeId_sectionId: {
|
||||
agentTypeId,
|
||||
sectionId,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (existing) {
|
||||
// Update existing assignment
|
||||
return this.prisma.agentTypeSection.update({
|
||||
where: { id: existing.id },
|
||||
data: {
|
||||
sortOrder,
|
||||
...(isRequired !== undefined && { isRequired }),
|
||||
},
|
||||
include: { section: true },
|
||||
});
|
||||
} else {
|
||||
// Create new assignment (for global sections that need custom ordering)
|
||||
return this.prisma.agentTypeSection.create({
|
||||
data: {
|
||||
agentTypeId,
|
||||
sectionId,
|
||||
sortOrder,
|
||||
isRequired: isRequired ?? false,
|
||||
},
|
||||
include: { section: true },
|
||||
});
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
updated: results.length,
|
||||
assignments: results,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user