diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-09-15 03:24:12 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-09-15 03:24:12 +0000 |
| commit | 25b916d040a512cd5248dff319d727ae144d0652 (patch) | |
| tree | ed65d637d4807ce4a1575f3080ff0df98c430ae4 /lib/pcr/actions.ts | |
| parent | 3f293c90beb58ce206a66ff444d7acfc41b56429 (diff) | |
(최겸) 구매 PCR 개발(po -> pcr, ecc pcr-confirm test 필)
Diffstat (limited to 'lib/pcr/actions.ts')
| -rw-r--r-- | lib/pcr/actions.ts | 458 |
1 files changed, 458 insertions, 0 deletions
diff --git a/lib/pcr/actions.ts b/lib/pcr/actions.ts new file mode 100644 index 00000000..00c15f4b --- /dev/null +++ b/lib/pcr/actions.ts @@ -0,0 +1,458 @@ +"use server"
+
+import { revalidatePath } from "next/cache"
+import { getServerSession } from "next-auth"
+import { authOptions } from "@/app/api/auth/[...nextauth]/route"
+import { confirmPCR } from "@/lib/soap/ecc/send/pcr-confirm"
+import { format } from "date-fns"
+import db from "@/db/db"
+import { pcrPo } from "@/db/schema"
+import { eq } from "drizzle-orm"
+import {
+ createPcrPo,
+ createPcrPr,
+ updatePcrPo,
+ updatePcrPr,
+ deletePcrPo,
+ deletePcrPr,
+ getPcrPoById,
+ getPcrPrById,
+} from "./service"
+
+/**
+ * PCR_PO 생성 Server Action
+ */
+export async function createPcrPoAction(data: {
+ pcrApprovalStatus?: string;
+ changeType?: string;
+ details?: string;
+ project?: string;
+ pcrRequestDate: Date;
+ poContractNumber: string;
+ revItemNumber?: string;
+ purchaseContractManager?: string;
+ pcrCreator?: string;
+ poContractAmountBefore?: number;
+ poContractAmountAfter?: number;
+ contractCurrency?: string;
+ pcrReason?: string;
+ detailsReason?: string;
+ rejectionReason?: string;
+ pcrResponseDate?: Date;
+ vendorId?: number;
+}) {
+ try {
+ const result = await createPcrPo(data);
+
+ if (result.success) {
+ // 관련 페이지들 재검증
+ revalidatePath("/evcp/pcr");
+ revalidatePath("/partners/pcr");
+
+ return { success: true, message: "PCR_PO가 성공적으로 생성되었습니다", data: result.data }
+ } else {
+ return { success: false, error: result.error }
+ }
+ } catch (error) {
+ console.error("PCR_PO 생성 액션 오류:", error)
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "PCR_PO 생성에 실패했습니다"
+ }
+ }
+}
+
+/**
+ * PCR_PR 생성 Server Action
+ */
+export async function createPcrPrAction(data: {
+ materialNumber: string;
+ materialDetails?: string;
+ quantityBefore?: number;
+ quantityAfter?: number;
+ weightBefore?: number;
+ weightAfter?: number;
+ subcontractorWeightBefore?: number;
+ subcontractorWeightAfter?: number;
+ supplierWeightBefore?: number;
+ supplierWeightAfter?: number;
+ specDrawingBefore?: string;
+ specDrawingAfter?: string;
+ initialPoContractDate?: Date;
+ specChangeDate?: Date;
+ poContractModifiedDate?: Date;
+ confirmationDate?: Date;
+ designManager?: string;
+ poContractNumber: string;
+}) {
+ try {
+ const result = await createPcrPr(data);
+
+ if (result.success) {
+ // 관련 페이지들 재검증
+ revalidatePath("/evcp/pcr");
+ revalidatePath("/partners/pcr");
+
+ return { success: true, message: "PCR_PR이 성공적으로 생성되었습니다", data: result.data }
+ } else {
+ return { success: false, error: result.error }
+ }
+ } catch (error) {
+ console.error("PCR_PR 생성 액션 오류:", error)
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "PCR_PR 생성에 실패했습니다"
+ }
+ }
+}
+
+/**
+ * PCR_PO 업데이트 Server Action
+ */
+export async function updatePcrPoAction(id: number, data: Partial<{
+ pcrApprovalStatus: string;
+ changeType: string;
+ details: string;
+ project: string;
+ pcrRequestDate: Date;
+ poContractNumber: string;
+ revItemNumber: string;
+ purchaseContractManager: string;
+ pcrCreator: string;
+ poContractAmountBefore: number;
+ poContractAmountAfter: number;
+ contractCurrency: string;
+ pcrReason: string;
+ detailsReason: string;
+ rejectionReason: string;
+ pcrResponseDate: Date;
+ vendorId: number;
+}>) {
+ try {
+ const result = await updatePcrPo(id, data);
+
+ if (result.success) {
+ // 관련 페이지들 재검증
+ revalidatePath("/evcp/pcr");
+ revalidatePath("/partners/pcr");
+
+ return { success: true, message: "PCR_PO가 성공적으로 업데이트되었습니다", data: result.data }
+ } else {
+ return { success: false, error: result.error }
+ }
+ } catch (error) {
+ console.error("PCR_PO 업데이트 액션 오류:", error)
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "PCR_PO 업데이트에 실패했습니다"
+ }
+ }
+}
+
+/**
+ * PCR_PR 업데이트 Server Action
+ */
+export async function updatePcrPrAction(id: number, data: Partial<{
+ materialNumber: string;
+ materialDetails: string;
+ quantityBefore: number;
+ quantityAfter: number;
+ weightBefore: number;
+ weightAfter: number;
+ subcontractorWeightBefore: number;
+ subcontractorWeightAfter: number;
+ supplierWeightBefore: number;
+ supplierWeightAfter: number;
+ specDrawingBefore: string;
+ specDrawingAfter: string;
+ initialPoContractDate: Date;
+ specChangeDate: Date;
+ poContractModifiedDate: Date;
+ confirmationDate: Date;
+ designManager: string;
+ poContractNumber: string;
+}>) {
+ try {
+ const result = await updatePcrPr(id, data);
+
+ if (result.success) {
+ // 관련 페이지들 재검증
+ revalidatePath("/evcp/pcr");
+ revalidatePath("/partners/pcr");
+
+ return { success: true, message: "PCR_PR이 성공적으로 업데이트되었습니다", data: result.data }
+ } else {
+ return { success: false, error: result.error }
+ }
+ } catch (error) {
+ console.error("PCR_PR 업데이트 액션 오류:", error)
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "PCR_PR 업데이트에 실패했습니다"
+ }
+ }
+}
+
+/**
+ * PCR_PO 삭제 Server Action
+ */
+export async function deletePcrPoAction(id: number) {
+ try {
+ const result = await deletePcrPo(id);
+
+ if (result.success) {
+ // 관련 페이지들 재검증
+ revalidatePath("/evcp/pcr");
+ revalidatePath("/partners/pcr");
+
+ return { success: true, message: "PCR_PO가 성공적으로 삭제되었습니다" }
+ } else {
+ return { success: false, error: result.error }
+ }
+ } catch (error) {
+ console.error("PCR_PO 삭제 액션 오류:", error)
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "PCR_PO 삭제에 실패했습니다"
+ }
+ }
+}
+
+/**
+ * PCR_PR 삭제 Server Action
+ */
+export async function deletePcrPrAction(id: number) {
+ try {
+ const result = await deletePcrPr(id);
+
+ if (result.success) {
+ // 관련 페이지들 재검증
+ revalidatePath("/evcp/pcr");
+ revalidatePath("/partners/pcr");
+
+ return { success: true, message: "PCR_PR이 성공적으로 삭제되었습니다" }
+ } else {
+ return { success: false, error: result.error }
+ }
+ } catch (error) {
+ console.error("PCR_PR 삭제 액션 오류:", error)
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "PCR_PR 삭제에 실패했습니다"
+ }
+ }
+}
+
+/**
+ * PCR_PO 단일 조회 Server Action
+ */
+export async function getPcrPoByIdAction(id: number) {
+ try {
+ const data = await getPcrPoById(id);
+ return { success: true, data }
+ } catch (error) {
+ console.error("PCR_PO 조회 액션 오류:", error)
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "PCR_PO 조회에 실패했습니다"
+ }
+ }
+}
+
+/**
+ * PCR_PR 단일 조회 Server Action
+ */
+export async function getPcrPrByIdAction(id: number) {
+ try {
+ const data = await getPcrPrById(id);
+ return { success: true, data }
+ } catch (error) {
+ console.error("PCR_PR 조회 액션 오류:", error)
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "PCR_PR 조회에 실패했습니다"
+ }
+ }
+}
+
+/**
+ * PCR 승인 Server Action
+ */
+export async function approvePcrAction(id: number, reason?: string) {
+ try {
+ // PCR 데이터 조회
+ const pcrData = await getPcrPoById(id);
+ if (!pcrData) {
+ return { success: false, error: "PCR 데이터를 찾을 수 없습니다" }
+ }
+
+ // PCR 확인 데이터 구성
+ const confirmData = {
+ PCR_REQ: pcrData.poContractNumber, // PO 계약번호를 PCR 요청번호로 사용
+ PCR_REQ_SEQ: String(pcrData.id).padStart(5, '0'), // ID를 순번으로 사용
+ PCR_DEC_DATE: format(new Date(), 'yyyyMMdd'), // 오늘 날짜
+ EBELN: pcrData.poContractNumber, // PO 계약번호
+ EBELP: pcrData.revItemNumber || '00010', // REV/품번 또는 기본값
+ PCR_STATUS: 'A', // 승인 상태
+ CONFIRM_CD: 'APPROVED',
+ CONFIRM_RSN: reason || 'PCR 승인 완료'
+ };
+
+ console.log(`🚀 PCR 승인 요청 시작: ${confirmData.PCR_REQ}-${confirmData.PCR_REQ_SEQ}`);
+
+ // ECC로 승인 요청 전송
+ const confirmResult = await confirmPCR(confirmData);
+
+ if (!confirmResult.success) {
+ console.error(`❌ PCR 승인 실패: ${confirmResult.message}`);
+ return { success: false, error: confirmResult.message }
+ }
+
+ // DB에서 PCR 상태 업데이트
+ const updateResult = await updatePcrPo(id, {
+ pcrApprovalStatus: 'APPROVED',
+ pcrResponseDate: new Date()
+ });
+
+ if (!updateResult.success) {
+ console.error(`❌ PCR 승인 상태 업데이트 실패: ${updateResult.error}`);
+ return { success: false, error: updateResult.error }
+ }
+
+ // 관련 페이지들 재검증
+ revalidatePath("/evcp/pcr");
+ revalidatePath("/partners/pcr");
+
+ console.log(`✅ PCR 승인 완료: ${confirmData.PCR_REQ}-${confirmData.PCR_REQ_SEQ}`);
+
+ return {
+ success: true,
+ message: "PCR이 성공적으로 승인되었습니다",
+ data: {
+ confirmResult,
+ updateResult: updateResult.data
+ }
+ }
+ } catch (error) {
+ console.error("PCR 승인 액션 오류:", error)
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "PCR 승인에 실패했습니다"
+ }
+ }
+}
+
+/**
+ * PCR 거절 Server Action
+ */
+export async function rejectPcrAction(id: number, reason: string) {
+ try {
+ // PCR 데이터 조회
+ const pcrData = await getPcrPoById(id);
+ if (!pcrData) {
+ return { success: false, error: "PCR 데이터를 찾을 수 없습니다" }
+ }
+
+ // PCR 확인 데이터 구성
+ const confirmData = {
+ PCR_REQ: pcrData.poContractNumber, // PO 계약번호를 PCR 요청번호로 사용
+ PCR_REQ_SEQ: String(pcrData.id).padStart(5, '0'), // ID를 순번으로 사용
+ PCR_DEC_DATE: format(new Date(), 'yyyyMMdd'), // 오늘 날짜
+ EBELN: pcrData.poContractNumber, // PO 계약번호
+ EBELP: pcrData.revItemNumber || '00010', // REV/품번 또는 기본값
+ PCR_STATUS: 'R', // 거절 상태
+ REJ_CD: 'REJECTED',
+ REJ_RSN: reason
+ };
+
+ console.log(`🚫 PCR 거절 요청 시작: ${confirmData.PCR_REQ}-${confirmData.PCR_REQ_SEQ}`);
+
+ // ECC로 거절 요청 전송
+ const confirmResult = await confirmPCR(confirmData);
+
+ if (!confirmResult.success) {
+ console.error(`❌ PCR 거절 실패: ${confirmResult.message}`);
+ return { success: false, error: confirmResult.message }
+ }
+
+ // DB에서 PCR 상태 업데이트
+ const updateResult = await updatePcrPo(id, {
+ pcrApprovalStatus: 'REJECTED',
+ rejectionReason: reason,
+ pcrResponseDate: new Date()
+ });
+
+ if (!updateResult.success) {
+ console.error(`❌ PCR 거절 상태 업데이트 실패: ${updateResult.error}`);
+ return { success: false, error: updateResult.error }
+ }
+
+ // 관련 페이지들 재검증
+ revalidatePath("/evcp/pcr");
+ revalidatePath("/partners/pcr");
+
+ console.log(`✅ PCR 거절 완료: ${confirmData.PCR_REQ}-${confirmData.PCR_REQ_SEQ}`);
+
+ return {
+ success: true,
+ message: "PCR이 성공적으로 거절되었습니다",
+ data: {
+ confirmResult,
+ updateResult: updateResult.data
+ }
+ }
+ } catch (error) {
+ console.error("PCR 거절 액션 오류:", error)
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "PCR 거절에 실패했습니다"
+ }
+ }
+}
+
+/**
+ * PCR 거절사유 수정 액션
+ */
+export async function updatePcrRejectionReasonAction(data: {
+ id: number;
+ rejectionReason?: string;
+}) {
+ try {
+ const session = await getServerSession(authOptions);
+ if (!session?.user?.id) {
+ throw new Error("로그인이 필요합니다.");
+ }
+
+ const now = new Date();
+ const updateData = {
+ rejectionReason: data.rejectionReason,
+ updatedBy: session.user.id,
+ updatedAt: now,
+ };
+
+ const result = await db
+ .update(pcrPo)
+ .set(updateData)
+ .where(eq(pcrPo.id, data.id))
+ .returning();
+
+ if (result.length === 0) {
+ throw new Error("PCR 데이터를 찾을 수 없습니다.");
+ }
+
+ // 캐시 무효화
+ revalidatePath("/evcp/pcr");
+ revalidatePath("/partners/pcr");
+
+ return {
+ success: true,
+ data: result[0],
+ };
+ } catch (error) {
+ console.error("PCR 수정 액션 오류:", error);
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "PCR 수정에 실패했습니다"
+ };
+ }
+}
\ No newline at end of file |
