feat: GTI Gerenciador as the single source of truth for clients; bump to 1.1.2
Tenant gains source (LOCAL|GTI_GERENCIADOR), external_client_id, external_code, active and synced_at (migration 0024). central/app/client_sync.py fetches from the panel's new GET /internal/fiscal/clients (dedicated bearer token, never MySQL credentials) and upserts Tenant rows, never touching a LOCAL row. /agents/new now offers only active GTI_GERENCIADOR tenants, with a client-side search box; the POST validates the same rule server-side, not just in the dropdown. central/scripts/sync_clients_from_gerenciador.py is the operator-run sync + reconciliation report. GTI_FISCAL_VERSION/AGENT_VERSION bumped to 1.1.2 (release/VERSION single source of truth), incorporating the installation_id persistence fix. Rebuilt the EXE installer trio at 1.1.2 (scripts/build_windows_installer.ps1). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -6,12 +6,14 @@
|
||||
{% if error %}<p class="error" role="alert">{{ error }}</p>{% endif %}
|
||||
{% if not releases %}
|
||||
<p class="muted">Nenhuma versão do Agent está publicada ainda. Publique uma release primeiro (<code>python central/scripts/publish_agent_release.py</code>) e ela aparecerá aqui.</p>
|
||||
{% elif not tenants %}
|
||||
<p class="muted">Nenhum cliente ativo encontrado no GTI Gerenciador. Verifique o cadastro por lá, ou rode a sincronização (<code>python central/scripts/sync_clients_from_gerenciador.py</code>).</p>
|
||||
{% else %}
|
||||
<form method="post" action="/agents/new">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
||||
<label>Cliente
|
||||
<select name="tenant_id" required>
|
||||
<option value="">Selecione</option>
|
||||
<input type="text" id="filtro-cliente" placeholder="Buscar cliente..." autocomplete="off" oninput="filtrarClientes(this.value)">
|
||||
<select name="tenant_id" id="select-cliente" size="8" required>
|
||||
{% for tenant in tenants %}<option value="{{ tenant.id }}">{{ tenant.name }}</option>{% endfor %}
|
||||
</select>
|
||||
</label>
|
||||
@@ -28,6 +30,14 @@
|
||||
</label>
|
||||
<p><button type="submit">Criar instalação</button></p>
|
||||
</form>
|
||||
<script>
|
||||
function filtrarClientes(termo) {
|
||||
var alvo = termo.trim().toLowerCase();
|
||||
document.querySelectorAll("#select-cliente option").forEach(function (opcao) {
|
||||
opcao.hidden = alvo.length > 0 && opcao.textContent.toLowerCase().indexOf(alvo) === -1;
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{% endif %}
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
<section class="panel">
|
||||
<h2>Detalhes</h2>
|
||||
<table>
|
||||
<tr><th>Cliente</th><td>{{ tenant.name if tenant else "-" }}</td></tr>
|
||||
<tr><th>Cliente</th><td>{{ tenant.name if tenant else "-" }}{% if tenant and not tenant.active %} <span class="badge critical">INATIVO</span>{% endif %}</td></tr>
|
||||
<tr><th>Nome</th><td>{{ enr.display_name }}</td></tr>
|
||||
<tr><th>Hostname esperado</th><td>{{ enr.expected_hostname or "não informado" }}</td></tr>
|
||||
<tr><th>Versão do Agent</th><td>{{ release.version if release else "-" }} ({{ release.platform if release else "" }}/{{ release.architecture if release else "" }})</td></tr>
|
||||
|
||||
Reference in New Issue
Block a user