feat(reportes): Permite consulta consolidada en Detalle de Distribución
All checks were successful
Optimized Build and Deploy / remote-build-and-deploy (push) Successful in 2m34s

Implementa la funcionalidad para generar el reporte "Detalle de Distribución de Canillas" de forma consolidada para todas las empresas, separando entre Canillitas y Accionistas. Adicionalmente, se realizan correcciones y mejoras visuales en otros reportes.

### Cambios Principales

-   **Frontend (`ReporteDetalleDistribucionCanillasPage`):**
    -   Se añade la opción "TODAS" al selector de Empresas.
    -   Al seleccionar "TODAS", se muestra un nuevo control para elegir entre "Canillitas" o "Accionistas".
    -   La vista del reporte se simplifica en el modo "TODAS", mostrando solo la tabla correspondiente y ocultando el resumen por tipo de vendedor.

-   **Backend (`ReportesService`, `ReportesRepository`):**
    -   Se modifica el servicio para recibir el parámetro `esAccionista`.
    -   Se implementa una nueva lógica que, si `idEmpresa` es 0, llama a los nuevos procedimientos almacenados que consultan todas las empresas.
    -   Se ajusta el `ReportesController` para aceptar y pasar el nuevo parámetro.

### Correcciones

-   **Base de Datos:**
    -   Se añade la función SQL `FN_ObtenerPrecioVigente` para los nuevos Stored Procedures.
    -   Se crean los Stored Procedures `SP_DistCanillasEntradaSalidaPubli_AllEmpresas` y `SP_DistCanillasAccEntradaSalidaPubli_AllEmpresas`.
-   **Backend (`ReportesController`):**
    -   Se corrigen errores de compilación (`CS7036`, `CS8130`) añadiendo el parámetro `esAccionista` faltante en las llamadas al servicio `ObtenerReporteDistribucionCanillasAsync`.

### Mejoras Visuales

-   **PDF (`ControlDevolucionesDocument.cs`):**
    -   Se ajustan los espaciados verticales (`Padding` y `Spacing`) en la plantilla QuestPDF del reporte "Control de Devoluciones" para lograr un diseño más compacto.
This commit is contained in:
2025-11-04 11:51:43 -03:00
parent e123dae182
commit 2c584e9383
10 changed files with 282 additions and 149 deletions

View File

@@ -8,6 +8,7 @@ import reportesService from '../../services/Reportes/reportesService';
import type { ReporteDistribucionCanillasResponseDto } from '../../models/dtos/Reportes/ReporteDistribucionCanillasResponseDto';
import SeleccionaReporteDetalleDistribucionCanillas from './SeleccionaReporteDetalleDistribucionCanillas';
import * as XLSX from 'xlsx';
import { usePermissions } from '../../hooks/usePermissions';
import axios from 'axios';
// Para el tipo del footer en DataGridSectionProps
@@ -81,9 +82,12 @@ const ReporteDetalleDistribucionCanillasPage: React.FC = () => {
const [currentParams, setCurrentParams] = useState<{
fecha: string;
idEmpresa: number;
esAccionista: boolean;
nombreEmpresa?: string;
} | null>(null);
const [pdfSoloTotales, setPdfSoloTotales] = useState(false);
const { tienePermiso, isSuperAdmin } = usePermissions();
const puedeVerReporte = isSuperAdmin || tienePermiso("MC005");
const initialTotals: TotalesComunes = { totalCantSalida: 0, totalCantEntrada: 0, vendidos: 0, totalRendir: 0 };
const [totalesCanillas, setTotalesCanillas] = useState<TotalesComunes>(initialTotals);
@@ -115,16 +119,29 @@ const ReporteDetalleDistribucionCanillasPage: React.FC = () => {
const handleGenerarReporte = useCallback(async (params: {
fecha: string;
idEmpresa: number;
esAccionista: boolean;
}) => {
if (!puedeVerReporte) {
setError("No tiene permiso para generar este reporte.");
setLoading(false);
return;
}
setLoading(true);
setError(null);
setApiErrorParams(null);
const empresaService = (await import('../../services/Distribucion/empresaService')).default;
const empData = await empresaService.getEmpresaById(params.idEmpresa);
setCurrentParams({ ...params, nombreEmpresa: empData?.nombre });
setReportData(null);
// Resetear totales
let nombreEmpresa = `Empresa ID ${params.idEmpresa}`;
if (params.idEmpresa !== 0) {
const empresaService = (await import('../../services/Distribucion/empresaService')).default;
const empData = await empresaService.getEmpresaById(params.idEmpresa);
nombreEmpresa = empData?.nombre ?? nombreEmpresa;
} else {
nombreEmpresa = "TODAS";
}
setCurrentParams({ ...params, nombreEmpresa });
setReportData(null);
setTotalesCanillas(initialTotals);
setTotalesAccionistas(initialTotals);
setTotalesCanillasOtraFecha(initialTotals);
@@ -140,7 +157,7 @@ const ReporteDetalleDistribucionCanillasPage: React.FC = () => {
const processedData = {
canillas: addIds(data.canillas, 'can'),
canillasAccionistas: addIds(data.canillasAccionistas, 'acc'),
canillasTodos: addIds(data.canillasTodos, 'all'), // Aún necesita IDs para DataGridSection
canillasTodos: addIds(data.canillasTodos, 'all'),
canillasLiquidadasOtraFecha: addIds(data.canillasLiquidadasOtraFecha, 'canliq'),
canillasAccionistasLiquidadasOtraFecha: addIds(data.canillasAccionistasLiquidadasOtraFecha, 'accliq'),
controlDevolucionesDetalle: addIds(data.controlDevolucionesDetalle, 'cdd'),
@@ -167,7 +184,7 @@ const ReporteDetalleDistribucionCanillasPage: React.FC = () => {
} finally {
setLoading(false);
}
}, []);
}, [puedeVerReporte]);
const handleVolverAParametros = useCallback(() => {
setShowParamSelector(true);
@@ -188,10 +205,9 @@ const ReporteDetalleDistribucionCanillasPage: React.FC = () => {
if (data && data.length > 0) {
const exportedData = data.map(item => {
const row: Record<string, any> = {};
// Excluir el 'id' generado para DataGrid si existe
const { id, ...itemData } = item;
Object.keys(fields).forEach(key => {
row[fields[key]] = (itemData as any)[key]; // Usar itemData
row[fields[key]] = (itemData as any)[key];
if (key === 'fecha' && (itemData as any)[key]) {
row[fields[key]] = new Date((itemData as any)[key]).toLocaleDateString('es-AR', { timeZone: 'UTC' });
}
@@ -215,18 +231,18 @@ const ReporteDetalleDistribucionCanillasPage: React.FC = () => {
}
};
// Definición de campos para la exportación
const fieldsCanillaAccionista = { publicacion: "Publicación", canilla: "Canilla", totalCantSalida: "Llevados", totalCantEntrada: "Devueltos", vendidos: "Vendidos", totalRendir: "A Rendir" };
const fieldsCanillaAccionistaFechaLiq = { publicacion: "Publicación", canilla: "Canilla", fecha: "Fecha Mov.", totalCantSalida: "Llevados", totalCantEntrada: "Devueltos", vendidos: "Vendidos", totalRendir: "A Rendir" };
const fieldsTodos = { publicacion: "Publicación", tipoVendedor: "Tipo", totalCantSalida: "Llevados", totalCantEntrada: "Devueltos", vendidos: "Vendidos", totalRendir: "A Rendir" };
formatAndSheet(reportData.canillas, "Canillitas_Dia", fieldsCanillaAccionista);
formatAndSheet(reportData.canillasAccionistas, "Accionistas_Dia", fieldsCanillaAccionista);
formatAndSheet(reportData.canillasTodos, "Resumen_Dia", fieldsTodos);
if (currentParams?.idEmpresa !== 0) {
formatAndSheet(reportData.canillasTodos, "Resumen_Dia", fieldsTodos);
}
formatAndSheet(reportData.canillasLiquidadasOtraFecha, "Canillitas_OtrasFechas", fieldsCanillaAccionistaFechaLiq);
formatAndSheet(reportData.canillasAccionistasLiquidadasOtraFecha, "Accionistas_OtrasFechas", fieldsCanillaAccionistaFechaLiq);
let fileName = "ReporteDetalleDistribucionCanillitas";
if (currentParams) {
fileName += `_${currentParams.nombreEmpresa?.replace(/\s+/g, '') ?? `Emp${currentParams.idEmpresa}`}`;
@@ -265,8 +281,6 @@ const ReporteDetalleDistribucionCanillasPage: React.FC = () => {
}
}, [currentParams]);
// --- Definiciones de Columnas ---
const commonColumns: GridColDef[] = [
{ field: 'publicacion', headerName: 'Publicación', width: 200, flex: 1.2 },
{ field: 'canilla', headerName: 'Canillita', width: 220, flex: 1.3 },
@@ -295,8 +309,7 @@ const ReporteDetalleDistribucionCanillasPage: React.FC = () => {
{ field: 'totalRendir', headerName: 'A Rendir', type: 'number', width: 150, align: 'right', headerAlign: 'right', valueFormatter: (value) => currencyFormatter(Number(value)) },
];
// --- Custom Footers ---
const createCustomFooterComponent = (totals: TotalesComunes, columnsDef: GridColDef[]): CustomFooterType => { // Especificar el tipo de retorno
const createCustomFooterComponent = (totals: TotalesComunes, columnsDef: GridColDef[]): CustomFooterType => {
const getCellStyle = (colConfig: GridColDef | undefined, isPlaceholder: boolean = false) => {
if (!colConfig) return { width: 100, textAlign: 'right' as const, pr: isPlaceholder ? 0 : 1, fontWeight: 'bold' };
const defaultWidth = colConfig.field === 'publicacion' ? 200 : (colConfig.field === 'canilla' || colConfig.field === 'tipoVendedor' ? 150 : 100);
@@ -310,10 +323,9 @@ const ReporteDetalleDistribucionCanillasPage: React.FC = () => {
};
};
// eslint-disable-next-line react/display-name
const FooterComponent: CustomFooterType = (props) => ( // El componente debe aceptar props
<GridFooterContainer {...props} sx={{ // Pasar props y combinar sx
...(props.sx as any), // Castear props.sx temporalmente si es necesario
const FooterComponent: CustomFooterType = (props) => (
<GridFooterContainer {...props} sx={{
...(props.sx as any),
justifyContent: 'space-between', alignItems: 'center', width: '100%',
borderTop: (theme) => `1px solid ${theme.palette.divider}`, minHeight: '52px',
}}>
@@ -339,6 +351,7 @@ const ReporteDetalleDistribucionCanillasPage: React.FC = () => {
return FooterComponent;
};
// Usar los componentes creados con useMemo
const FooterCanillas = useMemo(() => createCustomFooterComponent(totalesCanillas, commonColumns), [totalesCanillas]);
const FooterAccionistas = useMemo(() => createCustomFooterComponent(totalesAccionistas, commonColumns), [totalesAccionistas]);
const FooterCanillasOtraFecha = useMemo(() => createCustomFooterComponent(totalesCanillasOtraFecha, commonColumnsWithFecha), [totalesCanillasOtraFecha]);
@@ -346,12 +359,16 @@ const ReporteDetalleDistribucionCanillasPage: React.FC = () => {
const FooterResumen = useMemo(() => createCustomFooterComponent(totalesResumen, columnsTodos), [totalesResumen, columnsTodos]);
if (showParamSelector) {
if (!loading && !puedeVerReporte) {
return <Alert severity="error" sx={{ m: 2 }}>No tiene permiso para acceder a este reporte.</Alert>;
}
return (
<Box sx={{ p: 2, display: 'flex', justifyContent: 'center', mt: 2 }}>
<Paper sx={{ width: '100%', maxWidth: 600 }} elevation={3}>
<SeleccionaReporteDetalleDistribucionCanillas
onGenerarReporte={handleGenerarReporte}
onCancel={handleVolverAParametros} // Aunque el componente no lo use directamente.
onCancel={handleVolverAParametros}
isLoading={loading}
apiErrorMessage={apiErrorParams}
/>
@@ -360,17 +377,45 @@ const ReporteDetalleDistribucionCanillasPage: React.FC = () => {
);
}
const renderContent = () => {
if (loading) return <Box sx={{ display: 'flex', justifyContent: 'center', my: 2 }}><CircularProgress /></Box>;
if (error && !loading) return <Alert severity="info" sx={{ my: 2 }}>{error}</Alert>;
if (!reportData) return <Typography sx={{ mt: 2, fontStyle: 'italic' }}>No se encontraron datos.</Typography>;
if (currentParams?.idEmpresa === 0) {
if (currentParams.esAccionista) {
return <DataGridSection title="Accionistas (Todas las Empresas)" data={reportData.canillasAccionistas || []} columns={commonColumns} footerComponent={FooterAccionistas} />;
}
return <DataGridSection title="Canillitas (Todas las Empresas)" data={reportData.canillas || []} columns={commonColumns} footerComponent={FooterCanillas} />;
}
return (
<>
<DataGridSection title="Canillitas" data={reportData.canillas || []} columns={commonColumns} footerComponent={FooterCanillas} />
<DataGridSection title="Accionistas" data={reportData.canillasAccionistas || []} columns={commonColumns} footerComponent={FooterAccionistas} />
<DataGridSection title="Resumen por Tipo de Vendedor" data={reportData.canillasTodos || []} columns={columnsTodos} footerComponent={FooterResumen} />
{reportData.canillasLiquidadasOtraFecha && reportData.canillasLiquidadasOtraFecha.length > 0 &&
<DataGridSection title="Canillitas (Liquidados de Otras Fechas)" data={reportData.canillasLiquidadasOtraFecha} columns={commonColumnsWithFecha} footerComponent={FooterCanillasOtraFecha} />}
{reportData.canillasAccionistasLiquidadasOtraFecha && reportData.canillasAccionistasLiquidadasOtraFecha.length > 0 &&
<DataGridSection title="Accionistas (Liquidados de Otras Fechas)" data={reportData.canillasAccionistasLiquidadasOtraFecha} columns={commonColumnsWithFecha} footerComponent={FooterAccionistasOtraFecha} />}
</>
);
};
return (
<Box sx={{ p: 2 }}>
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2, flexWrap: 'wrap', gap: 1 }}>
<Typography variant="h5">Reporte: Detalle Distribución Canillitas ({currentParams?.nombreEmpresa}) - {currentParams?.fecha ? new Date(currentParams.fecha + 'T00:00:00').toLocaleDateString('es-AR', { timeZone: 'UTC' }) : ''}</Typography>
<Typography variant="h5">Reporte: Detalle Distribución ({currentParams?.nombreEmpresa}) - {currentParams?.fecha ? new Date(currentParams.fecha + 'T00:00:00').toLocaleDateString('es-AR', { timeZone: 'UTC' }) : ''}</Typography>
<Box sx={{ display: 'flex', gap: 1, flexWrap: 'wrap' }}>
{currentParams?.idEmpresa !== 0 && (
<Button onClick={() => handleGenerarYAbrirPdf(true)} variant="contained" color="secondary" disabled={loadingPdf || !reportData || !!error} size="small">
{loadingPdf && pdfSoloTotales ? <CircularProgress size={20} color="inherit" /> : "PDF Totales"}
</Button>
)}
<Button onClick={() => handleGenerarYAbrirPdf(false)} variant="contained" disabled={loadingPdf || !reportData || !!error} size="small">
{loadingPdf && !pdfSoloTotales ? <CircularProgress size={20} color="inherit" /> : "PDF Detalle"}
</Button>
<Button onClick={() => handleGenerarYAbrirPdf(true)} variant="contained" color="secondary" disabled={loadingPdf || !reportData || !!error} size="small">
{loadingPdf && pdfSoloTotales ? <CircularProgress size={20} color="inherit" /> : "PDF Totales"}
</Button>
<Button onClick={handleExportToExcel} variant="outlined" disabled={!reportData || !!error} size="small">
Exportar a Excel
</Button>
@@ -379,34 +424,7 @@ const ReporteDetalleDistribucionCanillasPage: React.FC = () => {
</Button>
</Box>
</Box>
{loading && <Box sx={{ textAlign: 'center', my: 2 }}><CircularProgress /></Box>}
{error && !loading && <Alert severity="info" sx={{ my: 2 }}>{error}</Alert>}
{!loading && !error && reportData && (
<>
<DataGridSection title="Canillitas" data={reportData.canillas || []} columns={commonColumns} footerComponent={FooterCanillas} />
<DataGridSection title="Accionistas" data={reportData.canillasAccionistas || []} columns={commonColumns} footerComponent={FooterAccionistas} />
<DataGridSection
title="Resumen por Tipo de Vendedor"
data={reportData.canillasTodos || []}
columns={columnsTodos}
footerComponent={FooterResumen} // <-- PASAR EL FOOTER
height={220} // El height ya no es necesario si autoHeight está activado por tener footer
/>
{reportData.canillasLiquidadasOtraFecha && reportData.canillasLiquidadasOtraFecha.length > 0 &&
<DataGridSection title="Canillitas (Liquidados de Otras Fechas)" data={reportData.canillasLiquidadasOtraFecha} columns={commonColumnsWithFecha} footerComponent={FooterCanillasOtraFecha} />}
{reportData.canillasAccionistasLiquidadasOtraFecha && reportData.canillasAccionistasLiquidadasOtraFecha.length > 0 &&
<DataGridSection title="Accionistas (Liquidados de Otras Fechas)" data={reportData.canillasAccionistasLiquidadasOtraFecha} columns={commonColumnsWithFecha} footerComponent={FooterAccionistasOtraFecha} />}
</>
)}
{!loading && !error && reportData &&
Object.values(reportData).every(arr => !arr || arr.length === 0) &&
<Typography sx={{ mt: 2, fontStyle: 'italic' }}>No se encontraron datos para los criterios seleccionados.</Typography>
}
{renderContent()}
</Box>
);
};

View File

@@ -1,16 +1,16 @@
import React, { useState, useEffect } from 'react';
import {
Box, Typography, TextField, Button, CircularProgress, Alert,
FormControl, InputLabel, Select, MenuItem
FormControl, InputLabel, Select, MenuItem, ToggleButtonGroup, ToggleButton
} from '@mui/material';
import type { EmpresaDto } from '../../models/dtos/Distribucion/EmpresaDto';
import type { EmpresaDropdownDto } from '../../models/dtos/Distribucion/EmpresaDropdownDto';
import empresaService from '../../services/Distribucion/empresaService';
interface SeleccionaReporteDetalleDistribucionCanillasProps {
onGenerarReporte: (params: {
fecha: string;
idEmpresa: number;
// soloTotales: boolean; // Podríamos añadirlo si el usuario elige la versión del PDF
esAccionista: boolean; // Añadimos este parámetro
}) => Promise<void>;
onCancel: () => void;
isLoading?: boolean;
@@ -24,9 +24,9 @@ const SeleccionaReporteDetalleDistribucionCanillas: React.FC<SeleccionaReporteDe
}) => {
const [fecha, setFecha] = useState<string>(new Date().toISOString().split('T')[0]);
const [idEmpresa, setIdEmpresa] = useState<number | string>('');
// const [soloTotales, setSoloTotales] = useState<boolean>(false); // Si se añade la opción
const [esAccionista, setEsAccionista] = useState<boolean>(false); // Nuevo estado
const [empresas, setEmpresas] = useState<EmpresaDto[]>([]);
const [empresas, setEmpresas] = useState<EmpresaDropdownDto[]>([]);
const [loadingDropdowns, setLoadingDropdowns] = useState(false);
const [localErrors, setLocalErrors] = useState<{ [key: string]: string | null }>({});
@@ -34,8 +34,9 @@ const SeleccionaReporteDetalleDistribucionCanillas: React.FC<SeleccionaReporteDe
const fetchEmpresas = async () => {
setLoadingDropdowns(true);
try {
const data = await empresaService.getAllEmpresas(); // Asume que este servicio existe
setEmpresas(data);
const data = await empresaService.getEmpresasDropdown();
// Añadimos la opción "TODAS" al principio
setEmpresas([{ idEmpresa: 0, nombre: 'TODAS' }, ...data]);
} catch (error) {
console.error("Error al cargar empresas:", error);
setLocalErrors(prev => ({ ...prev, dropdowns: 'Error al cargar empresas.' }));
@@ -49,7 +50,8 @@ const SeleccionaReporteDetalleDistribucionCanillas: React.FC<SeleccionaReporteDe
const validate = (): boolean => {
const errors: { [key: string]: string | null } = {};
if (!fecha) errors.fecha = 'La fecha es obligatoria.';
if (!idEmpresa) errors.idEmpresa = 'Debe seleccionar una empresa.';
// El idEmpresa ya no puede estar vacío, porque se preselecciona "TODAS" o una empresa
if (idEmpresa === '') errors.idEmpresa = 'Debe seleccionar una empresa.';
setLocalErrors(errors);
return Object.keys(errors).length === 0;
};
@@ -59,14 +61,14 @@ const SeleccionaReporteDetalleDistribucionCanillas: React.FC<SeleccionaReporteDe
onGenerarReporte({
fecha,
idEmpresa: Number(idEmpresa),
// soloTotales // Si se añade la opción
esAccionista // Pasamos el nuevo parámetro
});
};
return (
<Box sx={{ p: 2, border: '1px solid #ccc', borderRadius: '4px', minWidth: 380 }}>
<Box sx={{ p: 2, border: '1px solid #ccc', borderRadius: '4px', minWidth: 420 }}>
<Typography variant="h6" gutterBottom>
Parámetros: Detalle Distribución Canillitas
Parámetros: Detalle Distribución Canillas
</Typography>
<TextField
label="Fecha"
@@ -89,26 +91,32 @@ const SeleccionaReporteDetalleDistribucionCanillas: React.FC<SeleccionaReporteDe
value={idEmpresa}
onChange={(e) => { setIdEmpresa(e.target.value as number); setLocalErrors(p => ({ ...p, idEmpresa: null })); }}
>
<MenuItem value="" disabled><em>Seleccione una empresa</em></MenuItem>
{empresas.map((e) => (
<MenuItem key={e.idEmpresa} value={e.idEmpresa}>{e.nombre}</MenuItem>
))}
</Select>
{localErrors.idEmpresa && <Typography color="error" variant="caption" sx={{ml:1.5}}>{localErrors.idEmpresa}</Typography>}
</FormControl>
{/*
<FormControlLabel
control={
<Checkbox
checked={soloTotales}
onChange={(e) => setSoloTotales(e.target.checked)}
{/* Selector condicional para Canillitas/Accionistas */}
{idEmpresa === 0 && (
<Box sx={{ mt: 2, display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
<Typography variant="subtitle2" sx={{ mb: 1, fontWeight: 'medium' }}>
Mostrar para todas las empresas
</Typography>
<ToggleButtonGroup
value={esAccionista ? 'accionistas' : 'canillitas'}
exclusive
onChange={(_, value) => { if (value !== null) setEsAccionista(value === 'accionistas'); }}
aria-label="Tipo de Vendedor"
disabled={isLoading}
/>
}
label="Generar solo resumen de totales (PDF)"
sx={{ mt: 1, mb: 1 }}
/>
*/}
color="primary"
>
<ToggleButton value="canillitas">Canillitas</ToggleButton>
<ToggleButton value="accionistas">Accionistas</ToggleButton>
</ToggleButtonGroup>
</Box>
)}
{apiErrorMessage && <Alert severity="error" sx={{ mt: 2 }}>{apiErrorMessage}</Alert>}
{localErrors.dropdowns && <Alert severity="warning" sx={{ mt: 1 }}>{localErrors.dropdowns}</Alert>}

View File

@@ -20,6 +20,7 @@ import type { NovedadesCanillasReporteDto } from '../../models/dtos/Reportes/Nov
import type { CanillaGananciaReporteDto } from '../../models/dtos/Reportes/CanillaGananciaReporteDto';
import type { ListadoDistCanMensualDiariosDto } from '../../models/dtos/Reportes/ListadoDistCanMensualDiariosDto';
import type { ListadoDistCanMensualPubDto } from '../../models/dtos/Reportes/ListadoDistCanMensualPubDto';
import axios from 'axios';
interface GetExistenciaPapelParams {
fechaDesde: string; // yyyy-MM-dd
@@ -209,24 +210,43 @@ const getVentaMensualSecretariaTirDevoPdf = async (params: { fechaDesde: string;
return response.data;
};
const getReporteDistribucionCanillas = async (params: {
fecha: string;
idEmpresa: number;
const getReporteDistribucionCanillas = async (params: {
fecha: string;
idEmpresa: number;
esAccionista?: boolean; // Hacerlo opcional
}): Promise<ReporteDistribucionCanillasResponseDto> => {
const response = await apiClient.get<ReporteDistribucionCanillasResponseDto>('/reportes/distribucion-canillas', { params });
return response.data;
try {
const response = await apiClient.get<ReporteDistribucionCanillasResponseDto>('/reportes/distribucion-canillas', { params });
return response.data;
} catch (error) {
console.error('Error al obtener datos del reporte de distribución de canillas:', error);
throw error;
}
};
const getReporteDistribucionCanillasPdf = async (params: {
fecha: string;
idEmpresa: number;
soloTotales: boolean; // Nuevo parámetro
fecha: string;
idEmpresa: number;
esAccionista?: boolean; // Opcional
soloTotales: boolean;
}): Promise<Blob> => {
const response = await apiClient.get('/reportes/distribucion-canillas/pdf', { // La ruta no necesita cambiar si el backend lo maneja
params, // soloTotales se enviará como query param si el backend lo espera así
responseType: 'blob',
});
return response.data;
try {
const response = await apiClient.get('/reportes/distribucion-canillas/pdf', {
params,
responseType: 'blob'
});
return response.data;
} catch (error) {
console.error('Error al generar PDF del reporte de distribución de canillas:', error);
if (axios.isAxiosError(error) && error.response?.data) {
// Si el error es un JSON dentro de un Blob, hay que leerlo
if (error.response.data.type === 'application/json') {
const errorJson = JSON.parse(await error.response.data.text());
throw new Error(errorJson.message || "Error al generar PDF");
}
}
throw error;
}
};
const getTiradasPublicacionesSecciones = async (params: {