Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/model.nlp

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion backend/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ async function bootstrap() {

app.enableCors();
app.setGlobalPrefix('ProDeskApi');
app.useGlobalPipes(new ValidationPipe());

const config = new DocumentBuilder()
.setTitle('ProDesk')
Expand Down
3 changes: 2 additions & 1 deletion backend/src/modules/auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export class AuthService {
}

async register(user: Readonly<CreateUserDTO>): Promise<UserDetails | any> {
const { name, email, password, role, companyId, categories } = user;
const { name, email, password, role, companyId, categories, level } = user;

const existingUser = await this.userService.findByEmail(email);

Expand All @@ -41,6 +41,7 @@ export class AuthService {
role,
companyId,
categories,
level
);

return this.userService._getUser(newUser);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export interface CreateTicketInput {
title: string;
description: string;
clientId: string;
level?: number;
}

export interface CreateTicketOutput {
Expand All @@ -20,6 +21,7 @@ export interface CreateTicketOutput {
clientId: string;
fileUrls: string[];
status: TicketStatus;
level: number;
createdAt: Date;
}

Expand Down Expand Up @@ -51,6 +53,7 @@ export class CreateTicketUseCase {
clientId: primitives.clientId,
fileUrls: primitives.fileUrls,
status: primitives.status,
level: primitives.escalationLevel,
createdAt: primitives.createdAt,
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export interface EscalateTicketInput {
id: string;
groupId: string;
category: string;
whatWasDone: string;
}

export interface EscalateTicketOutput {
Expand Down Expand Up @@ -36,7 +37,7 @@ export class EscalateTicketUseCase {
throw new Error('Ticket not found');
}

foundedTicket.escalate(input.groupId, input.category);
foundedTicket.escalate(input.groupId, input.category, input.whatWasDone);

const escalatedTicket = await this.repository.save(foundedTicket);

Expand Down
11 changes: 10 additions & 1 deletion backend/src/modules/ticket/domain/entities/ticket.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export enum TicketValidationErrors {
ECALATE_WITH_NO_AGENT_ERROR = 'The ticket must be assigned to an agent before being escalated.',
CLOSE_WITH_WRONG_STATUS_ERROR = 'A ticket can only be closed when in progress status.',
CLOSE_WITH_NO_SOLUTION_ERROR = 'The solution cannot be empty.',
ESCALATION_LEVEL_MAX_ERROR = 'The ticket has reached the maximum escalation level.'
}

export type TicketHistoryEntry = {
Expand Down Expand Up @@ -100,6 +101,7 @@ export class Ticket {
category: string;
description: string;
clientId: string;
level?: number;
}): Ticket {
const ticket = new Ticket(
props.title,
Expand All @@ -110,6 +112,7 @@ export class Ticket {

ticket._id = randomUUID();
ticket.createdAt = new Date();
ticket.escalationLevel = props.level ?? 1;

ticket.addHistory({
event: TicketEvents.OPEN_NEW_TICKET,
Expand Down Expand Up @@ -180,6 +183,7 @@ export class Ticket {
agentId: this._agentId,
groupId: this._groupId,
escalationLevel: this.escalationLevel,
history: this.history,
createdAt: this.createdAt,
updatedAt: this.updatedAt,
closedAt: this.closedAt,
Expand Down Expand Up @@ -221,11 +225,15 @@ export class Ticket {
}

// Escalates the ticket to a new responsible group and optionally changes the category
escalate(groupId: string, category?: string): void {
escalate(groupId: string, category?: string, whatWasDone?: string): void {
if (!this._agentId) {
throw new Error(TicketValidationErrors.ECALATE_WITH_NO_AGENT_ERROR);
}

if (this.escalationLevel >= 3) {
throw new Error(TicketValidationErrors.ESCALATION_LEVEL_MAX_ERROR);
}

this.touch();

this._groupId = groupId;
Expand All @@ -238,6 +246,7 @@ export class Ticket {
responsibleAgent: this._agentId,
status: TicketStatus.ESCALATED,
message: TicketEventMessage.ESCALATE_MSG,
solution: whatWasDone ?? null
});
}

Expand Down
9 changes: 8 additions & 1 deletion backend/src/modules/ticket/presentation/dtos/create.dto.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IsNotEmpty, IsString } from 'class-validator';
import { IsNotEmpty, IsNumber, IsOptional, IsString, Max, Min } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';

export class CreateTicketRequest {
Expand All @@ -17,4 +17,11 @@ export class CreateTicketRequest {
@IsString()
@IsNotEmpty()
clientId!: string;

@ApiProperty({ example: 1, description: 'Nível do chamado (1 a 3)' })
@IsOptional()
@IsNumber()
@Min(1)
@Max(3)
level?: number;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,15 @@ export class EscalateTicketRequest {
@IsNotEmpty()
groupId!: string;

@ApiProperty({
example: 'web_app',
description: 'Categoria do ticket',
})
@ApiProperty({ example: 'web_app', description: 'Categoria do ticket' })
@IsString()
@IsNotEmpty()
category!: string;

@ApiProperty({
example: 'Reiniciei o servidor e o problema persistiu.',
description: 'O que foi feito antes de escalonar' })
@IsString()
@IsNotEmpty()
whatWasDone!: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export class TicketMapper {
title: req.title,
description: req.description,
clientId: req.clientId,
level: req.level
};
}

Expand All @@ -32,6 +33,7 @@ export class TicketMapper {
id: id,
groupId: req.groupId,
category: req.category,
whatWasDone: req.whatWasDone
};
}
}
23 changes: 23 additions & 0 deletions backend/src/modules/user/dtos/createUserDTO.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import {
IsStrongPassword,
IsArray,
IsMongoId,
IsNumber,
Min,
Max,
} from 'class-validator';
import { UserRole } from '../user.schema';
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
Expand Down Expand Up @@ -57,6 +60,16 @@ export class CreateUserDTO {
@IsArray()
@IsMongoId({ each: true })
categories?: string[];

@ApiPropertyOptional({
example: 1,
description: 'Nível do atendente (1 a 3)'
})
@IsOptional()
@IsNumber()
@Min(1)
@Max(3)
level?: number;
}

export class CreateAdminDTO {
Expand Down Expand Up @@ -127,6 +140,16 @@ export class CreateSupportDTO {
@IsArray()
@IsMongoId({ each: true })
categories?: string[];

@ApiPropertyOptional({
example: 1,
description: 'Nível do atendente (1 a 3)'
})
@IsOptional()
@IsNumber()
@Min(1)
@Max(3)
level?: number;
}

export class CreateClientDTO {
Expand Down
9 changes: 8 additions & 1 deletion backend/src/modules/user/dtos/updateUserDTO.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IsEmail, IsString, IsOptional } from 'class-validator';
import { IsEmail, IsString, IsOptional, IsNumber, Min, Max } from 'class-validator';
import { ApiPropertyOptional } from '@nestjs/swagger';

export class UpdateUserDTO {
Expand All @@ -16,4 +16,11 @@ export class UpdateUserDTO {
@IsOptional()
@IsString()
companyId?: string;

@ApiPropertyOptional({ example: 1, description: 'Nível do atendente (1 a 3)' })
@IsOptional()
@IsNumber()
@Min(1)
@Max(3)
level?: number;
}
1 change: 1 addition & 0 deletions backend/src/modules/user/user.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export interface UserDetails {
name: string;
email: string;
role: UserRole;
level?: number;
company?: CompanyDetails;
categories?: CategoryDetails[];
profileImage?: string;
Expand Down
6 changes: 6 additions & 0 deletions backend/src/modules/user/user.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ export class User {
})
role: UserRole;

@Prop({
required: false,
default: 1
})
level: number;

@Prop({
type: Types.ObjectId,
ref: 'Company',
Expand Down
3 changes: 3 additions & 0 deletions backend/src/modules/user/user.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ export class UserService {
role: UserRole,
companyId?: string,
categories?: string[],
level?: number
): Promise<UserDocument> {
if (companyId) {
const company = await this.companyService.findById(companyId);
Expand All @@ -130,6 +131,7 @@ export class UserService {
role,
companyId,
categories,
level
});

const savedUser = await newUser.save();
Expand Down Expand Up @@ -199,6 +201,7 @@ export class UserService {
name: user.name,
email: user.email,
role: user.role,
level: user.level,
profileImage: user.profileImage,

company: user.companyId
Expand Down
Loading