fix: 사원 등록 시 이메일 중복 체크 및 user_id 충돌 방지

- 이메일 중복 체크 추가 (삭제된 사용자 포함)
- generateUniqueUserId() 메서드 추가 (중복 시 최대 10회 재시도)
- email_already_exists 에러 메시지 추가

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-01-14 20:29:00 +09:00
parent b82f9c786b
commit 12ca2cf4d3
2 changed files with 31 additions and 8 deletions

View File

@@ -98,14 +98,23 @@ public function store(array $data): TenantUserProfile
$tenantId = $this->tenantId();
$userId = $this->apiUserId();
return DB::transaction(function () use ($data, $tenantId, $userId) {
// 1. 비밀번호 결정: password가 있으면 시스템 계정 생성
// 1. 이메일 중복 체크 (전역 유니크)
$existingUser = User::withTrashed()->where('email', $data['email'])->first();
if ($existingUser) {
throw new \InvalidArgumentException(__('error.email_already_exists'));
}
// 2. user_id 중복 체크 및 유니크 ID 생성
$userIdValue = $data['user_id'] ?? $this->generateUniqueUserId($data['email']);
return DB::transaction(function () use ($data, $tenantId, $userId, $userIdValue) {
// 3. 비밀번호 결정: password가 있으면 시스템 계정 생성
// User 모델에 'password' => 'hashed' 캐스트가 있으므로 Hash::make() 불필요
$password = ! empty($data['password']) ? $data['password'] : null;
// 2. users 테이블에 사용자 생성
// 4. users 테이블에 사용자 생성
$user = User::create([
'user_id' => $data['user_id'] ?? $this->generateUserId($data['email']),
'user_id' => $userIdValue,
'name' => $data['name'],
'email' => $data['email'],
'phone' => $data['phone'] ?? null,
@@ -377,13 +386,26 @@ public function revokeAccount(int $id): TenantUserProfile
}
/**
* 사용자 ID 자동 생성
* 유니크한 사용자 ID 자동 생성
* 중복 시 최대 10회까지 재시도
*/
private function generateUserId(string $email): string
private function generateUniqueUserId(string $email): string
{
$prefix = explode('@', $email)[0];
$suffix = Str::random(4);
$prefix = strtolower(preg_replace('/[^a-zA-Z0-9]/', '', $prefix));
return strtolower($prefix.'_'.$suffix);
$maxAttempts = 10;
for ($i = 0; $i < $maxAttempts; $i++) {
$suffix = Str::random(6); // 4자리 → 6자리로 증가
$userId = $prefix.'_'.$suffix;
// 중복 체크 (삭제된 사용자 포함)
if (! User::withTrashed()->where('user_id', $userId)->exists()) {
return $userId;
}
}
// 최대 시도 후에도 실패 시 타임스탬프 추가
return $prefix.'_'.time().'_'.Str::random(4);
}
}

View File

@@ -22,6 +22,7 @@
// 검증/파라미터
'validation_failed' => '요청 데이터 검증에 실패했습니다.', // 422
'missing_parameter' => '필수 파라미터가 누락되었습니다.', // 400
'email_already_exists' => '이미 사용 중인 이메일 주소입니다.', // 400
'business_num_format' => '사업자등록번호 형식이 올바르지 않습니다 (000-00-00000)',
'business_num_duplicate_active' => '이미 등록된 사업자등록번호입니다 (정식 서비스 업체)',
'user_id_format' => '아이디는 영문, 숫자, _, - 만 사용할 수 있습니다',