fix: 발주/입고관리 그룹 편집 시 단건만 저장되던 문제 수정
EditModal.tsx: conditional-container 존재 시 onSave 미전달 로직 수정 ModalRepeaterTableComponent.tsx: groupedData prop 우선 사용하도록 변경
This commit is contained in:
parent
60ae073606
commit
e8bdcbb95c
|
|
@ -309,17 +309,10 @@ export const EditModal: React.FC<EditModalProps> = ({ className }) => {
|
||||||
// 🆕 그룹 데이터 조회 함수
|
// 🆕 그룹 데이터 조회 함수
|
||||||
const loadGroupData = async () => {
|
const loadGroupData = async () => {
|
||||||
if (!modalState.tableName || !modalState.groupByColumns || modalState.groupByColumns.length === 0) {
|
if (!modalState.tableName || !modalState.groupByColumns || modalState.groupByColumns.length === 0) {
|
||||||
// console.warn("테이블명 또는 그룹핑 컬럼이 없습니다.");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// console.log("🔍 그룹 데이터 조회 시작:", {
|
|
||||||
// tableName: modalState.tableName,
|
|
||||||
// groupByColumns: modalState.groupByColumns,
|
|
||||||
// editData: modalState.editData,
|
|
||||||
// });
|
|
||||||
|
|
||||||
// 그룹핑 컬럼 값 추출 (예: order_no = "ORD-20251124-001")
|
// 그룹핑 컬럼 값 추출 (예: order_no = "ORD-20251124-001")
|
||||||
const groupValues: Record<string, any> = {};
|
const groupValues: Record<string, any> = {};
|
||||||
modalState.groupByColumns.forEach((column) => {
|
modalState.groupByColumns.forEach((column) => {
|
||||||
|
|
@ -329,15 +322,9 @@ export const EditModal: React.FC<EditModalProps> = ({ className }) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (Object.keys(groupValues).length === 0) {
|
if (Object.keys(groupValues).length === 0) {
|
||||||
// console.warn("그룹핑 컬럼 값이 없습니다:", modalState.groupByColumns);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// console.log("🔍 그룹 조회 요청:", {
|
|
||||||
// tableName: modalState.tableName,
|
|
||||||
// groupValues,
|
|
||||||
// });
|
|
||||||
|
|
||||||
// 같은 그룹의 모든 레코드 조회 (entityJoinApi 사용)
|
// 같은 그룹의 모든 레코드 조회 (entityJoinApi 사용)
|
||||||
const { entityJoinApi } = await import("@/lib/api/entityJoin");
|
const { entityJoinApi } = await import("@/lib/api/entityJoin");
|
||||||
const response = await entityJoinApi.getTableDataWithJoins(modalState.tableName, {
|
const response = await entityJoinApi.getTableDataWithJoins(modalState.tableName, {
|
||||||
|
|
@ -347,23 +334,19 @@ export const EditModal: React.FC<EditModalProps> = ({ className }) => {
|
||||||
enableEntityJoin: true,
|
enableEntityJoin: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
// console.log("🔍 그룹 조회 응답:", response);
|
|
||||||
|
|
||||||
// entityJoinApi는 배열 또는 { data: [] } 형식으로 반환
|
// entityJoinApi는 배열 또는 { data: [] } 형식으로 반환
|
||||||
const dataArray = Array.isArray(response) ? response : response?.data || [];
|
const dataArray = Array.isArray(response) ? response : response?.data || [];
|
||||||
|
|
||||||
if (dataArray.length > 0) {
|
if (dataArray.length > 0) {
|
||||||
// console.log("✅ 그룹 데이터 조회 성공:", dataArray.length, "건");
|
|
||||||
setGroupData(dataArray);
|
setGroupData(dataArray);
|
||||||
setOriginalGroupData(JSON.parse(JSON.stringify(dataArray))); // Deep copy
|
setOriginalGroupData(JSON.parse(JSON.stringify(dataArray))); // Deep copy
|
||||||
toast.info(`${dataArray.length}개의 관련 품목을 불러왔습니다.`);
|
toast.info(`${dataArray.length}개의 관련 품목을 불러왔습니다.`);
|
||||||
} else {
|
} else {
|
||||||
console.warn("그룹 데이터가 없습니다:", response);
|
|
||||||
setGroupData([modalState.editData]); // 기본값: 선택된 행만
|
setGroupData([modalState.editData]); // 기본값: 선택된 행만
|
||||||
setOriginalGroupData([JSON.parse(JSON.stringify(modalState.editData))]);
|
setOriginalGroupData([JSON.parse(JSON.stringify(modalState.editData))]);
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error("❌ 그룹 데이터 조회 오류:", error);
|
console.error("그룹 데이터 조회 오류:", error);
|
||||||
toast.error("관련 데이터를 불러오는 중 오류가 발생했습니다.");
|
toast.error("관련 데이터를 불러오는 중 오류가 발생했습니다.");
|
||||||
setGroupData([modalState.editData]); // 기본값: 선택된 행만
|
setGroupData([modalState.editData]); // 기본값: 선택된 행만
|
||||||
setOriginalGroupData([JSON.parse(JSON.stringify(modalState.editData))]);
|
setOriginalGroupData([JSON.parse(JSON.stringify(modalState.editData))]);
|
||||||
|
|
@ -1043,17 +1026,18 @@ export const EditModal: React.FC<EditModalProps> = ({ className }) => {
|
||||||
const groupedDataProp = groupData.length > 0 ? groupData : undefined;
|
const groupedDataProp = groupData.length > 0 ? groupData : undefined;
|
||||||
|
|
||||||
// 🆕 UniversalFormModal이 있는지 확인 (자체 저장 로직 사용)
|
// 🆕 UniversalFormModal이 있는지 확인 (자체 저장 로직 사용)
|
||||||
// 최상위 컴포넌트 또는 조건부 컨테이너 내부 화면에 universal-form-modal이 있는지 확인
|
// 최상위 컴포넌트에 universal-form-modal이 있는지 확인
|
||||||
|
// ⚠️ 수정: conditional-container는 제외 (groupData가 있으면 EditModal.handleSave 사용)
|
||||||
const hasUniversalFormModal = screenData.components.some(
|
const hasUniversalFormModal = screenData.components.some(
|
||||||
(c) => {
|
(c) => {
|
||||||
// 최상위에 universal-form-modal이 있는 경우
|
// 최상위에 universal-form-modal이 있는 경우만 자체 저장 로직 사용
|
||||||
if (c.componentType === "universal-form-modal") return true;
|
if (c.componentType === "universal-form-modal") return true;
|
||||||
// 조건부 컨테이너 내부에 universal-form-modal이 있는 경우
|
|
||||||
// (조건부 컨테이너가 있으면 내부 화면에서 universal-form-modal을 사용하는 것으로 가정)
|
|
||||||
if (c.componentType === "conditional-container") return true;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 🆕 그룹 데이터가 있으면 EditModal.handleSave 사용 (일괄 저장)
|
||||||
|
const shouldUseEditModalSave = groupData.length > 0 || !hasUniversalFormModal;
|
||||||
|
|
||||||
// 🔑 첨부파일 컴포넌트가 행(레코드) 단위로 파일을 저장할 수 있도록 tableName 추가
|
// 🔑 첨부파일 컴포넌트가 행(레코드) 단위로 파일을 저장할 수 있도록 tableName 추가
|
||||||
const enrichedFormData = {
|
const enrichedFormData = {
|
||||||
|
|
@ -1095,9 +1079,9 @@ export const EditModal: React.FC<EditModalProps> = ({ className }) => {
|
||||||
id: modalState.screenId!,
|
id: modalState.screenId!,
|
||||||
tableName: screenData.screenInfo?.tableName,
|
tableName: screenData.screenInfo?.tableName,
|
||||||
}}
|
}}
|
||||||
// 🆕 UniversalFormModal이 있으면 onSave 전달 안 함 (자체 저장 로직 사용)
|
// 🆕 그룹 데이터가 있거나 UniversalFormModal이 없으면 EditModal.handleSave 사용
|
||||||
// ModalRepeaterTable만 있으면 기존대로 onSave 전달 (호환성 유지)
|
// groupData가 있으면 일괄 저장을 위해 반드시 EditModal.handleSave 사용
|
||||||
onSave={hasUniversalFormModal ? undefined : handleSave}
|
onSave={shouldUseEditModalSave ? handleSave : undefined}
|
||||||
isInModal={true}
|
isInModal={true}
|
||||||
// 🆕 그룹 데이터를 ModalRepeaterTable에 전달
|
// 🆕 그룹 데이터를 ModalRepeaterTable에 전달
|
||||||
groupedData={groupedDataProp}
|
groupedData={groupedDataProp}
|
||||||
|
|
|
||||||
|
|
@ -180,8 +180,11 @@ export function ModalRepeaterTableComponent({
|
||||||
filterCondition: propFilterCondition,
|
filterCondition: propFilterCondition,
|
||||||
companyCode: propCompanyCode,
|
companyCode: propCompanyCode,
|
||||||
|
|
||||||
|
// 🆕 그룹 데이터 (EditModal에서 전달, 같은 그룹의 여러 품목)
|
||||||
|
groupedData,
|
||||||
|
|
||||||
...props
|
...props
|
||||||
}: ModalRepeaterTableComponentProps) {
|
}: ModalRepeaterTableComponentProps & { groupedData?: Record<string, any>[] }) {
|
||||||
// ✅ config 또는 component.config 또는 개별 prop 우선순위로 병합
|
// ✅ config 또는 component.config 또는 개별 prop 우선순위로 병합
|
||||||
const componentConfig = {
|
const componentConfig = {
|
||||||
...config,
|
...config,
|
||||||
|
|
@ -208,9 +211,16 @@ export function ModalRepeaterTableComponent({
|
||||||
// 모달 필터 설정
|
// 모달 필터 설정
|
||||||
const modalFilters = componentConfig?.modalFilters || [];
|
const modalFilters = componentConfig?.modalFilters || [];
|
||||||
|
|
||||||
// ✅ value는 formData[columnName] 우선, 없으면 prop 사용
|
// ✅ value는 groupedData 우선, 없으면 formData[columnName], 없으면 prop 사용
|
||||||
const columnName = component?.columnName;
|
const columnName = component?.columnName;
|
||||||
const externalValue = (columnName && formData?.[columnName]) || componentConfig?.value || propValue || [];
|
|
||||||
|
// 🆕 groupedData가 전달되면 (EditModal에서 그룹 조회 결과) 우선 사용
|
||||||
|
const externalValue = (() => {
|
||||||
|
if (groupedData && groupedData.length > 0) {
|
||||||
|
return groupedData;
|
||||||
|
}
|
||||||
|
return (columnName && formData?.[columnName]) || componentConfig?.value || propValue || [];
|
||||||
|
})();
|
||||||
|
|
||||||
// 빈 객체 판단 함수 (수정 모달의 실제 데이터는 유지)
|
// 빈 객체 판단 함수 (수정 모달의 실제 데이터는 유지)
|
||||||
const isEmptyRow = (item: any): boolean => {
|
const isEmptyRow = (item: any): boolean => {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue