Files
tinker_tickets/scripts/add_closed_at_column.php

73 lines
2.3 KiB
PHP
Raw Permalink Normal View History

#!/usr/bin/env php
<?php
/**
* Migration: Add closed_at column to tickets table
*
* Adds a dedicated timestamp for when tickets are closed,
* so avg resolution time isn't inflated by post-close edits.
*
* Usage: php scripts/add_closed_at_column.php
*/
require_once dirname(__DIR__) . '/config/config.php';
$conn = new mysqli(
$GLOBALS['config']['DB_HOST'],
$GLOBALS['config']['DB_USER'],
$GLOBALS['config']['DB_PASS'],
$GLOBALS['config']['DB_NAME']
);
if ($conn->connect_error) {
die("Database connection failed: " . $conn->connect_error . "\n");
}
echo "Adding closed_at column to tickets table...\n";
// Add the column if it doesn't exist
$result = $conn->query("SHOW COLUMNS FROM tickets LIKE 'closed_at'");
if ($result->num_rows > 0) {
echo "Column 'closed_at' already exists, skipping ALTER TABLE.\n";
} else {
$sql = "ALTER TABLE tickets ADD COLUMN closed_at TIMESTAMP NULL DEFAULT NULL AFTER updated_at";
if ($conn->query($sql)) {
echo "Column added successfully.\n";
} else {
die("Failed to add column: " . $conn->error . "\n");
}
// Add index for stats queries
$conn->query("CREATE INDEX idx_tickets_closed_at ON tickets (closed_at)");
echo "Index created.\n";
}
// Backfill: For existing closed tickets, use the audit log to find when they were closed
echo "\nBackfilling closed_at from audit log...\n";
$sql = "UPDATE tickets t
JOIN (
SELECT entity_id as ticket_id, MIN(created_at) as first_closed
FROM audit_log
WHERE entity_type = 'ticket'
AND action_type = 'update'
AND details LIKE '%\"status\":\"Closed\"%'
GROUP BY entity_id
) al ON t.ticket_id = al.ticket_id
SET t.closed_at = al.first_closed
WHERE t.status = 'Closed' AND t.closed_at IS NULL";
$result = $conn->query($sql);
$backfilled = $conn->affected_rows;
echo "Backfilled $backfilled tickets from audit log.\n";
// For any remaining closed tickets without audit log entries, use updated_at as fallback
$sql = "UPDATE tickets SET closed_at = updated_at WHERE status = 'Closed' AND closed_at IS NULL";
$conn->query($sql);
$fallback = $conn->affected_rows;
if ($fallback > 0) {
echo "Used updated_at as fallback for $fallback tickets without audit log entries.\n";
}
echo "\nMigration complete!\n";
$conn->close();