Files
sam-api/app/Swagger/v1/CompanyApi.php
hskwon 7781253491 feat: Phase 8.3 회사 추가 API 구현
- 사업자등록번호 유효성 검사 API (바로빌 연동)
- 회사 추가 신청/승인/반려 워크플로우
- 신청 승인 시 테넌트 자동 생성 및 사용자 연결
- 관리자용 신청 목록/상세 조회
- 사용자용 내 신청 목록 조회
- Swagger 문서 및 i18n 메시지 추가
2025-12-22 15:30:38 +09:00

420 lines
19 KiB
PHP

<?php
namespace App\Swagger\v1;
/**
* @OA\Tag(name="Companies", description="회사 관리")
*
* @OA\Schema(
* schema="CompanyRequest",
* type="object",
* description="회사 추가 신청 정보",
*
* @OA\Property(property="id", type="integer", example=1, description="신청 ID"),
* @OA\Property(property="user_id", type="integer", example=1, description="신청자 ID"),
* @OA\Property(property="business_number", type="string", example="1234567890", description="사업자등록번호"),
* @OA\Property(property="formatted_business_number", type="string", example="123-45-67890", description="사업자등록번호 (포맷)"),
* @OA\Property(property="company_name", type="string", example="주식회사 테스트", description="회사명"),
* @OA\Property(property="ceo_name", type="string", nullable=true, example="홍길동", description="대표자명"),
* @OA\Property(property="address", type="string", nullable=true, example="서울시 강남구 테헤란로 123", description="주소"),
* @OA\Property(property="phone", type="string", nullable=true, example="02-1234-5678", description="전화번호"),
* @OA\Property(property="email", type="string", nullable=true, example="contact@test.com", description="이메일"),
* @OA\Property(property="status", type="string", enum={"pending","approved","rejected"}, example="pending", description="상태"),
* @OA\Property(property="status_label", type="string", example="대기중", description="상태 라벨"),
* @OA\Property(property="message", type="string", nullable=true, description="신청 메시지"),
* @OA\Property(property="reject_reason", type="string", nullable=true, description="반려 사유"),
* @OA\Property(property="barobill_response", type="object", nullable=true, description="바로빌 검증 응답"),
* @OA\Property(property="approved_by", type="integer", nullable=true, description="승인/반려 처리자 ID"),
* @OA\Property(property="created_tenant_id", type="integer", nullable=true, description="생성된 테넌트 ID"),
* @OA\Property(property="processed_at", type="string", format="date-time", nullable=true, description="처리일시"),
* @OA\Property(property="is_pending", type="boolean", example=true, description="대기중 여부"),
* @OA\Property(property="is_approved", type="boolean", example=false, description="승인됨 여부"),
* @OA\Property(property="is_rejected", type="boolean", example=false, description="반려됨 여부"),
* @OA\Property(property="user", type="object", nullable=true,
* @OA\Property(property="id", type="integer", example=1),
* @OA\Property(property="name", type="string", example="홍길동"),
* @OA\Property(property="email", type="string", example="user@example.com"),
* description="신청자 정보"
* ),
* @OA\Property(property="approver", type="object", nullable=true,
* @OA\Property(property="id", type="integer", example=1),
* @OA\Property(property="name", type="string", example="관리자"),
* @OA\Property(property="email", type="string", example="admin@example.com"),
* description="처리자 정보"
* ),
* @OA\Property(property="created_tenant", type="object", nullable=true,
* @OA\Property(property="id", type="integer", example=1),
* @OA\Property(property="company_name", type="string", example="주식회사 테스트"),
* @OA\Property(property="code", type="string", example="TEST0001"),
* description="생성된 테넌트 정보"
* ),
* @OA\Property(property="created_at", type="string", format="date-time"),
* @OA\Property(property="updated_at", type="string", format="date-time")
* )
*
* @OA\Schema(
* schema="BusinessNumberCheckResponse",
* type="object",
* description="사업자등록번호 검증 결과",
*
* @OA\Property(property="valid", type="boolean", example=true, description="유효 여부"),
* @OA\Property(property="status", type="string", example="01", description="상태 코드"),
* @OA\Property(property="status_label", type="string", example="사업중", description="상태 라벨"),
* @OA\Property(property="corp_name", type="string", nullable=true, example="주식회사 테스트", description="회사명 (바로빌 조회)"),
* @OA\Property(property="ceo_name", type="string", nullable=true, example="홍길동", description="대표자명 (바로빌 조회)"),
* @OA\Property(property="message", type="string", example="유효한 사업자등록번호입니다.", description="결과 메시지"),
* @OA\Property(property="already_exists", type="boolean", example=false, description="이미 등록된 회사 여부"),
* @OA\Property(property="existing_company_name", type="string", nullable=true, description="이미 등록된 회사명")
* )
*
* @OA\Schema(
* schema="CompanyRequestCreateRequest",
* type="object",
* required={"business_number", "company_name"},
* description="회사 추가 신청 요청",
*
* @OA\Property(property="business_number", type="string", example="1234567890", minLength=10, maxLength=13, description="사업자등록번호 (하이픈 포함/미포함 모두 가능)"),
* @OA\Property(property="company_name", type="string", example="주식회사 테스트", maxLength=200, description="회사명"),
* @OA\Property(property="ceo_name", type="string", example="홍길동", maxLength=50, nullable=true, description="대표자명"),
* @OA\Property(property="address", type="string", example="서울시 강남구 테헤란로 123", maxLength=300, nullable=true, description="주소"),
* @OA\Property(property="phone", type="string", example="02-1234-5678", maxLength=30, nullable=true, description="전화번호"),
* @OA\Property(property="email", type="string", format="email", example="contact@test.com", maxLength=100, nullable=true, description="이메일"),
* @OA\Property(property="message", type="string", example="신규 법인 등록 요청드립니다.", maxLength=1000, nullable=true, description="신청 메시지")
* )
*
* @OA\Schema(
* schema="CompanyRequestActionRequest",
* type="object",
* description="회사 추가 신청 처리 요청",
*
* @OA\Property(property="reason", type="string", example="서류 미비로 반려합니다.", maxLength=500, nullable=true, description="처리 사유 (반려 시 필수)")
* )
*
* @OA\Schema(
* schema="CompanyRequestPagination",
* type="object",
* description="회사 추가 신청 목록 (페이지네이션)",
*
* @OA\Property(property="data", type="array", @OA\Items(ref="#/components/schemas/CompanyRequest")),
* @OA\Property(property="links", type="object",
* @OA\Property(property="first", type="string"),
* @OA\Property(property="last", type="string"),
* @OA\Property(property="prev", type="string", nullable=true),
* @OA\Property(property="next", type="string", nullable=true)
* ),
* @OA\Property(property="meta", type="object",
* @OA\Property(property="current_page", type="integer", example=1),
* @OA\Property(property="from", type="integer", example=1),
* @OA\Property(property="last_page", type="integer", example=1),
* @OA\Property(property="per_page", type="integer", example=20),
* @OA\Property(property="to", type="integer", example=5),
* @OA\Property(property="total", type="integer", example=5)
* )
* )
*/
class CompanyApi
{
/**
* @OA\Post(
* path="/api/v1/companies/check",
* operationId="checkBusinessNumber",
* tags={"Companies"},
* summary="사업자등록번호 유효성 검사",
* description="사업자등록번호의 유효성을 검사합니다. 바로빌 API를 통해 휴폐업 여부를 확인하고, 이미 등록된 회사인지 확인합니다.",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
*
* @OA\RequestBody(
* required=true,
* description="사업자등록번호",
*
* @OA\JsonContent(
* required={"business_number"},
*
* @OA\Property(property="business_number", type="string", example="1234567890", description="사업자등록번호 (10자리, 하이픈 제거)")
* )
* ),
*
* @OA\Response(
* response=200,
* description="검증 결과",
*
* @OA\JsonContent(
* type="object",
*
* @OA\Property(property="success", type="boolean", example=true),
* @OA\Property(property="message", type="string", example="검증이 완료되었습니다."),
* @OA\Property(property="data", ref="#/components/schemas/BusinessNumberCheckResponse")
* )
* ),
*
* @OA\Response(response=400, description="잘못된 요청"),
* @OA\Response(response=401, description="인증 실패")
* )
*/
public function check() {}
/**
* @OA\Post(
* path="/api/v1/companies/request",
* operationId="createCompanyRequest",
* tags={"Companies"},
* summary="회사 추가 신청",
* description="새로운 회사 추가를 신청합니다. 관리자 승인 후 테넌트가 생성됩니다.",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
*
* @OA\RequestBody(
* required=true,
* description="회사 정보",
*
* @OA\JsonContent(ref="#/components/schemas/CompanyRequestCreateRequest")
* ),
*
* @OA\Response(
* response=201,
* description="신청 완료",
*
* @OA\JsonContent(
* type="object",
*
* @OA\Property(property="success", type="boolean", example=true),
* @OA\Property(property="message", type="string", example="회사 추가 신청이 완료되었습니다."),
* @OA\Property(property="data", ref="#/components/schemas/CompanyRequest")
* )
* ),
*
* @OA\Response(response=400, description="잘못된 요청 (중복 신청, 이미 등록된 회사 등)"),
* @OA\Response(response=401, description="인증 실패")
* )
*/
public function request() {}
/**
* @OA\Get(
* path="/api/v1/companies/requests",
* operationId="getCompanyRequests",
* tags={"Companies"},
* summary="회사 추가 신청 목록 (관리자용)",
* description="회사 추가 신청 목록을 조회합니다. 관리자 권한이 필요합니다.",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
*
* @OA\Parameter(name="status", in="query", description="상태 필터",
*
* @OA\Schema(type="string", enum={"pending","approved","rejected"})
* ),
*
* @OA\Parameter(name="search", in="query", description="검색어 (사업자번호, 회사명, 신청자명)",
*
* @OA\Schema(type="string")
* ),
*
* @OA\Parameter(name="start_date", in="query", description="시작일",
*
* @OA\Schema(type="string", format="date")
* ),
*
* @OA\Parameter(name="end_date", in="query", description="종료일",
*
* @OA\Schema(type="string", format="date")
* ),
*
* @OA\Parameter(name="sort_by", in="query", description="정렬 기준",
*
* @OA\Schema(type="string", enum={"created_at","company_name","status","processed_at"})
* ),
*
* @OA\Parameter(name="sort_dir", in="query", description="정렬 방향",
*
* @OA\Schema(type="string", enum={"asc","desc"})
* ),
*
* @OA\Parameter(name="per_page", in="query", description="페이지당 항목 수",
*
* @OA\Schema(type="integer", minimum=1, maximum=100, default=20)
* ),
*
* @OA\Parameter(name="page", in="query", description="페이지 번호",
*
* @OA\Schema(type="integer", minimum=1)
* ),
*
* @OA\Response(
* response=200,
* description="신청 목록",
*
* @OA\JsonContent(
* type="object",
*
* @OA\Property(property="success", type="boolean", example=true),
* @OA\Property(property="message", type="string", example="조회되었습니다."),
* @OA\Property(property="data", ref="#/components/schemas/CompanyRequestPagination")
* )
* ),
*
* @OA\Response(response=401, description="인증 실패"),
* @OA\Response(response=403, description="권한 없음")
* )
*/
public function requests() {}
/**
* @OA\Get(
* path="/api/v1/companies/requests/{id}",
* operationId="getCompanyRequest",
* tags={"Companies"},
* summary="회사 추가 신청 상세",
* description="회사 추가 신청 상세 정보를 조회합니다.",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, description="신청 ID",
*
* @OA\Schema(type="integer")
* ),
*
* @OA\Response(
* response=200,
* description="신청 상세",
*
* @OA\JsonContent(
* type="object",
*
* @OA\Property(property="success", type="boolean", example=true),
* @OA\Property(property="message", type="string", example="조회되었습니다."),
* @OA\Property(property="data", ref="#/components/schemas/CompanyRequest")
* )
* ),
*
* @OA\Response(response=401, description="인증 실패"),
* @OA\Response(response=404, description="신청 없음")
* )
*/
public function showRequest() {}
/**
* @OA\Post(
* path="/api/v1/companies/requests/{id}/approve",
* operationId="approveCompanyRequest",
* tags={"Companies"},
* summary="회사 추가 신청 승인",
* description="회사 추가 신청을 승인합니다. 승인 시 새로운 테넌트가 생성되고, 신청자가 해당 테넌트에 연결됩니다.",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, description="신청 ID",
*
* @OA\Schema(type="integer")
* ),
*
* @OA\Response(
* response=200,
* description="승인 완료",
*
* @OA\JsonContent(
* type="object",
*
* @OA\Property(property="success", type="boolean", example=true),
* @OA\Property(property="message", type="string", example="승인되었습니다."),
* @OA\Property(property="data", ref="#/components/schemas/CompanyRequest")
* )
* ),
*
* @OA\Response(response=400, description="잘못된 요청 (이미 처리됨 등)"),
* @OA\Response(response=401, description="인증 실패"),
* @OA\Response(response=403, description="권한 없음"),
* @OA\Response(response=404, description="신청 없음")
* )
*/
public function approve() {}
/**
* @OA\Post(
* path="/api/v1/companies/requests/{id}/reject",
* operationId="rejectCompanyRequest",
* tags={"Companies"},
* summary="회사 추가 신청 반려",
* description="회사 추가 신청을 반려합니다.",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, description="신청 ID",
*
* @OA\Schema(type="integer")
* ),
*
* @OA\RequestBody(
* description="반려 사유",
*
* @OA\JsonContent(ref="#/components/schemas/CompanyRequestActionRequest")
* ),
*
* @OA\Response(
* response=200,
* description="반려 완료",
*
* @OA\JsonContent(
* type="object",
*
* @OA\Property(property="success", type="boolean", example=true),
* @OA\Property(property="message", type="string", example="반려되었습니다."),
* @OA\Property(property="data", ref="#/components/schemas/CompanyRequest")
* )
* ),
*
* @OA\Response(response=400, description="잘못된 요청 (이미 처리됨 등)"),
* @OA\Response(response=401, description="인증 실패"),
* @OA\Response(response=403, description="권한 없음"),
* @OA\Response(response=404, description="신청 없음")
* )
*/
public function reject() {}
/**
* @OA\Get(
* path="/api/v1/companies/my-requests",
* operationId="getMyCompanyRequests",
* tags={"Companies"},
* summary="내 회사 추가 신청 목록",
* description="현재 사용자의 회사 추가 신청 목록을 조회합니다.",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
*
* @OA\Parameter(name="status", in="query", description="상태 필터",
*
* @OA\Schema(type="string", enum={"pending","approved","rejected"})
* ),
*
* @OA\Parameter(name="sort_by", in="query", description="정렬 기준",
*
* @OA\Schema(type="string", enum={"created_at","company_name","status","processed_at"})
* ),
*
* @OA\Parameter(name="sort_dir", in="query", description="정렬 방향",
*
* @OA\Schema(type="string", enum={"asc","desc"})
* ),
*
* @OA\Parameter(name="per_page", in="query", description="페이지당 항목 수",
*
* @OA\Schema(type="integer", minimum=1, maximum=100, default=20)
* ),
*
* @OA\Parameter(name="page", in="query", description="페이지 번호",
*
* @OA\Schema(type="integer", minimum=1)
* ),
*
* @OA\Response(
* response=200,
* description="내 신청 목록",
*
* @OA\JsonContent(
* type="object",
*
* @OA\Property(property="success", type="boolean", example=true),
* @OA\Property(property="message", type="string", example="조회되었습니다."),
* @OA\Property(property="data", ref="#/components/schemas/CompanyRequestPagination")
* )
* ),
*
* @OA\Response(response=401, description="인증 실패")
* )
*/
public function myRequests() {}
}