summaryrefslogtreecommitdiff
path: root/lib/rfqs/service.ts
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-04-08 03:08:19 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-04-08 03:08:19 +0000
commit9ceed79cf32c896f8a998399bf1b296506b2cd4a (patch)
treef84750fa6cac954d5e31221fc47a54c655fc06a9 /lib/rfqs/service.ts
parent230ce796836c25df26c130dbcd616ef97d12b2ec (diff)
로그인 및 미들웨어 처리. 구조 변경
Diffstat (limited to 'lib/rfqs/service.ts')
-rw-r--r--lib/rfqs/service.ts122
1 files changed, 95 insertions, 27 deletions
diff --git a/lib/rfqs/service.ts b/lib/rfqs/service.ts
index 6b8b4738..b56349e2 100644
--- a/lib/rfqs/service.ts
+++ b/lib/rfqs/service.ts
@@ -208,6 +208,7 @@ export async function modifyRfq(input: UpdateRfqSchema & { id: number }) {
rfqCode: input.rfqCode,
projectId: input.projectId || null,
dueDate: input.dueDate,
+ rfqType: input.rfqType,
status: input.status as "DRAFT" | "PUBLISHED" | "EVALUATION" | "AWARDED",
createdBy: input.createdBy,
});
@@ -1246,6 +1247,11 @@ export async function getTBE(input: GetTBESchema, rfqId: number) {
}
export async function getTBEforVendor(input: GetTBESchema, vendorId: number) {
+
+ if (isNaN(vendorId) || vendorId === null || vendorId === undefined) {
+ throw new Error("유효하지 않은 vendorId: 숫자 값이 필요합니다");
+ }
+
return unstable_cache(
async () => {
// 1) 페이징
@@ -1801,13 +1807,6 @@ export interface BudgetaryRfq {
projectName: string | null;
}
-interface GetBudgetaryRfqsParams {
- search?: string;
- projectId?: number;
- limit?: number;
- offset?: number;
-}
-
type GetBudgetaryRfqsResponse =
| { rfqs: BudgetaryRfq[]; totalCount: number; error?: never }
| { error: string; rfqs?: never; totalCount: number }
@@ -1816,16 +1815,40 @@ type GetBudgetaryRfqsResponse =
* Purchase RFQ 생성 시 부모 RFQ로 선택할 수 있도록 함
* 페이징 및 필터링 기능 포함
*/
+export interface GetBudgetaryRfqsParams {
+ search?: string;
+ projectId?: number;
+ rfqId?: number; // 특정 ID로 단일 RFQ 검색
+ rfqTypes?: RfqType[]; // 특정 RFQ 타입들로 필터링
+ limit?: number;
+ offset?: number;
+}
+
export async function getBudgetaryRfqs(params: GetBudgetaryRfqsParams = {}): Promise<GetBudgetaryRfqsResponse> {
- const { search, projectId, limit = 50, offset = 0 } = params;
- const cacheKey = `budgetary-rfqs-${JSON.stringify(params)}`;
+ const { search, projectId, rfqId, rfqTypes, limit = 50, offset = 0 } = params;
+ const cacheKey = `rfqs-query-${JSON.stringify(params)}`;
+
return unstable_cache(
async () => {
try {
-
- const baseCondition = eq(rfqs.rfqType, RfqType.BUDGETARY);
-
- let where1
+ // 기본 검색 조건 구성
+ let baseCondition;
+
+ // 특정 RFQ 타입들로 필터링 (rfqTypes 배열이 주어진 경우)
+ if (rfqTypes && rfqTypes.length > 0) {
+ // 여러 타입으로 필터링 (OR 조건)
+ baseCondition = inArray(rfqs.rfqType, rfqTypes);
+ } else {
+ // 기본적으로 BUDGETARY 타입만 검색 (이전 동작 유지)
+ baseCondition = eq(rfqs.rfqType, RfqType.BUDGETARY);
+ }
+
+ // 특정 ID로 검색하는 경우
+ if (rfqId) {
+ baseCondition = and(baseCondition, eq(rfqs.id, rfqId));
+ }
+
+ let where1;
// 검색어 조건 추가 (있을 경우)
if (search && search.trim()) {
const searchTerm = `%${search.trim()}%`;
@@ -1835,30 +1858,31 @@ export async function getBudgetaryRfqs(params: GetBudgetaryRfqsParams = {}): Pro
ilike(projects.code, searchTerm),
ilike(projects.name, searchTerm)
);
- where1 = searchCondition
+ where1 = searchCondition;
}
-
- let where2
+
+ let where2;
// 프로젝트 ID 조건 추가 (있을 경우)
if (projectId) {
where2 = eq(rfqs.projectId, projectId);
}
-
- const finalWhere = and(where1, where2, baseCondition)
-
+
+ const finalWhere = and(baseCondition, where1, where2);
+
// 총 개수 조회
const [countResult] = await db
.select({ count: count() })
.from(rfqs)
.leftJoin(projects, eq(rfqs.projectId, projects.id))
.where(finalWhere);
-
+
// 실제 데이터 조회
- const budgetaryRfqs = await db
+ const resultRfqs = await db
.select({
id: rfqs.id,
rfqCode: rfqs.rfqCode,
description: rfqs.description,
+ rfqType: rfqs.rfqType, // RFQ 타입 필드 추가
projectId: rfqs.projectId,
projectCode: projects.code,
projectName: projects.name,
@@ -1869,15 +1893,15 @@ export async function getBudgetaryRfqs(params: GetBudgetaryRfqsParams = {}): Pro
.orderBy(desc(rfqs.createdAt))
.limit(limit)
.offset(offset);
-
+
return {
- rfqs: budgetaryRfqs as BudgetaryRfq[], // 타입 단언으로 호환성 보장
+ rfqs: resultRfqs,
totalCount: Number(countResult?.count) || 0
};
} catch (error) {
- console.error("Error fetching budgetary RFQs:", error);
+ console.error("Error fetching RFQs:", error);
return {
- error: "Failed to fetch budgetary RFQs",
+ error: "Failed to fetch RFQs",
totalCount: 0
};
}
@@ -1885,11 +1909,10 @@ export async function getBudgetaryRfqs(params: GetBudgetaryRfqsParams = {}): Pro
[cacheKey],
{
revalidate: 60, // 1분 캐시
- tags: ["rfqs-budgetary"],
+ tags: ["rfqs-query"],
}
)();
}
-
export async function getAllVendors() {
// Adjust the query as needed (add WHERE, ORDER, etc.)
const allVendors = await db.select().from(vendors)
@@ -2812,4 +2835,49 @@ export async function getCBE(input: GetCBESchema, rfqId: number) {
tags: ["cbe-vendors"],
}
)();
+}
+
+
+export async function generateNextRfqCode(rfqType: RfqType): Promise<{ code: string; error?: string }> {
+ try {
+ if (!rfqType) {
+ return { code: "", error: 'RFQ 타입이 필요합니다' };
+ }
+
+ // 현재 연도 가져오기
+ const currentYear = new Date().getFullYear();
+
+ // 현재 연도와 타입에 맞는 최신 RFQ 코드 찾기
+ const latestRfqs = await db.select({ rfqCode: rfqs.rfqCode })
+ .from(rfqs)
+ .where(and(
+ sql`SUBSTRING(${rfqs.rfqCode}, 5, 4) = ${currentYear.toString()}`,
+ eq(rfqs.rfqType, rfqType)
+ ))
+ .orderBy(desc(rfqs.rfqCode))
+ .limit(1);
+
+ let sequenceNumber = 1;
+
+ if (latestRfqs.length > 0 && latestRfqs[0].rfqCode) {
+ // null 체크 추가 - TypeScript 오류 해결
+ const latestCode = latestRfqs[0].rfqCode;
+ const matches = latestCode.match(/[A-Z]+-\d{4}-(\d{3})/);
+
+ if (matches && matches[1]) {
+ sequenceNumber = parseInt(matches[1], 10) + 1;
+ }
+ }
+
+ // 새로운 RFQ 코드 포맷팅
+ const typePrefix = rfqType === RfqType.BUDGETARY ? 'BUD' :
+ rfqType === RfqType.PURCHASE_BUDGETARY ? 'PBU' : 'RFQ';
+
+ const newCode = `${typePrefix}-${currentYear}-${String(sequenceNumber).padStart(3, '0')}`;
+
+ return { code: newCode };
+ } catch (error) {
+ console.error('Error generating next RFQ code:', error);
+ return { code: "", error: '코드 생성에 실패했습니다' };
+ }
} \ No newline at end of file