fix: [user] 사용자 영구삭제 시 FK 제약 위반 500 에러 수정

- users.id를 참조하는 모든 FK를 information_schema에서 동적 조회
- NULLABLE FK → NULL 설정, NOT NULL FK → 관련 행 삭제
- 기존 5개 테이블만 처리하던 것을 전체 FK 대응으로 확장
This commit is contained in:
김보곤
2026-03-03 19:57:50 +09:00
parent 650f0ee3a7
commit 7885c1581d

View File

@@ -384,25 +384,48 @@ public function forceDeleteUser(int $id): bool
// 1. 아카이브에 저장 (복원 가능하도록)
$this->archiveService->archiveUser($user);
// 2. 관련 데이터 삭제
$user->tenants()->detach(); // user_tenants 관계 삭제
// 2-1. user_roles 영구 삭제 (외래 키 제약 때문에 forceDelete 필요)
// 2. 피벗/소유 테이블 삭제
$user->tenants()->detach();
DB::table('user_roles')->where('user_id', $user->id)->delete();
// 2-2. department_user 영구 삭제
DB::table('department_user')->where('user_id', $user->id)->delete();
// 2-3. sales_partners 삭제 (영업파트너)
DB::table('sales_partners')->where('user_id', $user->id)->delete();
// 2-4. sales_manager_documents 삭제 (영업파트너 서류)
DB::table('sales_manager_documents')->where('user_id', $user->id)->delete();
DB::table('login_tokens')->where('user_id', $user->id)->delete();
DB::table('notification_settings')->where('user_id', $user->id)->delete();
DB::table('notification_setting_group_states')->where('user_id', $user->id)->delete();
// 2-5. 하위 사용자의 parent_id 해제
// 3. 하위 사용자의 parent_id 해제
User::where('parent_id', $user->id)->update(['parent_id' => null]);
// 3. 사용자 영구 삭제
// 4. DB에서 users.id를 참조하는 모든 FK를 동적 조회 → NULL 또는 삭제
$dbName = DB::getDatabaseName();
$fkRefs = DB::select("
SELECT kcu.TABLE_NAME, kcu.COLUMN_NAME, c.IS_NULLABLE
FROM information_schema.KEY_COLUMN_USAGE kcu
JOIN information_schema.COLUMNS c
ON c.TABLE_SCHEMA = kcu.TABLE_SCHEMA
AND c.TABLE_NAME = kcu.TABLE_NAME
AND c.COLUMN_NAME = kcu.COLUMN_NAME
WHERE kcu.REFERENCED_TABLE_NAME = 'users'
AND kcu.REFERENCED_COLUMN_NAME = 'id'
AND kcu.TABLE_SCHEMA = ?
", [$dbName]);
$skipTables = ['user_tenants', 'user_roles', 'department_user', 'sales_partners', 'sales_manager_documents', 'login_tokens', 'notification_settings', 'notification_setting_group_states', 'users'];
foreach ($fkRefs as $ref) {
if (in_array($ref->TABLE_NAME, $skipTables)) {
continue;
}
if ($ref->IS_NULLABLE === 'YES') {
DB::table($ref->TABLE_NAME)->where($ref->COLUMN_NAME, $user->id)->update([$ref->COLUMN_NAME => null]);
} else {
DB::table($ref->TABLE_NAME)->where($ref->COLUMN_NAME, $user->id)->delete();
}
}
// 5. 사용자 영구 삭제
return $user->forceDelete();
});
}