6.8 KiB
6.8 KiB
재고 조정 위치 이동 요청 — 입고관리 → 재고 상세
날짜: 2026-03-17 요청자: R&D실 (백엔드) 대상: React 프론트엔드 API 상태: 구현 완료
변경 요약
재고 조정 기능을 입고관리 화면에서 분리하여 재고현황 > 재고 상세 화면으로 이동한다.
현재 구조 (AS-IS)
입고관리 목록 (ReceivingList.tsx)
→ 헤더에 [재고 조정] 버튼 → InventoryAdjustmentDialog 팝업
입고관리 상세 (ReceivingDetail.tsx)
→ 하단에 재고 조정 이력 섹션
문제: 재고 조정은 특정 입고 건과 무관하게 품목 재고를 직접 증감하는 기능이므로, 입고관리보다 재고현황에 위치하는 것이 적합하다.
변경 구조 (TO-BE)
재고현황 (/material/stock-status)
└─ 재고 상세 (/material/stock-status/{id})
├─ 기본 정보 (기존)
│ ├─ 자재번호, 품목코드, 품목유형, 품목명
│ ├─ 규격, 단위, 재고량, 안전재고
│ └─ 재공품, 상태
│
└─ 재고 조정 섹션 ← 기본 정보 바로 아래에 추가
├─ 이력 테이블 (No, 조정일시, 증감 수량, 사유, 검수자)
└─ + 추가 버튼
대상 컴포넌트
제거 (입고관리)
| 파일 | 변경 |
|---|---|
ReceivingManagement/ReceivingList.tsx |
헤더의 "재고 조정" 버튼 + isAdjustmentOpen 상태 + InventoryAdjustmentDialog 제거 |
ReceivingManagement/ReceivingDetail.tsx |
재고 조정 이력 섹션 렌더링 제거 |
ReceivingManagement/types.ts |
InventoryAdjustmentRecord 타입은 유지 (공유) 또는 이동 |
추가 (재고 상세)
| 파일 | 변경 |
|---|---|
StockStatus/StockStatusDetail.tsx |
기본 정보 카드 아래에 재고 조정 섹션 추가 |
재사용
| 파일 | 설명 |
|---|---|
ReceivingManagement/InventoryAdjustmentDialog.tsx |
재고 조정 다이얼로그 (공통 위치로 추출 권장) |
재고 조정 섹션 UI 명세
이력 테이블
┌──────────────────────────────────────────────────────────────────┐
│ 재고 조정 [+ 추가] │
├──────────────────────────────────────────────────────────────────┤
│ No │ 조정일시 │ 증감 수량 │ 사유 │ 검수자 │
├──────┼─────────────────────┼────────────┼─────────┼────────────┤
│ 1 │ 2026-03-17 14:30 │ +100 │ 실사조정 │ 김보곤 │
│ 2 │ 2026-03-16 10:15 │ -50 │ 파손폐기 │ 홍길동 │
├──────────────────────────────────────────────────────────────────┤
│ 재고 조정 이력이 없습니다. │
└──────────────────────────────────────────────────────────────────┘
컬럼 정의
| 컬럼 | 필드 | 설명 |
|---|---|---|
| No | (순번) | 행 번호 |
| 조정일시 | adjusted_at |
조정 시각 (YYYY-MM-DD HH:mm) |
| 증감 수량 | quantity |
양수(+): 증가, 음수(-): 감소 |
| 사유 | remark |
조정 사유 (nullable) |
| 검수자 | inspector |
조정 수행자 이름 |
+ 추가 버튼 동작
- 클릭 시 간단한 입력 폼 또는 모달 오픈
- 증감 수량 (필수, 0 제외) 및 사유 (선택) 입력
- 저장 시
POST /api/v1/stocks/{stockId}/adjustments호출 - 성공 시 이력 테이블 새로고침 + 기본 정보의 재고량 갱신
API 엔드포인트 (구현 완료)
1. 재고 조정 이력 조회
GET /api/v1/stocks/{stockId}/adjustments
응답:
{
"success": true,
"message": "데이터를 조회했습니다.",
"data": [
{
"id": 1,
"adjusted_at": "2026-03-17 14:30",
"quantity": 100,
"balance_qty": 196,
"remark": "실사 조정",
"inspector": "김보곤"
},
{
"id": 2,
"adjusted_at": "2026-03-16 10:15",
"quantity": -50,
"balance_qty": 96,
"remark": "파손 폐기",
"inspector": "홍길동"
}
]
}
stockId는 재고 상세 조회(GET /api/v1/stocks/{id})에서 받는stock.id값이다.
2. 재고 조정 등록
POST /api/v1/stocks/{stockId}/adjustments
요청:
{
"quantity": 100,
"remark": "실사 조정"
}
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
quantity |
number | O | 증감 수량 (양수: 증가, 음수: 감소, 0 불가) |
remark |
string | X | 조정 사유 (최대 500자) |
응답:
{
"success": true,
"message": "데이터를 생성했습니다.",
"data": {
"id": 3,
"adjusted_at": "2026-03-17 15:00",
"quantity": 100,
"balance_qty": 296,
"remark": "실사 조정",
"inspector": "김보곤"
}
}
3. stockId 확인 방법
재고 상세 조회 응답에서 stock 관계의 id를 사용한다:
GET /api/v1/stocks/{itemId} ← 이것은 Item ID
→ response.data.stock.id ← 이것이 stockId (adjustments에 사용)
TypeScript 타입 정의
interface StockAdjustmentRecord {
id: number;
adjusted_at: string; // "2026-03-17 14:30"
quantity: number; // 양수: 증가, 음수: 감소
balance_qty: number; // 조정 후 잔량
remark: string | null; // 조정 사유
inspector: string; // 검수자 이름
}
interface StockAdjustmentForm {
quantity: number; // 필수, 0 불가
remark?: string; // 선택, 최대 500자
}
Server Action 예시
// actions.ts에 추가
export async function getStockAdjustments(stockId: number) {
return fetchApi(`/stocks/${stockId}/adjustments`);
}
export async function createStockAdjustment(
stockId: number,
data: StockAdjustmentForm
) {
return fetchApi(`/stocks/${stockId}/adjustments`, {
method: 'POST',
body: JSON.stringify(data),
});
}
참고
- 재고 상세 화면:
/material/stock-status/{id} - 기존 재고 조정 컴포넌트:
ReceivingManagement/InventoryAdjustmentDialog.tsx - 재고 상세 컴포넌트:
StockStatus/StockStatusDetail.tsx - API 커밋:
feat: [stock] 재고 조정 API 추가