summaryrefslogtreecommitdiff
path: root/lib/rfq-last/service.ts
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rfq-last/service.ts')
-rw-r--r--lib/rfq-last/service.ts229
1 files changed, 229 insertions, 0 deletions
diff --git a/lib/rfq-last/service.ts b/lib/rfq-last/service.ts
index 8475aac0..2c1aa2ca 100644
--- a/lib/rfq-last/service.ts
+++ b/lib/rfq-last/service.ts
@@ -5515,4 +5515,233 @@ export async function getVendorDocumentConfirmStatus(
console.error("문서 확정 상태 조회 중 오류:", error);
return { isConfirmed: false, count: 0 };
}
+}
+
+// 일반견적 수정 입력 인터페이스
+interface UpdateGeneralRfqInput {
+ id: number; // 수정할 RFQ ID
+ rfqType: string;
+ rfqTitle: string;
+ dueDate: Date;
+ picUserId: number;
+ projectId?: number;
+ remark?: string;
+ items: Array<{
+ itemCode: string;
+ itemName: string;
+ materialCode?: string;
+ materialName?: string;
+ quantity: number;
+ uom: string;
+ remark?: string;
+ }>;
+ updatedBy: number;
+}
+
+// 일반견적 수정 서버 액션
+export async function updateGeneralRfqAction(input: UpdateGeneralRfqInput) {
+ try {
+ // 트랜잭션으로 처리
+ const result = await db.transaction(async (tx) => {
+ // 1. 기존 RFQ 조회 (존재 확인 및 상태 확인)
+ const existingRfq = await tx
+ .select()
+ .from(rfqsLast)
+ .where(eq(rfqsLast.id, input.id))
+ .limit(1);
+
+ if (!existingRfq || existingRfq.length === 0) {
+ throw new Error("수정할 일반견적을 찾을 수 없습니다");
+ }
+
+ const rfq = existingRfq[0];
+
+ // 상태 검증 (RFQ 생성 상태만 수정 가능)
+ if (rfq.status !== "RFQ 생성") {
+ throw new Error("RFQ 생성 상태인 일반견적만 수정할 수 있습니다");
+ }
+
+ // 2. 구매 담당자 정보 조회
+ const picUser = await tx
+ .select({
+ name: users.name,
+ email: users.email,
+ userCode: users.userCode
+ })
+ .from(users)
+ .where(eq(users.id, input.picUserId))
+ .limit(1);
+
+ if (!picUser || picUser.length === 0) {
+ throw new Error("구매 담당자를 찾을 수 없습니다");
+ }
+
+ // 3. userCode 확인 (3자리)
+ const userCode = picUser[0].userCode;
+ if (!userCode || userCode.length !== 3) {
+ throw new Error("구매 담당자의 userCode가 올바르지 않습니다 (3자리 필요)");
+ }
+
+ // 4. 대표 아이템 정보 추출 (첫 번째 아이템)
+ const representativeItem = input.items[0];
+
+ // 5. rfqsLast 테이블 업데이트
+ const [updatedRfq] = await tx
+ .update(rfqsLast)
+ .set({
+ rfqType: input.rfqType,
+ rfqTitle: input.rfqTitle,
+ dueDate: input.dueDate,
+ projectId: input.projectId || null,
+ itemCode: representativeItem.itemCode,
+ itemName: representativeItem.itemName,
+ pic: input.picUserId,
+ picCode: userCode,
+ picName: picUser[0].name || '',
+ remark: input.remark || null,
+ updatedBy: input.updatedBy,
+ updatedAt: new Date(),
+ })
+ .where(eq(rfqsLast.id, input.id))
+ .returning();
+
+ // 6. 기존 rfqPrItems 삭제 후 재삽입
+ await tx
+ .delete(rfqPrItems)
+ .where(eq(rfqPrItems.rfqsLastId, input.id));
+
+ // 7. rfqPrItems 테이블에 아이템들 재삽입
+ const prItemsData = input.items.map((item, index) => ({
+ rfqsLastId: input.id,
+ rfqItem: `${index + 1}`.padStart(3, '0'), // 001, 002, ...
+ prItem: null, // 일반견적에서는 PR 아이템 번호를 null로 설정
+ prNo: null, // 일반견적에서는 PR 번호를 null로 설정
+
+ materialCode: item.materialCode || item.itemCode, // SAP 자재코드 (없으면 자재그룹코드 사용)
+ materialCategory: item.itemCode, // 자재그룹코드
+ materialDescription: item.materialName || item.itemName, // SAP 자재명 (없으면 자재그룹명 사용)
+ quantity: item.quantity,
+ uom: item.uom,
+
+ majorYn: index === 0, // 첫 번째 아이템을 주요 아이템으로 설정
+ remark: item.remark || null,
+ }));
+
+ await tx.insert(rfqPrItems).values(prItemsData);
+
+ return updatedRfq;
+ });
+
+ return {
+ success: true,
+ message: "일반견적이 성공적으로 수정되었습니다",
+ data: {
+ id: result.id,
+ rfqCode: result.rfqCode,
+ },
+ };
+
+ } catch (error) {
+ console.error("일반견적 수정 오류:", error);
+
+ if (error instanceof Error) {
+ return {
+ success: false,
+ error: error.message,
+ };
+ }
+
+ return {
+ success: false,
+ error: "일반견적 수정 중 오류가 발생했습니다",
+ };
+ }
+}
+
+// 일반견적 수정용 데이터 조회 함수
+export async function getGeneralRfqForUpdate(rfqId: number) {
+ try {
+ // RFQ 기본 정보 조회
+ const rfqData = await db
+ .select({
+ id: rfqsLast.id,
+ rfqCode: rfqsLast.rfqCode,
+ rfqType: rfqsLast.rfqType,
+ rfqTitle: rfqsLast.rfqTitle,
+ status: rfqsLast.status,
+ dueDate: rfqsLast.dueDate,
+ projectId: rfqsLast.projectId,
+ pic: rfqsLast.pic,
+ picCode: rfqsLast.picCode,
+ picName: rfqsLast.picName,
+ remark: rfqsLast.remark,
+ createdAt: rfqsLast.createdAt,
+ updatedAt: rfqsLast.updatedAt,
+ })
+ .from(rfqsLast)
+ .where(
+ and(
+ eq(rfqsLast.id, rfqId),
+ eq(rfqsLast.status, "RFQ 생성") // RFQ 생성 상태만 조회
+ )
+ )
+ .limit(1);
+
+ if (!rfqData || rfqData.length === 0) {
+ return {
+ success: false,
+ error: "수정할 일반견적을 찾을 수 없거나 수정할 수 없는 상태입니다",
+ };
+ }
+
+ const rfq = rfqData[0];
+
+ // RFQ 아이템들 조회
+ const items = await db
+ .select({
+ rfqItem: rfqPrItems.rfqItem,
+ materialCode: rfqPrItems.materialCode,
+ materialCategory: rfqPrItems.materialCategory,
+ materialDescription: rfqPrItems.materialDescription,
+ quantity: rfqPrItems.quantity,
+ uom: rfqPrItems.uom,
+ remark: rfqPrItems.remark,
+ })
+ .from(rfqPrItems)
+ .where(eq(rfqPrItems.rfqsLastId, rfqId))
+ .orderBy(rfqPrItems.rfqItem);
+
+ // 아이템 데이터를 폼 형식으로 변환
+ const formItems = items.map(item => ({
+ itemCode: item.materialCategory || "", // 자재그룹코드
+ itemName: item.materialDescription || "", // 자재그룹명
+ materialCode: item.materialCode || "", // SAP 자재코드
+ materialName: item.materialDescription || "", // SAP 자재명 (설명으로 사용)
+ quantity: Math.floor(Number(item.quantity)), // 소수점 제거
+ uom: item.uom,
+ remark: item.remark || "",
+ }));
+
+ return {
+ success: true,
+ data: {
+ id: rfq.id,
+ rfqCode: rfq.rfqCode,
+ rfqType: rfq.rfqType,
+ rfqTitle: rfq.rfqTitle,
+ dueDate: rfq.dueDate,
+ picUserId: rfq.pic,
+ projectId: rfq.projectId,
+ remark: rfq.remark,
+ items: formItems,
+ },
+ };
+
+ } catch (error) {
+ console.error("일반견적 조회 오류:", error);
+ return {
+ success: false,
+ error: "일반견적 조회 중 오류가 발생했습니다",
+ };
+ }
} \ No newline at end of file