import { Injectable } from '@nestjs/common'; import { calcBenefitAmount, calcBenefitSummary, generateCouponNo } from '@dukang/domain'; import { PrismaService } from '../../common/prisma/prisma.module'; import { serializeBigInt } from '../../common/decorators/current-user.decorator'; import { buildBenefitLedgerEvent, benefitLedgerWhere } from '../../common/event/event.helpers'; @Injectable() export class BenefitService { constructor(private readonly prisma: PrismaService) {} async grantOnOrderPaid(orderId: bigint) { const order = await this.prisma.order.findUniqueOrThrow({ where: { id: orderId }, }); const product = await this.prisma.commonProductItem.findUnique({ where: { id: order.productId } }); const unitBenefit = calcBenefitAmount({ price: Number(order.listUnitPrice), benefitAmount: product?.benefitAmount ? Number(product.benefitAmount) : null, }); const totalBenefit = unitBenefit * order.quantity; const coupon = await this.prisma.benefitCoupon.create({ data: { couponNo: generateCouponNo(), userId: order.userId, orderId: order.id, totalAmount: totalBenefit, balance: totalBenefit, sourceProduct: order.productName, }, }); await this.prisma.commonEvent.create({ data: buildBenefitLedgerEvent({ userId: order.userId, couponId: coupon.id, type: 'GRANT', amount: totalBenefit, balanceAfter: totalBenefit, refType: 'ORDER', refId: order.id, remark: '购酒赠券', }), }); return serializeBigInt(coupon); } async listCoupons(userId: bigint) { const list = await this.prisma.benefitCoupon.findMany({ where: { userId, status: { in: ['ACTIVE', 'USED_UP'] } }, orderBy: { createdAt: 'desc' }, }); return serializeBigInt(list); } async getSummary(userId: bigint) { const coupons = await this.prisma.benefitCoupon.findMany({ where: { userId, status: 'ACTIVE' }, orderBy: { createdAt: 'asc' }, }); const summary = calcBenefitSummary( coupons.map((c) => Number(c.balance)), ); return serializeBigInt(summary); } async getLedger(userId: bigint, couponId?: bigint) { const list = await this.prisma.commonEvent.findMany({ where: benefitLedgerWhere(userId, couponId), orderBy: { createdAt: 'desc' }, }); return serializeBigInt(list); } async getCoupon(userId: bigint, couponId: bigint) { const coupon = await this.prisma.benefitCoupon.findFirst({ where: { id: couponId, userId }, }); if (!coupon) return null; const ledgers = await this.prisma.commonEvent.findMany({ where: benefitLedgerWhere(undefined, couponId), orderBy: { createdAt: 'desc' }, }); return serializeBigInt({ coupon, ledgers }); } }