summaryrefslogtreecommitdiff
path: root/lib/b-rfq/service.ts
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-06-13 07:11:18 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-06-13 07:11:18 +0000
commit0fddf148402fd6b99a1b3800d73679899bcb2ed3 (patch)
treeeb51c02e6fa6037ddcc38a3b57d10d8c739125cf /lib/b-rfq/service.ts
parentc72d0897f7b37843109c86f61d97eba05ba3ca0d (diff)
(대표님) 20250613 16시 10분 global css, b-rfq, document 등
Diffstat (limited to 'lib/b-rfq/service.ts')
-rw-r--r--lib/b-rfq/service.ts218
1 files changed, 216 insertions, 2 deletions
diff --git a/lib/b-rfq/service.ts b/lib/b-rfq/service.ts
index e60e446d..0dc61832 100644
--- a/lib/b-rfq/service.ts
+++ b/lib/b-rfq/service.ts
@@ -4,15 +4,16 @@ import { revalidateTag, unstable_cache } from "next/cache"
import { count, desc, asc, and, or, gte, lte, ilike, eq, inArray, sql } from "drizzle-orm"
import { filterColumns } from "@/lib/filter-columns"
import db from "@/db/db"
-import { RfqDashboardView, bRfqAttachmentRevisions, bRfqs, bRfqsAttachments, projects, users, vendorAttachmentResponses, vendors } from "@/db/schema" // 실제 스키마 import 경로에 맞게 수정
+import { Incoterm, RfqDashboardView, Vendor, bRfqAttachmentRevisions, bRfqs, bRfqsAttachments, incoterms, initialRfq, initialRfqDetailView, projects, users, vendorAttachmentResponses, vendors } from "@/db/schema" // 실제 스키마 import 경로에 맞게 수정
import { rfqDashboardView } from "@/db/schema" // 뷰 import
import type { SQL } from "drizzle-orm"
-import { AttachmentRecord, CreateRfqInput, DeleteAttachmentsInput, GetRFQDashboardSchema, GetRfqAttachmentsSchema, attachmentRecordSchema, createRfqServerSchema, deleteAttachmentsSchema } from "./validations"
+import { AttachmentRecord, CreateRfqInput, DeleteAttachmentsInput, GetInitialRfqDetailSchema, GetRFQDashboardSchema, GetRfqAttachmentsSchema, attachmentRecordSchema, createRfqServerSchema, deleteAttachmentsSchema } from "./validations"
import { getServerSession } from "next-auth/next"
import { authOptions } from "@/app/api/auth/[...nextauth]/route"
import { unlink } from "fs/promises"
const tag = {
+ initialRfqDetail:"initial-rfq",
rfqDashboard: 'rfq-dashboard',
rfq: (id: number) => `rfq-${id}`,
rfqAttachments: (rfqId: number) => `rfq-attachments-${rfqId}`,
@@ -1017,4 +1018,217 @@ export async function deleteRfqAttachments(input: DeleteAttachmentsInput) {
message: error instanceof Error ? error.message : "첨부파일 삭제 중 오류가 발생했습니다.",
}
}
+}
+
+
+
+//Initial RFQ
+
+export async function getInitialRfqDetail(input: GetInitialRfqDetailSchema, rfqId?: number) {
+ return unstable_cache(
+ async () => {
+ try {
+ const offset = (input.page - 1) * input.perPage;
+
+ // 1) 고급 필터 조건
+ let advancedWhere: SQL<unknown> | undefined = undefined;
+ if (input.filters && input.filters.length > 0) {
+ advancedWhere = filterColumns({
+ table: initialRfqDetailView,
+ filters: input.filters,
+ joinOperator: input.joinOperator || 'and',
+ });
+ }
+
+ // 2) 기본 필터 조건
+ let basicWhere: SQL<unknown> | undefined = undefined;
+ if (input.basicFilters && input.basicFilters.length > 0) {
+ basicWhere = filterColumns({
+ table: initialRfqDetailView,
+ filters: input.basicFilters,
+ joinOperator: input.basicJoinOperator || 'and',
+ });
+ }
+
+ let rfqIdWhere: SQL<unknown> | undefined = undefined;
+ if (rfqId) {
+ rfqIdWhere = eq(initialRfqDetailView.rfqId, rfqId);
+ }
+
+
+ // 3) 글로벌 검색 조건
+ let globalWhere: SQL<unknown> | undefined = undefined;
+ if (input.search) {
+ const s = `%${input.search}%`;
+
+ const validSearchConditions: SQL<unknown>[] = [];
+
+ const rfqCodeCondition = ilike(initialRfqDetailView.rfqCode, s);
+ if (rfqCodeCondition) validSearchConditions.push(rfqCodeCondition);
+
+ const vendorNameCondition = ilike(initialRfqDetailView.vendorName, s);
+ if (vendorNameCondition) validSearchConditions.push(vendorNameCondition);
+
+ const vendorCodeCondition = ilike(initialRfqDetailView.vendorCode, s);
+ if (vendorCodeCondition) validSearchConditions.push(vendorCodeCondition);
+
+ const vendorCountryCondition = ilike(initialRfqDetailView.vendorCountry, s);
+ if (vendorCountryCondition) validSearchConditions.push(vendorCountryCondition);
+
+ const incotermsDescriptionCondition = ilike(initialRfqDetailView.incotermsDescription, s);
+ if (incotermsDescriptionCondition) validSearchConditions.push(incotermsDescriptionCondition);
+
+ const classificationCondition = ilike(initialRfqDetailView.classification, s);
+ if (classificationCondition) validSearchConditions.push(classificationCondition);
+
+ const sparepartCondition = ilike(initialRfqDetailView.sparepart, s);
+ if (sparepartCondition) validSearchConditions.push(sparepartCondition);
+
+ if (validSearchConditions.length > 0) {
+ globalWhere = or(...validSearchConditions);
+ }
+ }
+
+
+ // 5) 최종 WHERE 조건 생성
+ const whereConditions: SQL<unknown>[] = [];
+
+ if (advancedWhere) whereConditions.push(advancedWhere);
+ if (basicWhere) whereConditions.push(basicWhere);
+ if (globalWhere) whereConditions.push(globalWhere);
+ if (rfqIdWhere) whereConditions.push(rfqIdWhere);
+
+ const finalWhere = whereConditions.length > 0 ? and(...whereConditions) : undefined;
+
+ // 6) 전체 데이터 수 조회
+ const totalResult = await db
+ .select({ count: count() })
+ .from(initialRfqDetailView)
+ .where(finalWhere);
+
+ const total = totalResult[0]?.count || 0;
+
+ if (total === 0) {
+ return { data: [], pageCount: 0, total: 0 };
+ }
+
+ console.log(total);
+
+ // 7) 정렬 및 페이징 처리된 데이터 조회
+ const orderByColumns = input.sort.map((sort) => {
+ const column = sort.id as keyof typeof initialRfqDetailView.$inferSelect;
+ return sort.desc ? desc(initialRfqDetailView[column]) : asc(initialRfqDetailView[column]);
+ });
+
+ if (orderByColumns.length === 0) {
+ orderByColumns.push(desc(initialRfqDetailView.createdAt));
+ }
+
+ const initialRfqData = await db
+ .select()
+ .from(initialRfqDetailView)
+ .where(finalWhere)
+ .orderBy(...orderByColumns)
+ .limit(input.perPage)
+ .offset(offset);
+
+ const pageCount = Math.ceil(total / input.perPage);
+
+ return { data: initialRfqData, pageCount, total };
+ } catch (err) {
+ console.error("Error in getInitialRfqDetail:", err);
+ return { data: [], pageCount: 0, total: 0 };
+ }
+ },
+ [JSON.stringify(input)],
+ { revalidate: 3600, tags: [tag.initialRfqDetail] },
+ )();
+}
+
+export async function getVendorsForSelection() {
+ try {
+ const vendorsData = await db
+ .select({
+ id: vendors.id,
+ vendorName: vendors.vendorName,
+ vendorCode: vendors.vendorCode,
+ country: vendors.country,
+ status: vendors.status,
+ })
+ .from(vendors)
+ // .where(
+ // and(
+ // ne(vendors.status, "BLACKLISTED"),
+ // ne(vendors.status, "REJECTED")
+ // )
+ // )
+ .orderBy(vendors.vendorName)
+
+ return vendorsData.map(vendor => ({
+ id: vendor.id,
+ vendorName: vendor.vendorName || "",
+ vendorCode: vendor.vendorCode || "",
+ country: vendor.country || "",
+ status: vendor.status,
+ }))
+ } catch (error) {
+ console.error("Error fetching vendors:", error)
+ throw new Error("Failed to fetch vendors")
+ }
+}
+
+export async function addInitialRfqRecord(data: AddInitialRfqFormData & { rfqId: number }) {
+ try {
+ const [newRecord] = await db
+ .insert(initialRfq)
+ .values({
+ rfqId: data.rfqId,
+ vendorId: data.vendorId,
+ initialRfqStatus: data.initialRfqStatus,
+ dueDate: data.dueDate,
+ validDate: data.validDate,
+ incotermsCode: data.incotermsCode,
+ gtc: data.gtc,
+ gtcValidDate: data.gtcValidDate,
+ classification: data.classification,
+ sparepart: data.sparepart,
+ shortList: data.shortList,
+ returnYn: data.returnYn,
+ cpRequestYn: data.cpRequestYn,
+ prjectGtcYn: data.prjectGtcYn,
+ returnRevision: data.returnRevision,
+ })
+ .returning()
+
+ return {
+ success: true,
+ message: "초기 RFQ가 성공적으로 추가되었습니다.",
+ data: newRecord,
+ }
+ } catch (error) {
+ console.error("Error adding initial RFQ:", error)
+ return {
+ success: false,
+ message: "초기 RFQ 추가에 실패했습니다.",
+ error,
+ }
+ }
+}
+
+export async function getIncotermsForSelection() {
+ try {
+ const incotermData = await db
+ .select({
+ code: incoterms.code,
+ description: incoterms.description,
+ })
+ .from(incoterms)
+ .orderBy(incoterms.code)
+
+ return incotermData
+
+ } catch (error) {
+ console.error("Error fetching incoterms:", error)
+ throw new Error("Failed to fetch incoterms")
+ }
} \ No newline at end of file