12-05-2026 Frontend dev
This commit is contained in:
parent
405df0a122
commit
5b8bdf4182
779 changed files with 480564 additions and 6241 deletions
143
app/Services/Import/ContactImporter.php
Normal file
143
app/Services/Import/ContactImporter.php
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
<?php
|
||||
|
||||
namespace App\Services\Import;
|
||||
|
||||
use App\Enums\Portal;
|
||||
use App\Models\Contact;
|
||||
use App\Models\LegacyImportMap;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class ContactImporter
|
||||
{
|
||||
private const CHUNK_SIZE = 500;
|
||||
|
||||
public function run(ImportContext $ctx): ImportResult
|
||||
{
|
||||
$result = new ImportResult;
|
||||
$conn = $ctx->connection;
|
||||
$legacyPortal = $ctx->legacyPortalValue();
|
||||
$portal = $ctx->portalEnum;
|
||||
|
||||
DB::connection($conn)
|
||||
->table('contact')
|
||||
->orderBy('id')
|
||||
->chunk(self::CHUNK_SIZE, function ($rows) use ($ctx, $result, $legacyPortal, $portal): void {
|
||||
foreach ($rows as $row) {
|
||||
try {
|
||||
$this->importRow($row, $ctx, $result, $legacyPortal, $portal);
|
||||
} catch (\Throwable $e) {
|
||||
$result->addError("Contact legacy_id={$row->id}: {$e->getMessage()}");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function importRow(
|
||||
object $row,
|
||||
ImportContext $ctx,
|
||||
ImportResult $result,
|
||||
string $legacyPortal,
|
||||
Portal $portal,
|
||||
): void {
|
||||
$alreadyImported = LegacyImportMap::query()
|
||||
->where('legacy_portal', $legacyPortal)
|
||||
->where('legacy_table', 'contact')
|
||||
->where('legacy_id', $row->id)
|
||||
->exists();
|
||||
|
||||
if ($alreadyImported && ! $ctx->force) {
|
||||
$result->incrementSkipped();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($ctx->dryRun) {
|
||||
$result->incrementImported();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Firma aus Import-Map auflösen
|
||||
$companyId = null;
|
||||
if ($row->company_id) {
|
||||
$companyMap = LegacyImportMap::query()
|
||||
->where('legacy_portal', $legacyPortal)
|
||||
->where('legacy_table', 'company')
|
||||
->where('legacy_id', $row->company_id)
|
||||
->first();
|
||||
$companyId = $companyMap?->target_id;
|
||||
}
|
||||
|
||||
if (! $companyId) {
|
||||
// Kontakt ohne zugeordnete Firma überspringen (FK-Constraint)
|
||||
$result->incrementSkipped();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$salutationKey = $this->mapSalutation($row->salutation_id ?? 0);
|
||||
|
||||
$contact = Contact::withoutTimestamps(function () use ($legacyPortal, $row, $companyId, $portal, $salutationKey): Contact {
|
||||
return Contact::withoutGlobalScopes()->updateOrCreate(
|
||||
['legacy_portal' => $legacyPortal, 'legacy_id' => $row->id],
|
||||
[
|
||||
'company_id' => $companyId,
|
||||
'portal' => $portal->value,
|
||||
'salutation_key' => $salutationKey,
|
||||
'title' => $this->cleanText($row->title, 80),
|
||||
'first_name' => $this->cleanText($row->first_name, 80),
|
||||
'last_name' => $this->cleanText($row->last_name, 80),
|
||||
'responsibility' => $this->cleanText($row->responsibility, 255),
|
||||
'phone' => $this->cleanText($row->phone, 255),
|
||||
'fax' => $this->cleanText($row->fax, 255),
|
||||
'email' => $this->cleanText($row->email, 190),
|
||||
'created_at' => $row->created_at ?? now(),
|
||||
'updated_at' => $row->updated_at ?? $row->created_at ?? now(),
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
LegacyImportMap::query()->updateOrCreate(
|
||||
[
|
||||
'legacy_portal' => $legacyPortal,
|
||||
'legacy_table' => 'contact',
|
||||
'legacy_id' => $row->id,
|
||||
],
|
||||
[
|
||||
'target_table' => 'contacts',
|
||||
'target_id' => $contact->id,
|
||||
'imported_at' => now(),
|
||||
]
|
||||
);
|
||||
|
||||
if ($alreadyImported) {
|
||||
$result->incrementUpdated();
|
||||
} else {
|
||||
$result->incrementImported();
|
||||
}
|
||||
}
|
||||
|
||||
private function mapSalutation(int $salutationId): ?string
|
||||
{
|
||||
return match ($salutationId) {
|
||||
1 => 'mr',
|
||||
2 => 'mrs',
|
||||
default => null,
|
||||
};
|
||||
}
|
||||
|
||||
private function cleanText(?string $value, int $maxLength): ?string
|
||||
{
|
||||
if (blank($value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$clean = html_entity_decode((string) $value, ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
||||
$clean = preg_replace('/[\x00-\x1F\x7F\xC2\xA0]/u', ' ', $clean) ?? $clean;
|
||||
$clean = trim((string) $clean);
|
||||
|
||||
return blank($clean) ? null : mb_substr($clean, 0, $maxLength);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue