safety-eval-service-frontend/docs/test-reports/测试用例/test-qual-filing-full-e2e.mjs

411 lines
15 KiB
JavaScript
Raw Normal View History

2026-06-30 17:32:29 +08:00
/**
* 资质申请管理 三模块完整流程联调模拟前端 persist 链路
*
* 运行: node docs/test-reports/测试用例/test-qual-filing-full-e2e.mjs
*/
import path from "node:path";
import { fileURLToPath } from "node:url";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const ROOT = path.resolve(__dirname, "../../..");
2026-07-02 14:51:26 +08:00
const API_BASE = process.env.API_BASE || "http://127.0.0.1:8095/safetyEval";
2026-06-30 17:32:29 +08:00
const ORG_INFO_ID = process.env.ORG_INFO_ID || "1";
const DEFAULT_URL =
"https://s1.aigei.com/prevfiles/6f2754563be2491bad7c957904cd7d2a.jpg?e=2051020800&token=P7S2Xpzfz11vAkASLTkfHN7Fw-oOZBecqeJaxypL:CR60zg7VKDp-jUWyYls_rdvyQMM=";
const issues = [];
let passed = 0;
let failed = 0;
const ctx = {};
function log(step, msg) {
console.log(`[${step}] ${msg}`);
}
function pass(name, detail = "") {
passed += 1;
console.log(`${name}${detail ? `${detail}` : ""}`);
}
function fail(name, detail = "") {
failed += 1;
console.log(`${name}${detail ? `${detail}` : ""}`);
}
function recordIssue(module, severity, title, detail) {
issues.push({ module, severity, title, detail });
}
async function api(method, apiPath, body) {
const res = await fetch(`${API_BASE}${apiPath}`, {
method,
headers: { "Content-Type": "application/json", orgInfoId: ORG_INFO_ID },
body: body !== undefined ? JSON.stringify(body) : undefined,
});
const text = await res.text();
try {
return { httpStatus: res.status, ...JSON.parse(text) };
}
catch {
return { httpStatus: res.status, success: false, raw: text };
}
}
async function uploadAllMaterials(filingId) {
const detail = await api("GET", `/qual-filing/detail?id=${filingId}`);
for (const m of detail.data?.materials || []) {
if (!m.attachmentUrl) {
await api("POST", "/qual-filing-material/upload", { id: m.id, attachmentUrl: DEFAULT_URL });
}
}
}
const FORMAL_BASIC = {
filingTerritoryName: "渝北区",
filingTerritoryCode: "渝北区",
filingUnitName: "重庆渝安安全评价技术有限公司",
filingUnitTypeCode: "本地单位",
filingUnitTypeName: "本地单位",
businessScope: "石油加工业,化学原料、化学品及医药制造业",
registerAddress: "重庆市渝北区黄山大道中段88号",
officeAddress: "重庆市渝北区黄山大道中段88号安全评价大厦12层",
creditCode: "91500000MA5U8K9X2L",
qualCertNo: "AQPJ-渝-2024-0018",
legalPersonPhone: "王建国 / 023-67891234",
contactPhone: "陈晓明 / 13912345678",
infoDisclosureUrl: "https://www.yuan-an-safety.com/disclosure",
fixedAssetAmount: 1580,
workplaceArea: 1860,
archiveRoomArea: 120,
fulltimeEvaluatorCount: 32,
registeredEngineerCount: 12,
unitIntro: "本公司成立于2018年主要从事安全评价、安全技术服务具备独立法人资格。",
attachmentUrl: DEFAULT_URL,
};
async function persistLikeFrontend(filingId, mode = "application") {
const saveRes = await api("POST", "/qual-filing/save-draft", { id: filingId, ...FORMAL_BASIC });
if (!saveRes.success) {
throw new Error(saveRes.message || "save-draft failed");
}
await api("POST", `/qual-filing-material/init-template?filingId=${filingId}`);
await uploadAllMaterials(filingId);
const commitmentContent =
"本人是王建国是重庆渝安安全评价技术有限公司法定代表人,现代表我单位承诺如下:本单位提交的资质备案申请材料真实、准确、完整。";
await api("POST", "/qual-filing-commitment/save-or-update", {
filingId,
signDate: "2026-06-30",
legalRepSignatureUrl: DEFAULT_URL,
commitmentContent,
});
const personnelPage = await api("GET", "/org-personnel/page?current=1&size=20");
const personnelIds = (personnelPage.data || []).map((p) => p.id).filter(Boolean);
if (personnelIds.length) {
await api("POST", "/qual-filing-personnel/batch-add-from-org", {
filingId,
sourcePersonnelIds: personnelIds,
});
}
const equipPage = await api("GET", "/org-equipment/page?current=1&size=20");
const equipIds = (equipPage.data || []).map((e) => e.id).filter(Boolean);
if (equipIds.length) {
await api("POST", "/qual-filing-equipment/batch-add-from-org", {
filingId,
sourceEquipmentIds: equipIds,
});
}
return api("GET", `/qual-filing/detail?id=${filingId}`);
}
// ── 模块1资质备案申请 ──
async function testModule1Application() {
console.log("\n=== 模块1资质备案申请 ===");
const existingPage = await api("GET", "/qual-filing/page?current=1&size=5&applyTypeCode=1&filingStatusCode=5");
let filingId = existingPage.data?.[0]?.id;
if (filingId) {
pass("复用已有暂存记录", `id=${filingId}`);
}
else {
const draft = await api("POST", "/qual-filing/draft?applyTypeCode=1");
filingId = draft.data?.id;
if (draft.success && filingId) {
pass("新建申请草稿", `id=${filingId}`);
}
else {
fail("新建申请草稿", draft.message);
return;
}
}
ctx.applicationId = filingId;
const detailRes = await persistLikeFrontend(filingId);
const detail = detailRes.data || {};
pass("暂存-基本信息", detail.filingUnitName);
pass("暂存-材料10项已上传", (detail.materials || []).every((m) => m.uploadStatusCode === 2));
pass("暂存-承诺书", !!detail.commitment?.commitmentContent);
pass("暂存-人员", `count=${(detail.personnelList || []).length}`);
pass("暂存-装备", `count=${(detail.equipmentList || []).length}`);
const listRes = await api("GET", "/qual-filing/page?current=1&size=20&applyTypeCode=1");
const inList = (listRes.data || []).some((r) => String(r.id) === String(filingId));
if (inList && detail.filingStatusCode === 5) {
pass("列表-暂存记录可见", detail.filingStatusName);
}
else {
fail("列表-暂存记录可见", `status=${detail.filingStatusCode}`);
}
const reload = await api("GET", `/qual-filing/detail?id=${filingId}`);
if (reload.data?.businessScope?.includes("化学")) {
pass("回显-修改后业务范围");
}
else {
fail("回显-修改后业务范围");
}
const verifyMod = await import(path.join(ROOT, "src/pages/Container/QualApplication/filingVerify.js"));
const verifyResult = verifyMod.verifyFilingPrerequisites({
...FORMAL_BASIC,
materials: reload.data?.materials || [],
personnelList: reload.data?.personnelList || [],
equipmentList: reload.data?.equipmentList || [],
});
if (!verifyResult.passed) {
const failedItems = verifyResult.items.filter((i) => !i.passed).map((i) => i.label);
recordIssue(
"资质备案申请",
"阻塞",
"前端提交核验:人员数量/结构未通过",
`当前机构人员 ${(reload.data?.personnelList || []).length} 人,核验失败项:${failedItems.join("、")}。用户要求测试阶段暂不判断此项,但前端「提交申请」确认按钮仍被禁用。`,
);
pass("前端核验-预期失败(人员不足)", failedItems.join(","));
}
else {
pass("前端核验-全部通过");
}
const submit = await api("POST", `/qual-filing/submit?id=${filingId}`);
if (submit.success && submit.data?.filingStatusCode === 2) {
pass("后端提交-进入审核中", submit.data.filingStatusName);
}
else {
fail("后端提交", submit.message);
recordIssue("资质备案申请", "阻塞", "后端提交失败", submit.message || JSON.stringify(submit));
return;
}
const approve = await api("POST", `/qual-filing/approve?id=${filingId}`);
if (approve.success && approve.data?.filingStatusCode === 1) {
pass("审核通过-已备案", approve.data.filingStatusName);
ctx.approvedApplicationId = filingId;
}
else {
fail("审核通过", approve.message || approve.data?.filingStatusName);
}
}
// ── 模块2已备案资质管理 ──
async function testModule2FiledManage() {
console.log("\n=== 模块2已备案资质管理 ===");
const filedPage = await api("GET", "/qual-filing/filed/page?current=1&size=20");
const filedList = filedPage.data || [];
if (filedList.length > 0) {
pass("已备案列表有数据", `count=${filedList.length}`);
ctx.originFiledId = filedList[0].id;
}
else {
fail("已备案列表有数据", "审核通过后应出现 applyType=3 记录");
recordIssue("已备案资质管理", "阻塞", "审核通过后已备案列表为空", "需确认 approve 是否创建 filed 记录");
return;
}
const origin = filedList[0];
if (origin.applyTypeCode === 3) {
pass("已备案记录类型", origin.applyTypeName);
}
else {
fail("已备案记录类型", `applyTypeCode=${origin.applyTypeCode}`);
}
const filedDraft = await api("POST", "/qual-filing/filed/draft");
const filedDraftId = filedDraft.data?.id;
if (!filedDraft.success || !filedDraftId) {
fail("资质备案填报-创建草稿", filedDraft.message);
return;
}
pass("资质备案填报-创建草稿", `id=${filedDraftId}`);
ctx.filedDraftId = filedDraftId;
const saveRes = await persistLikeFrontend(filedDraftId);
const detail = saveRes.data || {};
if (detail.filingStatusCode === 5 && detail.applyTypeCode === 3) {
pass("填报暂存", `${detail.filingStatusName} applyType=${detail.applyTypeCode}`);
}
else {
fail("填报暂存", `status=${detail.filingStatusCode} type=${detail.applyTypeCode}`);
}
const filedPageDefault = await api("GET", "/qual-filing/filed/page?current=1&size=20");
const draftInDefaultList = (filedPageDefault.data || []).some((r) => String(r.id) === String(filedDraftId));
if (!draftInDefaultList) {
pass("已备案列表-默认不含填报暂存");
}
else {
fail("已备案列表-默认不含填报暂存");
recordIssue("已备案资质管理", "一般", "填报暂存不应出现在默认已备案列表", `draftId=${filedDraftId}`);
}
const filedPageDraftFilter = await api("GET", "/qual-filing/filed/page?current=1&size=20&filingStatusCode=5");
const draftInFilteredList = (filedPageDraftFilter.data || []).some((r) => String(r.id) === String(filedDraftId));
if (draftInFilteredList) {
pass("已备案列表-显式筛选暂存可见");
}
else {
fail("已备案列表-显式筛选暂存可见", `draftId=${filedDraftId}`);
}
}
// ── 模块3备案变更管理 ──
async function testModule3FilingChange() {
console.log("\n=== 模块3备案变更管理 ===");
const originId = ctx.originFiledId;
if (!originId) {
fail("发起变更", "无已备案 origin 记录");
return;
}
const changePage = await api("GET", "/qual-filing/change/page?current=1&size=20");
const changeList = changePage.data || [];
if (changeList.length > 0) {
pass("变更列表有数据", `count=${changeList.length}`);
}
else {
fail("变更列表有数据", "应有已备案记录");
}
const origin = changeList.find((r) => String(r.id) === String(originId)) || changeList[0];
if (!origin) {
fail("变更源记录", "未找到");
return;
}
if (origin.filingStatusCode === 4) {
recordIssue("备案变更管理", "阻塞", "已备案记录处于变更审核中", "无法再次发起变更");
fail("可发起变更", "状态=变更审核中");
return;
}
pass("可发起变更", origin.filingStatusName);
const start = await api("POST", `/qual-filing-change/start?originFilingId=${originId}`);
const draftId = start.data?.draftFilingId || start.data;
if (!start.success || !draftId) {
fail("发起变更", start.message);
return;
}
pass("发起变更", `draftId=${draftId}`);
ctx.changeDraftId = draftId;
const changeBasic = {
...FORMAL_BASIC,
businessScope: "石油加工业,化学原料、化学品及医药制造业;金属、非金属矿及其他矿采选业",
unitIntro: "变更后:新增矿山采选业安全评价业务范围。",
};
await api("POST", "/qual-filing/save-draft", { id: draftId, ...changeBasic });
await uploadAllMaterials(draftId);
await api("POST", "/qual-filing-commitment/save-or-update", {
filingId: draftId,
signDate: "2026-06-30",
legalRepSignatureUrl: DEFAULT_URL,
commitmentContent: "变更备案承诺书",
});
const changeDetail = await api("GET", `/qual-filing/detail?id=${draftId}`);
if (changeDetail.data?.businessScope?.includes("矿采选业")) {
pass("变更草稿-业务范围已修改");
}
else {
fail("变更草稿-业务范围已修改", changeDetail.data?.businessScope);
}
const changeSubmit = await api("POST", "/qual-filing-change/submit", { draftFilingId: draftId });
if (changeSubmit.success) {
pass("提交变更", "success");
}
else {
fail("提交变更", changeSubmit.message);
recordIssue("备案变更管理", "阻塞", "变更提交失败", changeSubmit.message);
return;
}
const history = await api("GET", `/qual-filing-change/history?originFilingId=${originId}`);
const changeCount = history.data?.changeCount ?? 0;
if (history.success && changeCount > 0) {
pass("变更历史", `changeCount=${changeCount}`);
}
else {
fail("变更历史", `count=${changeCount}`);
}
const changeAfter = await api("GET", "/qual-filing/change/page?current=1&size=20");
const updated = (changeAfter.data || []).find((r) => String(r.id) === String(originId));
if (updated?.changeCount > 0) {
pass("变更列表-变更次数更新", `${updated.filingStatusName} count=${updated.changeCount}`);
}
else {
fail("变更列表-变更次数更新");
recordIssue("备案变更管理", "一般", "变更列表变更次数未更新", `originId=${originId}`);
}
}
async function checkDataQuality() {
console.log("\n=== 数据质量检查 ===");
const personnelPage = await api("GET", "/org-personnel/page?current=1&size=10");
const missingName = (personnelPage.data || []).filter((p) => !p.personName && !p.staffName);
if (missingName.length) {
recordIssue(
"通用",
"一般",
"机构人员主数据姓名为空",
`${missingName.length} 条人员记录 personName/staffName 为空,表单人员列表可能显示空白。`,
);
pass("人员主数据-姓名缺失(已知)", `count=${missingName.length}`);
}
}
async function main() {
console.log("资质申请管理 — 三模块完整流程联调");
console.log(`API=${API_BASE} orgInfoId=${ORG_INFO_ID}\n`);
await checkDataQuality();
await testModule1Application();
await testModule2FiledManage();
await testModule3FilingChange();
console.log(`\n=== 结果: ${passed} 通过, ${failed} 失败 ===`);
console.log(`=== 问题记录: ${issues.length} 条 ===\n`);
for (const [i, issue] of issues.entries()) {
console.log(`${i + 1}. [${issue.module}] [${issue.severity}] ${issue.title}`);
console.log(` ${issue.detail}\n`);
}
return { passed, failed, issues, ctx };
}
const result = await main();
if (result.failed > 0) {
process.exitCode = 1;
}
export default result;