1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
"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<ProjectWithContracts[]> {
// 세션에서 도메인 정보 가져오기
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,
})
.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<number, ProjectWithContracts>()
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())
}
|