php – Como mostrar porcentaje de avance mediante ajax al ejecutar script

Estimados tengo el siguiente problema. Tratare de ser lo más breve posible en la explicación del código para que se entienda mi objetivo.

Tengo un script php donde se envían una serie de datos mediante ajax, en dicho script se realizan las validaciones correspondientes y se van retornando los respectivos mensajes ya sean de error o de éxito, los cuales se muestran al usuario para advertirle si:

  • Faltan datos
  • Si no a seleccionado un archivo
  • Si todo salió correcto

Cuando todo sale correcto, se insertan los datos en la base de datos, se envía un correo electrónico al usuario y se genera una orden de servicio la cual se le muestra al usuario en pantalla.

Obviamente todo el proceso desde que se inicia el script hasta hasta que todo sale bien, transcurre en un determinado tiempo.
Me gustaría mostrar en caso de éxito un % de avance hasta que el cliente recibe el mensaje con la orden de servicio en pantalla.

Adjunto un poco lo que tengo, pero el % de avance se muestra siempre, salga todo bien o todo mal. Aclaro que es la primera vez que intento implementar una barra de progreso.

public function Orden(){
    $con = new Conexion(DB_PORTAL); 
    $mail = new EnviarCorreo();
    $idusuario = $_SESSION('idusuario');
    $creditos = $con->obtenerdato("creditos","usuarios","idusuario = ?",($idusuario));
    if($creditos > 0){
        if(!(empty($_POST('fabricante'))) and !(empty($_POST('modelo'))) and !(empty($_POST('año'))) and !(empty($_POST('motor'))) and !(empty($_POST('transmision'))) and !(empty($_POST('combustible'))) and !(empty($_POST('patente'))) and !(empty($_POST('kilometraje'))) and !(empty($_POST('ecu'))) and !(empty($_POST('herramienta'))) and !(empty($_POST('versionherramienta'))) and !(empty($_POST('servicioprincipal'))) and !(empty($_FILES('archivo'))) and ($_POST('confirmado') == '1')){
           //AQUI SE RECIBEN, VALIDAN Y SANEAN TOSOS LOS DATOS, LOS OMITI PORQUE SON MUCHOS INPUTS
            $totalcreditos = $total_servicioprincipal + $total_adicionales;
            $query_saldo = $con->obtenerdatos("creditos","usuarios","idusuario = ?",($idusuario));
            $saldoanterior = $query_saldo(0)('creditos');
            $saldoactual = $saldoanterior - $totalcreditos;
            $conjunto = array(NULL,$ordenservicio,$servicioprincipal,$implode,$totalcreditos,$saldoanterior,$saldoactual,$fabricante,$modelo,$año,$motor,$transmision,$combustible,$patente,$kilometraje,$ecu,$herramienta,$versionherramienta,$informacion,'archivos',$nombrefinal,"",$fecha,$idusuario,$estado,NULL,$totalcreditos,$idusuario);
            if($creditos >= $totalcreditos){
                $subir = move_uploaded_file($nombretemporal,$ruta.$nombrefinal);
                if($subir){
                    $query = $con->insertar_actualizar("ordenes","?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?","usuarios","creditos = creditos - ?","idusuario = ?",$conjunto);
                    include dirname(__FILE__).'/../../../logica/portal/general/plantilla_ordenes.php';
                    $enviar = $mail->Enviar($correoOrigen,$aliasCorreo,$asunto,$body,$correo,$nombre,$imagenes);
                    if($query){
                        if($enviar == 'correo enviado'){
                            $HTML = ('Orden generada exitosamente',$ordenservicio);
                        }else{
                            $HTML = ('Orden generada exitosamente, pero a ocurrido un error al enviar el correo de respaldo',$ordenservicio);
                        }
                    }else{
                        $HTML = 'A ocurrido un error a la hora de generar la orden de servicio, favor intente nuevamente';
                        unlink($nombrefinal);
                    }
                }else{
                    $HTML = 'Error al subir el archivo';
                }
            }else{
                $HTML = ('Creditos insuficientes','SALDO INSUFICIENTE PARA EL SERVICIO SELECCIONADO');
            }
        }else{
            $HTML = $this->validar();
        }
    }else{
        $HTML = ('Creditos insuficientes','SALDO ACTUAL IGUAL O MENOR A 0');
    }
    return $HTML;

}   

Función ajax que procesa y envía los datos

function generar_orden(){
   //AQUI SE PASAN TODOS LOS VALORES DE LOS INPUT A UN FORM DATA, OMITIDOS AL SER MUCHOS
    $.ajax({  
        url:"<?php echo $dominioRaiz;?>logica/portal/ordenes/generar_orden.php",
        xhrFields: { withCredentials: true },
        method: "POST",
        dataType: "json",
        contentType:false,
        data: datos,
        processData:false,  
        success:function(data){   
            if(data.html1 == 'Existen campos vacios que deben ser llenados'){
                $('#faltan_datos').modal('show');
            }else if(data.html1 == 'Favor acepte los terminos y condiciones'){
                $('#aceptar_terminos').modal('show');                   
            }else if(data.html1 == 'Favor seleccione un archivo para subir'){
                $('#archivo_vacio').modal('show');
            }else if(data.html1(0) == 'Creditos insuficientes'){
                $('#mensaje_creditos').html(data.html1(1));
                $('#creditos_insuficientes').modal('show');
            }else if(data.html1(0) == 'Orden generada exitosamente'){
                $('#nro_orden').html(data.html1(1));
                $('#registro_correcto').modal('show');
                creditos();
                saldo_actual();
            }
            // console.log(data.html1);
        },
        xhr: function() {
            var xhr = new window.XMLHttpRequest();

            xhr.upload.addEventListener("progress", function(evt) {
            if (evt.lengthComputable) {
                var percentComplete = evt.loaded / evt.total;
                percentComplete = parseInt(percentComplete * 100);
                console.log(percentComplete);
            //   $(".xprogress").html("Progreso: "+ percentComplete +"%");
            //  $(".progressbar .carga").css("width" , percentComplete + "%");

            //   if (percentComplete === 100) {

            //   }

            }
            }, false);

            return xhr;
        },
    }); 
}