@mostajs/recette 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/package.json +1 -1
- package/src/recette.js +31 -4
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|
**Auteur** : Dr Hamid MADANI <drmdh@msn.com>
|
|
4
4
|
|
|
5
|
+
## 0.3.0 — 2026-10-23
|
|
6
|
+
|
|
7
|
+
### Corrigé
|
|
8
|
+
|
|
9
|
+
- **Une ligne, une issue : le DERNIER relevé fait foi.** Le formulaire enregistre à chaque
|
|
10
|
+
changement, comme un questionnaire ; un testeur qui hésitait entre `ko` et `ok`, ou qui écrivait
|
|
11
|
+
sa remarque en plusieurs fois, laissait plusieurs relevés pour la même ligne, et tous étaient
|
|
12
|
+
comptés. Une hésitation devenait un `ko` de plus au dossier, une remarque tapée en trois fois
|
|
13
|
+
trois `ok` — et le verdict proposé au certificateur s'en trouvait faussé. Les compteurs du
|
|
14
|
+
dossier et de `etat()` ne retiennent plus que le dernier relevé de chaque (feuillet, ligne).
|
|
15
|
+
**T-REC-15** le verrouille.
|
|
16
|
+
|
|
17
|
+
### Ajouté
|
|
18
|
+
|
|
19
|
+
- `releves.derniersDuFeuillet(feuilletId)` — le relevé qui fait foi pour chaque ligne, issue et
|
|
20
|
+
remarque comprises : ce qu'un formulaire réaffiche.
|
|
21
|
+
- Le dossier figé porte `relevesRemplaces` : combien de relevés ont été remplacés. L'historique
|
|
22
|
+
reste en base, rien n'est effacé.
|
|
23
|
+
|
|
24
|
+
> Le **contenu** d'un dossier figé change de forme (`releves` ne garde que les relevés qui font
|
|
25
|
+
> foi) : son empreinte n'est pas comparable à celle d'un dossier figé en 0.2.x. Les dossiers déjà
|
|
26
|
+
> figés ne sont pas touchés.
|
|
27
|
+
|
|
5
28
|
## 0.2.1 — 2026-09-10
|
|
6
29
|
|
|
7
30
|
Correction née d'une panne **en production**, invisible depuis les essais.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mostajs/recette",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Validation & recette applicative : trame `mostajs-devtest/1` reçue signée du certificateur, points enrichis POUR LE CLIENT (l'import n'écrase jamais l'enrichissement), feuillets composés à l'image du manifeste PDF (ok/ko/er), anomalies déclarées puis qualifiées, dossier figé et EXPORTÉ SIGNÉ — aucun appel réseau —, certificat reçu et vérifié, feu d'exploitation DÉRIVÉ du certificat. Powers ValiTrax (valitrax.mostajs.dev).",
|
|
5
5
|
"author": "Dr Hamid MADANI <drmdh@msn.com>",
|
|
6
6
|
"license": "AGPL-3.0-or-later",
|
package/src/recette.js
CHANGED
|
@@ -261,6 +261,29 @@ export function createRecette({ repositories, ports = {}, clock = () => new Date
|
|
|
261
261
|
},
|
|
262
262
|
};
|
|
263
263
|
|
|
264
|
+
/**
|
|
265
|
+
* UNE LIGNE, UNE ISSUE : le DERNIER relevé de chaque (feuillet, ligne) fait foi.
|
|
266
|
+
*
|
|
267
|
+
* Un relevé ne s'efface pas, il se remplace : le formulaire enregistre à chaque changement, comme
|
|
268
|
+
* un questionnaire, et le testeur qui hésite entre `ko` et `ok`, ou qui écrit sa remarque en
|
|
269
|
+
* plusieurs fois, laisse plusieurs relevés pour la même ligne. Les compter tous faisait d'une
|
|
270
|
+
* hésitation un `ko` de plus au dossier, et d'une remarque tapée en trois fois trois `ok` :
|
|
271
|
+
* le verdict proposé au certificateur s'en trouvait faussé. L'historique reste en base ; le
|
|
272
|
+
* dossier dit combien de relevés ont été remplacés.
|
|
273
|
+
*/
|
|
274
|
+
const instant = (r) => +new Date(r.createdAt || r.at || 0);
|
|
275
|
+
function derniers(rs) {
|
|
276
|
+
const parLigne = new Map();
|
|
277
|
+
rs.forEach((r, i) => {
|
|
278
|
+
const cle = `${r.feuilletId}\u0000${r.ref}`;
|
|
279
|
+
const avant = parLigne.get(cle);
|
|
280
|
+
// À instant égal, l'ordre de lecture départage : le plus tard lu est le plus récent.
|
|
281
|
+
if (!avant || instant(r) >= instant(avant.r)) parLigne.set(cle, { r, i });
|
|
282
|
+
});
|
|
283
|
+
return [...parLigne.values()].sort((a, b) => a.i - b.i).map((x) => x.r);
|
|
284
|
+
}
|
|
285
|
+
const compter = (rs) => ({ ok: rs.filter((r) => r.issue === 'ok').length, ko: rs.filter((r) => r.issue === 'ko').length, er: rs.filter((r) => r.issue === 'er').length });
|
|
286
|
+
|
|
264
287
|
const releves = {
|
|
265
288
|
/**
|
|
266
289
|
* Consigner une observation.
|
|
@@ -285,6 +308,8 @@ export function createRecette({ repositories, ports = {}, clock = () => new Date
|
|
|
285
308
|
},
|
|
286
309
|
of: (campagneId) => repo.releves.find((r) => r.campagneId === campagneId),
|
|
287
310
|
duFeuillet: (feuilletId) => repo.releves.find((r) => r.feuilletId === feuilletId),
|
|
311
|
+
/** Le relevé QUI FAIT FOI pour chaque ligne d'un feuillet : le dernier consigné (voir `derniers`). */
|
|
312
|
+
derniersDuFeuillet: async (feuilletId) => derniers(await repo.releves.find((r) => r.feuilletId === feuilletId)),
|
|
288
313
|
};
|
|
289
314
|
|
|
290
315
|
const anomalies = {
|
|
@@ -368,14 +393,16 @@ export function createRecette({ repositories, ports = {}, clock = () => new Date
|
|
|
368
393
|
if (obstacles.length && !force) throw new Error(`figement refusé — ${obstacles.join(' · ')}`);
|
|
369
394
|
|
|
370
395
|
const fs = await feuillets.of(campagneId);
|
|
371
|
-
const
|
|
396
|
+
const tous = await releves.of(campagneId);
|
|
397
|
+
const rs = derniers(tous);
|
|
372
398
|
const as = await anomalies.of(campagneId);
|
|
373
399
|
const contenu = {
|
|
374
400
|
campagne: { no: c.no, releaseRef: c.releaseRef, projet: c.projet, perimetre: c.perimetre, instanceUrl: c.instanceUrl },
|
|
375
401
|
feuillets: fs.map((f) => ({ role: f.role, langue: f.langue, state: f.state, planVersion: f.planVersion })),
|
|
376
402
|
releves: rs.map((r) => ({ ref: r.ref, issue: r.issue, at: r.at, source: r.source, confiance: r.confiance, texte: r.texte })),
|
|
377
403
|
anomalies: as.map((a) => ({ titre: a.titre, graviteProposee: a.graviteProposee, graviteQualifiee: a.graviteQualifiee, state: a.state, bugRef: a.bugRef, motifEcart: a.motifEcart })),
|
|
378
|
-
compteurs:
|
|
404
|
+
compteurs: compter(rs),
|
|
405
|
+
relevesRemplaces: tous.length - rs.length,
|
|
379
406
|
obstaclesAuFigement: obstacles, // consignés même en `force` : un dossier dit ce qu'il vaut
|
|
380
407
|
};
|
|
381
408
|
const empreinte = createHash('sha256').update(JSON.stringify(contenu)).digest('hex');
|
|
@@ -499,12 +526,12 @@ export function createRecette({ repositories, ports = {}, clock = () => new Date
|
|
|
499
526
|
async function etat(campagneId) {
|
|
500
527
|
const c = await getCampagne(campagneId);
|
|
501
528
|
const fs = await feuillets.of(campagneId);
|
|
502
|
-
const rs = await releves.of(campagneId);
|
|
529
|
+
const rs = derniers(await releves.of(campagneId));
|
|
503
530
|
const as = await anomalies.of(campagneId);
|
|
504
531
|
return {
|
|
505
532
|
campagne: { no: c.no, state: c.state, releaseRef: c.releaseRef },
|
|
506
533
|
feuillets: { remis: fs.length, rendus: fs.filter((f) => f.state !== 'remis').length },
|
|
507
|
-
releves:
|
|
534
|
+
releves: compter(rs),
|
|
508
535
|
anomalies: { declarees: as.filter((a) => a.state === 'declaree').length, bloquantes: as.filter((a) => a.graviteQualifiee === 'bloquante').length, total: as.length },
|
|
509
536
|
obstacles: await obstaclesAuDepot(campagneId),
|
|
510
537
|
};
|