summaryrefslogtreecommitdiff
path: root/lib/vendor-document-list
diff options
context:
space:
mode:
Diffstat (limited to 'lib/vendor-document-list')
-rw-r--r--lib/vendor-document-list/enhanced-document-service.ts52
-rw-r--r--lib/vendor-document-list/import-service.ts31
-rw-r--r--lib/vendor-document-list/plant/document-stage-validations.ts13
-rw-r--r--lib/vendor-document-list/plant/document-stages-columns.tsx32
-rw-r--r--lib/vendor-document-list/plant/document-stages-service.ts81
-rw-r--r--lib/vendor-document-list/repository.ts6
6 files changed, 109 insertions, 106 deletions
diff --git a/lib/vendor-document-list/enhanced-document-service.ts b/lib/vendor-document-list/enhanced-document-service.ts
index d2cec15d..05ace8d5 100644
--- a/lib/vendor-document-list/enhanced-document-service.ts
+++ b/lib/vendor-document-list/enhanced-document-service.ts
@@ -4,7 +4,7 @@
import { revalidatePath, unstable_cache } from "next/cache"
import { and, asc, desc, eq, ilike, or, count, avg, inArray, sql } from "drizzle-orm"
import db from "@/db/db"
-import { documentAttachments, documentStagesOnlyView, documents, enhancedDocumentsView, issueStages, revisions, simplifiedDocumentsView, type EnhancedDocumentsView } from "@/db/schema/vendorDocu"
+import { StageDocumentsView, documentAttachments, documentStagesOnlyView, documents, enhancedDocumentsView, issueStages, revisions, simplifiedDocumentsView, type EnhancedDocumentsView } from "@/db/schema/vendorDocu"
import { filterColumns } from "@/lib/filter-columns"
import type {
CreateDocumentInput,
@@ -42,6 +42,22 @@ export interface GetEnhancedDocumentsSchema {
}>
}
+export interface GetDocumentsSchema {
+ page: number
+ perPage: number
+ search?: string
+ filters?: Array<{
+ id: string
+ value: string | string[]
+ operator?: "eq" | "ne" | "like" | "ilike" | "in" | "notin" | "lt" | "lte" | "gt" | "gte"
+ }>
+ joinOperator?: "and" | "or"
+ sort?: Array<{
+ id: keyof StageDocumentsView
+ desc: boolean
+ }>
+}
+
// Repository 함수들
export async function selectEnhancedDocuments(
tx: any,
@@ -1024,19 +1040,7 @@ export async function getDocumentDetails(documentId: number) {
if (!companyId) {
return { data: [], pageCount: 0, total: 0, drawingKind: null, vendorInfo: null }
}
-
- // 2. 해당 벤더의 모든 계약 ID들 조회
- const vendorContracts = await db
- .select({ projectId: contracts.projectId, contractId:contracts.id })
- .from(contracts)
- .where(eq(contracts.vendorId, companyId))
-
- const contractIds = vendorContracts.map(c => c.contractId)
-
- if (contractIds.length === 0) {
- return { data: [], pageCount: 0, total: 0, drawingKind: null, vendorInfo: null }
- }
-
+
// 3. 고급 필터 처리
const advancedWhere = filterColumns({
table: simplifiedDocumentsView,
@@ -1057,7 +1061,7 @@ export async function getDocumentDetails(documentId: number) {
// 5. 최종 WHERE 조건 (계약 ID들로 필터링)
const finalWhere = and(
- inArray(simplifiedDocumentsView.contractId, contractIds),
+ eq(simplifiedDocumentsView.vendorId, Number(companyId)),
advancedWhere,
globalWhere,
)
@@ -1133,32 +1137,18 @@ export async function getDocumentDetails(documentId: number) {
}
const companyId = session?.user?.companyId;
-
if (!companyId) {
return { stats: {}, totalDocuments: 0, primaryDrawingKind: null }
}
-
- // 해당 벤더의 계약 ID들 조회
- const vendorContracts = await db
- .select({ id: contracts.id })
- .from(contracts)
- .where(eq(contracts.vendorId, companyId))
-
- const contractIds = vendorContracts.map(c => c.id)
-
- if (contractIds.length === 0) {
- return { stats: {}, totalDocuments: 0, primaryDrawingKind: null }
- }
-
+
// DrawingKind별 통계 조회
const documents = await db
.select({
drawingKind: simplifiedDocumentsView.drawingKind,
- contractId: simplifiedDocumentsView.contractId,
})
.from(simplifiedDocumentsView)
- .where(inArray(simplifiedDocumentsView.contractId, contractIds))
+ .where(eq(simplifiedDocumentsView.vendorId, Number(companyId)))
// 통계 계산
const stats = documents.reduce((acc, doc) => {
diff --git a/lib/vendor-document-list/import-service.ts b/lib/vendor-document-list/import-service.ts
index 84e4263c..216e373e 100644
--- a/lib/vendor-document-list/import-service.ts
+++ b/lib/vendor-document-list/import-service.ts
@@ -9,6 +9,8 @@ import { v4 as uuidv4 } from "uuid"
import { extname } from "path"
import * as crypto from "crypto"
import { debugError, debugWarn, debugSuccess, debugProcess } from "@/lib/debug-utils"
+import { getServerSession } from "next-auth/next"
+import { authOptions } from "@/app/api/auth/[...nextauth]/route"
export interface ImportResult {
success: boolean
@@ -155,11 +157,11 @@ class ImportService {
throw new Error(`Project code or vendor code not found for contract ${projectId}`)
}
- debugLog(`계약 정보 조회 완료`, {
- projectId,
- projectCode: contractInfo.projectCode,
- vendorCode: contractInfo.vendorCode
- })
+ // debugLog(`계약 정보 조회 완료`, {
+ // projectId,
+ // projectCode: contractInfo.projectCode,
+ // vendorCode: contractInfo.vendorCode
+ // })
// 2. 각 drawingKind별로 데이터 조회
const allDocuments: DOLCEDocument[] = []
@@ -324,6 +326,13 @@ class ImportService {
projectCode: string;
vendorCode: string;
} | null> {
+
+ const session = await getServerSession(authOptions)
+ if (!session?.user?.companyId) {
+ throw new Error("인증이 필요합니다.")
+ }
+
+
const [result] = await db
.select({
projectCode: projects.code,
@@ -332,7 +341,7 @@ class ImportService {
.from(contracts)
.innerJoin(projects, eq(contracts.projectId, projects.id))
.innerJoin(vendors, eq(contracts.vendorId, vendors.id))
- .where(eq(contracts.projectId, projectId))
+ .where(and(eq(contracts.projectId, projectId),eq(contracts.vendorId, Number(session.user.companyId))))
.limit(1)
return result?.projectCode && result?.vendorCode
@@ -633,6 +642,15 @@ class ImportService {
dolceDoc: DOLCEDocument,
sourceSystem: string
): Promise<'NEW' | 'UPDATED' | 'SKIPPED'> {
+
+ const session = await getServerSession(authOptions)
+ if (!session?.user?.companyId) {
+ throw new Error("인증이 필요합니다.")
+ }
+
+ const vendorId = Number(session.user.companyId)
+
+
// 기존 문서 조회 (문서 번호로)
const existingDoc = await db
.select()
@@ -646,6 +664,7 @@ class ImportService {
// DOLCE 문서를 DB 스키마에 맞게 변환
const documentData = {
projectId,
+ vendorId,
docNumber: dolceDoc.DrawingNo,
title: dolceDoc.DrawingName,
status: 'ACTIVE',
diff --git a/lib/vendor-document-list/plant/document-stage-validations.ts b/lib/vendor-document-list/plant/document-stage-validations.ts
index 037293e3..434459a7 100644
--- a/lib/vendor-document-list/plant/document-stage-validations.ts
+++ b/lib/vendor-document-list/plant/document-stage-validations.ts
@@ -8,7 +8,7 @@ import {
parseAsStringEnum,
} from "nuqs/server"
import { getFiltersStateParser, getSortingStateParser } from "@/lib/parsers"
-import { DocumentStagesOnlyView } from "@/db/schema"
+import { DocumentStagesOnlyView, StageDocumentsView } from "@/db/schema"
// =============================================================================
// 1. 문서 관련 스키마들
@@ -153,7 +153,7 @@ export const searchParamsSchema = z.object({
export const documentStageSearchParamsCache = createSearchParamsCache({
page: parseAsInteger.withDefault(1),
perPage: parseAsInteger.withDefault(10),
- sort: getSortingStateParser<DocumentStagesOnlyView>().withDefault([
+ sort: getSortingStateParser<StageDocumentsView>().withDefault([
{ id: "createdAt", desc: true },
]),
@@ -161,15 +161,6 @@ export const documentStageSearchParamsCache = createSearchParamsCache({
filters: getFiltersStateParser().withDefault([]),
joinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"),
search: parseAsString.withDefault(""),
-
- // 문서 스테이지 전용 필터들
- drawingKind: parseAsStringEnum(["all", "B3", "B4", "B5"]).withDefault("all"),
- stageStatus: parseAsStringEnum(["all", "PLANNED", "IN_PROGRESS", "SUBMITTED", "APPROVED", "REJECTED", "COMPLETED"]).withDefault("all"),
- priority: parseAsStringEnum(["all", "HIGH", "MEDIUM", "LOW"]).withDefault("all"),
- isOverdue: parseAsStringEnum(["all", "true", "false"]).withDefault("all"),
- assignee: parseAsString.withDefault(""),
- dateFrom: parseAsString.withDefault(""),
- dateTo: parseAsString.withDefault(""),
})
// =============================================================================
diff --git a/lib/vendor-document-list/plant/document-stages-columns.tsx b/lib/vendor-document-list/plant/document-stages-columns.tsx
index 7456c2aa..742b8a8a 100644
--- a/lib/vendor-document-list/plant/document-stages-columns.tsx
+++ b/lib/vendor-document-list/plant/document-stages-columns.tsx
@@ -272,22 +272,22 @@ export function getDocumentStagesColumns({
),
cell: ({ row }) => {
const doc = row.original
- if (!doc.currentStageName) {
- return (
- <Button
- size="sm"
- variant="outline"
- onClick={(e) => {
- e.stopPropagation()
- setRowAction({ row, type: "add_stage" })
- }}
- className="h-6 text-xs"
- >
- <Plus className="w-3 h-3 mr-1" />
- Add stage
- </Button>
- )
- }
+ // if (!doc.currentStageName) {
+ // return (
+ // <Button
+ // size="sm"
+ // variant="outline"
+ // onClick={(e) => {
+ // e.stopPropagation()
+ // setRowAction({ row, type: "add_stage" })
+ // }}
+ // className="h-6 text-xs"
+ // >
+ // <Plus className="w-3 h-3 mr-1" />
+ // Add stage
+ // </Button>
+ // )
+ // }
return (
<div className="flex items-center gap-2">
diff --git a/lib/vendor-document-list/plant/document-stages-service.ts b/lib/vendor-document-list/plant/document-stages-service.ts
index 1e60a062..c6a891c8 100644
--- a/lib/vendor-document-list/plant/document-stages-service.ts
+++ b/lib/vendor-document-list/plant/document-stages-service.ts
@@ -4,7 +4,7 @@
import { revalidatePath, revalidateTag } from "next/cache"
import { redirect } from "next/navigation"
import db from "@/db/db"
-import { codeGroups, comboBoxSettings, contracts, documentClassOptions, documentClasses, documentNumberTypeConfigs, documentNumberTypes, documentStagesOnlyView, documents, issueStages } from "@/db/schema"
+import { codeGroups, comboBoxSettings, contracts, documentClassOptions, documentClasses, documentNumberTypeConfigs, documentNumberTypes, documentStagesOnlyView, documents, issueStages, stageDocuments, stageDocumentsView, stageIssueStages } from "@/db/schema"
import { and, eq, asc, desc, sql, inArray, max, ne, or, ilike } from "drizzle-orm"
import {
createDocumentSchema,
@@ -28,7 +28,7 @@ import {
} from "./document-stage-validations"
import { unstable_noStore as noStore } from "next/cache"
import { filterColumns } from "@/lib/filter-columns"
-import { GetEnhancedDocumentsSchema } from "../enhanced-document-service"
+import { GetEnhancedDocumentsSchema, GetDocumentsSchema } from "../enhanced-document-service"
import { countDocumentStagesOnly, selectDocumentStagesOnly } from "../repository"
interface UpdateDocumentData {
@@ -914,21 +914,20 @@ export async function createDocument(data: CreateDocumentData) {
columns: {
id: true,
projectId: true,
+ vendorId: true,
},
})
if (!contract) {
return { success: false, error: "유효하지 않은 계약(ID)입니다." }
}
- const { projectId } = contract
+ const { projectId, vendorId } = contract
/* ──────────────────────────────── 1. 문서번호 타입 설정 조회 ─────────────────────────────── */
const configsResult = await getDocumentNumberTypeConfigs(
data.documentNumberTypeId
)
- console.log(configsResult, "configsResult")
-
if (!configsResult.success) {
return { success: false, error: configsResult.error }
}
@@ -937,7 +936,8 @@ export async function createDocument(data: CreateDocumentData) {
/* ──────────────────────────────── 3. 문서 레코드 삽입 ─────────────────────────────── */
const insertData = {
// 필수
- projectId, // ★ 새로 추가
+ projectId,
+ vendorId, // ★ 새로 추가
contractId: data.contractId,
docNumber: data.docNumber,
title: data.title,
@@ -946,20 +946,19 @@ export async function createDocument(data: CreateDocumentData) {
updatedAt: new Date(),
// 선택
- pic: data.pic ?? null,
- vendorDocNumber: data.vendorDocNumber ?? null,
+ vendorDocNumber: data.vendorDocNumber === null || data.vendorDocNumber ==='' ? null: data.vendorDocNumber ,
}
const [document] = await db
- .insert(documents)
+ .insert(stageDocuments)
.values(insertData)
.onConflictDoNothing({
// ★ 유니크 키가 projectId 기반이라면 target 도 같이 변경
target: [
- documents.projectId,
- documents.docNumber,
- documents.status,
+ stageDocuments.projectId,
+ stageDocuments.docNumber,
+ stageDocuments.status,
],
})
.returning()
@@ -975,22 +974,27 @@ export async function createDocument(data: CreateDocumentData) {
const stageOptionsResult = await getDocumentClassOptions(
data.documentClassId
)
+
+
+ console.log(data.documentClassId,"documentClassId")
+ console.log(stageOptionsResult.data)
+
if (stageOptionsResult.success && stageOptionsResult.data.length > 0) {
const now = new Date()
const stageInserts = stageOptionsResult.data.map((opt, idx) => ({
documentId: document.id,
- stageName: opt.optionValue,
+ stageName: opt.optionCode,
stageOrder: opt.sortOrder ?? idx + 1,
stageStatus: "PLANNED" as const,
planDate: data.planDates[opt.id] ?? null,
createdAt: now,
updatedAt: now,
}))
- await db.insert(issueStages).values(stageInserts)
+ await db.insert(stageIssueStages).values(stageInserts)
}
/* ──────────────────────────────── 5. 캐시 무효화 및 응답 ─────────────────────────────── */
- revalidatePath(`/contracts/${data.contractId}/documents`)
+ revalidatePath(`/partners/${data.contractId}/document-list-only`)
return {
success: true,
@@ -1004,7 +1008,7 @@ export async function createDocument(data: CreateDocumentData) {
export async function getDocumentStagesOnly(
- input: GetEnhancedDocumentsSchema,
+ input: GetDocumentsSchema,
contractId: number
) {
try {
@@ -1012,7 +1016,7 @@ export async function getDocumentStagesOnly(
// 고급 필터 처리
const advancedWhere = filterColumns({
- table: documentStagesOnlyView,
+ table: stageDocumentsView,
filters: input.filters || [],
joinOperator: input.joinOperator || "and",
})
@@ -1022,12 +1026,11 @@ export async function getDocumentStagesOnly(
if (input.search) {
const searchTerm = `%${input.search}%`
globalWhere = or(
- ilike(documentStagesOnlyView.title, searchTerm),
- ilike(documentStagesOnlyView.docNumber, searchTerm),
- ilike(documentStagesOnlyView.currentStageName, searchTerm),
- ilike(documentStagesOnlyView.currentStageAssigneeName, searchTerm),
- ilike(documentStagesOnlyView.vendorDocNumber, searchTerm),
- ilike(documentStagesOnlyView.pic, searchTerm)
+ ilike(stageDocumentsView.title, searchTerm),
+ ilike(stageDocumentsView.docNumber, searchTerm),
+ ilike(stageDocumentsView.currentStageName, searchTerm),
+ ilike(stageDocumentsView.currentStageAssigneeName, searchTerm),
+ ilike(stageDocumentsView.vendorDocNumber, searchTerm),
)
}
@@ -1035,17 +1038,17 @@ export async function getDocumentStagesOnly(
const finalWhere = and(
advancedWhere,
globalWhere,
- eq(documentStagesOnlyView.contractId, contractId)
+ eq(stageDocumentsView.contractId, contractId)
)
// 정렬 처리
const orderBy = input.sort && input.sort.length > 0
? input.sort.map((item) =>
item.desc
- ? desc(documentStagesOnlyView[item.id])
- : asc(documentStagesOnlyView[item.id])
+ ? desc(stageDocumentsView[item.id])
+ : asc(stageDocumentsView[item.id])
)
- : [desc(documentStagesOnlyView.createdAt)]
+ : [desc(stageDocumentsView.createdAt)]
// 트랜잭션 실행
const { data, total } = await db.transaction(async (tx) => {
@@ -1075,8 +1078,8 @@ export async function getDocumentStagesOnlyById(documentId: number) {
try {
const result = await db
.select()
- .from(documentStagesOnlyView)
- .where(eq(documentStagesOnlyView.documentId, documentId))
+ .from(stageDocumentsView)
+ .where(eq(stageDocumentsView.documentId, documentId))
.limit(1)
return result[0] || null
@@ -1091,8 +1094,8 @@ export async function getDocumentStagesOnlyCount(contractId: number) {
try {
const result = await db
.select({ count: sql<number>`count(*)` })
- .from(documentStagesOnlyView)
- .where(eq(documentStagesOnlyView.contractId, contractId))
+ .from(stageDocumentsView)
+ .where(eq(stageDocumentsView.contractId, contractId))
return result[0]?.count ?? 0
} catch (err) {
@@ -1113,8 +1116,8 @@ export async function getDocumentProgressStats(contractId: number) {
overdueDocuments: sql<number>`count(case when is_overdue = true then 1 end)`,
avgProgress: sql<number>`round(avg(progress_percentage), 2)`,
})
- .from(documentStagesOnlyView)
- .where(eq(documentStagesOnlyView.contractId, contractId))
+ .from(stageDocumentsView)
+ .where(eq(stageDocumentsView.contractId, contractId))
return result[0] || {
totalDocuments: 0,
@@ -1142,16 +1145,16 @@ export async function getDocumentsByStageStats(contractId: number) {
try {
const result = await db
.select({
- stageName: documentStagesOnlyView.currentStageName,
- stageStatus: documentStagesOnlyView.currentStageStatus,
+ stageName: stageDocumentsView.currentStageName,
+ stageStatus: stageDocumentsView.currentStageStatus,
documentCount: sql<number>`count(*)`,
overdueCount: sql<number>`count(case when is_overdue = true then 1 end)`,
})
- .from(documentStagesOnlyView)
- .where(eq(documentStagesOnlyView.contractId, contractId))
+ .from(stageDocumentsView)
+ .where(eq(stageDocumentsView.contractId, contractId))
.groupBy(
- documentStagesOnlyView.currentStageName,
- documentStagesOnlyView.currentStageStatus
+ stageDocumentsView.currentStageName,
+ stageDocumentsView.currentStageStatus
)
.orderBy(sql`count(*) desc`)
diff --git a/lib/vendor-document-list/repository.ts b/lib/vendor-document-list/repository.ts
index 4eab3853..ab47f013 100644
--- a/lib/vendor-document-list/repository.ts
+++ b/lib/vendor-document-list/repository.ts
@@ -1,5 +1,5 @@
import db from "@/db/db";
-import { documentStagesOnlyView, documentStagesView } from "@/db/schema/vendorDocu";
+import { stageDocumentsView, documentStagesView } from "@/db/schema/vendorDocu";
import {
eq,
inArray,
@@ -58,7 +58,7 @@ export async function selectDocumentStagesOnly(
return tx
.select()
- .from(documentStagesOnlyView)
+ .from(stageDocumentsView)
.where(where)
.orderBy(...(orderBy ?? []))
.offset(offset)
@@ -70,7 +70,7 @@ export async function countDocumentStagesOnly(
tx: PgTransaction<any, any, any>,
where?: any
) {
- const res = await tx.select({ count: count() }).from(documentStagesOnlyView).where(where);
+ const res = await tx.select({ count: count() }).from(stageDocumentsView).where(where);
return res[0]?.count ?? 0;
}