Files
service_manager/scripts/fix_sla_dates.py

83 lines
2.7 KiB
Python

"""
Backfill SLA response_due and resolution_due on all tickets that have
a category but no SLA dates set.
"""
import asyncio
import os
import sys
from datetime import timedelta
sys.path.insert(0, '/app')
os.chdir('/app')
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker
from sqlalchemy import text
async def run():
database_url = os.environ.get(
'DATABASE_URL',
'postgresql+asyncpg://postgres:postgres@db:5432/servicemanager'
)
engine = create_async_engine(database_url)
async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
async with async_session() as session:
# Find all tickets with a category but missing SLA dates
result = await session.execute(text("""
SELECT
t.id,
t.created_at,
c.sla_response_hours,
c.sla_resolution_hours
FROM tickets t
JOIN ticket_categories c ON c.id = t.category_id
WHERE t.sla_response_due IS NULL
AND t.sla_resolution_due IS NULL
"""))
rows = result.fetchall()
print(f"Tickets to update: {len(rows)}")
updated = 0
for row in rows:
ticket_id, created_at, resp_h, res_h = row
# Ensure naive datetime for DB compatibility
if hasattr(created_at, 'tzinfo') and created_at.tzinfo is not None:
from datetime import timezone
created_at = created_at.astimezone(timezone.utc).replace(tzinfo=None)
sla_response_due = created_at + timedelta(hours=float(resp_h))
sla_resolution_due = created_at + timedelta(hours=float(res_h))
await session.execute(text("""
UPDATE tickets
SET sla_response_due = :sla_resp,
sla_resolution_due = :sla_res
WHERE id = :ticket_id
"""), {
"sla_resp": sla_response_due,
"sla_res": sla_resolution_due,
"ticket_id": ticket_id,
})
updated += 1
await session.commit()
print(f"Updated {updated} tickets with SLA dates.")
# Verify
r2 = await session.execute(text("""
SELECT ticket_number, sla_response_due, sla_resolution_due
FROM tickets
WHERE sla_response_due IS NOT NULL
ORDER BY created_at
LIMIT 10
"""))
print("\nSample of tickets with SLA dates now:")
for row in r2.fetchall():
print(f" {row[0]}: response_due={row[1]}, resolution_due={row[2]}")
await engine.dispose()
asyncio.run(run())