summaryrefslogtreecommitdiff
path: root/lib/vendor-rfq-response/service.ts
diff options
context:
space:
mode:
Diffstat (limited to 'lib/vendor-rfq-response/service.ts')
-rw-r--r--lib/vendor-rfq-response/service.ts181
1 files changed, 172 insertions, 9 deletions
diff --git a/lib/vendor-rfq-response/service.ts b/lib/vendor-rfq-response/service.ts
index cba6c414..8f2954d7 100644
--- a/lib/vendor-rfq-response/service.ts
+++ b/lib/vendor-rfq-response/service.ts
@@ -1,10 +1,14 @@
-import { unstable_cache } from "next/cache";
+'use server'
+
+import { revalidateTag, unstable_cache } from "next/cache";
import db from "@/db/db";
import { and, desc, eq, inArray, isNull, or, sql } from "drizzle-orm";
-import { rfqAttachments, rfqComments, rfqItems } from "@/db/schema/rfq";
+import { rfqAttachments, rfqComments, rfqItems, vendorResponses } from "@/db/schema/rfq";
import { vendorResponsesView, vendorTechnicalResponses, vendorCommercialResponses, vendorResponseAttachments } from "@/db/schema/rfq";
import { items } from "@/db/schema/items";
import { GetRfqsForVendorsSchema } from "../rfqs/validations";
+import { ItemData } from "./vendor-cbe-table/rfq-items-table/rfq-items-table";
+import * as z from "zod"
@@ -27,7 +31,7 @@ export async function getRfqResponsesForVendor(input: GetRfqsForVendorsSchema, v
);
}
- // 벤더 ID 필터링
+ // 협력업체 ID 필터링
const mainWhere = and(eq(vendorResponsesView.vendorId, vendorId), globalWhere);
// 정렬: 응답 시간순
@@ -75,7 +79,7 @@ export async function getRfqResponsesForVendor(input: GetRfqsForVendorsSchema, v
.leftJoin(items, eq(rfqItems.itemCode, items.itemCode))
.where(inArray(rfqItems.rfqId, distinctRfqs));
- // 3-B) RFQ 첨부 파일 (벤더용)
+ // 3-B) RFQ 첨부 파일 (협력업체용)
const attachAll = await db
.select()
.from(rfqAttachments)
@@ -101,7 +105,7 @@ export async function getRfqResponsesForVendor(input: GetRfqsForVendorsSchema, v
);
- // 3-E) 벤더 응답 상세 - 기술
+ // 3-E) 협력업체 응답 상세 - 기술
const technicalResponsesAll = await db
.select()
.from(vendorTechnicalResponses)
@@ -112,7 +116,7 @@ export async function getRfqResponsesForVendor(input: GetRfqsForVendorsSchema, v
)
);
- // 3-F) 벤더 응답 상세 - 상업
+ // 3-F) 협력업체 응답 상세 - 상업
const commercialResponsesAll = await db
.select()
.from(vendorCommercialResponses)
@@ -123,7 +127,7 @@ export async function getRfqResponsesForVendor(input: GetRfqsForVendorsSchema, v
)
);
- // 3-G) 벤더 응답 첨부 파일
+ // 3-G) 협력업체 응답 첨부 파일
const responseAttachmentsAll = await db
.select()
.from(vendorResponseAttachments)
@@ -257,7 +261,7 @@ export async function getRfqResponsesForVendor(input: GetRfqsForVendorsSchema, v
projectCode: row.projectCode,
projectName: row.projectName,
- // 벤더 정보
+ // 협력업체 정보
vendorId: row.vendorId,
vendorName: row.vendorName,
vendorCode: row.vendorCode,
@@ -277,7 +281,7 @@ export async function getRfqResponsesForVendor(input: GetRfqsForVendorsSchema, v
result: row.cbeResult,
} : null,
- // 벤더 응답 상세
+ // 협력업체 응답 상세
technicalResponse: techResponseByResponseId.get(row.responseId) || null,
commercialResponse: commResponseByResponseId.get(row.responseId) || null,
responseAttachments: respAttachByResponseId.get(row.responseId) || [],
@@ -298,4 +302,163 @@ export async function getRfqResponsesForVendor(input: GetRfqsForVendorsSchema, v
tags: ["rfqs-vendor", `vendor-${vendorId}`],
}
)();
+}
+
+
+export async function getItemsByRfqId(rfqId: number): Promise<ResponseType> {
+ try {
+ if (!rfqId || isNaN(Number(rfqId))) {
+ return {
+ success: false,
+ error: "Invalid RFQ ID provided",
+ }
+ }
+
+ // Query the database to get all items for the given RFQ ID
+ const items = await db
+ .select()
+ .from(rfqItems)
+ .where(eq(rfqItems.rfqId, rfqId))
+ .orderBy(rfqItems.itemCode)
+
+
+ return {
+ success: true,
+ data: items as ItemData[],
+ }
+ } catch (error) {
+ console.error("Error fetching RFQ items:", error)
+
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "Unknown error occurred when fetching RFQ items",
+ }
+ }
+}
+
+
+// Define the schema for validation
+const commercialResponseSchema = z.object({
+ responseId: z.number(),
+ vendorId: z.number(), // Added vendorId field
+ responseStatus: z.enum(["PENDING", "IN_PROGRESS", "SUBMITTED", "REJECTED", "ACCEPTED"]),
+ totalPrice: z.number().optional(),
+ currency: z.string().default("USD"),
+ paymentTerms: z.string().optional(),
+ incoterms: z.string().optional(),
+ deliveryPeriod: z.string().optional(),
+ warrantyPeriod: z.string().optional(),
+ validityPeriod: z.string().optional(),
+ priceBreakdown: z.string().optional(),
+ commercialNotes: z.string().optional(),
+})
+
+type CommercialResponseInput = z.infer<typeof commercialResponseSchema>
+
+interface ResponseType {
+ success: boolean
+ error?: string
+ data?: any
+}
+
+export async function updateCommercialResponse(input: CommercialResponseInput): Promise<ResponseType> {
+ try {
+ // Validate input data
+ const validated = commercialResponseSchema.parse(input)
+
+ // Check if a commercial response already exists for this responseId
+ const existingResponse = await db
+ .select()
+ .from(vendorCommercialResponses)
+ .where(eq(vendorCommercialResponses.responseId, validated.responseId))
+ .limit(1)
+
+ const now = new Date()
+
+ if (existingResponse.length > 0) {
+ // Update existing record
+ await db
+ .update(vendorCommercialResponses)
+ .set({
+ responseStatus: validated.responseStatus,
+ totalPrice: validated.totalPrice,
+ currency: validated.currency,
+ paymentTerms: validated.paymentTerms,
+ incoterms: validated.incoterms,
+ deliveryPeriod: validated.deliveryPeriod,
+ warrantyPeriod: validated.warrantyPeriod,
+ validityPeriod: validated.validityPeriod,
+ priceBreakdown: validated.priceBreakdown,
+ commercialNotes: validated.commercialNotes,
+ updatedAt: now,
+ })
+ .where(eq(vendorCommercialResponses.responseId, validated.responseId))
+
+ } else {
+ // Return error instead of creating a new record
+ return {
+ success: false,
+ error: "해당 응답 ID에 대한 상업 응답 정보를 찾을 수 없습니다."
+ }
+ }
+
+ // Also update the main vendor response status if submitted
+ if (validated.responseStatus === "SUBMITTED") {
+ // Get the vendor response
+ const vendorResponseResult = await db
+ .select()
+ .from(vendorResponses)
+ .where(eq(vendorResponses.id, validated.responseId))
+ .limit(1)
+
+ if (vendorResponseResult.length > 0) {
+ // Update the main response status to RESPONDED
+ await db
+ .update(vendorResponses)
+ .set({
+ responseStatus: "RESPONDED",
+ updatedAt: now,
+ })
+ .where(eq(vendorResponses.id, validated.responseId))
+ }
+ }
+
+ // Use vendorId for revalidateTag
+ revalidateTag(`cbe-vendor-${validated.vendorId}`)
+
+ return {
+ success: true,
+ data: { responseId: validated.responseId }
+ }
+
+ } catch (error) {
+ console.error("Error updating commercial response:", error)
+
+ if (error instanceof z.ZodError) {
+ return {
+ success: false,
+ error: "유효하지 않은 데이터가 제공되었습니다."
+ }
+ }
+
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "Unknown error occurred"
+ }
+ }
+}
+// Helper function to get responseId from rfqId and vendorId
+export async function getCommercialResponseByResponseId(responseId: number): Promise<any | null> {
+ try {
+ const response = await db
+ .select()
+ .from(vendorCommercialResponses)
+ .where(eq(vendorCommercialResponses.responseId, responseId))
+ .limit(1)
+
+ return response.length > 0 ? response[0] : null
+ } catch (error) {
+ console.error("Error getting commercial response:", error)
+ return null
+ }
} \ No newline at end of file