군 피복 구매관리 시스템 REST API 명세
- Base URL:
http://localhost:8000/api - 인증: Bearer Token (JWT)
- Content-Type:
application/json
Authorization: Bearer <access_token>
{
"id": 1,
"name": "데이터",
...
}{
"total": 100,
"page": 1,
"page_size": 20,
"items": [...]
}{
"detail": "에러 메시지"
}POST /api/auth/login
Request Body:
{
"username": "admin",
"password": "admin123"
}Response:
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "bearer"
}GET /api/auth/me
Response:
{
"user_id": 1,
"username": "admin",
"name": "관리자",
"role": "admin",
"service_number": "20-123456",
"rank": {
"id": 2,
"name": "대령"
},
"unit": "군수사령부",
"current_point": 800000,
"reserved_point": 0,
"sales_office_id": null,
"tailor_company_id": null
}권한: admin
GET /api/users
Query Parameters:
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
| page | int | No | 페이지 번호 (기본: 1) |
| page_size | int | No | 페이지 크기 (기본: 20) |
| role | string | No | 권한 필터 |
| rank_id | int | No | 계급 필터 |
| is_active | bool | No | 활성 상태 필터 |
| keyword | string | No | 검색어 (이름, 아이디, 군번) |
Response:
{
"total": 50,
"page": 1,
"page_size": 20,
"total_pages": 3,
"items": [
{
"id": 1,
"username": "user01",
"name": "홍길동",
"email": "user01@example.com",
"role": "general",
"rank": {"id": 4, "name": "대위"},
"service_number": "21-100001",
"unit": "제1보병사단",
"service_years": 3,
"current_point": 600000,
"reserved_point": 0,
"is_active": true
}
]
}GET /api/users/{user_id}
POST /api/users
Request Body:
{
"username": "user11",
"password": "user123",
"name": "새사용자",
"email": "user11@example.com",
"role": "general",
"rank_id": 4,
"service_number": "21-100011",
"unit": "제1보병사단",
"enlistment_date": "2021-03-01"
}PUT /api/users/{user_id}
DELETE /api/users/{user_id}
GET /api/users/by-service-number/{service_number}
Response:
{
"id": 1,
"username": "user01",
"name": "홍길동",
"service_number": "21-100001",
"unit": "제1보병사단",
"rank": {"id": 4, "name": "대위"},
"current_point": 600000
}POST /api/users/bulk-import
Request Body:
{
"users": [
{"username": "user11", "password": "user123", ...},
{"username": "user12", "password": "user123", ...}
]
}Response:
{
"created": 2,
"total": 2,
"errors": []
}POST /api/users/{user_id}/promote
Request Body:
{
"new_rank_id": 3,
"promotion_date": "2024-04-01"
}GET /api/users/ranks
GET /api/categories
GET /api/categories/tree
Response:
[
{
"id": 1,
"name": "상의",
"children": [
{
"id": 11,
"name": "전투복",
"children": [
{"id": 111, "name": "전투복 상의"}
]
}
]
}
]GET /api/clothings
Query Parameters:
| 파라미터 | 타입 | 설명 |
|---|---|---|
| category_id | int | 카테고리 필터 |
| clothing_type | string | ready_made / custom |
| keyword | string | 검색어 |
| is_active | bool | 활성 상태 |
GET /api/clothings/{id}
GET /api/clothings/{id}/specs
Response:
[
{
"id": 1,
"spec_code": "TV-90",
"size": "90",
"points": 50000,
"is_active": true
}
]GET /api/inventory
Query Parameters:
| 파라미터 | 타입 | 설명 |
|---|---|---|
| sales_office_id | int | 판매소 ID |
| keyword | string | 검색어 |
Response:
{
"items": [
{
"id": 1,
"sales_office_id": 1,
"item_id": 1,
"item_name": "전투복 상의",
"item_code": "TV-001",
"spec_id": 1,
"spec_size": "90",
"quantity": 100,
"reserved_quantity": 10,
"available_quantity": 90
}
]
}GET /api/inventory/available
Query Parameters:
| 파라미터 | 타입 | 설명 |
|---|---|---|
| sales_office_id | int | 판매소 ID (필수) |
| clothing_type | string | ready_made / custom |
Response:
{
"items": [
{
"item_id": 1,
"item_name": "전투복 상의",
"item_code": "TV-001",
"spec_id": 1,
"spec_size": "90",
"points": 50000,
"available_quantity": 90,
"clothing_type": "ready_made"
}
]
}POST /api/inventory/adjust
Request Body:
{
"sales_office_id": 1,
"item_id": 1,
"spec_id": 1,
"adjustment_type": "increase",
"quantity": 50,
"reason": "입고"
}GET /api/inventory/history
권한: general
GET /api/orders
Response:
{
"total": 10,
"items": [
{
"id": 1,
"order_number": "ORD-20240101-0001",
"status": "delivered",
"order_type": "online",
"total_amount": 100000,
"used_point": 100000,
"ordered_at": "2024-01-01T10:00:00",
"item_count": 2,
"items": [
{
"id": 1,
"item_name": "전투복 상의",
"spec_size": "90",
"quantity": 2,
"unit_price": 50000,
"total_price": 100000
}
],
"delivery": {
"delivery_type": "parcel",
"status": "delivered",
"tracking_number": "1234567890"
}
}
]
}GET /api/orders/{id}
POST /api/orders
Request Body:
{
"sales_office_id": 1,
"items": [
{
"item_id": 1,
"spec_id": 1,
"quantity": 2
}
],
"delivery_type": "parcel",
"recipient_name": "홍길동",
"recipient_phone": "010-1234-5678",
"shipping_address": "서울시 강남구..."
}Response:
{
"id": 1,
"order_number": "ORD-20240101-0001",
"status": "pending",
"total_amount": 100000,
"reserved_point": 100000
}POST /api/orders/{id}/cancel
권한: sales_office, admin
GET /api/sales/orders
Query Parameters:
| 파라미터 | 타입 | 설명 |
|---|---|---|
| status | string | 주문 상태 필터 |
| order_type | string | online / offline |
| keyword | string | 주문번호 검색 |
Response:
{
"total": 50,
"items": [
{
"id": 1,
"order_number": "ORD-20240101-0001",
"user": {
"id": 10,
"name": "홍길동",
"service_number": "21-100001",
"rank": "대위",
"unit": "제1보병사단"
},
"status": "pending",
"order_type": "online",
"total_amount": 100000,
"reserved_point": 100000,
"item_count": 2,
"items": [...],
"delivery": {...}
}
]
}PUT /api/sales/orders/{id}/status
Request Body:
{
"status": "shipped",
"tracking_number": "1234567890"
}POST /api/sales/offline
Request Body:
{
"user_id": 10,
"sales_office_id": 1,
"items": [
{
"item_id": 1,
"spec_id": 1,
"quantity": 2,
"unit_price": 50000
}
]
}POST /api/sales/refund
Request Body:
{
"order_id": 1,
"items": [
{
"order_item_id": 1,
"quantity": 1,
"reason": "사이즈 불만"
}
]
}POST /api/points/grant-single
Request Body:
{
"user_id": 10,
"year": 2024,
"base_amount": 600000,
"service_year_bonus": 15000,
"grant_date": "2024-01-01"
}POST /api/points/grant-bulk
Request Body:
{
"year": 2024,
"grant_date": "2024-01-01"
}GET /api/points/grant-history
GET /api/tailor-vouchers
Query Parameters:
| 파라미터 | 타입 | 설명 |
|---|---|---|
| user_id | int | 사용자 ID (미지정 시 본인) |
| status | string | issued / registered / used / cancelled |
| keyword | string | 검색어 |
Response:
{
"total": 10,
"items": [
{
"id": 1,
"voucher_number": "TV-20240101-ABCD1234",
"user": {
"id": 10,
"name": "홍길동",
"service_number": "21-100001",
"unit": "제1보병사단",
"rank": {"name": "대위"}
},
"item": {"id": 5, "name": "맞춤 정장"},
"amount": 100000,
"status": "issued",
"issued_at": "2024-01-01T10:00:00"
}
]
}맞춤피복 구매 시 주문 없이 체척권만 발행
POST /api/tailor-vouchers/issue-direct
Request Body:
{
"user_id": 10,
"item_id": 8,
"amount": 1,
"sales_office_id": 1,
"notes": "맞춤피복 체척권 발행"
}Response:
{
"id": 1,
"voucher_number": "TV-20250219-ABCD1234",
"user_id": 10,
"item_id": 8,
"amount": 1,
"status": "issued",
"issued_at": "2025-02-19T10:00:00",
"notes": "맞춤피복 체척권 발행"
}POST /api/tailor-vouchers/register
Request Body:
{
"voucher_id": 1,
"tailor_company_id": 1
}POST /api/tailor-vouchers/{id}/cancel-request
Request Body:
{
"reason": "취소 사유"
}GET /api/tailor-vouchers/companies
재고 관리 없이 활성화된 맞춤피복 목록만 조회
GET /api/clothings/custom/available
Response:
{
"items": [
{
"item_id": 8,
"spec_id": 43,
"item_name": "정복상의맞춤",
"category_id": 14,
"category_name": "정복상의맞춤",
"clothing_type": "custom",
"description": "정복상의맞춤 - 맞춤 제작",
"image_url": null,
"thumbnail_url": null,
"spec_size": "맞춤",
"spec_price": 149000
}
],
"total": 4
}GET /api/delivery-locations
POST /api/delivery-locations
PUT /api/delivery-locations/{id}
DELETE /api/delivery-locations/{id}
GET /api/sales-offices
Response:
[
{
"id": 1,
"name": "제1판매소",
"code": "S001",
"address": "서울시 용산구...",
"phone": "02-1234-5678"
}
]| 코드 | 설명 |
|---|---|
| 200 | 성공 |
| 201 | 생성 성공 |
| 204 | 삭제 성공 (내용 없음) |
| 400 | 잘못된 요청 |
| 401 | 인증 실패 |
| 403 | 권한 없음 |
| 404 | 리소스 없음 |
| 422 | 유효성 검사 실패 |
| 500 | 서버 오류 |