Refinamiento de permisos y ajustes en controles. Añade gestión sobre saldos y visualización. Entre otros..
This commit is contained in:
162
Frontend/src/components/Modals/Contables/AjusteSaldoModal.tsx
Normal file
162
Frontend/src/components/Modals/Contables/AjusteSaldoModal.tsx
Normal file
@@ -0,0 +1,162 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import {
|
||||
Modal, Box, Typography, TextField, Button, CircularProgress, Alert, InputAdornment
|
||||
} from '@mui/material';
|
||||
import type { SaldoGestionDto } from '../../../models/dtos/Contables/SaldoGestionDto';
|
||||
import type { AjusteSaldoRequestDto } from '../../../models/dtos/Contables/AjusteSaldoRequestDto';
|
||||
|
||||
const modalStyle = {
|
||||
position: 'absolute' as 'absolute',
|
||||
top: '50%',
|
||||
left: '50%',
|
||||
transform: 'translate(-50%, -50%)',
|
||||
width: { xs: '90%', sm: 450 },
|
||||
bgcolor: 'background.paper',
|
||||
border: '2px solid #000',
|
||||
boxShadow: 24,
|
||||
p: 3,
|
||||
};
|
||||
|
||||
interface AjusteSaldoModalProps {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
onSubmit: (data: AjusteSaldoRequestDto) => Promise<void>; // El padre maneja la recarga
|
||||
saldoParaAjustar: SaldoGestionDto | null;
|
||||
errorMessage?: string | null;
|
||||
clearErrorMessage: () => void;
|
||||
}
|
||||
|
||||
const AjusteSaldoModal: React.FC<AjusteSaldoModalProps> = ({
|
||||
open,
|
||||
onClose,
|
||||
onSubmit,
|
||||
saldoParaAjustar,
|
||||
errorMessage,
|
||||
clearErrorMessage
|
||||
}) => {
|
||||
const [montoAjuste, setMontoAjuste] = useState<string>('');
|
||||
const [justificacion, setJustificacion] = useState('');
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [localErrors, setLocalErrors] = useState<{ [key: string]: string | null }>({});
|
||||
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
setMontoAjuste('');
|
||||
setJustificacion('');
|
||||
setLocalErrors({});
|
||||
clearErrorMessage();
|
||||
}
|
||||
}, [open, clearErrorMessage]);
|
||||
|
||||
const validate = (): boolean => {
|
||||
const errors: { [key: string]: string | null } = {};
|
||||
const numMontoAjuste = parseFloat(montoAjuste);
|
||||
|
||||
if (!montoAjuste.trim()) {
|
||||
errors.montoAjuste = 'El monto de ajuste es obligatorio.';
|
||||
} else if (isNaN(numMontoAjuste)) {
|
||||
errors.montoAjuste = 'El monto debe ser un número.';
|
||||
} else if (numMontoAjuste === 0) {
|
||||
errors.montoAjuste = 'El monto de ajuste no puede ser cero.';
|
||||
}
|
||||
|
||||
if (!justificacion.trim()) {
|
||||
errors.justificacion = 'La justificación es obligatoria.';
|
||||
} else if (justificacion.trim().length < 5 || justificacion.trim().length > 250) {
|
||||
errors.justificacion = 'La justificación debe tener entre 5 y 250 caracteres.';
|
||||
}
|
||||
setLocalErrors(errors);
|
||||
return Object.keys(errors).length === 0;
|
||||
};
|
||||
|
||||
const handleInputChange = (fieldName: 'montoAjuste' | 'justificacion') => {
|
||||
if (localErrors[fieldName]) setLocalErrors(prev => ({ ...prev, [fieldName]: null }));
|
||||
if (errorMessage) clearErrorMessage();
|
||||
};
|
||||
|
||||
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault();
|
||||
clearErrorMessage();
|
||||
if (!validate() || !saldoParaAjustar) return;
|
||||
|
||||
setLoading(true);
|
||||
try {
|
||||
const dataToSubmit: AjusteSaldoRequestDto = {
|
||||
destino: saldoParaAjustar.destino as 'Distribuidores' | 'Canillas',
|
||||
idDestino: saldoParaAjustar.idDestino,
|
||||
idEmpresa: saldoParaAjustar.idEmpresa,
|
||||
montoAjuste: parseFloat(montoAjuste),
|
||||
justificacion,
|
||||
};
|
||||
await onSubmit(dataToSubmit);
|
||||
onClose(); // Cerrar en éxito (el padre recargará)
|
||||
} catch (error: any) {
|
||||
// El error de API es manejado por la página padre
|
||||
console.error("Error en submit de AjusteSaldoModal:", error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
if (!saldoParaAjustar) return null;
|
||||
|
||||
return (
|
||||
<Modal open={open} onClose={onClose}>
|
||||
<Box sx={modalStyle}>
|
||||
<Typography variant="h6" component="h2" gutterBottom>
|
||||
Ajustar Saldo Manualmente
|
||||
</Typography>
|
||||
<Typography variant="body2" gutterBottom>
|
||||
Destinatario: <strong>{saldoParaAjustar.nombreDestinatario}</strong> ({saldoParaAjustar.destino})
|
||||
</Typography>
|
||||
<Typography variant="body2" gutterBottom>
|
||||
Empresa: <strong>{saldoParaAjustar.nombreEmpresa}</strong>
|
||||
</Typography>
|
||||
<Typography variant="body2" color="text.secondary" gutterBottom>
|
||||
Saldo Actual: <strong>{saldoParaAjustar.monto.toLocaleString('es-AR', { style: 'currency', currency: 'ARS' })}</strong>
|
||||
</Typography>
|
||||
|
||||
<Box component="form" onSubmit={handleSubmit} sx={{ mt: 2 }}>
|
||||
<TextField
|
||||
label="Monto de Ajuste (+/-)"
|
||||
type="number"
|
||||
fullWidth
|
||||
required
|
||||
value={montoAjuste}
|
||||
onChange={(e) => { setMontoAjuste(e.target.value); handleInputChange('montoAjuste'); }}
|
||||
margin="normal"
|
||||
error={!!localErrors.montoAjuste}
|
||||
helperText={localErrors.montoAjuste || 'Ingrese un valor positivo para aumentar deuda o negativo para disminuirla.'}
|
||||
disabled={loading}
|
||||
InputProps={{ startAdornment: <InputAdornment position="start">$</InputAdornment> }}
|
||||
inputProps={{ step: "0.01" }}
|
||||
autoFocus
|
||||
/>
|
||||
<TextField
|
||||
label="Justificación del Ajuste"
|
||||
fullWidth
|
||||
required
|
||||
value={justificacion}
|
||||
onChange={(e) => { setJustificacion(e.target.value); handleInputChange('justificacion'); }}
|
||||
margin="normal"
|
||||
multiline
|
||||
rows={3}
|
||||
error={!!localErrors.justificacion}
|
||||
helperText={localErrors.justificacion || ''}
|
||||
disabled={loading}
|
||||
inputProps={{ maxLength: 250 }}
|
||||
/>
|
||||
{errorMessage && <Alert severity="error" sx={{ mt: 1 }}>{errorMessage}</Alert>}
|
||||
<Box sx={{ mt: 3, display: 'flex', justifyContent: 'flex-end', gap: 1 }}>
|
||||
<Button onClick={onClose} color="secondary" disabled={loading}>Cancelar</Button>
|
||||
<Button type="submit" variant="contained" disabled={loading}>
|
||||
{loading ? <CircularProgress size={24} /> : 'Aplicar Ajuste'}
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default AjusteSaldoModal;
|
||||
Reference in New Issue
Block a user