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>
78 lines
2.7 KiB
PHP
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;
|
|
}
|
|
}
|