e9e61b52bc
8 routes under /v1/support (session-auth). RestClient gains createTicket/escalate/ listTickets/patchTicket/requestCallback/createQueue/joinQueue/setAvailability + Ticket/CallbackRequest types. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
77 lines
3.0 KiB
TypeScript
77 lines
3.0 KiB
TypeScript
import { BadRequestException, Body, Controller, Get, Headers, Param, Patch, Post, Query } from '@nestjs/common';
|
|
import { IiosTicketState } from '@prisma/client';
|
|
import { SupportService } from './support.service';
|
|
import { AssignmentService } from './assignment.service';
|
|
import { SessionVerifier } from '../platform/session.verifier';
|
|
import type { MessagePrincipal } from '../identity/actor.resolver';
|
|
import {
|
|
AvailabilityDto,
|
|
CallbackDto,
|
|
CreateQueueDto,
|
|
CreateTicketDto,
|
|
EscalateDto,
|
|
PatchTicketDto,
|
|
} from './support.dto';
|
|
|
|
@Controller('v1/support')
|
|
export class SupportController {
|
|
constructor(
|
|
private readonly support: SupportService,
|
|
private readonly assignment: AssignmentService,
|
|
private readonly session: SessionVerifier,
|
|
) {}
|
|
|
|
@Post('tickets')
|
|
async createTicket(@Body() body: CreateTicketDto, @Headers('authorization') auth?: string) {
|
|
return this.support.createTicket(this.principal(auth), body);
|
|
}
|
|
|
|
@Post('escalate')
|
|
async escalate(@Body() body: EscalateDto, @Headers('authorization') auth?: string) {
|
|
return this.support.escalate(body.threadId, this.principal(auth), body.subject);
|
|
}
|
|
|
|
@Get('tickets')
|
|
async listTickets(@Query('scope') scope?: string, @Headers('authorization') auth?: string) {
|
|
return this.support.listTickets(this.principal(auth), { scope: scope === 'assigned' ? 'assigned' : 'mine' });
|
|
}
|
|
|
|
@Patch('tickets/:id')
|
|
async patchTicket(@Param('id') id: string, @Body() body: PatchTicketDto, @Headers('authorization') auth?: string) {
|
|
return this.support.transition(id, this.principal(auth), body.state as IiosTicketState, body.reason);
|
|
}
|
|
|
|
@Post('callbacks')
|
|
async callback(@Body() body: CallbackDto, @Headers('authorization') auth?: string) {
|
|
return this.support.requestCallback(this.principal(auth), {
|
|
preferChannel: body.preferChannel,
|
|
preferredTime: body.preferredTime ? new Date(body.preferredTime) : undefined,
|
|
notes: body.notes,
|
|
ticketId: body.ticketId,
|
|
});
|
|
}
|
|
|
|
// ─── admin / agent ────────────────────────────────────────────────
|
|
|
|
@Post('queues')
|
|
async createQueue(@Body() body: CreateQueueDto, @Headers('authorization') auth?: string) {
|
|
return this.assignment.createQueue(this.principal(auth), body.name);
|
|
}
|
|
|
|
@Post('queues/:id/members')
|
|
async joinQueue(@Param('id') id: string, @Headers('authorization') auth?: string) {
|
|
return this.assignment.addMember(id, this.principal(auth));
|
|
}
|
|
|
|
@Patch('members/me/availability')
|
|
async availability(@Body() body: AvailabilityDto, @Headers('authorization') auth?: string) {
|
|
return this.assignment.setAvailability(this.principal(auth), body.state);
|
|
}
|
|
|
|
private principal(authorization?: string): MessagePrincipal {
|
|
const token = (authorization ?? '').replace(/^Bearer\s+/i, '');
|
|
if (!token) throw new BadRequestException('Authorization bearer token is required');
|
|
return this.session.verify(token);
|
|
}
|
|
}
|