Feat(suscripciones): Implementa manejo de pagos parciales en facturas
All checks were successful
Optimized Build and Deploy / remote-build-and-deploy (push) Successful in 8m3s
All checks were successful
Optimized Build and Deploy / remote-build-and-deploy (push) Successful in 8m3s
Se introduce una refactorización completa del sistema de registro de pagos para manejar correctamente los abonos parciales, asegurando que el estado de la factura y el saldo pendiente se reflejen con precisión tanto en el backend como en la interfaz de usuario. ### 🐛 Problema Solucionado - Anteriormente, el sistema no reconocía los pagos parciales. Una factura permanecía en estado "Pendiente" hasta que el monto total era cubierto, y la interfaz de usuario siempre mostraba el 100% del saldo como pendiente, lo cual era incorrecto y confuso. ### ✨ Nuevas Características y Mejoras - **Nuevo Estado de Factura "Pagada Parcialmente":** - Se introduce un nuevo estado para las facturas que han recibido uno o más pagos pero cuyo saldo aún no es cero. - El `PagoService` ahora actualiza el estado de la factura a "Pagada Parcialmente" cuando recibe un abono que no cubre el total. - **Mejoras en la Interfaz de Usuario (`ConsultaFacturasPage`):** - **Nuevas Columnas:** Se han añadido las columnas "Pagado" y "Saldo" a la tabla de detalle de facturas, mostrando explícitamente el monto abonado y el restante. - **Visualización de Estado:** El `Chip` de estado ahora muestra "Pagada Parcialmente" con un color distintivo (azul/primary) para una rápida identificación visual. - **Cálculo de Saldo Correcto:** El saldo pendiente total por suscriptor y el saldo para el modal de pago manual ahora se calculan correctamente, restando el `totalPagado` del `importeFinal`. ### 🔄 Cambios en el Backend - **`PagoService`:** Se actualizó la lógica para establecer el estado de la factura (`Pendiente`, `Pagada Parcialmente`, `Pagada`) basado en el `nuevoTotalPagado` después de registrar un pago. - **`FacturacionService`:** El método `ObtenerResumenesDeCuentaPorPeriodo` ahora calcula correctamente el `SaldoPendienteTotal` y pasa la propiedad `TotalPagado` al DTO del frontend. - **DTOs:** Se actualizó `FacturaConsolidadaDto` para incluir la propiedad `TotalPagado`.
This commit is contained in:
@@ -8,6 +8,7 @@ namespace GestionIntegral.Api.Dtos.Suscripciones
|
|||||||
public string EstadoPago { get; set; } = string.Empty;
|
public string EstadoPago { get; set; } = string.Empty;
|
||||||
public string EstadoFacturacion { get; set; } = string.Empty;
|
public string EstadoFacturacion { get; set; } = string.Empty;
|
||||||
public string? NumeroFactura { get; set; }
|
public string? NumeroFactura { get; set; }
|
||||||
|
public decimal TotalPagado { get; set; }
|
||||||
public List<FacturaDetalleDto> Detalles { get; set; } = new List<FacturaDetalleDto>();
|
public List<FacturaDetalleDto> Detalles { get; set; } = new List<FacturaDetalleDto>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -282,7 +282,7 @@ namespace GestionIntegral.Api.Services.Suscripciones
|
|||||||
{
|
{
|
||||||
var periodo = $"{anio}-{mes:D2}";
|
var periodo = $"{anio}-{mes:D2}";
|
||||||
var facturasData = await _facturaRepository.GetByPeriodoEnrichedAsync(periodo, nombreSuscriptor, estadoPago, estadoFacturacion);
|
var facturasData = await _facturaRepository.GetByPeriodoEnrichedAsync(periodo, nombreSuscriptor, estadoPago, estadoFacturacion);
|
||||||
var detallesData = await _facturaDetalleRepository.GetDetallesPorPeriodoAsync(periodo); // Necesitaremos este nuevo método en el repo
|
var detallesData = await _facturaDetalleRepository.GetDetallesPorPeriodoAsync(periodo);
|
||||||
var empresas = await _empresaRepository.GetAllAsync(null, null);
|
var empresas = await _empresaRepository.GetAllAsync(null, null);
|
||||||
|
|
||||||
var resumenes = facturasData
|
var resumenes = facturasData
|
||||||
@@ -301,6 +301,7 @@ namespace GestionIntegral.Api.Services.Suscripciones
|
|||||||
EstadoPago = itemFactura.Factura.EstadoPago,
|
EstadoPago = itemFactura.Factura.EstadoPago,
|
||||||
EstadoFacturacion = itemFactura.Factura.EstadoFacturacion,
|
EstadoFacturacion = itemFactura.Factura.EstadoFacturacion,
|
||||||
NumeroFactura = itemFactura.Factura.NumeroFactura,
|
NumeroFactura = itemFactura.Factura.NumeroFactura,
|
||||||
|
TotalPagado = itemFactura.TotalPagado,
|
||||||
Detalles = detallesData
|
Detalles = detallesData
|
||||||
.Where(d => d.IdFactura == itemFactura.Factura.IdFactura)
|
.Where(d => d.IdFactura == itemFactura.Factura.IdFactura)
|
||||||
.Select(d => new FacturaDetalleDto { Descripcion = d.Descripcion, ImporteNeto = d.ImporteNeto })
|
.Select(d => new FacturaDetalleDto { Descripcion = d.Descripcion, ImporteNeto = d.ImporteNeto })
|
||||||
@@ -314,7 +315,7 @@ namespace GestionIntegral.Api.Services.Suscripciones
|
|||||||
NombreSuscriptor = primerItem.NombreSuscriptor,
|
NombreSuscriptor = primerItem.NombreSuscriptor,
|
||||||
Facturas = facturasConsolidadas,
|
Facturas = facturasConsolidadas,
|
||||||
ImporteTotal = facturasConsolidadas.Sum(f => f.ImporteFinal),
|
ImporteTotal = facturasConsolidadas.Sum(f => f.ImporteFinal),
|
||||||
SaldoPendienteTotal = facturasConsolidadas.Sum(f => f.EstadoPago == "Pagada" ? 0 : f.ImporteFinal)
|
SaldoPendienteTotal = facturasConsolidadas.Sum(f => f.ImporteFinal - f.TotalPagado)
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -70,14 +70,11 @@ namespace GestionIntegral.Api.Services.Suscripciones
|
|||||||
{
|
{
|
||||||
var factura = await _facturaRepository.GetByIdAsync(createDto.IdFactura);
|
var factura = await _facturaRepository.GetByIdAsync(createDto.IdFactura);
|
||||||
if (factura == null) return (null, "La factura especificada no existe.");
|
if (factura == null) return (null, "La factura especificada no existe.");
|
||||||
|
|
||||||
// Usar EstadoPago para la validación
|
|
||||||
if (factura.EstadoPago == "Anulada") return (null, "No se puede registrar un pago sobre una factura anulada.");
|
if (factura.EstadoPago == "Anulada") return (null, "No se puede registrar un pago sobre una factura anulada.");
|
||||||
|
|
||||||
var formaPago = await _formaPagoRepository.GetByIdAsync(createDto.IdFormaPago);
|
var formaPago = await _formaPagoRepository.GetByIdAsync(createDto.IdFormaPago);
|
||||||
if (formaPago == null || !formaPago.Activo) return (null, "La forma de pago no es válida.");
|
if (formaPago == null || !formaPago.Activo) return (null, "La forma de pago no es válida.");
|
||||||
|
|
||||||
// Obtenemos la suma de pagos ANTERIORES
|
|
||||||
var totalPagadoAnteriormente = await _pagoRepository.GetTotalPagadoAprobadoAsync(createDto.IdFactura, transaction);
|
var totalPagadoAnteriormente = await _pagoRepository.GetTotalPagadoAprobadoAsync(createDto.IdFactura, transaction);
|
||||||
|
|
||||||
var nuevoPago = new Pago
|
var nuevoPago = new Pago
|
||||||
@@ -96,37 +93,31 @@ namespace GestionIntegral.Api.Services.Suscripciones
|
|||||||
var pagoCreado = await _pagoRepository.CreateAsync(nuevoPago, transaction);
|
var pagoCreado = await _pagoRepository.CreateAsync(nuevoPago, transaction);
|
||||||
if (pagoCreado == null) throw new DataException("No se pudo registrar el pago.");
|
if (pagoCreado == null) throw new DataException("No se pudo registrar el pago.");
|
||||||
|
|
||||||
// Calculamos el nuevo total EN MEMORIA
|
|
||||||
var nuevoTotalPagado = totalPagadoAnteriormente + pagoCreado.Monto;
|
var nuevoTotalPagado = totalPagadoAnteriormente + pagoCreado.Monto;
|
||||||
|
|
||||||
// Comparamos y actualizamos el estado si es necesario
|
// Nueva lógica para manejar todos los estados de pago
|
||||||
// CORRECCIÓN: Usar EstadoPago y el método correcto del repositorio
|
string nuevoEstadoPago = factura.EstadoPago;
|
||||||
if (factura.EstadoPago != "Pagada" && nuevoTotalPagado >= factura.ImporteFinal)
|
if (nuevoTotalPagado >= factura.ImporteFinal)
|
||||||
{
|
{
|
||||||
bool actualizado = await _facturaRepository.UpdateEstadoPagoAsync(factura.IdFactura, "Pagada", transaction);
|
nuevoEstadoPago = "Pagada";
|
||||||
if (!actualizado) throw new DataException("No se pudo actualizar el estado de la factura a 'Pagada'.");
|
}
|
||||||
|
else if (nuevoTotalPagado > 0)
|
||||||
|
{
|
||||||
|
nuevoEstadoPago = "Pagada Parcialmente";
|
||||||
|
}
|
||||||
|
// Si nuevoTotalPagado es 0, el estado no cambia.
|
||||||
|
|
||||||
|
// Solo actualizamos si el estado calculado es diferente al actual.
|
||||||
|
if (nuevoEstadoPago != factura.EstadoPago)
|
||||||
|
{
|
||||||
|
bool actualizado = await _facturaRepository.UpdateEstadoPagoAsync(factura.IdFactura, nuevoEstadoPago, transaction);
|
||||||
|
if (!actualizado) throw new DataException($"No se pudo actualizar el estado de la factura a '{nuevoEstadoPago}'.");
|
||||||
}
|
}
|
||||||
|
|
||||||
transaction.Commit();
|
transaction.Commit();
|
||||||
_logger.LogInformation("Pago manual ID {IdPago} registrado para Factura ID {IdFactura} por Usuario ID {IdUsuario}", pagoCreado.IdPago, pagoCreado.IdFactura, idUsuario);
|
_logger.LogInformation("Pago manual ID {IdPago} registrado para Factura ID {IdFactura} por Usuario ID {IdUsuario}", pagoCreado.IdPago, pagoCreado.IdFactura, idUsuario);
|
||||||
|
|
||||||
// Construimos el DTO de respuesta SIN volver a consultar la base de datos
|
var dto = await MapToDto(pagoCreado); // MapToDto ahora es más simple
|
||||||
var usuario = await _usuarioRepository.GetByIdAsync(idUsuario);
|
|
||||||
var dto = new PagoDto
|
|
||||||
{
|
|
||||||
IdPago = pagoCreado.IdPago,
|
|
||||||
IdFactura = pagoCreado.IdFactura,
|
|
||||||
FechaPago = pagoCreado.FechaPago.ToString("yyyy-MM-dd"),
|
|
||||||
IdFormaPago = pagoCreado.IdFormaPago,
|
|
||||||
NombreFormaPago = formaPago.Nombre,
|
|
||||||
Monto = pagoCreado.Monto,
|
|
||||||
Estado = pagoCreado.Estado,
|
|
||||||
Referencia = pagoCreado.Referencia,
|
|
||||||
Observaciones = pagoCreado.Observaciones,
|
|
||||||
IdUsuarioRegistro = pagoCreado.IdUsuarioRegistro,
|
|
||||||
NombreUsuarioRegistro = usuario != null ? $"{usuario.Nombre} {usuario.Apellido}" : "N/A"
|
|
||||||
};
|
|
||||||
|
|
||||||
return (dto, null);
|
return (dto, null);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export interface FacturaConsolidadaDto {
|
|||||||
estadoPago: string;
|
estadoPago: string;
|
||||||
estadoFacturacion: string;
|
estadoFacturacion: string;
|
||||||
numeroFactura?: string | null;
|
numeroFactura?: string | null;
|
||||||
|
totalPagado: number;
|
||||||
detalles: FacturaDetalleDto[];
|
detalles: FacturaDetalleDto[];
|
||||||
// Añadimos el id del suscriptor para que sea fácil pasarlo a los handlers
|
// Añadimos el id del suscriptor para que sea fácil pasarlo a los handlers
|
||||||
idSuscriptor: number;
|
idSuscriptor: number;
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ const meses = [
|
|||||||
{ value: 10, label: 'Octubre' }, { value: 11, label: 'Noviembre' }, { value: 12, label: 'Diciembre' }
|
{ value: 10, label: 'Octubre' }, { value: 11, label: 'Noviembre' }, { value: 12, label: 'Diciembre' }
|
||||||
];
|
];
|
||||||
|
|
||||||
const estadosPago = ['Pendiente', 'Pagada', 'Rechazada', 'Anulada'];
|
const estadosPago = ['Pendiente', 'Pagada', 'Pagada Parcialmente', 'Rechazada', 'Anulada'];
|
||||||
const estadosFacturacion = ['Pendiente de Facturar', 'Facturado'];
|
const estadosFacturacion = ['Pendiente de Facturar', 'Facturado'];
|
||||||
|
|
||||||
const SuscriptorRow: React.FC<{
|
const SuscriptorRow: React.FC<{
|
||||||
@@ -33,50 +33,83 @@ const SuscriptorRow: React.FC<{
|
|||||||
handleOpenHistorial: (factura: FacturaConsolidadaDto) => void;
|
handleOpenHistorial: (factura: FacturaConsolidadaDto) => void;
|
||||||
}> = ({ resumen, handleMenuOpen, handleOpenHistorial }) => {
|
}> = ({ resumen, handleMenuOpen, handleOpenHistorial }) => {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
|
// Función para formatear moneda
|
||||||
|
const formatCurrency = (value: number) => `$${value.toFixed(2)}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<TableRow sx={{ '& > *': { borderBottom: 'unset' } }} hover>
|
<TableRow sx={{ '& > *': { borderBottom: 'unset' } }} hover>
|
||||||
<TableCell><IconButton size="small" onClick={() => setOpen(!open)}>{open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}</IconButton></TableCell>
|
<TableCell><IconButton size="small" onClick={() => setOpen(!open)}>{open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}</IconButton></TableCell>
|
||||||
<TableCell component="th" scope="row">{resumen.nombreSuscriptor}</TableCell>
|
<TableCell component="th" scope="row">{resumen.nombreSuscriptor}</TableCell>
|
||||||
<TableCell align="right">
|
<TableCell align="right">
|
||||||
<Typography variant="body2" sx={{ fontWeight: 'bold', color: resumen.saldoPendienteTotal > 0 ? 'error.main' : 'success.main' }}>${resumen.saldoPendienteTotal.toFixed(2)}</Typography>
|
<Typography variant="body2" sx={{ fontWeight: 'bold', color: resumen.saldoPendienteTotal > 0 ? 'error.main' : 'success.main' }}>
|
||||||
<Typography variant="caption" color="text.secondary">de ${resumen.importeTotal.toFixed(2)}</Typography>
|
{formatCurrency(resumen.saldoPendienteTotal)}
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="caption" color="text.secondary">de {formatCurrency(resumen.importeTotal)}</Typography>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell colSpan={5}></TableCell>
|
<TableCell colSpan={7}></TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={8}>
|
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={10}>
|
||||||
<Collapse in={open} timeout="auto" unmountOnExit>
|
<Collapse in={open} timeout="auto" unmountOnExit>
|
||||||
<Box sx={{ margin: 1, padding: 2, backgroundColor: 'grey.50', borderRadius: 1 }}>
|
<Box sx={{ margin: 1, padding: 2, backgroundColor: 'grey.50', borderRadius: 1 }}>
|
||||||
<Typography variant="h6" gutterBottom component="div" sx={{ fontSize: '1rem', fontWeight: 'bold' }}>Facturas del Período para {resumen.nombreSuscriptor}</Typography>
|
<Typography variant="h6" gutterBottom component="div" sx={{ fontSize: '1rem', fontWeight: 'bold' }}>
|
||||||
|
Facturas del Período para {resumen.nombreSuscriptor}
|
||||||
|
</Typography>
|
||||||
<Table size="small">
|
<Table size="small">
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell>Empresa</TableCell><TableCell align="right">Importe</TableCell>
|
<TableCell>Empresa</TableCell>
|
||||||
<TableCell>Estado Pago</TableCell><TableCell>Estado Facturación</TableCell>
|
<TableCell align="right">Importe Total</TableCell>
|
||||||
<TableCell>Nro. Factura</TableCell><TableCell align="right">Acciones</TableCell>
|
<TableCell align="right">Pagado</TableCell>
|
||||||
|
<TableCell align="right">Saldo</TableCell>
|
||||||
|
<TableCell>Estado Pago</TableCell>
|
||||||
|
<TableCell>Estado Facturación</TableCell>
|
||||||
|
<TableCell>Nro. Factura</TableCell>
|
||||||
|
<TableCell align="right">Acciones</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{resumen.facturas.map((factura) => (
|
{resumen.facturas.map((factura) => {
|
||||||
<TableRow key={factura.idFactura}>
|
const saldo = factura.importeFinal - factura.totalPagado;
|
||||||
<TableCell sx={{ fontWeight: 'medium' }}>{factura.nombreEmpresa}</TableCell>
|
return (
|
||||||
<TableCell align="right">${factura.importeFinal.toFixed(2)}</TableCell>
|
<TableRow key={factura.idFactura}>
|
||||||
<TableCell><Chip label={factura.estadoPago} size="small" color={factura.estadoPago === 'Pagada' ? 'success' : (factura.estadoPago === 'Rechazada' ? 'error' : 'default')} /></TableCell>
|
<TableCell sx={{ fontWeight: 'medium' }}>{factura.nombreEmpresa}</TableCell>
|
||||||
<TableCell><Chip label={factura.estadoFacturacion} size="small" color={factura.estadoFacturacion === 'Facturado' ? 'info' : 'warning'} /></TableCell>
|
<TableCell align="right">{formatCurrency(factura.importeFinal)}</TableCell>
|
||||||
<TableCell>{factura.numeroFactura || '-'}</TableCell>
|
<TableCell align="right" sx={{ color: 'success.dark' }}>
|
||||||
<TableCell align="right">
|
{formatCurrency(factura.totalPagado)}
|
||||||
<IconButton onClick={(e) => handleMenuOpen(e, factura)} disabled={factura.estadoPago === 'Anulada'}>
|
</TableCell>
|
||||||
<MoreVertIcon />
|
<TableCell align="right" sx={{ fontWeight: 'bold', color: saldo > 0 ? 'error.main' : 'inherit' }}>
|
||||||
</IconButton>
|
{formatCurrency(saldo)}
|
||||||
<Tooltip title="Ver Historial de Envíos">
|
</TableCell>
|
||||||
<IconButton onClick={() => handleOpenHistorial(factura)}>
|
<TableCell>
|
||||||
<MailOutlineIcon />
|
<Chip
|
||||||
|
label={factura.estadoPago}
|
||||||
|
size="small"
|
||||||
|
color={
|
||||||
|
factura.estadoPago === 'Pagada' ? 'success' :
|
||||||
|
factura.estadoPago === 'Pagada Parcialmente' ? 'primary' :
|
||||||
|
factura.estadoPago === 'Rechazada' ? 'error' :
|
||||||
|
'default'
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell><Chip label={factura.estadoFacturacion} size="small" color={factura.estadoFacturacion === 'Facturado' ? 'info' : 'warning'} /></TableCell>
|
||||||
|
<TableCell>{factura.numeroFactura || '-'}</TableCell>
|
||||||
|
<TableCell align="right">
|
||||||
|
<IconButton onClick={(e) => handleMenuOpen(e, factura)} disabled={factura.estadoPago === 'Anulada'}>
|
||||||
|
<MoreVertIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
<Tooltip title="Ver Historial de Envíos">
|
||||||
</TableCell>
|
<IconButton onClick={() => handleOpenHistorial(factura)}>
|
||||||
</TableRow>
|
<MailOutlineIcon />
|
||||||
))}
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -162,7 +195,7 @@ const ConsultaFacturasPage: React.FC = () => {
|
|||||||
setLoadingLogs(false);
|
setLoadingLogs(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSubmitPagoModal = async (data: CreatePagoDto) => {
|
const handleSubmitPagoModal = async (data: CreatePagoDto) => {
|
||||||
setApiError(null);
|
setApiError(null);
|
||||||
try {
|
try {
|
||||||
@@ -231,10 +264,10 @@ const ConsultaFacturasPage: React.FC = () => {
|
|||||||
{loading ? (<TableRow><TableCell colSpan={8} align="center"><CircularProgress /></TableCell></TableRow>)
|
{loading ? (<TableRow><TableCell colSpan={8} align="center"><CircularProgress /></TableCell></TableRow>)
|
||||||
: resumenes.length === 0 ? (<TableRow><TableCell colSpan={8} align="center">No hay facturas para el período seleccionado.</TableCell></TableRow>)
|
: resumenes.length === 0 ? (<TableRow><TableCell colSpan={8} align="center">No hay facturas para el período seleccionado.</TableCell></TableRow>)
|
||||||
: (resumenes.map(resumen => (
|
: (resumenes.map(resumen => (
|
||||||
<SuscriptorRow
|
<SuscriptorRow
|
||||||
key={resumen.idSuscriptor}
|
key={resumen.idSuscriptor}
|
||||||
resumen={resumen}
|
resumen={resumen}
|
||||||
handleMenuOpen={handleMenuOpen}
|
handleMenuOpen={handleMenuOpen}
|
||||||
handleOpenHistorial={handleOpenHistorial}
|
handleOpenHistorial={handleOpenHistorial}
|
||||||
/>
|
/>
|
||||||
)))}
|
)))}
|
||||||
@@ -257,12 +290,12 @@ const ConsultaFacturasPage: React.FC = () => {
|
|||||||
idFactura: selectedFactura.idFactura,
|
idFactura: selectedFactura.idFactura,
|
||||||
nombreSuscriptor: resumenes.find(r => r.idSuscriptor === resumenes.find(res => res.facturas.some(f => f.idFactura === selectedFactura.idFactura))?.idSuscriptor)?.nombreSuscriptor || '',
|
nombreSuscriptor: resumenes.find(r => r.idSuscriptor === resumenes.find(res => res.facturas.some(f => f.idFactura === selectedFactura.idFactura))?.idSuscriptor)?.nombreSuscriptor || '',
|
||||||
importeFinal: selectedFactura.importeFinal,
|
importeFinal: selectedFactura.importeFinal,
|
||||||
saldoPendiente: selectedFactura.estadoPago === 'Pagada' ? 0 : selectedFactura.importeFinal,
|
saldoPendiente: selectedFactura.importeFinal - selectedFactura.totalPagado,
|
||||||
|
totalPagado: selectedFactura.totalPagado,
|
||||||
idSuscriptor: resumenes.find(res => res.facturas.some(f => f.idFactura === selectedFactura.idFactura))?.idSuscriptor || 0,
|
idSuscriptor: resumenes.find(res => res.facturas.some(f => f.idFactura === selectedFactura.idFactura))?.idSuscriptor || 0,
|
||||||
periodo: '',
|
periodo: '',
|
||||||
fechaEmision: '',
|
fechaEmision: '',
|
||||||
fechaVencimiento: '',
|
fechaVencimiento: '',
|
||||||
totalPagado: selectedFactura.importeFinal - (selectedFactura.estadoPago === 'Pagada' ? 0 : selectedFactura.importeFinal),
|
|
||||||
estadoPago: selectedFactura.estadoPago,
|
estadoPago: selectedFactura.estadoPago,
|
||||||
estadoFacturacion: selectedFactura.estadoFacturacion,
|
estadoFacturacion: selectedFactura.estadoFacturacion,
|
||||||
numeroFactura: selectedFactura.numeroFactura,
|
numeroFactura: selectedFactura.numeroFactura,
|
||||||
@@ -272,7 +305,7 @@ const ConsultaFacturasPage: React.FC = () => {
|
|||||||
errorMessage={apiError}
|
errorMessage={apiError}
|
||||||
clearErrorMessage={() => setApiError(null)}
|
clearErrorMessage={() => setApiError(null)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<HistorialEnviosModal
|
<HistorialEnviosModal
|
||||||
open={historialModalOpen}
|
open={historialModalOpen}
|
||||||
onClose={() => setHistorialModalOpen(false)}
|
onClose={() => setHistorialModalOpen(false)}
|
||||||
|
|||||||
Reference in New Issue
Block a user