ilot/completions] took 348.68808100000024 ms 2025-05-05 13:48:24.472 [info] [streamChoices] solution 0 returned. finish reason: [stop] 2025-05-05 13:48:24.474 [info] [streamChoices] request done: headerRequestId: [38cc47ae-d892-40ec-9d3d-70b836f870ca] model deployment ID: [] 2025-05-05 13:48:56.020 [info] [fetchCompletions] request.response: [https://proxy.individual.githubcopilot.com/v1/engines/gpt-4o-copilot/completions] took 380.0173570010811 ms 2025-05-05 13:48:56.022 [info] [streamChoices] solution 0 returned. finish reason: [stop] 2025-05-05 13:48:56.023 [info] [streamChoices] request done: headerRequestId: [478b0044-bad9-43f7-9db9-84fefdff578b] model deployment ID: [] 2025-05-05 13:49:03.171 [info] [fetchCompletions] request.response: [https://proxy.individual.githubcopilot.com/v1/engines/gpt-4o-copilot/completions] took 620.0514080002904 ms 2025-05-05 13:49:03.173 [info] [streamChoices] solution 0 returned. finish reason: [stop] 2025-05-05 13:49:03.174 [info] [streamChoices] request done: headerRequestId: [809cb7fd-e572-4558-bce4-f3624e01a307] model deployment ID: [] 2025-05-05 13:50:17.104 [info] [fetchCompletions] request.response: [https://proxy.individual.githubcopilot.com/v1/engines/gpt-4o-copilot/completions] took 580.8991209995002 ms 2025-05-05 13:50:17.107 [info] [streamChoices] request done: headerRequestId: [ce2a1246-4ef8-442f-9631-2a09f60abf7a] model deployment ID: [] 2025-05-05 13:50:17.112 [info] [fetchCompletions] request.response: [https://proxy.individual.githubcopilot.com/v1/engines/gpt-4o-copilot/completions] took 384.8809099998325 ms 2025-05-05 13:50:17.114 [info] [streamChoices] solution 0 returned. finish reason: [stop] 2025-05-05 13:50:17.115 [info] [streamChoices] request done: headerRequestId: [9c596ac6-66a6-4e8f-a0fa-835f281ca2e6] model deployment ID: [] 2025-05-05 13:50:17.127 [info] [fetchCompletions] request.response: [https://proxy.individual.githubcopilot.com/v1/engines/gpt-4o-copilot/completions] took 900.2564310003072 ms 2025-05-05 13:50:17.128 [info] [streamChoices] request done: headerRequestId: [34545419-18a7-42cf-8401-3ef35d6f85d9] model deployment ID: [] 2025-05-05 13:50:19.107 [info] [fetchCompletions] request.response: [https://proxy.individual.githubcopilot.com/v1/engines/gpt-4o-copilot/completions] took 294.7287289984524 ms 2025-05-05 13:50:19.109 [info] [streamChoices] request done: headerRequestId: [cac85f79-62c6-46f4-8345-b10cbfdf5ca2] model deployment ID: [] 2025-05-05 13:50:19.296 [info] [fetchCompletions] request.response: [https://proxy.individual.githubcopilot.com/v1/engines/gpt-4o-copilot/completions] took 183.60912000015378 ms 2025-05-05 13:50:19.298 [info] [streamChoices] solution 0 returned. finish reason: [stop] 2025-05-05 13:50:19.298 [info] [streamChoices] request done: headerRequestId: [dc414c21-3084-4099-9c42-25ca780f0ab3] model deployment ID: [] 2025-05-05 13:51:34.243 [info] [fetchCompletions] request.response: [https://proxy.individual.githubcopilot.com/v1/engines/gpt-4o-copilot/completions] took 298.3448719996959 ms 2025-05-05 13:51:34.244 [info] [streamChoices] solution 0 returned. finish reason: [stop] 2025-05-05 13:51:34.246 [info] [streamChoices] request done: headerRequestId: [f6fefb0a-e838-48eb-b216-d4c2efa29c71] model deployment ID: [] 2025-05-05 13:52:52.408 [info] [fetchCompletions] request.response: [https://proxy.individual.githubcopilot.com/v1/engines/gpt-4o-copilot/completions] took 230.17692800052464 ms 2025-05-05 13:52:52.409 [info] [streamChoices] solution 0 returned. finish reason: [stop] 2025-05-05 13:52:52.411 [info] [streamChoices] request done: headerRequestId: [9c2b60f0-a870-4adf-9ed2-792b7717df9f] model deployment ID: [] 2025-05-05 13:54:49.302 [info] [fetchCompletions] request.response: [https://proxy.individual.githubcopilot.com/v1/engines/gpt-4o-copilot/completions] took 299.83326200023293 ms 2025-05-05 13:54:49.305 [info] [streamChoices] solution 0 returned. finish reason: [stop] 2025-05-05 13:54:49.307 [info] [streamChoices] request done: headerRequestId: [aa205900-e0be-4e37-a0bd-bd0ec34b5d77] model deployment ID: [] 2025-05 true, CURLOPT_HTTPHEADER => ["Authorization: Zoho-oauthtoken {$zbToken}"] ]); $resp = curl_exec($ch); curl_close($ch); $catalogo = json_decode($resp, true)['chartofaccounts'] ?? []; if (empty($catalogo)) { showMessage('Error', 'No se obtuvo catálogo de cuentas.'); return; } // 4. Bulk export de transacciones desde Zoho Analytics // (copia lógica de getPolizas: obtener jobId, poll, descargar) $analyticsOrg = '722699151'; // tu org Analytics $workspace = '2296733000000004013'; $view = '2296733000030848002'; // obtener token Analytics (donatello) $don = json_decode( file_get_contents("https://donatello.aptuslegal.app/oauth/token/{$analyticsOrg}"), true ); $anToken = $don['access_token'] ?? ''; if (!$anToken) { showMessage('Error', 'No token Analytics'); return; } // export bulk $dias = cal_days_in_month(CAL_GREGORIAN, intval($mesCata), intval($anioCat)); $config = urlencode(json_encode([ "criteria" => "\"Fecha de transaccion\" between '{$anioCat}-{$mesCata}-01' and '{$anioCat}-{$mesCata}-{$dias}'", "responseFormat"=> "json" ])); $bulkUrl = "https://analyticsapi.zoho.com/restapi/v2/bulk" . "/workspaces/{$workspace}/views/{$view}/data?CONFIG={$config}"; $ch = curl_init($bulkUrl); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "ZANALYTICS-ORGID: {$analyticsOrg}", "Authorization: Zoho-oauthtoken {$anToken}", "Content-Type: application/json" ] ]); $j1 = json_decode(curl_exec($ch), true); curl_close($ch); $jobId = $j1['data']['jobId'] ?? ''; if (!$jobId) { showMessage('Error', 'No se inició export Analytics'); return; } // poll hasta completar do { sleep(3); $chk = curl_init("https://analyticsapi.zoho.com/restapi/v2/bulk" . "/workspaces/{$workspace}/exportjobs/{$jobId}"); curl_setopt_array($chk, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "ZANALYTICS-ORGID: {$analyticsOrg}", "Authorization: Zoho-oauthtoken {$anToken}" ] ]); $js = json_decode(curl_exec($chk), true); curl_close($chk); $status = $js['data']['jobStatus'] ?? 'ERROR'; if ($status==='ERROR') { showMessage('Error','Error en job Analytics'); return; } } while ($status !== 'JOB COMPLETED'); $downloadUrl = $js['data']['downloadUrl'] ?? ''; if (!$downloadUrl) { showMessage('Error','No download URL Analytics'); return; } // descargar registros $ch = curl_init($downloadUrl); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "ZANALYTICS-ORGID: {$analyticsOrg}", "Authorization: Zoho-oauthtoken {$anToken}" ] ]); $rows = json_decode(curl_exec($ch), true)['data'] ?? []; curl_close($ch); // 5. Agrupar transacciones por NumCta $txPorCta = []; foreach ($rows as $r) { $cta = $r['NumCta'] ?? ''; if (!$cta) continue; $txPorCta[$cta][] = [ 'Fecha' => str_replace('.', '-', $r['Fecha de transaccion']), 'NumUnIdenPol' => $r['Transaccion'], 'Concepto' => $r['Concepto'], 'Debe' => (float)$r['Debe'], 'Haber' => (float)$r['Haber'] ]; } // 6. Crear el DOM del Auxiliar de Cuentas $xml = new DOMDocument('1.0','UTF-8'); $xml->formatOutput = true; $root = $xml->createElementNS( 'http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/AuxiliarCtas', 'AuxiliarCtas:AuxiliarCtas' ); $xml->appendChild($root); // namespace + schemaLocation $root->setAttribute('xmlns:xsi','http://www.w3.org/2001/XMLSchema-instance'); $root->setAttribute( 'xsi:schemaLocation', 'http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/AuxiliarCtas ' .'http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/AuxiliarCtas/AuxiliarCtas_1_3.xsd' ); // atributos de cabecera $root->setAttribute('Version','1.3'); $root->setAttribute('RFC', $rfc); $root->setAttribute('Mes', str_pad($mesCata,2,'0',STR_PAD_LEFT)); $root->setAttribute('Anio',$anioCat); $root->setAttribute('TipoSolicitud',$tipoSolicitud); $root->setAttribute('NumOrden',$numOrden); // 7. Recorrer catálogo y agregar nodos foreach ($catalogo as $ctaInfo) { $numCta = $ctaInfo['account_code'] ?? ''; if (!$numCta || empty($txPorCta[$numCta])) continue; // $nC = $xml->createElement('AuxiliarCtas:Cuenta'); $root->appendChild($nC); $nC->setAttribute('NumCta', $numCta); $nC->setAttribute('DesCta', utf8_decode(substr($ctaInfo['account_name'],11))); $nC->setAttribute('SaldoIni','0.00'); $nC->setAttribute('SaldoFin','0.00'); // foreach ($txPorCta[$numCta] as $t) { $nD = $xml->createElement('AuxiliarCtas:DetalleAux'); $nC->appendChild($nD); $nD->setAttribute('Fecha', $t['Fecha']); $nD->setAttribute('NumUnIdenPol', $t['NumUnIdenPol']); $nD->setAttribute('Concepto', $t['Concepto']); $nD->setAttribute('Debe', number_format($t['Debe'],2,'.','')); $nD->setAttribute('Haber', number_format($t['Haber'],2,'.','')); } } // 8. Guardar XML y ZIP $base = __DIR__ . '/archs_xml/'; $fnXml = "{$rfc}{$anioCat}{$mesCata}AC.xml"; $fnZip = "{$rfc}{$anioCat}{$mesCata}AC.zip"; $xml->save($base . $fnXml); chmod($base . $fnXml, 0777); $zip = new ZipArchive(); $zip->open(__DIR__ . '/archs_zip/' . $fnZip, ZipArchive::CREATE|ZipArchive::OVERWRITE); $zip->addFile($base . $fnXml, $fnXml); $zip->close(); // 9. Devolver nombres de archivo para frontend echo json_encode([ 'code' => '200', 'xml_file' => $fnXml, 'zip_file' => $fnZip