apps/recallassess/recallassess-api/src/api/client/promo-code/promo-code.service.ts
Methods |
|
constructor(prisma: BNestPrismaService)
|
||||||
|
Parameters :
|
| calculateDiscount |
calculateDiscount(originalAmount: number, discountPercentage: number)
|
|
Calculate discount amount based on promo code and original amount
Returns :
number
|
| Async getPromoCodeDetails | ||||||
getPromoCodeDetails(code: string)
|
||||||
|
Get detailed info about a valid promo code (Only returns data if code is valid)
Parameters :
Returns :
Promise<ValidPromoCodeDto | null>
|
| Async incrementUsage | ||||||
incrementUsage(code: string)
|
||||||
|
Increment usage count when a promo code is applied This should be called after a successful purchase/subscription
Parameters :
Returns :
Promise<void>
|
| Async validatePromoCode | ||||||
validatePromoCode(code: string)
|
||||||
|
Validate a promo code Checks if code exists, is active, not expired, and not sold out
Parameters :
Returns :
Promise<PromoCodeValidationDto>
|
import { bnestPlainToDto } from "@bish-nest/core";
import { BNestPrismaService } from "@bish-nest/core/services/database/prisma/prisma.service";
import { Injectable } from "@nestjs/common";
import { PromoCodeValidationDto, ValidPromoCodeDto } from "./dto";
@Injectable()
export class CLPromoCodeService {
constructor(private readonly prisma: BNestPrismaService) {}
/**
* Validate a promo code
* Checks if code exists, is active, not expired, and not sold out
*/
async validatePromoCode(code: string): Promise<PromoCodeValidationDto> {
const promoCode = await this.prisma.client.promoCode.findUnique({
where: { promo_code: code.toUpperCase() },
});
// Code doesn't exist
if (!promoCode) {
return bnestPlainToDto(
{
is_valid: false,
message: "Promo code not found",
error_code: "NOT_FOUND",
},
PromoCodeValidationDto,
);
}
// Code is inactive
if (!promoCode.is_active) {
return bnestPlainToDto(
{
is_valid: false,
promo_code: promoCode.promo_code,
message: "This promo code is no longer active",
error_code: "INACTIVE",
},
PromoCodeValidationDto,
);
}
const now = new Date();
// Code hasn't started yet
if (promoCode.valid_from && new Date(promoCode.valid_from) > now) {
return bnestPlainToDto(
{
is_valid: false,
promo_code: promoCode.promo_code,
message: "This promo code is not yet valid",
error_code: "NOT_STARTED",
},
PromoCodeValidationDto,
);
}
// Code has expired
if (promoCode.valid_until && new Date(promoCode.valid_until) < now) {
return bnestPlainToDto(
{
is_valid: false,
promo_code: promoCode.promo_code,
message: "This promo code has expired",
error_code: "EXPIRED",
},
PromoCodeValidationDto,
);
}
// Code usage limit reached (sold out)
if (promoCode.usage_limit && promoCode.usage_count >= promoCode.usage_limit) {
return bnestPlainToDto(
{
is_valid: false,
promo_code: promoCode.promo_code,
message: "This promo code has reached its usage limit",
error_code: "SOLD_OUT",
},
PromoCodeValidationDto,
);
}
// Code is valid!
return bnestPlainToDto(
{
is_valid: true,
promo_code: promoCode.promo_code,
discount_percentage: Number(promoCode.discount_percentage),
message: "Promo code is valid",
},
PromoCodeValidationDto,
);
}
/**
* Get detailed info about a valid promo code
* (Only returns data if code is valid)
*/
async getPromoCodeDetails(code: string): Promise<ValidPromoCodeDto | null> {
const validation = await this.validatePromoCode(code);
if (!validation.is_valid) {
return null;
}
const promoCode = await this.prisma.client.promoCode.findUnique({
where: { promo_code: code.toUpperCase() },
});
if (!promoCode) {
return null;
}
const remaining_uses = promoCode.usage_limit
? Math.max(0, promoCode.usage_limit - promoCode.usage_count)
: null;
return bnestPlainToDto(
{
promo_code: promoCode.promo_code,
title: promoCode.title,
discount_percentage: Number(promoCode.discount_percentage),
valid_until: promoCode.valid_until,
remaining_uses,
},
ValidPromoCodeDto,
);
}
/**
* Increment usage count when a promo code is applied
* This should be called after a successful purchase/subscription
*/
async incrementUsage(code: string): Promise<void> {
await this.prisma.client.promoCode.update({
where: { promo_code: code.toUpperCase() },
data: {
usage_count: {
increment: 1,
},
},
});
}
/**
* Calculate discount amount based on promo code and original amount
*/
calculateDiscount(originalAmount: number, discountPercentage: number): number {
return (originalAmount * discountPercentage) / 100;
}
}