Como criar um modulo
Modulos de negocio (protocolo, financeiro, tributario, atendimento) sao adicionados em modules/<nome>/ (manifestos) + apps/api/src/modules/<nome>/ (runtime).
1. Esqueleto
modules/protocolo/
├── module.json
├── audit.json
├── openapi.yaml
└── README.md
apps/api/src/modules/protocolo/
├── protocolo.module.ts
├── protocolo.controller.ts
├── protocolo.service.ts
├── protocolo.service.test.ts
└── dto/
├── criar-protocolo.dto.ts
└── movimentar.dto.ts2. Schema
// apps/api/prisma/schema.prisma
model Protocolo {
id String @id @default(uuid())
municipioId String // OBRIGATORIO (R10)
numero String
...
@@index([municipioId])
@@map("protocolos")
}Rode prisma migrate diff para gerar a migration.
3. Service usando tenant + audit
@Injectable()
export class ProtocoloService {
constructor(private prisma: GovonPrismaService) {}
async criar(input: CriarProtocoloInput) {
return this.prisma.db.protocolo.create({
data: scopedData({
numero: gerarNumero(),
requerenteCpf: input.cpf,
}),
});
}
async listar() {
return this.prisma.db.protocolo.findMany({
where: scopedWhere({}),
orderBy: { criadoEm: 'desc' },
});
}
}4. Controller com permissoes
@Controller('protocolo')
export class ProtocoloController {
constructor(private service: ProtocoloService) {}
@Post()
@RequirePermission('protocolo.criar')
criar(@Body() body: CriarProtocoloInput) { ... }
@Get()
@RequirePermission('protocolo.ler')
listar() { ... }
@Post(':id/movimentacoes')
@RequirePermission('protocolo.movimentar')
movimentar(@Param('id') id: string, @Body() body) { ... }
}5. Mascarar dados sensiveis em listagens
import { maskObject } from '@govon/mask';
return items.map(p => maskObject(p, { cpfRequerente: 'cpf' }));6. Upload de anexos
import { UploadHandler, LocalFileStorage } from '@govon/upload';
const storage = new LocalFileStorage({ baseDir: process.env.UPLOAD_DIR! });
const upload = new UploadHandler({
storage,
rules: { allowedMime: ['application/pdf'], maxBytes: 10 * 1024 * 1024 },
audit: (e) => prisma.uploadAuditLog.create({ data: e }),
});7. Job de notificacao
import { BullMqQueueAdapter, JobRunner } from '@govon/jobs';
const queue = new BullMqQueueAdapter({
queueName: 'protocolo.notificar',
connection: { host: 'redis', port: 6379 },
maxAttempts: 5,
baseDelayMs: 2000,
});
const runner = new JobRunner(queue, {
name: 'protocolo.notificar',
audit: (e) => prisma.jobAuditLog.create({ data: e }),
});
await runner.enqueue({ protocoloId });8. Validacao
npm run typecheck && npm run lint && npm run test && npm run buildChecklist completo em /modulos.