summaryrefslogtreecommitdiff
path: root/lib/approval-log
diff options
context:
space:
mode:
authorjoonhoekim <26rote@gmail.com>2025-11-05 19:28:49 +0900
committerjoonhoekim <26rote@gmail.com>2025-11-05 19:28:49 +0900
commite890fbae0c9c273b825ac808aa516de1f87fb218 (patch)
treec2b7bdacd22043a8b4781e9b4c6ea682468abd0f /lib/approval-log
parent35e373fe29a4145d0692ee35ff9e6b0c887df0eb (diff)
(김준회) 실사의뢰 결재 오류 수정, 결재 캐시 백그라운드 컨텍스트에서 패스로 무효화 처리, pm2 ecosystem 설정 변경 (npm 레이어 로그 문제), git 줄바꿈 문제 2건 커밋으로 처리
Diffstat (limited to 'lib/approval-log')
-rw-r--r--lib/approval-log/service.ts160
1 files changed, 91 insertions, 69 deletions
diff --git a/lib/approval-log/service.ts b/lib/approval-log/service.ts
index 5690e0f9..64ae40a2 100644
--- a/lib/approval-log/service.ts
+++ b/lib/approval-log/service.ts
@@ -10,6 +10,7 @@ import {
or,
sql,
} from 'drizzle-orm';
+import { unstable_cache } from 'next/cache';
import db from '@/db/db';
import { approvalLogs } from '@/db/schema/knox/approvals';
@@ -39,85 +40,106 @@ interface ListInput {
sort?: Array<{ id: string; desc: boolean }>;
}
+/**
+ * 결재 로그 목록 조회 (캐시 적용)
+ *
+ * 캐시 태그: 'approval-logs'
+ * 캐시 무효화: /api/revalidate/approval 호출 시
+ */
export async function getApprovalLogList(input: ListInput) {
- const offset = (input.page - 1) * input.perPage;
+ // 캐시 키 생성 (검색/필터/정렬 조건 포함)
+ const cacheKey = `approval-logs-${JSON.stringify(input)}`;
+
+ return unstable_cache(
+ async () => {
+ const offset = (input.page - 1) * input.perPage;
- /* ------------------------------------------------------------------
- * WHERE 절 구성
- * ----------------------------------------------------------------*/
- const advancedWhere = filterColumns({
- table: approvalLogs,
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- filters: (input.filters ?? []) as any,
- joinOperator: (input.joinOperator ?? 'and') as 'and' | 'or',
- });
+ /* ------------------------------------------------------------------
+ * WHERE 절 구성
+ * ----------------------------------------------------------------*/
+ const advancedWhere = filterColumns({
+ table: approvalLogs,
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ filters: (input.filters ?? []) as any,
+ joinOperator: (input.joinOperator ?? 'and') as 'and' | 'or',
+ });
- // 전역 검색 (subject, content, emailAddress, userId)
- let globalWhere;
- if (input.search) {
- const s = `%${input.search}%`;
- globalWhere = or(
- ilike(approvalLogs.subject, s),
- ilike(approvalLogs.content, s),
- ilike(approvalLogs.emailAddress, s),
- ilike(approvalLogs.userId, s),
- );
- }
+ // 전역 검색 (subject, content, emailAddress, userId)
+ let globalWhere;
+ if (input.search) {
+ const s = `%${input.search}%`;
+ globalWhere = or(
+ ilike(approvalLogs.subject, s),
+ ilike(approvalLogs.content, s),
+ ilike(approvalLogs.emailAddress, s),
+ ilike(approvalLogs.userId, s),
+ );
+ }
- let where = eq(approvalLogs.isDeleted, false); // 기본적으로 삭제되지 않은 것만 조회
+ let where = eq(approvalLogs.isDeleted, false); // 기본적으로 삭제되지 않은 것만 조회
- if (advancedWhere && globalWhere) {
- where = and(where, advancedWhere, globalWhere);
- } else if (advancedWhere) {
- where = and(where, advancedWhere);
- } else if (globalWhere) {
- where = and(where, globalWhere);
- }
+ if (advancedWhere && globalWhere) {
+ const combined = and(where, advancedWhere, globalWhere);
+ if (combined) where = combined;
+ } else if (advancedWhere) {
+ const combined = and(where, advancedWhere);
+ if (combined) where = combined;
+ } else if (globalWhere) {
+ const combined = and(where, globalWhere);
+ if (combined) where = combined;
+ }
- /* ------------------------------------------------------------------
- * ORDER BY 절 구성
- * ----------------------------------------------------------------*/
- let orderBy;
- try {
- orderBy = input.sort && input.sort.length > 0
- ? input.sort
- .map((item) => {
- if (!item || !item.id || typeof item.id !== 'string') return null;
- if (!(item.id in approvalLogs)) return null;
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- const col = approvalLogs[item.id];
- return item.desc ? desc(col) : asc(col);
- })
- .filter((v): v is Exclude<typeof v, null> => v !== null)
- : [desc(approvalLogs.createdAt)];
- } catch {
- orderBy = [desc(approvalLogs.createdAt)];
- }
+ /* ------------------------------------------------------------------
+ * ORDER BY 절 구성
+ * ----------------------------------------------------------------*/
+ let orderBy;
+ try {
+ orderBy = input.sort && input.sort.length > 0
+ ? input.sort
+ .map((item) => {
+ if (!item || !item.id || typeof item.id !== 'string') return null;
+ if (!(item.id in approvalLogs)) return null;
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ const col = approvalLogs[item.id];
+ return item.desc ? desc(col) : asc(col);
+ })
+ .filter((v): v is Exclude<typeof v, null> => v !== null)
+ : [desc(approvalLogs.createdAt)];
+ } catch {
+ orderBy = [desc(approvalLogs.createdAt)];
+ }
- /* ------------------------------------------------------------------
- * 데이터 조회
- * ----------------------------------------------------------------*/
- const data = await db
- .select()
- .from(approvalLogs)
- .where(where)
- .orderBy(...orderBy)
- .limit(input.perPage)
- .offset(offset);
+ /* ------------------------------------------------------------------
+ * 데이터 조회
+ * ----------------------------------------------------------------*/
+ const data = await db
+ .select()
+ .from(approvalLogs)
+ .where(where)
+ .orderBy(...orderBy)
+ .limit(input.perPage)
+ .offset(offset);
- const totalResult = await db
- .select({ count: count() })
- .from(approvalLogs)
- .where(where);
+ const totalResult = await db
+ .select({ count: count() })
+ .from(approvalLogs)
+ .where(where);
- const total = totalResult[0]?.count ?? 0;
- const pageCount = Math.ceil(total / input.perPage);
+ const total = totalResult[0]?.count ?? 0;
+ const pageCount = Math.ceil(total / input.perPage);
- return {
- data,
- pageCount,
- };
+ return {
+ data,
+ pageCount,
+ };
+ },
+ [cacheKey],
+ {
+ tags: ['approval-logs'], // 캐시 태그
+ revalidate: 60, // 60초마다 자동 재검증 (폴백)
+ }
+ )();
}
// ----------------------------------------------------