Skip to main content

Reportes de Ventas

El módulo de reportes de ventas permite analizar el desempeño comercial con múltiples formatos de exportación y agrupaciones.

Tipos de Reportes Disponibles

Registro de Ventas

Reporte general de todas las ventas del periodo con filtros por mes/año

Ventas por Producto

Agrupación de ventas por producto con cantidades y totales

Reporte de Ganancias

Análisis de rentabilidad comparando precio de venta vs costo

Registro RVTA

Formato SUNAT para declaraciones (PLE 14.1)

Generar Reporte de Ventas

1

Acceder al módulo

Navega a Facturación → Ventas y haz clic en el botón Exportar o Reportes.
2

Seleccionar periodo

// Filtros disponibles
{
  mes: '01-12',      // Mes del reporte
  anio: '2024',      // Año del reporte
  formato: 'excel'   // excel, pdf, txt, rvta
}
Elige el mes y año que deseas analizar. Por defecto se usa el mes actual.
3

Elegir formato

  • Excel (.xlsx): Hoja de cálculo con formato y totales
  • PDF: Documento imprimible con diseño profesional
  • TXT: Formato PLE 14.1 para SUNAT (35 campos pipe-separated)
  • RVTA: Registro de Ventas e Ingresos en Excel formato SUNAT

Formatos de Exportación

Excel - Registro Simple

Endpoint: POST /api/ventas/export/excel Columnas del reporte:
ColumnaDescripciónFormato
DocumentoTipo + Serie-NúmeroFAC F001-00000123
FechaFecha de emisióndd/mm/yyyy
ClienteNombre o razón socialTexto
RUC/DNIDocumento del cliente11 u 8 dígitos
SubtotalBase imponible0.00
IGVImpuesto (18%)0.00
TotalMonto total0.00
MonedaPEN o USDTexto
EstadoACTIVA/ANULADATexto
SUNATEstado envíoENVIADO/PENDIENTE
Características:
  • Encabezado con título y fecha de generación
  • Filas alternadas con color gris claro (#F9FAFB)
  • Total general al final
  • Formato numérico: #,##0.00
  • Excluye documentos anulados del total
// VentaExportController.php:187-312
public function exportarExcel(Request $request)
{
    [$user, $ventas, $mes, $anio] = $this->getVentasPeriodo($request);
    
    $spreadsheet = new Spreadsheet();
    $sheet = $spreadsheet->getActiveSheet();
    
    // Título con formato
    $sheet->setCellValue('A1', "REGISTRO DE VENTAS - {$meses[(int)$mes]} {$anio}");
    $sheet->getStyle('A1')->applyFromArray([
        'font' => ['bold' => true, 'size' => 13],
        'fill' => ['fillType' => Fill::FILL_SOLID, 'startColor' => ['rgb' => 'F3F4F6']]
    ]);
    
    // ... genera filas y totales
}

TXT - Formato PLE 14.1 (SUNAT)

Endpoint: POST /api/ventas/export/txt Nombre del archivo: LE{RUC}{PERIODO}140100{IND}111.TXT Ejemplo: LE20612706702202401001401001111.TXT Estructura de 35 campos:
  1. Periodo: YYYYMM00 (ej: 20240100)
  2. CUO: Código Único de Operación (M000000001)
  3. Correlativo: M-1
  4. Fecha Emisión: dd/mm/yyyy
  5. Fecha Vencimiento: dd/mm/yyyy (opcional)
  6. Tipo Comprobante: 01 (Factura), 03 (Boleta)
  7. Serie: F001, B001
  8. Número: 00000123
  9. Número Final: Vacío (para consolidados)
  10. Tipo Doc Identidad: 1 (DNI), 6 (RUC), 0 (Otros)
  11. Número Doc Identidad: RUC/DNI del cliente
  12. Razón Social: Nombre del cliente
  13. Exportación: 0.00 (no aplica)
  14. Base Imponible: Subtotal gravado
  15. Descuento Base: 0.00
  16. IGV: 18% de la base
  17. Descuento IGV: 0.00
  18. Exonerado: Monto exonerado
  19. Inafecto: Monto inafecto
  20. ISC: 0.00 21-35. Otros tributos y referencias: Campos adicionales SUNAT
// VentaExportController.php:86-182
public function exportarTxt(Request $request)
{
    $ruc = $empresa->ruc ?? '00000000000';
    $periodo = $anio . str_pad($mes, 2, '0', STR_PAD_LEFT) . '00';
    
    foreach ($ventas as $venta) {
        $campos = [
            $periodo,
            'M' . str_pad($correlativo, 9, '0', STR_PAD_LEFT),
            'M-1',
            $venta->fecha_emision->format('d/m/Y'),
            // ... 31 campos más
        ];
        
        $lines[] = implode('|', $campos) . '|';
    }
    
    $filename = "LE{$ruc}{$periodo}140100{$indicador}111.TXT";
}

RVTA - Registro de Ventas e Ingresos

Endpoint: POST /api/ventas/export/rvta Formato: Excel con estructura SUNAT completa Columnas:
  • CUO (Código Único de Operación)
  • Fecha Emisión
  • Tipo Doc (código SUNAT)
  • Serie / Número
  • Tipo Doc Cliente / Nro Doc / Razón Social
  • Base Imponible / IGV / Exonerado / Inafecto
  • ISC / ICBPER / Otros / Total
  • Moneda / Estado
Características:
  • Título con periodo, RUC y razón social
  • Formato profesional con colores corporativos
  • Totales de Base, IGV y Total General
  • Filas alternadas para mejor lectura
  • Ancho de columnas predefinido para impresión
// VentaExportController.php:317-472
public function reporteRVTA(Request $request)
{
    $sheet->setCellValue('A1', "REGISTRO DE VENTAS E INGRESOS");
    $sheet->setCellValue('A2', "PERIODO: {$meses[(int)$mes]} {$anio} | RUC: {$ruc}");
    
    // 18 columnas con formato SUNAT
    $headers = ['CUO', 'Fecha Emisión', 'Tipo Doc', 'Serie', 'Número', ...];
    
    $filename = "RVTA-{$periodo}.xlsx";
}

Reporte de Ventas por Producto

Endpoint: POST /api/ventas/export/ventas-producto Agrupa todas las ventas del periodo por producto, sumando cantidades y montos. Columnas:
  • Código del producto
  • Nombre del producto
  • Unidad de medida
  • Cantidad vendida (suma)
  • Número de ventas
  • Subtotal / IGV / Total
Ordenamiento: Por total vendido (descendente)
Solo incluye ventas en estado ACTIVA. Las ventas anuladas se excluyen automáticamente.
// VentaExportController.php:477-611
public function reporteVentasProducto(Request $request)
{
    // Agrupar productos vendidos
    $productos = [];
    foreach ($ventas as $v) {
        if (in_array($v->estado, ['2', 'A'])) continue;
        
        foreach ($v->productosVentas as $pv) {
            $key = $pv->id_producto ?? $pv->codigo_producto;
            if (!isset($productos[$key])) {
                $productos[$key] = [
                    'codigo' => $pv->codigo_producto,
                    'nombre' => $pv->descripcion,
                    'cantidad' => 0,
                    'total' => 0,
                    'ventas_count' => 0
                ];
            }
            $productos[$key]['cantidad'] += $pv->cantidad;
            $productos[$key]['total'] += $pv->total;
        }
    }
    
    // Ordenar por total descendente
    usort($productos, fn($a, $b) => $b['total'] <=> $a['total']);
}

Reporte de Ganancias

Endpoint: POST /api/ventas/export/ganancias Analiza la rentabilidad de cada producto vendido comparando el precio de venta con el costo registrado. Columnas:
  • Documento de venta
  • Fecha / Cliente
  • Producto
  • Cantidad
  • Precio Venta / Costo / Total Venta
  • Ganancia (Total - Costo × Cantidad)
Características:
  • Color verde para ganancias positivas (#059669)
  • Color rojo para pérdidas (#DC2626)
  • Total de venta, costo total y ganancia total
  • Cálculo de % margen: (Ganancia / Total Venta) × 100
// VentaExportController.php:616-752
public function reporteGanancias(Request $request)
{
    foreach ($ventas as $v) {
        foreach ($v->productosVentas as $pv) {
            $costo = $pv->producto->costo ?? 0;
            $costoTotal = $costo * $pv->cantidad;
            $ganancia = $pv->total - $costoTotal;
            
            // Color según ganancia
            $colorGanancia = $ganancia >= 0 ? '059669' : 'DC2626';
            $sheet->getStyle("I{$row}")->applyFromArray([
                'font' => ['bold' => true, 'color' => ['rgb' => $colorGanancia]]
            ]);
        }
    }
    
    // Cálculo de margen
    $margen = ($totalGanancia / $totalVenta) * 100;
}
Producto: Laptop HP
  • Cantidad vendida: 5 unidades
  • Precio de venta unitario: S/ 2,500.00
  • Costo unitario: S/ 1,800.00
  • Total venta: S/ 12,500.00
  • Costo total: S/ 9,000.00
  • Ganancia: S/ 3,500.00
  • Margen: 28%

PDF - Reporte Imprimible

Endpoint: POST /api/ventas/export/pdf Genera un PDF con formato landscape (horizontal) usando mPDF. Configuración:
$mpdf = new Mpdf([
    'mode' => 'utf-8',
    'format' => 'A4-L',  // Landscape
    'tempDir' => storage_path('app/mpdf'),
    'margin_left' => 10,
    'margin_right' => 10
]);
Vista Blade: resources/views/reportes/ventas-lista.blade.php

Filtros y Opciones

Filtros por Periodo

// Mes y año actual por defecto
const [filters, setFilters] = useState({
  mes: new Date().getMonth() + 1,
  anio: new Date().getFullYear()
});

// Solicitar reporte
const handleExport = async (formato) => {
  await fetch(`/api/ventas/export/${formato}`, {
    method: 'POST',
    body: JSON.stringify(filters)
  });
};

Excluir Documentos Anulados

Todos los reportes excluyen automáticamente:
  • Ventas con estado = '2' (anuladas)
  • Ventas con estado = 'A' (anuladas alternativo)
Para el formato TXT/RVTA, los documentos anulados se incluyen con montos en 0.00 y estado “2” (Anulado).

Solución de Problemas

Causa: Formato incorrecto o RUC inválido.Solución:
  1. Verifica que el RUC de la empresa esté configurado correctamente
  2. Revisa que el periodo tenga formato YYYYMM00 (ej: 20240100)
  3. Asegúrate de usar el código SUNAT correcto para cada tipo de documento:
    • 01 = Factura
    • 03 = Boleta
  4. El archivo debe tener exactamente 35 campos por línea
Causa: Solo incluye facturas y boletas (códigos 01 y 03).Solución: Las notas de venta y otros documentos no fiscales no aparecen en RVTA. Para reportes completos, usa el formato Excel simple.
Causa: El costo del producto no está registrado o es mayor al precio de venta.Solución:
  1. Ve a Almacén → Productos
  2. Edita cada producto y verifica el campo Costo
  3. Asegúrate de que el costo sea menor al precio de venta
Causa: No hay ventas en el periodo seleccionado.Solución: Verifica que:
  • El mes y año sean correctos
  • Existan ventas con estado = '1' (activas)
  • La empresa del usuario coincida con las ventas

Próximos Pasos

Reportes de Compras

Analiza tus gastos y proveedores

Exportar a Contabilidad

Formatos para sistemas contables

Reportes Financieros

Caja, bancos y utilidades

Reportes de Inventario

Stock, kardex y movimientos

Build docs developers (and LLMs) love