diff --git a/backend/src/Controller/EmployeeImportController.php b/backend/src/Controller/EmployeeImportController.php index 4222d69..22df7ac 100644 --- a/backend/src/Controller/EmployeeImportController.php +++ b/backend/src/Controller/EmployeeImportController.php @@ -27,6 +27,11 @@ final class EmployeeImportController ]; /** Felder der Geschäftsadresse. */ private const ADDRESS = ['street', 'houseNumber', 'addressLine2', 'zip', 'city', 'state', 'country']; + /** Felder der Privatadresse (Import-Keys → Adress-Teilfeld). */ + private const ADDRESS_PRIVATE = [ + 'privateStreet' => 'street', 'privateHouseNumber' => 'houseNumber', 'privateAddressLine2' => 'addressLine2', + 'privateZip' => 'zip', 'privateCity' => 'city', 'privateState' => 'state', 'privateCountry' => 'country', + ]; /** Felder, die als Unique-Schlüssel zum Abgleich erlaubt sind. */ private const UNIQUE_ALLOWED = ['email', 'emailPrivate', 'phone', 'mobile', 'slug']; @@ -103,7 +108,7 @@ final class EmployeeImportController private function extract(array $row): array { $out = []; - foreach ([...self::SCALAR, ...self::ADDRESS] as $key) { + foreach ([...self::SCALAR, ...self::ADDRESS, ...array_keys(self::ADDRESS_PRIVATE)] as $key) { if (\array_key_exists($key, $row)) { $out[$key] = trim((string) $row[$key]); } @@ -129,17 +134,34 @@ final class EmployeeImportController } // Geschäftsadresse: vorhandene Werte beibehalten, neue überschreiben - $addr = $isNew ? [] : ($e->getAddressBusiness() ?? []); + $bizMap = array_combine(self::ADDRESS, self::ADDRESS); + if (null !== ($biz = $this->mergeAddress($isNew ? [] : ($e->getAddressBusiness() ?? []), $v, $bizMap))) { + $e->setAddressBusiness($biz); + } + // Privatadresse (Import-Keys mit private-Präfix) + if (null !== ($priv = $this->mergeAddress($isNew ? [] : ($e->getAddressPrivate() ?? []), $v, self::ADDRESS_PRIVATE))) { + $e->setAddressPrivate($priv); + } + } + + /** + * @param array $existing + * @param array $v + * @param array $map Import-Key → Adress-Teilfeld + * + * @return array|null null = nichts zu setzen + */ + private function mergeAddress(array $existing, array $v, array $map): ?array + { $touched = false; - foreach (self::ADDRESS as $key) { - if (\array_key_exists($key, $v) && '' !== $v[$key]) { - $addr[$key] = $v[$key]; + foreach ($map as $importKey => $addrKey) { + if (\array_key_exists($importKey, $v) && '' !== $v[$importKey]) { + $existing[$addrKey] = $v[$importKey]; $touched = true; } } - if ($touched) { - $e->setAddressBusiness($addr); - } + + return $touched ? $existing : null; } private function uniqueSlug(Company $company, string $first, string $last): string diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 529a4b4..6426d8a 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -12,7 +12,8 @@ "pdfjs-dist": "^6.0.227", "pinia": "^3.0.4", "vue": "^3.5.34", - "vue-router": "^4.6.4" + "vue-router": "^4.6.4", + "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz" }, "devDependencies": { "@types/node": "^24.12.3", @@ -2032,6 +2033,18 @@ "peerDependencies": { "typescript": ">=5.0.0" } + }, + "node_modules/xlsx": { + "version": "0.20.3", + "resolved": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz", + "integrity": "sha512-oLDq3jw7AcLqKWH2AhCpVTZl8mf6X2YReP+Neh0SJUzV/BdZYjth94tG5toiMB1PPrYtxOCfaoUCkvtuH+3AJA==", + "license": "Apache-2.0", + "bin": { + "xlsx": "bin/xlsx.njs" + }, + "engines": { + "node": ">=0.8" + } } } } diff --git a/frontend/package.json b/frontend/package.json index e183f47..d8d4345 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -13,7 +13,8 @@ "pdfjs-dist": "^6.0.227", "pinia": "^3.0.4", "vue": "^3.5.34", - "vue-router": "^4.6.4" + "vue-router": "^4.6.4", + "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz" }, "devDependencies": { "@types/node": "^24.12.3", diff --git a/frontend/src/components/EmployeeImport.vue b/frontend/src/components/EmployeeImport.vue index f558674..9c9ff2a 100644 --- a/frontend/src/components/EmployeeImport.vue +++ b/frontend/src/components/EmployeeImport.vue @@ -1,5 +1,6 @@