Commit ce99ff67 by Augusto

0.0.2

parent 7e09e55c
-- Add BACKOFFICE status to the status enum
ALTER TABLE occurrences MODIFY COLUMN status ENUM(
'OPEN',
'BACKOFFICE',
'ASSIGNED',
'IN_PROGRESS',
'RESOLVED',
'PAUSED',
'CLOSED',
'PARCIAL_RESOLVED',
'CANCELLED'
) NOT NULL DEFAULT 'OPEN';
-- Update occurrence_logs table to include BACKOFFICE status
ALTER TABLE occurrence_logs MODIFY COLUMN status ENUM(
'OPEN',
'BACKOFFICE',
'ASSIGNED',
'IN_PROGRESS',
'RESOLVED',
'PAUSED',
'CLOSED',
'PARCIAL_RESOLVED',
'CANCELLED'
) NOT NULL DEFAULT 'OPEN';
-- Update comments table to include BACKOFFICE status
ALTER TABLE comments MODIFY COLUMN status ENUM(
'OPEN',
'BACKOFFICE',
'ASSIGNED',
'IN_PROGRESS',
'RESOLVED',
'PAUSED',
'CLOSED',
'PARCIAL_RESOLVED',
'CANCELLED'
);
-- Remove unique constraint from conclusions.occurrenceId to allow multiple conclusions per occurrence
ALTER TABLE conclusions DROP INDEX occurrenceId;
-- Add createdBy column to conclusions table to track who created each conclusion
ALTER TABLE conclusions ADD COLUMN createdBy varchar(25) NOT NULL;
-- Add foreign key constraint to users table
ALTER TABLE conclusions ADD CONSTRAINT conclusions_createdBy_fkey
FOREIGN KEY (createdBy) REFERENCES users(id);
-- Add index for performance
ALTER TABLE conclusions ADD INDEX conclusion_created_by_idx (createdBy);
{
"name": "unike-form",
"version": "0.0.1",
"version": "0.0.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
......
......@@ -21,6 +21,7 @@ export const userRoleEnum = mysqlEnum('user_role', [
]);
export const occurrenceStatusEnum = mysqlEnum('status', [
'OPEN',
'BACKOFFICE',
'ASSIGNED',
'IN_PROGRESS',
'RESOLVED',
......@@ -155,12 +156,14 @@ export const conclusions = mysqlTable(
description: text('description').notNull(),
fieldMaterial: boolean('fieldMaterial').notNull().default(false),
materialUsed: text('materialUsed'),
occurrenceId: varchar('occurrenceId', { length: 25 }).notNull().unique(),
occurrenceId: varchar('occurrenceId', { length: 25 }).notNull(),
createdBy: varchar('createdBy', { length: 25 }).notNull(),
createdAt: timestamp('createdAt').notNull().defaultNow(),
updatedAt: timestamp('updatedAt').notNull().defaultNow().onUpdateNow(),
},
(table) => ({
occurrenceIdx: index('conclusion_occurrence_idx').on(table.occurrenceId),
createdByIdx: index('conclusion_created_by_idx').on(table.createdBy),
}),
);
......@@ -255,7 +258,7 @@ export const occurrencesRelations = relations(occurrences, ({ one, many }) => ({
occurrenceAssistants: many(occurrenceAssistants),
comments: many(comments),
attachments: many(attachments),
conclusion: one(conclusions),
conclusions: many(conclusions),
logs: many(occurrenceLogs),
}));
......@@ -282,6 +285,10 @@ export const conclusionsRelations = relations(conclusions, ({ one }) => ({
fields: [conclusions.occurrenceId],
references: [occurrences.id],
}),
createdByUser: one(users, {
fields: [conclusions.createdBy],
references: [users.id],
}),
}));
export const occurrenceLogsRelations = relations(occurrenceLogs, ({ one }) => ({
......@@ -339,6 +346,7 @@ export type NewOccurrenceAssistant = typeof occurrenceAssistants.$inferInsert;
export type UserRole = 'USER' | 'MODERATOR' | 'ADMIN';
export type OccurrenceStatus =
| 'OPEN'
| 'BACKOFFICE'
| 'ASSIGNED'
| 'IN_PROGRESS'
| 'RESOLVED'
......@@ -374,6 +382,7 @@ export const UserRoleEnum = {
export const OccurrenceStatusEnum = {
OPEN: 'OPEN' as const,
BACKOFFICE: 'BACKOFFICE' as const,
ASSIGNED: 'ASSIGNED' as const,
IN_PROGRESS: 'IN_PROGRESS' as const,
RESOLVED: 'RESOLVED' as const,
......
......@@ -21,6 +21,8 @@ import { CreateConclusionDto } from './dto/create-conclusion.dto';
import { UpdateConclusionDto } from './dto/update-conclusion.dto';
import { ConclusionResponseDto } from './dto/conclusion-response.dto';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { CurrentUser } from '../auth/decorators/current-user.decorator';
import { UserResponseDto } from '../user/dto/user-response.dto';
@ApiTags('conclusions')
@ApiBearerAuth()
......@@ -45,8 +47,13 @@ export class ConclusionController {
async create(
@Param('occurrenceId') occurrenceId: string,
@Body() createConclusionDto: CreateConclusionDto,
@CurrentUser() user: UserResponseDto,
): Promise<ConclusionResponseDto> {
return this.conclusionService.create(occurrenceId, createConclusionDto);
return this.conclusionService.create(
occurrenceId,
createConclusionDto,
user.id,
);
}
@Get('occurrence/:occurrenceId')
......
......@@ -5,7 +5,7 @@ import {
ConflictException,
} from '@nestjs/common';
import { DrizzleService } from '../../common/drizzle.service';
import { conclusions, occurrences } from '../../drizzle/schema';
import { conclusions, occurrences, users } from '../../drizzle/schema';
import { eq } from 'drizzle-orm';
import { CreateConclusionDto } from './dto/create-conclusion.dto';
import { UpdateConclusionDto } from './dto/update-conclusion.dto';
......@@ -18,6 +18,7 @@ export class ConclusionService {
async create(
occurrenceId: string,
createConclusionDto: CreateConclusionDto,
createdBy: string,
): Promise<ConclusionResponseDto> {
// Check if occurrence exists
const [occurrence] = await this.drizzle.db
......@@ -32,17 +33,15 @@ export class ConclusionService {
);
}
// Check if conclusion already exists for this occurrence
const [existingConclusion] = await this.drizzle.db
// Validate that the user exists
const [user] = await this.drizzle.db
.select()
.from(conclusions)
.where(eq(conclusions.occurrenceId, occurrenceId))
.from(users)
.where(eq(users.id, createdBy))
.limit(1);
if (existingConclusion) {
throw new ConflictException(
`Conclusion already exists for occurrence ${occurrenceId}`,
);
if (!user) {
throw new BadRequestException('User not found');
}
// Validate material fields
......@@ -69,6 +68,7 @@ export class ConclusionService {
id: conclusionId,
...createConclusionDto,
occurrenceId,
createdBy,
});
// Get the created conclusion
......
......@@ -32,6 +32,29 @@ export class ConclusionResponseDto {
occurrenceId: string;
@ApiProperty({
description: 'ID of the user who created the conclusion',
example: 'clxy123456789',
})
createdBy: string;
@ApiPropertyOptional({
description: 'User who created the conclusion',
type: 'object',
properties: {
id: { type: 'string', example: 'clxy123456789' },
firstName: { type: 'string', example: 'John' },
lastName: { type: 'string', example: 'Doe' },
email: { type: 'string', example: 'john.doe@example.com' },
},
})
createdByUser?: {
id: string;
firstName: string;
lastName: string;
email: string;
};
@ApiProperty({
description: 'Date and time when the conclusion was created',
example: '2023-12-01T10:00:00Z',
})
......
......@@ -214,8 +214,8 @@ export class OccurrenceResponseDto {
};
@ApiPropertyOptional({
description: 'Conclusion for this occurrence',
type: ConclusionResponseDto,
description: 'Conclusions for this occurrence',
type: [ConclusionResponseDto],
})
conclusion?: ConclusionResponseDto | null;
conclusions?: ConclusionResponseDto[];
}
......@@ -129,12 +129,28 @@ export class OccurrenceService {
.leftJoin(users, eq(occurrenceAssistants.assignedBy, users.id))
.where(eq(occurrenceAssistants.occurrenceId, occurrenceId));
// Get conclusion if exists
const [conclusion] = await this.drizzle.db
.select()
// Get conclusions if any exist with user info
const conclusionsList = await this.drizzle.db
.select({
id: conclusions.id,
description: conclusions.description,
fieldMaterial: conclusions.fieldMaterial,
materialUsed: conclusions.materialUsed,
occurrenceId: conclusions.occurrenceId,
createdBy: conclusions.createdBy,
createdAt: conclusions.createdAt,
updatedAt: conclusions.updatedAt,
createdByUser: {
id: users.id,
firstName: users.firstName,
lastName: users.lastName,
email: users.email,
},
})
.from(conclusions)
.leftJoin(users, eq(conclusions.createdBy, users.id))
.where(eq(conclusions.occurrenceId, occurrenceId))
.limit(1);
.orderBy(desc(conclusions.createdAt));
// Get counts
const [commentCount] = await this.drizzle.db
......@@ -153,7 +169,7 @@ export class OccurrenceService {
assignedTo,
managedBy,
assistants: assistantsList.length > 0 ? assistantsList : undefined,
conclusion: conclusion || undefined,
conclusions: conclusionsList.length > 0 ? conclusionsList : undefined,
_count: {
comments: commentCount.count,
attachments: attachmentCount.count,
......@@ -443,6 +459,7 @@ export class OccurrenceService {
try {
const statusMap = {
OPEN: 'Aberta',
BACKOFFICE: 'Backoffice',
ASSIGNED: 'Atribuída',
IN_PROGRESS: 'Em Progresso',
RESOLVED: 'Resolvida',
......@@ -772,8 +789,8 @@ export class OccurrenceService {
dualAssignOccurrenceDto: DualAssignOccurrenceDto,
performedBy: string,
): Promise<OccurrenceResponseDto> {
// Check if occurrence exists
await this.findOne(occurrenceId);
// Check if occurrence exists and get current status
const currentOccurrence = await this.findOne(occurrenceId);
// Validate that at least one field is provided
if (
......@@ -823,8 +840,17 @@ export class OccurrenceService {
updateData.managerId = dualAssignOccurrenceDto.managerId;
}
// Set status to ASSIGNED if either assignee or manager is being assigned
// Set status based on assignment type and current status
if (dualAssignOccurrenceDto.assigneeId) {
// If assignee is being assigned, set to ASSIGNED
updateData.status = OccurrenceStatusEnum.ASSIGNED;
} else if (dualAssignOccurrenceDto.managerId) {
// If only manager is being assigned, set to BACKOFFICE (unless already ASSIGNED)
if (currentOccurrence.status !== OccurrenceStatusEnum.ASSIGNED) {
updateData.status = OccurrenceStatusEnum.BACKOFFICE;
}
// If already ASSIGNED, don't change status
}
// Update occurrence with provided fields
await this.drizzle.db
......@@ -832,7 +858,7 @@ export class OccurrenceService {
.set(updateData)
.where(eq(occurrences.id, occurrenceId));
// Create system comments for assignments
// Create system comments for assignments and status changes
try {
if (dualAssignOccurrenceDto.assigneeId && assignee) {
await this.commentService.createSystemComment(
......@@ -851,6 +877,19 @@ export class OccurrenceService {
performedBy,
);
}
// Create system comment for status change to BACKOFFICE
if (
updateData.status === OccurrenceStatusEnum.BACKOFFICE &&
currentOccurrence.status !== OccurrenceStatusEnum.BACKOFFICE
) {
await this.commentService.createSystemComment(
occurrenceId,
'Status alterado para "Backoffice"',
true,
performedBy,
);
}
} catch (commentError) {
console.error(
'Failed to create system comments for assignments:',
......
......@@ -2,6 +2,7 @@
export type UserRole = 'USER' | 'MODERATOR' | 'ADMIN';
export type OccurrenceStatus =
| 'OPEN'
| 'BACKOFFICE'
| 'ASSIGNED'
| 'IN_PROGRESS'
| 'RESOLVED'
......@@ -37,6 +38,7 @@ export const UserRoleEnum = {
export const OccurrenceStatusEnum = {
OPEN: 'OPEN' as const,
BACKOFFICE: 'BACKOFFICE' as const,
ASSIGNED: 'ASSIGNED' as const,
IN_PROGRESS: 'IN_PROGRESS' as const,
RESOLVED: 'RESOLVED' as const,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment