Project

General

Profile

Tareas #33 » backfill_sys_created_by.py

Demo MiGestion365 Admin, 03/27/2026 12:52 PM

 
#!/usr/bin/env python3
"""
Backfill de sys_created_by en sn.case

- Busca registros con sys_created_by IS NULL
- Consulta ServiceNow por number
- Actualiza PostgreSQL solo si SN devuelve valor
"""

import requests
import psycopg2
import logging
import urllib3

# ================= CONFIG =================

# ServiceNow
SN_BASE_URL = "https://atowerarprod.service-now.com/api/now/table/sn_customerservice_case"
SN_USER = "plataformas.atc"
SN_PASS = "fiberatc1"

# PostgreSQL
PG_CONN = {
"host": "localhost",
"database": "postgres",
"user": "postgres",
"password": "post3008"
}

# ================= LOGGING =================
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)s %(message)s"
)

# Desactivar warning SSL (mismo criterio que loaders)
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

# ================= FUNCTIONS =================

def get_cases_with_null_sys_created_by(conn):
sql = """
SELECT number
FROM sn."case"
WHERE sys_created_by IS NULL
AND number IS NOT NULL;
"""
with conn.cursor() as cur:
cur.execute(sql)
return [r[0] for r in cur.fetchall()]


def fetch_sys_created_by_from_sn(number):
params = {
"sysparm_query": f"number={number}",
"sysparm_fields": "number,sys_created_by",
"sysparm_display_value": "true",
"sysparm_exclude_reference_link": "true"
}

resp = requests.get(
SN_BASE_URL,
auth=(SN_USER, SN_PASS),
params=params,
verify=False,
timeout=30
)

resp.raise_for_status()
data = resp.json().get("result", [])

if not data:
return None

return data[0].get("sys_created_by")


def update_sys_created_by(conn, number, sys_created_by):
sql = """
UPDATE sn."case"
SET sys_created_by = %s
WHERE number = %s
AND sys_created_by IS NULL;
"""
with conn.cursor() as cur:
cur.execute(sql, (sys_created_by, number))


# ================= MAIN =================

def main():
conn = psycopg2.connect(**PG_CONN)
conn.autocommit = False

try:
numbers = get_cases_with_null_sys_created_by(conn)
logging.info(f"Casos a reparar: {len(numbers)}")

for number in numbers:
try:
sys_created_by = fetch_sys_created_by_from_sn(number)

if sys_created_by:
update_sys_created_by(conn, number, sys_created_by)
conn.commit()
logging.info(f"{number} -> sys_created_by actualizado ({sys_created_by})")
else:
conn.rollback()
logging.warning(f"{number} -> SN no devolvió sys_created_by")

except Exception as e:
conn.rollback()
logging.error(f"{number} -> error: {e}")

finally:
conn.close()


if __name__ == "__main__":
main()
(3-3/3)