feat: 수정 모드 UPSERT 기능 구현
- SelectedItemsDetailInput 컴포넌트 수정 모드 지원 - 그룹화된 데이터 UPSERT API 추가 (/api/data/upsert-grouped) - 부모 키 기준으로 기존 레코드 조회 후 INSERT/UPDATE/DELETE - 각 레코드의 모든 필드 조합을 고유 키로 사용 - created_date 보존 (UPDATE 시) - 수정 모드에서 groupByColumns 기준으로 관련 레코드 조회 - 날짜 타입 ISO 형식 자동 감지 및 포맷팅 (YYYY.MM.DD) 주요 변경사항: - backend: dataService.upsertGroupedRecords() 메서드 구현 - backend: dataRoutes POST /api/data/upsert-grouped 엔드포인트 추가 - frontend: ScreenModal에서 groupByColumns 파라미터 전달 - frontend: SelectedItemsDetailInput 수정 모드 로직 추가 - frontend: 날짜 필드 타임존 제거 및 포맷팅 개선
This commit is contained in:
@@ -6,9 +6,28 @@
|
||||
export interface ColumnFilter {
|
||||
id: string;
|
||||
columnName: string;
|
||||
operator: "equals" | "not_equals" | "in" | "not_in" | "contains" | "starts_with" | "ends_with" | "is_null" | "is_not_null";
|
||||
operator:
|
||||
| "equals"
|
||||
| "not_equals"
|
||||
| "in"
|
||||
| "not_in"
|
||||
| "contains"
|
||||
| "starts_with"
|
||||
| "ends_with"
|
||||
| "is_null"
|
||||
| "is_not_null"
|
||||
| "greater_than"
|
||||
| "less_than"
|
||||
| "greater_than_or_equal"
|
||||
| "less_than_or_equal"
|
||||
| "between"
|
||||
| "date_range_contains";
|
||||
value: string | string[];
|
||||
valueType: "static" | "category" | "code";
|
||||
valueType: "static" | "category" | "code" | "dynamic";
|
||||
rangeConfig?: {
|
||||
startColumn: string;
|
||||
endColumn: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface DataFilterConfig {
|
||||
@@ -123,6 +142,71 @@ export function buildDataFilterWhereClause(
|
||||
conditions.push(`${columnRef} IS NOT NULL`);
|
||||
break;
|
||||
|
||||
case "greater_than":
|
||||
conditions.push(`${columnRef} > $${paramIndex}`);
|
||||
params.push(value);
|
||||
paramIndex++;
|
||||
break;
|
||||
|
||||
case "less_than":
|
||||
conditions.push(`${columnRef} < $${paramIndex}`);
|
||||
params.push(value);
|
||||
paramIndex++;
|
||||
break;
|
||||
|
||||
case "greater_than_or_equal":
|
||||
conditions.push(`${columnRef} >= $${paramIndex}`);
|
||||
params.push(value);
|
||||
paramIndex++;
|
||||
break;
|
||||
|
||||
case "less_than_or_equal":
|
||||
conditions.push(`${columnRef} <= $${paramIndex}`);
|
||||
params.push(value);
|
||||
paramIndex++;
|
||||
break;
|
||||
|
||||
case "between":
|
||||
if (Array.isArray(value) && value.length === 2) {
|
||||
conditions.push(`${columnRef} BETWEEN $${paramIndex} AND $${paramIndex + 1}`);
|
||||
params.push(value[0], value[1]);
|
||||
paramIndex += 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case "date_range_contains":
|
||||
// 날짜 범위 포함: start_date <= value <= end_date
|
||||
// filter.rangeConfig = { startColumn: "start_date", endColumn: "end_date" }
|
||||
// NULL 처리:
|
||||
// - start_date만 있고 end_date가 NULL이면: start_date <= value (이후 계속)
|
||||
// - end_date만 있고 start_date가 NULL이면: value <= end_date (이전 계속)
|
||||
// - 둘 다 있으면: start_date <= value <= end_date
|
||||
if (filter.rangeConfig && filter.rangeConfig.startColumn && filter.rangeConfig.endColumn) {
|
||||
const startCol = getColumnRef(filter.rangeConfig.startColumn);
|
||||
const endCol = getColumnRef(filter.rangeConfig.endColumn);
|
||||
|
||||
// value가 "TODAY"면 현재 날짜로 변환
|
||||
const actualValue = filter.valueType === "dynamic" && value === "TODAY"
|
||||
? "CURRENT_DATE"
|
||||
: `$${paramIndex}`;
|
||||
|
||||
if (actualValue === "CURRENT_DATE") {
|
||||
// CURRENT_DATE는 파라미터가 아니므로 직접 SQL에 포함
|
||||
// NULL 처리: (start_date IS NULL OR start_date <= CURRENT_DATE) AND (end_date IS NULL OR end_date >= CURRENT_DATE)
|
||||
conditions.push(
|
||||
`((${startCol} IS NULL OR ${startCol} <= CURRENT_DATE) AND (${endCol} IS NULL OR ${endCol} >= CURRENT_DATE))`
|
||||
);
|
||||
} else {
|
||||
// NULL 처리: (start_date IS NULL OR start_date <= $param) AND (end_date IS NULL OR end_date >= $param)
|
||||
conditions.push(
|
||||
`((${startCol} IS NULL OR ${startCol} <= $${paramIndex}) AND (${endCol} IS NULL OR ${endCol} >= $${paramIndex}))`
|
||||
);
|
||||
params.push(value);
|
||||
paramIndex++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// 알 수 없는 연산자는 무시
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user