summaryrefslogtreecommitdiff
path: root/lib/dolce/actions.ts
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dolce/actions.ts')
-rw-r--r--lib/dolce/actions.ts258
1 files changed, 220 insertions, 38 deletions
diff --git a/lib/dolce/actions.ts b/lib/dolce/actions.ts
index 552a9a6a..8c5dfa1b 100644
--- a/lib/dolce/actions.ts
+++ b/lib/dolce/actions.ts
@@ -172,7 +172,7 @@ async function dolceApiCall<T>(endpoint: string, body: Record<string, unknown>):
});
if (!response.ok) {
- throw new Error(`DOLCE API 오류 (${endpoint}): ${response.status} ${response.statusText}`);
+ throw new Error(`DOLCE API error (${endpoint}): ${response.status} ${response.statusText}`);
}
const data = await response.json();
@@ -356,7 +356,7 @@ export async function downloadDolceFile(params: {
if (!response.ok) {
const errorText = await response.text();
console.error("[DOLCE] 에러 응답:", errorText);
- throw new Error(`파일 다운로드 실패: ${response.status} - ${errorText}`);
+ throw new Error(`File download failed: ${response.status} - ${errorText}`);
}
// HTML/텍스트 응답인 경우 에러일 수 있음
@@ -364,7 +364,7 @@ export async function downloadDolceFile(params: {
if (contentType.includes("text") || contentType.includes("html")) {
const errorText = await response.text();
console.error("[DOLCE] 텍스트 응답 (에러):", errorText);
- throw new Error(`예상치 못한 응답: ${errorText.substring(0, 200)}`);
+ throw new Error(`Unexpected response: ${errorText.substring(0, 200)}`);
}
const blob = await response.blob();
@@ -387,7 +387,7 @@ export async function getVendorSessionInfo() {
try {
const session = await getServerSession(authOptions);
if (!session?.user) {
- throw new Error("로그인이 필요합니다");
+ throw new Error("Login required");
}
// DB에서 사용자 정보 조회
@@ -403,7 +403,7 @@ export async function getVendorSessionInfo() {
});
if (!userInfo || !userInfo.companyId) {
- throw new Error("벤더 정보를 찾을 수 없습니다");
+ throw new Error("Vendor information not found");
}
// 벤더 정보 조회
@@ -417,7 +417,7 @@ export async function getVendorSessionInfo() {
});
if (!vendorInfo) {
- throw new Error("벤더 정보를 찾을 수 없습니다");
+ throw new Error("Vendor information not found");
}
// GTT 벤더 확인 (A0016193)
@@ -582,7 +582,7 @@ export async function uploadFilesToDetailDrawing(
const fileCount = parseInt(formData.get("fileCount") as string);
if (!uploadId || !userId || !fileCount) {
- throw new Error("필수 파라미터가 누락되었습니다");
+ throw new Error("Required parameters are missing");
}
const uploadResults: Array<{
@@ -629,7 +629,7 @@ export async function uploadFilesToDetailDrawing(
if (!uploadResponse.ok) {
throw new Error(
- `파일 업로드 실패: ${uploadResponse.status} ${uploadResponse.statusText}`
+ `File upload failed: ${uploadResponse.status} ${uploadResponse.statusText}`
);
}
@@ -661,13 +661,13 @@ export async function uploadFilesToDetailDrawing(
if (!resultResponse.ok) {
throw new Error(
- `업로드 완료 통지 실패: ${resultResponse.status} ${resultResponse.statusText}`
+ `Upload notification failed: ${resultResponse.status} ${resultResponse.statusText}`
);
}
const resultText = await resultResponse.text();
if (resultText !== "Success") {
- throw new Error(`업로드 완료 통지 실패: ${resultText}`);
+ throw new Error(`Upload notification failed: ${resultText}`);
}
return {
@@ -678,7 +678,7 @@ export async function uploadFilesToDetailDrawing(
console.error("파일 업로드 실패:", error);
return {
success: false,
- error: error instanceof Error ? error.message : "알 수 없는 오류",
+ error: error instanceof Error ? error.message : "Unknown error",
};
}
}
@@ -747,7 +747,7 @@ async function parseB4FileName(fileName: string): Promise<{
try {
const lastDotIndex = fileName.lastIndexOf(".");
if (lastDotIndex === -1) {
- return { valid: false, error: "파일 확장자가 없습니다" };
+ return { valid: false, error: "File extension is missing" };
}
const nameWithoutExt = fileName.substring(0, lastDotIndex);
@@ -756,7 +756,7 @@ async function parseB4FileName(fileName: string): Promise<{
if (parts.length < 3) {
return {
valid: false,
- error: `공백이 최소 2개 있어야 합니다 (현재: ${parts.length - 1}개)`,
+ error: `At least 2 spaces required (current: ${parts.length - 1})`,
};
}
@@ -765,30 +765,212 @@ async function parseB4FileName(fileName: string): Promise<{
const drawingNo = drawingTokens.join("-");
if (!drawingNo || !revNo) {
- return { valid: false, error: "도면번호 또는 리비전번호가 비어있습니다" };
+ return { valid: false, error: "Drawing number or revision number is empty" };
}
return { valid: true, drawingNo: drawingNo.trim(), revNo: revNo.trim() };
} catch (error) {
return {
valid: false,
- error: error instanceof Error ? error.message : "알 수 없는 오류",
+ error: error instanceof Error ? error.message : "Unknown error",
};
}
}
/**
- * B4 파일 일괄 업로드 V2
+ * B4 일괄 업로드를 위한 상세도면 준비 (V2)
*
- * MatchBatchFileDwg/MatchBatchFileDwgEdit API 대신
- * DetailDwgReceiptMgmtEdit API와 업로드 서비스만 사용
+ * 반환값: DrawingNo + RevNo별 UploadId 정보
+ * 파일 업로드는 클라이언트에서 직접 처리
+ */
+export interface B4DetailDrawingInfo {
+ drawingNo: string;
+ revNo: string;
+ uploadId: string;
+ isNew: boolean; // 새로 생성된 상세도면인지 여부
+ drawingName?: string;
+ discipline?: string;
+}
+
+export async function prepareB4DetailDrawingsV2(params: {
+ projectNo: string;
+ userId: string;
+ userNm: string;
+ email: string;
+ vendorCode: string;
+ registerKind: string;
+ drawingRevisions: Array<{ drawingNo: string; revNo: string }>;
+}): Promise<{
+ success: boolean;
+ detailDrawings?: B4DetailDrawingInfo[];
+ error?: string;
+}> {
+ try {
+ console.log("[V2 Prepare] 상세도면 준비 시작");
+
+ const { projectNo, userId, userNm, email, vendorCode, registerKind, drawingRevisions } = params;
+
+ const detailDrawings: B4DetailDrawingInfo[] = [];
+
+ // 중복 제거: 동일한 DrawingNo + RevNo 조합은 1번만 처리
+ const uniqueRevisions = Array.from(
+ new Map(
+ drawingRevisions.map((r) => [`${r.drawingNo}_${r.revNo}`, r])
+ ).values()
+ );
+
+ if (uniqueRevisions.length !== drawingRevisions.length) {
+ console.warn(
+ `[V2 Prepare] 중복 제거: ${drawingRevisions.length}개 → ${uniqueRevisions.length}개`
+ );
+ }
+
+ console.log(`[V2 Prepare] 처리할 리비전: ${uniqueRevisions.length}개`);
+
+ // DrawingNo별로 그룹화
+ const drawingNoSet = new Set(uniqueRevisions.map((r) => r.drawingNo));
+ const drawingInfoMap = new Map<string, GttDwgReceiptItem>();
+
+ // 1. 기본 도면 정보 조회
+ for (const drawingNo of drawingNoSet) {
+ try {
+ const dwgList = await fetchDwgReceiptList({
+ project: projectNo,
+ drawingKind: "B4",
+ drawingMoveGbn: "도면입수",
+ drawingNo: drawingNo,
+ });
+
+ const dwgInfo = dwgList.find(
+ (d) => (d as GttDwgReceiptItem).DrawingNo === drawingNo
+ ) as GttDwgReceiptItem | undefined;
+
+ if (dwgInfo) {
+ drawingInfoMap.set(drawingNo, dwgInfo);
+ }
+ } catch (error) {
+ console.error(`[V2 Prepare] 도면 정보 조회 실패: ${drawingNo}`, error);
+ }
+ }
+
+ // 2. 각 RevNo별로 상세도면 확인/생성 (중복 제거된 리스트 사용)
+ for (const { drawingNo, revNo } of uniqueRevisions) {
+ try {
+ const drawingInfo = drawingInfoMap.get(drawingNo);
+ if (!drawingInfo) {
+ throw new Error(`Drawing information not found: ${drawingNo}`);
+ }
+
+ console.log(`[V2 Prepare] 처리 중: ${drawingNo} Rev.${revNo}`);
+
+ // 기존 상세도면 조회
+ const detailDwgList = await fetchDetailDwgReceiptList({
+ project: projectNo,
+ drawingNo: drawingNo,
+ discipline: drawingInfo.Discipline,
+ drawingKind: "B4",
+ userId: userId,
+ });
+
+ // 해당 RevNo의 상세도면 찾기
+ const existingDetail = detailDwgList.find(
+ (d) => d.DrawingRevNo === revNo
+ );
+
+ let uploadId: string;
+ let isNew = false;
+
+ if (existingDetail) {
+ // 1. 기존 상세도면이 있는 경우: 해당 uploadId 재사용
+ uploadId = existingDetail.UploadId;
+ isNew = false;
+ console.log(
+ `[V2 Prepare] ✓ 기존 상세도면 재사용: ${drawingNo} Rev.${revNo}, UploadId: ${uploadId}`
+ );
+ } else {
+ // 2. 상세도면이 없는 경우: 새로 1번만 생성
+ uploadId = crypto.randomUUID();
+ isNew = true;
+ console.log(
+ `[V2 Prepare] ✓ 새 상세도면 생성: ${drawingNo} Rev.${revNo}, UploadId: ${uploadId}`
+ );
+
+ const category = detailDwgList.length > 0 ? detailDwgList[0].Category : "NORM";
+
+ const addRequest: DetailDwgEditRequest = {
+ Mode: "ADD",
+ Status: "01",
+ RegisterId: 0,
+ ProjectNo: projectNo,
+ Discipline: drawingInfo.Discipline,
+ DrawingKind: "B4",
+ DrawingNo: drawingNo,
+ DrawingName: drawingInfo.DrawingName,
+ RegisterGroupId: drawingInfo.RegisterGroupId,
+ RegisterSerialNo: drawingInfo.RegisterGroup,
+ RegisterKind: registerKind,
+ DrawingRevNo: revNo,
+ Category: category,
+ Receiver: null,
+ Manager: drawingInfo.Manager || "970043",
+ RegisterDesc: "",
+ UploadId: uploadId,
+ RegCompanyCode: vendorCode,
+ };
+
+ await editDetailDwgReceipt({
+ dwgList: [addRequest],
+ userId: userId,
+ userNm: userNm,
+ vendorCode: vendorCode,
+ email: email,
+ });
+
+ console.log(`[V2 Prepare] ✓ DetailDwgReceiptMgmtEdit 호출 완료`);
+ }
+
+ detailDrawings.push({
+ drawingNo,
+ revNo,
+ uploadId,
+ isNew,
+ drawingName: drawingInfo.DrawingName,
+ discipline: drawingInfo.Discipline,
+ });
+ } catch (error) {
+ console.error(
+ `[V2 Prepare] ✗ 상세도면 준비 실패: ${drawingNo} Rev.${revNo}`,
+ error
+ );
+ throw error;
+ }
+ }
+
+ const newCount = detailDrawings.filter((d) => d.isNew).length;
+ const existingCount = detailDrawings.length - newCount;
+
+ console.log(
+ `[V2 Prepare] ✓ 완료: 총 ${detailDrawings.length}개 (신규: ${newCount}개, 기존: ${existingCount}개)`
+ );
+
+ return {
+ success: true,
+ detailDrawings,
+ };
+ } catch (error) {
+ console.error("[V2 Prepare] 실패:", error);
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : "Unknown error",
+ };
+ }
+}
+
+/**
+ * B4 파일 일괄 업로드 V2 (레거시 - 사용 안 함)
*
- * 프로세스:
- * 1. 파일명 파싱하여 DrawingNo, RevNo 추출
- * 2. 기존 도면 정보 조회 (fetchDwgReceiptList)
- * 3. 기존 상세도면 조회 (fetchDetailDwgReceiptList)
- * 4. 없으면 ADD, 있으면 기존 UploadId 사용
- * 5. 파일 업로드 (/api/dolce/upload-files)
+ * @deprecated 서버 액션에서 fetch 호출 시 상대 경로 문제로 사용 중단
+ * 대신 prepareB4DetailDrawingsV2 + 클라이언트 uploadFilesWithProgress 사용
*/
export async function bulkUploadB4FilesV2(
formData: FormData
@@ -806,7 +988,7 @@ export async function bulkUploadB4FilesV2(
const fileCount = parseInt(formData.get("fileCount") as string);
if (!projectNo || !userId || !userNm || !email || !vendorCode || !registerKind || !fileCount) {
- throw new Error("필수 파라미터가 누락되었습니다");
+ throw new Error("Required parameters are missing");
}
console.log(`[V2] 프로젝트: ${projectNo}, 사용자: ${userId}, 파일 수: ${fileCount}`);
@@ -843,7 +1025,7 @@ export async function bulkUploadB4FilesV2(
revNo: "",
fileName: file.name,
success: false,
- error: parseResult.error || "파일명 파싱 실패",
+ error: parseResult.error || "Failed to parse filename",
});
failCount++;
continue;
@@ -922,7 +1104,7 @@ export async function bulkUploadB4FilesV2(
// 도면 정보가 없으면 실패
if (!drawingInfo) {
- throw new Error(`도면 정보를 찾을 수 없습니다: ${drawingNo}`);
+ throw new Error(`Drawing information not found: ${drawingNo}`);
}
// 4-1. 기존 상세도면 조회
@@ -1009,13 +1191,13 @@ export async function bulkUploadB4FilesV2(
if (!uploadResponse.ok) {
const errorData = await uploadResponse.json();
- throw new Error(errorData.error || `파일 업로드 실패: ${uploadResponse.status}`);
+ throw new Error(errorData.error || `File upload failed: ${uploadResponse.status}`);
}
const uploadResult = await uploadResponse.json();
if (!uploadResult.success) {
- throw new Error(uploadResult.error || "파일 업로드 실패");
+ throw new Error(uploadResult.error || "File upload failed");
}
console.log(`[V2] 파일 업로드 완료: ${groupKey}`);
@@ -1033,7 +1215,7 @@ export async function bulkUploadB4FilesV2(
} catch (error) {
// 실패 처리
const errorMessage =
- error instanceof Error ? error.message : "알 수 없는 오류";
+ error instanceof Error ? error.message : "Unknown error";
console.error(`[V2] 그룹 처리 실패: ${groupKey}`, error);
@@ -1062,7 +1244,7 @@ export async function bulkUploadB4FilesV2(
console.error("[V2] 일괄 업로드 실패:", error);
return {
success: false,
- error: error instanceof Error ? error.message : "알 수 없는 오류",
+ error: error instanceof Error ? error.message : "Unknown error",
};
}
}
@@ -1082,7 +1264,7 @@ export async function bulkUploadB4Files(
const registerKind = formData.get("registerKind") as string;
if (!projectNo || !userId || !fileCount || !registerKind) {
- throw new Error("필수 파라미터가 누락되었습니다");
+ throw new Error("Required parameters are missing");
}
const results: Array<{
@@ -1176,7 +1358,7 @@ export async function bulkUploadB4Files(
if (!uploadResponse.ok) {
throw new Error(
- `파일 업로드 실패: ${uploadResponse.status} ${uploadResponse.statusText}`
+ `File upload failed: ${uploadResponse.status} ${uploadResponse.statusText}`
);
}
@@ -1208,13 +1390,13 @@ export async function bulkUploadB4Files(
if (!resultResponse.ok) {
throw new Error(
- `업로드 완료 통지 실패: ${resultResponse.status} ${resultResponse.statusText}`
+ `Upload notification failed: ${resultResponse.status} ${resultResponse.statusText}`
);
}
const resultText = await resultResponse.text();
if (resultText !== "Success") {
- throw new Error(`업로드 완료 통지 실패: ${resultText}`);
+ throw new Error(`Upload notification failed: ${resultText}`);
}
// 4. 매핑 현황 재조회 (MatchBatchFileDwg)
@@ -1228,7 +1410,7 @@ export async function bulkUploadB4Files(
const mappingData = mappingCheckResults[0];
if (!mappingData || mappingData.RegisterGroupId === 0) {
- throw new Error("매핑 정보를 찾을 수 없습니다");
+ throw new Error("Mapping information not found");
}
// 5. 매핑 정보 저장 (MatchBatchFileDwgEdit)
@@ -1278,7 +1460,7 @@ export async function bulkUploadB4Files(
} catch (error) {
// 실패 처리
const errorMessage =
- error instanceof Error ? error.message : "알 수 없는 오류";
+ error instanceof Error ? error.message : "Unknown error";
for (const fileInfo of files) {
results.push({
@@ -1303,7 +1485,7 @@ export async function bulkUploadB4Files(
console.error("일괄 업로드 실패:", error);
return {
success: false,
- error: error instanceof Error ? error.message : "알 수 없는 오류",
+ error: error instanceof Error ? error.message : "Unknown error",
};
}
}