barobillService->checkBusinessNumber($businessNumber); // 이미 등록된 회사인지 확인 $normalizedNumber = preg_replace('/[^0-9]/', '', $businessNumber); $existingTenant = Tenant::query() ->where('business_num', $normalizedNumber) ->orWhere('business_num', $this->formatBusinessNumber($normalizedNumber)) ->first(); if ($existingTenant) { $result['already_exists'] = true; $result['existing_company_name'] = $existingTenant->company_name; } else { $result['already_exists'] = false; $result['existing_company_name'] = null; } return $result; } /** * 사업자등록번호 포맷 (하이픈 추가) */ private function formatBusinessNumber(string $number): string { $number = preg_replace('/[^0-9]/', '', $number); if (strlen($number) === 10) { return substr($number, 0, 3).'-'.substr($number, 3, 2).'-'.substr($number, 5, 5); } return $number; } // ========================================================================= // 회사 추가 신청 // ========================================================================= /** * 회사 추가 신청 생성 */ public function createRequest(array $data): CompanyRequest { $userId = $this->apiUserId(); $businessNumber = preg_replace('/[^0-9]/', '', $data['business_number']); // 중복 신청 확인 (대기중인 신청이 있는지) $existingRequest = CompanyRequest::query() ->where('user_id', $userId) ->where('business_number', $businessNumber) ->where('status', CompanyRequest::STATUS_PENDING) ->first(); if ($existingRequest) { throw new BadRequestHttpException(__('error.company.request_already_exists')); } // 이미 등록된 회사인지 확인 $existingTenant = Tenant::query() ->where('business_num', $businessNumber) ->orWhere('business_num', $this->formatBusinessNumber($businessNumber)) ->first(); if ($existingTenant) { // 이미 존재하는 회사에 합류 신청 // 해당 회사의 관리자에게 알림을 보내거나 별도 처리 가능 throw new BadRequestHttpException(__('error.company.already_registered')); } // 사업자등록번호 유효성 검사 $validationResult = $this->barobillService->checkBusinessNumber($businessNumber); return CompanyRequest::create([ 'user_id' => $userId, 'business_number' => $businessNumber, 'company_name' => $data['company_name'], 'ceo_name' => $data['ceo_name'] ?? $validationResult['ceo_name'] ?? null, 'address' => $data['address'] ?? null, 'phone' => $data['phone'] ?? null, 'email' => $data['email'] ?? null, 'message' => $data['message'] ?? null, 'status' => CompanyRequest::STATUS_PENDING, 'barobill_response' => $validationResult, ]); } /** * 회사 추가 신청 목록 (관리자용) */ public function getRequests(array $params): LengthAwarePaginator { $query = CompanyRequest::query() ->with(['user:id,name,email', 'approver:id,name,email', 'createdTenant:id,company_name,code']); // 상태 필터 if (! empty($params['status'])) { $query->ofStatus($params['status']); } // 검색 (사업자번호, 회사명, 신청자명) if (! empty($params['search'])) { $search = $params['search']; $query->where(function ($q) use ($search) { $q->where('business_number', 'like', "%{$search}%") ->orWhere('company_name', 'like', "%{$search}%") ->orWhereHas('user', function ($uq) use ($search) { $uq->where('name', 'like', "%{$search}%"); }); }); } // 날짜 범위 필터 if (! empty($params['start_date'])) { $query->whereDate('created_at', '>=', $params['start_date']); } if (! empty($params['end_date'])) { $query->whereDate('created_at', '<=', $params['end_date']); } // 정렬 $sortBy = $params['sort_by'] ?? 'created_at'; $sortDir = $params['sort_dir'] ?? 'desc'; $query->orderBy($sortBy, $sortDir); $perPage = $params['per_page'] ?? 20; return $query->paginate($perPage); } /** * 회사 추가 신청 상세 */ public function getRequest(int $id): CompanyRequest { return CompanyRequest::query() ->with(['user:id,name,email', 'approver:id,name,email', 'createdTenant:id,company_name,code']) ->findOrFail($id); } // ========================================================================= // 신청 처리 (관리자) // ========================================================================= /** * 회사 추가 신청 승인 */ public function approveRequest(int $id): CompanyRequest { $userId = $this->apiUserId(); $request = CompanyRequest::findOrFail($id); if (! $request->is_pending) { throw new BadRequestHttpException(__('error.company.request_not_pending')); } return DB::transaction(function () use ($request, $userId) { // 테넌트 생성 $tenantCode = $this->tenantService->generateTenantCode($request->company_name); $tenant = Tenant::create([ 'code' => $tenantCode, 'company_name' => $request->company_name, 'business_num' => $request->business_number, 'ceo_name' => $request->ceo_name, 'address' => $request->address, 'phone' => $request->phone, 'email' => $request->email, ]); // 신청자를 테넌트에 연결 UserTenant::create([ 'user_id' => $request->user_id, 'tenant_id' => $tenant->id, 'is_active' => true, 'is_default' => true, 'joined_at' => now(), ]); // 신청 승인 처리 $request->approve($userId, $tenant->id); return $request->fresh(['user', 'approver', 'createdTenant']); }); } /** * 회사 추가 신청 반려 */ public function rejectRequest(int $id, ?string $reason = null): CompanyRequest { $userId = $this->apiUserId(); $request = CompanyRequest::findOrFail($id); if (! $request->is_pending) { throw new BadRequestHttpException(__('error.company.request_not_pending')); } $request->reject($userId, $reason); return $request->fresh(['user', 'approver']); } // ========================================================================= // 내 신청 목록 (사용자용) // ========================================================================= /** * 내 회사 추가 신청 목록 */ public function getMyRequests(array $params): LengthAwarePaginator { $userId = $this->apiUserId(); $query = CompanyRequest::query() ->where('user_id', $userId) ->with(['approver:id,name,email', 'createdTenant:id,company_name,code']); // 상태 필터 if (! empty($params['status'])) { $query->ofStatus($params['status']); } // 정렬 $sortBy = $params['sort_by'] ?? 'created_at'; $sortDir = $params['sort_dir'] ?? 'desc'; $query->orderBy($sortBy, $sortDir); $perPage = $params['per_page'] ?? 20; return $query->paginate($perPage); } }