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:
@@ -3866,8 +3866,23 @@ export const MESSAGE_AUTOMATION_FIELDS = [
|
||||
{ token: "{شرکت}", label: "نام شرکت" },
|
||||
] as const;
|
||||
|
||||
/** First-part Persian SMS limit (legacy UI estimate). Prefer countSmsParts(). */
|
||||
export const MESSAGE_AUTOMATION_SMS_SEGMENT = 70;
|
||||
|
||||
/** Hamkar-compatible Persian multipart limits: 70 / 64 / 67 */
|
||||
export function countSmsParts(text: string): number {
|
||||
const length = [...String(text ?? "").trim()].length;
|
||||
if (length <= 0) return 0;
|
||||
const first = 70;
|
||||
const second = 64;
|
||||
const rest = 67;
|
||||
if (length <= first) return 1;
|
||||
if (length <= first + second) return 2;
|
||||
const thirdThreshold = first + second + rest;
|
||||
if (length <= thirdThreshold) return 3;
|
||||
return 3 + Math.ceil((length - thirdThreshold) / rest);
|
||||
}
|
||||
|
||||
export const MESSAGE_AUTOMATION_CHANNEL_LABELS: Record<
|
||||
MessageAutomationChannel,
|
||||
string
|
||||
@@ -5734,6 +5749,94 @@ export interface TreasuryDashboardDto {
|
||||
upcomingPayables: FinancialDocumentDto[];
|
||||
}
|
||||
|
||||
/* ───────── کیفپول پیامک (صورتحساب محیط) ───────── */
|
||||
|
||||
export type SmsBalanceLevel = "healthy" | "warning" | "critical" | "unknown";
|
||||
export type SmsPanelMode = "platform" | "own";
|
||||
|
||||
export interface SmsWalletSummaryDto {
|
||||
billingEnabled: boolean;
|
||||
balanceRials: number;
|
||||
pricePerPartRials: number;
|
||||
isBlocked: boolean;
|
||||
autoBlocked: boolean;
|
||||
balanceLevel: SmsBalanceLevel;
|
||||
panelMode: SmsPanelMode | string;
|
||||
chargeInfo: SmsChargeInfoDto | null;
|
||||
}
|
||||
|
||||
export interface SmsChargeInfoDto {
|
||||
card: string;
|
||||
iban: string;
|
||||
accountHolder: string;
|
||||
instruction: string;
|
||||
}
|
||||
|
||||
export interface PlatformSmsTenantRowDto {
|
||||
id: string;
|
||||
name: string;
|
||||
slug: string;
|
||||
isActive: boolean;
|
||||
isBlocked: boolean;
|
||||
panelMode: string;
|
||||
sms: {
|
||||
balanceRials: number;
|
||||
pricePerPartRials: number;
|
||||
autoBlockBelowRials: number | null;
|
||||
balanceLevel: SmsBalanceLevel;
|
||||
billingEnabled: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export interface PlatformSmsOverviewDto {
|
||||
organization: {
|
||||
id: string;
|
||||
name: string;
|
||||
slug: string;
|
||||
isActive: boolean;
|
||||
};
|
||||
account: {
|
||||
id: string;
|
||||
organizationId: string;
|
||||
balanceRials: number;
|
||||
pricePerPartRials: number;
|
||||
isBlocked: boolean;
|
||||
autoBlockBelowRials: number | null;
|
||||
alertCriticalRials: number;
|
||||
alertWarningRials: number;
|
||||
panelMode: SmsPanelMode;
|
||||
ownPanelType: string;
|
||||
ownPanelUsername: string | null;
|
||||
ownPanelFrom: string | null;
|
||||
hasOwnPanelPassword: boolean;
|
||||
balanceLevel: SmsBalanceLevel;
|
||||
billingEnabled: boolean;
|
||||
};
|
||||
chargeInfo: SmsChargeInfoDto;
|
||||
today: { messages: number; parts: number; amountRials: number };
|
||||
month: { messages: number; parts: number; amountRials: number };
|
||||
ledgers: Array<{
|
||||
id: string;
|
||||
type: string;
|
||||
amountRials: number;
|
||||
balanceAfterRials: number;
|
||||
parts: number | null;
|
||||
note: string | null;
|
||||
createdAt: string;
|
||||
}>;
|
||||
sendLogs: Array<{
|
||||
id: string;
|
||||
receiver: string;
|
||||
body: string;
|
||||
parts: number;
|
||||
totalAmountRials: number;
|
||||
provider: string | null;
|
||||
source: string | null;
|
||||
isAlert: boolean;
|
||||
createdAt: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
/* ───────── باشگاه امتیازات (گیمیفیکیشن کارکنان) ───────── */
|
||||
|
||||
export * from "./gamification";
|
||||
|
||||
Reference in New Issue
Block a user