mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 17:38:12 +00:00
Initial commit of edr-passenger-api alpha version
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
import { Controller, Get, Param, Post, UseGuards } from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
|
||||
import { LoyaltyService } from './loyalty.service';
|
||||
import { JwtGuard } from '../../common/jwt.guard';
|
||||
|
||||
@ApiTags('Loyalty')
|
||||
@Controller('loyalty')
|
||||
@UseGuards(JwtGuard)
|
||||
@ApiBearerAuth('JWT-auth')
|
||||
export class LoyaltyController {
|
||||
constructor(private service: LoyaltyService) {}
|
||||
@Get(':passengerId') @ApiOperation({ summary: 'Get loyalty account with tier progress' }) getAccount(@Param('passengerId') id: string) { return this.service.getAccount(id); }
|
||||
@Get(':passengerId/rewards') @ApiOperation({ summary: 'Get available rewards' }) getRewards(@Param('passengerId') id: string) { return this.service.getRewards(id); }
|
||||
@Post(':passengerId/rewards/:rewardId/redeem') @ApiOperation({ summary: 'Redeem a loyalty reward' }) redeemReward(@Param('passengerId') pid: string, @Param('rewardId') rid: string) { return this.service.redeemReward(pid, rid); }
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { LoyaltyController } from './loyalty.controller';
|
||||
import { LoyaltyService } from './loyalty.service';
|
||||
|
||||
@Module({ controllers: [LoyaltyController], providers: [LoyaltyService] })
|
||||
export class LoyaltyModule {}
|
||||
@@ -0,0 +1,43 @@
|
||||
import { Injectable, NotFoundException, BadRequestException } from '@nestjs/common';
|
||||
import { PrismaService } from '../../common/prisma.service';
|
||||
|
||||
@Injectable()
|
||||
export class LoyaltyService {
|
||||
constructor(private prisma: PrismaService) {}
|
||||
|
||||
async getAccount(passengerId: string) {
|
||||
const account = await this.prisma.loyaltyAccount.findUnique({ where: { passengerId }, include: { ledger: { orderBy: { createdAt: 'desc' }, take: 20 } } });
|
||||
if (!account) throw new NotFoundException('Loyalty account not found');
|
||||
const tiers = ['BRONZE', 'SILVER', 'GOLD', 'PLATINUM'];
|
||||
const thresholds: Record<string, number> = { BRONZE: 0, SILVER: 2000, GOLD: 5000, PLATINUM: 10000 };
|
||||
const idx = tiers.indexOf(account.tier);
|
||||
const nextTier = tiers[idx + 1] ?? null;
|
||||
const nextThreshold = nextTier ? thresholds[nextTier] : null;
|
||||
return {
|
||||
...account, nextTier,
|
||||
points: account.pointsBalance,
|
||||
nextTierPoints: nextThreshold ?? account.pointsBalance,
|
||||
pointsToNextTier: nextThreshold ? nextThreshold - account.pointsBalance : 0,
|
||||
tierProgressPercent: nextThreshold ? +((account.pointsBalance - thresholds[account.tier]) / (nextThreshold - thresholds[account.tier]) * 100).toFixed(2) : 100,
|
||||
};
|
||||
}
|
||||
|
||||
async getRewards(passengerId: string) {
|
||||
const account = await this.prisma.loyaltyAccount.findUnique({ where: { passengerId } });
|
||||
if (!account) throw new NotFoundException('Loyalty account not found');
|
||||
return this.prisma.loyaltyReward.findMany({ where: { accountId: account.id, available: true } });
|
||||
}
|
||||
|
||||
async redeemReward(passengerId: string, rewardId: string) {
|
||||
const account = await this.prisma.loyaltyAccount.findUnique({ where: { passengerId } });
|
||||
if (!account) throw new NotFoundException('Loyalty account not found');
|
||||
const reward = await this.prisma.loyaltyReward.findUnique({ where: { id: rewardId } });
|
||||
if (!reward?.available) throw new NotFoundException('Reward not available');
|
||||
if (account.pointsBalance < reward.costPoints) throw new BadRequestException('Insufficient points');
|
||||
const newBalance = account.pointsBalance - reward.costPoints;
|
||||
await this.prisma.loyaltyAccount.update({ where: { passengerId }, data: { pointsBalance: newBalance } });
|
||||
await this.prisma.loyaltyLedgerEntry.create({ data: { accountId: account.id, delta: -reward.costPoints, reason: 'REWARD_REDEEMED', balanceAfter: newBalance } });
|
||||
await this.prisma.loyaltyReward.update({ where: { id: rewardId }, data: { available: false } });
|
||||
return { redeemed: true, pointsUsed: reward.costPoints, balanceAfter: newBalance };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user