- 사업자등록번호 유효성 검사 API (바로빌 연동) - 회사 추가 신청/승인/반려 워크플로우 - 신청 승인 시 테넌트 자동 생성 및 사용자 연결 - 관리자용 신청 목록/상세 조회 - 사용자용 내 신청 목록 조회 - Swagger 문서 및 i18n 메시지 추가
259 lines
8.7 KiB
PHP
259 lines
8.7 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\CompanyRequest;
|
|
use App\Models\Members\UserTenant;
|
|
use App\Models\Tenants\Tenant;
|
|
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
|
|
|
class CompanyService extends Service
|
|
{
|
|
public function __construct(
|
|
private readonly BarobillService $barobillService,
|
|
private readonly TenantService $tenantService
|
|
) {}
|
|
|
|
// =========================================================================
|
|
// 사업자등록번호 검증
|
|
// =========================================================================
|
|
|
|
/**
|
|
* 사업자등록번호 유효성 검사
|
|
*/
|
|
public function checkBusinessNumber(string $businessNumber): array
|
|
{
|
|
// 바로빌 서비스를 통한 사업자등록번호 검증
|
|
$result = $this->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);
|
|
}
|
|
}
|