diff --git a/backend-node/src/controllers/tableManagementController.ts b/backend-node/src/controllers/tableManagementController.ts index e38e2cc5..be6a6402 100644 --- a/backend-node/src/controllers/tableManagementController.ts +++ b/backend-node/src/controllers/tableManagementController.ts @@ -662,14 +662,14 @@ export async function getTableRecord( logger.info(`필터: ${filterColumn} = ${filterValue}`); logger.info(`표시 컬럼: ${displayColumn}`); - if (!tableName || !filterColumn || !filterValue || !displayColumn) { + if (!tableName || !filterColumn || !filterValue) { const response: ApiResponse = { success: false, message: "필수 파라미터가 누락되었습니다.", error: { code: "MISSING_PARAMETERS", details: - "tableName, filterColumn, filterValue, displayColumn이 필요합니다.", + "tableName, filterColumn, filterValue가 필요합니다. displayColumn은 선택적입니다.", }, }; res.status(400).json(response); @@ -701,9 +701,12 @@ export async function getTableRecord( } const record = result.data[0]; - const displayValue = record[displayColumn]; + // displayColumn이 "*"이거나 없으면 전체 레코드 반환 + const displayValue = displayColumn && displayColumn !== "*" + ? record[displayColumn] + : record; - logger.info(`레코드 조회 완료: ${displayColumn} = ${displayValue}`); + logger.info(`레코드 조회 완료: ${displayColumn || "*"} = ${typeof displayValue === 'object' ? '[전체 레코드]' : displayValue}`); const response: ApiResponse<{ value: any; record: any }> = { success: true, diff --git a/frontend/app/(main)/screens/[screenId]/page.tsx b/frontend/app/(main)/screens/[screenId]/page.tsx index eb7ecce5..b86facfd 100644 --- a/frontend/app/(main)/screens/[screenId]/page.tsx +++ b/frontend/app/(main)/screens/[screenId]/page.tsx @@ -202,7 +202,89 @@ function ScreenViewPage() { } }, [screenId]); - // 🆕 autoFill 자동 입력 초기화 + // 🆕 메인 테이블 데이터 자동 로드 (단일 레코드 폼) + // 화면의 메인 테이블에서 사용자 회사 코드로 데이터를 조회하여 폼에 자동 채움 + useEffect(() => { + const loadMainTableData = async () => { + if (!screen || !layout || !layout.components || !companyCode) { + return; + } + + const mainTableName = screen.tableName; + if (!mainTableName) { + return; + } + + // 테이블 위젯이 없는 경우에만 자동 로드 (테이블이 있으면 행 선택으로 데이터 로드) + const hasTableWidget = layout.components.some( + (comp: any) => + comp.componentType === "table-list" || + comp.componentType === "v2-table-list" || + comp.widgetType === "table" + ); + + if (hasTableWidget) { + console.log("📋 테이블 위젯이 있어 자동 로드 건너뜀 (행 선택으로 데이터 로드)"); + return; + } + + // 인풋 컴포넌트들 중 메인 테이블의 컬럼을 사용하는 것들 찾기 + const inputComponents = layout.components.filter((comp: any) => { + const compType = comp.componentType || comp.widgetType; + const isInputType = compType?.includes("input") || + compType?.includes("select") || + compType?.includes("textarea") || + compType?.includes("v2-input") || + compType?.includes("v2-select"); + const hasColumnName = !!(comp as any).columnName; + return isInputType && hasColumnName; + }); + + if (inputComponents.length === 0) { + return; + } + + // 메인 테이블에서 현재 회사의 데이터 조회 + try { + const { tableTypeApi } = await import("@/lib/api/screen"); + + // company_code로 필터링하여 단일 레코드 조회 + const result = await tableTypeApi.getTableRecord( + mainTableName, + "company_code", + companyCode, + "*" // 모든 컬럼 + ); + + if (result && result.record) { + console.log("📦 메인 테이블 데이터 자동 로드:", mainTableName, result.record); + + // 각 인풋 컴포넌트에 해당하는 데이터 채우기 + const newFormData: Record = {}; + inputComponents.forEach((comp: any) => { + const columnName = comp.columnName; + if (columnName && result.record[columnName] !== undefined) { + newFormData[columnName] = result.record[columnName]; + } + }); + + if (Object.keys(newFormData).length > 0) { + setFormData((prev) => ({ + ...prev, + ...newFormData, + })); + } + } + } catch (error) { + console.log("메인 테이블 자동 로드 실패 (정상일 수 있음):", error); + // 에러는 무시 - 데이터가 없거나 권한이 없을 수 있음 + } + }; + + loadMainTableData(); + }, [screen, layout, companyCode]); + + // 🆕 개별 autoFill 처리 (메인 테이블과 다른 테이블에서 조회하는 경우) useEffect(() => { const initAutoFill = async () => { if (!layout || !layout.components || !user) { @@ -215,7 +297,7 @@ function ScreenViewPage() { const widget = comp as any; const fieldName = widget.columnName || widget.id; - // autoFill 처리 + // autoFill 처리 (명시적으로 설정된 경우만) if (widget.autoFill?.enabled || (comp as any).autoFill?.enabled) { const autoFillConfig = widget.autoFill || (comp as any).autoFill; const currentValue = formData[fieldName]; diff --git a/frontend/components/screen/panels/TablesPanel.tsx b/frontend/components/screen/panels/TablesPanel.tsx index 480222a6..12dcc19a 100644 --- a/frontend/components/screen/panels/TablesPanel.tsx +++ b/frontend/components/screen/panels/TablesPanel.tsx @@ -431,7 +431,8 @@ export const TablesPanel: React.FC = ({ } return ( -
+ // 엔티티 조인 테이블에 고유 접두사 추가 (메인 테이블과 키 중복 방지) +
{/* 조인 테이블 헤더 */}