feat: Enhance Excel upload functionality with automatic numbering column detection

- Implemented automatic detection of numbering columns in the Excel upload modal, improving user experience by streamlining the upload process.
- Updated the master-detail Excel upload configuration to reflect changes in how numbering rules are applied, ensuring consistency across uploads.
- Refactored related components to remove deprecated properties and improve clarity in the configuration settings.
- Enhanced error handling and logging for better debugging during the upload process.
This commit is contained in:
kjs
2026-02-11 15:43:50 +09:00
parent eac2fa63b1
commit 2bbb5d7013
4 changed files with 362 additions and 305 deletions

View File

@@ -84,12 +84,9 @@ export interface ExcelUploadModalProps {
masterColumns: Array<{ name: string; label: string; inputType: string; isFromMaster: boolean }>;
detailColumns: Array<{ name: string; label: string; inputType: string; isFromMaster: boolean }>;
};
// 🆕 마스터-디테일 엑셀 업로드 설정
// 마스터-디테일 엑셀 업로드 설정
masterDetailExcelConfig?: MasterDetailExcelConfig;
// 🆕 단일 테이블 채번 설정
numberingRuleId?: string;
numberingTargetColumn?: string;
// 🆕 업로드 후 제어 실행 설정
// 업로드 후 제어 실행 설정
afterUploadFlows?: Array<{ flowId: string; order: number }>;
}
@@ -112,9 +109,6 @@ export const ExcelUploadModal: React.FC<ExcelUploadModalProps> = ({
isMasterDetail = false,
masterDetailRelation,
masterDetailExcelConfig,
// 단일 테이블 채번 설정
numberingRuleId,
numberingTargetColumn,
// 업로드 후 제어 실행 설정
afterUploadFlows,
}) => {
@@ -627,6 +621,44 @@ export const ExcelUploadModal: React.FC<ExcelUploadModalProps> = ({
setCurrentStep((prev) => Math.max(prev - 1, 1));
};
// 테이블 타입 관리에서 채번 컬럼 자동 감지
const detectNumberingColumn = async (
targetTableName: string
): Promise<{ columnName: string; numberingRuleId: string } | null> => {
try {
const { getTableColumns } = await import("@/lib/api/tableManagement");
const response = await getTableColumns(targetTableName);
if (response.success && response.data?.columns) {
for (const col of response.data.columns) {
if (col.inputType === "numbering") {
try {
const settings =
typeof col.detailSettings === "string"
? JSON.parse(col.detailSettings)
: col.detailSettings;
if (settings?.numberingRuleId) {
console.log(
`✅ 채번 컬럼 자동 감지: ${col.columnName} → 규칙 ID: ${settings.numberingRuleId}`
);
return {
columnName: col.columnName,
numberingRuleId: settings.numberingRuleId,
};
}
} catch {
// detailSettings 파싱 실패 시 무시
}
}
}
}
return null;
} catch (error) {
console.error("채번 컬럼 감지 실패:", error);
return null;
}
};
// 업로드 핸들러
const handleUpload = async () => {
if (!file || !tableName) {
@@ -667,19 +699,24 @@ export const ExcelUploadModal: React.FC<ExcelUploadModalProps> = ({
`📊 엑셀 업로드: 전체 ${mappedData.length}행 중 유효한 ${filteredData.length}`
);
// 🆕 마스터-디테일 간단 모드 처리 (마스터 필드 선택 + 채번)
// 마스터-디테일 간단 모드 처리 (마스터 필드 선택 + 채번 자동 감지)
if (isSimpleMasterDetailMode && screenId && masterDetailRelation) {
// 마스터 테이블에서 채번 컬럼 자동 감지
const masterNumberingInfo = await detectNumberingColumn(masterDetailRelation.masterTable);
const detectedNumberingRuleId = masterNumberingInfo?.numberingRuleId || masterDetailExcelConfig?.numberingRuleId;
console.log("📊 마스터-디테일 간단 모드 업로드:", {
masterDetailRelation,
masterFieldValues,
numberingRuleId: masterDetailExcelConfig?.numberingRuleId,
detectedNumberingRuleId,
autoDetected: !!masterNumberingInfo,
});
const uploadResult = await DynamicFormApi.uploadMasterDetailSimple(
screenId,
filteredData,
masterFieldValues,
masterDetailExcelConfig?.numberingRuleId || undefined,
detectedNumberingRuleId || undefined,
masterDetailExcelConfig?.afterUploadFlowId || undefined, // 하위 호환성
masterDetailExcelConfig?.afterUploadFlows || undefined // 다중 제어
);
@@ -704,6 +741,24 @@ export const ExcelUploadModal: React.FC<ExcelUploadModalProps> = ({
else if (isMasterDetail && screenId && masterDetailRelation) {
console.log("📊 마스터-디테일 업로드 모드:", masterDetailRelation);
// 마스터 키 컬럼 매핑 검증 (채번 타입이면 자동 생성되므로 검증 생략)
const masterKeyCol = masterDetailRelation.masterKeyColumn;
const hasMasterKey = filteredData.length > 0 && filteredData[0][masterKeyCol] !== undefined && filteredData[0][masterKeyCol] !== null && filteredData[0][masterKeyCol] !== "";
if (!hasMasterKey) {
// 채번 여부 확인 - 채번이면 백엔드에서 자동 생성하므로 통과
const numberingInfo = await detectNumberingColumn(masterDetailRelation.masterTable);
const isMasterKeyAutoNumbering = numberingInfo && numberingInfo.columnName === masterKeyCol;
if (!isMasterKeyAutoNumbering) {
toast.error(
`마스터 키 컬럼(${masterKeyCol})이 매핑되지 않았습니다. 컬럼 매핑에서 [마스터] 항목을 확인해주세요.`
);
setIsUploading(false);
return;
}
console.log(`✅ 마스터 키(${masterKeyCol})는 채번 타입 → 백엔드에서 자동 생성`);
}
const uploadResult = await DynamicFormApi.uploadMasterDetailData(
screenId,
filteredData
@@ -731,8 +786,9 @@ export const ExcelUploadModal: React.FC<ExcelUploadModalProps> = ({
let skipCount = 0;
let overwriteCount = 0;
// 단일 테이블 채번 설정 확인
const hasNumbering = numberingRuleId && numberingTargetColumn;
// 단일 테이블 채번 자동 감지 (테이블 타입 관리에서 input_type = 'numbering' 컬럼)
const numberingInfo = await detectNumberingColumn(tableName);
const hasNumbering = !!numberingInfo;
// 중복 체크 설정 확인
const duplicateCheckMappings = columnMappings.filter(
@@ -816,14 +872,14 @@ export const ExcelUploadModal: React.FC<ExcelUploadModalProps> = ({
continue;
}
// 채번 적용: 각 행마다 채번 API 호출 (신규 등록 시에만)
if (hasNumbering && uploadMode === "insert" && !shouldUpdate) {
// 채번 적용: 각 행마다 채번 API 호출 (신규 등록 시에만, 자동 감지된 채번 규칙 사용)
if (hasNumbering && numberingInfo && uploadMode === "insert" && !shouldUpdate) {
try {
const { apiClient } = await import("@/lib/api/client");
const numberingResponse = await apiClient.post(`/numbering-rules/${numberingRuleId}/allocate`);
const numberingResponse = await apiClient.post(`/numbering-rules/${numberingInfo.numberingRuleId}/allocate`);
const generatedCode = numberingResponse.data?.data?.generatedCode || numberingResponse.data?.data?.code;
if (numberingResponse.data?.success && generatedCode) {
dataToSave[numberingTargetColumn] = generatedCode;
dataToSave[numberingInfo.columnName] = generatedCode;
}
} catch (numError) {
console.error("채번 오류:", numError);