feat: 단가 관리 API 구현 및 Flow Tester 호환성 개선
- Price, PriceRevision 모델 추가 (PriceHistory 대체) - PricingService: CRUD, 원가 조회, 확정 기능 - PricingController: statusCode 파라미터로 201 반환 지원 - NotFoundHttpException(404) 적용 (존재하지 않는 리소스) - FormRequest 분리 (Store, Update, Index, Cost, ByItems) - Swagger 문서 업데이트 - ApiResponse::handle()에 statusCode 옵션 추가 - prices/price_revisions 마이그레이션 및 데이터 이관
This commit is contained in:
@@ -3,87 +3,137 @@
|
||||
namespace App\Swagger\v1;
|
||||
|
||||
/**
|
||||
* @OA\Tag(name="Pricing", description="가격 이력 관리")
|
||||
* @OA\Tag(name="Pricing", description="단가 관리")
|
||||
*
|
||||
* ========= 스키마 정의 =========
|
||||
*
|
||||
* @OA\Schema(
|
||||
* schema="PriceHistory",
|
||||
* schema="Price",
|
||||
* type="object",
|
||||
* required={"id","item_type_code","item_id","price_type_code","price","started_at"},
|
||||
* description="단가 마스터",
|
||||
*
|
||||
* @OA\Property(property="id", type="integer", example=1),
|
||||
* @OA\Property(property="tenant_id", type="integer", example=1),
|
||||
* @OA\Property(property="item_type_code", type="string", enum={"PRODUCT","MATERIAL"}, example="PRODUCT", description="항목 유형"),
|
||||
* @OA\Property(property="item_id", type="integer", example=10, description="제품/자재 ID"),
|
||||
* @OA\Property(property="price_type_code", type="string", enum={"SALE","PURCHASE"}, example="SALE", description="가격 유형"),
|
||||
* @OA\Property(property="client_group_id", type="integer", nullable=true, example=1, description="고객 그룹 ID (NULL=기본 가격)"),
|
||||
* @OA\Property(property="price", type="number", format="decimal", example=50000.00),
|
||||
* @OA\Property(property="started_at", type="string", format="date", example="2025-01-01"),
|
||||
* @OA\Property(property="ended_at", type="string", format="date", nullable=true, example="2025-12-31"),
|
||||
* @OA\Property(property="created_at", type="string", example="2025-10-01 12:00:00"),
|
||||
* @OA\Property(property="updated_at", type="string", example="2025-10-01 12:00:00")
|
||||
* @OA\Property(property="item_type_code", type="string", enum={"PRODUCT","MATERIAL"}, example="PRODUCT", description="품목 유형"),
|
||||
* @OA\Property(property="item_id", type="integer", example=10, description="품목 ID"),
|
||||
* @OA\Property(property="client_group_id", type="integer", nullable=true, example=1, description="고객그룹 ID (NULL=기본가)"),
|
||||
* @OA\Property(property="purchase_price", type="number", format="decimal", nullable=true, example=10000.00, description="매입단가 (표준원가)"),
|
||||
* @OA\Property(property="processing_cost", type="number", format="decimal", nullable=true, example=2000.00, description="가공비"),
|
||||
* @OA\Property(property="loss_rate", type="number", format="decimal", nullable=true, example=5.00, description="LOSS율 (%)"),
|
||||
* @OA\Property(property="margin_rate", type="number", format="decimal", nullable=true, example=25.00, description="마진율 (%)"),
|
||||
* @OA\Property(property="sales_price", type="number", format="decimal", nullable=true, example=15800.00, description="판매단가"),
|
||||
* @OA\Property(property="rounding_rule", type="string", enum={"round","ceil","floor"}, example="round", description="반올림 규칙"),
|
||||
* @OA\Property(property="rounding_unit", type="integer", example=100, description="반올림 단위 (1,10,100,1000)"),
|
||||
* @OA\Property(property="supplier", type="string", nullable=true, example="ABC공급", description="공급업체"),
|
||||
* @OA\Property(property="effective_from", type="string", format="date", example="2025-01-01", description="적용 시작일"),
|
||||
* @OA\Property(property="effective_to", type="string", format="date", nullable=true, example="2025-12-31", description="적용 종료일"),
|
||||
* @OA\Property(property="note", type="string", nullable=true, example="2025년 상반기 가격", description="비고"),
|
||||
* @OA\Property(property="status", type="string", enum={"draft","active","inactive","finalized"}, example="active", description="상태"),
|
||||
* @OA\Property(property="is_final", type="boolean", example=false, description="최종 확정 여부"),
|
||||
* @OA\Property(property="finalized_at", type="string", format="datetime", nullable=true, example="2025-01-15 10:30:00", description="확정 일시"),
|
||||
* @OA\Property(property="finalized_by", type="integer", nullable=true, example=1, description="확정자 ID"),
|
||||
* @OA\Property(property="created_at", type="string", example="2025-01-01 12:00:00"),
|
||||
* @OA\Property(property="updated_at", type="string", example="2025-01-01 12:00:00"),
|
||||
* @OA\Property(
|
||||
* property="client_group",
|
||||
* type="object",
|
||||
* nullable=true,
|
||||
* @OA\Property(property="id", type="integer", example=1),
|
||||
* @OA\Property(property="name", type="string", example="VIP 고객")
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* @OA\Schema(
|
||||
* schema="PriceHistoryPagination",
|
||||
* schema="PricePagination",
|
||||
* type="object",
|
||||
*
|
||||
* @OA\Property(property="current_page", type="integer", example=1),
|
||||
* @OA\Property(
|
||||
* property="data",
|
||||
* type="array",
|
||||
*
|
||||
* @OA\Items(ref="#/components/schemas/PriceHistory")
|
||||
* ),
|
||||
*
|
||||
* @OA\Property(property="data", type="array", @OA\Items(ref="#/components/schemas/Price")),
|
||||
* @OA\Property(property="first_page_url", type="string", example="/api/v1/pricing?page=1"),
|
||||
* @OA\Property(property="from", type="integer", example=1),
|
||||
* @OA\Property(property="last_page", type="integer", example=3),
|
||||
* @OA\Property(property="last_page_url", type="string", example="/api/v1/pricing?page=3"),
|
||||
* @OA\Property(
|
||||
* property="links",
|
||||
* type="array",
|
||||
*
|
||||
* @OA\Items(type="object",
|
||||
*
|
||||
* @OA\Property(property="url", type="string", nullable=true, example=null),
|
||||
* @OA\Property(property="label", type="string", example="« Previous"),
|
||||
* @OA\Property(property="active", type="boolean", example=false)
|
||||
* )
|
||||
* ),
|
||||
* @OA\Property(property="next_page_url", type="string", nullable=true, example="/api/v1/pricing?page=2"),
|
||||
* @OA\Property(property="links", type="array", @OA\Items(type="object",
|
||||
* @OA\Property(property="url", type="string", nullable=true),
|
||||
* @OA\Property(property="label", type="string"),
|
||||
* @OA\Property(property="active", type="boolean")
|
||||
* )),
|
||||
* @OA\Property(property="next_page_url", type="string", nullable=true),
|
||||
* @OA\Property(property="path", type="string", example="/api/v1/pricing"),
|
||||
* @OA\Property(property="per_page", type="integer", example=15),
|
||||
* @OA\Property(property="prev_page_url", type="string", nullable=true, example=null),
|
||||
* @OA\Property(property="to", type="integer", example=15),
|
||||
* @OA\Property(property="per_page", type="integer", example=20),
|
||||
* @OA\Property(property="prev_page_url", type="string", nullable=true),
|
||||
* @OA\Property(property="to", type="integer", example=20),
|
||||
* @OA\Property(property="total", type="integer", example=50)
|
||||
* )
|
||||
*
|
||||
* @OA\Schema(
|
||||
* schema="PriceUpsertRequest",
|
||||
* schema="PriceRevision",
|
||||
* type="object",
|
||||
* required={"item_type_code","item_id","price_type_code","price","started_at"},
|
||||
* description="단가 변경 이력",
|
||||
*
|
||||
* @OA\Property(property="id", type="integer", example=1),
|
||||
* @OA\Property(property="price_id", type="integer", example=1),
|
||||
* @OA\Property(property="revision_number", type="integer", example=1, description="리비전 번호"),
|
||||
* @OA\Property(property="changed_at", type="string", format="datetime", example="2025-01-01 12:00:00", description="변경 일시"),
|
||||
* @OA\Property(property="changed_by", type="integer", example=1, description="변경자 ID"),
|
||||
* @OA\Property(property="change_reason", type="string", nullable=true, example="2025년 단가 인상", description="변경 사유"),
|
||||
* @OA\Property(property="before_snapshot", type="object", nullable=true, description="변경 전 데이터"),
|
||||
* @OA\Property(property="after_snapshot", type="object", description="변경 후 데이터"),
|
||||
* @OA\Property(
|
||||
* property="changed_by_user",
|
||||
* type="object",
|
||||
* nullable=true,
|
||||
* @OA\Property(property="id", type="integer", example=1),
|
||||
* @OA\Property(property="name", type="string", example="홍길동")
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* @OA\Schema(
|
||||
* schema="PriceStoreRequest",
|
||||
* type="object",
|
||||
* required={"item_type_code","item_id","effective_from"},
|
||||
*
|
||||
* @OA\Property(property="item_type_code", type="string", enum={"PRODUCT","MATERIAL"}, example="PRODUCT"),
|
||||
* @OA\Property(property="item_id", type="integer", example=10),
|
||||
* @OA\Property(property="price_type_code", type="string", enum={"SALE","PURCHASE"}, example="SALE"),
|
||||
* @OA\Property(property="client_group_id", type="integer", nullable=true, example=1, description="NULL=기본 가격"),
|
||||
* @OA\Property(property="price", type="number", format="decimal", example=50000.00),
|
||||
* @OA\Property(property="started_at", type="string", format="date", example="2025-01-01"),
|
||||
* @OA\Property(property="ended_at", type="string", format="date", nullable=true, example="2025-12-31")
|
||||
* @OA\Property(property="client_group_id", type="integer", nullable=true, example=1),
|
||||
* @OA\Property(property="purchase_price", type="number", nullable=true, example=10000.00),
|
||||
* @OA\Property(property="processing_cost", type="number", nullable=true, example=2000.00),
|
||||
* @OA\Property(property="loss_rate", type="number", nullable=true, example=5.00),
|
||||
* @OA\Property(property="margin_rate", type="number", nullable=true, example=25.00),
|
||||
* @OA\Property(property="sales_price", type="number", nullable=true, example=15800.00),
|
||||
* @OA\Property(property="rounding_rule", type="string", enum={"round","ceil","floor"}, example="round"),
|
||||
* @OA\Property(property="rounding_unit", type="integer", enum={1,10,100,1000}, example=100),
|
||||
* @OA\Property(property="supplier", type="string", nullable=true, example="ABC공급"),
|
||||
* @OA\Property(property="effective_from", type="string", format="date", example="2025-01-01"),
|
||||
* @OA\Property(property="effective_to", type="string", format="date", nullable=true, example="2025-12-31"),
|
||||
* @OA\Property(property="note", type="string", nullable=true, example="2025년 상반기 가격"),
|
||||
* @OA\Property(property="status", type="string", enum={"draft","active","inactive"}, example="draft")
|
||||
* )
|
||||
*
|
||||
* @OA\Schema(
|
||||
* schema="PriceQueryResult",
|
||||
* schema="PriceUpdateRequest",
|
||||
* type="object",
|
||||
*
|
||||
* @OA\Property(property="price", type="number", format="decimal", nullable=true, example=50000.00),
|
||||
* @OA\Property(property="price_history_id", type="integer", nullable=true, example=1),
|
||||
* @OA\Property(property="item_type_code", type="string", enum={"PRODUCT","MATERIAL"}, example="PRODUCT"),
|
||||
* @OA\Property(property="item_id", type="integer", example=10),
|
||||
* @OA\Property(property="client_group_id", type="integer", nullable=true, example=1),
|
||||
* @OA\Property(property="warning", type="string", nullable=true, example="가격을 찾을 수 없습니다")
|
||||
* @OA\Property(property="purchase_price", type="number", nullable=true, example=10000.00),
|
||||
* @OA\Property(property="processing_cost", type="number", nullable=true, example=2000.00),
|
||||
* @OA\Property(property="loss_rate", type="number", nullable=true, example=5.00),
|
||||
* @OA\Property(property="margin_rate", type="number", nullable=true, example=25.00),
|
||||
* @OA\Property(property="sales_price", type="number", nullable=true, example=15800.00),
|
||||
* @OA\Property(property="rounding_rule", type="string", enum={"round","ceil","floor"}, example="round"),
|
||||
* @OA\Property(property="rounding_unit", type="integer", enum={1,10,100,1000}, example=100),
|
||||
* @OA\Property(property="supplier", type="string", nullable=true, example="ABC공급"),
|
||||
* @OA\Property(property="effective_from", type="string", format="date", example="2025-01-01"),
|
||||
* @OA\Property(property="effective_to", type="string", format="date", nullable=true, example="2025-12-31"),
|
||||
* @OA\Property(property="note", type="string", nullable=true, example="2025년 상반기 가격"),
|
||||
* @OA\Property(property="status", type="string", enum={"draft","active","inactive"}, example="active"),
|
||||
* @OA\Property(property="change_reason", type="string", nullable=true, example="단가 인상", description="변경 사유 (리비전 기록용)")
|
||||
* )
|
||||
*
|
||||
* @OA\Schema(
|
||||
* schema="BulkPriceQueryRequest",
|
||||
* schema="PriceByItemsRequest",
|
||||
* type="object",
|
||||
* required={"items"},
|
||||
*
|
||||
@@ -93,32 +143,39 @@
|
||||
*
|
||||
* @OA\Items(type="object",
|
||||
*
|
||||
* @OA\Property(property="item_type", type="string", enum={"PRODUCT","MATERIAL"}, example="PRODUCT"),
|
||||
* @OA\Property(property="item_type_code", type="string", enum={"PRODUCT","MATERIAL"}, example="PRODUCT"),
|
||||
* @OA\Property(property="item_id", type="integer", example=10)
|
||||
* )
|
||||
* ),
|
||||
* @OA\Property(property="client_id", type="integer", nullable=true, example=5),
|
||||
* @OA\Property(property="date", type="string", format="date", nullable=true, example="2025-10-13")
|
||||
* @OA\Property(property="client_group_id", type="integer", nullable=true, example=1),
|
||||
* @OA\Property(property="date", type="string", format="date", nullable=true, example="2025-01-15")
|
||||
* )
|
||||
*
|
||||
* @OA\Schema(
|
||||
* schema="BulkPriceQueryResult",
|
||||
* schema="PriceByItemsResult",
|
||||
* type="array",
|
||||
*
|
||||
* @OA\Items(type="object",
|
||||
*
|
||||
* @OA\Property(property="item_type_code", type="string", example="PRODUCT"),
|
||||
* @OA\Property(property="item_id", type="integer", example=10),
|
||||
* @OA\Property(property="price", ref="#/components/schemas/Price", nullable=true),
|
||||
* @OA\Property(property="has_price", type="boolean", example=true)
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* @OA\Schema(
|
||||
* schema="PriceCostResult",
|
||||
* type="object",
|
||||
*
|
||||
* @OA\Property(
|
||||
* property="prices",
|
||||
* type="array",
|
||||
*
|
||||
* @OA\Items(type="object",
|
||||
*
|
||||
* @OA\Property(property="item_type", type="string", example="PRODUCT"),
|
||||
* @OA\Property(property="item_id", type="integer", example=10),
|
||||
* @OA\Property(property="price", type="number", nullable=true, example=50000.00),
|
||||
* @OA\Property(property="price_history_id", type="integer", nullable=true, example=1),
|
||||
* @OA\Property(property="client_group_id", type="integer", nullable=true, example=1)
|
||||
* )
|
||||
* ),
|
||||
* @OA\Property(property="warnings", type="array", @OA\Items(type="string"))
|
||||
* @OA\Property(property="item_type_code", type="string", example="MATERIAL"),
|
||||
* @OA\Property(property="item_id", type="integer", example=123),
|
||||
* @OA\Property(property="date", type="string", format="date", example="2025-01-15"),
|
||||
* @OA\Property(property="cost_source", type="string", enum={"receipt","standard","not_found"}, example="receipt", description="원가 출처"),
|
||||
* @OA\Property(property="purchase_price", type="number", nullable=true, example=10500.00),
|
||||
* @OA\Property(property="receipt_id", type="integer", nullable=true, example=456, description="수입검사 ID (cost_source=receipt일 때)"),
|
||||
* @OA\Property(property="receipt_date", type="string", format="date", nullable=true, example="2025-01-10"),
|
||||
* @OA\Property(property="price_id", type="integer", nullable=true, example=null, description="단가 ID (cost_source=standard일 때)")
|
||||
* )
|
||||
*/
|
||||
class PricingApi
|
||||
@@ -127,22 +184,24 @@ class PricingApi
|
||||
* @OA\Get(
|
||||
* path="/api/v1/pricing",
|
||||
* tags={"Pricing"},
|
||||
* summary="가격 이력 목록",
|
||||
* summary="단가 목록 조회",
|
||||
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
|
||||
*
|
||||
* @OA\Parameter(name="q", in="query", description="검색어 (supplier, note)", @OA\Schema(type="string")),
|
||||
* @OA\Parameter(name="item_type_code", in="query", @OA\Schema(type="string", enum={"PRODUCT","MATERIAL"})),
|
||||
* @OA\Parameter(name="item_id", in="query", @OA\Schema(type="integer")),
|
||||
* @OA\Parameter(name="price_type_code", in="query", @OA\Schema(type="string", enum={"SALE","PURCHASE"})),
|
||||
* @OA\Parameter(name="client_group_id", in="query", @OA\Schema(type="integer")),
|
||||
* @OA\Parameter(name="date", in="query", description="특정 날짜 기준 유효한 가격", @OA\Schema(type="string", format="date")),
|
||||
* @OA\Parameter(name="size", in="query", @OA\Schema(type="integer", example=15)),
|
||||
* @OA\Parameter(name="client_group_id", in="query", description="고객그룹 ID (빈값/null=기본가만)", @OA\Schema(type="string")),
|
||||
* @OA\Parameter(name="status", in="query", @OA\Schema(type="string", enum={"draft","active","inactive","finalized"})),
|
||||
* @OA\Parameter(name="valid_at", in="query", description="특정 날짜에 유효한 단가만", @OA\Schema(type="string", format="date")),
|
||||
* @OA\Parameter(name="size", in="query", @OA\Schema(type="integer", example=20)),
|
||||
* @OA\Parameter(name="page", in="query", @OA\Schema(type="integer", example=1)),
|
||||
*
|
||||
* @OA\Response(response=200, description="조회 성공",
|
||||
*
|
||||
* @OA\JsonContent(allOf={
|
||||
*
|
||||
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
|
||||
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/PriceHistoryPagination"))
|
||||
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/PricePagination"))
|
||||
* })
|
||||
* ),
|
||||
*
|
||||
@@ -153,86 +212,188 @@ public function index() {}
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/api/v1/pricing/show",
|
||||
* path="/api/v1/pricing/{id}",
|
||||
* tags={"Pricing"},
|
||||
* summary="단일 항목 가격 조회",
|
||||
* description="특정 제품/자재의 현재 유효한 가격 조회",
|
||||
* summary="단가 상세 조회",
|
||||
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
|
||||
*
|
||||
* @OA\Parameter(name="item_type", in="query", required=true, @OA\Schema(type="string", enum={"PRODUCT","MATERIAL"})),
|
||||
* @OA\Parameter(name="item_id", in="query", required=true, @OA\Schema(type="integer")),
|
||||
* @OA\Parameter(name="client_id", in="query", @OA\Schema(type="integer"), description="고객 ID (고객 그룹별 가격 적용)"),
|
||||
* @OA\Parameter(name="date", in="query", @OA\Schema(type="string", format="date"), description="기준일 (미지정시 오늘)"),
|
||||
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
|
||||
*
|
||||
* @OA\Response(response=200, description="조회 성공",
|
||||
*
|
||||
* @OA\JsonContent(allOf={
|
||||
*
|
||||
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
|
||||
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/PriceQueryResult"))
|
||||
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Price"))
|
||||
* })
|
||||
* )
|
||||
* ),
|
||||
*
|
||||
* @OA\Response(response=404, description="미존재", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
|
||||
* )
|
||||
*/
|
||||
public function show() {}
|
||||
|
||||
/**
|
||||
* @OA\Post(
|
||||
* path="/api/v1/pricing/bulk",
|
||||
* path="/api/v1/pricing",
|
||||
* tags={"Pricing"},
|
||||
* summary="여러 항목 일괄 가격 조회",
|
||||
* description="여러 제품/자재의 가격을 한 번에 조회",
|
||||
* summary="단가 등록",
|
||||
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
|
||||
*
|
||||
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/BulkPriceQueryRequest")),
|
||||
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/PriceStoreRequest")),
|
||||
*
|
||||
* @OA\Response(response=200, description="조회 성공",
|
||||
* @OA\Response(response=200, description="등록 성공",
|
||||
*
|
||||
* @OA\JsonContent(allOf={
|
||||
*
|
||||
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
|
||||
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/BulkPriceQueryResult"))
|
||||
* })
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function bulk() {}
|
||||
|
||||
/**
|
||||
* @OA\Post(
|
||||
* path="/api/v1/pricing/upsert",
|
||||
* tags={"Pricing"},
|
||||
* summary="가격 등록/수정",
|
||||
* description="가격 이력 등록 (동일 조건 존재 시 업데이트)",
|
||||
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
|
||||
*
|
||||
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/PriceUpsertRequest")),
|
||||
*
|
||||
* @OA\Response(response=200, description="저장 성공",
|
||||
*
|
||||
* @OA\JsonContent(allOf={
|
||||
*
|
||||
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
|
||||
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/PriceHistory"))
|
||||
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Price"))
|
||||
* })
|
||||
* ),
|
||||
*
|
||||
* @OA\Response(response=400, description="검증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
|
||||
* )
|
||||
*/
|
||||
public function upsert() {}
|
||||
public function store() {}
|
||||
|
||||
/**
|
||||
* @OA\Put(
|
||||
* path="/api/v1/pricing/{id}",
|
||||
* tags={"Pricing"},
|
||||
* summary="단가 수정",
|
||||
* description="확정(finalized) 상태의 단가는 수정 불가",
|
||||
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
|
||||
*
|
||||
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
|
||||
*
|
||||
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/PriceUpdateRequest")),
|
||||
*
|
||||
* @OA\Response(response=200, description="수정 성공",
|
||||
*
|
||||
* @OA\JsonContent(allOf={
|
||||
*
|
||||
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
|
||||
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Price"))
|
||||
* })
|
||||
* ),
|
||||
*
|
||||
* @OA\Response(response=400, description="수정 불가 (확정된 단가)", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
|
||||
* )
|
||||
*/
|
||||
public function update() {}
|
||||
|
||||
/**
|
||||
* @OA\Delete(
|
||||
* path="/api/v1/pricing/{id}",
|
||||
* tags={"Pricing"},
|
||||
* summary="가격 이력 삭제(soft)",
|
||||
* summary="단가 삭제 (soft)",
|
||||
* description="확정(finalized) 상태의 단가는 삭제 불가",
|
||||
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
|
||||
*
|
||||
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
|
||||
*
|
||||
* @OA\Response(response=200, description="삭제 성공", @OA\JsonContent(ref="#/components/schemas/ApiResponse"))
|
||||
* @OA\Response(response=200, description="삭제 성공", @OA\JsonContent(ref="#/components/schemas/ApiResponse")),
|
||||
* @OA\Response(response=400, description="삭제 불가", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
|
||||
* )
|
||||
*/
|
||||
public function destroy() {}
|
||||
|
||||
/**
|
||||
* @OA\Post(
|
||||
* path="/api/v1/pricing/{id}/finalize",
|
||||
* tags={"Pricing"},
|
||||
* summary="단가 확정",
|
||||
* description="단가를 확정 상태로 변경 (확정 후 수정/삭제 불가)",
|
||||
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
|
||||
*
|
||||
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
|
||||
*
|
||||
* @OA\Response(response=200, description="확정 성공",
|
||||
*
|
||||
* @OA\JsonContent(allOf={
|
||||
*
|
||||
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
|
||||
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Price"))
|
||||
* })
|
||||
* ),
|
||||
*
|
||||
* @OA\Response(response=400, description="확정 불가", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
|
||||
* )
|
||||
*/
|
||||
public function finalize() {}
|
||||
|
||||
/**
|
||||
* @OA\Post(
|
||||
* path="/api/v1/pricing/by-items",
|
||||
* tags={"Pricing"},
|
||||
* summary="품목별 단가 현황 조회",
|
||||
* description="여러 품목의 현재 유효한 단가를 한번에 조회",
|
||||
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
|
||||
*
|
||||
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/PriceByItemsRequest")),
|
||||
*
|
||||
* @OA\Response(response=200, description="조회 성공",
|
||||
*
|
||||
* @OA\JsonContent(allOf={
|
||||
*
|
||||
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
|
||||
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/PriceByItemsResult"))
|
||||
* })
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function byItems() {}
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/api/v1/pricing/{id}/revisions",
|
||||
* tags={"Pricing"},
|
||||
* summary="변경 이력 조회",
|
||||
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
|
||||
*
|
||||
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
|
||||
* @OA\Parameter(name="size", in="query", @OA\Schema(type="integer", example=20)),
|
||||
*
|
||||
* @OA\Response(response=200, description="조회 성공",
|
||||
*
|
||||
* @OA\JsonContent(allOf={
|
||||
*
|
||||
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
|
||||
* @OA\Schema(@OA\Property(property="data", type="object",
|
||||
*
|
||||
* @OA\Property(property="current_page", type="integer"),
|
||||
* @OA\Property(property="data", type="array", @OA\Items(ref="#/components/schemas/PriceRevision")),
|
||||
* @OA\Property(property="total", type="integer")
|
||||
* ))
|
||||
* })
|
||||
* ),
|
||||
*
|
||||
* @OA\Response(response=404, description="단가 미존재", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
|
||||
* )
|
||||
*/
|
||||
public function revisions() {}
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/api/v1/pricing/cost",
|
||||
* tags={"Pricing"},
|
||||
* summary="원가 조회",
|
||||
* description="품목의 원가를 조회. 자재는 수입검사 입고단가 우선, 없으면 표준원가 사용",
|
||||
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
|
||||
*
|
||||
* @OA\Parameter(name="item_type_code", in="query", required=true, @OA\Schema(type="string", enum={"PRODUCT","MATERIAL"})),
|
||||
* @OA\Parameter(name="item_id", in="query", required=true, @OA\Schema(type="integer")),
|
||||
* @OA\Parameter(name="date", in="query", description="기준일 (미지정시 오늘)", @OA\Schema(type="string", format="date")),
|
||||
*
|
||||
* @OA\Response(response=200, description="조회 성공",
|
||||
*
|
||||
* @OA\JsonContent(allOf={
|
||||
*
|
||||
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
|
||||
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/PriceCostResult"))
|
||||
* })
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function cost() {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user