add call and sms cost

This commit is contained in:
Simon Larsen 2023-10-27 17:14:58 +01:00
parent 17509225ee
commit dca1d2c370
No known key found for this signature in database
GPG Key ID: AB45983AA9C81CDE
8 changed files with 70 additions and 33 deletions

View File

@ -28,3 +28,12 @@ export interface CallRequestMessage {
export default interface CallRequest extends CallRequestMessage {
to: Phone;
}
export const isHighRiskPhoneNumber: Function = (phoneNumber: Phone): boolean => {
// Pakistan
if (phoneNumber.toString().startsWith('+92')) {
return true;
}
return false;
};

View File

@ -1,5 +1,5 @@
# OneUptime notification Deployment
{{- $notificationEnv := dict "PORT" $.Values.port.notification "SMS_DEFAULT_COST_IN_CENTS" $.Values.billing.smsDefaultValueInCents "CALL_DEFAULT_COST_IN_CENTS_PER_MINUTE" $.Values.billing.callDefaultValueInCentsPerMinute "INTERNAL_SMTP_EMAIL" $.Values.internalSmtp.email "INTERNAL_SMTP_PASSWORD" "internal_smtp_password" -}}
{{- $notificationEnv := dict "PORT" $.Values.port.notification "SMS_HIGH_RISK_COST_IN_CENTS" $.Values.billing.smsHighRiskValueInCents "CALL_HIGH_RISK_COST_IN_CENTS_PER_MINUTE" $.Values.billing.callHighRiskValueInCentsPerMinute "SMS_DEFAULT_COST_IN_CENTS" $.Values.billing.smsDefaultValueInCents "CALL_DEFAULT_COST_IN_CENTS_PER_MINUTE" $.Values.billing.callDefaultValueInCentsPerMinute "INTERNAL_SMTP_EMAIL" $.Values.internalSmtp.email "INTERNAL_SMTP_PASSWORD" "internal_smtp_password" -}}
{{- $notificationDeploymentArgs :=dict "IsServer" true "ServiceName" "notification" "Port" $.Values.port.notification "Release" $.Release "Values" $.Values "Env" $notificationEnv -}}
{{- include "oneuptime.deployment" $notificationDeploymentArgs }}
---

View File

@ -87,7 +87,9 @@ billing:
publicKey:
privateKey:
smsDefaultValueInCents:
callDefaultValueInCentsPerMinute:
callDefaultValueInCentsPerMinute:
smsHighRiskValueInCents:
callHighRiskValueInCentsPerMinute:
subscriptionPlan:
basic:

View File

@ -185,6 +185,18 @@ export const SMSDefaultCostInCents: number = process.env[
? parseInt(process.env['SMS_DEFAULT_COST_IN_CENTS'])
: 0;
export const SMSHighRiskCostInCents: number = process.env[
'SMS_HIGH_RISK_COST_IN_CENTS'
]
? parseInt(process.env['SMS_HIGH_RISK_COST_IN_CENTS'])
: 0;
export const CallHighRiskCostInCentsPerMinute: number = process.env[
'CALL_HIGH_RISK_COST_IN_CENTS_PER_MINUTE'
]
? parseInt(process.env['CALL_HIGH_RISK_COST_IN_CENTS_PER_MINUTE'])
: 0;
export const CallDefaultCostInCentsPerMinute: number = process.env[
'CALL_DEFAULT_COST_IN_CENTS_PER_MINUTE'
]

View File

@ -2,13 +2,18 @@ import ObjectID from 'Common/Types/ObjectID';
import Phone from 'Common/Types/Phone';
import {
CallDefaultCostInCentsPerMinute,
CallHighRiskCostInCentsPerMinute,
TwilioConfig,
getTwilioConfig,
} from '../Config';
import Twilio from 'twilio';
import CallLog from 'Model/Models/CallLog';
import CallStatus from 'Common/Types/Call/CallStatus';
import CallRequest, { GatherInput, Say } from 'Common/Types/Call/CallRequest';
import CallRequest, {
GatherInput,
Say,
isHighRiskPhoneNumber,
} from 'Common/Types/Call/CallRequest';
import { IsBillingEnabled } from 'CommonServer/EnvironmentConfig';
import CallLogService from 'CommonServer/Services/CallLogService';
import ProjectService from 'CommonServer/Services/ProjectService';
@ -33,6 +38,15 @@ export default class CallService {
userOnCallLogTimelineId?: ObjectID | undefined; // user notification log timeline id
}
): Promise<void> {
let callCost: number = 0;
if (IsBillingEnabled) {
callCost = CallDefaultCostInCentsPerMinute / 100;
if (isHighRiskPhoneNumber(callRequest.to)) {
callCost = CallHighRiskCostInCentsPerMinute / 100;
}
}
const twilioConfig: TwilioConfig | null = await getTwilioConfig();
if (!twilioConfig) {
@ -165,9 +179,7 @@ export default class CallService {
`We tried to make a call to ${callRequest.to.toString()}. This call was not made because project does not have enough balance to make calls. Current balance is ${
(project.smsOrCallCurrentBalanceInUSDCents ||
0) / 100
} USD. Required balance to send this SMS should is ${
CallDefaultCostInCentsPerMinute / 100
} USD. Please enable auto recharge or recharge manually.`
} USD. Required balance to send this SMS should is ${callCost} USD. Please enable auto recharge or recharge manually.`
);
}
return;
@ -175,14 +187,12 @@ export default class CallService {
if (
project.smsOrCallCurrentBalanceInUSDCents <
CallDefaultCostInCentsPerMinute
callCost * 100
) {
callLog.status = CallStatus.LowBalance;
callLog.statusMessage = `Project does not have enough balance to make this call. Current balance is ${
project.smsOrCallCurrentBalanceInUSDCents / 100
} USD. Required balance is ${
CallDefaultCostInCentsPerMinute / 100
} USD to make this call.`;
} USD. Required balance is ${callCost} USD to make this call.`;
logger.error(callLog.statusMessage);
await CallLogService.create({
data: callLog,
@ -207,9 +217,7 @@ export default class CallService {
(project.name || ''),
`We tried to make a call to ${callRequest.to.toString()}. This call was not made because project does not have enough balance to make a call. Current balance is ${
project.smsOrCallCurrentBalanceInUSDCents / 100
} USD. Required balance is ${
CallDefaultCostInCentsPerMinute / 100
} USD to make this call. Please enable auto recharge or recharge manually.`
} USD. Required balance is ${callCost} USD to make this call. Please enable auto recharge or recharge manually.`
);
}
return;
@ -230,18 +238,17 @@ export default class CallService {
logger.info('Call Request sent successfully.');
logger.info(callLog.statusMessage);
if (IsBillingEnabled && project) {
callLog.callCostInUSDCents = CallDefaultCostInCentsPerMinute;
callLog.callCostInUSDCents = callCost * 100;
if (twillioCall && parseInt(twillioCall.duration) > 60) {
callLog.callCostInUSDCents = Math.ceil(
Math.ceil(parseInt(twillioCall.duration) / 60) *
CallDefaultCostInCentsPerMinute
(callCost * 100)
);
}
project.smsOrCallCurrentBalanceInUSDCents = Math.floor(
project.smsOrCallCurrentBalanceInUSDCents! -
CallDefaultCostInCentsPerMinute
project.smsOrCallCurrentBalanceInUSDCents! - callCost * 100
);
await ProjectService.updateOneById({

View File

@ -2,6 +2,7 @@ import ObjectID from 'Common/Types/ObjectID';
import Phone from 'Common/Types/Phone';
import {
SMSDefaultCostInCents,
SMSHighRiskCostInCents,
TwilioConfig,
getTwilioConfig,
} from '../Config';
@ -18,6 +19,7 @@ import logger from 'CommonServer/Utils/Logger';
import UserOnCallLogTimelineService from 'CommonServer/Services/UserOnCallLogTimelineService';
import UserNotificationStatus from 'Common/Types/UserNotification/UserNotificationStatus';
import BadDataException from 'Common/Types/Exception/BadDataException';
import { isHighRiskPhoneNumber } from 'Common/Types/Call/CallRequest';
export default class SmsService {
public static async sendSms(
@ -30,6 +32,16 @@ export default class SmsService {
userOnCallLogTimelineId?: ObjectID | undefined;
}
): Promise<void> {
let smsCost: number = 0;
if (IsBillingEnabled) {
smsCost = SMSDefaultCostInCents / 100;
if (isHighRiskPhoneNumber(to)) {
smsCost = SMSHighRiskCostInCents / 100;
}
}
const twilioConfig: TwilioConfig | null = await getTwilioConfig();
if (!twilioConfig) {
@ -161,24 +173,17 @@ export default class SmsService {
`We tried to send an SMS to ${to.toString()} with message: <br/> <br/> ${message} <br/>This SMS was not sent because project does not have enough balance to send SMS. Current balance is ${
(project.smsOrCallCurrentBalanceInUSDCents ||
0) / 100
} USD cents. Required balance to send this SMS should is ${
SMSDefaultCostInCents / 100
} USD. Please enable auto recharge or recharge manually.`
} USD cents. Required balance to send this SMS should is ${smsCost} USD. Please enable auto recharge or recharge manually.`
);
}
return;
}
if (
project.smsOrCallCurrentBalanceInUSDCents <
SMSDefaultCostInCents
) {
if (project.smsOrCallCurrentBalanceInUSDCents < smsCost * 100) {
smsLog.status = SmsStatus.LowBalance;
smsLog.statusMessage = `Project does not have enough balance to send SMS. Current balance is ${
project.smsOrCallCurrentBalanceInUSDCents / 100
} USD. Required balance is ${
SMSDefaultCostInCents / 100
} USD to send this SMS.`;
} USD. Required balance is ${smsCost} USD to send this SMS.`;
logger.error(smsLog.statusMessage);
await SmsLogService.create({
data: smsLog,
@ -203,9 +208,7 @@ export default class SmsService {
(project.name || ''),
`We tried to send an SMS to ${to.toString()} with message: <br/> <br/> ${message} <br/> <br/> This SMS was not sent because project does not have enough balance to send SMS. Current balance is ${
project.smsOrCallCurrentBalanceInUSDCents / 100
} USD. Required balance is ${
SMSDefaultCostInCents / 100
} USD to send this SMS. Please enable auto recharge or recharge manually.`
} USD. Required balance is ${smsCost} USD to send this SMS. Please enable auto recharge or recharge manually.`
);
}
return;
@ -229,11 +232,10 @@ export default class SmsService {
logger.info(smsLog.statusMessage);
if (IsBillingEnabled && project) {
smsLog.smsCostInUSDCents = SMSDefaultCostInCents;
smsLog.smsCostInUSDCents = smsCost * 100;
project.smsOrCallCurrentBalanceInUSDCents = Math.floor(
project.smsOrCallCurrentBalanceInUSDCents! -
SMSDefaultCostInCents
project.smsOrCallCurrentBalanceInUSDCents! - smsCost * 100
);
await ProjectService.updateOneById({

View File

@ -177,6 +177,9 @@ METERED_PLAN_ACTIVE_MONITORING=priceMonthlyId,1,active-monitor,month
SMS_DEFAULT_COST_IN_CENTS=
CALL_DEFAULT_COST_IN_CENTS_PER_MINUTE=
SMS_HIGH_RISK_COST_IN_CENTS=
CALL_HIGH_RISK_COST_IN_CENTS_PER_MINUTE=
# IS BILLING ENABLED for this installer.
BILLING_ENABLED=false
# Public and private key for billing provider, usually stripe.

View File

@ -172,6 +172,8 @@ services:
PORT: ${NOTIFICATION_PORT}
SMS_DEFAULT_COST_IN_CENTS: ${SMS_DEFAULT_COST_IN_CENTS}
CALL_DEFAULT_COST_IN_CENTS_PER_MINUTE: ${CALL_DEFAULT_COST_IN_CENTS_PER_MINUTE}
SMS_HIGH_RISK_COST_IN_CENTS: ${SMS_HIGH_RISK_COST_IN_CENTS}
CALL_HIGH_RISK_COST_IN_CENTS_PER_MINUTE: ${CALL_HIGH_RISK_COST_IN_CENTS_PER_MINUTE}
INTERNAL_SMTP_EMAIL: ${INTERNAL_SMTP_EMAIL}
INTERNAL_SMTP_PASSWORD: ${INTERNAL_SMTP_PASSWORD}
depends_on: