Lot 5 : changement de magasin instantané et contrôle des droits

Grille
- Corrige le lot 4 : au changement de magasin, les chiffres et le tri
  affichés suivent tout de suite (nouvelle liste), la sélection est gardée.
- Lignes toujours chargées « Nos 2 magasins » ; changement de magasin sans
  aller-retour serveur (URL mise à jour par l'historique du navigateur).
- Complément de l'API FF par magasin servi à part (/api/grid/rows/store-patch),
  appliqué à son arrivée, calcul identique à l'ancien (lib/store-patch.ts).
- La recherche ne reconstruit plus toutes les lignes à chaque frappe ; la
  sélection n'est remise à zéro qu'au changement de fournisseur.

Sécurité
- lib/authz.ts : session relue en base (cache 1 min), rôle de la base
  prioritaire ; variantes pour actions, routes et pages.
- Paramètres réservés aux administrateurs ; session vérifiée dans les actions
  Grille, Commandes, Historique et les routes ; diagnostics réservés admin.
- Mots de passe et clés d'IA plus envoyés au navigateur ; champ vide = mot de
  passe conservé ; plus de mot de passe dans le localStorage ; l'enregistrement
  de la base n'efface plus les clés d'IA.
- admin/admin créé seulement si aucun utilisateur ; fichier de secours utilisé
  uniquement si la base est injoignable ; data/ ignoré par git.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AcA129WzGTH6zxPHFBGWmn
This commit is contained in:
Claude committed 2026-10-04 06:39:49 +00:00
1 parent b7ee413d67
commit 26b9364232
44 files changed
+1155 -531

No files matched your search

+14 -2
View File
@@ -5,6 +5,7 @@ import { and, eq } from "drizzle-orm";
import { db } from "@/db";
import { commandeCadences } from "@/db/schema";
import { getDerniereReceptionCached, getFournisseursCached } from "@/lib/ff-cache";
import { requireSession, verifierSession } from "@/lib/authz";
export type CadenceStatut = "a_commander" | "bientot" | "ok" | "inconnu";
@@ -37,6 +38,7 @@ function calcStatut(joursRestants: number | null): CadenceStatut {
/** Liste des fournisseurs (référentiel) pour le sélecteur de cadence. */
export async function getFournisseursPourCadence(): Promise<{ code: string; nom: string }[]> {
await requireSession();
return getFournisseursCached();
}
@@ -45,6 +47,7 @@ export async function getFournisseursPourCadence(): Promise<{ code: string; nom:
* de la dernière réception (FF Nancy).
*/
export async function listCadences(): Promise<CadenceView[]> {
await requireSession();
let rows: typeof commandeCadences.$inferSelect[] = [];
let receptions = new Map<string, string>();
try {
@@ -95,6 +98,9 @@ export interface UpsertCadenceInput {
/** Crée ou met à jour la cadence d'un fournisseur sur un site. */
export async function upsertCadence(input: UpsertCadenceInput): Promise<{ ok: boolean; error?: string }> {
const acces = await verifierSession();
if (!acces.ok) return { ok: false, error: acces.message };
const codefou = input.codefou?.trim();
const site = input.site?.trim();
const intervalle = Math.round(Number(input.intervalleSemaines));
@@ -132,7 +138,10 @@ export async function upsertCadence(input: UpsertCadenceInput): Promise<{ ok: bo
}
/** Active / désactive une cadence sans la supprimer. */
export async function toggleCadence(codefou: string, site: string, actif: boolean): Promise<{ ok: boolean }> {
export async function toggleCadence(codefou: string, site: string, actif: boolean): Promise<{ ok: boolean; error?: string }> {
const acces = await verifierSession();
if (!acces.ok) return { ok: false, error: acces.message };
try {
await db
.update(commandeCadences)
@@ -147,7 +156,10 @@ export async function toggleCadence(codefou: string, site: string, actif: boolea
}
/** Supprime définitivement une cadence. */
export async function removeCadence(codefou: string, site: string): Promise<{ ok: boolean }> {
export async function removeCadence(codefou: string, site: string): Promise<{ ok: boolean; error?: string }> {
const acces = await verifierSession();
if (!acces.ok) return { ok: false, error: acces.message };
try {
await db
.delete(commandeCadences)