presseportale/app/Console/Commands/ImportLegacyBillingAddresses.php
Kevin Adametz 5d199f0130 Rechnungsadressen der Bestandskunden aus dem Legacy-Archiv uebernehmen
Befund 06.07.: Der MAN-Rechnungslauf ueberspringt Vereinbarungen ohne
Rechnungsadresse — der Bestandsschutz laeuft dann am Periodenende faktisch
aus. Der Grandfather-Import nahm die Adressen bisher nicht mit, weil die
Altportale sie nur als Freitext-Blob fuehren.

- legacy:import-billing-addresses: uebernimmt Adressen der grandfathered
  Kunden aus der Quell-Rechnung im Archiv (pdf_payload.billing_address),
  nie ueberschreibend, mit Dry-Run und Report der manuell nachzupflegenden
  Faelle (leere/unparsebare Blobs, unbekannte Laender)
- LegacyAddressParser: Best-Effort-Strukturierung der Blobs (mehrzeilig,
  kommasepariert, CH-PLZ-Praefix, Firmen-/Zusatzzeilen); raet nie
- Laenderaufloesung ueber die country-Tabellen der Legacy-Verbindungen
- config/countries.php: CY ergaenzt (reale Bestandskunden aus Zypern)
- WS-7- und QA-Checkliste: Import-Schritt nach dem Grandfathering

Lokal: 11 von 21 Bestandskunden importiert, 9 im Report (7 leere Blobs);
MAN-Lauf rechnet zuvor blockierte Vereinbarungen jetzt ab.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 12:19:50 +00:00

78 lines
2.7 KiB
PHP

<?php
namespace App\Console\Commands;
use App\Services\Billing\LegacyBillingAddressImporter;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
/**
* Übernimmt die Rechnungsadressen der Bestandskunden aus dem Rechnungsarchiv
* (Befund 06.07.2026: ohne Adresse überspringt der MAN-Rechnungslauf die
* Vereinbarung und der Bestandsschutz läuft am Periodenende aus). Läuft
* NACH legacy:grandfather-subscriptions; die Legacy-Verbindungen werden nur
* für die Länderauflösung (country_id → Name) gebraucht. Wiederholbar:
* bestehende Adressen werden nie überschrieben.
*
* Verwendung:
* php artisan legacy:import-billing-addresses --dry-run
* php artisan legacy:import-billing-addresses
*/
class ImportLegacyBillingAddresses extends Command
{
protected $signature = 'legacy:import-billing-addresses
{--dry-run : Nur anzeigen, nichts schreiben}';
protected $description = 'Übernimmt Rechnungsadressen der grandfathered Bestandskunden aus dem Legacy-Rechnungsarchiv.';
private const CONNECTIONS = [
'presseecho' => 'mysql_presseecho',
'businessportal24' => 'mysql_businessportal',
];
public function handle(LegacyBillingAddressImporter $importer): int
{
$dryRun = (bool) $this->option('dry-run');
if ($dryRun) {
$this->warn('[DRY-RUN] Kein tatsächlicher Schreibvorgang.');
}
$countryNamesByPortal = [];
foreach (self::CONNECTIONS as $portal => $connection) {
$countryNamesByPortal[$portal] = DB::connection($connection)
->table('country')
->pluck('name', 'id')
->map(fn ($name): string => (string) $name)
->all();
}
$report = $importer->import($countryNamesByPortal, $dryRun);
$this->table(
['Importiert', 'Adresse vorhanden', 'Nicht parsebar', 'Land unbekannt', 'Quell-Rechnung fehlt'],
[[
$report['imported'],
$report['skipped_existing'],
count($report['unparseable']),
count($report['unknown_country']),
count($report['missing_invoice']),
]],
);
foreach ($report['unparseable'] as $line) {
$this->warn("Manuell nachpflegen (Adresse nicht parsebar): {$line}");
}
foreach ($report['unknown_country'] as $line) {
$this->warn("Manuell nachpflegen (Land nicht zuordenbar): {$line}");
}
foreach ($report['missing_invoice'] as $email) {
$this->warn("Manuell prüfen (Quell-Rechnung nicht im Archiv): {$email}");
}
return self::SUCCESS;
}
}