feat: 품목관리 기능 개선 및 문서화 업데이트

- 품목 상세/수정 페이지 파일 다운로드 기능 개선
- DynamicItemForm 파일 업로드 UI/UX 개선 (시방서, 인정서)
- BendingDiagramSection 조립/절곡 부품 전개도 통합
- API proxy route 품목 타입별 라우팅 개선
- ItemListClient 파일 다운로드 유틸리티 적용
- 품목코드 중복 체크 및 다이얼로그 추가

문서화:
- DynamicItemForm 훅 분리 계획서 추가 (2161줄 → 900줄 목표)
- 백엔드 API 마이그레이션 문서 추가
- 대용량 파일 처리 전략 가이드 추가
- 테넌트 데이터 격리 감사 문서 추가

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
byeongcheolryu
2025-12-16 11:01:25 +09:00
parent 8457dba0fc
commit b1587071f2
25 changed files with 3905 additions and 183 deletions

View File

@@ -174,15 +174,11 @@ export default function ItemListClient() {
try {
console.log('[Delete] 삭제 요청:', itemToDelete);
// Materials (SM, RM, CS)는 /products/materials 엔드포인트 사용
// Products (FG, PT)는 /items 엔드포인트 사용
// 2025-12-10: item_type 파라미터를 실제 코드(SM, RM, CS)로 전달
const isMaterial = MATERIAL_TYPES.includes(itemToDelete.itemType);
const deleteUrl = isMaterial
? `/api/proxy/products/materials/${itemToDelete.id}?item_type=${itemToDelete.itemType}`
: `/api/proxy/items/${itemToDelete.id}`;
// 2025-12-15: 백엔드 동적 테이블 라우팅 - 모든 품목이 /items 엔드포인트 사용
// /products/materials 라우트 삭제됨
const deleteUrl = `/api/proxy/items/${itemToDelete.id}?item_type=${itemToDelete.itemType}`;
console.log('[Delete] URL:', deleteUrl, '(isMaterial:', isMaterial, ', itemType:', itemToDelete.itemType, ')');
console.log('[Delete] URL:', deleteUrl, '(itemType:', itemToDelete.itemType, ')');
const response = await fetch(deleteUrl, {
method: 'DELETE',
@@ -230,7 +226,7 @@ export default function ItemListClient() {
};
// 일괄 삭제 핸들러
// 2025-12-10: item_type 파라미터를 실제 코드(SM, RM, CS)로 전달
// 2025-12-15: 백엔드 동적 테이블 라우팅으로 모든 품목에 item_type 필수
const handleBulkDelete = async () => {
const itemIds = Array.from(selectedItems);
let successCount = 0;
@@ -240,11 +236,8 @@ export default function ItemListClient() {
try {
// 해당 품목의 itemType 찾기
const item = items.find((i) => i.id === id);
const isMaterial = item ? MATERIAL_TYPES.includes(item.itemType) : false;
// Materials는 /products/materials 엔드포인트 + item_type, Products는 /items 엔드포인트
const deleteUrl = isMaterial
? `/api/proxy/products/materials/${id}?item_type=${item?.itemType}`
: `/api/proxy/items/${id}`;
// 2025-12-15: 백엔드 동적 테이블 라우팅 - 모든 품목이 /items 엔드포인트 사용
const deleteUrl = `/api/proxy/items/${id}?item_type=${item?.itemType}`;
const response = await fetch(deleteUrl, {
method: 'DELETE',