Fix: Fechas de Estado Bobinas
All checks were successful
Optimized Build and Deploy / remote-build-and-deploy (push) Successful in 14m8s

- Las fechas de estado de las bobinas no pueden ser anterior a la fecha de remito (ingreso).
This commit is contained in:
2026-02-11 14:52:58 -03:00
parent fc27b4b43e
commit 9201d7222b
2 changed files with 266 additions and 243 deletions

View File

@@ -199,13 +199,21 @@ namespace GestionIntegral.Api.Services.Impresion
using var transaction = connection.BeginTransaction(); using var transaction = connection.BeginTransaction();
try try
{ {
var bobina = await _stockBobinaRepository.GetByIdAsync(idBobina); // Obtener dentro de la transacción var bobina = await _stockBobinaRepository.GetByIdAsync(idBobina);
if (bobina == null) if (bobina == null)
{ {
try { transaction.Rollback(); } catch { } try { transaction.Rollback(); } catch { }
return (false, "Bobina no encontrada."); return (false, "Bobina no encontrada.");
} }
// Comparamos solo las fechas (sin hora) para evitar problemas de precisión.
if (cambiarEstadoDto.FechaCambioEstado.Date < bobina.FechaRemito.Date)
{
try { transaction.Rollback(); } catch { }
return (false, $"Error de integridad: La fecha del nuevo estado ({cambiarEstadoDto.FechaCambioEstado:dd/MM/yyyy}) " +
$"no puede ser anterior a la fecha de ingreso por remito ({bobina.FechaRemito:dd/MM/yyyy}).");
}
var nuevoEstado = await _estadoBobinaRepository.GetByIdAsync(cambiarEstadoDto.NuevoEstadoId); var nuevoEstado = await _estadoBobinaRepository.GetByIdAsync(cambiarEstadoDto.NuevoEstadoId);
if (nuevoEstado == null) if (nuevoEstado == null)
{ {

View File

@@ -7,7 +7,6 @@ import {
import type { StockBobinaDto } from '../../../models/dtos/Impresion/StockBobinaDto'; import type { StockBobinaDto } from '../../../models/dtos/Impresion/StockBobinaDto';
import type { CambiarEstadoBobinaDto } from '../../../models/dtos/Impresion/CambiarEstadoBobinaDto'; import type { CambiarEstadoBobinaDto } from '../../../models/dtos/Impresion/CambiarEstadoBobinaDto';
import type { EstadoBobinaDto } from '../../../models/dtos/Impresion/EstadoBobinaDto'; import type { EstadoBobinaDto } from '../../../models/dtos/Impresion/EstadoBobinaDto';
// --- CAMBIO: Importar PublicacionDropdownDto ---
import type { PublicacionDropdownDto } from '../../../models/dtos/Distribucion/PublicacionDropdownDto'; import type { PublicacionDropdownDto } from '../../../models/dtos/Distribucion/PublicacionDropdownDto';
import type { PubliSeccionDto } from '../../../models/dtos/Distribucion/PubliSeccionDto'; import type { PubliSeccionDto } from '../../../models/dtos/Distribucion/PubliSeccionDto';
import estadoBobinaService from '../../../services/Impresion/estadoBobinaService'; import estadoBobinaService from '../../../services/Impresion/estadoBobinaService';
@@ -56,7 +55,6 @@ const StockBobinaCambioEstadoModal: React.FC<StockBobinaCambioEstadoModalProps>
const [fechaCambioEstado, setFechaCambioEstado] = useState(''); const [fechaCambioEstado, setFechaCambioEstado] = useState('');
const [estadosDisponibles, setEstadosDisponibles] = useState<EstadoBobinaDto[]>([]); const [estadosDisponibles, setEstadosDisponibles] = useState<EstadoBobinaDto[]>([]);
// --- CAMBIO: Usar PublicacionDropdownDto para el estado ---
const [publicacionesDisponibles, setPublicacionesDisponibles] = useState<PublicacionDropdownDto[]>([]); const [publicacionesDisponibles, setPublicacionesDisponibles] = useState<PublicacionDropdownDto[]>([]);
const [seccionesDisponibles, setSeccionesDisponibles] = useState<PubliSeccionDto[]>([]); const [seccionesDisponibles, setSeccionesDisponibles] = useState<PubliSeccionDto[]>([]);
@@ -77,7 +75,6 @@ const StockBobinaCambioEstadoModal: React.FC<StockBobinaCambioEstadoModalProps>
} else if (bobinaActual.idEstadoBobina === ID_ESTADO_EN_USO) { } else if (bobinaActual.idEstadoBobina === ID_ESTADO_EN_USO) {
estadosFiltrados = todosLosEstados.filter(e => e.idEstadoBobina === ID_ESTADO_DANADA); estadosFiltrados = todosLosEstados.filter(e => e.idEstadoBobina === ID_ESTADO_DANADA);
} else if (bobinaActual.idEstadoBobina === ID_ESTADO_DISPONIBLE) { } else if (bobinaActual.idEstadoBobina === ID_ESTADO_DISPONIBLE) {
// --- CAMBIO: Usar ID_ESTADO_EN_USO ---
estadosFiltrados = todosLosEstados.filter( estadosFiltrados = todosLosEstados.filter(
e => e.idEstadoBobina === ID_ESTADO_EN_USO || e.idEstadoBobina === ID_ESTADO_DANADA e => e.idEstadoBobina === ID_ESTADO_EN_USO || e.idEstadoBobina === ID_ESTADO_DANADA
); );
@@ -90,7 +87,6 @@ const StockBobinaCambioEstadoModal: React.FC<StockBobinaCambioEstadoModalProps>
const sePuedePonerEnUso = estadosFiltrados.some(e => e.idEstadoBobina === ID_ESTADO_EN_USO); const sePuedePonerEnUso = estadosFiltrados.some(e => e.idEstadoBobina === ID_ESTADO_EN_USO);
if (sePuedePonerEnUso) { if (sePuedePonerEnUso) {
// --- CAMBIO: La data es PublicacionDropdownDto[] ---
const publicacionesData: PublicacionDropdownDto[] = await publicacionService.getPublicacionesForDropdown(true); const publicacionesData: PublicacionDropdownDto[] = await publicacionService.getPublicacionesForDropdown(true);
setPublicacionesDisponibles(publicacionesData); setPublicacionesDisponibles(publicacionesData);
} else { } else {
@@ -170,8 +166,16 @@ const StockBobinaCambioEstadoModal: React.FC<StockBobinaCambioEstadoModalProps>
const validate = (): boolean => { const validate = (): boolean => {
const errors: { [key: string]: string | null } = {}; const errors: { [key: string]: string | null } = {};
if (!nuevoEstadoId) errors.nuevoEstadoId = 'Seleccione un nuevo estado.'; if (!nuevoEstadoId) errors.nuevoEstadoId = 'Seleccione un nuevo estado.';
if (!fechaCambioEstado.trim()) errors.fechaCambioEstado = 'La fecha es obligatoria.'; if (!fechaCambioEstado.trim()) {
else if (!/^\d{4}-\d{2}-\d{2}$/.test(fechaCambioEstado)) errors.fechaCambioEstado = 'Formato de fecha inválido.'; errors.fechaCambioEstado = 'La fecha es obligatoria.';
} else if (!/^\d{4}-\d{2}-\d{2}$/.test(fechaCambioEstado)) {
errors.fechaCambioEstado = 'Formato de fecha inválido.';
} else if (bobinaActual) {
const fechaRemitoSimple = bobinaActual.fechaRemito.split('T')[0];
if (fechaCambioEstado < fechaRemitoSimple) {
errors.fechaCambioEstado = `La fecha no puede ser anterior al ingreso (${fechaRemitoSimple}).`;
}
}
if (Number(nuevoEstadoId) === ID_ESTADO_EN_USO) { if (Number(nuevoEstadoId) === ID_ESTADO_EN_USO) {
if (!idPublicacion) errors.idPublicacion = 'Seleccione una publicación.'; if (!idPublicacion) errors.idPublicacion = 'Seleccione una publicación.';
@@ -274,10 +278,21 @@ const StockBobinaCambioEstadoModal: React.FC<StockBobinaCambioEstadoModalProps>
</> </>
)} )}
<TextField label="Fecha Cambio de Estado" type="date" value={fechaCambioEstado} required <TextField
label="Fecha Cambio de Estado"
type="date"
value={fechaCambioEstado}
required
onChange={(e) => { setFechaCambioEstado(e.target.value); handleInputChange('fechaCambioEstado'); }} onChange={(e) => { setFechaCambioEstado(e.target.value); handleInputChange('fechaCambioEstado'); }}
margin="dense" fullWidth error={!!localErrors.fechaCambioEstado} helperText={localErrors.fechaCambioEstado || ''} margin="dense"
disabled={loading} InputLabelProps={{ shrink: true }} fullWidth
error={!!localErrors.fechaCambioEstado}
helperText={localErrors.fechaCambioEstado || ''}
disabled={loading}
InputLabelProps={{ shrink: true }}
inputProps={{
min: bobinaActual?.fechaRemito.split('T')[0]
}}
/> />
<TextField label="Observaciones (Opcional)" value={obs} <TextField label="Observaciones (Opcional)" value={obs}
onChange={(e) => setObs(e.target.value)} onChange={(e) => setObs(e.target.value)}