Files
apps-registry/workloads/commerce-backend/src/api/admin/reviews/[id]/route.ts
T
devopsandClaude Opus 5.5 cfd9a7ec96 feat(reseñas): reseñas de productos de compradores verificados, moderadas
Backend (commerce-backend):
- Módulo product-review (tabla nueva product_review; migración generada con
  medusa db:generate, no toca tablas existentes).
- GET /store/reviews?product_id (solo aprobadas), /store/reviews/summary,
  GET /store/reviews/me y POST /store/reviews con auth de cliente: exige que
  el pedido sea del cliente, no esté cancelado y contenga el producto
  ("Compra verificada"); 1 reseña por cliente y producto; nace "pending".
- /admin/reviews (+ /:id POST status, DELETE) y página "Reseñas" en el admin
  para aprobar/rechazar/borrar.

Storefront (ecommerce):
- /cuenta/pedidos ("Mis pedidos"): historial real + diálogo "Califica tu
  compra" (radiogroup accesible, flechas de teclado).
- Ficha: sección de reseñas con "Compra verificada" y estrellas junto al
  título; tarjetas: promedio y cantidad (una llamada /api/reviews/summary).
- Accesos: "Mis pedidos y reseñas" en la cuenta y en Ayuda.

Validado en entorno descartable (Postgres/Redis/Meilisearch/Medusa propios):
E2E de API 20/20 (incluye pedido interno por draft order, cancelación y
borrado), E2E de tienda con navegador 15/15, admin "Reseñas" verificado en
build de producción. Revisado por frontend-critic (contraste de estrellas
amber-600, patrón radiogroup).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_018r19s4H8MBGegqToqw5guP
2026-09-27 07:57:20 +00:00

25 lines
1.3 KiB
TypeScript

import type { MedusaRequest, MedusaResponse } from "@medusajs/framework";
import { MedusaError } from "@medusajs/framework/utils";
import { PRODUCT_REVIEW_MODULE } from "../../../../modules/product-review";
import type ProductReviewModuleService from "../../../../modules/product-review/service";
const STATUSES = ["pending", "approved", "rejected"] as const;
// POST /admin/reviews/:id { status } -- aprobar / rechazar / volver a
// pendiente. DELETE /admin/reviews/:id -- borrar (ej. reseñas de prueba).
export async function POST(req: MedusaRequest<{ status?: string }>, res: MedusaResponse) {
const status = req.body?.status;
if (!status || !STATUSES.includes(status as (typeof STATUSES)[number])) {
throw new MedusaError(MedusaError.Types.INVALID_DATA, `status debe ser uno de: ${STATUSES.join(", ")}`);
}
const reviews = req.scope.resolve<ProductReviewModuleService>(PRODUCT_REVIEW_MODULE);
const review = await reviews.updateProductReviews({ id: req.params.id, status: status as (typeof STATUSES)[number] });
res.json({ review });
}
export async function DELETE(req: MedusaRequest, res: MedusaResponse) {
const reviews = req.scope.resolve<ProductReviewModuleService>(PRODUCT_REVIEW_MODULE);
await reviews.deleteProductReviews(req.params.id);
res.json({ id: req.params.id, deleted: true });
}