diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-10-15 12:52:11 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-10-15 12:52:11 +0000 |
| commit | b54f6f03150dd78d86db62201b6386bf14b72394 (patch) | |
| tree | b3092bb34805fdc65eee5282e86a9fb90ba20d6e /lib/cover/service.ts | |
| parent | c1bd1a2f499ee2f0742170021b37dab410983ab7 (diff) | |
(대표님) 커버, 데이터룸, 파일매니저, 담당자할당 등
Diffstat (limited to 'lib/cover/service.ts')
| -rw-r--r-- | lib/cover/service.ts | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/lib/cover/service.ts b/lib/cover/service.ts new file mode 100644 index 00000000..91ea3458 --- /dev/null +++ b/lib/cover/service.ts @@ -0,0 +1,123 @@ +"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 { tagTypeClassFormMappings } from "@/db/schema/vendorData"; +import { asc, desc, ilike, inArray, and, gte, lte, not, or, eq } from "drizzle-orm"; +import { countProjectLists, selectProjectLists } from "./repository"; +import { projects, projectCoverTemplates, generatedCoverPages } from "@/db/schema"; +import { GetProjectListsSchema } from "./validation"; + +export async function getProjectListsForCover(input: GetProjectListsSchema) { + try { + const offset = (input.page - 1) * input.perPage; + const advancedTable = true; + + const advancedWhere = filterColumns({ + table: projects, + filters: input.filters, + joinOperator: input.joinOperator, + }); + + let globalWhere + if (input.search) { + const s = `%${input.search}%` + globalWhere = or( + ilike(projects.name, s), + ilike(projects.code, s), + ilike(projects.type, s), + ) + } + + const finalWhere = and( + eq(projects.type, "plant"), + advancedWhere, + globalWhere + ) + + const where = finalWhere + + const orderBy = + input.sort.length > 0 + ? input.sort.map((item) => + item.desc ? desc(projects[item.id]) : asc(projects[item.id]) + ) + : [asc(projects.createdAt)]; + + // 트랜잭션 내부에서 Repository 호출 + const { data, total } = await db.transaction(async (tx) => { + const projectData = await selectProjectLists(tx, { + where, + orderBy, + offset, + limit: input.perPage, + }); + + // 프로젝트 ID 목록 추출 + const projectIds = projectData.map(p => p.id); + + // 활성 템플릿 정보 조회 + const templates = projectIds.length > 0 + ? await tx + .select() + .from(projectCoverTemplates) + .where( + and( + inArray(projectCoverTemplates.projectId, projectIds), + eq(projectCoverTemplates.isActive, true) + ) + ) + : []; + + // 템플릿 맵 생성 + const templateMap = new Map( + templates.map(t => [t.projectId, t]) + ); + + // 생성된 커버 페이지 조회 (각 템플릿의 최신 것만) + const templateIds = templates.map(t => t.id); + const generatedCovers = templateIds.length > 0 + ? await tx + .select() + .from(generatedCoverPages) + .where(inArray(generatedCoverPages.templateId, templateIds)) + .orderBy(desc(generatedCoverPages.generatedAt)) + : []; + + // 각 템플릿별 최신 생성 커버 맵 생성 + const latestCoverMap = new Map(); + for (const cover of generatedCovers) { + if (!latestCoverMap.has(cover.templateId)) { + latestCoverMap.set(cover.templateId, cover); + } + } + + // 프로젝트에 템플릿 및 생성된 커버 정보 병합 + const data = projectData.map(project => { + const template = templateMap.get(project.id); + const latestCover = template ? latestCoverMap.get(template.id) : null; + + return { + ...project, + coverTemplatePath: template?.filePath || null, + templateVariables: template?.variables || null, + template: template || null, + generatedCover: latestCover || null, + generatedCoverPath: latestCover?.filePath || null, + }; + }); + + const total = await countProjectLists(tx, where); + return { data, total }; + }); + + const pageCount = Math.ceil(total / input.perPage); + + return { data, pageCount }; + } catch (err) { + console.error("❌ getProjectListsForCover 오류:", err); + return { data: [], pageCount: 0 }; + } +}
\ No newline at end of file |
