feat(repeat-screen-modal): 복수 외부 테이블 집계 지원 및 집계 설정 모달 UI 추가

- 여러 외부 테이블 데이터를 합산하여 집계 계산 지원
- 집계 설정 전용 모달(AggregationSettingsModal) 추가
- AggregationConfig에 hidden 속성 추가 (연산에만 사용, 표시 제외)
- 채번 규칙 API 에러 처리 개선 (조용히 무시, 로그 최소화)
This commit is contained in:
SeongHyun Kim 2025-12-10 10:37:33 +09:00
parent 5e97a3a5e9
commit ae6f022f88
7 changed files with 1623 additions and 134 deletions

View File

@ -607,7 +607,9 @@ class NumberingRuleService {
}
const result = await pool.query(query, params);
if (result.rowCount === 0) return null;
if (result.rowCount === 0) {
return null;
}
const rule = result.rows[0];

View File

@ -317,6 +317,11 @@ apiClient.interceptors.response.use(
return Promise.reject(error);
}
// 채번 규칙 미리보기 API 실패는 조용하게 처리 (화면 로드 시 자주 발생)
if (url?.includes("/numbering-rules/") && url?.includes("/preview")) {
return Promise.reject(error);
}
// 다른 에러들은 기존처럼 상세 로그 출력
console.error("API 응답 오류:", {
status: status,
@ -324,7 +329,6 @@ apiClient.interceptors.response.use(
url: url,
data: error.response?.data,
message: error.message,
headers: error.config?.headers,
});
// 401 에러 처리

View File

@ -109,11 +109,24 @@ export async function deleteNumberingRule(ruleId: string): Promise<ApiResponse<v
export async function previewNumberingCode(
ruleId: string
): Promise<ApiResponse<{ generatedCode: string }>> {
// ruleId 유효성 검사
if (!ruleId || ruleId === "undefined" || ruleId === "null") {
return { success: false, error: "채번 규칙 ID가 설정되지 않았습니다" };
}
try {
const response = await apiClient.post(`/numbering-rules/${ruleId}/preview`);
if (!response.data) {
return { success: false, error: "서버 응답이 비어있습니다" };
}
return response.data;
} catch (error: any) {
return { success: false, error: error.message || "코드 미리보기 실패" };
const errorMessage =
error.response?.data?.error ||
error.response?.data?.message ||
error.message ||
"코드 미리보기 실패";
return { success: false, error: errorMessage };
}
}

View File

@ -590,18 +590,24 @@ export function RepeatScreenModalComponent({
if (!hasExternalAggregation) return;
// contentRows에서 외부 테이블 데이터 소스가 있는 table 타입 행 찾기
const tableRowWithExternalSource = contentRows.find(
// contentRows에서 외부 테이블 데이터 소스가 있는 모든 table 타입 행 찾기
const tableRowsWithExternalSource = contentRows.filter(
(row) => row.type === "table" && row.tableDataSource?.enabled
);
if (!tableRowWithExternalSource) return;
if (tableRowsWithExternalSource.length === 0) return;
// 각 카드의 집계 재계산
const updatedCards = groupedCardsData.map((card) => {
const key = `${card._cardId}-${tableRowWithExternalSource.id}`;
// 🆕 v3.7: 삭제된 행은 집계에서 제외
const externalRows = (extData[key] || []).filter((row) => !row._isDeleted);
// 🆕 v3.11: 모든 외부 테이블 행의 데이터를 합침
const allExternalRows: any[] = [];
for (const tableRow of tableRowsWithExternalSource) {
const key = `${card._cardId}-${tableRow.id}`;
// 🆕 v3.7: 삭제된 행은 집계에서 제외
const rows = (extData[key] || []).filter((row) => !row._isDeleted);
allExternalRows.push(...rows);
}
const externalRows = allExternalRows;
// 집계 재계산
const newAggregations: Record<string, number> = {};

View File

@ -289,6 +289,9 @@ export interface AggregationConfig {
resultField: string; // 결과 필드명 (예: "total_balance_qty")
label: string; // 표시 라벨 (예: "총수주잔량")
// === 🆕 v3.10: 숨김 설정 ===
hidden?: boolean; // 레이아웃에서 숨김 (연산에만 사용, 기본: false)
// === 🆕 v3.9: 저장 설정 ===
saveConfig?: AggregationSaveConfig; // 연관 테이블 저장 설정
}

View File

@ -113,22 +113,20 @@ export const TextInputComponent: React.FC<TextInputComponentProps> = ({
// 채번 규칙은 비동기로 처리
if (testAutoGeneration.type === "numbering_rule") {
const ruleId = testAutoGeneration.options?.numberingRuleId;
if (ruleId) {
if (ruleId && ruleId !== "undefined" && ruleId !== "null") {
try {
console.log("🚀 채번 규칙 API 호출 시작:", ruleId);
const { generateNumberingCode } = await import("@/lib/api/numberingRule");
const response = await generateNumberingCode(ruleId);
console.log("✅ 채번 규칙 API 응답:", response);
const { previewNumberingCode } = await import("@/lib/api/numberingRule");
const response = await previewNumberingCode(ruleId);
if (response.success && response.data) {
generatedValue = response.data.generatedCode;
}
} catch (error) {
console.error("❌ 채번 규칙 코드 생성 실패:", error);
// 실패 시 조용히 무시 (채번 규칙이 없어도 화면은 정상 로드)
} catch {
// 네트워크 에러 등 예외 상황은 조용히 무시
} finally {
isGeneratingRef.current = false; // 생성 완료
isGeneratingRef.current = false;
}
} else {
console.warn("⚠️ 채번 규칙 ID가 없습니다");
isGeneratingRef.current = false;
}
} else {