完成五人团队正式内用最小收口(07-18-small-team-internal-readiness)

这个提交包含在:
2026-07-18 15:46:14 +08:00
父节点 58c8decef9
当前提交 5d0a5f9a38
共修改 134 个文件,包含 10790 行新增和 1413 行删除
@@ -131,9 +131,15 @@ async function buildApp({
},
};
});
const attachmentDelete = vi.fn(async ({ where }) => {
if (state.attachment?.id === where.id) {
state.attachment = null;
}
return { id: where.id };
});
const tx = {
purchaseAttachment: { create: attachmentCreate },
purchaseAttachment: { create: attachmentCreate, delete: attachmentDelete },
auditLog: { create: uploadAuditCreate },
};
const prisma = {
@@ -211,6 +217,7 @@ async function buildApp({
return {
app,
attachmentCreate,
attachmentDelete,
downloadAuditCreate,
prisma,
state,
@@ -470,6 +477,58 @@ describe("purchase attachment upload", () => {
});
});
describe("purchase attachment delete", () => {
it("requires a reason and records it with the attachment audit", async () => {
const { app, attachmentDelete, state, uploadAuditCreate } = await buildApp();
try {
const response = await app.inject({
method: "DELETE",
url: `/api/purchase-requests/${PURCHASE_REQUEST_ID}/attachments/${ATTACHMENT_ID}`,
headers: { authorization: "Bearer unit-test", "content-type": "application/json" },
payload: { reason: "重复上传" },
});
expect(response.statusCode).toBe(200);
expect(response.json().data).toEqual({ outcome: "deleted", attachmentId: ATTACHMENT_ID });
expect(attachmentDelete).toHaveBeenCalledWith({ where: { id: ATTACHMENT_ID } });
expect(uploadAuditCreate).toHaveBeenCalledWith(
expect.objectContaining({
data: expect.objectContaining({
action: "PURCHASE_ATTACHMENT_DELETED",
target_id: ATTACHMENT_ID,
extra: expect.objectContaining({ purchaseRequestId: PURCHASE_REQUEST_ID, reason: "重复上传" }),
}),
}),
);
expect(state.attachment).toBeNull();
} finally {
await app.close();
}
});
it("rejects a missing reason before attachment lookup or deletion", async () => {
const { app, attachmentDelete, prisma, uploadAuditCreate } = await buildApp();
try {
const response = await app.inject({
method: "DELETE",
url: `/api/purchase-requests/${PURCHASE_REQUEST_ID}/attachments/${ATTACHMENT_ID}`,
headers: { authorization: "Bearer unit-test", "content-type": "application/json" },
payload: {},
});
expect(response.statusCode).toBe(400);
expect(response.json().error.code).toBe("VALID_001");
expect(prisma.purchaseRequest.findUnique).not.toHaveBeenCalled();
expect(attachmentDelete).not.toHaveBeenCalled();
expect(uploadAuditCreate).not.toHaveBeenCalled();
} finally {
await app.close();
}
});
});
describe("purchase attachment authenticated download", () => {
const downloadUrl = `/api/purchase-requests/${PURCHASE_REQUEST_ID}/attachments/${ATTACHMENT_ID}/download`;