fix: UniversalFormModal 채번 규칙 자동 생성 기능 개선

- 모달 재오픈 시 동일 번호 유지 (previewCode 사용)
- 저장 시 정상적인 순번 증가 (allocateCode에서 nextSequence 사용)
- refreshKey를 React key로 전달하여 컴포넌트 강제 리마운트
- ruleId를 부모 컴포넌트까지 전달하여 buttonActions에서 감지
- 미리보기와 저장 번호 일치 (currentSequence + 1 통일)
This commit is contained in:
SeongHyun Kim
2025-12-12 10:55:09 +09:00
parent ab8b5a2c91
commit a9135165d9
3 changed files with 35 additions and 15 deletions

View File

@@ -959,9 +959,10 @@ class NumberingRuleService {
switch (part.partType) { switch (part.partType) {
case "sequence": { case "sequence": {
// 순번 (자동 증가 숫자) // 순번 (자동 증가 숫자 - 다음 번호 사용)
const length = autoConfig.sequenceLength || 3; const length = autoConfig.sequenceLength || 3;
return String(rule.currentSequence || 1).padStart(length, "0"); const nextSequence = (rule.currentSequence || 0) + 1;
return String(nextSequence).padStart(length, "0");
} }
case "number": { case "number": {

View File

@@ -468,7 +468,8 @@ export const DynamicComponentRenderer: React.FC<DynamicComponentRendererProps> =
return rendererInstance.render(); return rendererInstance.render();
} else { } else {
// 함수형 컴포넌트 // 함수형 컴포넌트
return <NewComponentRenderer {...rendererProps} />; // refreshKey를 React key로 전달하여 컴포넌트 리마운트 강제
return <NewComponentRenderer key={refreshKey} {...rendererProps} />;
} }
} }
} catch (error) { } catch (error) {

View File

@@ -23,7 +23,7 @@ import { ChevronDown, ChevronUp, Plus, Trash2, RefreshCw, Loader2 } from "lucide
import { toast } from "sonner"; import { toast } from "sonner";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { apiClient } from "@/lib/api/client"; import { apiClient } from "@/lib/api/client";
import { generateNumberingCode, allocateNumberingCode } from "@/lib/api/numberingRule"; import { generateNumberingCode, allocateNumberingCode, previewNumberingCode } from "@/lib/api/numberingRule";
import { useCascadingDropdown } from "@/hooks/useCascadingDropdown"; import { useCascadingDropdown } from "@/hooks/useCascadingDropdown";
import { CascadingDropdownConfig } from "@/types/screen-management"; import { CascadingDropdownConfig } from "@/types/screen-management";
@@ -257,8 +257,11 @@ export function UniversalFormModalComponent({
// 외부 formData에 이미 값이 있어도 UniversalFormModal 값으로 덮어씀 // 외부 formData에 이미 값이 있어도 UniversalFormModal 값으로 덮어씀
// (UniversalFormModal이 해당 필드의 주인이므로) // (UniversalFormModal이 해당 필드의 주인이므로)
for (const [key, value] of Object.entries(formData)) { for (const [key, value] of Object.entries(formData)) {
// 설정에 정의된 필드만 병합 // 설정에 정의된 필드 또는 채번 규칙 ID 필드만 병합
if (configuredFields.has(key)) { const isConfiguredField = configuredFields.has(key);
const isNumberingRuleId = key.endsWith("_numberingRuleId");
if (isConfiguredField || isNumberingRuleId) {
if (value !== undefined && value !== null && value !== "") { if (value !== undefined && value !== null && value !== "") {
event.detail.formData[key] = value; event.detail.formData[key] = value;
console.log(`[UniversalFormModal] 필드 병합: ${key} =`, value); console.log(`[UniversalFormModal] 필드 병합: ${key} =`, value);
@@ -401,7 +404,7 @@ export function UniversalFormModalComponent({
} }
isGeneratingRef.current = true; // 진행 중 표시 isGeneratingRef.current = true; // 진행 중 표시
console.log('[채번] 생성 시작'); console.log('[채번] 미리보기 생성 시작');
const updatedData = { ...currentFormData }; const updatedData = { ...currentFormData };
let hasChanges = false; let hasChanges = false;
@@ -417,17 +420,32 @@ export function UniversalFormModalComponent({
!updatedData[field.columnName] !updatedData[field.columnName]
) { ) {
try { try {
console.log(`[채번 API 호출] ${field.columnName}, ruleId: ${field.numberingRule.ruleId}`); console.log(`[채번 미리보기 API 호출] ${field.columnName}, ruleId: ${field.numberingRule.ruleId}`);
// generateOnOpen: 모달 열 때 실제 순번 할당 (DB 시퀀스 즉시 증가) // generateOnOpen: 미리보기만 표시 (DB 시퀀스 증가 안 함)
const response = await allocateNumberingCode(field.numberingRule.ruleId); const response = await previewNumberingCode(field.numberingRule.ruleId);
if (response.success && response.data?.generatedCode) { if (response.success && response.data?.generatedCode) {
updatedData[field.columnName] = response.data.generatedCode; updatedData[field.columnName] = response.data.generatedCode;
// 저장 시 실제 할당을 위해 ruleId 저장 (TextInput과 동일한 키 형식)
const ruleIdKey = `${field.columnName}_numberingRuleId`;
updatedData[ruleIdKey] = field.numberingRule.ruleId;
hasChanges = true; hasChanges = true;
numberingGeneratedRef.current = true; // 생성 완료 표시 numberingGeneratedRef.current = true; // 생성 완료 표시
console.log(`[채번 완료] ${field.columnName} = ${response.data.generatedCode}`); console.log(`[채번 미리보기 완료] ${field.columnName} = ${response.data.generatedCode} (저장 시 실제 할당)`);
console.log(`[채번 규칙 ID 저장] ${ruleIdKey} = ${field.numberingRule.ruleId}`);
// 부모 컴포넌트에도 ruleId 전달 (ModalRepeaterTable → ScreenModal)
if (onChange) {
onChange({
...updatedData,
[ruleIdKey]: field.numberingRule.ruleId
});
console.log(`[채번] 부모에게 ruleId 전달: ${ruleIdKey}`);
}
} }
} catch (error) { } catch (error) {
console.error(`채번규칙 생성 실패 (${field.columnName}):`, error); console.error(`채번규칙 미리보기 실패 (${field.columnName}):`, error);
} }
} }
} }
@@ -439,7 +457,7 @@ export function UniversalFormModalComponent({
setFormData(updatedData); setFormData(updatedData);
} }
}, },
[config], [config, onChange],
); );
// 필드 값 변경 핸들러 // 필드 값 변경 핸들러
@@ -659,9 +677,9 @@ export function UniversalFormModalComponent({
const saveSingleRow = useCallback(async () => { const saveSingleRow = useCallback(async () => {
const dataToSave = { ...formData }; const dataToSave = { ...formData };
// 메타데이터 필드 제거 // 메타데이터 필드 제거 (채번 규칙 ID는 유지 - buttonActions.ts에서 사용)
Object.keys(dataToSave).forEach((key) => { Object.keys(dataToSave).forEach((key) => {
if (key.startsWith("_")) { if (key.startsWith("_") && !key.includes("_numberingRuleId")) {
delete dataToSave[key]; delete dataToSave[key];
} }
}); });