// 운영 E2E: 가입(또는 기존 로그인) → 발주 → 관리자 승인 → 메일 // 모든 거래처 비밀번호: test1234 (AES 인코딩 일치) // 관리자: plm_admin / qlalfqjsgh11 (FITO 마스터) import pg from "pg"; const BASE = process.env.E2E_BASE || "https://momo.junggomoa.com"; const DB_URL = "postgresql://momo_app:qlalfqjsgh11@183.99.177.40:5432/distribution"; const log = (...a) => console.log("[e2e]", ...a); const fail = (m) => { console.error("[e2e] ✖", m); process.exit(1); }; const apiClient = (jar) => async (path, init = {}) => { const res = await fetch(`${BASE}${path}`, { ...init, headers: { "Content-Type": "application/json", ...(jar.value ? { Cookie: jar.value } : {}), ...(init.headers ?? {}), }, redirect: "manual", }); const sc = res.headers.getSetCookie?.() || []; for (const c of sc) { const kv = c.split(";")[0]; const k = kv.split("=")[0]; jar.value = jar.value ? jar.value.split("; ").filter((p) => !p.startsWith(k + "=")).concat(kv).join("; ") : kv; } const text = await res.text(); let json; try { json = JSON.parse(text); } catch { json = { raw: text.slice(0, 200) }; } return { status: res.status, body: json }; }; // 1. 헬스체크 log("0. 헬스체크"); const h = await fetch(`${BASE}/`); log(` ${h.status} ${BASE}/`); // 2. DB 시드 검증 const db = new pg.Client({ connectionString: DB_URL }); await db.connect(); const itemRows = await db.query(`SELECT objid, item_name FROM momo_items WHERE item_code LIKE 'SAMP-%' ORDER BY item_code LIMIT 5`); log(` 샘플 품목 ${itemRows.rowCount}개 확인`); // 3. 거래처 로그인 (chpark@wace.me / test1234) log("1. 거래처 로그인 — chpark@wace.me"); const userJar = { value: "" }; const userApi = apiClient(userJar); const login = await userApi("/api/auth/login", { method: "POST", body: JSON.stringify({ userId: "chpark@wace.me", password: "test1234" }), }); if (!login.body.success) fail(`거래처 로그인 실패: ${JSON.stringify(login.body)}`); log(` ✔ 로그인 성공, redirectTo=${login.body.redirectTo}`); // 4. 품목 조회 log("2. 품목 검색"); const items = await userApi("/api/m/items/list", { method: "POST", body: JSON.stringify({ keyword: "SAMP" }), }); const visible = (items.body.RESULTLIST || []).filter((r) => r.ITEM_CODE?.startsWith("SAMP-")); if (visible.length === 0) fail(`품목 조회 실패: ${JSON.stringify(items.body)}`); log(` ✔ ${visible.length}개 품목 노출 (재고 ${visible[0].STOCK_QTY})`); // 5. 출고 요청 log("3. 출고 요청"); const order = await userApi("/api/m/orders/save", { method: "POST", body: JSON.stringify({ lines: [ { itemObjid: visible[0].OBJID, qty: 5 }, { itemObjid: visible[1]?.OBJID, qty: 3 }, ].filter((l) => l.itemObjid), memo: "최종 E2E 테스트", }), }); if (!order.body.success) fail(`발주 실패: ${JSON.stringify(order.body)}`); log(` ✔ 발주번호 ${order.body.orderNo}`); // 6. 관리자 로그인 log("4. 관리자 로그인 (plm_admin)"); const adminJar = { value: "" }; const adminApi = apiClient(adminJar); const adminLogin = await adminApi("/api/auth/login", { method: "POST", body: JSON.stringify({ userId: "plm_admin", password: "qlalfqjsgh11" }), }); if (!adminLogin.body.success) fail(`관리자 로그인 실패: ${JSON.stringify(adminLogin.body)}`); log(` ✔ 관리자 세션`); // 7. 출고 관리 목록 조회 log("5. 출고 목록 조회 (관리자)"); const orderList = await adminApi("/api/m/orders/list", { method: "POST", body: JSON.stringify({ status: "REQUESTED" }), }); log(` 요청 상태 발주: ${orderList.body.RESULTLIST?.length ?? 0}건`); // 8. 발주 승인 + 메일 발송 log("6. 발주 승인 (메일 자동 발송)"); const approve = await adminApi("/api/m/orders/approve", { method: "POST", body: JSON.stringify({ objid: order.body.objId }), }); if (!approve.body.success) fail(`승인 실패: ${JSON.stringify(approve.body)}`); log(` ✔ 승인 완료. mailSent=${approve.body.mailSent}, error=${approve.body.mailError ?? "(none)"}`); // 9. 후속 검증 const finalRow = await db.query( `SELECT order_no, status, total_amount, total_taxfree, total_taxable FROM momo_orders WHERE objid = $1`, [order.body.objId] ); log(` 주문 ${finalRow.rows[0].order_no}: status=${finalRow.rows[0].status}, total=${finalRow.rows[0].total_amount}`); const mailRow = await db.query( `SELECT to_email, subject, status FROM momo_mail_logs WHERE ref_objid = $1 ORDER BY regdate DESC LIMIT 1`, [order.body.objId] ); if (mailRow.rowCount > 0) { const m = mailRow.rows[0]; log(` 메일 → ${m.to_email}, status=${m.status}, subject=${m.subject}`); } await db.end(); log("✔ E2E 전체 통과");