feat(M08-A): 接入顾客端权益明细
This commit is contained in:
@@ -55,6 +55,45 @@ interface LedgerRow extends RowDataPacket {
|
||||
createdAt: Date;
|
||||
}
|
||||
|
||||
interface CouponDetailRow extends RowDataPacket {
|
||||
id: string;
|
||||
templateId: string;
|
||||
name: string;
|
||||
status: string;
|
||||
couponType: string;
|
||||
discountAmountCents: number;
|
||||
timeMinutes: number;
|
||||
minOrderAmountCents: number;
|
||||
remainingUses: number;
|
||||
validFrom: Date;
|
||||
validTo: Date;
|
||||
storeId: string | null;
|
||||
roomCategoryId: string | null;
|
||||
roomId: string | null;
|
||||
holidayOnly: number;
|
||||
frozenOrderId: string | null;
|
||||
usedAt: Date | null;
|
||||
}
|
||||
|
||||
interface PackageDetailRow extends RowDataPacket {
|
||||
id: string;
|
||||
planId: string;
|
||||
name: string;
|
||||
status: string;
|
||||
priceCents: number;
|
||||
minutesTotal: number;
|
||||
amountCentsTotal: number;
|
||||
remainingMinutes: number;
|
||||
remainingAmountCents: number;
|
||||
validFrom: Date;
|
||||
validTo: Date;
|
||||
storeId: string | null;
|
||||
roomCategoryId: string | null;
|
||||
roomId: string | null;
|
||||
holidayOnly: number;
|
||||
frozenOrderId: string | null;
|
||||
}
|
||||
|
||||
interface CountRow extends RowDataPacket { total: number }
|
||||
|
||||
export interface MemberActor {
|
||||
@@ -167,6 +206,93 @@ export class MemberProfileService {
|
||||
};
|
||||
}
|
||||
|
||||
async getMyBenefits(input: {
|
||||
tenantId: string;
|
||||
userId: string;
|
||||
limit?: number;
|
||||
}) {
|
||||
const limit = Math.max(1, Math.min(input.limit ?? 50, 100));
|
||||
const [coupons] = await this.pool.execute<CouponDetailRow[]>(
|
||||
`SELECT g.id, g.template_id AS templateId, t.name, g.status,
|
||||
t.coupon_type AS couponType,
|
||||
t.discount_amount_cents AS discountAmountCents,
|
||||
t.time_minutes AS timeMinutes,
|
||||
t.min_order_amount_cents AS minOrderAmountCents,
|
||||
g.remaining_uses AS remainingUses,
|
||||
g.valid_from AS validFrom, g.valid_to AS validTo,
|
||||
t.store_id AS storeId, t.room_category_id AS roomCategoryId,
|
||||
t.room_id AS roomId, t.holiday_only AS holidayOnly,
|
||||
g.frozen_order_id AS frozenOrderId, g.used_at AS usedAt
|
||||
FROM qipai_coupon_grants g
|
||||
INNER JOIN qipai_coupon_templates t
|
||||
ON t.tenant_id = g.tenant_id AND t.id = g.template_id
|
||||
WHERE g.tenant_id = ? AND g.user_id = ? AND t.deleted_at IS NULL
|
||||
ORDER BY FIELD(g.status, 'AVAILABLE', 'FROZEN', 'USED', 'EXPIRED'),
|
||||
g.valid_to ASC, g.id DESC
|
||||
LIMIT ?`,
|
||||
[input.tenantId, input.userId, limit]
|
||||
);
|
||||
const [packages] = await this.pool.execute<PackageDetailRow[]>(
|
||||
`SELECT h.id, h.plan_id AS planId, p.name, h.status,
|
||||
p.price_cents AS priceCents,
|
||||
p.minutes_total AS minutesTotal,
|
||||
p.amount_cents_total AS amountCentsTotal,
|
||||
h.remaining_minutes AS remainingMinutes,
|
||||
h.remaining_amount_cents AS remainingAmountCents,
|
||||
h.valid_from AS validFrom, h.valid_to AS validTo,
|
||||
p.store_id AS storeId, p.room_category_id AS roomCategoryId,
|
||||
p.room_id AS roomId, p.holiday_only AS holidayOnly,
|
||||
h.frozen_order_id AS frozenOrderId
|
||||
FROM qipai_package_holdings h
|
||||
INNER JOIN qipai_package_plans p
|
||||
ON p.tenant_id = h.tenant_id AND p.id = h.plan_id
|
||||
WHERE h.tenant_id = ? AND h.user_id = ? AND p.deleted_at IS NULL
|
||||
ORDER BY FIELD(h.status, 'ACTIVE', 'FROZEN', 'EXHAUSTED', 'EXPIRED'),
|
||||
h.valid_to ASC, h.id DESC
|
||||
LIMIT ?`,
|
||||
[input.tenantId, input.userId, limit]
|
||||
);
|
||||
return {
|
||||
coupons: coupons.map((row) => ({
|
||||
couponGrantId: String(row.id),
|
||||
templateId: String(row.templateId),
|
||||
name: row.name,
|
||||
status: row.status,
|
||||
couponType: row.couponType,
|
||||
discountAmountCents: Number(row.discountAmountCents),
|
||||
timeMinutes: Number(row.timeMinutes),
|
||||
minOrderAmountCents: Number(row.minOrderAmountCents),
|
||||
remainingUses: Number(row.remainingUses),
|
||||
validFrom: row.validFrom,
|
||||
validTo: row.validTo,
|
||||
storeId: row.storeId === null ? null : String(row.storeId),
|
||||
roomCategoryId: row.roomCategoryId === null ? null : String(row.roomCategoryId),
|
||||
roomId: row.roomId === null ? null : String(row.roomId),
|
||||
holidayOnly: Number(row.holidayOnly) === 1,
|
||||
frozenOrderId: row.frozenOrderId === null ? null : String(row.frozenOrderId),
|
||||
usedAt: row.usedAt
|
||||
})),
|
||||
packages: packages.map((row) => ({
|
||||
packageHoldingId: String(row.id),
|
||||
planId: String(row.planId),
|
||||
name: row.name,
|
||||
status: row.status,
|
||||
priceCents: Number(row.priceCents),
|
||||
minutesTotal: Number(row.minutesTotal),
|
||||
amountCentsTotal: Number(row.amountCentsTotal),
|
||||
remainingMinutes: Number(row.remainingMinutes),
|
||||
remainingAmountCents: Number(row.remainingAmountCents),
|
||||
validFrom: row.validFrom,
|
||||
validTo: row.validTo,
|
||||
storeId: row.storeId === null ? null : String(row.storeId),
|
||||
roomCategoryId: row.roomCategoryId === null ? null : String(row.roomCategoryId),
|
||||
roomId: row.roomId === null ? null : String(row.roomId),
|
||||
holidayOnly: Number(row.holidayOnly) === 1,
|
||||
frozenOrderId: row.frozenOrderId === null ? null : String(row.frozenOrderId)
|
||||
}))
|
||||
};
|
||||
}
|
||||
|
||||
private async memberCard(actor: MemberActor, row: MemberRow) {
|
||||
const memberId = String(row.id);
|
||||
const [walletRows] = await this.pool.execute<WalletSummaryRow[]>(
|
||||
|
||||
Reference in New Issue
Block a user