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:
2025-12-08 19:03:50 +09:00
parent 56c707f033
commit 8d3ea4bb39
18 changed files with 1933 additions and 251 deletions

View File

@@ -0,0 +1,277 @@
{
"name": "단가 관리 CRUD 테스트",
"description": "단가(Pricing) API의 생성, 조회, 수정, 확정, 삭제 전체 플로우 테스트",
"version": "1.0",
"config": {
"baseUrl": "",
"timeout": 30000,
"stopOnFailure": true
},
"variables": {
"user_id": "{{$env.FLOW_TESTER_USER_ID}}",
"user_pwd": "{{$env.FLOW_TESTER_USER_PWD}}"
},
"steps": [
{
"id": "login",
"name": "로그인",
"method": "POST",
"endpoint": "/login",
"body": {
"user_id": "{{user_id}}",
"user_pwd": "{{user_pwd}}"
},
"expect": {
"status": [200],
"jsonPath": {
"$.message": "로그인 성공",
"$.access_token": "@isString"
}
},
"extract": {
"token": "$.access_token"
}
},
{
"id": "list_prices",
"name": "단가 목록 조회",
"method": "GET",
"endpoint": "/pricing",
"headers": {
"Authorization": "Bearer {{login.token}}"
},
"query": {
"per_page": 10,
"page": 1
},
"expect": {
"status": [200],
"jsonPath": {
"$.success": true,
"$.data.data": "@isArray"
}
}
},
{
"id": "create_price",
"name": "단가 생성 (MATERIAL)",
"method": "POST",
"endpoint": "/pricing",
"headers": {
"Authorization": "Bearer {{login.token}}"
},
"body": {
"item_type_code": "MATERIAL",
"item_id": 1,
"client_group_id": null,
"purchase_price": 10000,
"processing_cost": 500,
"loss_rate": 5,
"margin_rate": 20,
"sales_price": 12600,
"rounding_rule": "round",
"rounding_unit": 100,
"supplier": "테스트 공급업체",
"effective_from": "2025-01-01",
"effective_to": "2025-12-31",
"note": "API Flow 테스트용 단가",
"status": "draft"
},
"expect": {
"status": [201],
"jsonPath": {
"$.success": true,
"$.data.id": "@isNumber",
"$.data.item_type_code": "MATERIAL",
"$.data.purchase_price": 10000,
"$.data.status": "draft"
}
},
"extract": {
"price_id": "$.data.id"
}
},
{
"id": "show_price",
"name": "생성된 단가 상세 조회",
"method": "GET",
"endpoint": "/pricing/{{create_price.price_id}}",
"headers": {
"Authorization": "Bearer {{login.token}}"
},
"expect": {
"status": [200],
"jsonPath": {
"$.success": true,
"$.data.id": "{{create_price.price_id}}",
"$.data.item_type_code": "MATERIAL",
"$.data.supplier": "테스트 공급업체"
}
}
},
{
"id": "update_price",
"name": "단가 수정 (가격 변경)",
"method": "PUT",
"endpoint": "/pricing/{{create_price.price_id}}",
"headers": {
"Authorization": "Bearer {{login.token}}"
},
"body": {
"purchase_price": 11000,
"processing_cost": 600,
"margin_rate": 25,
"sales_price": 14500,
"note": "단가 수정 테스트",
"change_reason": "원가 인상으로 인한 가격 조정",
"status": "active"
},
"expect": {
"status": [200],
"jsonPath": {
"$.success": true,
"$.data.purchase_price": 11000,
"$.data.processing_cost": 600,
"$.data.status": "active"
}
}
},
{
"id": "get_revisions",
"name": "변경 이력 조회",
"method": "GET",
"endpoint": "/pricing/{{create_price.price_id}}/revisions",
"headers": {
"Authorization": "Bearer {{login.token}}"
},
"expect": {
"status": [200],
"jsonPath": {
"$.success": true,
"$.data": "@isArray"
}
}
},
{
"id": "get_cost",
"name": "원가 조회 (receipt > standard 폴백)",
"method": "GET",
"endpoint": "/pricing/cost",
"headers": {
"Authorization": "Bearer {{login.token}}"
},
"query": {
"item_type_code": "MATERIAL",
"item_id": 1,
"date": "2025-06-15"
},
"expect": {
"status": [200],
"jsonPath": {
"$.success": true,
"$.data.item_type_code": "MATERIAL",
"$.data.item_id": 1
}
}
},
{
"id": "by_items",
"name": "다중 품목 단가 조회",
"method": "POST",
"endpoint": "/pricing/by-items",
"headers": {
"Authorization": "Bearer {{login.token}}"
},
"body": {
"items": [
{
"item_type_code": "MATERIAL",
"item_id": 1
}
],
"date": "2025-06-15"
},
"expect": {
"status": [200],
"jsonPath": {
"$.success": true,
"$.data": "@isArray"
}
}
},
{
"id": "create_price_for_finalize",
"name": "확정 테스트용 단가 생성",
"method": "POST",
"endpoint": "/pricing",
"headers": {
"Authorization": "Bearer {{login.token}}"
},
"body": {
"item_type_code": "PRODUCT",
"item_id": 1,
"purchase_price": 50000,
"sales_price": 70000,
"effective_from": "2025-01-01",
"status": "active"
},
"expect": {
"status": [201],
"jsonPath": {
"$.success": true,
"$.data.id": "@isNumber"
}
},
"extract": {
"finalize_price_id": "$.data.id"
}
},
{
"id": "finalize_price",
"name": "가격 확정 (불변 처리)",
"method": "POST",
"endpoint": "/pricing/{{create_price_for_finalize.finalize_price_id}}/finalize",
"headers": {
"Authorization": "Bearer {{login.token}}"
},
"expect": {
"status": [200],
"jsonPath": {
"$.success": true,
"$.data.status": "finalized",
"$.data.is_final": true
}
}
},
{
"id": "delete_price",
"name": "단가 삭제 (soft delete)",
"method": "DELETE",
"endpoint": "/pricing/{{create_price.price_id}}",
"headers": {
"Authorization": "Bearer {{login.token}}"
},
"expect": {
"status": [200],
"jsonPath": {
"$.success": true
}
}
},
{
"id": "verify_deleted",
"name": "삭제된 단가 조회 시 404 확인",
"method": "GET",
"endpoint": "/pricing/{{create_price.price_id}}",
"headers": {
"Authorization": "Bearer {{login.token}}"
},
"expect": {
"status": [404],
"jsonPath": {
"$.success": false
}
}
}
]
}