From 2e9df3659f2e810ba99a701ac7729bc10e6047b6 Mon Sep 17 00:00:00 2001 From: Mathieu Date: Tue, 9 Jun 2026 09:33:11 +0200 Subject: [PATCH] =?UTF-8?q?feat(plan5):=20types=20cr=C3=A9ation=20+=20mod?= =?UTF-8?q?=C3=A8le=20Prisma=20ProductCreation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../migration.sql | 14 +++++ prisma/schema.prisma | 29 +++++++--- src/types/creation.ts | 57 +++++++++++++++++++ 3 files changed, 93 insertions(+), 7 deletions(-) create mode 100644 prisma/migrations/20260609073303_add_product_creation/migration.sql create mode 100644 src/types/creation.ts diff --git a/prisma/migrations/20260609073303_add_product_creation/migration.sql b/prisma/migrations/20260609073303_add_product_creation/migration.sql new file mode 100644 index 0000000..7c11762 --- /dev/null +++ b/prisma/migrations/20260609073303_add_product_creation/migration.sql @@ -0,0 +1,14 @@ +-- CreateTable +CREATE TABLE "ProductCreation" ( + "id" TEXT NOT NULL PRIMARY KEY, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "userId" TEXT NOT NULL, + "sheetTab" TEXT NOT NULL, + "sheetRow" INTEGER NOT NULL, + "shopifyId" TEXT NOT NULL, + "sku" TEXT NOT NULL, + "title" TEXT NOT NULL, + "status" TEXT NOT NULL DEFAULT 'success', + "errorMessage" TEXT NOT NULL DEFAULT '', + CONSTRAINT "ProductCreation_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE +); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index e3c7ec5..388f119 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -7,13 +7,14 @@ datasource db { } model User { - id String @id @default(cuid()) - email String @unique - name String - password String - role String @default("gestionnaire") - createdAt DateTime @default(now()) - syncRuns SyncRun[] + id String @id @default(cuid()) + email String @unique + name String + password String + role String @default("gestionnaire") + createdAt DateTime @default(now()) + syncRuns SyncRun[] + productCreations ProductCreation[] } model SyncRun { @@ -28,3 +29,17 @@ model SyncRun { errors Int @default(0) log String @default("[]") } + +model ProductCreation { + id String @id @default(cuid()) + createdAt DateTime @default(now()) + userId String + user User @relation(fields: [userId], references: [id]) + sheetTab String + sheetRow Int + shopifyId String + sku String + title String + status String @default("success") + errorMessage String @default("") +} diff --git a/src/types/creation.ts b/src/types/creation.ts new file mode 100644 index 0000000..b36e249 --- /dev/null +++ b/src/types/creation.ts @@ -0,0 +1,57 @@ +/** Un produit en attente de création, extrait d'un onglet Sheets */ +export interface PendingProduct { + tab: string // nom de l'onglet (famille) + rowNumber: number // numéro de ligne 1-indexé dans le sheet + sku: string // UGS + title: string // Nom + priceMarket: string // Prix marché (compare_at_price), ex: "29.99" + priceActual: string // Prix remisé (price), ex: "19.99" + stock: number + weightKg: number + vendor: string // Marque + famille: string // Famille (contexte IA) + sousFamille: string + comment: string // Commentaire + collectionId: string // ID FAMILLE → collection Shopify + subCollectionId: string // ID SOUS FAMILLE + hasPhoto: boolean + specificFields: Record // header → valeur pour les métachamps +} + +/** Définition de métachamp existante dans Shopify */ +export interface MetafieldDefinition { + id: string // ex: "123" + namespace: string // ex: "custom" + key: string // ex: "puissance" + name: string // ex: "Puissance" + type: string // ex: "single_line_text_field" +} + +/** Résolution d'une colonne spécifique vers un métachamp */ +export interface MetafieldResolution { + columnHeader: string // en-tête colonne Sheets, ex: "Puissance (AN)" + action: 'create' | 'map' | 'skip' + namespace: string // "custom" par défaut + key: string // clé normalisée + existingDefinitionId?: string // si action === 'map' +} + +/** Événement streamé par /api/creation/execute */ +export type CreationStreamEvent = + | { type: 'progress'; current: number; total: number; tab: string; title: string; step: string } + | { type: 'error'; title: string; message: string } + | { type: 'done'; summary: { created: number; errors: number; status: 'success' | 'partial' | 'error' } } + +/** Résumé d'une création (stocké en DB) */ +export interface CreationRecord { + id: string + createdAt: string + userName: string + sheetTab: string + sheetRow: number + shopifyId: string + sku: string + title: string + status: 'success' | 'error' + errorMessage?: string +}