์กฐ๋ฌ ์์คํ ๋ฐฑ์๋ API ์๋ฒ์ ๋๋ค. ๊ณต๊ธ์ฌ(Vendor) ๊ด๋ฆฌ์ ๋ฐ์ฃผ์(PO) ๋๋ฉ์ธ์ ์ ๊ณตํฉ๋๋ค.
| ๋ถ๋ฅ | ๊ธฐ์ |
|---|---|
| Language / Framework | Java 25 / Spring Boot 4 |
| ORM | Spring Data JPA + PostgreSQL |
| API ๋ฌธ์ | Springdoc OpenAPI (Swagger UI) |
| ์ ๋ ฅ ๊ฒ์ฆ | Bean Validation (@Valid, @Validated) |
| ์๋ฌ ์๋ต | ProblemDetail ๊ธฐ๋ฐ (RFC 9457) |
| # | Method | Endpoint | ๊ธฐ๋ฅ | ์๋ต ์ฝ๋ |
|---|---|---|---|---|
| 1 | GET |
/api/vendors/stats |
๊ณต๊ธ์ฌ ์ ์ฒด ํต๊ณ ์กฐํ | 200 |
| 2 | GET |
/api/vendors/{vendorCode}/stats |
๊ณต๊ธ์ฌ ์์ธ ํต๊ณ ์กฐํ | 200, 404 |
| 3 | GET |
/api/vendors |
๊ณต๊ธ์ฌ ๋ชฉ๋ก ์กฐํ (๊ฒ์ยทํํฐยท์ ๋ ฌยทํ์ด์ง) | 200, 400 |
| 4 | POST |
/api/vendors |
๊ณต๊ธ์ฌ ๋ฑ๋ก | 201, 400 |
| 5 | GET |
/api/vendors/{vendorCode} |
๊ณต๊ธ์ฌ ์์ธ ์กฐํ | 200, 404 |
| 6 | PUT |
/api/vendors/{vendorCode} |
๊ณต๊ธ์ฌ ์ ๋ณด ์์ | 204, 400, 404, 422 |
| 7 | PATCH |
/api/vendors/{vendorCode}/active |
๊ณต๊ธ์ฌ ํ์ฑ ์ฌ๋ถ ๋ณ๊ฒฝ | 204, 400, 404, 422 |
| # | Method | Endpoint | ๊ธฐ๋ฅ | ์๋ต ์ฝ๋ |
|---|---|---|---|---|
| 1 | POST |
/api/purchase-orders |
๋ฐ์ฃผ ๋ฑ๋ก (DRAFT ๋๋ CONFIRMED) | 201, 400, 401, 403, 404, 422 |
| 2 | PUT |
/api/purchase-orders/{poNumber} |
๋ฐ์ฃผ ์์ (DRAFT ์ ์ฉ) | 204, 400, 401, 403, 404, 422 |
| 3 | DELETE |
/api/purchase-orders/{poNumber} |
๋ฐ์ฃผ ์ญ์ (DRAFT ์ ์ฉ, ๋ฌผ๋ฆฌ ์ญ์ ) | 204, 400, 401, 403, 404, 422 |
๋ชจ๋ ์๋ฌ๋ ProblemDetail ํ์์ผ๋ก ๋ฐํ๋ฉ๋๋ค. code ์ timestamp ํ๋๊ฐ ํญ์ ํฌํจ๋ฉ๋๋ค.
{
"status": 404,
"detail": "๊ณต๊ธ์ฌ๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค: VD-999",
"code": "VENDOR_NOT_FOUND",
"timestamp": "2026-06-05T10:30:00+09:00"
}| code | HTTP | ๋ฐ์ ์กฐ๊ฑด |
|---|---|---|
VENDOR_NOT_FOUND |
404 | ํด๋น ์ฝ๋์ ๊ณต๊ธ์ฌ๊ฐ ์กด์ฌํ์ง ์์ ๋ |
VENDOR_INACTIVE |
422 | ๋นํ์ฑ ๊ณต๊ธ์ฌ๋ฅผ ์์ ํ๋ ค ํ ๋ |
VENDOR_HAS_ACTIVE_PO |
422 | ์งํ ์ค PO(DRAFT/CONFIRMED)๊ฐ ์๋ ๊ณต๊ธ์ฌ๋ฅผ ๋นํ์ฑํํ๋ ค ํ ๋ |
VENDOR_DUPLICATE |
409 | ๊ณต๊ธ์ฌ ์ฝ๋ UNIQUE ์ ์ฝ ์๋ฐ |
PO_NOT_FOUND |
404 | ํด๋น ๋ฒํธ์ ๋ฐ์ฃผ์๊ฐ ์กด์ฌํ์ง ์์ ๋ |
PO_INVALID_STATUS |
422 | ํ์ฉ๋์ง ์๋ PO ์ํ์์ ์์ ยท์ญ์ ๋ฅผ ์๋ํ ๋ (DRAFT ์๋) |
PO_VENDOR_INACTIVE |
422 | ๋นํ์ฑ ๊ณต๊ธ์ฌ์ ๋ฐ์ฃผํ๋ ค ํ ๋ |
PO_ITEM_NOT_FOUND |
422 | ์ฃผ๋ฌธ ๋ผ์ธ์ SKU์ ํด๋นํ๋ ๋ถํ์ด ์กด์ฌํ์ง ์์ ๋ |
PO_ITEM_INACTIVE |
422 | ๋นํ์ฑ ๋ถํ์ผ๋ก ๋ฐ์ฃผํ๋ ค ํ ๋ |
PO_WAREHOUSE_INVALID |
422 | ๋ฉํ ์ฐฝ๊ณ ์ฝ๋๊ฐ ์กด์ฌํ์ง ์์ ๋ |
PO_DUPLICATE_SKU |
422 | ํ ๋ฐ์ฃผ์ ์ฃผ๋ฌธ ๋ผ์ธ์ ๋์ผ SKU๊ฐ ์ค๋ณต๋ ๋ |
PO_DUPLICATE |
409 | ๋ฐ์ฃผ ๋ฒํธ UNIQUE ์ ์ฝ ์๋ฐ |
COMMON_INVALID_INPUT |
400 | ํ๋ยทํ๋ผ๋ฏธํฐ ๊ฒ์ฆ ์คํจ (@Valid ๋ฐ๋ / @Validated PathยทQuery) |
COMMON_BAD_REQUEST |
400 | ๊ทธ ์ธ ์๋ชป๋ ์์ฒญ (405ยท415ยท๊นจ์ง JSON ๋ฑ ๋ฏธ๋ถ๋ฅ) |
COMMON_INTERNAL_ERROR |
500 | ์ฒ๋ฆฌ๋์ง ์์ ์๋ฒ ๋ด๋ถ ์ค๋ฅ |
๊ณต๊ธ์ฌ ๋์๋ณด๋ ์๋จ ์นด๋ ์์ญ์ ํ์ํ ์ง๊ณ ์์น๋ฅผ ๋ฐํํฉ๋๋ค.
- ์ ์ฒด / ํ์ฑ / ๋นํ์ฑ ๊ณต๊ธ์ฌ ์
- ์งํ ์ค PO(DRAFT + CONFIRMED) ๊ฑด์ ๋ฐ ์ด ๊ธ์ก
Request โ ํ๋ผ๋ฏธํฐ ์์
Response 200
{
"totalCount": 20,
"activeCount": 18,
"inactiveCount": 2,
"activePoCount": 5,
"activePoAmount": 150000000
}| ํ๋ | ํ์ | ์ค๋ช |
|---|---|---|
totalCount |
long | ์ ์ฒด ๊ณต๊ธ์ฌ ์ |
activeCount |
long | ํ์ฑ ๊ณต๊ธ์ฌ ์ |
inactiveCount |
long | ๋นํ์ฑ ๊ณต๊ธ์ฌ ์ (total - active) |
activePoCount |
long | ์งํ ์ค PO ๊ฑด์ (DRAFT + CONFIRMED) |
activePoAmount |
long | ์งํ ์ค PO ์ด ๊ธ์ก (์ ๋จ์) |
ํน์ ๊ณต๊ธ์ฌ์ ๊ฑฐ๋ ํํฉ์ ์์ฝํ ํต๊ณ๋ฅผ ๋ฐํํฉ๋๋ค. ๊ณต๊ธ์ฌ ์์ธ ํ์ด์ง์ ํต๊ณ ์นด๋ ์์ญ์์ ์ฌ์ฉํฉ๋๋ค.
Path Parameter
| ํ๋ผ๋ฏธํฐ | ํ์ | ์์ | ์ค๋ช |
|---|---|---|---|
vendorCode |
String | VD-014 |
๊ณต๊ธ์ฌ ์ฝ๋ (ํ์, ๊ณต๋ฐฑ ๋ถ๊ฐ) |
Response 200
{
"activePo": 3,
"tradeAmount30d": 92400000,
"avgLeadTimeDays": 5.2
}| ํ๋ | ํ์ | ์ค๋ช |
|---|---|---|
activePo |
long | ํด๋น ๊ณต๊ธ์ฌ์ ์งํ ์ค PO ์ (DRAFT + CONFIRMED) |
tradeAmount30d |
long | ์ต๊ทผ 30์ผ ๊ฑฐ๋์ก. CONFIRMED + RECEIVED ์ํ PO๋ง ์ง๊ณ (DRAFT, CANCELED ์ ์ธ) |
avgLeadTimeDays |
Double (nullable) | ํ๊ท ๋ฆฌ๋ํ์(์ผ). RECEIVED ์ํ PO์ orderedAt โ receivedAt ๊ธฐ์ค. RECEIVED PO๊ฐ ์์ผ๋ฉด null ๋ฐํ |
Error
| ์ํ | code | ์ค๋ช |
|---|---|---|
| 404 | VENDOR_NOT_FOUND |
ํด๋น ์ฝ๋์ ๊ณต๊ธ์ฌ๊ฐ ์กด์ฌํ์ง ์์ |
๋ฑ๋ก๋ ๊ณต๊ธ์ฌ๋ฅผ ๊ฒ์ยทํํฐยท์ ๋ ฌ๊ณผ ํจ๊ป offset ํ์ด์ง ๋จ์๋ก ์กฐํํฉ๋๋ค.
Query Parameters
| ํ๋ผ๋ฏธํฐ | ํ์ | ๊ธฐ๋ณธ๊ฐ | ์ค๋ช |
|---|---|---|---|
page |
int | 0 |
ํ์ด์ง ๋ฒํธ (0-based, 0 ์ด์) |
size |
int | 10 |
ํ์ด์ง๋น ํญ๋ชฉ ์ (1~100) |
search |
String | โ | ๊ณต๊ธ์ฌ๋ช ยท์ฝ๋ ๋ถ๋ถ ๊ฒ์ (๋ฏธ์ ๋ ฅ ์ ์ ์ฒด) |
active |
Boolean | โ | ํ์ฑ ์ฌ๋ถ ํํฐ (๋ฏธ์ ๋ ฅ ์ ์ ์ฒด) |
sort |
String | recentTrade |
์ ๋ ฌ ๊ธฐ์ค. recentTrade(์ต๊ทผ ๊ฑฐ๋์) ๋๋ code(์ฝ๋ ์ค๋ฆ์ฐจ์) |
recentTrade๋ ๊ฐ ๊ณต๊ธ์ฌ์ ๊ฐ์ฅ ์ต๊ทผ ๋ฐ์ฃผ(orderedAt) ๊ธฐ์ค ๋ด๋ฆผ์ฐจ์์ด๋ฉฐ, ๊ฑฐ๋ ์ด๋ ฅ์ด ์๋ ๊ณต๊ธ์ฌ๋ ๋ค๋ก ์ ๋ ฌ๋ฉ๋๋ค(NULLS LAST).
Response 200
{
"content": [
{
"id": 1,
"code": "VD-001",
"name": "(์ฃผ)๋์ฑ์ ๋ฐ",
"contactPerson": "๊น์ํธ",
"phone": "02-1234-5678",
"address": "๊ฒฝ๊ธฐ ์์ฐ์ ๋จ์๊ตฌ ๋ณ๋ง๋ก 178",
"active": true,
"createdAt": "2026-05-01T09:00:00+09:00"
}
],
"page": 0,
"size": 10,
"totalElements": 20,
"totalPages": 2
}Error
| ์ํ | code | ์ค๋ช |
|---|---|---|
| 400 | COMMON_INVALID_INPUT |
size ๋ฒ์(1~100) ์ด๊ณผ, sort ๋ฏธ์ ์ ๊ฐ, page ์์ |
์๋ก์ด ๊ณต๊ธ์ฌ๋ฅผ ๋ฑ๋กํฉ๋๋ค.
๊ณต๊ธ์ฌ ์ฝ๋(code)๋ ์๋ฒ์์ ์๋ ์ฑ๋ฒ๋๋ฉฐ (VD-001, VD-002, โฆ ํ์), ํด๋ผ์ด์ธํธ๊ฐ ์ง์ ํ ์ ์์ต๋๋ค.
์ ๊ท ๋ฑ๋ก๋ ๊ณต๊ธ์ฌ์ active ๊ธฐ๋ณธ๊ฐ์ true์
๋๋ค.
Request Body
{
"name": "(์ฃผ)๋์ฑ์ ๋ฐ",
"contactPerson": "๊น์ํธ",
"phone": "02-1234-5678",
"address": "๊ฒฝ๊ธฐ ์์ฐ์ ๋จ์๊ตฌ ๋ณ๋ง๋ก 178"
}| ํ๋ | ํ์ | ํ์ | ๊ฒ์ฆ ๊ท์น |
|---|---|---|---|
name |
String | โ | ๊ณต๋ฐฑ ๋ถ๊ฐ |
contactPerson |
String | โ | ๊ณต๋ฐฑ ๋ถ๊ฐ |
phone |
String | โ | 0XX-XXXX-XXXX ๋๋ 0X-XXX-XXXX ํ์ |
address |
String | โ | ๊ณต๋ฐฑ ๋ถ๊ฐ |
Response 201 โ ์์ฑ๋ ๊ณต๊ธ์ฌ ์ ๋ณด (VendorResponse)
Error
| ์ํ | code | ์ค๋ช |
|---|---|---|
| 400 | COMMON_INVALID_INPUT |
ํ๋ ๊ฒ์ฆ ์คํจ (์์ธ ๋ฉ์์ง ํฌํจ) |
๊ณต๊ธ์ฌ ๊ธฐ๋ณธ ์ ๋ณด์ ํจ๊ป ํด๋น ๊ณต๊ธ์ฌ์ ์ต๊ทผ PO ์ต๋ 6๊ฑด์ ๋ฐํํฉ๋๋ค.
PO ๋ชฉ๋ก์ createdAt ๊ธฐ์ค ๋ด๋ฆผ์ฐจ์ ์ ๋ ฌ์
๋๋ค.
Path Parameter
| ํ๋ผ๋ฏธํฐ | ํ์ | ์์ |
|---|---|---|
vendorCode |
String | VD-014 |
Response 200
{
"id": 1,
"code": "VD-001",
"name": "(์ฃผ)๋์ฑ์ ๋ฐ",
"contactPerson": "๊น์ํธ",
"phone": "02-1234-5678",
"address": "๊ฒฝ๊ธฐ ์์ฐ์ ๋จ์๊ตฌ ๋ณ๋ง๋ก 178",
"active": true,
"recentPos": [
{
"poNumber": "PO-2026-0421",
"status": "CONFIRMED",
"totalAmount": 5000000,
"orderedAt": "2026-05-20T14:32:00+09:00"
}
],
"createdAt": "2026-05-01T09:00:00+09:00",
"updatedAt": "2026-05-20T15:00:00+09:00"
}| ํ๋ | ์ค๋ช |
|---|---|
recentPos |
์ต๊ทผ PO ์ต๋ 6๊ฑด. poNumber, status, totalAmount, orderedAt ํฌํจ |
updatedAt |
๋ง์ง๋ง ์์ ์ผ์ (KST, ISO-8601) |
Error
| ์ํ | code | ์ค๋ช |
|---|---|---|
| 404 | VENDOR_NOT_FOUND |
ํด๋น ์ฝ๋์ ๊ณต๊ธ์ฌ๊ฐ ์กด์ฌํ์ง ์์ |
๊ณต๊ธ์ฌ์ ๊ธฐ๋ณธ ์ ๋ณด(์ด๋ฆ, ๋ํ์, ์ ํ๋ฒํธ, ์ฃผ์)๋ฅผ ์์ ํฉ๋๋ค.
- ๊ณต๊ธ์ฌ ์ฝ๋(
code)๋ ์์ ๋ถ๊ฐ์ ๋๋ค. ์ฝ๋๋ Path Variable๋ก๋ง ์ฌ์ฉ๋ฉ๋๋ค. - ๋นํ์ฑ(
active: false) ์ํ์ ๊ณต๊ธ์ฌ๋ ์์ ํ ์ ์์ต๋๋ค. ๋จผ์ ํ์ฑํ ํ ์์ ํด์ผ ํฉ๋๋ค. - ์ฑ๊ณต ์ ์๋ต ๋ณธ๋ฌธ ์์ด
204 No Content๋ฅผ ๋ฐํํฉ๋๋ค.
Path Parameter
| ํ๋ผ๋ฏธํฐ | ํ์ | ์์ |
|---|---|---|
code |
String | VD-003 |
Request Body โ POST /api/vendors์ Request Body์ ๋์ผํ ํ๋ ๋ฐ ๊ฒ์ฆ ๊ท์น ์ ์ฉ
Response 204 No Content
Error
| ์ํ | code | ์ค๋ช |
|---|---|---|
| 400 | COMMON_INVALID_INPUT |
ํ๋ ๊ฒ์ฆ ์คํจ |
| 404 | VENDOR_NOT_FOUND |
ํด๋น ์ฝ๋์ ๊ณต๊ธ์ฌ๊ฐ ์กด์ฌํ์ง ์์ |
| 422 | VENDOR_INACTIVE |
๋นํ์ฑ ๊ณต๊ธ์ฌ๋ ์์ ๋ถ๊ฐ |
๊ณต๊ธ์ฌ๋ฅผ ํ์ฑํํ๊ฑฐ๋ ๋นํ์ฑํํฉ๋๋ค.
- ๋นํ์ฑํ ์ ํด๋น ๊ณต๊ธ์ฌ์ ์งํ ์ค PO(DRAFT ๋๋ CONFIRMED ์ํ)๊ฐ 1๊ฑด์ด๋ผ๋ ์กด์ฌํ๋ฉด
422๋ฅผ ๋ฐํํฉ๋๋ค. ์ด๋ ์งํ ์ค์ธ ๋ฐ์ฃผ ์ฒ๋ฆฌ๋ฅผ ๋ณดํธํ๊ธฐ ์ํ ๋น์ฆ๋์ค ๊ท์น์ ๋๋ค. - ํ์ฑํ ์์๋ ๋ณ๋ ์ ์ฝ ์์ด ์ฆ์ ์ ์ฉ๋ฉ๋๋ค.
- ์ฑ๊ณต ์ ์๋ต ๋ณธ๋ฌธ ์์ด
204 No Content๋ฅผ ๋ฐํํฉ๋๋ค.
Path Parameter
| ํ๋ผ๋ฏธํฐ | ํ์ | ์์ |
|---|---|---|
vendorCode |
String | VD-014 |
Request Body
{ "active": false }| ํ๋ | ํ์ | ํ์ | ์ค๋ช |
|---|---|---|---|
active |
Boolean | โ | true (ํ์ฑํ) / false (๋นํ์ฑํ) |
Response 204 No Content
Error
| ์ํ | code | ์ค๋ช |
|---|---|---|
| 400 | COMMON_INVALID_INPUT |
active ํ๋ ๋๋ฝ |
| 404 | VENDOR_NOT_FOUND |
ํด๋น ์ฝ๋์ ๊ณต๊ธ์ฌ๊ฐ ์กด์ฌํ์ง ์์ |
| 422 | VENDOR_HAS_ACTIVE_PO |
์งํ ์ค PO๊ฐ ์กด์ฌํ์ฌ ๋นํ์ฑํ ๋ถ๊ฐ (์๋ฌ ๋ฉ์์ง์ ๊ฑด์ ํฌํจ) |
๋ชจ๋ PO API์ ๊ธฐ๋ณธ ๊ฒฝ๋ก๋
/api/purchase-orders์ ๋๋ค. ๋ฐ์ฃผ ์๊ฐ ํ๋๋ ์๊ฐ ์ปจ๋ฒค์ ์ ๋ฐ๋ผ offset์ด ๋ช ์๋OffsetDateTime(KST, ISO-8601)์ผ๋ก ์ฃผ๊ณ ๋ฐ์ต๋๋ค.
์ ๊ท ๋ฐ์ฃผ๋ฅผ ๋ฑ๋กํฉ๋๋ค.
confirm๊ฐ์ ๋ฐ๋ผ ์์ฑ ์ํ๊ฐ ๊ฒฐ์ ๋ฉ๋๋ค.false๋ฉด DRAFT,true๋ฉด CONFIRMED(์น์ธ์ยท๋ฐ์ฃผ์ผ์ ๊ธฐ๋ก)๋ก ์์ฑ๋ฉ๋๋ค.- ๋ฐ์ฃผ ๋ฒํธ(
poNumber)๋ ์๋ฒ์์ ์๋ ์ฑ๋ฒ๋ฉ๋๋ค. ํ์์PO-{๋ }-{4์๋ฆฌ ์ผ๋ จ๋ฒํธ}(์:PO-2026-0005)์ด๋ฉฐ, 9999 ์ด๊ณผ ์ ์๋ฆฟ์๊ฐ ์๋ ํ์ฅ๋ฉ๋๋ค. - ๋ฑ๋ก ๊ณผ์ ์์ ๊ณต๊ธ์ฌยท๋ฉํ ์ฐฝ๊ณ ยท๋ถํ(SKU)์ ์กด์ฌ ๋ฐ ํ์ฑ ์ฌ๋ถ๋ฅผ ๊ฒ์ฆํ๊ณ , ๋ถํ์ ์ด๋ฆยท๋จ๊ฐ๋ฅผ ์ค๋ ์ท์ผ๋ก ์ ์ฅํฉ๋๋ค.
Request Body
{
"vendorCode": "VD-001",
"targetWarehouseCode": "WH-01",
"expectedArrival": "2026-06-20T09:00:00+09:00",
"note": "๊ธด๊ธ ๋ฐ์ฃผ ๊ฑด",
"confirm": false,
"lines": [
{ "sku": "SKU-1001", "quantity": 10 },
{ "sku": "SKU-1002", "quantity": 5 }
]
}| ํ๋ | ํ์ | ํ์ | ๊ฒ์ฆ ๊ท์น |
|---|---|---|---|
vendorCode |
String | โ | ๊ณต๋ฐฑ ๋ถ๊ฐ |
targetWarehouseCode |
String | โ | ๊ณต๋ฐฑ ๋ถ๊ฐ |
expectedArrival |
OffsetDateTime | โ | ์ค๋ ์ดํ(ํ์ฌ ํฌํจ) |
note |
String | โ | 500์ ์ดํ |
confirm |
Boolean | โ | false=DRAFT / true=CONFIRMED |
lines |
Array | โ | ์ต์ 1๊ฑด, ์ต๋ 100๊ฑด |
lines[].sku |
String | โ | ๊ณต๋ฐฑ ๋ถ๊ฐ, ๋ผ์ธ ๊ฐ ์ค๋ณต ๋ถ๊ฐ |
lines[].quantity |
Integer | โ | 1 ์ด์ |
Response 201
{
"poNumber": "PO-2026-0005",
"status": "DRAFT",
"vendorCode": "VD-001",
"vendorName": "(์ฃผ)๋์ฑ์ ๋ฐ",
"targetWarehouseCode": "WH-01",
"expectedArrival": "2026-06-20T09:00:00+09:00",
"note": "๊ธด๊ธ ๋ฐ์ฃผ ๊ฑด",
"totalAmount": 1500000,
"lines": [
{
"lineNo": 1,
"sku": "SKU-1001",
"nameSnapshot": "๋ฒ ์ด๋ง 6202",
"unitPriceSnapshot": 100000,
"quantity": 10
}
],
"createdAt": "2026-06-09T10:30:00+09:00"
}| ํ๋ | ์ค๋ช |
|---|---|
status |
๋ฐ์ฃผ ์ํ (DRAFT / CONFIRMED) |
vendorName |
๋ฑ๋ก ์์ ์ ๊ณต๊ธ์ฌ๋ช |
totalAmount |
๋ผ์ธ๋ณ ๋จ๊ฐ ์ค๋
์ท ร ์๋์ ํฉ๊ณ (์ ๋จ์) |
lines[].nameSnapshot / unitPriceSnapshot |
๋ฑ๋ก ์์ ์ ๋ถํ ์ด๋ฆยท๋จ๊ฐ ์ค๋ ์ท |
Error
| ์ํ | code | ์ค๋ช |
|---|---|---|
| 400 | COMMON_INVALID_INPUT |
ํ๋ ๊ฒ์ฆ ์คํจ |
| 404 | VENDOR_NOT_FOUND |
๊ณต๊ธ์ฌ๊ฐ ์กด์ฌํ์ง ์์ |
| 422 | PO_VENDOR_INACTIVE |
๋นํ์ฑ ๊ณต๊ธ์ฌ์๋ ๋ฐ์ฃผ ๋ถ๊ฐ |
| 422 | PO_DUPLICATE_SKU |
์ฃผ๋ฌธ ๋ผ์ธ์ ๋์ผ SKU ์ค๋ณต |
| 422 | PO_WAREHOUSE_INVALID |
๋ฉํ ์ฐฝ๊ณ ๊ฐ ์กด์ฌํ์ง ์์ |
| 422 | PO_ITEM_NOT_FOUND |
๋ถํ(SKU)์ด ์กด์ฌํ์ง ์์ |
| 422 | PO_ITEM_INACTIVE |
๋นํ์ฑ ๋ถํ์ผ๋ก๋ ๋ฐ์ฃผ ๋ถ๊ฐ |
DRAFT ์ํ์ธ ๋ฐ์ฃผ์ ์ ๋ณด๋ฅผ ์์ ํฉ๋๋ค.
- DRAFT ์ํ์์๋ง ์์ ๊ฐ๋ฅํฉ๋๋ค. CONFIRMED ์ดํ ์ํ์์๋
422๋ฅผ ๋ฐํํฉ๋๋ค. (์ํ ๊ฒ์ฆ์ ์ ๋ ฅ ์์ ๊ฒ์ฆ๋ณด๋ค ๋จผ์ ์ํํฉ๋๋ค.) - ์ฃผ๋ฌธ ๋ผ์ธ์ ์ ์ฒด ๊ต์ฒด(replace)๋ฉ๋๋ค. ๊ธฐ์กด ๋ผ์ธ์ ๋ชจ๋ ์ ๊ฑฐํ ๋ค ์์ฒญ ๋ผ์ธ์ผ๋ก ๋ค์ ๊ตฌ์ฑํฉ๋๋ค.
- ๋ฑ๋ก๊ณผ ๋ฌ๋ฆฌ ์ํ ์ ์ด๋ฅผ ํ์ง ์์ผ๋ฏ๋ก
confirmํ๋๊ฐ ์์ต๋๋ค. - ์ฑ๊ณต ์ ์๋ต ๋ณธ๋ฌธ ์์ด
204 No Content๋ฅผ ๋ฐํํฉ๋๋ค.
Path Parameter
| ํ๋ผ๋ฏธํฐ | ํ์ | ์์ | ์ค๋ช |
|---|---|---|---|
poNumber |
String | PO-2026-0005 |
๋ฐ์ฃผ ๋ฒํธ (ํ์, ๊ณต๋ฐฑ ๋ถ๊ฐ) |
Request Body โ POST /api/purchase-orders์ Request Body์์ confirm ํ๋๋ฅผ ์ ์ธํ ๋์ผํ ํ๋ ๋ฐ ๊ฒ์ฆ ๊ท์น ์ ์ฉ
Response 204 No Content
Error
| ์ํ | code | ์ค๋ช |
|---|---|---|
| 400 | COMMON_INVALID_INPUT |
ํ๋ ๊ฒ์ฆ ์คํจ |
| 404 | PO_NOT_FOUND |
๋ฐ์ฃผ๊ฐ ์กด์ฌํ์ง ์์ |
| 404 | VENDOR_NOT_FOUND |
๊ณต๊ธ์ฌ๊ฐ ์กด์ฌํ์ง ์์ |
| 422 | PO_INVALID_STATUS |
DRAFT ์ํ๊ฐ ์๋์ด์ ์์ ๋ถ๊ฐ |
| 422 | PO_VENDOR_INACTIVE |
๋นํ์ฑ ๊ณต๊ธ์ฌ |
| 422 | PO_DUPLICATE_SKU |
์ฃผ๋ฌธ ๋ผ์ธ์ ๋์ผ SKU ์ค๋ณต |
| 422 | PO_WAREHOUSE_INVALID |
๋ฉํ ์ฐฝ๊ณ ๊ฐ ์กด์ฌํ์ง ์์ |
| 422 | PO_ITEM_NOT_FOUND |
๋ถํ(SKU)์ด ์กด์ฌํ์ง ์์ |
| 422 | PO_ITEM_INACTIVE |
๋นํ์ฑ ๋ถํ |
DRAFT ์ํ์ธ ๋ฐ์ฃผ๋ฅผ ๋ฌผ๋ฆฌ ์ญ์ ํฉ๋๋ค.
- DRAFT ์ํ์์๋ง ์ญ์ ๊ฐ๋ฅํฉ๋๋ค. CONFIRMED ์ดํ ์ํ์์๋
422๋ฅผ ๋ฐํํ๋ฉฐ, ์ด ๊ฒฝ์ฐ ์ทจ์๋cancelAPI๋ฅผ ์ฌ์ฉํฉ๋๋ค. - DB์์ ๋ ์ฝ๋๋ฅผ ์์ ํ ์ ๊ฑฐํ๋ฉฐ ์ด๋ ฅ์ด ๋จ์ง ์์ต๋๋ค. (soft delete์ธ
cancel๊ณผ ๊ตฌ๋ถ) - ์ฑ๊ณต ์ ์๋ต ๋ณธ๋ฌธ ์์ด
204 No Content๋ฅผ ๋ฐํํฉ๋๋ค.
Path Parameter
| ํ๋ผ๋ฏธํฐ | ํ์ | ์์ | ์ค๋ช |
|---|---|---|---|
poNumber |
String | PO-2026-0005 |
๋ฐ์ฃผ ๋ฒํธ (ํ์, ๊ณต๋ฐฑ ๋ถ๊ฐ) |
Response 204 No Content
Error
| ์ํ | code | ์ค๋ช |
|---|---|---|
| 400 | COMMON_INVALID_INPUT |
poNumber ๋๋ฝยท๊ณต๋ฐฑ |
| 404 | PO_NOT_FOUND |
๋ฐ์ฃผ๊ฐ ์กด์ฌํ์ง ์์ |
| 422 | PO_INVALID_STATUS |
DRAFT ์ํ๊ฐ ์๋์ด์ ์ญ์ ๋ถ๊ฐ |
๊ณต๊ธ์ฌ๋ active ํ๋๊ทธ๋ก ํ์ฑ/๋นํ์ฑ ์ํ๋ฅผ ๊ด๋ฆฌํฉ๋๋ค.
ํ์ฑ(active: true) โโ๋นํ์ฑํโโโบ ๋นํ์ฑ(active: false)
โฒ โ
โโโโโโโโโโํ์ฑํโโโโโโโโโโโโโโโโโโโโ
| ์ํ | ์ค๋ช |
|---|---|
active: true |
๋ฐ์ฃผ ์์ฑ ๊ฐ๋ฅ, ์ ๋ณด ์์ ๊ฐ๋ฅ |
active: false |
๋ฐ์ฃผ ์์ฑ ๋ถ๊ฐ, ์ ๋ณด ์์ ๋ถ๊ฐ |
์ ์ด ๊ท์น
| ์ ์ด | ์กฐ๊ฑด | ๋น๊ณ |
|---|---|---|
| ํ์ฑ โ ๋นํ์ฑ | ์งํ ์ค PO(DRAFT/CONFIRMED)๊ฐ 0๊ฑด์ผ ๋๋ง ๊ฐ๋ฅ | PO ์กด์ฌ ์ 422 VENDOR_HAS_ACTIVE_PO |
| ๋นํ์ฑ โ ํ์ฑ | ์ ์ฝ ์์ |
๋ฑ๋ก(
POST)ยท์์ (PUT)ยท์ญ์ (DELETE)์ ์ํ ์ ์ด API(confirm/receive/cancel)๊ฐ ๋ชจ๋ ๊ตฌํ๋์ด ์์ต๋๋ค.
DRAFT โโconfirm()โโโบ CONFIRMED โโreceive()โโโบ RECEIVED
โ โ
โ โโโcancel()โโโโโโโบ CANCELED
โโโdelete() โโ ๋ฌผ๋ฆฌ ์ญ์ (DB์์ ์์ ์ ๊ฑฐ)
| ์ํ | ์ค๋ช | IN_PROGRESS | TRADE |
|---|---|---|---|
DRAFT |
์์ฑ ์ค. ์์ง ๋ฐ์ฃผ๋์ง ์์ ์์ ์ํ | โ | โ |
CONFIRMED |
๋ฐ์ฃผ ํ์ . ์น์ธ์ ์ ๋ณด ๋ฐ ๋ฐ์ฃผ์ผ์ ๊ธฐ๋ก | โ | โ |
RECEIVED |
์ ๊ณ ์๋ฃ. ๋ผ์ธ๋ณ ์๋ น ์๋ ๊ธฐ๋ก | โ | โ |
CANCELED |
์ทจ์ ์ฒ๋ฆฌ. DB์ ์ด๋ ฅ์ผ๋ก ๋จ์ | โ | โ |
IN_PROGRESS (DRAFT + CONFIRMED): ๊ณต๊ธ์ฌ ๋นํ์ฑํ ๊ฐ๋ฅ ์ฌ๋ถ ํ๋จ ๋ฐ ์งํ ์ค PO ํต๊ณ์ ์ฌ์ฉ
TRADE (CONFIRMED + RECEIVED): ๊ฑฐ๋์ก ์ง๊ณ(tradeAmount30d) ์ฐ์ถ์ ์ฌ์ฉ
| ์ ์ด | ์ถ๋ฐ ์ํ | ์ค๋ช |
|---|---|---|
confirm() |
DRAFT | CONFIRMED๋ก ์ ์ด. ์น์ธ์ ์ ๋ณด(approvedBy, approvedName)์ ๋ฐ์ฃผ์ผ์(orderedAt) ๊ธฐ๋ก |
receive() |
CONFIRMED | RECEIVED๋ก ์ ์ด. ์
๊ณ ์ผ์(receivedAt) ๊ธฐ๋ก. ๋ผ์ธ๋ณ ์๋ น ์๋ ๋ฐ์ |
cancel() |
CONFIRMED | CANCELED๋ก ์ ์ด. DB์ ์ทจ์ ์ด๋ ฅ์ผ๋ก ๋ณด์กด๋จ (DRAFT๋ ์ทจ์ ๋์ ์๋, delete๋ก ๋ฌผ๋ฆฌ ์ญ์ ) |
delete() |
DRAFT ์ ์ฉ | DB์์ ๋ฌผ๋ฆฌ ์ญ์ . ๋ชฉ๋ก์์ ์์ ํ ์ ๊ฑฐ. ์ด๋ ฅ ์์ |
| ๊ตฌ๋ถ | cancel | delete |
|---|---|---|
| ๋์ ์ํ | CONFIRMED๋ง ๊ฐ๋ฅ | DRAFT๋ง ๊ฐ๋ฅ |
| ์ฒ๋ฆฌ ๋ฐฉ์ | ์ํ๋ฅผ CANCELED๋ก ๋ณ๊ฒฝ (์ํํธ ์ญ์ ) | DB์์ ๋ ์ฝ๋ ์์ ์ ๊ฑฐ (ํ๋ ์ญ์ ) |
| ์ด๋ ฅ ๋ณด์กด | โ ์ทจ์ ์ด๋ ฅ ๋จ์ | โ ํ์ ์์ด ์ญ์ |
| ์ฌ์ฉ ์๋๋ฆฌ์ค | ํ์ ๋ ๋ฐ์ฃผ๋ฅผ ๋๋๋ฆด ๋ | ์ค์๋ก ๋ง๋ ์์ ๋ฐ์ฃผ์(DRAFT)๋ฅผ ๋ชฉ๋ก์์ ์์ ํ ์ ๊ฑฐํ ๋ |