petitspas/backend/src/modules/numero-dossier/numero-dossier.service.ts

56 lines
1.8 KiB
TypeScript

import { Injectable } from '@nestjs/common';
import { EntityManager } from 'typeorm';
const FORMAT_MAX_SEQUENCE = 990000;
/**
* Service de génération du numéro de dossier (ticket #103).
* Format AAAA-NNNNNN (année + 6 chiffres), séquence par année.
* Si séquence >= 990000, overflowWarning est true (alerte gestionnaire).
*/
@Injectable()
export class NumeroDossierService {
/**
* Génère le prochain numéro de dossier dans le cadre d'une transaction.
* À appeler avec le manager de la transaction pour garantir l'unicité.
*/
async getNextNumeroDossier(manager: EntityManager): Promise<{
numero: string;
overflowWarning: boolean;
}> {
const year = new Date().getFullYear();
// Garantir l'existence de la ligne pour l'année
await manager.query(
`INSERT INTO numero_dossier_sequence (annee, prochain)
VALUES ($1, 1)
ON CONFLICT (annee) DO NOTHING`,
[year],
);
// Prendre le prochain numéro et incrémenter (FOR UPDATE pour concurrence)
const selectRows = await manager.query(
`SELECT prochain FROM numero_dossier_sequence WHERE annee = $1 FOR UPDATE`,
[year],
);
const currentVal = selectRows?.[0]?.prochain ?? 1;
await manager.query(
`UPDATE numero_dossier_sequence SET prochain = prochain + 1 WHERE annee = $1`,
[year],
);
const nextVal = currentVal;
const overflowWarning = nextVal >= FORMAT_MAX_SEQUENCE;
if (overflowWarning) {
// Log pour alerte gestionnaire (ticket #103)
console.warn(
`[NumeroDossierService] Séquence année ${year} >= ${FORMAT_MAX_SEQUENCE} (valeur ${nextVal}). Prévoir renouvellement ou format.`,
);
}
const numero = `${year}-${String(nextVal).padStart(6, '0')}`;
return { numero, overflowWarning };
}
}