135 lines
6.2 KiB
PHP
135 lines
6.2 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
|
|
{
|
|
if (! config('helpdesk.legacy.enabled', false)) {
|
|
$this->error('Legacy Helpdesk support is disabled. Set HELPDESK_LEGACY_ENABLED=true to enable it.');
|
|
|
|
return self::FAILURE;
|
|
}
|
|
|
|
$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()]);
|
|
});
|
|
}
|
|
}
|