"use server"; import db from "@/db/db" import { items } from "@/db/schema/items" import { projects } from "@/db/schema/projects" import { eq, and } from "drizzle-orm" import { contractItems, contracts } from "@/db/schema/contract"; import { getServerSession } from "next-auth"; import { authOptions } from "@/app/api/auth/[...nextauth]/route"; export interface ProjectWithContracts { projectId: number projectCode: string projectName: string projectType: string contracts: { contractId: number contractNo: string contractName: string packages: { itemId: number // contract_items.id itemName: string }[] }[] } export async function getVendorProjectsAndContracts( vendorId?: number, projectType?: "ship" | "plant" ): Promise { // 세션에서 도메인 정보 가져오기 const session = await getServerSession(authOptions) // EVCP 도메인일 때만 전체 조회 const isEvcpDomain = session?.user?.domain === "evcp" // where 조건들을 배열로 관리 // eslint-disable-next-line @typescript-eslint/no-explicit-any const whereConditions: any[] = [] // vendorId 조건 추가 if (!isEvcpDomain && vendorId) { whereConditions.push(eq(contracts.vendorId, vendorId)) } // projectType 조건 추가 if (projectType) { whereConditions.push(eq(projects.type, projectType)) } const query = db .select({ projectId: projects.id, projectCode: projects.code, projectName: projects.name, projectType: projects.type, contractId: contracts.id, contractNo: contracts.contractNo, contractName: contracts.contractName, itemId: contractItems.id, itemName: items.itemName, packageCode: items.packageCode, packageName: items.description, }) .from(contracts) .innerJoin(projects, eq(contracts.projectId, projects.id)) .innerJoin(contractItems, eq(contractItems.contractId, contracts.id)) .innerJoin(items, eq(contractItems.itemId, items.id)) // 조건이 있으면 where 절 추가 if (whereConditions.length > 0) { query.where(and(...whereConditions)) } const rows = await query const projectMap = new Map() for (const row of rows) { // 1) 프로젝트 그룹 찾기 let projectEntry = projectMap.get(row.projectId) if (!projectEntry) { // 새 프로젝트 항목 생성 projectEntry = { projectId: row.projectId, projectCode: row.projectCode, projectName: row.projectName, projectType: row.projectType, contracts: [], } projectMap.set(row.projectId, projectEntry) } // 2) 프로젝트 안에서 계약(contractId) 찾기 let contractEntry = projectEntry.contracts.find( (c) => c.contractId === row.contractId ) if (!contractEntry) { // 새 계약 항목 contractEntry = { contractId: row.contractId, contractNo: row.contractNo, contractName: row.contractName, packages: [], } projectEntry.contracts.push(contractEntry) } // 3) 계약의 packages 배열에 아이템 추가 (중복 체크) // itemName이 같은 항목이 이미 존재하는지 확인 const existingItem = contractEntry.packages.find( (pkg) => pkg.itemName === row.itemName ) // 같은 itemName이 없는 경우에만 추가 if (!existingItem) { contractEntry.packages.push({ itemId: row.itemId, itemName: row.itemName, }) } } return Array.from(projectMap.values()) } interface ProjectWithPackages { projectId: number projectCode: string projectName: string projectType: "ship" | "plant" packages: { packageCode: string packageName: string | null }[] } export async function getVendorProjectsWithPackages( vendorId?: number, projectType?: "ship" | "plant" ): Promise { // 세션에서 도메인 정보 가져오기 const session = await getServerSession(authOptions) // EVCP 도메인일 때만 전체 조회 const isEvcpDomain = session?.user?.domain === "evcp" // where 조건들을 배열로 관리 // eslint-disable-next-line @typescript-eslint/no-explicit-any const whereConditions: any[] = [] // vendorId 조건 추가 if (!isEvcpDomain && vendorId) { whereConditions.push(eq(contracts.vendorId, vendorId)) } // projectType 조건 추가 if (projectType) { whereConditions.push(eq(projects.type, projectType)) } const query = db .select({ projectId: projects.id, projectCode: projects.code, projectName: projects.name, projectType: projects.type, packageCode: items.packageCode, packageName: items.description, }) .from(contracts) .innerJoin(projects, eq(contracts.projectId, projects.id)) .innerJoin(contractItems, eq(contractItems.contractId, contracts.id)) .innerJoin(items, eq(contractItems.itemId, items.id)) // 조건이 있으면 where 절 추가 if (whereConditions.length > 0) { query.where(and(...whereConditions)) } const rows = await query const projectMap = new Map() for (const row of rows) { // 1) 프로젝트 그룹 찾기 let projectEntry = projectMap.get(row.projectId) if (!projectEntry) { // 새 프로젝트 항목 생성 projectEntry = { projectId: row.projectId, projectCode: row.projectCode, projectName: row.projectName, projectType: row.projectType, packages: [], } projectMap.set(row.projectId, projectEntry) } // 2) 프로젝트의 packages 배열에 패키지 추가 (중복 체크) // packageCode가 같은 항목이 이미 존재하는지 확인 const existingPackage = projectEntry.packages.find( (pkg) => pkg.packageCode === row.packageCode ) // 같은 packageCode가 없는 경우에만 추가 if (!existingPackage) { projectEntry.packages.push({ packageCode: row.packageCode, packageName: row.packageName, }) } } return Array.from(projectMap.values()) }