feat: 사원-회원 연결 기능 구현 (Phase 2 API)
- store() 수정: create_account=false면 password=NULL 허용 (사원 전용)
- revokeAccount() 추가: 시스템 계정 해제 (password=NULL, 토큰 무효화)
- POST /employees/{id}/revoke-account 라우트 추가
- ko/employee.php, en/employee.php 언어 파일 생성
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -109,6 +109,17 @@ public function createAccount(int $id, Request $request): JsonResponse
|
||||
|
||||
return ApiResponse::handle(function () use ($id, $request) {
|
||||
return $this->service->createAccount($id, $request->input('password'));
|
||||
}, __('message.updated'));
|
||||
}, __('employee.account_created'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 시스템 계정 해제 (로그인 불가, 사원 정보 유지)
|
||||
* POST /v1/employees/{id}/revoke-account
|
||||
*/
|
||||
public function revokeAccount(int $id): JsonResponse
|
||||
{
|
||||
return ApiResponse::handle(function () use ($id) {
|
||||
return $this->service->revokeAccount($id);
|
||||
}, __('employee.account_revoked'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,6 +89,10 @@ public function show(int $id): TenantUserProfile
|
||||
|
||||
/**
|
||||
* 사원 등록 (users 테이블에 사용자 생성 + tenant_user_profiles 생성)
|
||||
*
|
||||
* @param array $data 사원 데이터
|
||||
* - create_account: bool (true=시스템 계정 생성, false=사원 전용)
|
||||
* - password: string (create_account=true일 때 필수)
|
||||
*/
|
||||
public function store(array $data): TenantUserProfile
|
||||
{
|
||||
@@ -96,25 +100,32 @@ public function store(array $data): TenantUserProfile
|
||||
$userId = $this->apiUserId();
|
||||
|
||||
return DB::transaction(function () use ($data, $tenantId, $userId) {
|
||||
// 1. users 테이블에 사용자 생성
|
||||
// 1. 비밀번호 결정: create_account=false면 NULL (사원 전용, 로그인 불가)
|
||||
$password = null;
|
||||
$createAccount = $data['create_account'] ?? false;
|
||||
if ($createAccount && ! empty($data['password'])) {
|
||||
$password = Hash::make($data['password']);
|
||||
}
|
||||
|
||||
// 2. users 테이블에 사용자 생성
|
||||
$user = User::create([
|
||||
'user_id' => $data['user_id'] ?? $this->generateUserId($data['email']),
|
||||
'name' => $data['name'],
|
||||
'email' => $data['email'],
|
||||
'phone' => $data['phone'] ?? null,
|
||||
'password' => Hash::make($data['password'] ?? Str::random(16)),
|
||||
'password' => $password,
|
||||
'is_active' => $data['is_active'] ?? true,
|
||||
'created_by' => $userId,
|
||||
]);
|
||||
|
||||
// 2. user_tenants pivot에 관계 추가
|
||||
// 3. user_tenants pivot에 관계 추가
|
||||
$user->tenantsMembership()->attach($tenantId, [
|
||||
'is_active' => true,
|
||||
'is_default' => true,
|
||||
'joined_at' => now(),
|
||||
]);
|
||||
|
||||
// 3. tenant_user_profiles 생성
|
||||
// 4. tenant_user_profiles 생성
|
||||
$profile = TenantUserProfile::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'user_id' => $user->id,
|
||||
@@ -129,7 +140,7 @@ public function store(array $data): TenantUserProfile
|
||||
'display_name' => $data['display_name'] ?? null,
|
||||
]);
|
||||
|
||||
// 4. json_extra 사원 정보 설정
|
||||
// 5. json_extra 사원 정보 설정
|
||||
$profile->updateEmployeeInfo([
|
||||
'employee_code' => $data['employee_code'] ?? null,
|
||||
'resident_number' => $data['resident_number'] ?? null,
|
||||
@@ -331,6 +342,43 @@ public function createAccount(int $id, string $password): TenantUserProfile
|
||||
return $profile->fresh(['user', 'department', 'manager']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 시스템 계정 해제 (비밀번호 제거 → 로그인 불가, 사원 정보 유지)
|
||||
*/
|
||||
public function revokeAccount(int $id): TenantUserProfile
|
||||
{
|
||||
$tenantId = $this->tenantId();
|
||||
$userId = $this->apiUserId();
|
||||
|
||||
$profile = TenantUserProfile::query()
|
||||
->where('tenant_id', $tenantId)
|
||||
->with('user')
|
||||
->find($id);
|
||||
|
||||
if (! $profile) {
|
||||
throw new NotFoundHttpException(__('error.not_found'));
|
||||
}
|
||||
|
||||
$user = $profile->user;
|
||||
|
||||
// 이미 계정이 없는 경우
|
||||
if (empty($user->password)) {
|
||||
throw new \InvalidArgumentException(__('employee.no_account'));
|
||||
}
|
||||
|
||||
// 1. 비밀번호 제거 (로그인 불가)
|
||||
$user->update([
|
||||
'password' => null,
|
||||
'must_change_password' => false,
|
||||
'updated_by' => $userId,
|
||||
]);
|
||||
|
||||
// 2. 기존 토큰 무효화 (로그아웃 처리)
|
||||
$user->tokens()->delete();
|
||||
|
||||
return $profile->fresh(['user', 'department', 'manager']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 사용자 ID 자동 생성
|
||||
*/
|
||||
|
||||
22
lang/en/employee.php
Normal file
22
lang/en/employee.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Employee management messages
|
||||
* - Account management (create/revoke)
|
||||
* - Employee status changes
|
||||
*/
|
||||
return [
|
||||
// Account management
|
||||
'account_created' => 'System account has been created.',
|
||||
'account_revoked' => 'System account has been revoked.',
|
||||
'no_account' => 'This employee does not have a system account.',
|
||||
'already_has_account' => 'This employee already has a system account.',
|
||||
|
||||
// Employee status
|
||||
'status_changed' => 'Employee status has been changed.',
|
||||
'resigned' => 'Employee has been marked as resigned.',
|
||||
|
||||
// Employee registration
|
||||
'created_employee_only' => 'Employee registered. (No login account)',
|
||||
'created_with_account' => 'Employee registered. (System account created)',
|
||||
];
|
||||
22
lang/ko/employee.php
Normal file
22
lang/ko/employee.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* 사원 관리 관련 메시지
|
||||
* - 계정 관리 (생성/해제)
|
||||
* - 사원 상태 변경
|
||||
*/
|
||||
return [
|
||||
// 계정 관리
|
||||
'account_created' => '시스템 계정이 생성되었습니다.',
|
||||
'account_revoked' => '시스템 계정이 해제되었습니다.',
|
||||
'no_account' => '시스템 계정이 없는 사원입니다.',
|
||||
'already_has_account' => '이미 시스템 계정을 보유하고 있습니다.',
|
||||
|
||||
// 사원 상태
|
||||
'status_changed' => '사원 상태가 변경되었습니다.',
|
||||
'resigned' => '퇴직 처리되었습니다.',
|
||||
|
||||
// 사원 등록
|
||||
'created_employee_only' => '사원이 등록되었습니다. (로그인 계정 없음)',
|
||||
'created_with_account' => '사원이 등록되었습니다. (시스템 계정 생성됨)',
|
||||
];
|
||||
@@ -286,6 +286,7 @@
|
||||
Route::delete('/{id}', [EmployeeController::class, 'destroy'])->name('v1.employees.destroy');
|
||||
Route::post('/bulk-delete', [EmployeeController::class, 'bulkDelete'])->name('v1.employees.bulkDelete');
|
||||
Route::post('/{id}/create-account', [EmployeeController::class, 'createAccount'])->name('v1.employees.createAccount');
|
||||
Route::post('/{id}/revoke-account', [EmployeeController::class, 'revokeAccount'])->name('v1.employees.revokeAccount');
|
||||
});
|
||||
|
||||
// Attendance API (근태 관리)
|
||||
|
||||
Reference in New Issue
Block a user