diff --git a/app/Domains/Cart/documentacion/README.md b/app/Domains/Cart/documentacion/README.md index e9c8e3b..0645713 100644 --- a/app/Domains/Cart/documentacion/README.md +++ b/app/Domains/Cart/documentacion/README.md @@ -6,13 +6,13 @@ Gestiona el carrito activo de un tenant tanto para visitantes como para usuarios ## Modelo -- `Cart`: pertenece a un tenant y opcionalmente a un usuario; calcula el total y permite agregar, actualizar o quitar ítems. +- `Cart`: pertenece a un tenant y opcionalmente a un usuario; calcula el total, permite agregar, actualizar o quitar ítems y apunta a su reserva de stock vigente mediante `current_stock_reservation_id`. - `CartItem`: referencia un `CatalogItem` y, opcionalmente, una `Variant`; sólo persiste la selección y cantidad, y expone siempre los datos vigentes del catálogo. ## Servicios - `CartService`: obtiene el carrito, modifica ítems y administra la cookie del token invitado. -- `ExpireCartReservationsService`: libera las reservas vencidas de carritos activos y elimina los carritos que quedan vacíos. +- `ExpireCartReservationsService`: libera como conjunto las reservas vencidas de carritos activos sin eliminar el contenido del carrito. - `GuestCartMergeService`: incorpora el carrito invitado al usuario cuando este se autentica. ## Endpoints @@ -34,4 +34,6 @@ Depende de `Catalog` para productos y variantes, de `Tenant` para aislar datos y Un carrito puede pasar a `checkout`. Las compras directas usan un carrito técnico con `origin=direct_checkout`; los carritos normales conservan `origin=user` y pueden restaurarse al cancelar o vencer la compra. -El comando unificado `php artisan reservations:expire` procesa primero las compras vencidas y luego las reservas activas sin compra cuyo `expires_at` haya vencido. Se ejecuta cada minuto mediante el scheduler, conserva la fila de reserva con estado `expired`, elimina el ítem abandonado y elimina lógicamente el carrito cuando queda vacío. Cada intento registra sus resultados o su error en el log diario `storage/logs/commands/commands-AAAA-MM-DD.log`. +Cada edición sincroniza una única reserva para el carrito completo. Si varios ítems o bundles consumen el mismo inventario, se persiste una sola línea con la cantidad agregada. Al editar durante checkout, la compra anterior queda `superseded`, su reserva se libera con el motivo correspondiente y se crea otra para el carrito actualizado. + +El comando unificado `php artisan reservations:expire` procesa primero las compras vencidas y luego las reservas activas de carrito cuyo `expires_at` haya vencido. Se ejecuta cada minuto mediante el scheduler, conserva la reserva y sus líneas como historial, libera el stock como conjunto y deja intactos el carrito y sus ítems. diff --git a/app/Domains/Catalog/documentacion/README.md b/app/Domains/Catalog/documentacion/README.md index baa2bb3..42ff288 100644 --- a/app/Domains/Catalog/documentacion/README.md +++ b/app/Domains/Catalog/documentacion/README.md @@ -9,7 +9,7 @@ Modela y publica la oferta comercial del tenant: productos, variantes, categorí - `CatalogItem` es la raíz del producto y se relaciona con tenant, categoría, marca, inventario, variantes, atributos, adjuntos y grupos destacados. - `Variant`, `ItemAttribute`, `Attribute`, `AttributeOption` y `VariantDefinition` describen opciones comercializables. - `Inventory` administra stock disponible, reservado y comprado. -- `StockReservation` atribuye cada unidad reservada a un ítem de carrito y, durante checkout, a una compra, con estados `active`, `committed`, `released` y `expired`. +- `StockReservation` representa la reserva completa de un carrito o checkout, con estados `active`, `committed`, `released` y `expired`. Sus `StockReservationLine` agregan la cantidad requerida por inventario, incluso cuando varios ítems o bundles consumen el mismo stock. - `Category` soporta jerarquía y categorías globales o propias del tenant. - `FeaturedGroup` y `FeaturedItem` organizan secciones destacadas. - `BundleComponent` representa los componentes de un paquete. @@ -18,7 +18,7 @@ Modela y publica la oferta comercial del tenant: productos, variantes, categorí - `CatalogService`: alta, búsqueda, detalle, listado por categoría y eliminación. - `CatalogInventoryService`: consulta, reserva, libera y confirma inventario. -- `StockReservationService`: mantiene el ledger de reservas sincronizado con `Inventory.reserved_stock`. +- `StockReservationService`: sincroniza el carrito como conjunto, bloquea todos sus inventarios en orden estable y mantiene el ledger agregado consistente con `Inventory.reserved_stock`. - `FeaturedGroupService`: pagina los ítems destacados para la tienda. - `OnTicketFeaturedGroupService`: administra grupos destacados del panel para sitios de tickets. diff --git a/app/Domains/Purchase/documentacion/README.md b/app/Domains/Purchase/documentacion/README.md index 46838f0..65e23f3 100644 --- a/app/Domains/Purchase/documentacion/README.md +++ b/app/Domains/Purchase/documentacion/README.md @@ -6,7 +6,7 @@ Implementa el ciclo de compra y checkout: crea la cabecera de compra desde un ca ## Modelo -- `Purchase`: raíz de la compra; estados `created`, `pending_payment`, `in_review`, `paid`, `cancelled`, `rejected` y `expired`. +- `Purchase`: raíz de la compra; estados `created`, `pending_payment`, `in_review`, `paid`, `cancelled`, `rejected` y `expired`, y referencia la reserva que respaldó ese intento de checkout. - `PurchaseItem`: snapshot definitivo del producto o variante, creado recién al confirmar la compra. - `TelepagosQr` y `TelepagosPayment`: datos del QR e intentos/resultados del proveedor. - `PurchasePaid`: evento emitido una sola vez al pasar a pagada bajo bloqueo transaccional. @@ -15,7 +15,7 @@ Implementa el ciclo de compra y checkout: crea la cabecera de compra desde un ca `CheckoutService` es la fachada estable. Delega en: -- `StartCheckoutService`: inicia la compra desde el carrito o crea un carrito técnico para compra directa, sin crear todavía `PurchaseItem`. +- `StartCheckoutService`: inicia la compra desde el carrito o crea un carrito técnico para compra directa, refresca el vencimiento de la reserva agregada y crea los snapshots `PurchaseItem`. - `EditCheckoutService`: modifica los datos del comprador antes del cierre. - `CompleteCheckoutService`: completa, envía a revisión o materializa los `PurchaseItem` al confirmar el pago. - `ReleaseCheckoutService`: cancela, vence y procesa vencimientos pendientes. @@ -24,7 +24,7 @@ Implementa el ciclo de compra y checkout: crea la cabecera de compra desde un ca Al informar una transferencia, la compra pasa de `pending_payment` a `in_review` y deja de vencer. Si el comprador abandona el checkout durante la revisión, la compra y sus reservas permanecen intactas y se crea un carrito activo nuevo para que pueda seguir comprando. Adminapp puede confirmar o anular explícitamente la compra en revisión. -Las cantidades y variantes se editan mediante el dominio Cart. El endpoint autenticado `PATCH /checkout-carts/{cart}/items/{cartItem}` valida que el carrito pertenezca al usuario y a una compra editable. Cuando existe un cambio real, invalida atómicamente el intento de pago anterior, recalcula el total y renueva la reserva; Purchase no expone operaciones sobre líneas antes de la confirmación. +Las cantidades y variantes se editan mediante el dominio Cart. El endpoint autenticado `PATCH /checkout-carts/{cart}/items/{cartItem}` valida que el carrito pertenezca al usuario y a una compra editable. Cuando existe un cambio real, invalida atómicamente el intento de pago anterior, libera su reserva completa y crea otra para el contenido actualizado; Purchase no expone operaciones sobre líneas antes de la confirmación. `UserPurchaseLimitService` controla límites de compra y `CheckoutService` conserva el punto de entrada para controladores e integraciones.