refactor: Remove password masking functionality from data services

- Deleted the `maskPasswordColumns` function from `dataService.ts` and its usage in data responses, simplifying the data handling process.
- Removed password handling logic from `DynamicFormService`, ensuring that password management is streamlined and centralized.
- Updated related components to reflect the removal of password masking, improving code clarity and maintainability.
This commit is contained in:
DDD1542
2026-02-13 11:51:59 +09:00
parent 95f668d40d
commit a466e523d9
6 changed files with 147 additions and 219 deletions

View File

@@ -67,6 +67,10 @@ export const SelectedItemsDetailInputComponent: React.FC<SelectedItemsDetailInpu
[config, component.config, component.id],
);
// 소스 테이블의 키 필드명 (기본값: "item_id" → 하위 호환)
// 예: item_info 기반이면 "item_id", customer_mng 기반이면 "customer_id"
const sourceKeyField = componentConfig.sourceKeyField || "item_id";
// 🆕 dataSourceId 우선순위: URL 파라미터 > 컴포넌트 설정 > component.id
const dataSourceId = useMemo(
() => urlDataSourceId || componentConfig.dataSourceId || component.id || "default",
@@ -228,7 +232,21 @@ export const SelectedItemsDetailInputComponent: React.FC<SelectedItemsDetailInpu
const editTableName = new URLSearchParams(window.location.search).get("tableName");
const allTableData: Record<string, Record<string, any>[]> = {};
if (firstRecord.customer_id && firstRecord.item_id) {
// 동적 필터 구성: parentDataMapping의 targetField + sourceKeyField
const editFilters: Record<string, any> = {};
const parentMappings = componentConfig.parentDataMapping || [];
parentMappings.forEach((mapping: any) => {
if (mapping.targetField && firstRecord[mapping.targetField]) {
editFilters[mapping.targetField] = firstRecord[mapping.targetField];
}
});
if (firstRecord[sourceKeyField]) {
editFilters[sourceKeyField] = firstRecord[sourceKeyField];
}
const hasRequiredKeys = Object.keys(editFilters).length >= 2;
if (hasRequiredKeys) {
try {
const { dataApi } = await import("@/lib/api/data");
// 모든 sourceTable의 데이터를 API로 전체 로드 (중복 테이블 제거)
@@ -238,10 +256,7 @@ export const SelectedItemsDetailInputComponent: React.FC<SelectedItemsDetailInpu
for (const table of allTables) {
const response = await dataApi.getTableData(table, {
filters: {
customer_id: firstRecord.customer_id,
item_id: firstRecord.item_id,
},
filters: editFilters,
sortBy: "created_date",
sortOrder: "desc",
});
@@ -350,8 +365,8 @@ export const SelectedItemsDetailInputComponent: React.FC<SelectedItemsDetailInpu
}
const newItem: ItemData = {
// 수정 모드: item_id를 우선 사용 (id는 가격레코드의 PK일 수 있음)
id: String(firstRecord.item_id || firstRecord.id || "edit"),
// 수정 모드: sourceKeyField를 우선 사용 (id는 가격레코드의 PK일 수 있음)
id: String(firstRecord[sourceKeyField] || firstRecord.id || "edit"),
originalData: firstRecord,
fieldGroups: mainFieldGroups,
};
@@ -635,39 +650,39 @@ export const SelectedItemsDetailInputComponent: React.FC<SelectedItemsDetailInpu
const mainGroups = groupsByTable.get(mainTable) || [];
for (const item of items) {
// item_id 추출: originalData.item_id를 최우선 사용
// sourceKeyField 값 추출 (예: item_id 또는 customer_id)
// (수정 모드에서 autoFillFrom:"id"가 가격 레코드 PK를 반환하는 문제 방지)
let itemId: string | null = null;
let sourceKeyValue: string | null = null;
// 1순위: originalData에 item_id가 직접 있으면 사용 (수정 모드에서 정확한 값)
if (item.originalData && item.originalData.item_id) {
itemId = item.originalData.item_id;
// 1순위: originalData에 sourceKeyField가 직접 있으면 사용 (수정 모드에서 정확한 값)
if (item.originalData && item.originalData[sourceKeyField]) {
sourceKeyValue = item.originalData[sourceKeyField];
}
// 2순위: autoFillFrom 로직 (신규 등록 모드에서 사용)
if (!itemId) {
if (!sourceKeyValue) {
mainGroups.forEach((group) => {
const groupFields = additionalFields.filter((f) => f.groupId === group.id);
groupFields.forEach((field) => {
if (field.name === "item_id" && field.autoFillFrom && item.originalData) {
itemId = item.originalData[field.autoFillFrom] || null;
if (field.name === sourceKeyField && field.autoFillFrom && item.originalData) {
sourceKeyValue = item.originalData[field.autoFillFrom] || null;
}
});
});
}
// 3순위: fallback (최후의 수단)
if (!itemId && item.originalData) {
itemId = item.originalData.id || null;
if (!sourceKeyValue && item.originalData) {
sourceKeyValue = item.originalData.id || null;
}
if (!itemId) {
console.error("❌ [2단계 저장] item_id를 찾을 수 없음:", item);
if (!sourceKeyValue) {
console.error(`❌ [2단계 저장] ${sourceKeyField}를 찾을 수 없음:`, item);
continue;
}
// upsert 공통 parentKeys: customer_id + item_id (정확한 매칭)
const itemParentKeys = { ...parentKeys, item_id: itemId };
// upsert 공통 parentKeys: parentMapping 키 + sourceKeyField (정확한 매칭)
const itemParentKeys = { ...parentKeys, [sourceKeyField]: sourceKeyValue };
// === Step 1: 메인 테이블(customer_item_mapping) 저장 ===
// 여러 개의 매핑 레코드 지원 (거래처 품번/품명이 다중일 수 있음)
@@ -688,11 +703,11 @@ export const SelectedItemsDetailInputComponent: React.FC<SelectedItemsDetailInpu
if (entry._dbRecordId) {
record.id = entry._dbRecordId;
}
// item_id는 정확한 itemId 변수 사용 (autoFillFrom:"id" 오작동 방지)
record.item_id = itemId;
// sourceKeyField는 정확한 sourceKeyValue 변수 사용 (autoFillFrom:"id" 오작동 방지)
record[sourceKeyField] = sourceKeyValue;
// 나머지 autoFillFrom 필드 처리
groupFields.forEach((field) => {
if (field.name !== "item_id" && field.autoFillFrom && item.originalData) {
if (field.name !== sourceKeyField && field.autoFillFrom && item.originalData) {
const value = item.originalData[field.autoFillFrom];
if (value !== undefined && value !== null && !record[field.name]) {
record[field.name] = value;
@@ -1700,7 +1715,7 @@ export const SelectedItemsDetailInputComponent: React.FC<SelectedItemsDetailInpu
// 디자인 모드: 샘플 데이터로 미리보기 표시
if (isDesignMode) {
const sampleDisplayCols = componentConfig.displayColumns || [];
const sampleFields = (componentConfig.additionalFields || []).filter(f => f.name !== "item_id" && f.width !== "0px");
const sampleFields = (componentConfig.additionalFields || []).filter(f => f.name !== sourceKeyField && f.width !== "0px");
const sampleGroups = componentConfig.fieldGroups || [{ id: "default", title: "입력 정보", order: 0 }];
const gridCols = sampleGroups.length === 1 ? "grid-cols-1" : "grid-cols-2";