Files
lislgosms/api/src/operations/admin-operations.controller.ts
T

329 lines
10 KiB
TypeScript

import { Body, Controller, Get, Param, Post, Query, Res } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { CurrentSessionUserId } from '../auth/current-session-user.decorator';
import { RequireRecentAuthentication } from '../auth/require-recent-authentication.decorator';
import { SendChainService } from '../send-chain/send-chain.service';
import { OperationsService } from './operations.service';
import { ProtocolLogsService } from '../protocol-logs/protocol-logs.service';
type DownloadResponse = {
setHeader(name: string, value: number | string): void;
send(content: string | Buffer): void;
};
@ApiTags('operations')
@Controller('admin/operations')
export class AdminOperationsController {
constructor(
private readonly operations: OperationsService,
private readonly sendChain: SendChainService,
) {}
@Get('monitor')
monitor(@Query('tenantId') tenantId?: string, @Query('channelId') channelId?: string) {
return this.operations.monitor({ tenantId, channelId });
}
@Get('task-progress')
taskProgress(@Query('tenantId') tenantId?: string, @Query('status') status?: string) {
return this.operations.listBatchTasks({ tenantId, status });
}
@Get('messages')
listMessages(
@Query('tenantId') tenantId?: string,
@Query('applicationId') applicationId?: string,
@Query('channelId') channelId?: string,
@Query('taskId') taskId?: string,
@Query('messageId') messageId?: string,
@Query('phoneNumber') phoneNumber?: string,
@Query('contentKeyword') contentKeyword?: string,
@Query('channelKeyword') channelKeyword?: string,
@Query('queuedAtFrom') queuedAtFrom?: string,
@Query('queuedAtTo') queuedAtTo?: string,
@Query('status') status?: string,
) {
return this.operations.listMessages({
tenantId,
applicationId,
channelId,
taskId,
messageId,
phoneNumber,
contentKeyword,
channelKeyword,
queuedAtFrom,
queuedAtTo,
status,
});
}
@Get('message-segment-audits')
messageSegmentAudits(
@Query('messageId') messageId?: string,
@Query('messageRecordId') messageRecordId?: string,
) {
return this.operations.listMessageSegmentAudits({ messageId, messageRecordId });
}
@Get('uplink-messages')
listUplinkMessages(@Query('tenantId') tenantId?: string, @Query('channelId') channelId?: string) {
return this.operations.listUplinkMessages({ tenantId, channelId });
}
@Post('uplink-messages/:id/claim')
claimUplinkMatchCandidate(
@Param('id') id: string,
@Body() body: { candidateId?: string; operatorId?: string },
) {
return this.sendChain.claimUplinkMatchCandidate(id, String(body.candidateId ?? ''), body.operatorId);
}
@Get('dashboard')
dashboard(@Query('tenantId') tenantId?: string) {
return this.operations.dashboard({ tenantId });
}
@Get('dashboard/statistics')
dashboardStatistics(@Query('tenantId') tenantId?: string) {
return this.operations.dashboard({ tenantId });
}
@Get('statistics')
statistics(@Query('tenantId') tenantId?: string, @Query('groupBy') groupBy?: string) {
return this.operations.statistics({ tenantId, groupBy });
}
@Get('send-quality')
sendQuality(@Query('date') date?: string) {
return this.operations.sendQuality(date);
}
@Get('signature-quality')
signatureQuality(
@Query('date') date?: string,
@Query('keyword') keyword?: string,
@Query('page') page?: string,
@Query('pageSize') pageSize?: string,
) {
return this.operations.signatureQuality({
date,
keyword,
page: Number(page),
pageSize: Number(pageSize),
});
}
@Get('audit-logs')
auditLogs(
@Query('tenantId') tenantId?: string,
@Query('userId') userId?: string,
@Query('page') page?: string,
@Query('pageSize') pageSize?: string,
) {
return this.operations.auditLogs({ tenantId, userId, page: Number(page), pageSize: Number(pageSize) });
}
@Get('audit-summary')
auditSummary(@Query('tenantId') tenantId?: string) {
return this.operations.auditSummary({ tenantId });
}
@Get('trace')
trace(
@Query('tenantId') tenantId?: string,
@Query('applicationId') applicationId?: string,
@Query('channelId') channelId?: string,
@Query('taskId') taskId?: string,
@Query('phoneNumber') phoneNumber?: string,
@Query('messageId') messageId?: string,
) {
return this.operations.trace({ tenantId, applicationId, channelId, taskId, phoneNumber, messageId });
}
@Get('reconciliation')
reconciliation(@Query('tenantId') tenantId?: string, @Query('taskId') taskId?: string) {
return this.operations.reconciliation({ tenantId, taskId });
}
@Get('gateway-submit-dead-letters')
gatewaySubmitDeadLetters(
@Query('tenantId') tenantId?: string,
@Query('applicationId') applicationId?: string,
@Query('channelId') channelId?: string,
@Query('status') status?: string,
@Query('keyword') keyword?: string,
@Query('page') page?: string,
@Query('pageSize') pageSize?: string,
) {
return this.operations.listGatewaySubmitDeadLetters({
tenantId,
applicationId,
channelId,
status,
keyword,
page: Number(page),
pageSize: Number(pageSize),
});
}
@Post('gateway-submit-dead-letters/:id/requeue')
@RequireRecentAuthentication()
requeueGatewaySubmitDeadLetter(
@Param('id') id: string,
@Body() body: { confirmedNotSubmitted?: boolean; reason?: string },
@CurrentSessionUserId() operatorId?: string,
) {
return this.sendChain.requeueGatewaySubmitDeadLetter(id, { ...body, operatorId });
}
@Get('downstream-deliveries')
downstreamDeliveries(
@Query('tenantId') tenantId?: string,
@Query('applicationId') applicationId?: string,
@Query('deliveryType') deliveryType?: string,
@Query('createdAtFrom') createdAtFrom?: string,
@Query('createdAtTo') createdAtTo?: string,
@Query('status') status?: string,
@Query('keyword') keyword?: string,
@Query('page') page?: string,
@Query('pageSize') pageSize?: string,
) {
return this.operations.listDownstreamDeliveries({
tenantId,
applicationId,
deliveryType,
createdAtFrom,
createdAtTo,
status,
keyword,
page: Number(page),
pageSize: Number(pageSize),
});
}
@Get('downstream-deliveries/dashboard')
downstreamDeliveryDashboard(
@Query('tenantId') tenantId?: string,
@Query('applicationId') applicationId?: string,
@Query('deliveryType') deliveryType?: string,
@Query('createdAtFrom') createdAtFrom?: string,
@Query('createdAtTo') createdAtTo?: string,
) {
return this.operations.downstreamDeliveryDashboard({
tenantId,
applicationId,
deliveryType,
createdAtFrom,
createdAtTo,
});
}
@Get('downstream-recovery-statuses')
downstreamRecoveryStatuses(
@Query('tenantId') tenantId?: string,
@Query('applicationId') applicationId?: string,
@Query('state') state?: string,
@Query('failureCategory') failureCategory?: string,
@Query('keyword') keyword?: string,
@Query('updatedAtFrom') updatedAtFrom?: string,
@Query('updatedAtTo') updatedAtTo?: string,
@Query('page') page?: string,
@Query('pageSize') pageSize?: string,
) {
return this.operations.listDownstreamRecoveryStatuses({
tenantId,
applicationId,
state,
failureCategory,
keyword,
updatedAtFrom,
updatedAtTo,
page: Number(page),
pageSize: Number(pageSize),
});
}
@Get('downstream-recovery-statuses/export')
async exportDownstreamRecoveryStatuses(
@Query('tenantId') tenantId: string | undefined,
@Query('applicationId') applicationId: string | undefined,
@Query('state') state: string | undefined,
@Query('failureCategory') failureCategory: string | undefined,
@Query('keyword') keyword: string | undefined,
@Query('updatedAtFrom') updatedAtFrom: string | undefined,
@Query('updatedAtTo') updatedAtTo: string | undefined,
@Res() response: DownloadResponse,
) {
const exported = await this.operations.exportDownstreamRecoveryStatuses({
tenantId,
applicationId,
state,
failureCategory,
keyword,
updatedAtFrom,
updatedAtTo,
});
response.setHeader('Content-Type', 'text/csv; charset=utf-8');
response.setHeader('Content-Disposition', `attachment; filename*=UTF-8''${encodeURIComponent(exported.fileName)}`);
response.send(`\uFEFF${exported.content}`);
}
@Get('downstream-recovery-statuses/:id')
downstreamRecoveryStatusDetail(@Param('id') id: string) {
return this.operations.getDownstreamRecoveryStatus(id);
}
@Post('downstream-deliveries/:id/requeue')
requeueDownstreamDelivery(@Param('id') id: string) {
return this.sendChain.requeueDownstreamDelivery(id);
}
@Post('downstream-deliveries/requeue')
batchRequeueDownstreamDeliveries(@Body() body: { ids?: string[] }) {
return this.sendChain.batchRequeueDownstreamDeliveries(body.ids ?? []);
}
}
@ApiTags('admin-system-logs')
@Controller('admin/system-logs')
export class AdminSystemLogsController {
constructor(
private readonly operations: OperationsService,
private readonly protocolLogs: ProtocolLogsService,
) {}
@Get('protocol-interactions')
protocolInteractions(
@Query('protocol') protocol?: string,
@Query('direction') direction?: string,
@Query('eventType') eventType?: string,
@Query('status') status?: string,
@Query('keyword') keyword?: string,
@Query('range') range?: string,
@Query('page') page?: string,
@Query('pageSize') pageSize?: string,
) {
return this.protocolLogs.list({ protocol, direction, eventType, status, keyword, range, page: Number(page), pageSize: Number(pageSize) });
}
@Get()
list(
@Query('tenantId') tenantId?: string,
@Query('userId') userId?: string,
@Query('keyword') keyword?: string,
@Query('level') level?: string,
@Query('module') module?: string,
@Query('range') range?: string,
@Query('page') page?: string,
@Query('pageSize') pageSize?: string,
) {
return this.operations.systemLogs({ tenantId, userId, keyword, level, module, range, page: Number(page), pageSize: Number(pageSize) });
}
@Post('exports')
export(@Body() body: { tenantId?: string; userId?: string; keyword?: string; level?: string; module?: string; range?: string }) {
return this.operations.exportSystemLogs(body);
}
}