184 lines
4.6 KiB
TypeScript
184 lines
4.6 KiB
TypeScript
import {
|
|
Body,
|
|
Controller,
|
|
Delete,
|
|
Get,
|
|
Param,
|
|
Patch,
|
|
Post,
|
|
Query,
|
|
Res,
|
|
StreamableFile,
|
|
UseGuards,
|
|
} from '@nestjs/common';
|
|
import type { Response } from 'express';
|
|
import { JwtAuthGuard } from '../auth/jwt-auth.guard';
|
|
import { CurrentUser } from '../auth/current-user.decorator';
|
|
import { Roles } from '../auth/roles.decorator';
|
|
import { RolesGuard } from '../auth/roles.guard';
|
|
import type { Actor } from '../common/record-scope';
|
|
import {
|
|
AdjustLoyaltyPointsDto,
|
|
BulkAdjustLoyaltyDto,
|
|
CreateLoyaltyRewardDto,
|
|
CreateLoyaltyTierDto,
|
|
LoyaltyMessageDto,
|
|
RedeemLoyaltyRewardDto,
|
|
UpdateLoyaltyRewardDto,
|
|
UpdateLoyaltySettingsDto,
|
|
UpdateLoyaltyTierDto,
|
|
} from './dto';
|
|
import { LoyaltyService } from './loyalty.service';
|
|
import { brand } from '@mento/shared';
|
|
|
|
@Controller('loyalty')
|
|
@UseGuards(JwtAuthGuard, RolesGuard)
|
|
export class LoyaltyController {
|
|
constructor(private readonly loyalty: LoyaltyService) {}
|
|
|
|
@Get('stats')
|
|
stats(@CurrentUser() user: Actor) {
|
|
return this.loyalty.getStats(user);
|
|
}
|
|
|
|
@Get('settings')
|
|
settings(@CurrentUser() user: Actor) {
|
|
return this.loyalty.getSettings(user.organizationId);
|
|
}
|
|
|
|
@Patch('settings')
|
|
@Roles('owner', 'admin')
|
|
updateSettings(
|
|
@CurrentUser() user: Actor,
|
|
@Body() dto: UpdateLoyaltySettingsDto,
|
|
) {
|
|
return this.loyalty.updateSettings(user.organizationId, dto);
|
|
}
|
|
|
|
@Get('tiers')
|
|
listTiers(@CurrentUser() user: Actor) {
|
|
return this.loyalty.listTiers(user.organizationId);
|
|
}
|
|
|
|
@Post('tiers')
|
|
@Roles('owner', 'admin')
|
|
createTier(
|
|
@CurrentUser() user: Actor,
|
|
@Body() dto: CreateLoyaltyTierDto,
|
|
) {
|
|
return this.loyalty.createTier(user.organizationId, dto);
|
|
}
|
|
|
|
@Patch('tiers/:id')
|
|
@Roles('owner', 'admin')
|
|
updateTier(
|
|
@CurrentUser() user: Actor,
|
|
@Param('id') id: string,
|
|
@Body() dto: UpdateLoyaltyTierDto,
|
|
) {
|
|
return this.loyalty.updateTier(user.organizationId, id, dto);
|
|
}
|
|
|
|
@Delete('tiers/:id')
|
|
@Roles('owner', 'admin')
|
|
async deleteTier(@CurrentUser() user: Actor, @Param('id') id: string) {
|
|
await this.loyalty.deleteTier(user.organizationId, id);
|
|
return { ok: true };
|
|
}
|
|
|
|
@Get('members/export')
|
|
async exportMembers(
|
|
@CurrentUser() user: Actor,
|
|
@Query('q') q: string | undefined,
|
|
@Query('tierId') tierId: string | undefined,
|
|
@Res({ passthrough: true }) res: Response,
|
|
) {
|
|
const buffer = await this.loyalty.exportMembers(user, q, tierId);
|
|
res.set({
|
|
'Content-Type':
|
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
'Content-Disposition': `attachment; filename="${brand.filePrefix}-loyalty-members.xlsx"`,
|
|
});
|
|
return new StreamableFile(buffer);
|
|
}
|
|
|
|
@Get('members')
|
|
listMembers(
|
|
@CurrentUser() user: Actor,
|
|
@Query('q') q?: string,
|
|
@Query('tierId') tierId?: string,
|
|
) {
|
|
return this.loyalty.listMembers(user, q, tierId);
|
|
}
|
|
|
|
@Get('members/:personId/ledger')
|
|
listLedger(
|
|
@CurrentUser() user: Actor,
|
|
@Param('personId') personId: string,
|
|
) {
|
|
return this.loyalty.listLedger(user, personId);
|
|
}
|
|
|
|
@Post('members/bulk-adjust')
|
|
bulkAdjust(
|
|
@CurrentUser() user: Actor,
|
|
@Body() dto: BulkAdjustLoyaltyDto,
|
|
) {
|
|
return this.loyalty.bulkAdjust(user, dto.personIds, dto.delta, dto.reason);
|
|
}
|
|
|
|
@Post('members/message')
|
|
sendMessage(@CurrentUser() user: Actor, @Body() dto: LoyaltyMessageDto) {
|
|
return this.loyalty.sendMessage(user, dto.personIds, dto.text);
|
|
}
|
|
|
|
@Post('members/:personId/adjust')
|
|
adjust(
|
|
@CurrentUser() user: Actor,
|
|
@Param('personId') personId: string,
|
|
@Body() dto: AdjustLoyaltyPointsDto,
|
|
) {
|
|
return this.loyalty.adjustPoints(user, personId, dto.delta, dto.reason);
|
|
}
|
|
|
|
@Get('rewards')
|
|
listRewards(@CurrentUser() user: Actor) {
|
|
return this.loyalty.listRewards(user.organizationId);
|
|
}
|
|
|
|
@Post('rewards')
|
|
@Roles('owner', 'admin')
|
|
createReward(
|
|
@CurrentUser() user: Actor,
|
|
@Body() dto: CreateLoyaltyRewardDto,
|
|
) {
|
|
return this.loyalty.createReward(user.organizationId, dto);
|
|
}
|
|
|
|
@Patch('rewards/:id')
|
|
@Roles('owner', 'admin')
|
|
updateReward(
|
|
@CurrentUser() user: Actor,
|
|
@Param('id') id: string,
|
|
@Body() dto: UpdateLoyaltyRewardDto,
|
|
) {
|
|
return this.loyalty.updateReward(user.organizationId, id, dto);
|
|
}
|
|
|
|
@Delete('rewards/:id')
|
|
@Roles('owner', 'admin')
|
|
async deleteReward(@CurrentUser() user: Actor, @Param('id') id: string) {
|
|
await this.loyalty.deleteReward(user.organizationId, id);
|
|
return { ok: true };
|
|
}
|
|
|
|
@Post('rewards/:id/redeem')
|
|
redeem(
|
|
@CurrentUser() user: Actor,
|
|
@Param('id') id: string,
|
|
@Body() dto: RedeemLoyaltyRewardDto,
|
|
) {
|
|
return this.loyalty.redeemReward(user, id, dto.personId);
|
|
}
|
|
}
|