Autosave: 20260707-030605

This commit is contained in:
Flatlogic Bot 2026-07-07 03:05:06 +00:00
parent 2cde551bb9
commit 17c381597c
7 changed files with 122 additions and 58 deletions

View File

@ -206,8 +206,14 @@ include 'layout_header.php';
} }
?></td> ?></td>
<td> <td>
<?php if (!empty($pedido['voucher_restante_path'])): ?> <?php
<a href="<?php echo htmlspecialchars($pedido['voucher_restante_path']); ?>" target="_blank">Ver</a> $voucherRestantePath = $pedido['voucher_restante_path'] ?? '';
$voucherRestanteExists = $voucherRestantePath !== '' && file_exists(__DIR__ . '/' . $voucherRestantePath);
?>
<?php if ($voucherRestantePath && $voucherRestanteExists): ?>
<a href="<?php echo htmlspecialchars($voucherRestantePath); ?>" target="_blank" rel="noopener noreferrer">Ver</a>
<?php elseif (!empty($voucherRestantePath)): ?>
<span class="text-muted">No disponible</span>
<?php else: ?> <?php else: ?>
N/A N/A
<?php endif; ?> <?php endif; ?>

View File

@ -234,8 +234,14 @@ include 'layout_header.php';
<td><?php echo htmlspecialchars($pedido['asesor_nombre'] ?? 'N/A'); ?></td> <td><?php echo htmlspecialchars($pedido['asesor_nombre'] ?? 'N/A'); ?></td>
<td><?php echo htmlspecialchars($pedido['created_at']); ?></td> <td><?php echo htmlspecialchars($pedido['created_at']); ?></td>
<td> <td>
<?php if (!empty($pedido['voucher_restante_path'])): ?> <?php
<a href="<?php echo htmlspecialchars($pedido['voucher_restante_path']); ?>" target="_blank">Ver</a> $voucherRestantePath = $pedido['voucher_restante_path'] ?? '';
$voucherRestanteExists = $voucherRestantePath !== '' && file_exists(__DIR__ . '/' . $voucherRestantePath);
?>
<?php if ($voucherRestantePath && $voucherRestanteExists): ?>
<a href="<?php echo htmlspecialchars($voucherRestantePath); ?>" target="_blank" rel="noopener noreferrer">Ver</a>
<?php elseif (!empty($voucherRestantePath)): ?>
<span class="text-muted">No disponible</span>
<?php else: ?> <?php else: ?>
N/A N/A
<?php endif; ?> <?php endif; ?>

View File

@ -323,18 +323,34 @@ include 'layout_header.php';
<div class="col-md-6 mb-3"> <div class="col-md-6 mb-3">
<label for="voucher_adelanto" class="form-label">Voucher de Adelanto</label> <label for="voucher_adelanto" class="form-label">Voucher de Adelanto</label>
<input type="file" class="form-control" id="voucher_adelanto" name="voucher_adelanto"> <input type="file" class="form-control" id="voucher_adelanto" name="voucher_adelanto">
<?php if (!empty($pedido['voucher_adelanto_path'])): ?> <?php
$voucherAdelantoPath = $pedido['voucher_adelanto_path'] ?? '';
$voucherAdelantoExists = $voucherAdelantoPath !== '' && file_exists(__DIR__ . '/' . $voucherAdelantoPath);
?>
<?php if ($voucherAdelantoPath && $voucherAdelantoExists): ?>
<div class="mt-2"> <div class="mt-2">
<a href="<?php echo htmlspecialchars($pedido['voucher_adelanto_path']); ?>" target="_blank">Ver voucher actual</a> <a href="<?php echo htmlspecialchars($voucherAdelantoPath); ?>" target="_blank" rel="noopener noreferrer">Ver voucher actual</a>
</div>
<?php elseif (!empty($voucherAdelantoPath)): ?>
<div class="mt-2 text-muted" style="font-size: 0.9rem;">
Voucher no disponible (archivo no encontrado).
</div> </div>
<?php endif; ?> <?php endif; ?>
</div> </div>
<div class="col-md-6 mb-3"> <div class="col-md-6 mb-3">
<label for="voucher_restante" class="form-label">Voucher de Pago Restante</label> <label for="voucher_restante" class="form-label">Voucher de Pago Restante</label>
<input type="file" class="form-control" id="voucher_restante" name="voucher_restante"> <input type="file" class="form-control" id="voucher_restante" name="voucher_restante">
<?php if (!empty($pedido['voucher_restante_path'])): ?> <?php
$voucherRestantePath = $pedido['voucher_restante_path'] ?? '';
$voucherRestanteExists = $voucherRestantePath !== '' && file_exists(__DIR__ . '/' . $voucherRestantePath);
?>
<?php if ($voucherRestantePath && $voucherRestanteExists): ?>
<div class="mt-2"> <div class="mt-2">
<a href="<?php echo htmlspecialchars($pedido['voucher_restante_path']); ?>" target="_blank">Ver voucher actual</a> <a href="<?php echo htmlspecialchars($voucherRestantePath); ?>" target="_blank" rel="noopener noreferrer">Ver voucher actual</a>
</div>
<?php elseif (!empty($voucherRestantePath)): ?>
<div class="mt-2 text-muted" style="font-size: 0.9rem;">
Voucher no disponible (archivo no encontrado).
</div> </div>
<?php endif; ?> <?php endif; ?>
</div> </div>

View File

@ -235,8 +235,14 @@ include 'layout_header.php';
<?php if ($user_role !== 'Asesor'): ?><td><?php echo htmlspecialchars($pedido['asesor_nombre'] ?? 'N/A'); ?></td><?php endif; ?> <?php if ($user_role !== 'Asesor'): ?><td><?php echo htmlspecialchars($pedido['asesor_nombre'] ?? 'N/A'); ?></td><?php endif; ?>
<td><?php echo htmlspecialchars($pedido['created_at']); ?></td> <td><?php echo htmlspecialchars($pedido['created_at']); ?></td>
<td> <td>
<?php if (!empty($pedido['voucher_restante_path'])): ?> <?php
<a href="<?php echo htmlspecialchars($pedido['voucher_restante_path']); ?>" target="_blank">Ver</a> $voucherRestantePath = $pedido['voucher_restante_path'] ?? '';
$voucherRestanteExists = $voucherRestantePath !== '' && file_exists(__DIR__ . '/' . $voucherRestantePath);
?>
<?php if ($voucherRestantePath && $voucherRestanteExists): ?>
<a href="<?php echo htmlspecialchars($voucherRestantePath); ?>" target="_blank" rel="noopener noreferrer">Ver</a>
<?php elseif (!empty($voucherRestantePath)): ?>
<span class="text-muted">No disponible</span>
<?php else: ?> <?php else: ?>
N/A N/A
<?php endif; ?> <?php endif; ?>

View File

@ -274,10 +274,16 @@ include 'layout_header.php';
<?php if ($user_role !== 'Asesor'): ?><td><?php echo htmlspecialchars($pedido['asesor_nombre'] ?? 'N/A'); ?></td><?php endif; ?> <?php if ($user_role !== 'Asesor'): ?><td><?php echo htmlspecialchars($pedido['asesor_nombre'] ?? 'N/A'); ?></td><?php endif; ?>
<td><?php echo htmlspecialchars($pedido['created_at']); ?></td> <td><?php echo htmlspecialchars($pedido['created_at']); ?></td>
<td> <td>
<?php if (!empty($pedido['voucher_restante_path'])): ?> <?php
<a href="<?php echo htmlspecialchars($pedido['voucher_restante_path']); ?>" target="_blank">Ver</a> $voucherRestantePath = $pedido['voucher_restante_path'] ?? '';
<?php else: $voucherRestanteExists = $voucherRestantePath !== '' && file_exists(__DIR__ . '/' . $voucherRestantePath);
?>N/A ?>
<?php if ($voucherRestantePath && $voucherRestanteExists): ?>
<a href="<?php echo htmlspecialchars($voucherRestantePath); ?>" target="_blank" rel="noopener noreferrer">Ver</a>
<?php elseif (!empty($voucherRestantePath)): ?>
<span class="text-muted">No disponible</span>
<?php else: ?>
N/A
<?php endif; ?> <?php endif; ?>
</td> </td>
<td> <td>
@ -565,16 +571,27 @@ document.addEventListener('DOMContentLoaded', function() {
fetch(`shalom_api.php?orderNumber=${encodeURIComponent(orderNumber)}&orderCode=${encodeURIComponent(orderCode)}`) fetch(`shalom_api.php?orderNumber=${encodeURIComponent(orderNumber)}&orderCode=${encodeURIComponent(orderCode)}`)
.then(async response => { .then(async response => {
let rawText = '';
try { rawText = await response.text(); } catch (e) { /* ignore */ }
let data = null; let data = null;
try { data = await response.json(); } catch (e) { /* ignore */ } if (rawText) {
try { data = JSON.parse(rawText); } catch (e) { /* ignore */ }
}
if (!response.ok) { if (!response.ok) {
const msg = (data && data.error) ? data.error : `HTTP ${response.status}`; const msg =
const details = (data && data.details) ? data.details : ''; (data && data.error) ? data.error :
rawText ? (rawText.length > 140 ? rawText.slice(0, 140) + '…' : rawText) :
`HTTP ${response.status}`;
let detailsText = ''; let detailsText = '';
if (details) { if (data && Object.prototype.hasOwnProperty.call(data, 'details') && data.details !== undefined && data.details !== null && data.details !== '') {
const details = data.details;
detailsText = typeof details === 'string' ? details : JSON.stringify(details); detailsText = typeof details === 'string' ? details : JSON.stringify(details);
} else if (rawText) {
detailsText = rawText;
} }
// Devolvemos el error dentro de JSON para que el siguiente then lo pinte como Error // Devolvemos el error dentro de JSON para que el siguiente then lo pinte como Error
@ -607,8 +624,12 @@ document.addEventListener('DOMContentLoaded', function() {
badgeText = `Shalom ${codeMatch2[1]}`; badgeText = `Shalom ${codeMatch2[1]}`;
} else { } else {
const isTimeout = /timed out|timeout/i.test(errText) || /timed out|timeout/i.test(details); const isTimeout = /timed out|timeout/i.test(errText) || /timed out|timeout/i.test(details);
const httpMatch = errText.match(/HTTP\s*(\d{3})/i);
if (isTimeout) { if (isTimeout) {
badgeText = 'Shalom timeout'; badgeText = 'Shalom timeout';
} else if (httpMatch) {
badgeText = `Shalom HTTP ${httpMatch[1]}`;
} else if (/comunicaci[]n/i.test(errText)) { } else if (/comunicaci[]n/i.test(errText)) {
badgeText = 'Error API Shalom'; badgeText = 'Error API Shalom';
} else { } else {

View File

@ -9,23 +9,32 @@ require_once 'db/config.php';
function handle_upload($file_key, $current_path = null) { function handle_upload($file_key, $current_path = null) {
if (isset($_FILES[$file_key]) && $_FILES[$file_key]['error'] === UPLOAD_ERR_OK) { if (isset($_FILES[$file_key]) && $_FILES[$file_key]['error'] === UPLOAD_ERR_OK) {
$upload_dir = 'assets/uploads/vouchers/'; $upload_dir_rel = 'assets/uploads/vouchers/';
if (!is_dir($upload_dir)) { $upload_dir_abs = __DIR__ . '/' . $upload_dir_rel;
mkdir($upload_dir, 0775, true);
}
if ($current_path && file_exists($current_path)) { if (!is_dir($upload_dir_abs)) {
unlink($current_path); mkdir($upload_dir_abs, 0775, true);
} }
$filename = uniqid() . '-' . basename($_FILES[$file_key]['name']); $filename = uniqid() . '-' . basename($_FILES[$file_key]['name']);
$path = $upload_dir . $filename; $path_abs = $upload_dir_abs . $filename;
$path_rel = $upload_dir_rel . $filename;
if (move_uploaded_file($_FILES[$file_key]['tmp_name'], $path)) { // Move first; only delete the previous file after a successful upload.
return $path; if (move_uploaded_file($_FILES[$file_key]['tmp_name'], $path_abs)) {
if (!empty($current_path)) {
$current_abs = __DIR__ . '/' . $current_path;
if (file_exists($current_abs)) {
unlink($current_abs);
} }
}
return $path_rel;
}
// Upload failed: keep the previous path (if any)
return $current_path; return $current_path;
} }
return $current_path; return $current_path;
} }

View File

@ -1,14 +1,26 @@
<?php <?php
header('Content-Type: application/json'); header('Content-Type: application/json');
// Make sure we ALWAYS return valid JSON from this endpoint, even when
// upstream error bodies include invalid UTF-8 bytes.
$jsonOptions = JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE | JSON_PARTIAL_OUTPUT_ON_ERROR;
function respond_json(int $statusCode, array $payload, int $jsonOptions): void {
http_response_code($statusCode);
$json = json_encode($payload, $jsonOptions);
if ($json === false) {
$json = '{"error":"Error serializando la respuesta"}';
}
echo $json;
exit;
}
// Inputs // Inputs
$orderNumber = trim($_GET['orderNumber'] ?? ''); $orderNumber = trim($_GET['orderNumber'] ?? '');
$orderCode = trim($_GET['orderCode'] ?? ''); $orderCode = trim($_GET['orderCode'] ?? '');
if ($orderNumber === '' || $orderCode === '') { if ($orderNumber === '' || $orderCode === '') {
http_response_code(400); respond_json(400, ['error' => 'Número de orden y código de orden son requeridos.'], $jsonOptions);
echo json_encode(['error' => 'Número de orden y código de orden son requeridos.']);
exit;
} }
// Load env from executor/.env (helps when Apache/PHP doesn't export .env vars) // Load env from executor/.env (helps when Apache/PHP doesn't export .env vars)
@ -36,7 +48,6 @@ function load_dotenv_if_needed(array $keys): void {
// Strip potential surrounding quotes // Strip potential surrounding quotes
$v = trim($v, "\"' "); $v = trim($v, "\"' ");
// Do not override existing process env // Do not override existing process env
if (getenv($k) === false || getenv($k) === '') { if (getenv($k) === false || getenv($k) === '') {
putenv("{$k}={$v}"); putenv("{$k}={$v}");
@ -70,11 +81,9 @@ if (!$apiKey) {
} }
if (!$apiKey) { if (!$apiKey) {
http_response_code(500); respond_json(500, [
echo json_encode([
'error' => 'Falta SHALOM_API_KEY. Configura la clave en Configuración General (Administrador) o en tu .env para poder consultar el tracking.', 'error' => 'Falta SHALOM_API_KEY. Configura la clave en Configuración General (Administrador) o en tu .env para poder consultar el tracking.',
]); ], $jsonOptions);
exit;
} }
$url = 'https://shalom-api.lat/api/track'; $url = 'https://shalom-api.lat/api/track';
@ -86,9 +95,7 @@ $postData = [
$jsonData = json_encode($postData, JSON_UNESCAPED_UNICODE); $jsonData = json_encode($postData, JSON_UNESCAPED_UNICODE);
if ($jsonData === false) { if ($jsonData === false) {
http_response_code(500); respond_json(500, ['error' => 'Error serializando la solicitud a Shalom.'], $jsonOptions);
echo json_encode(['error' => 'Error serializando la solicitud a Shalom.']);
exit;
} }
$ch = curl_init(); $ch = curl_init();
@ -116,27 +123,21 @@ $curlError = curl_error($ch);
curl_close($ch); curl_close($ch);
if ($curlError) { if ($curlError) {
http_response_code(502); respond_json(502, [
echo json_encode([
'error' => 'Error en la comunicación con la API de Shalom', 'error' => 'Error en la comunicación con la API de Shalom',
'details' => $curlError, 'details' => $curlError,
]); ], $jsonOptions);
exit;
} }
if ($response === false || $response === null || $response === '') { if ($response === false || $response === null || $response === '') {
http_response_code(502); respond_json(502, [
echo json_encode([
'error' => 'Shalom no devolvió respuesta', 'error' => 'Shalom no devolvió respuesta',
'http_code' => $httpCode ?: null, 'http_code' => $httpCode ?: null,
]); ], $jsonOptions);
exit;
} }
// Error HTTP del proveedor // Error HTTP del proveedor
if ($httpCode >= 400) { if ($httpCode >= 400) {
http_response_code($httpCode);
$errorBody = json_decode($response, true); $errorBody = json_decode($response, true);
$shMessage = null; $shMessage = null;
@ -145,20 +146,19 @@ if ($httpCode >= 400) {
} }
if ($shMessage) { if ($shMessage) {
echo json_encode([ respond_json($httpCode, [
'error' => "Error de la API de Shalom: {$shMessage}", 'error' => "Error de la API de Shalom: {$shMessage}",
'http_code' => $httpCode, 'http_code' => $httpCode,
'details' => $errorBody ?: $response, 'details' => $errorBody ?: $response,
]); ], $jsonOptions);
} else { }
echo json_encode([
respond_json($httpCode, [
'error' => "Error de la API de Shalom (código {$httpCode}).", 'error' => "Error de la API de Shalom (código {$httpCode}).",
'http_code' => $httpCode, 'http_code' => $httpCode,
'details' => $response, 'details' => $response,
]); ], $jsonOptions);
}
exit;
} }
// OK: devolvemos tal cual lo que responde Shalom (la UI espera JSON con search/statuses) // OK: devolvemos tal cual lo que responde Shalom (la UI espera JSON)
echo $response; echo $response;