Files
Classeo/frontend/e2e/helpers.ts
Mathias STRASSER b7dc27f2a5
Some checks failed
CI / Backend Tests (push) Has been cancelled
CI / Frontend Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Naming Conventions (push) Has been cancelled
CI / Build Check (push) Has been cancelled
feat: Calculer automatiquement les moyennes après chaque saisie de notes
Les enseignants ont besoin de moyennes à jour immédiatement après la
publication ou modification des notes, sans attendre un batch nocturne.

Le système recalcule via Domain Events synchrones : statistiques
d'évaluation (min/max/moyenne/médiane), moyennes matières pondérées
(normalisation /20), et moyenne générale par élève. Les résultats sont
stockés dans des tables dénormalisées avec cache Redis (TTL 5 min).

Trois endpoints API exposent les données avec contrôle d'accès par rôle.
Une commande console permet le backfill des données historiques au
déploiement.
2026-04-04 02:25:00 +02:00

59 lines
2.0 KiB
TypeScript

import { execSync } from 'child_process';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
export const projectRoot = join(__dirname, '../..');
export const composeFile = join(projectRoot, 'compose.yaml');
export function execWithRetry(command: string, maxRetries = 3): string {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return execSync(command, { encoding: 'utf-8' });
} catch (error) {
if (attempt === maxRetries) throw error;
// Wait before retry: 1s, 2s, 3s
execSync(`sleep ${attempt}`);
}
}
throw new Error('Unreachable');
}
export function runSql(sql: string) {
execWithRetry(
`docker compose -f "${composeFile}" exec -T php php bin/console dbal:run-sql "${sql}" 2>&1`
);
}
export function clearCache() {
try {
execWithRetry(
`docker compose -f "${composeFile}" exec -T php php bin/console cache:pool:clear paginated_queries.cache 2>&1`
);
} catch {
// Cache pool may not exist
}
}
export function resolveDeterministicIds(tenantId: string): { schoolId: string; academicYearId: string } {
const output = execWithRetry(
`docker compose -f "${composeFile}" exec -T php php -r '` +
`require "/app/vendor/autoload.php"; ` +
`$t="${tenantId}"; $ns="6ba7b814-9dad-11d1-80b4-00c04fd430c8"; ` +
`echo Ramsey\\Uuid\\Uuid::uuid5($ns,"school-$t")->toString()."\\n"; ` +
`$m=(int)date("n"); $s=$m>=9?(int)date("Y"):(int)date("Y")-1; $e=$s+1; ` +
`echo Ramsey\\Uuid\\Uuid::uuid5($ns,"$t:$s-$e")->toString();` +
`' 2>&1`
).trim();
const [schoolId, academicYearId] = output.split('\n');
return { schoolId: schoolId!, academicYearId: academicYearId! };
}
export function createTestUser(tenant: string, email: string, password: string, role: string) {
execWithRetry(
`docker compose -f "${composeFile}" exec -T php php bin/console app:dev:create-test-user --tenant=${tenant} --email=${email} --password=${password} --role=${role} 2>&1`
);
}