mirror of
https://github.com/R0m1k3/CollectFlow.git
synced 2026-10-21 14:08:08 +02:00
Deux endpoints d'écriture dans /api/v1 :
- PUT /products/{codein}/gamme { gamme, fournisseur? } pour un article ;
- POST /gammes { fournisseur, changes[] } pour plusieurs articles d'un
fournisseur, en tout ou rien.
Ils passent par le même enregistrement que la Grille (extrait de
saveDraftChanges dans enregistrerGammes) : snapshot du fournisseur, cache
de la Grille et instantané grid_rows. Gamme validée contre la liste des
gammes (A, B, C, Y, Z) ; un article déjà dans la gamme demandée n'est pas
réécrit. Spec OpenAPI et page de connexion à l'API mises à jour ; la
légende des gammes de la spec, qui citait une gamme D inexistante, suit
désormais lib/gammes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VEXT61tGbsXHUDNBeghCXQ
81 lines
2.9 KiB
TypeScript
81 lines
2.9 KiB
TypeScript
import "server-only";
|
|
|
|
import { db } from "@/db";
|
|
import { sessionSnapshots } from "@/db/schema";
|
|
import { eq, desc } from "drizzle-orm";
|
|
import { patchGridRowsCache } from "./get-product-rows";
|
|
import { updateGridRowsGamme } from "@/lib/grid-store";
|
|
|
|
export interface ChangementGamme {
|
|
codein: string;
|
|
/** Gamme avant la modification (état serveur), conservée pour l'historique. */
|
|
codeGammeBefore: string | null;
|
|
codeGamme: string;
|
|
}
|
|
|
|
export interface EnregistrementGammes {
|
|
codeFournisseur: string;
|
|
nomFournisseur?: string | null;
|
|
magasin: string;
|
|
changes: ChangementGamme[];
|
|
userId: number | null;
|
|
/** Libellé du snapshot, « Draft — date » par défaut. */
|
|
label?: string;
|
|
}
|
|
|
|
/**
|
|
* Enregistre des gammes pour un fournisseur — chemin unique de la Grille et de /api/v1.
|
|
*
|
|
* Les changements sont fusionnés par-dessus le dernier snapshot du fournisseur,
|
|
* puis reportés dans le cache mémoire de la Grille et dans l'instantané `grid_rows`.
|
|
* Lève une erreur si l'écriture du snapshot échoue.
|
|
*/
|
|
export async function enregistrerGammes(input: EnregistrementGammes): Promise<number> {
|
|
const { codeFournisseur, nomFournisseur, magasin, changes, userId } = input;
|
|
if (changes.length === 0) return 0;
|
|
|
|
// Charger le dernier snapshot existant pour merger les changements
|
|
const existing = await db
|
|
.select()
|
|
.from(sessionSnapshots)
|
|
.where(eq(sessionSnapshots.codeFournisseur, codeFournisseur))
|
|
.orderBy(desc(sessionSnapshots.createdAt))
|
|
.limit(1);
|
|
|
|
const prevChanges: Record<string, { before: string | null; after: string }> =
|
|
existing.length > 0
|
|
? (existing[0].changes as Record<string, { before: string | null; after: string }>)
|
|
: {};
|
|
|
|
// Merger les nouveaux changements par-dessus l'existant
|
|
const mergedChanges = { ...prevChanges };
|
|
for (const c of changes) {
|
|
mergedChanges[c.codein] = {
|
|
before: c.codeGammeBefore,
|
|
after: c.codeGamme,
|
|
};
|
|
}
|
|
|
|
// Upsert : insérer un nouveau snapshot "draft" pour ce fournisseur
|
|
await db.insert(sessionSnapshots).values({
|
|
userId,
|
|
codeFournisseur,
|
|
nomFournisseur: nomFournisseur ?? null,
|
|
magasin,
|
|
label: input.label ?? `Draft — ${new Date().toLocaleDateString("fr-FR")}`,
|
|
changes: mergedChanges,
|
|
summaryJson: null,
|
|
type: "snapshot",
|
|
});
|
|
|
|
// Les lignes en cache reçoivent les nouvelles gammes au lieu d'être jetées :
|
|
// l'invalidation imposait un recalcul complet (jusqu'à ~40 s) à la
|
|
// réouverture suivante. L'instantané lu par /api/v1 suit, sans bloquer.
|
|
patchGridRowsCache(codeFournisseur, changes);
|
|
void updateGridRowsGamme(codeFournisseur, changes).catch((e) =>
|
|
console.error("[enregistrerGammes] mise à jour grid_rows KO:", (e as Error).message?.slice(0, 200)),
|
|
);
|
|
|
|
return changes.length;
|
|
}
|