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:
@@ -0,0 +1,35 @@
|
||||
"""Tenant mirror identity from GTI Gerenciador.
|
||||
|
||||
GTI Gerenciador (the panel) becomes the source of truth for clients.
|
||||
tenants gains source ('LOCAL' | 'GTI_GERENCIADOR'), external_client_id
|
||||
(Gerenciador's CLIENTE.ID), external_code, active and synced_at. Existing
|
||||
rows (pre-dating this sync) become source='LOCAL' and are never offered for
|
||||
a new installation, but keep every foreign key that already points at them.
|
||||
|
||||
Revision ID: 0024_tenant_gerenciador_mirror
|
||||
Revises: 0023_install_codes
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
revision = "0024_tenant_gerenciador_mirror"
|
||||
down_revision = "0023_install_codes"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.add_column("tenants", sa.Column("source", sa.String(16), nullable=False, server_default="LOCAL"))
|
||||
op.add_column("tenants", sa.Column("external_client_id", sa.Integer(), nullable=True))
|
||||
op.add_column("tenants", sa.Column("external_code", sa.String(16), nullable=True))
|
||||
op.add_column("tenants", sa.Column("active", sa.Boolean(), nullable=False, server_default="true"))
|
||||
op.add_column("tenants", sa.Column("synced_at", sa.DateTime(timezone=True), nullable=True))
|
||||
op.create_index("ix_tenants_external_client_id", "tenants", ["external_client_id"])
|
||||
op.create_unique_constraint("uq_tenant_external_identity", "tenants", ["source", "external_client_id"])
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.drop_constraint("uq_tenant_external_identity", "tenants", type_="unique")
|
||||
op.drop_index("ix_tenants_external_client_id", table_name="tenants")
|
||||
for column in ("synced_at", "active", "external_code", "external_client_id", "source"):
|
||||
op.drop_column("tenants", column)
|
||||
Reference in New Issue
Block a user