You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
chajia/__tests__/api/admin-markup-routes.test.ts

268 lines
8.4 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import { beforeEach, describe, expect, it, vi } from "vitest";
import { GET } from "@/app/api/admin/markup-configs/route";
import { PUT } from "@/app/api/admin/markup-configs/[customer_id]/route";
import { resetServiceTokenCache } from "@/modules/auth/service-token";
vi.mock("@/lib/prisma", () => ({
prisma: {
markupConfig: {
findMany: vi.fn(),
findFirst: vi.fn(),
create: vi.fn(),
update: vi.fn(),
},
hostCustomer: {
findMany: vi.fn().mockResolvedValue([]),
findFirst: vi.fn().mockResolvedValue(null),
},
businessCustomer: {
findMany: vi.fn().mockResolvedValue([]),
findFirst: vi.fn().mockResolvedValue(null),
count: vi.fn().mockResolvedValue(1),
},
businessCustomerUser: {
findMany: vi.fn().mockResolvedValue([]),
},
auditLog: {
create: vi.fn(),
},
},
}));
import { prisma } from "@/lib/prisma";
const ADMIN_HEADERS = {
authorization: "Bearer admin-jwt",
"x-auth-type": "admin",
"x-user-id": "admin_demo",
"x-user-role": "admin",
};
describe("admin markup-configs API", () => {
beforeEach(() => {
vi.clearAllMocks();
resetServiceTokenCache();
process.env.HOST_SERVICE_TOKENS = JSON.stringify({
"demo-host-token": {
customerId: "CUST_001",
permissions: ["pricing:markup:write"],
},
});
process.env.CUSTOMER_REGISTRY = "CUST_002,CUST_003";
});
it("GET 仅返回业务客户加价配置", async () => {
process.env.HOST_SERVICE_TOKENS = JSON.stringify({
"demo-host-token": {
customerId: "CUST_001",
permissions: ["pricing:markup:write"],
},
});
process.env.CUSTOMER_REGISTRY = "";
vi.mocked(prisma.businessCustomer.findMany).mockResolvedValue([
{
customerId: "CUST_001",
businessCustomerId: "BC_001",
name: "客户A",
externalCode: null,
status: "active",
remark: null,
createdAt: new Date("2026-07-28T10:00:00Z"),
updatedAt: new Date("2026-07-28T10:00:00Z"),
_count: { users: 0 },
},
] as never);
vi.mocked(prisma.markupConfig.findMany).mockResolvedValue([
{
customerId: "CUST_001",
businessCustomerId: "BC_001",
markupType: "percent",
markupPercent: 10,
markupFixedAmount: null,
operatorId: "admin_demo",
remark: null,
updatedAt: new Date("2026-06-15T10:00:00Z"),
},
] as never);
const res = await GET(
new Request("http://localhost/api/admin/markup-configs?page=1&size=10", {
headers: ADMIN_HEADERS,
}),
);
const body = await res.json();
expect(res.status).toBe(200);
expect(body.code).toBe(0);
expect(body.data.total).toBe(1);
expect(body.data.list[0].customer_id).toBe("CUST_001");
expect(body.data.list[0].business_customer_id).toBe("BC_001");
expect(body.data.list[0].business_customer_name).toBe("客户A");
expect(body.data.list[0].markup_percent).toBe(10);
});
it("GET keyword=客户代码 能命中(不因租户 ID 过滤丢结果)", async () => {
process.env.HOST_SERVICE_TOKENS = JSON.stringify({
"demo-host-token": {
customerId: "CUST_004",
permissions: ["pricing:markup:write"],
},
});
process.env.CUSTOMER_REGISTRY = "";
vi.mocked(prisma.businessCustomer.findMany).mockResolvedValue([
{
customerId: "CUST_004",
businessCustomerId: "29bb985b-54ae-4d89-a760-052ca9c09f1d",
name: "STAR",
externalCode: "SP012",
status: "active",
remark: null,
createdAt: new Date("2026-07-28T10:00:00Z"),
updatedAt: new Date("2026-07-28T10:00:00Z"),
_count: { users: 1 },
},
] as never);
vi.mocked(prisma.markupConfig.findMany).mockResolvedValue([
{
customerId: "CUST_004",
businessCustomerId: "29bb985b-54ae-4d89-a760-052ca9c09f1d",
markupType: "fixed",
markupPercent: 0,
markupFixedAmount: 3,
operatorId: "admin_demo",
remark: null,
updatedAt: new Date("2026-07-30T10:00:00Z"),
},
] as never);
const res = await GET(
new Request(
"http://localhost/api/admin/markup-configs?page=1&size=10&keyword=SP012",
{ headers: ADMIN_HEADERS },
),
);
const body = await res.json();
expect(res.status).toBe(200);
expect(body.code).toBe(0);
expect(body.data.total).toBe(1);
expect(body.data.list[0].business_customer_code).toBe("SP012");
expect(body.data.list[0].markup_type).toBe("fixed");
expect(body.data.list[0].markup_fixed_amount).toBe(3);
});
it("GET keyword=SPO(字母O)也能命中 SP012", async () => {
process.env.HOST_SERVICE_TOKENS = JSON.stringify({
"demo-host-token": {
customerId: "CUST_004",
permissions: ["pricing:markup:write"],
},
});
process.env.CUSTOMER_REGISTRY = "";
vi.mocked(prisma.businessCustomer.findMany).mockResolvedValue([
{
customerId: "CUST_004",
businessCustomerId: "29bb985b-54ae-4d89-a760-052ca9c09f1d",
name: "STAR",
externalCode: "SP012",
status: "active",
remark: null,
createdAt: new Date("2026-07-28T10:00:00Z"),
updatedAt: new Date("2026-07-28T10:00:00Z"),
_count: { users: 1 },
},
] as never);
vi.mocked(prisma.markupConfig.findMany).mockResolvedValue([] as never);
vi.mocked(prisma.businessCustomerUser.findMany).mockResolvedValue([] as never);
const res = await GET(
new Request(
"http://localhost/api/admin/markup-configs?page=1&size=10&keyword=SPO",
{ headers: ADMIN_HEADERS },
),
);
const body = await res.json();
expect(body.code).toBe(0);
expect(body.data.total).toBe(1);
expect(body.data.list[0].business_customer_code).toBe("SP012");
});
it("PUT 拒绝租户级加价", async () => {
const res = await PUT(
new Request("http://localhost/api/admin/markup-configs/CUST_001", {
method: "PUT",
headers: { ...ADMIN_HEADERS, "Content-Type": "application/json" },
body: JSON.stringify({
markup_type: "fixed",
markup_fixed_amount: 25,
remark: "测试",
}),
}),
{ params: Promise.resolve({ customer_id: "CUST_001" }) },
);
const body = await res.json();
expect(res.status).toBe(400);
expect(body.message).toBe("仅支持业务客户加价,租户不加价");
});
it("PUT 支持业务客户覆盖加价", async () => {
vi.mocked(prisma.markupConfig.findFirst).mockResolvedValue(null as never);
vi.mocked(prisma.markupConfig.create).mockResolvedValue({
customerId: "CUST_001",
businessCustomerId: "BC_001",
markupType: "percent",
markupPercent: 12,
markupFixedAmount: null,
operatorId: "admin_demo",
remark: "业务客户覆盖",
updatedAt: new Date("2026-07-28T10:00:00Z"),
} as never);
vi.mocked(prisma.businessCustomer.findFirst).mockResolvedValue({
customerId: "CUST_001",
businessCustomerId: "BC_001",
name: "客户A",
externalCode: "CODE_A",
status: "active",
remark: null,
createdAt: new Date("2026-07-28T10:00:00Z"),
updatedAt: new Date("2026-07-28T10:00:00Z"),
} as never);
const res = await PUT(
new Request("http://localhost/api/admin/markup-configs/CUST_001", {
method: "PUT",
headers: { ...ADMIN_HEADERS, "Content-Type": "application/json" },
body: JSON.stringify({
business_customer_id: "BC_001",
markup_percent: 12,
remark: "业务客户覆盖",
}),
}),
{ params: Promise.resolve({ customer_id: "CUST_001" }) },
);
const body = await res.json();
expect(res.status).toBe(200);
expect(body.data.business_customer_id).toBe("BC_001");
expect(body.data.business_customer_code).toBe("CODE_A");
expect(body.data.business_customer_name).toBe("客户A");
expect(body.data.markup_percent).toBe(12);
});
it("PUT 未知客户 400", async () => {
const res = await PUT(
new Request("http://localhost/api/admin/markup-configs/CUST_999", {
method: "PUT",
headers: { ...ADMIN_HEADERS, "Content-Type": "application/json" },
body: JSON.stringify({ markup_percent: 5 }),
}),
{ params: Promise.resolve({ customer_id: "CUST_999" }) },
);
const body = await res.json();
expect(res.status).toBe(400);
expect(body.message).toBe("客户不存在");
});
});