feat(M08-A): 接入顾客端权益明细

This commit is contained in:
Codex
2026-06-25 12:04:55 +08:00
parent fb1b593b24
commit e24920c9cc
20 changed files with 661 additions and 38 deletions
@@ -13,6 +13,7 @@ const forbiddenToken = signAccessToken({
}, secret, 900);
let profileInput;
let benefitsInput;
const app = await buildApp({
members: {
jwtSecret: secret,
@@ -46,6 +47,23 @@ const app = await buildApp({
service: {
async listMembers() { throw new Error('not called'); },
async getMember() { throw new Error('not called'); },
async getMyBenefits(input) {
benefitsInput = input;
return {
coupons: [{
couponGrantId: '401',
name: '30元抵扣券',
status: 'AVAILABLE',
discountAmountCents: 3000
}],
packages: [{
packageHoldingId: '501',
name: '三小时畅玩包',
status: 'ACTIVE',
remainingMinutes: 120
}]
};
},
async getMyProfile(input) {
profileInput = input;
return {
@@ -71,6 +89,17 @@ assert.equal(profileInput.tenantId, '7');
assert.equal(profileInput.userId, '21');
assert.equal(profile.json().data.wallet.totalBalanceCents, 1200);
const benefits = await app.inject({
method: 'GET',
url: '/app-api/profile/benefits',
headers: { authorization: `Bearer ${token}` }
});
assert.equal(benefits.statusCode, 200);
assert.equal(benefitsInput.tenantId, '7');
assert.equal(benefitsInput.userId, '21');
assert.equal(benefits.json().data.coupons[0].couponGrantId, '401');
assert.equal(benefits.json().data.packages[0].packageHoldingId, '501');
const unauthorized = await app.inject({
method: 'GET',
url: '/app-api/profile'
+150 -5
View File
@@ -47,25 +47,111 @@ const wallets = [
];
const coupons = [
{ tenantId: '7', userId: '21', status: 'AVAILABLE' },
{ tenantId: '7', userId: '21', status: 'FROZEN' },
{ tenantId: '7', userId: '22', status: 'USED' }
{
id: '401',
tenantId: '7',
userId: '21',
templateId: '301',
name: '30元抵扣券',
status: 'AVAILABLE',
couponType: 'FULL_REDUCTION',
discountAmountCents: 3000,
timeMinutes: 0,
minOrderAmountCents: 10000,
remainingUses: 1,
validFrom: new Date('2026-06-01T00:00:00.000Z'),
validTo: new Date('2026-07-01T00:00:00.000Z'),
storeId: '11',
roomCategoryId: null,
roomId: null,
holidayOnly: 0,
frozenOrderId: null,
usedAt: null
},
{
id: '402',
tenantId: '7',
userId: '21',
templateId: '302',
name: '60分钟券',
status: 'FROZEN',
couponType: 'TIME',
discountAmountCents: 0,
timeMinutes: 60,
minOrderAmountCents: 0,
remainingUses: 1,
validFrom: new Date('2026-06-01T00:00:00.000Z'),
validTo: new Date('2026-07-02T00:00:00.000Z'),
storeId: null,
roomCategoryId: null,
roomId: null,
holidayOnly: 0,
frozenOrderId: '301',
usedAt: null
},
{
id: '403',
tenantId: '7',
userId: '22',
templateId: '303',
name: '其他用户券',
status: 'USED',
couponType: 'FULL_REDUCTION',
discountAmountCents: 500,
timeMinutes: 0,
minOrderAmountCents: 0,
remainingUses: 0,
validFrom: new Date('2026-06-01T00:00:00.000Z'),
validTo: new Date('2026-07-01T00:00:00.000Z'),
storeId: null,
roomCategoryId: null,
roomId: null,
holidayOnly: 0,
frozenOrderId: null,
usedAt: new Date('2026-06-20T00:00:00.000Z')
}
];
const packages = [
{
id: '501',
tenantId: '7',
userId: '21',
planId: '601',
name: '三小时畅玩包',
status: 'ACTIVE',
priceCents: 9000,
minutesTotal: 180,
amountCentsTotal: 3000,
remainingMinutes: 120,
remainingAmountCents: 3_000
remainingAmountCents: 3_000,
validFrom: new Date('2026-06-01T00:00:00.000Z'),
validTo: new Date('2026-08-01T00:00:00.000Z'),
storeId: '11',
roomCategoryId: null,
roomId: null,
holidayOnly: 0,
frozenOrderId: null
},
{
id: '502',
tenantId: '7',
userId: '21',
planId: '602',
name: '锁定中的套餐',
status: 'FROZEN',
priceCents: 5000,
minutesTotal: 60,
amountCentsTotal: 2000,
remainingMinutes: 60,
remainingAmountCents: 2_000
remainingAmountCents: 2_000,
validFrom: new Date('2026-06-01T00:00:00.000Z'),
validTo: new Date('2026-08-02T00:00:00.000Z'),
storeId: null,
roomCategoryId: null,
roomId: null,
holidayOnly: 0,
frozenOrderId: '301'
}
];
@@ -185,6 +271,53 @@ function createService() {
.reduce((sum, item) => sum + item.remainingAmountCents, 0)
}], []];
}
if (sql.includes('FROM qipai_coupon_grants g')) {
const rows = coupons
.filter((item) => item.tenantId === String(params[0]) && item.userId === String(params[1]))
.slice(0, Number(params[2]));
return [rows.map((item) => ({
id: item.id,
templateId: item.templateId,
name: item.name,
status: item.status,
couponType: item.couponType,
discountAmountCents: item.discountAmountCents,
timeMinutes: item.timeMinutes,
minOrderAmountCents: item.minOrderAmountCents,
remainingUses: item.remainingUses,
validFrom: item.validFrom,
validTo: item.validTo,
storeId: item.storeId,
roomCategoryId: item.roomCategoryId,
roomId: item.roomId,
holidayOnly: item.holidayOnly,
frozenOrderId: item.frozenOrderId,
usedAt: item.usedAt
})), []];
}
if (sql.includes('FROM qipai_package_holdings h')) {
const rows = packages
.filter((item) => item.tenantId === String(params[0]) && item.userId === String(params[1]))
.slice(0, Number(params[2]));
return [rows.map((item) => ({
id: item.id,
planId: item.planId,
name: item.name,
status: item.status,
priceCents: item.priceCents,
minutesTotal: item.minutesTotal,
amountCentsTotal: item.amountCentsTotal,
remainingMinutes: item.remainingMinutes,
remainingAmountCents: item.remainingAmountCents,
validFrom: item.validFrom,
validTo: item.validTo,
storeId: item.storeId,
roomCategoryId: item.roomCategoryId,
roomId: item.roomId,
holidayOnly: item.holidayOnly,
frozenOrderId: item.frozenOrderId
})), []];
}
if (sql.includes('FROM qipai_recharge_orders')) {
const tenantId = String(params[0]);
const userId = String(params[1]);
@@ -306,6 +439,18 @@ const forbiddenReader = {
assert.equal(member.benefits.packageMinutes, 180);
}
{
const service = createService();
const benefits = await service.getMyBenefits({ tenantId: '7', userId: '21' });
assert.equal(benefits.coupons.length, 2);
assert.equal(benefits.coupons[0].couponGrantId, '401');
assert.equal(benefits.coupons[0].discountAmountCents, 3000);
assert.equal(benefits.coupons[1].frozenOrderId, '301');
assert.equal(benefits.packages.length, 2);
assert.equal(benefits.packages[0].packageHoldingId, '501');
assert.equal(benefits.packages[0].remainingAmountCents, 3000);
}
{
const service = createService();
const scoped = await service.listMembers({