Registro #87: la API key de cto entra a producción (el sync vuelve), la vista previa se valida contra el BIND real con FAC-171 y se construye en local el modal en vivo con "Aceptar", la campana y el modo automático configurable; capturas y video del recorrido

This commit is contained in:
Johann
2026-09-30 01:42:32 -06:00
parent 085e9037e8
commit bdafb06a03
13 changed files with 105 additions and 5 deletions
+55
View File
@@ -4,6 +4,11 @@
# url → lee la URL pública del túnel ngrok local (solo lectura)
# registrar → POST /rest/webhooks/1.0/webhook (ESCRIBE: 1 webhook de sitio)
# crear-ticket → POST /rest/api/3/issue (ESCRIBE: 1 ticket de prueba en FAC)
# crear-cotizacion [CLIENTE] → POST /rest/servicedeskapi/request (ESCRIBE: 1 ticket de
# prueba COMPLETO por el formulario "Cotización Bind", el que sí
# alcanza para armar la vista previa; default ACUNTIA, S.A.U.)
# vista-previa CLAVE [paputec] → espera el resultado de la vista previa automática
# del ticket y lo muestra con su dry-run (solo lectura)
# esperar CLAVE [paputec] → espera la detección en la BD local o, con "paputec",
# en la de producción por ssh (solo lectura)
# borrar-ticket CLAVE → DELETE /rest/api/3/issue/CLAVE (ESCRIBE: borra el ticket de prueba)
@@ -120,6 +125,56 @@ elif cmd == "crear-ticket":
else:
print(f"[{st}] {r}")
elif cmd == "crear-cotizacion":
# Formulario "Cotización Bind" (service desk 35, request type 1196): todos sus
# campos son obligatorios. Datos de prueba fijos y pequeños; el reporter es
# el dueño del token (Pedro), que recibe el correo de confirmación.
cliente = sys.argv[2] if len(sys.argv) > 2 else "ACUNTIA, S.A.U."
vence = time.strftime("%Y-%m-%d", time.localtime(time.time() + 7 * 86400))
st, r = jira("POST", "/rest/servicedeskapi/request", {
"serviceDeskId": "35", "requestTypeId": "1196",
"requestFieldValues": {
"summary": "[PRUEBA PLATAFORMA BALAM] Vista previa automática de cotización — se borra en minutos",
"description": f"Ticket de PRUEBA de la plataforma Balam ({time.strftime('%d/%m/%Y')}), autorizado por Johann, "
"para validar la vista previa automática de la cotización. Se elimina en cuanto se confirma.",
"customfield_11423": {"value": "Balam"}, # Empresa origen
"customfield_11598": {"value": cliente}, # Cliente
"customfield_11599": {"value": "Servicios Profesionales Generales"}, # Servicio/Producto
"customfield_11600": 1, # Cantidad
"customfield_10053": {"value": "MXN"}, # Tipo de Moneda
"customfield_11556": 1234, # Monto sin IVA
"customfield_11601": {"value": "16%"}, # IVA
"customfield_11597": vence, # Fecha de vencimiento
}})
if st == 201 and isinstance(r, dict):
estado(ticket=r["issueKey"], ticket_id=r["issueId"], creado=time.strftime("%Y-%m-%d %H:%M:%S"))
print(f"[201] ticket de prueba completo creado: {r['issueKey']} (id {r['issueId']}) · cliente {cliente}")
else:
print(f"[{st}] {r}")
elif cmd == "vista-previa":
clave = sys.argv[2]
destino = sys.argv[3] if len(sys.argv) > 3 else "local"
for i in range(60):
fila = sql(f"""SELECT e."Id", e."IssueKey", e."Verified", e."AuthMethod",
round(extract(epoch from (e."ReceivedAtUtc"-e."JiraTimestampUtc"))::numeric,2),
e."PreviewStatus", round(extract(epoch from (e."PreviewAtUtc"-e."JiraTimestampUtc"))::numeric,2),
coalesce(e."PreviewOperationId"::text,''), coalesce(e."PreviewDetail",'')
FROM "JiraTicketEvents" e WHERE e."IssueKey"='{clave}' AND e."PreviewStatus" IS NOT NULL""", destino)
if fila and "|" in fila:
print(f"VISTA PREVIA tras ~{i}s de espera: id | llave | verificado | auth | detección s | estado | lista a los s | operación | detalle")
print(" " + fila)
op = fila.split(" | ")[7].strip()
if op:
print(" dry-run guardado (WriteOperations): estatus | tipo | autor | confirmada")
print(" " + sql(f"""SELECT "Status", "Type", "CreatedBy", "ConfirmedAtUtc" IS NOT NULL
FROM "WriteOperations" WHERE "Id"={int(op)}""", destino))
print(sql(f"""SELECT "PayloadJson" FROM "WriteOperations" WHERE "Id"={int(op)}""", destino))
break
time.sleep(1)
else:
print(f"Sin vista previa de {clave} en 60 s.")
elif cmd == "esperar":
clave = sys.argv[2]
destino = sys.argv[3] if len(sys.argv) > 3 else "local"