legacy: --since-Delta für legacy:import + Importer setzen Timestamps wieder korrekt

--since=<Zeitpunkt> schränkt den Quell-Scan auf Legacy-Zeilen ein, deren
created_at ODER updated_at im Fenster liegt (users/companies/contacts/
press-releases; Kategorien und link-associations bleiben ungefiltert).
Kombiniert mit --force werden geänderte Bestandszeilen aktualisiert —
damit dauert ein Tages-Delta Sekunden statt eines Volldurchlaufs über
150k+ Zeilen.

Dazu Bugfix, der den Delta erst rund macht: User-/Company-/Contact-
Importer übergaben created_at/updated_at innerhalb von updateOrCreate —
die Felder sind nicht fillable und wurden stillschweigend verworfen
(Live-Befund: NULL-Timestamps, bisher nur durch legacy:fix-timestamps
geheilt). Jetzt explizit per forceFill wie im PressReleaseImporter.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-07-20 13:03:07 +00:00
parent 22b7bd38b7
commit a0c2e663dc
8 changed files with 136 additions and 11 deletions

View file

@ -12,6 +12,7 @@ use App\Services\Import\PressReleaseImporter;
use App\Services\Import\UserAssociationLinker;
use App\Services\Import\UserImporter;
use Illuminate\Console\Command;
use Illuminate\Support\Carbon;
/**
* Legacy-Import-Master-Command (Phase 6 – Datenmigration).
@ -22,6 +23,7 @@ use Illuminate\Console\Command;
* php artisan legacy:import --source=all --step=categories
* php artisan legacy:import --source=all --step=link-associations ← NEU
* php artisan legacy:import --source=presseecho --force
* php artisan legacy:import --source=presseecho --since=today --force ← Delta: nur heute Angelegtes/Geändertes
*
* Schritte (--step):
* categories – Kategorien + Translations (einmalig, beide Portale identisch)
@ -39,6 +41,7 @@ class ImportLegacyData extends Command
{--step=all : Schritt (categories|users|companies|contacts|press-releases|link-associations|all)}
{--dry-run : Nichts schreiben, nur zählen}
{--force : Bereits importierte Datensätze erneut verarbeiten}
{--since= : Nur Legacy-Zeilen mit created_at/updated_at ab diesem Zeitpunkt (z. B. "2026-07-20", "today"); für Updates mit --force kombinieren}
{--chunk-size=500 : Batch-Größe (Debugging)}';
protected $description = 'Legacy-Daten aus Presseecho / Businessportal24 in die neue DB importieren.';
@ -61,9 +64,29 @@ class ImportLegacyData extends Command
$isDryRun = (bool) $this->option('dry-run');
$isForce = (bool) $this->option('force');
$since = null;
if (filled($this->option('since'))) {
try {
$since = Carbon::parse((string) $this->option('since'), config('app.timezone'));
} catch (\Throwable) {
$this->error('Ungültiger --since-Wert: '.$this->option('since'));
return self::FAILURE;
}
}
$portals = $source === 'all' ? self::PORTALS : [$source];
$steps = $step === 'all' ? self::STEPS : [$step];
if ($since) {
$this->info('Delta-Modus: nur Legacy-Zeilen mit created_at/updated_at ab '.$since->format('d.m.Y H:i:s').'.');
if (! $isForce) {
$this->warn('Hinweis: ohne --force werden im Zeitfenster GEÄNDERTE, bereits importierte Datensätze übersprungen — nur Neue kommen dazu.');
}
}
if (! $isDryRun && ! $this->option('force')) {
$this->warn('WICHTIG: Dieser Command schreibt Daten in die Produktions-DB.');
$this->line(' Portale: '.implode(', ', $portals));
@ -86,7 +109,7 @@ class ImportLegacyData extends Command
foreach ($steps as $currentStep) {
// link-associations arbeitet auf der neuen DB → einmalig, portal-unabhängig
if ($currentStep === 'link-associations') {
$ctx = new ImportContext('all', $isDryRun, $isForce);
$ctx = new ImportContext('all', $isDryRun, $isForce, $since);
$this->info('▶ Schritt [link-associations] (beide Portale, neue DB)');
$start = microtime(true);
$result = app(UserAssociationLinker::class)->run($ctx);
@ -100,7 +123,7 @@ class ImportLegacyData extends Command
$stepPortals = ($currentStep === 'categories') ? [$portals[0]] : $portals;
foreach ($stepPortals as $portal) {
$ctx = new ImportContext($portal, $isDryRun, $isForce);
$ctx = new ImportContext($portal, $isDryRun, $isForce, $since);
$this->info("▶ Schritt [{$currentStep}] Portal [{$portal}]");
$start = microtime(true);