"use server"; import { revalidateTag, unstable_noStore } from "next/cache"; import db from "@/db/db"; import { unstable_cache } from "@/lib/unstable-cache"; import { filterColumns } from "@/lib/filter-columns"; import { tagClasses } from "@/db/schema/vendorData"; import { asc, desc, ilike, inArray, and, gte, lte, not, or, eq } from "drizzle-orm"; import { GetOcrRowSchema, UpdateOcrRowSchema } from "./validation"; import { OcrRow, ocrRows, users } from "@/db/schema"; import { countOcrRows, selectOcrRows } from "./repository"; import { getServerSession } from "next-auth/next" import { authOptions } from "@/app/api/auth/[...nextauth]/route" async function checkAdminPermission(email: string): Promise { const adminEmails = [ 'worldbest212@naver.com', 'jspwhale@naver.com', 'supervisor@company.com' ]; return adminEmails.includes(email.toLowerCase()); } export async function getOcrRows(input: GetOcrRowSchema) { try { const session = await getServerSession(authOptions); const requesterId = session?.user?.id ? Number(session.user.id) : null; const requesterEmail = session?.user?.email || 'worldbest212@naver.com'; // 로그인하지 않은 경우 빈 결과 반환 if (!requesterId) { return { data: [], pageCount: 0 }; } const offset = (input.page - 1) * input.perPage; const advancedTable = true; // advancedTable 모드면 filterColumns()로 where 절 구성 const advancedWhere = filterColumns({ table: ocrRows, filters: input.filters, joinOperator: input.joinOperator, }); let globalWhere; if (input.search) { const s = `%${input.search}%`; globalWhere = or( ilike(ocrRows.reportNo, s), ilike(ocrRows.identificationNo, s), ilike(ocrRows.tagNo, s), ilike(ocrRows.jointNo, s) ); } const isAdmin = await checkAdminPermission(requesterEmail); // 기본 userId 필터 (항상 적용) const userIdWhere = eq(ocrRows.userId, requesterId); // 모든 조건을 배열에 추가 const conditions = []; if (!isAdmin) { conditions.push(eq(ocrRows.userId, requesterId)); // 일반 사용자만 필터링 } if (advancedWhere) conditions.push(advancedWhere); if (globalWhere) conditions.push(globalWhere); // 모든 조건을 AND로 결합 const finalWhere = conditions.length > 1 ? and(...conditions) : conditions[0]; const orderBy = input.sort.length > 0 ? input.sort.map((item) => item.desc ? desc(ocrRows[item.id]) : asc(ocrRows[item.id]) ) : [asc(ocrRows.createdAt)]; // 트랜잭션 내부에서 Repository 호출 const { data, total } = await db.transaction(async (tx) => { const data = await selectOcrRows(tx, { where: finalWhere, orderBy, offset, limit: input.perPage, }); const total = await countOcrRows(tx, finalWhere); return { data, total }; }); const pageCount = Math.ceil(total / input.perPage); console.log(pageCount); return { data, pageCount }; } catch (err) { console.log(err); // 에러 발생 시 디폴트 return { data: [], pageCount: 0 }; } } interface ModifyOcrRowInput extends UpdateOcrRowSchema { id: string; } export async function modifyOcrRow(input: ModifyOcrRowInput) { try { const session = await getServerSession(authOptions); const requesterId = session?.user?.id ? Number(session.user.id) : null; // 로그인하지 않은 경우 권한 없음 if (!requesterId) { return { data: null, error: "로그인이 필요합니다." }; } const { id, ...updateData } = input; // 빈 문자열을 null로 변환 const cleanedData = Object.fromEntries( Object.entries(updateData).map(([key, value]) => [ key, value === "" ? null : value ]) ); // 자신의 데이터만 수정할 수 있도록 userId 조건 추가 const result = await db .update(ocrRows) .set({ ...cleanedData, // updatedAt: new Date(), // 필요한 경우 추가 }) .where(and( eq(ocrRows.id, id), eq(ocrRows.userId, requesterId) // 자신의 데이터만 수정 가능 )); return { data: null, error: null }; } catch (error) { console.error("OCR 행 업데이트 오류:", error); return { data: null, error: "OCR 행을 업데이트하는 중 오류가 발생했습니다." }; } } export async function getOcrAllRows(): Promise { try { const allRows = await db .select({ // ocrRows의 모든 필드 id: ocrRows.id, tableId: ocrRows.tableId, sessionId: ocrRows.sessionId, rowIndex: ocrRows.rowIndex, reportNo: ocrRows.reportNo, no: ocrRows.no, identificationNo: ocrRows.identificationNo, tagNo: ocrRows.tagNo, jointNo: ocrRows.jointNo, jointType: ocrRows.jointType, weldingDate: ocrRows.weldingDate, confidence: ocrRows.confidence, sourceTable: ocrRows.sourceTable, sourceRow: ocrRows.sourceRow, userId: ocrRows.userId, createdAt: ocrRows.createdAt, // users 테이블의 필드 userName: users.name, userEmail: users.email, }) .from(ocrRows) .leftJoin(users, eq(ocrRows.userId, users.id)) .orderBy(desc(ocrRows.createdAt)) return allRows } catch (error) { console.error("Error fetching all OCR rows:", error) throw new Error("Failed to fetch all OCR data") } }