Files
Helpddesk/Modules/Helpdesk/Console/ImportLegacyHelpdeskCommand.php
T

129 lines
5.9 KiB
PHP

<?php
declare(strict_types=1);
namespace Modules\Helpdesk\Console;
use Illuminate\Console\Command;
use Illuminate\Database\ConnectionInterface;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Modules\Helpdesk\Models\LegacyCategory;
use Modules\Helpdesk\Models\LegacyComment;
use Modules\Helpdesk\Models\LegacyTicket;
use Throwable;
final class ImportLegacyHelpdeskCommand extends Command
{
protected $signature = 'helpdesk:import-legacy {--connection= : Laravel database connection containing the old tickets tables} {--fresh : Clear previously imported legacy records first}';
protected $description = 'Import the old Helpdesk tickets and categories into the read-only Legacy System';
public function handle(): int
{
$connectionName = (string) ($this->option('connection') ?: config('helpdesk.legacy_connection', config('database.default')));
$source = DB::connection($connectionName);
$schema = Schema::connection($connectionName);
foreach (['tickets', 'tickets_categories'] as $table) {
if (! $schema->hasTable($table)) {
$this->error("Source table {$table} was not found on connection [{$connectionName}].");
return self::FAILURE;
}
}
if ($this->option('fresh')) {
LegacyComment::query()->delete();
LegacyTicket::query()->delete();
LegacyCategory::query()->delete();
}
$this->importCategories($source);
$this->importTickets($source, $schema);
$this->importComments($source, $schema);
$this->refreshCategoryCounts();
$this->info(sprintf('Legacy import complete: %d tickets, %d categories, %d comments.', LegacyTicket::count(), LegacyCategory::count(), LegacyComment::count()));
return self::SUCCESS;
}
private function importCategories(ConnectionInterface $source): void
{
$source->table('tickets_categories')->orderBy('id')->chunk(500, function ($rows): void {
foreach ($rows as $row) {
LegacyCategory::updateOrCreate(['legacy_id' => $row->id], ['name' => (string) $row->name, 'color' => $row->color ?? null]);
}
});
}
private function importTickets(ConnectionInterface $source, $schema): void
{
$columns = collect($schema->getColumnListing('tickets'));
$lookups = [
'category' => $this->lookup($source, $schema, 'tickets_categories'),
'status' => $this->lookup($source, $schema, 'tickets_statuses'),
'priority' => $this->lookup($source, $schema, 'tickets_priorities'),
'project' => $this->lookup($source, $schema, 'projects'),
'user' => $this->lookup($source, $schema, 'users'),
];
$source->table('tickets')->orderBy('id')->chunk(250, function ($rows) use ($columns, $lookups): void {
foreach ($rows as $row) {
$data = (array) $row;
LegacyTicket::updateOrCreate(['legacy_id' => $row->id], [
'reference' => $data['reference'] ?? null,
'subject' => (string) ($data['subject'] ?? 'Legacy ticket #'.$row->id),
'content' => $data['content'] ?? null,
'html_content' => $data['htmlcontent'] ?? null,
'legacy_category_id' => $data['category_id'] ?? null,
'category_name' => $lookups['category'][$data['category_id'] ?? 0] ?? null,
'status_name' => $lookups['status'][$data['status_id'] ?? 0] ?? null,
'priority_name' => $lookups['priority'][$data['priority_id'] ?? 0] ?? null,
'requester_name' => $lookups['user'][$data['user_id'] ?? 0] ?? null,
'agent_name' => $lookups['user'][$data['agent_id'] ?? 0] ?? null,
'project_name' => $lookups['project'][$data['project_id'] ?? 0] ?? null,
'legacy_created_at' => $data['created_at'] ?? null,
'legacy_updated_at' => $data['updated_at'] ?? null,
'completed_at' => $data['completed_at'] ?? null,
'archived_at' => $data['archived_at'] ?? null,
'legacy_data' => $data,
]);
}
});
}
private function importComments(ConnectionInterface $source, $schema): void
{
if (! $schema->hasTable('tickets_comments')) return;
$users = $this->lookup($source, $schema, 'users');
$source->table('tickets_comments')->orderBy('id')->chunk(500, function ($rows) use ($users): void {
foreach ($rows as $row) {
$data = (array) $row;
LegacyComment::updateOrCreate(['legacy_id' => $row->id], [
'legacy_ticket_id' => $data['ticket_id'],
'author_name' => $users[$data['user_id'] ?? 0] ?? null,
'content' => $data['content'] ?? null,
'html_content' => $data['htmlcontent'] ?? null,
'legacy_created_at' => $data['created_at'] ?? null,
'legacy_updated_at' => $data['updated_at'] ?? null,
]);
}
});
}
private function lookup(ConnectionInterface $source, $schema, string $table): array
{
if (! $schema->hasTable($table)) return [];
$columns = $schema->getColumnListing($table);
$nameColumn = in_array('name', $columns, true) ? 'name' : (in_array('username', $columns, true) ? 'username' : null);
if ($nameColumn === null) return [];
try { return $source->table($table)->pluck($nameColumn, 'id')->map(fn ($v) => (string) $v)->all(); } catch (Throwable) { return []; }
}
private function refreshCategoryCounts(): void
{
LegacyCategory::query()->each(function (LegacyCategory $category): void {
$category->update(['ticket_count' => LegacyTicket::query()->where('legacy_category_id', $category->legacy_id)->count()]);
});
}
}