feat: add per-org SMS wallet with adm panel and header credit
Bill all platform SMS (including OTP), allow negative balance with manual/auto cutoffs, and support own-panel bypass without wallet debit.
This commit is contained in:
@@ -1,13 +1,12 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { AuthModule } from '../auth/auth.module';
|
||||
import { SmsService } from '../common/sms.service';
|
||||
import { LoyaltyController } from './loyalty.controller';
|
||||
import { LoyaltyService } from './loyalty.service';
|
||||
|
||||
@Module({
|
||||
imports: [AuthModule],
|
||||
controllers: [LoyaltyController],
|
||||
providers: [LoyaltyService, SmsService],
|
||||
providers: [LoyaltyService],
|
||||
exports: [LoyaltyService],
|
||||
})
|
||||
export class LoyaltyModule {}
|
||||
|
||||
@@ -22,7 +22,7 @@ import { Prisma } from '@prisma/client';
|
||||
import { PrismaService } from '../prisma/prisma.service';
|
||||
import { buildSearchWhere, ci } from '../common/search';
|
||||
import { type Actor, ownerWhere } from '../common/record-scope';
|
||||
import { SmsService } from '../common/sms.service';
|
||||
import { SmsGatewayService } from '../sms-billing/sms-gateway.service';
|
||||
|
||||
const DEFAULT_TIERS = [
|
||||
{ name: 'برنزی', minPoints: 0, color: '#c9843a' },
|
||||
@@ -57,7 +57,7 @@ const DAY_MS = 86_400_000;
|
||||
export class LoyaltyService {
|
||||
constructor(
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly sms: SmsService,
|
||||
private readonly sms: SmsGatewayService,
|
||||
) {}
|
||||
|
||||
async ensureDefaults(organizationId: string): Promise<void> {
|
||||
@@ -447,10 +447,12 @@ export class LoyaltyService {
|
||||
const settings = await this.ensureSettings(actor.organizationId);
|
||||
if (settings.notifyOnAdjust && updated.mobile) {
|
||||
const sign = delta > 0 ? '+' : '';
|
||||
void this.sms.sendSmsDetailed(
|
||||
updated.mobile,
|
||||
`باشگاه مشتریان: ${sign}${Math.trunc(delta)} امتیاز. موجودی: ${updated.loyaltyPoints}`,
|
||||
);
|
||||
void this.sms.send({
|
||||
organizationId: actor.organizationId,
|
||||
phone: updated.mobile,
|
||||
text: `باشگاه مشتریان: ${sign}${Math.trunc(delta)} امتیاز. موجودی: ${updated.loyaltyPoints}`,
|
||||
source: 'loyalty',
|
||||
});
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
@@ -504,7 +506,12 @@ export class LoyaltyService {
|
||||
skipped += 1;
|
||||
continue;
|
||||
}
|
||||
const result = await this.sms.sendSmsDetailed(p.mobile, body);
|
||||
const result = await this.sms.send({
|
||||
organizationId: actor.organizationId,
|
||||
phone: p.mobile,
|
||||
text: body,
|
||||
source: 'loyalty',
|
||||
});
|
||||
if (result.ok) sent += 1;
|
||||
else failed += 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user