summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/forms/services.ts202
1 files changed, 198 insertions, 4 deletions
diff --git a/lib/forms/services.ts b/lib/forms/services.ts
index 2f7caec3..bf4fc3a0 100644
--- a/lib/forms/services.ts
+++ b/lib/forms/services.ts
@@ -163,7 +163,7 @@ export interface EditableFieldsInfo {
}
// TAG별 편집 가능 필드 조회 함수
-async function getEditableFieldsByTag(
+export async function getEditableFieldsByTag(
contractItemId: number,
projectId: number
): Promise<Map<string, string[]>> {
@@ -664,11 +664,21 @@ export async function syncMissingTags(
* data: [{ TAG_NO, ...}, ...] 배열에서 TAG_NO 매칭되는 항목을 업데이트
* 업데이트 후, revalidateTag()로 캐시 무효화.
*/
-type UpdateResponse = {
+export interface UpdateResponse {
success: boolean;
message: string;
- data?: any;
-};
+ data?: {
+ updatedCount?: number;
+ failedCount?: number;
+ updatedTags?: string[];
+ notFoundTags?: string[];
+ updateTimestamp?: string;
+ error?: any;
+ invalidRows?: any[];
+ TAG_NO?: string;
+ updatedFields?: string[];
+ };
+}
export async function updateFormDataInDB(
formCode: string,
@@ -801,6 +811,190 @@ export async function updateFormDataInDB(
};
}
}
+
+export async function updateFormDataBatchInDB(
+ formCode: string,
+ contractItemId: number,
+ newDataArray: Record<string, any>[]
+): Promise<UpdateResponse> {
+ try {
+ // 입력 유효성 검사
+ if (!newDataArray || newDataArray.length === 0) {
+ return {
+ success: false,
+ message: "업데이트할 데이터가 없습니다.",
+ };
+ }
+
+ // TAG_NO 유효성 검사
+ const invalidRows = newDataArray.filter(row => !row.TAG_NO);
+ if (invalidRows.length > 0) {
+ return {
+ success: false,
+ message: `${invalidRows.length}개 행에 TAG_NO가 없습니다.`,
+ data: { invalidRows }
+ };
+ }
+
+ // 1) DB에서 현재 데이터 가져오기
+ const entries = await db
+ .select()
+ .from(formEntries)
+ .where(
+ and(
+ eq(formEntries.formCode, formCode),
+ eq(formEntries.contractItemId, contractItemId)
+ )
+ )
+ .limit(1);
+
+ if (!entries || entries.length === 0) {
+ return {
+ success: false,
+ message: `폼 데이터를 찾을 수 없습니다. (formCode=${formCode}, contractItemId=${contractItemId})`,
+ };
+ }
+
+ const entry = entries[0];
+
+ // 데이터 형식 검증
+ if (!entry.data) {
+ return {
+ success: false,
+ message: "폼 데이터가 없습니다.",
+ };
+ }
+
+ const dataArray = entry.data as Array<Record<string, any>>;
+ if (!Array.isArray(dataArray)) {
+ return {
+ success: false,
+ message: "폼 데이터가 올바른 형식이 아닙니다. 배열 형식이어야 합니다.",
+ };
+ }
+
+ // 2) 모든 변경사항을 한번에 적용
+ const updatedArray = [...dataArray];
+ const updatedTags: string[] = [];
+ const notFoundTags: string[] = [];
+ const updateTimestamp = new Date().toISOString();
+
+ // 각 import row에 대해 업데이트 수행
+ for (const newData of newDataArray) {
+ const TAG_NO = newData.TAG_NO;
+ const idx = updatedArray.findIndex(item => item.TAG_NO === TAG_NO);
+
+ if (idx >= 0) {
+ // 기존 데이터와 병합
+ const oldItem = updatedArray[idx];
+ updatedArray[idx] = {
+ ...oldItem,
+ ...newData,
+ TAG_NO: oldItem.TAG_NO, // TAG_NO는 변경 불가
+ TAG_DESC: oldItem.TAG_DESC, // TAG_DESC도 보존
+ status: "Updated", // Excel import 표시
+ lastUpdated: updateTimestamp // 업데이트 시각 추가
+ };
+ updatedTags.push(TAG_NO);
+ } else {
+ // TAG를 찾을 수 없는 경우
+ notFoundTags.push(TAG_NO);
+ }
+ }
+
+ // 하나도 업데이트할 항목이 없는 경우
+ if (updatedTags.length === 0) {
+ return {
+ success: false,
+ message: `업데이트할 수 있는 TAG를 찾을 수 없습니다. 모든 ${notFoundTags.length}개 TAG가 데이터베이스에 없습니다.`,
+ data: {
+ updatedCount: 0,
+ failedCount: notFoundTags.length,
+ notFoundTags
+ }
+ };
+ }
+
+ // 3) DB에 한 번만 저장
+ try {
+ await db
+ .update(formEntries)
+ .set({
+ data: updatedArray,
+ updatedAt: new Date(),
+ })
+ .where(eq(formEntries.id, entry.id));
+
+ } catch (dbError) {
+ console.error("Database update error:", dbError);
+
+ if (dbError instanceof DrizzleError) {
+ return {
+ success: false,
+ message: `데이터베이스 업데이트 오류: ${dbError.message}`,
+ data: {
+ updatedCount: 0,
+ failedCount: newDataArray.length,
+ error: dbError
+ }
+ };
+ }
+
+ return {
+ success: false,
+ message: "데이터베이스 업데이트 중 오류가 발생했습니다.",
+ data: {
+ updatedCount: 0,
+ failedCount: newDataArray.length
+ }
+ };
+ }
+
+ // 4) 캐시 무효화
+ try {
+ const cacheTag = `form-data-${formCode}-${contractItemId}`;
+ console.log(`Cache invalidated: ${cacheTag}`);
+ revalidateTag(cacheTag);
+ } catch (cacheError) {
+ // 캐시 무효화 실패는 경고만
+ console.warn("Cache revalidation warning:", cacheError);
+ }
+
+ // 5) 성공 응답
+ const message = notFoundTags.length > 0
+ ? `${updatedTags.length}개 항목이 업데이트되었습니다. (${notFoundTags.length}개 TAG는 찾을 수 없음)`
+ : `${updatedTags.length}개 항목이 성공적으로 업데이트되었습니다.`;
+
+ return {
+ success: true,
+ message: message,
+ data: {
+ updatedCount: updatedTags.length,
+ updatedTags,
+ notFoundTags: notFoundTags.length > 0 ? notFoundTags : undefined,
+ failedCount: notFoundTags.length,
+ updateTimestamp
+ },
+ };
+
+ } catch (error) {
+ // 예상치 못한 오류 처리
+ console.error("Unexpected error in updateFormDataBatchInDB:", error);
+
+ return {
+ success: false,
+ message: error instanceof Error
+ ? `예상치 못한 오류가 발생했습니다: ${error.message}`
+ : "알 수 없는 오류가 발생했습니다.",
+ data: {
+ updatedCount: 0,
+ failedCount: newDataArray.length,
+ error: error
+ }
+ };
+ }
+}
+
// FormColumn Type (동일)
export interface FormColumn {
key: string;