Files
grow-api/src/subscriptions/subscription-automation.service.ts
T
2026-07-12 19:08:30 +03:30

77 lines
2.7 KiB
TypeScript

import { Injectable, Logger } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { SalonNotificationsService } from '../notifications/salon-notifications.service';
import { SmsService } from '../sms/sms.service';
import { SalonSubscriptionsService } from './salon-subscriptions.service';
@Injectable()
export class SubscriptionAutomationService {
private readonly logger = new Logger(SubscriptionAutomationService.name);
constructor(
private readonly salonSubscriptionsService: SalonSubscriptionsService,
private readonly salonNotificationsService: SalonNotificationsService,
private readonly smsService: SmsService,
) {}
/**
* Detects subscriptions (trial or paid) whose validity period just ended
* and, once per subscription, notifies the salon owner in-app and by SMS
* that they need to purchase a plan to keep using the product. Access is
* already blocked automatically by `ActiveSubscriptionGuard` once the
* subscription's `endDate` has passed, independent of this job.
*/
@Cron(CronExpression.EVERY_DAY_AT_10AM, {
name: 'subscription-expiry-notifications',
})
async notifyExpiredSubscriptions(): Promise<number> {
const subscriptions =
await this.salonSubscriptionsService.findSubscriptionsPendingExpiryNotification();
let notifiedCount = 0;
for (const subscription of subscriptions) {
try {
await this.salonSubscriptionsService.markExpiryNotified(
subscription.id,
);
const planLabel = subscription.plan?.isTrial
? 'دوره آزمایشی رایگان'
: `اشتراک ${subscription.plan?.name ?? ''}`.trim();
await this.salonNotificationsService.notifySubscriptionExpired({
salonId: subscription.salonId,
salonOwnerId: subscription.salon.ownerId,
salonName: subscription.salon.name,
planLabel,
endDate: subscription.endDate,
});
const ownerMobile = subscription.salon.owner?.mobile;
if (ownerMobile) {
await this.smsService.sendSms(
ownerMobile,
`${planLabel} سالن ${subscription.salon.name} به پایان رسید. برای ادامه استفاده از امکانات و ارسال پیامک، همین حالا اشتراک تهیه کنید.`,
);
}
notifiedCount += 1;
} catch (error) {
this.logger.error(
`Failed to send expiry notification for subscription ${subscription.id}`,
error instanceof Error ? error.stack : undefined,
);
}
}
if (notifiedCount > 0) {
this.logger.log(
`Sent expiry notifications for ${notifiedCount} subscription(s)`,
);
}
return notifiedCount;
}
}