diff --git a/workloads/commerce-backend/src/api/admin/product-import/route.ts b/workloads/commerce-backend/src/api/admin/product-import/route.ts index b64d39e..e1a46a4 100644 --- a/workloads/commerce-backend/src/api/admin/product-import/route.ts +++ b/workloads/commerce-backend/src/api/admin/product-import/route.ts @@ -7,7 +7,9 @@ import type { IStockLocationService, } from "@medusajs/framework/types"; import { + createCollectionsWorkflow, createInventoryItemsWorkflow, + createProductCategoriesWorkflow, createProductsWorkflow, uploadFilesWorkflow, } from "@medusajs/medusa/core-flows"; @@ -20,6 +22,15 @@ import { csvRowsToObjects, parseCsv } from "../../../lib/csv"; // fila se procesa independiente (una foto rota o categoria mal escrita // no tumba el resto del archivo). // +// categoria/coleccion: si el nombre no matchea una categoria/coleccion +// ya existente (case-insensitive), se crea nueva -- antes se descartaba +// en silencio y el producto quedaba sin categoria/coleccion sin avisar +// (confirmado en vivo: "Hello Kitty & Friends" nunca se creo como +// coleccion). El handle de la nueva categoria/coleccion se genera con +// el mismo slugify() ASCII-safe de mas abajo, por la misma razon que el +// handle del producto: el default de Medusa no quita tildes/enies y +// rompe la ruta publica. +// // Las fotos se descargan del origen y se re-alojan en el mismo // MinIO/S3 que ya usa el resto del catalogo (uploadFilesWorkflow -> // mismo File Module Provider de medusa-config.ts, ya corre en el NAS). @@ -215,8 +226,33 @@ export async function POST(req: MedusaRequest<{ csv: string }>, res: MedusaRespo const inventoryItemId = inventoryItems[0]?.id; if (!inventoryItemId) throw new Error("No se pudo crear el registro de inventario"); - const categoryId = row.categoria ? categoryByName.get(row.categoria.toLowerCase().trim()) : undefined; - const collectionId = row.coleccion ? collectionByName.get(row.coleccion.toLowerCase().trim()) : undefined; + const categoryName = row.categoria?.trim(); + let categoryId = categoryName ? categoryByName.get(categoryName.toLowerCase()) : undefined; + if (categoryName && !categoryId) { + const { result: createdCategories } = await createProductCategoriesWorkflow(req.scope).run({ + input: { + product_categories: [ + { name: categoryName, handle: slugify(categoryName, `${Date.now().toString(36)}${index}`) }, + ], + }, + }); + categoryId = createdCategories[0].id; + categoryByName.set(categoryName.toLowerCase(), categoryId); + } + + const collectionName = row.coleccion?.trim(); + let collectionId = collectionName ? collectionByName.get(collectionName.toLowerCase()) : undefined; + if (collectionName && !collectionId) { + const { result: createdCollections } = await createCollectionsWorkflow(req.scope).run({ + input: { + collections: [ + { title: collectionName, handle: slugify(collectionName, `${Date.now().toString(36)}${index}`) }, + ], + }, + }); + collectionId = createdCollections[0].id; + collectionByName.set(collectionName.toLowerCase(), collectionId); + } await createProductsWorkflow(req.scope).run({ input: {