- BOMItem Omit 타입 시그니처 통일 (useTemplateManagement, SectionsTab, ItemMasterContext) - HeadersInit → Record<string, string> 타입 변경 - Zustand useShallow 마이그레이션 (zustand/react/shallow) - DataTable, ListPageTemplate 제네릭 타입 제약 추가 - 설정 관리 페이지 추가 (직급, 직책, 휴가정책, 근무일정, 권한) - HR 관리 페이지 추가 (급여, 휴가) - 단가관리 페이지 리팩토링 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
9.6 KiB
9.6 KiB
단가관리 API 개선 요청서
작성일: 2025-12-08 요청자: 프론트엔드 개발팀 대상: sam-api 백엔드 팀
1. 현황 요약
현재 API 구조
| Endpoint | Method | 상태 |
|---|---|---|
/api/v1/pricing |
GET | 목록 조회 |
/api/v1/pricing/show |
GET | 단일 가격 조회 |
/api/v1/pricing/bulk |
POST | 일괄 가격 조회 |
/api/v1/pricing/upsert |
POST | 등록/수정 |
/api/v1/pricing/{id} |
DELETE | 삭제 |
✅ 이미 지원됨 (품목 정보)
item_type_code(품목유형) - PriceHistory 테이블item_code,item_name,specification,unit- item 관계 JOIN으로 조회 가능
❌ 문제점 (단가 상세 정보)
- 프론트엔드 단가관리 화면에서 요구하는 단가 계산 필드 대부분 누락
- 현재
price_histories테이블은 단순 가격 이력만 저장 (price단일 필드) - 프론트엔드는 원가 계산, 마진 관리, 리비전 관리 기능 필요
2. 테이블 스키마 변경 요청
2.1 price_histories 테이블 필드 추가
ALTER TABLE price_histories ADD COLUMN purchase_price DECIMAL(15,4) NULL COMMENT '매입단가(입고가)';
ALTER TABLE price_histories ADD COLUMN processing_cost DECIMAL(15,4) NULL COMMENT '가공비';
ALTER TABLE price_histories ADD COLUMN loss_rate DECIMAL(5,2) NULL COMMENT 'LOSS율(%)';
ALTER TABLE price_histories ADD COLUMN rounding_rule ENUM('round','ceil','floor') DEFAULT 'round' COMMENT '반올림 규칙';
ALTER TABLE price_histories ADD COLUMN rounding_unit INT DEFAULT 1 COMMENT '반올림 단위(1,10,100,1000)';
ALTER TABLE price_histories ADD COLUMN margin_rate DECIMAL(5,2) NULL COMMENT '마진율(%)';
ALTER TABLE price_histories ADD COLUMN sales_price DECIMAL(15,4) NULL COMMENT '판매단가';
ALTER TABLE price_histories ADD COLUMN supplier VARCHAR(255) NULL COMMENT '공급업체';
ALTER TABLE price_histories ADD COLUMN author VARCHAR(100) NULL COMMENT '작성자';
ALTER TABLE price_histories ADD COLUMN receive_date DATE NULL COMMENT '입고일';
ALTER TABLE price_histories ADD COLUMN note TEXT NULL COMMENT '비고';
ALTER TABLE price_histories ADD COLUMN revision_number INT DEFAULT 0 COMMENT '리비전 번호';
ALTER TABLE price_histories ADD COLUMN is_final BOOLEAN DEFAULT FALSE COMMENT '최종 확정 여부';
ALTER TABLE price_histories ADD COLUMN finalized_at DATETIME NULL COMMENT '확정일시';
ALTER TABLE price_histories ADD COLUMN finalized_by INT NULL COMMENT '확정자 ID';
ALTER TABLE price_histories ADD COLUMN status ENUM('draft','active','inactive','finalized') DEFAULT 'draft' COMMENT '상태';
2.2 기존 price 필드 처리 방안
옵션 A (권장): price 필드를 sales_price로 마이그레이션
UPDATE price_histories SET sales_price = price WHERE price_type_code = 'SALE';
UPDATE price_histories SET purchase_price = price WHERE price_type_code = 'PURCHASE';
-- 이후 price 필드 deprecated 또는 삭제
옵션 B: price 필드 유지, 새 필드와 병행 사용
- 기존 로직 호환성 유지
- 점진적 마이그레이션
3. API 엔드포인트 수정 요청
3.1 POST /api/v1/pricing/upsert 수정
현재 Request Body:
{
"item_type_code": "PRODUCT",
"item_id": 10,
"price_type_code": "SALE",
"client_group_id": 1,
"price": 50000.00,
"started_at": "2025-01-01",
"ended_at": "2025-12-31"
}
요청 Request Body:
{
"item_type_code": "PRODUCT",
"item_id": 10,
"client_group_id": 1,
"purchase_price": 45000,
"processing_cost": 5000,
"loss_rate": 3.5,
"rounding_rule": "round",
"rounding_unit": 100,
"margin_rate": 20.0,
"sales_price": 60000,
"supplier": "ABC공급",
"author": "홍길동",
"receive_date": "2025-01-01",
"started_at": "2025-01-01",
"ended_at": null,
"note": "2025년 1분기 단가",
"is_revision": false,
"revision_reason": "가격 인상"
}
3.2 GET /api/v1/pricing 수정 (목록 조회)
현재 Response:
{
"data": {
"data": [
{
"id": 1,
"item_type_code": "PRODUCT",
"item_id": 10,
"price_type_code": "SALE",
"price": 50000,
"started_at": "2025-01-01"
}
]
}
}
요청 Response:
{
"data": {
"data": [
{
"id": 1,
"item_type_code": "PRODUCT",
"item_id": 10,
"item_code": "SCREEN-001",
"item_name": "스크린 셔터 기본형",
"specification": "표준형",
"unit": "SET",
"purchase_price": 45000,
"processing_cost": 5000,
"loss_rate": 3.5,
"margin_rate": 20.0,
"sales_price": 60000,
"started_at": "2025-01-01",
"ended_at": null,
"status": "active",
"revision_number": 1,
"is_final": false,
"supplier": "ABC공급",
"created_at": "2025-01-01 10:00:00"
}
]
}
}
핵심 변경: 품목 정보 JOIN 필요 (item_masters 또는 products/materials 테이블)
4. 신규 API 엔드포인트 요청
4.1 품목 기반 단가 현황 조회 (신규)
용도: 품목 마스터 기준으로 단가 등록/미등록 현황 조회
Endpoint: GET /api/v1/pricing/by-items
Query Parameters:
| 파라미터 | 타입 | 설명 |
|---|---|---|
item_type_code |
string | 품목 유형 (FG, PT, SM, RM, CS) |
search |
string | 품목코드/품목명 검색 |
status |
string | all, registered, not_registered |
size |
int | 페이지당 항목 수 |
page |
int | 페이지 번호 |
Response:
{
"data": {
"data": [
{
"item_id": 1,
"item_code": "SCREEN-001",
"item_name": "스크린 셔터 기본형",
"item_type": "FG",
"specification": "표준형",
"unit": "SET",
"pricing_id": null,
"has_pricing": false,
"purchase_price": null,
"sales_price": null,
"margin_rate": null,
"status": "not_registered"
},
{
"item_id": 2,
"item_code": "GR-001",
"item_name": "가이드레일 130×80",
"item_type": "PT",
"specification": "130×80×2438",
"unit": "EA",
"pricing_id": 5,
"has_pricing": true,
"purchase_price": 45000,
"sales_price": 60000,
"margin_rate": 20.0,
"effective_date": "2025-01-01",
"status": "active",
"revision_number": 1,
"is_final": false
}
],
"stats": {
"total_items": 100,
"registered": 45,
"not_registered": 55,
"finalized": 10
}
}
}
4.2 단가 이력 조회 (신규)
Endpoint: GET /api/v1/pricing/{id}/revisions
Response:
{
"data": [
{
"revision_number": 2,
"revision_date": "2025-06-01",
"revision_by": "김철수",
"revision_reason": "원자재 가격 인상",
"previous_purchase_price": 40000,
"previous_sales_price": 55000,
"new_purchase_price": 45000,
"new_sales_price": 60000
},
{
"revision_number": 1,
"revision_date": "2025-01-01",
"revision_by": "홍길동",
"revision_reason": "최초 등록",
"previous_purchase_price": null,
"previous_sales_price": null,
"new_purchase_price": 40000,
"new_sales_price": 55000
}
]
}
4.3 단가 확정 (신규)
Endpoint: POST /api/v1/pricing/{id}/finalize
Request Body:
{
"finalize_reason": "2025년 1분기 단가 확정"
}
Response:
{
"data": {
"id": 5,
"is_final": true,
"finalized_at": "2025-12-08 14:30:00",
"finalized_by": 1,
"status": "finalized"
},
"message": "단가가 최종 확정되었습니다."
}
5. 프론트엔드 타입 참조
프론트엔드에서 사용하는 타입 정의 (src/components/pricing/types.ts):
interface PricingData {
id: string;
itemId: string;
itemCode: string;
itemName: string;
itemType: string;
specification?: string;
unit: string;
// 단가 정보
effectiveDate: string; // started_at
receiveDate?: string; // receive_date
author?: string; // author
purchasePrice?: number; // purchase_price
processingCost?: number; // processing_cost
loss?: number; // loss_rate
roundingRule?: RoundingRule; // rounding_rule
roundingUnit?: number; // rounding_unit
marginRate?: number; // margin_rate
salesPrice?: number; // sales_price
supplier?: string; // supplier
note?: string; // note
// 리비전 관리
currentRevision: number; // revision_number
isFinal: boolean; // is_final
revisions?: PricingRevision[];
finalizedDate?: string; // finalized_at
finalizedBy?: string; // finalized_by
status: PricingStatus; // status
}
6. 우선순위
| 순위 | 항목 | 중요도 |
|---|---|---|
| 1 | 테이블 스키마 변경 (필드 추가) | 🔴 필수 |
| 2 | POST /pricing/upsert 수정 |
🔴 필수 |
| 3 | GET /pricing/by-items 신규 |
🔴 필수 |
| 4 | GET /pricing 응답 확장 |
🟡 중요 |
| 5 | GET /pricing/{id}/revisions 신규 |
🟡 중요 |
| 6 | POST /pricing/{id}/finalize 신규 |
🟢 권장 |
7. 질문/협의 사항
- 기존 price 필드 처리: 마이그레이션 vs 병행 사용?
- 리비전 테이블 분리:
price_history_revisions별도 테이블 vs 현재 테이블 확장? - 품목 연결:
item_masters테이블 사용 vsproducts/materials각각 JOIN?
연락처: 프론트엔드 개발팀
관련 파일: src/components/pricing/types.ts