fix
This commit is contained in:
310
src/profile-fields/profile-sections.service.ts
Normal file
310
src/profile-fields/profile-sections.service.ts
Normal file
@@ -0,0 +1,310 @@
|
||||
import { Injectable, NotFoundException, ConflictException } from '@nestjs/common';
|
||||
import { PrismaService } from '../prisma';
|
||||
import { CreateSectionDto, UpdateSectionDto, AssignSectionDto, UpdateAssignmentDto } from './dto';
|
||||
|
||||
@Injectable()
|
||||
export class ProfileSectionsService {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
||||
/**
|
||||
* Generate a URL-friendly slug from the name
|
||||
*/
|
||||
private generateSlug(name: string): string {
|
||||
return name
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9]+/g, '-')
|
||||
.replace(/(^-|-$)/g, '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new profile section
|
||||
*/
|
||||
async create(createSectionDto: CreateSectionDto) {
|
||||
const slug = this.generateSlug(createSectionDto.name);
|
||||
|
||||
// Check if slug already exists
|
||||
const existing = await this.prisma.profileSection.findUnique({
|
||||
where: { slug },
|
||||
});
|
||||
|
||||
if (existing) {
|
||||
throw new ConflictException('A section with this name already exists');
|
||||
}
|
||||
|
||||
return this.prisma.profileSection.create({
|
||||
data: {
|
||||
...createSectionDto,
|
||||
slug,
|
||||
},
|
||||
include: {
|
||||
_count: {
|
||||
select: { fields: true, agentTypeSections: true },
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all profile sections
|
||||
*/
|
||||
async findAll(includeInactive = false) {
|
||||
const where = includeInactive ? {} : { isActive: true };
|
||||
|
||||
return this.prisma.profileSection.findMany({
|
||||
where,
|
||||
orderBy: [{ sortOrder: 'asc' }, { name: 'asc' }],
|
||||
include: {
|
||||
_count: {
|
||||
select: { fields: true, agentTypeSections: true },
|
||||
},
|
||||
agentTypeSections: {
|
||||
include: {
|
||||
agentType: {
|
||||
select: { id: true, name: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single section by ID with all fields
|
||||
*/
|
||||
async findOne(id: string) {
|
||||
const section = await this.prisma.profileSection.findUnique({
|
||||
where: { id },
|
||||
include: {
|
||||
fields: {
|
||||
orderBy: { sortOrder: 'asc' },
|
||||
},
|
||||
agentTypeSections: {
|
||||
include: {
|
||||
agentType: {
|
||||
select: { id: true, name: true },
|
||||
},
|
||||
},
|
||||
orderBy: { sortOrder: 'asc' },
|
||||
},
|
||||
_count: {
|
||||
select: { fields: true, agentTypeSections: true },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!section) {
|
||||
throw new NotFoundException(`Section with ID ${id} not found`);
|
||||
}
|
||||
|
||||
return section;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a section
|
||||
*/
|
||||
async update(id: string, updateSectionDto: UpdateSectionDto) {
|
||||
// Check if section exists
|
||||
await this.findOne(id);
|
||||
|
||||
const data: any = { ...updateSectionDto };
|
||||
|
||||
// If name is being updated, update the slug too
|
||||
if (updateSectionDto.name) {
|
||||
const newSlug = this.generateSlug(updateSectionDto.name);
|
||||
|
||||
// Check if new slug conflicts with another section
|
||||
const existing = await this.prisma.profileSection.findFirst({
|
||||
where: {
|
||||
AND: [{ id: { not: id } }, { slug: newSlug }],
|
||||
},
|
||||
});
|
||||
|
||||
if (existing) {
|
||||
throw new ConflictException('A section with this name already exists');
|
||||
}
|
||||
|
||||
data.slug = newSlug;
|
||||
}
|
||||
|
||||
return this.prisma.profileSection.update({
|
||||
where: { id },
|
||||
data,
|
||||
include: {
|
||||
_count: {
|
||||
select: { fields: true, agentTypeSections: true },
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a section
|
||||
*/
|
||||
async remove(id: string) {
|
||||
const section = await this.findOne(id);
|
||||
|
||||
// Check if section has any fields
|
||||
if (section._count.fields > 0) {
|
||||
throw new ConflictException(
|
||||
`Cannot delete section. It has ${section._count.fields} field(s). Delete the fields first.`,
|
||||
);
|
||||
}
|
||||
|
||||
return this.prisma.profileSection.delete({
|
||||
where: { id },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign a section to an agent type
|
||||
*/
|
||||
async assignToAgentType(sectionId: string, assignDto: AssignSectionDto) {
|
||||
// Verify section exists
|
||||
await this.findOne(sectionId);
|
||||
|
||||
// Verify agent type exists
|
||||
const agentType = await this.prisma.agentType.findUnique({
|
||||
where: { id: assignDto.agentTypeId },
|
||||
});
|
||||
|
||||
if (!agentType) {
|
||||
throw new NotFoundException(`Agent type with ID ${assignDto.agentTypeId} not found`);
|
||||
}
|
||||
|
||||
// Check if already assigned
|
||||
const existing = await this.prisma.agentTypeSection.findUnique({
|
||||
where: {
|
||||
agentTypeId_sectionId: {
|
||||
agentTypeId: assignDto.agentTypeId,
|
||||
sectionId,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (existing) {
|
||||
throw new ConflictException('This section is already assigned to this agent type');
|
||||
}
|
||||
|
||||
return this.prisma.agentTypeSection.create({
|
||||
data: {
|
||||
sectionId,
|
||||
agentTypeId: assignDto.agentTypeId,
|
||||
sortOrder: assignDto.sortOrder ?? 0,
|
||||
isRequired: assignDto.isRequired ?? false,
|
||||
},
|
||||
include: {
|
||||
section: true,
|
||||
agentType: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a section assignment
|
||||
*/
|
||||
async updateAssignment(sectionId: string, agentTypeId: string, updateDto: UpdateAssignmentDto) {
|
||||
const assignment = await this.prisma.agentTypeSection.findUnique({
|
||||
where: {
|
||||
agentTypeId_sectionId: {
|
||||
agentTypeId,
|
||||
sectionId,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!assignment) {
|
||||
throw new NotFoundException('Section assignment not found');
|
||||
}
|
||||
|
||||
return this.prisma.agentTypeSection.update({
|
||||
where: { id: assignment.id },
|
||||
data: updateDto,
|
||||
include: {
|
||||
section: true,
|
||||
agentType: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a section from an agent type
|
||||
*/
|
||||
async removeFromAgentType(sectionId: string, agentTypeId: string) {
|
||||
const assignment = await this.prisma.agentTypeSection.findUnique({
|
||||
where: {
|
||||
agentTypeId_sectionId: {
|
||||
agentTypeId,
|
||||
sectionId,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!assignment) {
|
||||
throw new NotFoundException('Section assignment not found');
|
||||
}
|
||||
|
||||
return this.prisma.agentTypeSection.delete({
|
||||
where: { id: assignment.id },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all sections for a specific agent type
|
||||
*/
|
||||
async getSectionsForAgentType(agentTypeId: string, includeFields = true) {
|
||||
const agentType = await this.prisma.agentType.findUnique({
|
||||
where: { id: agentTypeId },
|
||||
});
|
||||
|
||||
if (!agentType) {
|
||||
throw new NotFoundException(`Agent type with ID ${agentTypeId} not found`);
|
||||
}
|
||||
|
||||
// Get assigned sections
|
||||
const assignments = await this.prisma.agentTypeSection.findMany({
|
||||
where: { agentTypeId },
|
||||
orderBy: { sortOrder: 'asc' },
|
||||
include: {
|
||||
section: {
|
||||
include: includeFields
|
||||
? {
|
||||
fields: {
|
||||
where: { isActive: true },
|
||||
orderBy: { sortOrder: 'asc' },
|
||||
},
|
||||
}
|
||||
: undefined,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Also get global sections
|
||||
const globalSections = await this.prisma.profileSection.findMany({
|
||||
where: {
|
||||
isGlobal: true,
|
||||
isActive: true,
|
||||
},
|
||||
include: includeFields
|
||||
? {
|
||||
fields: {
|
||||
where: { isActive: true },
|
||||
orderBy: { sortOrder: 'asc' },
|
||||
},
|
||||
}
|
||||
: undefined,
|
||||
orderBy: { sortOrder: 'asc' },
|
||||
});
|
||||
|
||||
return {
|
||||
agentType,
|
||||
sections: [
|
||||
...globalSections.map((s) => ({ ...s, isRequired: false, isGlobal: true })),
|
||||
...assignments.map((a) => ({
|
||||
...a.section,
|
||||
isRequired: a.isRequired,
|
||||
isGlobal: false,
|
||||
})),
|
||||
],
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user