Add optional SMS auto-block threshold below balance.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+30
-4
@@ -146,6 +146,10 @@ export class SmsService {
|
||||
data: {
|
||||
pricePerPartRials: dto.pricePerPartRials ?? undefined,
|
||||
isBlocked: dto.isBlocked ?? undefined,
|
||||
autoBlockBelowRials:
|
||||
dto.autoBlockBelowRials === undefined
|
||||
? undefined
|
||||
: dto.autoBlockBelowRials,
|
||||
alertCriticalRials: dto.alertCriticalRials ?? undefined,
|
||||
alertWarningRials: dto.alertWarningRials ?? undefined,
|
||||
gatewayProvider: dto.gatewayProvider ?? undefined,
|
||||
@@ -254,21 +258,25 @@ export class SmsService {
|
||||
let reason: string | null = null;
|
||||
let allowed = true;
|
||||
|
||||
// Only the explicit block switch stops sending (parity with Hamkar/Khanegi panels).
|
||||
// Negative / low balance is allowed; UI can still show balanceLevel as warning.
|
||||
// Manual block switch, then optional auto-block threshold (empty = no auto block).
|
||||
// Alert SMS (isAlert) always bypasses both. Negative balance alone does not block.
|
||||
if (account.isBlocked && !isAlert) {
|
||||
allowed = false;
|
||||
reason = 'blocked';
|
||||
} else if (this.isAutoBlocked(account) && !isAlert) {
|
||||
allowed = false;
|
||||
reason = 'auto_blocked';
|
||||
} else if (!isAlert && account.balanceRials < estimatedCostRials) {
|
||||
reason = 'insufficient_balance';
|
||||
}
|
||||
|
||||
return {
|
||||
allowed,
|
||||
blocked: account.isBlocked,
|
||||
blocked: account.isBlocked || this.isAutoBlocked(account),
|
||||
reason,
|
||||
balanceRials: account.balanceRials,
|
||||
pricePerPartRials: account.pricePerPartRials,
|
||||
autoBlockBelowRials: account.autoBlockBelowRials,
|
||||
parts: safeParts,
|
||||
estimatedCostRials,
|
||||
balanceLevel,
|
||||
@@ -303,9 +311,16 @@ export class SmsService {
|
||||
});
|
||||
}
|
||||
|
||||
if (this.isAutoBlocked(account) && !isAlert) {
|
||||
throw new ForbiddenException({
|
||||
message: 'ارسال پیامک بهخاطر کمتر بودن موجودی از آستانه خودکار مسدود است',
|
||||
reason: 'auto_blocked',
|
||||
});
|
||||
}
|
||||
|
||||
const costRials = parts * account.pricePerPartRials;
|
||||
|
||||
// Allow negative wallet (same as product panels): only isBlocked stops send/consume.
|
||||
// Negative wallet still allowed unless manual/auto block applies.
|
||||
const nextBalance = account.balanceRials - costRials;
|
||||
|
||||
const updated = await tx.smsAccount.update({
|
||||
@@ -869,6 +884,16 @@ export class SmsService {
|
||||
return `${new Intl.NumberFormat('fa-IR').format(toman)} تومان`;
|
||||
}
|
||||
|
||||
private isAutoBlocked(account: {
|
||||
balanceRials: number;
|
||||
autoBlockBelowRials: number | null;
|
||||
}) {
|
||||
return (
|
||||
account.autoBlockBelowRials != null &&
|
||||
account.balanceRials < account.autoBlockBelowRials
|
||||
);
|
||||
}
|
||||
|
||||
private chargeInfoOf(account: SmsAccount) {
|
||||
return {
|
||||
card: account.chargeCard || '',
|
||||
@@ -884,6 +909,7 @@ export class SmsService {
|
||||
balanceRials: account.balanceRials,
|
||||
pricePerPartRials: account.pricePerPartRials,
|
||||
isBlocked: account.isBlocked,
|
||||
autoBlockBelowRials: account.autoBlockBelowRials,
|
||||
alertCriticalRials: account.alertCriticalRials,
|
||||
alertWarningRials: account.alertWarningRials,
|
||||
chargeCard: account.chargeCard,
|
||||
|
||||
Reference in New Issue
Block a user