Ver Mensaje Individual
  #9  
Antiguo Hace 15 Horas
espinete espinete is offline
Miembro
 
Registrado: mar 2009
Posts: 419
Reputación: 17
espinete Va camino a la fama
Cita:
Empezado por newtron Ver Mensaje
1- Entiendo que la factura debe de tener su número para poder validarla, si por lo que sea hay algún error y no dejáis guardarla/enviarla entiendo que el proceso se atasca. En ambientes de red, si otro está facturando por otro sitio entiendo que debería de dejarle enviar la factura siendo correcta y esta llevará un número posterior. Si al final la factura atascada no se puede llevar a término por el motivo que sea tendremos un problema y no sé si también aunque al final se envíe si se hace con una fecha+hora posterior a una factura posterior.
2- Igualmente si hay "bulla" y una factura se "atasca" se puede atascar igualmente la cosa con otros clientes que haya esperando.
3- Si por el motivo que sea no hay internet se debe de poder emitir la factura aunque se envíe posteriormente con incidencia (es mi opinión).
Al menos en nuestro caso, el número de factura no se asigna hasta el momento en que se guarda la factura, si se guarda, claro. Para eso usamos un "semáforo", con bloqueos de la tabla, etc. para evitar duplicados, etc. Que un PC no pueda emitir una factura no afectará a los demás, ni habrá huecos en la enumeración ni nada por el estilo.

Solo afectará a la cola de clientes que estén esperando, pero vamos, si hay cola es probablemente un comercio, donde no hay NIF del cliente ni otras cosas que puedan fallar, así que no será el caso.
Yo lo que haré es comprobar solo algunas de las validaciones, las que más sujetas estén a fallo por parte del usuario. Hay otras que tal como está diseñada la aplicación es imposible que se den nunca.

Por cierto, le he dado a ChatGPT el documento de validaciones y le he pedido que me cree un algoritmo en PHP que haga todas las validaciones del documento. Aún no me he puesto a revisarlo, pero creo que lo ha hecho bastante bien

No todas estas validaciones pueden hacerse ANTES de guardar la factura, y no todas requieren validación, pero algo se podrá aprovechar:

Código PHP:
<?php
function verifactu_precheck(array $datos): array {
    
$errores = [];

    
// Variables locales (usa isset para evitar errores de undefined)
    
$tipo_factura $datos['TipoFactura'] ?? '';
    
$tipo_rectificativa $datos['TipoRectificativa'] ?? '';
    
$calificacion $datos['CalificacionOperacion'] ?? '';
    
$clave_regimen $datos['ClaveRegimen'] ?? '';
    
$operacion_exenta $datos['OperacionExenta'] ?? '';
    
$tipo_impositivo $datos['TipoImpositivo'] ?? null;
    
$tipo_recargo_equivalencia $datos['TipoRecargoEquivalencia'] ?? null;
    
$cuota_repercutida $datos['CuotaRepercutida'] ?? null;
    
$cuota_recargo_equivalencia $datos['CuotaRecargoEquivalencia'] ?? null;
    
$base_imponible $datos['BaseImponibleOimporteNoSujeto'] ?? null;
    
$base_imponible_coste $datos['BaseImponibleACoste'] ?? null;
    
$impuesto $datos['Impuesto'] ?? '';
    
$fecha_operacion $datos['FechaOperacion'] ?? date('Y-m-d');
    
$factura_sin_identif_destinatario $datos['FacturaSinIdentifDestinatarioArticulo61d'] ?? '';
    
$num_registro_acuerdo $datos['NumRegistroAcuerdoFacturacion'] ?? '';

    
// CalificacionOperacion S2
    
if ($calificacion === 'S2') {
        if (!
in_array($tipo_factura, ['F1','F3','R1','R2','R3','R4'])) {
            
$errores[] = "La Calificación 'S2' solo es válida con TipoFactura F1, F3, R1, R2, R3 o R4.";
        }
        if (
$tipo_impositivo !== 0) {
            
$errores[] = "Si la Calificación es 'S2', el TipoImpositivo debe ser 0.";
        }
        if (
$cuota_repercutida != 0) {
            
$errores[] = "Si la Calificación es 'S2', la CuotaRepercutida debe ser 0.";
        }
    }

    
// CalificacionOperacion N1/N2
    
if (in_array($calificacion, ['N1''N2']) && ($impuesto === '01' || $impuesto === '')) {
        if (!empty(
$tipo_impositivo) && $clave_regimen !== '17') {
            
$errores[] = "TipoImpositivo no debe informarse si Calificación es N1/N2 y ClaveRegimen no es 17.";
        }
        if (!empty(
$cuota_repercutida) && $clave_regimen !== '17') {
            
$errores[] = "CuotaRepercutida no debe informarse si Calificación es N1/N2 y ClaveRegimen no es 17.";
        }
        if (!empty(
$tipo_recargo_equivalencia)) {
            
$errores[] = "TipoRecargoEquivalencia no debe informarse si Calificación es N1/N2.";
        }
        if (!empty(
$cuota_recargo_equivalencia)) {
            
$errores[] = "CuotaRecargoEquivalencia no debe informarse si Calificación es N1/N2.";
        }
    }

    
// OperacionExenta con campos incompatibles
    
if (!empty($operacion_exenta)) {
        if (!empty(
$tipo_impositivo) || !empty($cuota_repercutida) || !empty($tipo_recargo_equivalencia) || !empty($cuota_recargo_equivalencia)) {
            
$errores[] = "Si se informa OperacionExenta, no deben informarse TipoImpositivo, CuotaRepercutida ni Recargo de Equivalencia.";
        }
    }

    
// TipoImpositivo permitido según fecha y CalificacionOperacion
    
if (($impuesto === '01' || $impuesto === '03' || $impuesto === '') && $calificacion === 'S1') {
        
$permitidos = [02457.51021];
        if (
$fecha_operacion >= '2022-07-01' && $fecha_operacion <= '2024-09-30'$permitidos[] = 5;
        if (
$fecha_operacion >= '2024-10-01' && $fecha_operacion <= '2024-12-31'array_push($permitidos27.5);
        if (!
in_array($tipo_impositivo$permitidos)) {
            
$errores[] = "TipoImpositivo no válido para CalificacionOperacion S1 en la fecha dada.";
        }
    }

    
// Factura simplificada F2
    
if ($tipo_factura === 'F2') {
        
$importe_total $base_imponible $cuota_repercutida;
        if (
$importe_total 3010 && $factura_sin_identif_destinatario !== 'S' && empty($num_registro_acuerdo)) {
            
$errores[] = "Factura F2 no puede superar los 3.000€ (+10€ de margen) salvo acuerdo o identificación del destinatario.";
        }
    }

    
// ASCII en NumSerieFactura
    
if (!empty($datos['NumSerieFactura']) && !preg_match('/^[\x20-\x7E]+$/'$datos['NumSerieFactura'])) {
        
$errores[] = "El número de serie solo puede contener caracteres ASCII imprimibles.";
    }

    
// Huella en formato SHA-256
    
if (!empty($datos['Huella']) && !preg_match('/^[A-F0-9]{64}$/'$datos['Huella'])) {
        
$errores[] = "La huella debe tener 64 caracteres hexadecimales en mayúsculas (formato SHA-256).";
    }

    return 
$errores;
}
Responder Con Cita