Documentation Index
Fetch the complete documentation index at: https://mintlify.com/interezante456-pixel/proyecto-dise-o/llms.txt
Use this file to discover all available pages before exploring further.
VentaController gestiona el ciclo de vida completo de las ventas en Tienda MiCholo: desde el registro de nuevas ventas hasta la consulta del historial, la edición de datos de comprobante y la anulación con restauración automática de stock. El controller está decorado con [Authorize] a nivel de clase, por lo que todas las acciones requieren sesión iniciada. Recibe AppDbContext vía inyección de dependencias. El enum TipoComprobante (valores BOLETA / FACTURA) y EstadoVenta (valores Activa / Anulada) provienen del namespace TiendaMiCholo.Models.Enums.
GET /Venta/Registrar
Muestra el formulario vacío para registrar una nueva venta. Autorización:[Authorize] (cualquier usuario autenticado).
Comportamiento:
- Devuelve la vista sin enviar la lista de productos al modelo, ya que la búsqueda de productos se realiza dinámicamente vía AJAX mediante el endpoint
BuscarProductos.
View().
GET /Venta/BuscarProductos
Endpoint AJAX que busca productos activos por nombre o código para poblar el carrito en tiempo real. Autorización:[Authorize] (cualquier usuario autenticado).
Texto de búsqueda. Se compara contra
Nombre y Codigo del producto usando Contains. Si está vacío o es solo espacios, devuelve un array JSON vacío inmediatamente.Este endpoint devuelve JSON, no una vista Razor. Está pensado para ser consumido con
fetch o XMLHttpRequest desde el formulario de registro de ventas. Devuelve como máximo 20 resultados y solo incluye productos con Activo == true.Json(List<object>) — array JSON o array vacío [].
POST /Venta/Registrar
Registra una nueva venta completa envolviendo todo el proceso en una transacción de base de datos. Autorización:[Authorize] (cualquier usuario autenticado). Incluye [ValidateAntiForgeryToken].
Array de identificadores de producto (
IdProducto) en el orden del carrito.Array de cantidades solicitadas, indexado en paralelo con
productoIds.Array de precios unitarios aplicados, indexado en paralelo con
productoIds.Nombre o razón social del cliente. Si se omite o está vacío, se asigna automáticamente
"Público en general".Tipo de comprobante:
BOLETA o FACTURA.RUC del cliente. Obligatorio y debe tener exactamente 11 dígitos numéricos cuando
tipoComprobante == FACTURA.Celular del cliente. Obligatorio, debe tener 9 dígitos numéricos y comenzar con
9 cuando tipoComprobante == FACTURA. Para BOLETA se ignora y se establece como null.Arrays no vacíos
productoIds debe contener al menos un elemento; de lo contrario se establece TempData["Error"] y se devuelve el formulario.Consistencia de longitudes
cantidades.Length y precios.Length deben ser iguales a productoIds.Length. Si no coinciden, se devuelve error.Validaciones de FACTURA
Si
tipoComprobante == FACTURA: el cliente no puede ser "Público en general", el RUC debe tener 11 dígitos numéricos y el celular debe tener 9 dígitos empezando por 9.BeginTransactionAsync):
- Calcula el
Totalsumandocantidades[i] * precios[i]para todos los ítems. - Crea y persiste el registro
VentaconFechaVenta = DateTime.Now. - Para cada ítem del carrito:
- Busca el
ProductoconFindAsync. - Verifica que
producto.Stock >= cantidades[i]. - Descuenta el stock:
producto.Stock = Math.Max(0, producto.Stock - cant). - Crea el registro
DetalleVentaasociado a la venta.
- Busca el
- Llama a
SaveChangesAsyncyCommitAsync.
RedirectToAction("Historial") en éxito · View() en error (con el estado del carrito restaurado en ViewBag.RestoredCart).
GET /Venta/Historial
Devuelve el historial completo de ventas ordenado por fecha descendente. Autorización:[Authorize] (cualquier usuario autenticado).
Comportamiento:
- Consulta
_context.Ventascon.Include(v => v.DetallesVentas).ThenInclude(d => d.Producto)para cargar la navegación completa. - Ordena por
FechaVentadescendente (OrderByDescending). - En caso de excepción, establece
TempData["Error"]y redirige aHome/Index.
View(List<Venta>).
GET /Venta/Editar/
Muestra el formulario de edición para una venta existente. Autorización:[Authorize] (cualquier usuario autenticado).
Identificador de la venta (
IdVenta).- Carga la venta con
Include(v => v.DetallesVentas).ThenInclude(d => d.Producto). - Si no existe, establece
TempData["Error"]y redirige aHistorial. - Inyecta en
ViewBag.Productosla lista completa de productos (para dropdowns en la vista).
View(Venta) · RedirectToAction("Historial") si no se encuentra.
POST /Venta/Editar
Actualiza los datos de cabecera de una venta. No modifica los DetalleVenta ni el stock. Autorización:[Authorize] (cualquier usuario autenticado). Incluye [ValidateAntiForgeryToken].
Identificador de la venta. Debe coincidir con
venta.IdVenta; de lo contrario se devuelve error.Objeto
Venta con los datos actualizados desde el formulario.| Campo | Descripción |
|---|---|
Cliente | Nombre o razón social del cliente. |
TipoComprobante | BOLETA o FACTURA. |
Total | Monto total de la venta. |
Solo se actualizan
Cliente, TipoComprobante y Total. El resto de campos (FechaVenta, Estado, Ruc, Celular, ModificadoPor) no se modifican en esta acción.RedirectToAction("Historial") en éxito · View(Venta) en error.
GET /Venta/Eliminar/
Anula una venta (soft-delete) y restaura el stock de los productos involucrados. Autorización:[Authorize] (cualquier usuario autenticado).
Identificador de la venta (
IdVenta).- Carga la venta con
Include(v => v.DetallesVentas). - Si no existe, establece
TempData["Error"]y redirige aHistorial. - Para cada
DetalleVenta, sumadetalle.Cantidadde vuelta alStockdel producto correspondiente. - Establece
venta.Estado = EstadoVenta.Anulada. - Registra el usuario responsable en
venta.ModificadoPor = User.Identity.Name. - Persiste todos los cambios en una sola llamada a
SaveChangesAsync.
La anulación es un soft-delete: el registro
Venta y sus DetallesVentas se conservan en la base de datos con Estado = Anulada. El registro no se elimina físicamente.RedirectToAction("Historial") en todos los casos (anulado o error).