Etapa 7 — Motor de alertas (BullMQ)
Adiciona um processo worker separado do processo web (src/worker.ts, WorkerModule) com dois crons diários e processors do BullMQ para alertas de mensalidade (master→tenant) e cobrança (tenant→customer): marca faturas/parcelas atrasadas, resolve template com fallback tenant→master por canal, renderiza placeholders, dispara WhatsApp/e-mail com retry e backoff exponencial, e grava alert_logs com idempotência por dia. Módulo alerts (web) traz o CRUD de alert_templates (master e tenant) e a consulta de alert_logs com filtros. alert_templates/alert_logs não têm RLS no schema, então o isolamento entre tenants é feito manualmente (PrismaMasterService + filtro por tenant_id), coberto por teste e2e dedicado. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Param,
|
||||
ParseUUIDPipe,
|
||||
Post,
|
||||
Put,
|
||||
Query,
|
||||
Req,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import { Request } from 'express';
|
||||
import { CurrentUser } from '../auth/decorators/current-user.decorator';
|
||||
import { Roles } from '../auth/decorators/roles.decorator';
|
||||
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
|
||||
import { RolesGuard } from '../auth/guards/roles.guard';
|
||||
import { TenantGuard } from '../auth/guards/tenant.guard';
|
||||
import { JwtPayload } from '../auth/types/jwt-payload.type';
|
||||
import { CreateTenantAlertTemplateDto } from './dto/create-tenant-alert-template.dto';
|
||||
import { ListAlertTemplatesQueryDto } from './dto/list-alert-templates.query.dto';
|
||||
import { UpdateTenantAlertTemplateDto } from './dto/update-tenant-alert-template.dto';
|
||||
import { TenantAlertTemplatesService } from './tenant-alert-templates.service';
|
||||
|
||||
@UseGuards(JwtAuthGuard, TenantGuard, RolesGuard)
|
||||
@Roles('tenant_admin')
|
||||
@Controller('tenant/alertas/templates')
|
||||
export class TenantAlertTemplatesController {
|
||||
constructor(private readonly tenantAlertTemplatesService: TenantAlertTemplatesService) {}
|
||||
|
||||
@Post()
|
||||
create(
|
||||
@Body() dto: CreateTenantAlertTemplateDto,
|
||||
@CurrentUser() user: JwtPayload,
|
||||
@Req() req: Request,
|
||||
) {
|
||||
return this.tenantAlertTemplatesService.create(dto, user, req.ip);
|
||||
}
|
||||
|
||||
@Get()
|
||||
findAll(@Query() query: ListAlertTemplatesQueryDto, @CurrentUser() user: JwtPayload) {
|
||||
return this.tenantAlertTemplatesService.findAll(query, user);
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
findOne(@Param('id', ParseUUIDPipe) id: string, @CurrentUser() user: JwtPayload) {
|
||||
return this.tenantAlertTemplatesService.findOne(id, user);
|
||||
}
|
||||
|
||||
@Put(':id')
|
||||
update(
|
||||
@Param('id', ParseUUIDPipe) id: string,
|
||||
@Body() dto: UpdateTenantAlertTemplateDto,
|
||||
@CurrentUser() user: JwtPayload,
|
||||
@Req() req: Request,
|
||||
) {
|
||||
return this.tenantAlertTemplatesService.update(id, dto, user, req.ip);
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
remove(
|
||||
@Param('id', ParseUUIDPipe) id: string,
|
||||
@CurrentUser() user: JwtPayload,
|
||||
@Req() req: Request,
|
||||
) {
|
||||
return this.tenantAlertTemplatesService.remove(id, user, req.ip);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user