361 lines
16 KiB
PHP
361 lines
16 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
namespace App\Swagger\v1;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @OA\Tag(
|
||
|
|
* name="Bidding",
|
||
|
|
* description="입찰관리 API"
|
||
|
|
* )
|
||
|
|
*
|
||
|
|
* @OA\Schema(
|
||
|
|
* schema="Bidding",
|
||
|
|
* type="object",
|
||
|
|
*
|
||
|
|
* @OA\Property(property="id", type="integer", example=1),
|
||
|
|
* @OA\Property(property="tenant_id", type="integer", example=1),
|
||
|
|
* @OA\Property(property="bidding_code", type="string", example="BID-20260119-0001"),
|
||
|
|
* @OA\Property(property="quote_id", type="integer", nullable=true, example=1),
|
||
|
|
* @OA\Property(property="client_id", type="integer", nullable=true, example=1),
|
||
|
|
* @OA\Property(property="client_name", type="string", nullable=true, example="삼성물산"),
|
||
|
|
* @OA\Property(property="project_name", type="string", nullable=true, example="강남역 오피스타워 신축공사"),
|
||
|
|
* @OA\Property(property="bidding_date", type="string", format="date", nullable=true, example="2026-01-19"),
|
||
|
|
* @OA\Property(property="bid_date", type="string", format="date", nullable=true, example="2026-02-01"),
|
||
|
|
* @OA\Property(property="submission_date", type="string", format="date", nullable=true, example="2026-01-25"),
|
||
|
|
* @OA\Property(property="confirm_date", type="string", format="date", nullable=true, example="2026-02-15"),
|
||
|
|
* @OA\Property(property="total_count", type="integer", nullable=true, example=1),
|
||
|
|
* @OA\Property(property="bidding_amount", type="number", format="float", nullable=true, example=150000000),
|
||
|
|
* @OA\Property(property="status", type="string", enum={"waiting", "submitted", "failed", "invalid", "awarded", "hold"}, example="waiting"),
|
||
|
|
* @OA\Property(property="bidder_id", type="integer", nullable=true, example=1),
|
||
|
|
* @OA\Property(property="bidder_name", type="string", nullable=true, example="홍길동"),
|
||
|
|
* @OA\Property(property="construction_start_date", type="string", format="date", nullable=true, example="2026-03-01"),
|
||
|
|
* @OA\Property(property="construction_end_date", type="string", format="date", nullable=true, example="2026-12-31"),
|
||
|
|
* @OA\Property(property="vat_type", type="string", enum={"included", "excluded"}, example="included"),
|
||
|
|
* @OA\Property(property="remarks", type="string", nullable=true, example="특이사항 없음"),
|
||
|
|
* @OA\Property(property="expense_items", type="array", nullable=true, @OA\Items(type="object")),
|
||
|
|
* @OA\Property(property="estimate_detail_items", type="array", nullable=true, @OA\Items(type="object")),
|
||
|
|
* @OA\Property(property="created_by", type="integer", nullable=true),
|
||
|
|
* @OA\Property(property="updated_by", type="integer", nullable=true),
|
||
|
|
* @OA\Property(property="created_at", type="string", format="date-time"),
|
||
|
|
* @OA\Property(property="updated_at", type="string", format="date-time"),
|
||
|
|
* @OA\Property(property="quote", type="object", nullable=true),
|
||
|
|
* @OA\Property(property="client", type="object", nullable=true),
|
||
|
|
* @OA\Property(property="bidder", type="object", nullable=true)
|
||
|
|
* )
|
||
|
|
*
|
||
|
|
* @OA\Schema(
|
||
|
|
* schema="BiddingPagination",
|
||
|
|
* type="object",
|
||
|
|
*
|
||
|
|
* @OA\Property(property="current_page", type="integer", example=1),
|
||
|
|
* @OA\Property(property="data", type="array", @OA\Items(ref="#/components/schemas/Bidding")),
|
||
|
|
* @OA\Property(property="first_page_url", type="string"),
|
||
|
|
* @OA\Property(property="from", type="integer"),
|
||
|
|
* @OA\Property(property="last_page", type="integer"),
|
||
|
|
* @OA\Property(property="last_page_url", type="string"),
|
||
|
|
* @OA\Property(property="next_page_url", type="string", nullable=true),
|
||
|
|
* @OA\Property(property="path", type="string"),
|
||
|
|
* @OA\Property(property="per_page", type="integer"),
|
||
|
|
* @OA\Property(property="prev_page_url", type="string", nullable=true),
|
||
|
|
* @OA\Property(property="to", type="integer"),
|
||
|
|
* @OA\Property(property="total", type="integer")
|
||
|
|
* )
|
||
|
|
*
|
||
|
|
* @OA\Schema(
|
||
|
|
* schema="BiddingStats",
|
||
|
|
* type="object",
|
||
|
|
*
|
||
|
|
* @OA\Property(property="total", type="integer", example=100),
|
||
|
|
* @OA\Property(property="waiting", type="integer", example=30),
|
||
|
|
* @OA\Property(property="submitted", type="integer", example=20),
|
||
|
|
* @OA\Property(property="failed", type="integer", example=10),
|
||
|
|
* @OA\Property(property="invalid", type="integer", example=5),
|
||
|
|
* @OA\Property(property="awarded", type="integer", example=30),
|
||
|
|
* @OA\Property(property="hold", type="integer", example=5),
|
||
|
|
* @OA\Property(property="total_amount", type="number", format="float", example=5000000000),
|
||
|
|
* @OA\Property(property="awarded_amount", type="number", format="float", example=3000000000)
|
||
|
|
* )
|
||
|
|
*
|
||
|
|
* @OA\Schema(
|
||
|
|
* schema="BiddingUpdateRequest",
|
||
|
|
* type="object",
|
||
|
|
*
|
||
|
|
* @OA\Property(property="client_id", type="integer", nullable=true),
|
||
|
|
* @OA\Property(property="client_name", type="string", nullable=true, maxLength=100),
|
||
|
|
* @OA\Property(property="project_name", type="string", nullable=true, maxLength=200),
|
||
|
|
* @OA\Property(property="bidding_date", type="string", format="date", nullable=true),
|
||
|
|
* @OA\Property(property="bid_date", type="string", format="date", nullable=true),
|
||
|
|
* @OA\Property(property="submission_date", type="string", format="date", nullable=true),
|
||
|
|
* @OA\Property(property="confirm_date", type="string", format="date", nullable=true),
|
||
|
|
* @OA\Property(property="total_count", type="integer", nullable=true, minimum=0),
|
||
|
|
* @OA\Property(property="bidding_amount", type="number", format="float", nullable=true, minimum=0),
|
||
|
|
* @OA\Property(property="status", type="string", enum={"waiting", "submitted", "failed", "invalid", "awarded", "hold"}, nullable=true),
|
||
|
|
* @OA\Property(property="bidder_id", type="integer", nullable=true),
|
||
|
|
* @OA\Property(property="bidder_name", type="string", nullable=true, maxLength=50),
|
||
|
|
* @OA\Property(property="construction_start_date", type="string", format="date", nullable=true),
|
||
|
|
* @OA\Property(property="construction_end_date", type="string", format="date", nullable=true),
|
||
|
|
* @OA\Property(property="vat_type", type="string", enum={"included", "excluded"}, nullable=true),
|
||
|
|
* @OA\Property(property="remarks", type="string", nullable=true),
|
||
|
|
* @OA\Property(property="expense_items", type="array", nullable=true, @OA\Items(type="object")),
|
||
|
|
* @OA\Property(property="estimate_detail_items", type="array", nullable=true, @OA\Items(type="object"))
|
||
|
|
* )
|
||
|
|
*
|
||
|
|
* @OA\Schema(
|
||
|
|
* schema="BiddingStatusRequest",
|
||
|
|
* type="object",
|
||
|
|
* required={"status"},
|
||
|
|
*
|
||
|
|
* @OA\Property(property="status", type="string", enum={"waiting", "submitted", "failed", "invalid", "awarded", "hold"}, example="submitted")
|
||
|
|
* )
|
||
|
|
*
|
||
|
|
* @OA\Schema(
|
||
|
|
* schema="BiddingBulkDeleteRequest",
|
||
|
|
* type="object",
|
||
|
|
* required={"ids"},
|
||
|
|
*
|
||
|
|
* @OA\Property(property="ids", type="array", @OA\Items(type="integer"), example={1, 2, 3})
|
||
|
|
* )
|
||
|
|
*/
|
||
|
|
class BiddingApi
|
||
|
|
{
|
||
|
|
/**
|
||
|
|
* @OA\Get(
|
||
|
|
* path="/api/v1/biddings",
|
||
|
|
* tags={"Bidding"},
|
||
|
|
* summary="입찰 목록 조회",
|
||
|
|
* description="입찰 목록을 페이징하여 조회합니다.",
|
||
|
|
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
|
||
|
|
*
|
||
|
|
* @OA\Parameter(name="page", in="query", @OA\Schema(type="integer", default=1)),
|
||
|
|
* @OA\Parameter(name="size", in="query", @OA\Schema(type="integer", default=20)),
|
||
|
|
* @OA\Parameter(name="q", in="query", description="검색어 (입찰번호, 현장명, 거래처명)", @OA\Schema(type="string")),
|
||
|
|
* @OA\Parameter(name="status", in="query", description="상태 필터", @OA\Schema(type="string", enum={"waiting", "submitted", "failed", "invalid", "awarded", "hold"})),
|
||
|
|
* @OA\Parameter(name="client_id", in="query", description="거래처 ID", @OA\Schema(type="integer")),
|
||
|
|
* @OA\Parameter(name="bidder_id", in="query", description="입찰담당자 ID", @OA\Schema(type="integer")),
|
||
|
|
* @OA\Parameter(name="date_from", in="query", description="입찰일 시작", @OA\Schema(type="string", format="date")),
|
||
|
|
* @OA\Parameter(name="date_to", in="query", description="입찰일 종료", @OA\Schema(type="string", format="date")),
|
||
|
|
* @OA\Parameter(name="sort_by", in="query", description="정렬 기준", @OA\Schema(type="string", default="bidding_date")),
|
||
|
|
* @OA\Parameter(name="sort_order", in="query", description="정렬 순서", @OA\Schema(type="string", enum={"asc", "desc"}, default="desc")),
|
||
|
|
*
|
||
|
|
* @OA\Response(
|
||
|
|
* response=200,
|
||
|
|
* description="성공",
|
||
|
|
*
|
||
|
|
* @OA\JsonContent(
|
||
|
|
*
|
||
|
|
* @OA\Property(property="success", type="boolean", example=true),
|
||
|
|
* @OA\Property(property="message", type="string"),
|
||
|
|
* @OA\Property(property="data", ref="#/components/schemas/BiddingPagination")
|
||
|
|
* )
|
||
|
|
* )
|
||
|
|
* )
|
||
|
|
*/
|
||
|
|
public function index() {}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @OA\Get(
|
||
|
|
* path="/api/v1/biddings/stats",
|
||
|
|
* tags={"Bidding"},
|
||
|
|
* summary="입찰 통계 조회",
|
||
|
|
* description="상태별 입찰 건수와 금액을 조회합니다.",
|
||
|
|
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
|
||
|
|
*
|
||
|
|
* @OA\Response(
|
||
|
|
* response=200,
|
||
|
|
* description="성공",
|
||
|
|
*
|
||
|
|
* @OA\JsonContent(
|
||
|
|
*
|
||
|
|
* @OA\Property(property="success", type="boolean", example=true),
|
||
|
|
* @OA\Property(property="message", type="string"),
|
||
|
|
* @OA\Property(property="data", ref="#/components/schemas/BiddingStats")
|
||
|
|
* )
|
||
|
|
* )
|
||
|
|
* )
|
||
|
|
*/
|
||
|
|
public function stats() {}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @OA\Get(
|
||
|
|
* path="/api/v1/biddings/{id}",
|
||
|
|
* tags={"Bidding"},
|
||
|
|
* summary="입찰 단건 조회",
|
||
|
|
* description="입찰 상세 정보를 조회합니다.",
|
||
|
|
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
|
||
|
|
*
|
||
|
|
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
|
||
|
|
*
|
||
|
|
* @OA\Response(
|
||
|
|
* response=200,
|
||
|
|
* description="성공",
|
||
|
|
*
|
||
|
|
* @OA\JsonContent(
|
||
|
|
*
|
||
|
|
* @OA\Property(property="success", type="boolean", example=true),
|
||
|
|
* @OA\Property(property="message", type="string"),
|
||
|
|
* @OA\Property(property="data", ref="#/components/schemas/Bidding")
|
||
|
|
* )
|
||
|
|
* ),
|
||
|
|
*
|
||
|
|
* @OA\Response(response=404, description="입찰을 찾을 수 없습니다")
|
||
|
|
* )
|
||
|
|
*/
|
||
|
|
public function show() {}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @OA\Put(
|
||
|
|
* path="/api/v1/biddings/{id}",
|
||
|
|
* tags={"Bidding"},
|
||
|
|
* summary="입찰 수정",
|
||
|
|
* description="입찰 정보를 수정합니다.",
|
||
|
|
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
|
||
|
|
*
|
||
|
|
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
|
||
|
|
*
|
||
|
|
* @OA\RequestBody(
|
||
|
|
* required=true,
|
||
|
|
*
|
||
|
|
* @OA\JsonContent(ref="#/components/schemas/BiddingUpdateRequest")
|
||
|
|
* ),
|
||
|
|
*
|
||
|
|
* @OA\Response(
|
||
|
|
* response=200,
|
||
|
|
* description="성공",
|
||
|
|
*
|
||
|
|
* @OA\JsonContent(
|
||
|
|
*
|
||
|
|
* @OA\Property(property="success", type="boolean", example=true),
|
||
|
|
* @OA\Property(property="message", type="string"),
|
||
|
|
* @OA\Property(property="data", ref="#/components/schemas/Bidding")
|
||
|
|
* )
|
||
|
|
* ),
|
||
|
|
*
|
||
|
|
* @OA\Response(response=404, description="입찰을 찾을 수 없습니다"),
|
||
|
|
* @OA\Response(response=422, description="유효성 검증 실패")
|
||
|
|
* )
|
||
|
|
*/
|
||
|
|
public function update() {}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @OA\Delete(
|
||
|
|
* path="/api/v1/biddings/{id}",
|
||
|
|
* tags={"Bidding"},
|
||
|
|
* summary="입찰 삭제",
|
||
|
|
* description="입찰을 삭제합니다 (Soft Delete).",
|
||
|
|
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
|
||
|
|
*
|
||
|
|
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
|
||
|
|
*
|
||
|
|
* @OA\Response(
|
||
|
|
* response=200,
|
||
|
|
* description="성공",
|
||
|
|
*
|
||
|
|
* @OA\JsonContent(
|
||
|
|
*
|
||
|
|
* @OA\Property(property="success", type="boolean", example=true),
|
||
|
|
* @OA\Property(property="message", type="string"),
|
||
|
|
* @OA\Property(property="data", type="null")
|
||
|
|
* )
|
||
|
|
* ),
|
||
|
|
*
|
||
|
|
* @OA\Response(response=404, description="입찰을 찾을 수 없습니다")
|
||
|
|
* )
|
||
|
|
*/
|
||
|
|
public function destroy() {}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @OA\Delete(
|
||
|
|
* path="/api/v1/biddings/bulk",
|
||
|
|
* tags={"Bidding"},
|
||
|
|
* summary="입찰 일괄 삭제",
|
||
|
|
* description="여러 입찰을 일괄 삭제합니다 (Soft Delete).",
|
||
|
|
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
|
||
|
|
*
|
||
|
|
* @OA\RequestBody(
|
||
|
|
* required=true,
|
||
|
|
*
|
||
|
|
* @OA\JsonContent(ref="#/components/schemas/BiddingBulkDeleteRequest")
|
||
|
|
* ),
|
||
|
|
*
|
||
|
|
* @OA\Response(
|
||
|
|
* response=200,
|
||
|
|
* description="성공",
|
||
|
|
*
|
||
|
|
* @OA\JsonContent(
|
||
|
|
*
|
||
|
|
* @OA\Property(property="success", type="boolean", example=true),
|
||
|
|
* @OA\Property(property="message", type="string"),
|
||
|
|
* @OA\Property(property="data", type="object",
|
||
|
|
* @OA\Property(property="deleted_count", type="integer", example=3)
|
||
|
|
* )
|
||
|
|
* )
|
||
|
|
* ),
|
||
|
|
*
|
||
|
|
* @OA\Response(response=422, description="유효성 검증 실패")
|
||
|
|
* )
|
||
|
|
*/
|
||
|
|
public function bulkDestroy() {}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @OA\Patch(
|
||
|
|
* path="/api/v1/biddings/{id}/status",
|
||
|
|
* tags={"Bidding"},
|
||
|
|
* summary="입찰 상태 변경",
|
||
|
|
* description="입찰 상태를 변경합니다.",
|
||
|
|
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
|
||
|
|
*
|
||
|
|
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
|
||
|
|
*
|
||
|
|
* @OA\RequestBody(
|
||
|
|
* required=true,
|
||
|
|
*
|
||
|
|
* @OA\JsonContent(ref="#/components/schemas/BiddingStatusRequest")
|
||
|
|
* ),
|
||
|
|
*
|
||
|
|
* @OA\Response(
|
||
|
|
* response=200,
|
||
|
|
* description="성공",
|
||
|
|
*
|
||
|
|
* @OA\JsonContent(
|
||
|
|
*
|
||
|
|
* @OA\Property(property="success", type="boolean", example=true),
|
||
|
|
* @OA\Property(property="message", type="string"),
|
||
|
|
* @OA\Property(property="data", ref="#/components/schemas/Bidding")
|
||
|
|
* )
|
||
|
|
* ),
|
||
|
|
*
|
||
|
|
* @OA\Response(response=404, description="입찰을 찾을 수 없습니다"),
|
||
|
|
* @OA\Response(response=422, description="유효성 검증 실패")
|
||
|
|
* )
|
||
|
|
*/
|
||
|
|
public function updateStatus() {}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @OA\Post(
|
||
|
|
* path="/api/v1/quotes/{id}/convert-to-bidding",
|
||
|
|
* tags={"Bidding"},
|
||
|
|
* 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(
|
||
|
|
*
|
||
|
|
* @OA\Property(property="success", type="boolean", example=true),
|
||
|
|
* @OA\Property(property="message", type="string"),
|
||
|
|
* @OA\Property(property="data", ref="#/components/schemas/Bidding")
|
||
|
|
* )
|
||
|
|
* ),
|
||
|
|
*
|
||
|
|
* @OA\Response(response=404, description="견적을 찾을 수 없습니다"),
|
||
|
|
* @OA\Response(response=400, description="이미 입찰로 변환된 견적입니다")
|
||
|
|
* )
|
||
|
|
*/
|
||
|
|
public function convertToBidding() {}
|
||
|
|
}
|