fix: resolve TypeORM cascade bug in ticket reply/close/updateStatus
- Replace ticketsRepo.save(ticket) with ticketsRepo.update() to avoid cascade orphaning existing messages (SET ticketId=null violates NOT NULL) - Fix reply(), close() in tickets.service.ts - Fix updateStatus() in tickets.controller.ts using new updateTicketFields() method - Add updateTicketFields() helper to TicketsService for safe partial updates
This commit is contained in:
@@ -107,11 +107,13 @@ export class TicketsController {
|
|||||||
@Request() req: any,
|
@Request() req: any,
|
||||||
@Body() dto: UpdateTicketStatusDto,
|
@Body() dto: UpdateTicketStatusDto,
|
||||||
) {
|
) {
|
||||||
const ticket = await this.ticketsService.findOne(id, req.user.id, req.user.role);
|
// Access check
|
||||||
ticket.status = dto.status;
|
await this.ticketsService.findOne(id, req.user.id, req.user.role);
|
||||||
|
const updateData: any = { status: dto.status };
|
||||||
if (dto.status === TicketStatus.CLOSED) {
|
if (dto.status === TicketStatus.CLOSED) {
|
||||||
ticket.closedAt = new Date();
|
updateData.closedAt = new Date();
|
||||||
}
|
}
|
||||||
return this.ticketsService['ticketsRepo'].save(ticket);
|
await this.ticketsService.updateTicketFields(id, updateData);
|
||||||
|
return this.ticketsService.findOne(id, req.user.id, req.user.role);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,24 +85,20 @@ export class TicketsService {
|
|||||||
|
|
||||||
// ─── Reply to ticket ───
|
// ─── Reply to ticket ───
|
||||||
async reply(ticketId: string, userId: string, userRole: UserRole, dto: ReplyTicketDto): Promise<TicketMessage> {
|
async reply(ticketId: string, userId: string, userRole: UserRole, dto: ReplyTicketDto): Promise<TicketMessage> {
|
||||||
const ticket = await this.findOne(ticketId, userId, userRole);
|
// Verify access first
|
||||||
|
await this.findOne(ticketId, userId, userRole);
|
||||||
|
|
||||||
const msg = this.messagesRepo.create({
|
const msg = this.messagesRepo.create({
|
||||||
ticketId: ticket.id,
|
ticketId,
|
||||||
senderId: userId,
|
senderId: userId,
|
||||||
senderRole: userRole,
|
senderRole: userRole,
|
||||||
message: dto.message,
|
message: dto.message,
|
||||||
});
|
});
|
||||||
const saved = await this.messagesRepo.save(msg);
|
const saved = await this.messagesRepo.save(msg);
|
||||||
|
|
||||||
// Update ticket status based on who replied
|
// Update ticket status directly (avoid cascade issues with loaded relations)
|
||||||
if (userRole === UserRole.USER) {
|
const newStatus = userRole === UserRole.USER ? TicketStatus.WAITING : TicketStatus.ANSWERED;
|
||||||
ticket.status = TicketStatus.WAITING;
|
await this.ticketsRepo.update(ticketId, { status: newStatus });
|
||||||
} else {
|
|
||||||
// Staff or admin replied
|
|
||||||
ticket.status = TicketStatus.ANSWERED;
|
|
||||||
}
|
|
||||||
await this.ticketsRepo.save(ticket);
|
|
||||||
|
|
||||||
this.logger.log(`Reply on ticket ${ticketId} by ${userRole} user ${userId}`);
|
this.logger.log(`Reply on ticket ${ticketId} by ${userRole} user ${userId}`);
|
||||||
return saved;
|
return saved;
|
||||||
@@ -110,10 +106,17 @@ export class TicketsService {
|
|||||||
|
|
||||||
// ─── Close ticket ───
|
// ─── Close ticket ───
|
||||||
async close(ticketId: string, userId: string, userRole: UserRole): Promise<Ticket> {
|
async close(ticketId: string, userId: string, userRole: UserRole): Promise<Ticket> {
|
||||||
const ticket = await this.findOne(ticketId, userId, userRole);
|
await this.findOne(ticketId, userId, userRole);
|
||||||
ticket.status = TicketStatus.CLOSED;
|
await this.ticketsRepo.update(ticketId, {
|
||||||
ticket.closedAt = new Date();
|
status: TicketStatus.CLOSED,
|
||||||
return this.ticketsRepo.save(ticket);
|
closedAt: new Date(),
|
||||||
|
});
|
||||||
|
return this.findOne(ticketId, userId, userRole);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Update ticket fields (safe, no cascade) ───
|
||||||
|
async updateTicketFields(ticketId: string, data: Partial<Ticket>): Promise<void> {
|
||||||
|
await this.ticketsRepo.update(ticketId, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── Staff: List department tickets ───
|
// ─── Staff: List department tickets ───
|
||||||
|
|||||||
Reference in New Issue
Block a user