8ea779e5f5df] model deployment ID: [] 2025-05-05 10:43:55.633 [info] [fetchCompletions] request.response: [https://proxy.individual.githubcopilot.com/v1/engines/gpt-4o-copilot/completions] took 592.6488279998302 ms 2025-05-05 10:43:55.635 [info] [streamChoices] solution 0 returned. finish reason: [stop] 2025-05-05 10:43:55.637 [info] [streamChoices] request done: headerRequestId: [e5568023-1e2c-46f3-af25-069d6cf0b3f4] model deployment ID: [] 2025-05-05 10:43:56.379 [info] [fetchCompletions] request.response: [https://proxy.individual.githubcopilot.com/v1/engines/gpt-4o-copilot/completions] took 381.95936600025743 ms 2025-05-05 10:43:56.381 [info] [streamChoices] solution 0 returned. finish reason: [stop] 2025-05-05 10:43:56.383 [info] [streamChoices] request done: headerRequestId: [1224f128-aa9e-4c6a-a82a-27f3baef5aed] model deployment ID: [] 2025-05-05 10:43:59.248 [info] [fetchCompletions] request.response: [https://proxy.individual.githubcopilot.com/v1/engines/gpt-4o-copilot/completions] took 379.46587899979204 ms 2025-05-05 10:43:59.251 [info] [streamChoices] solution 0 returned. finish reason: [stop] 2025-05-05 10:43:59.254 [info] [streamChoices] request done: headerRequestId: [95a7275c-8bd4-446f-b09c-764136079033] model deployment ID: [] 2025-05-05 10:44:00.801 [info] [fetchCompletions] request.response: [https://proxy.individual.githubcopilot.com/v1/engines/gpt-4o-copilot/completions] took 591.6104780002497 ms 2025-05-05 10:44:00.803 [info] [streamChoices] solution 0 returned. finish reason: [stop] 2025-05-05 10:44:00.804 [info] [streamChoices] request done: headerRequestId: [6e7c47c5-2b91-4818-ae30-4ba272ccd740] model deployment ID: [] 2025-05-05 10:44:07.824 [info] [fetchCompletions] request.response: [https://proxy.individual.githubcopilot.com/v1/engines/gpt-4o-copilot/completions] took 392.1041799997911 ms 2025-05-05 10:44:07.826 [info] [streamChoices] solution 0 returned. finish reason: [stop] 2025-05-05 10:44:07.827 [info] [streamChoices] request done: headerRequestId: [eb5918e9-a258-43ce-adea-3379d339af2d] model deployment ID: [] 2025-05-05 10:44:10.493 [info] [fetchCompletions] request.response: [https://proxy.individual.githubcopilot.com/v1/engines/gpt-4o-copilot/completions] took 298.94387000007555 ms 2025-05-05 10:44:10.494 [info] [streamChoices] solution 0 returned. finish reason: [stop] 2025-05-05 10:44:10.498 [info] [streamChoices] request done: headerRequestId: [37be3b80-7f89-4bef-8835-ac4f5305660d] model deployment ID: [] 2025-05-05 10:44:16.484 [info] [fetchCompletions] request.response: [https://proxy.individual.githubcopilot.com/v1/engines/gpt-4o-copilot/completions] took 506.0273099998012 ms 2025-05-05 10:44:16.485 [info] [streamChoices] solution 0 returned. finish reason: [stop] 2025-05-05 10:44:16.487 [info] [streamChoices] request done: headerRequestId: [36d464bc-7aa2-4293-a9cd-d21f0f8d6e30] model deployment ID: [] 2025-05-05 10:44:18.397 [info] [fetchCompletions] request.response: [https://proxy.individual.githubcopilot.com/v1/engines/gpt-4o-copilot/completions] took 316.3816700000316 ms 2025-05-05 10:44:18.398 [info] [streamChoices] solution 0 returned. finish reason: [stop] 2025-05-05 10:44:18.401 [info] [streamChoices] request done: headerRequestId: [e3973431-2dc1-4366-b562-37deb43b29e8] model deployment ID: [] 2025-05-05 10:44:28.035 [info] [fetchCompletions] request.response: [https://proxy.individual.githubcopilot.com/v1/engines/gpt-4o-copilot/completions] took 514.9118439997546 ms 2025-05-05 10:44:28.037 [info] [streamChoices] request done: headerRequestId: [03c117e3-d8b3-4822-9489-c7647cda22a8] model deployment ID: [] 2025-05-05 10:44:28.322 [info] [fetchCompletions] request.response: [https://proxy.individual.githubcopilot.com/v1/engines/gpt-4o-copilot/completions] took 291.69905199995264 ms 2025-05-05 10:44:28.325 [info] [streamChoices] solution 0 returned. finish reason: [stop] 2025-05-05 10:44:28.329 [info] [streamChoices] request done: headerRequestId: [10875f5a-c9c3-457f-9c14-6f488d88abdb] model deployment ID: [] 2025-05-05 10:44:30.115 [info] [fetchCompletions] request.respon "301", "message" => "ERROR - [wsPolizasAnalytics] Parametros incompletos para el Servicio Web, faltan el appOwner"); $Resultado = json_encode($j_array); echo $Resultado; return $Resultado; } if($anio == "") { $j_array = array('code' => "302", "message" => "ERROR - [wsPolizasAnalytics] Parametros incompletos para el Servicio Web, faltan el Anio de vigencia"); $Resultado = json_encode($j_array); echo $Resultado; return $Resultado; } if($mes == "") { $j_array = array('code' => "303", "message" => "ERROR - [wsPolizasAnalytics] Parametros incompletos para el Servicio Web, faltan el Mes de vigencia"); $Resultado = json_encode($j_array); echo $Resultado; return $Resultado; } if($organi_id_Analytics == "") { $j_array = array('code' => "304", "message" => "ERROR - [wsPolizasAnalytics] Parametros incompletos para el Servicio Web, faltan el Organization ID de Analytics"); $Resultado = json_encode($j_array); echo $Resultado; return $Resultado; } if($RFC == "") { $j_array = array('code' => "305", "message" => "ERROR - [wsPolizasAnalytics] Parametros incompletos para el Servicio Web, faltan el RFC"); $Resultado = json_encode($j_array); echo $Resultado; return $Resultado; } if($idWorkspace == "") { $j_array = array('code' => "306", "message" => "ERROR - [wsPolizasAnalytics] Parametros incompletos para el Servicio Web, faltan el ID del workspace"); $Resultado = json_encode($j_array); echo $Resultado; return $Resultado; } if($idView == "") { $j_array = array('code' => "307", "message" => "ERROR - [wsPolizasAnalytics] Parametros incompletos para el Servicio Web, faltan el Organization ID de la vista"); $Resultado = json_encode($j_array); echo $Resultado; return $Resultado; } $dirBase = realpath("../"); ### DEFINICIÓN DE CONSTANTES ################################################### $SendaPEM = "archs_pem/"; $SendaXML = "archs_xml/"; $SendaZIP = "archs_zip/"; #---------------------------------------------------------------- #== Llamado para generar el token para donatello #---------------------------------------------------------------- $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => 'https://donatello.aptuslegal.app/oauth/token/'.$organi_id_Analytics, CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'GET', CURLOPT_HTTPHEADER => array( 'Authorization: Token e68d5a079f937ea29ad2ec5a5b105b75491a0e0c' ), )); $response = curl_exec($curl); curl_close($curl); // Decodificamos la respuesta JSON $data = json_decode($response, true); // Accedemos al valor de 'access_token de donatello' $access_token = $data['access_token']; #---------------------------------------------------------------- #== Hacemos el llamado para generar la obtención de los datos en la operación Bulk y obtenemos el Job ID. #---------------------------------------------------------------- $curl = curl_init(); $dia = obtenerDiasDelMes($mes); if($dia == "Formato de mes inválido."){ $j_array = array('code' => "309", "message" => "ERROR - [wsPolizasAnalytics] El formato del parámetro del mes no es valido"); $Resultado = json_encode($j_array); echo $Resultado; return $Resultado; } curl_setopt_array($curl, array( CURLOPT_URL => 'https://analyticsapi.zoho.com/restapi/v2/bulk/workspaces/'.$idWorkspace.'/views/'.$idView.'/data?CONFIG=%7B%22criteria%22%3A%22%5C%22Fecha%20de%20transaccion%5C%22%20between%20%27'.$anio.'-'.$mes.'-01%27%20and%20%27'.$anio.'-'.$mes.'-'.$dia.'%27%22%2C%20%22responseFormat%22%3A%22json%22%7D', CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'GET', CURLOPT_HTTPHEADER => array( 'ZANALYTICS-ORGID: '.$organi_id_Analytics, 'Authorization: Zoho-oauthtoken '.$access_token, 'Content-Type: application/json' ), )); $response = curl_exec($curl); curl_close($curl); $responseData = json_decode($response, true); ob_start(); echo '
'; print_r($responseData); echo ''; $debug_output = ob_get_clean(); // Acceder al 'jobId' $jobId = $responseData['data']['jobId']; #---------------------------------------------------------------- #== Obtenemos el status del JobId para saber si se puede descargar la respuesta #---------------------------------------------------------------- $jobStatus = "JOB IN PROGRESS"; while ($jobStatus === "JOB IN PROGRESS") { $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => 'https://analyticsapi.zoho.com/restapi/v2/bulk/workspaces/'.$idWorkspace.'/exportjobs/'.$jobId, CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'GET', CURLOPT_HTTPHEADER => array( 'ZANALYTICS-ORGID: '.$organi_id_Analytics, 'Authorization: Zoho-oauthtoken '.$access_token ), )); $response = curl_exec($curl); // Decodificar la respuesta JSON $responseData = json_decode($response, true); // Verificar el status del trabajo if (isset($responseData['data']['jobStatus'])) { $jobStatus = $responseData['data']['jobStatus']; } else { // Si no se encuentra jobStatus en la respuesta, salir del ciclo $j_array = array('code' => "311", "message" => "ERROR - [wsPolizasAnalytics] Error al esperar el Status de JobId de Analytics"); $Resultado = json_encode($j_array); echo $Resultado; return $Resultado; } // Esperar 5 segundos antes de volver a consultar sleep(5); } //Si se obtiene un status diferente al esperado lo interpreta como error if($jobStatus != "JOB COMPLETED"){ $j_array = array('code' => "312", "message" => "ERROR - [wsPolizasAnalytics] Error el Status del JobId inesperado"); $Resultado = json_encode($j_array); echo $Resultado; return $Resultado; } if (isset($responseData['data']['downloadUrl'])) { $downloadUrl = $responseData['data']['downloadUrl']; // echo "Download URL: " . $downloadUrl; } else { $j_array = array('code' => "313", "message" => "ERROR - [wsPolizasAnalytics] Error al obtener el downloadUrl de Analytics"); $Resultado = json_encode($j_array); echo $Resultado; return $Resultado; } #---------------------------------------------------------------- #== Llamado para la obtención de los datos en formato JSON de la vista de Analytics. #---------------------------------------------------------------- $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $downloadUrl, CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'GET', CURLOPT_HTTPHEADER => array( 'ZANALYTICS-ORGID: '.$organi_id_Analytics, 'Authorization: Zoho-oauthtoken '.$access_token ), )); $response = curl_exec($curl); curl_close($curl); // Decodificar el JSON $responseData = json_decode($response, true); // Verificar si el campo 'data' existe if (isset($responseData['data'])) { #---------------------------------------------------------------- #== Creación de la variable de tipo DOM, aquí se conforma el XML a timbrar posteriormente. #---------------------------------------------------------------- $xml = new DOMdocument('1.0', 'UTF-8'); $root = $xml->createElement("PLZ:Polizas"); $root = $xml->appendChild($root); #== Se crea e inserta el primer nodo donde se declaran los namespaces ====== cargaAttNodo( $root, array("xsi:schemaLocation"=>"http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/PolizasPeriodo/PolizasPeriodo_1_3.xsd", "xmlns:PLZ"=>"http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/PolizasPeriodo", "xmlns:xsi"=>"http://www.w3.org/2001/XMLSchema") ); #== Rutina de integración de nodos ========================================= cargaAttNodo($root, array( "Version"=>"1.3", "RFC"=>$RFC, "Mes"=>$mes, "Anio"=>$anio, "TipoSolicitud"=> $TipoSolicitud, "NumOrden"=> $txbNumeroOrden ) ); $sumTotalDebe = 0; $sumTotalHaber = 0; $totalDebe = 0; $totalHaber = 0; $polizaControl = ""; $polizaNodo = null; // Variable para mantener la referencia al nodo Poliza $numeroTotalPolizas = 0; $array = array_reverse($responseData['data']); foreach ($array as $item) { // Asignar cada valor a variables $tipoPoliza = $item['Tipo Poliza']; $transaccion = $item['Transaccion']; $fechaTransaccion = str_replace('.', '-', $item['Fecha de transaccion']); $idCuenta = $item['ID de la cuenta']; $nombre = $item['Nombre']; $debe = $item['Debe']; $haber = $item['Haber']; $creditoDebitoTotal = $item['Credito-Debito - Total']; $debitoCreditoTotal = $item['Debito-Credito Total']; $concepto = $item['Concepto']; $numCta = $item['NumCta']; $UUID = $item['UUID']; $rfc = $item['RFC']; $monto = $item['Monto total']; // Cuando detectas una nueva transacción (nueva póliza) if($transaccion != $polizaControl){ // Crear una nueva póliza $polizaControl = $transaccion; $Poliza = $xml->createElement("PLZ:Poliza"); $polizaNodo = $root->appendChild($Poliza); cargaAttNodo($polizaNodo, array( "NumUnIdenPol" => $transaccion, "Fecha" => $fechaTransaccion, "Concepto" => $tipoPoliza )); // Reiniciar los totales para la nueva póliza $totalDebe = 0; $totalHaber = 0; } // Crear un nodo Transaccion y agregarlo a la póliza actual $transaccion = $xml->createElement("PLZ:Transaccion"); $nodo = $Poliza->appendChild($transaccion); cargaAttNodo($nodo, array( "NumCta" => $numCta, "DesCta" => $nombre, "Concepto" => $concepto, "Debe" => $debe, "Haber" => $haber )); // Crear nodo PLZ:CompNal y agregarlo dentro del nodo Transaccion si existe alguno de estos valores, de lo contrario no se agrega if($UUID != "" || $rfc != "" || $monto != ""){ $compNal = $xml->createElement("PLZ:CompNal"); $compNal = $nodo->appendChild($compNal); cargaAttNodo($compNal, array( "UUID_CFDI" => $UUID, "RFC" => $rfc, "MontoTotal" => $monto )); } // Acumular los valores de Debe y Haber $totalDebe += (float)$debe; $totalHaber += (float)$haber; // Acumular los totales generales $sumTotalDebe += (float)$debe; $sumTotalHaber += (float)$haber; $numeroTotalPolizas += 1; } // Establecer el tipo de contenido a XML y devolver el contenido // header('Content-Type: application/xml; charset=utf-8'); // echo $xml->saveXML(); #=== Se guarda el archivo .XML del Catalogo de Cuentas ======================= $file_name_with_full_path = '/var/www/html/aptusContaElec/archs_xml/'.$RFC.$anio.$mes."PL.xml"; #=== Si existe el archivo XML se elimina para crear el nuevo ======================= if(!file_exists($file_name_with_full_path)){ unlink($file_name_with_full_path); } #=== Se guarda el archivo XML creado ======================= $polizaXML = $xml->saveXML(); $xml->formatOutput = true; $xml->save($file_name_with_full_path); unset($xml); #=== Se dan permisos de escritura al archivo .xml. ========================= chmod($file_name_with_full_path, 0777); #=== Se procede a crear el archivo ZIP del Catalogo de Cuentas ========================= $zip = new ZipArchive(); $nombreArchivoZip = '/var/www/html/aptusContaElec/archs_zip/'.$RFC.$anio.$mes."PL.zip"; $nameArchZip = $RFC.$anio.$mes."PL.zip"; #=== Si existe el archivo ZIP se elimina para crear el nuevo ======================= if(!file_exists($nombreArchivoZip)){ unlink($nombreArchivoZip); } if (!$zip->open($nombreArchivoZip, ZipArchive::CREATE | ZipArchive::OVERWRITE)) { exit("Error abriendo ZIP en $nombreArchivoZip"); } $nombre = basename($file_name_with_full_path); $zip->addFile($file_name_with_full_path, $nombre); $resultado = $zip->close(); if ($resultado) { } else { $j_array = array('code' => "318", "message" => "ERROR - [wsPolizasAnalytics] Error al crear el archivo ZIP"); $Resultado = json_encode($j_array); echo $Resultado; return $Resultado; } #---------------------------------------------------------------- # Se sube archivo ZIP a Workdrive #---------------------------------------------------------------- $woa_access_token = oauth($appOwner, 'ZWorkrdv', $woa_RefreshToken, $woa_ClientId, $woa_ClientSecret, $woa_RedirectUri, $woa_GrantType, $woa_AuthUrl); $urlWorkdrv = 'https://workdrive.zoho.com/api/v1/upload?parent_id='.$wdrv_parent_id.'&filename='.$nameArchZip.'&override-name-exist=true'; $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $urlWorkdrv, CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS => array('content'=> new CURLFILE($nombreArchivoZip)), CURLOPT_HTTPHEADER => array('Authorization: Zoho-oauthtoken '.$woa_access_token ), ) ); $response = curl_exec($curl); curl_close($curl); #=== FIN DEL PROCESO ======================= $j_array = array('code' => "200", 'message' => "Proceso de creacion de archivo de pólizas del periodo exitoso", 'xml_file_name' => $RFC.$anio.$mes."PL.xml", 'zip_file_name' => $RFC.$anio.$mes."PL.zip",'Total de Polizas' => $numeroTotalPolizas,'Total Debe' =>number_format($sumTotalDebe, 2, '.', ''),'Total Haber' => number_format($sumTotalHaber, 2, '.', '')); $Resultado = json_encode($j_array); echo $Resultado; return $Resultado; } else { $j_array = array('code' => "315", "message" => "ERROR - [wsPolizasAnalytics] No se obtuvieron datos de la vista"); $Resultado = json_encode($j_array); echo $Resultado; return $Resultado; } ### FUNCIONES DEL MÓDULO ######################################################### # Función que integra los nodos al archivo .XML function cargaAttNodo(&$nodo, $attr){ global $xmldoc; foreach ($attr as $key => $val){ $val = preg_replace('/\s\s+/', ' ', $val); $val = trim($val); if (strlen($val)>0){ $val = utf8_encode(str_replace("|","/",$val)); $nodo->setAttribute($key,$val); } } } function obtenerDiasDelMes($mes) { // Validar que el parámetro sea una cadena con dos dígitos if (!preg_match('/^\d{2}$/', $mes)) { return "Formato de mes inválido."; } // Obtener el año actual $anio = date("Y"); // Usar la función `cal_days_in_month` para obtener la cantidad de días del mes $dias = cal_days_in_month(CAL_GREGORIAN, intval($mes), $anio); return $dias; }