- 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>
353 lines
11 KiB
TypeScript
353 lines
11 KiB
TypeScript
/**
|
|
* 품목 관리 타입 정의
|
|
*
|
|
* React 프로젝트에서 마이그레이션
|
|
* Source: sma-react-v2.0/src/components/contexts/DataContext.tsx
|
|
*/
|
|
|
|
// ===== 기본 타입 =====
|
|
|
|
/**
|
|
* 품목 유형
|
|
* - FG: Finished Goods (완제품)
|
|
* - PT: Parts (부품)
|
|
* - SM: Sub-Materials (부자재)
|
|
* - RM: Raw Materials (원자재)
|
|
* - CS: Consumables (소모품)
|
|
*/
|
|
export type ItemType = 'FG' | 'PT' | 'SM' | 'RM' | 'CS';
|
|
|
|
/**
|
|
* 제품 카테고리
|
|
*/
|
|
export type ProductCategory = 'SCREEN' | 'STEEL';
|
|
|
|
/**
|
|
* 부품 유형
|
|
* - ASSEMBLY: 조립 부품
|
|
* - BENDING: 절곡 부품
|
|
* - PURCHASED: 구매 부품
|
|
*/
|
|
export type PartType = 'ASSEMBLY' | 'BENDING' | 'PURCHASED';
|
|
|
|
/**
|
|
* 부품 용도
|
|
*/
|
|
export type PartUsage =
|
|
| 'GUIDE_RAIL' // 가이드레일
|
|
| 'BOTTOM_FINISH' // 하단마감재
|
|
| 'CASE' // 케이스
|
|
| 'DOOR' // 도어
|
|
| 'BRACKET' // 브라켓
|
|
| 'GENERAL'; // 일반
|
|
|
|
// ===== 절곡품 전개도 =====
|
|
|
|
/**
|
|
* 절곡품 전개도 상세 데이터
|
|
*/
|
|
export interface BendingDetail {
|
|
id: string;
|
|
no: number; // 번호
|
|
input: number; // 입력값
|
|
elongation: number; // 연신율 (기본값 -1)
|
|
calculated: number; // 연신율 계산 후 값
|
|
sum: number; // 합계
|
|
shaded: boolean; // 음영 여부
|
|
aAngle?: number; // A각
|
|
}
|
|
|
|
// ===== BOM (자재명세서) =====
|
|
|
|
/**
|
|
* 부품구성표 (Bill of Materials)
|
|
* 제품의 하위 구성 품목 정보
|
|
*/
|
|
export interface BOMLine {
|
|
id: string;
|
|
childItemCode: string; // 하위 품목 코드
|
|
childItemName: string; // 하위 품목명
|
|
specification?: string; // 규격
|
|
material?: string; // 재질
|
|
quantity: number; // 기준 수량
|
|
unit: string; // 단위
|
|
unitPrice?: number; // 단가
|
|
quantityFormula?: string; // 수량 계산식 (예: "W * 2", "H + 100")
|
|
note?: string; // 비고
|
|
width?: number; // 폭 (절곡품)
|
|
|
|
// 절곡품 관련 (하위 절곡 부품용)
|
|
isBending?: boolean; // 절곡품 여부
|
|
bendingDiagram?: string; // 전개도 이미지 URL
|
|
bendingDetails?: BendingDetail[]; // 전개도 상세 데이터
|
|
}
|
|
|
|
// ===== 품목 수정 이력 =====
|
|
|
|
/**
|
|
* 품목 수정 이력
|
|
*/
|
|
export interface ItemRevision {
|
|
revisionNumber: number; // 수정 차수 (1차, 2차, 3차...)
|
|
revisionDate: string; // 수정일
|
|
revisionBy: string; // 수정자
|
|
revisionReason?: string; // 수정 사유
|
|
previousData: any; // 이전 버전의 전체 데이터
|
|
}
|
|
|
|
// ===== 품목 마스터 (메인) =====
|
|
|
|
/**
|
|
* 품목 마스터 데이터
|
|
* 모든 품목 유형(FG/PT/SM/RM/CS)을 포괄하는 통합 인터페이스
|
|
*/
|
|
export interface ItemMaster {
|
|
// === 공통 필드 (모든 품목 유형) ===
|
|
id: string;
|
|
itemCode: string; // 품목 코드 (예: "KD-FG-001")
|
|
itemName: string; // 품목명
|
|
itemType: ItemType; // 품목 유형
|
|
unit: string; // 단위 (EA, SET, KG, M 등)
|
|
specification?: string; // 규격
|
|
isActive?: boolean; // 활성/비활성
|
|
|
|
// === 분류 ===
|
|
category1?: string; // 대분류
|
|
category2?: string; // 중분류
|
|
category3?: string; // 소분류
|
|
|
|
// === 가격 정보 ===
|
|
purchasePrice?: number; // 구매 단가
|
|
salesPrice?: number; // 판매 단가
|
|
marginRate?: number; // 마진율
|
|
processingCost?: number; // 가공비
|
|
laborCost?: number; // 노무비
|
|
installCost?: number; // 설치비
|
|
|
|
// === BOM (자재명세서) ===
|
|
bom?: BOMLine[]; // 하위 품목 구성
|
|
bomCategories?: string[]; // BOM 카테고리
|
|
|
|
// === 제품(FG) 전용 필드 ===
|
|
productName?: string; // 상품명 (고객용)
|
|
productCategory?: ProductCategory; // 제품 카테고리
|
|
lotAbbreviation?: string; // 로트 약자 (예: "KD")
|
|
note?: string; // 비고
|
|
description?: string; // 설명
|
|
|
|
// === 부품(PT) 전용 필드 ===
|
|
partType?: PartType; // 부품 유형
|
|
partUsage?: PartUsage; // 부품 용도
|
|
|
|
// 조립 부품 관련
|
|
installationType?: string; // 설치 유형 (벽면형/측면형)
|
|
assemblyType?: string; // 종류 (M/T/C/D/S/U)
|
|
sideSpecWidth?: string; // 측면 규격 가로 (mm)
|
|
sideSpecHeight?: string; // 측면 규격 세로 (mm)
|
|
assemblyLength?: string; // 길이 (2438/3000/3500/4000/4300)
|
|
|
|
// 가이드레일 관련
|
|
guideRailModelType?: string; // 가이드레일 모델 유형
|
|
guideRailModel?: string; // 가이드레일 모델
|
|
|
|
// 절곡품 관련
|
|
bendingDiagram?: string; // 전개도 이미지 URL
|
|
bendingDetails?: BendingDetail[]; // 전개도 상세 데이터
|
|
material?: string; // 재질 (EGI 1.55T, SUS 1.2T)
|
|
length?: string; // 길이/목함 (mm)
|
|
bendingLength?: string; // 절곡품 길이 규격
|
|
|
|
// 구매 부품 관련
|
|
electricOpenerPower?: string; // 전동개폐기 전원 (220V/380V)
|
|
electricOpenerCapacity?: string; // 전동개폐기 용량 (150/300/400/500/600/800/1000 KG)
|
|
motorVoltage?: string; // 모터 전압 (220V/380V)
|
|
motorCapacity?: string; // 모터 용량 (kg)
|
|
chainSpec?: string; // 체인 규격
|
|
|
|
// === 인정 정보 (제품/부품) ===
|
|
certificationNumber?: string; // 인정번호
|
|
certificationStartDate?: string; // 인정 유효기간 시작일
|
|
certificationEndDate?: string; // 인정 유효기간 종료일
|
|
specificationFile?: string; // 시방서 파일 URL
|
|
specificationFileName?: string; // 시방서 파일명
|
|
certificationFile?: string; // 인정서 파일 URL
|
|
certificationFileName?: string; // 인정서 파일명
|
|
|
|
// === 메타데이터 ===
|
|
safetyStock?: number; // 안전재고
|
|
leadTime?: number; // 리드타임
|
|
isVariableSize?: boolean; // 가변 크기 여부
|
|
|
|
// 버전 관리
|
|
currentRevision: number; // 현재 차수 (0 = 최초, 1 = 1차 수정...)
|
|
revisions?: ItemRevision[]; // 수정 이력
|
|
isFinal: boolean; // 최종 확정 여부
|
|
finalizedDate?: string; // 최종 확정일
|
|
finalizedBy?: string; // 최종 확정자
|
|
|
|
createdAt: string;
|
|
updatedAt?: string;
|
|
}
|
|
|
|
// ===== API 응답 타입 =====
|
|
|
|
/**
|
|
* Laravel API 응답 기본 구조
|
|
*/
|
|
export interface ApiResponse<T> {
|
|
success: boolean;
|
|
data: T;
|
|
message?: string;
|
|
errors?: Record<string, string[]>;
|
|
}
|
|
|
|
/**
|
|
* 페이지네이션 응답
|
|
*/
|
|
export interface PaginatedResponse<T> {
|
|
data: T[];
|
|
current_page: number;
|
|
last_page: number;
|
|
per_page: number;
|
|
total: number;
|
|
}
|
|
|
|
/**
|
|
* 품목 목록 조회 파라미터
|
|
*/
|
|
export interface FetchItemsParams {
|
|
itemType?: ItemType;
|
|
search?: string;
|
|
category1?: string;
|
|
category2?: string;
|
|
category3?: string;
|
|
isActive?: boolean;
|
|
page?: number;
|
|
per_page?: number;
|
|
}
|
|
|
|
/**
|
|
* 품목 생성/수정 데이터
|
|
*/
|
|
export type CreateItemData = Omit<ItemMaster, 'id' | 'createdAt' | 'updatedAt' | 'currentRevision' | 'revisions' | 'isFinal'>;
|
|
export type UpdateItemData = Partial<CreateItemData>;
|
|
|
|
// ===== 동적 템플릿 시스템 타입 (선택적) =====
|
|
|
|
/**
|
|
* 필드 표시 조건
|
|
*/
|
|
export interface FieldDisplayCondition {
|
|
dependsOn: string; // 의존하는 필드 키
|
|
showWhen: string | string[]; // 표시 조건 값
|
|
hideWhen?: string | string[]; // 숨김 조건 값
|
|
}
|
|
|
|
/**
|
|
* 필드 속성
|
|
*/
|
|
export interface ItemFieldProperty {
|
|
id?: string;
|
|
key?: string;
|
|
label?: string;
|
|
type?: 'textbox' | 'dropdown' | 'checkbox' | 'number' | 'date' | 'textarea';
|
|
inputType: 'textbox' | 'dropdown' | 'checkbox' | 'number' | 'date' | 'textarea' | 'section';
|
|
required: boolean;
|
|
row: number;
|
|
col: number;
|
|
options?: string[];
|
|
defaultValue?: string;
|
|
placeholder?: string;
|
|
multiColumn?: boolean;
|
|
columnCount?: number;
|
|
columnNames?: string[];
|
|
}
|
|
|
|
/**
|
|
* 필드 정의
|
|
*/
|
|
export interface ItemField {
|
|
id: string;
|
|
name: string; // 항목명
|
|
fieldKey: string; // 필드 키
|
|
property: ItemFieldProperty; // 속성
|
|
displayCondition?: FieldDisplayCondition; // 조건부 표시
|
|
}
|
|
|
|
/**
|
|
* 섹션 정의
|
|
*/
|
|
export interface ItemSection {
|
|
id: string;
|
|
title: string; // 섹션 제목
|
|
description?: string; // 설명
|
|
category?: string[]; // 카테고리 조건
|
|
fields: ItemField[]; // 섹션에 포함된 항목들
|
|
type?: 'fields' | 'bom'; // 섹션 타입
|
|
order: number; // 섹션 순서
|
|
isCollapsible: boolean; // 접기/펼치기 가능 여부
|
|
isCollapsed: boolean; // 기본 접힘 상태
|
|
}
|
|
|
|
/**
|
|
* 페이지 템플릿 정의
|
|
*/
|
|
export interface ItemPage {
|
|
id: string;
|
|
pageName: string; // 페이지명
|
|
itemType: ItemType; // 품목 유형
|
|
sections: ItemSection[]; // 페이지 내 섹션들
|
|
isActive: boolean; // 사용 여부
|
|
absolutePath?: string; // 절대경로
|
|
createdAt: string;
|
|
updatedAt?: string;
|
|
}
|
|
|
|
// ===== 유틸리티 타입 =====
|
|
|
|
/**
|
|
* 품목 코드 체계
|
|
* 형식: {업체코드}-{품목유형}-{일련번호}
|
|
* 예: KD-FG-001, KD-PT-001
|
|
*/
|
|
export type ItemCodeFormat = `${string}-${ItemType}-${string}`;
|
|
|
|
/**
|
|
* 품목 유형 라벨 맵
|
|
*/
|
|
export const ITEM_TYPE_LABELS: Record<ItemType, string> = {
|
|
FG: '제품',
|
|
PT: '부품',
|
|
SM: '부자재',
|
|
RM: '원자재',
|
|
CS: '소모품',
|
|
} as const;
|
|
|
|
/**
|
|
* 제품 카테고리 라벨
|
|
*/
|
|
export const PRODUCT_CATEGORY_LABELS: Record<ProductCategory, string> = {
|
|
SCREEN: '스크린',
|
|
STEEL: '철재',
|
|
} as const;
|
|
|
|
/**
|
|
* 부품 유형 라벨
|
|
*/
|
|
export const PART_TYPE_LABELS: Record<PartType, string> = {
|
|
ASSEMBLY: '조립 부품',
|
|
BENDING: '절곡 부품',
|
|
PURCHASED: '구매 부품',
|
|
} as const;
|
|
|
|
/**
|
|
* 부품 용도 라벨
|
|
*/
|
|
export const PART_USAGE_LABELS: Record<PartUsage, string> = {
|
|
GUIDE_RAIL: '가이드레일',
|
|
BOTTOM_FINISH: '하단마감재',
|
|
CASE: '케이스',
|
|
DOOR: '도어',
|
|
BRACKET: '브라켓',
|
|
GENERAL: '일반',
|
|
} as const; |