Files
rips_manager/app/templates/terceros.html
T
Lizandro GuarnizoandClaude Sonnet 4.6 b3b283a7d0 fix: syntaxHighlight regex adding spaces inside time values
The number regex /:(\s*)(\d+)/ was matching colons inside time strings
like "14:51:26" turning them into "14: 51: 26". Changed to require the
space that JSON.stringify always adds after key-value colons (": \d+")
so colons inside string values are not affected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01 17:41:37 -05:00

131 lines
6.3 KiB
HTML

{% extends "base.html" %}
{% block title %}Terceros{% endblock %}
{% block header %}Envío de Terceros{% endblock %}
{% block content %}
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<div>
<div class="bg-white rounded-xl shadow-sm border border-gray-200">
<div class="px-6 py-4 border-b border-gray-200">
<h3 class="font-semibold text-gray-800"><i class="fas fa-cog mr-2 text-blue-500"></i>Generar y Enviar</h3>
</div>
<div class="p-6">
<form id="form-terceros" class="space-y-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Consulta SQL</label>
<select name="query_id" required
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm">
<option value="">Seleccionar consulta...</option>
{% for q in queries %}
<option value="{{ q.id }}">{{ q.name }}</option>
{% endfor %}
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">
Número de Documento <span class="text-xs text-red-400">* requerido</span>
</label>
<input type="text" name="doc_num" required
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm"
placeholder="Ej: 27567400">
</div>
<div class="flex space-x-3">
<button type="button" onclick="previewTerceros()"
class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg text-sm font-medium hover:bg-gray-200">
<i class="fas fa-eye mr-1"></i> Vista Previa
</button>
<button type="button" onclick="sendTerceros()"
class="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg text-sm font-medium">
<i class="fas fa-paper-plane mr-1"></i> Enviar a API
</button>
</div>
</form>
</div>
</div>
<div class="mt-6 bg-white rounded-xl shadow-sm border border-gray-200">
<div class="px-6 py-4 border-b border-gray-200">
<h3 class="font-semibold text-gray-800"><i class="fas fa-eye mr-2 text-blue-500"></i>JSON Generado</h3>
</div>
<div class="p-6">
<pre id="json-preview" class="text-xs font-mono bg-gray-50 rounded-lg p-4 overflow-x-auto max-h-96 text-gray-600"><i class="fas fa-info-circle mr-1"></i> Haz clic en "Vista Previa" para ver el JSON</pre>
</div>
</div>
</div>
<div>
<div class="bg-white rounded-xl shadow-sm border border-gray-200">
<div class="px-6 py-4 border-b border-gray-200">
<h3 class="font-semibold text-gray-800"><i class="fas fa-history mr-2 text-blue-500"></i>Últimos Envíos</h3>
</div>
<div class="p-4">
{% if envios %}
<div class="space-y-2">
{% for e in envios %}
<div class="p-3 rounded-lg border border-gray-100 text-sm">
<div class="flex justify-between items-center">
<span class="px-2 py-0.5 rounded text-xs font-medium {% if e.status == 'success' %}bg-green-100 text-green-700{% else %}bg-red-100 text-red-700{% endif %}">
{{ 'Exitoso' if e.status == 'success' else 'Error' }}
</span>
<span class="text-xs text-gray-400">{{ e.created_at[:19] }}</span>
</div>
<p class="text-xs text-gray-500 mt-1 truncate">{{ e.respuesta_api[:100] if e.respuesta_api else 'Sin respuesta' }}</p>
</div>
{% endfor %}
</div>
{% else %}
<p class="text-center text-gray-400 py-4 text-sm">No hay envíos de terceros aún</p>
{% endif %}
</div>
</div>
</div>
</div>
<script>
async function previewTerceros() {
const form = document.getElementById('form-terceros');
const data = new FormData(form);
const btn = form.querySelector('[onclick="previewTerceros()"]');
showLoading(btn);
const resp = await fetch('/terceros/preview', {method:'POST', body: data, credentials: 'include'});
const result = await resp.json();
hideLoading(btn, '<i class="fas fa-eye mr-1"></i> Vista Previa');
const pre = document.getElementById('json-preview');
if (result.success && result.generated_json) {
pre.innerHTML = syntaxHighlight(result.generated_json);
} else {
pre.innerHTML = '<span class="text-red-600">Error: ' + (result.message || 'Sin datos') + '</span>';
}
}
async function sendTerceros() {
if (!confirm('¿Enviar terceros a la API?')) return;
const form = document.getElementById('form-terceros');
const data = new FormData(form);
const btn = form.querySelector('[onclick="sendTerceros()"]');
showLoading(btn);
const resp = await fetch('/terceros/send', {method:'POST', body: data, credentials: 'include'});
const result = await resp.json();
hideLoading(btn, '<i class="fas fa-paper-plane mr-1"></i> Enviar a API');
if (result.success) {
showToast('Envío exitoso! CUV: ' + (result.cuv || ''), 'success');
setTimeout(() => location.reload(), 1500);
} else {
showToast('Error: ' + result.message, 'error');
}
}
function syntaxHighlight(obj) {
let json = JSON.stringify(obj, null, 2);
json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
return json.replace(/("(?:[^"\\]|\\.)*")(?=\s*:)/g, '<span class="text-blue-600">$1</span>')
.replace(/:(\s*)("(?:[^"\\]|\\.)*")/g, ': $1<span class="text-green-600">$2</span>')
.replace(/: (\d+)/g, ': <span class="text-orange-600">$1</span>')
.replace(/: (null|true|false)/g, ': <span class="text-purple-600">$1</span>');
}
</script>
{% endblock %}